Merge branch 'master' of gitlab.com:peter-iakovlev/TelegramCore

This commit is contained in:
overtake 2018-11-20 19:07:32 +04:00
commit f59b9e432e
11 changed files with 313 additions and 6 deletions

View File

@ -331,6 +331,10 @@
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 */; };
D0529D2421A4123400D7C3C4 /* SynchronizeRecentlyUsedMediaOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0529D2321A4123400D7C3C4 /* SynchronizeRecentlyUsedMediaOperations.swift */; };
D0529D2521A4123400D7C3C4 /* SynchronizeRecentlyUsedMediaOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0529D2321A4123400D7C3C4 /* SynchronizeRecentlyUsedMediaOperations.swift */; };
D0529D2721A4141800D7C3C4 /* ManagedSynchronizeRecentlyUsedMediaOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0529D2621A4141800D7C3C4 /* ManagedSynchronizeRecentlyUsedMediaOperations.swift */; };
D0529D2821A4141800D7C3C4 /* ManagedSynchronizeRecentlyUsedMediaOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0529D2621A4141800D7C3C4 /* ManagedSynchronizeRecentlyUsedMediaOperations.swift */; };
D053B3FB1F1651FA00E2D58A /* MonotonicTime.h in Headers */ = {isa = PBXBuildFile; fileRef = D053B3F91F1651FA00E2D58A /* MonotonicTime.h */; };
D053B3FC1F1651FA00E2D58A /* MonotonicTime.m in Sources */ = {isa = PBXBuildFile; fileRef = D053B3FA1F1651FA00E2D58A /* MonotonicTime.m */; };
D053B3FE1F16534400E2D58A /* MonotonicTime.swift in Sources */ = {isa = PBXBuildFile; fileRef = D053B3FD1F16534400E2D58A /* MonotonicTime.swift */; };
@ -942,6 +946,8 @@
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>"; };
D0529D2321A4123400D7C3C4 /* SynchronizeRecentlyUsedMediaOperations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SynchronizeRecentlyUsedMediaOperations.swift; sourceTree = "<group>"; };
D0529D2621A4141800D7C3C4 /* ManagedSynchronizeRecentlyUsedMediaOperations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManagedSynchronizeRecentlyUsedMediaOperations.swift; sourceTree = "<group>"; };
D053B3F91F1651FA00E2D58A /* MonotonicTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MonotonicTime.h; sourceTree = "<group>"; };
D053B3FA1F1651FA00E2D58A /* MonotonicTime.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MonotonicTime.m; sourceTree = "<group>"; };
D053B3FD1F16534400E2D58A /* MonotonicTime.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MonotonicTime.swift; sourceTree = "<group>"; };
@ -1490,6 +1496,8 @@
D00422D221677F4500719B67 /* ManagedAccountPresence.swift */,
D0A8998E217A37A000759EE6 /* NotificationAutolockReportManager.swift */,
09028385218E5DBB0067EFBD /* ManagedVoipConfigurationUpdates.swift */,
D0529D2321A4123400D7C3C4 /* SynchronizeRecentlyUsedMediaOperations.swift */,
D0529D2621A4141800D7C3C4 /* ManagedSynchronizeRecentlyUsedMediaOperations.swift */,
);
name = State;
sourceTree = "<group>";
@ -2397,6 +2405,7 @@
D058E0D11E8AD65C00A442DE /* StandaloneSendMessage.swift in Sources */,
D0BC38751E40A7F70044D6FE /* RemovePeerChat.swift in Sources */,
D09F9DC820767D2C00DB4DE1 /* Api3.swift in Sources */,
D0529D2721A4141800D7C3C4 /* ManagedSynchronizeRecentlyUsedMediaOperations.swift in Sources */,
D0AB0B961D662F0B002C78E7 /* ManagedChatListHoles.swift in Sources */,
D05A32E41E6F0B2E002760B4 /* RecentAccountSessions.swift in Sources */,
D01A21A61F38CDC700DDA104 /* SynchronizeSavedStickersOperation.swift in Sources */,
@ -2431,6 +2440,7 @@
D0B85AC51F6B2B9400B8B5CE /* RecentlyUsedHashtags.swift in Sources */,
D0B843C31DA7FF30005F29E1 /* NBPhoneMetaDataGenerator.m in Sources */,
C2366C861E4F403C0097CCFF /* AddressNames.swift in Sources */,
D0529D2421A4123400D7C3C4 /* SynchronizeRecentlyUsedMediaOperations.swift in Sources */,
D0FA08BB2046B37900DD23FC /* ContentPrivacySettings.swift in Sources */,
D0F8C39D20178B9B00236FC5 /* GroupFeedPeers.swift in Sources */,
D0B843C11DA7FF30005F29E1 /* NBPhoneMetaData.m in Sources */,
@ -2673,6 +2683,7 @@
D001F3E91E128A1C007A8C60 /* SecretChatState.swift in Sources */,
D08F4A6A1E79CECB00A2AA15 /* ManagedSynchronizeInstalledStickerPacksOperations.swift in Sources */,
D0B8444B1DAB91FD005F29E1 /* ManagedSynchronizePeerReadStates.swift in Sources */,
D0529D2521A4123400D7C3C4 /* SynchronizeRecentlyUsedMediaOperations.swift in Sources */,
D06ECFC920B810D300C576C2 /* TermsOfService.swift in Sources */,
9F06831121A40DEC001D8EDB /* NotificationExceptionsList.swift in Sources */,
D0F8C39E20178B9B00236FC5 /* GroupFeedPeers.swift in Sources */,
@ -2781,6 +2792,7 @@
D0448CA61E29215A005A61A7 /* MediaResourceApiUtils.swift in Sources */,
D001F3F11E128A1C007A8C60 /* SynchronizePeerReadState.swift in Sources */,
D054648F20738626002ECC1E /* SecureIdDriversLicenseValue.swift in Sources */,
D0529D2821A4141800D7C3C4 /* ManagedSynchronizeRecentlyUsedMediaOperations.swift in Sources */,
D050F2641E4A5AEB00988324 /* ManagedSynchronizePinnedChatsOperations.swift in Sources */,
D0575AF21E9FFA5D006F2541 /* SynchronizeSavedGifsOperation.swift in Sources */,
D0528E661E65C82400E2FEF5 /* UpdateContactName.swift in Sources */,

View File

@ -1064,7 +1064,7 @@ public class Account {
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(managedSynchronizeMarkFeaturedStickerPacksAsSeenOperations(postbox: self.postbox, network: self.network).start())
self.managedOperationsDisposable.add(managedRecentStickers(postbox: self.postbox, network: self.network).start())
self.managedOperationsDisposable.add(managedSynchronizeRecentlyUsedMediaOperations(postbox: self.postbox, network: self.network, category: .stickers, revalidationContext: self.mediaReferenceRevalidationContext).start())
self.managedOperationsDisposable.add(managedSynchronizeSavedGifsOperations(postbox: self.postbox, network: self.network, revalidationContext: self.mediaReferenceRevalidationContext).start())
self.managedOperationsDisposable.add(managedSynchronizeSavedStickersOperations(postbox: self.postbox, network: self.network, revalidationContext: self.mediaReferenceRevalidationContext).start())
self.managedOperationsDisposable.add(managedRecentlyUsedInlineBots(postbox: self.postbox, network: self.network, accountPeerId: peerId).start())

View File

@ -87,6 +87,7 @@ private var declaredEncodables: Void = {
declareEncodable(SynchronizeChatInputStateOperation.self, f: { SynchronizeChatInputStateOperation(decoder: $0) })
declareEncodable(SynchronizeSavedGifsOperation.self, f: { SynchronizeSavedGifsOperation(decoder: $0) })
declareEncodable(SynchronizeSavedStickersOperation.self, f: { SynchronizeSavedStickersOperation(decoder: $0) })
declareEncodable(SynchronizeRecentlyUsedMediaOperation.self, f: { SynchronizeRecentlyUsedMediaOperation(decoder: $0) })
declareEncodable(CacheStorageSettings.self, f: { CacheStorageSettings(decoder: $0) })
declareEncodable(LocalizationSettings.self, f: { LocalizationSettings(decoder: $0) })
declareEncodable(LocalizationListState.self, f: { LocalizationListState(decoder: $0) })

View File

@ -203,7 +203,7 @@ public func authorizeWithCode(account: UnauthorizedAccount, code: String, termsO
return .fail(.limitExceeded)
} else if errorDescription == "PHONE_CODE_INVALID" {
return .fail(.invalidCode)
} else if errorDescription == "CODE_HASH_EXPIRED" {
} else if errorDescription == "CODE_HASH_EXPIRED" || errorDescription == "PHONE_CODE_EXPIRED" {
return .fail(.codeExpired)
} else if errorDescription == "PHONE_NUMBER_UNOCCUPIED" {
return .single(.signUp)

View File

@ -71,7 +71,7 @@ private final class ContactSyncManagerImpl {
let timestamp = CFAbsoluteTimeGetCurrent()
let shouldUpdate: Bool
if let lastContactPresencesRequestTimestamp = strongSelf.lastContactPresencesRequestTimestamp {
if timestamp > lastContactPresencesRequestTimestamp + 30.0 * 60.0 {
if timestamp > lastContactPresencesRequestTimestamp + 2.0 * 60.0 {
shouldUpdate = true
} else {
shouldUpdate = false

View File

@ -1018,8 +1018,12 @@ extension InstantPageBlock {
self = .blockQuote(text: RichText(apiText: text), caption: RichText(apiText: caption))
case let .pageBlockPullquote(text, caption):
self = .pullQuote(text: RichText(apiText: text), caption: RichText(apiText: caption))
case let .pageBlockPhoto(_, photoId, caption, url, webpageId):
self = .image(id: MediaId(namespace: Namespaces.Media.CloudImage, id: photoId), caption: InstantPageCaption(apiCaption: caption), url: url, webpageId: webpageId != nil ? MediaId(namespace: Namespaces.Media.CloudWebpage, id: webpageId!) : nil)
case let .pageBlockPhoto(flags, photoId, caption, url, webpageId):
var webpageMediaId: MediaId?
if (flags & (1 << 0)) != 0, let webpageId = webpageId, webpageId != 0 {
webpageMediaId = MediaId(namespace: Namespaces.Media.CloudWebpage, id: webpageId)
}
self = .image(id: MediaId(namespace: Namespaces.Media.CloudImage, id: photoId), caption: InstantPageCaption(apiCaption: caption), url: url, webpageId: webpageMediaId)
case let .pageBlockVideo(flags, videoId, caption):
self = .video(id: MediaId(namespace: Namespaces.Media.CloudFile, id: videoId), caption: InstantPageCaption(apiCaption: caption), autoplay: (flags & (1 << 0)) != 0, loop: (flags & (1 << 1)) != 0)
case let .pageBlockCover(cover):

View File

@ -1195,7 +1195,7 @@ private func sendMessage(postbox: Postbox, network: Network, messageId: MessageI
}
for file in sentStickers {
transaction.addOrMoveToFirstPositionOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudRecentStickers, item: OrderedItemListEntry(id: RecentMediaItemId(file.fileId).rawValue, contents: RecentMediaItem(file)), removeTailIfCountExceeds: 20)
addRecentlyUsedSticker(transaction: transaction, fileReference: .standalone(media: file))
}
}
}

View File

@ -0,0 +1,183 @@
import Foundation
#if os(macOS)
import PostboxMac
import SwiftSignalKitMac
import MtProtoKitMac
#else
import Postbox
import SwiftSignalKit
import MtProtoKitDynamic
#endif
private final class ManagedSynchronizeRecentlyUsedMediaOperationsHelper {
var operationDisposables: [Int32: Disposable] = [:]
func update(_ entries: [PeerMergedOperationLogEntry]) -> (disposeOperations: [Disposable], beginOperations: [(PeerMergedOperationLogEntry, MetaDisposable)]) {
var disposeOperations: [Disposable] = []
var beginOperations: [(PeerMergedOperationLogEntry, MetaDisposable)] = []
var hasRunningOperationForPeerId = Set<PeerId>()
var validMergedIndices = Set<Int32>()
for entry in entries {
if !hasRunningOperationForPeerId.contains(entry.peerId) {
hasRunningOperationForPeerId.insert(entry.peerId)
validMergedIndices.insert(entry.mergedIndex)
if self.operationDisposables[entry.mergedIndex] == nil {
let disposable = MetaDisposable()
beginOperations.append((entry, disposable))
self.operationDisposables[entry.mergedIndex] = disposable
}
}
}
var removeMergedIndices: [Int32] = []
for (mergedIndex, disposable) in self.operationDisposables {
if !validMergedIndices.contains(mergedIndex) {
removeMergedIndices.append(mergedIndex)
disposeOperations.append(disposable)
}
}
for mergedIndex in removeMergedIndices {
self.operationDisposables.removeValue(forKey: mergedIndex)
}
return (disposeOperations, beginOperations)
}
func reset() -> [Disposable] {
let disposables = Array(self.operationDisposables.values)
self.operationDisposables.removeAll()
return disposables
}
}
private func withTakenOperation(postbox: Postbox, peerId: PeerId, tag: PeerOperationLogTag, tagLocalIndex: Int32, _ f: @escaping (Transaction, PeerMergedOperationLogEntry?) -> Signal<Void, NoError>) -> Signal<Void, NoError> {
return postbox.transaction { transaction -> Signal<Void, NoError> in
var result: PeerMergedOperationLogEntry?
transaction.operationLogUpdateEntry(peerId: peerId, tag: tag, tagLocalIndex: tagLocalIndex, { entry in
if let entry = entry, let _ = entry.mergedIndex, entry.contents is SynchronizeRecentlyUsedMediaOperation {
result = entry.mergedEntry!
return PeerOperationLogEntryUpdate(mergedIndex: .none, contents: .none)
} else {
return PeerOperationLogEntryUpdate(mergedIndex: .none, contents: .none)
}
})
return f(transaction, result)
} |> switchToLatest
}
func managedSynchronizeRecentlyUsedMediaOperations(postbox: Postbox, network: Network, category: RecentlyUsedMediaCategory, revalidationContext: MediaReferenceRevalidationContext) -> Signal<Void, NoError> {
return Signal { _ in
let tag: PeerOperationLogTag
switch category {
case .stickers:
tag = OperationLogTags.SynchronizeRecentlyUsedStickers
}
let helper = Atomic<ManagedSynchronizeRecentlyUsedMediaOperationsHelper>(value: ManagedSynchronizeRecentlyUsedMediaOperationsHelper())
let disposable = postbox.mergedOperationLogView(tag: tag, limit: 10).start(next: { view in
let (disposeOperations, beginOperations) = helper.with { helper -> (disposeOperations: [Disposable], beginOperations: [(PeerMergedOperationLogEntry, MetaDisposable)]) in
return helper.update(view.entries)
}
for disposable in disposeOperations {
disposable.dispose()
}
for (entry, disposable) in beginOperations {
let signal = withTakenOperation(postbox: postbox, peerId: entry.peerId, tag: tag, tagLocalIndex: entry.tagLocalIndex, { transaction, entry -> Signal<Void, NoError> in
if let entry = entry {
if let operation = entry.contents as? SynchronizeRecentlyUsedMediaOperation {
return synchronizeRecentlyUsedMedia(transaction: transaction, postbox: postbox, network: network, revalidationContext: revalidationContext, operation: operation)
} else {
assertionFailure()
}
}
return .complete()
})
|> then(postbox.transaction { transaction -> Void in
let _ = transaction.operationLogRemoveEntry(peerId: entry.peerId, tag: tag, tagLocalIndex: entry.tagLocalIndex)
})
disposable.set(signal.start())
}
})
return ActionDisposable {
let disposables = helper.with { helper -> [Disposable] in
return helper.reset()
}
for disposable in disposables {
disposable.dispose()
}
disposable.dispose()
}
}
}
private enum SaveRecentlyUsedMediaError {
case generic
case invalidReference
}
private func synchronizeRecentlyUsedMedia(transaction: Transaction, postbox: Postbox, network: Network, revalidationContext: MediaReferenceRevalidationContext, operation: SynchronizeRecentlyUsedMediaOperation) -> Signal<Void, NoError> {
switch operation.content {
case let .add(id, accessHash, fileReference):
guard let fileReference = fileReference else {
return .complete()
}
let addSticker: (Data) -> Signal<Api.Bool, SaveRecentlyUsedMediaError> = { fileReference in
return network.request(Api.functions.messages.saveRecentSticker(flags: 0, id: .inputDocument(id: id, accessHash: accessHash, fileReference: Buffer(data: fileReference)), unsave: .boolFalse))
|> mapError { error -> SaveRecentlyUsedMediaError in
if error.errorDescription.hasPrefix("FILEREF_INVALID") || error.errorDescription.hasPrefix("FILE_REFERENCE_") {
return .invalidReference
}
return .generic
}
}
let initialSignal: Signal<Api.Bool, SaveRecentlyUsedMediaError>
if let reference = (fileReference.media.resource as? CloudDocumentMediaResource)?.fileReference {
initialSignal = addSticker(reference)
} else {
initialSignal = .fail(.invalidReference)
}
return initialSignal
|> `catch` { error -> Signal<Api.Bool, SaveRecentlyUsedMediaError> in
switch error {
case .generic:
return .fail(.generic)
case .invalidReference:
return revalidateMediaResourceReference(postbox: postbox, network: network, revalidationContext: revalidationContext, info: TelegramCloudMediaResourceFetchInfo(reference: fileReference.resourceReference(fileReference.media.resource), preferBackgroundReferenceRevalidation: false), resource: fileReference.media.resource)
|> mapError { _ -> SaveRecentlyUsedMediaError in
return .generic
}
|> mapToSignal { reference -> Signal<Api.Bool, SaveRecentlyUsedMediaError> in
return addSticker(reference)
}
}
}
|> `catch` { _ -> Signal<Api.Bool, NoError> in
return .complete()
}
|> mapToSignal { _ -> Signal<Void, NoError> in
return .complete()
}
case let .remove(id, accessHash):
return network.request(Api.functions.messages.saveRecentSticker(flags: 0, id: .inputDocument(id: id, accessHash: accessHash, fileReference: Buffer()), unsave: .boolTrue))
|> `catch` { _ -> Signal<Api.Bool, NoError> in
return .single(.boolFalse)
}
|> mapToSignal { _ -> Signal<Void, NoError> in
return .complete()
}
case .sync:
return managedRecentStickers(postbox: postbox, network: network)
}
}

View File

@ -125,6 +125,7 @@ public struct OperationLogTags {
static let SynchronizeSavedStickers = PeerOperationLogTag(value: 14)
static let SynchronizeGroupedPeers = PeerOperationLogTag(value: 15)
static let SynchronizeMarkAllUnseenPersonalMessages = PeerOperationLogTag(value: 16)
static let SynchronizeRecentlyUsedStickers = PeerOperationLogTag(value: 17)
}
public extension PeerSummaryCounterTags {

View File

@ -27,6 +27,7 @@ func manageStickerPacks(network: Network, postbox: Postbox) -> Signal<Void, NoEr
addSynchronizeInstalledStickerPacksOperation(transaction: transaction, namespace: .masks, content: .sync)
addSynchronizeSavedGifsOperation(transaction: transaction, operation: .sync)
addSynchronizeSavedStickersOperation(transaction: transaction, operation: .sync)
addSynchronizeRecentlyUsedMediaOperation(transaction: transaction, category: .stickers, operation: .sync)
} |> then(.complete() |> suspendAwareDelay(1.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart
}

View File

@ -0,0 +1,105 @@
import Foundation
#if os(macOS)
import PostboxMac
import SwiftSignalKitMac
#else
import Postbox
import SwiftSignalKit
#endif
private enum SynchronizeRecentlyUsedMediaOperationContentType: Int32 {
case add
case remove
case sync
}
enum SynchronizeRecentlyUsedMediaOperationContent: PostboxCoding {
case add(id: Int64, accessHash: Int64, fileReference: FileMediaReference?)
case remove(id: Int64, accessHash: Int64)
case sync
init(decoder: PostboxDecoder) {
switch decoder.decodeInt32ForKey("r", orElse: 0) {
case SynchronizeRecentlyUsedMediaOperationContentType.add.rawValue:
self = .add(id: decoder.decodeInt64ForKey("i", orElse: 0), accessHash: decoder.decodeInt64ForKey("h", orElse: 0), fileReference: decoder.decodeAnyObjectForKey("fr", decoder: { FileMediaReference(decoder: $0) }) as? FileMediaReference)
case SynchronizeRecentlyUsedMediaOperationContentType.remove.rawValue:
self = .remove(id: decoder.decodeInt64ForKey("i", orElse: 0), accessHash: decoder.decodeInt64ForKey("h", orElse: 0))
case SynchronizeRecentlyUsedMediaOperationContentType.sync.rawValue:
self = .sync
default:
assertionFailure()
self = .sync
}
}
func encode(_ encoder: PostboxEncoder) {
switch self {
case let .add(id, accessHash, fileReference):
encoder.encodeInt32(SynchronizeRecentlyUsedMediaOperationContentType.add.rawValue, forKey: "r")
encoder.encodeInt64(id, forKey: "i")
encoder.encodeInt64(accessHash, forKey: "h")
if let fileReference = fileReference {
encoder.encodeObjectWithEncoder(fileReference, encoder: fileReference.encode, forKey: "fr")
} else {
encoder.encodeNil(forKey: "fr")
}
case let .remove(id, accessHash):
encoder.encodeInt32(SynchronizeRecentlyUsedMediaOperationContentType.remove.rawValue, forKey: "r")
encoder.encodeInt64(id, forKey: "i")
encoder.encodeInt64(accessHash, forKey: "h")
case .sync:
encoder.encodeInt32(SynchronizeRecentlyUsedMediaOperationContentType.sync.rawValue, forKey: "r")
}
}
}
final class SynchronizeRecentlyUsedMediaOperation: PostboxCoding {
let content: SynchronizeRecentlyUsedMediaOperationContent
init(content: SynchronizeRecentlyUsedMediaOperationContent) {
self.content = content
}
init(decoder: PostboxDecoder) {
self.content = decoder.decodeObjectForKey("c", decoder: { SynchronizeRecentlyUsedMediaOperationContent(decoder: $0) }) as! SynchronizeRecentlyUsedMediaOperationContent
}
func encode(_ encoder: PostboxEncoder) {
encoder.encodeObject(self.content, forKey: "c")
}
}
enum RecentlyUsedMediaCategory {
case stickers
}
func addSynchronizeRecentlyUsedMediaOperation(transaction: Transaction, category: RecentlyUsedMediaCategory, operation: SynchronizeRecentlyUsedMediaOperationContent) {
let tag: PeerOperationLogTag
switch category {
case .stickers:
tag = OperationLogTags.SynchronizeRecentlyUsedStickers
}
let peerId = PeerId(namespace: 0, id: 0)
var topOperation: (SynchronizeRecentlyUsedMediaOperation, Int32)?
transaction.operationLogEnumerateEntries(peerId: peerId, tag: tag, { entry in
if let operation = entry.contents as? SynchronizeRecentlyUsedMediaOperation {
topOperation = (operation, entry.tagLocalIndex)
}
return false
})
if let (topOperation, topLocalIndex) = topOperation, case .sync = topOperation.content {
let _ = transaction.operationLogRemoveEntry(peerId: peerId, tag: tag, tagLocalIndex: topLocalIndex)
}
transaction.operationLogAddEntry(peerId: peerId, tag: tag, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: SynchronizeRecentlyUsedMediaOperation(content: operation))
transaction.operationLogAddEntry(peerId: peerId, tag: tag, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: SynchronizeRecentlyUsedMediaOperation(content: .sync))
}
func addRecentlyUsedSticker(transaction: Transaction, fileReference: FileMediaReference) {
if let resource = fileReference.media.resource as? CloudDocumentMediaResource {
transaction.addOrMoveToFirstPositionOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudRecentStickers, item: OrderedItemListEntry(id: RecentMediaItemId(fileReference.media.fileId).rawValue, contents: RecentMediaItem(fileReference.media)), removeTailIfCountExceeds: 20)
addSynchronizeRecentlyUsedMediaOperation(transaction: transaction, category: .stickers, operation: .add(id: resource.fileId, accessHash: resource.accessHash, fileReference: fileReference))
}
}