mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-18 19:40:19 +00:00
no message
This commit is contained in:
parent
760861b8d2
commit
fbe8936d6f
@ -258,6 +258,10 @@
|
||||
D0448CA61E29215A005A61A7 /* MediaResourceApiUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0448CA41E29215A005A61A7 /* MediaResourceApiUtils.swift */; };
|
||||
D0458C881E69B4AB00FB34C1 /* OutgoingContentInfoMessageAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0458C871E69B4AB00FB34C1 /* OutgoingContentInfoMessageAttribute.swift */; };
|
||||
D0458C891E69B4AB00FB34C1 /* OutgoingContentInfoMessageAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0458C871E69B4AB00FB34C1 /* OutgoingContentInfoMessageAttribute.swift */; };
|
||||
D0467D0B20D7F1E60055C28F /* SynchronizeMarkAllUnseenPersonalMessagesOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0467D0A20D7F1E60055C28F /* SynchronizeMarkAllUnseenPersonalMessagesOperation.swift */; };
|
||||
D0467D0C20D7F1E60055C28F /* SynchronizeMarkAllUnseenPersonalMessagesOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0467D0A20D7F1E60055C28F /* SynchronizeMarkAllUnseenPersonalMessagesOperation.swift */; };
|
||||
D0467D1520D7F2C90055C28F /* ManagedSynchronizeMarkAllUnseenPersonalMessagesOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0467D1420D7F2C90055C28F /* ManagedSynchronizeMarkAllUnseenPersonalMessagesOperations.swift */; };
|
||||
D0467D1620D7F2C90055C28F /* ManagedSynchronizeMarkAllUnseenPersonalMessagesOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0467D1420D7F2C90055C28F /* ManagedSynchronizeMarkAllUnseenPersonalMessagesOperations.swift */; };
|
||||
D048B4AC20A5DA4300C79D31 /* ManagedProxyInfoUpdates.swift in Sources */ = {isa = PBXBuildFile; fileRef = D048B4AB20A5DA4300C79D31 /* ManagedProxyInfoUpdates.swift */; };
|
||||
D048B4AD20A5DA4300C79D31 /* ManagedProxyInfoUpdates.swift in Sources */ = {isa = PBXBuildFile; fileRef = D048B4AB20A5DA4300C79D31 /* ManagedProxyInfoUpdates.swift */; };
|
||||
D049EAD51E43D98500A2CD3A /* RecentMediaItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D049EAD41E43D98500A2CD3A /* RecentMediaItem.swift */; };
|
||||
@ -875,6 +879,8 @@
|
||||
D0448CA11E291B14005A61A7 /* FetchSecretFileResource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchSecretFileResource.swift; sourceTree = "<group>"; };
|
||||
D0448CA41E29215A005A61A7 /* MediaResourceApiUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaResourceApiUtils.swift; sourceTree = "<group>"; };
|
||||
D0458C871E69B4AB00FB34C1 /* OutgoingContentInfoMessageAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutgoingContentInfoMessageAttribute.swift; sourceTree = "<group>"; };
|
||||
D0467D0A20D7F1E60055C28F /* SynchronizeMarkAllUnseenPersonalMessagesOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SynchronizeMarkAllUnseenPersonalMessagesOperation.swift; sourceTree = "<group>"; };
|
||||
D0467D1420D7F2C90055C28F /* ManagedSynchronizeMarkAllUnseenPersonalMessagesOperations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManagedSynchronizeMarkAllUnseenPersonalMessagesOperations.swift; sourceTree = "<group>"; };
|
||||
D048B4AB20A5DA4300C79D31 /* ManagedProxyInfoUpdates.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManagedProxyInfoUpdates.swift; sourceTree = "<group>"; };
|
||||
D049EAD41E43D98500A2CD3A /* RecentMediaItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecentMediaItem.swift; sourceTree = "<group>"; };
|
||||
D049EAD71E43DAD200A2CD3A /* ManagedRecentStickers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedRecentStickers.swift; sourceTree = "<group>"; };
|
||||
@ -1419,6 +1425,8 @@
|
||||
D0C26D7A1FE31DAC004ABF18 /* ManagedGroupFeedReadStateSyncOperations.swift */,
|
||||
D0380DB9204EF306000414AB /* MessageMediaPreuploadManager.swift */,
|
||||
D048B4AB20A5DA4300C79D31 /* ManagedProxyInfoUpdates.swift */,
|
||||
D0467D0A20D7F1E60055C28F /* SynchronizeMarkAllUnseenPersonalMessagesOperation.swift */,
|
||||
D0467D1420D7F2C90055C28F /* ManagedSynchronizeMarkAllUnseenPersonalMessagesOperations.swift */,
|
||||
);
|
||||
name = State;
|
||||
sourceTree = "<group>";
|
||||
@ -2089,6 +2097,7 @@
|
||||
D03B0D5F1D631A6900955575 /* Serialization.swift in Sources */,
|
||||
D093D7F920641AA500BC3599 /* SecureIdEmailValue.swift in Sources */,
|
||||
D0C44B611FC616E200227BE0 /* SearchGroupMembers.swift in Sources */,
|
||||
D0467D1520D7F2C90055C28F /* ManagedSynchronizeMarkAllUnseenPersonalMessagesOperations.swift in Sources */,
|
||||
D03B0D441D6319F900955575 /* CloudFileMediaResource.swift in Sources */,
|
||||
D018D3371E648ACF00C5E089 /* CreateChannel.swift in Sources */,
|
||||
D01AC9211DD5E7E500E8160F /* RequestEditMessage.swift in Sources */,
|
||||
@ -2267,6 +2276,7 @@
|
||||
D0561DEA1E5754FA00E6B9E9 /* ChannelAdmins.swift in Sources */,
|
||||
D099D7461EEF0C2700A3128C /* ChannelMessageStateVersionAttribute.swift in Sources */,
|
||||
D0E412DC206A99AE00BEE4A2 /* SecureIdValueAccessContext.swift in Sources */,
|
||||
D0467D0B20D7F1E60055C28F /* SynchronizeMarkAllUnseenPersonalMessagesOperation.swift in Sources */,
|
||||
D0613FCA1E60440600202CDB /* InvitationLinks.swift in Sources */,
|
||||
D03B0D721D631ABA00955575 /* SearchMessages.swift in Sources */,
|
||||
D0DC35501DE36900000195EB /* ChatContextResult.swift in Sources */,
|
||||
@ -2468,6 +2478,7 @@
|
||||
D03C536A1DAD5CA9004C17B3 /* TelegramUser.swift in Sources */,
|
||||
D001F3EA1E128A1C007A8C60 /* TelegramPeerNotificationSettings.swift in Sources */,
|
||||
D0E412F5206B9BDC00BEE4A2 /* SecureIdVerificationDocumentReference.swift in Sources */,
|
||||
D0467D0C20D7F1E60055C28F /* SynchronizeMarkAllUnseenPersonalMessagesOperation.swift in Sources */,
|
||||
D0FA8BA81E1FA6DF001E855B /* TelegramSecretChat.swift in Sources */,
|
||||
C23BC3881E9BE3CB00D79F92 /* ImportContact.swift in Sources */,
|
||||
D0B85AC61F6B2B9400B8B5CE /* RecentlyUsedHashtags.swift in Sources */,
|
||||
@ -2689,6 +2700,7 @@
|
||||
D0B418971D7E0580004562A4 /* TelegramMediaImage.swift in Sources */,
|
||||
D041E3F91E535A88008C24B4 /* RemovePeerMember.swift in Sources */,
|
||||
D049EAF61E44DF3300A2CD3A /* AccountState.swift in Sources */,
|
||||
D0467D1620D7F2C90055C28F /* ManagedSynchronizeMarkAllUnseenPersonalMessagesOperations.swift in Sources */,
|
||||
D041E3F61E535464008C24B4 /* AddPeerMember.swift in Sources */,
|
||||
D0B844361DAB91E0005F29E1 /* NBPhoneNumberUtil.m in Sources */,
|
||||
D0E305A81E5B5CBE00D7A3A2 /* PeerAdmins.swift in Sources */,
|
||||
|
@ -260,6 +260,8 @@ private var declaredEncodables: Void = {
|
||||
declareEncodable(SecureFileMediaResource.self, f: { SecureFileMediaResource(decoder: $0) })
|
||||
declareEncodable(CachedStickerQueryResult.self, f: { CachedStickerQueryResult(decoder: $0) })
|
||||
declareEncodable(TelegramWallpaper.self, f: { TelegramWallpaper(decoder: $0) })
|
||||
declareEncodable(SynchronizeMarkAllUnseenPersonalMessagesOperation.self, f: { SynchronizeMarkAllUnseenPersonalMessagesOperation(decoder: $0) })
|
||||
declareEncodable(CachedRecentPeers.self, f: { CachedRecentPeers(decoder: $0) })
|
||||
|
||||
return
|
||||
}()
|
||||
@ -780,6 +782,8 @@ public class Account {
|
||||
self.managedOperationsDisposable.add(managedSynchronizeConsumeMessageContentOperations(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
|
||||
self.managedOperationsDisposable.add(managedConsumePersonalMessagesActions(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
|
||||
|
||||
self.managedOperationsDisposable.add(managedSynchronizeMarkAllUnseenPersonalMessagesOperations(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
|
||||
|
||||
let importantBackgroundOperations: [Signal<AccountRunningImportantTasks, NoError>] = [
|
||||
managedSynchronizeChatInputStateOperations(postbox: self.postbox, network: self.network) |> map { $0 ? AccountRunningImportantTasks.other : [] },
|
||||
self.pendingMessageManager.hasPendingMessages |> map { $0 ? AccountRunningImportantTasks.pendingMessages : [] }
|
||||
|
@ -749,7 +749,13 @@ private func finalStateWithUpdatesAndServerTime(account: Account, state: Account
|
||||
if let message = StoreMessage(apiMessage: apiMessage) {
|
||||
if let previousState = updatedState.chatStates[message.id.peerId] as? ChannelState {
|
||||
if previousState.pts >= pts {
|
||||
Logger.shared.log("State", "channel \(message.id.peerId) (\((updatedState.peers[message.id.peerId] as? TelegramChannel)?.title ?? "nil")) skip old message \(message.id) (\(message.text))")
|
||||
let messageText: String
|
||||
if Logger.shared.redactSensitiveData {
|
||||
messageText = "[[redacted]]"
|
||||
} else {
|
||||
messageText = message.text
|
||||
}
|
||||
Logger.shared.log("State", "channel \(message.id.peerId) (\((updatedState.peers[message.id.peerId] as? TelegramChannel)?.title ?? "nil")) skip old message \(message.id) (\(messageText))")
|
||||
} else if previousState.pts + ptsCount == pts {
|
||||
if let preCachedResources = apiMessage.preCachedResources {
|
||||
for (resource, data) in preCachedResources {
|
||||
|
@ -457,6 +457,26 @@ public final class AccountViewTracker {
|
||||
}
|
||||
}
|
||||
|
||||
public func updateMarkAllMentionsSeen(peerId: PeerId) {
|
||||
self.queue.async {
|
||||
guard let account = self.account else {
|
||||
return
|
||||
}
|
||||
let _ = (account.postbox.transaction { transaction -> Set<MessageId> in
|
||||
let ids = Set(transaction.getMessageIndicesWithTag(peerId: peerId, tag: .unseenPersonalMessage).map({ $0.id }))
|
||||
if let summary = transaction.getMessageTagSummary(peerId: peerId, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud), summary.count > 0 {
|
||||
transaction.replaceMessageTagSummary(peerId: peerId, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, count: 0, maxId: summary.range.maxId)
|
||||
addSynchronizeMarkAllUnseenPersonalMessagesOperation(transaction: transaction, peerId: peerId, maxId: summary.range.maxId)
|
||||
}
|
||||
|
||||
return ids
|
||||
}
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] messageIds in
|
||||
//self?.updateMarkMentionsSeenForMessageIds(messageIds: messageIds)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
public func updateMarkMentionsSeenForMessageIds(messageIds: Set<MessageId>) {
|
||||
self.queue.async {
|
||||
var addedMessageIds: [MessageId] = []
|
||||
|
@ -643,6 +643,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-74070332] = { return Api.InputPhoto.parse_inputPhoto($0) }
|
||||
dict[-567906571] = { return Api.contacts.TopPeers.parse_topPeersNotModified($0) }
|
||||
dict[1891070632] = { return Api.contacts.TopPeers.parse_topPeers($0) }
|
||||
dict[-1255369827] = { return Api.contacts.TopPeers.parse_topPeersDisabled($0) }
|
||||
dict[1035688326] = { return Api.auth.SentCodeType.parse_sentCodeTypeApp($0) }
|
||||
dict[-1073693790] = { return Api.auth.SentCodeType.parse_sentCodeTypeSms($0) }
|
||||
dict[1398007207] = { return Api.auth.SentCodeType.parse_sentCodeTypeCall($0) }
|
||||
|
@ -1257,6 +1257,7 @@ struct contacts {
|
||||
enum TopPeers: TypeConstructorDescription {
|
||||
case topPeersNotModified
|
||||
case topPeers(categories: [Api.TopPeerCategoryPeers], chats: [Api.Chat], users: [Api.User])
|
||||
case topPeersDisabled
|
||||
|
||||
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
@ -1285,6 +1286,12 @@ struct contacts {
|
||||
for item in users {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
case .topPeersDisabled:
|
||||
if boxed {
|
||||
buffer.appendInt32(-1255369827)
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -1295,6 +1302,8 @@ struct contacts {
|
||||
return ("topPeersNotModified", [])
|
||||
case .topPeers(let categories, let chats, let users):
|
||||
return ("topPeers", [("categories", categories), ("chats", chats), ("users", users)])
|
||||
case .topPeersDisabled:
|
||||
return ("topPeersDisabled", [])
|
||||
}
|
||||
}
|
||||
|
||||
@ -1324,6 +1333,9 @@ struct contacts {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
static func parse_topPeersDisabled(_ reader: BufferReader) -> TopPeers? {
|
||||
return Api.contacts.TopPeers.topPeersDisabled
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -3892,6 +3892,20 @@ extension Api {
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
static func toggleTopPeers(enabled: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-2062238246)
|
||||
enabled.serialize(buffer, true)
|
||||
return (FunctionDescription(name: "contacts.toggleTopPeers", parameters: [("enabled", enabled)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Bool?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.Bool
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
struct help {
|
||||
static func getConfig() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Config>) {
|
||||
|
@ -114,7 +114,7 @@ func applySecretOutgoingMessageReadActions(transaction: Transaction, id: Message
|
||||
}
|
||||
}
|
||||
|
||||
public func togglePeerUnreadMarkInteractively(postbox: Postbox, peerId: PeerId) -> Signal<Void, NoError> {
|
||||
public func togglePeerUnreadMarkInteractively(postbox: Postbox, viewTracker: AccountViewTracker, peerId: PeerId) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Void in
|
||||
let namespace: MessageId.Namespace
|
||||
if peerId.namespace == Namespaces.Peer.SecretChat {
|
||||
@ -129,6 +129,7 @@ public func togglePeerUnreadMarkInteractively(postbox: Postbox, peerId: PeerId)
|
||||
if let index = transaction.getTopPeerMessageIndex(peerId: peerId, namespace: namespace) {
|
||||
let _ = transaction.applyInteractiveReadMaxIndex(index)
|
||||
}
|
||||
viewTracker.updateMarkAllMentionsSeen(peerId: peerId)
|
||||
} else {
|
||||
transaction.applyMarkUnread(peerId: peerId, namespace: namespace, value: true, interactive: true)
|
||||
}
|
||||
|
@ -70,6 +70,7 @@ public final class Logger {
|
||||
|
||||
public var logToFile: Bool = true
|
||||
public var logToConsole: Bool = true
|
||||
public var redactSensitiveData: Bool = true
|
||||
|
||||
public static func setSharedLogger(_ logger: Logger) {
|
||||
sharedLogger = logger
|
||||
|
@ -12,42 +12,42 @@ import Foundation
|
||||
public final class LoggingSettings: PreferencesEntry, Equatable {
|
||||
public let logToFile: Bool
|
||||
public let logToConsole: Bool
|
||||
public let redactSensitiveData: Bool
|
||||
|
||||
#if DEBUG
|
||||
public static var defaultSettings = LoggingSettings(logToFile: true, logToConsole: true)
|
||||
public static var defaultSettings = LoggingSettings(logToFile: true, logToConsole: true, redactSensitiveData: true)
|
||||
#else
|
||||
public static var defaultSettings = LoggingSettings(logToFile: false, logToConsole: false)
|
||||
public static var defaultSettings = LoggingSettings(logToFile: false, logToConsole: false, redactSensitiveData: true)
|
||||
#endif
|
||||
|
||||
public init(logToFile: Bool, logToConsole: Bool) {
|
||||
public init(logToFile: Bool, logToConsole: Bool, redactSensitiveData: Bool) {
|
||||
self.logToFile = logToFile
|
||||
self.logToConsole = logToConsole
|
||||
self.redactSensitiveData = redactSensitiveData
|
||||
}
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
self.logToFile = decoder.decodeInt32ForKey("logToFile", orElse: 0) != 0
|
||||
self.logToConsole = decoder.decodeInt32ForKey("logToConsole", orElse: 0) != 0
|
||||
self.redactSensitiveData = decoder.decodeInt32ForKey("redactSensitiveData", orElse: 1) != 0
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeInt32(self.logToFile ? 1 : 0, forKey: "logToFile")
|
||||
encoder.encodeInt32(self.logToConsole ? 1 : 0, forKey: "logToConsole")
|
||||
encoder.encodeInt32(self.redactSensitiveData ? 1 : 0, forKey: "redactSensitiveData")
|
||||
}
|
||||
|
||||
public func withUpdatedLogToFile(_ logToFile: Bool) -> LoggingSettings {
|
||||
return LoggingSettings(logToFile: logToFile, logToConsole: self.logToConsole)
|
||||
return LoggingSettings(logToFile: logToFile, logToConsole: self.logToConsole, redactSensitiveData: self.redactSensitiveData)
|
||||
}
|
||||
|
||||
public func withUpdatedLogToConsole(_ logToConsole: Bool) -> LoggingSettings {
|
||||
return LoggingSettings(logToFile: self.logToFile, logToConsole: logToConsole)
|
||||
return LoggingSettings(logToFile: self.logToFile, logToConsole: logToConsole, redactSensitiveData: self.redactSensitiveData)
|
||||
}
|
||||
|
||||
public func isEqual(to: PreferencesEntry) -> Bool {
|
||||
guard let to = to as? LoggingSettings else {
|
||||
return false
|
||||
}
|
||||
|
||||
return self == to
|
||||
public func withUpdatedRedactSensitiveData(_ redactSensitiveData: Bool) -> LoggingSettings {
|
||||
return LoggingSettings(logToFile: self.logToFile, logToConsole: self.logToConsole, redactSensitiveData: redactSensitiveData)
|
||||
}
|
||||
|
||||
public static func ==(lhs: LoggingSettings, rhs: LoggingSettings) -> Bool {
|
||||
@ -57,8 +57,19 @@ public final class LoggingSettings: PreferencesEntry, Equatable {
|
||||
if lhs.logToConsole != rhs.logToConsole {
|
||||
return false
|
||||
}
|
||||
if lhs.redactSensitiveData != rhs.redactSensitiveData {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
public func isEqual(to: PreferencesEntry) -> Bool {
|
||||
guard let to = to as? LoggingSettings else {
|
||||
return false
|
||||
}
|
||||
|
||||
return self == to
|
||||
}
|
||||
}
|
||||
|
||||
public func updateLoggingSettings(postbox: Postbox, _ f: @escaping (LoggingSettings) -> LoggingSettings) -> Signal<Void, NoError> {
|
||||
@ -77,6 +88,7 @@ public func updateLoggingSettings(postbox: Postbox, _ f: @escaping (LoggingSetti
|
||||
if let updated = updated {
|
||||
Logger.shared.logToFile = updated.logToFile
|
||||
Logger.shared.logToConsole = updated.logToConsole
|
||||
Logger.shared.redactSensitiveData = updated.redactSensitiveData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,186 @@
|
||||
import Foundation
|
||||
#if os(macOS)
|
||||
import PostboxMac
|
||||
import SwiftSignalKitMac
|
||||
import MtProtoKitMac
|
||||
#else
|
||||
import Postbox
|
||||
import SwiftSignalKit
|
||||
import MtProtoKitDynamic
|
||||
#endif
|
||||
|
||||
private final class ManagedSynchronizeMarkAllUnseenPersonalMessagesOperationsHelper {
|
||||
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 SynchronizeMarkAllUnseenPersonalMessagesOperation {
|
||||
result = entry.mergedEntry!
|
||||
return PeerOperationLogEntryUpdate(mergedIndex: .none, contents: .none)
|
||||
} else {
|
||||
return PeerOperationLogEntryUpdate(mergedIndex: .none, contents: .none)
|
||||
}
|
||||
})
|
||||
|
||||
return f(transaction, result)
|
||||
} |> switchToLatest
|
||||
}
|
||||
|
||||
func managedSynchronizeMarkAllUnseenPersonalMessagesOperations(postbox: Postbox, network: Network, stateManager: AccountStateManager) -> Signal<Void, NoError> {
|
||||
return Signal { _ in
|
||||
let tag: PeerOperationLogTag = OperationLogTags.SynchronizeMarkAllUnseenPersonalMessages
|
||||
|
||||
let helper = Atomic<ManagedSynchronizeMarkAllUnseenPersonalMessagesOperationsHelper>(value: ManagedSynchronizeMarkAllUnseenPersonalMessagesOperationsHelper())
|
||||
|
||||
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? SynchronizeMarkAllUnseenPersonalMessagesOperation {
|
||||
return synchronizeMarkAllUnseen(transaction: transaction, postbox: postbox, network: network, stateManager: stateManager, peerId: entry.peerId, 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 GetUnseenIdsError {
|
||||
case done
|
||||
case error(MTRpcError)
|
||||
}
|
||||
|
||||
private func synchronizeMarkAllUnseen(transaction: Transaction, postbox: Postbox, network: Network, stateManager: AccountStateManager, peerId: PeerId, operation: SynchronizeMarkAllUnseenPersonalMessagesOperation) -> Signal<Void, NoError> {
|
||||
guard let inputPeer = transaction.getPeer(peerId).flatMap(apiInputPeer) else {
|
||||
return .complete()
|
||||
}
|
||||
let inputChannel = transaction.getPeer(peerId).flatMap(apiInputChannel)
|
||||
let oneOperation: Signal<Bool, MTRpcError> = network.request(Api.functions.messages.getUnreadMentions(peer: inputPeer, offsetId: 0, addOffset: 0, limit: 100, maxId: 0, minId: 0))
|
||||
|> mapToSignal { result -> Signal<[MessageId], MTRpcError> in
|
||||
switch result {
|
||||
case let .messages(messages, _, _):
|
||||
return .single(messages.compactMap({ $0.id }))
|
||||
case let .channelMessages(channelMessages):
|
||||
return .single(channelMessages.messages.compactMap({ $0.id }))
|
||||
case .messagesNotModified:
|
||||
return .single([])
|
||||
case let .messagesSlice(messagesSlice):
|
||||
return .single(messagesSlice.messages.compactMap({ $0.id }))
|
||||
}
|
||||
}
|
||||
|> mapToSignal { ids -> Signal<Bool, MTRpcError> in
|
||||
if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
guard let inputChannel = inputChannel else {
|
||||
return .single(true)
|
||||
}
|
||||
return network.request(Api.functions.channels.readMessageContents(channel: inputChannel, id: ids.map { $0.id }))
|
||||
|> mapToSignal { result -> Signal<Bool, MTRpcError> in
|
||||
return .single(true)
|
||||
}
|
||||
} else {
|
||||
return network.request(Api.functions.messages.readMessageContents(id: ids.map { $0.id }))
|
||||
|> mapToSignal { result -> Signal<Bool, MTRpcError> in
|
||||
switch result {
|
||||
case let .affectedMessages(pts, ptsCount):
|
||||
stateManager.addUpdateGroups([.updatePts(pts: pts, ptsCount: ptsCount)])
|
||||
}
|
||||
return .single(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
let loopOperations: Signal<Void, GetUnseenIdsError> = (
|
||||
(oneOperation
|
||||
|> `catch` { error -> Signal<Bool, GetUnseenIdsError> in
|
||||
return .fail(.error(error))
|
||||
}
|
||||
)
|
||||
|> mapToSignal { result -> Signal<Void, GetUnseenIdsError> in
|
||||
if result {
|
||||
return .fail(.done)
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
|> `catch` { error -> Signal<Void, GetUnseenIdsError> in
|
||||
switch error {
|
||||
case .done, .error:
|
||||
return .fail(error)
|
||||
}
|
||||
}
|
||||
|> restart
|
||||
)
|
||||
return loopOperations
|
||||
|> `catch` { _ -> Signal<Void, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
}
|
@ -123,6 +123,7 @@ struct OperationLogTags {
|
||||
static let SynchronizeLocalizationUpdates = PeerOperationLogTag(value: 13)
|
||||
static let SynchronizeSavedStickers = PeerOperationLogTag(value: 14)
|
||||
static let SynchronizeGroupedPeers = PeerOperationLogTag(value: 15)
|
||||
static let SynchronizeMarkAllUnseenPersonalMessages = PeerOperationLogTag(value: 16)
|
||||
}
|
||||
|
||||
private enum PreferencesKeyValues: Int32 {
|
||||
|
@ -7,13 +7,86 @@ import Foundation
|
||||
import SwiftSignalKit
|
||||
#endif
|
||||
|
||||
public func recentPeers(account: Account) -> Signal<[Peer], NoError> {
|
||||
let cachedPeers = account.postbox.recentPeers()
|
||||
|> take(1)
|
||||
public enum RecentPeers {
|
||||
case peers([Peer])
|
||||
case disabled
|
||||
}
|
||||
|
||||
final class CachedRecentPeers: PostboxCoding {
|
||||
let enabled: Bool
|
||||
let ids: [PeerId]
|
||||
|
||||
let remotePeers = account.network.request(Api.functions.contacts.getTopPeers(flags: 1 << 0, offset: 0, limit: 16, hash: 0))
|
||||
|> retryRequest
|
||||
|> map { result -> ([Peer], [PeerId: PeerPresence])? in
|
||||
init(enabled: Bool, ids: [PeerId]) {
|
||||
self.enabled = enabled
|
||||
self.ids = ids
|
||||
}
|
||||
|
||||
init(decoder: PostboxDecoder) {
|
||||
self.enabled = decoder.decodeInt32ForKey("enabled", orElse: 0) != 0
|
||||
self.ids = decoder.decodeInt64ArrayForKey("ids").map(PeerId.init)
|
||||
}
|
||||
|
||||
func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeInt32(self.enabled ? 1 : 0, forKey: "enabled")
|
||||
encoder.encodeInt64Array(self.ids.map({ $0.toInt64() }), forKey: "ids")
|
||||
}
|
||||
|
||||
static func cacheKey() -> ValueBoxKey {
|
||||
let key = ValueBoxKey(length: 0)
|
||||
return key
|
||||
}
|
||||
}
|
||||
|
||||
private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 1, highWaterItemCount: 1)
|
||||
|
||||
private func cachedRecentPeersEntryId() -> ItemCacheEntryId {
|
||||
return ItemCacheEntryId(collectionId: 101, key: CachedRecentPeers.cacheKey())
|
||||
}
|
||||
|
||||
public func recentPeers(account: Account) -> Signal<RecentPeers, NoError> {
|
||||
let key = PostboxViewKey.cachedItem(cachedRecentPeersEntryId())
|
||||
return account.postbox.combinedView(keys: [key])
|
||||
|> mapToSignal { views -> Signal<RecentPeers, NoError> in
|
||||
if let value = (views.views[key] as? CachedItemView)?.value as? CachedRecentPeers {
|
||||
if value.enabled {
|
||||
return account.postbox.multiplePeersView(value.ids)
|
||||
|> map { view -> RecentPeers in
|
||||
var peers: [Peer] = []
|
||||
for id in value.ids {
|
||||
if let peer = view.peers[id], id != account.peerId {
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
return .peers(peers)
|
||||
}
|
||||
} else {
|
||||
return .single(.disabled)
|
||||
}
|
||||
} else {
|
||||
return .single(.peers([]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func managedUpdatedRecentPeers(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
|
||||
let key = PostboxViewKey.cachedItem(cachedRecentPeersEntryId())
|
||||
let peersEnabled = postbox.combinedView(keys: [key])
|
||||
|> map { views -> Bool in
|
||||
if let value = (views.views[key] as? CachedItemView)?.value as? CachedRecentPeers {
|
||||
return value.enabled
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
|
||||
let updateOnce =
|
||||
network.request(Api.functions.contacts.getTopPeers(flags: 1 << 0, offset: 0, limit: 16, hash: 0))
|
||||
|> `catch` { _ -> Signal<Api.contacts.TopPeers, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
|> mapToSignal { result -> Signal<Void, NoError> in
|
||||
return postbox.transaction { transaction -> Void in
|
||||
switch result {
|
||||
case let .topPeers(_, _, users):
|
||||
var peers: [Peer] = []
|
||||
@ -25,39 +98,33 @@ public func recentPeers(account: Account) -> Signal<[Peer], NoError> {
|
||||
peerPresences[telegramUser.id] = presence
|
||||
}
|
||||
}
|
||||
return (peers, peerPresences)
|
||||
case .topPeersNotModified:
|
||||
break
|
||||
}
|
||||
return ([], [:])
|
||||
}
|
||||
|
||||
let updatedRemotePeers = remotePeers
|
||||
|> mapToSignal { peersAndPresences -> Signal<[Peer], NoError> in
|
||||
if let (peers, peerPresences) = peersAndPresences {
|
||||
return account.postbox.transaction { transaction -> [Peer] in
|
||||
updatePeers(transaction: transaction, peers: peers, update: { return $1 })
|
||||
transaction.updatePeerPresences(peerPresences)
|
||||
transaction.replaceRecentPeerIds(peers.map({ $0.id }))
|
||||
return peers
|
||||
}
|
||||
} else {
|
||||
return .complete()
|
||||
|
||||
transaction.putItemCacheEntry(id: cachedRecentPeersEntryId(), entry: CachedRecentPeers(enabled: true, ids: peers.map { $0.id }), collectionSpec: collectionSpec)
|
||||
case .topPeersNotModified:
|
||||
break
|
||||
case .topPeersDisabled:
|
||||
transaction.putItemCacheEntry(id: cachedRecentPeersEntryId(), entry: CachedRecentPeers(enabled: false, ids: []), collectionSpec: collectionSpec)
|
||||
}
|
||||
}
|
||||
return cachedPeers
|
||||
|> then(updatedRemotePeers |> filter({ !$0.isEmpty }))
|
||||
|> map { peers -> [Peer] in
|
||||
return peers.filter { $0.id != account.peerId }
|
||||
}
|
||||
}
|
||||
|
||||
return peersEnabled |> mapToSignal { _ -> Signal<Void, NoError> in
|
||||
return updateOnce
|
||||
}
|
||||
}
|
||||
|
||||
public func removeRecentPeer(account: Account, peerId: PeerId) -> Signal<Void, NoError> {
|
||||
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||
var peerIds = transaction.getRecentPeerIds()
|
||||
if let index = peerIds.index(of: peerId) {
|
||||
peerIds.remove(at: index)
|
||||
transaction.replaceRecentPeerIds(peerIds)
|
||||
guard let entry = transaction.retrieveItemCacheEntry(id: cachedRecentPeersEntryId()) as? CachedRecentPeers else {
|
||||
return .complete()
|
||||
}
|
||||
|
||||
if let index = entry.ids.index(of: peerId) {
|
||||
var updatedIds = entry.ids
|
||||
updatedIds.remove(at: index)
|
||||
transaction.putItemCacheEntry(id: cachedRecentPeersEntryId(), entry: CachedRecentPeers(enabled: entry.enabled, ids: updatedIds), collectionSpec: collectionSpec)
|
||||
}
|
||||
if let peer = transaction.getPeer(peerId), let apiPeer = apiInputPeer(peer) {
|
||||
return account.network.request(Api.functions.contacts.resetTopPeerRating(category: .topPeerCategoryCorrespondents, peer: apiPeer))
|
||||
@ -73,11 +140,39 @@ public func removeRecentPeer(account: Account, peerId: PeerId) -> Signal<Void, N
|
||||
} |> switchToLatest
|
||||
}
|
||||
|
||||
public func updateRecentPeersEnabled(postbox: Postbox, network: Network, enabled: Bool) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||
var currentValue = true
|
||||
if let entry = transaction.retrieveItemCacheEntry(id: cachedRecentPeersEntryId()) as? CachedRecentPeers {
|
||||
currentValue = entry.enabled
|
||||
if !enabled {
|
||||
transaction.putItemCacheEntry(id: cachedRecentPeersEntryId(), entry: CachedRecentPeers(enabled: false, ids: []), collectionSpec: collectionSpec)
|
||||
} else {
|
||||
transaction.putItemCacheEntry(id: cachedRecentPeersEntryId(), entry: CachedRecentPeers(enabled: true, ids: entry.ids), collectionSpec: collectionSpec)
|
||||
}
|
||||
}
|
||||
|
||||
if currentValue == enabled {
|
||||
return .complete()
|
||||
}
|
||||
|
||||
return network.request(Api.functions.contacts.toggleTopPeers(enabled: currentValue ? .boolTrue : .boolFalse))
|
||||
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
||||
return .single(.boolFalse)
|
||||
}
|
||||
|> mapToSignal { _ -> Signal<Void, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
} |> switchToLatest
|
||||
}
|
||||
|
||||
public func managedRecentlyUsedInlineBots(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
|
||||
let remotePeers = network.request(Api.functions.contacts.getTopPeers(flags: 1 << 2, offset: 0, limit: 16, hash: 0))
|
||||
|> retryRequest
|
||||
|> map { result -> ([Peer], [PeerId: PeerPresence], [(PeerId, Double)])? in
|
||||
switch result {
|
||||
case .topPeersDisabled:
|
||||
break
|
||||
case let .topPeers(categories, _, users):
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: PeerPresence] = [:]
|
||||
|
@ -48,10 +48,10 @@ func apiFunctionDescription(of desc: FunctionDescription) -> String {
|
||||
redactParam = redactParams.contains(param.0)
|
||||
}
|
||||
|
||||
if redactParam {
|
||||
if redactParam, Logger.shared.redactSensitiveData {
|
||||
result.append("[[redacted]]")
|
||||
} else {
|
||||
result.append(recursiveDescription(redact: true, of: param.1))
|
||||
result.append(recursiveDescription(redact: Logger.shared.redactSensitiveData, of: param.1))
|
||||
}
|
||||
}
|
||||
result.append(")")
|
||||
@ -195,13 +195,7 @@ public class BoxedMessage: NSObject {
|
||||
|
||||
override public var description: String {
|
||||
get {
|
||||
let redact: Bool
|
||||
#if DEBUG
|
||||
redact = true
|
||||
#else
|
||||
redact = true
|
||||
#endif
|
||||
return recursiveDescription(redact: redact, of: self.body)
|
||||
return recursiveDescription(redact: Logger.shared.redactSensitiveData, of: self.body)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,47 @@
|
||||
import Foundation
|
||||
#if os(macOS)
|
||||
import PostboxMac
|
||||
import SwiftSignalKitMac
|
||||
#else
|
||||
import Postbox
|
||||
import SwiftSignalKit
|
||||
#endif
|
||||
|
||||
final class SynchronizeMarkAllUnseenPersonalMessagesOperation: PostboxCoding {
|
||||
let maxId: MessageId.Id
|
||||
|
||||
init(maxId: MessageId.Id) {
|
||||
self.maxId = maxId
|
||||
}
|
||||
|
||||
init(decoder: PostboxDecoder) {
|
||||
self.maxId = decoder.decodeInt32ForKey("maxId", orElse: Int32.min + 1)
|
||||
}
|
||||
|
||||
func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeInt32(self.maxId, forKey: "maxId")
|
||||
}
|
||||
}
|
||||
|
||||
func addSynchronizeMarkAllUnseenPersonalMessagesOperation(transaction: Transaction, peerId: PeerId, maxId: MessageId.Id) {
|
||||
let tag: PeerOperationLogTag = OperationLogTags.SynchronizeMarkAllUnseenPersonalMessages
|
||||
|
||||
var topLocalIndex: Int32?
|
||||
var currentMaxId: MessageId.Id?
|
||||
transaction.operationLogEnumerateEntries(peerId: peerId, tag: tag, { entry in
|
||||
topLocalIndex = entry.tagLocalIndex
|
||||
if let operation = entry.contents as? SynchronizeMarkAllUnseenPersonalMessagesOperation {
|
||||
currentMaxId = operation.maxId
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
if let topLocalIndex = topLocalIndex {
|
||||
if let currentMaxId = currentMaxId, currentMaxId >= maxId {
|
||||
return
|
||||
}
|
||||
let _ = transaction.operationLogRemoveEntry(peerId: peerId, tag: tag, tagLocalIndex: topLocalIndex)
|
||||
}
|
||||
|
||||
transaction.operationLogAddEntry(peerId: peerId, tag: tag, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: SynchronizeMarkAllUnseenPersonalMessagesOperation(maxId: maxId))
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user