diff --git a/TelegramCore.xcodeproj/project.pbxproj b/TelegramCore.xcodeproj/project.pbxproj index 6d06bee5dd..e476fe37a5 100644 --- a/TelegramCore.xcodeproj/project.pbxproj +++ b/TelegramCore.xcodeproj/project.pbxproj @@ -45,6 +45,7 @@ D01AC91D1DD5DA5E00E8160F /* RequestMessageActionCallback.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01AC91C1DD5DA5E00E8160F /* RequestMessageActionCallback.swift */; }; D01AC9211DD5E7E500E8160F /* RequestEditMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01AC9201DD5E7E500E8160F /* RequestEditMessage.swift */; }; D01AC9231DD5E9A200E8160F /* ApplyUpdateMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01AC9221DD5E9A200E8160F /* ApplyUpdateMessage.swift */; }; + D01B27A21E394D8B0022A4C0 /* PrivacySettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01B27A11E394D8B0022A4C0 /* PrivacySettings.swift */; }; D021E0DF1DB539FC00C6B04F /* StickerPack.swift in Sources */ = {isa = PBXBuildFile; fileRef = D021E0DE1DB539FC00C6B04F /* StickerPack.swift */; }; D021E0E21DB5401A00C6B04F /* StickerManagement.swift in Sources */ = {isa = PBXBuildFile; fileRef = D021E0E11DB5401A00C6B04F /* StickerManagement.swift */; }; D02ABC7B1E30058F00CAE539 /* DeleteMessagesInteractively.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02ABC7A1E30058F00CAE539 /* DeleteMessagesInteractively.swift */; }; @@ -148,6 +149,8 @@ D07827BB1E00451F00071108 /* SearchPeers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07827BA1E00451F00071108 /* SearchPeers.swift */; }; D07827C91E02F59C00071108 /* InstantPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07827C81E02F59C00071108 /* InstantPage.swift */; }; D07827CB1E02F5B200071108 /* RichText.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07827CA1E02F5B200071108 /* RichText.swift */; }; + D08774FC1E3E39F600A97350 /* ManagedGlobalNotificationSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08774FB1E3E39F600A97350 /* ManagedGlobalNotificationSettings.swift */; }; + D08774FE1E3E3A3500A97350 /* GlobalNotificationSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08774FD1E3E3A3500A97350 /* GlobalNotificationSettings.swift */; }; D099EA1C1DE72867001AF5A8 /* PeerCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = D099EA1B1DE72867001AF5A8 /* PeerCommands.swift */; }; D09A2FE61D7CD4940018FB72 /* TelegramChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09A2FE51D7CD4940018FB72 /* TelegramChannel.swift */; }; D09A2FEB1D7CDC320018FB72 /* PeerAccessRestrictionInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09A2FEA1D7CDC320018FB72 /* PeerAccessRestrictionInfo.swift */; }; @@ -255,6 +258,9 @@ D0B8444B1DAB91FD005F29E1 /* ManagedSynchronizePeerReadStates.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0AB0B991D666520002C78E7 /* ManagedSynchronizePeerReadStates.swift */; }; D0B8444C1DAB91FD005F29E1 /* UpdateCachedPeerData.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B843861DA6F705005F29E1 /* UpdateCachedPeerData.swift */; }; D0B844531DAC0773005F29E1 /* TelegramUserPresence.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B844521DAC0773005F29E1 /* TelegramUserPresence.swift */; }; + D0BC386E1E3FDAB70044D6FE /* CreateGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BC386D1E3FDAB70044D6FE /* CreateGroup.swift */; }; + D0BC38701E40853E0044D6FE /* UpdatePeers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BC386F1E40853E0044D6FE /* UpdatePeers.swift */; }; + D0BC38751E40A7F70044D6FE /* RemovePeerChat.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BC38741E40A7F70044D6FE /* RemovePeerChat.swift */; }; D0CAF2EA1D75EC600011F558 /* MtProtoKitDynamic.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0CAF2E91D75EC600011F558 /* MtProtoKitDynamic.framework */; }; D0DC354E1DE368F7000195EB /* RequestChatContextResults.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DC354D1DE368F7000195EB /* RequestChatContextResults.swift */; }; D0DC35501DE36900000195EB /* ChatContextResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DC354F1DE36900000195EB /* ChatContextResult.swift */; }; @@ -270,6 +276,8 @@ D0E35A131DE4C69100BC6096 /* OutgoingChatContextResultMessageAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E35A111DE4A25E00BC6096 /* OutgoingChatContextResultMessageAttribute.swift */; }; D0E35A141DE4C69C00BC6096 /* FetchHttpResource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E35A0D1DE4953E00BC6096 /* FetchHttpResource.swift */; }; D0E35A151DE4C6A200BC6096 /* OutgoingMessageWithChatContextResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E35A0F1DE49E1C00BC6096 /* OutgoingMessageWithChatContextResult.swift */; }; + D0E6521F1E3A364A004EEA91 /* UpdateAccountPeerName.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E6521E1E3A364A004EEA91 /* UpdateAccountPeerName.swift */; }; + D0E652201E3A364A004EEA91 /* UpdateAccountPeerName.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E6521E1E3A364A004EEA91 /* UpdateAccountPeerName.swift */; }; D0F3CC791DDE2859008148FA /* SearchMessages.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0D711D631ABA00955575 /* SearchMessages.swift */; }; D0F3CC7A1DDE2859008148FA /* RequestMessageActionCallback.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01AC91C1DD5DA5E00E8160F /* RequestMessageActionCallback.swift */; }; D0F3CC7B1DDE2859008148FA /* RequestEditMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01AC9201DD5E7E500E8160F /* RequestEditMessage.swift */; }; @@ -336,6 +344,7 @@ D01AC91C1DD5DA5E00E8160F /* RequestMessageActionCallback.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestMessageActionCallback.swift; sourceTree = ""; }; D01AC9201DD5E7E500E8160F /* RequestEditMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestEditMessage.swift; sourceTree = ""; }; D01AC9221DD5E9A200E8160F /* ApplyUpdateMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApplyUpdateMessage.swift; sourceTree = ""; }; + D01B27A11E394D8B0022A4C0 /* PrivacySettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrivacySettings.swift; sourceTree = ""; }; D021E0DE1DB539FC00C6B04F /* StickerPack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StickerPack.swift; sourceTree = ""; }; D021E0E11DB5401A00C6B04F /* StickerManagement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StickerManagement.swift; sourceTree = ""; }; D02ABC7A1E30058F00CAE539 /* DeleteMessagesInteractively.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeleteMessagesInteractively.swift; sourceTree = ""; }; @@ -418,6 +427,8 @@ D07827BA1E00451F00071108 /* SearchPeers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchPeers.swift; sourceTree = ""; }; D07827C81E02F59C00071108 /* InstantPage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InstantPage.swift; sourceTree = ""; }; D07827CA1E02F5B200071108 /* RichText.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RichText.swift; sourceTree = ""; }; + D08774FB1E3E39F600A97350 /* ManagedGlobalNotificationSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedGlobalNotificationSettings.swift; sourceTree = ""; }; + D08774FD1E3E3A3500A97350 /* GlobalNotificationSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlobalNotificationSettings.swift; sourceTree = ""; }; D099EA1B1DE72867001AF5A8 /* PeerCommands.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PeerCommands.swift; sourceTree = ""; }; D09A2FE51D7CD4940018FB72 /* TelegramChannel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TelegramChannel.swift; sourceTree = ""; }; D09A2FEA1D7CDC320018FB72 /* PeerAccessRestrictionInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PeerAccessRestrictionInfo.swift; sourceTree = ""; }; @@ -479,6 +490,9 @@ D0B843B01DA7FF30005F29E1 /* NBPhoneNumberUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NBPhoneNumberUtil.h; sourceTree = ""; }; D0B843B11DA7FF30005F29E1 /* NBPhoneNumberUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NBPhoneNumberUtil.m; sourceTree = ""; }; D0B844521DAC0773005F29E1 /* TelegramUserPresence.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TelegramUserPresence.swift; sourceTree = ""; }; + D0BC386D1E3FDAB70044D6FE /* CreateGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateGroup.swift; sourceTree = ""; }; + D0BC386F1E40853E0044D6FE /* UpdatePeers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdatePeers.swift; sourceTree = ""; }; + D0BC38741E40A7F70044D6FE /* RemovePeerChat.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RemovePeerChat.swift; sourceTree = ""; }; D0CAF2E91D75EC600011F558 /* MtProtoKitDynamic.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MtProtoKitDynamic.framework; path = "../../../../Library/Developer/Xcode/DerivedData/Telegram-iOS-diblohvjozhgaifjcniwdlixlilx/Build/Products/Debug-iphonesimulator/MtProtoKitDynamic.framework"; sourceTree = ""; }; D0DC354D1DE368F7000195EB /* RequestChatContextResults.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestChatContextResults.swift; sourceTree = ""; }; D0DC354F1DE36900000195EB /* ChatContextResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatContextResult.swift; sourceTree = ""; }; @@ -489,6 +503,7 @@ D0E35A0D1DE4953E00BC6096 /* FetchHttpResource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchHttpResource.swift; sourceTree = ""; }; D0E35A0F1DE49E1C00BC6096 /* OutgoingMessageWithChatContextResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutgoingMessageWithChatContextResult.swift; sourceTree = ""; }; D0E35A111DE4A25E00BC6096 /* OutgoingChatContextResultMessageAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutgoingChatContextResultMessageAttribute.swift; sourceTree = ""; }; + D0E6521E1E3A364A004EEA91 /* UpdateAccountPeerName.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdateAccountPeerName.swift; sourceTree = ""; }; D0F3CC7C1DDE289E008148FA /* ResolvePeerByName.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResolvePeerByName.swift; sourceTree = ""; }; D0F7AB2B1DCE889D009AD9A1 /* EditedMessageAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditedMessageAttribute.swift; sourceTree = ""; }; D0F7AB2E1DCF507E009AD9A1 /* ReplyMarkupMessageAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReplyMarkupMessageAttribute.swift; sourceTree = ""; }; @@ -537,6 +552,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + D01B27A01E394D7B0022A4C0 /* Settings */ = { + isa = PBXGroup; + children = ( + D01B27A11E394D8B0022A4C0 /* PrivacySettings.swift */, + D08774FD1E3E3A3500A97350 /* GlobalNotificationSettings.swift */, + ); + name = Settings; + sourceTree = ""; + }; D021E0DD1DB539E800C6B04F /* Item Collections */ = { isa = PBXGroup; children = ( @@ -620,6 +644,7 @@ D03B0CD11D62242F00955575 /* Messages */, D0FA8B961E1E952D001E855B /* Secret Chats */, D021E0DD1DB539E800C6B04F /* Item Collections */, + D01B27A01E394D7B0022A4C0 /* Settings */, ); name = Objects; sourceTree = ""; @@ -766,6 +791,8 @@ D0AB0B951D662F0B002C78E7 /* ManagedChatListHoles.swift */, D0B843861DA6F705005F29E1 /* UpdateCachedPeerData.swift */, D00C7CCE1E3628180080C3D5 /* UpdateCachedChannelParticipants.swift */, + D0E6521E1E3A364A004EEA91 /* UpdateAccountPeerName.swift */, + D08774FB1E3E39F600A97350 /* ManagedGlobalNotificationSettings.swift */, ); name = Account; sourceTree = ""; @@ -896,12 +923,15 @@ D0DF0C881D819C5F008AEB01 /* Peers */ = { isa = PBXGroup; children = ( + D0BC386F1E40853E0044D6FE /* UpdatePeers.swift */, D0DF0C891D819C7E008AEB01 /* JoinChannel.swift */, D0DF0CA71D82BF32008AEB01 /* PeerParticipants.swift */, D099EA1B1DE72867001AF5A8 /* PeerCommands.swift */, D0B843961DA7FBBC005F29E1 /* ChangePeerNotificationSettings.swift */, D0F3CC7C1DDE289E008148FA /* ResolvePeerByName.swift */, D07827BA1E00451F00071108 /* SearchPeers.swift */, + D0BC386D1E3FDAB70044D6FE /* CreateGroup.swift */, + D0BC38741E40A7F70044D6FE /* RemovePeerChat.swift */, ); name = Peers; sourceTree = ""; @@ -1101,6 +1131,7 @@ D07827C91E02F59C00071108 /* InstantPage.swift in Sources */, D07827CB1E02F5B200071108 /* RichText.swift in Sources */, D03B0CE01D62249100955575 /* StoreMessage_Telegram.swift in Sources */, + D08774FE1E3E3A3500A97350 /* GlobalNotificationSettings.swift in Sources */, D00C7CCF1E3628180080C3D5 /* UpdateCachedChannelParticipants.swift in Sources */, D03B0CB91D62233400955575 /* Either.swift in Sources */, D03B0CBD1D62234300955575 /* Regex.swift in Sources */, @@ -1110,6 +1141,7 @@ D03B0D0E1D62255C00955575 /* UpdateGroup.swift in Sources */, D01AC9231DD5E9A200E8160F /* ApplyUpdateMessage.swift in Sources */, D03B0CF71D62250800955575 /* TelegramMediaImage.swift in Sources */, + D0BC386E1E3FDAB70044D6FE /* CreateGroup.swift in Sources */, D0FA8BB31E201B02001E855B /* ProcessSecretChatIncomingEncryptedOperations.swift in Sources */, D073CE601DCB9D14007511FD /* OutgoingMessageInfoAttribute.swift in Sources */, D03B0D6B1D631A9D00955575 /* Phonebook.swift in Sources */, @@ -1134,6 +1166,7 @@ D03B0CCE1D62239600955575 /* PhoneNumbers.swift in Sources */, D0FA8B981E1E955C001E855B /* SecretChatOutgoingOperation.swift in Sources */, D0DF0C911D81A857008AEB01 /* ImageRepresentationsUtils.swift in Sources */, + D0E6521F1E3A364A004EEA91 /* UpdateAccountPeerName.swift in Sources */, D03B0D5A1D631A6900955575 /* Api.swift in Sources */, D02ABC7B1E30058F00CAE539 /* DeleteMessagesInteractively.swift in Sources */, D0448C9F1E27F5EB005A61A7 /* Random.swift in Sources */, @@ -1203,15 +1236,18 @@ D0AAD1AA1E32638500D5B9DE /* ApplyMaxReadIndexInteractively.swift in Sources */, D03B0D5C1D631A6900955575 /* Download.swift in Sources */, D01749591E1092BC0057C89A /* RequestStartBot.swift in Sources */, + D01B27A21E394D8B0022A4C0 /* PrivacySettings.swift in Sources */, D017495E1E118F790057C89A /* AccountStateManager.swift in Sources */, D0FA8BB61E223C16001E855B /* SecretApiLayer8.swift in Sources */, D0B843C71DA7FF30005F29E1 /* NBPhoneNumberDefines.m in Sources */, D03B0D5D1D631A6900955575 /* MultipartFetch.swift in Sources */, + D0BC38751E40A7F70044D6FE /* RemovePeerChat.swift in Sources */, D0AB0B961D662F0B002C78E7 /* ManagedChatListHoles.swift in Sources */, D02ABC841E32183300CAE539 /* ManagedSynchronizePinnedCloudChatsOperations.swift in Sources */, D03B0CD71D62245300955575 /* TelegramGroup.swift in Sources */, D0B8438C1DA7CF50005F29E1 /* BotInfo.swift in Sources */, D021E0E21DB5401A00C6B04F /* StickerManagement.swift in Sources */, + D0BC38701E40853E0044D6FE /* UpdatePeers.swift in Sources */, D03B0CE21D62249B00955575 /* InlineBotMessageAttribute.swift in Sources */, D0AB0B9A1D666520002C78E7 /* ManagedSynchronizePeerReadStates.swift in Sources */, D03B0D5B1D631A6900955575 /* Buffer.swift in Sources */, @@ -1227,6 +1263,7 @@ D02ABC811E310E5D00CAE539 /* ManagedCloudChatRemoveMessagesOperations.swift in Sources */, D03B0D651D631A8B00955575 /* Account.swift in Sources */, D0AB0B941D662ECE002C78E7 /* ManagedMessageHistoryHoles.swift in Sources */, + D08774FC1E3E39F600A97350 /* ManagedGlobalNotificationSettings.swift in Sources */, D03B0CF41D62250800955575 /* TelegramMediaAction.swift in Sources */, D0B417C11D7DCEEF004562A4 /* ApiGroupOrChannel.swift in Sources */, D0B843BF1DA7FF30005F29E1 /* NBNumberFormat.m in Sources */, @@ -1376,6 +1413,7 @@ D02ABC7F1E3109F000CAE539 /* CloudChatRemoveMessagesOperation.swift in Sources */, D0FA8BA51E1FA341001E855B /* SecretChatKeychain.swift in Sources */, D0F7B1E71E045C87007EB8A5 /* JoinChannel.swift in Sources */, + D0E652201E3A364A004EEA91 /* UpdateAccountPeerName.swift in Sources */, D0FA8BA21E1F99E1001E855B /* SecretChatFileReference.swift in Sources */, D0B844301DAB91E0005F29E1 /* NBNumberFormat.m in Sources */, D001F3F71E128A1C007A8C60 /* ApplyUpdateMessage.swift in Sources */, diff --git a/TelegramCore/Account.swift b/TelegramCore/Account.swift index 63715ff045..c91aa3a5d7 100644 --- a/TelegramCore/Account.swift +++ b/TelegramCore/Account.swift @@ -264,6 +264,9 @@ private var declaredEncodables: Void = { declareEncodable(SecretFileMediaResource.self, f: { SecretFileMediaResource(decoder: $0) }) declareEncodable(CloudChatRemoveMessagesOperation.self, f: { CloudChatRemoveMessagesOperation(decoder: $0) }) declareEncodable(AutoremoveTimeoutMessageAttribute.self, f: { AutoremoveTimeoutMessageAttribute(decoder: $0) }) + declareEncodable(GlobalNotificationSettings.self, f: { GlobalNotificationSettings(decoder: $0) }) + declareEncodable(CloudChatRemoveChatOperation.self, f: { CloudChatRemoveChatOperation(decoder: $0) }) + return }() @@ -561,6 +564,7 @@ public class Account { self.managedOperationsDisposable.add(managedSecretChatOutgoingOperations(postbox: self.postbox, network: self.network).start()) self.managedOperationsDisposable.add(managedCloudChatRemoveMessagesOperations(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start()) self.managedOperationsDisposable.add(managedAutoremoveMessageOperations(postbox: self.postbox).start()) + self.managedOperationsDisposable.add(managedGlobalNotificationSettings(postbox: self.postbox, network: self.network).start()) let updatedPresence = self.shouldKeepOnlinePresence.get() |> distinctUntilChanged diff --git a/TelegramCore/AccountStateManagementUtils.swift b/TelegramCore/AccountStateManagementUtils.swift index 5a000cf07e..e9f20b4a31 100644 --- a/TelegramCore/AccountStateManagementUtils.swift +++ b/TelegramCore/AccountStateManagementUtils.swift @@ -1285,7 +1285,7 @@ func replayFinalState(mediaBox: MediaBox, modifier: Modifier, finalState: Accoun peers.append(groupOrChannel) } } - modifier.updatePeers(peers, update: { _, updated in + updatePeers(modifier: modifier, peers: peers, update: { _, updated in return updated }) case let .MergeApiUsers(users): @@ -1295,12 +1295,12 @@ func replayFinalState(mediaBox: MediaBox, modifier: Modifier, finalState: Accoun peers.append(telegramUser) } } - modifier.updatePeers(peers, update: { _, updated in + updatePeers(modifier: modifier, peers: peers, update: { _, updated in return updated }) case let .UpdatePeer(id, f): if let peer = modifier.getPeer(id) { - modifier.updatePeers([f(peer)], update: { _, updated in + updatePeers(modifier: modifier, peers: [f(peer)], update: { _, updated in return updated }) } @@ -1317,7 +1317,7 @@ func replayFinalState(mediaBox: MediaBox, modifier: Modifier, finalState: Accoun if let currentPeer = currentPeer, let currentState = currentState { let state = currentState.withUpdatedEmbeddedState(.terminated) let peer = currentPeer.withUpdatedEmbeddedState(state.embeddedState.peerState) - modifier.updatePeers([peer], update: { _, updated in return updated }) + updatePeers(modifier: modifier, peers: [peer], update: { _, updated in return updated }) modifier.setPeerChatState(peer.id, state: state) modifier.operationLogRemoveAllEntries(peerId: peer.id, tag: OperationLogTags.SecretOutgoing) } else { @@ -1327,9 +1327,9 @@ func replayFinalState(mediaBox: MediaBox, modifier: Modifier, finalState: Accoun break case let .encryptedChatRequested(_, accessHash, date, adminId, participantId, gA): if currentPeer == nil { - let state = SecretChatState(role: .participant, embeddedState: .handshake, keychain: SecretChatKeychain(keys: []), messageAutoremoveTimeout: nil) - let peer = TelegramSecretChat(id: chat.peerId, regularPeerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: adminId), accessHash: accessHash, embeddedState: state.embeddedState.peerState, messageAutoremoveTimeout: nil) - modifier.updatePeers([peer], update: { _, updated in return updated }) + let state = SecretChatState(role: .participant, embeddedState: .handshake, keychain: SecretChatKeychain(keys: []), keyFingerprint: nil, messageAutoremoveTimeout: nil) + let peer = TelegramSecretChat(id: chat.peerId, creationDate: date, regularPeerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: adminId), accessHash: accessHash, embeddedState: state.embeddedState.peerState, messageAutoremoveTimeout: nil) + updatePeers(modifier: modifier, peers: [peer], update: { _, updated in return updated }) modifier.resetIncomingReadStates([peer.id: [ Namespaces.Message.SecretIncoming: .indexBased(maxIncomingReadIndex: MessageIndex.lowerBound(peerId: peer.id), maxOutgoingReadIndex: MessageIndex.lowerBound(peerId: peer.id), count: 0), Namespaces.Message.Local: .indexBased(maxIncomingReadIndex: MessageIndex.lowerBound(peerId: peer.id), maxOutgoingReadIndex: MessageIndex.lowerBound(peerId: peer.id), count: 0) diff --git a/TelegramCore/AccountStateManager.swift b/TelegramCore/AccountStateManager.swift index 730a5ce1c2..bad285b0ac 100644 --- a/TelegramCore/AccountStateManager.swift +++ b/TelegramCore/AccountStateManager.swift @@ -165,7 +165,7 @@ public final class AccountStateManager { if !self.operations.isEmpty { for operation in self.operations { - if case let .pollCompletion(pollId, subscribers) = operation { + if case let .pollCompletion(_, subscribers) = operation { collectedPollCompletionSubscribers.append(contentsOf: subscribers) } } @@ -174,7 +174,7 @@ public final class AccountStateManager { self.operations.removeAll() self.operations.append(operation) for (id, f) in collectedPollCompletionSubscribers { - self.addPollCompletion(f, id: id) + let _ = self.addPollCompletion(f, id: id) } } @@ -289,7 +289,7 @@ public final class AccountStateManager { assertionFailure() trace("AccountStateManager", what: "processUpdateGroups signal completed with error") }) - case let .collectUpdateGroups(groups, timeout): + case let .collectUpdateGroups(_, timeout): self.operationTimer?.invalidate() let operationTimer = SignalKitTimer(timeout: timeout, repeat: false, completion: { [weak self] in if let strongSelf = self { @@ -314,7 +314,7 @@ public final class AccountStateManager { let mediaBox = account.postbox.mediaBox let queue = self.queue let signal = initialStateWithUpdateGroups(account, groups: groups) - |> mapToSignal { [weak self] state -> Signal<(AccountReplayedFinalState?, AccountFinalState), NoError> in + |> mapToSignal { state -> Signal<(AccountReplayedFinalState?, AccountFinalState), NoError> in return finalStateWithUpdateGroups(account, state: state, groups: groups) |> mapToSignal { finalState in if !finalState.state.preCachedResources.isEmpty { @@ -330,7 +330,7 @@ public final class AccountStateManager { |> deliverOn(queue) } } - signal.start(next: { [weak self] replayedState, finalState in + let _ = signal.start(next: { [weak self] replayedState, finalState in if let strongSelf = self { if case let .processUpdateGroups(groups) = strongSelf.operations.removeFirst() { if let replayedState = replayedState, !finalState.shouldPoll { diff --git a/TelegramCore/AccountViewTracker.swift b/TelegramCore/AccountViewTracker.swift index c525136331..ec040dc87b 100644 --- a/TelegramCore/AccountViewTracker.swift +++ b/TelegramCore/AccountViewTracker.swift @@ -99,7 +99,7 @@ private func fetchWebpage(account: Account, messageId: MessageId) -> Signal Peer in + updatePeers(modifier: modifier, peers: peers, update: { _, updated -> Peer in return updated }) modifier.updatePeerPresences(peerPresences) diff --git a/TelegramCore/ApiGroupOrChannel.swift b/TelegramCore/ApiGroupOrChannel.swift index cb6dac7514..49a964b113 100644 --- a/TelegramCore/ApiGroupOrChannel.swift +++ b/TelegramCore/ApiGroupOrChannel.swift @@ -22,7 +22,7 @@ private func imageRepresentationsForApiChatPhoto(_ photo: Api.ChatPhoto) -> [Tel public func parseTelegramGroupOrChannel(chat: Api.Chat) -> Peer? { switch chat { case let .chat(flags, id, title, photo, participantsCount, date, version, migratedTo): - let left = (flags & (1 | 2)) != 0 + let left = (flags & ((1 << 1) | (1 << 2))) != 0 var migrationReference: TelegramGroupToChannelMigrationReference? if let migratedTo = migratedTo { switch migratedTo { @@ -45,11 +45,11 @@ public func parseTelegramGroupOrChannel(chat: Api.Chat) -> Peer? { if (flags & (1 << 5)) != 0 { groupFlags.insert(.deactivated) } - return TelegramGroup(id: PeerId(namespace: Namespaces.Peer.CloudGroup, id: id), title: title, photo: imageRepresentationsForApiChatPhoto(photo), participantCount: Int(participantsCount), role: role, membership: left ? .Left : .Member, flags: groupFlags, migrationReference: migrationReference, version: Int(version)) + return TelegramGroup(id: PeerId(namespace: Namespaces.Peer.CloudGroup, id: id), title: title, photo: imageRepresentationsForApiChatPhoto(photo), participantCount: Int(participantsCount), role: role, membership: left ? .Left : .Member, flags: groupFlags, migrationReference: migrationReference, creationDate: date, version: Int(version)) case let .chatEmpty(id): - TelegramGroup(id: PeerId(namespace: Namespaces.Peer.CloudGroup, id: id), title: "", photo: [], participantCount: 0, role: .member, membership: .Removed, flags: [], migrationReference: nil, version: 0) + return TelegramGroup(id: PeerId(namespace: Namespaces.Peer.CloudGroup, id: id), title: "", photo: [], participantCount: 0, role: .member, membership: .Removed, flags: [], migrationReference: nil, creationDate: 0, version: 0) case let .chatForbidden(id, title): - TelegramGroup(id: PeerId(namespace: Namespaces.Peer.CloudGroup, id: id), title: title, photo: [], participantCount: 0, role: .member, membership: .Removed, flags: [], migrationReference: nil, version: 0) + return TelegramGroup(id: PeerId(namespace: Namespaces.Peer.CloudGroup, id: id), title: title, photo: [], participantCount: 0, role: .member, membership: .Removed, flags: [], migrationReference: nil, creationDate: 0, version: 0) case let .channel(flags, id, accessHash, title, username, photo, date, version, restrictionReason): let participationStatus: TelegramChannelParticipationStatus if (flags & Int32(1 << 1)) != 0 { @@ -102,17 +102,13 @@ public func parseTelegramGroupOrChannel(chat: Api.Chat) -> Peer? { case let .channelForbidden(flags, id, accessHash, title): let info: TelegramChannelInfo if (flags & Int32(1 << 8)) != 0 { - var infoFlags = TelegramChannelGroupFlags() - info = .group(TelegramChannelGroupInfo(flags: infoFlags)) + info = .group(TelegramChannelGroupInfo(flags: [])) } else { - var infoFlags = TelegramChannelBroadcastFlags() info = .broadcast(TelegramChannelBroadcastInfo(flags: [])) } return TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: id), accessHash: accessHash, title: title, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .kicked, role: .member, info: info, flags: TelegramChannelFlags(), restrictionInfo: nil) } - - return nil } func mergeGroupOrChannel(lhs: Peer?, rhs: Api.Chat) -> Peer? { diff --git a/TelegramCore/ChangePeerNotificationSettings.swift b/TelegramCore/ChangePeerNotificationSettings.swift index b4170aee78..e0cb922895 100644 --- a/TelegramCore/ChangePeerNotificationSettings.swift +++ b/TelegramCore/ChangePeerNotificationSettings.swift @@ -20,10 +20,12 @@ public func changePeerNotificationSettings(account: Account, peerId: PeerId, set } let sound: String switch settings.messageSound { - case .appDefault: - sound = "default" - case let .bundled(index): - sound = "\(index)" + case .none: + sound = "" + case let .bundledModern(id): + sound = "\(id)" + case let .bundledClassic(id): + sound = "\(id + 12)" } let inputSettings = Api.InputPeerNotifySettings.inputPeerNotifySettings(flags: Int32(1 << 0), muteUntil: muteUntil, sound: sound) return account.network.request(Api.functions.account.updateNotifySettings(peer: .inputNotifyPeer(peer: inputPeer), settings: inputSettings)) diff --git a/TelegramCore/CloudChatRemoveMessagesOperation.swift b/TelegramCore/CloudChatRemoveMessagesOperation.swift index e9c98fd12c..f97f9ec54d 100644 --- a/TelegramCore/CloudChatRemoveMessagesOperation.swift +++ b/TelegramCore/CloudChatRemoveMessagesOperation.swift @@ -43,6 +43,26 @@ final class CloudChatRemoveMessagesOperation: Coding { } } +final class CloudChatRemoveChatOperation: Coding { + let peerId: PeerId + + init(peerId: PeerId) { + self.peerId = peerId + } + + init(decoder: Decoder) { + self.peerId = PeerId(decoder.decodeInt64ForKey("p")) + } + + func encode(_ encoder: Encoder) { + encoder.encodeInt64(self.peerId.toInt64(), forKey: "p") + } +} + func cloudChatAddRemoveMessagesOperation(modifier: Modifier, peerId: PeerId, messageIds: [MessageId], type: CloudChatRemoveMessagesType) { modifier.operationLogAddEntry(peerId: peerId, tag: OperationLogTags.CloudChatRemoveMessages, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: CloudChatRemoveMessagesOperation(messageIds: messageIds, type: type)) } + +func cloudChatAddRemoveChatOperation(modifier: Modifier, peerId: PeerId) { + modifier.operationLogAddEntry(peerId: peerId, tag: OperationLogTags.CloudChatRemoveMessages, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: CloudChatRemoveChatOperation(peerId: peerId)) +} diff --git a/TelegramCore/ContactManagement.swift b/TelegramCore/ContactManagement.swift index be6899f7c5..683c1e78fd 100644 --- a/TelegramCore/ContactManagement.swift +++ b/TelegramCore/ContactManagement.swift @@ -79,7 +79,7 @@ func manageContacts(network: Network, postbox: Postbox) -> Signal |> mapToSignal { peersAndPresences -> Signal in if let (peers, peerPresences) = peersAndPresences { return postbox.modify { modifier in - modifier.updatePeers(peers, update: { return $1 }) + updatePeers(modifier: modifier, peers: peers, update: { return $1 }) modifier.updatePeerPresences(peerPresences) modifier.replaceContactPeerIds(Set(peers.map { $0.id })) } diff --git a/TelegramCore/CreateGroup.swift b/TelegramCore/CreateGroup.swift new file mode 100644 index 0000000000..a52fd112e3 --- /dev/null +++ b/TelegramCore/CreateGroup.swift @@ -0,0 +1,47 @@ +import Foundation +#if os(macOS) + import PostboxMac + import SwiftSignalKitMac + import MtProtoKitMac +#else + import Postbox + import SwiftSignalKit + import MtProtoKitDynamic +#endif + +public func createGroup(account: Account, title: String, peerIds: [PeerId]) -> Signal { + return account.postbox.modify { modifier -> Signal in + var inputUsers: [Api.InputUser] = [] + for peerId in peerIds { + if let peer = modifier.getPeer(peerId), let inputUser = apiInputUser(peer) { + inputUsers.append(inputUser) + } else { + return .single(nil) + } + } + return account.network.request(Api.functions.messages.createChat(users: inputUsers, title: title)) + |> map { Optional($0) } + |> `catch` { _ in + return Signal.single(nil) + } + |> mapToSignal { updates -> Signal in + if let updates = updates { + account.stateManager.addUpdates(updates) + if let message = updates.messages.first, let peerId = message.peerId { + return account.postbox.multiplePeersView([peerId]) + |> filter { view in + return view.peers[peerId] != nil + } + |> take(1) + |> map { _ in + return peerId + } + |> timeout(5.0, queue: Queue.concurrentDefaultQueue(), alternate: .single(nil)) + } + return .single(nil) + } else { + return .single(nil) + } + } + } |> switchToLatest +} diff --git a/TelegramCore/GlobalNotificationSettings.swift b/TelegramCore/GlobalNotificationSettings.swift new file mode 100644 index 0000000000..de64e1fc9e --- /dev/null +++ b/TelegramCore/GlobalNotificationSettings.swift @@ -0,0 +1,151 @@ +import Foundation +#if os(macOS) + import PostboxMac +#else + import Postbox +#endif + +public struct MessageNotificationSettings: Coding, Equatable { + public let enabled: Bool + public let displayPreviews: Bool + public let sound: PeerMessageSound + + public static var defaultSettings: MessageNotificationSettings { + return MessageNotificationSettings(enabled: true, displayPreviews: true, sound: .bundledModern(id: 0)) + } + + public init(enabled: Bool, displayPreviews: Bool, sound: PeerMessageSound) { + self.enabled = enabled + self.displayPreviews = displayPreviews + self.sound = sound + } + + public init(decoder: Decoder) { + self.enabled = (decoder.decodeInt32ForKey("e") as Int32) != 0 + self.displayPreviews = (decoder.decodeInt32ForKey("p") as Int32) != 0 + self.sound = PeerMessageSound.decodeInline(decoder) + } + + public func encode(_ encoder: Encoder) { + encoder.encodeInt32(self.enabled ? 1 : 0, forKey: "e") + encoder.encodeInt32(self.displayPreviews ? 1 : 0, forKey: "p") + self.sound.encodeInline(encoder) + } + + public func withUpdatedEnabled(_ enabled: Bool) -> MessageNotificationSettings { + return MessageNotificationSettings(enabled: enabled, displayPreviews: self.displayPreviews, sound: self.sound) + } + + public func withUpdatedDisplayPreviews(_ displayPreviews: Bool) -> MessageNotificationSettings { + return MessageNotificationSettings(enabled: self.enabled, displayPreviews: displayPreviews, sound: self.sound) + } + + public func withUpdatedSound(_ sound: PeerMessageSound) -> MessageNotificationSettings { + return MessageNotificationSettings(enabled: self.enabled, displayPreviews: self.displayPreviews, sound: sound) + } + + public static func ==(lhs: MessageNotificationSettings, rhs: MessageNotificationSettings) -> Bool { + if lhs.enabled != rhs.enabled { + return false + } + if lhs.displayPreviews != rhs.displayPreviews { + return false + } + if lhs.sound != rhs.sound { + return false + } + return true + } +} + +public struct GlobalNotificationSettingsSet: Coding, Equatable { + public let privateChats: MessageNotificationSettings + public let groupChats: MessageNotificationSettings + + public static var defaultSettings: GlobalNotificationSettingsSet { + return GlobalNotificationSettingsSet(privateChats: MessageNotificationSettings.defaultSettings, groupChats: .defaultSettings) + } + + public init(privateChats: MessageNotificationSettings, groupChats: MessageNotificationSettings) { + self.privateChats = privateChats + self.groupChats = groupChats + } + + public init(decoder: Decoder) { + self.privateChats = decoder.decodeObjectForKey("p", decoder: { MessageNotificationSettings(decoder: $0) }) as! MessageNotificationSettings + self.groupChats = decoder.decodeObjectForKey("g", decoder: { MessageNotificationSettings(decoder: $0) }) as! MessageNotificationSettings + } + + public func encode(_ encoder: Encoder) { + encoder.encodeObject(self.privateChats, forKey: "p") + encoder.encodeObject(self.groupChats, forKey: "g") + } + + public func withUpdatedPrivateChats(_ f: (MessageNotificationSettings) -> MessageNotificationSettings) -> GlobalNotificationSettingsSet { + return GlobalNotificationSettingsSet(privateChats: f(self.privateChats), groupChats: self.groupChats) + } + + public func withUpdatedGroupChats(_ f: (MessageNotificationSettings) -> MessageNotificationSettings) -> GlobalNotificationSettingsSet { + return GlobalNotificationSettingsSet(privateChats: self.privateChats, groupChats: f(self.groupChats)) + } + + public static func ==(lhs: GlobalNotificationSettingsSet, rhs: GlobalNotificationSettingsSet) -> Bool { + if lhs.privateChats != rhs.privateChats { + return false + } + if lhs.groupChats != rhs.groupChats { + return false + } + return true + } +} + +public struct GlobalNotificationSettings: PreferencesEntry, Equatable { + let toBeSynchronized: GlobalNotificationSettingsSet? + let remote: GlobalNotificationSettingsSet + + public var effective: GlobalNotificationSettingsSet { + if let toBeSynchronized = self.toBeSynchronized { + return toBeSynchronized + } else { + return self.remote + } + } + + init(toBeSynchronized: GlobalNotificationSettingsSet?, remote: GlobalNotificationSettingsSet) { + self.toBeSynchronized = toBeSynchronized + self.remote = remote + } + + public init(decoder: Decoder) { + self.toBeSynchronized = decoder.decodeObjectForKey("s", decoder: { GlobalNotificationSettingsSet(decoder: $0) }) as? GlobalNotificationSettingsSet + self.remote = decoder.decodeObjectForKey("r", decoder: { GlobalNotificationSettingsSet(decoder: $0) }) as! GlobalNotificationSettingsSet + } + + public func encode(_ encoder: Encoder) { + if let toBeSynchronized = self.toBeSynchronized { + encoder.encodeObject(toBeSynchronized, forKey: "s") + } else { + encoder.encodeNil(forKey: "s") + } + encoder.encodeObject(self.remote, forKey: "r") + } + + public static func ==(lhs: GlobalNotificationSettings, rhs: GlobalNotificationSettings) -> Bool { + if lhs.toBeSynchronized != rhs.toBeSynchronized { + return false + } + if lhs.remote != rhs.remote { + return false + } + return true + } + + public func isEqual(to: PreferencesEntry) -> Bool { + if let to = to as? GlobalNotificationSettings { + return self == to + } else { + return false + } + } +} diff --git a/TelegramCore/Holes.swift b/TelegramCore/Holes.swift index eef701a21c..435dcdc1be 100644 --- a/TelegramCore/Holes.swift +++ b/TelegramCore/Holes.swift @@ -130,7 +130,7 @@ func fetchMessageHistoryHole(network: Network, postbox: Postbox, hole: MessageHi } } - modifier.updatePeers(peers, update: { _, updated -> Peer in + updatePeers(modifier: modifier, peers: peers, update: { _, updated -> Peer in return updated }) modifier.updatePeerPresences(peerPresences) @@ -298,7 +298,7 @@ func fetchChatListHole(network: Network, postbox: Postbox, hole: ChatListHole) - } return postbox.modify { modifier in - modifier.updatePeers(peers, update: { _, updated -> Peer in + updatePeers(modifier: modifier, peers: peers, update: { _, updated -> Peer in return updated }) modifier.updatePeerPresences(peerPresences) diff --git a/TelegramCore/ManagedCloudChatRemoveMessagesOperations.swift b/TelegramCore/ManagedCloudChatRemoveMessagesOperations.swift index 0d86030246..3ddb18d5c1 100644 --- a/TelegramCore/ManagedCloudChatRemoveMessagesOperations.swift +++ b/TelegramCore/ManagedCloudChatRemoveMessagesOperations.swift @@ -57,7 +57,7 @@ private func withTakenOperation(postbox: Postbox, peerId: PeerId, tagLocalIndex: return postbox.modify { modifier -> Signal in var result: PeerMergedOperationLogEntry? modifier.operationLogUpdateEntry(peerId: peerId, tag: OperationLogTags.CloudChatRemoveMessages, tagLocalIndex: tagLocalIndex, { entry in - if let entry = entry, let _ = entry.mergedIndex, let operation = entry.contents as? CloudChatRemoveMessagesOperation { + if let entry = entry, let _ = entry.mergedIndex, (entry.contents is CloudChatRemoveMessagesOperation || entry.contents is CloudChatRemoveChatOperation) { result = entry.mergedEntry! return PeerOperationLogEntryUpdate(mergedIndex: .none, contents: .none) } else { @@ -91,6 +91,12 @@ func managedCloudChatRemoveMessagesOperations(postbox: Postbox, network: Network } else { return .complete() } + } else if let operation = entry.contents as? CloudChatRemoveChatOperation { + if let peer = modifier.getPeer(entry.peerId) { + return removeChat(modifier: modifier, postbox: postbox, network: network, stateManager: stateManager, peer: peer, operation: operation) + } else { + return .complete() + } } else { assertionFailure() } @@ -98,7 +104,7 @@ func managedCloudChatRemoveMessagesOperations(postbox: Postbox, network: Network return .complete() }) |> then(postbox.modify { modifier -> Void in - modifier.operationLogRemoveEntry(peerId: entry.peerId, tag: OperationLogTags.CloudChatRemoveMessages, tagLocalIndex: entry.tagLocalIndex) + let _ = modifier.operationLogRemoveEntry(peerId: entry.peerId, tag: OperationLogTags.CloudChatRemoveMessages, tagLocalIndex: entry.tagLocalIndex) }) disposable.set(signal.start()) @@ -112,6 +118,7 @@ func managedCloudChatRemoveMessagesOperations(postbox: Postbox, network: Network for disposable in disposables { disposable.dispose() } + disposable.dispose() } } } @@ -151,3 +158,68 @@ private func removeMessages(postbox: Postbox, network: Network, stateManager: Ac } } } + +private func removeChat(modifier: Modifier, postbox: Postbox, network: Network, stateManager: AccountStateManager, peer: Peer, operation: CloudChatRemoveChatOperation) -> Signal { + if peer.id.namespace == Namespaces.Peer.CloudChannel { + if let inputChannel = apiInputChannel(peer) { + let signal: Signal + if let channel = peer as? TelegramChannel, case .creator = channel.role { + signal = network.request(Api.functions.channels.deleteChannel(channel: inputChannel)) + } else { + signal = network.request(Api.functions.channels.leaveChannel(channel: inputChannel)) + } + return signal + |> map { result -> Api.Updates? in + return result + } + |> `catch` { _ in + return .single(nil) + } + |> mapToSignal { updates in + if let updates = updates { + stateManager.addUpdates(updates) + } + return .complete() + } + } else { + return .complete() + } + } else if peer.id.namespace == Namespaces.Peer.CloudGroup { + return network.request(Api.functions.messages.deleteChatUser(chatId: peer.id.id, userId: Api.InputUser.inputUserSelf)) + |> map { result -> Api.Updates? in + return result + } + |> `catch` { _ in + return .single(nil) + } + |> mapToSignal { updates in + if let updates = updates { + stateManager.addUpdates(updates) + } + return .complete() + } + } else if peer.id.namespace == Namespaces.Peer.CloudUser { + if let inputPeer = apiInputPeer(peer), let topMessageId = modifier.getTopPeerMessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud) { + return network.request(Api.functions.messages.deleteHistory(peer: inputPeer, maxId: topMessageId.id)) + |> map { result -> Api.messages.AffectedHistory? in + return result + } + |> `catch` { _ in + return .single(nil) + } + |> mapToSignal { result in + if let result = result { + switch result { + case let .affectedHistory(pts, ptsCount, _): + stateManager.addUpdateGroups([.updatePts(pts: pts, ptsCount: ptsCount)]) + } + } + return .complete() + } + } else { + return .complete() + } + } else { + return .complete() + } +} diff --git a/TelegramCore/ManagedGlobalNotificationSettings.swift b/TelegramCore/ManagedGlobalNotificationSettings.swift new file mode 100644 index 0000000000..e308dca2a4 --- /dev/null +++ b/TelegramCore/ManagedGlobalNotificationSettings.swift @@ -0,0 +1,141 @@ +import Foundation +#if os(macOS) + import PostboxMac + import SwiftSignalKitMac + import MtProtoKitMac +#else + import Postbox + import SwiftSignalKit + import MtProtoKitDynamic +#endif + +public func updateGlobalNotificationSettingsInteractively(postbox: Postbox, _ f: @escaping (GlobalNotificationSettingsSet) -> GlobalNotificationSettingsSet) -> Signal { + return postbox.modify { modifier -> Void in + modifier.updatePreferencesEntry(key: PreferencesKeys.globalNotifications, { current in + if let current = current as? GlobalNotificationSettings { + return GlobalNotificationSettings(toBeSynchronized: f(current.effective), remote: current.remote) + } else { + let settings = f(GlobalNotificationSettingsSet.defaultSettings) + return GlobalNotificationSettings(toBeSynchronized: settings, remote: settings) + } + }) + } +} + +public func resetPeerNotificationSettings(network: Network) -> Signal { + return network.request(Api.functions.account.resetNotifySettings()) + |> retryRequest + |> mapToSignal { _ in return Signal.complete() } +} + +private enum SynchronizeGlobalSettingsData: Equatable { + case none + case fetch + case push(GlobalNotificationSettingsSet) + + static func ==(lhs: SynchronizeGlobalSettingsData, rhs: SynchronizeGlobalSettingsData) -> Bool { + switch lhs { + case .none: + if case .none = rhs { + return true + } else { + return false + } + case .fetch: + if case .fetch = rhs { + return true + } else { + return false + } + case let .push(settings): + if case .push(settings) = rhs { + return true + } else { + return false + } + } + } +} + +func managedGlobalNotificationSettings(postbox: Postbox, network: Network) -> Signal { + let data = postbox.preferencesView(keys: [PreferencesKeys.globalNotifications]) + |> map { view -> SynchronizeGlobalSettingsData in + if let preferences = view.values[PreferencesKeys.globalNotifications] as? GlobalNotificationSettings { + if let settings = preferences.toBeSynchronized { + return .push(settings) + } else { + return .none + } + } else { + return .fetch + } + } + let action = data + |> distinctUntilChanged + |> mapToSignal { data -> Signal in + switch data { + case .none: + return .complete() + case .fetch: + return fetchedNotificationSettings(network: network) + |> mapToSignal { settings -> Signal in + return postbox.modify { modifier -> Void in + modifier.updatePreferencesEntry(key: PreferencesKeys.globalNotifications, { current in + if let current = current as? GlobalNotificationSettings { + return GlobalNotificationSettings(toBeSynchronized: current.toBeSynchronized, remote: settings) + } else { + return GlobalNotificationSettings(toBeSynchronized: nil, remote: settings) + } + }) + } + } + case let .push(settings): + return pushedNotificationSettings(network: network, settings: settings) + |> then(postbox.modify { modifier -> Void in + modifier.updatePreferencesEntry(key: PreferencesKeys.globalNotifications, { current in + if let current = current as? GlobalNotificationSettings, current.toBeSynchronized == settings { + return GlobalNotificationSettings(toBeSynchronized: nil, remote: settings) + } else { + return current + } + }) + }) + } + } + + return action +} + +private func fetchedNotificationSettings(network: Network) -> Signal { + let chats = network.request(Api.functions.account.getNotifySettings(peer: Api.InputNotifyPeer.inputNotifyChats)) + let users = network.request(Api.functions.account.getNotifySettings(peer: Api.InputNotifyPeer.inputNotifyUsers)) + + return combineLatest(chats, users) + |> retryRequest + |> map { chats, users in + let chatsSettings: MessageNotificationSettings + switch chats { + case .peerNotifySettingsEmpty: + chatsSettings = MessageNotificationSettings.defaultSettings + case let .peerNotifySettings(flags, muteUntil, sound): + chatsSettings = MessageNotificationSettings(enabled: muteUntil == 0, displayPreviews: (flags & (1 << 0)) != 0, sound: PeerMessageSound(apiSound: sound)) + } + + let userSettings: MessageNotificationSettings + switch users { + case .peerNotifySettingsEmpty: + userSettings = MessageNotificationSettings.defaultSettings + case let .peerNotifySettings(flags, muteUntil, sound): + userSettings = MessageNotificationSettings(enabled: muteUntil == 0, displayPreviews: (flags & (1 << 0)) != 0, sound: PeerMessageSound(apiSound: sound)) + } + return GlobalNotificationSettingsSet(privateChats: userSettings, groupChats: chatsSettings) + } +} + +private func pushedNotificationSettings(network: Network, settings: GlobalNotificationSettingsSet) -> Signal { + let pushedChats = network.request(Api.functions.account.updateNotifySettings(peer: Api.InputNotifyPeer.inputNotifyChats, settings: Api.InputPeerNotifySettings.inputPeerNotifySettings(flags: settings.groupChats.displayPreviews ? (1 << 0) : 0, muteUntil: settings.groupChats.enabled ? 0 : Int32.max, sound: settings.groupChats.sound.apiSound))) + let pushedUsers = network.request(Api.functions.account.updateNotifySettings(peer: Api.InputNotifyPeer.inputNotifyUsers, settings: Api.InputPeerNotifySettings.inputPeerNotifySettings(flags: settings.privateChats.displayPreviews ? (1 << 0) : 0, muteUntil: settings.privateChats.enabled ? 0 : Int32.max, sound: settings.privateChats.sound.apiSound))) + return combineLatest(pushedChats, pushedUsers) + |> retryRequest + |> mapToSignal { _ -> Signal in return .complete() } +} diff --git a/TelegramCore/MergeLists.swift b/TelegramCore/MergeLists.swift index e45bb28e25..94a870b702 100644 --- a/TelegramCore/MergeLists.swift +++ b/TelegramCore/MergeLists.swift @@ -93,7 +93,7 @@ public func mergeListsStableWithUpdates(leftList: [T], rightList: [T]) -> ([I #if (arch(i386) || arch(x86_64)) && os(iOS) var existingStableIds: [T.T: T] = [:] for item in leftList { - if let other = existingStableIds[item.stableId] { + if let _ = existingStableIds[item.stableId] { assertionFailure() } else { existingStableIds[item.stableId] = item diff --git a/TelegramCore/Namespaces.swift b/TelegramCore/Namespaces.swift index a47fb2741c..4546f6b45a 100644 --- a/TelegramCore/Namespaces.swift +++ b/TelegramCore/Namespaces.swift @@ -65,3 +65,21 @@ struct OperationLogTags { static let SynchronizePinnedCloudChats = PeerOperationLogTag(value: 4) static let AutoremoveMessages = PeerOperationLogTag(value: 5) } + +private enum PreferencesKeyValues: Int32 { + case globalNotifications = 0 +} + +public func applicationSpecificPreferencesKey(_ value: Int32) -> ValueBoxKey { + let key = ValueBoxKey(length: 4) + key.setInt32(0, value: value + 1000) + return key +} + +public struct PreferencesKeys { + public static let globalNotifications: ValueBoxKey = { + let key = ValueBoxKey(length: 4) + key.setInt32(0, value: PreferencesKeyValues.globalNotifications.rawValue) + return key + }() +} diff --git a/TelegramCore/NetworkLogging.m b/TelegramCore/NetworkLogging.m index a6a09e4fa0..ff106f7bb2 100644 --- a/TelegramCore/NetworkLogging.m +++ b/TelegramCore/NetworkLogging.m @@ -16,7 +16,7 @@ void setBridgingTraceFunction(void (*f)(NSString *, NSString *)) { #if TARGET_IPHONE_SIMULATOR static bool loggingEnabled = true; #else -static bool loggingEnabled = false; +static bool loggingEnabled = true; #endif static void TGTelegramLoggingFunction(NSString *format, va_list args) { diff --git a/TelegramCore/PeerUtils.swift b/TelegramCore/PeerUtils.swift index ee1eb53df5..1c6e8ec341 100644 --- a/TelegramCore/PeerUtils.swift +++ b/TelegramCore/PeerUtils.swift @@ -163,3 +163,31 @@ public func peerViewMainPeer(_ view: PeerView) -> Peer? { } } +public extension RenderedPeer { + public convenience init(message: Message) { + var peers = SimpleDictionary() + let peerId = message.id.peerId + if let peer = message.peers[peerId] { + peers[peer.id] = peer + if let peer = peer as? TelegramSecretChat { + if let regularPeer = message.peers[peer.regularPeerId] { + peers[regularPeer.id] = regularPeer + } + } + } + self.init(peerId: message.id.peerId, peers: peers) + } + + public var chatMainPeer: Peer? { + if let peer = self.peers[self.peerId] { + if let peer = peer as? TelegramSecretChat { + return self.peers[peer.regularPeerId] + } else { + return peer + } + } else { + return nil + } + } +} + diff --git a/TelegramCore/PrivacySettings.swift b/TelegramCore/PrivacySettings.swift new file mode 100644 index 0000000000..509953cbb7 --- /dev/null +++ b/TelegramCore/PrivacySettings.swift @@ -0,0 +1,17 @@ +import Foundation +#if os(macOS) + import PostboxMac +#else + import Postbox +#endif + +public enum SelectivePrivacySettings { + case enableEveryone(disableFor: [PeerId]) + case enableContacts(enableFor: [PeerId], disableFor: [PeerId]) + case disableEveryone(enableFor: [PeerId]) +} + +public struct AccountPrivacySettings { + public let presence: SelectivePrivacySettings + public let groupInvitations: SelectivePrivacySettings +} diff --git a/TelegramCore/ProcessSecretChatIncomingDecryptedOperations.swift b/TelegramCore/ProcessSecretChatIncomingDecryptedOperations.swift index b6c8cc47ec..4cf7ccee8d 100644 --- a/TelegramCore/ProcessSecretChatIncomingDecryptedOperations.swift +++ b/TelegramCore/ProcessSecretChatIncomingDecryptedOperations.swift @@ -295,7 +295,7 @@ func processSecretChatIncomingDecryptedOperations(mediaBox: MediaBox, modifier: modifier.setPeerChatState(peerId, state: updatedState) } if !peer.isEqual(updatedPeer) { - modifier.updatePeers([updatedPeer], update: { _, updated in + updatePeers(modifier: modifier, peers: [updatedPeer], update: { _, updated in return updated }) } diff --git a/TelegramCore/RecentPeers.swift b/TelegramCore/RecentPeers.swift index 0070bd03ce..74e178a5d1 100644 --- a/TelegramCore/RecentPeers.swift +++ b/TelegramCore/RecentPeers.swift @@ -36,7 +36,7 @@ public func recentPeers(account: Account) -> Signal<[Peer], NoError> { |> mapToSignal { peersAndPresences -> Signal<[Peer], NoError> in if let (peers, peerPresences) = peersAndPresences { return account.postbox.modify { modifier -> [Peer] in - modifier.updatePeers(peers, update: { return $1 }) + updatePeers(modifier: modifier, peers: peers, update: { return $1 }) modifier.updatePeerPresences(peerPresences) modifier.replaceRecentPeerIds(peers.map({ $0.id })) return peers diff --git a/TelegramCore/RemovePeerChat.swift b/TelegramCore/RemovePeerChat.swift new file mode 100644 index 0000000000..88eb8aed4f --- /dev/null +++ b/TelegramCore/RemovePeerChat.swift @@ -0,0 +1,19 @@ +import Foundation +#if os(macOS) + import PostboxMac + import SwiftSignalKitMac +#else + import Postbox + import SwiftSignalKit +#endif + +public func removePeerChat(postbox: Postbox, peerId: PeerId) -> Signal { + return postbox.modify { modifier -> Void in + if peerId.namespace == Namespaces.Peer.SecretChat { + + } else { + cloudChatAddRemoveChatOperation(modifier: modifier, peerId: peerId) + } + modifier.updatePeerChatListInclusion(peerId, inclusion: .never) + } +} diff --git a/TelegramCore/ResolvePeerByName.swift b/TelegramCore/ResolvePeerByName.swift index f31f6558e4..3b48f2e923 100644 --- a/TelegramCore/ResolvePeerByName.swift +++ b/TelegramCore/ResolvePeerByName.swift @@ -98,7 +98,7 @@ public func resolvePeerByName(account: Account, name: String, ageLimit: Int32 = if let peer = peers[apiPeer.peerId] { peerId = peer.id - modifier.updatePeers(Array(peers.values), update: { _, updated -> Peer in + updatePeers(modifier: modifier, peers: Array(peers.values), update: { _, updated -> Peer in return updated }) } diff --git a/TelegramCore/SecretChatState.swift b/TelegramCore/SecretChatState.swift index 927003ed50..e74490334d 100644 --- a/TelegramCore/SecretChatState.swift +++ b/TelegramCore/SecretChatState.swift @@ -15,32 +15,46 @@ enum SecretChatLayer: Int32 { case layer46 = 46 } -struct SecretChatBasicFingerprint: Equatable { - let k0: Int64 - let k1: Int64 +public struct SecretChatKeyFingerprint: Coding, Equatable { + public let k0: Int64 + public let k1: Int64 + public let k2: Int64 + public let k3: Int64 - static func ==(lhs: SecretChatBasicFingerprint, rhs: SecretChatBasicFingerprint) -> Bool { - if lhs.k0 != rhs.k0 { - return false - } - if lhs.k1 != rhs.k1 { - return false - } - return true + public init(k0: Int64, k1: Int64, k2: Int64, k3: Int64) { + self.k0 = k0 + self.k1 = k1 + self.k2 = k2 + self.k3 = k3 } -} - -struct SecretChatExtendedFingerprint: Equatable { - let k0: Int64 - let k1: Int64 - static func ==(lhs: SecretChatExtendedFingerprint, rhs: SecretChatExtendedFingerprint) -> Bool { + public init(decoder: Decoder) { + self.k0 = decoder.decodeInt64ForKey("k0") + self.k1 = decoder.decodeInt64ForKey("k1") + self.k2 = decoder.decodeInt64ForKey("k2") + self.k3 = decoder.decodeInt64ForKey("k3") + } + + public func encode(_ encoder: Encoder) { + encoder.encodeInt64(self.k0, forKey: "") + encoder.encodeInt64(self.k1, forKey: "") + encoder.encodeInt64(self.k2, forKey: "") + encoder.encodeInt64(self.k3, forKey: "") + } + + public static func ==(lhs: SecretChatKeyFingerprint, rhs: SecretChatKeyFingerprint) -> Bool { if lhs.k0 != rhs.k0 { return false } if lhs.k1 != rhs.k1 { return false } + if lhs.k2 != rhs.k2 { + return false + } + if lhs.k3 != rhs.k3 { + return false + } return true } } @@ -364,12 +378,14 @@ final class SecretChatState: PeerChatState, Equatable { let role: SecretChatRole let embeddedState: SecretChatEmbeddedState let keychain: SecretChatKeychain + let keyFingerprint: SecretChatKeyFingerprint? let messageAutoremoveTimeout: Int32? - init(role: SecretChatRole, embeddedState: SecretChatEmbeddedState, keychain: SecretChatKeychain, messageAutoremoveTimeout: Int32?) { + init(role: SecretChatRole, embeddedState: SecretChatEmbeddedState, keychain: SecretChatKeychain, keyFingerprint: SecretChatKeyFingerprint?, messageAutoremoveTimeout: Int32?) { self.role = role self.embeddedState = embeddedState self.keychain = keychain + self.keyFingerprint = keyFingerprint self.messageAutoremoveTimeout = messageAutoremoveTimeout } @@ -377,6 +393,7 @@ final class SecretChatState: PeerChatState, Equatable { self.role = SecretChatRole(rawValue: decoder.decodeInt32ForKey("r"))! self.embeddedState = decoder.decodeObjectForKey("s", decoder: { return SecretChatEmbeddedState(decoder: $0) }) as! SecretChatEmbeddedState self.keychain = decoder.decodeObjectForKey("k", decoder: { return SecretChatKeychain(decoder: $0) }) as! SecretChatKeychain + self.keyFingerprint = decoder.decodeObjectForKey("f", decoder: { return SecretChatKeyFingerprint(decoder: $0) }) as? SecretChatKeyFingerprint self.messageAutoremoveTimeout = decoder.decodeInt32ForKey("a") } @@ -384,6 +401,11 @@ final class SecretChatState: PeerChatState, Equatable { encoder.encodeInt32(self.role.rawValue, forKey: "r") encoder.encodeObject(self.embeddedState, forKey: "s") encoder.encodeObject(self.keychain, forKey: "k") + if let keyFingerprint = self.keyFingerprint { + encoder.encodeObject(keyFingerprint, forKey: "f") + } else { + encoder.encodeNil(forKey: "f") + } if let messageAutoremoveTimeout = self.messageAutoremoveTimeout { encoder.encodeInt32(messageAutoremoveTimeout, forKey: "a") } else { @@ -402,15 +424,19 @@ final class SecretChatState: PeerChatState, Equatable { return lhs.role == rhs.role && lhs.embeddedState == rhs.embeddedState && lhs.keychain == rhs.keychain && lhs.messageAutoremoveTimeout == rhs.messageAutoremoveTimeout } + func withUpdatedKeyFingerprint(_ keyFingerprint: SecretChatKeyFingerprint?) -> SecretChatState { + return SecretChatState(role: self.role, embeddedState: self.embeddedState, keychain: self.keychain, keyFingerprint: keyFingerprint, messageAutoremoveTimeout: self.messageAutoremoveTimeout) + } + func withUpdatedEmbeddedState(_ embeddedState: SecretChatEmbeddedState) -> SecretChatState { - return SecretChatState(role: self.role, embeddedState: embeddedState, keychain: self.keychain, messageAutoremoveTimeout: self.messageAutoremoveTimeout) + return SecretChatState(role: self.role, embeddedState: embeddedState, keychain: self.keychain, keyFingerprint: self.keyFingerprint, messageAutoremoveTimeout: self.messageAutoremoveTimeout) } func withUpdatedKeychain(_ keychain: SecretChatKeychain) -> SecretChatState { - return SecretChatState(role: self.role, embeddedState: self.embeddedState, keychain: keychain, messageAutoremoveTimeout: self.messageAutoremoveTimeout) + return SecretChatState(role: self.role, embeddedState: self.embeddedState, keychain: keychain, keyFingerprint: self.keyFingerprint, messageAutoremoveTimeout: self.messageAutoremoveTimeout) } func withUpdatedMessageAutoremoveTimeout(_ messageAutoremoveTimeout: Int32?) -> SecretChatState { - return SecretChatState(role: self.role, embeddedState: self.embeddedState, keychain: self.keychain, messageAutoremoveTimeout: messageAutoremoveTimeout) + return SecretChatState(role: self.role, embeddedState: self.embeddedState, keychain: self.keychain, keyFingerprint: self.keyFingerprint, messageAutoremoveTimeout: messageAutoremoveTimeout) } } diff --git a/TelegramCore/SetSecretChatMessageAutoremoveTimeoutInteractively.swift b/TelegramCore/SetSecretChatMessageAutoremoveTimeoutInteractively.swift index ebe9e954d6..c5546d84a8 100644 --- a/TelegramCore/SetSecretChatMessageAutoremoveTimeoutInteractively.swift +++ b/TelegramCore/SetSecretChatMessageAutoremoveTimeoutInteractively.swift @@ -13,7 +13,7 @@ public func setSecretChatMessageAutoremoveTimeoutInteractively(account: Account, let updatedPeer = peer.withUpdatedMessageAutoremoveTimeout(timeout) let updatedState = state.withUpdatedMessageAutoremoveTimeout(timeout) if !updatedPeer.isEqual(peer) { - modifier.updatePeers([updatedPeer], update: { $1 }) + updatePeers(modifier: modifier, peers: [updatedPeer], update: { $1 }) } if updatedState != state { modifier.setPeerChatState(peerId, state: updatedState) diff --git a/TelegramCore/TelegramGroup.swift b/TelegramCore/TelegramGroup.swift index ed25d4d7de..84e61e9f47 100644 --- a/TelegramCore/TelegramGroup.swift +++ b/TelegramCore/TelegramGroup.swift @@ -50,6 +50,7 @@ public final class TelegramGroup: Peer { public let membership: TelegramGroupMembership public let flags: TelegramGroupFlags public let migrationReference: TelegramGroupToChannelMigrationReference? + public let creationDate: Int32 public let version: Int public var indexName: PeerIndexNameRepresentation { @@ -59,7 +60,7 @@ public final class TelegramGroup: Peer { public let associatedPeerIds: [PeerId]? = nil public let notificationSettingsPeerId: PeerId? = nil - public init(id: PeerId, title: String, photo: [TelegramMediaImageRepresentation], participantCount: Int, role: TelegramGroupRole, membership: TelegramGroupMembership, flags: TelegramGroupFlags, migrationReference: TelegramGroupToChannelMigrationReference?, version: Int) { + public init(id: PeerId, title: String, photo: [TelegramMediaImageRepresentation], participantCount: Int, role: TelegramGroupRole, membership: TelegramGroupMembership, flags: TelegramGroupFlags, migrationReference: TelegramGroupToChannelMigrationReference?, creationDate: Int32, version: Int) { self.id = id self.title = title self.photo = photo @@ -68,6 +69,7 @@ public final class TelegramGroup: Peer { self.membership = membership self.flags = flags self.migrationReference = migrationReference + self.creationDate = creationDate self.version = version } @@ -86,6 +88,7 @@ public final class TelegramGroup: Peer { } else { self.migrationReference = nil } + self.creationDate = decoder.decodeInt32ForKey("d") self.version = Int(decoder.decodeInt32ForKey("v")) } @@ -103,6 +106,7 @@ public final class TelegramGroup: Peer { encoder.encodeNil(forKey: "mr.i") encoder.encodeNil(forKey: "mr.a") } + encoder.encodeInt32(self.creationDate, forKey: "d") encoder.encodeInt32(Int32(self.version), forKey: "v") } @@ -132,6 +136,9 @@ public final class TelegramGroup: Peer { if self.migrationReference != other.migrationReference { return false } + if self.creationDate != other.creationDate { + return false + } if self.flags != other.flags { return false } @@ -140,10 +147,8 @@ public final class TelegramGroup: Peer { return false } } - - //id: PeerId, title: String, photo: [TelegramMediaImageRepresentation], participantCount: Int, role: TelegramGroupRole, membership: TelegramGroupMembership, flags: TelegramGroupFlags, migrationReference: TelegramGroupToChannelMigrationReference?, version: Int public func updateFlags(flags: TelegramGroupFlags, version: Int) -> TelegramGroup { - return TelegramGroup(id: self.id, title: self.title, photo: self.photo, participantCount: self.participantCount, role: self.role, membership: self.membership, flags: flags, migrationReference: self.migrationReference, version: version) + return TelegramGroup(id: self.id, title: self.title, photo: self.photo, participantCount: self.participantCount, role: self.role, membership: self.membership, flags: flags, migrationReference: self.migrationReference, creationDate: self.creationDate, version: version) } } diff --git a/TelegramCore/TelegramPeerNotificationSettings.swift b/TelegramCore/TelegramPeerNotificationSettings.swift index 8cb0e971aa..dc6c60ada0 100644 --- a/TelegramCore/TelegramPeerNotificationSettings.swift +++ b/TelegramCore/TelegramPeerNotificationSettings.swift @@ -50,46 +50,63 @@ public enum PeerMuteState: Equatable { } } +private enum PeerMessageSoundValue: Int32 { + case none + case bundledModern + case bundledClassic +} + public enum PeerMessageSound: Equatable { - case appDefault - case bundled(index: Int32) + case none + case bundledModern(id: Int32) + case bundledClassic(id: Int32) - fileprivate static func decodeInline(_ decoder: Decoder) -> PeerMessageSound { + static func decodeInline(_ decoder: Decoder) -> PeerMessageSound { switch decoder.decodeInt32ForKey("s.v") as Int32 { - case 0: - return .appDefault - case 1: - return .bundled(index: decoder.decodeInt32ForKey("s.i")) + case PeerMessageSoundValue.none.rawValue: + return .none + case PeerMessageSoundValue.bundledModern.rawValue: + return .bundledModern(id: decoder.decodeInt32ForKey("s.i")) + case PeerMessageSoundValue.bundledClassic.rawValue: + return .bundledClassic(id: decoder.decodeInt32ForKey("s.i")) default: - return .appDefault + assertionFailure() + return .bundledModern(id: 0) } } - fileprivate func encodeInline(_ encoder: Encoder) { + func encodeInline(_ encoder: Encoder) { switch self { - case .appDefault: - encoder.encodeInt32(0, forKey: "s.v") - case let .bundled(index): - encoder.encodeInt32(1, forKey: "s.v") - encoder.encodeInt32(index, forKey: "s.i") + case .none: + encoder.encodeInt32(PeerMessageSoundValue.none.rawValue, forKey: "s.v") + case let .bundledModern(id): + encoder.encodeInt32(PeerMessageSoundValue.bundledModern.rawValue, forKey: "s.v") + encoder.encodeInt32(id, forKey: "s.i") + case let .bundledClassic(id): + encoder.encodeInt32(PeerMessageSoundValue.bundledClassic.rawValue, forKey: "s.v") + encoder.encodeInt32(id, forKey: "s.i") } } public static func ==(lhs: PeerMessageSound, rhs: PeerMessageSound) -> Bool { switch lhs { - case .appDefault: - switch rhs { - case .appDefault: - return true - default: - return false + case .none: + if case .none = rhs { + return true + } else { + return false } - case let .bundled(lhsIndex): - switch rhs { - case .bundled(lhsIndex): - return true - default: - return false + case let .bundledModern(id): + if case .bundledModern(id) = rhs { + return true + } else { + return false + } + case let .bundledClassic(id): + if case .bundledClassic(id) = rhs { + return true + } else { + return false } } } @@ -99,6 +116,10 @@ public final class TelegramPeerNotificationSettings: PeerNotificationSettings, E public let muteState: PeerMuteState public let messageSound: PeerMessageSound + public static var defaultSettings: TelegramPeerNotificationSettings { + return TelegramPeerNotificationSettings(muteState: .unmuted, messageSound: .bundledModern(id: 0)) + } + public var isRemovedFromTotalUnreadCount: Bool { switch self.muteState { case .unmuted: @@ -137,12 +158,53 @@ public final class TelegramPeerNotificationSettings: PeerNotificationSettings, E } extension TelegramPeerNotificationSettings { - public convenience init(apiSettings: Api.PeerNotifySettings) { + convenience init(apiSettings: Api.PeerNotifySettings) { switch apiSettings { case .peerNotifySettingsEmpty: - self.init(muteState: .unmuted, messageSound: .appDefault) + self.init(muteState: .unmuted, messageSound: .bundledModern(id: 0)) case let .peerNotifySettings(_, muteUntil, sound): - self.init(muteState: muteUntil == 0 ? .unmuted : .muted(until: muteUntil), messageSound: sound == "default" ? .appDefault : .bundled(index: Int32(sound) ?? 0)) + self.init(muteState: muteUntil == 0 ? .unmuted : .muted(until: muteUntil), messageSound: PeerMessageSound(apiSound: sound)) + } + } +} + +extension PeerMessageSound { + init(apiSound: String) { + let parsedSound: PeerMessageSound + if apiSound == "default" { + parsedSound = .bundledModern(id: 0) + } else if apiSound == "" || apiSound == "0" { + parsedSound = .none + } else { + let soundId: Int32 + if let id = Int32(apiSound) { + soundId = id + } else { + soundId = 1 + } + if soundId >= 1 && soundId < 13 { + parsedSound = .bundledModern(id: soundId - 1) + } else if soundId >= 13 && soundId <= 20 { + parsedSound = .bundledClassic(id: soundId - 13) + } else { + parsedSound = .bundledModern(id: 0) + } + } + self = parsedSound + } + + var apiSound: String { + switch self { + case .none: + return "" + case let .bundledModern(id): + if id == 0 { + return "default" + } else { + return "\(id + 1)" + } + case let .bundledClassic(id): + return "\(id + 13)" } } } diff --git a/TelegramCore/TelegramSecretChat.swift b/TelegramCore/TelegramSecretChat.swift index 59b54a30ea..741cf67341 100644 --- a/TelegramCore/TelegramSecretChat.swift +++ b/TelegramCore/TelegramSecretChat.swift @@ -9,6 +9,7 @@ public final class TelegramSecretChat: Peer { public let id: PeerId public let regularPeerId: PeerId public let accessHash: Int64 + public let creationDate: Int32 public let embeddedState: SecretChatEmbeddedPeerState public let messageAutoremoveTimeout: Int32? @@ -19,10 +20,11 @@ public final class TelegramSecretChat: Peer { public let associatedPeerIds: [PeerId]? public let notificationSettingsPeerId: PeerId? - init(id: PeerId, regularPeerId: PeerId, accessHash: Int64, embeddedState: SecretChatEmbeddedPeerState, messageAutoremoveTimeout: Int32?) { + init(id: PeerId, creationDate: Int32, regularPeerId: PeerId, accessHash: Int64, embeddedState: SecretChatEmbeddedPeerState, messageAutoremoveTimeout: Int32?) { self.id = id self.regularPeerId = regularPeerId self.accessHash = accessHash + self.creationDate = creationDate self.embeddedState = embeddedState self.associatedPeerIds = [regularPeerId] self.notificationSettingsPeerId = regularPeerId @@ -34,6 +36,7 @@ public final class TelegramSecretChat: Peer { self.regularPeerId = PeerId(decoder.decodeInt64ForKey("r")) self.notificationSettingsPeerId = self.regularPeerId self.accessHash = decoder.decodeInt64ForKey("h") + self.creationDate = decoder.decodeInt32ForKey("d") self.embeddedState = SecretChatEmbeddedPeerState(rawValue: decoder.decodeInt32ForKey("s"))! self.associatedPeerIds = [self.regularPeerId] self.messageAutoremoveTimeout = decoder.decodeInt32ForKey("at") @@ -43,6 +46,7 @@ public final class TelegramSecretChat: Peer { encoder.encodeInt64(self.id.toInt64(), forKey: "i") encoder.encodeInt64(self.regularPeerId.toInt64(), forKey: "r") encoder.encodeInt64(self.accessHash, forKey: "h") + encoder.encodeInt32(self.creationDate, forKey: "d") encoder.encodeInt32(self.embeddedState.rawValue, forKey: "s") if let messageAutoremoveTimeout = self.messageAutoremoveTimeout { encoder.encodeInt32(messageAutoremoveTimeout, forKey: "at") @@ -53,17 +57,17 @@ public final class TelegramSecretChat: Peer { public func isEqual(_ other: Peer) -> Bool { if let other = other as? TelegramSecretChat { - return self.id == other.id && self.regularPeerId == other.regularPeerId && self.accessHash == other.accessHash && self.embeddedState == other.embeddedState && self.messageAutoremoveTimeout == other.messageAutoremoveTimeout + return self.id == other.id && self.regularPeerId == other.regularPeerId && self.accessHash == other.accessHash && self.embeddedState == other.embeddedState && self.messageAutoremoveTimeout == other.messageAutoremoveTimeout && self.creationDate == other.creationDate } else { return false } } func withUpdatedEmbeddedState(_ embeddedState: SecretChatEmbeddedPeerState) -> TelegramSecretChat { - return TelegramSecretChat(id: self.id, regularPeerId: self.regularPeerId, accessHash: self.accessHash, embeddedState: embeddedState, messageAutoremoveTimeout: self.messageAutoremoveTimeout) + return TelegramSecretChat(id: self.id, creationDate: self.creationDate, regularPeerId: self.regularPeerId, accessHash: self.accessHash, embeddedState: embeddedState, messageAutoremoveTimeout: self.messageAutoremoveTimeout) } func withUpdatedMessageAutoremoveTimeout(_ messageAutoremoveTimeout: Int32?) -> TelegramSecretChat { - return TelegramSecretChat(id: self.id, regularPeerId: self.regularPeerId, accessHash: self.accessHash, embeddedState: self.embeddedState, messageAutoremoveTimeout: messageAutoremoveTimeout) + return TelegramSecretChat(id: self.id, creationDate: self.creationDate, regularPeerId: self.regularPeerId, accessHash: self.accessHash, embeddedState: self.embeddedState, messageAutoremoveTimeout: messageAutoremoveTimeout) } } diff --git a/TelegramCore/UpdateAccountPeerName.swift b/TelegramCore/UpdateAccountPeerName.swift new file mode 100644 index 0000000000..df9f5919b4 --- /dev/null +++ b/TelegramCore/UpdateAccountPeerName.swift @@ -0,0 +1,28 @@ +import Foundation +#if os(macOS) + import PostboxMac + import SwiftSignalKitMac + import MtProtoKitMac +#else + import Postbox + import SwiftSignalKit + import MtProtoKitDynamic +#endif + +public func updateAccountPeerName(account: Account, firstName: String, lastName: String) -> Signal { + return account.network.request(Api.functions.account.updateProfile(flags: (1 << 0) | (1 << 1), firstName: firstName, lastName: lastName, about: nil)) + |> map { result -> Api.User? in + return result + } + |> `catch` { _ in + return .single(nil) + } + |> mapToSignal { result -> Signal in + return account.postbox.modify { modifier -> Void in + if let result = result { + let peer = TelegramUser(user: result) + updatePeers(modifier: modifier, peers: [peer], update: { $1 }) + } + } + } +} diff --git a/TelegramCore/UpdateCachedChannelParticipants.swift b/TelegramCore/UpdateCachedChannelParticipants.swift index 02fb7a7351..2e0a7e1fd4 100644 --- a/TelegramCore/UpdateCachedChannelParticipants.swift +++ b/TelegramCore/UpdateCachedChannelParticipants.swift @@ -27,7 +27,7 @@ func fetchAndUpdateCachedParticipants(peerId: PeerId, network: Network, postbox: } } - modifier.updatePeers(peers, update: { _, updated -> Peer in + updatePeers(modifier: modifier, peers: peers, update: { _, updated -> Peer in return updated }) @@ -67,7 +67,7 @@ func fetchAndUpdateCachedParticipants(peerId: PeerId, network: Network, postbox: } } - modifier.updatePeers(peers, update: { _, updated -> Peer in + updatePeers(modifier: modifier, peers: peers, update: { _, updated -> Peer in return updated }) diff --git a/TelegramCore/UpdateCachedPeerData.swift b/TelegramCore/UpdateCachedPeerData.swift index d4a7f9f2ce..1332a58ff1 100644 --- a/TelegramCore/UpdateCachedPeerData.swift +++ b/TelegramCore/UpdateCachedPeerData.swift @@ -19,7 +19,7 @@ func fetchAndUpdateCachedPeerData(peerId: PeerId, network: Network, postbox: Pos case let .userFull(_, user, _, _, _, notifySettings, _, commonChatCount): let telegramUser = TelegramUser(user: user) - modifier.updatePeers([telegramUser], update: { _, updated -> Peer in + updatePeers(modifier: modifier, peers: [telegramUser], update: { _, updated -> Peer in return updated }) modifier.updatePeerNotificationSettings([peerId: TelegramPeerNotificationSettings(apiSettings: notifySettings)]) @@ -59,7 +59,7 @@ func fetchAndUpdateCachedPeerData(peerId: PeerId, network: Network, postbox: Pos } } - modifier.updatePeers(peers, update: { _, updated -> Peer in + updatePeers(modifier: modifier, peers: peers, update: { _, updated -> Peer in return updated }) @@ -102,7 +102,7 @@ func fetchAndUpdateCachedPeerData(peerId: PeerId, network: Network, postbox: Pos } } - modifier.updatePeers(peers, update: { _, updated -> Peer in + updatePeers(modifier: modifier, peers: peers, update: { _, updated -> Peer in return updated }) diff --git a/TelegramCore/UpdatesApiUtils.swift b/TelegramCore/UpdatesApiUtils.swift index 268d0039ff..eef2f58eb2 100644 --- a/TelegramCore/UpdatesApiUtils.swift +++ b/TelegramCore/UpdatesApiUtils.swift @@ -31,6 +31,12 @@ extension Api.MessageMedia { return nil } case let .messageMediaDocument(document, _): + switch document { + case .document: + break + default: + break + } return nil default: return nil @@ -52,7 +58,7 @@ extension Api.Message { var id: MessageId? { switch self { - case let .message(flags, id, fromId, toId, fwdFrom, viaBotId, replyToMsgId, date, message, media, _, entities, views, _): + case let .message(flags, id, fromId, toId, _, _, _, _, _, _, _, _, _, _): let peerId: PeerId switch toId { case let .peerUser(userId): @@ -65,7 +71,7 @@ extension Api.Message { return MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: id) case .messageEmpty: return nil - case let .messageService(flags, id, fromId, toId, replyToMsgId, date, action): + case let .messageService(flags, id, fromId, toId, _, _, _): let peerId: PeerId switch toId { case let .peerUser(userId): @@ -226,8 +232,6 @@ extension Api.Update { return message.peerIds case let .updateEditMessage(message, _, _): return message.peerIds - case let .updateEditChannelMessage(message, _, _): - return message.peerIds //case let .updateReadChannelInbox(channelId, _): // return [PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)] case let .updateUserName(userId, _, _, _): @@ -322,7 +326,7 @@ extension Api.Updates { } else { return [] } - case let .updateShortSentMessage: + case .updateShortSentMessage: return [] case .updatesTooLong: return []