Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions NextcloudTalk/Calls/CallKitManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -435,14 +435,10 @@ - (void)checkCallStateWithPeersForCall:(CallKitCall *)call
return;
}

NSInteger callAPIVersion = [ObjcNCAPIVersion getAPIVersionForType:NCAPITypeCall withAccount:account];
for (NSMutableDictionary *user in peers) {
NSString *userId = [user objectForKey:@"userId"];
BOOL isUserActorType = YES;
if (callAPIVersion >= NCAPIVersionAPIv3) {
userId = [user objectForKey:@"actorId"];
isUserActorType = [[user objectForKey:@"actorType"] isEqualToString:@"users"];
}
NSString *userId = [user objectForKey:@"actorId"];
BOOL isUserActorType = [[user objectForKey:@"actorType"] isEqualToString:@"users"];;

if ([account.userId isEqualToString:userId] && isUserActorType) {
// Account is already in a call (answered the call on a different device) -> no need to keep ringing
[self endCallWithUUID:call.uuid];
Expand Down
9 changes: 1 addition & 8 deletions NextcloudTalk/Calls/NCCallController.m
Original file line number Diff line number Diff line change
Expand Up @@ -1636,17 +1636,10 @@ - (TalkActor * _Nullable)getActorFromSessionId:(NSString *)sessionId
return [_externalSignalingController getParticipantFromSessionId:sessionId].actor;
}

NSInteger callAPIVersion = [ObjcNCAPIVersion getAPIVersionForType:NCAPITypeCall withAccount:_account];

for (NSMutableDictionary *user in _peersInCall) {
NSString *userSessionId = [user objectForKey:@"sessionId"];
if ([userSessionId isEqualToString:sessionId]) {
TalkActor *actor = [[TalkActor alloc] initWithActorId:[user objectForKey:@"userId"] actorType:@"users" actorDisplayName:[user objectForKey:@"displayName"]];

if (callAPIVersion >= NCAPIVersionAPIv3) {
[actor setId:[user objectForKey:@"actorId"]];
[actor setType:[user objectForKey:@"actorType"]];
}
TalkActor *actor = [[TalkActor alloc] initWithActorId:[user objectForKey:@"actorId"] actorType:[user objectForKey:@"actorType"] actorDisplayName:[user objectForKey:@"displayName"]];

return actor;
}
Expand Down
2 changes: 1 addition & 1 deletion NextcloudTalk/Database/NCDatabaseManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
NSString * const kNotificationsCapabilityExists = @"exists";
NSString * const kNotificationsCapabilityTestPush = @"test-push";

NSString * const kMinimumRequiredTalkCapability = kCapabilityForceMute; // Talk 9.0 is the minimum required version
NSString * const kMinimumRequiredTalkCapability = kCapabilityConversationV4; // Talk 12.0 is the minimum required version

NSString * const NCDatabaseManagerPendingFederationInvitationsDidChange = @"NCDatabaseManagerPendingFederationInvitationsDidChange";
NSString * const NCDatabaseManagerRoomCapabilitiesChangedNotification = @"NCDatabaseManagerRoomCapabilitiesChangedNotification";
Expand Down
36 changes: 2 additions & 34 deletions NextcloudTalk/Network/NCAPIController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -748,34 +748,6 @@ class NCAPIController: NSObject, NKCommonDelegate {
return try await apiSessionManager.deleteOcs(urlString, account: account, parameters: parameters)
}

@nonobjc
@MainActor
@discardableResult
public func removeParticipant(_ participant: String, forRoom token: String, forAccount account: TalkAccount) async throws -> OcsResponse {
guard let apiSessionManager = self.getAPISessionManager(forAccountId: account.accountId),
let encodedToken = token.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
else { throw ApiControllerError.preconditionError }

let urlString = self.getRequestURL(forConversationEndpoint: "room/\(encodedToken)/participants", forAccount: account)
let parameters: [String: String] = ["participant": participant]

return try await apiSessionManager.deleteOcs(urlString, account: account, parameters: parameters)
}

@nonobjc
@MainActor
@discardableResult
public func removeGuest(_ guest: String, forRoom token: String, forAccount account: TalkAccount) async throws -> OcsResponse {
guard let apiSessionManager = self.getAPISessionManager(forAccountId: account.accountId),
let encodedToken = token.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
else { throw ApiControllerError.preconditionError }

let urlString = self.getRequestURL(forConversationEndpoint: "room/\(encodedToken)/guests", forAccount: account)
let parameters: [String: String] = ["participant": guest]

return try await apiSessionManager.deleteOcs(urlString, account: account, parameters: parameters)
}

@MainActor
@discardableResult
public func removeSelf(fromRoom token: String, forAccount account: TalkAccount) async throws -> OcsResponse {
Expand All @@ -795,17 +767,13 @@ class NCAPIController: NSObject, NKCommonDelegate {
@nonobjc
@MainActor
@discardableResult
public func changeModerationPermission(forParticipantId participantId: String, withType type: ModeratorPermissionChangeType, inRoom token: String, forAccount account: TalkAccount) async throws -> OcsResponse {
public func changeModerationPermission(forAttendeeId attendeeId: Int, withType type: ModeratorPermissionChangeType, inRoom token: String, forAccount account: TalkAccount) async throws -> OcsResponse {
guard let apiSessionManager = self.getAPISessionManager(forAccountId: account.accountId),
let encodedToken = token.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
else { throw ApiControllerError.preconditionError }

let urlString = self.getRequestURL(forConversationEndpoint: "room/\(encodedToken)/moderators", forAccount: account)
var parameters = ["participant": participantId]

if NCAPIVersion(forType: .conversation, withAccount: account) >= .APIv3 {
parameters = ["attendeeId": participantId]
}
let parameters = ["attendeeId": attendeeId]

if type == .promoteToModerator {
return try await apiSessionManager.postOcs(urlString, account: account, parameters: parameters)
Expand Down
36 changes: 3 additions & 33 deletions NextcloudTalk/Network/NCAPIVersions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,6 @@
// SPDX-License-Identifier: GPL-3.0-or-later
//

// TODO: Remove when CallKitManager and NCCallController are migrated to swift
@objcMembers
public class ObjcNCAPIVersion: NSObject {
public static func getAPIVersion(forType type: NCAPIType, withAccount account: TalkAccount) -> Int {
return NCAPIVersion(forType: type, withAccount: account).rawValue
}
}

@objc
public enum NCAPIVersion: Int, Comparable {

Expand All @@ -21,34 +13,12 @@ public enum NCAPIVersion: Int, Comparable {

init(forType type: NCAPIType, withAccount account: TalkAccount) {
switch type {
case .conversation:
if NCDatabaseManager.sharedInstance().serverHasTalkCapability(kCapabilityConversationV4, forAccountId: account.accountId) {
self = .APIv4
return
}

if NCDatabaseManager.sharedInstance().serverHasTalkCapability(kCapabilityChatReadStatus, forAccountId: account.accountId) {
self = .APIv3
return
}

self = .APIv2
case .call:
self = NCAPIVersion(forType: .conversation, withAccount: account)
case .conversation, .call:
self = .APIv4
case .chat, .reactions, .polls, .breakoutRooms, .federation, .ban, .bots, .recording, .settings, .avatar:
self = .APIv1
case .signaling:
if NCDatabaseManager.sharedInstance().serverHasTalkCapability(kCapabilitySignalingV3, forAccountId: account.accountId) {
self = .APIv3
return
}

if NCDatabaseManager.sharedInstance().serverHasTalkCapability(kCapabilitySIPSupport, forAccountId: account.accountId) {
self = .APIv2
return
}

self = .APIv1
self = .APIv3
}
}

Expand Down
29 changes: 2 additions & 27 deletions NextcloudTalk/Rooms/NCRoomParticipant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,12 @@ public class NCRoomParticipant: NSObject {
var statusMessage: String?
var invitedActorId: String?

// Deprecated in conversation APIv3
var userId: String?

// Deprecated in conversation APIv4
var sessionId: String?

init(dictionary: [String: Any]) {
self.attendeeId = dictionary["attendeeId"] as? Int ?? 0
self.actorId = dictionary["actorId"] as? String
self.displayName = dictionary["displayName"] as? String ?? ""
self.lastPing = dictionary["lastPing"] as? Int ?? 0
self.sessionId = dictionary["sessionId"] as? String
self.sessionIds = dictionary["sessionIds"] as? [String]
self.userId = dictionary["userId"] as? String

if let attendeeTypeRaw = dictionary["actorType"] as? String,
let attendeeType = AttendeeType(rawValue: attendeeTypeRaw) {
Expand Down Expand Up @@ -101,7 +93,7 @@ public class NCRoomParticipant: NSObject {

public var isAppUser: Bool {
let activeAccount = NCDatabaseManager.sharedInstance().activeAccount()
return participantId == activeAccount.userId
return actorType == .user && actorId == activeAccount.userId
}

public var isBridgeBotUser: Bool {
Expand All @@ -125,24 +117,7 @@ public class NCRoomParticipant: NSObject {
}

public var isOffline: Bool {
return (sessionId == "0" || sessionId == nil) && (sessionIds ?? []).isEmpty
}

public var participantId: String? {
let activeAccount = NCDatabaseManager.sharedInstance().activeAccount()
if NCAPIVersion(forType: .conversation, withAccount: activeAccount) >= .APIv3 {
return String(attendeeId)
}

if let actorId {
return actorId
}

if isGuest {
return sessionId
}

return userId
return (sessionIds ?? []).isEmpty
}

public var detailedName: String {
Expand Down
22 changes: 3 additions & 19 deletions NextcloudTalk/Rooms/RoomInfo/RoomInfoParticipantsSection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,9 @@ struct RoomInfoParticipantsSection: View {
}

func changeModerationPermission(forParticipant participant: NCRoomParticipant, canModerate: Bool) {
guard let participantId = participant.participantId else { return }

Task {
do {
try await NCAPIController.sharedInstance().changeModerationPermission(forParticipantId: participantId, withType: canModerate ? .promoteToModerator : .demoteToParticipant, inRoom: room.token, forAccount: room.account!)
try await NCAPIController.sharedInstance().changeModerationPermission(forAttendeeId: participant.attendeeId, withType: canModerate ? .promoteToModerator : .demoteToParticipant, inRoom: room.token, forAccount: room.account!)
self.getParticipants()
} catch {
NCUserInterfaceController.sharedInstance().presentAlert(withTitle: NSLocalizedString("Could not change moderation permissions of the participant", comment: ""), withMessage: nil)
Expand Down Expand Up @@ -189,28 +187,14 @@ struct RoomInfoParticipantsSection: View {
func removeParticipant(participant: NCRoomParticipant) async {
let activeAccount = NCDatabaseManager.sharedInstance().activeAccount()

if NCAPIVersion(forType: .conversation, withAccount: activeAccount) >= .APIv3 {
do {
try await NCAPIController.sharedInstance().removeAttendee(participant.attendeeId, forRoom: room.token, forAccount: activeAccount)
} catch {
NCUserInterfaceController.sharedInstance().presentAlert(withTitle: NSLocalizedString("Could not remove participant", comment: ""), withMessage: nil)
}

self.getParticipants()
return
}

guard let participantId = participant.participantId else { return }

let method = participant.isGuest ? NCAPIController.sharedInstance().removeGuest : NCAPIController.sharedInstance().removeParticipant

do {
_ = try await method(participantId, room.token, activeAccount)
try await NCAPIController.sharedInstance().removeAttendee(participant.attendeeId, forRoom: room.token, forAccount: activeAccount)
} catch {
NCUserInterfaceController.sharedInstance().presentAlert(withTitle: NSLocalizedString("Could not remove participant", comment: ""), withMessage: nil)
}

self.getParticipants()
return
}

func banParticipant(participant: NCRoomParticipant, withInternalNote internalNote: String) {
Expand Down
7 changes: 5 additions & 2 deletions NextcloudTalkTests/Integration/IntegrationRoomTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@
let activeAccount = NCDatabaseManager.sharedInstance().activeAccount()
let room = try await createUniqueRoom(prefix: "SensitiveConversation", withAccount: activeAccount)

// TODO: Check for lastMessage does not work, since we don't create a reference to the lastMessage when creating a room just by a dict

Check warning on line 304 in NextcloudTalkTests/Integration/IntegrationRoomTest.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Todo Violation: TODOs should be resolved (Check for lastMessage does not...) (todo)
/*
let message = "SensitiveTestMessage"

Expand Down Expand Up @@ -427,17 +427,20 @@
let participantAlice = try XCTUnwrap(participants.first(where: { $0.displayName == "alice" }))

// Promote alice to moderator
try await NCAPIController.sharedInstance().changeModerationPermission(forParticipantId: participantAlice.participantId!, withType: .promoteToModerator, inRoom: room.token, forAccount: activeAccount)
try await NCAPIController.sharedInstance().changeModerationPermission(forAttendeeId: participantAlice.attendeeId, withType: .promoteToModerator, inRoom: room.token, forAccount: activeAccount)
participants = try await NCAPIController.sharedInstance().getParticipants(forRoom: room.token, forAccount: activeAccount)

XCTAssertTrue(participants.contains { $0.displayName == "alice" && $0.canModerate })

// Demote alice to participant
try await NCAPIController.sharedInstance().changeModerationPermission(forParticipantId: participantAlice.participantId!, withType: .demoteToParticipant, inRoom: room.token, forAccount: activeAccount)
try await NCAPIController.sharedInstance().changeModerationPermission(forAttendeeId: participantAlice.attendeeId, withType: .demoteToParticipant, inRoom: room.token, forAccount: activeAccount)
participants = try await NCAPIController.sharedInstance().getParticipants(forRoom: room.token, forAccount: activeAccount)

XCTAssertTrue(participants.contains { $0.displayName == "alice" && !$0.canModerate })

// Also check that the test user is in the room and correctly identified as the app user
XCTAssertTrue(participants.contains { $0.displayName == "admin" && $0.isAppUser })

// Try to remove admin which should fail, as admin is the last moderator
do {
try await NCAPIController.sharedInstance().removeSelf(fromRoom: room.token, forAccount: activeAccount)
Expand Down
1 change: 0 additions & 1 deletion NextcloudTalkTests/Unit/UnitNCRoomParticipantTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ final class UnitNCRoomParticipantTest: TestBaseRealm {
XCTAssertEqual(participant.status, "busy")
XCTAssertEqual(participant.statusIcon, "💬")
XCTAssertEqual(participant.statusMessage, "In a call")
XCTAssertNil(participant.userId)
}

}
Loading