Various fixes

This commit is contained in:
Ilya Laktyushin 2023-02-23 23:49:04 +04:00
parent 8188bc2858
commit 4c500ce3b2
17 changed files with 107 additions and 2098 deletions

View File

@ -8934,3 +8934,5 @@ Sorry for the inconvenience.";
"MediaPicker.VoiceOver.Camera" = "Camera";
"ChatList.ReadAll" = "Read All";
"ChatList.ClearSavedMessagesConfirmation" = "Are you sure you want to delete all your saved messages?";

View File

@ -2177,6 +2177,18 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
reorderedFilterIdsValue = reorderedFilterIds
}
let completion = { [weak self] in
guard let strongSelf = self else {
return
}
strongSelf.chatListDisplayNode.isReorderingFilters = false
strongSelf.isReorderingTabsValue.set(false)
(strongSelf.parent as? TabBarController)?.updateIsTabBarEnabled(true, transition: .animated(duration: 0.2, curve: .easeInOut))
strongSelf.searchContentNode?.setIsEnabled(true, animated: true)
if let layout = strongSelf.validLayout {
strongSelf.updateLayout(layout: layout, transition: .animated(duration: 0.2, curve: .easeInOut))
}
}
if let reorderedFilterIds = reorderedFilterIdsValue {
let _ = (self.context.engine.peers.updateChatListFiltersInteractively { stateFilters in
var updatedFilters: [ChatListFilter] = []
@ -2199,18 +2211,11 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
return
}
strongSelf.reloadFilters(firstUpdate: {
guard let strongSelf = self else {
return
}
strongSelf.chatListDisplayNode.isReorderingFilters = false
strongSelf.isReorderingTabsValue.set(false)
(strongSelf.parent as? TabBarController)?.updateIsTabBarEnabled(true, transition: .animated(duration: 0.2, curve: .easeInOut))
strongSelf.searchContentNode?.setIsEnabled(true, animated: true)
if let layout = strongSelf.validLayout {
strongSelf.updateLayout(layout: layout, transition: .animated(duration: 0.2, curve: .easeInOut))
}
completion()
})
})
} else {
completion()
}
}

View File

@ -32,7 +32,7 @@ func chatListSelectionOptions(context: AccountContext, peerIds: Set<PeerId>, fil
return context.engine.data.subscribe(TelegramEngine.EngineData.Item.Messages.TotalReadCounters())
|> map { readCounters -> ChatListSelectionOptions in
var hasUnread = false
if readCounters.count(for: .filtered, in: .chats, with: .all) != 0 {
if readCounters.count(for: .raw, in: .chats, with: .all) != 0 {
hasUnread = true
}
return ChatListSelectionOptions(read: .all(enabled: hasUnread), delete: false)

View File

@ -129,7 +129,7 @@ private final class DeleteChatPeerActionSheetItemNode: ActionSheetItemNode {
}
case let .clearHistory(canClearCache):
if peer.id == context.account.peerId {
text = PresentationStrings.FormattedString(string: strings.ChatList_DeleteSavedMessagesConfirmation, ranges: [])
text = PresentationStrings.FormattedString(string: strings.ChatList_ClearSavedMessagesConfirmation, ranges: [])
} else if case .user = peer {
text = strings.ChatList_ClearChatConfirmation(peer.displayTitle(strings: strings, displayOrder: nameOrder))
} else {

View File

@ -1514,7 +1514,7 @@ open class TextNode: ASDisplayNode {
if glyphCount == 2, let font = attributes["NSFont"] as? UIFont, font.fontName.contains("ColorEmoji"), let string = layout.attributedString {
let range = CTRunGetStringRange(run)
if range.location < string.length && (range.location + range.length) < string.length {
if range.location < string.length && (range.location + range.length) <= string.length {
let substring = string.attributedSubstring(from: NSMakeRange(range.location, range.length)).string
let heart = Unicode.Scalar(0x2764)!

View File

@ -1,435 +0,0 @@
import Foundation
import UIKit
import Display
import SwiftSignalKit
import Postbox
import TelegramCore
import TelegramPresentationData
import ItemListUI
import PresentationDataUtils
import AccountContext
private enum NetworkUsageControllerSection {
case cellular
case wifi
}
private final class NetworkUsageStatsControllerArguments {
let resetStatistics: (NetworkUsageControllerSection) -> Void
init(resetStatistics: @escaping (NetworkUsageControllerSection) -> Void) {
self.resetStatistics = resetStatistics
}
}
private enum NetworkUsageStatsSection: Int32 {
case messages
case image
case video
case audio
case file
case call
case total
case reset
}
private enum NetworkUsageStatsEntry: ItemListNodeEntry {
case messagesHeader(PresentationTheme, String)
case messagesSent(PresentationTheme, String, String)
case messagesReceived(PresentationTheme, String, String)
case imageHeader(PresentationTheme, String)
case imageSent(PresentationTheme, String, String)
case imageReceived(PresentationTheme, String, String)
case videoHeader(PresentationTheme, String)
case videoSent(PresentationTheme, String, String)
case videoReceived(PresentationTheme, String, String)
case audioHeader(PresentationTheme, String)
case audioSent(PresentationTheme, String, String)
case audioReceived(PresentationTheme, String, String)
case fileHeader(PresentationTheme, String)
case fileSent(PresentationTheme, String, String)
case fileReceived(PresentationTheme, String, String)
case callHeader(PresentationTheme, String)
case callSent(PresentationTheme, String, String)
case callReceived(PresentationTheme, String, String)
case reset(PresentationTheme, NetworkUsageControllerSection, String)
case resetTimestamp(PresentationTheme, String)
var section: ItemListSectionId {
switch self {
case .messagesHeader, .messagesSent, .messagesReceived:
return NetworkUsageStatsSection.messages.rawValue
case .imageHeader, .imageSent, .imageReceived:
return NetworkUsageStatsSection.image.rawValue
case .videoHeader, .videoSent, .videoReceived:
return NetworkUsageStatsSection.video.rawValue
case .audioHeader, .audioSent, .audioReceived:
return NetworkUsageStatsSection.audio.rawValue
case .fileHeader, .fileSent, .fileReceived:
return NetworkUsageStatsSection.file.rawValue
case .callHeader, .callSent, .callReceived:
return NetworkUsageStatsSection.call.rawValue
case .reset, .resetTimestamp:
return NetworkUsageStatsSection.reset.rawValue
}
}
var stableId: Int32 {
switch self {
case .messagesHeader:
return 0
case .messagesSent:
return 1
case .messagesReceived:
return 2
case .imageHeader:
return 3
case .imageSent:
return 4
case .imageReceived:
return 5
case .videoHeader:
return 6
case .videoSent:
return 7
case .videoReceived:
return 8
case .audioHeader:
return 9
case .audioSent:
return 10
case .audioReceived:
return 11
case .fileHeader:
return 12
case .fileSent:
return 13
case .fileReceived:
return 14
case .callHeader:
return 15
case .callSent:
return 16
case .callReceived:
return 17
case .reset:
return 18
case .resetTimestamp:
return 19
}
}
static func ==(lhs: NetworkUsageStatsEntry, rhs: NetworkUsageStatsEntry) -> Bool {
switch lhs {
case let .messagesHeader(lhsTheme, lhsText):
if case let .messagesHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .messagesSent(lhsTheme, lhsText, lhsValue):
if case let .messagesSent(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
return true
} else {
return false
}
case let .messagesReceived(lhsTheme, lhsText, lhsValue):
if case let .messagesReceived(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
return true
} else {
return false
}
case let .imageHeader(lhsTheme, lhsText):
if case let .imageHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .imageSent(lhsTheme, lhsText, lhsValue):
if case let .imageSent(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
return true
} else {
return false
}
case let .imageReceived(lhsTheme, lhsText, lhsValue):
if case let .imageReceived(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
return true
} else {
return false
}
case let .videoHeader(lhsTheme, lhsText):
if case let .videoHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .videoSent(lhsTheme, lhsText, lhsValue):
if case let .videoSent(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
return true
} else {
return false
}
case let .videoReceived(lhsTheme, lhsText, lhsValue):
if case let .videoReceived(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
return true
} else {
return false
}
case let .audioHeader(lhsTheme, lhsText):
if case let .audioHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .audioSent(lhsTheme, lhsText, lhsValue):
if case let .audioSent(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
return true
} else {
return false
}
case let .audioReceived(lhsTheme, lhsText, lhsValue):
if case let .audioReceived(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
return true
} else {
return false
}
case let .fileHeader(lhsTheme, lhsText):
if case let .fileHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .fileSent(lhsTheme, lhsText, lhsValue):
if case let .fileSent(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
return true
} else {
return false
}
case let .fileReceived(lhsTheme, lhsText, lhsValue):
if case let .fileReceived(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
return true
} else {
return false
}
case let .callHeader(lhsTheme, lhsText):
if case let .callHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .callSent(lhsTheme, lhsText, lhsValue):
if case let .callSent(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
return true
} else {
return false
}
case let .callReceived(lhsTheme, lhsText, lhsValue):
if case let .callReceived(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
return true
} else {
return false
}
case let .reset(lhsTheme, lhsSection, lhsText):
if case let .reset(rhsTheme, rhsSection, rhsText) = rhs, lhsTheme === rhsTheme, lhsSection == rhsSection, lhsText == rhsText {
return true
} else {
return false
}
case let .resetTimestamp(lhsTheme, lhsText):
if case let .resetTimestamp(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
}
}
static func <(lhs: NetworkUsageStatsEntry, rhs: NetworkUsageStatsEntry) -> Bool {
return lhs.stableId < rhs.stableId
}
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
let arguments = arguments as! NetworkUsageStatsControllerArguments
switch self {
case let .messagesHeader(_, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .messagesSent(_, text, value):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
case let .messagesReceived(_, text, value):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
case let .imageHeader(_, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .imageSent(_, text, value):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
case let .imageReceived(_, text, value):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
case let .videoHeader(_, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .videoSent(_, text, value):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
case let .videoReceived(_, text, value):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
case let .audioHeader(_, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .audioSent(_, text, value):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
case let .audioReceived(_, text, value):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
case let .fileHeader(_, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .fileSent(_, text, value):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
case let .fileReceived(_, text, value):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
case let .callHeader(_, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .callSent(_, text, value):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
case let .callReceived(_, text, value):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
case let .reset(_, section, text):
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
arguments.resetStatistics(section)
})
case let .resetTimestamp(_, text):
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
}
}
}
private func networkUsageStatsControllerEntries(presentationData: PresentationData, section: NetworkUsageControllerSection, stats: NetworkUsageStats) -> [NetworkUsageStatsEntry] {
var entries: [NetworkUsageStatsEntry] = []
let formatting = DataSizeStringFormatting(presentationData: presentationData)
switch section {
case .cellular:
entries.append(.messagesHeader(presentationData.theme, presentationData.strings.NetworkUsageSettings_GeneralDataSection))
entries.append(.messagesSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.generic.cellular.outgoing, formatting: formatting)))
entries.append(.messagesReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.generic.cellular.incoming, formatting: formatting)))
entries.append(.imageHeader(presentationData.theme, presentationData.strings.NetworkUsageSettings_MediaImageDataSection))
entries.append(.imageSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.image.cellular.outgoing, formatting: formatting)))
entries.append(.imageReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.image.cellular.incoming, formatting: formatting)))
entries.append(.videoHeader(presentationData.theme, presentationData.strings.NetworkUsageSettings_MediaVideoDataSection))
entries.append(.videoSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.video.cellular.outgoing, formatting: formatting)))
entries.append(.videoReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.video.cellular.incoming, formatting: formatting)))
entries.append(.audioHeader(presentationData.theme, presentationData.strings.NetworkUsageSettings_MediaAudioDataSection))
entries.append(.audioSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.audio.cellular.outgoing, formatting: formatting)))
entries.append(.audioReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.audio.cellular.incoming, formatting: formatting)))
entries.append(.fileHeader(presentationData.theme, presentationData.strings.NetworkUsageSettings_MediaDocumentDataSection))
entries.append(.fileSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.file.cellular.outgoing, formatting: formatting)))
entries.append(.fileReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.file.cellular.incoming, formatting: formatting)))
entries.append(.callHeader(presentationData.theme, presentationData.strings.NetworkUsageSettings_CallDataSection))
entries.append(.callSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.call.cellular.outgoing, formatting: formatting)))
entries.append(.callReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.call.cellular.incoming, formatting: formatting)))
entries.append(.reset(presentationData.theme, section, presentationData.strings.NetworkUsageSettings_ResetStats))
if stats.resetCellularTimestamp != 0 {
let formatter = DateFormatter()
formatter.dateFormat = "E, d MMM yyyy HH:mm"
let dateStringPlain = formatter.string(from: Date(timeIntervalSince1970: Double(stats.resetCellularTimestamp)))
entries.append(.resetTimestamp(presentationData.theme, presentationData.strings.NetworkUsageSettings_CellularUsageSince(dateStringPlain).string))
}
case .wifi:
entries.append(.messagesHeader(presentationData.theme, presentationData.strings.NetworkUsageSettings_GeneralDataSection))
entries.append(.messagesSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.generic.wifi.outgoing, formatting: formatting)))
entries.append(.messagesReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.generic.wifi.incoming, formatting: formatting)))
entries.append(.imageHeader(presentationData.theme, presentationData.strings.NetworkUsageSettings_MediaImageDataSection))
entries.append(.imageSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.image.wifi.outgoing, formatting: formatting)))
entries.append(.imageReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.image.wifi.incoming, formatting: formatting)))
entries.append(.videoHeader(presentationData.theme, presentationData.strings.NetworkUsageSettings_MediaVideoDataSection))
entries.append(.videoSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.video.wifi.outgoing, formatting: formatting)))
entries.append(.videoReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.video.wifi.incoming, formatting: formatting)))
entries.append(.audioHeader(presentationData.theme, presentationData.strings.NetworkUsageSettings_MediaAudioDataSection))
entries.append(.audioSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.audio.wifi.outgoing, formatting: formatting)))
entries.append(.audioReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.audio.wifi.incoming, formatting: formatting)))
entries.append(.fileHeader(presentationData.theme, presentationData.strings.NetworkUsageSettings_MediaDocumentDataSection))
entries.append(.fileSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.file.wifi.outgoing, formatting: formatting)))
entries.append(.fileReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.file.wifi.incoming, formatting: formatting)))
entries.append(.callHeader(presentationData.theme, presentationData.strings.NetworkUsageSettings_CallDataSection))
entries.append(.callSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.call.wifi.outgoing, formatting: formatting)))
entries.append(.callReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.call.wifi.incoming, formatting: formatting)))
entries.append(.reset(presentationData.theme, section, presentationData.strings.NetworkUsageSettings_ResetStats))
if stats.resetWifiTimestamp != 0 {
let formatter = DateFormatter()
formatter.dateFormat = "E, d MMM yyyy HH:mm"
let dateStringPlain = formatter.string(from: Date(timeIntervalSince1970: Double(stats.resetWifiTimestamp)))
entries.append(.resetTimestamp(presentationData.theme, presentationData.strings.NetworkUsageSettings_WifiUsageSince(dateStringPlain).string))
}
}
return entries
}
func networkUsageStatsController(context: AccountContext) -> ViewController {
let section = ValuePromise<NetworkUsageControllerSection>(.cellular)
let stats = Promise<NetworkUsageStats>()
stats.set(accountNetworkUsageStats(account: context.account, reset: []))
var presentControllerImpl: ((ViewController) -> Void)?
let arguments = NetworkUsageStatsControllerArguments(resetStatistics: { [weak stats] section in
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let controller = ActionSheetController(presentationData: presentationData)
let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated()
}
controller.setItemGroups([
ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: presentationData.strings.NetworkUsageSettings_ResetStats, color: .destructive, action: {
dismissAction()
let reset: ResetNetworkUsageStats
switch section {
case .wifi:
reset = .wifi
case .cellular:
reset = .cellular
}
stats?.set(accountNetworkUsageStats(account: context.account, reset: reset))
}),
]),
ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })])
])
presentControllerImpl?(controller)
})
let signal = combineLatest(context.sharedContext.presentationData, section.get(), stats.get()) |> deliverOnMainQueue
|> map { presentationData, section, stats -> (ItemListControllerState, (ItemListNodeState, Any)) in
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .sectionControl([presentationData.strings.NetworkUsageSettings_Cellular, presentationData.strings.NetworkUsageSettings_Wifi], 0), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: networkUsageStatsControllerEntries(presentationData: presentationData, section: section, stats: stats), style: .blocks, emptyStateItem: nil, animateChanges: false)
return (controllerState, (listState, arguments))
}
let controller = ItemListController(context: context, state: signal)
controller.titleControlValueChanged = { [weak section] index in
section?.set(index == 0 ? .cellular : .wifi)
}
presentControllerImpl = { [weak controller] c in
controller?.present(c, in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}
return controller
}

View File

@ -16,6 +16,7 @@ import UrlHandling
import AccountUtils
import PremiumUI
import PasswordSetupUI
import StorageUsageScreen
private struct DeleteAccountOptionsArguments {
let changePhoneNumber: () -> Void
@ -276,7 +277,9 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo
}, clearCache: {
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_clear_cache_tap")
pushControllerImpl?(storageUsageController(context: context))
pushControllerImpl?(StorageUsageScreen(context: context, makeStorageUsageExceptionsScreen: { category in
return storageUsageExceptionsScreen(context: context, category: category)
}))
dismissImpl?()
}, clearSyncedContacts: {
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_clear_contacts_tap")

View File

@ -15,6 +15,7 @@ import PresentationDataUtils
import UrlHandling
import AccountUtils
import PremiumUI
import StorageUsageScreen
private struct LogoutOptionsItemArguments {
let addAccount: () -> Void
@ -181,7 +182,9 @@ public func logoutOptionsController(context: AccountContext, navigationControlle
})
dismissImpl?()
}, clearCache: {
pushControllerImpl?(storageUsageController(context: context))
pushControllerImpl?(StorageUsageScreen(context: context, makeStorageUsageExceptionsScreen: { category in
return storageUsageExceptionsScreen(context: context, category: category)
}))
dismissImpl?()
}, changePhoneNumber: {
let introController = PrivacyIntroController(context: context, mode: .changePhoneNumber(phoneNumber), proceedAction: {

View File

@ -20,6 +20,7 @@ import InstantPageCache
import NotificationPeerExceptionController
import QrCodeUI
import PremiumUI
import StorageUsageScreen
enum SettingsSearchableItemIcon {
case profile
@ -681,16 +682,54 @@ private func dataSearchableItems(context: AccountContext) -> [SettingsSearchable
presentDataSettings(context, present, nil)
}),
SettingsSearchableItem(id: .data(1), title: strings.ChatSettings_Cache, alternate: synonyms(strings.SettingsSearch_Synonyms_Data_Storage_Title), icon: icon, breadcrumbs: [strings.Settings_ChatSettings], present: { context, _, present in
present(.push, storageUsageController(context: context))
let controller = StorageUsageScreen(context: context, makeStorageUsageExceptionsScreen: { category in
return storageUsageExceptionsScreen(context: context, category: category)
})
present(.push, controller)
}),
SettingsSearchableItem(id: .data(2), title: strings.Cache_KeepMedia, alternate: synonyms(strings.SettingsSearch_Synonyms_Data_Storage_KeepMedia), icon: icon, breadcrumbs: [strings.Settings_ChatSettings, strings.ChatSettings_Cache], present: { context, _, present in
present(.push, storageUsageController(context: context))
let controller = StorageUsageScreen(context: context, makeStorageUsageExceptionsScreen: { category in
return storageUsageExceptionsScreen(context: context, category: category)
})
present(.push, controller)
}),
SettingsSearchableItem(id: .data(3), title: strings.Cache_ClearCache, alternate: synonyms(strings.SettingsSearch_Synonyms_Data_Storage_ClearCache), icon: icon, breadcrumbs: [strings.Settings_ChatSettings, strings.ChatSettings_Cache], present: { context, _, present in
present(.push, storageUsageController(context: context))
let controller = StorageUsageScreen(context: context, makeStorageUsageExceptionsScreen: { category in
return storageUsageExceptionsScreen(context: context, category: category)
})
present(.push, controller)
}),
SettingsSearchableItem(id: .data(4), title: strings.NetworkUsageSettings_Title, alternate: synonyms(strings.SettingsSearch_Synonyms_Data_NetworkUsage), icon: icon, breadcrumbs: [strings.Settings_ChatSettings], present: { context, _, present in
present(.push, networkUsageStatsController(context: context))
let mediaAutoDownloadSettings = context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.automaticMediaDownloadSettings])
|> map { sharedData -> MediaAutoDownloadSettings in
var automaticMediaDownloadSettings: MediaAutoDownloadSettings
if let value = sharedData.entries[ApplicationSpecificSharedDataKeys.automaticMediaDownloadSettings]?.get(MediaAutoDownloadSettings.self) {
automaticMediaDownloadSettings = value
} else {
automaticMediaDownloadSettings = .defaultSettings
}
return automaticMediaDownloadSettings
}
let _ = (combineLatest(
accountNetworkUsageStats(account: context.account, reset: []),
mediaAutoDownloadSettings
)
|> take(1)
|> deliverOnMainQueue).start(next: { stats, mediaAutoDownloadSettings in
var stats = stats
if stats.resetWifiTimestamp == 0 {
var value = stat()
if stat(context.account.basePath, &value) == 0 {
stats.resetWifiTimestamp = Int32(value.st_ctimespec.tv_sec)
}
}
present(.push, DataUsageScreen(context: context, stats: stats, mediaAutoDownloadSettings: mediaAutoDownloadSettings, makeAutodownloadSettingsController: { isCellular in
return autodownloadMediaConnectionTypeController(context: context, connectionType: isCellular ? .cellular : .wifi)
}))
})
}),
SettingsSearchableItem(id: .data(5), title: strings.ChatSettings_AutoDownloadUsingCellular, alternate: synonyms(strings.SettingsSearch_Synonyms_Data_AutoDownloadUsingCellular), icon: icon, breadcrumbs: [strings.Settings_ChatSettings, strings.ChatSettings_AutoDownloadTitle], present: { context, _, present in
present(.push, autodownloadMediaConnectionTypeController(context: context, connectionType: .cellular))

View File

@ -89,6 +89,7 @@ import ChatListHeaderComponent
import ChatControllerInteraction
import FeaturedStickersScreen
import ChatEntityKeyboardInputNode
import StorageUsageScreen
#if DEBUG
import os.signpost
@ -11704,6 +11705,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self?.beginClearHistory(type: type)
}
let context = self.context
let _ = (self.context.engine.data.get(
TelegramEngine.EngineData.Item.Peer.ParticipantCount(id: peerId),
TelegramEngine.EngineData.Item.Peer.CanDeleteHistory(id: peerId)
@ -11890,9 +11892,19 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
default:
text = strongSelf.presentationData.strings.ChatList_DeleteForCurrentUser
}
items.append(ActionSheetButtonItem(title: text, color: .destructive, action: { [weak actionSheet] in
items.append(ActionSheetButtonItem(title: text, color: .destructive, action: { [weak self, weak actionSheet] in
actionSheet?.dismissAnimated()
if mainPeer.id == context.account.peerId, let strongSelf = self {
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: strongSelf.presentationData.strings.ChatList_DeleteSavedMessagesConfirmationTitle, text: strongSelf.presentationData.strings.ChatList_DeleteSavedMessagesConfirmationText, actions: [
TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {
}),
TextAlertAction(type: .destructiveAction, title: strongSelf.presentationData.strings.ChatList_DeleteSavedMessagesConfirmationAction, action: {
beginClear(.forLocalPeer)
})
], parseMarkdown: true), in: .window(.root))
} else {
beginClear(.forLocalPeer)
}
}))
}
}
@ -12160,7 +12172,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState({ $0.withoutSelectionState() }) })
if let strongSelf = self {
let controller = storageUsageController(context: strongSelf.context, isModal: true)
let context = strongSelf.context
let controller = StorageUsageScreen(context: context, makeStorageUsageExceptionsScreen: { category in
return storageUsageExceptionsScreen(context: context, category: category)
})
strongSelf.present(controller, in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}
}))
@ -16974,7 +16989,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
actionSheet?.dismissAnimated()
if let strongSelf = self, !presented {
presented = true
strongSelf.push(storageUsageController(context: strongSelf.context, isModal: true))
let context = strongSelf.context
strongSelf.push(StorageUsageScreen(context: context, makeStorageUsageExceptionsScreen: { category in
return storageUsageExceptionsScreen(context: context, category: category)
}))
}
}))

View File

@ -2461,8 +2461,10 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
if textView.inputView !== updatedInputView {
textView.inputView = updatedInputView
if textView.isFirstResponder {
if self.chatPresentationInterfaceStateRequiresInputFocus(chatPresentationInterfaceState) {
if let validLayout = self.validLayout, let inputHeight = validLayout.0.inputHeight, inputHeight > 100.0 {
if self.chatPresentationInterfaceStateRequiresInputFocus(chatPresentationInterfaceState), let validLayout = self.validLayout {
if case .compact = validLayout.0.metrics.widthClass {
waitForKeyboardLayout = true
} else if let inputHeight = validLayout.0.inputHeight, inputHeight > 100.0 {
waitForKeyboardLayout = true
}
}

View File

@ -5,6 +5,7 @@ import AccountContext
import AlertUI
import PresentationDataUtils
import SettingsUI
import StorageUsageScreen
private func totalDiskSpace() -> Int64 {
do {
@ -31,7 +32,9 @@ func checkAvailableDiskSpace(context: AccountContext, threshold: Int64 = 100 * 1
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let controller = textAlertController(context: context, title: nil, text: presentationData.strings.Cache_LowDiskSpaceText, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.AccessDenied_Settings, action: {
push(storageUsageController(context: context, isModal: true))
push(StorageUsageScreen(context: context, makeStorageUsageExceptionsScreen: { category in
return storageUsageExceptionsScreen(context: context, category: category)
}))
}), TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})])
push(controller)

View File

@ -199,7 +199,7 @@ class ContactMultiselectionControllerImpl: ViewController, ContactMultiselection
let rightNavigationButton = UIBarButtonItem(title: self.presentationData.strings.Common_Next, style: .done, target: self, action: #selector(self.rightNavigationButtonPressed))
self.rightNavigationButton = rightNavigationButton
self.navigationItem.rightBarButtonItem = self.rightNavigationButton
rightNavigationButton.isEnabled = count != 0 || self.params.alwaysEnabled
rightNavigationButton.isEnabled = true //count != 0 || self.params.alwaysEnabled
case .channelCreation:
self.titleView.title = CounterContollerTitle(title: self.presentationData.strings.GroupInfo_AddParticipantTitle, counter: "")
let rightNavigationButton = UIBarButtonItem(title: self.presentationData.strings.Common_Next, style: .done, target: self, action: #selector(self.rightNavigationButtonPressed))

View File

@ -907,7 +907,7 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur
let _ = (settings
|> deliverOnMainQueue).start(next: { settings in
if settings.defaultWebBrowser == nil {
if isCompact {
if !"".isEmpty && isCompact {
let controller = BrowserScreen(context: context, subject: .webPage(url: parsedUrl.absoluteString))
navigationController?.pushViewController(controller)
} else {

View File

@ -4564,7 +4564,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
canSetupAutoremoveTimeout = true
}
} else if let user = chatPeer as? TelegramUser {
if user.id != strongSelf.context.account.peerId && user.botInfo == nil {
if user.id != strongSelf.context.account.peerId {
canSetupAutoremoveTimeout = true
}
} else if let channel = chatPeer as? TelegramChannel {

View File

@ -1239,8 +1239,9 @@ public final class SharedAccountContextImpl: SharedAccountContext {
guard let navigationController = self.mainWindow?.viewController as? NavigationController else {
return
}
let controller = storageUsageController(context: context, isModal: true)
let controller = StorageUsageScreen(context: context, makeStorageUsageExceptionsScreen: { category in
return storageUsageExceptionsScreen(context: context, category: category)
})
navigationController.pushViewController(controller)
}