mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-25 17:43:18 +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 */; };
|
||||
D0528E6A1E65DD2100E2FEF5 /* 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 */; };
|
||||
D0561DE41E5737FC00E6B9E9 /* UpdatePeerInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0561DE21E5737FC00E6B9E9 /* UpdatePeerInfo.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 */; };
|
||||
D0BC387B1E40D2880044D6FE /* 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 */; };
|
||||
D0BEAF5E1E54941B00BD963D /* Authorization.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEAF5C1E54941B00BD963D /* Authorization.swift */; };
|
||||
D0BEAF601E54ACF900BD963D /* 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 */; };
|
||||
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 */; };
|
||||
D0DC35501DE36900000195EB /* ChatContextResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DC354F1DE36900000195EB /* ChatContextResult.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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -686,9 +693,11 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -786,6 +795,8 @@
|
||||
D01D6BF81E42A713006151C6 /* SearchStickers.swift */,
|
||||
D049EAD71E43DAD200A2CD3A /* ManagedRecentStickers.swift */,
|
||||
C251D7421E65E50500283EDE /* StickerSetInstallation.swift */,
|
||||
D0D748011E7AE98B00F4B1F6 /* StickerPackInteractiveOperations.swift */,
|
||||
D05452061E7B5093006EEF19 /* LoadedStickerpack.swift */,
|
||||
);
|
||||
name = "Sticker Management";
|
||||
sourceTree = "<group>";
|
||||
@ -1001,6 +1012,7 @@
|
||||
D03B0D571D631A6900955575 /* MultipartFetch.swift */,
|
||||
D03C53761DAFF20F004C17B3 /* MultipartUpload.swift */,
|
||||
D03B0D581D631A6900955575 /* Network.swift */,
|
||||
D0BE383D1E7C5995000079AF /* MediaPool.swift */,
|
||||
D03B0D591D631A6900955575 /* Serialization.swift */,
|
||||
);
|
||||
name = Network;
|
||||
@ -1440,6 +1452,7 @@
|
||||
D08774FE1E3E3A3500A97350 /* GlobalNotificationSettings.swift in Sources */,
|
||||
D00C7CCF1E3628180080C3D5 /* UpdateCachedChannelParticipants.swift in Sources */,
|
||||
D03B0CB91D62233400955575 /* Either.swift in Sources */,
|
||||
D0D748021E7AE98B00F4B1F6 /* StickerPackInteractiveOperations.swift in Sources */,
|
||||
D03B0CBD1D62234300955575 /* Regex.swift in Sources */,
|
||||
D03B0D661D631A8B00955575 /* AccountSettings.swift in Sources */,
|
||||
D0B843B91DA7FF30005F29E1 /* NBMetadataCoreTest.m in Sources */,
|
||||
@ -1514,6 +1527,7 @@
|
||||
D03B0CF91D62250800955575 /* TelegramMediaMap.swift in Sources */,
|
||||
D0BC38791E40BAF20044D6FE /* SynchronizePinnedChatsOperation.swift in Sources */,
|
||||
D050F2101E48AB0600988324 /* InteractivePhoneFormatter.swift in Sources */,
|
||||
D0BE383E1E7C5995000079AF /* MediaPool.swift in Sources */,
|
||||
D03B0D671D631A8B00955575 /* AccountViewTracker.swift in Sources */,
|
||||
D0B843BB1DA7FF30005F29E1 /* NBMetadataCoreTestMapper.m in Sources */,
|
||||
D03B0D101D62255C00955575 /* UpdatesApiUtils.swift in Sources */,
|
||||
@ -1535,6 +1549,7 @@
|
||||
D0FA8BB91E2240B4001E855B /* SecretChatIncomingDecryptedOperation.swift in Sources */,
|
||||
D0561DE31E5737FC00E6B9E9 /* UpdatePeerInfo.swift in Sources */,
|
||||
D0DF0C8A1D819C7E008AEB01 /* JoinChannel.swift in Sources */,
|
||||
D05452071E7B5093006EEF19 /* LoadedStickerpack.swift in Sources */,
|
||||
D0F7AB2F1DCF507E009AD9A1 /* ReplyMarkupMessageAttribute.swift in Sources */,
|
||||
D0B843971DA7FBBC005F29E1 /* ChangePeerNotificationSettings.swift in Sources */,
|
||||
D0448CA21E291B14005A61A7 /* FetchSecretFileResource.swift in Sources */,
|
||||
@ -1659,6 +1674,7 @@
|
||||
D050F26E1E4A5B6D00988324 /* RemovePeerChat.swift in Sources */,
|
||||
D0613FD81E606B3B00202CDB /* ConvertGroupToSupergroup.swift in Sources */,
|
||||
D01D6BFA1E42A718006151C6 /* SearchStickers.swift in Sources */,
|
||||
D0D748031E7AE98B00F4B1F6 /* StickerPackInteractiveOperations.swift in Sources */,
|
||||
C2A315C01E2E776A00D89000 /* RequestStartBot.swift in Sources */,
|
||||
D0F7B1EA1E045C87007EB8A5 /* ChangePeerNotificationSettings.swift in Sources */,
|
||||
D0B418A71D7E0592004562A4 /* Fetch.swift in Sources */,
|
||||
@ -1733,6 +1749,7 @@
|
||||
D001F3E81E128A1C007A8C60 /* ChannelState.swift in Sources */,
|
||||
C2366C8A1E4F40480097CCFF /* SupportPeerId.swift in Sources */,
|
||||
D0B844451DAB91FD005F29E1 /* AccountViewTracker.swift in Sources */,
|
||||
D0BE383F1E7C5995000079AF /* MediaPool.swift in Sources */,
|
||||
D050F2601E4A5AD500988324 /* AutoremoveTimeoutMessageAttribute.swift in Sources */,
|
||||
D049EAD91E43DAD200A2CD3A /* ManagedRecentStickers.swift in Sources */,
|
||||
D0B418A61D7E0592004562A4 /* CloudFileMediaResource.swift in Sources */,
|
||||
@ -1754,6 +1771,7 @@
|
||||
D0B8444B1DAB91FD005F29E1 /* ManagedSynchronizePeerReadStates.swift in Sources */,
|
||||
D073CE6C1DCBCF17007511FD /* TextEntitiesMessageAttribute.swift in Sources */,
|
||||
D03C53751DAD5CA9004C17B3 /* TelegramUserPresence.swift in Sources */,
|
||||
D05452081E7B5093006EEF19 /* LoadedStickerpack.swift in Sources */,
|
||||
D0561DE41E5737FC00E6B9E9 /* UpdatePeerInfo.swift in Sources */,
|
||||
D0DC35521DE36908000195EB /* ChatContextResult.swift in Sources */,
|
||||
D0F7AB301DCF507E009AD9A1 /* ReplyMarkupMessageAttribute.swift in Sources */,
|
||||
|
||||
@ -99,6 +99,7 @@ public func ==(lhs: AuthorizedAccountState.State, rhs: AuthorizedAccountState.St
|
||||
}
|
||||
|
||||
public class UnauthorizedAccount {
|
||||
public let apiId: Int32
|
||||
public let id: AccountRecordId
|
||||
public let appGroupPath: String
|
||||
public let basePath: String
|
||||
@ -112,7 +113,8 @@ public class UnauthorizedAccount {
|
||||
|
||||
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.appGroupPath = appGroupPath
|
||||
self.basePath = basePath
|
||||
@ -143,9 +145,9 @@ public class UnauthorizedAccount {
|
||||
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
|
||||
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())
|
||||
return updated
|
||||
}
|
||||
@ -212,6 +214,7 @@ private var declaredEncodables: Void = {
|
||||
declareEncodable(OutgoingContentInfoMessageAttribute.self, f: { OutgoingContentInfoMessageAttribute(decoder: $0) })
|
||||
declareEncodable(ConsumableContentMessageAttribute.self, f: { ConsumableContentMessageAttribute(decoder: $0) })
|
||||
declareEncodable(TelegramMediaGame.self, f: { TelegramMediaGame(decoder: $0) })
|
||||
declareEncodable(SynchronizeInstalledStickerPacksOperation.self, f: { SynchronizeInstalledStickerPacksOperation(decoder: $0) })
|
||||
|
||||
return
|
||||
}()
|
||||
@ -224,7 +227,7 @@ private func accountRecordIdPathName(_ id: AccountRecordId) -> String {
|
||||
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
|
||||
let _ = declaredEncodables
|
||||
|
||||
@ -258,12 +261,12 @@ public func accountWithId(_ id: AccountRecordId, appGroupPath: String, testingEn
|
||||
if let accountState = accountState {
|
||||
switch accountState {
|
||||
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
|
||||
.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:
|
||||
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
|
||||
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
|
||||
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
|
||||
#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
|
||||
|> mapToSignal { _ -> Signal<Void, NoError> in
|
||||
return .complete()
|
||||
@ -490,7 +493,7 @@ public class Account {
|
||||
appSandbox = .boolTrue
|
||||
#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
|
||||
|> mapToSignal { _ -> Signal<Void, NoError> in
|
||||
return .complete()
|
||||
@ -537,6 +540,8 @@ public class Account {
|
||||
self.managedOperationsDisposable.add(managedAutoremoveMessageOperations(postbox: self.postbox).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(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(managedRecentGifs(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
|
||||
}
|
||||
|
||||
enum AccountStateUpdateStickerPacksOperation {
|
||||
case add(Api.messages.StickerSet)
|
||||
case reorder(SynchronizeInstalledStickerPacksOperationNamespace, [Int64])
|
||||
case sync
|
||||
}
|
||||
|
||||
enum AccountStateMutationOperation {
|
||||
case AddMessages([StoreMessage], AddMessagesLocation)
|
||||
case DeleteMessagesWithGlobalIds([Int32])
|
||||
@ -60,6 +66,8 @@ enum AccountStateMutationOperation {
|
||||
case AddPeerInputActivity(chatPeerId: PeerId, peerId: PeerId?, activity: PeerInputActivity?)
|
||||
case UpdatePinnedPeerIds(AccountStateUpdatePinnerPeerIdsOperation)
|
||||
case ReadGlobalMessageContents([Int32])
|
||||
case UpdateMessageImpressionCount(MessageId, Int32)
|
||||
case UpdateInstalledStickerPacks(AccountStateUpdateStickerPacksOperation)
|
||||
}
|
||||
|
||||
struct AccountMutableState {
|
||||
@ -232,9 +240,17 @@ struct AccountMutableState {
|
||||
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) {
|
||||
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
|
||||
case let .AddMessages(messages, _):
|
||||
for message in messages {
|
||||
|
||||
@ -14,7 +14,7 @@ private enum AccountKind {
|
||||
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()
|
||||
|> distinctUntilChanged(isEqual: { lhs, rhs in
|
||||
return lhs == rhs
|
||||
@ -23,7 +23,7 @@ public func currentAccount(manager: AccountManager, appGroupPath: String, testin
|
||||
if let id = id {
|
||||
let reload = ValuePromise<Bool>(true, ignoreRepeated: false)
|
||||
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
|
||||
let postbox: Postbox
|
||||
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
|
||||
let loggedOutAccounts = Atomic<[AccountRecordId: MetaDisposable]>(value: [:])
|
||||
let disposable = accountManager.accountRecords().start(next: { view in
|
||||
@ -139,7 +139,7 @@ public func managedCleanupAccounts(accountManager: AccountManager, appGroupPath:
|
||||
disposable.dispose()
|
||||
}
|
||||
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> {
|
||||
return accountWithId(id, appGroupPath: appGroupPath, testingEnvironment: false)
|
||||
private func cleanupAccount(apiId: Int32, accountManager: AccountManager, id: AccountRecordId, appGroupPath: String) -> Signal<Void, NoError> {
|
||||
return accountWithId(apiId: apiId, id: id, appGroupPath: appGroupPath, testingEnvironment: false)
|
||||
|> mapToSignal { account -> Signal<Void, NoError> in
|
||||
switch account {
|
||||
case .left:
|
||||
|
||||
@ -968,6 +968,20 @@ private func finalStateWithUpdates(account: Account, state: AccountMutableState,
|
||||
}
|
||||
case let .updateReadMessagesContents(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:
|
||||
break
|
||||
}
|
||||
@ -1301,7 +1315,7 @@ private func optimizedOperations(_ operations: [AccountStateMutationOperation])
|
||||
var currentAddMessages: OptimizeAddMessagesState?
|
||||
for operation in operations {
|
||||
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 {
|
||||
result.append(.AddMessages(currentAddMessages.messages, currentAddMessages.location))
|
||||
}
|
||||
@ -1349,6 +1363,8 @@ func replayFinalState(accountPeerId: PeerId, mediaBox: MediaBox, modifier: Modif
|
||||
var updatedSecretChatTypingActivities = Set<PeerId>()
|
||||
var updatedWebpages: [MediaId: TelegramMediaWebpage] = [:]
|
||||
|
||||
var stickerPackOperations: [AccountStateUpdateStickerPacksOperation] = []
|
||||
|
||||
for operation in optimizedOperations(finalState.state.operations) {
|
||||
switch operation {
|
||||
case let .AddMessages(messages, location):
|
||||
@ -1478,6 +1494,144 @@ func replayFinalState(accountPeerId: PeerId, mediaBox: MediaBox, modifier: Modif
|
||||
for messageId in modifier.messageIdsForGlobalIds(globalIds) {
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
let tag: PeerOperationLogTag
|
||||
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> {
|
||||
return .complete()
|
||||
private func hashForStickerPackInfos(_ infos: [StickerPackCollectionInfo]) -> Int32 {
|
||||
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.completed = completed
|
||||
|
||||
if let hintFileSize = hintFileSize, hintFileSize > 1 * 1024 * 1024 {
|
||||
if let hintFileSize = hintFileSize, hintFileSize > 5 * 1024 * 1024 {
|
||||
self.defaultPartSize = 512 * 1024
|
||||
self.bigTotalParts = (hintFileSize / self.defaultPartSize) + (hintFileSize % self.defaultPartSize == 0 ? 0 : 1)
|
||||
} else {
|
||||
|
||||
@ -94,7 +94,7 @@ private var registeredLoggingFunctions: Void = {
|
||||
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
|
||||
Queue.concurrentDefaultQueue().async {
|
||||
let _ = registeredLoggingFunctions
|
||||
@ -103,7 +103,7 @@ func initializedNetwork(datacenterId: Int, keychain: Keychain, networkUsageInfoP
|
||||
|
||||
let apiEnvironment = MTApiEnvironment()
|
||||
|
||||
apiEnvironment.apiId = 1
|
||||
apiEnvironment.apiId = apiId
|
||||
apiEnvironment.layer = NSNumber(value: Int(serialization.currentLayer()))
|
||||
|
||||
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> {
|
||||
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)
|
||||
|> take(1)
|
||||
|> map { view -> Int32 in
|
||||
@ -38,7 +43,7 @@ func manageStickerPacks(network: Network, postbox: Postbox) -> Signal<Void, NoEr
|
||||
switch result {
|
||||
case let .allStickers(_, sets):
|
||||
for apiSet in sets {
|
||||
stickerPackInfos.append(StickerPackCollectionInfo(apiSet: apiSet))
|
||||
stickerPackInfos.append(StickerPackCollectionInfo(apiSet: apiSet, namespace: Namespaces.ItemCollection.CloudStickerPacks))
|
||||
}
|
||||
case .allStickersNotModified:
|
||||
break
|
||||
@ -53,7 +58,6 @@ func manageStickerPacks(network: Network, postbox: Postbox) -> Signal<Void, NoEr
|
||||
switch result {
|
||||
case let .stickerSet(_, packs, documents):
|
||||
var indexKeysByFile: [MediaId: [MemoryBuffer]] = [:]
|
||||
//stickerPack#12b299d4 emoticon:string documents:Vector<long> = StickerPack;
|
||||
for pack in packs {
|
||||
switch pack {
|
||||
case let .stickerPack(text, fileIds):
|
||||
|
||||
@ -134,7 +134,7 @@ public final class StickerPackItem: ItemCollectionItem, Equatable {
|
||||
}
|
||||
|
||||
extension StickerPackCollectionInfo {
|
||||
convenience init(apiSet: Api.StickerSet) {
|
||||
convenience init(apiSet: Api.StickerSet, namespace: ItemCollectionId.Namespace) {
|
||||
switch apiSet {
|
||||
case let .stickerSet(flags, id, accessHash, title, shortName, count, nHash):
|
||||
var setFlags: StickerPackCollectionInfoFlags = StickerPackCollectionInfoFlags()
|
||||
@ -144,7 +144,7 @@ extension StickerPackCollectionInfo {
|
||||
if (flags & (1 << 3)) != 0 {
|
||||
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 {
|
||||
case let .stickerSet(set, packs, documents):
|
||||
|
||||
info = StickerPackCollectionInfo(apiSet: set)
|
||||
info = StickerPackCollectionInfo(apiSet: set, namespace: Namespaces.ItemCollection.CloudStickerPacks)
|
||||
|
||||
switch set {
|
||||
case let .stickerSet(data):
|
||||
@ -150,7 +150,7 @@ public func installStickerSetInteractively(account:Account, info: StickerPackCol
|
||||
apiDocuments = covers
|
||||
}
|
||||
|
||||
let info = StickerPackCollectionInfo(apiSet: apiSet)
|
||||
let info = StickerPackCollectionInfo(apiSet: apiSet, namespace: Namespaces.ItemCollection.CloudStickerPacks)
|
||||
|
||||
var items:[StickerPackItem] = []
|
||||
for apiDocument in apiDocuments {
|
||||
|
||||
@ -31,17 +31,24 @@ final class SynchronizeInstalledStickerPacksOperation: Coding {
|
||||
func addSynchronizeInstalledStickerPacksOperation(modifier: Modifier, namespace: SynchronizeInstalledStickerPacksOperationNamespace) {
|
||||
var updateLocalIndex: Int32?
|
||||
let tag: PeerOperationLogTag
|
||||
let itemCollectionNamespace: ItemCollectionId.Namespace
|
||||
switch namespace {
|
||||
case .stickers:
|
||||
tag = OperationLogTags.SynchronizeInstalledStickerPacks
|
||||
itemCollectionNamespace = Namespaces.ItemCollection.CloudStickerPacks
|
||||
case .masks:
|
||||
tag = OperationLogTags.SynchronizeInstalledMasks
|
||||
itemCollectionNamespace = Namespaces.ItemCollection.CloudMaskPacks
|
||||
}
|
||||
var previousSrickerPackIds: [ItemCollectionId]?
|
||||
modifier.operationLogEnumerateEntries(peerId: PeerId(namespace: 0, id: 0), tag: tag, { entry in
|
||||
updateLocalIndex = entry.tagLocalIndex
|
||||
if let operation = entry.contents as? SynchronizeInstalledStickerPacksOperation {
|
||||
previousSrickerPackIds = operation.previousPacks
|
||||
}
|
||||
return false
|
||||
})
|
||||
let operationContents = SynchronizePinnedChatsOperation(previousPeerIds: modifier.getPinnedPeerIds())
|
||||
let operationContents = SynchronizeInstalledStickerPacksOperation(previousPacks: previousSrickerPackIds ?? modifier.getItemCollectionsInfos(namespace: itemCollectionNamespace).map { $0.0 })
|
||||
if let updateLocalIndex = updateLocalIndex {
|
||||
let _ = modifier.operationLogRemoveEntry(peerId: PeerId(namespace: 0, id: 0), tag: tag, tagLocalIndex: updateLocalIndex)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user