mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various fixes
This commit is contained in:
parent
8188bc2858
commit
4c500ce3b2
@ -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?";
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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)!
|
||||
|
@ -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
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -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")
|
||||
|
@ -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: {
|
||||
|
@ -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))
|
||||
|
@ -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)
|
||||
}))
|
||||
}
|
||||
}))
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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))
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user