diff --git a/TelegramCore/Account.swift b/TelegramCore/Account.swift index c993147b83..3ee02ddbfa 100644 --- a/TelegramCore/Account.swift +++ b/TelegramCore/Account.swift @@ -245,6 +245,7 @@ private var declaredEncodables: Void = { declareEncodable(SavedStickerItem.self, f: { SavedStickerItem(decoder: $0) }) declareEncodable(ConsumablePersonalMentionMessageAttribute.self, f: { ConsumablePersonalMentionMessageAttribute(decoder: $0) }) declareEncodable(ConsumePersonalMessageAction.self, f: { ConsumePersonalMessageAction(decoder: $0) }) + declareEncodable(CachedStickerPack.self, f: { CachedStickerPack(decoder: $0) }) return }() diff --git a/TelegramCore/AccountStateManager.swift b/TelegramCore/AccountStateManager.swift index 3fadcd97b4..d1aff26e7a 100644 --- a/TelegramCore/AccountStateManager.swift +++ b/TelegramCore/AccountStateManager.swift @@ -681,6 +681,11 @@ public final class AccountStateManager { } public func messageForNotification(modifier: Modifier, id: MessageId, alwaysReturnMessage: Bool) -> (message: Message?, notify: Bool, sound: PeerMessageSound, displayContents: Bool) { + guard let message = modifier.getMessage(id) else { + Logger.shared.log("AccountStateManager", "notification message doesn't exist") + return (nil, false, .bundledModern(id: 0), false) + } + var notify = true var sound: PeerMessageSound = .bundledModern(id: 0) var displayContents = true @@ -691,6 +696,9 @@ public func messageForNotification(modifier: Modifier, id: MessageId, alwaysRetu if let peer = modifier.getPeer(id.peerId), let associatedPeerId = peer.associatedPeerId { notificationPeerId = associatedPeerId } + if message.personal, let author = message.author { + notificationPeerId = author.id + } if let notificationSettings = modifier.getPeerNotificationSettings(notificationPeerId) as? TelegramPeerNotificationSettings { switch notificationSettings.muteState { @@ -702,14 +710,18 @@ public func messageForNotification(modifier: Modifier, id: MessageId, alwaysRetu break } var defaultSound: PeerMessageSound = .bundledModern(id: 0) + var defaultNotify: Bool = true if let globalNotificationSettings = modifier.getPreferencesEntry(key: PreferencesKeys.globalNotifications) as? GlobalNotificationSettings { if id.peerId.namespace == Namespaces.Peer.CloudUser { + defaultNotify = globalNotificationSettings.effective.privateChats.enabled defaultSound = globalNotificationSettings.effective.privateChats.sound displayContents = globalNotificationSettings.effective.privateChats.displayPreviews } else if id.peerId.namespace == Namespaces.Peer.SecretChat { + defaultNotify = globalNotificationSettings.effective.privateChats.enabled defaultSound = globalNotificationSettings.effective.privateChats.sound displayContents = false } else { + defaultNotify = globalNotificationSettings.effective.groupChats.enabled defaultSound = globalNotificationSettings.effective.groupChats.sound displayContents = globalNotificationSettings.effective.groupChats.displayPreviews } @@ -719,41 +731,38 @@ public func messageForNotification(modifier: Modifier, id: MessageId, alwaysRetu } else { sound = notificationSettings.messageSound } + if !defaultNotify { + notify = false + } } else { Logger.shared.log("AccountStateManager", "notification settings for \(notificationPeerId) are undefined") } - let message = modifier.getMessage(id) - if let message = message { - if let channel = message.peers[message.id.peerId] as? TelegramChannel { - switch channel.participationStatus { - case .kicked, .left: - return (nil, false, sound, false) - case .member: - break - } + if let channel = message.peers[message.id.peerId] as? TelegramChannel { + switch channel.participationStatus { + case .kicked, .left: + return (nil, false, sound, false) + case .member: + break } - - var foundReadState = false - var isUnread = true - if let readState = modifier.getCombinedPeerReadState(id.peerId) { - if readState.isIncomingMessageIndexRead(MessageIndex(message)) { - isUnread = false - } - foundReadState = true - } - - if !foundReadState { - Logger.shared.log("AccountStateManager", "read state for \(id.peerId) is undefined") - } - - if notify || message.personal { - return (message, isUnread, sound, displayContents) - } else { - return (alwaysReturnMessage ? message : nil, false, sound, displayContents) + } + + var foundReadState = false + var isUnread = true + if let readState = modifier.getCombinedPeerReadState(id.peerId) { + if readState.isIncomingMessageIndexRead(MessageIndex(message)) { + isUnread = false } + foundReadState = true + } + + if !foundReadState { + Logger.shared.log("AccountStateManager", "read state for \(id.peerId) is undefined") + } + + if notify { + return (message, isUnread, sound, displayContents) } else { - Logger.shared.log("AccountStateManager", "notification message doesn't exist") - return (nil, false, .bundledModern(id: 0), false) + return (alwaysReturnMessage ? message : nil, false, sound, displayContents) } } diff --git a/TelegramCore/CachedChannelData.swift b/TelegramCore/CachedChannelData.swift index 16ac511b5d..376fd24853 100644 --- a/TelegramCore/CachedChannelData.swift +++ b/TelegramCore/CachedChannelData.swift @@ -113,6 +113,7 @@ public final class CachedChannelData: CachedPeerData { public let stickerPack: StickerPackCollectionInfo? public let peerIds: Set + public let messageIds: Set init() { self.flags = [] @@ -124,6 +125,7 @@ public final class CachedChannelData: CachedPeerData { self.reportStatus = .unknown self.pinnedMessageId = nil self.peerIds = Set() + self.messageIds = Set() self.stickerPack = nil } @@ -148,6 +150,12 @@ public final class CachedChannelData: CachedPeerData { peerIds.insert(botInfo.peerId) } self.peerIds = peerIds + + var messageIds = Set() + if let pinnedMessageId = self.pinnedMessageId { + messageIds.insert(pinnedMessageId) + } + self.messageIds = messageIds } func withUpdatedFlags(_ flags: CachedChannelFlags) -> CachedChannelData { @@ -217,6 +225,12 @@ public final class CachedChannelData: CachedPeerData { } self.peerIds = peerIds + + var messageIds = Set() + if let pinnedMessageId = self.pinnedMessageId { + messageIds.insert(pinnedMessageId) + } + self.messageIds = messageIds } public func encode(_ encoder: PostboxEncoder) { diff --git a/TelegramCore/CachedGroupData.swift b/TelegramCore/CachedGroupData.swift index e909c31c1a..c6fc779b0d 100644 --- a/TelegramCore/CachedGroupData.swift +++ b/TelegramCore/CachedGroupData.swift @@ -36,6 +36,7 @@ public final class CachedGroupData: CachedPeerData { public let reportStatus: PeerReportStatus public let peerIds: Set + public let messageIds = Set() init() { self.participants = nil diff --git a/TelegramCore/CachedStickerPack.swift b/TelegramCore/CachedStickerPack.swift index d06a0ce4c5..bc87be1726 100644 --- a/TelegramCore/CachedStickerPack.swift +++ b/TelegramCore/CachedStickerPack.swift @@ -7,64 +7,77 @@ import Foundation import SwiftSignalKit #endif -private final class CachedStickerPack: PostboxCoding { +final class CachedStickerPack: PostboxCoding { + let info: StickerPackCollectionInfo? let items: [StickerPackItem] let hash: Int32 - init(items: [StickerPackItem], hash: Int32) { + init(info: StickerPackCollectionInfo?, items: [StickerPackItem], hash: Int32) { + self.info = info self.items = items self.hash = hash } init(decoder: PostboxDecoder) { + self.info = decoder.decodeObjectForKey("in", decoder: { StickerPackCollectionInfo(decoder: $0) }) as? StickerPackCollectionInfo self.items = decoder.decodeObjectArrayForKey("it").map { $0 as! StickerPackItem } self.hash = decoder.decodeInt32ForKey("h", orElse: 0) } func encode(_ encoder: PostboxEncoder) { + if let info = self.info { + encoder.encodeObject(info, forKey: "in") + } else { + encoder.encodeNil(forKey: "in") + } encoder.encodeObjectArray(self.items, forKey: "it") encoder.encodeInt32(self.hash, forKey: "h") } - static func cacheKey(_ info: StickerPackCollectionInfo) -> ValueBoxKey { + static func cacheKey(_ id: ItemCollectionId) -> ValueBoxKey { let key = ValueBoxKey(length: 4 + 8) - key.setInt32(0, value: info.id.namespace) - key.setInt64(4, value: info.id.id) + key.setInt32(0, value: id.namespace) + key.setInt64(4, value: 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)) +public func cachedStickerPack(postbox: Postbox, network: Network, reference: StickerPackReference) -> Signal<(StickerPackCollectionInfo, [ItemCollectionItem], Bool)?, NoError> { + return postbox.modify { modifier -> Signal<(StickerPackCollectionInfo, [ItemCollectionItem], Bool)?, NoError> in + let namespace = Namespaces.ItemCollection.CloudStickerPacks + if case let .id(id, _) = reference, let currentInfo = modifier.getItemCollectionInfo(collectionId: ItemCollectionId(namespace: namespace, id: id)) as? StickerPackCollectionInfo { + let items = modifier.getItemCollectionItems(collectionId: ItemCollectionId(namespace: namespace, id: id)) + return .single((currentInfo, items, true)) } else { - let current: Signal<(StickerPackCollectionInfo, [ItemCollectionItem])?, NoError> + let current: Signal<(StickerPackCollectionInfo, [ItemCollectionItem], Bool)?, 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 case let .id(id, _) = reference, let cached = modifier.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(ItemCollectionId(namespace: namespace, id: id)))) as? CachedStickerPack, let info = cached.info { + current = .single((info, cached.items, false)) if cached.hash != info.hash { loadRemote = true } } else { - current = .complete() + current = .single(nil) 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 + let appliedRemote = remoteStickerPack(network: network, reference: reference) + |> mapToSignal { result -> Signal<(StickerPackCollectionInfo, [ItemCollectionItem], Bool)?, NoError> in + return postbox.modify { modifier -> (StickerPackCollectionInfo, [ItemCollectionItem], Bool)? 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) + modifier.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(result.0.id)), entry: CachedStickerPack(info: result.0, items: result.1.map { $0 as! StickerPackItem }, hash: result.0.hash), collectionSpec: collectionSpec) + + let currentInfo = modifier.getItemCollectionInfo(collectionId: result.0.id) as? StickerPackCollectionInfo + + return (result.0, result.1, currentInfo != nil) + } else { + return nil } - - return result } } diff --git a/TelegramCore/CachedUserData.swift b/TelegramCore/CachedUserData.swift index 92015663d8..4829593f57 100644 --- a/TelegramCore/CachedUserData.swift +++ b/TelegramCore/CachedUserData.swift @@ -13,6 +13,7 @@ public final class CachedUserData: CachedPeerData { public let commonGroupCount: Int32 public let peerIds = Set() + public let messageIds = Set() init() { self.about = nil diff --git a/TelegramCore/LoadedStickerPack.swift b/TelegramCore/LoadedStickerPack.swift index d0802ebe1f..2086b03bb9 100644 --- a/TelegramCore/LoadedStickerPack.swift +++ b/TelegramCore/LoadedStickerPack.swift @@ -86,7 +86,18 @@ func remoteStickerPack(network: Network, reference: StickerPackReference) -> Sig } } -public func loadedStickerPack(account: Account, reference: StickerPackReference) -> Signal { +public func loadedStickerPack(postbox: Postbox, network: Network, reference: StickerPackReference) -> Signal { + return cachedStickerPack(postbox: postbox, network: network, reference: reference) + |> map { result -> LoadedStickerPack in + if let result = result { + return .result(info: result.0, items: result.1, installed: result.2) + } else { + return .fetching + } + } +} + +private func loadedStickerPack1(account: Account, reference: StickerPackReference) -> Signal { return account.postbox.modify { modifier -> Signal in switch reference { case let .id(id, _): diff --git a/TelegramCore/PeerSpecificStickerPack.swift b/TelegramCore/PeerSpecificStickerPack.swift index e18d6ce685..7645a04118 100644 --- a/TelegramCore/PeerSpecificStickerPack.swift +++ b/TelegramCore/PeerSpecificStickerPack.swift @@ -25,7 +25,14 @@ public func peerSpecificStickerPack(postbox: Postbox, network: Network, peerId: |> distinctUntilChanged |> mapToSignal { info -> Signal<(StickerPackCollectionInfo, [ItemCollectionItem])?, NoError> in if let info = info.info { - return cachedStickerPack(postbox: postbox, network: network, info: info) + return cachedStickerPack(postbox: postbox, network: network, reference: .id(id: info.id.id, accessHash: info.accessHash)) + |> map { result -> (StickerPackCollectionInfo, [ItemCollectionItem])? in + if let result = result { + return (result.0, result.1) + } else { + return nil + } + } } else { return .single(nil) } diff --git a/TelegramCore/PendingMessageManager.swift b/TelegramCore/PendingMessageManager.swift index c5ce6e865f..9e8bd6b1d4 100644 --- a/TelegramCore/PendingMessageManager.swift +++ b/TelegramCore/PendingMessageManager.swift @@ -8,10 +8,11 @@ import Foundation #endif public struct PendingMessageStatus: Equatable { + public let isRunning: Bool public let progress: Float public static func ==(lhs: PendingMessageStatus, rhs: PendingMessageStatus) -> Bool { - return lhs.progress.isEqual(to: rhs.progress) + return lhs.isRunning == rhs.isRunning && lhs.progress.isEqual(to: rhs.progress) } } @@ -173,7 +174,7 @@ public final class PendingMessageManager { self.messageContexts[id] = messageContext } - let status = PendingMessageStatus(progress: 0.0) + let status = PendingMessageStatus(isRunning: false, progress: 0.0) if status != messageContext.status { messageContext.status = status for subscriber in messageContext.statusSubscribers.copyItems() { @@ -245,14 +246,14 @@ public final class PendingMessageManager { assert(strongSelf.queue.isCurrent()) switch next { - case let .progress(progress): - if let current = strongSelf.messageContexts[messageId] { - let status = PendingMessageStatus(progress: progress) - current.status = status - for subscriber in current.statusSubscribers.copyItems() { - subscriber(status) + case let .progress(progress): + if let current = strongSelf.messageContexts[messageId] { + let status = PendingMessageStatus(isRunning: true, progress: progress) + current.status = status + for subscriber in current.statusSubscribers.copyItems() { + subscriber(status) + } } - } } } })) @@ -261,6 +262,12 @@ public final class PendingMessageManager { private func beginUploadingMessage(messageContext: PendingMessageContext, id: MessageId, uploadSignal: Signal) { messageContext.state = .uploading + let status = PendingMessageStatus(isRunning: true, progress: 0.0) + messageContext.status = status + for subscriber in messageContext.statusSubscribers.copyItems() { + subscriber(status) + } + messageContext.disposable.set((uploadSignal |> deliverOn(self.queue)).start(next: { [weak self] next in if let strongSelf = self { assert(strongSelf.queue.isCurrent()) @@ -268,7 +275,7 @@ public final class PendingMessageManager { switch next { case let .progress(progress): if let current = strongSelf.messageContexts[id] { - let status = PendingMessageStatus(progress: progress) + let status = PendingMessageStatus(isRunning: true, progress: progress) current.status = status for subscriber in current.statusSubscribers.copyItems() { subscriber(status) @@ -293,6 +300,12 @@ public final class PendingMessageManager { if case let .waitingForUploadToStart(uploadSignal) = context.state { if self.canBeginUploadingMessage(id: contextId) { context.state = .uploading + let status = PendingMessageStatus(isRunning: true, progress: 0.0) + context.status = status + for subscriber in context.statusSubscribers.copyItems() { + subscriber(status) + } + context.disposable.set((uploadSignal |> deliverOn(self.queue)).start(next: { [weak self] next in if let strongSelf = self { assert(strongSelf.queue.isCurrent()) @@ -300,7 +313,7 @@ public final class PendingMessageManager { switch next { case let .progress(progress): if let current = strongSelf.messageContexts[contextId] { - let status = PendingMessageStatus(progress: progress) + let status = PendingMessageStatus(isRunning: true, progress: progress) current.status = status for subscriber in current.statusSubscribers.copyItems() { subscriber(status) @@ -320,7 +333,7 @@ public final class PendingMessageManager { switch next { case let .progress(progress): if let current = strongSelf.messageContexts[contextId] { - let status = PendingMessageStatus(progress: progress) + let status = PendingMessageStatus(isRunning: true, progress: progress) current.status = status for subscriber in current.statusSubscribers.copyItems() { subscriber(status) diff --git a/TelegramCore/TelegramSecretChat.swift b/TelegramCore/TelegramSecretChat.swift index 3a9cc8da6d..6e24cfbce6 100644 --- a/TelegramCore/TelegramSecretChat.swift +++ b/TelegramCore/TelegramSecretChat.swift @@ -78,6 +78,7 @@ public final class TelegramSecretChat: Peer { public final class CachedSecretChatData: CachedPeerData { public let peerIds: Set = Set() + public let messageIds: Set = Set() public let reportStatus: PeerReportStatus