From da6f1b7fb2129a239dc2c1ad46a7a2b8687cac18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=BCller?= Date: Sat, 14 Sep 2024 14:01:09 +0200 Subject: [PATCH 1/8] Always require an accountId for rooms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcel Müller --- NextcloudTalk/NCRoom.h | 9 ++++----- NextcloudTalk/NCRoom.m | 18 +++++------------- NextcloudTalk/NCRoom.swift | 4 ++++ NextcloudTalkTests/Integration/Helpers.swift | 6 +++--- 4 files changed, 16 insertions(+), 21 deletions(-) diff --git a/NextcloudTalk/NCRoom.h b/NextcloudTalk/NCRoom.h index 76828ea8a..34393099b 100644 --- a/NextcloudTalk/NCRoom.h +++ b/NextcloudTalk/NCRoom.h @@ -88,8 +88,8 @@ extern NSString * const NCRoomObjectTypeRoom; @interface NCRoom : RLMObject -@property (nonatomic, copy) NSString *internalId; // accountId@token -@property (nonatomic, copy) NSString *accountId; +@property (nonatomic, copy, nonnull) NSString *internalId; // accountId@token +@property (nonatomic, copy, nonnull) NSString *accountId; @property (nonatomic, copy) NSString *token; @property (nonatomic, copy) NSString *name; @property (nonatomic, copy) NSString *displayName; @@ -143,8 +143,7 @@ extern NSString * const NCRoomObjectTypeRoom; @property (nonatomic, copy) NSString *lastReceivedProxyHash; @property (nonatomic, assign) NSInteger mentionPermissions; -+ (instancetype)roomWithDictionary:(NSDictionary *)roomDict; -+ (instancetype)roomWithDictionary:(NSDictionary *)roomDict andAccountId:(NSString *)accountId; -+ (void)updateRoom:(NCRoom *)managedRoom withRoom:(NCRoom *)room; ++ (instancetype _Nullable)roomWithDictionary:(NSDictionary * _Nullable)roomDict andAccountId:(NSString * _Nullable)accountId; ++ (void)updateRoom:(NCRoom * _Nonnull)managedRoom withRoom:(NCRoom * _Nonnull)room; @end diff --git a/NextcloudTalk/NCRoom.m b/NextcloudTalk/NCRoom.m index 99f0df722..b919dfd59 100644 --- a/NextcloudTalk/NCRoom.m +++ b/NextcloudTalk/NCRoom.m @@ -14,13 +14,16 @@ @implementation NCRoom -+ (instancetype)roomWithDictionary:(NSDictionary *)roomDict ++ (instancetype)roomWithDictionary:(NSDictionary *)roomDict andAccountId:(NSString *)accountId { + if (!roomDict) { return nil; } - + NCRoom *room = [[self alloc] init]; + room.accountId = accountId; + room.internalId = [NSString stringWithFormat:@"%@@%@", room.accountId, room.token]; room.token = [roomDict objectForKey:@"token"]; room.type = (NCRoomType)[[roomDict objectForKey:@"type"] integerValue]; room.roomDescription = [roomDict objectForKey:@"description"]; @@ -129,17 +132,6 @@ + (instancetype)roomWithDictionary:(NSDictionary *)roomDict return room; } -+ (instancetype)roomWithDictionary:(NSDictionary *)roomDict andAccountId:(NSString *)accountId -{ - NCRoom *room = [self roomWithDictionary:roomDict]; - if (room) { - room.accountId = accountId; - room.internalId = [NSString stringWithFormat:@"%@@%@", room.accountId, room.token]; - } - - return room; -} - + (void)updateRoom:(NCRoom *)managedRoom withRoom:(NCRoom *)room { managedRoom.name = room.name; diff --git a/NextcloudTalk/NCRoom.swift b/NextcloudTalk/NCRoom.swift index 4d2a4f13b..be1e7e642 100644 --- a/NextcloudTalk/NCRoom.swift +++ b/NextcloudTalk/NCRoom.swift @@ -268,4 +268,8 @@ import Realm return "\(account.server)\(indexString)/call/\(token)" } + public var account: TalkAccount? { + return NCDatabaseManager.sharedInstance().talkAccount(forAccountId: self.accountId) + } + } diff --git a/NextcloudTalkTests/Integration/Helpers.swift b/NextcloudTalkTests/Integration/Helpers.swift index caedcbdd5..4cea6f961 100644 --- a/NextcloudTalkTests/Integration/Helpers.swift +++ b/NextcloudTalkTests/Integration/Helpers.swift @@ -10,11 +10,11 @@ import Foundation extension XCTestCase { // TODO: This should probably be part of APIController - func getRoomDict(from rawRoomDict: [Any]) -> [NCRoom] { + func getRoomDict(from rawRoomDict: [Any], for account: TalkAccount) -> [NCRoom] { var rooms: [NCRoom] = [] for roomDict in rawRoomDict { if let roomDict = roomDict as? [AnyHashable: Any] { - rooms.append(NCRoom(dictionary: roomDict)) + rooms.append(NCRoom(dictionary: roomDict, andAccountId: account.accountId)) } } @@ -27,7 +27,7 @@ extension XCTestCase { NCAPIController.sharedInstance().getRooms(forAccount: account, updateStatus: false, modifiedSince: 0) { roomsDict, error in XCTAssertNil(error) - let rooms = self.getRoomDict(from: roomsDict!) + let rooms = self.getRoomDict(from: roomsDict!, for: account) let room = rooms.first(where: { $0.displayName == roomName }) XCTAssertNotNil(room) From c2f7467c2e80fcc2ce74ce9026bfc3fb0a3aa0d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=BCller?= Date: Sat, 14 Sep 2024 14:55:29 +0200 Subject: [PATCH 2/8] Reduce usage of activeAccount MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcel Müller --- .../AddParticipantsTableViewController.m | 7 +- NextcloudTalk/AvatarButton.swift | 9 +- NextcloudTalk/AvatarImageView.swift | 9 +- NextcloudTalk/AvatarManager.swift | 14 +- .../BannedActorTableViewController.swift | 8 +- NextcloudTalk/BaseChatTableViewCell.swift | 15 +- NextcloudTalk/BaseChatViewController.swift | 128 ++++++++++-------- NextcloudTalk/CallParticipantViewCell.m | 3 +- NextcloudTalk/ChatViewController.swift | 43 +++--- ...ntactsSearchResultTableViewContoller.swift | 3 +- NextcloudTalk/InputbarViewController.swift | 7 +- NextcloudTalk/NCChatMessage.swift | 9 +- .../NewRoomTableViewController.swift | 3 +- .../PollResultsDetailsViewController.swift | 4 +- NextcloudTalk/PollVotingView.swift | 9 +- NextcloudTalk/ReactionsSummaryView.swift | 4 +- NextcloudTalk/ReferenceTalkView.swift | 2 +- .../ResultMultiSelectionTableViewController.m | 7 +- .../RoomAvatarInfoTableViewController.swift | 10 +- .../RoomCreationTableViewController.swift | 3 +- NextcloudTalk/RoomInfoTableViewController.m | 6 +- NextcloudTalk/RoomSearchTableViewController.m | 6 +- .../RoomSharedItemsTableViewController.swift | 7 +- NextcloudTalk/SearchTableViewController.m | 8 +- NextcloudTalk/UserStatusOptionsSwiftUI.swift | 4 +- NextcloudTalkTests/Integration/Helpers.swift | 4 +- 26 files changed, 183 insertions(+), 149 deletions(-) diff --git a/NextcloudTalk/AddParticipantsTableViewController.m b/NextcloudTalk/AddParticipantsTableViewController.m index ba98a27b7..bb1f19dba 100644 --- a/NextcloudTalk/AddParticipantsTableViewController.m +++ b/NextcloudTalk/AddParticipantsTableViewController.m @@ -429,7 +429,12 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N } cell.labelTitle.text = participant.name; - [cell.contactImage setActorAvatarForId:participant.userId withType:participant.source withDisplayName:participant.name withRoomToken:_room.token]; + + TalkAccount *account = self->_room.account; + + if (account) { + [cell.contactImage setActorAvatarForId:participant.userId withType:participant.source withDisplayName:participant.name withRoomToken:_room.token using:account]; + } UIImage *selectionImage = [UIImage systemImageNamed:@"circle"]; UIColor *selectionImageColor = [UIColor tertiaryLabelColor]; diff --git a/NextcloudTalk/AvatarButton.swift b/NextcloudTalk/AvatarButton.swift index 3e768e241..65033f45a 100644 --- a/NextcloudTalk/AvatarButton.swift +++ b/NextcloudTalk/AvatarButton.swift @@ -64,14 +64,11 @@ import SDWebImage // MARK: - User avatars public func setActorAvatar(forMessage message: NCChatMessage) { - self.setActorAvatar(forId: message.actorId, withType: message.actorType, withDisplayName: message.actorDisplayName, withRoomToken: message.token) + guard let account = message.account else { return } + self.setActorAvatar(forId: message.actorId, withType: message.actorType, withDisplayName: message.actorDisplayName, withRoomToken: message.token, using: account) } - public func setActorAvatar(forId actorId: String?, withType actorType: String?, withDisplayName actorDisplayName: String?, withRoomToken roomToken: String?) { - self.setActorAvatar(forId: actorId, withType: actorType, withDisplayName: actorDisplayName, withRoomToken: roomToken, using: nil) - } - - public func setActorAvatar(forId actorId: String?, withType actorType: String?, withDisplayName actorDisplayName: String?, withRoomToken roomToken: String?, using account: TalkAccount?) { + public func setActorAvatar(forId actorId: String?, withType actorType: String?, withDisplayName actorDisplayName: String?, withRoomToken roomToken: String?, using account: TalkAccount) { self.cancelCurrentRequest() self.currentRequest = AvatarManager.shared.getActorAvatar(forId: actorId, withType: actorType, withDisplayName: actorDisplayName, withRoomToken: roomToken, withStyle: self.traitCollection.userInterfaceStyle, usingAccount: account) { image in diff --git a/NextcloudTalk/AvatarImageView.swift b/NextcloudTalk/AvatarImageView.swift index 1a6f81eb0..0ad5de89b 100644 --- a/NextcloudTalk/AvatarImageView.swift +++ b/NextcloudTalk/AvatarImageView.swift @@ -61,14 +61,11 @@ import SDWebImage // MARK: - User avatars public func setActorAvatar(forMessage message: NCChatMessage) { - self.setActorAvatar(forId: message.actorId, withType: message.actorType, withDisplayName: message.actorDisplayName, withRoomToken: message.token) + guard let account = message.account else { return } + self.setActorAvatar(forId: message.actorId, withType: message.actorType, withDisplayName: message.actorDisplayName, withRoomToken: message.token, using: account) } - public func setActorAvatar(forId actorId: String?, withType actorType: String?, withDisplayName actorDisplayName: String?, withRoomToken roomToken: String?) { - self.setActorAvatar(forId: actorId, withType: actorType, withDisplayName: actorDisplayName, withRoomToken: roomToken, using: nil) - } - - public func setActorAvatar(forId actorId: String?, withType actorType: String?, withDisplayName actorDisplayName: String?, withRoomToken roomToken: String?, using account: TalkAccount?) { + public func setActorAvatar(forId actorId: String?, withType actorType: String?, withDisplayName actorDisplayName: String?, withRoomToken roomToken: String?, using account: TalkAccount) { self.cancelCurrentRequest() self.currentRequest = AvatarManager.shared.getActorAvatar(forId: actorId, withType: actorType, withDisplayName: actorDisplayName, withRoomToken: roomToken, withStyle: self.traitCollection.userInterfaceStyle, usingAccount: account) { image in diff --git a/NextcloudTalk/AvatarManager.swift b/NextcloudTalk/AvatarManager.swift index bd30962f7..1fefb4185 100644 --- a/NextcloudTalk/AvatarManager.swift +++ b/NextcloudTalk/AvatarManager.swift @@ -15,7 +15,7 @@ import SDWebImage // MARK: - Conversation avatars public func getAvatar(for room: NCRoom, with style: UIUserInterfaceStyle, completionBlock: @escaping (_ image: UIImage?) -> Void) -> SDWebImageCombinedOperation? { - if room.accountId != nil, NCDatabaseManager.sharedInstance().serverHasTalkCapability(kCapabilityConversationAvatars, forAccountId: room.accountId) { + if NCDatabaseManager.sharedInstance().serverHasTalkCapability(kCapabilityConversationAvatars, forAccountId: room.accountId) { // Server supports conversation avatars -> try to get the avatar using this API return NCAPIController.sharedInstance().getAvatarFor(room, with: style) { image, _ in @@ -50,7 +50,7 @@ import SDWebImage } else { switch room.type { case .oneToOne: - let account = NCDatabaseManager.sharedInstance().talkAccount(forAccountId: room.accountId) + guard let account = room.account else { return nil } return self.getUserAvatar(forId: room.name, withStyle: style, usingAccount: account, completionBlock: completionBlock) case .formerOneToOne: completionBlock(UIImage(named: "user-avatar", in: nil, compatibleWith: traitCollection)) @@ -71,7 +71,7 @@ import SDWebImage // MARK: - Actor avatars // swiftlint:disable:next function_parameter_count - public func getActorAvatar(forId actorId: String?, withType actorType: String?, withDisplayName actorDisplayName: String?, withRoomToken roomToken: String?, withStyle style: UIUserInterfaceStyle, usingAccount account: TalkAccount?, completionBlock: @escaping (_ image: UIImage?) -> Void) -> SDWebImageCombinedOperation? { + public func getActorAvatar(forId actorId: String?, withType actorType: String?, withDisplayName actorDisplayName: String?, withRoomToken roomToken: String?, withStyle style: UIUserInterfaceStyle, usingAccount account: TalkAccount, completionBlock: @escaping (_ image: UIImage?) -> Void) -> SDWebImageCombinedOperation? { if let actorId { if actorType == "bots" { return getBotsAvatar(forId: actorId, withStyle: style, completionBlock: completionBlock) @@ -123,9 +123,7 @@ import SDWebImage return NCUtils.getImage(withString: "X", withBackgroundColor: .systemGray3, withBounds: self.avatarDefaultSize, isCircular: true) } - private func getUserAvatar(forId actorId: String, withStyle style: UIUserInterfaceStyle, usingAccount account: TalkAccount?, completionBlock: @escaping (_ image: UIImage?) -> Void) -> SDWebImageCombinedOperation? { - let account = account ?? NCDatabaseManager.sharedInstance().activeAccount() - + private func getUserAvatar(forId actorId: String, withStyle style: UIUserInterfaceStyle, usingAccount account: TalkAccount, completionBlock: @escaping (_ image: UIImage?) -> Void) -> SDWebImageCombinedOperation? { return NCAPIController.sharedInstance().getUserAvatar(forUser: actorId, using: account, with: style) { image, _ in if image != nil { completionBlock(image) @@ -138,9 +136,7 @@ import SDWebImage } } - private func getFederatedUserAvatar(forId actorId: String, withRoomToken roomToken: String?, withStyle style: UIUserInterfaceStyle, usingAccount account: TalkAccount?, completionBlock: @escaping (_ image: UIImage?) -> Void) -> SDWebImageCombinedOperation? { - let account = account ?? NCDatabaseManager.sharedInstance().activeAccount() - + private func getFederatedUserAvatar(forId actorId: String, withRoomToken roomToken: String?, withStyle style: UIUserInterfaceStyle, usingAccount account: TalkAccount, completionBlock: @escaping (_ image: UIImage?) -> Void) -> SDWebImageCombinedOperation? { return NCAPIController.sharedInstance().getFederatedUserAvatar(forUser: actorId, inRoom: roomToken, using: account, with: style) { image, _ in if image != nil { completionBlock(image) diff --git a/NextcloudTalk/BannedActorTableViewController.swift b/NextcloudTalk/BannedActorTableViewController.swift index 481583647..892a172f6 100644 --- a/NextcloudTalk/BannedActorTableViewController.swift +++ b/NextcloudTalk/BannedActorTableViewController.swift @@ -54,9 +54,7 @@ } func getData() { - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() - - NCAPIController.sharedInstance().listBans(for: activeAccount.accountId, in: room.token) { [weak self] bannedActors in + NCAPIController.sharedInstance().listBans(for: room.accountId, in: room.token) { [weak self] bannedActors in guard let self else { return } self.bannedActors = bannedActors ?? [] @@ -105,9 +103,7 @@ self.showActivityIndicator() cell.setDisabledState() - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() - - NCAPIController.sharedInstance().unbanActor(for: activeAccount.accountId, in: self.room.token, with: bannedActor.banId) { [weak self] success in + NCAPIController.sharedInstance().unbanActor(for: room.accountId, in: self.room.token, with: bannedActor.banId) { [weak self] success in if !success { NotificationPresenter.shared().present(text: NSLocalizedString("Failed to unban selected entry", comment: ""), dismissAfterDelay: 5.0, includedStyle: .error) } diff --git a/NextcloudTalk/BaseChatTableViewCell.swift b/NextcloudTalk/BaseChatTableViewCell.swift index d30d164c0..1436ead31 100644 --- a/NextcloudTalk/BaseChatTableViewCell.swift +++ b/NextcloudTalk/BaseChatTableViewCell.swift @@ -204,7 +204,7 @@ class BaseChatTableViewCell: UITableViewCell, AudioPlayerViewDelegate, Reactions let quoteString = parent.parsedMarkdownForChat()?.string ?? "" self.quotedMessageView?.messageLabel.text = quoteString self.quotedMessageView?.actorLabel.attributedText = parent.actor.attributedDisplayName - self.quotedMessageView?.highlighted = parent.isMessage(from: activeAccount.userId) + self.quotedMessageView?.highlighted = parent.isMessage(from: account.userId) self.quotedMessageView?.avatarView.setActorAvatar(forMessage: parent) } @@ -269,7 +269,7 @@ class BaseChatTableViewCell: UITableViewCell, AudioPlayerViewDelegate, Reactions self.setupForPollCell(with: message) } else if message.file() != nil { // File message - self.setupForFileCell(with: message, with: activeAccount) + self.setupForFileCell(with: message, with: account) } else if message.geoLocation() != nil { // Location message self.setupForLocationCell(with: message) @@ -461,11 +461,10 @@ class BaseChatTableViewCell: UITableViewCell, AudioPlayerViewDelegate, Reactions // MARK: - Avatar User Menu func getDeferredUserMenu() -> UIMenu? { - guard let message = self.message else { return nil } + guard let message = self.message, let account = message.account + else { return nil } - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() - - if message.actorType != "users" || message.actorId == activeAccount.userId { + if message.actorType != "users" || message.actorId == account.userId { return nil } @@ -480,9 +479,9 @@ class BaseChatTableViewCell: UITableViewCell, AudioPlayerViewDelegate, Reactions } func getMenuUserAction(for message: NCChatMessage, completionBlock: @escaping ([UIMenuElement]) -> Void) { - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() + guard let account = message.account else { return } - NCAPIController.sharedInstance().getUserActions(forUser: message.actorId, using: activeAccount) { userActionsRaw, error in + NCAPIController.sharedInstance().getUserActions(forUser: message.actorId, using: account) { userActionsRaw, error in guard error == nil, let userActionsDict = userActionsRaw as? [String: AnyObject], let userActions = userActionsDict["actions"] as? [[String: String]], diff --git a/NextcloudTalk/BaseChatViewController.swift b/NextcloudTalk/BaseChatViewController.swift index 1b6d2ee1c..ea2c7318b 100644 --- a/NextcloudTalk/BaseChatViewController.swift +++ b/NextcloudTalk/BaseChatViewController.swift @@ -490,13 +490,14 @@ import SwiftUI // MARK: - Temporary messages - internal func createTemporaryMessage(message: String, replyTo parentMessage: NCChatMessage?, messageParameters: String, silently: Bool) -> NCChatMessage { + internal func createTemporaryMessage(message: String, replyTo parentMessage: NCChatMessage?, messageParameters: String, silently: Bool) -> NCChatMessage? { + guard let account = self.room.account else { return nil } + let temporaryMessage = NCChatMessage() - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() - temporaryMessage.accountId = activeAccount.accountId - temporaryMessage.actorDisplayName = activeAccount.userDisplayName - temporaryMessage.actorId = activeAccount.userId + temporaryMessage.accountId = account.accountId + temporaryMessage.actorDisplayName = account.userDisplayName + temporaryMessage.actorId = account.userId temporaryMessage.actorType = "users" temporaryMessage.timestamp = Int(Date().timeIntervalSince1970) temporaryMessage.token = room.token @@ -868,13 +869,14 @@ import SwiftUI } func showReplyView(for message: NCChatMessage) { + guard let account = message.account else { return } + let isAtBottom = self.shouldScrollOnNewMessages() - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() if let replyProxyView = self.replyProxyView as? ReplyMessageView { self.replyMessageView = replyProxyView - replyProxyView.presentReply(with: message, withUserId: activeAccount.userId) + replyProxyView.presentReply(with: message, withUserId: account.userId) self.presentKeyboard(true) // Make sure we're really at the bottom after showing the replyMessageView @@ -946,13 +948,13 @@ import SwiftUI } func didPressNoteToSelf(for message: NCChatMessage) { - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() + guard let account = message.account else { return } - NCAPIController.sharedInstance().getNoteToSelfRoom(forAccount: activeAccount) { roomDict, error in - if error == nil, let room = NCRoom(dictionary: roomDict, andAccountId: activeAccount.accountId) { + NCAPIController.sharedInstance().getNoteToSelfRoom(forAccount: account) { roomDict, error in + if error == nil, let room = NCRoom(dictionary: roomDict, andAccountId: account.accountId) { if message.isObjectShare { - NCAPIController.sharedInstance().shareRichObject(message.richObjectFromObjectShare, inRoom: room.token, for: activeAccount) { error in + NCAPIController.sharedInstance().shareRichObject(message.richObjectFromObjectShare, inRoom: room.token, for: account) { error in if error == nil { NotificationPresenter.shared().present(text: NSLocalizedString("Added note to self", comment: ""), dismissAfterDelay: 5.0, includedStyle: .success) } else { @@ -960,7 +962,7 @@ import SwiftUI } } } else { - NCAPIController.sharedInstance().sendChatMessage(message.parsedMessage().string, toRoom: room.token, displayName: nil, replyTo: -1, referenceId: nil, silently: false, for: activeAccount) { error in + NCAPIController.sharedInstance().sendChatMessage(message.parsedMessage().string, toRoom: room.token, displayName: nil, replyTo: -1, referenceId: nil, silently: false, for: account) { error in if error == nil { NotificationPresenter.shared().present(text: NSLocalizedString("Added note to self", comment: ""), dismissAfterDelay: 5.0, includedStyle: .success) } else { @@ -1002,8 +1004,7 @@ import SwiftUI } func didPressTranslate(for message: NCChatMessage) { - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() - let translateMessageVC = MessageTranslationViewController(message: message.parsedMessage().string, availableTranslations: NCDatabaseManager.sharedInstance().availableTranslations(forAccountId: activeAccount.accountId)) + let translateMessageVC = MessageTranslationViewController(message: message.parsedMessage().string, availableTranslations: NCDatabaseManager.sharedInstance().availableTranslations(forAccountId: self.room.accountId)) self.presentWithNavigation(translateMessageVC, animated: true) } @@ -1097,9 +1098,9 @@ import SwiftUI self.updateMessage(withMessageId: deletingMessage.messageId, updatedMessage: deletingMessage) } - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() + guard let account = message.account else { return } - NCAPIController.sharedInstance().deleteChatMessage(inRoom: self.room.token, withMessageId: message.messageId, for: activeAccount) { messageDict, error, statusCode in + NCAPIController.sharedInstance().deleteChatMessage(inRoom: self.room.token, withMessageId: message.messageId, for: account) { messageDict, error, statusCode in if error == nil, let messageDict, let parent = messageDict["parent"] as? [AnyHashable: Any] { @@ -1110,7 +1111,7 @@ import SwiftUI NotificationPresenter.shared().present(text: NSLocalizedString("Message deleted successfully", comment: ""), dismissAfterDelay: 5.0, includedStyle: .success) } - if let deleteMessage = NCChatMessage(dictionary: parent, andAccountId: activeAccount.accountId) { + if let deleteMessage = NCChatMessage(dictionary: parent, andAccountId: account.accountId) { self.updateMessage(withMessageId: deleteMessage.messageId, updatedMessage: deleteMessage) } } else if error != nil { @@ -1332,10 +1333,11 @@ import SwiftUI } } - internal func createShareConfirmationViewController() -> (shareConfirmationVC: ShareConfirmationViewController, navController: NCNavigationController) { - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() - let serverCapabilities = NCDatabaseManager.sharedInstance().serverCapabilities(forAccountId: activeAccount.accountId) - let shareConfirmationVC = ShareConfirmationViewController(room: self.room, account: activeAccount, serverCapabilities: serverCapabilities!)! + internal func createShareConfirmationViewController() -> (shareConfirmationVC: ShareConfirmationViewController, navController: NCNavigationController)? { + guard let account = room.account else { return nil } + + let serverCapabilities = NCDatabaseManager.sharedInstance().serverCapabilities(forAccountId: account.accountId) + let shareConfirmationVC = ShareConfirmationViewController(room: self.room, account: account, serverCapabilities: serverCapabilities!)! shareConfirmationVC.delegate = self shareConfirmationVC.isModal = true let navigationController = NCNavigationController(rootViewController: shareConfirmationVC) @@ -1357,7 +1359,7 @@ import SwiftUI return } - let (shareConfirmationVC, navigationController) = self.createShareConfirmationViewController() + guard let (shareConfirmationVC, navigationController) = self.createShareConfirmationViewController() else { return } picker.dismiss(animated: true) { self.present(navigationController, animated: true) { @@ -1400,9 +1402,9 @@ import SwiftUI public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) { self.saveImagePickerSettings(picker) - let (shareConfirmationVC, navigationController) = self.createShareConfirmationViewController() - - guard let mediaType = info[.mediaType] as? String else { return } + guard let (shareConfirmationVC, navigationController) = self.createShareConfirmationViewController(), + let mediaType = info[.mediaType] as? String + else { return } if mediaType == "public.image" { guard let image = info[.originalImage] as? UIImage else { return } @@ -1437,7 +1439,7 @@ import SwiftUI // MARK: - UIDocumentPickerViewController Delegate public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { - let (shareConfirmationVC, navigationController) = self.createShareConfirmationViewController() + guard let (shareConfirmationVC, navigationController) = self.createShareConfirmationViewController() else { return } self.present(navigationController, animated: true) { for url in urls { @@ -1449,10 +1451,11 @@ import SwiftUI // MARK: - ShareLocationViewController Delegate public func shareLocationViewController(_ viewController: ShareLocationViewController, didSelectLocationWithLatitude latitude: Double, longitude: Double, andName name: String) { + guard let account = room.account else { return } + let richObject = GeoLocationRichObject(latitude: latitude, longitude: longitude, name: name) - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() - NCAPIController.sharedInstance().shareRichObject(richObject.richObjectDictionary(), inRoom: self.room.token, for: activeAccount) { error in + NCAPIController.sharedInstance().shareRichObject(richObject.richObjectDictionary(), inRoom: self.room.token, for: account) { error in if let error { print("Error sharing rich object: \(error)") } @@ -1464,7 +1467,9 @@ import SwiftUI // MARK: - CNContactPickerViewController Delegate public func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) { - guard let vCardData = try? CNContactVCardSerialization.data(with: [contact]) else { return } + guard let account = room.account, + let vCardData = try? CNContactVCardSerialization.data(with: [contact]) + else { return } var vcString = String(data: vCardData, encoding: .utf8) @@ -1482,9 +1487,8 @@ import SwiftUI try vcString?.write(toFile: filePath, atomically: true, encoding: .utf8) let url = URL(fileURLWithPath: filePath) let contactFileName = "\(contact.identifier).vcf" - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() - NCAPIController.sharedInstance().uniqueNameForFileUpload(withName: contactFileName, originalName: true, for: activeAccount) { fileServerURL, fileServerPath, _, _ in + NCAPIController.sharedInstance().uniqueNameForFileUpload(withName: contactFileName, originalName: true, for: account) { fileServerURL, fileServerPath, _, _ in if let fileServerURL, let fileServerPath { self.uploadFileAtPath(localPath: url.path, withFileServerURL: fileServerURL, andFileServerPath: fileServerPath, withMetaData: nil) } else { @@ -1660,6 +1664,8 @@ import SwiftUI } func shareVoiceMessage() { + guard let account = room.account else { return } + let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd HH-mm-ss" let dateString = dateFormatter.string(from: Date()) @@ -1682,8 +1688,7 @@ import SwiftUI audioFileName += ".mp3" - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() - NCAPIController.sharedInstance().uniqueNameForFileUpload(withName: audioFileName, originalName: true, for: activeAccount, withCompletionBlock: { fileServerURL, fileServerPath, _, _ in + NCAPIController.sharedInstance().uniqueNameForFileUpload(withName: audioFileName, originalName: true, for: account, withCompletionBlock: { fileServerURL, fileServerPath, _, _ in if let fileServerURL, let fileServerPath, let recorder = self.recorder { let talkMetaData: [String: String] = ["messageType": "voice-message"] self.uploadFileAtPath(localPath: recorder.url.path, withFileServerURL: fileServerURL, andFileServerPath: fileServerPath, withMetaData: talkMetaData) @@ -1694,8 +1699,9 @@ import SwiftUI } func uploadFileAtPath(localPath: String, withFileServerURL fileServerURL: String, andFileServerPath fileServerPath: String, withMetaData talkMetaData: [String: String]?) { - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() - NCAPIController.sharedInstance().setupNCCommunication(for: activeAccount) + guard let account = room.account else { return } + + NCAPIController.sharedInstance().setupNCCommunication(for: account) NextcloudKit.shared.upload(serverUrlFileName: fileServerURL, fileNameLocalPath: localPath, taskHandler: { _ in NSLog("Upload task") @@ -1705,13 +1711,13 @@ import SwiftUI NSLog("Upload completed with error code: %ld", error.errorCode) if error.errorCode == 0 { - NCAPIController.sharedInstance().shareFileOrFolder(for: activeAccount, atPath: fileServerPath, toRoom: self.room.token, talkMetaData: talkMetaData, withCompletionBlock: { error in + NCAPIController.sharedInstance().shareFileOrFolder(for: account, atPath: fileServerPath, toRoom: self.room.token, talkMetaData: talkMetaData, withCompletionBlock: { error in if error != nil { NSLog("Failed to share voice message") } }) } else if error.errorCode == 404 || error.errorCode == 409 { - NCAPIController.sharedInstance().checkOrCreateAttachmentFolder(for: activeAccount, withCompletionBlock: { created, _ in + NCAPIController.sharedInstance().checkOrCreateAttachmentFolder(for: account, withCompletionBlock: { created, _ in if created { self.uploadFileAtPath(localPath: localPath, withFileServerURL: fileServerURL, andFileServerPath: fileServerPath, withMetaData: talkMetaData) } else { @@ -2266,21 +2272,21 @@ import SwiftUI collapseByMessage.collapsedMessages.add(newMessage.messageId as NSNumber) collapseByMessage.isCollapsed = true - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() + guard let account = room.account else { return } var isUser0Self = false var isUser1Self = false if let userDict = collapseByMessage.messageParameters["user"] as? [String: Any] { - isUser0Self = userDict["id"] as? String == activeAccount.userId && userDict["type"] as? String == "user" + isUser0Self = userDict["id"] as? String == account.userId && userDict["type"] as? String == "user" } if let userDict = newMessage.messageParameters["user"] as? [String: Any] { - isUser1Self = userDict["id"] as? String == activeAccount.userId && userDict["type"] as? String == "user" + isUser1Self = userDict["id"] as? String == account.userId && userDict["type"] as? String == "user" } - let isActor0Self = collapseByMessage.actorId == activeAccount.userId && collapseByMessage.actorType == "users" - let isActor1Self = newMessage.actorId == activeAccount.userId && newMessage.actorType == "users" + let isActor0Self = collapseByMessage.actorId == account.userId && collapseByMessage.actorType == "users" + let isActor1Self = newMessage.actorId == account.userId && newMessage.actorType == "users" let isActor0Admin = collapseByMessage.actorId == "cli" && collapseByMessage.actorType == "guests" collapseByMessage.collapsedIncludesUserSelf = isUser0Self || isUser1Self @@ -2494,12 +2500,13 @@ import SwiftUI return } - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() + guard let account = message.account else { return } + self.setTemporaryReaction(reaction: reaction, withState: .adding, toMessage: message) - NCDatabaseManager.sharedInstance().increaseEmojiUsage(forEmoji: reaction, forAccount: activeAccount.accountId) + NCDatabaseManager.sharedInstance().increaseEmojiUsage(forEmoji: reaction, forAccount: account.accountId) - NCAPIController.sharedInstance().addReaction(reaction, toMessage: message.messageId, inRoom: self.room.token, for: activeAccount) { _, error, _ in + NCAPIController.sharedInstance().addReaction(reaction, toMessage: message.messageId, inRoom: self.room.token, for: account) { _, error, _ in if error != nil { NotificationPresenter.shared().present(text: NSLocalizedString("An error occurred while adding a reaction to a message", comment: ""), dismissAfterDelay: 5.0, includedStyle: .error) self.removeTemporaryReaction(reaction: reaction, forMessageId: message.messageId) @@ -2508,10 +2515,11 @@ import SwiftUI } func removeReaction(reaction: String, from message: NCChatMessage) { - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() + guard let account = message.account else { return } + self.setTemporaryReaction(reaction: reaction, withState: .removing, toMessage: message) - NCAPIController.sharedInstance().removeReaction(reaction, fromMessage: message.messageId, inRoom: self.room.token, for: activeAccount) { _, error, _ in + NCAPIController.sharedInstance().removeReaction(reaction, fromMessage: message.messageId, inRoom: self.room.token, for: account) { _, error, _ in if error != nil { NotificationPresenter.shared().present(text: NSLocalizedString("An error occurred while removing a reaction from a message", comment: ""), dismissAfterDelay: 5.0, includedStyle: .error) self.removeTemporaryReaction(reaction: reaction, forMessageId: message.messageId) @@ -2578,8 +2586,9 @@ import SwiftUI reactionsVC.room = self.room self.presentWithNavigation(reactionsVC, animated: true) - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() - NCAPIController.sharedInstance().getReactions(nil, fromMessage: message.messageId, inRoom: self.room.token, for: activeAccount) { reactionsDict, error, _ in + guard let account = message.account else { return } + + NCAPIController.sharedInstance().getReactions(nil, fromMessage: message.messageId, inRoom: self.room.token, for: account) { reactionsDict, error, _ in if error == nil, let reactions = reactionsDict as? [String: [[String: AnyObject]]] { @@ -3413,12 +3422,11 @@ import SwiftUI pollVC.room = self.room self.presentWithNavigation(pollVC, animated: true) - if let pollId = Int(poll.parameterId) { - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() - NCAPIController.sharedInstance().getPollWithId(pollId, inRoom: self.room.token, for: activeAccount) { poll, error, _ in - if error == nil, let poll { - pollVC.updatePoll(poll: poll) - } + guard let pollId = Int(poll.parameterId), let account = room.account else { return } + + NCAPIController.sharedInstance().getPollWithId(pollId, inRoom: self.room.token, for: account) { poll, error, _ in + if error == nil, let poll { + pollVC.updatePoll(poll: poll) } } } @@ -3426,8 +3434,9 @@ import SwiftUI // MARK: - PollCreationViewControllerDelegate func pollCreationViewControllerWantsToCreatePoll(pollCreationViewController: PollCreationViewController, question: String, options: [String], resultMode: NCPollResultMode, maxVotes: Int) { - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() - NCAPIController.sharedInstance().createPoll(withQuestion: question, options: options, resultMode: resultMode, maxVotes: maxVotes, inRoom: self.room.token, for: activeAccount) { _, error, _ in + guard let account = room.account else { return } + + NCAPIController.sharedInstance().createPoll(withQuestion: question, options: options, resultMode: resultMode, maxVotes: maxVotes, inRoom: self.room.token, for: account) { _, error, _ in if error != nil { pollCreationViewController.showCreationError() } else { @@ -3598,9 +3607,8 @@ import SwiftUI extension Sequence where Iterator.Element == NCChatMessage { - func containsUserMessage() -> Bool { - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() - return self.contains(where: { !$0.isSystemMessage && $0.actorId == activeAccount.userId }) + func containsMessage(forUserId userId: String) -> Bool { + return self.contains(where: { !$0.isSystemMessage && $0.actorId == userId }) } func containsVisibleMessages() -> Bool { diff --git a/NextcloudTalk/CallParticipantViewCell.m b/NextcloudTalk/CallParticipantViewCell.m index df676e27d..fa92f36cd 100644 --- a/NextcloudTalk/CallParticipantViewCell.m +++ b/NextcloudTalk/CallParticipantViewCell.m @@ -124,7 +124,8 @@ - (void)setAvatarForActor:(TalkActor * _Nullable)actor [self setBackgroundColor:[[ColorGenerator shared] usernameToColor:actor.id]]; } - [self.peerAvatarImageView setActorAvatarForId:actor.id withType:actor.type withDisplayName:actor.displayName withRoomToken:nil]; + TalkAccount *activeAccount = [[NCDatabaseManager sharedInstance] activeAccount]; + [self.peerAvatarImageView setActorAvatarForId:actor.id withType:actor.type withDisplayName:actor.displayName withRoomToken:nil using:activeAccount]; } - (void)setDisplayName:(NSString *)displayName diff --git a/NextcloudTalk/ChatViewController.swift b/NextcloudTalk/ChatViewController.swift index a74c212f9..d7240eb13 100644 --- a/NextcloudTalk/ChatViewController.swift +++ b/NextcloudTalk/ChatViewController.swift @@ -527,7 +527,8 @@ import UIKit override func sendChatMessage(message: String, withParentMessage parentMessage: NCChatMessage?, messageParameters: String, silently: Bool) { // Create temporary message - let temporaryMessage = self.createTemporaryMessage(message: message, replyTo: parentMessage, messageParameters: messageParameters, silently: silently) + guard let temporaryMessage = self.createTemporaryMessage(message: message, replyTo: parentMessage, messageParameters: messageParameters, silently: silently) + else { return } if NCDatabaseManager.sharedInstance().roomHasTalkCapability(kCapabilityChatReferenceId, for: room) { self.appendTemporaryMessage(temporaryMessage: temporaryMessage) @@ -1016,8 +1017,10 @@ import UIKit } } completion: { _ in + guard let account = self.room.account else { return } + // Remove unread messages separator when user writes a message - if messages.containsUserMessage() { + if messages.containsMessage(forUserId: account.userId) { self.removeUnreadMessagesSeparator() } @@ -1025,7 +1028,7 @@ import UIKit // Otherwise we would scroll whenever a unread message separator is available if addedUnreadMessageSeparator, let indexPathUnreadMessageSeparator = self.indexPathForUnreadMessageSeparator() { tableView.scrollToRow(at: indexPathUnreadMessageSeparator, at: .middle, animated: true) - } else if (shouldScrollOnNewMessages || messages.containsUserMessage()), let lastIndexPath = self.getLastRealMessage()?.indexPath { + } else if (shouldScrollOnNewMessages || messages.containsMessage(forUserId: account.userId)), let lastIndexPath = self.getLastRealMessage()?.indexPath { tableView.scrollToRow(at: lastIndexPath, at: .none, animated: true) } else if self.firstUnreadMessage == nil, newMessagesContainVisibleMessages, let firstNewMessage = messages.first { // This check is needed since several calls to receiveMessages API might be needed @@ -1196,11 +1199,10 @@ import UIKit guard serverSupportsConversationPermissions else { return } - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() - // Retrieve the information about ourselves - guard let userDict = notification.userInfo?["users"] as? [[String: String]], - let appUserDict = userDict.first(where: { $0["userId"] == activeAccount.userId }) + guard let account = room.account, + let userDict = notification.userInfo?["users"] as? [[String: String]], + let appUserDict = userDict.first(where: { $0["userId"] == account.userId }) else { return } // Check if we still have the same permissions @@ -1226,15 +1228,15 @@ import UIKit // Don't show a typing indicator for ourselves or if typing indicator setting is disabled // Workaround: TypingPrivacy should be checked locally, not from the remote server, use serverCapabilities for now // TODO: Remove workaround for federated typing indicators. - guard let serverCapabilities = NCDatabaseManager.sharedInstance().serverCapabilities(forAccountId: self.room.accountId) + guard let account = room.account, + let serverCapabilities = NCDatabaseManager.sharedInstance().serverCapabilities(forAccountId: self.room.accountId) else { return } - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() let userId = notification.userInfo?["userId"] as? String let isFederated = notification.userInfo?["isFederated"] as? Bool ?? false // Since our own userId can exist on other servers, only suppress the notification if it's not federated - if (userId == activeAccount.userId && !isFederated) || serverCapabilities.typingPrivacy { + if (userId == account.userId && !isFederated) || serverCapabilities.typingPrivacy { return } @@ -1362,14 +1364,12 @@ import UIKit // MARK: - Editing support public override func didCommitTextEditing(_ sender: Any) { - if let editingMessage { - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() - + if let editingMessage, let account = self.room.account { let messageParametersJSONString = NCMessageParameter.messageParametersJSONString(from: self.mentionsDict) ?? "" editingMessage.message = self.replaceMentionsDisplayNamesWithMentionsKeysInMessage(message: self.textView.text, parameters: messageParametersJSONString) editingMessage.messageParametersJSONString = messageParametersJSONString - NCAPIController.sharedInstance().editChatMessage(inRoom: editingMessage.token, withMessageId: editingMessage.messageId, withMessage: editingMessage.sendingMessage, for: activeAccount) { messageDict, error, _ in + NCAPIController.sharedInstance().editChatMessage(inRoom: editingMessage.token, withMessageId: editingMessage.messageId, withMessage: editingMessage.sendingMessage, for: account) { messageDict, error, _ in if error != nil { NotificationPresenter.shared().present(text: NSLocalizedString("Error occurred while editing a message", comment: ""), dismissAfterDelay: 5.0, includedStyle: .error) return @@ -1377,7 +1377,7 @@ import UIKit guard let messageDict, let parent = messageDict["parent"] as? [AnyHashable: Any], - let updatedMessage = NCChatMessage(dictionary: parent, andAccountId: activeAccount.accountId) + let updatedMessage = NCChatMessage(dictionary: parent, andAccountId: account.accountId) else { return } self.updateMessage(withMessageId: editingMessage.messageId, updatedMessage: updatedMessage) @@ -1613,7 +1613,9 @@ import UIKit } } - guard let message = self.message(for: indexPath) else { return nil } + guard let message = self.message(for: indexPath), + let account = message.account + else { return nil } if message.isSystemMessage || message.isDeletedMessage || message.messageId == kUnreadMessagesSeparatorIdentifier { return nil @@ -1621,7 +1623,6 @@ import UIKit var actions: [UIMenuElement] = [] var informationalActions: [UIMenuElement] = [] - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() let hasChatPermissions = !NCDatabaseManager.sharedInstance().roomHasTalkCapability(kCapabilityChatPermission, for: room) || self.room.permissions.contains(.chat) // Show edit information @@ -1661,7 +1662,7 @@ import UIKit } // Reply-privately option (only to other users and not in one-to-one) - if self.isMessageReplyable(message: message), self.room.type != .oneToOne, message.actorType == "users", message.actorId != activeAccount.userId { + if self.isMessageReplyable(message: message), self.room.type != .oneToOne, message.actorType == "users", message.actorId != account.userId { actions.append(UIAction(title: NSLocalizedString("Reply privately", comment: ""), image: .init(systemName: "person")) { _ in self.didPressReplyPrivately(for: message) }) @@ -1736,7 +1737,7 @@ import UIKit }) // Translate - if !self.offlineMode, NCDatabaseManager.sharedInstance().hasAvailableTranslations(forAccountId: activeAccount.accountId) { + if !self.offlineMode, NCDatabaseManager.sharedInstance().hasAvailableTranslations(forAccountId: account.accountId) { actions.append(UIAction(title: NSLocalizedString("Translate", comment: ""), image: .init(systemName: "character.book.closed")) { _ in self.didPressTranslate(for: message) }) @@ -1761,14 +1762,14 @@ import UIKit var destructiveMenuActions: [UIMenuElement] = [] // Edit option - if message.isEditable(for: activeAccount, in: self.room) && hasChatPermissions { + if message.isEditable(for: account, in: self.room) && hasChatPermissions { destructiveMenuActions.append(UIAction(title: NSLocalizedString("Edit", comment: "Edit a message or room participants"), image: .init(systemName: "pencil")) { _ in self.didPressEdit(for: message) }) } // Delete option - if message.sendingFailed || message.isOfflineMessage || (message.isDeletable(for: activeAccount, in: self.room) && hasChatPermissions) { + if message.sendingFailed || message.isOfflineMessage || (message.isDeletable(for: account, in: self.room) && hasChatPermissions) { destructiveMenuActions.append(UIAction(title: NSLocalizedString("Delete", comment: ""), image: .init(systemName: "trash"), attributes: .destructive) { _ in self.didPressDelete(for: message) }) diff --git a/NextcloudTalk/ContactsSearchResultTableViewContoller.swift b/NextcloudTalk/ContactsSearchResultTableViewContoller.swift index 1279f6b89..82fc97135 100644 --- a/NextcloudTalk/ContactsSearchResultTableViewContoller.swift +++ b/NextcloudTalk/ContactsSearchResultTableViewContoller.swift @@ -86,7 +86,8 @@ import UIKit contactCell.labelTitle.text = contact.name let contactType = contact.source as String - contactCell.contactImage.setActorAvatar(forId: contact.userId, withType: contactType, withDisplayName: contact.name, withRoomToken: nil) + let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() + contactCell.contactImage.setActorAvatar(forId: contact.userId, withType: contactType, withDisplayName: contact.name, withRoomToken: nil, using: activeAccount) return contactCell } diff --git a/NextcloudTalk/InputbarViewController.swift b/NextcloudTalk/InputbarViewController.swift index 4a30fcb61..5594ff82f 100644 --- a/NextcloudTalk/InputbarViewController.swift +++ b/NextcloudTalk/InputbarViewController.swift @@ -220,8 +220,7 @@ import UIKit func showSuggestions(for string: String) { self.autocompletionUsers = [] - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() - NCAPIController.sharedInstance().getMentionSuggestions(for: activeAccount.accountId, in: self.room.token, with: string) { mentions in + NCAPIController.sharedInstance().getMentionSuggestions(for: self.room.accountId, in: self.room.token, with: string) { mentions in guard let mentions else { return } self.autocompletionUsers = mentions @@ -310,7 +309,9 @@ import UIKit if suggestion.id == "all" { cell.avatarButton.setAvatar(for: self.room) } else { - cell.avatarButton.setActorAvatar(forId: suggestion.id, withType: suggestion.source, withDisplayName: suggestion.label, withRoomToken: self.room.token) + if let account = room.account { + cell.avatarButton.setActorAvatar(forId: suggestion.id, withType: suggestion.source, withDisplayName: suggestion.label, withRoomToken: self.room.token, using: account) + } } cell.accessibilityIdentifier = AutoCompletionCellIdentifier diff --git a/NextcloudTalk/NCChatMessage.swift b/NextcloudTalk/NCChatMessage.swift index 135c0d939..eb5106bf9 100644 --- a/NextcloudTalk/NCChatMessage.swift +++ b/NextcloudTalk/NCChatMessage.swift @@ -195,9 +195,7 @@ import SwiftyAttributes internal var isReferenceApiSupported: Bool { // Check capabilities directly, otherwise NCSettingsController introduces new dependencies in NotificationServiceExtension - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() - - if let serverCapabilities = NCDatabaseManager.sharedInstance().serverCapabilities(forAccountId: activeAccount.accountId) { + if self.accountId != nil, let serverCapabilities = NCDatabaseManager.sharedInstance().serverCapabilities(forAccountId: self.accountId) { return serverCapabilities.referenceApiSupported } @@ -232,6 +230,10 @@ import SwiftyAttributes return TalkActor(actorId: self.actorId, actorType: self.actorType, actorDisplayName: self.actorDisplayName) } + public var account: TalkAccount? { + return NCDatabaseManager.sharedInstance().talkAccount(forAccountId: self.accountId) + } + public var messageIconName: String? { if let file = self.file() { if NCUtils.isImage(fileType: file.mimetype) { @@ -267,5 +269,4 @@ import SwiftyAttributes return file.size <= maxGifSize } - } diff --git a/NextcloudTalk/NewRoomTableViewController.swift b/NextcloudTalk/NewRoomTableViewController.swift index c5a68b178..e4f5c3cf4 100644 --- a/NextcloudTalk/NewRoomTableViewController.swift +++ b/NextcloudTalk/NewRoomTableViewController.swift @@ -215,7 +215,8 @@ enum NewRoomOption: Int { contactCell.labelTitle.text = contact.name let contactType = contact.source as String - contactCell.contactImage.setActorAvatar(forId: contact.userId, withType: contactType, withDisplayName: contact.name, withRoomToken: nil) + let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() + contactCell.contactImage.setActorAvatar(forId: contact.userId, withType: contactType, withDisplayName: contact.name, withRoomToken: nil, using: account) return contactCell } diff --git a/NextcloudTalk/PollResultsDetailsViewController.swift b/NextcloudTalk/PollResultsDetailsViewController.swift index e3fc01118..efa27eb88 100644 --- a/NextcloudTalk/PollResultsDetailsViewController.swift +++ b/NextcloudTalk/PollResultsDetailsViewController.swift @@ -119,7 +119,9 @@ import UIKit cell.titleLabel.text = detail.actorDisplayName // Actor avatar - cell.avatarImageView.setActorAvatar(forId: detail.actorId, withType: detail.actorType, withDisplayName: detail.actorDisplayName, withRoomToken: self.room.token) + if let account = room.account { + cell.avatarImageView.setActorAvatar(forId: detail.actorId, withType: detail.actorType, withDisplayName: detail.actorDisplayName, withRoomToken: self.room.token, using: account) + } return cell } diff --git a/NextcloudTalk/PollVotingView.swift b/NextcloudTalk/PollVotingView.swift index 1b47e4bd7..6ac0016e2 100644 --- a/NextcloudTalk/PollVotingView.swift +++ b/NextcloudTalk/PollVotingView.swift @@ -73,7 +73,8 @@ import UIKit } func setupPollView() { - guard let poll = poll else {return} + guard let poll else {return} + // Set poll settings let activeAccountUserId = NCDatabaseManager.sharedInstance().activeAccount().userId self.isPollOpen = poll.status == .open @@ -130,7 +131,8 @@ import UIKit } func voteButtonPressed() { - guard let poll = poll, let room = room else {return} + guard let poll, let room else {return} + footerView.primaryButton.isEnabled = false NCAPIController.sharedInstance().voteOnPoll(withId: poll.pollId, inRoom: room.token, withOptions: userSelectedOptions, for: NCDatabaseManager.sharedInstance().activeAccount()) { responsePoll, error, _ in @@ -190,7 +192,8 @@ import UIKit } func closePoll() { - guard let poll = poll, let room = room else {return} + guard let poll, let room else {return} + NCAPIController.sharedInstance().closePoll(withId: poll.pollId, inRoom: room.token, for: NCDatabaseManager.sharedInstance().activeAccount()) { responsePoll, error, _ in if let responsePoll = responsePoll, error == nil { self.poll = responsePoll diff --git a/NextcloudTalk/ReactionsSummaryView.swift b/NextcloudTalk/ReactionsSummaryView.swift index 823171c6f..7b6cf5590 100644 --- a/NextcloudTalk/ReactionsSummaryView.swift +++ b/NextcloudTalk/ReactionsSummaryView.swift @@ -106,7 +106,9 @@ import UIKit let actorId = actor?["actorId"] as? String ?? "" let actorType = actor?["actorType"] as? String ?? "" - cell.avatarImageView.setActorAvatar(forId: actorId, withType: actorType, withDisplayName: actorDisplayName, withRoomToken: self.room?.token) + if let room, let account = room.account { + cell.avatarImageView.setActorAvatar(forId: actorId, withType: actorType, withDisplayName: actorDisplayName, withRoomToken: room.token, using: account) + } return cell } diff --git a/NextcloudTalk/ReferenceTalkView.swift b/NextcloudTalk/ReferenceTalkView.swift index 05a4d2560..93b055135 100644 --- a/NextcloudTalk/ReferenceTalkView.swift +++ b/NextcloudTalk/ReferenceTalkView.swift @@ -76,7 +76,7 @@ import SwiftyAttributes let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() let room = NCDatabaseManager.sharedInstance().room(withToken: roomToken, forAccountId: activeAccount.accountId) - if let room = room { + if let room { self.referenceTypeIcon.setAvatar(for: room) self.referenceTypeIcon.layer.cornerRadius = self.referenceTypeIcon.frame.height / 2 } else { diff --git a/NextcloudTalk/ResultMultiSelectionTableViewController.m b/NextcloudTalk/ResultMultiSelectionTableViewController.m index 2f71662a3..b456ed72a 100644 --- a/NextcloudTalk/ResultMultiSelectionTableViewController.m +++ b/NextcloudTalk/ResultMultiSelectionTableViewController.m @@ -107,8 +107,13 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N // Only when adding new (email) participants we show the mail avatar [cell.contactImage setMailAvatar]; } else { - [cell.contactImage setActorAvatarForId:contact.userId withType:contact.source withDisplayName:contact.name withRoomToken:_room.token]; + TalkAccount *activeAccount = [[NCDatabaseManager sharedInstance] activeAccount]; + + if (activeAccount) { + [cell.contactImage setActorAvatarForId:contact.userId withType:contact.source withDisplayName:contact.name withRoomToken:_room.token using:activeAccount]; + } } + UIImage *selectionImage = [UIImage systemImageNamed:@"circle"]; UIColor *selectionImageColor = [UIColor tertiaryLabelColor]; for (NCUser *user in _selectedParticipants) { diff --git a/NextcloudTalk/RoomAvatarInfoTableViewController.swift b/NextcloudTalk/RoomAvatarInfoTableViewController.swift index 2052b3861..5afc614b4 100644 --- a/NextcloudTalk/RoomAvatarInfoTableViewController.swift +++ b/NextcloudTalk/RoomAvatarInfoTableViewController.swift @@ -169,11 +169,12 @@ enum RoomAvatarInfoSection: Int { } func setButtonPressed() { + guard let account = room.account else { return } + self.showModifyingView() self.descriptionHeaderView.button.isHidden = true - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() - NCAPIController.sharedInstance().setRoomDescription(currentDescription, forRoom: room.token, forAccount: activeAccount) { error in + NCAPIController.sharedInstance().setRoomDescription(currentDescription, forRoom: room.token, forAccount: account) { error in if error != nil { NCUserInterfaceController.sharedInstance().presentAlert(withTitle: NSLocalizedString("An error occurred while setting description", comment: ""), withMessage: nil) } @@ -380,10 +381,11 @@ enum RoomAvatarInfoSection: Int { return true } + guard let account = room.account else { return true } + self.showModifyingView() - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() - NCAPIController.sharedInstance().renameRoom(self.room.token, forAccount: activeAccount, withName: newRoomValue) { error in + NCAPIController.sharedInstance().renameRoom(self.room.token, forAccount: account, withName: newRoomValue) { error in if error != nil { let alertTitle = NSLocalizedString("Could not rename the conversation", comment: "") NCUserInterfaceController.sharedInstance().presentAlert(withTitle: alertTitle, withMessage: nil) diff --git a/NextcloudTalk/RoomCreationTableViewController.swift b/NextcloudTalk/RoomCreationTableViewController.swift index 12ef0042c..9248947ec 100644 --- a/NextcloudTalk/RoomCreationTableViewController.swift +++ b/NextcloudTalk/RoomCreationTableViewController.swift @@ -455,7 +455,8 @@ enum RoomVisibilityOption: Int { participantCell.labelTitle.text = participant.name let participantType = participant.source as String - participantCell.contactImage.setActorAvatar(forId: participant.userId, withType: participantType, withDisplayName: participant.name, withRoomToken: nil) + let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() + participantCell.contactImage.setActorAvatar(forId: participant.userId, withType: participantType, withDisplayName: participant.name, withRoomToken: nil, using: activeAccount) return participantCell } diff --git a/NextcloudTalk/RoomInfoTableViewController.m b/NextcloudTalk/RoomInfoTableViewController.m index 418ac7edc..acb38b50f 100644 --- a/NextcloudTalk/RoomInfoTableViewController.m +++ b/NextcloudTalk/RoomInfoTableViewController.m @@ -2275,7 +2275,11 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N cell.labelTitle.text = [self detailedNameForParticipant:participant]; // Avatar - [cell.contactImage setActorAvatarForId:participant.actorId withType:participant.actorType withDisplayName:participant.displayName withRoomToken:self.room.token]; + TalkAccount *account = self->_room.account; + + if (account) { + [cell.contactImage setActorAvatarForId:participant.actorId withType:participant.actorType withDisplayName:participant.displayName withRoomToken:self.room.token using:account]; + } // User status [cell setUserStatus:participant.status]; diff --git a/NextcloudTalk/RoomSearchTableViewController.m b/NextcloudTalk/RoomSearchTableViewController.m index 89afdbb2c..369fd1a85 100644 --- a/NextcloudTalk/RoomSearchTableViewController.m +++ b/NextcloudTalk/RoomSearchTableViewController.m @@ -193,7 +193,8 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForMessageAtIndexPat [cell.roomImage setImageWithURL:thumbnailURL placeholderImage:nil]; cell.roomImage.contentMode = UIViewContentModeScaleToFill; } else { - [cell.roomImage setActorAvatarForId:actorId withType:actorType withDisplayName:@"" withRoomToken:nil]; + TalkAccount *activeAccount = [[NCDatabaseManager sharedInstance] activeAccount]; + [cell.roomImage setActorAvatarForId:actorId withType:actorType withDisplayName:@"" withRoomToken:nil using:activeAccount]; } // Clear possible content not removed by cell reuse @@ -234,7 +235,8 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForUserAtIndexPath:( cell.titleLabel.text = user.name; cell.titleOnly = YES; - [cell.roomImage setActorAvatarForId:user.userId withType:user.source withDisplayName:user.name withRoomToken:nil]; + TalkAccount *activeAccount = [[NCDatabaseManager sharedInstance] activeAccount]; + [cell.roomImage setActorAvatarForId:user.userId withType:user.source withDisplayName:user.name withRoomToken:nil using:activeAccount]; return cell; } diff --git a/NextcloudTalk/RoomSharedItemsTableViewController.swift b/NextcloudTalk/RoomSharedItemsTableViewController.swift index 1a703ed28..dbcde20b0 100644 --- a/NextcloudTalk/RoomSharedItemsTableViewController.swift +++ b/NextcloudTalk/RoomSharedItemsTableViewController.swift @@ -13,7 +13,6 @@ import QuickLook VLCKitVideoViewControllerDelegate { let room: NCRoom - let account: TalkAccount = NCDatabaseManager.sharedInstance().activeAccount() let itemsOverviewLimit: Int = 1 let itemLimit: Int = 100 var sharedItemsOverview: [String: [NCChatMessage]] = [:] @@ -72,7 +71,10 @@ import QuickLook } func getItemsForItemType(itemType: String) { + guard let account = room.account else { return } + showFetchingItemsPlaceholderView() + NCAPIController.sharedInstance() .getSharedItems(ofType: itemType, fromLastMessageId: currentLastItemId, withLimit: itemLimit, inRoom: room.token, for: account) { items, lastItemId, error, _ in @@ -109,7 +111,10 @@ import QuickLook } func getItemsOverview() { + guard let account = room.account else { return } + showFetchingItemsPlaceholderView() + NCAPIController.sharedInstance() .getSharedItemsOverview(inRoom: room.token, withLimit: itemsOverviewLimit, for: account) { itemsOverview, error, _ in if error == nil { diff --git a/NextcloudTalk/SearchTableViewController.m b/NextcloudTalk/SearchTableViewController.m index c820f254c..9cd2803f3 100644 --- a/NextcloudTalk/SearchTableViewController.m +++ b/NextcloudTalk/SearchTableViewController.m @@ -102,8 +102,12 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N cell.labelTitle.text = contact.name; - [cell.contactImage setActorAvatarForId:contact.userId withType:contact.source withDisplayName:contact.name withRoomToken:nil]; - + TalkAccount *activeAccount = [[NCDatabaseManager sharedInstance] activeAccount]; + + if (activeAccount) { + [cell.contactImage setActorAvatarForId:contact.userId withType:contact.source withDisplayName:contact.name withRoomToken:nil using:activeAccount]; + } + return cell; } diff --git a/NextcloudTalk/UserStatusOptionsSwiftUI.swift b/NextcloudTalk/UserStatusOptionsSwiftUI.swift index d7ab7383f..070b6e7e9 100644 --- a/NextcloudTalk/UserStatusOptionsSwiftUI.swift +++ b/NextcloudTalk/UserStatusOptionsSwiftUI.swift @@ -51,8 +51,8 @@ struct UserStatusOptionsSwiftUI: View { } func setActiveUserStatus(userStatus: String) { - let activeAcoount: TalkAccount = NCDatabaseManager.sharedInstance().activeAccount() - NCAPIController.sharedInstance().setUserStatus(userStatus, for: activeAcoount) { _ in + let activeAccount: TalkAccount = NCDatabaseManager.sharedInstance().activeAccount() + NCAPIController.sharedInstance().setUserStatus(userStatus, for: activeAccount) { _ in getActiveUserStatus() dismiss() changed.toggle() diff --git a/NextcloudTalkTests/Integration/Helpers.swift b/NextcloudTalkTests/Integration/Helpers.swift index 4cea6f961..fc79999e1 100644 --- a/NextcloudTalkTests/Integration/Helpers.swift +++ b/NextcloudTalkTests/Integration/Helpers.swift @@ -13,8 +13,8 @@ extension XCTestCase { func getRoomDict(from rawRoomDict: [Any], for account: TalkAccount) -> [NCRoom] { var rooms: [NCRoom] = [] for roomDict in rawRoomDict { - if let roomDict = roomDict as? [AnyHashable: Any] { - rooms.append(NCRoom(dictionary: roomDict, andAccountId: account.accountId)) + if let roomDict = roomDict as? [AnyHashable: Any], let ncRooms = NCRoom(dictionary: roomDict, andAccountId: account.accountId) { + rooms.append(ncRooms) } } From b5f4e3ec21493073551f634c70e57888d271af21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=BCller?= Date: Mon, 16 Sep 2024 13:16:10 +0200 Subject: [PATCH 3/8] internalId and accountId are nullable for NCChatMessage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcel Müller --- NextcloudTalk/NCChatMessage.h | 4 ++-- NextcloudTalk/NCChatMessage.swift | 5 +++-- NextcloudTalk/NCMediaViewerViewController.swift | 13 +++++++++---- NextcloudTalk/NCRoomsManagerExtensions.swift | 3 ++- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/NextcloudTalk/NCChatMessage.h b/NextcloudTalk/NCChatMessage.h index 367068427..2bf5bfd39 100644 --- a/NextcloudTalk/NCChatMessage.h +++ b/NextcloudTalk/NCChatMessage.h @@ -40,8 +40,8 @@ typedef void (^GetReferenceDataCompletionBlock)(NCChatMessage *message, NSDictio @interface NCChatMessage : RLMObject -@property (nonatomic, strong) NSString *internalId; // accountId@token@messageId -@property (nonatomic, strong) NSString *accountId; +@property (nonatomic, strong, nullable) NSString *internalId; // accountId@token@messageId +@property (nonatomic, strong, nullable) NSString *accountId; @property (nonatomic, strong) NSString *actorDisplayName; @property (nonatomic, strong) NSString *actorId; @property (nonatomic, strong) NSString *actorType; diff --git a/NextcloudTalk/NCChatMessage.swift b/NextcloudTalk/NCChatMessage.swift index eb5106bf9..d06a41334 100644 --- a/NextcloudTalk/NCChatMessage.swift +++ b/NextcloudTalk/NCChatMessage.swift @@ -195,7 +195,7 @@ import SwiftyAttributes internal var isReferenceApiSupported: Bool { // Check capabilities directly, otherwise NCSettingsController introduces new dependencies in NotificationServiceExtension - if self.accountId != nil, let serverCapabilities = NCDatabaseManager.sharedInstance().serverCapabilities(forAccountId: self.accountId) { + if let accountId, let serverCapabilities = NCDatabaseManager.sharedInstance().serverCapabilities(forAccountId: accountId) { return serverCapabilities.referenceApiSupported } @@ -231,7 +231,8 @@ import SwiftyAttributes } public var account: TalkAccount? { - return NCDatabaseManager.sharedInstance().talkAccount(forAccountId: self.accountId) + guard let accountId else { return nil } + return NCDatabaseManager.sharedInstance().talkAccount(forAccountId: accountId) } public var messageIconName: String? { diff --git a/NextcloudTalk/NCMediaViewerViewController.swift b/NextcloudTalk/NCMediaViewerViewController.swift index ed75a2af8..c0106a9ad 100644 --- a/NextcloudTalk/NCMediaViewerViewController.swift +++ b/NextcloudTalk/NCMediaViewerViewController.swift @@ -94,8 +94,10 @@ import UIKit // MARK: - PageViewController delegate - func getAllFileMessages() -> RLMResults { - let query = NSPredicate(format: "accountId = %@ AND token = %@ AND messageParametersJSONString contains[cd] %@", self.initialMessage.accountId, self.initialMessage.token, "\"file\":") + func getAllFileMessages() -> RLMResults? { + guard let accountId = self.initialMessage.accountId else { return nil } + + let query = NSPredicate(format: "accountId = %@ AND token = %@ AND messageParametersJSONString contains[cd] %@", accountId, self.initialMessage.token, "\"file\":") let messages = NCChatMessage.objects(with: query).sortedResults(usingKeyPath: "messageId", ascending: true) return messages @@ -103,7 +105,9 @@ import UIKit func getPreviousFileMessage(from message: NCChatMessage) -> NCChatMessage? { let prevQuery = NSPredicate(format: "messageId < %ld", message.messageId) - let messageObject = self.getAllFileMessages().objects(with: prevQuery).lastObject() + + guard let queriedObjects = self.getAllFileMessages()?.objects(with: prevQuery) else { return nil } + let messageObject = queriedObjects.lastObject() if let message = messageObject as? NCChatMessage { if NCUtils.isImage(fileType: message.file().mimetype) { @@ -119,7 +123,8 @@ import UIKit func getNextFileMessage(from message: NCChatMessage) -> NCChatMessage? { let prevQuery = NSPredicate(format: "messageId > %ld", message.messageId) - let messageObject = self.getAllFileMessages().objects(with: prevQuery).firstObject() + + guard let messageObject = self.getAllFileMessages()?.objects(with: prevQuery).firstObject() else { return nil } if let message = messageObject as? NCChatMessage { if NCUtils.isImage(fileType: message.file().mimetype) { diff --git a/NextcloudTalk/NCRoomsManagerExtensions.swift b/NextcloudTalk/NCRoomsManagerExtensions.swift index 48ac92b09..02c98ebb3 100644 --- a/NextcloudTalk/NCRoomsManagerExtensions.swift +++ b/NextcloudTalk/NCRoomsManagerExtensions.swift @@ -421,7 +421,8 @@ import Foundation // Inform the chatViewController about this change NotificationCenter.default.post(name: .NCChatControllerDidSendChatMessage, object: self, userInfo: userInfo) } else { - if let room = NCDatabaseManager.sharedInstance().room(withToken: offlineMessage.token, forAccountId: offlineMessage.accountId), + if let accountId = offlineMessage.accountId, + let room = NCDatabaseManager.sharedInstance().room(withToken: offlineMessage.token, forAccountId: accountId), let chatController = NCChatController(for: room) { chatController.send(offlineMessage) } From 9bfead8209df62a78d7ff73a6aa93e5f93d18cec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=BCller?= Date: Mon, 16 Sep 2024 13:31:36 +0200 Subject: [PATCH 4/8] Use accountId to init NCChatMessage test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcel Müller --- .../Unit/Chat/UnitBaseChatViewControllerTest.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NextcloudTalkTests/Unit/Chat/UnitBaseChatViewControllerTest.swift b/NextcloudTalkTests/Unit/Chat/UnitBaseChatViewControllerTest.swift index 8e549c479..f0bfeb8c5 100644 --- a/NextcloudTalkTests/Unit/Chat/UnitBaseChatViewControllerTest.swift +++ b/NextcloudTalkTests/Unit/Chat/UnitBaseChatViewControllerTest.swift @@ -39,7 +39,7 @@ final class UnitBaseChatViewControllerTest: TestBaseRealm { try super.setUpWithError() baseController = BaseChatViewController(for: NCRoom())! - testMessage = NCChatMessage() + testMessage = NCChatMessage(dictionary: [:], andAccountId: UnitBaseChatViewControllerTest.fakeAccountId) } func testInvisibleCellHeight() throws { From d04d6ebc67f36b78b1424e71f4c84043049b2517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=BCller?= Date: Sat, 9 Nov 2024 23:27:07 +0100 Subject: [PATCH 5/8] Correctly guard room on breakout room switch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcel Müller --- NextcloudTalk/CallViewController.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/NextcloudTalk/CallViewController.swift b/NextcloudTalk/CallViewController.swift index 7ca8e5b7e..14a7bb796 100644 --- a/NextcloudTalk/CallViewController.swift +++ b/NextcloudTalk/CallViewController.swift @@ -831,7 +831,8 @@ class CallViewController: UIViewController, // Connect to new call let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() NCRoomsManager.sharedInstance().updateRoom(token) { roomDict, error in - guard error == nil else { + guard error == nil, let newRoom = NCRoom(dictionary: roomDict, andAccountId: activeAccount.accountId) + else { print("Error getting room to switch") return } @@ -842,7 +843,7 @@ class CallViewController: UIViewController, self.delegate?.callViewController(self, wantsToSwitchFromCall: self.room.token, toRoom: token) // Assign new room as current room - self.room = NCRoom(dictionary: roomDict, andAccountId: activeAccount.accountId) + self.room = newRoom // Save current audio and video state self.audioDisabledAtStart = !audioEnabled From 468d940b336140cf7f4066d7a95a73dfc6b60dd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=BCller?= Date: Sat, 9 Nov 2024 23:27:48 +0100 Subject: [PATCH 6/8] Adjust activeAccount in BaseChatTableViewCell after rebase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcel Müller --- NextcloudTalk/BaseChatTableViewCell.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/NextcloudTalk/BaseChatTableViewCell.swift b/NextcloudTalk/BaseChatTableViewCell.swift index 1436ead31..cfbf3eeb3 100644 --- a/NextcloudTalk/BaseChatTableViewCell.swift +++ b/NextcloudTalk/BaseChatTableViewCell.swift @@ -189,7 +189,9 @@ class BaseChatTableViewCell: UITableViewCell, AudioPlayerViewDelegate, Reactions self.titleLabel.attributedText = titleLabel - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() + guard let account = message.account + else { return } + let shouldShowDeliveryStatus = NCDatabaseManager.sharedInstance().roomHasTalkCapability(kCapabilityChatReadStatus, for: room) var shouldShowReadStatus = false @@ -221,7 +223,7 @@ class BaseChatTableViewCell: UITableViewCell, AudioPlayerViewDelegate, Reactions self.setDeliveryState(to: .failed) } else if message.isTemporary { self.setDeliveryState(to: .sending) - } else if message.isMessage(from: activeAccount.userId), shouldShowDeliveryStatus { + } else if message.isMessage(from: account.userId), shouldShowDeliveryStatus { if room.lastCommonReadMessage >= message.messageId, shouldShowReadStatus { self.setDeliveryState(to: .read) } else { From 1a3a4aad08dc6fe5a14bb760a390a210689c8ee2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=BCller?= Date: Sat, 9 Nov 2024 23:28:25 +0100 Subject: [PATCH 7/8] Assign token before internalId MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcel Müller --- NextcloudTalk/NCRoom.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NextcloudTalk/NCRoom.m b/NextcloudTalk/NCRoom.m index b919dfd59..ae60fff80 100644 --- a/NextcloudTalk/NCRoom.m +++ b/NextcloudTalk/NCRoom.m @@ -23,8 +23,8 @@ + (instancetype)roomWithDictionary:(NSDictionary *)roomDict andAccountId:(NSStri NCRoom *room = [[self alloc] init]; room.accountId = accountId; - room.internalId = [NSString stringWithFormat:@"%@@%@", room.accountId, room.token]; room.token = [roomDict objectForKey:@"token"]; + room.internalId = [NSString stringWithFormat:@"%@@%@", room.accountId, room.token]; room.type = (NCRoomType)[[roomDict objectForKey:@"type"] integerValue]; room.roomDescription = [roomDict objectForKey:@"description"]; room.hasPassword = [[roomDict objectForKey:@"hasPassword"] boolValue]; From 167fb425615757c27f5d65621c26a8f24b9f5e00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=BCller?= Date: Sun, 10 Nov 2024 00:10:34 +0100 Subject: [PATCH 8/8] Reduce usage of activeAccount in CallViewController MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcel Müller --- NextcloudTalk/CallViewController.swift | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/NextcloudTalk/CallViewController.swift b/NextcloudTalk/CallViewController.swift index 14a7bb796..aa649ba7c 100644 --- a/NextcloudTalk/CallViewController.swift +++ b/NextcloudTalk/CallViewController.swift @@ -259,13 +259,12 @@ class CallViewController: UIViewController, self.userDisabledSpeaker = true } - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() // 'conversation-permissions' capability was not added in Talk 13 release, so we check for 'direct-mention-flag' capability // as a workaround. let serverSupportsConversationPermissions = - NCDatabaseManager.sharedInstance().serverHasTalkCapability(kCapabilityConversationPermissions, forAccountId: activeAccount.accountId) || - NCDatabaseManager.sharedInstance().serverHasTalkCapability(kCapabilityDirectMentionFlag, forAccountId: activeAccount.accountId) + NCDatabaseManager.sharedInstance().serverHasTalkCapability(kCapabilityConversationPermissions, forAccountId: room.accountId) || + NCDatabaseManager.sharedInstance().serverHasTalkCapability(kCapabilityDirectMentionFlag, forAccountId: room.accountId) if serverSupportsConversationPermissions { self.setAudioMuteButtonEnabled(room.permissions.contains(.canPublishAudio)) @@ -278,7 +277,7 @@ class CallViewController: UIViewController, NotificationCenter.default.addObserver(self, selector: #selector(sensorStateChange(notification:)), name: UIDevice.proximityStateDidChangeNotification, object: nil) // callStartTime is only available if we have the "recording-v1" capability - if NCDatabaseManager.sharedInstance().serverHasTalkCapability(kCapabilityRecordingV1, forAccountId: activeAccount.accountId) { + if NCDatabaseManager.sharedInstance().serverHasTalkCapability(kCapabilityRecordingV1, forAccountId: room.accountId) { self.callDurationTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(callDurationTimerUpdate), userInfo: nil, repeats: true) } } @@ -829,9 +828,8 @@ class CallViewController: UIViewController, } // Connect to new call - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() NCRoomsManager.sharedInstance().updateRoom(token) { roomDict, error in - guard error == nil, let newRoom = NCRoom(dictionary: roomDict, andAccountId: activeAccount.accountId) + guard error == nil, let newRoom = NCRoom(dictionary: roomDict, andAccountId: self.room.accountId) else { print("Error getting room to switch") return @@ -1297,8 +1295,7 @@ class CallViewController: UIViewController, } // Send a reaction - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() - let serverCapabilities = NCDatabaseManager.sharedInstance().serverCapabilities(forAccountId: activeAccount.accountId) + let serverCapabilities = NCDatabaseManager.sharedInstance().serverCapabilities(forAccountId: room.accountId) // Disable swiftlint -> not supported on Realm object // swiftlint:disable:next empty_count @@ -1308,7 +1305,10 @@ class CallViewController: UIViewController, for reaction in callReactions { reactionItems.append(UIAction(title: String(reaction), handler: { [unowned self] _ in callController.sendReaction(reaction) - self.addReaction(reaction, fromUser: activeAccount.userDisplayName) + + if let account = room.account { + self.addReaction(reaction, fromUser: account.userDisplayName) + } })) } @@ -1906,9 +1906,7 @@ class CallViewController: UIViewController, func showChat() { if chatNavigationController == nil { - let activeAccount = NCDatabaseManager.sharedInstance().activeAccount() - - guard let room = NCDatabaseManager.sharedInstance().room(withToken: room.token, forAccountId: activeAccount.accountId), + guard let room = NCDatabaseManager.sharedInstance().room(withToken: room.token, forAccountId: room.accountId), let chatViewController = ChatViewController(for: room) else { return }