diff --git a/TelegramUI/ChatHistoryListNode.swift b/TelegramUI/ChatHistoryListNode.swift index 6f109dd442..96496e9d39 100644 --- a/TelegramUI/ChatHistoryListNode.swift +++ b/TelegramUI/ChatHistoryListNode.swift @@ -55,7 +55,7 @@ public struct ChatHistoryCombinedInitialData { } enum ChatHistoryViewUpdate { - case Loading(initialData: ChatHistoryCombinedInitialData?) + case Loading(initialData: ChatHistoryCombinedInitialData?, type: ChatHistoryViewUpdateType) case HistoryView(view: MessageHistoryView, type: ChatHistoryViewUpdateType, scrollPosition: ChatHistoryViewScrollPosition?, originalScrollPosition: ChatHistoryViewScrollPosition?, initialData: ChatHistoryCombinedInitialData, id: Int32) } @@ -483,9 +483,30 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { let historyViewTransition = combineLatest(historyViewUpdate, self.chatPresentationDataPromise.get(), selectedMessages, automaticDownloadNetworkType, self.historyAppearsClearedPromise.get()) |> introduceError(Void.self) |> mapToQueue { [weak self] update, chatPresentationData, selectedMessages, networkType, historyAppearsCleared -> Signal in + func applyHole() { + Queue.mainQueue().async { + if let strongSelf = self { + let historyView = (strongSelf.opaqueTransactionState as? ChatHistoryTransactionOpaqueState)?.historyView + let displayRange = strongSelf.displayedItemRange + if let filteredEntries = historyView?.filteredEntries, let visibleRange = displayRange.visibleRange { + let lastEntry = filteredEntries[filteredEntries.count - 1 - visibleRange.lastIndex] + + strongSelf.chatHistoryLocation.set(ChatHistoryLocationInput(content: .Navigation(index: .message(lastEntry.index), anchorIndex: .message(lastEntry.index), count: historyMessageCount), id: 0)) + } else { + strongSelf.chatHistoryLocation.set(ChatHistoryLocationInput(content: .Initial(count: 60), id: 0)) + } + } + } + } + let initialData: ChatHistoryCombinedInitialData? switch update { - case let .Loading(combinedInitialData): + case let .Loading(combinedInitialData, type): + if case .Generic(.FillHole) = type { + applyHole() + return .fail(Void()) + } + initialData = combinedInitialData Queue.mainQueue().async { if let strongSelf = self { @@ -512,19 +533,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { return .complete() case let .HistoryView(view, type, scrollPosition, originalScrollPosition, data, id): if case .Generic(.FillHole) = type { - Queue.mainQueue().async { - if let strongSelf = self { - let historyView = (strongSelf.opaqueTransactionState as? ChatHistoryTransactionOpaqueState)?.historyView - let displayRange = strongSelf.displayedItemRange - if let filteredEntries = historyView?.filteredEntries, let visibleRange = displayRange.visibleRange { - let lastEntry = filteredEntries[filteredEntries.count - 1 - visibleRange.lastIndex] - - strongSelf.chatHistoryLocation.set(ChatHistoryLocationInput(content: .Navigation(index: .message(lastEntry.index), anchorIndex: .message(lastEntry.index), count: historyMessageCount), id: 0)) - } else { - strongSelf.chatHistoryLocation.set(ChatHistoryLocationInput(content: .Initial(count: 60), id: 0)) - } - } - } + applyHole() return .fail(Void()) } @@ -630,7 +639,9 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { if apply { switch chatLocation { case .peer: - let _ = applyMaxReadIndexInteractively(postbox: context.account.postbox, stateManager: context.account.stateManager, index: messageIndex).start() + if !context.sharedContext.immediateExperimentalUISettings.skipReadHistory { + let _ = applyMaxReadIndexInteractively(postbox: context.account.postbox, stateManager: context.account.stateManager, index: messageIndex).start() + } /*case let .group(groupId): let _ = context.account.postbox.transaction({ transaction -> Void in transaction.applyGroupFeedInteractiveReadMaxIndex(groupId: groupId, index: messageIndex) @@ -1270,7 +1281,9 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { } } else if self.interactiveReadActionDisposable == nil { if case let .peer(peerId) = self.chatLocation { - self.interactiveReadActionDisposable = installInteractiveReadMessagesAction(postbox: self.context.account.postbox, stateManager: self.context.account.stateManager, peerId: peerId) + if !self.context.sharedContext.immediateExperimentalUISettings.skipReadHistory { + self.interactiveReadActionDisposable = installInteractiveReadMessagesAction(postbox: self.context.account.postbox, stateManager: self.context.account.stateManager, peerId: peerId) + } } } } diff --git a/TelegramUI/ChatHistoryViewForLocation.swift b/TelegramUI/ChatHistoryViewForLocation.swift index 3ce5d6ff8a..f18a491e3a 100644 --- a/TelegramUI/ChatHistoryViewForLocation.swift +++ b/TelegramUI/ChatHistoryViewForLocation.swift @@ -25,7 +25,7 @@ func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, account: A return .HistoryView(view: view, type: .Generic(type: updateType), scrollPosition: nil, originalScrollPosition: nil, initialData: combinedInitialData, id: location.id) } else { if view.isLoading { - return .Loading(initialData: combinedInitialData) + return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType)) } var scrollPosition: ChatHistoryViewScrollPosition? @@ -53,7 +53,7 @@ func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, account: A if case let .peer(peerId) = chatLocation, let combinedReadStates = view.fixedReadStates, case let .peer(readStates) = combinedReadStates, let readState = readStates[peerId], readState.count == incomingCount { } else { fadeIn = true - return .Loading(initialData: combinedInitialData) + return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType)) } } } @@ -62,7 +62,7 @@ func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, account: A } else { if view.entries.isEmpty && (view.holeEarlier || view.holeLater) { fadeIn = true - return .Loading(initialData: combinedInitialData) + return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType)) } } @@ -105,11 +105,11 @@ func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, account: A let maxIndex = min(view.entries.count, targetIndex + count / 2) if minIndex == 0 && view.holeEarlier { fadeIn = true - return .Loading(initialData: combinedInitialData) + return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType)) } if maxIndex == view.entries.count && view.holeLater { fadeIn = true - return .Loading(initialData: combinedInitialData) + return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType)) } } diff --git a/TelegramUI/DebugController.swift b/TelegramUI/DebugController.swift index 2afde5b657..6c42df43cc 100644 --- a/TelegramUI/DebugController.swift +++ b/TelegramUI/DebugController.swift @@ -36,6 +36,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { case redactSensitiveData(PresentationTheme, Bool) case enableRaiseToSpeak(PresentationTheme, Bool) case keepChatNavigationStack(PresentationTheme, Bool) + case skipReadHistory(PresentationTheme, Bool) case clearTips(PresentationTheme) case reimport(PresentationTheme) case resetData(PresentationTheme) @@ -50,7 +51,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { return DebugControllerSection.logs.rawValue case .logToFile, .logToConsole, .redactSensitiveData: return DebugControllerSection.logging.rawValue - case .enableRaiseToSpeak, .keepChatNavigationStack: + case .enableRaiseToSpeak, .keepChatNavigationStack, .skipReadHistory: return DebugControllerSection.experiments.rawValue case .clearTips, .reimport, .resetData, .animatedStickers: return DebugControllerSection.experiments.rawValue @@ -79,6 +80,8 @@ private enum DebugControllerEntry: ItemListNodeEntry { return 7 case .keepChatNavigationStack: return 8 + case .skipReadHistory: + return 9 case .clearTips: return 10 case .reimport: @@ -208,6 +211,14 @@ private enum DebugControllerEntry: ItemListNodeEntry { return settings }).start() }) + case let .skipReadHistory(theme, value): + return ItemListSwitchItem(theme: theme, title: "Skip read history", value: value, sectionId: self.section, style: .blocks, updated: { value in + let _ = updateExperimentalUISettingsInteractively(accountManager: arguments.sharedContext.accountManager, { settings in + var settings = settings + settings.skipReadHistory = value + return settings + }).start() + }) case let .clearTips(theme): return ItemListActionItem(theme: theme, title: "Clear Tips", kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: { let _ = (arguments.sharedContext.accountManager.transaction { transaction -> Void in @@ -276,6 +287,9 @@ private func debugControllerEntries(presentationData: PresentationData, loggingS entries.append(.enableRaiseToSpeak(presentationData.theme, mediaInputSettings.enableRaiseToSpeak)) entries.append(.keepChatNavigationStack(presentationData.theme, experimentalSettings.keepChatNavigationStack)) + #if DEBUG + entries.append(.skipReadHistory(presentationData.theme, experimentalSettings.skipReadHistory)) + #endif entries.append(.clearTips(presentationData.theme)) if hasLegacyAppData { entries.append(.reimport(presentationData.theme)) diff --git a/TelegramUI/ExperimentalUISettings.swift b/TelegramUI/ExperimentalUISettings.swift index 0e212348e4..e2a1c7a79a 100644 --- a/TelegramUI/ExperimentalUISettings.swift +++ b/TelegramUI/ExperimentalUISettings.swift @@ -4,21 +4,25 @@ import SwiftSignalKit public struct ExperimentalUISettings: Equatable, PreferencesEntry { public var keepChatNavigationStack: Bool + public var skipReadHistory: Bool public static var defaultSettings: ExperimentalUISettings { - return ExperimentalUISettings(keepChatNavigationStack: false) + return ExperimentalUISettings(keepChatNavigationStack: false, skipReadHistory: false) } - public init(keepChatNavigationStack: Bool) { + public init(keepChatNavigationStack: Bool, skipReadHistory: Bool) { self.keepChatNavigationStack = keepChatNavigationStack + self.skipReadHistory = skipReadHistory } public init(decoder: PostboxDecoder) { self.keepChatNavigationStack = decoder.decodeInt32ForKey("keepChatNavigationStack", orElse: 0) != 0 + self.skipReadHistory = decoder.decodeInt32ForKey("skipReadHistory", orElse: 0) != 0 } public func encode(_ encoder: PostboxEncoder) { encoder.encodeInt32(self.keepChatNavigationStack ? 1 : 0, forKey: "keepChatNavigationStack") + encoder.encodeInt32(self.skipReadHistory ? 1 : 0, forKey: "skipReadHistory") } public func isEqual(to: PreferencesEntry) -> Bool { diff --git a/TelegramUI/SharedAccountContext.swift b/TelegramUI/SharedAccountContext.swift index c4a6ad1c73..8aac02380b 100644 --- a/TelegramUI/SharedAccountContext.swift +++ b/TelegramUI/SharedAccountContext.swift @@ -158,7 +158,7 @@ public final class SharedAccountContext { private let displayUpgradeProgress: (Float?) -> Void - public init(mainWindow: Window1?, basePath: String, encryptionKey: Data, accountManager: AccountManager, applicationBindings: TelegramApplicationBindings, initialPresentationDataAndSettings: InitialPresentationDataAndSettings, networkArguments: NetworkInitializationArguments, rootPath: String, legacyBasePath: String?, legacyCache: LegacyCache?, apsNotificationToken: Signal, voipNotificationToken: Signal, setNotificationCall: @escaping (PresentationCall?) -> Void, navigateToChat: @escaping (AccountRecordId, PeerId, MessageId?) -> Void, displayUpgradeProgress: @escaping (Float?) -> Void = { _ in }) { + public init(mainWindow: Window1?, basePath: String, encryptionParameters: ValueBoxEncryptionParameters, accountManager: AccountManager, applicationBindings: TelegramApplicationBindings, initialPresentationDataAndSettings: InitialPresentationDataAndSettings, networkArguments: NetworkInitializationArguments, rootPath: String, legacyBasePath: String?, legacyCache: LegacyCache?, apsNotificationToken: Signal, voipNotificationToken: Signal, setNotificationCall: @escaping (PresentationCall?) -> Void, navigateToChat: @escaping (AccountRecordId, PeerId, MessageId?) -> Void, displayUpgradeProgress: @escaping (Float?) -> Void = { _ in }) { assert(Queue.mainQueue().isCurrent()) self.mainWindow = mainWindow self.applicationBindings = applicationBindings @@ -331,7 +331,7 @@ public final class SharedAccountContext { var addedAuthSignal: Signal = .single(nil) for (id, attributes) in records { if self.activeAccountsValue?.accounts.firstIndex(where: { $0.0 == id}) == nil { - addedSignals.append(accountWithId(accountManager: accountManager, networkArguments: networkArguments, id: id, encryptionKey: encryptionKey, supplementary: !applicationBindings.isMainApp, rootPath: rootPath, beginWithTestingEnvironment: attributes.isTestingEnvironment, auxiliaryMethods: telegramAccountAuxiliaryMethods) + addedSignals.append(accountWithId(accountManager: accountManager, networkArguments: networkArguments, id: id, encryptionParameters: encryptionParameters, supplementary: !applicationBindings.isMainApp, rootPath: rootPath, beginWithTestingEnvironment: attributes.isTestingEnvironment, auxiliaryMethods: telegramAccountAuxiliaryMethods) |> map { result -> AddedAccountResult in switch result { case let .authorized(account): @@ -352,7 +352,7 @@ public final class SharedAccountContext { } } if let authRecord = authRecord, authRecord.0 != self.activeAccountsValue?.currentAuth?.id { - addedAuthSignal = accountWithId(accountManager: accountManager, networkArguments: networkArguments, id: authRecord.0, encryptionKey: encryptionKey, supplementary: !applicationBindings.isMainApp, rootPath: rootPath, beginWithTestingEnvironment: authRecord.1, auxiliaryMethods: telegramAccountAuxiliaryMethods) + addedAuthSignal = accountWithId(accountManager: accountManager, networkArguments: networkArguments, id: authRecord.0, encryptionParameters: encryptionParameters, supplementary: !applicationBindings.isMainApp, rootPath: rootPath, beginWithTestingEnvironment: authRecord.1, auxiliaryMethods: telegramAccountAuxiliaryMethods) |> map { result -> UnauthorizedAccount? in switch result { case let .unauthorized(account): @@ -590,7 +590,7 @@ public final class SharedAccountContext { let _ = immediateHasOngoingCallValue.swap(value) }) - let _ = managedCleanupAccounts(networkArguments: networkArguments, accountManager: self.accountManager, rootPath: rootPath, auxiliaryMethods: telegramAccountAuxiliaryMethods, encryptionKey: encryptionKey).start() + let _ = managedCleanupAccounts(networkArguments: networkArguments, accountManager: self.accountManager, rootPath: rootPath, auxiliaryMethods: telegramAccountAuxiliaryMethods, encryptionParameters: encryptionParameters).start() self.updateNotificationTokensRegistration() } diff --git a/TelegramUI/UpgradedAccounts.swift b/TelegramUI/UpgradedAccounts.swift index fc7737ac41..82a65dfa30 100644 --- a/TelegramUI/UpgradedAccounts.swift +++ b/TelegramUI/UpgradedAccounts.swift @@ -107,7 +107,7 @@ private func upgradedSharedDataValue(_ value: PreferencesEntry?) -> PreferencesE } } -public func upgradedAccounts(accountManager: AccountManager, rootPath: String, encryptionKey: Data) -> Signal { +public func upgradedAccounts(accountManager: AccountManager, rootPath: String, encryptionParameters: ValueBoxEncryptionParameters) -> Signal { return accountManager.transaction { transaction -> (Int32, AccountRecordId?) in return (transaction.getVersion(), transaction.getCurrent()?.0) } @@ -115,7 +115,7 @@ public func upgradedAccounts(accountManager: AccountManager, rootPath: String, e var signal: Signal = .complete() if version < 1 { if let currentId = currentId { - let upgradePreferences = accountPreferenceEntries(rootPath: rootPath, id: currentId, keys: Set(preferencesKeyMapping.keys.map({ $0.key }) + applicationSpecificPreferencesKeyMapping.keys.map({ $0.key })), encryptionKey: encryptionKey) + let upgradePreferences = accountPreferenceEntries(rootPath: rootPath, id: currentId, keys: Set(preferencesKeyMapping.keys.map({ $0.key }) + applicationSpecificPreferencesKeyMapping.keys.map({ $0.key })), encryptionParameters: encryptionParameters) |> mapToSignal { path, values -> Signal in return accountManager.transaction { transaction -> Void in for (key, value) in values { @@ -187,7 +187,7 @@ public func upgradedAccounts(accountManager: AccountManager, rootPath: String, e } if version < 2 { if let currentId = currentId { - let upgradeNotices = accountNoticeEntries(rootPath: rootPath, id: currentId, encryptionKey: encryptionKey) + let upgradeNotices = accountNoticeEntries(rootPath: rootPath, id: currentId, encryptionParameters: encryptionParameters) |> mapToSignal { path, values -> Signal in return accountManager.transaction { transaction -> Void in for (key, value) in values { @@ -221,7 +221,7 @@ public func upgradedAccounts(accountManager: AccountManager, rootPath: String, e } if version < 3 { if let currentId = currentId { - let upgradeAccessChallengeData = accountLegacyAccessChallengeData(rootPath: rootPath, id: currentId, encryptionKey: encryptionKey) + let upgradeAccessChallengeData = accountLegacyAccessChallengeData(rootPath: rootPath, id: currentId, encryptionParameters: encryptionParameters) |> mapToSignal { accessChallengeData -> Signal in return accountManager.transaction { transaction -> Void in if case .none = transaction.getAccessChallengeData() { @@ -248,7 +248,7 @@ public func upgradedAccounts(accountManager: AccountManager, rootPath: String, e |> mapToSignal { globalSettings, ids -> Signal in var importSignal: Signal = .complete() for id in ids { - let importInfoAccounttSignal = accountTransaction(rootPath: rootPath, id: id, encryptionKey: encryptionKey, transaction: { transaction -> Void in + let importInfoAccounttSignal = accountTransaction(rootPath: rootPath, id: id, encryptionParameters: encryptionParameters, transaction: { transaction -> Void in transaction.updatePreferencesEntry(key: PreferencesKeys.contactsSettings, { current in var settings = current as? ContactsSettings ?? ContactsSettings.defaultSettings settings.synchronizeContacts = globalSettings._legacySynchronizeDeviceContacts