mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-25 09:32:46 +00:00
no message
This commit is contained in:
parent
935a534de5
commit
ee7d69819c
@ -234,6 +234,8 @@
|
|||||||
D0528E661E65C82400E2FEF5 /* UpdateContactName.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0528E641E65C82400E2FEF5 /* UpdateContactName.swift */; };
|
D0528E661E65C82400E2FEF5 /* UpdateContactName.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0528E641E65C82400E2FEF5 /* UpdateContactName.swift */; };
|
||||||
D0528E6A1E65DD2100E2FEF5 /* WebpagePreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0528E691E65DD2100E2FEF5 /* WebpagePreview.swift */; };
|
D0528E6A1E65DD2100E2FEF5 /* WebpagePreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0528E691E65DD2100E2FEF5 /* WebpagePreview.swift */; };
|
||||||
D0528E6B1E65DD2100E2FEF5 /* WebpagePreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0528E691E65DD2100E2FEF5 /* WebpagePreview.swift */; };
|
D0528E6B1E65DD2100E2FEF5 /* WebpagePreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0528E691E65DD2100E2FEF5 /* WebpagePreview.swift */; };
|
||||||
|
D05452071E7B5093006EEF19 /* LoadedStickerpack.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05452061E7B5093006EEF19 /* LoadedStickerpack.swift */; };
|
||||||
|
D05452081E7B5093006EEF19 /* LoadedStickerpack.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05452061E7B5093006EEF19 /* LoadedStickerpack.swift */; };
|
||||||
D0561DE31E5737FC00E6B9E9 /* UpdatePeerInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0561DE21E5737FC00E6B9E9 /* UpdatePeerInfo.swift */; };
|
D0561DE31E5737FC00E6B9E9 /* UpdatePeerInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0561DE21E5737FC00E6B9E9 /* UpdatePeerInfo.swift */; };
|
||||||
D0561DE41E5737FC00E6B9E9 /* UpdatePeerInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0561DE21E5737FC00E6B9E9 /* UpdatePeerInfo.swift */; };
|
D0561DE41E5737FC00E6B9E9 /* UpdatePeerInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0561DE21E5737FC00E6B9E9 /* UpdatePeerInfo.swift */; };
|
||||||
D0561DEA1E5754FA00E6B9E9 /* ChannelAdmins.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0561DE91E5754FA00E6B9E9 /* ChannelAdmins.swift */; };
|
D0561DEA1E5754FA00E6B9E9 /* ChannelAdmins.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0561DE91E5754FA00E6B9E9 /* ChannelAdmins.swift */; };
|
||||||
@ -389,11 +391,15 @@
|
|||||||
D0BC38791E40BAF20044D6FE /* SynchronizePinnedChatsOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BC38781E40BAF20044D6FE /* SynchronizePinnedChatsOperation.swift */; };
|
D0BC38791E40BAF20044D6FE /* SynchronizePinnedChatsOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BC38781E40BAF20044D6FE /* SynchronizePinnedChatsOperation.swift */; };
|
||||||
D0BC387B1E40D2880044D6FE /* TogglePeerChatPinned.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BC387A1E40D2880044D6FE /* TogglePeerChatPinned.swift */; };
|
D0BC387B1E40D2880044D6FE /* TogglePeerChatPinned.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BC387A1E40D2880044D6FE /* TogglePeerChatPinned.swift */; };
|
||||||
D0BC387C1E40D2880044D6FE /* TogglePeerChatPinned.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BC387A1E40D2880044D6FE /* TogglePeerChatPinned.swift */; };
|
D0BC387C1E40D2880044D6FE /* TogglePeerChatPinned.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BC387A1E40D2880044D6FE /* TogglePeerChatPinned.swift */; };
|
||||||
|
D0BE383E1E7C5995000079AF /* MediaPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE383D1E7C5995000079AF /* MediaPool.swift */; };
|
||||||
|
D0BE383F1E7C5995000079AF /* MediaPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE383D1E7C5995000079AF /* MediaPool.swift */; };
|
||||||
D0BEAF5D1E54941B00BD963D /* Authorization.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEAF5C1E54941B00BD963D /* Authorization.swift */; };
|
D0BEAF5D1E54941B00BD963D /* Authorization.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEAF5C1E54941B00BD963D /* Authorization.swift */; };
|
||||||
D0BEAF5E1E54941B00BD963D /* Authorization.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEAF5C1E54941B00BD963D /* Authorization.swift */; };
|
D0BEAF5E1E54941B00BD963D /* Authorization.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEAF5C1E54941B00BD963D /* Authorization.swift */; };
|
||||||
D0BEAF601E54ACF900BD963D /* AccountManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEAF5F1E54ACF900BD963D /* AccountManager.swift */; };
|
D0BEAF601E54ACF900BD963D /* AccountManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEAF5F1E54ACF900BD963D /* AccountManager.swift */; };
|
||||||
D0BEAF611E54ACF900BD963D /* AccountManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEAF5F1E54ACF900BD963D /* AccountManager.swift */; };
|
D0BEAF611E54ACF900BD963D /* AccountManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEAF5F1E54ACF900BD963D /* AccountManager.swift */; };
|
||||||
D0CAF2EA1D75EC600011F558 /* MtProtoKitDynamic.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0CAF2E91D75EC600011F558 /* MtProtoKitDynamic.framework */; };
|
D0CAF2EA1D75EC600011F558 /* MtProtoKitDynamic.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0CAF2E91D75EC600011F558 /* MtProtoKitDynamic.framework */; };
|
||||||
|
D0D748021E7AE98B00F4B1F6 /* StickerPackInteractiveOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D748011E7AE98B00F4B1F6 /* StickerPackInteractiveOperations.swift */; };
|
||||||
|
D0D748031E7AE98B00F4B1F6 /* StickerPackInteractiveOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D748011E7AE98B00F4B1F6 /* StickerPackInteractiveOperations.swift */; };
|
||||||
D0DC354E1DE368F7000195EB /* RequestChatContextResults.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DC354D1DE368F7000195EB /* RequestChatContextResults.swift */; };
|
D0DC354E1DE368F7000195EB /* RequestChatContextResults.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DC354D1DE368F7000195EB /* RequestChatContextResults.swift */; };
|
||||||
D0DC35501DE36900000195EB /* ChatContextResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DC354F1DE36900000195EB /* ChatContextResult.swift */; };
|
D0DC35501DE36900000195EB /* ChatContextResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DC354F1DE36900000195EB /* ChatContextResult.swift */; };
|
||||||
D0DC35511DE36908000195EB /* RequestChatContextResults.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DC354D1DE368F7000195EB /* RequestChatContextResults.swift */; };
|
D0DC35511DE36908000195EB /* RequestChatContextResults.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DC354D1DE368F7000195EB /* RequestChatContextResults.swift */; };
|
||||||
@ -595,6 +601,7 @@
|
|||||||
D0528E5F1E65B94E00E2FEF5 /* SingleMessageView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleMessageView.swift; sourceTree = "<group>"; };
|
D0528E5F1E65B94E00E2FEF5 /* SingleMessageView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleMessageView.swift; sourceTree = "<group>"; };
|
||||||
D0528E641E65C82400E2FEF5 /* UpdateContactName.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdateContactName.swift; sourceTree = "<group>"; };
|
D0528E641E65C82400E2FEF5 /* UpdateContactName.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdateContactName.swift; sourceTree = "<group>"; };
|
||||||
D0528E691E65DD2100E2FEF5 /* WebpagePreview.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebpagePreview.swift; sourceTree = "<group>"; };
|
D0528E691E65DD2100E2FEF5 /* WebpagePreview.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebpagePreview.swift; sourceTree = "<group>"; };
|
||||||
|
D05452061E7B5093006EEF19 /* LoadedStickerpack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadedStickerpack.swift; sourceTree = "<group>"; };
|
||||||
D0561DE21E5737FC00E6B9E9 /* UpdatePeerInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdatePeerInfo.swift; sourceTree = "<group>"; };
|
D0561DE21E5737FC00E6B9E9 /* UpdatePeerInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdatePeerInfo.swift; sourceTree = "<group>"; };
|
||||||
D0561DE91E5754FA00E6B9E9 /* ChannelAdmins.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChannelAdmins.swift; sourceTree = "<group>"; };
|
D0561DE91E5754FA00E6B9E9 /* ChannelAdmins.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChannelAdmins.swift; sourceTree = "<group>"; };
|
||||||
D05A32E01E6F0982002760B4 /* UpdatedAccountPrivacySettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdatedAccountPrivacySettings.swift; sourceTree = "<group>"; };
|
D05A32E01E6F0982002760B4 /* UpdatedAccountPrivacySettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdatedAccountPrivacySettings.swift; sourceTree = "<group>"; };
|
||||||
@ -686,9 +693,11 @@
|
|||||||
D0BC38761E40BAAA0044D6FE /* ManagedSynchronizePinnedChatsOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedSynchronizePinnedChatsOperations.swift; sourceTree = "<group>"; };
|
D0BC38761E40BAAA0044D6FE /* ManagedSynchronizePinnedChatsOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedSynchronizePinnedChatsOperations.swift; sourceTree = "<group>"; };
|
||||||
D0BC38781E40BAF20044D6FE /* SynchronizePinnedChatsOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronizePinnedChatsOperation.swift; sourceTree = "<group>"; };
|
D0BC38781E40BAF20044D6FE /* SynchronizePinnedChatsOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronizePinnedChatsOperation.swift; sourceTree = "<group>"; };
|
||||||
D0BC387A1E40D2880044D6FE /* TogglePeerChatPinned.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TogglePeerChatPinned.swift; sourceTree = "<group>"; };
|
D0BC387A1E40D2880044D6FE /* TogglePeerChatPinned.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TogglePeerChatPinned.swift; sourceTree = "<group>"; };
|
||||||
|
D0BE383D1E7C5995000079AF /* MediaPool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaPool.swift; sourceTree = "<group>"; };
|
||||||
D0BEAF5C1E54941B00BD963D /* Authorization.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Authorization.swift; sourceTree = "<group>"; };
|
D0BEAF5C1E54941B00BD963D /* Authorization.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Authorization.swift; sourceTree = "<group>"; };
|
||||||
D0BEAF5F1E54ACF900BD963D /* AccountManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountManager.swift; sourceTree = "<group>"; };
|
D0BEAF5F1E54ACF900BD963D /* AccountManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountManager.swift; sourceTree = "<group>"; };
|
||||||
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 = "<group>"; };
|
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 = "<group>"; };
|
||||||
|
D0D748011E7AE98B00F4B1F6 /* StickerPackInteractiveOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StickerPackInteractiveOperations.swift; sourceTree = "<group>"; };
|
||||||
D0DC354D1DE368F7000195EB /* RequestChatContextResults.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestChatContextResults.swift; sourceTree = "<group>"; };
|
D0DC354D1DE368F7000195EB /* RequestChatContextResults.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestChatContextResults.swift; sourceTree = "<group>"; };
|
||||||
D0DC354F1DE36900000195EB /* ChatContextResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatContextResult.swift; sourceTree = "<group>"; };
|
D0DC354F1DE36900000195EB /* ChatContextResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatContextResult.swift; sourceTree = "<group>"; };
|
||||||
D0DF0C891D819C7E008AEB01 /* JoinChannel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JoinChannel.swift; sourceTree = "<group>"; };
|
D0DF0C891D819C7E008AEB01 /* JoinChannel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JoinChannel.swift; sourceTree = "<group>"; };
|
||||||
@ -786,6 +795,8 @@
|
|||||||
D01D6BF81E42A713006151C6 /* SearchStickers.swift */,
|
D01D6BF81E42A713006151C6 /* SearchStickers.swift */,
|
||||||
D049EAD71E43DAD200A2CD3A /* ManagedRecentStickers.swift */,
|
D049EAD71E43DAD200A2CD3A /* ManagedRecentStickers.swift */,
|
||||||
C251D7421E65E50500283EDE /* StickerSetInstallation.swift */,
|
C251D7421E65E50500283EDE /* StickerSetInstallation.swift */,
|
||||||
|
D0D748011E7AE98B00F4B1F6 /* StickerPackInteractiveOperations.swift */,
|
||||||
|
D05452061E7B5093006EEF19 /* LoadedStickerpack.swift */,
|
||||||
);
|
);
|
||||||
name = "Sticker Management";
|
name = "Sticker Management";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1001,6 +1012,7 @@
|
|||||||
D03B0D571D631A6900955575 /* MultipartFetch.swift */,
|
D03B0D571D631A6900955575 /* MultipartFetch.swift */,
|
||||||
D03C53761DAFF20F004C17B3 /* MultipartUpload.swift */,
|
D03C53761DAFF20F004C17B3 /* MultipartUpload.swift */,
|
||||||
D03B0D581D631A6900955575 /* Network.swift */,
|
D03B0D581D631A6900955575 /* Network.swift */,
|
||||||
|
D0BE383D1E7C5995000079AF /* MediaPool.swift */,
|
||||||
D03B0D591D631A6900955575 /* Serialization.swift */,
|
D03B0D591D631A6900955575 /* Serialization.swift */,
|
||||||
);
|
);
|
||||||
name = Network;
|
name = Network;
|
||||||
@ -1440,6 +1452,7 @@
|
|||||||
D08774FE1E3E3A3500A97350 /* GlobalNotificationSettings.swift in Sources */,
|
D08774FE1E3E3A3500A97350 /* GlobalNotificationSettings.swift in Sources */,
|
||||||
D00C7CCF1E3628180080C3D5 /* UpdateCachedChannelParticipants.swift in Sources */,
|
D00C7CCF1E3628180080C3D5 /* UpdateCachedChannelParticipants.swift in Sources */,
|
||||||
D03B0CB91D62233400955575 /* Either.swift in Sources */,
|
D03B0CB91D62233400955575 /* Either.swift in Sources */,
|
||||||
|
D0D748021E7AE98B00F4B1F6 /* StickerPackInteractiveOperations.swift in Sources */,
|
||||||
D03B0CBD1D62234300955575 /* Regex.swift in Sources */,
|
D03B0CBD1D62234300955575 /* Regex.swift in Sources */,
|
||||||
D03B0D661D631A8B00955575 /* AccountSettings.swift in Sources */,
|
D03B0D661D631A8B00955575 /* AccountSettings.swift in Sources */,
|
||||||
D0B843B91DA7FF30005F29E1 /* NBMetadataCoreTest.m in Sources */,
|
D0B843B91DA7FF30005F29E1 /* NBMetadataCoreTest.m in Sources */,
|
||||||
@ -1514,6 +1527,7 @@
|
|||||||
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 */,
|
D050F2101E48AB0600988324 /* InteractivePhoneFormatter.swift in Sources */,
|
||||||
|
D0BE383E1E7C5995000079AF /* MediaPool.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 */,
|
||||||
@ -1535,6 +1549,7 @@
|
|||||||
D0FA8BB91E2240B4001E855B /* SecretChatIncomingDecryptedOperation.swift in Sources */,
|
D0FA8BB91E2240B4001E855B /* SecretChatIncomingDecryptedOperation.swift in Sources */,
|
||||||
D0561DE31E5737FC00E6B9E9 /* UpdatePeerInfo.swift in Sources */,
|
D0561DE31E5737FC00E6B9E9 /* UpdatePeerInfo.swift in Sources */,
|
||||||
D0DF0C8A1D819C7E008AEB01 /* JoinChannel.swift in Sources */,
|
D0DF0C8A1D819C7E008AEB01 /* JoinChannel.swift in Sources */,
|
||||||
|
D05452071E7B5093006EEF19 /* LoadedStickerpack.swift in Sources */,
|
||||||
D0F7AB2F1DCF507E009AD9A1 /* ReplyMarkupMessageAttribute.swift in Sources */,
|
D0F7AB2F1DCF507E009AD9A1 /* ReplyMarkupMessageAttribute.swift in Sources */,
|
||||||
D0B843971DA7FBBC005F29E1 /* ChangePeerNotificationSettings.swift in Sources */,
|
D0B843971DA7FBBC005F29E1 /* ChangePeerNotificationSettings.swift in Sources */,
|
||||||
D0448CA21E291B14005A61A7 /* FetchSecretFileResource.swift in Sources */,
|
D0448CA21E291B14005A61A7 /* FetchSecretFileResource.swift in Sources */,
|
||||||
@ -1659,6 +1674,7 @@
|
|||||||
D050F26E1E4A5B6D00988324 /* RemovePeerChat.swift in Sources */,
|
D050F26E1E4A5B6D00988324 /* RemovePeerChat.swift in Sources */,
|
||||||
D0613FD81E606B3B00202CDB /* ConvertGroupToSupergroup.swift in Sources */,
|
D0613FD81E606B3B00202CDB /* ConvertGroupToSupergroup.swift in Sources */,
|
||||||
D01D6BFA1E42A718006151C6 /* SearchStickers.swift in Sources */,
|
D01D6BFA1E42A718006151C6 /* SearchStickers.swift in Sources */,
|
||||||
|
D0D748031E7AE98B00F4B1F6 /* StickerPackInteractiveOperations.swift in Sources */,
|
||||||
C2A315C01E2E776A00D89000 /* RequestStartBot.swift in Sources */,
|
C2A315C01E2E776A00D89000 /* RequestStartBot.swift in Sources */,
|
||||||
D0F7B1EA1E045C87007EB8A5 /* ChangePeerNotificationSettings.swift in Sources */,
|
D0F7B1EA1E045C87007EB8A5 /* ChangePeerNotificationSettings.swift in Sources */,
|
||||||
D0B418A71D7E0592004562A4 /* Fetch.swift in Sources */,
|
D0B418A71D7E0592004562A4 /* Fetch.swift in Sources */,
|
||||||
@ -1733,6 +1749,7 @@
|
|||||||
D001F3E81E128A1C007A8C60 /* ChannelState.swift in Sources */,
|
D001F3E81E128A1C007A8C60 /* ChannelState.swift in Sources */,
|
||||||
C2366C8A1E4F40480097CCFF /* SupportPeerId.swift in Sources */,
|
C2366C8A1E4F40480097CCFF /* SupportPeerId.swift in Sources */,
|
||||||
D0B844451DAB91FD005F29E1 /* AccountViewTracker.swift in Sources */,
|
D0B844451DAB91FD005F29E1 /* AccountViewTracker.swift in Sources */,
|
||||||
|
D0BE383F1E7C5995000079AF /* MediaPool.swift in Sources */,
|
||||||
D050F2601E4A5AD500988324 /* AutoremoveTimeoutMessageAttribute.swift in Sources */,
|
D050F2601E4A5AD500988324 /* AutoremoveTimeoutMessageAttribute.swift in Sources */,
|
||||||
D049EAD91E43DAD200A2CD3A /* ManagedRecentStickers.swift in Sources */,
|
D049EAD91E43DAD200A2CD3A /* ManagedRecentStickers.swift in Sources */,
|
||||||
D0B418A61D7E0592004562A4 /* CloudFileMediaResource.swift in Sources */,
|
D0B418A61D7E0592004562A4 /* CloudFileMediaResource.swift in Sources */,
|
||||||
@ -1754,6 +1771,7 @@
|
|||||||
D0B8444B1DAB91FD005F29E1 /* ManagedSynchronizePeerReadStates.swift in Sources */,
|
D0B8444B1DAB91FD005F29E1 /* ManagedSynchronizePeerReadStates.swift in Sources */,
|
||||||
D073CE6C1DCBCF17007511FD /* TextEntitiesMessageAttribute.swift in Sources */,
|
D073CE6C1DCBCF17007511FD /* TextEntitiesMessageAttribute.swift in Sources */,
|
||||||
D03C53751DAD5CA9004C17B3 /* TelegramUserPresence.swift in Sources */,
|
D03C53751DAD5CA9004C17B3 /* TelegramUserPresence.swift in Sources */,
|
||||||
|
D05452081E7B5093006EEF19 /* LoadedStickerpack.swift in Sources */,
|
||||||
D0561DE41E5737FC00E6B9E9 /* UpdatePeerInfo.swift in Sources */,
|
D0561DE41E5737FC00E6B9E9 /* UpdatePeerInfo.swift in Sources */,
|
||||||
D0DC35521DE36908000195EB /* ChatContextResult.swift in Sources */,
|
D0DC35521DE36908000195EB /* ChatContextResult.swift in Sources */,
|
||||||
D0F7AB301DCF507E009AD9A1 /* ReplyMarkupMessageAttribute.swift in Sources */,
|
D0F7AB301DCF507E009AD9A1 /* ReplyMarkupMessageAttribute.swift in Sources */,
|
||||||
|
|||||||
@ -99,6 +99,7 @@ public func ==(lhs: AuthorizedAccountState.State, rhs: AuthorizedAccountState.St
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class UnauthorizedAccount {
|
public class UnauthorizedAccount {
|
||||||
|
public let apiId: Int32
|
||||||
public let id: AccountRecordId
|
public let id: AccountRecordId
|
||||||
public let appGroupPath: String
|
public let appGroupPath: String
|
||||||
public let basePath: String
|
public let basePath: String
|
||||||
@ -112,7 +113,8 @@ public class UnauthorizedAccount {
|
|||||||
|
|
||||||
public let shouldBeServiceTaskMaster = Promise<AccountServiceTaskMasterMode>()
|
public let shouldBeServiceTaskMaster = Promise<AccountServiceTaskMasterMode>()
|
||||||
|
|
||||||
init(id: AccountRecordId, appGroupPath: String, basePath: String, testingEnvironment: Bool, postbox: Postbox, network: Network, shouldKeepAutoConnection: Bool = true) {
|
init(apiId: Int32, id: AccountRecordId, appGroupPath: String, basePath: String, testingEnvironment: Bool, postbox: Postbox, network: Network, shouldKeepAutoConnection: Bool = true) {
|
||||||
|
self.apiId = apiId
|
||||||
self.id = id
|
self.id = id
|
||||||
self.appGroupPath = appGroupPath
|
self.appGroupPath = appGroupPath
|
||||||
self.basePath = basePath
|
self.basePath = basePath
|
||||||
@ -143,9 +145,9 @@ public class UnauthorizedAccount {
|
|||||||
postbox.removeKeychainEntryForKey(key)
|
postbox.removeKeychainEntryForKey(key)
|
||||||
})
|
})
|
||||||
|
|
||||||
return initializedNetwork(datacenterId: Int(masterDatacenterId), keychain: keychain, networkUsageInfoPath: accountNetworkUsageInfoPath(basePath: self.basePath), testingEnvironment: self.testingEnvironment)
|
return initializedNetwork(apiId: self.apiId, datacenterId: Int(masterDatacenterId), keychain: keychain, networkUsageInfoPath: accountNetworkUsageInfoPath(basePath: self.basePath), testingEnvironment: self.testingEnvironment)
|
||||||
|> map { network in
|
|> map { network in
|
||||||
let updated = UnauthorizedAccount(id: self.id, appGroupPath: self.appGroupPath, basePath: self.basePath, testingEnvironment: self.testingEnvironment, postbox: self.postbox, network: network)
|
let updated = UnauthorizedAccount(apiId: self.apiId, id: self.id, appGroupPath: self.appGroupPath, basePath: self.basePath, testingEnvironment: self.testingEnvironment, postbox: self.postbox, network: network)
|
||||||
updated.shouldBeServiceTaskMaster.set(self.shouldBeServiceTaskMaster.get())
|
updated.shouldBeServiceTaskMaster.set(self.shouldBeServiceTaskMaster.get())
|
||||||
return updated
|
return updated
|
||||||
}
|
}
|
||||||
@ -212,6 +214,7 @@ private var declaredEncodables: Void = {
|
|||||||
declareEncodable(OutgoingContentInfoMessageAttribute.self, f: { OutgoingContentInfoMessageAttribute(decoder: $0) })
|
declareEncodable(OutgoingContentInfoMessageAttribute.self, f: { OutgoingContentInfoMessageAttribute(decoder: $0) })
|
||||||
declareEncodable(ConsumableContentMessageAttribute.self, f: { ConsumableContentMessageAttribute(decoder: $0) })
|
declareEncodable(ConsumableContentMessageAttribute.self, f: { ConsumableContentMessageAttribute(decoder: $0) })
|
||||||
declareEncodable(TelegramMediaGame.self, f: { TelegramMediaGame(decoder: $0) })
|
declareEncodable(TelegramMediaGame.self, f: { TelegramMediaGame(decoder: $0) })
|
||||||
|
declareEncodable(SynchronizeInstalledStickerPacksOperation.self, f: { SynchronizeInstalledStickerPacksOperation(decoder: $0) })
|
||||||
|
|
||||||
return
|
return
|
||||||
}()
|
}()
|
||||||
@ -224,7 +227,7 @@ private func accountRecordIdPathName(_ id: AccountRecordId) -> String {
|
|||||||
return "account-\(UInt64(bitPattern: id.int64))"
|
return "account-\(UInt64(bitPattern: id.int64))"
|
||||||
}
|
}
|
||||||
|
|
||||||
public func accountWithId(_ id: AccountRecordId, appGroupPath: String, testingEnvironment: Bool, shouldKeepAutoConnection: Bool = true) -> Signal<Either<UnauthorizedAccount, Account>, NoError> {
|
public func accountWithId(apiId: Int32, id: AccountRecordId, appGroupPath: String, testingEnvironment: Bool, shouldKeepAutoConnection: Bool = true) -> Signal<Either<UnauthorizedAccount, Account>, NoError> {
|
||||||
return Signal<(String, Postbox, Coding?), NoError> { subscriber in
|
return Signal<(String, Postbox, Coding?), NoError> { subscriber in
|
||||||
let _ = declaredEncodables
|
let _ = declaredEncodables
|
||||||
|
|
||||||
@ -258,12 +261,12 @@ public func accountWithId(_ id: AccountRecordId, appGroupPath: String, testingEn
|
|||||||
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(apiId: apiId, 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, appGroupPath: appGroupPath, basePath: basePath, testingEnvironment: testingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection))
|
.left(value: UnauthorizedAccount(apiId: apiId, id: id, appGroupPath: appGroupPath, basePath: basePath, testingEnvironment: testingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection))
|
||||||
}
|
}
|
||||||
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(apiId: apiId, 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, testingEnvironment: testingEnvironment, postbox: postbox, network: network, peerId: authorizedState.peerId))
|
||||||
}
|
}
|
||||||
@ -272,9 +275,9 @@ public func accountWithId(_ id: AccountRecordId, appGroupPath: String, testingEn
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return initializedNetwork(datacenterId: 2, keychain: keychain, networkUsageInfoPath: accountNetworkUsageInfoPath(basePath: basePath), testingEnvironment: testingEnvironment)
|
return initializedNetwork(apiId: apiId, 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, appGroupPath: appGroupPath, basePath: basePath, testingEnvironment: testingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection))
|
return .left(value: UnauthorizedAccount(apiId: apiId, id: id, appGroupPath: appGroupPath, basePath: basePath, testingEnvironment: testingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -457,7 +460,7 @@ public class Account {
|
|||||||
appSandbox = .boolTrue
|
appSandbox = .boolTrue
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return network.request(Api.functions.account.registerDevice(tokenType: 1, token: tokenString, deviceModel: "iPhone Simulator", systemVersion: systemVersion, appVersion: appVersionString, appSandbox: appSandbox))
|
return network.request(Api.functions.account.registerDevice(tokenType: 1, token: tokenString, deviceModel: "iPhone", systemVersion: systemVersion, appVersion: appVersionString, appSandbox: appSandbox))
|
||||||
|> retryRequest
|
|> retryRequest
|
||||||
|> mapToSignal { _ -> Signal<Void, NoError> in
|
|> mapToSignal { _ -> Signal<Void, NoError> in
|
||||||
return .complete()
|
return .complete()
|
||||||
@ -490,7 +493,7 @@ public class Account {
|
|||||||
appSandbox = .boolTrue
|
appSandbox = .boolTrue
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return network.request(Api.functions.account.registerDevice(tokenType: 9, token: tokenString, deviceModel: "iPhone Simulator", systemVersion: systemVersion, appVersion: appVersionString, appSandbox: appSandbox))
|
return network.request(Api.functions.account.registerDevice(tokenType: 9, token: tokenString, deviceModel: "iPhone", systemVersion: systemVersion, appVersion: appVersionString, appSandbox: appSandbox))
|
||||||
|> retryRequest
|
|> retryRequest
|
||||||
|> mapToSignal { _ -> Signal<Void, NoError> in
|
|> mapToSignal { _ -> Signal<Void, NoError> in
|
||||||
return .complete()
|
return .complete()
|
||||||
@ -537,6 +540,8 @@ 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(managedSynchronizeInstalledStickerPacksOperations(postbox: self.postbox, network: self.network, stateManager: self.stateManager, namespace: .stickers).start())
|
||||||
|
self.managedOperationsDisposable.add(managedSynchronizeInstalledStickerPacksOperations(postbox: self.postbox, network: self.network, stateManager: self.stateManager, namespace: .masks).start())
|
||||||
self.managedOperationsDisposable.add(managedRecentStickers(postbox: self.postbox, network: self.network).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(managedRecentGifs(postbox: self.postbox, network: self.network).start())
|
||||||
self.managedOperationsDisposable.add(managedRecentlyUsedInlineBots(postbox: self.postbox, network: self.network).start())
|
self.managedOperationsDisposable.add(managedRecentlyUsedInlineBots(postbox: self.postbox, network: self.network).start())
|
||||||
|
|||||||
@ -36,6 +36,12 @@ enum AccountStateUpdatePinnerPeerIdsOperation {
|
|||||||
case sync
|
case sync
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum AccountStateUpdateStickerPacksOperation {
|
||||||
|
case add(Api.messages.StickerSet)
|
||||||
|
case reorder(SynchronizeInstalledStickerPacksOperationNamespace, [Int64])
|
||||||
|
case sync
|
||||||
|
}
|
||||||
|
|
||||||
enum AccountStateMutationOperation {
|
enum AccountStateMutationOperation {
|
||||||
case AddMessages([StoreMessage], AddMessagesLocation)
|
case AddMessages([StoreMessage], AddMessagesLocation)
|
||||||
case DeleteMessagesWithGlobalIds([Int32])
|
case DeleteMessagesWithGlobalIds([Int32])
|
||||||
@ -60,6 +66,8 @@ enum AccountStateMutationOperation {
|
|||||||
case AddPeerInputActivity(chatPeerId: PeerId, peerId: PeerId?, activity: PeerInputActivity?)
|
case AddPeerInputActivity(chatPeerId: PeerId, peerId: PeerId?, activity: PeerInputActivity?)
|
||||||
case UpdatePinnedPeerIds(AccountStateUpdatePinnerPeerIdsOperation)
|
case UpdatePinnedPeerIds(AccountStateUpdatePinnerPeerIdsOperation)
|
||||||
case ReadGlobalMessageContents([Int32])
|
case ReadGlobalMessageContents([Int32])
|
||||||
|
case UpdateMessageImpressionCount(MessageId, Int32)
|
||||||
|
case UpdateInstalledStickerPacks(AccountStateUpdateStickerPacksOperation)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AccountMutableState {
|
struct AccountMutableState {
|
||||||
@ -232,9 +240,17 @@ struct AccountMutableState {
|
|||||||
self.addOperation(.ReadGlobalMessageContents(globalIds))
|
self.addOperation(.ReadGlobalMessageContents(globalIds))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutating func addUpdateMessageImpressionCount(id: MessageId, count: Int32) {
|
||||||
|
self.addOperation(.UpdateMessageImpressionCount(id, count))
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func addUpdateInstalledStickerPacks(_ operation: AccountStateUpdateStickerPacksOperation) {
|
||||||
|
self.addOperation(.UpdateInstalledStickerPacks(operation))
|
||||||
|
}
|
||||||
|
|
||||||
mutating func addOperation(_ operation: AccountStateMutationOperation) {
|
mutating func addOperation(_ operation: AccountStateMutationOperation) {
|
||||||
switch operation {
|
switch operation {
|
||||||
case .AddHole, .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMedia, .ReadOutbox, .MergePeerPresences, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedPeerIds, .ReadGlobalMessageContents:
|
case .AddHole, .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMedia, .ReadOutbox, .MergePeerPresences, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedPeerIds, .ReadGlobalMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks:
|
||||||
break
|
break
|
||||||
case let .AddMessages(messages, _):
|
case let .AddMessages(messages, _):
|
||||||
for message in messages {
|
for message in messages {
|
||||||
|
|||||||
@ -14,7 +14,7 @@ private enum AccountKind {
|
|||||||
case unauthorized
|
case unauthorized
|
||||||
}
|
}
|
||||||
|
|
||||||
public func currentAccount(manager: AccountManager, appGroupPath: String, testingEnvironment: Bool) -> Signal<Either<UnauthorizedAccount, Account>?, NoError> {
|
public func currentAccount(apiId: Int32, manager: AccountManager, appGroupPath: String, testingEnvironment: Bool) -> Signal<Either<UnauthorizedAccount, Account>?, NoError> {
|
||||||
return manager.allocatedCurrentAccountId()
|
return manager.allocatedCurrentAccountId()
|
||||||
|> distinctUntilChanged(isEqual: { lhs, rhs in
|
|> distinctUntilChanged(isEqual: { lhs, rhs in
|
||||||
return lhs == rhs
|
return lhs == rhs
|
||||||
@ -23,7 +23,7 @@ public func currentAccount(manager: AccountManager, appGroupPath: String, testin
|
|||||||
if let id = id {
|
if let id = id {
|
||||||
let reload = ValuePromise<Bool>(true, ignoreRepeated: false)
|
let reload = ValuePromise<Bool>(true, ignoreRepeated: false)
|
||||||
return reload.get() |> mapToSignal { _ -> Signal<Either<UnauthorizedAccount, Account>?, NoError> in
|
return reload.get() |> mapToSignal { _ -> Signal<Either<UnauthorizedAccount, Account>?, NoError> in
|
||||||
return accountWithId(id, appGroupPath: appGroupPath, testingEnvironment: testingEnvironment)
|
return accountWithId(apiId: apiId, id: id, appGroupPath: appGroupPath, testingEnvironment: testingEnvironment)
|
||||||
|> mapToSignal { account -> Signal<Either<UnauthorizedAccount, Account>?, NoError> in
|
|> mapToSignal { account -> Signal<Either<UnauthorizedAccount, Account>?, NoError> in
|
||||||
let postbox: Postbox
|
let postbox: Postbox
|
||||||
let initialKind: AccountKind
|
let initialKind: AccountKind
|
||||||
@ -96,7 +96,7 @@ public func logoutFromAccount(id: AccountRecordId, accountManager: AccountManage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func managedCleanupAccounts(accountManager: AccountManager, appGroupPath: String) -> Signal<Void, NoError> {
|
public func managedCleanupAccounts(apiId: Int32, accountManager: AccountManager, appGroupPath: String) -> Signal<Void, NoError> {
|
||||||
return Signal { subscriber in
|
return Signal { subscriber in
|
||||||
let loggedOutAccounts = Atomic<[AccountRecordId: MetaDisposable]>(value: [:])
|
let loggedOutAccounts = Atomic<[AccountRecordId: MetaDisposable]>(value: [:])
|
||||||
let disposable = accountManager.accountRecords().start(next: { view in
|
let disposable = accountManager.accountRecords().start(next: { view in
|
||||||
@ -139,7 +139,7 @@ public func managedCleanupAccounts(accountManager: AccountManager, appGroupPath:
|
|||||||
disposable.dispose()
|
disposable.dispose()
|
||||||
}
|
}
|
||||||
for (id, disposable) in beginList {
|
for (id, disposable) in beginList {
|
||||||
disposable.set(cleanupAccount(accountManager: accountManager, id: id, appGroupPath: appGroupPath).start())
|
disposable.set(cleanupAccount(apiId: apiId, accountManager: accountManager, id: id, appGroupPath: appGroupPath).start())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -150,8 +150,8 @@ public func managedCleanupAccounts(accountManager: AccountManager, appGroupPath:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private func cleanupAccount(accountManager: AccountManager, id: AccountRecordId, appGroupPath: String) -> Signal<Void, NoError> {
|
private func cleanupAccount(apiId: Int32, accountManager: AccountManager, id: AccountRecordId, appGroupPath: String) -> Signal<Void, NoError> {
|
||||||
return accountWithId(id, appGroupPath: appGroupPath, testingEnvironment: false)
|
return accountWithId(apiId: apiId, id: id, appGroupPath: appGroupPath, testingEnvironment: false)
|
||||||
|> mapToSignal { account -> Signal<Void, NoError> in
|
|> mapToSignal { account -> Signal<Void, NoError> in
|
||||||
switch account {
|
switch account {
|
||||||
case .left:
|
case .left:
|
||||||
|
|||||||
@ -968,6 +968,20 @@ private func finalStateWithUpdates(account: Account, state: AccountMutableState,
|
|||||||
}
|
}
|
||||||
case let .updateReadMessagesContents(messages, _, _):
|
case let .updateReadMessagesContents(messages, _, _):
|
||||||
updatedState.addReadGlobalMessagesContents(messages)
|
updatedState.addReadGlobalMessagesContents(messages)
|
||||||
|
case let .updateChannelMessageViews(channelId, id, views):
|
||||||
|
updatedState.addUpdateMessageImpressionCount(id: MessageId(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId), namespace: Namespaces.Message.Cloud, id: id), count: views)
|
||||||
|
case let .updateNewStickerSet(stickerset):
|
||||||
|
updatedState.addUpdateInstalledStickerPacks(.add(stickerset))
|
||||||
|
case let .updateStickerSetsOrder(flags, order):
|
||||||
|
let namespace: SynchronizeInstalledStickerPacksOperationNamespace
|
||||||
|
if (flags & (1 << 0)) != 0 {
|
||||||
|
namespace = .masks
|
||||||
|
} else {
|
||||||
|
namespace = .stickers
|
||||||
|
}
|
||||||
|
updatedState.addUpdateInstalledStickerPacks(.reorder(namespace, order))
|
||||||
|
case .updateStickerSets:
|
||||||
|
updatedState.addUpdateInstalledStickerPacks(.sync)
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -1301,7 +1315,7 @@ private func optimizedOperations(_ operations: [AccountStateMutationOperation])
|
|||||||
var currentAddMessages: OptimizeAddMessagesState?
|
var currentAddMessages: OptimizeAddMessagesState?
|
||||||
for operation in operations {
|
for operation in operations {
|
||||||
switch operation {
|
switch operation {
|
||||||
case .AddHole, .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMedia, .MergeApiChats, .MergeApiUsers, .MergePeerPresences, .UpdatePeer, .ReadInbox, .ReadOutbox, .ResetReadState, .UpdatePeerNotificationSettings, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedPeerIds, .ReadGlobalMessageContents:
|
case .AddHole, .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMedia, .MergeApiChats, .MergeApiUsers, .MergePeerPresences, .UpdatePeer, .ReadInbox, .ReadOutbox, .ResetReadState, .UpdatePeerNotificationSettings, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedPeerIds, .ReadGlobalMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks:
|
||||||
if let currentAddMessages = currentAddMessages, !currentAddMessages.messages.isEmpty {
|
if let currentAddMessages = currentAddMessages, !currentAddMessages.messages.isEmpty {
|
||||||
result.append(.AddMessages(currentAddMessages.messages, currentAddMessages.location))
|
result.append(.AddMessages(currentAddMessages.messages, currentAddMessages.location))
|
||||||
}
|
}
|
||||||
@ -1349,6 +1363,8 @@ func replayFinalState(accountPeerId: PeerId, mediaBox: MediaBox, modifier: Modif
|
|||||||
var updatedSecretChatTypingActivities = Set<PeerId>()
|
var updatedSecretChatTypingActivities = Set<PeerId>()
|
||||||
var updatedWebpages: [MediaId: TelegramMediaWebpage] = [:]
|
var updatedWebpages: [MediaId: TelegramMediaWebpage] = [:]
|
||||||
|
|
||||||
|
var stickerPackOperations: [AccountStateUpdateStickerPacksOperation] = []
|
||||||
|
|
||||||
for operation in optimizedOperations(finalState.state.operations) {
|
for operation in optimizedOperations(finalState.state.operations) {
|
||||||
switch operation {
|
switch operation {
|
||||||
case let .AddMessages(messages, location):
|
case let .AddMessages(messages, location):
|
||||||
@ -1478,6 +1494,144 @@ func replayFinalState(accountPeerId: PeerId, mediaBox: MediaBox, modifier: Modif
|
|||||||
for messageId in modifier.messageIdsForGlobalIds(globalIds) {
|
for messageId in modifier.messageIdsForGlobalIds(globalIds) {
|
||||||
markMessageContentAsConsumedRemotely(modifier: modifier, messageId: messageId)
|
markMessageContentAsConsumedRemotely(modifier: modifier, messageId: messageId)
|
||||||
}
|
}
|
||||||
|
case let .UpdateMessageImpressionCount(id, count):
|
||||||
|
modifier.updateMessage(id, update: { currentMessage in
|
||||||
|
var storeForwardInfo: StoreMessageForwardInfo?
|
||||||
|
if let forwardInfo = currentMessage.forwardInfo {
|
||||||
|
storeForwardInfo = StoreMessageForwardInfo(authorId: forwardInfo.author.id, sourceId: forwardInfo.source?.id, sourceMessageId: forwardInfo.sourceMessageId, date: forwardInfo.date)
|
||||||
|
}
|
||||||
|
var attributes = currentMessage.attributes
|
||||||
|
loop: for j in 0 ..< attributes.count {
|
||||||
|
if let attribute = attributes[j] as? ViewCountMessageAttribute {
|
||||||
|
attributes[j] = ViewCountMessageAttribute(count: max(attribute.count, Int(count)))
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media)
|
||||||
|
})
|
||||||
|
case let .UpdateInstalledStickerPacks(operation):
|
||||||
|
stickerPackOperations.append(operation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !stickerPackOperations.isEmpty {
|
||||||
|
if stickerPackOperations.contains(where: {
|
||||||
|
if case .sync = $0 {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
addSynchronizeInstalledStickerPacksOperation(modifier: modifier, namespace: .stickers)
|
||||||
|
addSynchronizeInstalledStickerPacksOperation(modifier: modifier, namespace: .masks)
|
||||||
|
} else {
|
||||||
|
var syncStickers = false
|
||||||
|
var syncMasks = false
|
||||||
|
loop: for operation in stickerPackOperations {
|
||||||
|
switch operation {
|
||||||
|
case let .add(apiSet):
|
||||||
|
let namespace: ItemCollectionId.Namespace
|
||||||
|
var items: [ItemCollectionItem] = []
|
||||||
|
let info: StickerPackCollectionInfo
|
||||||
|
switch apiSet {
|
||||||
|
case let .stickerSet(set, packs, documents):
|
||||||
|
var indexKeysByFile: [MediaId: [MemoryBuffer]] = [:]
|
||||||
|
for pack in packs {
|
||||||
|
switch pack {
|
||||||
|
case let .stickerPack(text, fileIds):
|
||||||
|
let key = ValueBoxKey(text).toMemoryBuffer()
|
||||||
|
for fileId in fileIds {
|
||||||
|
let mediaId = MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)
|
||||||
|
if indexKeysByFile[mediaId] == nil {
|
||||||
|
indexKeysByFile[mediaId] = [key]
|
||||||
|
} else {
|
||||||
|
indexKeysByFile[mediaId]!.append(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for apiDocument in documents {
|
||||||
|
if let file = telegramMediaFileFromApiDocument(apiDocument), let id = file.id {
|
||||||
|
let fileIndexKeys: [MemoryBuffer]
|
||||||
|
if let indexKeys = indexKeysByFile[id] {
|
||||||
|
fileIndexKeys = indexKeys
|
||||||
|
} else {
|
||||||
|
fileIndexKeys = []
|
||||||
|
}
|
||||||
|
items.append(StickerPackItem(index: ItemCollectionItemIndex(index: Int32(items.count), id: id.id), file: file, indexKeys: fileIndexKeys))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch set {
|
||||||
|
case let .stickerSet(flags, _, _, _, _, _, _):
|
||||||
|
if (flags & (1 << 3)) != 0 {
|
||||||
|
namespace = Namespaces.ItemCollection.CloudMaskPacks
|
||||||
|
} else {
|
||||||
|
namespace = Namespaces.ItemCollection.CloudStickerPacks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
info = StickerPackCollectionInfo(apiSet: set, namespace: namespace)
|
||||||
|
}
|
||||||
|
|
||||||
|
if namespace == Namespaces.ItemCollection.CloudMaskPacks && syncMasks {
|
||||||
|
continue loop
|
||||||
|
} else if namespace == Namespaces.ItemCollection.CloudStickerPacks && syncStickers {
|
||||||
|
continue loop
|
||||||
|
}
|
||||||
|
|
||||||
|
var updatedInfos = modifier.getItemCollectionsInfos(namespace: info.id.namespace).map { $0.1 as! StickerPackCollectionInfo }
|
||||||
|
if let index = updatedInfos.index(where: { $0.id == info.id }) {
|
||||||
|
let currentInfo = updatedInfos[index]
|
||||||
|
updatedInfos.remove(at: index)
|
||||||
|
updatedInfos.insert(currentInfo, at: 0)
|
||||||
|
} else {
|
||||||
|
updatedInfos.insert(info, at: 0)
|
||||||
|
modifier.replaceItemCollectionItems(collectionId: info.id, items: items)
|
||||||
|
}
|
||||||
|
modifier.replaceItemCollectionInfos(namespace: info.id.namespace, itemCollectionInfos: updatedInfos.map { ($0.id, $0) })
|
||||||
|
case let .reorder(namespace, ids):
|
||||||
|
let collectionNamespace: ItemCollectionId.Namespace
|
||||||
|
switch namespace {
|
||||||
|
case .stickers:
|
||||||
|
collectionNamespace = Namespaces.ItemCollection.CloudStickerPacks
|
||||||
|
case .masks:
|
||||||
|
collectionNamespace = Namespaces.ItemCollection.CloudMaskPacks
|
||||||
|
}
|
||||||
|
let currentInfos = modifier.getItemCollectionsInfos(namespace: collectionNamespace).map { $0.1 as! StickerPackCollectionInfo }
|
||||||
|
if Set(currentInfos.map { $0.id.id }) != Set(ids) {
|
||||||
|
switch namespace {
|
||||||
|
case .stickers:
|
||||||
|
syncStickers = true
|
||||||
|
case .masks:
|
||||||
|
syncMasks = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var currentDict: [ItemCollectionId: StickerPackCollectionInfo] = [:]
|
||||||
|
for info in currentInfos {
|
||||||
|
currentDict[info.id] = info
|
||||||
|
}
|
||||||
|
var updatedInfos: [StickerPackCollectionInfo] = []
|
||||||
|
for id in ids {
|
||||||
|
let currentInfo = currentDict[ItemCollectionId(namespace: collectionNamespace, id: id)]!
|
||||||
|
updatedInfos.append(currentInfo)
|
||||||
|
}
|
||||||
|
modifier.replaceItemCollectionInfos(namespace: collectionNamespace, itemCollectionInfos: updatedInfos.map { ($0.id, $0) })
|
||||||
|
}
|
||||||
|
case .sync:
|
||||||
|
syncStickers = true
|
||||||
|
syncMasks = true
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if syncStickers {
|
||||||
|
addSynchronizeInstalledStickerPacksOperation(modifier: modifier, namespace: .stickers)
|
||||||
|
}
|
||||||
|
if syncMasks {
|
||||||
|
addSynchronizeInstalledStickerPacksOperation(modifier: modifier, namespace: .masks)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
123
TelegramCore/LoadedStickerpack.swift
Normal file
123
TelegramCore/LoadedStickerpack.swift
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
import Foundation
|
||||||
|
#if os(macOS)
|
||||||
|
import PostboxMac
|
||||||
|
import SwiftSignalKitMac
|
||||||
|
#else
|
||||||
|
import Postbox
|
||||||
|
import SwiftSignalKit
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extension StickerPackReference {
|
||||||
|
init(_ stickerPackInfo: StickerPackCollectionInfo) {
|
||||||
|
self = .id(id: stickerPackInfo.id.id, accessHash: stickerPackInfo.accessHash)
|
||||||
|
}
|
||||||
|
|
||||||
|
var apiInputStickerSet: Api.InputStickerSet {
|
||||||
|
switch self {
|
||||||
|
case let .id(id, accessHash):
|
||||||
|
return .inputStickerSetID(id: id, accessHash: accessHash)
|
||||||
|
case let .name(name):
|
||||||
|
return .inputStickerSetShortName(shortName: name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum LoadedStickerPack {
|
||||||
|
case fetching
|
||||||
|
case none
|
||||||
|
case result(info: StickerPackCollectionInfo, items: [ItemCollectionItem], installed: Bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func loadedStickerPack(account: Account, reference: StickerPackReference) -> Signal<LoadedStickerPack, NoError> {
|
||||||
|
return account.postbox.modify { modifier -> Signal<LoadedStickerPack, NoError> in
|
||||||
|
switch reference {
|
||||||
|
case let .id(id, _):
|
||||||
|
if let info = modifier.getItemCollectionInfo(collectionId: ItemCollectionId(namespace: Namespaces.ItemCollection.CloudStickerPacks, id: id)) as? StickerPackCollectionInfo {
|
||||||
|
return account.postbox.combinedView(keys: [PostboxViewKey.itemCollectionInfo(id: info.id)])
|
||||||
|
|> map { view in
|
||||||
|
if let view = view.views[PostboxViewKey.itemCollectionInfo(id: info.id)] as? ItemCollectionInfoView, let info = view.info as? StickerPackCollectionInfo {
|
||||||
|
return .result(info: info, items: modifier.getItemCollectionItems(collectionId: info.id), installed: true)
|
||||||
|
} else {
|
||||||
|
return .result(info: info, items: modifier.getItemCollectionItems(collectionId: info.id), installed: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if let info = modifier.getItemCollectionInfo(collectionId: ItemCollectionId(namespace: Namespaces.ItemCollection.CloudMaskPacks, id: id)) as? StickerPackCollectionInfo {
|
||||||
|
return account.postbox.combinedView(keys: [PostboxViewKey.itemCollectionInfo(id: info.id)])
|
||||||
|
|> map { view in
|
||||||
|
if let view = view.views[PostboxViewKey.itemCollectionInfo(id: info.id)] as? ItemCollectionInfoView, let info = view.info as? StickerPackCollectionInfo {
|
||||||
|
return .result(info: info, items: modifier.getItemCollectionItems(collectionId: info.id), installed: true)
|
||||||
|
} else {
|
||||||
|
return .result(info: info, items: modifier.getItemCollectionItems(collectionId: info.id), installed: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
let signal: Signal<LoadedStickerPack, NoError> = account.network.request(Api.functions.messages.getStickerSet(stickerset: reference.apiInputStickerSet))
|
||||||
|
|> map { Optional($0) }
|
||||||
|
|> `catch` { _ -> Signal<Api.messages.StickerSet?, NoError> in
|
||||||
|
return .single(nil)
|
||||||
|
}
|
||||||
|
|> mapToSignal { result -> Signal<LoadedStickerPack, NoError> in
|
||||||
|
guard let result = result else {
|
||||||
|
return .single(.none)
|
||||||
|
}
|
||||||
|
|
||||||
|
let info: StickerPackCollectionInfo
|
||||||
|
var items: [ItemCollectionItem] = []
|
||||||
|
switch result {
|
||||||
|
case let .stickerSet(set, packs, documents):
|
||||||
|
let namespace: ItemCollectionId.Namespace
|
||||||
|
switch set {
|
||||||
|
case let .stickerSet(flags, _, _, _, _, _, _):
|
||||||
|
if (flags & (1 << 3)) != 0 {
|
||||||
|
namespace = Namespaces.ItemCollection.CloudMaskPacks
|
||||||
|
} else {
|
||||||
|
namespace = Namespaces.ItemCollection.CloudStickerPacks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
info = StickerPackCollectionInfo(apiSet: set, namespace: namespace)
|
||||||
|
var indexKeysByFile: [MediaId: [MemoryBuffer]] = [:]
|
||||||
|
for pack in packs {
|
||||||
|
switch pack {
|
||||||
|
case let .stickerPack(text, fileIds):
|
||||||
|
let key = ValueBoxKey(text).toMemoryBuffer()
|
||||||
|
for fileId in fileIds {
|
||||||
|
let mediaId = MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)
|
||||||
|
if indexKeysByFile[mediaId] == nil {
|
||||||
|
indexKeysByFile[mediaId] = [key]
|
||||||
|
} else {
|
||||||
|
indexKeysByFile[mediaId]!.append(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for apiDocument in documents {
|
||||||
|
if let file = telegramMediaFileFromApiDocument(apiDocument), let id = file.id {
|
||||||
|
let fileIndexKeys: [MemoryBuffer]
|
||||||
|
if let indexKeys = indexKeysByFile[id] {
|
||||||
|
fileIndexKeys = indexKeys
|
||||||
|
} else {
|
||||||
|
fileIndexKeys = []
|
||||||
|
}
|
||||||
|
items.append(StickerPackItem(index: ItemCollectionItemIndex(index: Int32(items.count), id: id.id), file: file, indexKeys: fileIndexKeys))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return account.postbox.combinedView(keys: [PostboxViewKey.itemCollectionInfo(id: info.id)])
|
||||||
|
|> map { view in
|
||||||
|
if let view = view.views[PostboxViewKey.itemCollectionInfo(id: info.id)] as? ItemCollectionInfoView, let info = view.info as? StickerPackCollectionInfo {
|
||||||
|
return .result(info: info, items: items, installed: true)
|
||||||
|
} else {
|
||||||
|
return .result(info: info, items: items, installed: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return .single(.fetching) |> then(signal)
|
||||||
|
} |> switchToLatest
|
||||||
|
}
|
||||||
@ -69,7 +69,7 @@ private func withTakenOperation(postbox: Postbox, peerId: PeerId, tag: PeerOpera
|
|||||||
} |> switchToLatest
|
} |> switchToLatest
|
||||||
}
|
}
|
||||||
|
|
||||||
func managedSynchronizePinnedChatsOperations(postbox: Postbox, network: Network, stateManager: AccountStateManager, namespace: SynchronizeInstalledStickerPacksOperationNamespace) -> Signal<Void, NoError> {
|
func managedSynchronizeInstalledStickerPacksOperations(postbox: Postbox, network: Network, stateManager: AccountStateManager, namespace: SynchronizeInstalledStickerPacksOperationNamespace) -> Signal<Void, NoError> {
|
||||||
return Signal { _ in
|
return Signal { _ in
|
||||||
let tag: PeerOperationLogTag
|
let tag: PeerOperationLogTag
|
||||||
switch namespace {
|
switch namespace {
|
||||||
@ -121,6 +121,316 @@ func managedSynchronizePinnedChatsOperations(postbox: Postbox, network: Network,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func synchronizeInstalledStickerPacks(modifier: Modifier, postbox: Postbox, network: Network, stateManager: AccountStateManager, namespace: SynchronizeInstalledStickerPacksOperationNamespace, operation: SynchronizeInstalledStickerPacksOperation) -> Signal<Void, NoError> {
|
private func hashForStickerPackInfos(_ infos: [StickerPackCollectionInfo]) -> Int32 {
|
||||||
return .complete()
|
var acc: UInt32 = 0
|
||||||
|
|
||||||
|
for info in infos {
|
||||||
|
acc = UInt32(bitPattern: Int32(bitPattern: acc &* UInt32(20261)) &+ info.hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Int32(bitPattern: acc % 0x7FFFFFFF)
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum SynchronizeInstalledStickerPacksError {
|
||||||
|
case restart
|
||||||
|
case done
|
||||||
|
}
|
||||||
|
|
||||||
|
private func fetchStickerPack(network: Network, info: StickerPackCollectionInfo) -> Signal<(ItemCollectionId, [ItemCollectionItem]), NoError> {
|
||||||
|
return network.request(Api.functions.messages.getStickerSet(stickerset: .inputStickerSetID(id: info.id.id, accessHash: info.accessHash)))
|
||||||
|
|> map { result -> (ItemCollectionId, [ItemCollectionItem]) in
|
||||||
|
var items: [ItemCollectionItem] = []
|
||||||
|
switch result {
|
||||||
|
case let .stickerSet(_, packs, documents):
|
||||||
|
var indexKeysByFile: [MediaId: [MemoryBuffer]] = [:]
|
||||||
|
for pack in packs {
|
||||||
|
switch pack {
|
||||||
|
case let .stickerPack(text, fileIds):
|
||||||
|
let key = ValueBoxKey(text).toMemoryBuffer()
|
||||||
|
for fileId in fileIds {
|
||||||
|
let mediaId = MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)
|
||||||
|
if indexKeysByFile[mediaId] == nil {
|
||||||
|
indexKeysByFile[mediaId] = [key]
|
||||||
|
} else {
|
||||||
|
indexKeysByFile[mediaId]!.append(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for apiDocument in documents {
|
||||||
|
if let file = telegramMediaFileFromApiDocument(apiDocument), let id = file.id {
|
||||||
|
let fileIndexKeys: [MemoryBuffer]
|
||||||
|
if let indexKeys = indexKeysByFile[id] {
|
||||||
|
fileIndexKeys = indexKeys
|
||||||
|
} else {
|
||||||
|
fileIndexKeys = []
|
||||||
|
}
|
||||||
|
items.append(StickerPackItem(index: ItemCollectionItemIndex(index: Int32(items.count), id: id.id), file: file, indexKeys: fileIndexKeys))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return (info.id, items)
|
||||||
|
}
|
||||||
|
|> `catch` { _ -> Signal<(ItemCollectionId, [ItemCollectionItem]), NoError> in
|
||||||
|
return .single((info.id, []))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func resolveStickerPacks(network: Network, remoteInfos: [ItemCollectionId: StickerPackCollectionInfo], localInfos: [ItemCollectionId: StickerPackCollectionInfo]) -> Signal<[ItemCollectionId: [ItemCollectionItem]], NoError> {
|
||||||
|
var signals: [Signal<(ItemCollectionId, [ItemCollectionItem]), NoError>] = []
|
||||||
|
for (id, remoteInfo) in remoteInfos {
|
||||||
|
let localInfo = localInfos[id]
|
||||||
|
if localInfo == nil || localInfo!.hash != remoteInfo.hash {
|
||||||
|
signals.append(fetchStickerPack(network: network, info: remoteInfo))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return combineLatest(signals)
|
||||||
|
|> map { result -> [ItemCollectionId: [ItemCollectionItem]] in
|
||||||
|
var dict: [ItemCollectionId: [ItemCollectionItem]] = [:]
|
||||||
|
for (id, items) in result {
|
||||||
|
dict[id] = items
|
||||||
|
}
|
||||||
|
return dict
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func installRemoteStickerPacks(network: Network, infos: [StickerPackCollectionInfo]) -> Signal<Set<ItemCollectionId>, NoError> {
|
||||||
|
var signals: [Signal<Set<ItemCollectionId>, NoError>] = []
|
||||||
|
for info in infos {
|
||||||
|
let install = network.request(Api.functions.messages.installStickerSet(stickerset: .inputStickerSetID(id: info.id.id, accessHash: info.accessHash), archived: .boolFalse))
|
||||||
|
|> map { result -> Set<ItemCollectionId> in
|
||||||
|
switch result {
|
||||||
|
case .stickerSetInstallResultSuccess:
|
||||||
|
return Set()
|
||||||
|
case let .stickerSetInstallResultArchive(archivedSets):
|
||||||
|
var archivedIds = Set<ItemCollectionId>()
|
||||||
|
for archivedSet in archivedSets {
|
||||||
|
switch archivedSet {
|
||||||
|
case let .stickerSetCovered(set, _):
|
||||||
|
archivedIds.insert(StickerPackCollectionInfo(apiSet: set, namespace: info.id.namespace).id)
|
||||||
|
case let .stickerSetMultiCovered(set, _):
|
||||||
|
archivedIds.insert(StickerPackCollectionInfo(apiSet: set, namespace: info.id.namespace).id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return archivedIds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|> `catch` { _ -> Signal<Set<ItemCollectionId>, NoError> in
|
||||||
|
return .single(Set())
|
||||||
|
}
|
||||||
|
signals.append(install)
|
||||||
|
}
|
||||||
|
return combineLatest(signals)
|
||||||
|
|> map { idsSets -> Set<ItemCollectionId> in
|
||||||
|
var result = Set<ItemCollectionId>()
|
||||||
|
for ids in idsSets {
|
||||||
|
result.formUnion(ids)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func archiveRemoteStickerPacks(network: Network, infos: [StickerPackCollectionInfo]) -> Signal<Void, NoError> {
|
||||||
|
var signals: [Signal<Void, NoError>] = []
|
||||||
|
for info in infos {
|
||||||
|
let archive = network.request(Api.functions.messages.installStickerSet(stickerset: .inputStickerSetID(id: info.id.id, accessHash: info.accessHash), archived: .boolTrue))
|
||||||
|
|> mapToSignal { _ -> Signal<Void, MTRpcError> in
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
|> `catch` { _ -> Signal<Void, NoError> in
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
signals.append(archive)
|
||||||
|
}
|
||||||
|
return combineLatest(signals) |> map { _ in return Void() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private func reorderRemoteStickerPacks(network: Network, namespace: SynchronizeInstalledStickerPacksOperationNamespace, ids: [ItemCollectionId]) -> Signal<Void, NoError> {
|
||||||
|
var flags: Int32 = 0
|
||||||
|
switch namespace {
|
||||||
|
case .stickers:
|
||||||
|
break
|
||||||
|
case .masks:
|
||||||
|
flags |= (1 << 0)
|
||||||
|
}
|
||||||
|
return network.request(Api.functions.messages.reorderStickerSets(flags: flags, order: ids.map { $0.id }))
|
||||||
|
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
||||||
|
return .single(.boolFalse)
|
||||||
|
}
|
||||||
|
|> mapToSignal { _ -> Signal<Void, NoError> in
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func synchronizeInstalledStickerPacks(modifier: Modifier, postbox: Postbox, network: Network, stateManager: AccountStateManager, namespace: SynchronizeInstalledStickerPacksOperationNamespace, operation: SynchronizeInstalledStickerPacksOperation) -> Signal<Void, NoError> {
|
||||||
|
let collectionNamespace: ItemCollectionId.Namespace
|
||||||
|
switch namespace {
|
||||||
|
case .stickers:
|
||||||
|
collectionNamespace = Namespaces.ItemCollection.CloudStickerPacks
|
||||||
|
case .masks:
|
||||||
|
collectionNamespace = Namespaces.ItemCollection.CloudMaskPacks
|
||||||
|
}
|
||||||
|
|
||||||
|
let localCollectionInfos = modifier.getItemCollectionsInfos(namespace: collectionNamespace).map { $0.1 as! StickerPackCollectionInfo }
|
||||||
|
let initialLocalHash = hashForStickerPackInfos(localCollectionInfos)
|
||||||
|
|
||||||
|
let request: Signal<Api.messages.AllStickers, MTRpcError>
|
||||||
|
switch namespace {
|
||||||
|
case .stickers:
|
||||||
|
request = network.request(Api.functions.messages.getAllStickers(hash: initialLocalHash))
|
||||||
|
case .masks:
|
||||||
|
request = network.request(Api.functions.messages.getMaskStickers(hash: initialLocalHash))
|
||||||
|
}
|
||||||
|
|
||||||
|
let sequence = request
|
||||||
|
|> retryRequest
|
||||||
|
|> mapError { _ -> SynchronizeInstalledStickerPacksError in
|
||||||
|
return .restart
|
||||||
|
}
|
||||||
|
|> mapToSignal { result -> Signal<Void, SynchronizeInstalledStickerPacksError> in
|
||||||
|
return postbox.modify { modifier -> Signal<Void, SynchronizeInstalledStickerPacksError> in
|
||||||
|
let checkLocalCollectionInfos = modifier.getItemCollectionsInfos(namespace: collectionNamespace).map { $0.1 as! StickerPackCollectionInfo }
|
||||||
|
if checkLocalCollectionInfos != localCollectionInfos {
|
||||||
|
return .fail(.restart)
|
||||||
|
}
|
||||||
|
|
||||||
|
let localInitialStateCollectionOrder = operation.previousPacks
|
||||||
|
let localInitialStateCollectionIds = Set(localInitialStateCollectionOrder)
|
||||||
|
|
||||||
|
let localCollectionOrder = checkLocalCollectionInfos.map { $0.id }
|
||||||
|
let localCollectionIds = Set(localCollectionOrder)
|
||||||
|
|
||||||
|
var remoteCollectionInfos: [StickerPackCollectionInfo] = []
|
||||||
|
switch result {
|
||||||
|
case let .allStickers(_, sets):
|
||||||
|
for apiSet in sets {
|
||||||
|
let info = StickerPackCollectionInfo(apiSet: apiSet, namespace: collectionNamespace)
|
||||||
|
remoteCollectionInfos.append(info)
|
||||||
|
}
|
||||||
|
case .allStickersNotModified:
|
||||||
|
remoteCollectionInfos = checkLocalCollectionInfos
|
||||||
|
}
|
||||||
|
|
||||||
|
let remoteCollectionOrder = remoteCollectionInfos.map { $0.id }
|
||||||
|
let remoteCollectionIds = Set(remoteCollectionOrder)
|
||||||
|
|
||||||
|
var remoteInfos: [ItemCollectionId: StickerPackCollectionInfo] = [:]
|
||||||
|
for info in remoteCollectionInfos {
|
||||||
|
remoteInfos[info.id] = info
|
||||||
|
}
|
||||||
|
var localInfos: [ItemCollectionId: StickerPackCollectionInfo] = [:]
|
||||||
|
for info in checkLocalCollectionInfos {
|
||||||
|
localInfos[info.id] = info
|
||||||
|
}
|
||||||
|
|
||||||
|
if localInitialStateCollectionOrder == localCollectionOrder {
|
||||||
|
if checkLocalCollectionInfos == remoteCollectionInfos {
|
||||||
|
return .fail(.done)
|
||||||
|
} else {
|
||||||
|
return resolveStickerPacks(network: network, remoteInfos: remoteInfos, localInfos: localInfos)
|
||||||
|
|> mapError { _ -> SynchronizeInstalledStickerPacksError in
|
||||||
|
return .restart
|
||||||
|
}
|
||||||
|
|> mapToSignal { replaceItems -> Signal<Void, SynchronizeInstalledStickerPacksError> in
|
||||||
|
return (postbox.modify { modifier -> Void in
|
||||||
|
modifier.replaceItemCollectionInfos(namespace: collectionNamespace, itemCollectionInfos: remoteCollectionInfos.map { ($0.id, $0) })
|
||||||
|
for (id, items) in replaceItems {
|
||||||
|
modifier.replaceItemCollectionItems(collectionId: id, items: items)
|
||||||
|
}
|
||||||
|
for id in localCollectionIds.subtracting(remoteCollectionIds) {
|
||||||
|
modifier.replaceItemCollectionItems(collectionId: id, items: [])
|
||||||
|
}
|
||||||
|
} |> mapError { _ -> SynchronizeInstalledStickerPacksError in return .restart }) |> then(.fail(.done))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let locallyRemovedCollectionIds = localInitialStateCollectionIds.subtracting(localCollectionIds)
|
||||||
|
let locallyAddedCollectionIds = localCollectionIds.subtracting(localInitialStateCollectionIds)
|
||||||
|
let remotelyAddedCollections = remoteCollectionInfos.filter { info in
|
||||||
|
return !locallyRemovedCollectionIds.contains(info.id) && !localCollectionIds.contains(info.id)
|
||||||
|
}
|
||||||
|
let remotelyRemovedCollectionIds = remoteCollectionIds.subtracting(localInitialStateCollectionIds).subtracting(locallyAddedCollectionIds)
|
||||||
|
|
||||||
|
var resultingCollectionInfos: [StickerPackCollectionInfo] = []
|
||||||
|
resultingCollectionInfos.append(contentsOf: remotelyAddedCollections)
|
||||||
|
resultingCollectionInfos.append(contentsOf: checkLocalCollectionInfos.filter { info in
|
||||||
|
return !remotelyRemovedCollectionIds.contains(info.id)
|
||||||
|
})
|
||||||
|
|
||||||
|
let resultingCollectionIds = Set(resultingCollectionInfos.map { $0.id })
|
||||||
|
let removeRemoteCollectionIds = remoteCollectionIds.subtracting(resultingCollectionIds)
|
||||||
|
let addRemoteCollectionIds = resultingCollectionIds.subtracting(remoteCollectionIds)
|
||||||
|
|
||||||
|
var removeRemoteCollectionInfos: [StickerPackCollectionInfo] = []
|
||||||
|
for id in removeRemoteCollectionIds {
|
||||||
|
if let info = remoteInfos[id] {
|
||||||
|
removeRemoteCollectionInfos.append(info)
|
||||||
|
} else if let info = localInfos[id] {
|
||||||
|
removeRemoteCollectionInfos.append(info)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var addRemoteCollectionInfos: [StickerPackCollectionInfo] = []
|
||||||
|
for id in addRemoteCollectionIds {
|
||||||
|
if let info = remoteInfos[id] {
|
||||||
|
addRemoteCollectionInfos.append(info)
|
||||||
|
} else if let info = localInfos[id] {
|
||||||
|
addRemoteCollectionInfos.append(info)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let archivedIds = (archiveRemoteStickerPacks(network: network, infos: removeRemoteCollectionInfos)
|
||||||
|
|> then(Signal<Void, NoError>.single(Void())))
|
||||||
|
|> mapToSignal { _ -> Signal<Set<ItemCollectionId>, NoError> in
|
||||||
|
return installRemoteStickerPacks(network: network, infos: addRemoteCollectionInfos)
|
||||||
|
|> mapToSignal { ids -> Signal<Set<ItemCollectionId>, NoError> in
|
||||||
|
return (reorderRemoteStickerPacks(network: network, namespace: namespace, ids: resultingCollectionInfos.map({ $0.id }).filter({ !ids.contains($0) }))
|
||||||
|
|> then(Signal<Void, NoError>.single(Void())))
|
||||||
|
|> map { _ -> Set<ItemCollectionId> in
|
||||||
|
return ids
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var resultingInfos: [ItemCollectionId: StickerPackCollectionInfo] = [:]
|
||||||
|
for info in resultingCollectionInfos {
|
||||||
|
resultingInfos[info.id] = info
|
||||||
|
}
|
||||||
|
let resolvedItems = resolveStickerPacks(network: network, remoteInfos: resultingInfos, localInfos: localInfos)
|
||||||
|
|
||||||
|
return combineLatest(archivedIds, resolvedItems)
|
||||||
|
|> mapError { _ -> SynchronizeInstalledStickerPacksError in return .restart }
|
||||||
|
|> mapToSignal { archivedIds, replaceItems -> Signal<Void, SynchronizeInstalledStickerPacksError> in
|
||||||
|
return (postbox.modify { modifier -> Void in
|
||||||
|
modifier.replaceItemCollectionInfos(namespace: collectionNamespace, itemCollectionInfos: resultingCollectionInfos.filter({ info in
|
||||||
|
return !archivedIds.contains(info.id)
|
||||||
|
}).map({ ($0.id, $0) }))
|
||||||
|
for (id, items) in replaceItems {
|
||||||
|
if !archivedIds.contains(id) {
|
||||||
|
modifier.replaceItemCollectionItems(collectionId: id, items: items)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for id in localCollectionIds.subtracting(resultingCollectionIds).union(archivedIds) {
|
||||||
|
modifier.replaceItemCollectionItems(collectionId: id, items: [])
|
||||||
|
}
|
||||||
|
} |> mapError { _ -> SynchronizeInstalledStickerPacksError in return .restart }) |> then(.fail(.done))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} |> mapError { _ -> SynchronizeInstalledStickerPacksError in return .restart } |> switchToLatest
|
||||||
|
}
|
||||||
|
return ((sequence
|
||||||
|
|> `catch` { error -> Signal<Void, SynchronizeInstalledStickerPacksError> in
|
||||||
|
switch error {
|
||||||
|
case .done:
|
||||||
|
return .fail(.done)
|
||||||
|
case .restart:
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
}) |> restart) |> `catch` { _ -> Signal<Void, NoError> in
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
90
TelegramCore/MediaPool.swift
Normal file
90
TelegramCore/MediaPool.swift
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import Foundation
|
||||||
|
#if os(macOS)
|
||||||
|
import PostboxMac
|
||||||
|
import SwiftSignalKitMac
|
||||||
|
import MtProtoKitMac
|
||||||
|
#else
|
||||||
|
import Postbox
|
||||||
|
import SwiftSignalKit
|
||||||
|
import MtProtoKitDynamic
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if os(macOS)
|
||||||
|
private typealias SignalKitTimer = SwiftSignalKitMac.Timer
|
||||||
|
#else
|
||||||
|
private typealias SignalKitTimer = SwiftSignalKit.Timer
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct MediaPoolDownloadPart {
|
||||||
|
let location: Api.InputFileLocation
|
||||||
|
let offset: Int
|
||||||
|
let length: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class DownloadRequest {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
final class MediaPool {
|
||||||
|
private let queue = Queue()
|
||||||
|
|
||||||
|
private var downloads: [Int32: Download] = [:]
|
||||||
|
private var inactiveDownloads = Set<Int32>()
|
||||||
|
private var nextDownloadId: Int32 = 0
|
||||||
|
private var collectInactiveDownloadsTimer: SignalKitTimer?
|
||||||
|
|
||||||
|
private var requests = Bag<DownloadRequest>()
|
||||||
|
|
||||||
|
private var interfaces = Bag<MediaPoolInterface>()
|
||||||
|
|
||||||
|
init() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private func takeInactiveDownload() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func part(_ part: MediaPoolDownloadPart) -> Signal<Data, NoError> {
|
||||||
|
return Signal { subscriber in
|
||||||
|
let disposable = MetaDisposable()
|
||||||
|
self.queue.async {
|
||||||
|
let index = self.requests.add(DownloadRequest())
|
||||||
|
disposable.set(ActionDisposable {
|
||||||
|
self.queue.async {
|
||||||
|
self.requests.remove(index)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return disposable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func poolInterface() -> Signal<MediaPoolInterface, NoError> {
|
||||||
|
return Signal { subscriber in
|
||||||
|
let disposable = MetaDisposable()
|
||||||
|
self.queue.async {
|
||||||
|
let index = self.interfaces.add(MediaPoolInterface())
|
||||||
|
disposable.set(ActionDisposable {
|
||||||
|
self.queue.async {
|
||||||
|
self.interfaces.remove(index)
|
||||||
|
self.update()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return disposable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func update() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class MediaPoolInterface {
|
||||||
|
func part(_ part: MediaPoolDownloadPart) -> Signal<Data, NoError> {
|
||||||
|
return Signal { _ in
|
||||||
|
return EmptyDisposable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -168,7 +168,7 @@ private final class MultipartUploadManager {
|
|||||||
self.progress = progress
|
self.progress = progress
|
||||||
self.completed = completed
|
self.completed = completed
|
||||||
|
|
||||||
if let hintFileSize = hintFileSize, hintFileSize > 1 * 1024 * 1024 {
|
if let hintFileSize = hintFileSize, hintFileSize > 5 * 1024 * 1024 {
|
||||||
self.defaultPartSize = 512 * 1024
|
self.defaultPartSize = 512 * 1024
|
||||||
self.bigTotalParts = (hintFileSize / self.defaultPartSize) + (hintFileSize % self.defaultPartSize == 0 ? 0 : 1)
|
self.bigTotalParts = (hintFileSize / self.defaultPartSize) + (hintFileSize % self.defaultPartSize == 0 ? 0 : 1)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -94,7 +94,7 @@ private var registeredLoggingFunctions: Void = {
|
|||||||
registerLoggingFunctions()
|
registerLoggingFunctions()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
func initializedNetwork(datacenterId: Int, keychain: Keychain, networkUsageInfoPath: String?, testingEnvironment: Bool) -> Signal<Network, NoError> {
|
func initializedNetwork(apiId: Int32, datacenterId: Int, keychain: Keychain, networkUsageInfoPath: String?, testingEnvironment: Bool) -> Signal<Network, NoError> {
|
||||||
return Signal { subscriber in
|
return Signal { subscriber in
|
||||||
Queue.concurrentDefaultQueue().async {
|
Queue.concurrentDefaultQueue().async {
|
||||||
let _ = registeredLoggingFunctions
|
let _ = registeredLoggingFunctions
|
||||||
@ -103,7 +103,7 @@ func initializedNetwork(datacenterId: Int, keychain: Keychain, networkUsageInfoP
|
|||||||
|
|
||||||
let apiEnvironment = MTApiEnvironment()
|
let apiEnvironment = MTApiEnvironment()
|
||||||
|
|
||||||
apiEnvironment.apiId = 1
|
apiEnvironment.apiId = apiId
|
||||||
apiEnvironment.layer = NSNumber(value: Int(serialization.currentLayer()))
|
apiEnvironment.layer = NSNumber(value: Int(serialization.currentLayer()))
|
||||||
|
|
||||||
let context = MTContext(serialization: serialization, apiEnvironment: apiEnvironment)!
|
let context = MTContext(serialization: serialization, apiEnvironment: apiEnvironment)!
|
||||||
|
|||||||
@ -19,6 +19,11 @@ private func hashForInfos(_ infos: [StickerPackCollectionInfo]) -> Int32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func manageStickerPacks(network: Network, postbox: Postbox) -> Signal<Void, NoError> {
|
func manageStickerPacks(network: Network, postbox: Postbox) -> Signal<Void, NoError> {
|
||||||
|
return postbox.modify { modifier -> Void in
|
||||||
|
addSynchronizeInstalledStickerPacksOperation(modifier: modifier, namespace: .stickers)
|
||||||
|
addSynchronizeInstalledStickerPacksOperation(modifier: modifier, namespace: .masks)
|
||||||
|
}
|
||||||
|
|
||||||
let currentHash = postbox.itemCollectionsView(orderedItemListCollectionIds: [], 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
|
||||||
@ -38,7 +43,7 @@ func manageStickerPacks(network: Network, postbox: Postbox) -> Signal<Void, NoEr
|
|||||||
switch result {
|
switch result {
|
||||||
case let .allStickers(_, sets):
|
case let .allStickers(_, sets):
|
||||||
for apiSet in sets {
|
for apiSet in sets {
|
||||||
stickerPackInfos.append(StickerPackCollectionInfo(apiSet: apiSet))
|
stickerPackInfos.append(StickerPackCollectionInfo(apiSet: apiSet, namespace: Namespaces.ItemCollection.CloudStickerPacks))
|
||||||
}
|
}
|
||||||
case .allStickersNotModified:
|
case .allStickersNotModified:
|
||||||
break
|
break
|
||||||
@ -53,7 +58,6 @@ func manageStickerPacks(network: Network, postbox: Postbox) -> Signal<Void, NoEr
|
|||||||
switch result {
|
switch result {
|
||||||
case let .stickerSet(_, packs, documents):
|
case let .stickerSet(_, packs, documents):
|
||||||
var indexKeysByFile: [MediaId: [MemoryBuffer]] = [:]
|
var indexKeysByFile: [MediaId: [MemoryBuffer]] = [:]
|
||||||
//stickerPack#12b299d4 emoticon:string documents:Vector<long> = StickerPack;
|
|
||||||
for pack in packs {
|
for pack in packs {
|
||||||
switch pack {
|
switch pack {
|
||||||
case let .stickerPack(text, fileIds):
|
case let .stickerPack(text, fileIds):
|
||||||
|
|||||||
@ -134,7 +134,7 @@ public final class StickerPackItem: ItemCollectionItem, Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension StickerPackCollectionInfo {
|
extension StickerPackCollectionInfo {
|
||||||
convenience init(apiSet: Api.StickerSet) {
|
convenience init(apiSet: Api.StickerSet, namespace: ItemCollectionId.Namespace) {
|
||||||
switch apiSet {
|
switch apiSet {
|
||||||
case let .stickerSet(flags, id, accessHash, title, shortName, count, nHash):
|
case let .stickerSet(flags, id, accessHash, title, shortName, count, nHash):
|
||||||
var setFlags: StickerPackCollectionInfoFlags = StickerPackCollectionInfoFlags()
|
var setFlags: StickerPackCollectionInfoFlags = StickerPackCollectionInfoFlags()
|
||||||
@ -144,7 +144,7 @@ extension StickerPackCollectionInfo {
|
|||||||
if (flags & (1 << 3)) != 0 {
|
if (flags & (1 << 3)) != 0 {
|
||||||
setFlags.insert(.masks)
|
setFlags.insert(.masks)
|
||||||
}
|
}
|
||||||
self.init(id: ItemCollectionId(namespace: Namespaces.ItemCollection.CloudStickerPacks, id: id), flags: setFlags, accessHash: accessHash, title: title, shortName: shortName, hash: nHash, count: count)
|
self.init(id: ItemCollectionId(namespace: namespace, id: id), flags: setFlags, accessHash: accessHash, title: title, shortName: shortName, hash: nHash, count: count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
54
TelegramCore/StickerPackInteractiveOperations.swift
Normal file
54
TelegramCore/StickerPackInteractiveOperations.swift
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import Foundation
|
||||||
|
#if os(macOS)
|
||||||
|
import PostboxMac
|
||||||
|
import SwiftSignalKitMac
|
||||||
|
#else
|
||||||
|
import Postbox
|
||||||
|
import SwiftSignalKit
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public func addStickerPackInteractively(postbox: Postbox, info: StickerPackCollectionInfo, items: [ItemCollectionItem]) -> Signal<Void, NoError> {
|
||||||
|
return postbox.modify { modifier -> Void in
|
||||||
|
let namespace: SynchronizeInstalledStickerPacksOperationNamespace?
|
||||||
|
switch info.id.namespace {
|
||||||
|
case Namespaces.ItemCollection.CloudStickerPacks:
|
||||||
|
namespace = .stickers
|
||||||
|
case Namespaces.ItemCollection.CloudMaskPacks:
|
||||||
|
namespace = .masks
|
||||||
|
default:
|
||||||
|
namespace = nil
|
||||||
|
}
|
||||||
|
if let namespace = namespace {
|
||||||
|
addSynchronizeInstalledStickerPacksOperation(modifier: modifier, namespace: namespace)
|
||||||
|
var updatedInfos = modifier.getItemCollectionsInfos(namespace: info.id.namespace).map { $0.1 as! StickerPackCollectionInfo }
|
||||||
|
if let index = updatedInfos.index(where: { $0.id == info.id }) {
|
||||||
|
let currentInfo = updatedInfos[index]
|
||||||
|
updatedInfos.remove(at: index)
|
||||||
|
updatedInfos.insert(currentInfo, at: 0)
|
||||||
|
} else {
|
||||||
|
updatedInfos.insert(info, at: 0)
|
||||||
|
modifier.replaceItemCollectionItems(collectionId: info.id, items: items)
|
||||||
|
}
|
||||||
|
modifier.replaceItemCollectionInfos(namespace: info.id.namespace, itemCollectionInfos: updatedInfos.map { ($0.id, $0) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public func removeStickerPackInteractively(postbox: Postbox, id: ItemCollectionId) -> Signal<Void, NoError> {
|
||||||
|
return postbox.modify { modifier -> Void in
|
||||||
|
let namespace: SynchronizeInstalledStickerPacksOperationNamespace?
|
||||||
|
switch id.namespace {
|
||||||
|
case Namespaces.ItemCollection.CloudStickerPacks:
|
||||||
|
namespace = .stickers
|
||||||
|
case Namespaces.ItemCollection.CloudMaskPacks:
|
||||||
|
namespace = .masks
|
||||||
|
default:
|
||||||
|
namespace = nil
|
||||||
|
}
|
||||||
|
if let namespace = namespace {
|
||||||
|
addSynchronizeInstalledStickerPacksOperation(modifier: modifier, namespace: namespace)
|
||||||
|
modifier.removeItemCollection(collectionId: id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -49,7 +49,7 @@ public func requestStickerSet(account:Account, reference: StickerPackReference)
|
|||||||
switch result {
|
switch result {
|
||||||
case let .stickerSet(set, packs, documents):
|
case let .stickerSet(set, packs, documents):
|
||||||
|
|
||||||
info = StickerPackCollectionInfo(apiSet: set)
|
info = StickerPackCollectionInfo(apiSet: set, namespace: Namespaces.ItemCollection.CloudStickerPacks)
|
||||||
|
|
||||||
switch set {
|
switch set {
|
||||||
case let .stickerSet(data):
|
case let .stickerSet(data):
|
||||||
@ -150,7 +150,7 @@ public func installStickerSetInteractively(account:Account, info: StickerPackCol
|
|||||||
apiDocuments = covers
|
apiDocuments = covers
|
||||||
}
|
}
|
||||||
|
|
||||||
let info = StickerPackCollectionInfo(apiSet: apiSet)
|
let info = StickerPackCollectionInfo(apiSet: apiSet, namespace: Namespaces.ItemCollection.CloudStickerPacks)
|
||||||
|
|
||||||
var items:[StickerPackItem] = []
|
var items:[StickerPackItem] = []
|
||||||
for apiDocument in apiDocuments {
|
for apiDocument in apiDocuments {
|
||||||
|
|||||||
@ -31,17 +31,24 @@ final class SynchronizeInstalledStickerPacksOperation: Coding {
|
|||||||
func addSynchronizeInstalledStickerPacksOperation(modifier: Modifier, namespace: SynchronizeInstalledStickerPacksOperationNamespace) {
|
func addSynchronizeInstalledStickerPacksOperation(modifier: Modifier, namespace: SynchronizeInstalledStickerPacksOperationNamespace) {
|
||||||
var updateLocalIndex: Int32?
|
var updateLocalIndex: Int32?
|
||||||
let tag: PeerOperationLogTag
|
let tag: PeerOperationLogTag
|
||||||
|
let itemCollectionNamespace: ItemCollectionId.Namespace
|
||||||
switch namespace {
|
switch namespace {
|
||||||
case .stickers:
|
case .stickers:
|
||||||
tag = OperationLogTags.SynchronizeInstalledStickerPacks
|
tag = OperationLogTags.SynchronizeInstalledStickerPacks
|
||||||
|
itemCollectionNamespace = Namespaces.ItemCollection.CloudStickerPacks
|
||||||
case .masks:
|
case .masks:
|
||||||
tag = OperationLogTags.SynchronizeInstalledMasks
|
tag = OperationLogTags.SynchronizeInstalledMasks
|
||||||
|
itemCollectionNamespace = Namespaces.ItemCollection.CloudMaskPacks
|
||||||
}
|
}
|
||||||
|
var previousSrickerPackIds: [ItemCollectionId]?
|
||||||
modifier.operationLogEnumerateEntries(peerId: PeerId(namespace: 0, id: 0), tag: tag, { entry in
|
modifier.operationLogEnumerateEntries(peerId: PeerId(namespace: 0, id: 0), tag: tag, { entry in
|
||||||
updateLocalIndex = entry.tagLocalIndex
|
updateLocalIndex = entry.tagLocalIndex
|
||||||
|
if let operation = entry.contents as? SynchronizeInstalledStickerPacksOperation {
|
||||||
|
previousSrickerPackIds = operation.previousPacks
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
let operationContents = SynchronizePinnedChatsOperation(previousPeerIds: modifier.getPinnedPeerIds())
|
let operationContents = SynchronizeInstalledStickerPacksOperation(previousPacks: previousSrickerPackIds ?? modifier.getItemCollectionsInfos(namespace: itemCollectionNamespace).map { $0.0 })
|
||||||
if let updateLocalIndex = updateLocalIndex {
|
if let updateLocalIndex = updateLocalIndex {
|
||||||
let _ = modifier.operationLogRemoveEntry(peerId: PeerId(namespace: 0, id: 0), tag: tag, tagLocalIndex: updateLocalIndex)
|
let _ = modifier.operationLogRemoveEntry(peerId: PeerId(namespace: 0, id: 0), tag: tag, tagLocalIndex: updateLocalIndex)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user