Replace PublicChatManager
This commit is contained in:
parent
b8d9334d19
commit
e38dae5a05
|
@ -295,6 +295,7 @@
|
|||
B8CA011525A293800091AF73 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8CA011425A293800091AF73 /* Configuration.swift */; };
|
||||
B8CA011F25A2939F0091AF73 /* SharedSenderKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8CA011E25A2939F0091AF73 /* SharedSenderKeys.swift */; };
|
||||
B8CA014125A293EE0091AF73 /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8CA014025A293EE0091AF73 /* Storage.swift */; };
|
||||
B8CADAE925AFADF400AAFA15 /* OpenGroupManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3AAFFCB25AE92150089E6DD /* OpenGroupManager.swift */; };
|
||||
B8CCF6352396005F0091D419 /* SpaceMono-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = B8CCF6342396005F0091D419 /* SpaceMono-Regular.ttf */; };
|
||||
B8CCF63723961D6D0091D419 /* NewPrivateChatVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8CCF63623961D6D0091D419 /* NewPrivateChatVC.swift */; };
|
||||
B8CCF63F23975CFB0091D419 /* JoinPublicChatVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8CCF63E23975CFB0091D419 /* JoinPublicChatVC.swift */; };
|
||||
|
@ -475,7 +476,6 @@
|
|||
C33FDC95255A582000E217F9 /* OWSFailedMessagesJob.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDADB255A580400E217F9 /* OWSFailedMessagesJob.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C33FDC96255A582000E217F9 /* NSObject+Casting.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDADC255A580400E217F9 /* NSObject+Casting.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C33FDC98255A582000E217F9 /* SwiftSingletons.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDADE255A580400E217F9 /* SwiftSingletons.swift */; };
|
||||
C33FDC99255A582000E217F9 /* PublicChatManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDADF255A580400E217F9 /* PublicChatManager.swift */; };
|
||||
C33FDC9A255A582000E217F9 /* ByteParser.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDAE0255A580400E217F9 /* ByteParser.m */; };
|
||||
C33FDCA2255A582000E217F9 /* OWSMessageUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDAE8255A580500E217F9 /* OWSMessageUtils.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C33FDCC7255A582000E217F9 /* NSArray+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB0D255A580800E217F9 /* NSArray+OWS.m */; };
|
||||
|
@ -718,7 +718,6 @@
|
|||
C3A7229C2558E4310043A11F /* OpenGroupMessage+Conversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3A7229B2558E4310043A11F /* OpenGroupMessage+Conversion.swift */; };
|
||||
C3AABDDF2553ECF00042FF4C /* Array+Description.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2A5D12553860800C340D1 /* Array+Description.swift */; };
|
||||
C3AAFFC225AE916D0089E6DD /* OpenGroupManagerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3AAFFC125AE916D0089E6DD /* OpenGroupManagerProtocol.swift */; };
|
||||
C3AAFFD525AE92860089E6DD /* OpenGroupManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3AAFFCB25AE92150089E6DD /* OpenGroupManager.swift */; };
|
||||
C3AAFFE825AE975D0089E6DD /* ConfigurationMessage+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3AAFFDE25AE96FF0089E6DD /* ConfigurationMessage+Convenience.swift */; };
|
||||
C3AAFFF225AE99710089E6DD /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3AAFFF125AE99710089E6DD /* AppDelegate.swift */; };
|
||||
C3BBE0762554CDA60050F1E3 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3BBE0752554CDA60050F1E3 /* Configuration.swift */; };
|
||||
|
@ -1391,7 +1390,6 @@
|
|||
C33FDADC255A580400E217F9 /* NSObject+Casting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+Casting.h"; sourceTree = "<group>"; };
|
||||
C33FDADD255A580400E217F9 /* TSInfoMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSInfoMessage.h; sourceTree = "<group>"; };
|
||||
C33FDADE255A580400E217F9 /* SwiftSingletons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftSingletons.swift; sourceTree = "<group>"; };
|
||||
C33FDADF255A580400E217F9 /* PublicChatManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PublicChatManager.swift; sourceTree = "<group>"; };
|
||||
C33FDAE0255A580400E217F9 /* ByteParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ByteParser.m; sourceTree = "<group>"; };
|
||||
C33FDAE1255A580400E217F9 /* OWSReadTracking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSReadTracking.h; sourceTree = "<group>"; };
|
||||
C33FDAE4255A580400E217F9 /* TSAttachmentStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSAttachmentStream.h; sourceTree = "<group>"; };
|
||||
|
@ -3118,8 +3116,6 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
C33FDB19255A580900E217F9 /* GroupUtilities.swift */,
|
||||
C33FDADF255A580400E217F9 /* PublicChatManager.swift */,
|
||||
C3AAFFCB25AE92150089E6DD /* OpenGroupManager.swift */,
|
||||
C38EF3E5255B6DF4007E1867 /* ContactCellView.h */,
|
||||
C38EF3D6255B6DEF007E1867 /* ContactCellView.m */,
|
||||
C38EF3E6255B6DF4007E1867 /* ContactTableViewCell.h */,
|
||||
|
@ -3197,6 +3193,7 @@
|
|||
C3A721362558BDFA0043A11F /* OpenGroupInfo.swift */,
|
||||
C3A721342558BDF90043A11F /* OpenGroupMessage.swift */,
|
||||
C3A7229B2558E4310043A11F /* OpenGroupMessage+Conversion.swift */,
|
||||
C3AAFFCB25AE92150089E6DD /* OpenGroupManager.swift */,
|
||||
);
|
||||
path = "Open Groups";
|
||||
sourceTree = "<group>";
|
||||
|
@ -4640,7 +4637,6 @@
|
|||
C38EF3C3255B6DE7007E1867 /* ImageEditorTextItem.swift in Sources */,
|
||||
C33FDC7D255A582000E217F9 /* OWSDispatch.m in Sources */,
|
||||
C38EF247255B6D67007E1867 /* NSAttributedString+OWS.m in Sources */,
|
||||
C33FDC99255A582000E217F9 /* PublicChatManager.swift in Sources */,
|
||||
C33FDD49255A582000E217F9 /* ParamParser.swift in Sources */,
|
||||
C38EF35F255B6DCC007E1867 /* SelectRecipientViewController.m in Sources */,
|
||||
C38EF3C5255B6DE7007E1867 /* OWSViewController+ImageEditor.swift in Sources */,
|
||||
|
@ -4709,7 +4705,6 @@
|
|||
C33FDCFA255A582000E217F9 /* SignalIOSProto.swift in Sources */,
|
||||
C33FDD13255A582000E217F9 /* OWSFailedAttachmentDownloadsJob.m in Sources */,
|
||||
C38EF24D255B6D67007E1867 /* UIView+OWS.swift in Sources */,
|
||||
C3AAFFD525AE92860089E6DD /* OpenGroupManager.swift in Sources */,
|
||||
C38EF408255B6DF7007E1867 /* OWSSearchBar.m in Sources */,
|
||||
C38EF327255B6DBF007E1867 /* BlockListUIUtils.m in Sources */,
|
||||
C38EF310255B6DBF007E1867 /* DebugLogger.m in Sources */,
|
||||
|
@ -4927,6 +4922,7 @@
|
|||
C32C5EDC256DF501003C73A2 /* YapDatabaseConnection+OWS.m in Sources */,
|
||||
C3BBE0762554CDA60050F1E3 /* Configuration.swift in Sources */,
|
||||
B8B32033258B235D0020074B /* Storage+Contacts.swift in Sources */,
|
||||
B8CADAE925AFADF400AAFA15 /* OpenGroupManager.swift in Sources */,
|
||||
B8856D69256F141F001CE70E /* OWSWindowManager.m in Sources */,
|
||||
C3D9E3BE25676AD70040E4F3 /* TSAttachmentPointer.m in Sources */,
|
||||
C3ECBF7B257056B700EA7FCE /* Threading.swift in Sources */,
|
||||
|
|
|
@ -395,45 +395,14 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, UIScrol
|
|||
|
||||
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
|
||||
guard let thread = self.thread(at: indexPath.row) else { return [] }
|
||||
let openGroup = Storage.shared.getOpenGroup(for: thread.uniqueId!)
|
||||
let delete = UITableViewRowAction(style: .destructive, title: NSLocalizedString("TXT_DELETE_TITLE", comment: "")) { [weak self] _, _ in
|
||||
var message = NSLocalizedString("CONVERSATION_DELETE_CONFIRMATION_ALERT_MESSAGE", comment: "")
|
||||
if let thread = thread as? TSGroupThread, thread.isClosedGroup, thread.groupModel.groupAdminIds.contains(getUserHexEncodedPublicKey()) {
|
||||
message = "Because you are the creator of this group it will be deleted for everyone. This cannot be undone."
|
||||
}
|
||||
let alert = UIAlertController(title: NSLocalizedString("CONVERSATION_DELETE_CONFIRMATION_ALERT_TITLE", comment: ""), message: message, preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: NSLocalizedString("TXT_DELETE_TITLE", comment: ""), style: .destructive) { _ in
|
||||
Storage.write { transaction in
|
||||
Storage.shared.cancelPendingMessageSendJobs(for: thread.uniqueId!, using: transaction)
|
||||
if let openGroup = openGroup {
|
||||
var messageIDs: Set<String> = []
|
||||
thread.enumerateInteractions(with: transaction) { interaction, _ in
|
||||
messageIDs.insert(interaction.uniqueId!)
|
||||
}
|
||||
OWSPrimaryStorage.shared().updateMessageIDCollectionByPruningMessagesWithIDs(messageIDs, in: transaction)
|
||||
transaction.removeObject(forKey: "\(openGroup.server).\(openGroup.channel)", inCollection: Storage.lastMessageServerIDCollection)
|
||||
transaction.removeObject(forKey: "\(openGroup.server).\(openGroup.channel)", inCollection: Storage.lastDeletionServerIDCollection)
|
||||
let _ = OpenGroupAPI.leave(openGroup.channel, on: openGroup.server)
|
||||
thread.removeAllThreadInteractions(with: transaction)
|
||||
thread.remove(with: transaction)
|
||||
} else if let thread = thread as? TSGroupThread, thread.isClosedGroup == true {
|
||||
let groupID = thread.groupModel.groupId
|
||||
let groupPublicKey = LKGroupUtilities.getDecodedGroupID(groupID)
|
||||
do {
|
||||
try MessageSender.leave(groupPublicKey, using: transaction)
|
||||
} catch {
|
||||
// TODO: Handle
|
||||
}
|
||||
Storage.write { transaction in
|
||||
thread.removeAllThreadInteractions(with: transaction)
|
||||
thread.remove(with: transaction)
|
||||
}
|
||||
} else {
|
||||
thread.removeAllThreadInteractions(with: transaction)
|
||||
thread.remove(with: transaction)
|
||||
}
|
||||
}
|
||||
NotificationCenter.default.post(name: .threadDeleted, object: nil, userInfo: [ "threadId" : thread.uniqueId! ])
|
||||
alert.addAction(UIAlertAction(title: NSLocalizedString("TXT_DELETE_TITLE", comment: ""), style: .destructive) { [weak self] _ in
|
||||
self?.delete(thread)
|
||||
})
|
||||
alert.addAction(UIAlertAction(title: NSLocalizedString("TXT_CANCEL_TITLE", comment: ""), style: .default) { _ in })
|
||||
guard let self = self else { return }
|
||||
|
@ -460,6 +429,29 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, UIScrol
|
|||
}
|
||||
}
|
||||
|
||||
private func delete(_ thread: TSThread) {
|
||||
let openGroup = Storage.shared.getOpenGroup(for: thread.uniqueId!)
|
||||
Storage.write { transaction in
|
||||
Storage.shared.cancelPendingMessageSendJobs(for: thread.uniqueId!, using: transaction)
|
||||
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
|
||||
let groupPublicKey = LKGroupUtilities.getDecodedGroupID(groupID)
|
||||
do {
|
||||
try MessageSender.leave(groupPublicKey, using: transaction)
|
||||
} catch {
|
||||
// TODO: Handle
|
||||
}
|
||||
thread.removeAllThreadInteractions(with: transaction)
|
||||
thread.remove(with: transaction)
|
||||
} else {
|
||||
thread.removeAllThreadInteractions(with: transaction)
|
||||
thread.remove(with: transaction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func openSettings() {
|
||||
let settingsVC = SettingsVC()
|
||||
let navigationController = OWSNavigationController(rootViewController: settingsVC)
|
||||
|
|
|
@ -756,10 +756,10 @@ static NSTimeInterval launchStartedAt;
|
|||
|
||||
- (void)startOpenGroupPollersIfNeeded
|
||||
{
|
||||
[LKPublicChatManager.shared startPollersIfNeeded];
|
||||
[SNOpenGroupManager.shared startPolling];
|
||||
}
|
||||
|
||||
- (void)stopOpenGroupPollers { [LKPublicChatManager.shared stopPollers]; }
|
||||
- (void)stopOpenGroupPollers { [SNOpenGroupManager.shared stopPolling]; }
|
||||
|
||||
# pragma mark - App Mode
|
||||
|
||||
|
@ -813,7 +813,7 @@ static NSTimeInterval launchStartedAt;
|
|||
[self stopPoller];
|
||||
[self stopClosedGroupPoller];
|
||||
[self stopOpenGroupPollers];
|
||||
[LKPublicChatManager.shared stopPollers];
|
||||
[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.
|
||||
|
|
|
@ -13,6 +13,7 @@ extension AppDelegate {
|
|||
let job = MessageSendJob(message: configurationMessage, destination: destination)
|
||||
JobQueue.shared.add(job, using: transaction)
|
||||
}
|
||||
userDefaults[.lastConfigurationSync] = Date()
|
||||
}
|
||||
|
||||
func forceSyncConfigurationNowIfNeeded() -> Promise<Void> {
|
||||
|
|
|
@ -132,11 +132,9 @@ final class JoinPublicChatVC : BaseVC, UIPageViewControllerDataSource, UIPageVie
|
|||
}
|
||||
isJoining = true
|
||||
ModalActivityIndicatorViewController.present(fromViewController: navigationController!, canCancel: false) { [weak self] _ in
|
||||
Storage.shared.write { transaction in
|
||||
OpenGroupManager.shared.addOpenGroup(with: urlAsString, using: transaction)
|
||||
Storage.shared.write(with: { transaction in
|
||||
OpenGroupManager.shared.add(with: urlAsString, using: transaction)
|
||||
.done(on: DispatchQueue.main) { [weak self] _ in
|
||||
let appDelegate = UIApplication.shared.delegate as! AppDelegate
|
||||
appDelegate.forceSyncConfigurationNowIfNeeded().retainUntilComplete() // FIXME: It's probably cleaner to do this inside addOpenGroup(...)
|
||||
self?.presentingViewController!.dismiss(animated: true, completion: nil)
|
||||
}
|
||||
.catch(on: DispatchQueue.main) { [weak self] error in
|
||||
|
@ -150,7 +148,10 @@ final class JoinPublicChatVC : BaseVC, UIPageViewControllerDataSource, UIPageVie
|
|||
self?.isJoining = false
|
||||
self?.showError(title: title, message: message)
|
||||
}
|
||||
}
|
||||
}, completion: {
|
||||
let appDelegate = UIApplication.shared.delegate as! AppDelegate
|
||||
appDelegate.forceSyncConfigurationNowIfNeeded().retainUntilComplete() // FIXME: It's probably cleaner to do this inside addOpenGroup(...)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -116,16 +116,6 @@ extension Storage {
|
|||
(transaction as! YapDatabaseReadWriteTransaction).removeObject(forKey: server, inCollection: Storage.openGroupPublicKeyCollection)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// MARK: - Deletion
|
||||
|
||||
public func clearAllData(for group: UInt64, on server: String, using transaction: Any) {
|
||||
removeLastMessageServerID(for: group, on: server, using: transaction)
|
||||
removeLastDeletionServerID(for: group, on: server, using: transaction)
|
||||
removeOpenGroupPublicKey(for: server, using: transaction)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// MARK: - Last Message Server ID
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
import PromiseKit
|
||||
|
||||
@objc(SNOpenGroupManager)
|
||||
public final class OpenGroupManager : NSObject, OpenGroupManagerProtocol {
|
||||
private var pollers: [String:OpenGroupPoller] = [:]
|
||||
private var isPolling = false
|
||||
|
||||
// MARK: Error
|
||||
public enum Error : LocalizedError {
|
||||
case invalidURL
|
||||
|
||||
public var errorDescription: String? {
|
||||
switch self {
|
||||
case .invalidURL: return "Invalid URL."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Initialization
|
||||
@objc public static let shared = OpenGroupManager()
|
||||
|
||||
private override init() { }
|
||||
|
||||
// MARK: Polling
|
||||
@objc public func startPolling() {
|
||||
guard !isPolling else { return }
|
||||
isPolling = true
|
||||
let openGroups = Storage.shared.getAllUserOpenGroups()
|
||||
for (_, openGroup) in openGroups {
|
||||
if let poller = pollers[openGroup.id] { poller.stop() } // Should never occur
|
||||
let poller = OpenGroupPoller(for: openGroup)
|
||||
poller.startIfNeeded()
|
||||
pollers[openGroup.id] = poller
|
||||
}
|
||||
}
|
||||
|
||||
@objc public func stopPolling() {
|
||||
pollers.forEach { (_, openGroupPoller) in openGroupPoller.stop() }
|
||||
pollers.removeAll()
|
||||
}
|
||||
|
||||
// MARK: Adding & Removing
|
||||
public func add(with url: String, using transaction: Any) -> Promise<Void> {
|
||||
guard let url = URL(string: url), let scheme = url.scheme, scheme == "https", url.host != nil else {
|
||||
return Promise(error: Error.invalidURL)
|
||||
}
|
||||
let channel: UInt64 = 1
|
||||
let server = url.absoluteString
|
||||
let userPublicKey = getUserHexEncodedPublicKey()
|
||||
let profileManager = SSKEnvironment.shared.profileManager
|
||||
let displayName = profileManager.profileNameForRecipient(withID: userPublicKey)
|
||||
let profilePictureURL = profileManager.profilePictureURL()
|
||||
let profileKey = profileManager.localProfileKey().keyData
|
||||
Storage.shared.removeLastMessageServerID(for: channel, on: server, using: transaction)
|
||||
Storage.shared.removeLastDeletionServerID(for: channel, on: server, using: transaction)
|
||||
return OpenGroupAPI.getInfo(for: channel, on: server).done { info in
|
||||
let openGroup = OpenGroup(channel: channel, server: server, displayName: info.displayName, isDeletable: true)!
|
||||
let groupID = LKGroupUtilities.getEncodedOpenGroupIDAsData(openGroup.id)
|
||||
let model = TSGroupModel(title: openGroup.displayName, memberIds: [ userPublicKey ], image: nil, groupId: groupID, groupType: .openGroup, adminIds: [])
|
||||
Storage.shared.write(with: { transaction in
|
||||
let thread = TSGroupThread.getOrCreateThread(with: model, transaction: transaction as! YapDatabaseReadWriteTransaction)
|
||||
Storage.shared.setOpenGroup(openGroup, for: thread.uniqueId!, using: transaction)
|
||||
}, completion: {
|
||||
let _ = OpenGroupAPI.setDisplayName(to: displayName, on: server)
|
||||
let _ = OpenGroupAPI.setProfilePictureURL(to: profilePictureURL, using: profileKey, on: server)
|
||||
let _ = OpenGroupAPI.join(channel, on: server)
|
||||
if let poller = OpenGroupManager.shared.pollers[openGroup.id] {
|
||||
poller.stop()
|
||||
OpenGroupManager.shared.pollers[openGroup.id] = nil
|
||||
}
|
||||
let poller = OpenGroupPoller(for: openGroup)
|
||||
poller.startIfNeeded()
|
||||
OpenGroupManager.shared.pollers[openGroup.id] = poller
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
public func delete(_ openGroup: OpenGroup, associatedWith thread: TSThread, using transaction: YapDatabaseReadWriteTransaction) {
|
||||
if let poller = pollers[openGroup.id] {
|
||||
poller.stop()
|
||||
pollers[openGroup.id] = nil
|
||||
}
|
||||
var messageIDs: Set<String> = []
|
||||
thread.enumerateInteractions(with: transaction) { interaction, _ in
|
||||
messageIDs.insert(interaction.uniqueId!)
|
||||
}
|
||||
SNMessagingKitConfiguration.shared.storage.updateMessageIDCollectionByPruningMessagesWithIDs(messageIDs, using: transaction)
|
||||
Storage.shared.removeLastMessageServerID(for: openGroup.channel, on: openGroup.server, using: transaction)
|
||||
Storage.shared.removeLastDeletionServerID(for: openGroup.channel, on: openGroup.server, using: transaction)
|
||||
let _ = OpenGroupAPI.leave(openGroup.channel, on: openGroup.server)
|
||||
Storage.shared.removeOpenGroupPublicKey(for: openGroup.server, using: transaction)
|
||||
thread.removeAllThreadInteractions(with: transaction)
|
||||
thread.remove(with: transaction)
|
||||
Storage.shared.removeOpenGroup(for: thread.uniqueId!, using: transaction)
|
||||
}
|
||||
}
|
|
@ -2,5 +2,5 @@ import PromiseKit
|
|||
|
||||
public protocol OpenGroupManagerProtocol {
|
||||
|
||||
func addOpenGroup(with url: String, using transaction: Any) -> Promise<Void>
|
||||
func add(with url: String, using transaction: Any) -> Promise<Void>
|
||||
}
|
||||
|
|
|
@ -92,22 +92,6 @@ extension MessageReceiver {
|
|||
}
|
||||
}
|
||||
|
||||
private static func handleConfigurationMessage(_ message: ConfigurationMessage, using transaction: Any) {
|
||||
guard message.sender == getUserHexEncodedPublicKey() else { return }
|
||||
let storage = SNMessagingKitConfiguration.shared.storage
|
||||
let allClosedGroupPublicKeys = storage.getUserClosedGroupPublicKeys()
|
||||
for closedGroup in message.closedGroups {
|
||||
guard !allClosedGroupPublicKeys.contains(closedGroup.publicKey) else { continue }
|
||||
handleNewClosedGroup(groupPublicKey: closedGroup.publicKey, name: closedGroup.name, encryptionKeyPair: closedGroup.encryptionKeyPair,
|
||||
members: [String](closedGroup.members), admins: [String](closedGroup.admins), using: transaction)
|
||||
}
|
||||
let allOpenGroups = Set(storage.getAllUserOpenGroups().keys)
|
||||
for openGroupURL in message.openGroups {
|
||||
guard !allOpenGroups.contains(openGroupURL) else { continue }
|
||||
SNMessagingKitConfiguration.shared.openGroupManager.addOpenGroup(with: openGroupURL, using: transaction).retainUntilComplete()
|
||||
}
|
||||
}
|
||||
|
||||
public static func setExpirationTimer(to duration: UInt32, for senderPublicKey: String, groupPublicKey: String?, using transaction: Any) {
|
||||
let transaction = transaction as! YapDatabaseReadWriteTransaction
|
||||
var isGroup = false
|
||||
|
@ -151,6 +135,22 @@ extension MessageReceiver {
|
|||
message.save(with: transaction)
|
||||
SSKEnvironment.shared.disappearingMessagesJob.startIfNecessary()
|
||||
}
|
||||
|
||||
private static func handleConfigurationMessage(_ message: ConfigurationMessage, using transaction: Any) {
|
||||
guard message.sender == getUserHexEncodedPublicKey() else { return }
|
||||
let storage = SNMessagingKitConfiguration.shared.storage
|
||||
let allClosedGroupPublicKeys = storage.getUserClosedGroupPublicKeys()
|
||||
for closedGroup in message.closedGroups {
|
||||
guard !allClosedGroupPublicKeys.contains(closedGroup.publicKey) else { continue }
|
||||
handleNewClosedGroup(groupPublicKey: closedGroup.publicKey, name: closedGroup.name, encryptionKeyPair: closedGroup.encryptionKeyPair,
|
||||
members: [String](closedGroup.members), admins: [String](closedGroup.admins), using: transaction)
|
||||
}
|
||||
let allOpenGroups = Set(storage.getAllUserOpenGroups().keys)
|
||||
for openGroupURL in message.openGroups {
|
||||
guard !allOpenGroups.contains(openGroupURL) else { continue }
|
||||
SNMessagingKitConfiguration.shared.openGroupManager.add(with: openGroupURL, using: transaction).retainUntilComplete()
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
public static func handleVisibleMessage(_ message: VisibleMessage, associatedWithProto proto: SNProtoContent, openGroupID: String?, isBackgroundPoll: Bool, using transaction: Any) throws -> String {
|
||||
|
|
|
@ -53,6 +53,7 @@ public protocol SessionMessagingKitStorageProtocol {
|
|||
func getAllUserOpenGroups() -> [String:OpenGroup]
|
||||
func getOpenGroup(for threadID: String) -> OpenGroup?
|
||||
func getThreadID(for openGroupID: String) -> String?
|
||||
func updateMessageIDCollectionByPruningMessagesWithIDs(_ messageIDs: Set<String>, using transaction: Any)
|
||||
|
||||
// MARK: - Open Group Public Keys
|
||||
|
||||
|
|
|
@ -1,2 +1,8 @@
|
|||
|
||||
extension Storage : SessionMessagingKitStorageProtocol, SessionProtocolKitStorageProtocol, SessionSnodeKitStorageProtocol { }
|
||||
extension Storage : SessionMessagingKitStorageProtocol, SessionProtocolKitStorageProtocol, SessionSnodeKitStorageProtocol {
|
||||
|
||||
public func updateMessageIDCollectionByPruningMessagesWithIDs(_ messageIDs: Set<String>, using transaction: Any) {
|
||||
let transaction = transaction as! YapDatabaseReadWriteTransaction
|
||||
OWSPrimaryStorage.shared().updateMessageIDCollectionByPruningMessagesWithIDs(messageIDs, in: transaction)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
import PromiseKit
|
||||
|
||||
public final class OpenGroupManager : OpenGroupManagerProtocol {
|
||||
|
||||
public enum Error : LocalizedError {
|
||||
case invalidURL
|
||||
|
||||
public var errorDescription: String? {
|
||||
switch self {
|
||||
case .invalidURL: return "Invalid URL."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static let shared = OpenGroupManager()
|
||||
|
||||
private init() { }
|
||||
|
||||
public func addOpenGroup(with url: String, using transaction: Any) -> Promise<Void> {
|
||||
guard let url = URL(string: url), let scheme = url.scheme, scheme == "https", url.host != nil else {
|
||||
return Promise(error: Error.invalidURL)
|
||||
}
|
||||
let channelID: UInt64 = 1
|
||||
let urlAsString = url.absoluteString
|
||||
let userPublicKey = getUserHexEncodedPublicKey()
|
||||
let profileManager = OWSProfileManager.shared()
|
||||
let displayName = profileManager.profileNameForRecipient(withID: userPublicKey)
|
||||
let profilePictureURL = profileManager.profilePictureURL()
|
||||
let profileKey = profileManager.localProfileKey().keyData
|
||||
let transaction = transaction as! YapDatabaseReadWriteTransaction
|
||||
transaction.removeObject(forKey: "\(urlAsString).\(channelID)", inCollection: Storage.lastMessageServerIDCollection)
|
||||
transaction.removeObject(forKey: "\(urlAsString).\(channelID)", inCollection: Storage.lastDeletionServerIDCollection)
|
||||
return PublicChatManager.shared.addChat(server: urlAsString, channel: channelID).done(on: DispatchQueue.main) { _ in
|
||||
let _ = OpenGroupAPI.setDisplayName(to: displayName, on: urlAsString)
|
||||
let _ = OpenGroupAPI.setProfilePictureURL(to: profilePictureURL, using: profileKey, on: urlAsString)
|
||||
let _ = OpenGroupAPI.join(channelID, on: urlAsString)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,131 +0,0 @@
|
|||
import PromiseKit
|
||||
|
||||
// TODO: Clean
|
||||
|
||||
@objc(LKPublicChatManager)
|
||||
public final class PublicChatManager : NSObject {
|
||||
private let storage = OWSPrimaryStorage.shared()
|
||||
@objc public var chats: [String:OpenGroup] = [:]
|
||||
private var pollers: [String:OpenGroupPoller] = [:]
|
||||
private var isPolling = false
|
||||
|
||||
private var userHexEncodedPublicKey: String? {
|
||||
return OWSIdentityManager.shared().identityKeyPair()?.hexEncodedPublicKey
|
||||
}
|
||||
|
||||
public enum Error : Swift.Error {
|
||||
case chatCreationFailed
|
||||
case userPublicKeyNotFound
|
||||
}
|
||||
|
||||
@objc public static let shared = PublicChatManager()
|
||||
|
||||
private override init() {
|
||||
super.init()
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(onThreadDeleted(_:)), name: .threadDeleted, object: nil)
|
||||
refreshChatsAndPollers()
|
||||
}
|
||||
|
||||
deinit {
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
}
|
||||
|
||||
@objc public func startPollersIfNeeded() {
|
||||
for (threadID, publicChat) in chats {
|
||||
if let poller = pollers[threadID] {
|
||||
poller.startIfNeeded()
|
||||
} else {
|
||||
let poller = OpenGroupPoller(for: publicChat)
|
||||
poller.startIfNeeded()
|
||||
pollers[threadID] = poller
|
||||
}
|
||||
}
|
||||
isPolling = true
|
||||
}
|
||||
|
||||
@objc public func stopPollers() {
|
||||
for poller in pollers.values { poller.stop() }
|
||||
isPolling = false
|
||||
}
|
||||
|
||||
public func addChat(server: String, channel: UInt64) -> Promise<OpenGroup> {
|
||||
if let existingChat = getChat(server: server, channel: channel) {
|
||||
if let newChat = self.addChat(server: server, channel: channel, name: existingChat.displayName) {
|
||||
return Promise.value(newChat)
|
||||
} else {
|
||||
return Promise(error: Error.chatCreationFailed)
|
||||
}
|
||||
}
|
||||
return OpenGroupAPI.getInfo(for: channel, on: server).map2 { channelInfo -> OpenGroup in
|
||||
guard let chat = self.addChat(server: server, channel: channel, name: channelInfo.displayName) else { throw Error.chatCreationFailed }
|
||||
return chat
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
@objc(addChatWithServer:channel:name:)
|
||||
public func addChat(server: String, channel: UInt64, name: String) -> OpenGroup? {
|
||||
guard let chat = OpenGroup(channel: channel, server: server, displayName: name, isDeletable: true) else { return nil }
|
||||
let model = TSGroupModel(title: chat.displayName, memberIds: [userHexEncodedPublicKey!, chat.server], image: nil, groupId: LKGroupUtilities.getEncodedOpenGroupIDAsData(chat.id), groupType: .openGroup, adminIds: [])
|
||||
|
||||
// Store the group chat mapping
|
||||
Storage.writeSync { transaction in
|
||||
let thread = TSGroupThread.getOrCreateThread(with: model, transaction: transaction)
|
||||
|
||||
// Save the group chat
|
||||
Storage.shared.setOpenGroup(chat, for: thread.uniqueId!, using: transaction)
|
||||
}
|
||||
|
||||
// Update chats and pollers
|
||||
self.refreshChatsAndPollers()
|
||||
|
||||
return chat
|
||||
}
|
||||
|
||||
@objc(addChatWithServer:channel:)
|
||||
public func objc_addChat(server: String, channel: UInt64) -> AnyPromise {
|
||||
return AnyPromise.from(addChat(server: server, channel: channel))
|
||||
}
|
||||
|
||||
@objc func refreshChatsAndPollers() {
|
||||
let newChats = Storage.shared.getAllUserOpenGroups()
|
||||
|
||||
// Remove any chats that don't exist in the database
|
||||
let removedChatThreadIds = self.chats.keys.filter { !newChats.keys.contains($0) }
|
||||
removedChatThreadIds.forEach { threadID in
|
||||
let poller = self.pollers.removeValue(forKey: threadID)
|
||||
poller?.stop()
|
||||
}
|
||||
|
||||
// Only append to chats if we have a thread for the chat
|
||||
self.chats = newChats.filter { (threadID, group) in
|
||||
return TSGroupThread.fetch(uniqueId: threadID) != nil
|
||||
}
|
||||
|
||||
if (isPolling) { startPollersIfNeeded() }
|
||||
}
|
||||
|
||||
@objc private func onThreadDeleted(_ notification: Notification) {
|
||||
guard let threadId = notification.userInfo?["threadId"] as? String else { return }
|
||||
|
||||
// Reset the last message cache
|
||||
if let chat = self.chats[threadId] {
|
||||
Storage.write { transaction in
|
||||
Storage.shared.clearAllData(for: chat.channel, on: chat.server, using: transaction)
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the chat from the db
|
||||
Storage.write { transaction in
|
||||
Storage.shared.removeOpenGroup(for: threadId, using: transaction)
|
||||
}
|
||||
|
||||
refreshChatsAndPollers()
|
||||
}
|
||||
|
||||
public func getChat(server: String, channel: UInt64) -> OpenGroup? {
|
||||
return chats.values.first { chat in
|
||||
return chat.server == server && chat.channel == channel
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue