no message

This commit is contained in:
Peter 2017-02-07 22:32:47 +03:00
parent 15c9274a8e
commit 2d6ed76631
25 changed files with 704 additions and 91 deletions

View File

@ -135,6 +135,18 @@
D0448CA31E291B14005A61A7 /* FetchSecretFileResource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0448CA11E291B14005A61A7 /* FetchSecretFileResource.swift */; }; D0448CA31E291B14005A61A7 /* FetchSecretFileResource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0448CA11E291B14005A61A7 /* FetchSecretFileResource.swift */; };
D0448CA51E29215A005A61A7 /* MediaResourceApiUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0448CA41E29215A005A61A7 /* MediaResourceApiUtils.swift */; }; D0448CA51E29215A005A61A7 /* MediaResourceApiUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0448CA41E29215A005A61A7 /* MediaResourceApiUtils.swift */; };
D0448CA61E29215A005A61A7 /* MediaResourceApiUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0448CA41E29215A005A61A7 /* MediaResourceApiUtils.swift */; }; D0448CA61E29215A005A61A7 /* MediaResourceApiUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0448CA41E29215A005A61A7 /* MediaResourceApiUtils.swift */; };
D049EAD51E43D98500A2CD3A /* RecentMediaItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D049EAD41E43D98500A2CD3A /* RecentMediaItem.swift */; };
D049EAD61E43D98500A2CD3A /* RecentMediaItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D049EAD41E43D98500A2CD3A /* RecentMediaItem.swift */; };
D049EAD81E43DAD200A2CD3A /* ManagedRecentStickers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D049EAD71E43DAD200A2CD3A /* ManagedRecentStickers.swift */; };
D049EAD91E43DAD200A2CD3A /* ManagedRecentStickers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D049EAD71E43DAD200A2CD3A /* ManagedRecentStickers.swift */; };
D049EAE81E44B67100A2CD3A /* RecentPeerItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D049EAE71E44B67100A2CD3A /* RecentPeerItem.swift */; };
D049EAE91E44B67100A2CD3A /* RecentPeerItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D049EAE71E44B67100A2CD3A /* RecentPeerItem.swift */; };
D049EAEB1E44B71B00A2CD3A /* RecentlySearchedPeerIds.swift in Sources */ = {isa = PBXBuildFile; fileRef = D049EAEA1E44B71B00A2CD3A /* RecentlySearchedPeerIds.swift */; };
D049EAEC1E44B71B00A2CD3A /* RecentlySearchedPeerIds.swift in Sources */ = {isa = PBXBuildFile; fileRef = D049EAEA1E44B71B00A2CD3A /* RecentlySearchedPeerIds.swift */; };
D049EAF51E44DF3300A2CD3A /* AccountState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D049EAF41E44DF3300A2CD3A /* AccountState.swift */; };
D049EAF61E44DF3300A2CD3A /* AccountState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D049EAF41E44DF3300A2CD3A /* AccountState.swift */; };
D050F2101E48AB0600988324 /* InteractivePhoneFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D050F20F1E48AB0600988324 /* InteractivePhoneFormatter.swift */; };
D050F2111E48AB0600988324 /* InteractivePhoneFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D050F20F1E48AB0600988324 /* InteractivePhoneFormatter.swift */; };
D067066C1D512ADB00DED3E3 /* Postbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D06706671D512ADB00DED3E3 /* Postbox.framework */; }; D067066C1D512ADB00DED3E3 /* Postbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D06706671D512ADB00DED3E3 /* Postbox.framework */; };
D067066D1D512ADB00DED3E3 /* SwiftSignalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D06706681D512ADB00DED3E3 /* SwiftSignalKit.framework */; }; D067066D1D512ADB00DED3E3 /* SwiftSignalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D06706681D512ADB00DED3E3 /* SwiftSignalKit.framework */; };
D073CE5D1DCB97F6007511FD /* ForwardSourceInfoAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = D073CE5C1DCB97F6007511FD /* ForwardSourceInfoAttribute.swift */; }; D073CE5D1DCB97F6007511FD /* ForwardSourceInfoAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = D073CE5C1DCB97F6007511FD /* ForwardSourceInfoAttribute.swift */; };
@ -424,6 +436,12 @@
D0448C9E1E27F5EB005A61A7 /* Random.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Random.swift; sourceTree = "<group>"; }; D0448C9E1E27F5EB005A61A7 /* Random.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Random.swift; sourceTree = "<group>"; };
D0448CA11E291B14005A61A7 /* FetchSecretFileResource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchSecretFileResource.swift; sourceTree = "<group>"; }; D0448CA11E291B14005A61A7 /* FetchSecretFileResource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchSecretFileResource.swift; sourceTree = "<group>"; };
D0448CA41E29215A005A61A7 /* MediaResourceApiUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaResourceApiUtils.swift; sourceTree = "<group>"; }; D0448CA41E29215A005A61A7 /* MediaResourceApiUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaResourceApiUtils.swift; sourceTree = "<group>"; };
D049EAD41E43D98500A2CD3A /* RecentMediaItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecentMediaItem.swift; sourceTree = "<group>"; };
D049EAD71E43DAD200A2CD3A /* ManagedRecentStickers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedRecentStickers.swift; sourceTree = "<group>"; };
D049EAE71E44B67100A2CD3A /* RecentPeerItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecentPeerItem.swift; sourceTree = "<group>"; };
D049EAEA1E44B71B00A2CD3A /* RecentlySearchedPeerIds.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecentlySearchedPeerIds.swift; sourceTree = "<group>"; };
D049EAF41E44DF3300A2CD3A /* AccountState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountState.swift; sourceTree = "<group>"; };
D050F20F1E48AB0600988324 /* InteractivePhoneFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InteractivePhoneFormatter.swift; sourceTree = "<group>"; };
D06706641D512ADB00DED3E3 /* AsyncDisplayKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AsyncDisplayKit.framework; path = "../../../../Library/Developer/Xcode/DerivedData/Telegram-iOS-diblohvjozhgaifjcniwdlixlilx/Build/Products/Debug-iphonesimulator/AsyncDisplayKit.framework"; sourceTree = "<group>"; }; D06706641D512ADB00DED3E3 /* AsyncDisplayKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AsyncDisplayKit.framework; path = "../../../../Library/Developer/Xcode/DerivedData/Telegram-iOS-diblohvjozhgaifjcniwdlixlilx/Build/Products/Debug-iphonesimulator/AsyncDisplayKit.framework"; sourceTree = "<group>"; };
D06706651D512ADB00DED3E3 /* Display.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Display.framework; path = "../../../../Library/Developer/Xcode/DerivedData/Telegram-iOS-diblohvjozhgaifjcniwdlixlilx/Build/Products/Debug-iphonesimulator/Display.framework"; sourceTree = "<group>"; }; D06706651D512ADB00DED3E3 /* Display.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Display.framework; path = "../../../../Library/Developer/Xcode/DerivedData/Telegram-iOS-diblohvjozhgaifjcniwdlixlilx/Build/Products/Debug-iphonesimulator/Display.framework"; sourceTree = "<group>"; };
D06706671D512ADB00DED3E3 /* Postbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Postbox.framework; path = "../../../../Library/Developer/Xcode/DerivedData/Telegram-iOS-diblohvjozhgaifjcniwdlixlilx/Build/Products/Debug-iphonesimulator/Postbox.framework"; sourceTree = "<group>"; }; D06706671D512ADB00DED3E3 /* Postbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Postbox.framework; path = "../../../../Library/Developer/Xcode/DerivedData/Telegram-iOS-diblohvjozhgaifjcniwdlixlilx/Build/Products/Debug-iphonesimulator/Postbox.framework"; sourceTree = "<group>"; };
@ -575,6 +593,8 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D021E0DE1DB539FC00C6B04F /* StickerPack.swift */, D021E0DE1DB539FC00C6B04F /* StickerPack.swift */,
D049EAD41E43D98500A2CD3A /* RecentMediaItem.swift */,
D049EAE71E44B67100A2CD3A /* RecentPeerItem.swift */,
); );
name = "Item Collections"; name = "Item Collections";
sourceTree = "<group>"; sourceTree = "<group>";
@ -584,6 +604,7 @@
children = ( children = (
D021E0E11DB5401A00C6B04F /* StickerManagement.swift */, D021E0E11DB5401A00C6B04F /* StickerManagement.swift */,
D01D6BF81E42A713006151C6 /* SearchStickers.swift */, D01D6BF81E42A713006151C6 /* SearchStickers.swift */,
D049EAD71E43DAD200A2CD3A /* ManagedRecentStickers.swift */,
); );
name = "Sticker Management"; name = "Sticker Management";
sourceTree = "<group>"; sourceTree = "<group>";
@ -643,6 +664,7 @@
D03B0CCD1D62239600955575 /* PhoneNumbers.swift */, D03B0CCD1D62239600955575 /* PhoneNumbers.swift */,
D0FA8BAC1E1FD6E2001E855B /* MemoryBufferExtensions.swift */, D0FA8BAC1E1FD6E2001E855B /* MemoryBufferExtensions.swift */,
D0448C9E1E27F5EB005A61A7 /* Random.swift */, D0448C9E1E27F5EB005A61A7 /* Random.swift */,
D050F20F1E48AB0600988324 /* InteractivePhoneFormatter.swift */,
); );
name = Utils; name = Utils;
sourceTree = "<group>"; sourceTree = "<group>";
@ -796,6 +818,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D03B0D611D631A8B00955575 /* Account.swift */, D03B0D611D631A8B00955575 /* Account.swift */,
D049EAF41E44DF3300A2CD3A /* AccountState.swift */,
D03B0D621D631A8B00955575 /* AccountSettings.swift */, D03B0D621D631A8B00955575 /* AccountSettings.swift */,
D03B0D631D631A8B00955575 /* AccountViewTracker.swift */, D03B0D631D631A8B00955575 /* AccountViewTracker.swift */,
D03B0D641D631A8B00955575 /* RecentPeers.swift */, D03B0D641D631A8B00955575 /* RecentPeers.swift */,
@ -946,6 +969,7 @@
D0BC386D1E3FDAB70044D6FE /* CreateGroup.swift */, D0BC386D1E3FDAB70044D6FE /* CreateGroup.swift */,
D0BC38741E40A7F70044D6FE /* RemovePeerChat.swift */, D0BC38741E40A7F70044D6FE /* RemovePeerChat.swift */,
D0BC387A1E40D2880044D6FE /* TogglePeerChatPinned.swift */, D0BC387A1E40D2880044D6FE /* TogglePeerChatPinned.swift */,
D049EAEA1E44B71B00A2CD3A /* RecentlySearchedPeerIds.swift */,
); );
name = Peers; name = Peers;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1182,6 +1206,7 @@
D0DF0C911D81A857008AEB01 /* ImageRepresentationsUtils.swift in Sources */, D0DF0C911D81A857008AEB01 /* ImageRepresentationsUtils.swift in Sources */,
D0E6521F1E3A364A004EEA91 /* UpdateAccountPeerName.swift in Sources */, D0E6521F1E3A364A004EEA91 /* UpdateAccountPeerName.swift in Sources */,
D03B0D5A1D631A6900955575 /* Api.swift in Sources */, D03B0D5A1D631A6900955575 /* Api.swift in Sources */,
D049EAE81E44B67100A2CD3A /* RecentPeerItem.swift in Sources */,
D02ABC7B1E30058F00CAE539 /* DeleteMessagesInteractively.swift in Sources */, D02ABC7B1E30058F00CAE539 /* DeleteMessagesInteractively.swift in Sources */,
D0448C9F1E27F5EB005A61A7 /* Random.swift in Sources */, D0448C9F1E27F5EB005A61A7 /* Random.swift in Sources */,
D0B843B21DA7FF30005F29E1 /* NBAsYouTypeFormatter.m in Sources */, D0B843B21DA7FF30005F29E1 /* NBAsYouTypeFormatter.m in Sources */,
@ -1193,6 +1218,7 @@
D03C53771DAFF20F004C17B3 /* MultipartUpload.swift in Sources */, D03C53771DAFF20F004C17B3 /* MultipartUpload.swift in Sources */,
D00C7CE01E3785710080C3D5 /* MarkMessageContentAsConsumedInteractively.swift in Sources */, D00C7CE01E3785710080C3D5 /* MarkMessageContentAsConsumedInteractively.swift in Sources */,
D0B843811DA6EDAE005F29E1 /* CachedUserData.swift in Sources */, D0B843811DA6EDAE005F29E1 /* CachedUserData.swift in Sources */,
D049EAD51E43D98500A2CD3A /* RecentMediaItem.swift in Sources */,
D03B0D0A1D62255C00955575 /* Holes.swift in Sources */, D03B0D0A1D62255C00955575 /* Holes.swift in Sources */,
D0B843CB1DA7FF30005F29E1 /* NBPhoneNumberUtil.m in Sources */, D0B843CB1DA7FF30005F29E1 /* NBPhoneNumberUtil.m in Sources */,
D03B0D5E1D631A6900955575 /* Network.swift in Sources */, D03B0D5E1D631A6900955575 /* Network.swift in Sources */,
@ -1202,10 +1228,12 @@
D03B0CFB1D62250800955575 /* TelegramMediaWebpage.swift in Sources */, D03B0CFB1D62250800955575 /* TelegramMediaWebpage.swift in Sources */,
D09A2FEB1D7CDC320018FB72 /* PeerAccessRestrictionInfo.swift in Sources */, D09A2FEB1D7CDC320018FB72 /* PeerAccessRestrictionInfo.swift in Sources */,
D0E35A101DE49E1C00BC6096 /* OutgoingMessageWithChatContextResult.swift in Sources */, D0E35A101DE49E1C00BC6096 /* OutgoingMessageWithChatContextResult.swift in Sources */,
D049EAD81E43DAD200A2CD3A /* ManagedRecentStickers.swift in Sources */,
D0448C991E268F9A005A61A7 /* SecretApiLayer46.swift in Sources */, D0448C991E268F9A005A61A7 /* SecretApiLayer46.swift in Sources */,
D003702B1DA42586004308D3 /* PhoneNumber.swift in Sources */, D003702B1DA42586004308D3 /* PhoneNumber.swift in Sources */,
D03B0CF91D62250800955575 /* TelegramMediaMap.swift in Sources */, D03B0CF91D62250800955575 /* TelegramMediaMap.swift in Sources */,
D0BC38791E40BAF20044D6FE /* SynchronizePinnedChatsOperation.swift in Sources */, D0BC38791E40BAF20044D6FE /* SynchronizePinnedChatsOperation.swift in Sources */,
D050F2101E48AB0600988324 /* InteractivePhoneFormatter.swift in Sources */,
D03B0D671D631A8B00955575 /* AccountViewTracker.swift in Sources */, D03B0D671D631A8B00955575 /* AccountViewTracker.swift in Sources */,
D0B843BB1DA7FF30005F29E1 /* NBMetadataCoreTestMapper.m in Sources */, D0B843BB1DA7FF30005F29E1 /* NBMetadataCoreTestMapper.m in Sources */,
D03B0D101D62255C00955575 /* UpdatesApiUtils.swift in Sources */, D03B0D101D62255C00955575 /* UpdatesApiUtils.swift in Sources */,
@ -1219,6 +1247,7 @@
D019B1CC1E2E3B6A00F80DB3 /* SecretChatRekeySession.swift in Sources */, D019B1CC1E2E3B6A00F80DB3 /* SecretChatRekeySession.swift in Sources */,
D03B0CD91D62245B00955575 /* PeerUtils.swift in Sources */, D03B0CD91D62245B00955575 /* PeerUtils.swift in Sources */,
D03B0CE41D62249F00955575 /* TextEntitiesMessageAttribute.swift in Sources */, D03B0CE41D62249F00955575 /* TextEntitiesMessageAttribute.swift in Sources */,
D049EAEB1E44B71B00A2CD3A /* RecentlySearchedPeerIds.swift in Sources */,
D03B0CD31D62244300955575 /* Namespaces.swift in Sources */, D03B0CD31D62244300955575 /* Namespaces.swift in Sources */,
D01D6BF91E42A713006151C6 /* SearchStickers.swift in Sources */, D01D6BF91E42A713006151C6 /* SearchStickers.swift in Sources */,
D0FA8BB91E2240B4001E855B /* SecretChatIncomingDecryptedOperation.swift in Sources */, D0FA8BB91E2240B4001E855B /* SecretChatIncomingDecryptedOperation.swift in Sources */,
@ -1258,6 +1287,7 @@
D017495E1E118F790057C89A /* AccountStateManager.swift in Sources */, D017495E1E118F790057C89A /* AccountStateManager.swift in Sources */,
D0FA8BB61E223C16001E855B /* SecretApiLayer8.swift in Sources */, D0FA8BB61E223C16001E855B /* SecretApiLayer8.swift in Sources */,
D0B843C71DA7FF30005F29E1 /* NBPhoneNumberDefines.m in Sources */, D0B843C71DA7FF30005F29E1 /* NBPhoneNumberDefines.m in Sources */,
D049EAF51E44DF3300A2CD3A /* AccountState.swift in Sources */,
D03B0D5D1D631A6900955575 /* MultipartFetch.swift in Sources */, D03B0D5D1D631A6900955575 /* MultipartFetch.swift in Sources */,
D0BC38751E40A7F70044D6FE /* RemovePeerChat.swift in Sources */, D0BC38751E40A7F70044D6FE /* RemovePeerChat.swift in Sources */,
D0AB0B961D662F0B002C78E7 /* ManagedChatListHoles.swift in Sources */, D0AB0B961D662F0B002C78E7 /* ManagedChatListHoles.swift in Sources */,
@ -1308,6 +1338,7 @@
D0F7B1EA1E045C87007EB8A5 /* ChangePeerNotificationSettings.swift in Sources */, D0F7B1EA1E045C87007EB8A5 /* ChangePeerNotificationSettings.swift in Sources */,
D0B418A71D7E0592004562A4 /* Fetch.swift in Sources */, D0B418A71D7E0592004562A4 /* Fetch.swift in Sources */,
D02ABC7C1E30058F00CAE539 /* DeleteMessagesInteractively.swift in Sources */, D02ABC7C1E30058F00CAE539 /* DeleteMessagesInteractively.swift in Sources */,
D050F2111E48AB0600988324 /* InteractivePhoneFormatter.swift in Sources */,
D0B418B81D7E05A6004562A4 /* ContactManagement.swift in Sources */, D0B418B81D7E05A6004562A4 /* ContactManagement.swift in Sources */,
D0F7B1E91E045C87007EB8A5 /* PeerCommands.swift in Sources */, D0F7B1E91E045C87007EB8A5 /* PeerCommands.swift in Sources */,
D00D97C81E32901700E5C2B6 /* PeerInputActivity.swift in Sources */, D00D97C81E32901700E5C2B6 /* PeerInputActivity.swift in Sources */,
@ -1343,11 +1374,13 @@
D0B844481DAB91FD005F29E1 /* ManagedMessageHistoryHoles.swift in Sources */, D0B844481DAB91FD005F29E1 /* ManagedMessageHistoryHoles.swift in Sources */,
D0F3CC7B1DDE2859008148FA /* RequestEditMessage.swift in Sources */, D0F3CC7B1DDE2859008148FA /* RequestEditMessage.swift in Sources */,
D0B844441DAB91FD005F29E1 /* AccountSettings.swift in Sources */, D0B844441DAB91FD005F29E1 /* AccountSettings.swift in Sources */,
D049EAEC1E44B71B00A2CD3A /* RecentlySearchedPeerIds.swift in Sources */,
D0FA8B991E1E955C001E855B /* SecretChatOutgoingOperation.swift in Sources */, D0FA8B991E1E955C001E855B /* SecretChatOutgoingOperation.swift in Sources */,
D001F3F01E128A1C007A8C60 /* AccountStateManagementUtils.swift in Sources */, D001F3F01E128A1C007A8C60 /* AccountStateManagementUtils.swift in Sources */,
D0F3CC791DDE2859008148FA /* SearchMessages.swift in Sources */, D0F3CC791DDE2859008148FA /* SearchMessages.swift in Sources */,
D0B8442B1DAB91E0005F29E1 /* NBMetadataCore.m in Sources */, D0B8442B1DAB91E0005F29E1 /* NBMetadataCore.m in Sources */,
D00C7CD01E3628180080C3D5 /* UpdateCachedChannelParticipants.swift in Sources */, D00C7CD01E3628180080C3D5 /* UpdateCachedChannelParticipants.swift in Sources */,
D049EAE91E44B67100A2CD3A /* RecentPeerItem.swift in Sources */,
D001F3F31E128A1C007A8C60 /* UpdateMessageService.swift in Sources */, D001F3F31E128A1C007A8C60 /* UpdateMessageService.swift in Sources */,
D0B8442D1DAB91E0005F29E1 /* NBMetadataCoreTest.m in Sources */, D0B8442D1DAB91E0005F29E1 /* NBMetadataCoreTest.m in Sources */,
D0B844131DAB91CD005F29E1 /* StringFormat.swift in Sources */, D0B844131DAB91CD005F29E1 /* StringFormat.swift in Sources */,
@ -1362,6 +1395,7 @@
D073CE6E1DCBCF17007511FD /* ForwardSourceInfoAttribute.swift in Sources */, D073CE6E1DCBCF17007511FD /* ForwardSourceInfoAttribute.swift in Sources */,
D001F3E81E128A1C007A8C60 /* ChannelState.swift in Sources */, D001F3E81E128A1C007A8C60 /* ChannelState.swift in Sources */,
D0B844451DAB91FD005F29E1 /* AccountViewTracker.swift in Sources */, D0B844451DAB91FD005F29E1 /* AccountViewTracker.swift in Sources */,
D049EAD91E43DAD200A2CD3A /* ManagedRecentStickers.swift in Sources */,
D0B418A61D7E0592004562A4 /* CloudFileMediaResource.swift in Sources */, D0B418A61D7E0592004562A4 /* CloudFileMediaResource.swift in Sources */,
D073CEA51DCBF3F5007511FD /* StickerManagement.swift in Sources */, D073CEA51DCBF3F5007511FD /* StickerManagement.swift in Sources */,
D03C536D1DAD5CA9004C17B3 /* ApiGroupOrChannel.swift in Sources */, D03C536D1DAD5CA9004C17B3 /* ApiGroupOrChannel.swift in Sources */,
@ -1427,6 +1461,7 @@
D0448CA61E29215A005A61A7 /* MediaResourceApiUtils.swift in Sources */, D0448CA61E29215A005A61A7 /* MediaResourceApiUtils.swift in Sources */,
D001F3F11E128A1C007A8C60 /* SynchronizePeerReadState.swift in Sources */, D001F3F11E128A1C007A8C60 /* SynchronizePeerReadState.swift in Sources */,
D0F7B1E81E045C87007EB8A5 /* PeerParticipants.swift in Sources */, D0F7B1E81E045C87007EB8A5 /* PeerParticipants.swift in Sources */,
D049EAD61E43D98500A2CD3A /* RecentMediaItem.swift in Sources */,
D0B844331DAB91E0005F29E1 /* NBPhoneNumber.m in Sources */, D0B844331DAB91E0005F29E1 /* NBPhoneNumber.m in Sources */,
D001F3F51E128A1C007A8C60 /* PendingMessageManager.swift in Sources */, D001F3F51E128A1C007A8C60 /* PendingMessageManager.swift in Sources */,
D001F3F61E128A1C007A8C60 /* PendingMessageUploadedContent.swift in Sources */, D001F3F61E128A1C007A8C60 /* PendingMessageUploadedContent.swift in Sources */,
@ -1438,6 +1473,7 @@
D0B844301DAB91E0005F29E1 /* NBNumberFormat.m in Sources */, D0B844301DAB91E0005F29E1 /* NBNumberFormat.m in Sources */,
D001F3F71E128A1C007A8C60 /* ApplyUpdateMessage.swift in Sources */, D001F3F71E128A1C007A8C60 /* ApplyUpdateMessage.swift in Sources */,
D0B418971D7E0580004562A4 /* TelegramMediaImage.swift in Sources */, D0B418971D7E0580004562A4 /* TelegramMediaImage.swift in Sources */,
D049EAF61E44DF3300A2CD3A /* AccountState.swift in Sources */,
D0B844361DAB91E0005F29E1 /* NBPhoneNumberUtil.m in Sources */, D0B844361DAB91E0005F29E1 /* NBPhoneNumberUtil.m in Sources */,
D073CE6F1DCBCF17007511FD /* OutgoingMessageInfoAttribute.swift in Sources */, D073CE6F1DCBCF17007511FD /* OutgoingMessageInfoAttribute.swift in Sources */,
D0B844431DAB91FD005F29E1 /* Account.swift in Sources */, D0B844431DAB91FD005F29E1 /* Account.swift in Sources */,

View File

@ -12,7 +12,7 @@
<key>TelegramCoreMac.xcscheme</key> <key>TelegramCoreMac.xcscheme</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>7</integer> <integer>5</integer>
</dict> </dict>
</dict> </dict>
<key>SuppressBuildableAutocreation</key> <key>SuppressBuildableAutocreation</key>

View File

@ -45,32 +45,6 @@ public func ==(lhs: AccountState, rhs: AccountState) -> Bool {
return lhs.equalsTo(rhs) return lhs.equalsTo(rhs)
} }
public final class UnauthorizedAccountState: AccountState {
let masterDatacenterId: Int32
public required init(decoder: Decoder) {
self.masterDatacenterId = decoder.decodeInt32ForKey("masterDatacenterId")
super.init()
}
override public func encode(_ encoder: Encoder) {
encoder.encodeInt32(self.masterDatacenterId, forKey: "masterDatacenterId")
}
init(masterDatacenterId: Int32) {
self.masterDatacenterId = masterDatacenterId
super.init()
}
override func equalsTo(_ other: AccountState) -> Bool {
if let other = other as? UnauthorizedAccountState {
return self.masterDatacenterId == other.masterDatacenterId
} else {
return false
}
}
}
public class AuthorizedAccountState: AccountState { public class AuthorizedAccountState: AccountState {
public final class State: Coding, Equatable, CustomStringConvertible { public final class State: Coding, Equatable, CustomStringConvertible {
let pts: Int32 let pts: Int32
@ -177,21 +151,25 @@ public func generateAccountId() -> AccountId {
public class UnauthorizedAccount { public class UnauthorizedAccount {
public let id: AccountId public let id: AccountId
public let appGroupPath: String
public let basePath: String public let basePath: String
public let testingEnvironment: Bool public let testingEnvironment: Bool
public let postbox: Postbox public let postbox: Postbox
public let network: Network public let network: Network
public let logger: Logger
public var masterDatacenterId: Int32 { public var masterDatacenterId: Int32 {
return Int32(self.network.mtProto.datacenterId) return Int32(self.network.mtProto.datacenterId)
} }
init(id: AccountId, basePath: String, testingEnvironment: Bool, postbox: Postbox, network: Network) { init(id: AccountId, appGroupPath: String, basePath: String, logger: Logger, testingEnvironment: Bool, postbox: Postbox, network: Network) {
self.id = id self.id = id
self.appGroupPath = appGroupPath
self.basePath = basePath self.basePath = basePath
self.testingEnvironment = testingEnvironment self.testingEnvironment = testingEnvironment
self.postbox = postbox self.postbox = postbox
self.network = network self.network = network
self.logger = logger
network.shouldKeepConnection.set(.single(true)) network.shouldKeepConnection.set(.single(true))
} }
@ -210,7 +188,7 @@ public class UnauthorizedAccount {
return initializedNetwork(datacenterId: Int(masterDatacenterId), keychain: keychain, networkUsageInfoPath: accountNetworkUsageInfoPath(basePath: self.basePath), testingEnvironment: self.testingEnvironment) return initializedNetwork(datacenterId: Int(masterDatacenterId), keychain: keychain, networkUsageInfoPath: accountNetworkUsageInfoPath(basePath: self.basePath), testingEnvironment: self.testingEnvironment)
|> map { network in |> map { network in
return UnauthorizedAccount(id: self.id, basePath: self.basePath, testingEnvironment: self.testingEnvironment, postbox: self.postbox, network: network) return UnauthorizedAccount(id: self.id, appGroupPath: self.appGroupPath, basePath: self.basePath, logger: self.logger, testingEnvironment: self.testingEnvironment, postbox: self.postbox, network: network)
} }
} }
} }
@ -267,6 +245,8 @@ private var declaredEncodables: Void = {
declareEncodable(GlobalNotificationSettings.self, f: { GlobalNotificationSettings(decoder: $0) }) declareEncodable(GlobalNotificationSettings.self, f: { GlobalNotificationSettings(decoder: $0) })
declareEncodable(CloudChatRemoveChatOperation.self, f: { CloudChatRemoveChatOperation(decoder: $0) }) declareEncodable(CloudChatRemoveChatOperation.self, f: { CloudChatRemoveChatOperation(decoder: $0) })
declareEncodable(SynchronizePinnedChatsOperation.self, f: { SynchronizePinnedChatsOperation(decoder: $0) }) declareEncodable(SynchronizePinnedChatsOperation.self, f: { SynchronizePinnedChatsOperation(decoder: $0) })
declareEncodable(RecentMediaItem.self, f: { RecentMediaItem(decoder: $0) })
declareEncodable(RecentPeerItem.self, f: { RecentPeerItem(decoder: $0) })
return return
}() }()
@ -275,8 +255,13 @@ func accountNetworkUsageInfoPath(basePath: String) -> String {
return basePath + "/network-usage" return basePath + "/network-usage"
} }
public func accountWithId(_ id: AccountId, appGroupPath: String, testingEnvironment: Bool) -> Signal<Either<UnauthorizedAccount, Account>, NoError> { public enum AccountLogger {
return Signal<(String, Postbox, AccountState?), NoError> { subscriber in case named(String)
case instance(Logger)
}
public func accountWithId(_ id: AccountId, appGroupPath: String, logger: AccountLogger, testingEnvironment: Bool) -> Signal<Either<UnauthorizedAccount, Account>, NoError> {
return Signal<(String, Postbox, Coding?), NoError> { subscriber in
let _ = declaredEncodables let _ = declaredEncodables
let path = "\(appGroupPath)/account\(id.stringValue)" let path = "\(appGroupPath)/account\(id.stringValue)"
@ -289,8 +274,9 @@ public func accountWithId(_ id: AccountId, appGroupPath: String, testingEnvironm
let seedConfiguration = SeedConfiguration(initializeChatListWithHoles: [ChatListHole(index: MessageIndex(id: MessageId(peerId: PeerId(namespace: Namespaces.Peer.Empty, id: 0), namespace: Namespaces.Message.Cloud, id: 1), timestamp: 1))], initializeMessageNamespacesWithHoles: initializeMessageNamespacesWithHoles, existingMessageTags: allMessageTags) let seedConfiguration = SeedConfiguration(initializeChatListWithHoles: [ChatListHole(index: MessageIndex(id: MessageId(peerId: PeerId(namespace: Namespaces.Peer.Empty, id: 0), namespace: Namespaces.Message.Cloud, id: 1), timestamp: 1))], initializeMessageNamespacesWithHoles: initializeMessageNamespacesWithHoles, existingMessageTags: allMessageTags)
let postbox = Postbox(basePath: path + "/postbox", globalMessageIdsNamespace: Namespaces.Message.Cloud, seedConfiguration: seedConfiguration) let postbox = Postbox(basePath: path + "/postbox", globalMessageIdsNamespace: Namespaces.Message.Cloud, seedConfiguration: seedConfiguration)
return (postbox.state() |> take(1) |> map { accountState in return (postbox.stateView() |> take(1) |> map { view -> (String, Postbox, Coding?) in
return (path, postbox, accountState as? AccountState) let accountState = view.state
return (path, postbox, accountState)
}).start(next: { args in }).start(next: { args in
subscriber.putNext(args) subscriber.putNext(args)
subscriber.putCompletion() subscriber.putCompletion()
@ -304,17 +290,25 @@ public func accountWithId(_ id: AccountId, appGroupPath: String, testingEnvironm
postbox.removeKeychainEntryForKey(key) postbox.removeKeychainEntryForKey(key)
}) })
let concreteLogger: Logger
switch logger {
case let .named(name):
concreteLogger = Logger(basePath: basePath + "/" + name)
case let .instance(instance):
concreteLogger = instance
}
if let accountState = accountState { if let accountState = accountState {
switch accountState { switch accountState {
case let unauthorizedState as UnauthorizedAccountState: case let unauthorizedState as UnauthorizedAccountState:
return initializedNetwork(datacenterId: Int(unauthorizedState.masterDatacenterId), keychain: keychain, networkUsageInfoPath: accountNetworkUsageInfoPath(basePath: basePath), testingEnvironment: testingEnvironment) return initializedNetwork(datacenterId: Int(unauthorizedState.masterDatacenterId), keychain: keychain, networkUsageInfoPath: accountNetworkUsageInfoPath(basePath: basePath), testingEnvironment: testingEnvironment)
|> map { network -> Either<UnauthorizedAccount, Account> in |> map { network -> Either<UnauthorizedAccount, Account> in
.left(value: UnauthorizedAccount(id: id, basePath: basePath, testingEnvironment: testingEnvironment, postbox: postbox, network: network)) .left(value: UnauthorizedAccount(id: id, appGroupPath: appGroupPath, basePath: basePath, logger: concreteLogger, testingEnvironment: testingEnvironment, postbox: postbox, network: network))
} }
case let authorizedState as AuthorizedAccountState: case let authorizedState as AuthorizedAccountState:
return initializedNetwork(datacenterId: Int(authorizedState.masterDatacenterId), keychain: keychain, networkUsageInfoPath: accountNetworkUsageInfoPath(basePath: basePath), testingEnvironment: testingEnvironment) return initializedNetwork(datacenterId: Int(authorizedState.masterDatacenterId), keychain: keychain, networkUsageInfoPath: accountNetworkUsageInfoPath(basePath: basePath), testingEnvironment: testingEnvironment)
|> map { network -> Either<UnauthorizedAccount, Account> in |> map { network -> Either<UnauthorizedAccount, Account> in
return .right(value: Account(id: id, basePath: basePath, testingEnvironment: testingEnvironment, postbox: postbox, network: network, peerId: authorizedState.peerId)) return .right(value: Account(id: id, basePath: basePath, logger: concreteLogger, testingEnvironment: testingEnvironment, postbox: postbox, network: network, peerId: authorizedState.peerId))
} }
case _: case _:
assertionFailure("Unexpected accountState \(accountState)") assertionFailure("Unexpected accountState \(accountState)")
@ -323,7 +317,7 @@ public func accountWithId(_ id: AccountId, appGroupPath: String, testingEnvironm
return initializedNetwork(datacenterId: 2, keychain: keychain, networkUsageInfoPath: accountNetworkUsageInfoPath(basePath: basePath), testingEnvironment: testingEnvironment) return initializedNetwork(datacenterId: 2, keychain: keychain, networkUsageInfoPath: accountNetworkUsageInfoPath(basePath: basePath), testingEnvironment: testingEnvironment)
|> map { network -> Either<UnauthorizedAccount, Account> in |> map { network -> Either<UnauthorizedAccount, Account> in
return .left(value: UnauthorizedAccount(id: id, basePath: basePath, testingEnvironment: testingEnvironment, postbox: postbox, network: network)) return .left(value: UnauthorizedAccount(id: id, appGroupPath: appGroupPath, basePath: basePath, logger: concreteLogger, testingEnvironment: testingEnvironment, postbox: postbox, network: network))
} }
} }
} }
@ -393,6 +387,8 @@ public class Account {
public let network: Network public let network: Network
public let peerId: PeerId public let peerId: PeerId
public let logger: Logger
public private(set) var stateManager: AccountStateManager! public private(set) var stateManager: AccountStateManager!
public private(set) var viewTracker: AccountViewTracker! public private(set) var viewTracker: AccountViewTracker!
public private(set) var pendingMessageManager: PendingMessageManager! public private(set) var pendingMessageManager: PendingMessageManager!
@ -426,13 +422,14 @@ public class Account {
return self.networkStateValue.get() return self.networkStateValue.get()
} }
public init(id: AccountId, basePath: String, testingEnvironment: Bool, postbox: Postbox, network: Network, peerId: PeerId) { public init(id: AccountId, basePath: String, logger: Logger, testingEnvironment: Bool, postbox: Postbox, network: Network, peerId: PeerId) {
self.id = id self.id = id
self.basePath = basePath self.basePath = basePath
self.testingEnvironment = testingEnvironment self.testingEnvironment = testingEnvironment
self.postbox = postbox self.postbox = postbox
self.network = network self.network = network
self.peerId = peerId self.peerId = peerId
self.logger = logger
self.peerInputActivityManager = PeerInputActivityManager() self.peerInputActivityManager = PeerInputActivityManager()
self.stateManager = AccountStateManager(account: self, peerInputActivityManager: self.peerInputActivityManager) self.stateManager = AccountStateManager(account: self, peerInputActivityManager: self.peerInputActivityManager)
@ -471,8 +468,6 @@ public class Account {
let appVersionString = "\(Bundle.main.infoDictionary?["CFBundleShortVersionString"] ?? "") (\(Bundle.main.infoDictionary?["CFBundleVersion"] ?? ""))" let appVersionString = "\(Bundle.main.infoDictionary?["CFBundleShortVersionString"] ?? "") (\(Bundle.main.infoDictionary?["CFBundleVersion"] ?? ""))"
let langCode = NSLocale.preferredLanguages.first ?? "en"
#if os(macOS) #if os(macOS)
let pInfo = ProcessInfo.processInfo let pInfo = ProcessInfo.processInfo
let systemVersion = pInfo.operatingSystemVersionString let systemVersion = pInfo.operatingSystemVersionString
@ -506,8 +501,6 @@ public class Account {
let appVersionString = "\(Bundle.main.infoDictionary?["CFBundleShortVersionString"] ?? "") (\(Bundle.main.infoDictionary?["CFBundleVersion"] ?? ""))" let appVersionString = "\(Bundle.main.infoDictionary?["CFBundleShortVersionString"] ?? "") (\(Bundle.main.infoDictionary?["CFBundleVersion"] ?? ""))"
let langCode = NSLocale.preferredLanguages.first ?? "en"
#if os(macOS) #if os(macOS)
let pInfo = ProcessInfo.processInfo let pInfo = ProcessInfo.processInfo
let systemVersion = pInfo.operatingSystemVersionString let systemVersion = pInfo.operatingSystemVersionString
@ -567,6 +560,9 @@ public class Account {
self.managedOperationsDisposable.add(managedAutoremoveMessageOperations(postbox: self.postbox).start()) self.managedOperationsDisposable.add(managedAutoremoveMessageOperations(postbox: self.postbox).start())
self.managedOperationsDisposable.add(managedGlobalNotificationSettings(postbox: self.postbox, network: self.network).start()) self.managedOperationsDisposable.add(managedGlobalNotificationSettings(postbox: self.postbox, network: self.network).start())
self.managedOperationsDisposable.add(managedSynchronizePinnedChatsOperations(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start()) self.managedOperationsDisposable.add(managedSynchronizePinnedChatsOperations(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
self.managedOperationsDisposable.add(managedRecentStickers(postbox: self.postbox, network: self.network).start())
self.managedOperationsDisposable.add(managedRecentGifs(postbox: self.postbox, network: self.network).start())
self.managedOperationsDisposable.add(managedRecentlyUsedInlineBots(postbox: self.postbox, network: self.network).start())
let updatedPresence = self.shouldKeepOnlinePresence.get() let updatedPresence = self.shouldKeepOnlinePresence.get()
|> distinctUntilChanged |> distinctUntilChanged
@ -597,8 +593,6 @@ public class Account {
return combineLatest(pushStatusOnce, updatePresenceLocally) return combineLatest(pushStatusOnce, updatePresenceLocally)
|> mapToSignal { _ -> Signal<Void, NoError> in return .complete() } |> mapToSignal { _ -> Signal<Void, NoError> in return .complete() }
} }
return .complete()
} else { } else {
return .complete() return .complete()
} }
@ -616,7 +610,7 @@ public class Account {
self.managedOperationsDisposable.dispose() self.managedOperationsDisposable.dispose()
} }
public func currentNetworkStats() -> Signal<MTNetworkUsageManagerStats, NoError> { /*public func currentNetworkStats() -> Signal<MTNetworkUsageManagerStats, NoError> {
return Signal { subscriber in return Signal { subscriber in
let manager = MTNetworkUsageManager(info: MTNetworkUsageCalculationInfo(filePath: accountNetworkUsageInfoPath(basePath: self.basePath)))! let manager = MTNetworkUsageManager(info: MTNetworkUsageCalculationInfo(filePath: accountNetworkUsageInfoPath(basePath: self.basePath)))!
manager.currentStats().start(next: { next in manager.currentStats().start(next: { next in
@ -628,7 +622,7 @@ public class Account {
return EmptyDisposable return EmptyDisposable
} }
} }*/
public func peerInputActivities(peerId: PeerId) -> Signal<[(PeerId, PeerInputActivity)], NoError> { public func peerInputActivities(peerId: PeerId) -> Signal<[(PeerId, PeerInputActivity)], NoError> {
return self.peerInputActivityManager.activities(peerId: peerId) return self.peerInputActivityManager.activities(peerId: peerId)

View File

@ -0,0 +1,194 @@
import Foundation
import Postbox
private enum SentAuthorizationCodeTypeValue: Int32 {
case otherSession = 0
case sms = 1
case call = 2
case flashCall = 3
}
public enum SentAuthorizationCodeType: Coding, Equatable {
case otherSession(length: Int32)
case sms(length: Int32)
case call(length: Int32)
case flashCall(pattern: String)
public init(decoder: Decoder) {
switch decoder.decodeInt32ForKey("v") as Int32 {
case SentAuthorizationCodeTypeValue.otherSession.rawValue:
self = .otherSession(length: decoder.decodeInt32ForKey("l"))
case SentAuthorizationCodeTypeValue.sms.rawValue:
self = .sms(length: decoder.decodeInt32ForKey("l"))
case SentAuthorizationCodeTypeValue.call.rawValue:
self = .call(length: decoder.decodeInt32ForKey("l"))
case SentAuthorizationCodeTypeValue.flashCall.rawValue:
self = .flashCall(pattern: decoder.decodeStringForKey("p"))
default:
preconditionFailure()
}
}
public func encode(_ encoder: Encoder) {
switch self {
case let .otherSession(length):
encoder.encodeInt32(SentAuthorizationCodeTypeValue.otherSession.rawValue, forKey: "v")
encoder.encodeInt32(length, forKey: "l")
case let .sms(length):
encoder.encodeInt32(SentAuthorizationCodeTypeValue.sms.rawValue, forKey: "v")
encoder.encodeInt32(length, forKey: "l")
case let .call(length):
encoder.encodeInt32(SentAuthorizationCodeTypeValue.call.rawValue, forKey: "v")
encoder.encodeInt32(length, forKey: "l")
case let .flashCall(pattern):
encoder.encodeInt32(SentAuthorizationCodeTypeValue.flashCall.rawValue, forKey: "v")
encoder.encodeString(pattern, forKey: "p")
}
}
public static func ==(lhs: SentAuthorizationCodeType, rhs: SentAuthorizationCodeType) -> Bool {
switch lhs {
case let .otherSession(length):
if case .otherSession(length) = rhs {
return true
} else {
return false
}
case let .sms(length):
if case .sms(length) = rhs {
return true
} else {
return false
}
case let .call(length):
if case .call(length) = rhs {
return true
} else {
return false
}
case let .flashCall(pattern):
if case .flashCall(pattern) = rhs {
return true
} else {
return false
}
}
}
}
public enum AuthorizationCodeNextType: Int32 {
case sms = 0
case call = 1
case flashCall = 2
}
private enum UnauthorizedAccountStateContentsValue: Int32 {
case empty = 0
case phoneEntry = 1
case confirmationCodeEntry = 2
case passwordEntry = 3
}
public enum UnauthorizedAccountStateContents: Coding {
case empty
case phoneEntry(countryCode: Int32, number: String)
case confirmationCodeEntry(number: String, type: SentAuthorizationCodeType, hash: String, timeout: Int32?, nextType: AuthorizationCodeNextType?)
case passwordEntry(hint: String)
public init(decoder: Decoder) {
switch decoder.decodeInt32ForKey("v") as Int32 {
case UnauthorizedAccountStateContentsValue.empty.rawValue:
self = .empty
case UnauthorizedAccountStateContentsValue.phoneEntry.rawValue:
self = .phoneEntry(countryCode: decoder.decodeInt32ForKey("cc"), number: decoder.decodeStringForKey("n"))
case UnauthorizedAccountStateContentsValue.confirmationCodeEntry.rawValue:
var nextType: AuthorizationCodeNextType?
if let value = decoder.decodeInt32ForKey("nt") as Int32? {
nextType = AuthorizationCodeNextType(rawValue: value)
}
self = .confirmationCodeEntry(number: decoder.decodeStringForKey("num"), type: decoder.decodeObjectForKey("t", decoder: { SentAuthorizationCodeType(decoder: $0) }) as! SentAuthorizationCodeType, hash: decoder.decodeStringForKey("h"), timeout: decoder.decodeInt32ForKey("tm"), nextType: nextType)
case UnauthorizedAccountStateContentsValue.passwordEntry.rawValue:
self = .passwordEntry(hint: decoder.decodeStringForKey("h"))
default:
assertionFailure()
self = .empty
}
}
public func encode(_ encoder: Encoder) {
switch self {
case .empty:
encoder.encodeInt32(UnauthorizedAccountStateContentsValue.empty.rawValue, forKey: "v")
case let .phoneEntry(countryCode, number):
encoder.encodeInt32(UnauthorizedAccountStateContentsValue.phoneEntry.rawValue, forKey: "v")
encoder.encodeInt32(countryCode, forKey: "cc")
encoder.encodeString(number, forKey: "n")
case let .confirmationCodeEntry(number, type, hash, timeout, nextType):
encoder.encodeInt32(UnauthorizedAccountStateContentsValue.confirmationCodeEntry.rawValue, forKey: "v")
encoder.encodeString(number, forKey: "num")
encoder.encodeObject(type, forKey: "t")
encoder.encodeString(hash, forKey: "h")
if let timeout = timeout {
encoder.encodeInt32(timeout, forKey: "tm")
} else {
encoder.encodeNil(forKey: "tm")
}
if let nextType = nextType {
encoder.encodeInt32(nextType.rawValue, forKey: "nt")
} else {
encoder.encodeNil(forKey: "nt")
}
case let .passwordEntry(hint):
encoder.encodeInt32(UnauthorizedAccountStateContentsValue.passwordEntry.rawValue, forKey: "v")
encoder.encodeString(hint, forKey: "h")
}
}
}
public final class UnauthorizedAccountState: Coding {
public let masterDatacenterId: Int32
public let contents: UnauthorizedAccountStateContents
public init(masterDatacenterId: Int32, contents: UnauthorizedAccountStateContents) {
self.masterDatacenterId = masterDatacenterId
self.contents = contents
}
public init(decoder: Decoder) {
self.masterDatacenterId = decoder.decodeInt32ForKey("dc")
self.contents = decoder.decodeObjectForKey("c", decoder: { UnauthorizedAccountStateContents(decoder: $0) }) as! UnauthorizedAccountStateContents
}
public func encode(_ encoder: Encoder) {
encoder.encodeInt32(self.masterDatacenterId, forKey: "dc")
encoder.encodeObject(self.contents, forKey: "c")
}
}
public extension SentAuthorizationCodeType {
init(apiType: Api.auth.SentCodeType) {
switch apiType {
case let .sentCodeTypeApp(length):
self = .otherSession(length: length)
case let .sentCodeTypeSms(length):
self = .sms(length: length)
case let .sentCodeTypeCall(length):
self = .call(length: length)
case let .sentCodeTypeFlashCall(pattern):
self = .flashCall(pattern: pattern)
}
}
}
public extension AuthorizationCodeNextType {
init(apiType: Api.auth.CodeType) {
switch apiType {
case .codeTypeSms:
self = .sms
case .codeTypeCall:
self = .call
case .codeTypeFlashCall:
self = .flashCall
}
}
}

View File

@ -1003,8 +1003,6 @@ private func resolveMissingPeerNotificationSettings(account: Account, state: Acc
return updatedState return updatedState
} }
} }
return .single(state)
} }
private func pollChannel(_ account: Account, peer: Peer, state: AccountMutableState) -> Signal<AccountMutableState, NoError> { private func pollChannel(_ account: Account, peer: Peer, state: AccountMutableState) -> Signal<AccountMutableState, NoError> {
@ -1135,7 +1133,7 @@ private func verifyTransaction(_ modifier: Modifier, finalState: AccountMutableS
} }
if !previousStateMatches { if !previousStateMatches {
trace("State", what: ".UpdateState previous state \(previousState) doesn't match current state \(currentState)") trace("State", what: ".UpdateState previous state \(previousState) doesn't match current state \(String(describing: currentState))")
failed = true failed = true
} }
} }
@ -1152,7 +1150,7 @@ private func verifyTransaction(_ modifier: Modifier, finalState: AccountMutableS
previousStateMatches = true previousStateMatches = true
} }
if !previousStateMatches { if !previousStateMatches {
trace("State", what: ".UpdateChannelState for \(peerId), previous state \(previousState) doesn't match current state \(currentState)") trace("State", what: ".UpdateChannelState for \(peerId), previous state \(previousState) doesn't match current state \(String(describing: currentState))")
failed = true failed = true
} }
} }

View File

@ -198,18 +198,17 @@ public final class AccountStateManager {
self.currentIsUpdatingValue = true self.currentIsUpdatingValue = true
let account = self.account let account = self.account
let mediaBox = account.postbox.mediaBox let mediaBox = account.postbox.mediaBox
let queue = self.queue let signal = account.postbox.stateView()
let signal = account.postbox.state() |> mapToSignal { view -> Signal<AuthorizedAccountState, NoError> in
|> filter { state in if let state = view.state as? AuthorizedAccountState {
if let _ = state as? AuthorizedAccountState { return .single(state)
return true
} else { } else {
return false return .complete()
} }
} }
|> take(1) |> take(1)
|> mapToSignal { state -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in |> mapToSignal { state -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in
if let authorizedState = (state as! AuthorizedAccountState).state { if let authorizedState = state.state {
let request = account.network.request(Api.functions.updates.getDifference(flags: 0, pts: authorizedState.pts, ptsTotalLimit: nil, date: authorizedState.date, qts: authorizedState.qts)) let request = account.network.request(Api.functions.updates.getDifference(flags: 0, pts: authorizedState.pts, ptsTotalLimit: nil, date: authorizedState.date, qts: authorizedState.qts))
|> retryRequest |> retryRequest
return request |> mapToSignal { difference -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in return request |> mapToSignal { difference -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in
@ -255,9 +254,9 @@ public final class AccountStateManager {
} }
} }
|> deliverOn(self.queue) |> deliverOn(self.queue)
signal.start(next: { [weak self] difference, finalState in let _ = signal.start(next: { [weak self] difference, finalState in
if let strongSelf = self { if let strongSelf = self {
if case let .pollDifference = strongSelf.operations.removeFirst() { if case .pollDifference = strongSelf.operations.removeFirst() {
let events: AccountFinalStateEvents let events: AccountFinalStateEvents
if let finalState = finalState { if let finalState = finalState {
events = currentEvents.union(with: AccountFinalStateEvents(state: finalState)) events = currentEvents.union(with: AccountFinalStateEvents(state: finalState))
@ -365,7 +364,7 @@ public final class AccountStateManager {
} }
} }
} }
(signal |> deliverOn(self.queue)).start(error: { _ in let _ = (signal |> deliverOn(self.queue)).start(error: { _ in
completed() completed()
}, completed: { }, completed: {
completed() completed()
@ -441,10 +440,10 @@ public final class AccountStateManager {
return messages return messages
} }
(signal |> deliverOn(self.queue)).start(next: { [weak self] messages in let _ = (signal |> deliverOn(self.queue)).start(next: { [weak self] messages in
if let strongSelf = self { if let strongSelf = self {
for message in messages { for message in messages {
print("notify: \(messageMainPeer(message)?.displayTitle): \(message.id)") print("notify: \(String(describing: messageMainPeer(message)?.displayTitle)): \(message.id)")
} }
strongSelf.notificationMessagesPipe.putNext(messages) strongSelf.notificationMessagesPipe.putNext(messages)
@ -458,7 +457,7 @@ public final class AccountStateManager {
if self.operations.count > 1 { if self.operations.count > 1 {
self.operations.removeFirst() self.operations.removeFirst()
for (id, f) in preSubscribers { for (id, f) in preSubscribers {
self.addPollCompletion(f, id: id) let _ = self.addPollCompletion(f, id: id)
} }
self.startFirstOperation() self.startFirstOperation()
} else { } else {
@ -477,7 +476,7 @@ public final class AccountStateManager {
} }
} else { } else {
for (id, f) in subscribers { for (id, f) in subscribers {
strongSelf.addPollCompletion(f, id: id) let _ = strongSelf.addPollCompletion(f, id: id)
} }
} }
strongSelf.startFirstOperation() strongSelf.startFirstOperation()
@ -486,7 +485,7 @@ public final class AccountStateManager {
} }
} }
} }
(signal |> deliverOn(self.queue)).start(error: { _ in let _ = (signal |> deliverOn(self.queue)).start(error: { _ in
completed() completed()
}, completed: { }, completed: {
completed() completed()

View File

@ -47,6 +47,8 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes
} }
} }
var sentStickers: [TelegramMediaFile] = []
modifier.updateMessage(message.id, update: { currentMessage in modifier.updateMessage(message.id, update: { currentMessage in
let updatedId: MessageId let updatedId: MessageId
if let messageId = messageId { if let messageId = messageId {
@ -97,11 +99,20 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes
applyMediaResourceChanges(from: fromMedia, to: toMedia, postbox: postbox) applyMediaResourceChanges(from: fromMedia, to: toMedia, postbox: postbox)
} }
for media in media {
if let file = media as? TelegramMediaFile, file.isSticker {
sentStickers.append(file)
}
}
return StoreMessage(id: updatedId, globallyUniqueId: nil, timestamp: updatedTimestamp ?? currentMessage.timestamp, flags: [], tags: tagsForStoreMessage(media), forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: text, attributes: attributes, media: media) return StoreMessage(id: updatedId, globallyUniqueId: nil, timestamp: updatedTimestamp ?? currentMessage.timestamp, flags: [], tags: tagsForStoreMessage(media), forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: text, attributes: attributes, media: media)
}) })
if let updatedTimestamp = updatedTimestamp { if let updatedTimestamp = updatedTimestamp {
modifier.offsetPendingMessagesTimestamps(lowerBound: message.id, timestamp: updatedTimestamp) modifier.offsetPendingMessagesTimestamps(lowerBound: message.id, timestamp: updatedTimestamp)
} }
for file in sentStickers {
modifier.addOrMoveToFirstPositionOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudRecentStickers, item: OrderedItemListEntry(id: RecentMediaItemId(file.fileId).rawValue, contents: RecentMediaItem(file)), removeTailIfCountExceeds: 20)
}
stateManager.addUpdates(result) stateManager.addUpdates(result)
} }
} }

View File

@ -0,0 +1,15 @@
import Foundation
import TelegramCorePrivateModule
public final class InteractivePhoneFormatter {
private let formatter = NBAsYouTypeFormatter(regionCode: "US")!
public init() {
}
public func updateText(_ text: String) -> (String?, String) {
self.formatter.clear()
let string = self.formatter.inputString(text)
return (self.formatter.regionPrefix, string ?? "")
}
}

View File

@ -29,14 +29,13 @@ public func trace(_ domain: String, what: @autoclosure() -> String) {
var curTime = timeval() var curTime = timeval()
gettimeofday(&curTime, nil) gettimeofday(&curTime, nil)
let seconds = curTime.tv_sec
let milliseconds = curTime.tv_usec / 1000 let milliseconds = curTime.tv_usec / 1000
queue.async { queue.async {
let result = String(format: "[%@] %d-%d-%d %02d:%02d:%03d %@", arguments: [domain, Int(timeinfo.tm_year) + 1900, Int(timeinfo.tm_mon + 1), Int(timeinfo.tm_yday), Int(timeinfo.tm_hour), Int(timeinfo.tm_min), Int(milliseconds), string]) let result = String(format: "[%@] %d-%d-%d %02d:%02d:%02d.%03d %@", arguments: [domain, Int(timeinfo.tm_year) + 1900, Int(timeinfo.tm_mon + 1), Int(timeinfo.tm_yday), Int(timeinfo.tm_hour), Int(timeinfo.tm_min), Int(seconds), Int(milliseconds), string])
//#if (arch(i386) || arch(x86_64))
print(result) print(result)
//#endif
} }
} }
@ -44,10 +43,111 @@ public func registerLoggingFunctions() {
setBridgingTraceFunction({ domain, what in setBridgingTraceFunction({ domain, what in
if let what = what { if let what = what {
if let domain = domain { if let domain = domain {
trace(domain as String, what: what as String) trace(domain, what: what as String)
} else { } else {
trace(what as String) trace("", what: what as String)
} }
} }
}) })
} }
public final class Logger {
private let queue = DispatchQueue(label: "org.telegram.Telegram.log", qos: .utility)
private let maxLength: Int = 512 * 1024
private let maxFiles: Int = 20
private let basePath: String
private var file: (Int32, Int)?
init(basePath: String) {
self.basePath = basePath
}
func log(_ tag: String, _ what: @autoclosure () -> String) {
let string = what()
var rawTime = time_t()
time(&rawTime)
var timeinfo = tm()
localtime_r(&rawTime, &timeinfo)
var curTime = timeval()
gettimeofday(&curTime, nil)
let seconds = curTime.tv_sec
let milliseconds = curTime.tv_usec / 1000
let content = String(format: "[%@] %d-%d-%d %02d:%02d:%02d.%03d %@", arguments: [tag, Int(timeinfo.tm_year) + 1900, Int(timeinfo.tm_mon + 1), Int(timeinfo.tm_yday), Int(timeinfo.tm_hour), Int(timeinfo.tm_min), Int(seconds), Int(milliseconds), string])
self.queue.async {
var fd: Int32?
var createNew = false
if let (file, length) = self.file {
if length < self.maxLength {
close(file)
createNew = true
} else {
fd = file
}
} else {
let _ = try? FileManager.default.createDirectory(atPath: self.basePath, withIntermediateDirectories: true, attributes: nil)
if let files = try? FileManager.default.contentsOfDirectory(at: URL(fileURLWithPath: self.basePath), includingPropertiesForKeys: [URLResourceKey.creationDateKey], options: []) {
var minCreationDate: (Date, URL)?
var maxCreationDate: (Date, URL)?
var count = 0
for url in files {
if url.lastPathComponent.hasPrefix("log-") {
if let values = try? url.resourceValues(forKeys: Set([URLResourceKey.creationDateKey])), let creationDate = values.creationDate {
count += 1
if minCreationDate == nil || minCreationDate!.0 > creationDate {
minCreationDate = (creationDate, url)
}
if maxCreationDate == nil || maxCreationDate!.0 < creationDate {
maxCreationDate = (creationDate, url)
}
}
}
}
if let (_, url) = minCreationDate, count >= self.maxFiles {
let _ = try? FileManager.default.removeItem(at: url)
}
if let (_, url) = maxCreationDate {
var value = stat()
if stat(url.path, &value) == 0 && Int(value.st_size) < self.maxLength {
let handle = open(url.path, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR)
if handle >= 0 {
fd = handle
self.file = (handle, Int(value.st_size))
}
} else {
createNew = true
}
} else {
createNew = true
}
}
}
if createNew {
let path = self.basePath + "/log-\(Date()).txt"
let handle = open(path, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR)
if handle >= 0 {
fd = handle
self.file = (handle, 0)
}
}
if let fd = fd {
if let data = content.data(using: .utf8) {
data.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) -> Void in
write(fd, bytes, data.count)
}
if let file = self.file {
self.file = (file.0, file.1 + data.count)
} else {
assertionFailure()
}
}
}
}
}
}

View File

@ -0,0 +1,81 @@
import Foundation
#if os(macOS)
import PostboxMac
import SwiftSignalKitMac
#else
import Postbox
import SwiftSignalKit
#endif
private func hashForIdsReverse(_ ids: [Int64]) -> Int32 {
var acc: UInt32 = 0
for id in ids {
let low = UInt32(UInt64(bitPattern: id) & UInt64(0xffffffff))
let high = UInt32((UInt64(bitPattern: id) >> 32) & UInt64(0xffffffff))
acc = (acc &* 20261) &+ high
acc = (acc &* 20261) &+ low
}
return Int32(bitPattern: acc % UInt32(0x7FFFFFFF))
}
private func managedRecentMedia(postbox: Postbox, network: Network, collectionId: Int32, fetch: @escaping (Int32) -> Signal<[OrderedItemListEntry]?, NoError>) -> Signal<Void, NoError> {
return postbox.modify { modifier -> Signal<Void, NoError> in
let itemIds = modifier.getOrderedListItemIds(collectionId: collectionId).map {
RecentMediaItemId($0).mediaId.id
}
return fetch(hashForIdsReverse(itemIds))
|> mapToSignal { items in
if let items = items {
return postbox.modify { modifier -> Void in
modifier.replaceOrderedItemListItems(collectionId: collectionId, items: items)
}
} else {
return .complete()
}
}
} |> switchToLatest
}
func managedRecentStickers(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
return managedRecentMedia(postbox: postbox, network: network, collectionId: Namespaces.OrderedItemList.CloudRecentStickers, fetch: { hash in
return network.request(Api.functions.messages.getRecentStickers(flags: 0, hash: hash))
|> retryRequest
|> mapToSignal { result -> Signal<[OrderedItemListEntry]?, NoError> in
switch result {
case .recentStickersNotModified:
return .single(nil)
case let .recentStickers(_, stickers):
var items: [OrderedItemListEntry] = []
for sticker in stickers {
if let file = telegramMediaFileFromApiDocument(sticker), let id = file.id {
items.append(OrderedItemListEntry(id: RecentMediaItemId(id).rawValue, contents: RecentMediaItem(file)))
}
}
return .single(items)
}
}
})
}
func managedRecentGifs(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
return managedRecentMedia(postbox: postbox, network: network, collectionId: Namespaces.OrderedItemList.CloudRecentGifs, fetch: { hash in
return network.request(Api.functions.messages.getSavedGifs(hash: hash))
|> retryRequest
|> mapToSignal { result -> Signal<[OrderedItemListEntry]?, NoError> in
switch result {
case .savedGifsNotModified:
return .single(nil)
case let .savedGifs(_, gifs):
var items: [OrderedItemListEntry] = []
for gif in gifs {
if let file = telegramMediaFileFromApiDocument(gif), let id = file.id {
items.append(OrderedItemListEntry(id: RecentMediaItemId(id).rawValue, contents: RecentMediaItem(file)))
}
}
return .single(items)
}
}
})
}

View File

@ -37,8 +37,14 @@ public struct Namespaces {
public struct ItemCollection { public struct ItemCollection {
public static let CloudStickerPacks: Int32 = 0 public static let CloudStickerPacks: Int32 = 0
public static let CloudMaskPacks: Int32 = 1 public static let CloudMaskPacks: Int32 = 1
public static let CloudRecentGifs: Int32 = 2 public static let CloudRecentStickers: Int32 = 2
}
public struct OrderedItemList {
public static let CloudRecentStickers: Int32 = 0 public static let CloudRecentStickers: Int32 = 0
public static let CloudRecentGifs: Int32 = 1
public static let RecentlySearchedPeerIds: Int32 = 2
public static let CloudRecentInlineBots: Int32 = 3
} }
struct CachedItemCollection { struct CachedItemCollection {

View File

@ -130,7 +130,7 @@ func initializedNetwork(datacenterId: Int, keychain: Keychain, networkUsageInfoP
} }
context.keychain = keychain context.keychain = keychain
let mtProto = MTProto(context: context, datacenterId: datacenterId, usageCalculationInfo: networkUsageInfoPath == nil ? nil : MTNetworkUsageCalculationInfo(filePath: networkUsageInfoPath))! let mtProto = MTProto(context: context, datacenterId: datacenterId, usageCalculationInfo: nil)!
let connectionStatus = Promise<ConnectionStatus>(.WaitingForNetwork) let connectionStatus = Promise<ConnectionStatus>(.WaitingForNetwork)

View File

@ -42,7 +42,7 @@ public extension Peer {
switch self { switch self {
case let user as TelegramUser: case let user as TelegramUser:
return user.username return user.username
case let group as TelegramGroup: case let _ as TelegramGroup:
return nil return nil
case let channel as TelegramChannel: case let channel as TelegramChannel:
return channel.username return channel.username

View File

@ -162,7 +162,7 @@ public final class PendingMessageManager {
assert(strongSelf.queue.isCurrent()) assert(strongSelf.queue.isCurrent())
for message in messages { for message in messages {
guard let peer = message.peers[message.id.peerId], let messageContext = strongSelf.messageContexts[message.id] else { guard let messageContext = strongSelf.messageContexts[message.id] else {
continue continue
} }
@ -237,7 +237,7 @@ public final class PendingMessageManager {
} }
var layer: SecretChatLayer? var layer: SecretChatLayer?
var state = modifier.getPeerChatState(message.id.peerId) as? SecretChatState let state = modifier.getPeerChatState(message.id.peerId) as? SecretChatState
if let state = state { if let state = state {
switch state.embeddedState { switch state.embeddedState {
case .terminated, .handshake: case .terminated, .handshake:
@ -303,7 +303,6 @@ public final class PendingMessageManager {
} else if let peer = modifier.getPeer(message.id.peerId), let inputPeer = apiInputPeer(peer) { } else if let peer = modifier.getPeer(message.id.peerId), let inputPeer = apiInputPeer(peer) {
var uniqueId: Int64 = 0 var uniqueId: Int64 = 0
var forwardSourceInfoAttribute: ForwardSourceInfoAttribute? var forwardSourceInfoAttribute: ForwardSourceInfoAttribute?
var outgoingChatContextResultAttribute: OutgoingChatContextResultMessageAttribute?
var replyMessageId: Int32? var replyMessageId: Int32?
for attribute in message.attributes { for attribute in message.attributes {
@ -313,13 +312,11 @@ public final class PendingMessageManager {
uniqueId = outgoingInfo.uniqueId uniqueId = outgoingInfo.uniqueId
} else if let attribute = attribute as? ForwardSourceInfoAttribute { } else if let attribute = attribute as? ForwardSourceInfoAttribute {
forwardSourceInfoAttribute = attribute forwardSourceInfoAttribute = attribute
} else if let attribute = attribute as? OutgoingChatContextResultMessageAttribute {
outgoingChatContextResultAttribute = attribute
} }
} }
var flags: Int32 = 0 var flags: Int32 = 0
if let replyMessageId = replyMessageId { if let _ = replyMessageId {
flags |= Int32(1 << 0) flags |= Int32(1 << 0)
} }
@ -327,7 +324,7 @@ public final class PendingMessageManager {
let sendMessageRequest: Signal<Api.Updates, NoError> let sendMessageRequest: Signal<Api.Updates, NoError>
switch content { switch content {
case let .text(text): case .text:
sendMessageRequest = network.request(Api.functions.messages.sendMessage(flags: flags, peer: inputPeer, replyToMsgId: replyMessageId, message: message.text, randomId: uniqueId, replyMarkup: nil, entities: nil), tag: dependencyTag) sendMessageRequest = network.request(Api.functions.messages.sendMessage(flags: flags, peer: inputPeer, replyToMsgId: replyMessageId, message: message.text, randomId: uniqueId, replyMarkup: nil, entities: nil), tag: dependencyTag)
|> mapError { _ -> NoError in |> mapError { _ -> NoError in
return NoError() return NoError()
@ -384,9 +381,6 @@ public final class PendingMessageManager {
} }
private func applySentMessage(postbox: Postbox, stateManager: AccountStateManager, message: Message, result: Api.Updates) -> Signal<Void, NoError> { private func applySentMessage(postbox: Postbox, stateManager: AccountStateManager, message: Message, result: Api.Updates) -> Signal<Void, NoError> {
let messageId = result.rawMessageIds.first
let apiMessage = result.messages.first
return applyUpdateMessage(postbox: postbox, stateManager: stateManager, message: message, result: result) |> afterDisposed { [weak self] in return applyUpdateMessage(postbox: postbox, stateManager: stateManager, message: message, result: result) |> afterDisposed { [weak self] in
if let strongSelf = self { if let strongSelf = self {
strongSelf.queue.async { strongSelf.queue.async {

View File

@ -0,0 +1,46 @@
import Foundation
#if os(macOS)
import PostboxMac
#else
import Postbox
#endif
public struct RecentMediaItemId {
public let rawValue: MemoryBuffer
public let mediaId: MediaId
init(_ rawValue: MemoryBuffer) {
self.rawValue = rawValue
assert(rawValue.length == 4 + 8)
var mediaIdNamespace: Int32 = 0
var mediaIdId: Int64 = 0
memcpy(&mediaIdNamespace, rawValue.memory, 4)
memcpy(&mediaIdId, rawValue.memory.advanced(by: 4), 8)
self.mediaId = MediaId(namespace: mediaIdNamespace, id: mediaIdId)
}
init(_ mediaId: MediaId) {
self.mediaId = mediaId
var mediaIdNamespace: Int32 = mediaId.namespace
var mediaIdId: Int64 = mediaId.id
self.rawValue = MemoryBuffer(memory: malloc(4 + 8)!, capacity: 4 + 8, length: 4 + 8, freeWhenDone: true)
memcpy(self.rawValue.memory, &mediaIdNamespace, 4)
memcpy(self.rawValue.memory.advanced(by: 4), &mediaIdId, 8)
}
}
public final class RecentMediaItem: OrderedItemListEntryContents {
public let media: Media
init(_ media: Media) {
self.media = media
}
public init(decoder: Decoder) {
self.media = decoder.decodeObjectForKey("m") as! Media
}
public func encode(_ encoder: Encoder) {
encoder.encodeObject(self.media, forKey: "m")
}
}

View File

@ -0,0 +1,37 @@
import Foundation
#if os(macOS)
import PostboxMac
#else
import Postbox
#endif
public struct RecentPeerItemId {
public let rawValue: MemoryBuffer
public let peerId: PeerId
init(_ rawValue: MemoryBuffer) {
self.rawValue = rawValue
assert(rawValue.length == 8)
var idValue: Int64 = 0
memcpy(&idValue, rawValue.memory, 8)
self.peerId = PeerId(idValue)
}
init(_ peerId: PeerId) {
self.peerId = peerId
var idValue: Int64 = peerId.toInt64()
self.rawValue = MemoryBuffer(memory: malloc(8)!, capacity: 8, length: 8, freeWhenDone: true)
memcpy(self.rawValue.memory, &idValue, 8)
}
}
public final class RecentPeerItem: OrderedItemListEntryContents {
init() {
}
public init(decoder: Decoder) {
}
public func encode(_ encoder: Encoder) {
}
}

View File

@ -47,3 +47,67 @@ public func recentPeers(account: Account) -> Signal<[Peer], NoError> {
} }
return cachedPeers |> then(updatedRemotePeers) |> filter({ !$0.isEmpty }) return cachedPeers |> then(updatedRemotePeers) |> filter({ !$0.isEmpty })
} }
public func managedRecentlyUsedInlineBots(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
let remotePeers = network.request(Api.functions.contacts.getTopPeers(flags: 1 << 2, offset: 0, limit: 16, hash: 0))
|> retryRequest
|> map { result -> ([Peer], [PeerId: PeerPresence])? in
switch result {
case let .topPeers(_, _, users):
var peers: [Peer] = []
var peerPresences: [PeerId: PeerPresence] = [:]
for user in users {
let telegramUser = TelegramUser(user: user)
peers.append(telegramUser)
if let presence = TelegramUserPresence(apiUser: user) {
peerPresences[telegramUser.id] = presence
}
}
return (peers, peerPresences)
case .topPeersNotModified:
break
}
return ([], [:])
}
let updatedRemotePeers = remotePeers
|> mapToSignal { peersAndPresences -> Signal<Void, NoError> in
if let (peers, peerPresences) = peersAndPresences {
return postbox.modify { modifier -> Void in
updatePeers(modifier: modifier, peers: peers, update: { return $1 })
modifier.updatePeerPresences(peerPresences)
modifier.replaceOrderedItemListItems(collectionId: Namespaces.OrderedItemList.CloudRecentInlineBots, items: peers.map { peer in
return OrderedItemListEntry(id: RecentPeerItemId(peer.id).rawValue, contents: RecentPeerItem())
})
}
} else {
return .complete()
}
}
return updatedRemotePeers
}
public func addRecentlyUsedInlineBot(postbox: Postbox, peerId: PeerId) -> Signal<Void, NoError> {
return postbox.modify { modifier -> Void in
modifier.addOrMoveToFirstPositionOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudRecentInlineBots, item: OrderedItemListEntry(id: RecentPeerItemId(peerId).rawValue, contents: RecentPeerItem()), removeTailIfCountExceeds: 20)
}
}
public func recentlyUsedInlineBots(postbox: Postbox) -> Signal<[Peer], NoError> {
return postbox.orderedItemListView(collectionId: Namespaces.OrderedItemList.CloudRecentInlineBots)
|> take(1)
|> mapToSignal { view -> Signal<[Peer], NoError> in
return postbox.modify { modifier -> [Peer] in
var peers: [Peer] = []
for item in view.items {
let peerId = RecentPeerItemId(item.id).peerId
if let peer = modifier.getPeer(peerId) {
peers.append(peer)
}
}
return peers
}
}
}

View File

@ -0,0 +1,31 @@
import Foundation
#if os(macOS)
import PostboxMac
import SwiftSignalKitMac
#else
import Postbox
import SwiftSignalKit
#endif
public func addRecentlySearchedPeer(postbox: Postbox, peerId: PeerId) -> Signal<Void, NoError> {
return postbox.modify { modifier -> Void in
modifier.addOrMoveToFirstPositionOrderedItemListItem(collectionId: Namespaces.OrderedItemList.RecentlySearchedPeerIds, item: OrderedItemListEntry(id: RecentPeerItemId(peerId).rawValue, contents: RecentPeerItem()), removeTailIfCountExceeds: 20)
}
}
public func recentlySearchedPeers(postbox: Postbox) -> Signal<[Peer], NoError> {
return postbox.orderedItemListView(collectionId: Namespaces.OrderedItemList.RecentlySearchedPeerIds)
|> take(1)
|> mapToSignal { view -> Signal<[Peer], NoError> in
return postbox.modify { modifier -> [Peer] in
var peers: [Peer] = []
for item in view.items {
let peerId = RecentPeerItemId(item.id).peerId
if let peer = modifier.getPeer(peerId) {
peers.append(peer)
}
}
return peers
}
}
}

View File

@ -12,14 +12,14 @@ private func hashForInfos(_ infos: [StickerPackCollectionInfo]) -> Int32 {
var acc: UInt32 = 0 var acc: UInt32 = 0
for info in infos { for info in infos {
acc = (acc &* 20261) &+ UInt32(bitPattern: info.hash) acc = UInt32(bitPattern: Int32(bitPattern: acc &* UInt32(20261)) &+ info.hash)
} }
return Int32(bitPattern: acc % UInt32(0x7FFFFFFF)) return Int32(bitPattern: acc % 0x7FFFFFFF)
} }
func manageStickerPacks(network: Network, postbox: Postbox) -> Signal<Void, NoError> { func manageStickerPacks(network: Network, postbox: Postbox) -> Signal<Void, NoError> {
let currentHash = postbox.itemCollectionsView(namespaces: [Namespaces.ItemCollection.CloudStickerPacks], aroundIndex: nil, count: 1) let currentHash = postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [Namespaces.ItemCollection.CloudStickerPacks], aroundIndex: nil, count: 1)
|> take(1) |> take(1)
|> map { view -> Int32 in |> map { view -> Int32 in
return hashForInfos(view.collectionInfos.map({ $0.1 as! StickerPackCollectionInfo })) return hashForInfos(view.collectionInfos.map({ $0.1 as! StickerPackCollectionInfo }))
@ -28,7 +28,7 @@ func manageStickerPacks(network: Network, postbox: Postbox) -> Signal<Void, NoEr
let remoteStickerPacks = currentHash let remoteStickerPacks = currentHash
|> mapToSignal { hash -> Signal<Void, NoError> in |> mapToSignal { hash -> Signal<Void, NoError> in
if hash != 0 { if hash != 0 {
//return .never() return .never()
} }
return network.request(Api.functions.messages.getAllStickers(hash: hash)) return network.request(Api.functions.messages.getAllStickers(hash: hash))

View File

@ -5,8 +5,6 @@ import Foundation
import Postbox import Postbox
#endif #endif
//stickerSet#cd303b41 flags:# installed:flags.0?true archived:flags.1?true official:flags.2?true masks:flags.3?true id:long access_hash:long title:string short_name:string count:int hash:int = StickerSet;
public final class StickerPackCollectionInfo: ItemCollectionInfo, Equatable { public final class StickerPackCollectionInfo: ItemCollectionInfo, Equatable {
public let id: ItemCollectionId public let id: ItemCollectionId
public let accessHash: Int64 public let accessHash: Int64
@ -14,7 +12,7 @@ public final class StickerPackCollectionInfo: ItemCollectionInfo, Equatable {
public let shortName: String public let shortName: String
public let hash: Int32 public let hash: Int32
init(id: ItemCollectionId, accessHash: Int64, title: String, shortName: String, hash: Int32) { public init(id: ItemCollectionId, accessHash: Int64, title: String, shortName: String, hash: Int32) {
self.id = id self.id = id
self.accessHash = accessHash self.accessHash = accessHash
self.title = title self.title = title
@ -48,7 +46,7 @@ public final class StickerPackItem: ItemCollectionItem, Equatable {
public let file: TelegramMediaFile public let file: TelegramMediaFile
public var indexKeys: [MemoryBuffer] public var indexKeys: [MemoryBuffer]
init(index: ItemCollectionItemIndex, file: TelegramMediaFile, indexKeys: [MemoryBuffer]) { public init(index: ItemCollectionItemIndex, file: TelegramMediaFile, indexKeys: [MemoryBuffer]) {
self.index = index self.index = index
self.file = file self.file = file
self.indexKeys = indexKeys self.indexKeys = indexKeys

View File

@ -1,6 +1,7 @@
module TelegramCorePrivateModule { module TelegramCorePrivateModule {
header "../../third-party/libphonenumber-iOS/NBPhoneNumber.h" header "../../third-party/libphonenumber-iOS/NBPhoneNumber.h"
header "../../third-party/libphonenumber-iOS/NBPhoneNumberUtil.h" header "../../third-party/libphonenumber-iOS/NBPhoneNumberUtil.h"
header "../../third-party/libphonenumber-iOS/NBAsYouTypeFormatter.h"
header "../NetworkLogging.h" header "../NetworkLogging.h"
header "../TelegramCoreIncludes.h" header "../TelegramCoreIncludes.h"
} }

View File

@ -126,7 +126,7 @@ public enum UserPresenceStatus: Comparable, Coding {
public final class TelegramUserPresence: PeerPresence { public final class TelegramUserPresence: PeerPresence {
public let status: UserPresenceStatus public let status: UserPresenceStatus
init(status: UserPresenceStatus) { public init(status: UserPresenceStatus) {
self.status = status self.status = status
} }

View File

@ -50,6 +50,8 @@ public func updatePeers(modifier: Modifier, peers: [Peer], update: (Peer?, Peer)
updatedInclusion = .ifHasMessages updatedInclusion = .ifHasMessages
} }
} }
case .left:
updatedInclusion = .never
default: default:
if currentInclusion == .notSpecified { if currentInclusion == .notSpecified {
updatedInclusion = .never updatedInclusion = .never

View File

@ -33,4 +33,6 @@
@property (nonatomic, assign, readonly) BOOL isSuccessfulFormatting; @property (nonatomic, assign, readonly) BOOL isSuccessfulFormatting;
@property (nonatomic, strong, readonly) NSString *regionPrefix;
@end @end

View File

@ -1290,4 +1290,8 @@
return self.currentOutput_; return self.currentOutput_;
} }
- (NSString *)regionPrefix {
return self.prefixBeforeNationalNumber_;
}
@end @end