diff --git a/Session/Conversations/ConversationVC+Interaction.swift b/Session/Conversations/ConversationVC+Interaction.swift index 83b37ef40..deae7bea9 100644 --- a/Session/Conversations/ConversationVC+Interaction.swift +++ b/Session/Conversations/ConversationVC+Interaction.swift @@ -495,9 +495,12 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc let alert = UIAlertController(title: "Ban This User?", message: nil, preferredStyle: .alert) let threadID = thread.uniqueId! alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in - guard let openGroup = Storage.shared.getOpenGroup(for: threadID) else { return } let publicKey = message.authorId - OpenGroupAPI.ban(publicKey, from: openGroup.server).retainUntilComplete() + if let openGroupV2 = Storage.shared.getV2OpenGroup(for: threadID) { + OpenGroupAPIV2.ban(publicKey, from: openGroupV2.room, on: openGroupV2.server).retainUntilComplete() + } else if let openGroup = Storage.shared.getOpenGroup(for: threadID) { + OpenGroupAPI.ban(publicKey, from: openGroup.server).retainUntilComplete() + } })) alert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: nil)) present(alert, animated: true, completion: nil) diff --git a/Session/Conversations/ConversationViewItem.m b/Session/Conversations/ConversationViewItem.m index 2b013ef21..1c8713ae5 100644 --- a/Session/Conversations/ConversationViewItem.m +++ b/Session/Conversations/ConversationViewItem.m @@ -994,20 +994,32 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) // Get the open group SNOpenGroup *openGroup = [LKStorage.shared getOpenGroupForThreadID:groupThread.uniqueId]; - if (openGroup == nil) return; + SNOpenGroupV2 *openGroupV2 = [LKStorage.shared getV2OpenGroupForThreadID:groupThread.uniqueId]; + if (openGroup == nil && openGroupV2 == nil) return; // If it's an incoming message the user must have moderator status if (self.interaction.interactionType == OWSInteractionType_IncomingMessage) { NSString *userPublicKey = [LKStorage.shared getUserPublicKey]; - if (![SNOpenGroupAPI isUserModerator:userPublicKey forChannel:openGroup.channel onServer:openGroup.server]) { return; } + if (openGroupV2 != nil) { + if (![SNOpenGroupAPIV2 isUserModerator:userPublicKey forRoom:openGroupV2.room onServer:openGroupV2.server]) { return; } + } else if (openGroup != nil) { + if (![SNOpenGroupAPI isUserModerator:userPublicKey forChannel:openGroup.channel onServer:openGroup.server]) { return; } + } } // Delete the message BOOL wasSentByUser = (interationType == OWSInteractionType_OutgoingMessage); - [[SNOpenGroupAPI deleteMessageWithID:message.openGroupServerMessageID forGroup:openGroup.channel onServer:openGroup.server isSentByUser:wasSentByUser].catch(^(NSError *error) { - // Roll back - [self.interaction save]; - }) retainUntilComplete]; + if (openGroupV2 != nil) { + [[SNOpenGroupAPIV2 deleteMessageWithID:message.openGroupServerMessageID forRoom:openGroupV2.room onServer:openGroupV2.server isSentByUser:wasSentByUser].catch(^(NSError *error) { + // Roll back + [self.interaction save]; + }) retainUntilComplete]; + } else if (openGroup != nil) { + [[SNOpenGroupAPI deleteMessageWithID:message.openGroupServerMessageID forGroup:openGroup.channel onServer:openGroup.server isSentByUser:wasSentByUser].catch(^(NSError *error) { + // Roll back + [self.interaction save]; + }) retainUntilComplete]; + } } } @@ -1064,11 +1076,16 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) // Ensure we have the details needed to contact the server SNOpenGroup *openGroup = [LKStorage.shared getOpenGroupForThreadID:groupThread.uniqueId]; - if (openGroup == nil) return true; + SNOpenGroupV2 *openGroupV2 = [LKStorage.shared getV2OpenGroupForThreadID:groupThread.uniqueId]; + if (openGroup == nil && openGroupV2 == nil) return true; if (interationType == OWSInteractionType_IncomingMessage) { // Only allow deletion on incoming messages if the user has moderation permission - return [SNOpenGroupAPI isUserModerator:[SNGeneralUtilities getUserPublicKey] forChannel:openGroup.channel onServer:openGroup.server]; + if (openGroupV2 != nil) { + return [SNOpenGroupAPIV2 isUserModerator:[SNGeneralUtilities getUserPublicKey] forRoom:openGroupV2.room onServer:openGroupV2.server]; + } else { + return [SNOpenGroupAPI isUserModerator:[SNGeneralUtilities getUserPublicKey] forChannel:openGroup.channel onServer:openGroup.server]; + } } else { return YES; } @@ -1085,10 +1102,15 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) // Ensure we have the details needed to contact the server SNOpenGroup *openGroup = [LKStorage.shared getOpenGroupForThreadID:groupThread.uniqueId]; - if (openGroup == nil) return false; + SNOpenGroupV2 *openGroupV2 = [LKStorage.shared getV2OpenGroupForThreadID:groupThread.uniqueId]; + if (openGroup == nil && openGroupV2 == nil) return false; // Check that we're a moderator - return [SNOpenGroupAPI isUserModerator:[SNGeneralUtilities getUserPublicKey] forChannel:openGroup.channel onServer:openGroup.server]; + if (openGroupV2 != nil) { + return [SNOpenGroupAPIV2 isUserModerator:[SNGeneralUtilities getUserPublicKey] forRoom:openGroupV2.room onServer:openGroupV2.server]; + } else { + return [SNOpenGroupAPI isUserModerator:[SNGeneralUtilities getUserPublicKey] forChannel:openGroup.channel onServer:openGroup.server]; + } } @end diff --git a/Session/Conversations/Input View/InputView.swift b/Session/Conversations/Input View/InputView.swift index 9d957d566..9525a7b6c 100644 --- a/Session/Conversations/Input View/InputView.swift +++ b/Session/Conversations/Input View/InputView.swift @@ -309,7 +309,10 @@ final class InputView : UIView, InputViewButtonDelegate, InputTextViewDelegate, } func showMentionsUI(for candidates: [Mention], in thread: TSThread) { - if let openGroup = Storage.shared.getOpenGroup(for: thread.uniqueId!) { + if let openGroupV2 = Storage.shared.getV2OpenGroup(for: thread.uniqueId!) { + mentionsView.openGroupServer = openGroupV2.server + mentionsView.openGroupRoom = openGroupV2.room + } else if let openGroup = Storage.shared.getOpenGroup(for: thread.uniqueId!) { mentionsView.openGroupServer = openGroup.server mentionsView.openGroupChannel = openGroup.channel } diff --git a/Session/Conversations/Input View/MentionSelectionView.swift b/Session/Conversations/Input View/MentionSelectionView.swift index dc5eed141..26e31dd89 100644 --- a/Session/Conversations/Input View/MentionSelectionView.swift +++ b/Session/Conversations/Input View/MentionSelectionView.swift @@ -8,6 +8,7 @@ final class MentionSelectionView : UIView, UITableViewDataSource, UITableViewDel } var openGroupServer: String? var openGroupChannel: UInt64? + var openGroupRoom: String? var delegate: MentionSelectionViewDelegate? // MARK: Components @@ -66,6 +67,7 @@ final class MentionSelectionView : UIView, UITableViewDataSource, UITableViewDel cell.mentionCandidate = mentionCandidate cell.openGroupServer = openGroupServer cell.openGroupChannel = openGroupChannel + cell.openGroupRoom = openGroupRoom cell.separator.isHidden = (indexPath.row == (candidates.count - 1)) return cell } @@ -85,6 +87,7 @@ private extension MentionSelectionView { var mentionCandidate = Mention(publicKey: "", displayName: "") { didSet { update() } } var openGroupServer: String? var openGroupChannel: UInt64? + var openGroupRoom: String? // MARK: Components private lazy var profilePictureView = ProfilePictureView() @@ -159,7 +162,10 @@ private extension MentionSelectionView { displayNameLabel.text = mentionCandidate.displayName profilePictureView.publicKey = mentionCandidate.publicKey profilePictureView.update() - if let server = openGroupServer, let channel = openGroupChannel { + if let server = openGroupServer, let room = openGroupRoom { + let isUserModerator = OpenGroupAPIV2.isUserModerator(mentionCandidate.publicKey, for: room, on: server) + moderatorIconImageView.isHidden = !isUserModerator + } else if let server = openGroupServer, let channel = openGroupChannel { let isUserModerator = OpenGroupAPI.isUserModerator(mentionCandidate.publicKey, for: channel, on: server) moderatorIconImageView.isHidden = !isUserModerator } else { diff --git a/Session/Conversations/Message Cells/VisibleMessageCell.swift b/Session/Conversations/Message Cells/VisibleMessageCell.swift index bb0e6d370..9c0eb271c 100644 --- a/Session/Conversations/Message Cells/VisibleMessageCell.swift +++ b/Session/Conversations/Message Cells/VisibleMessageCell.swift @@ -218,10 +218,16 @@ final class VisibleMessageCell : MessageCell, LinkPreviewViewDelegate { if let senderSessionID = senderSessionID { profilePictureView.update(for: senderSessionID) } - if let thread = thread as? TSGroupThread, thread.isOpenGroup, - let openGroup = Storage.shared.getOpenGroup(for: thread.uniqueId!), let senderSessionID = senderSessionID { - let isUserModerator = OpenGroupAPI.isUserModerator(senderSessionID, for: openGroup.channel, on: openGroup.server) - moderatorIconImageView.isHidden = !isUserModerator || profilePictureView.isHidden + if let thread = thread as? TSGroupThread, thread.isOpenGroup, let senderSessionID = senderSessionID { + if let openGroupV2 = Storage.shared.getV2OpenGroup(for: thread.uniqueId!) { + let isUserModerator = OpenGroupAPIV2.isUserModerator(senderSessionID, for: openGroupV2.room, on: openGroupV2.server) + moderatorIconImageView.isHidden = !isUserModerator || profilePictureView.isHidden + } else if let openGroup = Storage.shared.getOpenGroup(for: thread.uniqueId!) { + let isUserModerator = OpenGroupAPI.isUserModerator(senderSessionID, for: openGroup.channel, on: openGroup.server) + moderatorIconImageView.isHidden = !isUserModerator || profilePictureView.isHidden + } else { + moderatorIconImageView.isHidden = true + } } else { moderatorIconImageView.isHidden = true } diff --git a/Session/Conversations/Views & Modals/ConversationTitleView.swift b/Session/Conversations/Views & Modals/ConversationTitleView.swift index 19392cef5..e7820d90a 100644 --- a/Session/Conversations/Views & Modals/ConversationTitleView.swift +++ b/Session/Conversations/Views & Modals/ConversationTitleView.swift @@ -100,7 +100,9 @@ final class ConversationTitleView : UIView { switch thread.groupModel.groupType { case .closedGroup: userCount = thread.groupModel.groupMemberIds.count case .openGroup: - if let openGroup = Storage.shared.getOpenGroup(for: self.thread.uniqueId!) { + if let openGroupV2 = Storage.shared.getV2OpenGroup(for: self.thread.uniqueId!) { + userCount = Storage.shared.getUserCount(forV2OpenGroupWithID: openGroup.id) + } else if let openGroup = Storage.shared.getOpenGroup(for: self.thread.uniqueId!) { userCount = Storage.shared.getUserCount(forOpenGroupWithID: openGroup.id) } default: break diff --git a/Session/Home/HomeVC.swift b/Session/Home/HomeVC.swift index 9fcff03ca..238a0f607 100644 --- a/Session/Home/HomeVC.swift +++ b/Session/Home/HomeVC.swift @@ -352,10 +352,13 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv } private func delete(_ thread: TSThread) { + let openGroupV2 = Storage.shared.getV2OpenGroup(for: thread.uniqueId!) let openGroup = Storage.shared.getOpenGroup(for: thread.uniqueId!) Storage.write { transaction in Storage.shared.cancelPendingMessageSendJobs(for: thread.uniqueId!, using: transaction) - if let openGroup = openGroup { + if let openGroupV2 = openGroupV2 { + OpenGroupManagerV2.shared.delete(openGroupV2, associatedWith: thread, using: transaction) + } else if let openGroup = openGroup { OpenGroupManager.shared.delete(openGroup, associatedWith: thread, using: transaction) } else if let thread = thread as? TSGroupThread, thread.isClosedGroup == true { let groupID = thread.groupModel.groupId diff --git a/Session/Meta/AppDelegate.m b/Session/Meta/AppDelegate.m index 65bbc43f8..df72f2c19 100644 --- a/Session/Meta/AppDelegate.m +++ b/Session/Meta/AppDelegate.m @@ -737,9 +737,13 @@ static NSTimeInterval launchStartedAt; - (void)startOpenGroupPollersIfNeeded { [SNOpenGroupManager.shared startPolling]; + [SNOpenGroupManagerV2.shared startPolling]; } -- (void)stopOpenGroupPollers { [SNOpenGroupManager.shared stopPolling]; } +- (void)stopOpenGroupPollers { + [SNOpenGroupManager.shared stopPolling]; + [SNOpenGroupManagerV2.shared stopPolling]; +} # pragma mark - App Mode @@ -789,7 +793,6 @@ static NSTimeInterval launchStartedAt; [self stopPoller]; [self stopClosedGroupPoller]; [self stopOpenGroupPollers]; - [SNOpenGroupManager.shared stopPolling]; BOOL wasUnlinked = [NSUserDefaults.standardUserDefaults boolForKey:@"wasUnlinked"]; [SignalApp resetAppData:^{ // Resetting the data clears the old user defaults. We need to restore the unlink default. diff --git a/Session/Utilities/BackgroundPoller.swift b/Session/Utilities/BackgroundPoller.swift index 31fcabd66..48c99245a 100644 --- a/Session/Utilities/BackgroundPoller.swift +++ b/Session/Utilities/BackgroundPoller.swift @@ -19,6 +19,12 @@ public final class BackgroundPoller : NSObject { poller.stop() promises.append(poller.pollForNewMessages(isBackgroundPoll: true)) } + let v2OpenGroups: [String:OpenGroupV2] = Storage.shared.getAllV2OpenGroups() + v2OpenGroups.values.forEach { openGroupV2 in + let poller = OpenGroupPollerV2(for: openGroupV2) + poller.stop() + promises.append(poller.pollForNewMessages(isBackgroundPoll: true)) + } when(resolved: promises).done { _ in completionHandler(.newData) }.catch { _ in diff --git a/Session/Utilities/MentionUtilities.swift b/Session/Utilities/MentionUtilities.swift index 6764634a4..7935d2179 100644 --- a/Session/Utilities/MentionUtilities.swift +++ b/Session/Utilities/MentionUtilities.swift @@ -10,6 +10,7 @@ public final class MentionUtilities : NSObject { @objc public static func highlightMentions(in string: String, isOutgoingMessage: Bool, threadID: String, attributes: [NSAttributedString.Key:Any]) -> NSAttributedString { let openGroup = Storage.shared.getOpenGroup(for: threadID) + let openGroupV2 = Storage.shared.getV2OpenGroup(for: threadID) OWSPrimaryStorage.shared().dbReadConnection.read { transaction in MentionsManager.populateUserPublicKeyCacheIfNeeded(for: threadID, in: transaction) } @@ -22,7 +23,7 @@ public final class MentionUtilities : NSObject { let publicKey = String((string as NSString).substring(with: match.range).dropFirst()) // Drop the @ let matchEnd: Int if knownPublicKeys.contains(publicKey) { - let context: Contact.Context = (openGroup != nil) ? .openGroup : .regular + let context: Contact.Context = (openGroupV2 != nil || openGroup != nil) ? .openGroup : .regular let displayName = Storage.shared.getContact(with: publicKey)?.displayName(for: context) if let displayName = displayName { string = (string as NSString).replacingCharacters(in: match.range, with: "@\(displayName)") diff --git a/SessionMessagingKit/Sending & Receiving/Mentions/MentionsManager.swift b/SessionMessagingKit/Sending & Receiving/Mentions/MentionsManager.swift index bd509c784..820cdf93a 100644 --- a/SessionMessagingKit/Sending & Receiving/Mentions/MentionsManager.swift +++ b/SessionMessagingKit/Sending & Receiving/Mentions/MentionsManager.swift @@ -31,9 +31,10 @@ public final class MentionsManager : NSObject { var candidates: [Mention] = [] // Gather candidates let openGroup = Storage.shared.getOpenGroup(for: threadID) + let openGroupV2 = Storage.shared.getV2OpenGroup(for: threadID) storage.dbReadConnection.read { transaction in candidates = cache.compactMap { publicKey in - let context: Contact.Context = (openGroup != nil) ? .openGroup : .regular + let context: Contact.Context = (openGroupV2 != nil || openGroup != nil) ? .openGroup : .regular let displayNameOrNil = Storage.shared.getContact(with: publicKey)?.displayName(for: context) guard let displayName = displayNameOrNil else { return nil } guard !displayName.hasPrefix("Anonymous") else { return nil } diff --git a/SignalUtilitiesKit/Messaging/ConfigurationMessage+Convenience.swift b/SignalUtilitiesKit/Messaging/ConfigurationMessage+Convenience.swift index 0e52dbab0..234ae89b0 100644 --- a/SignalUtilitiesKit/Messaging/ConfigurationMessage+Convenience.swift +++ b/SignalUtilitiesKit/Messaging/ConfigurationMessage+Convenience.swift @@ -27,6 +27,7 @@ extension ConfigurationMessage { case .openGroup: guard let openGroup = storage.getOpenGroup(for: thread.uniqueId!) else { return } openGroups.insert(openGroup.server) + // TODO: V2 open groups default: break } } diff --git a/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSender+Convenience.swift b/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSender+Convenience.swift index 85d81eaee..fa0d6baa7 100644 --- a/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSender+Convenience.swift +++ b/SignalUtilitiesKit/Messaging/Sending & Receiving/MessageSender+Convenience.swift @@ -43,7 +43,8 @@ extension MessageSender { let attachmentsToUpload = attachments.filter { !$0.isUploaded } let attachmentUploadPromises: [Promise] = attachmentsToUpload.map { stream in let openGroup = SNMessagingKitConfiguration.shared.storage.getOpenGroup(for: thread.uniqueId!) - let server = openGroup?.server ?? FileServerAPI.server + let openGroupV2 = SNMessagingKitConfiguration.shared.storage.getV2OpenGroup(for: thread.uniqueId!) + let server = openGroupV2?.server ?? openGroup?.server ?? FileServerAPI.server // FIXME: This is largely a duplication of the code in AttachmentUploadJob let maxRetryCount: UInt = (openGroup != nil) ? 24 : 8 return attempt(maxRetryCount: maxRetryCount, recoveringOn: DispatchQueue.global(qos: .userInitiated)) {