mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2026-01-17 09:51:20 +00:00
no message
This commit is contained in:
@@ -473,6 +473,10 @@
|
||||
D0C0B58B1ED9DA6B000F4D2C /* ManagedLocalizationUpdatesOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C0B5891ED9DA6B000F4D2C /* ManagedLocalizationUpdatesOperations.swift */; };
|
||||
D0C0B58D1ED9DC5A000F4D2C /* SynchronizeLocalizationUpdatesOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C0B58C1ED9DC5A000F4D2C /* SynchronizeLocalizationUpdatesOperation.swift */; };
|
||||
D0C0B58E1ED9DC5A000F4D2C /* SynchronizeLocalizationUpdatesOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C0B58C1ED9DC5A000F4D2C /* SynchronizeLocalizationUpdatesOperation.swift */; };
|
||||
D0C27B3F1F4B51D000A4E170 /* CachedStickerPack.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C27B3E1F4B51D000A4E170 /* CachedStickerPack.swift */; };
|
||||
D0C27B401F4B51D000A4E170 /* CachedStickerPack.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C27B3E1F4B51D000A4E170 /* CachedStickerPack.swift */; };
|
||||
D0C27B421F4B58C000A4E170 /* PeerSpecificStickerPack.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C27B411F4B58C000A4E170 /* PeerSpecificStickerPack.swift */; };
|
||||
D0C27B431F4B58C000A4E170 /* PeerSpecificStickerPack.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C27B411F4B58C000A4E170 /* PeerSpecificStickerPack.swift */; };
|
||||
D0C48F391E8138DF0075317D /* ArchivedStickerPacksInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C48F381E8138DF0075317D /* ArchivedStickerPacksInfo.swift */; };
|
||||
D0C48F3A1E8138DF0075317D /* ArchivedStickerPacksInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C48F381E8138DF0075317D /* ArchivedStickerPacksInfo.swift */; };
|
||||
D0C48F3C1E8142EF0075317D /* LoadedPeerFromMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C48F3B1E8142EF0075317D /* LoadedPeerFromMessage.swift */; };
|
||||
@@ -839,6 +843,8 @@
|
||||
D0BEAF5F1E54ACF900BD963D /* AccountManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountManager.swift; sourceTree = "<group>"; };
|
||||
D0C0B5891ED9DA6B000F4D2C /* ManagedLocalizationUpdatesOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedLocalizationUpdatesOperations.swift; sourceTree = "<group>"; };
|
||||
D0C0B58C1ED9DC5A000F4D2C /* SynchronizeLocalizationUpdatesOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronizeLocalizationUpdatesOperation.swift; sourceTree = "<group>"; };
|
||||
D0C27B3E1F4B51D000A4E170 /* CachedStickerPack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CachedStickerPack.swift; sourceTree = "<group>"; };
|
||||
D0C27B411F4B58C000A4E170 /* PeerSpecificStickerPack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PeerSpecificStickerPack.swift; sourceTree = "<group>"; };
|
||||
D0C48F381E8138DF0075317D /* ArchivedStickerPacksInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArchivedStickerPacksInfo.swift; sourceTree = "<group>"; };
|
||||
D0C48F3B1E8142EF0075317D /* LoadedPeerFromMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadedPeerFromMessage.swift; sourceTree = "<group>"; };
|
||||
D0C50E331E93A86600F62E39 /* CallSessionManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallSessionManager.swift; sourceTree = "<group>"; };
|
||||
@@ -962,6 +968,8 @@
|
||||
D0D748011E7AE98B00F4B1F6 /* StickerPackInteractiveOperations.swift */,
|
||||
D05452061E7B5093006EEF19 /* LoadedStickerPack.swift */,
|
||||
D0E23DDE1E8082A400B9B6D2 /* ArchivedStickerPacks.swift */,
|
||||
D0C27B3E1F4B51D000A4E170 /* CachedStickerPack.swift */,
|
||||
D0C27B411F4B58C000A4E170 /* PeerSpecificStickerPack.swift */,
|
||||
);
|
||||
name = "Sticker Management";
|
||||
sourceTree = "<group>";
|
||||
@@ -1754,6 +1762,7 @@
|
||||
D02ABC7B1E30058F00CAE539 /* DeleteMessagesInteractively.swift in Sources */,
|
||||
C2E064681ECEEF0A00387BB8 /* TelegramMediaInvoice.swift in Sources */,
|
||||
D0448C9F1E27F5EB005A61A7 /* Random.swift in Sources */,
|
||||
D0C27B3F1F4B51D000A4E170 /* CachedStickerPack.swift in Sources */,
|
||||
D0B843B21DA7FF30005F29E1 /* NBAsYouTypeFormatter.m in Sources */,
|
||||
D07047B71F3DF2CD00F6A8D4 /* ManagedConsumePersonalMessagesActions.swift in Sources */,
|
||||
D03B0CDB1D62245F00955575 /* ApiUtils.swift in Sources */,
|
||||
@@ -1875,6 +1884,7 @@
|
||||
D0177B7B1DF8A16C00A5083A /* SecretChatState.swift in Sources */,
|
||||
D0AAD1AA1E32638500D5B9DE /* ApplyMaxReadIndexInteractively.swift in Sources */,
|
||||
D03B0D5C1D631A6900955575 /* Download.swift in Sources */,
|
||||
D0C27B421F4B58C000A4E170 /* PeerSpecificStickerPack.swift in Sources */,
|
||||
D01749591E1092BC0057C89A /* RequestStartBot.swift in Sources */,
|
||||
D01B27A21E394D8B0022A4C0 /* PrivacySettings.swift in Sources */,
|
||||
D0223A9B1EA5654D00211D94 /* TelegramMediaResource.swift in Sources */,
|
||||
@@ -2052,6 +2062,7 @@
|
||||
D001F3F31E128A1C007A8C60 /* UpdateMessageService.swift in Sources */,
|
||||
D0C50E351E93A86600F62E39 /* CallSessionManager.swift in Sources */,
|
||||
D0B8442D1DAB91E0005F29E1 /* NBMetadataCoreTest.m in Sources */,
|
||||
D0C27B431F4B58C000A4E170 /* PeerSpecificStickerPack.swift in Sources */,
|
||||
D0B844131DAB91CD005F29E1 /* StringFormat.swift in Sources */,
|
||||
D0C0B58E1ED9DC5A000F4D2C /* SynchronizeLocalizationUpdatesOperation.swift in Sources */,
|
||||
D0E35A131DE4C69100BC6096 /* OutgoingChatContextResultMessageAttribute.swift in Sources */,
|
||||
@@ -2183,6 +2194,7 @@
|
||||
D0C0B58B1ED9DA6B000F4D2C /* ManagedLocalizationUpdatesOperations.swift in Sources */,
|
||||
D0B844331DAB91E0005F29E1 /* NBPhoneNumber.m in Sources */,
|
||||
D001F3F51E128A1C007A8C60 /* PendingMessageManager.swift in Sources */,
|
||||
D0C27B401F4B51D000A4E170 /* CachedStickerPack.swift in Sources */,
|
||||
D001F3F61E128A1C007A8C60 /* PendingMessageUploadedContent.swift in Sources */,
|
||||
D01C7ED71EF5E468008305F1 /* ProxySettings.swift in Sources */,
|
||||
C2366C871E4F403C0097CCFF /* AddressNames.swift in Sources */,
|
||||
|
||||
@@ -67,7 +67,7 @@ enum AccountStateMutationOperation {
|
||||
case ReadSecretOutbox(peerId: PeerId, maxTimestamp: Int32, actionTimestamp: Int32)
|
||||
case AddPeerInputActivity(chatPeerId: PeerId, peerId: PeerId?, activity: PeerInputActivity?)
|
||||
case UpdatePinnedPeerIds(AccountStateUpdatePinnerPeerIdsOperation)
|
||||
case ReadGlobalMessageContents([Int32])
|
||||
case ReadMessageContents((PeerId?, [Int32]))
|
||||
case UpdateMessageImpressionCount(MessageId, Int32)
|
||||
case UpdateInstalledStickerPacks(AccountStateUpdateStickerPacksOperation)
|
||||
case UpdateChatInputState(PeerId, SynchronizeableChatInputState?)
|
||||
@@ -245,8 +245,8 @@ struct AccountMutableState {
|
||||
self.addOperation(.UpdatePinnedPeerIds(operation))
|
||||
}
|
||||
|
||||
mutating func addReadGlobalMessagesContents(_ globalIds: [Int32]) {
|
||||
self.addOperation(.ReadGlobalMessageContents(globalIds))
|
||||
mutating func addReadMessagesContents(_ peerIdsAndMessageIds: (PeerId?, [Int32])) {
|
||||
self.addOperation(.ReadMessageContents(peerIdsAndMessageIds))
|
||||
}
|
||||
|
||||
mutating func addUpdateMessageImpressionCount(id: MessageId, count: Int32) {
|
||||
@@ -267,7 +267,7 @@ struct AccountMutableState {
|
||||
|
||||
mutating func addOperation(_ operation: AccountStateMutationOperation) {
|
||||
switch operation {
|
||||
case .AddHole, .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMedia, .ReadOutbox, .MergePeerPresences, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedPeerIds, .ReadGlobalMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateChatInputState, .UpdateCall, .UpdateLangPack:
|
||||
case .AddHole, .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMedia, .ReadOutbox, .MergePeerPresences, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedPeerIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateChatInputState, .UpdateCall, .UpdateLangPack:
|
||||
break
|
||||
case let .AddMessages(messages, _):
|
||||
for message in messages {
|
||||
|
||||
@@ -970,7 +970,9 @@ private func finalStateWithUpdates(account: Account, state: AccountMutableState,
|
||||
updatedState.addUpdatePinnedPeerIds(.sync)
|
||||
}
|
||||
case let .updateReadMessagesContents(messages, _, _):
|
||||
updatedState.addReadGlobalMessagesContents(messages)
|
||||
updatedState.addReadMessagesContents((nil, messages))
|
||||
case let .updateChannelReadMessagesContents(channelId, messages):
|
||||
updatedState.addReadMessagesContents((PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId), 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):
|
||||
@@ -1421,7 +1423,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, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateChatInputState, .UpdateCall, .UpdateLangPack:
|
||||
case .AddHole, .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMedia, .MergeApiChats, .MergeApiUsers, .MergePeerPresences, .UpdatePeer, .ReadInbox, .ReadOutbox, .ResetReadState, .UpdatePeerNotificationSettings, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedPeerIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateChatInputState, .UpdateCall, .UpdateLangPack:
|
||||
if let currentAddMessages = currentAddMessages, !currentAddMessages.messages.isEmpty {
|
||||
result.append(.AddMessages(currentAddMessages.messages, currentAddMessages.location))
|
||||
}
|
||||
@@ -1598,9 +1600,15 @@ func replayFinalState(accountPeerId: PeerId, mediaBox: MediaBox, modifier: Modif
|
||||
case .sync:
|
||||
addSynchronizePinnedChatsOperation(modifier: modifier)
|
||||
}
|
||||
case let .ReadGlobalMessageContents(globalIds):
|
||||
for messageId in modifier.messageIdsForGlobalIds(globalIds) {
|
||||
markMessageContentAsConsumedRemotely(modifier: modifier, messageId: messageId)
|
||||
case let .ReadMessageContents(peerId, messageIds):
|
||||
if let peerId = peerId {
|
||||
for id in messageIds {
|
||||
markMessageContentAsConsumedRemotely(modifier: modifier, messageId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: id))
|
||||
}
|
||||
} else {
|
||||
for messageId in modifier.messageIdsForGlobalIds(messageIds) {
|
||||
markMessageContentAsConsumedRemotely(modifier: modifier, messageId: messageId)
|
||||
}
|
||||
}
|
||||
case let .UpdateMessageImpressionCount(id, count):
|
||||
modifier.updateMessage(id, update: { currentMessage in
|
||||
|
||||
77
TelegramCore/CachedStickerPack.swift
Normal file
77
TelegramCore/CachedStickerPack.swift
Normal file
@@ -0,0 +1,77 @@
|
||||
import Foundation
|
||||
#if os(macOS)
|
||||
import PostboxMac
|
||||
import SwiftSignalKitMac
|
||||
#else
|
||||
import Postbox
|
||||
import SwiftSignalKit
|
||||
#endif
|
||||
|
||||
private final class CachedStickerPack: Coding {
|
||||
let items: [StickerPackItem]
|
||||
let hash: Int32
|
||||
|
||||
init(items: [StickerPackItem], hash: Int32) {
|
||||
self.items = items
|
||||
self.hash = hash
|
||||
}
|
||||
|
||||
init(decoder: Decoder) {
|
||||
self.items = decoder.decodeObjectArrayForKey("it").map { $0 as! StickerPackItem }
|
||||
self.hash = decoder.decodeInt32ForKey("h", orElse: 0)
|
||||
}
|
||||
|
||||
func encode(_ encoder: Encoder) {
|
||||
encoder.encodeObjectArray(self.items, forKey: "it")
|
||||
encoder.encodeInt32(self.hash, forKey: "h")
|
||||
}
|
||||
|
||||
static func cacheKey(_ info: StickerPackCollectionInfo) -> ValueBoxKey {
|
||||
let key = ValueBoxKey(length: 4 + 8)
|
||||
key.setInt32(0, value: info.id.namespace)
|
||||
key.setInt64(4, value: info.id.id)
|
||||
return key
|
||||
}
|
||||
}
|
||||
|
||||
private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 100, highWaterItemCount: 200)
|
||||
|
||||
public func cachedStickerPack(postbox: Postbox, network: Network, info: StickerPackCollectionInfo) -> Signal<(StickerPackCollectionInfo, [ItemCollectionItem])?, NoError> {
|
||||
return postbox.modify { modifier -> Signal<(StickerPackCollectionInfo, [ItemCollectionItem])?, NoError> in
|
||||
if let currentInfo = modifier.getItemCollectionInfo(collectionId: info.id) as? StickerPackCollectionInfo {
|
||||
let items = modifier.getItemCollectionItems(collectionId: info.id)
|
||||
return .single((currentInfo, items))
|
||||
} else {
|
||||
let current: Signal<(StickerPackCollectionInfo, [ItemCollectionItem])?, NoError>
|
||||
var loadRemote = false
|
||||
|
||||
if let cached = modifier.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(info))) as? CachedStickerPack {
|
||||
current = .single((info, cached.items))
|
||||
if cached.hash != info.hash {
|
||||
loadRemote = true
|
||||
}
|
||||
} else {
|
||||
current = .complete()
|
||||
loadRemote = true
|
||||
}
|
||||
|
||||
var signal = current
|
||||
if loadRemote {
|
||||
let appliedRemote = remoteStickerPack(network: network, reference: .id(id: info.id.id, accessHash: info.accessHash))
|
||||
|> mapToSignal { result -> Signal<(StickerPackCollectionInfo, [ItemCollectionItem])?, NoError> in
|
||||
return postbox.modify { modifier -> (StickerPackCollectionInfo, [ItemCollectionItem])? in
|
||||
if let result = result {
|
||||
modifier.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(result.0)), entry: CachedStickerPack(items: result.1.map { $0 as! StickerPackItem }, hash: result.0.hash), collectionSpec: collectionSpec)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
signal = signal |> then(appliedRemote)
|
||||
}
|
||||
|
||||
return signal
|
||||
}
|
||||
} |> switchToLatest
|
||||
}
|
||||
@@ -13,14 +13,22 @@ public func installInteractiveReadMessagesAction(postbox: Postbox, peerId: PeerI
|
||||
|
||||
for message in messages {
|
||||
if case let .Id(id) = message.id {
|
||||
var hasUnconsumedMention = false
|
||||
var hasUnconsumedContent = false
|
||||
|
||||
if message.tags.contains(.unseenPersonalMessage) {
|
||||
inner: for attribute in message.attributes {
|
||||
if let attribute = attribute as? ConsumablePersonalMentionMessageAttribute, !attribute.consumed, !attribute.pending {
|
||||
consumeMessageIds.append(id)
|
||||
break inner
|
||||
hasUnconsumedMention = true
|
||||
} else if let attribute = attribute as? ConsumableContentMessageAttribute, !attribute.consumed {
|
||||
hasUnconsumedContent = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if hasUnconsumedMention && !hasUnconsumedContent {
|
||||
consumeMessageIds.append(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,64 @@ public enum LoadedStickerPack {
|
||||
case result(info: StickerPackCollectionInfo, items: [ItemCollectionItem], installed: Bool)
|
||||
}
|
||||
|
||||
func remoteStickerPack(network: Network, reference: StickerPackReference) -> Signal<(StickerPackCollectionInfo, [ItemCollectionItem])?, NoError> {
|
||||
return network.request(Api.functions.messages.getStickerSet(stickerset: reference.apiInputStickerSet))
|
||||
|> map { Optional($0) }
|
||||
|> `catch` { _ -> Signal<Api.messages.StickerSet?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> map { result -> (StickerPackCollectionInfo, [ItemCollectionItem])? in
|
||||
guard let result = result else {
|
||||
return nil
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 (info, items)
|
||||
}
|
||||
}
|
||||
|
||||
public func loadedStickerPack(account: Account, reference: StickerPackReference) -> Signal<LoadedStickerPack, NoError> {
|
||||
return account.postbox.modify { modifier -> Signal<LoadedStickerPack, NoError> in
|
||||
switch reference {
|
||||
@@ -57,68 +115,21 @@ public func loadedStickerPack(account: Account, reference: StickerPackReference)
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
let signal = remoteStickerPack(network: account.network, reference: reference) |> mapToSignal { result -> Signal<LoadedStickerPack, NoError> in
|
||||
if let result = result {
|
||||
return account.postbox.combinedView(keys: [PostboxViewKey.itemCollectionInfo(id: result.0.id)])
|
||||
|> map { view in
|
||||
if let view = view.views[PostboxViewKey.itemCollectionInfo(id: result.0.id)] as? ItemCollectionInfoView, let info = view.info as? StickerPackCollectionInfo {
|
||||
return .result(info: info, items: result.1, installed: true)
|
||||
} else {
|
||||
return .result(info: result.0, items: result.1, installed: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return .single(.none)
|
||||
}
|
||||
}
|
||||
|
||||
return .single(.fetching) |> then(signal)
|
||||
} |> switchToLatest
|
||||
}
|
||||
|
||||
@@ -37,12 +37,14 @@ final class ManagedDeviceContactEntryContents: Coding {
|
||||
let lastName: String
|
||||
let phoneNumber: String
|
||||
let peerId: PeerId?
|
||||
let importDelayedUntil: Int32?
|
||||
|
||||
init(firstName: String, lastName: String, phoneNumber: String, peerId: PeerId?) {
|
||||
init(firstName: String, lastName: String, phoneNumber: String, peerId: PeerId?, importDelayedUntil: Int32?) {
|
||||
self.firstName = firstName
|
||||
self.lastName = lastName
|
||||
self.phoneNumber = phoneNumber
|
||||
self.peerId = peerId
|
||||
self.importDelayedUntil = importDelayedUntil
|
||||
}
|
||||
|
||||
init(decoder: Decoder) {
|
||||
@@ -54,6 +56,7 @@ final class ManagedDeviceContactEntryContents: Coding {
|
||||
} else {
|
||||
self.peerId = nil
|
||||
}
|
||||
self.importDelayedUntil = decoder.decodeOptionalInt32ForKey("dt")
|
||||
}
|
||||
|
||||
func encode(_ encoder: Encoder) {
|
||||
@@ -65,10 +68,19 @@ final class ManagedDeviceContactEntryContents: Coding {
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "p")
|
||||
}
|
||||
if let importDelayedUntil = self.importDelayedUntil {
|
||||
encoder.encodeInt32(importDelayedUntil, forKey: "dt")
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "dt")
|
||||
}
|
||||
}
|
||||
|
||||
func withUpdatedPeerId(_ peerId: PeerId?) -> ManagedDeviceContactEntryContents {
|
||||
return ManagedDeviceContactEntryContents(firstName: self.firstName, lastName: self.lastName, phoneNumber: self.phoneNumber, peerId: peerId)
|
||||
return ManagedDeviceContactEntryContents(firstName: self.firstName, lastName: self.lastName, phoneNumber: self.phoneNumber, peerId: peerId, importDelayedUntil: self.importDelayedUntil)
|
||||
}
|
||||
|
||||
func withUpdatedImportDelayedUntil(_ importDelayedUntil: Int32?) -> ManagedDeviceContactEntryContents {
|
||||
return ManagedDeviceContactEntryContents(firstName: self.firstName, lastName: self.lastName, phoneNumber: self.phoneNumber, peerId: self.peerId, importDelayedUntil: importDelayedUntil)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +88,7 @@ private func unorderedListEntriesForDeviceContact(_ deviceContact: DeviceContact
|
||||
var entries: [UnorderedItemListEntry] = []
|
||||
for phoneNumber in deviceContact.phoneNumbers {
|
||||
let stringToHash = "\(deviceContact.firstName):\(deviceContact.lastName):\(phoneNumber.number)"
|
||||
entries.append(UnorderedItemListEntry(id: ValueBoxKey(phoneNumber.number), info: UnorderedItemListEntryInfo(hashValue: Int64(stringToHash.hashValue)), contents: ManagedDeviceContactEntryContents(firstName: deviceContact.firstName, lastName: deviceContact.lastName, phoneNumber: phoneNumber.number, peerId: nil)))
|
||||
entries.append(UnorderedItemListEntry(id: ValueBoxKey(phoneNumber.number), info: UnorderedItemListEntryInfo(hashValue: Int64(stringToHash.hashValue)), contents: ManagedDeviceContactEntryContents(firstName: deviceContact.firstName, lastName: deviceContact.lastName, phoneNumber: phoneNumber.number, peerId: nil, importDelayedUntil: nil)))
|
||||
}
|
||||
return entries
|
||||
}
|
||||
@@ -106,9 +118,21 @@ func managedDeviceContacts(postbox: Postbox, network: Network, deviceContacts: S
|
||||
let appliedDifference = postbox.modify { modifier -> Signal<Void, ManagedDeviceContactsError> in
|
||||
let (metaInfo, added, removed, updated) = modifier.unorderedItemListDifference(tag: Namespaces.UnorderedItemList.synchronizedDeviceContacts, updatedEntryInfos: infos)
|
||||
|
||||
let timestamp = Int32(CFAbsoluteTimeGetCurrent())
|
||||
var reimportKeys = Set<ValueBoxKey>()
|
||||
modifier.unorderedItemListScan(tag: Namespaces.UnorderedItemList.synchronizedDeviceContacts, { entry in
|
||||
if let contents = entry.contents as? ManagedDeviceContactEntryContents {
|
||||
if let importDelayedUntil = contents.importDelayedUntil, importDelayedUntil <= timestamp {
|
||||
reimportKeys.insert(entry.id)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
var addedOrUpdatedContacts: [ManagedDeviceContactEntryContents] = []
|
||||
|
||||
for id in added {
|
||||
reimportKeys.remove(id)
|
||||
|
||||
if let entry = entries[id], let contents = entry.contents as? ManagedDeviceContactEntryContents {
|
||||
addedOrUpdatedContacts.append(contents)
|
||||
} else {
|
||||
@@ -117,6 +141,8 @@ func managedDeviceContacts(postbox: Postbox, network: Network, deviceContacts: S
|
||||
}
|
||||
|
||||
for previousEntry in updated {
|
||||
reimportKeys.remove(previousEntry.id)
|
||||
|
||||
if let entry = entries[previousEntry.id], let contents = entry.contents as? ManagedDeviceContactEntryContents {
|
||||
addedOrUpdatedContacts.append(contents)
|
||||
} else {
|
||||
@@ -126,6 +152,8 @@ func managedDeviceContacts(postbox: Postbox, network: Network, deviceContacts: S
|
||||
|
||||
var removedPeerIds: [PeerId] = []
|
||||
for entry in removed {
|
||||
reimportKeys.remove(entry.id)
|
||||
|
||||
if let contents = entry.contents as? ManagedDeviceContactEntryContents {
|
||||
if let peerId = contents.peerId {
|
||||
removedPeerIds.append(peerId)
|
||||
@@ -133,6 +161,12 @@ func managedDeviceContacts(postbox: Postbox, network: Network, deviceContacts: S
|
||||
}
|
||||
}
|
||||
|
||||
for id in reimportKeys {
|
||||
if let entry = entries[id], let contents = entry.contents as? ManagedDeviceContactEntryContents {
|
||||
addedOrUpdatedContacts.append(contents)
|
||||
}
|
||||
}
|
||||
|
||||
return (applyRemovedContacts(postbox: postbox, network: network, peerIds: removedPeerIds)
|
||||
|> map { _ -> ([Peer], [PeerId: PeerPresence], [ValueBoxKey: ManagedDeviceContactEntryContents]) in
|
||||
assertionFailure()
|
||||
@@ -264,9 +298,14 @@ private func applyAddedOrUpdatedContacts(network: Network, contacts: [ManagedDev
|
||||
|
||||
let reimportClientIds = Set(retryContacts)
|
||||
|
||||
let reimportTimestamp = Int32(CFAbsoluteTimeGetCurrent()) + Int32(1 * 60 * 60)
|
||||
for (clientId, contents) in clientIdToContact {
|
||||
if !importedClientIds.contains(clientId) && !reimportClientIds.contains(clientId) {
|
||||
importedContents[ValueBoxKey(contents.phoneNumber)] = contents
|
||||
if !importedClientIds.contains(clientId) {
|
||||
var updatedContents = contents
|
||||
if reimportClientIds.contains(clientId) {
|
||||
updatedContents = updatedContents.withUpdatedImportDelayedUntil(reimportTimestamp)
|
||||
}
|
||||
importedContents[ValueBoxKey(contents.phoneNumber)] = updatedContents
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,9 @@ public func markMessageContentAsConsumedInteractively(postbox: Postbox, messageI
|
||||
|
||||
addSynchronizeConsumeMessageContentsOperation(modifier: modifier, messageIds: [message.id])
|
||||
}
|
||||
break
|
||||
} else if let attribute = updatedAttributes[i] as? ConsumablePersonalMentionMessageAttribute, !attribute.consumed {
|
||||
modifier.setPendingMessageAction(type: .consumeUnseenPersonalMessage, id: messageId, action: ConsumePersonalMessageAction())
|
||||
updatedAttributes[i] = ConsumablePersonalMentionMessageAttribute(consumed: attribute.consumed, pending: true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +80,7 @@ func markMessageContentAsConsumedRemotely(modifier: Modifier, messageId: Message
|
||||
var updateMessage = false
|
||||
var updatedAttributes = message.attributes
|
||||
var updatedMedia = message.media
|
||||
var updatedTags = message.tags
|
||||
|
||||
for i in 0 ..< updatedAttributes.count {
|
||||
if let attribute = updatedAttributes[i] as? ConsumableContentMessageAttribute {
|
||||
@@ -85,7 +88,12 @@ func markMessageContentAsConsumedRemotely(modifier: Modifier, messageId: Message
|
||||
updatedAttributes[i] = ConsumableContentMessageAttribute(consumed: true)
|
||||
updateMessage = true
|
||||
}
|
||||
break
|
||||
} else if let attribute = updatedAttributes[i] as? ConsumablePersonalMentionMessageAttribute, !attribute.consumed {
|
||||
if attribute.pending {
|
||||
modifier.setPendingMessageAction(type: .consumeUnseenPersonalMessage, id: messageId, action: nil)
|
||||
}
|
||||
updatedAttributes[i] = ConsumablePersonalMentionMessageAttribute(consumed: true, pending: false)
|
||||
updatedTags.remove(.unseenPersonalMessage)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +126,7 @@ func markMessageContentAsConsumedRemotely(modifier: Modifier, messageId: Message
|
||||
if let forwardInfo = currentMessage.forwardInfo {
|
||||
storeForwardInfo = StoreMessageForwardInfo(authorId: forwardInfo.author.id, sourceId: forwardInfo.source?.id, sourceMessageId: forwardInfo.sourceMessageId, date: forwardInfo.date, authorSignature: forwardInfo.authorSignature)
|
||||
}
|
||||
return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: updatedAttributes, media: updatedMedia))
|
||||
return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: updatedTags, globalTags: currentMessage.globalTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: updatedAttributes, media: updatedMedia))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ public struct Namespaces {
|
||||
struct CachedItemCollection {
|
||||
public static let resolvedByNamePeers: Int8 = 0
|
||||
public static let cachedTwoStepToken: Int8 = 1
|
||||
public static let cachedStickerPacks: Int8 = 2
|
||||
}
|
||||
|
||||
struct UnorderedItemList {
|
||||
|
||||
36
TelegramCore/PeerSpecificStickerPack.swift
Normal file
36
TelegramCore/PeerSpecificStickerPack.swift
Normal file
@@ -0,0 +1,36 @@
|
||||
import Foundation
|
||||
#if os(macOS)
|
||||
import PostboxMac
|
||||
import SwiftSignalKitMac
|
||||
#else
|
||||
import Postbox
|
||||
import SwiftSignalKit
|
||||
#endif
|
||||
|
||||
private struct WrappedStickerPackCollectionInfo: Equatable {
|
||||
let info: StickerPackCollectionInfo?
|
||||
|
||||
static func ==(lhs: WrappedStickerPackCollectionInfo, rhs: WrappedStickerPackCollectionInfo) -> Bool {
|
||||
return lhs.info == rhs.info
|
||||
}
|
||||
}
|
||||
|
||||
public func peerSpecificStickerPack(postbox: Postbox, network: Network, peerId: PeerId) -> Signal<(StickerPackCollectionInfo, [ItemCollectionItem])?, NoError> {
|
||||
if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
return postbox.combinedView(keys: [.cachedPeerData(peerId: peerId)])
|
||||
|> map { view -> WrappedStickerPackCollectionInfo in
|
||||
let dataView = view.views[.cachedPeerData(peerId: peerId)] as? CachedPeerDataView
|
||||
return WrappedStickerPackCollectionInfo(info: (dataView?.cachedPeerData as? CachedChannelData)?.stickerPack)
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
|> mapToSignal { info -> Signal<(StickerPackCollectionInfo, [ItemCollectionItem])?, NoError> in
|
||||
if let info = info.info {
|
||||
return cachedStickerPack(postbox: postbox, network: network, info: info)
|
||||
} else {
|
||||
return .single(nil)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return .single(nil)
|
||||
}
|
||||
}
|
||||
@@ -428,7 +428,7 @@ extension StoreMessage {
|
||||
}
|
||||
|
||||
for case let file as TelegramMediaFile in medias {
|
||||
if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup {
|
||||
if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup || peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
if file.isVoice {
|
||||
consumableContent = (true, (flags & (1 << 5)) == 0)
|
||||
break
|
||||
|
||||
Reference in New Issue
Block a user