diff --git a/Session.xcodeproj/project.pbxproj b/Session.xcodeproj/project.pbxproj index e666cb4a6..f9da3a03d 100644 --- a/Session.xcodeproj/project.pbxproj +++ b/Session.xcodeproj/project.pbxproj @@ -333,7 +333,7 @@ C32C59C7256DB41F003C73A2 /* TSThread.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBB8255A581600E217F9 /* TSThread.m */; }; C32C5A02256DB658003C73A2 /* MessageSender+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8D8F1EF256621180092EF10 /* MessageSender+Convenience.swift */; }; C32C5A13256DB7A5003C73A2 /* PushNotificationAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBDE255A581900E217F9 /* PushNotificationAPI.swift */; }; - C32C5A24256DB7DB003C73A2 /* LKUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB6B255A580F00E217F9 /* LKUserDefaults.swift */; }; + C32C5A24256DB7DB003C73A2 /* SNUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB6B255A580F00E217F9 /* SNUserDefaults.swift */; }; C32C5A2D256DB849003C73A2 /* LKGroupUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBE1255A581A00E217F9 /* LKGroupUtilities.m */; }; C32C5A36256DB856003C73A2 /* LKGroupUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDBCA255A581700E217F9 /* LKGroupUtilities.h */; settings = {ATTRIBUTES = (Public, ); }; }; C32C5A47256DB8F0003C73A2 /* ECKeyPair+Hexadecimal.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDA73255A57FA00E217F9 /* ECKeyPair+Hexadecimal.swift */; }; @@ -717,6 +717,8 @@ C3A7225E2558C38D0043A11F /* Promise+Retaining.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3A7225D2558C38D0043A11F /* Promise+Retaining.swift */; }; 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 */; }; C3BBE0762554CDA60050F1E3 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3BBE0752554CDA60050F1E3 /* Configuration.swift */; }; C3BBE0802554CDD70050F1E3 /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3BBE07F2554CDD70050F1E3 /* Storage.swift */; }; C3BBE0A72554D4DE0050F1E3 /* Promise+Retrying.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2A5D62553860B00C340D1 /* Promise+Retrying.swift */; }; @@ -1449,7 +1451,7 @@ C33FDB67255A580F00E217F9 /* OWSMediaGalleryFinder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSMediaGalleryFinder.h; sourceTree = ""; }; C33FDB68255A580F00E217F9 /* ContentProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentProxy.swift; sourceTree = ""; }; C33FDB69255A580F00E217F9 /* FeatureFlags.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeatureFlags.swift; sourceTree = ""; }; - C33FDB6B255A580F00E217F9 /* LKUserDefaults.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LKUserDefaults.swift; sourceTree = ""; }; + C33FDB6B255A580F00E217F9 /* SNUserDefaults.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SNUserDefaults.swift; sourceTree = ""; }; C33FDB6C255A580F00E217F9 /* NSNotificationCenter+OWS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSNotificationCenter+OWS.m"; sourceTree = ""; }; C33FDB6F255A580F00E217F9 /* OWSOutgoingReceiptManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSOutgoingReceiptManager.m; sourceTree = ""; }; C33FDB71255A581000E217F9 /* OWSMediaGalleryFinder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSMediaGalleryFinder.m; sourceTree = ""; }; @@ -1737,6 +1739,8 @@ C3A7225D2558C38D0043A11F /* Promise+Retaining.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Promise+Retaining.swift"; sourceTree = ""; }; C3A7229B2558E4310043A11F /* OpenGroupMessage+Conversion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OpenGroupMessage+Conversion.swift"; sourceTree = ""; }; C3AA6BB824CE8F1B002358B6 /* Migrating Translations from Android.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = "Migrating Translations from Android.md"; path = "Meta/Translations/Migrating Translations from Android.md"; sourceTree = ""; }; + C3AAFFC125AE916D0089E6DD /* OpenGroupManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenGroupManagerProtocol.swift; sourceTree = ""; }; + C3AAFFCB25AE92150089E6DD /* OpenGroupManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenGroupManager.swift; sourceTree = ""; }; C3AECBEA24EF5244005743DE /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = fa.lproj/Localizable.strings; sourceTree = ""; }; C3B7845C25649DA600ADB2E7 /* TSIncomingMessage+Conversion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TSIncomingMessage+Conversion.swift"; sourceTree = ""; }; C3BBE0752554CDA60050F1E3 /* Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = ""; }; @@ -2259,7 +2263,6 @@ B8AE75A325A6C6A6001A84D2 /* Data+Trimming.swift */, C3C2A5D52553860A00C340D1 /* Dictionary+Description.swift */, B8BC00BF257D90E30032E807 /* General.swift */, - C33FDB6B255A580F00E217F9 /* LKUserDefaults.swift */, C3C2A5CE2553860700C340D1 /* Logging.swift */, C33FDAFD255A580600E217F9 /* LRUCache.swift */, C33FDB5C255A580E00E217F9 /* NSArray+Functional.h */, @@ -2276,6 +2279,7 @@ C33FDB51255A580D00E217F9 /* NSUserDefaults+OWS.h */, C33FDB77255A581000E217F9 /* NSUserDefaults+OWS.m */, C33FDB14255A580800E217F9 /* OWSMath.h */, + C33FDB6B255A580F00E217F9 /* SNUserDefaults.swift */, C33FDB3F255A580C00E217F9 /* String+SSK.swift */, C3C2AC2D2553CBEB00C340D1 /* String+Trimming.swift */, C38EF237255B6D65007E1867 /* UIDevice+featureSupport.swift */, @@ -3111,6 +3115,7 @@ children = ( C33FDB19255A580900E217F9 /* GroupUtilities.swift */, C33FDADF255A580400E217F9 /* PublicChatManager.swift */, + C3AAFFCB25AE92150089E6DD /* OpenGroupManager.swift */, C38EF3E5255B6DF4007E1867 /* ContactCellView.h */, C38EF3D6255B6DEF007E1867 /* ContactCellView.m */, C38EF3E6255B6DF4007E1867 /* ContactTableViewCell.h */, @@ -3327,6 +3332,7 @@ C32C5BB9256DC7C4003C73A2 /* To Do */, C3BBE0752554CDA60050F1E3 /* Configuration.swift */, C3BBE07F2554CDD70050F1E3 /* Storage.swift */, + C3AAFFC125AE916D0089E6DD /* OpenGroupManagerProtocol.swift */, B8B3201F258B1A540020074B /* Contacts */, C32C5BCB256DC818003C73A2 /* Database */, C300A5BB2554AFFB00555489 /* Messages */, @@ -4697,6 +4703,7 @@ 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 */, @@ -4820,7 +4827,7 @@ C3A71F892558BA9F0043A11F /* Mnemonic.swift in Sources */, C33FDEF8255A656D00E217F9 /* Promise+Delaying.swift in Sources */, B8BC00C0257D90E30032E807 /* General.swift in Sources */, - C32C5A24256DB7DB003C73A2 /* LKUserDefaults.swift in Sources */, + C32C5A24256DB7DB003C73A2 /* SNUserDefaults.swift in Sources */, C3D9E41F25676C870040E4F3 /* OWSPrimaryStorageProtocol.swift in Sources */, C3BBE0A72554D4DE0050F1E3 /* Promise+Retrying.swift in Sources */, B8856D7B256F14F4001CE70E /* UIView+OWS.m in Sources */, @@ -4842,6 +4849,7 @@ buildActionMask = 2147483647; files = ( C3A7229C2558E4310043A11F /* OpenGroupMessage+Conversion.swift in Sources */, + C3AAFFC225AE916D0089E6DD /* OpenGroupManagerProtocol.swift in Sources */, C32C5DBE256DD743003C73A2 /* OpenGroupPoller.swift in Sources */, B8856D08256F10F1001CE70E /* DeviceSleepManager.swift in Sources */, C3471F4C25553AB000297E91 /* MessageReceiver+Decryption.swift in Sources */, diff --git a/Session/Open Groups/JoinPublicChatVC.swift b/Session/Open Groups/JoinPublicChatVC.swift index 6697054f8..98fedc4ef 100644 --- a/Session/Open Groups/JoinPublicChatVC.swift +++ b/Session/Open Groups/JoinPublicChatVC.swift @@ -125,29 +125,15 @@ final class JoinPublicChatVC : BaseVC, UIPageViewControllerDataSource, UIPageVie joinPublicChatIfPossible(with: chatURL) } - fileprivate func joinPublicChatIfPossible(with chatURL: String) { + fileprivate func joinPublicChatIfPossible(with urlAsString: String) { guard !isJoining else { return } - guard let url = URL(string: chatURL), let scheme = url.scheme, scheme == "https", url.host != nil else { + guard let url = URL(string: urlAsString), let scheme = url.scheme, scheme == "https", url.host != nil else { return showError(title: NSLocalizedString("invalid_url", comment: ""), message: "Please check the URL you entered and try again") } isJoining = true - 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 - Storage.writeSync { transaction in - transaction.removeObject(forKey: "\(urlAsString).\(channelID)", inCollection: Storage.lastMessageServerIDCollection) - transaction.removeObject(forKey: "\(urlAsString).\(channelID)", inCollection: Storage.lastDeletionServerIDCollection) - } ModalActivityIndicatorViewController.present(fromViewController: navigationController!, canCancel: false) { [weak self] _ in - PublicChatManager.shared.addChat(server: urlAsString, channel: channelID) + OpenGroupManager.shared.addOpenGroup(with: urlAsString) .done(on: DispatchQueue.main) { [weak self] _ in - let _ = OpenGroupAPI.setDisplayName(to: displayName, on: urlAsString) - let _ = OpenGroupAPI.setProfilePictureURL(to: profilePictureURL, using: profileKey, on: urlAsString) - let _ = OpenGroupAPI.join(channelID, on: urlAsString) self?.presentingViewController!.dismiss(animated: true, completion: nil) } .catch(on: DispatchQueue.main) { [weak self] error in diff --git a/SessionMessagingKit/Configuration.swift b/SessionMessagingKit/Configuration.swift index dc4a80ec6..7751744b7 100644 --- a/SessionMessagingKit/Configuration.swift +++ b/SessionMessagingKit/Configuration.swift @@ -3,17 +3,19 @@ import SessionProtocolKit @objc public final class SNMessagingKitConfiguration : NSObject { public let storage: SessionMessagingKitStorageProtocol + public let openGroupManager: OpenGroupManagerProtocol @objc public static var shared: SNMessagingKitConfiguration! - fileprivate init(storage: SessionMessagingKitStorageProtocol) { + fileprivate init(storage: SessionMessagingKitStorageProtocol, openGroupManager: OpenGroupManagerProtocol) { self.storage = storage + self.openGroupManager = openGroupManager } } public enum SNMessagingKit { // Just to make the external API nice - public static func configure(storage: SessionMessagingKitStorageProtocol) { - SNMessagingKitConfiguration.shared = SNMessagingKitConfiguration(storage: storage) + public static func configure(storage: SessionMessagingKitStorageProtocol, openGroupManager: OpenGroupManagerProtocol) { + SNMessagingKitConfiguration.shared = SNMessagingKitConfiguration(storage: storage, openGroupManager: openGroupManager) } } diff --git a/SessionMessagingKit/OpenGroupManagerProtocol.swift b/SessionMessagingKit/OpenGroupManagerProtocol.swift new file mode 100644 index 000000000..b76ab5300 --- /dev/null +++ b/SessionMessagingKit/OpenGroupManagerProtocol.swift @@ -0,0 +1,6 @@ +import PromiseKit + +public protocol OpenGroupManagerProtocol { + + func addOpenGroup(with url: String) -> Promise +} diff --git a/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift b/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift index 32d23604a..cc4e73873 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift @@ -13,6 +13,7 @@ extension MessageReceiver { case let message as TypingIndicator: handleTypingIndicator(message, using: transaction) case let message as ClosedGroupUpdateV2: handleClosedGroupUpdateV2(message, using: transaction) case let message as ExpirationTimerUpdate: handleExpirationTimerUpdate(message, using: transaction) + case let message as ConfigurationMessage: handleConfigurationMessage(message, using: transaction) case let message as VisibleMessage: try handleVisibleMessage(message, associatedWithProto: proto, openGroupID: openGroupID, isBackgroundPoll: isBackgroundPoll, using: transaction) default: fatalError() } @@ -91,6 +92,22 @@ 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).retainUntilComplete() + } + } + public static func setExpirationTimer(to duration: UInt32, for senderPublicKey: String, groupPublicKey: String?, using transaction: Any) { let transaction = transaction as! YapDatabaseReadWriteTransaction var isGroup = false @@ -218,20 +235,22 @@ extension MessageReceiver { private static func handleClosedGroupUpdateV2(_ message: ClosedGroupUpdateV2, using transaction: Any) { switch message.kind! { - case .new: handleNewGroupV2(message, using: transaction) - case .update: handleGroupUpdateV2(message, using: transaction) - case .encryptionKeyPair: handleGroupEncryptionKeyPair(message, using: transaction) + case .new: handleNewClosedGroup(message, using: transaction) + case .update: handleClosedGroupUpdate(message, using: transaction) + case .encryptionKeyPair: handleClosedGroupEncryptionKeyPair(message, using: transaction) } } - private static func handleNewGroupV2(_ message: ClosedGroupUpdateV2, using transaction: Any) { - // Prepare + private static func handleNewClosedGroup(_ message: ClosedGroupUpdateV2, using transaction: Any) { guard case let .new(publicKeyAsData, name, encryptionKeyPair, membersAsData, adminsAsData) = message.kind else { return } - let transaction = transaction as! YapDatabaseReadWriteTransaction - // Unwrap the message let groupPublicKey = publicKeyAsData.toHexString() let members = membersAsData.map { $0.toHexString() } let admins = adminsAsData.map { $0.toHexString() } + handleNewClosedGroup(groupPublicKey: groupPublicKey, name: name, encryptionKeyPair: encryptionKeyPair, members: members, admins: admins, using: transaction) + } + + private static func handleNewClosedGroup(groupPublicKey: String, name: String, encryptionKeyPair: ECKeyPair, members: [String], admins: [String], using transaction: Any) { + let transaction = transaction as! YapDatabaseReadWriteTransaction // Create the group let groupID = LKGroupUtilities.getEncodedClosedGroupIDAsData(groupPublicKey) let group = TSGroupModel(title: name, memberIds: members, image: nil, groupId: groupID, groupType: .closedGroup, adminIds: admins) @@ -254,7 +273,7 @@ extension MessageReceiver { infoMessage.save(with: transaction) } - private static func handleGroupUpdateV2(_ message: ClosedGroupUpdateV2, using transaction: Any) { + private static func handleClosedGroupUpdate(_ message: ClosedGroupUpdateV2, using transaction: Any) { // Prepare guard case let .update(name, membersAsData) = message.kind else { return } let transaction = transaction as! YapDatabaseReadWriteTransaction @@ -313,7 +332,7 @@ extension MessageReceiver { } } - private static func handleGroupEncryptionKeyPair(_ message: ClosedGroupUpdateV2, using transaction: Any) { + private static func handleClosedGroupEncryptionKeyPair(_ message: ClosedGroupUpdateV2, using transaction: Any) { // Prepare guard case let .encryptionKeyPair(wrappers) = message.kind, let groupPublicKey = message.groupPublicKey else { return } let transaction = transaction as! YapDatabaseReadWriteTransaction diff --git a/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift b/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift index af6b04af6..3cf72f01a 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift @@ -95,8 +95,6 @@ public enum MessageReceiver { } // Don't process the envelope any further if the sender is blocked guard !isBlocked(sender) else { throw Error.senderBlocked } - // Ignore self sends - guard sender != userPublicKey else { throw Error.selfSend } // Parse the proto let proto: SNProtoContent do { @@ -111,24 +109,33 @@ public enum MessageReceiver { if let typingIndicator = TypingIndicator.fromProto(proto) { return typingIndicator } if let closedGroupUpdate = ClosedGroupUpdateV2.fromProto(proto) { return closedGroupUpdate } if let expirationTimerUpdate = ExpirationTimerUpdate.fromProto(proto) { return expirationTimerUpdate } + if let configurationMessage = ConfigurationMessage.fromProto(proto) { return configurationMessage } if let visibleMessage = VisibleMessage.fromProto(proto) { return visibleMessage } return nil }() if let message = message { + // Ignore self sends if needed + if !(message is ConfigurationMessage) { + guard sender != userPublicKey else { throw Error.selfSend } + } + // Guard against control messages in open groups if isOpenGroupMessage { guard message is VisibleMessage else { throw Error.invalidMessage } } + // Finish parsing message.sender = sender message.recipient = userPublicKey message.sentTimestamp = envelope.timestamp message.receivedTimestamp = NSDate.millisecondTimestamp() message.groupPublicKey = groupPublicKey message.openGroupServerMessageID = openGroupMessageServerID + // Validate var isValid = message.isValid if message is VisibleMessage && !isValid && proto.dataMessage?.attachments.isEmpty == false { isValid = true } guard isValid else { throw Error.invalidMessage } + // Return return (message, proto) } else { throw Error.unknownMessage diff --git a/SessionMessagingKit/Storage.swift b/SessionMessagingKit/Storage.swift index 3ea0c21f1..0af9f9e63 100644 --- a/SessionMessagingKit/Storage.swift +++ b/SessionMessagingKit/Storage.swift @@ -28,6 +28,7 @@ public protocol SessionMessagingKitStorageProtocol { // MARK: - Shared Sender Keys func getClosedGroupPrivateKey(for publicKey: String) -> String? + func getUserClosedGroupPublicKeys() -> Set func isClosedGroup(_ publicKey: String) -> Bool // MARK: - Jobs @@ -48,7 +49,8 @@ public protocol SessionMessagingKitStorageProtocol { func removeAuthToken(for server: String, using transaction: Any) // MARK: - Open Groups - + + func getAllUserOpenGroups() -> [String:OpenGroup] func getOpenGroup(for threadID: String) -> OpenGroup? func getThreadID(for openGroupID: String) -> String? diff --git a/SessionUtilitiesKit/General/LKUserDefaults.swift b/SessionUtilitiesKit/General/SNUserDefaults.swift similarity index 80% rename from SessionUtilitiesKit/General/LKUserDefaults.swift rename to SessionUtilitiesKit/General/SNUserDefaults.swift index 052fa58f8..6a6c0e70c 100644 --- a/SessionUtilitiesKit/General/LKUserDefaults.swift +++ b/SessionUtilitiesKit/General/SNUserDefaults.swift @@ -1,6 +1,6 @@ import Foundation -public enum LKUserDefaults { +public enum SNUserDefaults { public enum Bool : Swift.String { case hasLaunchedOnce @@ -8,6 +8,7 @@ public enum LKUserDefaults { case hasViewedSeed case isUsingFullAPNs case isMigratingToV2KeyPair + case isUsingMultiDevice } public enum Date : Swift.String { @@ -32,27 +33,27 @@ public enum LKUserDefaults { public extension UserDefaults { - subscript(bool: LKUserDefaults.Bool) -> Bool { + subscript(bool: SNUserDefaults.Bool) -> Bool { get { return self.bool(forKey: bool.rawValue) } set { set(newValue, forKey: bool.rawValue) } } - subscript(date: LKUserDefaults.Date) -> Date? { + subscript(date: SNUserDefaults.Date) -> Date? { get { return self.object(forKey: date.rawValue) as? Date } set { set(newValue, forKey: date.rawValue) } } - subscript(double: LKUserDefaults.Double) -> Double { + subscript(double: SNUserDefaults.Double) -> Double { get { return self.double(forKey: double.rawValue) } set { set(newValue, forKey: double.rawValue) } } - subscript(int: LKUserDefaults.Int) -> Int { + subscript(int: SNUserDefaults.Int) -> Int { get { return self.integer(forKey: int.rawValue) } set { set(newValue, forKey: int.rawValue) } } - subscript(string: LKUserDefaults.String) -> String? { + subscript(string: SNUserDefaults.String) -> String? { get { return self.string(forKey: string.rawValue) } set { set(newValue, forKey: string.rawValue) } } diff --git a/SignalUtilitiesKit/Configuration.swift b/SignalUtilitiesKit/Configuration.swift index b69c8dddd..a28d601ff 100644 --- a/SignalUtilitiesKit/Configuration.swift +++ b/SignalUtilitiesKit/Configuration.swift @@ -7,7 +7,7 @@ extension OWSPrimaryStorage : OWSPrimaryStorageProtocol { } public final class Configuration : NSObject { @objc public static func performMainSetup() { - SNMessagingKit.configure(storage: Storage.shared) + SNMessagingKit.configure(storage: Storage.shared, openGroupManager: OpenGroupManager.shared) SNSnodeKit.configure(storage: Storage.shared) SNUtilitiesKit.configure(owsPrimaryStorage: OWSPrimaryStorage.shared(), maxFileSize: UInt(Double(FileServerAPI.maxFileSize) / FileServerAPI.fileSizeORMultiplier)) } diff --git a/SignalUtilitiesKit/To Do/OpenGroupManager.swift b/SignalUtilitiesKit/To Do/OpenGroupManager.swift new file mode 100644 index 000000000..bb5c8eccc --- /dev/null +++ b/SignalUtilitiesKit/To Do/OpenGroupManager.swift @@ -0,0 +1,40 @@ +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) -> Promise { + 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 + Storage.writeSync { transaction in + 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) + } + } +}