Merge pull request #333 from oxen-io/multi-device
Multi Device & Account Restoration V2
This commit is contained in:
commit
9a76e45c82
|
@ -289,6 +289,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 */; };
|
||||
|
@ -482,7 +483,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 */; };
|
||||
|
@ -544,6 +544,9 @@
|
|||
C3548F0624456447009433A8 /* PNModeVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3548F0524456447009433A8 /* PNModeVC.swift */; };
|
||||
C3548F0824456AB6009433A8 /* UIView+Wrapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3548F0724456AB6009433A8 /* UIView+Wrapping.swift */; };
|
||||
C354E75A23FE2A7600CE22E3 /* BaseVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C354E75923FE2A7600CE22E3 /* BaseVC.swift */; };
|
||||
C35D0DA125AE582D00B6BF49 /* MultiDeviceVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C35D0DA025AE582D00B6BF49 /* MultiDeviceVC.swift */; };
|
||||
C35D0DAB25AE5BDE00B6BF49 /* SettingRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C35D0DAA25AE5BDE00B6BF49 /* SettingRow.swift */; };
|
||||
C35D0DB525AE5F1200B6BF49 /* UIEdgeInsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = C35D0DB425AE5F1200B6BF49 /* UIEdgeInsets.swift */; };
|
||||
C35E8AAE2485E51D00ACB629 /* IP2Country.swift in Sources */ = {isa = PBXBuildFile; fileRef = C35E8AAD2485E51D00ACB629 /* IP2Country.swift */; };
|
||||
C3645350252449260045C478 /* VoiceMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C364534F252449260045C478 /* VoiceMessageView.swift */; };
|
||||
C364535C252467900045C478 /* AudioUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C364535B252467900045C478 /* AudioUtilities.swift */; };
|
||||
|
@ -712,6 +715,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 */; };
|
||||
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 */; };
|
||||
C3BBE0802554CDD70050F1E3 /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3BBE07F2554CDD70050F1E3 /* Storage.swift */; };
|
||||
C3BBE0A72554D4DE0050F1E3 /* Promise+Retrying.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2A5D62553860B00C340D1 /* Promise+Retrying.swift */; };
|
||||
|
@ -788,6 +793,7 @@
|
|||
C3D9E4FD256778E30040E4F3 /* NSData+Image.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDB29255A580A00E217F9 /* NSData+Image.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C3D9E50E25677A510040E4F3 /* DataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDB54255A580D00E217F9 /* DataSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C3D9E52725677DF20040E4F3 /* OWSThumbnailService.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDAF1255A580500E217F9 /* OWSThumbnailService.swift */; };
|
||||
C3DA9C0725AE7396008F7C7E /* ConfigurationMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3DA9C0625AE7396008F7C7E /* ConfigurationMessage.swift */; };
|
||||
C3DAB3242480CB2B00725F25 /* SRCopyableLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3DAB3232480CB2A00725F25 /* SRCopyableLabel.swift */; };
|
||||
C3DFFAC623E96F0D0058DAF8 /* Sheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3DFFAC523E96F0D0058DAF8 /* Sheet.swift */; };
|
||||
C3E5C2FA251DBABB0040DFFC /* EditClosedGroupVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3E5C2F9251DBABB0040DFFC /* EditClosedGroupVC.swift */; };
|
||||
|
@ -1434,7 +1440,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>"; };
|
||||
|
@ -1588,6 +1593,9 @@
|
|||
C3548F0524456447009433A8 /* PNModeVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PNModeVC.swift; sourceTree = "<group>"; };
|
||||
C3548F0724456AB6009433A8 /* UIView+Wrapping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Wrapping.swift"; sourceTree = "<group>"; };
|
||||
C354E75923FE2A7600CE22E3 /* BaseVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseVC.swift; sourceTree = "<group>"; };
|
||||
C35D0DA025AE582D00B6BF49 /* MultiDeviceVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiDeviceVC.swift; sourceTree = "<group>"; };
|
||||
C35D0DAA25AE5BDE00B6BF49 /* SettingRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingRow.swift; sourceTree = "<group>"; };
|
||||
C35D0DB425AE5F1200B6BF49 /* UIEdgeInsets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIEdgeInsets.swift; sourceTree = "<group>"; };
|
||||
C35E8AA22485C72300ACB629 /* SwiftCSV.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftCSV.framework; path = ThirdParty/Carthage/Build/iOS/SwiftCSV.framework; sourceTree = "<group>"; };
|
||||
C35E8AAD2485E51D00ACB629 /* IP2Country.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IP2Country.swift; sourceTree = "<group>"; };
|
||||
C364534F252449260045C478 /* VoiceMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageView.swift; sourceTree = "<group>"; };
|
||||
|
@ -1772,6 +1780,9 @@
|
|||
C3A7225D2558C38D0043A11F /* Promise+Retaining.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Promise+Retaining.swift"; sourceTree = "<group>"; };
|
||||
C3A7229B2558E4310043A11F /* OpenGroupMessage+Conversion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OpenGroupMessage+Conversion.swift"; sourceTree = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
C3AAFFCB25AE92150089E6DD /* OpenGroupManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenGroupManager.swift; sourceTree = "<group>"; };
|
||||
C3AAFFDE25AE96FF0089E6DD /* ConfigurationMessage+Convenience.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ConfigurationMessage+Convenience.swift"; sourceTree = "<group>"; };
|
||||
C3AAFFF125AE99710089E6DD /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
C3AECBEA24EF5244005743DE /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = fa.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
C3B7845C25649DA600ADB2E7 /* TSIncomingMessage+Conversion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TSIncomingMessage+Conversion.swift"; sourceTree = "<group>"; };
|
||||
C3BBE0752554CDA60050F1E3 /* Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = "<group>"; };
|
||||
|
@ -1830,6 +1841,7 @@
|
|||
C3D9E40B25676C100040E4F3 /* Storage+Conformances.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Storage+Conformances.swift"; sourceTree = "<group>"; };
|
||||
C3D9E41E25676C870040E4F3 /* OWSPrimaryStorageProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OWSPrimaryStorageProtocol.swift; sourceTree = "<group>"; };
|
||||
C3D9E43025676D3D0040E4F3 /* Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = "<group>"; };
|
||||
C3DA9C0625AE7396008F7C7E /* ConfigurationMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationMessage.swift; sourceTree = "<group>"; };
|
||||
C3DAB3232480CB2A00725F25 /* SRCopyableLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRCopyableLabel.swift; sourceTree = "<group>"; };
|
||||
C3DFFAC523E96F0D0058DAF8 /* Sheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sheet.swift; sourceTree = "<group>"; };
|
||||
C3E5C2F9251DBABB0040DFFC /* EditClosedGroupVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditClosedGroupVC.swift; sourceTree = "<group>"; };
|
||||
|
@ -2321,6 +2333,7 @@
|
|||
C33FDB3F255A580C00E217F9 /* String+SSK.swift */,
|
||||
C3C2AC2D2553CBEB00C340D1 /* String+Trimming.swift */,
|
||||
C38EF237255B6D65007E1867 /* UIDevice+featureSupport.swift */,
|
||||
C35D0DB425AE5F1200B6BF49 /* UIEdgeInsets.swift */,
|
||||
C38EF23D255B6D66007E1867 /* UIView+OWS.h */,
|
||||
C38EF23E255B6D66007E1867 /* UIView+OWS.m */,
|
||||
C38EF2EF255B6DBB007E1867 /* Weak.swift */,
|
||||
|
@ -2367,6 +2380,7 @@
|
|||
C31D1DE22521718E005D4DA8 /* UserSelectionVC.swift */,
|
||||
34D2CCD82062E7D000CB1A14 /* OWSScreenLockUI.h */,
|
||||
34D2CCD92062E7D000CB1A14 /* OWSScreenLockUI.m */,
|
||||
C35D0DAA25AE5BDE00B6BF49 /* SettingRow.swift */,
|
||||
);
|
||||
path = Shared;
|
||||
sourceTree = "<group>";
|
||||
|
@ -2413,6 +2427,7 @@
|
|||
C300A5D22554B05A00555489 /* TypingIndicator.swift */,
|
||||
C34A977325A3E34A00852C71 /* ClosedGroupControlMessage.swift */,
|
||||
C300A5E62554B07300555489 /* ExpirationTimerUpdate.swift */,
|
||||
C3DA9C0625AE7396008F7C7E /* ConfigurationMessage.swift */,
|
||||
);
|
||||
path = "Control Messages";
|
||||
sourceTree = "<group>";
|
||||
|
@ -2789,6 +2804,7 @@
|
|||
B886B4A62398B23E00211ABE /* QRCodeVC.swift */,
|
||||
B86BD08523399CEF000F5AE3 /* SeedModal.swift */,
|
||||
B8CCF6422397711F0091D419 /* SettingsVC.swift */,
|
||||
C35D0DA025AE582D00B6BF49 /* MultiDeviceVC.swift */,
|
||||
);
|
||||
path = Settings;
|
||||
sourceTree = "<group>";
|
||||
|
@ -3143,7 +3159,6 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
C33FDB19255A580900E217F9 /* GroupUtilities.swift */,
|
||||
C33FDADF255A580400E217F9 /* PublicChatManager.swift */,
|
||||
C38EF3E5255B6DF4007E1867 /* ContactCellView.h */,
|
||||
C38EF3D6255B6DEF007E1867 /* ContactCellView.m */,
|
||||
C38EF3E6255B6DF4007E1867 /* ContactTableViewCell.h */,
|
||||
|
@ -3177,6 +3192,7 @@
|
|||
C38EF2E3255B6DB9007E1867 /* OWSUnreadIndicator.m */,
|
||||
C33FDAE8255A580500E217F9 /* OWSMessageUtils.h */,
|
||||
C33FDBD7255A581900E217F9 /* OWSMessageUtils.m */,
|
||||
C3AAFFDE25AE96FF0089E6DD /* ConfigurationMessage+Convenience.swift */,
|
||||
);
|
||||
path = Messaging;
|
||||
sourceTree = "<group>";
|
||||
|
@ -3206,6 +3222,7 @@
|
|||
C3A721362558BDFA0043A11F /* OpenGroupInfo.swift */,
|
||||
C3A721342558BDF90043A11F /* OpenGroupMessage.swift */,
|
||||
C3A7229B2558E4310043A11F /* OpenGroupMessage+Conversion.swift */,
|
||||
C3AAFFCB25AE92150089E6DD /* OpenGroupManager.swift */,
|
||||
);
|
||||
path = "Open Groups";
|
||||
sourceTree = "<group>";
|
||||
|
@ -3528,6 +3545,7 @@
|
|||
children = (
|
||||
76EB03C218170B33006006FC /* AppDelegate.h */,
|
||||
76EB03C318170B33006006FC /* AppDelegate.m */,
|
||||
C3AAFFF125AE99710089E6DD /* AppDelegate.swift */,
|
||||
34D99CE3217509C1000AFB39 /* AppEnvironment.swift */,
|
||||
B8FF8E6025C10D8B004D1F22 /* Countries */,
|
||||
34330A581E7875FB00DF2FB9 /* Fonts */,
|
||||
|
@ -4637,7 +4655,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 */,
|
||||
|
@ -4755,6 +4772,7 @@
|
|||
B8C2B332256376F000551B4D /* ThreadUtil.m in Sources */,
|
||||
C38EF40B255B6DF7007E1867 /* TappableStackView.swift in Sources */,
|
||||
C38EF31D255B6DBF007E1867 /* UIImage+OWS.swift in Sources */,
|
||||
C3AAFFE825AE975D0089E6DD /* ConfigurationMessage+Convenience.swift in Sources */,
|
||||
C38EF359255B6DCC007E1867 /* SheetViewController.swift in Sources */,
|
||||
C38EF386255B6DD2007E1867 /* AttachmentApprovalInputAccessoryView.swift in Sources */,
|
||||
B8C2B2C82563685C00551B4D /* CircleView.swift in Sources */,
|
||||
|
@ -4833,6 +4851,7 @@
|
|||
C3D9E41F25676C870040E4F3 /* OWSPrimaryStorageProtocol.swift in Sources */,
|
||||
C3BBE0A72554D4DE0050F1E3 /* Promise+Retrying.swift in Sources */,
|
||||
B8856D7B256F14F4001CE70E /* UIView+OWS.m in Sources */,
|
||||
C35D0DB525AE5F1200B6BF49 /* UIEdgeInsets.swift in Sources */,
|
||||
C3D9E4F4256778AF0040E4F3 /* NSData+Image.m in Sources */,
|
||||
C32C5E0C256DDAFA003C73A2 /* NSRegularExpression+SSK.swift in Sources */,
|
||||
C3BBE0A92554D4DE0050F1E3 /* HTTP.swift in Sources */,
|
||||
|
@ -4916,10 +4935,12 @@
|
|||
B8AE760B25ABFB5A001A84D2 /* GeneralUtilities.m in Sources */,
|
||||
C32C5C4F256DCC36003C73A2 /* Storage+OpenGroups.swift in Sources */,
|
||||
B8B3207B258C22550020074B /* DisplayNameUtilities.swift in Sources */,
|
||||
C3DA9C0725AE7396008F7C7E /* ConfigurationMessage.swift in Sources */,
|
||||
B8856CEE256F1054001CE70E /* OWSAudioPlayer.m in Sources */,
|
||||
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 */,
|
||||
|
@ -5052,6 +5073,7 @@
|
|||
B80A579F23DFF1F300876683 /* NewClosedGroupVC.swift in Sources */,
|
||||
D221A09A169C9E5E00537ABF /* main.m in Sources */,
|
||||
3496957221A301A100DCFE74 /* OWSBackup.m in Sources */,
|
||||
C35D0DA125AE582D00B6BF49 /* MultiDeviceVC.swift in Sources */,
|
||||
B86BD08623399CEF000F5AE3 /* SeedModal.swift in Sources */,
|
||||
34E3E5681EC4B19400495BAC /* AudioProgressView.swift in Sources */,
|
||||
34D1F0521F7E8EA30066283D /* GiphyDownloader.swift in Sources */,
|
||||
|
@ -5060,6 +5082,7 @@
|
|||
B82B408C239A068800A248E7 /* RegisterVC.swift in Sources */,
|
||||
346129991FD1E4DA00532771 /* SignalApp.m in Sources */,
|
||||
3496957121A301A100DCFE74 /* OWSBackupImportJob.m in Sources */,
|
||||
C35D0DAB25AE5BDE00B6BF49 /* SettingRow.swift in Sources */,
|
||||
34BECE301F7ABCF800D7438D /* GifPickerLayout.swift in Sources */,
|
||||
C331FFFE2558FF3B00070591 /* ConversationCell.swift in Sources */,
|
||||
C3DFFAC623E96F0D0058DAF8 /* Sheet.swift in Sources */,
|
||||
|
@ -5134,6 +5157,7 @@
|
|||
4CB5F26920F7D060004D1B42 /* MessageActions.swift in Sources */,
|
||||
340FC8B5204DAC8D007AEB0F /* AboutTableViewController.m in Sources */,
|
||||
C33100082558FF6D00070591 /* NewConversationButtonSet.swift in Sources */,
|
||||
C3AAFFF225AE99710089E6DD /* AppDelegate.swift in Sources */,
|
||||
B8BB82A5238F627000BA5194 /* HomeVC.swift in Sources */,
|
||||
C31A6C5A247F214E001123EF /* UIView+Glow.swift in Sources */,
|
||||
C31D1DE9252172D4005D4DA8 /* ContactUtilities.swift in Sources */,
|
||||
|
|
|
@ -174,6 +174,8 @@ final class NewClosedGroupVC : BaseVC, UITableViewDataSource, UITableViewDelegat
|
|||
promise = MessageSender.createClosedGroup(name: name, members: selectedContacts, transaction: transaction)
|
||||
}
|
||||
let _ = promise.done(on: DispatchQueue.main) { thread in
|
||||
let appDelegate = UIApplication.shared.delegate as! AppDelegate
|
||||
appDelegate.forceSyncConfigurationNowIfNeeded().retainUntilComplete() // FIXME: It's probably cleaner to do this inside createClosedGroup(...)
|
||||
self?.presentingViewController?.dismiss(animated: true, completion: nil)
|
||||
SignalApp.shared().presentConversation(for: thread, action: .compose, animated: false)
|
||||
}
|
||||
|
|
|
@ -354,45 +354,14 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, UIViewC
|
|||
|
||||
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 }
|
||||
|
@ -419,6 +388,29 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, UIViewC
|
|||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
@ -429,6 +429,7 @@ static NSTimeInterval launchStartedAt;
|
|||
|
||||
if (CurrentAppContext().isMainApp) {
|
||||
[SNJobQueue.shared resumePendingJobs];
|
||||
[self syncConfigurationIfNeeded];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -753,10 +754,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
|
||||
|
||||
|
@ -810,7 +811,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.
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
import PromiseKit
|
||||
|
||||
extension AppDelegate {
|
||||
|
||||
@objc(syncConfigurationIfNeeded)
|
||||
func syncConfigurationIfNeeded() {
|
||||
let userDefaults = UserDefaults.standard
|
||||
let lastSync = userDefaults[.lastConfigurationSync] ?? .distantPast
|
||||
guard Date().timeIntervalSince(lastSync) > 2 * 24 * 60 * 60 else { return } // Sync every 2 days
|
||||
let configurationMessage = ConfigurationMessage.getCurrent()
|
||||
let destination = Message.Destination.contact(publicKey: getUserHexEncodedPublicKey())
|
||||
Storage.shared.write { transaction in
|
||||
let job = MessageSendJob(message: configurationMessage, destination: destination)
|
||||
JobQueue.shared.add(job, using: transaction)
|
||||
}
|
||||
userDefaults[.lastConfigurationSync] = Date()
|
||||
}
|
||||
|
||||
func forceSyncConfigurationNowIfNeeded() -> Promise<Void> {
|
||||
let configurationMessage = ConfigurationMessage.getCurrent()
|
||||
let destination = Message.Destination.contact(publicKey: getUserHexEncodedPublicKey())
|
||||
let (promise, seal) = Promise<Void>.pending()
|
||||
Storage.writeSync { transaction in
|
||||
MessageSender.send(configurationMessage, to: destination, using: transaction).done {
|
||||
seal.fulfill(())
|
||||
}.catch { _ in
|
||||
seal.fulfill(()) // Fulfill even if this failed; the configuration in the swarm should be at most 2 days old
|
||||
}.retainUntilComplete()
|
||||
}
|
||||
return promise
|
||||
}
|
||||
}
|
|
@ -125,42 +125,33 @@ 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)
|
||||
.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
|
||||
self?.dismiss(animated: true, completion: nil) // Dismiss the loader
|
||||
var title = "Couldn't Join"
|
||||
var message = ""
|
||||
if case OnionRequestAPI.Error.httpRequestFailedAtDestination(let statusCode, _) = error, statusCode == 401 || statusCode == 403 {
|
||||
title = "Unauthorized"
|
||||
message = "Please ask the open group operator to add you to the group."
|
||||
Storage.shared.write(with: { transaction in
|
||||
OpenGroupManager.shared.add(with: urlAsString, using: transaction)
|
||||
.done(on: DispatchQueue.main) { [weak self] _ in
|
||||
self?.presentingViewController!.dismiss(animated: true, completion: nil)
|
||||
}
|
||||
self?.isJoining = false
|
||||
self?.showError(title: title, message: message)
|
||||
}
|
||||
.catch(on: DispatchQueue.main) { [weak self] error in
|
||||
self?.dismiss(animated: true, completion: nil) // Dismiss the loader
|
||||
var title = "Couldn't Join"
|
||||
var message = ""
|
||||
if case OnionRequestAPI.Error.httpRequestFailedAtDestination(let statusCode, _) = error, statusCode == 401 || statusCode == 403 {
|
||||
title = "Unauthorized"
|
||||
message = "Please ask the open group operator to add you to the group."
|
||||
}
|
||||
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(...)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
|
||||
final class MultiDeviceVC : BaseVC {
|
||||
|
||||
private let mnemonic: String = {
|
||||
let collection = OWSPrimaryStorageIdentityKeyStoreCollection
|
||||
let hexEncodedSeed: String! = OWSIdentityManager.shared().dbConnection.object(forKey: "LKLokiSeed", inCollection: collection) as! String?
|
||||
return Mnemonic.encode(hexEncodedString: hexEncodedSeed)
|
||||
}()
|
||||
|
||||
// MARK: UI Components
|
||||
private lazy var toggleLabel: UILabel = {
|
||||
let result = UILabel()
|
||||
result.textColor = Colors.text
|
||||
result.font = .systemFont(ofSize: Values.mediumFontSize)
|
||||
result.text = "Enable multi device"
|
||||
return result
|
||||
}()
|
||||
|
||||
private lazy var toggle: UISwitch = {
|
||||
let result = UISwitch()
|
||||
result.onTintColor = Colors.accent
|
||||
result.isOn = UserDefaults.standard[.isUsingMultiDevice]
|
||||
return result
|
||||
}()
|
||||
|
||||
private lazy var stepsRow: SettingRow = {
|
||||
let result = SettingRow(autoSize: true)
|
||||
result.isHidden = true
|
||||
return result
|
||||
}()
|
||||
|
||||
private lazy var stepsLabel1: UILabel = {
|
||||
let result = UILabel()
|
||||
result.textColor = Colors.text
|
||||
result.font = .systemFont(ofSize: Values.smallFontSize)
|
||||
result.text = """
|
||||
1. Clear your other device if it currently has an account on it (Settings > Clear Data).
|
||||
|
||||
2. On the landing page, click "Continue your Session".
|
||||
|
||||
3. Enter the following words when prompted:
|
||||
"""
|
||||
result.numberOfLines = 0
|
||||
result.lineBreakMode = .byWordWrapping
|
||||
return result
|
||||
}()
|
||||
|
||||
private lazy var mnemonicLabel: UILabel = {
|
||||
let result = UILabel()
|
||||
result.textColor = Colors.text
|
||||
result.font = Fonts.spaceMono(ofSize: Values.smallFontSize)
|
||||
result.text = mnemonic
|
||||
result.numberOfLines = 0
|
||||
result.lineBreakMode = .byWordWrapping
|
||||
result.textAlignment = .center
|
||||
return result
|
||||
}()
|
||||
|
||||
private lazy var copyButton: Button = {
|
||||
let result = Button(style: .prominentOutline, size: .medium)
|
||||
result.setTitle(NSLocalizedString("copy", comment: ""), for: UIControl.State.normal)
|
||||
result.addTarget(self, action: #selector(copyMnemonic), for: UIControl.Event.touchUpInside)
|
||||
return result
|
||||
}()
|
||||
|
||||
private lazy var stepsLabel2: UILabel = {
|
||||
let result = UILabel()
|
||||
result.textColor = Colors.text
|
||||
result.font = .systemFont(ofSize: Values.smallFontSize)
|
||||
result.text = """
|
||||
4. Enter your display name.
|
||||
|
||||
5. That's it!
|
||||
"""
|
||||
result.numberOfLines = 0
|
||||
result.lineBreakMode = .byWordWrapping
|
||||
return result
|
||||
}()
|
||||
|
||||
// MARK: Initialization
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
setUpUI()
|
||||
}
|
||||
|
||||
private func setUpUI() {
|
||||
setUpGradientBackground()
|
||||
setUpNavBarStyle()
|
||||
setNavBarTitle("Multi Device (Beta)")
|
||||
// Back button
|
||||
let backButton = UIBarButtonItem(title: "Back", style: .plain, target: nil, action: nil)
|
||||
backButton.tintColor = Colors.text
|
||||
navigationItem.backBarButtonItem = backButton
|
||||
// Toggle
|
||||
toggle.addTarget(self, action: #selector(handleToggle), for: UIControl.Event.valueChanged)
|
||||
let toggleStackView = UIStackView(arrangedSubviews: [ toggleLabel, toggle ])
|
||||
toggleStackView.axis = .horizontal
|
||||
toggleStackView.spacing = Values.mediumSpacing
|
||||
toggleStackView.alignment = .center
|
||||
let toggleRow = SettingRow()
|
||||
toggleRow.contentView.addSubview(toggleStackView)
|
||||
toggleStackView.pin(to: toggleRow.contentView, withInset: Values.mediumSpacing)
|
||||
// Steps
|
||||
let mnemonicLabelContainer = UIView()
|
||||
mnemonicLabelContainer.addSubview(mnemonicLabel)
|
||||
mnemonicLabel.pin(to: mnemonicLabelContainer, withInset: isIPhone6OrSmaller ? 4 : Values.smallSpacing)
|
||||
mnemonicLabelContainer.layer.cornerRadius = Values.textFieldCornerRadius
|
||||
mnemonicLabelContainer.layer.borderWidth = Values.borderThickness
|
||||
mnemonicLabelContainer.layer.borderColor = Colors.text.cgColor
|
||||
let stepsLabel1Container = UIView()
|
||||
stepsLabel1Container.addSubview(stepsLabel1)
|
||||
stepsLabel1.pin(.leading, to: .leading, of: stepsLabel1Container, withInset: Values.smallSpacing)
|
||||
stepsLabel1Container.pin(.trailing, to: .trailing, of: stepsLabel1, withInset: Values.smallSpacing)
|
||||
stepsLabel1.pin([ UIView.VerticalEdge.top, UIView.VerticalEdge.bottom ], to: stepsLabel1Container)
|
||||
let stepsLabel2Container = UIView()
|
||||
stepsLabel2Container.addSubview(stepsLabel2)
|
||||
stepsLabel2.pin(.leading, to: .leading, of: stepsLabel2Container, withInset: Values.smallSpacing)
|
||||
stepsLabel2Container.pin(.trailing, to: .trailing, of: stepsLabel2, withInset: Values.smallSpacing)
|
||||
stepsLabel2.pin([ UIView.VerticalEdge.top, UIView.VerticalEdge.bottom ], to: stepsLabel2Container)
|
||||
let stepsStackView = UIStackView(arrangedSubviews: [ stepsLabel1Container, mnemonicLabelContainer, copyButton, stepsLabel2Container ])
|
||||
stepsStackView.axis = .vertical
|
||||
stepsStackView.spacing = Values.mediumSpacing
|
||||
stepsRow.contentView.addSubview(stepsStackView)
|
||||
stepsStackView.pin(to: stepsRow.contentView, withInset: Values.mediumSpacing)
|
||||
// Main stack view
|
||||
let mainStackView = UIStackView(arrangedSubviews: [ toggleRow, stepsRow ])
|
||||
mainStackView.axis = .vertical
|
||||
mainStackView.spacing = Values.mediumSpacing
|
||||
mainStackView.isLayoutMarginsRelativeArrangement = true
|
||||
mainStackView.layoutMargins = UIEdgeInsets(uniform: Values.mediumSpacing)
|
||||
mainStackView.set(.width, to: UIScreen.main.bounds.width)
|
||||
// Scroll view
|
||||
let scrollView = UIScrollView()
|
||||
scrollView.showsVerticalScrollIndicator = false
|
||||
scrollView.addSubview(mainStackView)
|
||||
mainStackView.pin(to: scrollView)
|
||||
view.addSubview(scrollView)
|
||||
scrollView.pin(to: view)
|
||||
}
|
||||
|
||||
// MARK: Updating
|
||||
@objc private func enableCopyButton() {
|
||||
copyButton.isUserInteractionEnabled = true
|
||||
UIView.transition(with: copyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
|
||||
self.copyButton.setTitle(NSLocalizedString("copy", comment: ""), for: UIControl.State.normal)
|
||||
}, completion: nil)
|
||||
}
|
||||
|
||||
// MARK: Interaction
|
||||
@objc private func handleToggle() {
|
||||
stepsRow.isHidden = !toggle.isOn
|
||||
UserDefaults.standard[.isUsingMultiDevice] = toggle.isOn
|
||||
let appDelegate = UIApplication.shared.delegate as! AppDelegate
|
||||
appDelegate.forceSyncConfigurationNowIfNeeded().retainUntilComplete()
|
||||
}
|
||||
|
||||
@objc private func copyMnemonic() {
|
||||
UIPasteboard.general.string = mnemonic
|
||||
copyButton.isUserInteractionEnabled = false
|
||||
UIView.transition(with: copyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
|
||||
self.copyButton.setTitle("Copied", for: UIControl.State.normal)
|
||||
}, completion: nil)
|
||||
Timer.scheduledTimer(timeInterval: 4, target: self, selector: #selector(enableCopyButton), userInfo: nil, repeats: false)
|
||||
}
|
||||
}
|
|
@ -50,8 +50,14 @@ final class NukeDataModal : Modal {
|
|||
// MARK: Interaction
|
||||
@objc private func nuke() {
|
||||
func proceed() {
|
||||
UserDefaults.removeAll() // Not done in the nuke data implementation as unlinking requires this to happen later
|
||||
NotificationCenter.default.post(name: .dataNukeRequested, object: nil)
|
||||
let appDelegate = UIApplication.shared.delegate as! AppDelegate
|
||||
ModalActivityIndicatorViewController.present(fromViewController: self, canCancel: false) { [weak self] _ in
|
||||
appDelegate.forceSyncConfigurationNowIfNeeded().done(on: DispatchQueue.main) {
|
||||
self?.dismiss(animated: true, completion: nil) // Dismiss the loader
|
||||
UserDefaults.removeAll() // Not done in the nuke data implementation as unlinking requires this to happen later
|
||||
NotificationCenter.default.post(name: .dataNukeRequested, object: nil)
|
||||
}.retainUntilComplete()
|
||||
}
|
||||
}
|
||||
if KeyPairUtilities.hasV2KeyPair() {
|
||||
proceed()
|
||||
|
|
|
@ -59,16 +59,8 @@ final class SeedModal : Modal {
|
|||
buttonStackView.axis = .horizontal
|
||||
buttonStackView.spacing = Values.mediumSpacing
|
||||
buttonStackView.distribution = .fillEqually
|
||||
// Set up explanation label
|
||||
let disclaimerLabel = UILabel()
|
||||
disclaimerLabel.textColor = Colors.text.withAlphaComponent(Values.unimportantElementOpacity)
|
||||
disclaimerLabel.font = .systemFont(ofSize: 10)
|
||||
disclaimerLabel.text = "It is not possible to use the same Session ID on multiple devices simultaneously"
|
||||
disclaimerLabel.numberOfLines = 0
|
||||
disclaimerLabel.lineBreakMode = .byWordWrapping
|
||||
disclaimerLabel.textAlignment = .center
|
||||
// Set up stack view
|
||||
let stackView = UIStackView(arrangedSubviews: [ titleLabel, mnemonicLabelContainer, explanationLabel, buttonStackView, disclaimerLabel ])
|
||||
let stackView = UIStackView(arrangedSubviews: [ titleLabel, mnemonicLabelContainer, explanationLabel, buttonStackView ])
|
||||
stackView.axis = .vertical
|
||||
stackView.spacing = Values.largeSpacing
|
||||
contentView.addSubview(stackView)
|
||||
|
|
|
@ -181,6 +181,8 @@ final class SettingsVC : BaseVC, AvatarViewHelperDelegate {
|
|||
getSeparator(),
|
||||
getSettingButton(withTitle: NSLocalizedString("vc_settings_notifications_button_title", comment: ""), color: Colors.text, action: #selector(showNotificationSettings)),
|
||||
getSeparator(),
|
||||
getSettingButton(withTitle: "Multi Device (Beta)", color: Colors.text, action: #selector(showMultiDeviceOptions)),
|
||||
getSeparator(),
|
||||
getSettingButton(withTitle: "Invite", color: Colors.text, action: #selector(sendInvitation)),
|
||||
getSeparator()
|
||||
]
|
||||
|
@ -405,6 +407,11 @@ final class SettingsVC : BaseVC, AvatarViewHelperDelegate {
|
|||
navigationController!.pushViewController(notificationSettingsVC, animated: true)
|
||||
}
|
||||
|
||||
@objc private func showMultiDeviceOptions() {
|
||||
let multiDeviceVC = MultiDeviceVC()
|
||||
navigationController!.pushViewController(multiDeviceVC, animated: true)
|
||||
}
|
||||
|
||||
@objc private func sendInvitation() {
|
||||
let invitation = "Hey, I've been using Session to chat with complete privacy and security. Come join me! Download it at https://getsession.org/. My Session ID is \(getUserHexEncodedPublicKey())!"
|
||||
let shareVC = UIActivityViewController(activityItems: [ invitation ], applicationActivities: nil)
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
final class SettingRow : UIView {
|
||||
private let autoSize: Bool
|
||||
|
||||
lazy var contentView: UIView = {
|
||||
let result = UIView()
|
||||
result.backgroundColor = Colors.buttonBackground
|
||||
result.layer.cornerRadius = 8
|
||||
result.layer.masksToBounds = true
|
||||
return result
|
||||
}()
|
||||
|
||||
init(autoSize: Bool) {
|
||||
self.autoSize = autoSize
|
||||
super.init(frame: CGRect.zero)
|
||||
setUpUI()
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
autoSize = false
|
||||
super.init(frame: frame)
|
||||
setUpUI()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
autoSize = false
|
||||
super.init(coder: coder)
|
||||
setUpUI()
|
||||
}
|
||||
|
||||
private func setUpUI() {
|
||||
// Height
|
||||
if !autoSize {
|
||||
let height = Values.defaultSettingRowHeight
|
||||
set(.height, to: height)
|
||||
}
|
||||
// Shadow
|
||||
layer.shadowColor = UIColor.black.cgColor
|
||||
layer.shadowOffset = CGSize.zero
|
||||
layer.shadowOpacity = 0.4
|
||||
layer.shadowRadius = 4
|
||||
// Content view
|
||||
addSubview(contentView)
|
||||
contentView.pin(to: self)
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: 8).cgPath
|
||||
}
|
||||
}
|
|
@ -27,16 +27,31 @@ extension Storage {
|
|||
/// Returns the ID of the `TSIncomingMessage` that was constructed.
|
||||
public func persist(_ message: VisibleMessage, quotedMessage: TSQuotedMessage?, linkPreview: OWSLinkPreview?, groupPublicKey: String?, openGroupID: String?, using transaction: Any) -> String? {
|
||||
let transaction = transaction as! YapDatabaseReadWriteTransaction
|
||||
guard let threadID = getOrCreateThread(for: message.sender!, groupPublicKey: groupPublicKey, openGroupID: openGroupID, using: transaction),
|
||||
guard let threadID = getOrCreateThread(for: message.syncTarget ?? message.sender!, groupPublicKey: groupPublicKey, openGroupID: openGroupID, using: transaction),
|
||||
let thread = TSThread.fetch(uniqueId: threadID, transaction: transaction) else { return nil }
|
||||
let message = TSIncomingMessage.from(message, quotedMessage: quotedMessage, linkPreview: linkPreview, associatedWith: thread)
|
||||
message.save(with: transaction)
|
||||
message.attachments(with: transaction).forEach { attachment in
|
||||
attachment.albumMessageId = message.uniqueId!
|
||||
let tsMessage: TSMessage
|
||||
if message.sender == getUserPublicKey() {
|
||||
let tsOutgoingMessage = TSOutgoingMessage.from(message, associatedWith: thread, using: transaction)
|
||||
var recipients: [String] = []
|
||||
if let syncTarget = message.syncTarget {
|
||||
recipients.append(syncTarget)
|
||||
} else if let thread = thread as? TSGroupThread, thread.isClosedGroup {
|
||||
recipients = thread.groupModel.groupMemberIds
|
||||
}
|
||||
recipients.forEach { recipient in
|
||||
tsOutgoingMessage.update(withSentRecipient: recipient, wasSentByUD: true, transaction: transaction)
|
||||
}
|
||||
tsMessage = tsOutgoingMessage
|
||||
} else {
|
||||
tsMessage = TSIncomingMessage.from(message, quotedMessage: quotedMessage, linkPreview: linkPreview, associatedWith: thread)
|
||||
}
|
||||
tsMessage.save(with: transaction)
|
||||
tsMessage.attachments(with: transaction).forEach { attachment in
|
||||
attachment.albumMessageId = tsMessage.uniqueId!
|
||||
attachment.save(with: transaction)
|
||||
}
|
||||
DispatchQueue.main.async { message.touch() } // FIXME: Hack for a thread updating issue
|
||||
return message.uniqueId!
|
||||
DispatchQueue.main.async { tsMessage.touch() } // FIXME: Hack for a thread updating issue
|
||||
return tsMessage.uniqueId!
|
||||
}
|
||||
|
||||
/// Returns the IDs of the saved attachments.
|
||||
|
@ -49,22 +64,22 @@ extension Storage {
|
|||
}
|
||||
|
||||
/// Also touches the associated message.
|
||||
public func setAttachmentState(to state: TSAttachmentPointerState, for pointer: TSAttachmentPointer, associatedWith tsIncomingMessageID: String, using transaction: Any) {
|
||||
public func setAttachmentState(to state: TSAttachmentPointerState, for pointer: TSAttachmentPointer, associatedWith tsMessageID: String, using transaction: Any) {
|
||||
let transaction = transaction as! YapDatabaseReadWriteTransaction
|
||||
// Workaround for some YapDatabase funkiness where pointer at this point can actually be a TSAttachmentStream
|
||||
guard pointer.responds(to: #selector(setter: TSAttachmentPointer.state)) else { return }
|
||||
pointer.state = state
|
||||
pointer.save(with: transaction)
|
||||
guard let tsIncomingMessage = TSIncomingMessage.fetch(uniqueId: tsIncomingMessageID, transaction: transaction) else { return }
|
||||
tsIncomingMessage.touch(with: transaction)
|
||||
guard let tsMessage = TSMessage.fetch(uniqueId: tsMessageID, transaction: transaction) else { return }
|
||||
tsMessage.touch(with: transaction)
|
||||
}
|
||||
|
||||
/// Also touches the associated message.
|
||||
public func persist(_ stream: TSAttachmentStream, associatedWith tsIncomingMessageID: String, using transaction: Any) {
|
||||
public func persist(_ stream: TSAttachmentStream, associatedWith tsMessageID: String, using transaction: Any) {
|
||||
let transaction = transaction as! YapDatabaseReadWriteTransaction
|
||||
stream.save(with: transaction)
|
||||
guard let tsIncomingMessage = TSIncomingMessage.fetch(uniqueId: tsIncomingMessageID, transaction: transaction) else { return }
|
||||
tsIncomingMessage.touch(with: transaction)
|
||||
guard let tsMessage = TSMessage.fetch(uniqueId: tsMessageID, transaction: transaction) else { return }
|
||||
tsMessage.touch(with: transaction)
|
||||
}
|
||||
|
||||
private static let receivedMessageTimestampsCollection = "ReceivedMessageTimestampsCollection"
|
||||
|
@ -78,6 +93,16 @@ extension Storage {
|
|||
}
|
||||
return result
|
||||
}
|
||||
|
||||
public func removeReceivedMessageTimestamps(_ timestamps: Set<UInt64>, using transaction: Any) {
|
||||
var receivedMessageTimestamps = getReceivedMessageTimestamps(using: transaction)
|
||||
timestamps.forEach { timestamp in
|
||||
guard let index = receivedMessageTimestamps.firstIndex(of: timestamp) else { return }
|
||||
receivedMessageTimestamps.remove(at: index)
|
||||
}
|
||||
let transaction = transaction as! YapDatabaseReadWriteTransaction
|
||||
transaction.setObject(receivedMessageTimestamps, forKey: "receivedMessageTimestamps", inCollection: Storage.receivedMessageTimestampsCollection)
|
||||
}
|
||||
|
||||
public func addReceivedMessageTimestamp(_ timestamp: UInt64, using transaction: Any) {
|
||||
var receivedMessageTimestamps = getReceivedMessageTimestamps(using: transaction)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -4,7 +4,7 @@ import SignalCoreKit
|
|||
|
||||
public final class AttachmentDownloadJob : NSObject, Job, NSCoding { // NSObject/NSCoding conformance is needed for YapDatabase compatibility
|
||||
public let attachmentID: String
|
||||
public let tsIncomingMessageID: String
|
||||
public let tsMessageID: String
|
||||
public var delegate: JobDelegate?
|
||||
public var id: String?
|
||||
public var failureCount: UInt = 0
|
||||
|
@ -24,25 +24,25 @@ public final class AttachmentDownloadJob : NSObject, Job, NSCoding { // NSObject
|
|||
public static let maxFailureCount: UInt = 20
|
||||
|
||||
// MARK: Initialization
|
||||
public init(attachmentID: String, tsIncomingMessageID: String) {
|
||||
public init(attachmentID: String, tsMessageID: String) {
|
||||
self.attachmentID = attachmentID
|
||||
self.tsIncomingMessageID = tsIncomingMessageID
|
||||
self.tsMessageID = tsMessageID
|
||||
}
|
||||
|
||||
// MARK: Coding
|
||||
public init?(coder: NSCoder) {
|
||||
guard let attachmentID = coder.decodeObject(forKey: "attachmentID") as! String?,
|
||||
let tsIncomingMessageID = coder.decodeObject(forKey: "tsIncomingMessageID") as! String?,
|
||||
let tsMessageID = coder.decodeObject(forKey: "tsIncomingMessageID") as! String?,
|
||||
let id = coder.decodeObject(forKey: "id") as! String? else { return nil }
|
||||
self.attachmentID = attachmentID
|
||||
self.tsIncomingMessageID = tsIncomingMessageID
|
||||
self.tsMessageID = tsMessageID
|
||||
self.id = id
|
||||
self.failureCount = coder.decodeObject(forKey: "failureCount") as! UInt? ?? 0
|
||||
}
|
||||
|
||||
public func encode(with coder: NSCoder) {
|
||||
coder.encode(attachmentID, forKey: "attachmentID")
|
||||
coder.encode(tsIncomingMessageID, forKey: "tsIncomingMessageID")
|
||||
coder.encode(tsMessageID, forKey: "tsIncomingMessageID")
|
||||
coder.encode(id, forKey: "id")
|
||||
coder.encode(failureCount, forKey: "failureCount")
|
||||
}
|
||||
|
@ -54,21 +54,21 @@ public final class AttachmentDownloadJob : NSObject, Job, NSCoding { // NSObject
|
|||
}
|
||||
let storage = SNMessagingKitConfiguration.shared.storage
|
||||
storage.write(with: { transaction in
|
||||
storage.setAttachmentState(to: .downloading, for: pointer, associatedWith: self.tsIncomingMessageID, using: transaction)
|
||||
storage.setAttachmentState(to: .downloading, for: pointer, associatedWith: self.tsMessageID, using: transaction)
|
||||
}, completion: { })
|
||||
let temporaryFilePath = URL(fileURLWithPath: OWSTemporaryDirectoryAccessibleAfterFirstAuth() + UUID().uuidString)
|
||||
let handleFailure: (Swift.Error) -> Void = { error in // Intentionally capture self
|
||||
OWSFileSystem.deleteFile(temporaryFilePath.absoluteString)
|
||||
if let error = error as? Error, case .noAttachment = error {
|
||||
storage.write(with: { transaction in
|
||||
storage.setAttachmentState(to: .failed, for: pointer, associatedWith: self.tsIncomingMessageID, using: transaction)
|
||||
storage.setAttachmentState(to: .failed, for: pointer, associatedWith: self.tsMessageID, using: transaction)
|
||||
}, completion: { })
|
||||
self.handlePermanentFailure(error: error)
|
||||
} else if let error = error as? DotNetAPI.Error, case .parsingFailed = error {
|
||||
// No need to retry if the response is invalid. Most likely this means we (incorrectly)
|
||||
// got a "Cannot GET ..." error from the file server.
|
||||
storage.write(with: { transaction in
|
||||
storage.setAttachmentState(to: .failed, for: pointer, associatedWith: self.tsIncomingMessageID, using: transaction)
|
||||
storage.setAttachmentState(to: .failed, for: pointer, associatedWith: self.tsMessageID, using: transaction)
|
||||
}, completion: { })
|
||||
self.handlePermanentFailure(error: error)
|
||||
} else {
|
||||
|
@ -99,7 +99,7 @@ public final class AttachmentDownloadJob : NSObject, Job, NSCoding { // NSObject
|
|||
}
|
||||
OWSFileSystem.deleteFile(temporaryFilePath.absoluteString)
|
||||
storage.write { transaction in
|
||||
storage.persist(stream, associatedWith: self.tsIncomingMessageID, using: transaction)
|
||||
storage.persist(stream, associatedWith: self.tsMessageID, using: transaction)
|
||||
}
|
||||
}.catch(on: DispatchQueue.global()) { error in
|
||||
handleFailure(error)
|
||||
|
|
|
@ -11,6 +11,13 @@ public final class ClosedGroupControlMessage : ControlMessage {
|
|||
}
|
||||
}
|
||||
|
||||
public override var isSelfSendValid: Bool {
|
||||
switch kind {
|
||||
case .new: return false
|
||||
default: return true
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Kind
|
||||
public enum Kind : CustomStringConvertible {
|
||||
case new(publicKey: Data, name: String, encryptionKeyPair: ECKeyPair, members: [Data], admins: [Data])
|
||||
|
@ -212,7 +219,7 @@ public final class ClosedGroupControlMessage : ControlMessage {
|
|||
closedGroupControlMessage = SNProtoDataMessageClosedGroupControlMessage.builder(type: .new)
|
||||
closedGroupControlMessage.setPublicKey(publicKey)
|
||||
closedGroupControlMessage.setName(name)
|
||||
let encryptionKeyPairAsProto = SNProtoDataMessageClosedGroupControlMessageKeyPair.builder(publicKey: encryptionKeyPair.publicKey, privateKey: encryptionKeyPair.privateKey)
|
||||
let encryptionKeyPairAsProto = SNProtoKeyPair.builder(publicKey: encryptionKeyPair.publicKey, privateKey: encryptionKeyPair.privateKey)
|
||||
do {
|
||||
closedGroupControlMessage.setEncryptionKeyPair(try encryptionKeyPairAsProto.build())
|
||||
} catch {
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
import SessionUtilitiesKit
|
||||
|
||||
@objc(SNConfigurationMessage)
|
||||
public final class ConfigurationMessage : ControlMessage {
|
||||
public var closedGroups: Set<ClosedGroup> = []
|
||||
public var openGroups: Set<String> = []
|
||||
|
||||
public override var ttl: UInt64 { 4 * 24 * 60 * 60 * 1000 }
|
||||
|
||||
public override var isSelfSendValid: Bool { true }
|
||||
|
||||
// MARK: Initialization
|
||||
public override init() { super.init() }
|
||||
|
||||
public init(closedGroups: Set<ClosedGroup>, openGroups: Set<String>) {
|
||||
super.init()
|
||||
self.closedGroups = closedGroups
|
||||
self.openGroups = openGroups
|
||||
}
|
||||
|
||||
// MARK: Coding
|
||||
public required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
if let closedGroups = coder.decodeObject(forKey: "closedGroups") as! Set<ClosedGroup>? { self.closedGroups = closedGroups }
|
||||
if let openGroups = coder.decodeObject(forKey: "openGroups") as! Set<String>? { self.openGroups = openGroups }
|
||||
}
|
||||
|
||||
public override func encode(with coder: NSCoder) {
|
||||
super.encode(with: coder)
|
||||
coder.encode(closedGroups, forKey: "closedGroups")
|
||||
coder.encode(openGroups, forKey: "openGroups")
|
||||
}
|
||||
|
||||
// MARK: Proto Conversion
|
||||
public override class func fromProto(_ proto: SNProtoContent) -> ConfigurationMessage? {
|
||||
guard let configurationProto = proto.configurationMessage else { return nil }
|
||||
let closedGroups = Set(configurationProto.closedGroups.compactMap { ClosedGroup.fromProto($0) })
|
||||
let openGroups = Set(configurationProto.openGroups)
|
||||
return ConfigurationMessage(closedGroups: closedGroups, openGroups: openGroups)
|
||||
}
|
||||
|
||||
public override func toProto(using transaction: YapDatabaseReadWriteTransaction) -> SNProtoContent? {
|
||||
let configurationProto = SNProtoConfigurationMessage.builder()
|
||||
configurationProto.setClosedGroups(closedGroups.compactMap { $0.toProto() })
|
||||
configurationProto.setOpenGroups([String](openGroups))
|
||||
let contentProto = SNProtoContent.builder()
|
||||
do {
|
||||
contentProto.setConfigurationMessage(try configurationProto.build())
|
||||
return try contentProto.build()
|
||||
} catch {
|
||||
SNLog("Couldn't construct configuration proto from: \(self).")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Description
|
||||
public override var description: String {
|
||||
"""
|
||||
ConfigurationMessage(
|
||||
closedGroups: \([ClosedGroup](closedGroups).prettifiedDescription)
|
||||
openGroups: \([String](openGroups).prettifiedDescription)
|
||||
)
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Closed Group
|
||||
extension ConfigurationMessage {
|
||||
|
||||
@objc(SNClosedGroup)
|
||||
public final class ClosedGroup : NSObject, NSCoding { // NSObject/NSCoding conformance is needed for YapDatabase compatibility
|
||||
public let publicKey: String
|
||||
public let name: String
|
||||
public let encryptionKeyPair: ECKeyPair
|
||||
public let members: Set<String>
|
||||
public let admins: Set<String>
|
||||
|
||||
public var isValid: Bool { !members.isEmpty && !admins.isEmpty }
|
||||
|
||||
public init(publicKey: String, name: String, encryptionKeyPair: ECKeyPair, members: Set<String>, admins: Set<String>) {
|
||||
self.publicKey = publicKey
|
||||
self.name = name
|
||||
self.encryptionKeyPair = encryptionKeyPair
|
||||
self.members = members
|
||||
self.admins = admins
|
||||
}
|
||||
|
||||
public required init?(coder: NSCoder) {
|
||||
guard let publicKey = coder.decodeObject(forKey: "publicKey") as! String?,
|
||||
let name = coder.decodeObject(forKey: "name") as! String?,
|
||||
let encryptionKeyPair = coder.decodeObject(forKey: "encryptionKeyPair") as! ECKeyPair?,
|
||||
let members = coder.decodeObject(forKey: "members") as! Set<String>?,
|
||||
let admins = coder.decodeObject(forKey: "admins") as! Set<String>? else { return nil }
|
||||
self.publicKey = publicKey
|
||||
self.name = name
|
||||
self.encryptionKeyPair = encryptionKeyPair
|
||||
self.members = members
|
||||
self.admins = admins
|
||||
}
|
||||
|
||||
public func encode(with coder: NSCoder) {
|
||||
coder.encode(publicKey, forKey: "publicKey")
|
||||
coder.encode(name, forKey: "name")
|
||||
coder.encode(encryptionKeyPair, forKey: "encryptionKeyPair")
|
||||
coder.encode(members, forKey: "members")
|
||||
coder.encode(admins, forKey: "admins")
|
||||
}
|
||||
|
||||
public static func fromProto(_ proto: SNProtoConfigurationMessageClosedGroup) -> ClosedGroup? {
|
||||
guard let publicKey = proto.publicKey?.toHexString(),
|
||||
let name = proto.name,
|
||||
let encryptionKeyPairAsProto = proto.encryptionKeyPair else { return nil }
|
||||
let encryptionKeyPair: ECKeyPair
|
||||
do {
|
||||
encryptionKeyPair = try ECKeyPair(publicKeyData: encryptionKeyPairAsProto.publicKey, privateKeyData: encryptionKeyPairAsProto.privateKey)
|
||||
} catch {
|
||||
SNLog("Couldn't construct closed group from proto: \(self).")
|
||||
return nil
|
||||
}
|
||||
let members = Set(proto.members.map { $0.toHexString() })
|
||||
let admins = Set(proto.admins.map { $0.toHexString() })
|
||||
return ClosedGroup(publicKey: publicKey, name: name, encryptionKeyPair: encryptionKeyPair, members: members, admins: admins)
|
||||
}
|
||||
|
||||
public func toProto() -> SNProtoConfigurationMessageClosedGroup? {
|
||||
let result = SNProtoConfigurationMessageClosedGroup.builder()
|
||||
result.setPublicKey(Data(hex: publicKey))
|
||||
result.setName(name)
|
||||
do {
|
||||
let encryptionKeyPairAsProto = try SNProtoKeyPair.builder(publicKey: encryptionKeyPair.publicKey, privateKey: encryptionKeyPair.privateKey).build()
|
||||
result.setEncryptionKeyPair(encryptionKeyPairAsProto)
|
||||
} catch {
|
||||
SNLog("Couldn't construct closed group proto from: \(self).")
|
||||
return nil
|
||||
}
|
||||
result.setMembers(members.map { Data(hex: $0) })
|
||||
result.setAdmins(admins.map { Data(hex: $0) })
|
||||
do {
|
||||
return try result.build()
|
||||
} catch {
|
||||
SNLog("Couldn't construct closed group proto from: \(self).")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
public override var description: String { name }
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@ public class Message : NSObject, NSCoding { // NSObject/NSCoding conformance is
|
|||
public var openGroupServerMessageID: UInt64?
|
||||
|
||||
public var ttl: UInt64 { 2 * 24 * 60 * 60 * 1000 }
|
||||
public var isSelfSendValid: Bool { false }
|
||||
|
||||
public override init() { }
|
||||
|
||||
|
|
|
@ -4,15 +4,25 @@ import SessionUtilitiesKit
|
|||
|
||||
@objc(from:associatedWith:)
|
||||
static func from(_ visibleMessage: VisibleMessage, associatedWith thread: TSThread) -> TSOutgoingMessage {
|
||||
return from(visibleMessage, associatedWith: thread, using: nil)
|
||||
}
|
||||
|
||||
static func from(_ visibleMessage: VisibleMessage, associatedWith thread: TSThread, using transaction: YapDatabaseReadWriteTransaction? = nil) -> TSOutgoingMessage {
|
||||
var expiration: UInt32 = 0
|
||||
if let disappearingMessagesConfiguration = OWSDisappearingMessagesConfiguration.fetch(uniqueId: thread.uniqueId!) {
|
||||
let disappearingMessagesConfigurationOrNil: OWSDisappearingMessagesConfiguration?
|
||||
if let transaction = transaction {
|
||||
disappearingMessagesConfigurationOrNil = OWSDisappearingMessagesConfiguration.fetch(uniqueId: thread.uniqueId!, transaction: transaction)
|
||||
} else {
|
||||
disappearingMessagesConfigurationOrNil = OWSDisappearingMessagesConfiguration.fetch(uniqueId: thread.uniqueId!)
|
||||
}
|
||||
if let disappearingMessagesConfiguration = disappearingMessagesConfigurationOrNil {
|
||||
expiration = disappearingMessagesConfiguration.isEnabled ? disappearingMessagesConfiguration.durationSeconds : 0
|
||||
}
|
||||
return TSOutgoingMessage(
|
||||
outgoingMessageWithTimestamp: visibleMessage.sentTimestamp!,
|
||||
in: thread,
|
||||
messageBody: visibleMessage.text,
|
||||
attachmentIds: NSMutableArray(),
|
||||
attachmentIds: NSMutableArray(array: visibleMessage.attachmentIDs),
|
||||
expiresInSeconds: expiration,
|
||||
expireStartedAt: 0,
|
||||
isVoiceMessage: false,
|
||||
|
|
|
@ -2,6 +2,10 @@ import SessionUtilitiesKit
|
|||
|
||||
@objc(SNVisibleMessage)
|
||||
public final class VisibleMessage : Message {
|
||||
/// In the case of a sync message, the public key of the person the message was targeted at.
|
||||
///
|
||||
/// - Note: `nil` if this isn't a sync message.
|
||||
public var syncTarget: String?
|
||||
@objc public var text: String?
|
||||
@objc public var attachmentIDs: [String] = []
|
||||
@objc public var quote: Quote?
|
||||
|
@ -9,6 +13,8 @@ public final class VisibleMessage : Message {
|
|||
@objc public var contact: Contact?
|
||||
@objc public var profile: Profile?
|
||||
|
||||
public override var isSelfSendValid: Bool { true }
|
||||
|
||||
// MARK: Initialization
|
||||
public override init() { super.init() }
|
||||
|
||||
|
@ -23,6 +29,7 @@ public final class VisibleMessage : Message {
|
|||
// MARK: Coding
|
||||
public required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
if let syncTarget = coder.decodeObject(forKey: "syncTarget") as! String? { self.syncTarget = syncTarget }
|
||||
if let text = coder.decodeObject(forKey: "body") as! String? { self.text = text }
|
||||
if let attachmentIDs = coder.decodeObject(forKey: "attachments") as! [String]? { self.attachmentIDs = attachmentIDs }
|
||||
if let quote = coder.decodeObject(forKey: "quote") as! Quote? { self.quote = quote }
|
||||
|
@ -33,6 +40,7 @@ public final class VisibleMessage : Message {
|
|||
|
||||
public override func encode(with coder: NSCoder) {
|
||||
super.encode(with: coder)
|
||||
coder.encode(syncTarget, forKey: "syncTarget")
|
||||
coder.encode(text, forKey: "body")
|
||||
coder.encode(attachmentIDs, forKey: "attachments")
|
||||
coder.encode(quote, forKey: "quote")
|
||||
|
@ -51,6 +59,7 @@ public final class VisibleMessage : Message {
|
|||
if let linkPreviewProto = dataMessage.preview.first, let linkPreview = LinkPreview.fromProto(linkPreviewProto) { result.linkPreview = linkPreview }
|
||||
// TODO: Contact
|
||||
if let profile = Profile.fromProto(dataMessage) { result.profile = profile }
|
||||
result.syncTarget = dataMessage.syncTarget
|
||||
return result
|
||||
}
|
||||
|
||||
|
@ -101,6 +110,10 @@ public final class VisibleMessage : Message {
|
|||
SNLog("Couldn't construct visible message proto from: \(self).")
|
||||
return nil
|
||||
}
|
||||
// Sync target
|
||||
if let syncTarget = syncTarget {
|
||||
dataMessage.setSyncTarget(syncTarget)
|
||||
}
|
||||
// Build
|
||||
do {
|
||||
proto.setDataMessage(try dataMessage.build())
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
import PromiseKit
|
||||
|
||||
@objc(SNOpenGroupManager)
|
||||
public final class OpenGroupManager : NSObject {
|
||||
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> = []
|
||||
var messageTimestamps: Set<UInt64> = []
|
||||
thread.enumerateInteractions(with: transaction) { interaction, _ in
|
||||
messageIDs.insert(interaction.uniqueId!)
|
||||
messageTimestamps.insert(interaction.timestamp)
|
||||
}
|
||||
SNMessagingKitConfiguration.shared.storage.updateMessageIDCollectionByPruningMessagesWithIDs(messageIDs, using: transaction)
|
||||
Storage.shared.removeReceivedMessageTimestamps(messageTimestamps, 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)
|
||||
}
|
||||
}
|
|
@ -354,15 +354,15 @@ extension SNProtoTypingMessage.SNProtoTypingMessageBuilder {
|
|||
if let _value = dataMessage {
|
||||
builder.setDataMessage(_value)
|
||||
}
|
||||
if let _value = syncMessage {
|
||||
builder.setSyncMessage(_value)
|
||||
}
|
||||
if let _value = receiptMessage {
|
||||
builder.setReceiptMessage(_value)
|
||||
}
|
||||
if let _value = typingMessage {
|
||||
builder.setTypingMessage(_value)
|
||||
}
|
||||
if let _value = configurationMessage {
|
||||
builder.setConfigurationMessage(_value)
|
||||
}
|
||||
return builder
|
||||
}
|
||||
|
||||
|
@ -376,10 +376,6 @@ extension SNProtoTypingMessage.SNProtoTypingMessageBuilder {
|
|||
proto.dataMessage = valueParam.proto
|
||||
}
|
||||
|
||||
@objc public func setSyncMessage(_ valueParam: SNProtoSyncMessage) {
|
||||
proto.syncMessage = valueParam.proto
|
||||
}
|
||||
|
||||
@objc public func setReceiptMessage(_ valueParam: SNProtoReceiptMessage) {
|
||||
proto.receiptMessage = valueParam.proto
|
||||
}
|
||||
|
@ -388,6 +384,10 @@ extension SNProtoTypingMessage.SNProtoTypingMessageBuilder {
|
|||
proto.typingMessage = valueParam.proto
|
||||
}
|
||||
|
||||
@objc public func setConfigurationMessage(_ valueParam: SNProtoConfigurationMessage) {
|
||||
proto.configurationMessage = valueParam.proto
|
||||
}
|
||||
|
||||
@objc public func build() throws -> SNProtoContent {
|
||||
return try SNProtoContent.parseProto(proto)
|
||||
}
|
||||
|
@ -401,22 +401,22 @@ extension SNProtoTypingMessage.SNProtoTypingMessageBuilder {
|
|||
|
||||
@objc public let dataMessage: SNProtoDataMessage?
|
||||
|
||||
@objc public let syncMessage: SNProtoSyncMessage?
|
||||
|
||||
@objc public let receiptMessage: SNProtoReceiptMessage?
|
||||
|
||||
@objc public let typingMessage: SNProtoTypingMessage?
|
||||
|
||||
@objc public let configurationMessage: SNProtoConfigurationMessage?
|
||||
|
||||
private init(proto: SessionProtos_Content,
|
||||
dataMessage: SNProtoDataMessage?,
|
||||
syncMessage: SNProtoSyncMessage?,
|
||||
receiptMessage: SNProtoReceiptMessage?,
|
||||
typingMessage: SNProtoTypingMessage?) {
|
||||
typingMessage: SNProtoTypingMessage?,
|
||||
configurationMessage: SNProtoConfigurationMessage?) {
|
||||
self.proto = proto
|
||||
self.dataMessage = dataMessage
|
||||
self.syncMessage = syncMessage
|
||||
self.receiptMessage = receiptMessage
|
||||
self.typingMessage = typingMessage
|
||||
self.configurationMessage = configurationMessage
|
||||
}
|
||||
|
||||
@objc
|
||||
|
@ -435,11 +435,6 @@ extension SNProtoTypingMessage.SNProtoTypingMessageBuilder {
|
|||
dataMessage = try SNProtoDataMessage.parseProto(proto.dataMessage)
|
||||
}
|
||||
|
||||
var syncMessage: SNProtoSyncMessage? = nil
|
||||
if proto.hasSyncMessage {
|
||||
syncMessage = try SNProtoSyncMessage.parseProto(proto.syncMessage)
|
||||
}
|
||||
|
||||
var receiptMessage: SNProtoReceiptMessage? = nil
|
||||
if proto.hasReceiptMessage {
|
||||
receiptMessage = try SNProtoReceiptMessage.parseProto(proto.receiptMessage)
|
||||
|
@ -450,15 +445,20 @@ extension SNProtoTypingMessage.SNProtoTypingMessageBuilder {
|
|||
typingMessage = try SNProtoTypingMessage.parseProto(proto.typingMessage)
|
||||
}
|
||||
|
||||
var configurationMessage: SNProtoConfigurationMessage? = nil
|
||||
if proto.hasConfigurationMessage {
|
||||
configurationMessage = try SNProtoConfigurationMessage.parseProto(proto.configurationMessage)
|
||||
}
|
||||
|
||||
// MARK: - Begin Validation Logic for SNProtoContent -
|
||||
|
||||
// MARK: - End Validation Logic for SNProtoContent -
|
||||
|
||||
let result = SNProtoContent(proto: proto,
|
||||
dataMessage: dataMessage,
|
||||
syncMessage: syncMessage,
|
||||
receiptMessage: receiptMessage,
|
||||
typingMessage: typingMessage)
|
||||
typingMessage: typingMessage,
|
||||
configurationMessage: configurationMessage)
|
||||
return result
|
||||
}
|
||||
|
||||
|
@ -595,6 +595,118 @@ extension SNProtoClosedGroupCiphertextMessageWrapper.SNProtoClosedGroupCiphertex
|
|||
|
||||
#endif
|
||||
|
||||
// MARK: - SNProtoKeyPair
|
||||
|
||||
@objc public class SNProtoKeyPair: NSObject {
|
||||
|
||||
// MARK: - SNProtoKeyPairBuilder
|
||||
|
||||
@objc public class func builder(publicKey: Data, privateKey: Data) -> SNProtoKeyPairBuilder {
|
||||
return SNProtoKeyPairBuilder(publicKey: publicKey, privateKey: privateKey)
|
||||
}
|
||||
|
||||
// asBuilder() constructs a builder that reflects the proto's contents.
|
||||
@objc public func asBuilder() -> SNProtoKeyPairBuilder {
|
||||
let builder = SNProtoKeyPairBuilder(publicKey: publicKey, privateKey: privateKey)
|
||||
return builder
|
||||
}
|
||||
|
||||
@objc public class SNProtoKeyPairBuilder: NSObject {
|
||||
|
||||
private var proto = SessionProtos_KeyPair()
|
||||
|
||||
@objc fileprivate override init() {}
|
||||
|
||||
@objc fileprivate init(publicKey: Data, privateKey: Data) {
|
||||
super.init()
|
||||
|
||||
setPublicKey(publicKey)
|
||||
setPrivateKey(privateKey)
|
||||
}
|
||||
|
||||
@objc public func setPublicKey(_ valueParam: Data) {
|
||||
proto.publicKey = valueParam
|
||||
}
|
||||
|
||||
@objc public func setPrivateKey(_ valueParam: Data) {
|
||||
proto.privateKey = valueParam
|
||||
}
|
||||
|
||||
@objc public func build() throws -> SNProtoKeyPair {
|
||||
return try SNProtoKeyPair.parseProto(proto)
|
||||
}
|
||||
|
||||
@objc public func buildSerializedData() throws -> Data {
|
||||
return try SNProtoKeyPair.parseProto(proto).serializedData()
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate let proto: SessionProtos_KeyPair
|
||||
|
||||
@objc public let publicKey: Data
|
||||
|
||||
@objc public let privateKey: Data
|
||||
|
||||
private init(proto: SessionProtos_KeyPair,
|
||||
publicKey: Data,
|
||||
privateKey: Data) {
|
||||
self.proto = proto
|
||||
self.publicKey = publicKey
|
||||
self.privateKey = privateKey
|
||||
}
|
||||
|
||||
@objc
|
||||
public func serializedData() throws -> Data {
|
||||
return try self.proto.serializedData()
|
||||
}
|
||||
|
||||
@objc public class func parseData(_ serializedData: Data) throws -> SNProtoKeyPair {
|
||||
let proto = try SessionProtos_KeyPair(serializedData: serializedData)
|
||||
return try parseProto(proto)
|
||||
}
|
||||
|
||||
fileprivate class func parseProto(_ proto: SessionProtos_KeyPair) throws -> SNProtoKeyPair {
|
||||
guard proto.hasPublicKey else {
|
||||
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: publicKey")
|
||||
}
|
||||
let publicKey = proto.publicKey
|
||||
|
||||
guard proto.hasPrivateKey else {
|
||||
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: privateKey")
|
||||
}
|
||||
let privateKey = proto.privateKey
|
||||
|
||||
// MARK: - Begin Validation Logic for SNProtoKeyPair -
|
||||
|
||||
// MARK: - End Validation Logic for SNProtoKeyPair -
|
||||
|
||||
let result = SNProtoKeyPair(proto: proto,
|
||||
publicKey: publicKey,
|
||||
privateKey: privateKey)
|
||||
return result
|
||||
}
|
||||
|
||||
@objc public override var debugDescription: String {
|
||||
return "\(proto)"
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
extension SNProtoKeyPair {
|
||||
@objc public func serializedDataIgnoringErrors() -> Data? {
|
||||
return try! self.serializedData()
|
||||
}
|
||||
}
|
||||
|
||||
extension SNProtoKeyPair.SNProtoKeyPairBuilder {
|
||||
@objc public func buildIgnoringErrors() -> SNProtoKeyPair? {
|
||||
return try! self.build()
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// MARK: - SNProtoDataMessageQuoteQuotedAttachment
|
||||
|
||||
@objc public class SNProtoDataMessageQuoteQuotedAttachment: NSObject {
|
||||
|
@ -2172,118 +2284,6 @@ extension SNProtoDataMessageLokiProfile.SNProtoDataMessageLokiProfileBuilder {
|
|||
|
||||
#endif
|
||||
|
||||
// MARK: - SNProtoDataMessageClosedGroupControlMessageKeyPair
|
||||
|
||||
@objc public class SNProtoDataMessageClosedGroupControlMessageKeyPair: NSObject {
|
||||
|
||||
// MARK: - SNProtoDataMessageClosedGroupControlMessageKeyPairBuilder
|
||||
|
||||
@objc public class func builder(publicKey: Data, privateKey: Data) -> SNProtoDataMessageClosedGroupControlMessageKeyPairBuilder {
|
||||
return SNProtoDataMessageClosedGroupControlMessageKeyPairBuilder(publicKey: publicKey, privateKey: privateKey)
|
||||
}
|
||||
|
||||
// asBuilder() constructs a builder that reflects the proto's contents.
|
||||
@objc public func asBuilder() -> SNProtoDataMessageClosedGroupControlMessageKeyPairBuilder {
|
||||
let builder = SNProtoDataMessageClosedGroupControlMessageKeyPairBuilder(publicKey: publicKey, privateKey: privateKey)
|
||||
return builder
|
||||
}
|
||||
|
||||
@objc public class SNProtoDataMessageClosedGroupControlMessageKeyPairBuilder: NSObject {
|
||||
|
||||
private var proto = SessionProtos_DataMessage.ClosedGroupControlMessage.KeyPair()
|
||||
|
||||
@objc fileprivate override init() {}
|
||||
|
||||
@objc fileprivate init(publicKey: Data, privateKey: Data) {
|
||||
super.init()
|
||||
|
||||
setPublicKey(publicKey)
|
||||
setPrivateKey(privateKey)
|
||||
}
|
||||
|
||||
@objc public func setPublicKey(_ valueParam: Data) {
|
||||
proto.publicKey = valueParam
|
||||
}
|
||||
|
||||
@objc public func setPrivateKey(_ valueParam: Data) {
|
||||
proto.privateKey = valueParam
|
||||
}
|
||||
|
||||
@objc public func build() throws -> SNProtoDataMessageClosedGroupControlMessageKeyPair {
|
||||
return try SNProtoDataMessageClosedGroupControlMessageKeyPair.parseProto(proto)
|
||||
}
|
||||
|
||||
@objc public func buildSerializedData() throws -> Data {
|
||||
return try SNProtoDataMessageClosedGroupControlMessageKeyPair.parseProto(proto).serializedData()
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate let proto: SessionProtos_DataMessage.ClosedGroupControlMessage.KeyPair
|
||||
|
||||
@objc public let publicKey: Data
|
||||
|
||||
@objc public let privateKey: Data
|
||||
|
||||
private init(proto: SessionProtos_DataMessage.ClosedGroupControlMessage.KeyPair,
|
||||
publicKey: Data,
|
||||
privateKey: Data) {
|
||||
self.proto = proto
|
||||
self.publicKey = publicKey
|
||||
self.privateKey = privateKey
|
||||
}
|
||||
|
||||
@objc
|
||||
public func serializedData() throws -> Data {
|
||||
return try self.proto.serializedData()
|
||||
}
|
||||
|
||||
@objc public class func parseData(_ serializedData: Data) throws -> SNProtoDataMessageClosedGroupControlMessageKeyPair {
|
||||
let proto = try SessionProtos_DataMessage.ClosedGroupControlMessage.KeyPair(serializedData: serializedData)
|
||||
return try parseProto(proto)
|
||||
}
|
||||
|
||||
fileprivate class func parseProto(_ proto: SessionProtos_DataMessage.ClosedGroupControlMessage.KeyPair) throws -> SNProtoDataMessageClosedGroupControlMessageKeyPair {
|
||||
guard proto.hasPublicKey else {
|
||||
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: publicKey")
|
||||
}
|
||||
let publicKey = proto.publicKey
|
||||
|
||||
guard proto.hasPrivateKey else {
|
||||
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: privateKey")
|
||||
}
|
||||
let privateKey = proto.privateKey
|
||||
|
||||
// MARK: - Begin Validation Logic for SNProtoDataMessageClosedGroupControlMessageKeyPair -
|
||||
|
||||
// MARK: - End Validation Logic for SNProtoDataMessageClosedGroupControlMessageKeyPair -
|
||||
|
||||
let result = SNProtoDataMessageClosedGroupControlMessageKeyPair(proto: proto,
|
||||
publicKey: publicKey,
|
||||
privateKey: privateKey)
|
||||
return result
|
||||
}
|
||||
|
||||
@objc public override var debugDescription: String {
|
||||
return "\(proto)"
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
extension SNProtoDataMessageClosedGroupControlMessageKeyPair {
|
||||
@objc public func serializedDataIgnoringErrors() -> Data? {
|
||||
return try! self.serializedData()
|
||||
}
|
||||
}
|
||||
|
||||
extension SNProtoDataMessageClosedGroupControlMessageKeyPair.SNProtoDataMessageClosedGroupControlMessageKeyPairBuilder {
|
||||
@objc public func buildIgnoringErrors() -> SNProtoDataMessageClosedGroupControlMessageKeyPair? {
|
||||
return try! self.build()
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// MARK: - SNProtoDataMessageClosedGroupControlMessageKeyPairWrapper
|
||||
|
||||
@objc public class SNProtoDataMessageClosedGroupControlMessageKeyPairWrapper: NSObject {
|
||||
|
@ -2484,7 +2484,7 @@ extension SNProtoDataMessageClosedGroupControlMessageKeyPairWrapper.SNProtoDataM
|
|||
proto.name = valueParam
|
||||
}
|
||||
|
||||
@objc public func setEncryptionKeyPair(_ valueParam: SNProtoDataMessageClosedGroupControlMessageKeyPair) {
|
||||
@objc public func setEncryptionKeyPair(_ valueParam: SNProtoKeyPair) {
|
||||
proto.encryptionKeyPair = valueParam.proto
|
||||
}
|
||||
|
||||
|
@ -2531,7 +2531,7 @@ extension SNProtoDataMessageClosedGroupControlMessageKeyPairWrapper.SNProtoDataM
|
|||
|
||||
@objc public let type: SNProtoDataMessageClosedGroupControlMessageType
|
||||
|
||||
@objc public let encryptionKeyPair: SNProtoDataMessageClosedGroupControlMessageKeyPair?
|
||||
@objc public let encryptionKeyPair: SNProtoKeyPair?
|
||||
|
||||
@objc public let wrappers: [SNProtoDataMessageClosedGroupControlMessageKeyPairWrapper]
|
||||
|
||||
|
@ -2565,7 +2565,7 @@ extension SNProtoDataMessageClosedGroupControlMessageKeyPairWrapper.SNProtoDataM
|
|||
|
||||
private init(proto: SessionProtos_DataMessage.ClosedGroupControlMessage,
|
||||
type: SNProtoDataMessageClosedGroupControlMessageType,
|
||||
encryptionKeyPair: SNProtoDataMessageClosedGroupControlMessageKeyPair?,
|
||||
encryptionKeyPair: SNProtoKeyPair?,
|
||||
wrappers: [SNProtoDataMessageClosedGroupControlMessageKeyPairWrapper]) {
|
||||
self.proto = proto
|
||||
self.type = type
|
||||
|
@ -2589,9 +2589,9 @@ extension SNProtoDataMessageClosedGroupControlMessageKeyPairWrapper.SNProtoDataM
|
|||
}
|
||||
let type = SNProtoDataMessageClosedGroupControlMessageTypeWrap(proto.type)
|
||||
|
||||
var encryptionKeyPair: SNProtoDataMessageClosedGroupControlMessageKeyPair? = nil
|
||||
var encryptionKeyPair: SNProtoKeyPair? = nil
|
||||
if proto.hasEncryptionKeyPair {
|
||||
encryptionKeyPair = try SNProtoDataMessageClosedGroupControlMessageKeyPair.parseProto(proto.encryptionKeyPair)
|
||||
encryptionKeyPair = try SNProtoKeyPair.parseProto(proto.encryptionKeyPair)
|
||||
}
|
||||
|
||||
var wrappers: [SNProtoDataMessageClosedGroupControlMessageKeyPairWrapper] = []
|
||||
|
@ -2690,6 +2690,9 @@ extension SNProtoDataMessageClosedGroupControlMessage.SNProtoDataMessageClosedGr
|
|||
if let _value = closedGroupControlMessage {
|
||||
builder.setClosedGroupControlMessage(_value)
|
||||
}
|
||||
if let _value = syncTarget {
|
||||
builder.setSyncTarget(_value)
|
||||
}
|
||||
if let _value = publicChatInfo {
|
||||
builder.setPublicChatInfo(_value)
|
||||
}
|
||||
|
@ -2768,6 +2771,10 @@ extension SNProtoDataMessageClosedGroupControlMessage.SNProtoDataMessageClosedGr
|
|||
proto.closedGroupControlMessage = valueParam.proto
|
||||
}
|
||||
|
||||
@objc public func setSyncTarget(_ valueParam: String) {
|
||||
proto.syncTarget = valueParam
|
||||
}
|
||||
|
||||
@objc public func setPublicChatInfo(_ valueParam: SNProtoPublicChatInfo) {
|
||||
proto.publicChatInfo = valueParam.proto
|
||||
}
|
||||
|
@ -2840,6 +2847,16 @@ extension SNProtoDataMessageClosedGroupControlMessage.SNProtoDataMessageClosedGr
|
|||
return proto.hasTimestamp
|
||||
}
|
||||
|
||||
@objc public var syncTarget: String? {
|
||||
guard proto.hasSyncTarget else {
|
||||
return nil
|
||||
}
|
||||
return proto.syncTarget
|
||||
}
|
||||
@objc public var hasSyncTarget: Bool {
|
||||
return proto.hasSyncTarget
|
||||
}
|
||||
|
||||
private init(proto: SessionProtos_DataMessage,
|
||||
attachments: [SNProtoAttachmentPointer],
|
||||
group: SNProtoGroupContext?,
|
||||
|
@ -2942,6 +2959,275 @@ extension SNProtoDataMessage.SNProtoDataMessageBuilder {
|
|||
|
||||
#endif
|
||||
|
||||
// MARK: - SNProtoConfigurationMessageClosedGroup
|
||||
|
||||
@objc public class SNProtoConfigurationMessageClosedGroup: NSObject {
|
||||
|
||||
// MARK: - SNProtoConfigurationMessageClosedGroupBuilder
|
||||
|
||||
@objc public class func builder() -> SNProtoConfigurationMessageClosedGroupBuilder {
|
||||
return SNProtoConfigurationMessageClosedGroupBuilder()
|
||||
}
|
||||
|
||||
// asBuilder() constructs a builder that reflects the proto's contents.
|
||||
@objc public func asBuilder() -> SNProtoConfigurationMessageClosedGroupBuilder {
|
||||
let builder = SNProtoConfigurationMessageClosedGroupBuilder()
|
||||
if let _value = publicKey {
|
||||
builder.setPublicKey(_value)
|
||||
}
|
||||
if let _value = name {
|
||||
builder.setName(_value)
|
||||
}
|
||||
if let _value = encryptionKeyPair {
|
||||
builder.setEncryptionKeyPair(_value)
|
||||
}
|
||||
builder.setMembers(members)
|
||||
builder.setAdmins(admins)
|
||||
return builder
|
||||
}
|
||||
|
||||
@objc public class SNProtoConfigurationMessageClosedGroupBuilder: NSObject {
|
||||
|
||||
private var proto = SessionProtos_ConfigurationMessage.ClosedGroup()
|
||||
|
||||
@objc fileprivate override init() {}
|
||||
|
||||
@objc public func setPublicKey(_ valueParam: Data) {
|
||||
proto.publicKey = valueParam
|
||||
}
|
||||
|
||||
@objc public func setName(_ valueParam: String) {
|
||||
proto.name = valueParam
|
||||
}
|
||||
|
||||
@objc public func setEncryptionKeyPair(_ valueParam: SNProtoKeyPair) {
|
||||
proto.encryptionKeyPair = valueParam.proto
|
||||
}
|
||||
|
||||
@objc public func addMembers(_ valueParam: Data) {
|
||||
var items = proto.members
|
||||
items.append(valueParam)
|
||||
proto.members = items
|
||||
}
|
||||
|
||||
@objc public func setMembers(_ wrappedItems: [Data]) {
|
||||
proto.members = wrappedItems
|
||||
}
|
||||
|
||||
@objc public func addAdmins(_ valueParam: Data) {
|
||||
var items = proto.admins
|
||||
items.append(valueParam)
|
||||
proto.admins = items
|
||||
}
|
||||
|
||||
@objc public func setAdmins(_ wrappedItems: [Data]) {
|
||||
proto.admins = wrappedItems
|
||||
}
|
||||
|
||||
@objc public func build() throws -> SNProtoConfigurationMessageClosedGroup {
|
||||
return try SNProtoConfigurationMessageClosedGroup.parseProto(proto)
|
||||
}
|
||||
|
||||
@objc public func buildSerializedData() throws -> Data {
|
||||
return try SNProtoConfigurationMessageClosedGroup.parseProto(proto).serializedData()
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate let proto: SessionProtos_ConfigurationMessage.ClosedGroup
|
||||
|
||||
@objc public let encryptionKeyPair: SNProtoKeyPair?
|
||||
|
||||
@objc public var publicKey: Data? {
|
||||
guard proto.hasPublicKey else {
|
||||
return nil
|
||||
}
|
||||
return proto.publicKey
|
||||
}
|
||||
@objc public var hasPublicKey: Bool {
|
||||
return proto.hasPublicKey
|
||||
}
|
||||
|
||||
@objc public var name: String? {
|
||||
guard proto.hasName else {
|
||||
return nil
|
||||
}
|
||||
return proto.name
|
||||
}
|
||||
@objc public var hasName: Bool {
|
||||
return proto.hasName
|
||||
}
|
||||
|
||||
@objc public var members: [Data] {
|
||||
return proto.members
|
||||
}
|
||||
|
||||
@objc public var admins: [Data] {
|
||||
return proto.admins
|
||||
}
|
||||
|
||||
private init(proto: SessionProtos_ConfigurationMessage.ClosedGroup,
|
||||
encryptionKeyPair: SNProtoKeyPair?) {
|
||||
self.proto = proto
|
||||
self.encryptionKeyPair = encryptionKeyPair
|
||||
}
|
||||
|
||||
@objc
|
||||
public func serializedData() throws -> Data {
|
||||
return try self.proto.serializedData()
|
||||
}
|
||||
|
||||
@objc public class func parseData(_ serializedData: Data) throws -> SNProtoConfigurationMessageClosedGroup {
|
||||
let proto = try SessionProtos_ConfigurationMessage.ClosedGroup(serializedData: serializedData)
|
||||
return try parseProto(proto)
|
||||
}
|
||||
|
||||
fileprivate class func parseProto(_ proto: SessionProtos_ConfigurationMessage.ClosedGroup) throws -> SNProtoConfigurationMessageClosedGroup {
|
||||
var encryptionKeyPair: SNProtoKeyPair? = nil
|
||||
if proto.hasEncryptionKeyPair {
|
||||
encryptionKeyPair = try SNProtoKeyPair.parseProto(proto.encryptionKeyPair)
|
||||
}
|
||||
|
||||
// MARK: - Begin Validation Logic for SNProtoConfigurationMessageClosedGroup -
|
||||
|
||||
// MARK: - End Validation Logic for SNProtoConfigurationMessageClosedGroup -
|
||||
|
||||
let result = SNProtoConfigurationMessageClosedGroup(proto: proto,
|
||||
encryptionKeyPair: encryptionKeyPair)
|
||||
return result
|
||||
}
|
||||
|
||||
@objc public override var debugDescription: String {
|
||||
return "\(proto)"
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
extension SNProtoConfigurationMessageClosedGroup {
|
||||
@objc public func serializedDataIgnoringErrors() -> Data? {
|
||||
return try! self.serializedData()
|
||||
}
|
||||
}
|
||||
|
||||
extension SNProtoConfigurationMessageClosedGroup.SNProtoConfigurationMessageClosedGroupBuilder {
|
||||
@objc public func buildIgnoringErrors() -> SNProtoConfigurationMessageClosedGroup? {
|
||||
return try! self.build()
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// MARK: - SNProtoConfigurationMessage
|
||||
|
||||
@objc public class SNProtoConfigurationMessage: NSObject {
|
||||
|
||||
// MARK: - SNProtoConfigurationMessageBuilder
|
||||
|
||||
@objc public class func builder() -> SNProtoConfigurationMessageBuilder {
|
||||
return SNProtoConfigurationMessageBuilder()
|
||||
}
|
||||
|
||||
// asBuilder() constructs a builder that reflects the proto's contents.
|
||||
@objc public func asBuilder() -> SNProtoConfigurationMessageBuilder {
|
||||
let builder = SNProtoConfigurationMessageBuilder()
|
||||
builder.setClosedGroups(closedGroups)
|
||||
builder.setOpenGroups(openGroups)
|
||||
return builder
|
||||
}
|
||||
|
||||
@objc public class SNProtoConfigurationMessageBuilder: NSObject {
|
||||
|
||||
private var proto = SessionProtos_ConfigurationMessage()
|
||||
|
||||
@objc fileprivate override init() {}
|
||||
|
||||
@objc public func addClosedGroups(_ valueParam: SNProtoConfigurationMessageClosedGroup) {
|
||||
var items = proto.closedGroups
|
||||
items.append(valueParam.proto)
|
||||
proto.closedGroups = items
|
||||
}
|
||||
|
||||
@objc public func setClosedGroups(_ wrappedItems: [SNProtoConfigurationMessageClosedGroup]) {
|
||||
proto.closedGroups = wrappedItems.map { $0.proto }
|
||||
}
|
||||
|
||||
@objc public func addOpenGroups(_ valueParam: String) {
|
||||
var items = proto.openGroups
|
||||
items.append(valueParam)
|
||||
proto.openGroups = items
|
||||
}
|
||||
|
||||
@objc public func setOpenGroups(_ wrappedItems: [String]) {
|
||||
proto.openGroups = wrappedItems
|
||||
}
|
||||
|
||||
@objc public func build() throws -> SNProtoConfigurationMessage {
|
||||
return try SNProtoConfigurationMessage.parseProto(proto)
|
||||
}
|
||||
|
||||
@objc public func buildSerializedData() throws -> Data {
|
||||
return try SNProtoConfigurationMessage.parseProto(proto).serializedData()
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate let proto: SessionProtos_ConfigurationMessage
|
||||
|
||||
@objc public let closedGroups: [SNProtoConfigurationMessageClosedGroup]
|
||||
|
||||
@objc public var openGroups: [String] {
|
||||
return proto.openGroups
|
||||
}
|
||||
|
||||
private init(proto: SessionProtos_ConfigurationMessage,
|
||||
closedGroups: [SNProtoConfigurationMessageClosedGroup]) {
|
||||
self.proto = proto
|
||||
self.closedGroups = closedGroups
|
||||
}
|
||||
|
||||
@objc
|
||||
public func serializedData() throws -> Data {
|
||||
return try self.proto.serializedData()
|
||||
}
|
||||
|
||||
@objc public class func parseData(_ serializedData: Data) throws -> SNProtoConfigurationMessage {
|
||||
let proto = try SessionProtos_ConfigurationMessage(serializedData: serializedData)
|
||||
return try parseProto(proto)
|
||||
}
|
||||
|
||||
fileprivate class func parseProto(_ proto: SessionProtos_ConfigurationMessage) throws -> SNProtoConfigurationMessage {
|
||||
var closedGroups: [SNProtoConfigurationMessageClosedGroup] = []
|
||||
closedGroups = try proto.closedGroups.map { try SNProtoConfigurationMessageClosedGroup.parseProto($0) }
|
||||
|
||||
// MARK: - Begin Validation Logic for SNProtoConfigurationMessage -
|
||||
|
||||
// MARK: - End Validation Logic for SNProtoConfigurationMessage -
|
||||
|
||||
let result = SNProtoConfigurationMessage(proto: proto,
|
||||
closedGroups: closedGroups)
|
||||
return result
|
||||
}
|
||||
|
||||
@objc public override var debugDescription: String {
|
||||
return "\(proto)"
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
extension SNProtoConfigurationMessage {
|
||||
@objc public func serializedDataIgnoringErrors() -> Data? {
|
||||
return try! self.serializedData()
|
||||
}
|
||||
}
|
||||
|
||||
extension SNProtoConfigurationMessage.SNProtoConfigurationMessageBuilder {
|
||||
@objc public func buildIgnoringErrors() -> SNProtoConfigurationMessage? {
|
||||
return try! self.build()
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// MARK: - SNProtoReceiptMessage
|
||||
|
||||
@objc public class SNProtoReceiptMessage: NSObject {
|
||||
|
@ -3075,270 +3361,6 @@ extension SNProtoReceiptMessage.SNProtoReceiptMessageBuilder {
|
|||
|
||||
#endif
|
||||
|
||||
// MARK: - SNProtoSyncMessageSent
|
||||
|
||||
@objc public class SNProtoSyncMessageSent: NSObject {
|
||||
|
||||
// MARK: - SNProtoSyncMessageSentBuilder
|
||||
|
||||
@objc public class func builder() -> SNProtoSyncMessageSentBuilder {
|
||||
return SNProtoSyncMessageSentBuilder()
|
||||
}
|
||||
|
||||
// asBuilder() constructs a builder that reflects the proto's contents.
|
||||
@objc public func asBuilder() -> SNProtoSyncMessageSentBuilder {
|
||||
let builder = SNProtoSyncMessageSentBuilder()
|
||||
if let _value = destination {
|
||||
builder.setDestination(_value)
|
||||
}
|
||||
if hasTimestamp {
|
||||
builder.setTimestamp(timestamp)
|
||||
}
|
||||
if let _value = message {
|
||||
builder.setMessage(_value)
|
||||
}
|
||||
if hasExpirationStartTimestamp {
|
||||
builder.setExpirationStartTimestamp(expirationStartTimestamp)
|
||||
}
|
||||
if hasIsRecipientUpdate {
|
||||
builder.setIsRecipientUpdate(isRecipientUpdate)
|
||||
}
|
||||
return builder
|
||||
}
|
||||
|
||||
@objc public class SNProtoSyncMessageSentBuilder: NSObject {
|
||||
|
||||
private var proto = SessionProtos_SyncMessage.Sent()
|
||||
|
||||
@objc fileprivate override init() {}
|
||||
|
||||
@objc public func setDestination(_ valueParam: String) {
|
||||
proto.destination = valueParam
|
||||
}
|
||||
|
||||
@objc public func setTimestamp(_ valueParam: UInt64) {
|
||||
proto.timestamp = valueParam
|
||||
}
|
||||
|
||||
@objc public func setMessage(_ valueParam: SNProtoDataMessage) {
|
||||
proto.message = valueParam.proto
|
||||
}
|
||||
|
||||
@objc public func setExpirationStartTimestamp(_ valueParam: UInt64) {
|
||||
proto.expirationStartTimestamp = valueParam
|
||||
}
|
||||
|
||||
@objc public func setIsRecipientUpdate(_ valueParam: Bool) {
|
||||
proto.isRecipientUpdate = valueParam
|
||||
}
|
||||
|
||||
@objc public func build() throws -> SNProtoSyncMessageSent {
|
||||
return try SNProtoSyncMessageSent.parseProto(proto)
|
||||
}
|
||||
|
||||
@objc public func buildSerializedData() throws -> Data {
|
||||
return try SNProtoSyncMessageSent.parseProto(proto).serializedData()
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate let proto: SessionProtos_SyncMessage.Sent
|
||||
|
||||
@objc public let message: SNProtoDataMessage?
|
||||
|
||||
@objc public var destination: String? {
|
||||
guard proto.hasDestination else {
|
||||
return nil
|
||||
}
|
||||
return proto.destination
|
||||
}
|
||||
@objc public var hasDestination: Bool {
|
||||
return proto.hasDestination
|
||||
}
|
||||
|
||||
@objc public var timestamp: UInt64 {
|
||||
return proto.timestamp
|
||||
}
|
||||
@objc public var hasTimestamp: Bool {
|
||||
return proto.hasTimestamp
|
||||
}
|
||||
|
||||
@objc public var expirationStartTimestamp: UInt64 {
|
||||
return proto.expirationStartTimestamp
|
||||
}
|
||||
@objc public var hasExpirationStartTimestamp: Bool {
|
||||
return proto.hasExpirationStartTimestamp
|
||||
}
|
||||
|
||||
@objc public var isRecipientUpdate: Bool {
|
||||
return proto.isRecipientUpdate
|
||||
}
|
||||
@objc public var hasIsRecipientUpdate: Bool {
|
||||
return proto.hasIsRecipientUpdate
|
||||
}
|
||||
|
||||
private init(proto: SessionProtos_SyncMessage.Sent,
|
||||
message: SNProtoDataMessage?) {
|
||||
self.proto = proto
|
||||
self.message = message
|
||||
}
|
||||
|
||||
@objc
|
||||
public func serializedData() throws -> Data {
|
||||
return try self.proto.serializedData()
|
||||
}
|
||||
|
||||
@objc public class func parseData(_ serializedData: Data) throws -> SNProtoSyncMessageSent {
|
||||
let proto = try SessionProtos_SyncMessage.Sent(serializedData: serializedData)
|
||||
return try parseProto(proto)
|
||||
}
|
||||
|
||||
fileprivate class func parseProto(_ proto: SessionProtos_SyncMessage.Sent) throws -> SNProtoSyncMessageSent {
|
||||
var message: SNProtoDataMessage? = nil
|
||||
if proto.hasMessage {
|
||||
message = try SNProtoDataMessage.parseProto(proto.message)
|
||||
}
|
||||
|
||||
// MARK: - Begin Validation Logic for SNProtoSyncMessageSent -
|
||||
|
||||
// MARK: - End Validation Logic for SNProtoSyncMessageSent -
|
||||
|
||||
let result = SNProtoSyncMessageSent(proto: proto,
|
||||
message: message)
|
||||
return result
|
||||
}
|
||||
|
||||
@objc public override var debugDescription: String {
|
||||
return "\(proto)"
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
extension SNProtoSyncMessageSent {
|
||||
@objc public func serializedDataIgnoringErrors() -> Data? {
|
||||
return try! self.serializedData()
|
||||
}
|
||||
}
|
||||
|
||||
extension SNProtoSyncMessageSent.SNProtoSyncMessageSentBuilder {
|
||||
@objc public func buildIgnoringErrors() -> SNProtoSyncMessageSent? {
|
||||
return try! self.build()
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// MARK: - SNProtoSyncMessage
|
||||
|
||||
@objc public class SNProtoSyncMessage: NSObject {
|
||||
|
||||
// MARK: - SNProtoSyncMessageBuilder
|
||||
|
||||
@objc public class func builder() -> SNProtoSyncMessageBuilder {
|
||||
return SNProtoSyncMessageBuilder()
|
||||
}
|
||||
|
||||
// asBuilder() constructs a builder that reflects the proto's contents.
|
||||
@objc public func asBuilder() -> SNProtoSyncMessageBuilder {
|
||||
let builder = SNProtoSyncMessageBuilder()
|
||||
if let _value = sent {
|
||||
builder.setSent(_value)
|
||||
}
|
||||
if let _value = padding {
|
||||
builder.setPadding(_value)
|
||||
}
|
||||
return builder
|
||||
}
|
||||
|
||||
@objc public class SNProtoSyncMessageBuilder: NSObject {
|
||||
|
||||
private var proto = SessionProtos_SyncMessage()
|
||||
|
||||
@objc fileprivate override init() {}
|
||||
|
||||
@objc public func setSent(_ valueParam: SNProtoSyncMessageSent) {
|
||||
proto.sent = valueParam.proto
|
||||
}
|
||||
|
||||
@objc public func setPadding(_ valueParam: Data) {
|
||||
proto.padding = valueParam
|
||||
}
|
||||
|
||||
@objc public func build() throws -> SNProtoSyncMessage {
|
||||
return try SNProtoSyncMessage.parseProto(proto)
|
||||
}
|
||||
|
||||
@objc public func buildSerializedData() throws -> Data {
|
||||
return try SNProtoSyncMessage.parseProto(proto).serializedData()
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate let proto: SessionProtos_SyncMessage
|
||||
|
||||
@objc public let sent: SNProtoSyncMessageSent?
|
||||
|
||||
@objc public var padding: Data? {
|
||||
guard proto.hasPadding else {
|
||||
return nil
|
||||
}
|
||||
return proto.padding
|
||||
}
|
||||
@objc public var hasPadding: Bool {
|
||||
return proto.hasPadding
|
||||
}
|
||||
|
||||
private init(proto: SessionProtos_SyncMessage,
|
||||
sent: SNProtoSyncMessageSent?) {
|
||||
self.proto = proto
|
||||
self.sent = sent
|
||||
}
|
||||
|
||||
@objc
|
||||
public func serializedData() throws -> Data {
|
||||
return try self.proto.serializedData()
|
||||
}
|
||||
|
||||
@objc public class func parseData(_ serializedData: Data) throws -> SNProtoSyncMessage {
|
||||
let proto = try SessionProtos_SyncMessage(serializedData: serializedData)
|
||||
return try parseProto(proto)
|
||||
}
|
||||
|
||||
fileprivate class func parseProto(_ proto: SessionProtos_SyncMessage) throws -> SNProtoSyncMessage {
|
||||
var sent: SNProtoSyncMessageSent? = nil
|
||||
if proto.hasSent {
|
||||
sent = try SNProtoSyncMessageSent.parseProto(proto.sent)
|
||||
}
|
||||
|
||||
// MARK: - Begin Validation Logic for SNProtoSyncMessage -
|
||||
|
||||
// MARK: - End Validation Logic for SNProtoSyncMessage -
|
||||
|
||||
let result = SNProtoSyncMessage(proto: proto,
|
||||
sent: sent)
|
||||
return result
|
||||
}
|
||||
|
||||
@objc public override var debugDescription: String {
|
||||
return "\(proto)"
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
extension SNProtoSyncMessage {
|
||||
@objc public func serializedDataIgnoringErrors() -> Data? {
|
||||
return try! self.serializedData()
|
||||
}
|
||||
}
|
||||
|
||||
extension SNProtoSyncMessage.SNProtoSyncMessageBuilder {
|
||||
@objc public func buildIgnoringErrors() -> SNProtoSyncMessage? {
|
||||
return try! self.build()
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// MARK: - SNProtoAttachmentPointer
|
||||
|
||||
@objc public class SNProtoAttachmentPointer: NSObject {
|
||||
|
|
|
@ -209,15 +209,6 @@ struct SessionProtos_Content {
|
|||
/// Clears the value of `dataMessage`. Subsequent reads from it will return its default value.
|
||||
mutating func clearDataMessage() {_uniqueStorage()._dataMessage = nil}
|
||||
|
||||
var syncMessage: SessionProtos_SyncMessage {
|
||||
get {return _storage._syncMessage ?? SessionProtos_SyncMessage()}
|
||||
set {_uniqueStorage()._syncMessage = newValue}
|
||||
}
|
||||
/// Returns true if `syncMessage` has been explicitly set.
|
||||
var hasSyncMessage: Bool {return _storage._syncMessage != nil}
|
||||
/// Clears the value of `syncMessage`. Subsequent reads from it will return its default value.
|
||||
mutating func clearSyncMessage() {_uniqueStorage()._syncMessage = nil}
|
||||
|
||||
var receiptMessage: SessionProtos_ReceiptMessage {
|
||||
get {return _storage._receiptMessage ?? SessionProtos_ReceiptMessage()}
|
||||
set {_uniqueStorage()._receiptMessage = newValue}
|
||||
|
@ -236,6 +227,15 @@ struct SessionProtos_Content {
|
|||
/// Clears the value of `typingMessage`. Subsequent reads from it will return its default value.
|
||||
mutating func clearTypingMessage() {_uniqueStorage()._typingMessage = nil}
|
||||
|
||||
var configurationMessage: SessionProtos_ConfigurationMessage {
|
||||
get {return _storage._configurationMessage ?? SessionProtos_ConfigurationMessage()}
|
||||
set {_uniqueStorage()._configurationMessage = newValue}
|
||||
}
|
||||
/// Returns true if `configurationMessage` has been explicitly set.
|
||||
var hasConfigurationMessage: Bool {return _storage._configurationMessage != nil}
|
||||
/// Clears the value of `configurationMessage`. Subsequent reads from it will return its default value.
|
||||
mutating func clearConfigurationMessage() {_uniqueStorage()._configurationMessage = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
@ -276,6 +276,39 @@ struct SessionProtos_ClosedGroupCiphertextMessageWrapper {
|
|||
fileprivate var _ephemeralPublicKey: Data? = nil
|
||||
}
|
||||
|
||||
struct SessionProtos_KeyPair {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
/// @required
|
||||
var publicKey: Data {
|
||||
get {return _publicKey ?? SwiftProtobuf.Internal.emptyData}
|
||||
set {_publicKey = newValue}
|
||||
}
|
||||
/// Returns true if `publicKey` has been explicitly set.
|
||||
var hasPublicKey: Bool {return self._publicKey != nil}
|
||||
/// Clears the value of `publicKey`. Subsequent reads from it will return its default value.
|
||||
mutating func clearPublicKey() {self._publicKey = nil}
|
||||
|
||||
/// @required
|
||||
var privateKey: Data {
|
||||
get {return _privateKey ?? SwiftProtobuf.Internal.emptyData}
|
||||
set {_privateKey = newValue}
|
||||
}
|
||||
/// Returns true if `privateKey` has been explicitly set.
|
||||
var hasPrivateKey: Bool {return self._privateKey != nil}
|
||||
/// Clears the value of `privateKey`. Subsequent reads from it will return its default value.
|
||||
mutating func clearPrivateKey() {self._privateKey = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _publicKey: Data? = nil
|
||||
fileprivate var _privateKey: Data? = nil
|
||||
}
|
||||
|
||||
struct SessionProtos_DataMessage {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
|
@ -377,6 +410,15 @@ struct SessionProtos_DataMessage {
|
|||
/// Clears the value of `closedGroupControlMessage`. Subsequent reads from it will return its default value.
|
||||
mutating func clearClosedGroupControlMessage() {_uniqueStorage()._closedGroupControlMessage = nil}
|
||||
|
||||
var syncTarget: String {
|
||||
get {return _storage._syncTarget ?? String()}
|
||||
set {_uniqueStorage()._syncTarget = newValue}
|
||||
}
|
||||
/// Returns true if `syncTarget` has been explicitly set.
|
||||
var hasSyncTarget: Bool {return _storage._syncTarget != nil}
|
||||
/// Clears the value of `syncTarget`. Subsequent reads from it will return its default value.
|
||||
mutating func clearSyncTarget() {_uniqueStorage()._syncTarget = nil}
|
||||
|
||||
var publicChatInfo: SessionProtos_PublicChatInfo {
|
||||
get {return _storage._publicChatInfo ?? SessionProtos_PublicChatInfo()}
|
||||
set {_uniqueStorage()._publicChatInfo = newValue}
|
||||
|
@ -1062,8 +1104,8 @@ struct SessionProtos_DataMessage {
|
|||
/// Clears the value of `name`. Subsequent reads from it will return its default value.
|
||||
mutating func clearName() {_uniqueStorage()._name = nil}
|
||||
|
||||
var encryptionKeyPair: SessionProtos_DataMessage.ClosedGroupControlMessage.KeyPair {
|
||||
get {return _storage._encryptionKeyPair ?? SessionProtos_DataMessage.ClosedGroupControlMessage.KeyPair()}
|
||||
var encryptionKeyPair: SessionProtos_KeyPair {
|
||||
get {return _storage._encryptionKeyPair ?? SessionProtos_KeyPair()}
|
||||
set {_uniqueStorage()._encryptionKeyPair = newValue}
|
||||
}
|
||||
/// Returns true if `encryptionKeyPair` has been explicitly set.
|
||||
|
@ -1141,39 +1183,6 @@ struct SessionProtos_DataMessage {
|
|||
|
||||
}
|
||||
|
||||
struct KeyPair {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
/// @required
|
||||
var publicKey: Data {
|
||||
get {return _publicKey ?? SwiftProtobuf.Internal.emptyData}
|
||||
set {_publicKey = newValue}
|
||||
}
|
||||
/// Returns true if `publicKey` has been explicitly set.
|
||||
var hasPublicKey: Bool {return self._publicKey != nil}
|
||||
/// Clears the value of `publicKey`. Subsequent reads from it will return its default value.
|
||||
mutating func clearPublicKey() {self._publicKey = nil}
|
||||
|
||||
/// @required
|
||||
var privateKey: Data {
|
||||
get {return _privateKey ?? SwiftProtobuf.Internal.emptyData}
|
||||
set {_privateKey = newValue}
|
||||
}
|
||||
/// Returns true if `privateKey` has been explicitly set.
|
||||
var hasPrivateKey: Bool {return self._privateKey != nil}
|
||||
/// Clears the value of `privateKey`. Subsequent reads from it will return its default value.
|
||||
mutating func clearPrivateKey() {self._privateKey = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _publicKey: Data? = nil
|
||||
fileprivate var _privateKey: Data? = nil
|
||||
}
|
||||
|
||||
struct KeyPairWrapper {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
|
@ -1225,6 +1234,69 @@ extension SessionProtos_DataMessage.Flags: CaseIterable {
|
|||
|
||||
#endif // swift(>=4.2)
|
||||
|
||||
struct SessionProtos_ConfigurationMessage {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
var closedGroups: [SessionProtos_ConfigurationMessage.ClosedGroup] = []
|
||||
|
||||
var openGroups: [String] = []
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
struct ClosedGroup {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
var publicKey: Data {
|
||||
get {return _storage._publicKey ?? SwiftProtobuf.Internal.emptyData}
|
||||
set {_uniqueStorage()._publicKey = newValue}
|
||||
}
|
||||
/// Returns true if `publicKey` has been explicitly set.
|
||||
var hasPublicKey: Bool {return _storage._publicKey != nil}
|
||||
/// Clears the value of `publicKey`. Subsequent reads from it will return its default value.
|
||||
mutating func clearPublicKey() {_uniqueStorage()._publicKey = nil}
|
||||
|
||||
var name: String {
|
||||
get {return _storage._name ?? String()}
|
||||
set {_uniqueStorage()._name = newValue}
|
||||
}
|
||||
/// Returns true if `name` has been explicitly set.
|
||||
var hasName: Bool {return _storage._name != nil}
|
||||
/// Clears the value of `name`. Subsequent reads from it will return its default value.
|
||||
mutating func clearName() {_uniqueStorage()._name = nil}
|
||||
|
||||
var encryptionKeyPair: SessionProtos_KeyPair {
|
||||
get {return _storage._encryptionKeyPair ?? SessionProtos_KeyPair()}
|
||||
set {_uniqueStorage()._encryptionKeyPair = newValue}
|
||||
}
|
||||
/// Returns true if `encryptionKeyPair` has been explicitly set.
|
||||
var hasEncryptionKeyPair: Bool {return _storage._encryptionKeyPair != nil}
|
||||
/// Clears the value of `encryptionKeyPair`. Subsequent reads from it will return its default value.
|
||||
mutating func clearEncryptionKeyPair() {_uniqueStorage()._encryptionKeyPair = nil}
|
||||
|
||||
var members: [Data] {
|
||||
get {return _storage._members}
|
||||
set {_uniqueStorage()._members = newValue}
|
||||
}
|
||||
|
||||
var admins: [Data] {
|
||||
get {return _storage._admins}
|
||||
set {_uniqueStorage()._admins = newValue}
|
||||
}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _storage = _StorageClass.defaultInstance
|
||||
}
|
||||
|
||||
init() {}
|
||||
}
|
||||
|
||||
struct SessionProtos_ReceiptMessage {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
|
@ -1283,93 +1355,6 @@ extension SessionProtos_ReceiptMessage.TypeEnum: CaseIterable {
|
|||
|
||||
#endif // swift(>=4.2)
|
||||
|
||||
struct SessionProtos_SyncMessage {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
var sent: SessionProtos_SyncMessage.Sent {
|
||||
get {return _storage._sent ?? SessionProtos_SyncMessage.Sent()}
|
||||
set {_uniqueStorage()._sent = newValue}
|
||||
}
|
||||
/// Returns true if `sent` has been explicitly set.
|
||||
var hasSent: Bool {return _storage._sent != nil}
|
||||
/// Clears the value of `sent`. Subsequent reads from it will return its default value.
|
||||
mutating func clearSent() {_uniqueStorage()._sent = nil}
|
||||
|
||||
var padding: Data {
|
||||
get {return _storage._padding ?? SwiftProtobuf.Internal.emptyData}
|
||||
set {_uniqueStorage()._padding = newValue}
|
||||
}
|
||||
/// Returns true if `padding` has been explicitly set.
|
||||
var hasPadding: Bool {return _storage._padding != nil}
|
||||
/// Clears the value of `padding`. Subsequent reads from it will return its default value.
|
||||
mutating func clearPadding() {_uniqueStorage()._padding = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
struct Sent {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
var destination: String {
|
||||
get {return _storage._destination ?? String()}
|
||||
set {_uniqueStorage()._destination = newValue}
|
||||
}
|
||||
/// Returns true if `destination` has been explicitly set.
|
||||
var hasDestination: Bool {return _storage._destination != nil}
|
||||
/// Clears the value of `destination`. Subsequent reads from it will return its default value.
|
||||
mutating func clearDestination() {_uniqueStorage()._destination = nil}
|
||||
|
||||
var timestamp: UInt64 {
|
||||
get {return _storage._timestamp ?? 0}
|
||||
set {_uniqueStorage()._timestamp = newValue}
|
||||
}
|
||||
/// Returns true if `timestamp` has been explicitly set.
|
||||
var hasTimestamp: Bool {return _storage._timestamp != nil}
|
||||
/// Clears the value of `timestamp`. Subsequent reads from it will return its default value.
|
||||
mutating func clearTimestamp() {_uniqueStorage()._timestamp = nil}
|
||||
|
||||
var message: SessionProtos_DataMessage {
|
||||
get {return _storage._message ?? SessionProtos_DataMessage()}
|
||||
set {_uniqueStorage()._message = newValue}
|
||||
}
|
||||
/// Returns true if `message` has been explicitly set.
|
||||
var hasMessage: Bool {return _storage._message != nil}
|
||||
/// Clears the value of `message`. Subsequent reads from it will return its default value.
|
||||
mutating func clearMessage() {_uniqueStorage()._message = nil}
|
||||
|
||||
var expirationStartTimestamp: UInt64 {
|
||||
get {return _storage._expirationStartTimestamp ?? 0}
|
||||
set {_uniqueStorage()._expirationStartTimestamp = newValue}
|
||||
}
|
||||
/// Returns true if `expirationStartTimestamp` has been explicitly set.
|
||||
var hasExpirationStartTimestamp: Bool {return _storage._expirationStartTimestamp != nil}
|
||||
/// Clears the value of `expirationStartTimestamp`. Subsequent reads from it will return its default value.
|
||||
mutating func clearExpirationStartTimestamp() {_uniqueStorage()._expirationStartTimestamp = nil}
|
||||
|
||||
var isRecipientUpdate: Bool {
|
||||
get {return _storage._isRecipientUpdate ?? false}
|
||||
set {_uniqueStorage()._isRecipientUpdate = newValue}
|
||||
}
|
||||
/// Returns true if `isRecipientUpdate` has been explicitly set.
|
||||
var hasIsRecipientUpdate: Bool {return _storage._isRecipientUpdate != nil}
|
||||
/// Clears the value of `isRecipientUpdate`. Subsequent reads from it will return its default value.
|
||||
mutating func clearIsRecipientUpdate() {_uniqueStorage()._isRecipientUpdate = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _storage = _StorageClass.defaultInstance
|
||||
}
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _storage = _StorageClass.defaultInstance
|
||||
}
|
||||
|
||||
struct SessionProtos_AttachmentPointer {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
|
@ -2012,16 +1997,16 @@ extension SessionProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
|
|||
static let protoMessageName: String = _protobuf_package + ".Content"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "dataMessage"),
|
||||
2: .same(proto: "syncMessage"),
|
||||
5: .same(proto: "receiptMessage"),
|
||||
6: .same(proto: "typingMessage"),
|
||||
7: .same(proto: "configurationMessage"),
|
||||
]
|
||||
|
||||
fileprivate class _StorageClass {
|
||||
var _dataMessage: SessionProtos_DataMessage? = nil
|
||||
var _syncMessage: SessionProtos_SyncMessage? = nil
|
||||
var _receiptMessage: SessionProtos_ReceiptMessage? = nil
|
||||
var _typingMessage: SessionProtos_TypingMessage? = nil
|
||||
var _configurationMessage: SessionProtos_ConfigurationMessage? = nil
|
||||
|
||||
static let defaultInstance = _StorageClass()
|
||||
|
||||
|
@ -2029,9 +2014,9 @@ extension SessionProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
|
|||
|
||||
init(copying source: _StorageClass) {
|
||||
_dataMessage = source._dataMessage
|
||||
_syncMessage = source._syncMessage
|
||||
_receiptMessage = source._receiptMessage
|
||||
_typingMessage = source._typingMessage
|
||||
_configurationMessage = source._configurationMessage
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2045,7 +2030,7 @@ extension SessionProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
|
|||
public var isInitialized: Bool {
|
||||
return withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
if let v = _storage._dataMessage, !v.isInitialized {return false}
|
||||
if let v = _storage._syncMessage, !v.isInitialized {return false}
|
||||
if let v = _storage._configurationMessage, !v.isInitialized {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -2056,9 +2041,9 @@ extension SessionProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
|
|||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
switch fieldNumber {
|
||||
case 1: try decoder.decodeSingularMessageField(value: &_storage._dataMessage)
|
||||
case 2: try decoder.decodeSingularMessageField(value: &_storage._syncMessage)
|
||||
case 5: try decoder.decodeSingularMessageField(value: &_storage._receiptMessage)
|
||||
case 6: try decoder.decodeSingularMessageField(value: &_storage._typingMessage)
|
||||
case 7: try decoder.decodeSingularMessageField(value: &_storage._configurationMessage)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
@ -2070,15 +2055,15 @@ extension SessionProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
|
|||
if let v = _storage._dataMessage {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = _storage._syncMessage {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
|
||||
}
|
||||
if let v = _storage._receiptMessage {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 5)
|
||||
}
|
||||
if let v = _storage._typingMessage {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 6)
|
||||
}
|
||||
if let v = _storage._configurationMessage {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 7)
|
||||
}
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
@ -2089,9 +2074,9 @@ extension SessionProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
|
|||
let _storage = _args.0
|
||||
let rhs_storage = _args.1
|
||||
if _storage._dataMessage != rhs_storage._dataMessage {return false}
|
||||
if _storage._syncMessage != rhs_storage._syncMessage {return false}
|
||||
if _storage._receiptMessage != rhs_storage._receiptMessage {return false}
|
||||
if _storage._typingMessage != rhs_storage._typingMessage {return false}
|
||||
if _storage._configurationMessage != rhs_storage._configurationMessage {return false}
|
||||
return true
|
||||
}
|
||||
if !storagesAreEqual {return false}
|
||||
|
@ -2136,6 +2121,47 @@ extension SessionProtos_ClosedGroupCiphertextMessageWrapper: SwiftProtobuf.Messa
|
|||
}
|
||||
}
|
||||
|
||||
extension SessionProtos_KeyPair: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".KeyPair"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "publicKey"),
|
||||
2: .same(proto: "privateKey"),
|
||||
]
|
||||
|
||||
public var isInitialized: Bool {
|
||||
if self._publicKey == nil {return false}
|
||||
if self._privateKey == nil {return false}
|
||||
return true
|
||||
}
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
switch fieldNumber {
|
||||
case 1: try decoder.decodeSingularBytesField(value: &self._publicKey)
|
||||
case 2: try decoder.decodeSingularBytesField(value: &self._privateKey)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if let v = self._publicKey {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = self._privateKey {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 2)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: SessionProtos_KeyPair, rhs: SessionProtos_KeyPair) -> Bool {
|
||||
if lhs._publicKey != rhs._publicKey {return false}
|
||||
if lhs._privateKey != rhs._privateKey {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension SessionProtos_DataMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".DataMessage"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
|
@ -2151,6 +2177,7 @@ extension SessionProtos_DataMessage: SwiftProtobuf.Message, SwiftProtobuf._Messa
|
|||
10: .same(proto: "preview"),
|
||||
101: .same(proto: "profile"),
|
||||
104: .same(proto: "closedGroupControlMessage"),
|
||||
105: .same(proto: "syncTarget"),
|
||||
999: .same(proto: "publicChatInfo"),
|
||||
]
|
||||
|
||||
|
@ -2167,6 +2194,7 @@ extension SessionProtos_DataMessage: SwiftProtobuf.Message, SwiftProtobuf._Messa
|
|||
var _preview: [SessionProtos_DataMessage.Preview] = []
|
||||
var _profile: SessionProtos_DataMessage.LokiProfile? = nil
|
||||
var _closedGroupControlMessage: SessionProtos_DataMessage.ClosedGroupControlMessage? = nil
|
||||
var _syncTarget: String? = nil
|
||||
var _publicChatInfo: SessionProtos_PublicChatInfo? = nil
|
||||
|
||||
static let defaultInstance = _StorageClass()
|
||||
|
@ -2186,6 +2214,7 @@ extension SessionProtos_DataMessage: SwiftProtobuf.Message, SwiftProtobuf._Messa
|
|||
_preview = source._preview
|
||||
_profile = source._profile
|
||||
_closedGroupControlMessage = source._closedGroupControlMessage
|
||||
_syncTarget = source._syncTarget
|
||||
_publicChatInfo = source._publicChatInfo
|
||||
}
|
||||
}
|
||||
|
@ -2221,6 +2250,7 @@ extension SessionProtos_DataMessage: SwiftProtobuf.Message, SwiftProtobuf._Messa
|
|||
case 10: try decoder.decodeRepeatedMessageField(value: &_storage._preview)
|
||||
case 101: try decoder.decodeSingularMessageField(value: &_storage._profile)
|
||||
case 104: try decoder.decodeSingularMessageField(value: &_storage._closedGroupControlMessage)
|
||||
case 105: try decoder.decodeSingularStringField(value: &_storage._syncTarget)
|
||||
case 999: try decoder.decodeSingularMessageField(value: &_storage._publicChatInfo)
|
||||
default: break
|
||||
}
|
||||
|
@ -2266,6 +2296,9 @@ extension SessionProtos_DataMessage: SwiftProtobuf.Message, SwiftProtobuf._Messa
|
|||
if let v = _storage._closedGroupControlMessage {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 104)
|
||||
}
|
||||
if let v = _storage._syncTarget {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 105)
|
||||
}
|
||||
if let v = _storage._publicChatInfo {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 999)
|
||||
}
|
||||
|
@ -2290,6 +2323,7 @@ extension SessionProtos_DataMessage: SwiftProtobuf.Message, SwiftProtobuf._Messa
|
|||
if _storage._preview != rhs_storage._preview {return false}
|
||||
if _storage._profile != rhs_storage._profile {return false}
|
||||
if _storage._closedGroupControlMessage != rhs_storage._closedGroupControlMessage {return false}
|
||||
if _storage._syncTarget != rhs_storage._syncTarget {return false}
|
||||
if _storage._publicChatInfo != rhs_storage._publicChatInfo {return false}
|
||||
return true
|
||||
}
|
||||
|
@ -2986,7 +3020,7 @@ extension SessionProtos_DataMessage.ClosedGroupControlMessage: SwiftProtobuf.Mes
|
|||
var _type: SessionProtos_DataMessage.ClosedGroupControlMessage.TypeEnum? = nil
|
||||
var _publicKey: Data? = nil
|
||||
var _name: String? = nil
|
||||
var _encryptionKeyPair: SessionProtos_DataMessage.ClosedGroupControlMessage.KeyPair? = nil
|
||||
var _encryptionKeyPair: SessionProtos_KeyPair? = nil
|
||||
var _members: [Data] = []
|
||||
var _admins: [Data] = []
|
||||
var _wrappers: [SessionProtos_DataMessage.ClosedGroupControlMessage.KeyPairWrapper] = []
|
||||
|
@ -3100,47 +3134,6 @@ extension SessionProtos_DataMessage.ClosedGroupControlMessage.TypeEnum: SwiftPro
|
|||
]
|
||||
}
|
||||
|
||||
extension SessionProtos_DataMessage.ClosedGroupControlMessage.KeyPair: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = SessionProtos_DataMessage.ClosedGroupControlMessage.protoMessageName + ".KeyPair"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "publicKey"),
|
||||
2: .same(proto: "privateKey"),
|
||||
]
|
||||
|
||||
public var isInitialized: Bool {
|
||||
if self._publicKey == nil {return false}
|
||||
if self._privateKey == nil {return false}
|
||||
return true
|
||||
}
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
switch fieldNumber {
|
||||
case 1: try decoder.decodeSingularBytesField(value: &self._publicKey)
|
||||
case 2: try decoder.decodeSingularBytesField(value: &self._privateKey)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if let v = self._publicKey {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = self._privateKey {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 2)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: SessionProtos_DataMessage.ClosedGroupControlMessage.KeyPair, rhs: SessionProtos_DataMessage.ClosedGroupControlMessage.KeyPair) -> Bool {
|
||||
if lhs._publicKey != rhs._publicKey {return false}
|
||||
if lhs._privateKey != rhs._privateKey {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension SessionProtos_DataMessage.ClosedGroupControlMessage.KeyPairWrapper: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = SessionProtos_DataMessage.ClosedGroupControlMessage.protoMessageName + ".KeyPairWrapper"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
|
@ -3182,6 +3175,146 @@ extension SessionProtos_DataMessage.ClosedGroupControlMessage.KeyPairWrapper: Sw
|
|||
}
|
||||
}
|
||||
|
||||
extension SessionProtos_ConfigurationMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".ConfigurationMessage"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "closedGroups"),
|
||||
2: .same(proto: "openGroups"),
|
||||
]
|
||||
|
||||
public var isInitialized: Bool {
|
||||
if !SwiftProtobuf.Internal.areAllInitialized(self.closedGroups) {return false}
|
||||
return true
|
||||
}
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
switch fieldNumber {
|
||||
case 1: try decoder.decodeRepeatedMessageField(value: &self.closedGroups)
|
||||
case 2: try decoder.decodeRepeatedStringField(value: &self.openGroups)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if !self.closedGroups.isEmpty {
|
||||
try visitor.visitRepeatedMessageField(value: self.closedGroups, fieldNumber: 1)
|
||||
}
|
||||
if !self.openGroups.isEmpty {
|
||||
try visitor.visitRepeatedStringField(value: self.openGroups, fieldNumber: 2)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: SessionProtos_ConfigurationMessage, rhs: SessionProtos_ConfigurationMessage) -> Bool {
|
||||
if lhs.closedGroups != rhs.closedGroups {return false}
|
||||
if lhs.openGroups != rhs.openGroups {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension SessionProtos_ConfigurationMessage.ClosedGroup: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = SessionProtos_ConfigurationMessage.protoMessageName + ".ClosedGroup"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "publicKey"),
|
||||
2: .same(proto: "name"),
|
||||
3: .same(proto: "encryptionKeyPair"),
|
||||
4: .same(proto: "members"),
|
||||
5: .same(proto: "admins"),
|
||||
]
|
||||
|
||||
fileprivate class _StorageClass {
|
||||
var _publicKey: Data? = nil
|
||||
var _name: String? = nil
|
||||
var _encryptionKeyPair: SessionProtos_KeyPair? = nil
|
||||
var _members: [Data] = []
|
||||
var _admins: [Data] = []
|
||||
|
||||
static let defaultInstance = _StorageClass()
|
||||
|
||||
private init() {}
|
||||
|
||||
init(copying source: _StorageClass) {
|
||||
_publicKey = source._publicKey
|
||||
_name = source._name
|
||||
_encryptionKeyPair = source._encryptionKeyPair
|
||||
_members = source._members
|
||||
_admins = source._admins
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate mutating func _uniqueStorage() -> _StorageClass {
|
||||
if !isKnownUniquelyReferenced(&_storage) {
|
||||
_storage = _StorageClass(copying: _storage)
|
||||
}
|
||||
return _storage
|
||||
}
|
||||
|
||||
public var isInitialized: Bool {
|
||||
return withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
if let v = _storage._encryptionKeyPair, !v.isInitialized {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
_ = _uniqueStorage()
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
switch fieldNumber {
|
||||
case 1: try decoder.decodeSingularBytesField(value: &_storage._publicKey)
|
||||
case 2: try decoder.decodeSingularStringField(value: &_storage._name)
|
||||
case 3: try decoder.decodeSingularMessageField(value: &_storage._encryptionKeyPair)
|
||||
case 4: try decoder.decodeRepeatedBytesField(value: &_storage._members)
|
||||
case 5: try decoder.decodeRepeatedBytesField(value: &_storage._admins)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
if let v = _storage._publicKey {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = _storage._name {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 2)
|
||||
}
|
||||
if let v = _storage._encryptionKeyPair {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
|
||||
}
|
||||
if !_storage._members.isEmpty {
|
||||
try visitor.visitRepeatedBytesField(value: _storage._members, fieldNumber: 4)
|
||||
}
|
||||
if !_storage._admins.isEmpty {
|
||||
try visitor.visitRepeatedBytesField(value: _storage._admins, fieldNumber: 5)
|
||||
}
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: SessionProtos_ConfigurationMessage.ClosedGroup, rhs: SessionProtos_ConfigurationMessage.ClosedGroup) -> Bool {
|
||||
if lhs._storage !== rhs._storage {
|
||||
let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in
|
||||
let _storage = _args.0
|
||||
let rhs_storage = _args.1
|
||||
if _storage._publicKey != rhs_storage._publicKey {return false}
|
||||
if _storage._name != rhs_storage._name {return false}
|
||||
if _storage._encryptionKeyPair != rhs_storage._encryptionKeyPair {return false}
|
||||
if _storage._members != rhs_storage._members {return false}
|
||||
if _storage._admins != rhs_storage._admins {return false}
|
||||
return true
|
||||
}
|
||||
if !storagesAreEqual {return false}
|
||||
}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension SessionProtos_ReceiptMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".ReceiptMessage"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
|
@ -3224,182 +3357,6 @@ extension SessionProtos_ReceiptMessage.TypeEnum: SwiftProtobuf._ProtoNameProvidi
|
|||
]
|
||||
}
|
||||
|
||||
extension SessionProtos_SyncMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".SyncMessage"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "sent"),
|
||||
8: .same(proto: "padding"),
|
||||
]
|
||||
|
||||
fileprivate class _StorageClass {
|
||||
var _sent: SessionProtos_SyncMessage.Sent? = nil
|
||||
var _padding: Data? = nil
|
||||
|
||||
static let defaultInstance = _StorageClass()
|
||||
|
||||
private init() {}
|
||||
|
||||
init(copying source: _StorageClass) {
|
||||
_sent = source._sent
|
||||
_padding = source._padding
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate mutating func _uniqueStorage() -> _StorageClass {
|
||||
if !isKnownUniquelyReferenced(&_storage) {
|
||||
_storage = _StorageClass(copying: _storage)
|
||||
}
|
||||
return _storage
|
||||
}
|
||||
|
||||
public var isInitialized: Bool {
|
||||
return withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
if let v = _storage._sent, !v.isInitialized {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
_ = _uniqueStorage()
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
switch fieldNumber {
|
||||
case 1: try decoder.decodeSingularMessageField(value: &_storage._sent)
|
||||
case 8: try decoder.decodeSingularBytesField(value: &_storage._padding)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
if let v = _storage._sent {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = _storage._padding {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 8)
|
||||
}
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: SessionProtos_SyncMessage, rhs: SessionProtos_SyncMessage) -> Bool {
|
||||
if lhs._storage !== rhs._storage {
|
||||
let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in
|
||||
let _storage = _args.0
|
||||
let rhs_storage = _args.1
|
||||
if _storage._sent != rhs_storage._sent {return false}
|
||||
if _storage._padding != rhs_storage._padding {return false}
|
||||
return true
|
||||
}
|
||||
if !storagesAreEqual {return false}
|
||||
}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension SessionProtos_SyncMessage.Sent: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = SessionProtos_SyncMessage.protoMessageName + ".Sent"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "destination"),
|
||||
2: .same(proto: "timestamp"),
|
||||
3: .same(proto: "message"),
|
||||
4: .same(proto: "expirationStartTimestamp"),
|
||||
6: .same(proto: "isRecipientUpdate"),
|
||||
]
|
||||
|
||||
fileprivate class _StorageClass {
|
||||
var _destination: String? = nil
|
||||
var _timestamp: UInt64? = nil
|
||||
var _message: SessionProtos_DataMessage? = nil
|
||||
var _expirationStartTimestamp: UInt64? = nil
|
||||
var _isRecipientUpdate: Bool? = nil
|
||||
|
||||
static let defaultInstance = _StorageClass()
|
||||
|
||||
private init() {}
|
||||
|
||||
init(copying source: _StorageClass) {
|
||||
_destination = source._destination
|
||||
_timestamp = source._timestamp
|
||||
_message = source._message
|
||||
_expirationStartTimestamp = source._expirationStartTimestamp
|
||||
_isRecipientUpdate = source._isRecipientUpdate
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate mutating func _uniqueStorage() -> _StorageClass {
|
||||
if !isKnownUniquelyReferenced(&_storage) {
|
||||
_storage = _StorageClass(copying: _storage)
|
||||
}
|
||||
return _storage
|
||||
}
|
||||
|
||||
public var isInitialized: Bool {
|
||||
return withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
if let v = _storage._message, !v.isInitialized {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
_ = _uniqueStorage()
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
switch fieldNumber {
|
||||
case 1: try decoder.decodeSingularStringField(value: &_storage._destination)
|
||||
case 2: try decoder.decodeSingularUInt64Field(value: &_storage._timestamp)
|
||||
case 3: try decoder.decodeSingularMessageField(value: &_storage._message)
|
||||
case 4: try decoder.decodeSingularUInt64Field(value: &_storage._expirationStartTimestamp)
|
||||
case 6: try decoder.decodeSingularBoolField(value: &_storage._isRecipientUpdate)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
if let v = _storage._destination {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = _storage._timestamp {
|
||||
try visitor.visitSingularUInt64Field(value: v, fieldNumber: 2)
|
||||
}
|
||||
if let v = _storage._message {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
|
||||
}
|
||||
if let v = _storage._expirationStartTimestamp {
|
||||
try visitor.visitSingularUInt64Field(value: v, fieldNumber: 4)
|
||||
}
|
||||
if let v = _storage._isRecipientUpdate {
|
||||
try visitor.visitSingularBoolField(value: v, fieldNumber: 6)
|
||||
}
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: SessionProtos_SyncMessage.Sent, rhs: SessionProtos_SyncMessage.Sent) -> Bool {
|
||||
if lhs._storage !== rhs._storage {
|
||||
let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in
|
||||
let _storage = _args.0
|
||||
let rhs_storage = _args.1
|
||||
if _storage._destination != rhs_storage._destination {return false}
|
||||
if _storage._timestamp != rhs_storage._timestamp {return false}
|
||||
if _storage._message != rhs_storage._message {return false}
|
||||
if _storage._expirationStartTimestamp != rhs_storage._expirationStartTimestamp {return false}
|
||||
if _storage._isRecipientUpdate != rhs_storage._isRecipientUpdate {return false}
|
||||
return true
|
||||
}
|
||||
if !storagesAreEqual {return false}
|
||||
}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension SessionProtos_AttachmentPointer: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".AttachmentPointer"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
|
|
|
@ -35,10 +35,10 @@ message TypingMessage {
|
|||
}
|
||||
|
||||
message Content {
|
||||
optional DataMessage dataMessage = 1;
|
||||
optional SyncMessage syncMessage = 2;
|
||||
optional ReceiptMessage receiptMessage = 5;
|
||||
optional TypingMessage typingMessage = 6;
|
||||
optional DataMessage dataMessage = 1;
|
||||
optional ReceiptMessage receiptMessage = 5;
|
||||
optional TypingMessage typingMessage = 6;
|
||||
optional ConfigurationMessage configurationMessage = 7;
|
||||
}
|
||||
|
||||
message ClosedGroupCiphertextMessageWrapper {
|
||||
|
@ -48,6 +48,13 @@ message ClosedGroupCiphertextMessageWrapper {
|
|||
optional bytes ephemeralPublicKey = 2;
|
||||
}
|
||||
|
||||
message KeyPair {
|
||||
// @required
|
||||
required bytes publicKey = 1;
|
||||
// @required
|
||||
required bytes privateKey = 2;
|
||||
}
|
||||
|
||||
message DataMessage {
|
||||
|
||||
enum Flags {
|
||||
|
@ -171,13 +178,6 @@ message DataMessage {
|
|||
MEMBER_LEFT = 7;
|
||||
}
|
||||
|
||||
message KeyPair {
|
||||
// @required
|
||||
required bytes publicKey = 1;
|
||||
// @required
|
||||
required bytes privateKey = 2;
|
||||
}
|
||||
|
||||
message KeyPairWrapper {
|
||||
// @required
|
||||
required bytes publicKey = 1; // The public key of the user the key pair is meant for
|
||||
|
@ -207,9 +207,24 @@ message DataMessage {
|
|||
repeated Preview preview = 10;
|
||||
optional LokiProfile profile = 101;
|
||||
optional ClosedGroupControlMessage closedGroupControlMessage = 104;
|
||||
optional string syncTarget = 105;
|
||||
optional PublicChatInfo publicChatInfo = 999;
|
||||
}
|
||||
|
||||
message ConfigurationMessage {
|
||||
|
||||
message ClosedGroup {
|
||||
optional bytes publicKey = 1;
|
||||
optional string name = 2;
|
||||
optional KeyPair encryptionKeyPair = 3;
|
||||
repeated bytes members = 4;
|
||||
repeated bytes admins = 5;
|
||||
}
|
||||
|
||||
repeated ClosedGroup closedGroups = 1;
|
||||
repeated string openGroups = 2;
|
||||
}
|
||||
|
||||
message ReceiptMessage {
|
||||
|
||||
enum Type {
|
||||
|
@ -222,20 +237,6 @@ message ReceiptMessage {
|
|||
repeated uint64 timestamp = 2;
|
||||
}
|
||||
|
||||
message SyncMessage {
|
||||
|
||||
message Sent {
|
||||
optional string destination = 1;
|
||||
optional uint64 timestamp = 2;
|
||||
optional DataMessage message = 3;
|
||||
optional uint64 expirationStartTimestamp = 4;
|
||||
optional bool isRecipientUpdate = 6 [default = false];
|
||||
}
|
||||
|
||||
optional Sent sent = 1;
|
||||
optional bytes padding = 8;
|
||||
}
|
||||
|
||||
message AttachmentPointer {
|
||||
|
||||
enum Flags {
|
||||
|
|
|
@ -13,6 +13,7 @@ extension MessageReceiver {
|
|||
case let message as TypingIndicator: handleTypingIndicator(message, using: transaction)
|
||||
case let message as ClosedGroupControlMessage: handleClosedGroupControlMessage(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()
|
||||
}
|
||||
|
@ -141,6 +142,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 }
|
||||
OpenGroupManager.shared.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 {
|
||||
|
@ -182,7 +199,7 @@ extension MessageReceiver {
|
|||
}
|
||||
}
|
||||
// Get or create thread
|
||||
guard let threadID = storage.getOrCreateThread(for: message.sender!, groupPublicKey: message.groupPublicKey, openGroupID: openGroupID, using: transaction) else { throw Error.noThread }
|
||||
guard let threadID = storage.getOrCreateThread(for: message.syncTarget ?? message.sender!, groupPublicKey: message.groupPublicKey, openGroupID: openGroupID, using: transaction) else { throw Error.noThread }
|
||||
// Parse quote if needed
|
||||
var tsQuotedMessage: TSQuotedMessage? = nil
|
||||
if message.quote != nil && proto.dataMessage?.quote != nil, let thread = TSThread.fetch(uniqueId: threadID, transaction: transaction) {
|
||||
|
@ -200,12 +217,12 @@ extension MessageReceiver {
|
|||
}
|
||||
}
|
||||
// Persist the message
|
||||
guard let tsIncomingMessageID = storage.persist(message, quotedMessage: tsQuotedMessage, linkPreview: owsLinkPreview,
|
||||
guard let tsMessageID = storage.persist(message, quotedMessage: tsQuotedMessage, linkPreview: owsLinkPreview,
|
||||
groupPublicKey: message.groupPublicKey, openGroupID: openGroupID, using: transaction) else { throw Error.noThread }
|
||||
message.threadID = threadID
|
||||
// Start attachment downloads if needed
|
||||
attachmentsToDownload.forEach { attachmentID in
|
||||
let downloadJob = AttachmentDownloadJob(attachmentID: attachmentID, tsIncomingMessageID: tsIncomingMessageID)
|
||||
let downloadJob = AttachmentDownloadJob(attachmentID: attachmentID, tsMessageID: tsMessageID)
|
||||
if isMainAppAndActive {
|
||||
JobQueue.shared.add(downloadJob, using: transaction)
|
||||
} else {
|
||||
|
@ -218,13 +235,13 @@ extension MessageReceiver {
|
|||
}
|
||||
// Keep track of the open group server message ID ↔ message ID relationship
|
||||
if let serverID = message.openGroupServerMessageID {
|
||||
storage.setIDForMessage(withServerID: serverID, to: tsIncomingMessageID, using: transaction)
|
||||
storage.setIDForMessage(withServerID: serverID, to: tsMessageID, using: transaction)
|
||||
}
|
||||
// Notify the user if needed
|
||||
guard (isMainAppAndActive || isBackgroundPoll), let tsIncomingMessage = TSIncomingMessage.fetch(uniqueId: tsIncomingMessageID, transaction: transaction),
|
||||
let thread = TSThread.fetch(uniqueId: threadID, transaction: transaction) else { return tsIncomingMessageID }
|
||||
guard (isMainAppAndActive || isBackgroundPoll), let tsIncomingMessage = TSMessage.fetch(uniqueId: tsMessageID, transaction: transaction) as? TSIncomingMessage,
|
||||
let thread = TSThread.fetch(uniqueId: threadID, transaction: transaction) else { return tsMessageID }
|
||||
SSKEnvironment.shared.notificationsManager!.notifyUser(for: tsIncomingMessage, in: thread, transaction: transaction)
|
||||
return tsIncomingMessageID
|
||||
return tsMessageID
|
||||
}
|
||||
|
||||
private static func handleClosedGroupControlMessage(_ message: ClosedGroupControlMessage, using transaction: Any) {
|
||||
|
@ -242,11 +259,14 @@ extension MessageReceiver {
|
|||
private static func handleNewClosedGroup(_ message: ClosedGroupControlMessage, using transaction: Any) {
|
||||
// Prepare
|
||||
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)
|
||||
|
@ -294,9 +314,9 @@ extension MessageReceiver {
|
|||
return SNLog("Couldn't decrypt closed group encryption key pair.")
|
||||
}
|
||||
// Parse it
|
||||
let proto: SNProtoDataMessageClosedGroupControlMessageKeyPair
|
||||
let proto: SNProtoKeyPair
|
||||
do {
|
||||
proto = try SNProtoDataMessageClosedGroupControlMessageKeyPair.parseData(plaintext)
|
||||
proto = try SNProtoKeyPair.parseData(plaintext)
|
||||
} catch {
|
||||
return SNLog("Couldn't parse closed group encryption key pair.")
|
||||
}
|
||||
|
@ -341,7 +361,7 @@ extension MessageReceiver {
|
|||
infoMessage.save(with: transaction)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static func handleClosedGroupMembersRemoved(_ message: ClosedGroupControlMessage, using transaction: Any) {
|
||||
guard case let .membersRemoved(membersAsData) = message.kind else { return }
|
||||
let transaction = transaction as! YapDatabaseReadWriteTransaction
|
||||
|
@ -364,6 +384,7 @@ extension MessageReceiver {
|
|||
let _ = PushNotificationAPI.performOperation(.unsubscribe, for: groupPublicKey, publicKey: userPublicKey)
|
||||
}
|
||||
// Generate and distribute a new encryption key pair if needed
|
||||
// NOTE: If we're the admin we can be sure at this point that we weren't removed
|
||||
let isCurrentUserAdmin = group.groupAdminIds.contains(getUserHexEncodedPublicKey())
|
||||
if isCurrentUserAdmin {
|
||||
do {
|
||||
|
|
|
@ -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 closedGroupControlMessage = ClosedGroupControlMessage.fromProto(proto) { return closedGroupControlMessage }
|
||||
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.isSelfSendValid {
|
||||
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
|
||||
|
|
|
@ -62,7 +62,7 @@ extension MessageSender {
|
|||
// Generate the new encryption key pair
|
||||
let newKeyPair = Curve25519.generateKeyPair()
|
||||
// Distribute it
|
||||
let proto = try SNProtoDataMessageClosedGroupControlMessageKeyPair.builder(publicKey: newKeyPair.publicKey,
|
||||
let proto = try SNProtoKeyPair.builder(publicKey: newKeyPair.publicKey,
|
||||
privateKey: newKeyPair.privateKey).build()
|
||||
let plaintext = try proto.serializedData()
|
||||
let wrappers = try targetMembers.compactMap { publicKey -> ClosedGroupControlMessage.KeyPairWrapper in
|
||||
|
@ -165,6 +165,7 @@ extension MessageSender {
|
|||
|
||||
public static func removeMembers(_ membersToRemove: Set<String>, to groupPublicKey: String, using transaction: YapDatabaseReadWriteTransaction) throws {
|
||||
// Get the group, check preconditions & prepare
|
||||
let userPublicKey = getUserHexEncodedPublicKey()
|
||||
let groupID = LKGroupUtilities.getEncodedClosedGroupIDAsData(groupPublicKey)
|
||||
let threadID = TSGroupThread.threadId(fromGroupId: groupID)
|
||||
guard let thread = TSGroupThread.fetch(uniqueId: threadID, transaction: transaction) else {
|
||||
|
@ -175,9 +176,13 @@ extension MessageSender {
|
|||
SNLog("Invalid closed group update.")
|
||||
throw Error.invalidClosedGroupUpdate
|
||||
}
|
||||
guard !membersToRemove.contains(userPublicKey) else {
|
||||
SNLog("Invalid closed group update.")
|
||||
throw Error.invalidClosedGroupUpdate
|
||||
}
|
||||
let group = thread.groupModel
|
||||
let members = Set(group.groupMemberIds).subtracting(membersToRemove)
|
||||
let isCurrentUserAdmin = group.groupAdminIds.contains(getUserHexEncodedPublicKey())
|
||||
let isCurrentUserAdmin = group.groupAdminIds.contains(userPublicKey)
|
||||
// Send the update to the group and generate + distribute a new encryption key pair if needed
|
||||
let closedGroupControlMessage = ClosedGroupControlMessage(kind: .membersRemoved(members: membersToRemove.map { Data(hex: $0) }))
|
||||
if isCurrentUserAdmin {
|
||||
|
|
|
@ -105,7 +105,7 @@ public final class MessageSender : NSObject {
|
|||
}
|
||||
|
||||
// MARK: One-on-One Chats & Closed Groups
|
||||
internal static func sendToSnodeDestination(_ destination: Message.Destination, message: Message, using transaction: Any) -> Promise<Void> {
|
||||
internal static func sendToSnodeDestination(_ destination: Message.Destination, message: Message, using transaction: Any, isSyncMessage: Bool = false) -> Promise<Void> {
|
||||
let (promise, seal) = Promise<Void>.pending()
|
||||
let storage = SNMessagingKitConfiguration.shared.storage
|
||||
let transaction = transaction as! YapDatabaseReadWriteTransaction
|
||||
|
@ -137,8 +137,8 @@ public final class MessageSender : NSObject {
|
|||
}
|
||||
// Validate the message
|
||||
guard message.isValid else { handleFailure(with: Error.invalidMessage, using: transaction); return promise }
|
||||
// Stop here if this is a self-send
|
||||
guard !isSelfSend else {
|
||||
// Stop here if this is a self-send (unless it's a configuration message or a sync message)
|
||||
guard !isSelfSend || message is ConfigurationMessage || isSyncMessage else {
|
||||
storage.write(with: { transaction in
|
||||
MessageSender.handleSuccessfulMessageSend(message, to: destination, using: transaction)
|
||||
seal.fulfill(())
|
||||
|
@ -240,8 +240,8 @@ public final class MessageSender : NSObject {
|
|||
}
|
||||
}
|
||||
storage.write(with: { transaction in
|
||||
MessageSender.handleSuccessfulMessageSend(message, to: destination, using: transaction)
|
||||
var shouldNotify = (message is VisibleMessage)
|
||||
MessageSender.handleSuccessfulMessageSend(message, to: destination, isSyncMessage: isSyncMessage, using: transaction)
|
||||
var shouldNotify = (message is VisibleMessage && !isSyncMessage)
|
||||
if let closedGroupControlMessage = message as? ClosedGroupControlMessage, case .new = closedGroupControlMessage.kind {
|
||||
shouldNotify = true
|
||||
}
|
||||
|
@ -339,10 +339,12 @@ public final class MessageSender : NSObject {
|
|||
}
|
||||
|
||||
// MARK: Success & Failure Handling
|
||||
public static func handleSuccessfulMessageSend(_ message: Message, to destination: Message.Destination, using transaction: Any) {
|
||||
public static func handleSuccessfulMessageSend(_ message: Message, to destination: Message.Destination, isSyncMessage: Bool = false, using transaction: Any) {
|
||||
let storage = SNMessagingKitConfiguration.shared.storage
|
||||
let transaction = transaction as! YapDatabaseReadWriteTransaction
|
||||
guard let tsMessage = TSOutgoingMessage.find(withTimestamp: message.sentTimestamp!) else { return }
|
||||
// Ignore future self-sends
|
||||
Storage.shared.addReceivedMessageTimestamp(message.sentTimestamp!, using: transaction)
|
||||
// Track the open group server message ID
|
||||
tsMessage.openGroupServerMessageID = message.openGroupServerMessageID ?? 0
|
||||
tsMessage.save(with: transaction)
|
||||
|
@ -360,6 +362,15 @@ public final class MessageSender : NSObject {
|
|||
}
|
||||
// Start the disappearing messages timer if needed
|
||||
OWSDisappearingMessagesJob.shared().startAnyExpiration(for: tsMessage, expirationStartedAt: NSDate.millisecondTimestamp(), transaction: transaction)
|
||||
// Sync the message if:
|
||||
// • it's a visible message
|
||||
// • we didn't sync it already
|
||||
let userPublicKey = getUserHexEncodedPublicKey()
|
||||
if case .contact(let publicKey) = destination, !isSyncMessage, let message = message as? VisibleMessage {
|
||||
message.syncTarget = publicKey
|
||||
// FIXME: Make this a job
|
||||
sendToSnodeDestination(.contact(publicKey: userPublicKey), message: message, using: transaction, isSyncMessage: true).retainUntilComplete()
|
||||
}
|
||||
}
|
||||
|
||||
public static func handleFailedMessageSend(_ message: Message, with error: Swift.Error, using transaction: Any) {
|
||||
|
|
|
@ -146,21 +146,13 @@ public final class OpenGroupPoller : NSObject {
|
|||
let groupProto = SNProtoGroupContext.builder(id: id, type: .deliver)
|
||||
groupProto.setName(openGroup.displayName)
|
||||
dataMessageProto.setGroup(try! groupProto.build())
|
||||
// Sync target
|
||||
if wasSentByCurrentUser {
|
||||
dataMessageProto.setSyncTarget(openGroup.id)
|
||||
}
|
||||
// Content
|
||||
let content = SNProtoContent.builder()
|
||||
if !wasSentByCurrentUser { // Incoming message
|
||||
content.setDataMessage(try! dataMessageProto.build())
|
||||
} else { // Outgoing message
|
||||
// FIXME: This needs to be updated as we removed sync message handling
|
||||
let syncMessageSentBuilder = SNProtoSyncMessageSent.builder()
|
||||
syncMessageSentBuilder.setMessage(try! dataMessageProto.build())
|
||||
syncMessageSentBuilder.setDestination(userPublicKey)
|
||||
syncMessageSentBuilder.setTimestamp(message.timestamp)
|
||||
let syncMessageSent = try! syncMessageSentBuilder.build()
|
||||
let syncMessageBuilder = SNProtoSyncMessage.builder()
|
||||
syncMessageBuilder.setSent(syncMessageSent)
|
||||
content.setSyncMessage(try! syncMessageBuilder.build())
|
||||
}
|
||||
content.setDataMessage(try! dataMessageProto.build())
|
||||
// Envelope
|
||||
let envelope = SNProtoEnvelope.builder(type: .unidentifiedSender, timestamp: message.timestamp)
|
||||
envelope.setSource(senderPublicKey)
|
||||
|
|
|
@ -28,6 +28,7 @@ public protocol SessionMessagingKitStorageProtocol {
|
|||
// MARK: - Shared Sender Keys
|
||||
|
||||
func getClosedGroupPrivateKey(for publicKey: String) -> String?
|
||||
func getUserClosedGroupPublicKeys() -> Set<String>
|
||||
func isClosedGroup(_ publicKey: String) -> Bool
|
||||
|
||||
// MARK: - Jobs
|
||||
|
@ -48,9 +49,11 @@ 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?
|
||||
func updateMessageIDCollectionByPruningMessagesWithIDs(_ messageIDs: Set<String>, using transaction: Any)
|
||||
|
||||
// MARK: - Open Group Public Keys
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ public final class Values : NSObject {
|
|||
@objc public static var separatorThickness: CGFloat { return 1 / UIScreen.main.scale }
|
||||
@objc public static let tabBarHeight = isIPhone5OrSmaller ? CGFloat(32) : CGFloat(48)
|
||||
@objc public static let settingButtonHeight = isIPhone5OrSmaller ? CGFloat(52) : CGFloat(75)
|
||||
@objc public static let defaultSettingRowHeight = CGFloat(60)
|
||||
@objc public static let modalCornerRadius = CGFloat(10)
|
||||
@objc public static let modalButtonCornerRadius = CGFloat(5)
|
||||
@objc public static let fakeChatBubbleWidth = CGFloat(224)
|
||||
|
|
|
@ -8,11 +8,13 @@ public enum SNUserDefaults {
|
|||
case hasViewedSeed
|
||||
case isUsingFullAPNs
|
||||
case isMigratingToV2KeyPair
|
||||
case isUsingMultiDevice
|
||||
}
|
||||
|
||||
public enum Date : Swift.String {
|
||||
case lastProfilePictureUpload
|
||||
case lastKeyPairMigrationNudge
|
||||
case lastConfigurationSync
|
||||
}
|
||||
|
||||
public enum Double : Swift.String {
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
import UIKit
|
||||
|
||||
extension UIEdgeInsets {
|
||||
|
||||
public init(uniform value: CGFloat) {
|
||||
self.init(top: value, left: value, bottom: value, right: value)
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
|
||||
extension ConfigurationMessage {
|
||||
|
||||
public static func getCurrent() -> ConfigurationMessage {
|
||||
var closedGroups: Set<ClosedGroup> = []
|
||||
var openGroups: Set<String> = []
|
||||
Storage.read { transaction in
|
||||
TSGroupThread.enumerateCollectionObjects(with: transaction) { object, _ in
|
||||
guard let thread = object as? TSGroupThread else { return }
|
||||
switch thread.groupModel.groupType {
|
||||
case .closedGroup:
|
||||
guard thread.isCurrentUserMemberInGroup() else { return }
|
||||
let groupID = thread.groupModel.groupId
|
||||
let groupPublicKey = LKGroupUtilities.getDecodedGroupID(groupID)
|
||||
guard Storage.shared.isClosedGroup(groupPublicKey),
|
||||
let encryptionKeyPair = Storage.shared.getLatestClosedGroupEncryptionKeyPair(for: groupPublicKey) else { return }
|
||||
let closedGroup = ClosedGroup(publicKey: groupPublicKey, name: thread.groupModel.groupName!, encryptionKeyPair: encryptionKeyPair,
|
||||
members: Set(thread.groupModel.groupMemberIds), admins: Set(thread.groupModel.groupAdminIds))
|
||||
closedGroups.insert(closedGroup)
|
||||
case .openGroup:
|
||||
guard let openGroup = Storage.shared.getOpenGroup(for: thread.uniqueId!) else { return }
|
||||
openGroups.insert(openGroup.server)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
return ConfigurationMessage(closedGroups: closedGroups, openGroups: openGroups)
|
||||
}
|
||||
}
|
|
@ -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