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"; "MediaPicker.VoiceOver.Camera" = "Camera";
"ChatList.ReadAll" = "Read All"; "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 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 { if let reorderedFilterIds = reorderedFilterIdsValue {
let _ = (self.context.engine.peers.updateChatListFiltersInteractively { stateFilters in let _ = (self.context.engine.peers.updateChatListFiltersInteractively { stateFilters in
var updatedFilters: [ChatListFilter] = [] var updatedFilters: [ChatListFilter] = []
@ -2199,18 +2211,11 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
return return
} }
strongSelf.reloadFilters(firstUpdate: { strongSelf.reloadFilters(firstUpdate: {
guard let strongSelf = self else { completion()
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))
}
}) })
}) })
} 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()) return context.engine.data.subscribe(TelegramEngine.EngineData.Item.Messages.TotalReadCounters())
|> map { readCounters -> ChatListSelectionOptions in |> map { readCounters -> ChatListSelectionOptions in
var hasUnread = false 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 hasUnread = true
} }
return ChatListSelectionOptions(read: .all(enabled: hasUnread), delete: false) return ChatListSelectionOptions(read: .all(enabled: hasUnread), delete: false)

View File

@ -129,7 +129,7 @@ private final class DeleteChatPeerActionSheetItemNode: ActionSheetItemNode {
} }
case let .clearHistory(canClearCache): case let .clearHistory(canClearCache):
if peer.id == context.account.peerId { 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 { } else if case .user = peer {
text = strings.ChatList_ClearChatConfirmation(peer.displayTitle(strings: strings, displayOrder: nameOrder)) text = strings.ChatList_ClearChatConfirmation(peer.displayTitle(strings: strings, displayOrder: nameOrder))
} else { } 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 { if glyphCount == 2, let font = attributes["NSFont"] as? UIFont, font.fontName.contains("ColorEmoji"), let string = layout.attributedString {
let range = CTRunGetStringRange(run) 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 substring = string.attributedSubstring(from: NSMakeRange(range.location, range.length)).string
let heart = Unicode.Scalar(0x2764)! 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 AccountUtils
import PremiumUI import PremiumUI
import PasswordSetupUI import PasswordSetupUI
import StorageUsageScreen
private struct DeleteAccountOptionsArguments { private struct DeleteAccountOptionsArguments {
let changePhoneNumber: () -> Void let changePhoneNumber: () -> Void
@ -276,7 +277,9 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo
}, clearCache: { }, clearCache: {
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_clear_cache_tap") 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?() dismissImpl?()
}, clearSyncedContacts: { }, clearSyncedContacts: {
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_clear_contacts_tap") addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_clear_contacts_tap")

View File

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

View File

@ -20,6 +20,7 @@ import InstantPageCache
import NotificationPeerExceptionController import NotificationPeerExceptionController
import QrCodeUI import QrCodeUI
import PremiumUI import PremiumUI
import StorageUsageScreen
enum SettingsSearchableItemIcon { enum SettingsSearchableItemIcon {
case profile case profile
@ -681,16 +682,54 @@ private func dataSearchableItems(context: AccountContext) -> [SettingsSearchable
presentDataSettings(context, present, nil) 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 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 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 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 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 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)) present(.push, autodownloadMediaConnectionTypeController(context: context, connectionType: .cellular))

View File

@ -89,6 +89,7 @@ import ChatListHeaderComponent
import ChatControllerInteraction import ChatControllerInteraction
import FeaturedStickersScreen import FeaturedStickersScreen
import ChatEntityKeyboardInputNode import ChatEntityKeyboardInputNode
import StorageUsageScreen
#if DEBUG #if DEBUG
import os.signpost import os.signpost
@ -11704,6 +11705,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self?.beginClearHistory(type: type) self?.beginClearHistory(type: type)
} }
let context = self.context
let _ = (self.context.engine.data.get( let _ = (self.context.engine.data.get(
TelegramEngine.EngineData.Item.Peer.ParticipantCount(id: peerId), TelegramEngine.EngineData.Item.Peer.ParticipantCount(id: peerId),
TelegramEngine.EngineData.Item.Peer.CanDeleteHistory(id: peerId) TelegramEngine.EngineData.Item.Peer.CanDeleteHistory(id: peerId)
@ -11890,9 +11892,19 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
default: default:
text = strongSelf.presentationData.strings.ChatList_DeleteForCurrentUser 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() 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) 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() }) }) strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState({ $0.withoutSelectionState() }) })
if let strongSelf = self { 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)) strongSelf.present(controller, in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
} }
})) }))
@ -16974,7 +16989,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
actionSheet?.dismissAnimated() actionSheet?.dismissAnimated()
if let strongSelf = self, !presented { if let strongSelf = self, !presented {
presented = true 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 { if textView.inputView !== updatedInputView {
textView.inputView = updatedInputView textView.inputView = updatedInputView
if textView.isFirstResponder { if textView.isFirstResponder {
if self.chatPresentationInterfaceStateRequiresInputFocus(chatPresentationInterfaceState) { if self.chatPresentationInterfaceStateRequiresInputFocus(chatPresentationInterfaceState), let validLayout = self.validLayout {
if let validLayout = self.validLayout, let inputHeight = validLayout.0.inputHeight, inputHeight > 100.0 { if case .compact = validLayout.0.metrics.widthClass {
waitForKeyboardLayout = true
} else if let inputHeight = validLayout.0.inputHeight, inputHeight > 100.0 {
waitForKeyboardLayout = true waitForKeyboardLayout = true
} }
} }

View File

@ -5,6 +5,7 @@ import AccountContext
import AlertUI import AlertUI
import PresentationDataUtils import PresentationDataUtils
import SettingsUI import SettingsUI
import StorageUsageScreen
private func totalDiskSpace() -> Int64 { private func totalDiskSpace() -> Int64 {
do { do {
@ -31,7 +32,9 @@ func checkAvailableDiskSpace(context: AccountContext, threshold: Int64 = 100 * 1
let presentationData = context.sharedContext.currentPresentationData.with { $0 } 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: { 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: {})]) }), TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})])
push(controller) 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)) let rightNavigationButton = UIBarButtonItem(title: self.presentationData.strings.Common_Next, style: .done, target: self, action: #selector(self.rightNavigationButtonPressed))
self.rightNavigationButton = rightNavigationButton self.rightNavigationButton = rightNavigationButton
self.navigationItem.rightBarButtonItem = self.rightNavigationButton self.navigationItem.rightBarButtonItem = self.rightNavigationButton
rightNavigationButton.isEnabled = count != 0 || self.params.alwaysEnabled rightNavigationButton.isEnabled = true //count != 0 || self.params.alwaysEnabled
case .channelCreation: case .channelCreation:
self.titleView.title = CounterContollerTitle(title: self.presentationData.strings.GroupInfo_AddParticipantTitle, counter: "") 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)) 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 let _ = (settings
|> deliverOnMainQueue).start(next: { settings in |> deliverOnMainQueue).start(next: { settings in
if settings.defaultWebBrowser == nil { if settings.defaultWebBrowser == nil {
if isCompact { if !"".isEmpty && isCompact {
let controller = BrowserScreen(context: context, subject: .webPage(url: parsedUrl.absoluteString)) let controller = BrowserScreen(context: context, subject: .webPage(url: parsedUrl.absoluteString))
navigationController?.pushViewController(controller) navigationController?.pushViewController(controller)
} else { } else {

View File

@ -4564,7 +4564,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
canSetupAutoremoveTimeout = true canSetupAutoremoveTimeout = true
} }
} else if let user = chatPeer as? TelegramUser { } 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 canSetupAutoremoveTimeout = true
} }
} else if let channel = chatPeer as? TelegramChannel { } 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 { guard let navigationController = self.mainWindow?.viewController as? NavigationController else {
return return
} }
let controller = StorageUsageScreen(context: context, makeStorageUsageExceptionsScreen: { category in
let controller = storageUsageController(context: context, isModal: true) return storageUsageExceptionsScreen(context: context, category: category)
})
navigationController.pushViewController(controller) navigationController.pushViewController(controller)
} }