no message

This commit is contained in:
Peter 2017-04-14 16:04:42 +03:00
parent b4a2fe04f6
commit 46a2ead614
10 changed files with 308 additions and 17 deletions

View File

@ -245,6 +245,10 @@
D0561DE41E5737FC00E6B9E9 /* UpdatePeerInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0561DE21E5737FC00E6B9E9 /* UpdatePeerInfo.swift */; };
D0561DEA1E5754FA00E6B9E9 /* ChannelAdmins.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0561DE91E5754FA00E6B9E9 /* ChannelAdmins.swift */; };
D0561DEB1E5754FA00E6B9E9 /* ChannelAdmins.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0561DE91E5754FA00E6B9E9 /* ChannelAdmins.swift */; };
D0575AF11E9FFA5D006F2541 /* SynchronizeSavedGifsOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0575AF01E9FFA5D006F2541 /* SynchronizeSavedGifsOperation.swift */; };
D0575AF21E9FFA5D006F2541 /* SynchronizeSavedGifsOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0575AF01E9FFA5D006F2541 /* SynchronizeSavedGifsOperation.swift */; };
D0575AF41E9FFDDE006F2541 /* ManagedSynchronizeSavedGifsOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0575AF31E9FFDDD006F2541 /* ManagedSynchronizeSavedGifsOperations.swift */; };
D0575AF51E9FFDDE006F2541 /* ManagedSynchronizeSavedGifsOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0575AF31E9FFDDD006F2541 /* ManagedSynchronizeSavedGifsOperations.swift */; };
D058E0D11E8AD65C00A442DE /* StandaloneSendMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D058E0D01E8AD65C00A442DE /* StandaloneSendMessage.swift */; };
D058E0D21E8AD65C00A442DE /* StandaloneSendMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D058E0D01E8AD65C00A442DE /* StandaloneSendMessage.swift */; };
D05A32E11E6F0982002760B4 /* UpdatedAccountPrivacySettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05A32E01E6F0982002760B4 /* UpdatedAccountPrivacySettings.swift */; };
@ -635,6 +639,8 @@
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>"; };
D0575AF01E9FFA5D006F2541 /* SynchronizeSavedGifsOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronizeSavedGifsOperation.swift; sourceTree = "<group>"; };
D0575AF31E9FFDDD006F2541 /* ManagedSynchronizeSavedGifsOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedSynchronizeSavedGifsOperations.swift; sourceTree = "<group>"; };
D058E0D01E8AD65C00A442DE /* StandaloneSendMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StandaloneSendMessage.swift; sourceTree = "<group>"; };
D05A32E01E6F0982002760B4 /* UpdatedAccountPrivacySettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdatedAccountPrivacySettings.swift; sourceTree = "<group>"; };
D05A32E31E6F0B2E002760B4 /* RecentAccountSessions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecentAccountSessions.swift; sourceTree = "<group>"; };
@ -1029,6 +1035,8 @@
D0E23DD91E806F7700B9B6D2 /* ManagedSynchronizeMarkFeaturedStickerPacksAsSeenOperations.swift */,
D0F3A89E1E82C65400B4C64C /* SynchronizeChatInputStateOperation.swift */,
D0F3A8A11E82C65E00B4C64C /* ManagedSynchronizeChatInputStateOperations.swift */,
D0575AF01E9FFA5D006F2541 /* SynchronizeSavedGifsOperation.swift */,
D0575AF31E9FFDDD006F2541 /* ManagedSynchronizeSavedGifsOperations.swift */,
D058E0D01E8AD65C00A442DE /* StandaloneSendMessage.swift */,
D0F02CE41E9926C40065DEE2 /* ManagedConfigurationUpdates.swift */,
);
@ -1619,6 +1627,7 @@
D03B0CD31D62244300955575 /* Namespaces.swift in Sources */,
D01D6BF91E42A713006151C6 /* SearchStickers.swift in Sources */,
D08F4A691E79CECB00A2AA15 /* ManagedSynchronizeInstalledStickerPacksOperations.swift in Sources */,
D0575AF11E9FFA5D006F2541 /* SynchronizeSavedGifsOperation.swift in Sources */,
D0FA8BB91E2240B4001E855B /* SecretChatIncomingDecryptedOperation.swift in Sources */,
D0561DE31E5737FC00E6B9E9 /* UpdatePeerInfo.swift in Sources */,
D0DF0C8A1D819C7E008AEB01 /* JoinChannel.swift in Sources */,
@ -1682,6 +1691,7 @@
D03B0CD71D62245300955575 /* TelegramGroup.swift in Sources */,
D0B8438C1DA7CF50005F29E1 /* BotInfo.swift in Sources */,
D033FEB31E61F3C000644997 /* ReportPeer.swift in Sources */,
D0575AF41E9FFDDE006F2541 /* ManagedSynchronizeSavedGifsOperations.swift in Sources */,
D021E0E21DB5401A00C6B04F /* StickerManagement.swift in Sources */,
D0BC38701E40853E0044D6FE /* UpdatePeers.swift in Sources */,
D0F3A8A81E82CD7D00B4C64C /* UpdatePeerChatInterfaceState.swift in Sources */,
@ -1749,6 +1759,7 @@
D0458C891E69B4AB00FB34C1 /* OutgoingContentInfoMessageAttribute.swift in Sources */,
D050F26C1E4A5B6D00988324 /* UpdatePeers.swift in Sources */,
D050F26D1E4A5B6D00988324 /* CreateGroup.swift in Sources */,
D0575AF51E9FFDDE006F2541 /* ManagedSynchronizeSavedGifsOperations.swift in Sources */,
D00D34461E6EDD420057B307 /* SynchronizeConsumeMessageContentsOperation.swift in Sources */,
D00D34401E6ED6E50057B307 /* ConsumableContentMessageAttribute.swift in Sources */,
D050F26E1E4A5B6D00988324 /* RemovePeerChat.swift in Sources */,
@ -1929,6 +1940,7 @@
D0448CA61E29215A005A61A7 /* MediaResourceApiUtils.swift in Sources */,
D001F3F11E128A1C007A8C60 /* SynchronizePeerReadState.swift in Sources */,
D050F2641E4A5AEB00988324 /* ManagedSynchronizePinnedChatsOperations.swift in Sources */,
D0575AF21E9FFA5D006F2541 /* SynchronizeSavedGifsOperation.swift in Sources */,
D0528E661E65C82400E2FEF5 /* UpdateContactName.swift in Sources */,
D0F7B1E81E045C87007EB8A5 /* PeerParticipants.swift in Sources */,
D0C48F3A1E8138DF0075317D /* ArchivedStickerPacksInfo.swift in Sources */,

View File

@ -218,6 +218,7 @@ private var declaredEncodables: Void = {
declareEncodable(SynchronizeMarkFeaturedStickerPacksAsSeenOperation.self, f: { SynchronizeMarkFeaturedStickerPacksAsSeenOperation(decoder: $0) })
declareEncodable(ArchivedStickerPacksInfo.self, f: { ArchivedStickerPacksInfo(decoder: $0) })
declareEncodable(SynchronizeChatInputStateOperation.self, f: { SynchronizeChatInputStateOperation(decoder: $0) })
declareEncodable(SynchronizeSavedGifsOperation.self, f: { SynchronizeSavedGifsOperation(decoder: $0) })
return
}()
@ -570,7 +571,7 @@ public class Account {
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(managedRecentGifs(postbox: self.postbox, network: self.network).start())
self.managedOperationsDisposable.add(managedSynchronizeSavedGifsOperations(postbox: self.postbox, network: self.network).start())
self.managedOperationsDisposable.add(managedRecentlyUsedInlineBots(postbox: self.postbox, network: self.network).start())
self.managedOperationsDisposable.add(managedLocalTypingActivities(activities: self.localInputActivityManager.allActivities(), postbox: self.postbox, network: self.network).start())
self.managedOperationsDisposable.add(managedSynchronizeConsumeMessageContentOperations(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())

View File

@ -50,6 +50,7 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes
}
var sentStickers: [TelegramMediaFile] = []
var sentGifs: [TelegramMediaFile] = []
modifier.updateMessage(message.id, update: { currentMessage in
let updatedId: MessageId
@ -101,9 +102,15 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes
applyMediaResourceChanges(from: fromMedia, to: toMedia, postbox: postbox)
}
for media in media {
if let file = media as? TelegramMediaFile, file.isSticker {
sentStickers.append(file)
if storeForwardInfo == nil {
for media in media {
if let file = media as? TelegramMediaFile {
if file.isSticker {
sentStickers.append(file)
} else if file.isVideo && file.isAnimated {
sentGifs.append(file)
}
}
}
}
@ -123,6 +130,9 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes
for file in sentStickers {
modifier.addOrMoveToFirstPositionOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudRecentStickers, item: OrderedItemListEntry(id: RecentMediaItemId(file.fileId).rawValue, contents: RecentMediaItem(file)), removeTailIfCountExceeds: 20)
}
for file in sentGifs {
modifier.addOrMoveToFirstPositionOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudRecentGifs, item: OrderedItemListEntry(id: RecentMediaItemId(file.fileId).rawValue, contents: RecentMediaItem(file)), removeTailIfCountExceeds: 200)
}
stateManager.addUpdates(result)
}
}

View File

@ -18,8 +18,8 @@ private func messageFilterForTagMask(_ tagMask: MessageTags) -> Api.MessagesFilt
return Api.MessagesFilter.inputMessagesFilterMusic
} else if tagMask == .WebPage {
return Api.MessagesFilter.inputMessagesFilterUrl
} else if tagMask == .Voice {
return Api.MessagesFilter.inputMessagesFilterVoice
} else if tagMask == .VoiceOrInstantVideo {
return Api.MessagesFilter.inputMessagesFilterRoundVoice
} else {
return nil
}

View File

@ -0,0 +1,139 @@
import Foundation
#if os(macOS)
import PostboxMac
import SwiftSignalKitMac
import MtProtoKitMac
#else
import Postbox
import SwiftSignalKit
import MtProtoKitDynamic
#endif
private final class ManagedSynchronizeSavedGifsOperationsHelper {
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 (Modifier, PeerMergedOperationLogEntry?) -> Signal<Void, NoError>) -> Signal<Void, NoError> {
return postbox.modify { modifier -> Signal<Void, NoError> in
var result: PeerMergedOperationLogEntry?
modifier.operationLogUpdateEntry(peerId: peerId, tag: tag, tagLocalIndex: tagLocalIndex, { entry in
if let entry = entry, let _ = entry.mergedIndex, entry.contents is SynchronizeSavedGifsOperation {
result = entry.mergedEntry!
return PeerOperationLogEntryUpdate(mergedIndex: .none, contents: .none)
} else {
return PeerOperationLogEntryUpdate(mergedIndex: .none, contents: .none)
}
})
return f(modifier, result)
} |> switchToLatest
}
func managedSynchronizeSavedGifsOperations(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
return Signal { _ in
let tag: PeerOperationLogTag = OperationLogTags.SynchronizeSavedGifs
let helper = Atomic<ManagedSynchronizeSavedGifsOperationsHelper>(value: ManagedSynchronizeSavedGifsOperationsHelper())
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, { modifier, entry -> Signal<Void, NoError> in
if let entry = entry {
if let operation = entry.contents as? SynchronizeSavedGifsOperation {
return synchronizeSavedGifs(modifier: modifier, postbox: postbox, network: network, operation: operation)
} else {
assertionFailure()
}
}
return .complete()
})
|> then(postbox.modify { modifier -> Void in
let _ = modifier.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 func synchronizeSavedGifs(modifier: Modifier, postbox: Postbox, network: Network, operation: SynchronizeSavedGifsOperation) -> Signal<Void, NoError> {
switch operation.content {
case let .add(id, accessHash):
return network.request(Api.functions.messages.saveGif(id: .inputDocument(id: id, accessHash: accessHash), unsave: .boolFalse))
|> `catch` { _ -> Signal<Api.Bool, NoError> in
return .single(.boolFalse)
}
|> mapToSignal { _ -> Signal<Void, NoError> in
return .complete()
}
case let .remove(id, accessHash):
return network.request(Api.functions.messages.saveGif(id: .inputDocument(id: id, accessHash: accessHash), unsave: .boolTrue))
|> `catch` { _ -> Signal<Api.Bool, NoError> in
return .single(.boolFalse)
}
|> mapToSignal { _ -> Signal<Void, NoError> in
return .complete()
}
case .sync:
return managedRecentGifs(postbox: postbox, network: network)
}
}

View File

@ -60,10 +60,10 @@ public extension MessageTags {
static let File = MessageTags(rawValue: 1 << 1)
static let Music = MessageTags(rawValue: 1 << 2)
static let WebPage = MessageTags(rawValue: 1 << 3)
static let Voice = MessageTags(rawValue: 1 << 4)
static let VoiceOrInstantVideo = MessageTags(rawValue: 1 << 4)
}
let allMessageTags: MessageTags = [.PhotoOrVideo, .File, .Music, .WebPage, .Voice]
let allMessageTags: MessageTags = [.PhotoOrVideo, .File, .Music, .WebPage, .VoiceOrInstantVideo]
let peerIdNamespacesWithInitialCloudMessageHoles = [Namespaces.Peer.CloudUser, Namespaces.Peer.CloudGroup, Namespaces.Peer.CloudChannel]
struct OperationLogTags {
@ -79,6 +79,7 @@ struct OperationLogTags {
static let SynchronizeInstalledMasks = PeerOperationLogTag(value: 9)
static let SynchronizeMarkFeaturedStickerPacksAsSeen = PeerOperationLogTag(value: 10)
static let SynchronizeChatInputStates = PeerOperationLogTag(value: 11)
static let SynchronizeSavedGifs = PeerOperationLogTag(value: 12)
}
private enum PreferencesKeyValues: Int32 {

View File

@ -13,6 +13,12 @@ public func addRecentlySearchedPeer(postbox: Postbox, peerId: PeerId) -> Signal<
}
}
public func removeRecentlySearchedPeer(postbox: Postbox, peerId: PeerId) -> Signal<Void, NoError> {
return postbox.modify { modifier -> Void in
modifier.removeOrderedItemListItem(collectionId: Namespaces.OrderedItemList.RecentlySearchedPeerIds, itemId: RecentPeerItemId(peerId).rawValue)
}
}
public func recentlySearchedPeers(postbox: Postbox) -> Signal<[Peer], NoError> {
return postbox.combinedView(keys: [.orderedItemList(id: Namespaces.OrderedItemList.RecentlySearchedPeerIds)])
|> take(1)

View File

@ -25,6 +25,7 @@ func manageStickerPacks(network: Network, postbox: Postbox) -> Signal<Void, NoEr
return (postbox.modify { modifier -> Void in
addSynchronizeInstalledStickerPacksOperation(modifier: modifier, namespace: .stickers)
addSynchronizeInstalledStickerPacksOperation(modifier: modifier, namespace: .masks)
addSynchronizeSavedGifsOperation(modifier: modifier, operation: .sync)
} |> then(.complete() |> delay(1.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart
}

View File

@ -9,17 +9,33 @@ public func tagsForStoreMessage(media: [Media], textEntities: [MessageTextEntity
var tags = MessageTags()
for attachment in media {
if let _ = attachment as? TelegramMediaImage {
let _ = tags.insert(.PhotoOrVideo)
tags.insert(.PhotoOrVideo)
} else if let file = attachment as? TelegramMediaFile {
if file.isSticker || file.isAnimated {
} else if file.isVideo {
let _ = tags.insert(.PhotoOrVideo)
} else if file.isVoice {
let _ = tags.insert(.Voice)
} else if file.isMusic {
let _ = tags.insert(.Music)
var refinedTag: MessageTags?
inner: for attribute in file.attributes {
switch attribute {
case let .Video(_, _, flags):
if flags.contains(.instantRoundVideo) {
refinedTag = .VoiceOrInstantVideo
} else {
refinedTag = .PhotoOrVideo
}
break inner
case let .Audio(isVoice, _, _, _, _):
if isVoice {
refinedTag = .VoiceOrInstantVideo
} else {
refinedTag = .Music
}
break inner
default:
break
}
}
if let refinedTag = refinedTag {
tags.insert(refinedTag)
} else {
let _ = tags.insert(.File)
tags.insert(.File)
}
} else if let webpage = attachment as? TelegramMediaWebpage, case .Loaded = webpage.content {
tags.insert(.WebPage)

View File

@ -0,0 +1,105 @@
import Foundation
#if os(macOS)
import PostboxMac
import SwiftSignalKitMac
#else
import Postbox
import SwiftSignalKit
#endif
private enum SynchronizeSavedGifsOperationContentType: Int32 {
case add
case remove
case sync
}
enum SynchronizeSavedGifsOperationContent: Coding {
case add(id: Int64, accessHash: Int64)
case remove(id: Int64, accessHash: Int64)
case sync
init(decoder: Decoder) {
switch decoder.decodeInt32ForKey("r") as Int32 {
case SynchronizeSavedGifsOperationContentType.add.rawValue:
self = .add(id: decoder.decodeInt64ForKey("i"), accessHash: decoder.decodeInt64ForKey("h"))
case SynchronizeSavedGifsOperationContentType.remove.rawValue:
self = .remove(id: decoder.decodeInt64ForKey("i"), accessHash: decoder.decodeInt64ForKey("h"))
case SynchronizeSavedGifsOperationContentType.sync.rawValue:
self = .sync
default:
assertionFailure()
self = .sync
}
}
func encode(_ encoder: Encoder) {
switch self {
case let .add(id, accessHash):
encoder.encodeInt32(SynchronizeSavedGifsOperationContentType.add.rawValue, forKey: "r")
encoder.encodeInt64(id, forKey: "i")
encoder.encodeInt64(accessHash, forKey: "h")
case let .remove(id, accessHash):
encoder.encodeInt32(SynchronizeSavedGifsOperationContentType.remove.rawValue, forKey: "r")
encoder.encodeInt64(id, forKey: "i")
encoder.encodeInt64(accessHash, forKey: "h")
case .sync:
encoder.encodeInt32(SynchronizeSavedGifsOperationContentType.sync.rawValue, forKey: "r")
}
}
}
final class SynchronizeSavedGifsOperation: Coding {
let content: SynchronizeSavedGifsOperationContent
init(content: SynchronizeSavedGifsOperationContent) {
self.content = content
}
init(decoder: Decoder) {
self.content = decoder.decodeObjectForKey("c", decoder: { SynchronizeSavedGifsOperationContent(decoder: $0) }) as! SynchronizeSavedGifsOperationContent
}
func encode(_ encoder: Encoder) {
encoder.encodeObject(self.content, forKey: "c")
}
}
func addSynchronizeSavedGifsOperation(modifier: Modifier, operation: SynchronizeSavedGifsOperationContent) {
let tag: PeerOperationLogTag = OperationLogTags.SynchronizeSavedGifs
let peerId = PeerId(namespace: 0, id: 0)
var topOperation: (SynchronizeSavedGifsOperation, Int32)?
modifier.operationLogEnumerateEntries(peerId: peerId, tag: tag, { entry in
if let operation = entry.contents as? SynchronizeSavedGifsOperation {
topOperation = (operation, entry.tagLocalIndex)
}
return false
})
if let (topOperation, topLocalIndex) = topOperation, case .sync = topOperation.content {
let _ = modifier.operationLogRemoveEntry(peerId: peerId, tag: tag, tagLocalIndex: topLocalIndex)
}
modifier.operationLogAddEntry(peerId: peerId, tag: tag, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: SynchronizeSavedGifsOperation(content: operation))
modifier.operationLogAddEntry(peerId: peerId, tag: tag, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: SynchronizeSavedGifsOperation(content: .sync))
}
public func addSavedGif(postbox: Postbox, file: TelegramMediaFile) -> Signal<Void, NoError> {
return postbox.modify { modifier -> Void in
if let resource = file.resource as? CloudDocumentMediaResource {
modifier.addOrMoveToFirstPositionOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudRecentGifs, item: OrderedItemListEntry(id: RecentMediaItemId(file.fileId).rawValue, contents: RecentMediaItem(file)), removeTailIfCountExceeds: 200)
addSynchronizeSavedGifsOperation(modifier: modifier, operation: .add(id: resource.fileId, accessHash: resource.accessHash))
}
}
}
public func removeSavedGif(postbox: Postbox, mediaId: MediaId) -> Signal<Void, NoError> {
return postbox.modify { modifier -> Void in
if let entry = modifier.getOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudRecentGifs, itemId: RecentMediaItemId(mediaId).rawValue), let item = entry.contents as? RecentMediaItem {
if let file = item.media as? TelegramMediaFile, let resource = file.resource as? CloudDocumentMediaResource {
modifier.removeOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudRecentGifs, itemId: entry.id)
addSynchronizeSavedGifsOperation(modifier: modifier, operation: .remove(id: resource.fileId, accessHash: resource.accessHash))
}
}
}
}