From a1bcc9eafd78751df3e01143ecdebf49b615a087 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sat, 9 Mar 2019 22:14:27 +0300 Subject: [PATCH] Use in-app language locale for date/time formatting and use locale's decimal separator for data size formatting --- ...AutodownloadConnectionTypeController.swift | 10 ++-- .../AutodownloadMediaCategoryController.swift | 22 ++++----- TelegramUI/AutodownloadSizeLimitItem.swift | 10 ++-- .../ChatMessageAttachedContentNode.swift | 10 ++-- .../ChatMessageInteractiveFileNode.swift | 14 +++--- .../ChatMessageInteractiveMediaNode.swift | 28 +++++------ .../ChatMessageMediaBubbleContentNode.swift | 2 +- .../ChatMessageWebpageBubbleContentNode.swift | 2 +- .../ChatVideoGalleryItemScrubberView.swift | 8 ++-- .../DataAndStorageSettingsController.swift | 14 +++--- TelegramUI/ListMessageFileItemNode.swift | 6 +-- TelegramUI/NetworkUsageStatsController.swift | 48 +++++++++---------- TelegramUI/PresentationData.swift | 15 +++--- TelegramUI/SettingsController.swift | 2 +- TelegramUI/StorageUsageController.swift | 20 ++++---- TelegramUI/UniversalVideoGalleryItem.swift | 8 ++-- 16 files changed, 112 insertions(+), 107 deletions(-) diff --git a/TelegramUI/AutodownloadConnectionTypeController.swift b/TelegramUI/AutodownloadConnectionTypeController.swift index b53ea8f77f..af5f018955 100644 --- a/TelegramUI/AutodownloadConnectionTypeController.swift +++ b/TelegramUI/AutodownloadConnectionTypeController.swift @@ -183,13 +183,13 @@ private struct AutomaticDownloadPeers { } } -private func stringForAutomaticDownloadPeers(strings: PresentationStrings, peers: AutomaticDownloadPeers, category: AutomaticDownloadCategory) -> String { +private func stringForAutomaticDownloadPeers(strings: PresentationStrings, decimalSeparator: String, peers: AutomaticDownloadPeers, category: AutomaticDownloadCategory) -> String { var size: String? if var peersSize = peers.size, category == .video || category == .file { if peersSize == Int32.max { peersSize = 1536 * 1024 * 1024 } - size = autodownloadDataSizeString(Int64(peersSize)) + size = autodownloadDataSizeString(Int64(peersSize), decimalSeparator: decimalSeparator) } if peers.contacts && peers.otherPrivate && peers.groups && peers.channels { @@ -261,9 +261,9 @@ private func autodownloadMediaConnectionTypeControllerEntries(presentationData: entries.append(.dataUsageItem(presentationData.theme, presentationData.strings, AutomaticDownloadDataUsage(preset: connection.preset), customPosition, master)) entries.append(.typesHeader(presentationData.theme, presentationData.strings.AutoDownloadSettings_MediaTypes)) - entries.append(.photos(presentationData.theme, presentationData.strings.AutoDownloadSettings_Photos, stringForAutomaticDownloadPeers(strings: presentationData.strings, peers: photo, category: .photo), master)) - entries.append(.videos(presentationData.theme, presentationData.strings.AutoDownloadSettings_Videos, stringForAutomaticDownloadPeers(strings: presentationData.strings, peers: video, category: .video), master)) - entries.append(.files(presentationData.theme, presentationData.strings.AutoDownloadSettings_Files, stringForAutomaticDownloadPeers(strings: presentationData.strings, peers: file, category: .file), master)) + entries.append(.photos(presentationData.theme, presentationData.strings.AutoDownloadSettings_Photos, stringForAutomaticDownloadPeers(strings: presentationData.strings, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator, peers: photo, category: .photo), master)) + entries.append(.videos(presentationData.theme, presentationData.strings.AutoDownloadSettings_Videos, stringForAutomaticDownloadPeers(strings: presentationData.strings, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator, peers: video, category: .video), master)) + entries.append(.files(presentationData.theme, presentationData.strings.AutoDownloadSettings_Files, stringForAutomaticDownloadPeers(strings: presentationData.strings, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator, peers: file, category: .file), master)) entries.append(.voiceMessagesInfo(presentationData.theme, presentationData.strings.AutoDownloadSettings_VoiceMessagesInfo)) return entries diff --git a/TelegramUI/AutodownloadMediaCategoryController.swift b/TelegramUI/AutodownloadMediaCategoryController.swift index e242caf2aa..7bb3f82e05 100644 --- a/TelegramUI/AutodownloadMediaCategoryController.swift +++ b/TelegramUI/AutodownloadMediaCategoryController.swift @@ -4,18 +4,18 @@ import SwiftSignalKit import Postbox import TelegramCore -public func autodownloadDataSizeString(_ size: Int64) -> String { +public func autodownloadDataSizeString(_ size: Int64, decimalSeparator: String = ".") -> String { if size >= 1024 * 1024 * 1024 { let remainder = (size % (1024 * 1024 * 1024)) / (1024 * 1024 * 102) if remainder != 0 { - return "\(size / (1024 * 1024 * 1024)),\(remainder) GB" + return "\(size / (1024 * 1024 * 1024))\(decimalSeparator)\(remainder) GB" } else { return "\(size / (1024 * 1024 * 1024)) GB" } } else if size >= 1024 * 1024 { let remainder = (size % (1024 * 1024)) / (1024 * 102) if size < 10 * 1024 * 1024 { - return "\(size / (1024 * 1024)),\(remainder) MB" + return "\(size / (1024 * 1024))\(decimalSeparator)\(remainder) MB" } else { return "\(size / (1024 * 1024)) MB" } @@ -64,7 +64,7 @@ private enum AutodownloadMediaCategoryEntry: ItemListNodeEntry { case peerChannels(PresentationTheme, String, Bool) case sizeHeader(PresentationTheme, String) - case sizeItem(PresentationTheme, String, Int32) + case sizeItem(PresentationTheme, String, String, Int32) case sizePreload(PresentationTheme, String, Bool, Bool) case sizePreloadInfo(PresentationTheme, String) @@ -138,8 +138,8 @@ private enum AutodownloadMediaCategoryEntry: ItemListNodeEntry { } else { return false } - case let .sizeItem(lhsTheme, lhsText, lhsValue): - if case let .sizeItem(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { + case let .sizeItem(lhsTheme, lhsDecimalSeparator, lhsText, lhsValue): + if case let .sizeItem(rhsTheme, rhsDecimalSeparator, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsDecimalSeparator == rhsDecimalSeparator, lhsText == rhsText, lhsValue == rhsValue { return true } else { return false @@ -185,8 +185,8 @@ private enum AutodownloadMediaCategoryEntry: ItemListNodeEntry { }) case let .sizeHeader(theme, text): return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section) - case let .sizeItem(theme, text, value): - return AutodownloadSizeLimitItem(theme: theme, text: text, value: value, sectionId: self.section, updated: { value in + case let .sizeItem(theme, decimalSeparator, text, value): + return AutodownloadSizeLimitItem(theme: theme, decimalSeparator: decimalSeparator, text: text, value: value, sectionId: self.section, updated: { value in arguments.adjustSize(value) }) case let .sizePreload(theme, text, value, enabled): @@ -264,12 +264,12 @@ private func autodownloadMediaCategoryControllerEntries(presentationData: Presen let sizeText: String if size == Int32.max { - sizeText = autodownloadDataSizeString(1536 * 1024 * 1024) + sizeText = autodownloadDataSizeString(1536 * 1024 * 1024, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator) } else { - sizeText = autodownloadDataSizeString(Int64(size)) + sizeText = autodownloadDataSizeString(Int64(size), decimalSeparator: presentationData.dateTimeFormat.decimalSeparator) } let text = presentationData.strings.AutoDownloadSettings_UpTo(sizeText).0 - entries.append(.sizeItem(presentationData.theme, text, size)) + entries.append(.sizeItem(presentationData.theme, presentationData.dateTimeFormat.decimalSeparator, text, size)) if #available(iOSApplicationExtension 10.3, *), category == .video { entries.append(.sizePreload(presentationData.theme, presentationData.strings.AutoDownloadSettings_PreloadVideo, predownload, size > 2 * 1024 * 1024)) entries.append(.sizePreloadInfo(presentationData.theme, presentationData.strings.AutoDownloadSettings_PreloadVideoInfo(sizeText).0)) diff --git a/TelegramUI/AutodownloadSizeLimitItem.swift b/TelegramUI/AutodownloadSizeLimitItem.swift index cef141918e..9632b8b36c 100644 --- a/TelegramUI/AutodownloadSizeLimitItem.swift +++ b/TelegramUI/AutodownloadSizeLimitItem.swift @@ -47,13 +47,15 @@ private func sizeValue(for sliderValue: CGFloat) -> Int32 { class AutodownloadSizeLimitItem: ListViewItem, ItemListItem { let theme: PresentationTheme + let decimalSeparator: String let text: String let value: Int32 let sectionId: ItemListSectionId let updated: (Int32) -> Void - init(theme: PresentationTheme, text: String, value: Int32, sectionId: ItemListSectionId, updated: @escaping (Int32) -> Void) { + init(theme: PresentationTheme, decimalSeparator: String, text: String, value: Int32, sectionId: ItemListSectionId, updated: @escaping (Int32) -> Void) { self.theme = theme + self.decimalSeparator = decimalSeparator self.text = text self.value = value self.sectionId = sectionId @@ -192,9 +194,9 @@ class AutodownloadSizeLimitItemNode: ListViewItemNode { let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.text, font: Font.regular(17.0), textColor: item.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .center, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets())) - let (minTextLayout, minTextApply) = makeMinTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: dataSizeString(512 * 1024), font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .center, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets())) + let (minTextLayout, minTextApply) = makeMinTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: dataSizeString(512 * 1024, decimalSeparator: item.decimalSeparator), font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .center, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets())) - let (maxTextLayout, maxTextApply) = makeMaxTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: dataSizeString(1536 * 1024 * 1024), font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .center, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets())) + let (maxTextLayout, maxTextApply) = makeMaxTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: dataSizeString(1536 * 1024 * 1024, decimalSeparator: item.decimalSeparator), font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .center, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets())) contentSize = CGSize(width: params.width, height: 88.0) insets = itemListNeighborsGroupedInsets(neighbors) @@ -230,7 +232,7 @@ class AutodownloadSizeLimitItemNode: ListViewItemNode { let bottomStripeOffset: CGFloat switch neighbors.bottom { case .sameSection(false): - bottomStripeInset = 0.0 //params.leftInset + 16.0 + bottomStripeInset = 0.0 bottomStripeOffset = -separatorHeight default: bottomStripeInset = 0.0 diff --git a/TelegramUI/ChatMessageAttachedContentNode.swift b/TelegramUI/ChatMessageAttachedContentNode.swift index 5168a67a3b..eefcbdbee4 100644 --- a/TelegramUI/ChatMessageAttachedContentNode.swift +++ b/TelegramUI/ChatMessageAttachedContentNode.swift @@ -409,12 +409,12 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { } } - let (_, initialImageWidth, refineLayout) = contentImageLayout(context, presentationData.theme.theme, presentationData.strings, message, file, automaticDownload, associatedData.automaticDownloadPeerType, .constrained(CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)), layoutConstants, contentMode) + let (_, initialImageWidth, refineLayout) = contentImageLayout(context, presentationData.theme.theme, presentationData.strings, presentationData.dateTimeFormat, message, file, automaticDownload, associatedData.automaticDownloadPeerType, .constrained(CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)), layoutConstants, contentMode) initialWidth = initialImageWidth + horizontalInsets.left + horizontalInsets.right refineContentImageLayout = refineLayout } else if file.isSticker, let _ = file.dimensions { let automaticDownload = shouldDownloadMediaAutomatically(settings: automaticDownloadSettings, peerType: associatedData.automaticDownloadPeerType, networkType: associatedData.automaticDownloadNetworkType, authorPeerId: message.author?.id, contactsPeerIds: associatedData.contactsPeerIds, media: file) - let (_, initialImageWidth, refineLayout) = contentImageLayout(context, presentationData.theme.theme, presentationData.strings, message, file, automaticDownload ? .full : .none, associatedData.automaticDownloadPeerType, .constrained(CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)), layoutConstants, contentMode) + let (_, initialImageWidth, refineLayout) = contentImageLayout(context, presentationData.theme.theme, presentationData.strings, presentationData.dateTimeFormat, message, file, automaticDownload ? .full : .none, associatedData.automaticDownloadPeerType, .constrained(CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)), layoutConstants, contentMode) initialWidth = initialImageWidth + horizontalInsets.left + horizontalInsets.right refineContentImageLayout = refineLayout } else { @@ -439,7 +439,7 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { } else if let image = media as? TelegramMediaImage { if !flags.contains(.preferMediaInline) { let automaticDownload = shouldDownloadMediaAutomatically(settings: automaticDownloadSettings, peerType: associatedData.automaticDownloadPeerType, networkType: associatedData.automaticDownloadNetworkType, authorPeerId: message.author?.id, contactsPeerIds: associatedData.contactsPeerIds, media: image) - let (_, initialImageWidth, refineLayout) = contentImageLayout(context, presentationData.theme.theme, presentationData.strings, message, image, automaticDownload ? .full : .none, associatedData.automaticDownloadPeerType, .constrained(CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)), layoutConstants, contentMode) + let (_, initialImageWidth, refineLayout) = contentImageLayout(context, presentationData.theme.theme, presentationData.strings, presentationData.dateTimeFormat, message, image, automaticDownload ? .full : .none, associatedData.automaticDownloadPeerType, .constrained(CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)), layoutConstants, contentMode) initialWidth = initialImageWidth + horizontalInsets.left + horizontalInsets.right refineContentImageLayout = refineLayout } else if let dimensions = largestImageRepresentation(image.representations)?.dimensions { @@ -451,11 +451,11 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { } } else if let image = media as? TelegramMediaWebFile { let automaticDownload = shouldDownloadMediaAutomatically(settings: automaticDownloadSettings, peerType: associatedData.automaticDownloadPeerType, networkType: associatedData.automaticDownloadNetworkType, authorPeerId: message.author?.id, contactsPeerIds: associatedData.contactsPeerIds, media: image) - let (_, initialImageWidth, refineLayout) = contentImageLayout(context, presentationData.theme.theme, presentationData.strings, message, image, automaticDownload ? .full : .none, associatedData.automaticDownloadPeerType, .constrained(CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)), layoutConstants, contentMode) + let (_, initialImageWidth, refineLayout) = contentImageLayout(context, presentationData.theme.theme, presentationData.strings, presentationData.dateTimeFormat, message, image, automaticDownload ? .full : .none, associatedData.automaticDownloadPeerType, .constrained(CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)), layoutConstants, contentMode) initialWidth = initialImageWidth + horizontalInsets.left + horizontalInsets.right refineContentImageLayout = refineLayout } else if let wallpaper = media as? WallpaperPreviewMedia { - let (_, initialImageWidth, refineLayout) = contentImageLayout(context, presentationData.theme.theme, presentationData.strings, message, wallpaper, .full, associatedData.automaticDownloadPeerType, .constrained(CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)), layoutConstants, contentMode) + let (_, initialImageWidth, refineLayout) = contentImageLayout(context, presentationData.theme.theme, presentationData.strings, presentationData.dateTimeFormat, message, wallpaper, .full, associatedData.automaticDownloadPeerType, .constrained(CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)), layoutConstants, contentMode) initialWidth = initialImageWidth + horizontalInsets.left + horizontalInsets.right refineContentImageLayout = refineLayout } diff --git a/TelegramUI/ChatMessageInteractiveFileNode.swift b/TelegramUI/ChatMessageInteractiveFileNode.swift index 97babb1fda..2f9653ff59 100644 --- a/TelegramUI/ChatMessageInteractiveFileNode.swift +++ b/TelegramUI/ChatMessageInteractiveFileNode.swift @@ -58,7 +58,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { private var context: AccountContext? private var message: Message? - private var themeAndStrings: (ChatPresentationThemeData, PresentationStrings)? + private var themeAndStrings: (ChatPresentationThemeData, PresentationStrings, String)? private var file: TelegramMediaFile? private var progressFrame: CGRect? private var streamingCacheStatusFrame: CGRect? @@ -317,7 +317,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { if let performer = performer { descriptionText = performer } else if let size = file.size { - descriptionText = dataSizeString(size) + descriptionText = dataSizeString(size, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator) } else { descriptionText = "" } @@ -341,7 +341,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { } else if !isVoice { let descriptionText: String if let size = file.size { - descriptionText = dataSizeString(size) + descriptionText = dataSizeString(size, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator) } else { descriptionText = "" } @@ -485,7 +485,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { return (fittedLayoutSize, { [weak self] in if let strongSelf = self { strongSelf.context = context - strongSelf.themeAndStrings = (presentationData.theme, presentationData.strings) + strongSelf.themeAndStrings = (presentationData.theme, presentationData.strings, presentationData.dateTimeFormat.decimalSeparator) strongSelf.message = message strongSelf.file = file @@ -643,7 +643,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { guard let context = self.context else { return } - guard let presentationData = self.themeAndStrings?.0 else { + guard let (presentationData, _, decimalSeparator) = self.themeAndStrings else { return } guard let progressFrame = self.progressFrame, let streamingCacheStatusFrame = self.streamingCacheStatusFrame else { @@ -681,8 +681,8 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { switch fetchStatus { case let .Fetching(_, progress): if let size = file.size { - let compactString = dataSizeString(Int(Float(size) * progress), forceDecimal: true) - downloadingStrings = ("\(compactString) / \(dataSizeString(size, forceDecimal: true))", compactString) + let compactString = dataSizeString(Int(Float(size) * progress), forceDecimal: true, decimalSeparator: decimalSeparator) + downloadingStrings = ("\(compactString) / \(dataSizeString(size, forceDecimal: true, decimalSeparator: decimalSeparator))", compactString) } default: break diff --git a/TelegramUI/ChatMessageInteractiveMediaNode.swift b/TelegramUI/ChatMessageInteractiveMediaNode.swift index fcaccc4aa2..c9fead28f8 100644 --- a/TelegramUI/ChatMessageInteractiveMediaNode.swift +++ b/TelegramUI/ChatMessageInteractiveMediaNode.swift @@ -49,7 +49,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { private var context: AccountContext? private var message: Message? private var media: Media? - private var themeAndStrings: (PresentationTheme, PresentationStrings)? + private var themeAndStrings: (PresentationTheme, PresentationStrings, String)? private var sizeCalculation: InteractiveMediaNodeSizeCalculation? private var wideLayout: Bool? private var automaticDownload: InteractiveMediaNodeAutodownloadMode? @@ -189,7 +189,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { } } - func asyncLayout() -> (_ context: AccountContext, _ theme: PresentationTheme, _ strings: PresentationStrings, _ message: Message, _ media: Media, _ automaticDownload: InteractiveMediaNodeAutodownloadMode, _ peerType: MediaAutoDownloadPeerType, _ sizeCalculation: InteractiveMediaNodeSizeCalculation, _ layoutConstants: ChatMessageItemLayoutConstants, _ contentMode: InteractiveMediaNodeContentMode) -> (CGSize, CGFloat, (CGSize, Bool, Bool, ImageCorners) -> (CGFloat, (CGFloat) -> (CGSize, (ContainedViewLayoutTransition, Bool) -> Void))) { + func asyncLayout() -> (_ context: AccountContext, _ theme: PresentationTheme, _ strings: PresentationStrings, _ dateTimeFormat: PresentationDateTimeFormat, _ message: Message, _ media: Media, _ automaticDownload: InteractiveMediaNodeAutodownloadMode, _ peerType: MediaAutoDownloadPeerType, _ sizeCalculation: InteractiveMediaNodeSizeCalculation, _ layoutConstants: ChatMessageItemLayoutConstants, _ contentMode: InteractiveMediaNodeContentMode) -> (CGSize, CGFloat, (CGSize, Bool, Bool, ImageCorners) -> (CGFloat, (CGFloat) -> (CGSize, (ContainedViewLayoutTransition, Bool) -> Void))) { let currentMessage = self.message let currentMedia = self.media let imageLayout = self.imageNode.asyncLayout() @@ -199,7 +199,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { let currentAutomaticDownload = self.automaticDownload let currentAutomaticPlayback = self.automaticPlayback - return { [weak self] context, theme, strings, message, media, automaticDownload, peerType, sizeCalculation, layoutConstants, contentMode in + return { [weak self] context, theme, strings, dateTimeFormat, message, media, automaticDownload, peerType, sizeCalculation, layoutConstants, contentMode in var nativeSize: CGSize let isSecretMedia = message.containsSecretMedia @@ -554,7 +554,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { strongSelf.message = message strongSelf.media = media strongSelf.wideLayout = wideLayout - strongSelf.themeAndStrings = (theme, strings) + strongSelf.themeAndStrings = (theme, strings, dateTimeFormat.decimalSeparator) strongSelf.sizeCalculation = sizeCalculation strongSelf.automaticPlayback = automaticPlayback strongSelf.automaticDownload = automaticDownload @@ -755,7 +755,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { } private func updateFetchStatus() { - guard let (theme, strings) = self.themeAndStrings, let sizeCalculation = self.sizeCalculation, let message = self.message, var automaticPlayback = self.automaticPlayback, let wideLayout = self.wideLayout else { + guard let (theme, strings, decimalSeparator) = self.themeAndStrings, let sizeCalculation = self.sizeCalculation, let message = self.message, var automaticPlayback = self.automaticPlayback, let wideLayout = self.wideLayout else { return } @@ -911,7 +911,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { if let size = file.size { if let duration = file.duration, !message.flags.contains(.Unsent) { let durationString = file.isAnimated ? "GIF" : stringForDuration(playerDuration > 0 ? playerDuration : duration, position: playerPosition) - let sizeString = "\(dataSizeString(Int(Float(size) * progress), forceDecimal: true)) / \(dataSizeString(size, forceDecimal: true))" + let sizeString = "\(dataSizeString(Int(Float(size) * progress), forceDecimal: true, decimalSeparator: decimalSeparator)) / \(dataSizeString(size, forceDecimal: true, decimalSeparator: decimalSeparator))" if isMediaStreamable(message: message, media: file) { badgeContent = .mediaDownload(backgroundColor: bubbleTheme.mediaDateAndStatusFillColor, foregroundColor: bubbleTheme.mediaDateAndStatusTextColor, duration: durationString, size: active ? sizeString : nil, muted: muted, active: active) mediaDownloadState = .fetching(progress: automaticPlayback ? nil : adjustedProgress) @@ -929,14 +929,14 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { state = automaticPlayback ? .none : state } } else { - badgeContent = .mediaDownload(backgroundColor: bubbleTheme.mediaDateAndStatusFillColor, foregroundColor: bubbleTheme.mediaDateAndStatusTextColor, duration: "\(dataSizeString(Int(Float(size) * progress), forceDecimal: true)) / \(dataSizeString(size, forceDecimal: true))", size: nil, muted: false, active: false) + badgeContent = .mediaDownload(backgroundColor: bubbleTheme.mediaDateAndStatusFillColor, foregroundColor: bubbleTheme.mediaDateAndStatusTextColor, duration: "\(dataSizeString(Int(Float(size) * progress), forceDecimal: true, decimalSeparator: decimalSeparator)) / \(dataSizeString(size, forceDecimal: true, decimalSeparator: decimalSeparator))", size: nil, muted: false, active: false) } } else if let _ = file.duration { badgeContent = .mediaDownload(backgroundColor: bubbleTheme.mediaDateAndStatusFillColor, foregroundColor: bubbleTheme.mediaDateAndStatusTextColor, duration: strings.Conversation_Processing, size: nil, muted: false, active: active) } } else { if isMediaStreamable(message: message, media: file), let size = file.size { - let sizeString = "\(dataSizeString(Int(Float(size) * progress), forceDecimal: true)) / \(dataSizeString(size, forceDecimal: true))" + let sizeString = "\(dataSizeString(Int(Float(size) * progress), forceDecimal: true, decimalSeparator: decimalSeparator)) / \(dataSizeString(size, forceDecimal: true, decimalSeparator: decimalSeparator))" if message.flags.contains(.Unsent), let duration = file.duration { let durationString = stringForDuration(playerDuration > 0 ? playerDuration : duration, position: playerPosition) @@ -964,7 +964,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { let durationString = stringForDuration(playerDuration > 0 ? playerDuration : duration, position: playerPosition) if automaticPlayback, let size = file.size { - let sizeString = "\(dataSizeString(Int(Float(size) * progress), forceDecimal: true)) / \(dataSizeString(size, forceDecimal: true))" + let sizeString = "\(dataSizeString(Int(Float(size) * progress), forceDecimal: true, decimalSeparator: decimalSeparator)) / \(dataSizeString(size, forceDecimal: true, decimalSeparator: decimalSeparator))" mediaDownloadState = .fetching(progress: progress) badgeContent = .mediaDownload(backgroundColor: bubbleTheme.mediaDateAndStatusFillColor, foregroundColor: bubbleTheme.mediaDateAndStatusTextColor, duration: durationString, size: active ? sizeString : nil, muted: muted, active: active) } else { @@ -1015,7 +1015,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { if wideLayout { if isMediaStreamable(message: message, media: file) { state = automaticPlayback ? .none : .play(bubbleTheme.mediaOverlayControlForegroundColor) - badgeContent = .mediaDownload(backgroundColor: bubbleTheme.mediaDateAndStatusFillColor, foregroundColor: bubbleTheme.mediaDateAndStatusTextColor, duration: durationString, size: dataSizeString(file.size ?? 0), muted: muted, active: true) + badgeContent = .mediaDownload(backgroundColor: bubbleTheme.mediaDateAndStatusFillColor, foregroundColor: bubbleTheme.mediaDateAndStatusTextColor, duration: durationString, size: dataSizeString(file.size ?? 0, decimalSeparator: decimalSeparator), muted: muted, active: true) mediaDownloadState = .remote } else { state = automaticPlayback ? .none : state @@ -1100,12 +1100,12 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { } } - static func asyncLayout(_ node: ChatMessageInteractiveMediaNode?) -> (_ context: AccountContext, _ theme: PresentationTheme, _ strings: PresentationStrings, _ message: Message, _ media: Media, _ automaticDownload: InteractiveMediaNodeAutodownloadMode, _ peerType: MediaAutoDownloadPeerType, _ sizeCalculation: InteractiveMediaNodeSizeCalculation, _ layoutConstants: ChatMessageItemLayoutConstants, _ contentMode: InteractiveMediaNodeContentMode) -> (CGSize, CGFloat, (CGSize, Bool, Bool, ImageCorners) -> (CGFloat, (CGFloat) -> (CGSize, (ContainedViewLayoutTransition, Bool) -> ChatMessageInteractiveMediaNode))) { + static func asyncLayout(_ node: ChatMessageInteractiveMediaNode?) -> (_ context: AccountContext, _ theme: PresentationTheme, _ strings: PresentationStrings, _ dateTimeFormat: PresentationDateTimeFormat, _ message: Message, _ media: Media, _ automaticDownload: InteractiveMediaNodeAutodownloadMode, _ peerType: MediaAutoDownloadPeerType, _ sizeCalculation: InteractiveMediaNodeSizeCalculation, _ layoutConstants: ChatMessageItemLayoutConstants, _ contentMode: InteractiveMediaNodeContentMode) -> (CGSize, CGFloat, (CGSize, Bool, Bool, ImageCorners) -> (CGFloat, (CGFloat) -> (CGSize, (ContainedViewLayoutTransition, Bool) -> ChatMessageInteractiveMediaNode))) { let currentAsyncLayout = node?.asyncLayout() - return { context, theme, strings, message, media, automaticDownload, peerType, sizeCalculation, layoutConstants, contentMode in + return { context, theme, strings, dateTimeFormat, message, media, automaticDownload, peerType, sizeCalculation, layoutConstants, contentMode in var imageNode: ChatMessageInteractiveMediaNode - var imageLayout: (_ context: AccountContext, _ theme: PresentationTheme, _ strings: PresentationStrings, _ message: Message, _ media: Media, _ automaticDownload: InteractiveMediaNodeAutodownloadMode, _ peerType: MediaAutoDownloadPeerType, _ sizeCalculation: InteractiveMediaNodeSizeCalculation, _ layoutConstants: ChatMessageItemLayoutConstants, _ contentMode: InteractiveMediaNodeContentMode) -> (CGSize, CGFloat, (CGSize, Bool, Bool, ImageCorners) -> (CGFloat, (CGFloat) -> (CGSize, (ContainedViewLayoutTransition, Bool) -> Void))) + var imageLayout: (_ context: AccountContext, _ theme: PresentationTheme, _ strings: PresentationStrings, _ dateTimeFormat: PresentationDateTimeFormat, _ message: Message, _ media: Media, _ automaticDownload: InteractiveMediaNodeAutodownloadMode, _ peerType: MediaAutoDownloadPeerType, _ sizeCalculation: InteractiveMediaNodeSizeCalculation, _ layoutConstants: ChatMessageItemLayoutConstants, _ contentMode: InteractiveMediaNodeContentMode) -> (CGSize, CGFloat, (CGSize, Bool, Bool, ImageCorners) -> (CGFloat, (CGFloat) -> (CGSize, (ContainedViewLayoutTransition, Bool) -> Void))) if let node = node, let currentAsyncLayout = currentAsyncLayout { imageNode = node @@ -1115,7 +1115,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { imageLayout = imageNode.asyncLayout() } - let (unboundSize, initialWidth, continueLayout) = imageLayout(context, theme, strings, message, media, automaticDownload, peerType, sizeCalculation, layoutConstants, contentMode) + let (unboundSize, initialWidth, continueLayout) = imageLayout(context, theme, strings, dateTimeFormat, message, media, automaticDownload, peerType, sizeCalculation, layoutConstants, contentMode) return (unboundSize, initialWidth, { constrainedSize, automaticPlayback, wideLayout, corners in let (finalWidth, finalLayout) = continueLayout(constrainedSize, automaticPlayback, wideLayout, corners) diff --git a/TelegramUI/ChatMessageMediaBubbleContentNode.swift b/TelegramUI/ChatMessageMediaBubbleContentNode.swift index 242bdb341f..5e2605ee1a 100644 --- a/TelegramUI/ChatMessageMediaBubbleContentNode.swift +++ b/TelegramUI/ChatMessageMediaBubbleContentNode.swift @@ -118,7 +118,7 @@ class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode { sizeCalculation = .unconstrained } - let (unboundSize, initialWidth, refineLayout) = interactiveImageLayout(item.context, item.presentationData.theme.theme, item.presentationData.strings, item.message, selectedMedia!, automaticDownload, item.associatedData.automaticDownloadPeerType, sizeCalculation, layoutConstants, contentMode) + let (unboundSize, initialWidth, refineLayout) = interactiveImageLayout(item.context, item.presentationData.theme.theme, item.presentationData.strings, item.presentationData.dateTimeFormat, item.message, selectedMedia!, automaticDownload, item.associatedData.automaticDownloadPeerType, sizeCalculation, layoutConstants, contentMode) let forceFullCorners = false let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: true, headerSpacing: 7.0, hidesBackground: .emptyWallpaper, forceFullCorners: forceFullCorners, forceAlignment: .none) diff --git a/TelegramUI/ChatMessageWebpageBubbleContentNode.swift b/TelegramUI/ChatMessageWebpageBubbleContentNode.swift index 6b2f0056e2..33ed0c945f 100644 --- a/TelegramUI/ChatMessageWebpageBubbleContentNode.swift +++ b/TelegramUI/ChatMessageWebpageBubbleContentNode.swift @@ -268,7 +268,7 @@ final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContentNode { let media = WallpaperPreviewMedia(content: .file(file, patternColor)) mediaAndFlags = (media, [.preferMediaAspectFilled]) if let fileSize = file.size { - badge = dataSizeString(fileSize) + badge = dataSizeString(fileSize, decimalSeparator: item.presentationData.dateTimeFormat.decimalSeparator) } } else { mediaAndFlags = (file, []) diff --git a/TelegramUI/ChatVideoGalleryItemScrubberView.swift b/TelegramUI/ChatVideoGalleryItemScrubberView.swift index f188ae2fcf..264734175f 100644 --- a/TelegramUI/ChatVideoGalleryItemScrubberView.swift +++ b/TelegramUI/ChatVideoGalleryItemScrubberView.swift @@ -108,7 +108,7 @@ final class ChatVideoGalleryItemScrubberView: UIView { self.scrubberNode.bufferingStatus = status } - func setFetchStatusSignal(_ fetchStatus: Signal?, strings: PresentationStrings, fileSize: Int?) { + func setFetchStatusSignal(_ fetchStatus: Signal?, strings: PresentationStrings, decimalSeparator: String, fileSize: Int?) { if let fileSize = fileSize { if let fetchStatus = fetchStatus { self.fetchStatusDisposable.set((fetchStatus @@ -117,9 +117,9 @@ final class ChatVideoGalleryItemScrubberView: UIView { var text: String switch status { case .Remote: - text = dataSizeString(fileSize, forceDecimal: true) + text = dataSizeString(fileSize, forceDecimal: true, decimalSeparator: decimalSeparator) case let .Fetching(_, progress): - text = strings.DownloadingStatus(dataSizeString(Int64(Float(fileSize) * progress), forceDecimal: true), dataSizeString(fileSize, forceDecimal: true)).0 + text = strings.DownloadingStatus(dataSizeString(Int64(Float(fileSize) * progress), forceDecimal: true), dataSizeString(fileSize, forceDecimal: true, decimalSeparator: decimalSeparator)).0 default: text = "" } @@ -128,7 +128,7 @@ final class ChatVideoGalleryItemScrubberView: UIView { } })) } else { - self.fileSizeNode.attributedText = NSAttributedString(string: dataSizeString(fileSize, forceDecimal: true), font: textFont, textColor: .white) + self.fileSizeNode.attributedText = NSAttributedString(string: dataSizeString(fileSize, forceDecimal: true, decimalSeparator: decimalSeparator), font: textFont, textColor: .white) } } else { self.fileSizeNode.attributedText = nil diff --git a/TelegramUI/DataAndStorageSettingsController.swift b/TelegramUI/DataAndStorageSettingsController.swift index a129dd5974..0c04aa0ca7 100644 --- a/TelegramUI/DataAndStorageSettingsController.swift +++ b/TelegramUI/DataAndStorageSettingsController.swift @@ -344,16 +344,16 @@ private func stringForUseLessDataSetting(_ dataSaving: VoiceCallDataSaving, stri } } -private func stringForAutoDownloadTypes(strings: PresentationStrings, photo: Bool, videoSize: Int32?, fileSize: Int32?) -> String { +private func stringForAutoDownloadTypes(strings: PresentationStrings, decimalSeparator: String, photo: Bool, videoSize: Int32?, fileSize: Int32?) -> String { var types: [String] = [] if photo { types.append(strings.ChatSettings_AutoDownloadSettings_TypePhoto) } if let videoSize = videoSize { - types.append(strings.ChatSettings_AutoDownloadSettings_TypeVideo(autodownloadDataSizeString(Int64(videoSize))).0) + types.append(strings.ChatSettings_AutoDownloadSettings_TypeVideo(autodownloadDataSizeString(Int64(videoSize), decimalSeparator: decimalSeparator)).0) } if let fileSize = fileSize { - types.append(strings.ChatSettings_AutoDownloadSettings_TypeFile(autodownloadDataSizeString(Int64(fileSize))).0) + types.append(strings.ChatSettings_AutoDownloadSettings_TypeFile(autodownloadDataSizeString(Int64(fileSize), decimalSeparator: decimalSeparator)).0) } if types.isEmpty { @@ -370,7 +370,7 @@ private func stringForAutoDownloadTypes(strings: PresentationStrings, photo: Boo return string } -private func stringForAutoDownloadSetting(strings: PresentationStrings, settings: MediaAutoDownloadSettings, connectionType: AutomaticDownloadConnectionType) -> String { +private func stringForAutoDownloadSetting(strings: PresentationStrings, decimalSeparator: String, settings: MediaAutoDownloadSettings, connectionType: AutomaticDownloadConnectionType) -> String { let connection: MediaAutoDownloadConnection switch connectionType { case .cellular: @@ -387,7 +387,7 @@ private func stringForAutoDownloadSetting(strings: PresentationStrings, settings let video = isAutodownloadEnabledForAnyPeerType(category: categories.video) let file = isAutodownloadEnabledForAnyPeerType(category: categories.file) - return stringForAutoDownloadTypes(strings: strings, photo: photo, videoSize: video ? categories.video.sizeLimit : nil, fileSize: file ? categories.file.sizeLimit : nil) + return stringForAutoDownloadTypes(strings: strings, decimalSeparator: decimalSeparator, photo: photo, videoSize: video ? categories.video.sizeLimit : nil, fileSize: file ? categories.file.sizeLimit : nil) } } @@ -398,8 +398,8 @@ private func dataAndStorageControllerEntries(state: DataAndStorageControllerStat entries.append(.networkUsage(presentationData.theme, presentationData.strings.NetworkUsageSettings_Title)) entries.append(.automaticDownloadHeader(presentationData.theme, presentationData.strings.ChatSettings_AutoDownloadTitle)) - entries.append(.automaticDownloadCellular(presentationData.theme, presentationData.strings.ChatSettings_AutoDownloadUsingCellular, stringForAutoDownloadSetting(strings: presentationData.strings, settings: data.automaticMediaDownloadSettings, connectionType: .cellular))) - entries.append(.automaticDownloadWifi(presentationData.theme, presentationData.strings.ChatSettings_AutoDownloadUsingWiFi, stringForAutoDownloadSetting(strings: presentationData.strings, settings: data.automaticMediaDownloadSettings, connectionType: .wifi))) + entries.append(.automaticDownloadCellular(presentationData.theme, presentationData.strings.ChatSettings_AutoDownloadUsingCellular, stringForAutoDownloadSetting(strings: presentationData.strings, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator, settings: data.automaticMediaDownloadSettings, connectionType: .cellular))) + entries.append(.automaticDownloadWifi(presentationData.theme, presentationData.strings.ChatSettings_AutoDownloadUsingWiFi, stringForAutoDownloadSetting(strings: presentationData.strings, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator, settings: data.automaticMediaDownloadSettings, connectionType: .wifi))) let defaultSettings = MediaAutoDownloadSettings.defaultSettings entries.append(.automaticDownloadReset(presentationData.theme, presentationData.strings.ChatSettings_AutoDownloadReset, data.automaticMediaDownloadSettings.cellular != defaultSettings.cellular || data.automaticMediaDownloadSettings.wifi != defaultSettings.wifi)) diff --git a/TelegramUI/ListMessageFileItemNode.swift b/TelegramUI/ListMessageFileItemNode.swift index fe08a12dfc..3fa8941b24 100644 --- a/TelegramUI/ListMessageFileItemNode.swift +++ b/TelegramUI/ListMessageFileItemNode.swift @@ -345,7 +345,7 @@ final class ListMessageFileItemNode: ListMessageNode { if let performer = performer { descriptionString = performer } else if let size = file.size { - descriptionString = dataSizeString(size) + descriptionString = dataSizeString(size, decimalSeparator: item.dateTimeFormat.decimalSeparator) } else { descriptionString = "" } @@ -379,7 +379,7 @@ final class ListMessageFileItemNode: ListMessageNode { let descriptionString: String if let size = file.size { - descriptionString = "\(dataSizeString(size)) • \(dateString)" + descriptionString = "\(dataSizeString(size, decimalSeparator: item.dateTimeFormat.decimalSeparator)) • \(dateString)" } else { descriptionString = "\(dateString)" } @@ -768,7 +768,7 @@ final class ListMessageFileItemNode: ListMessageNode { switch fetchStatus { case let .Fetching(_, progress): if let file = self.currentMedia as? TelegramMediaFile, let size = file.size { - downloadingString = "\(dataSizeString(Int(Float(size) * progress), forceDecimal: true)) / \(dataSizeString(size, forceDecimal: true))" + downloadingString = "\(dataSizeString(Int(Float(size) * progress), forceDecimal: true, decimalSeparator: item.dateTimeFormat.decimalSeparator)) / \(dataSizeString(size, forceDecimal: true, decimalSeparator: item.dateTimeFormat.decimalSeparator))" } descriptionOffset = 14.0 case .Remote: diff --git a/TelegramUI/NetworkUsageStatsController.swift b/TelegramUI/NetworkUsageStatsController.swift index 785a7fece4..fea2ee3bc9 100644 --- a/TelegramUI/NetworkUsageStatsController.swift +++ b/TelegramUI/NetworkUsageStatsController.swift @@ -303,28 +303,28 @@ private func networkUsageStatsControllerEntries(presentationData: PresentationDa 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))) - entries.append(.messagesReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.generic.cellular.incoming))) + entries.append(.messagesSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.generic.cellular.outgoing, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) + entries.append(.messagesReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.generic.cellular.incoming, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) entries.append(.imageHeader(presentationData.theme, presentationData.strings.NetworkUsageSettings_MediaImageDataSection)) - entries.append(.imageSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.image.cellular.outgoing))) - entries.append(.imageReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.image.cellular.incoming))) + entries.append(.imageSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.image.cellular.outgoing, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) + entries.append(.imageReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.image.cellular.incoming, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) entries.append(.videoHeader(presentationData.theme, presentationData.strings.NetworkUsageSettings_MediaVideoDataSection)) - entries.append(.videoSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.video.cellular.outgoing))) - entries.append(.videoReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.video.cellular.incoming))) + entries.append(.videoSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.video.cellular.outgoing, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) + entries.append(.videoReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.video.cellular.incoming, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) entries.append(.audioHeader(presentationData.theme, presentationData.strings.NetworkUsageSettings_MediaAudioDataSection)) - entries.append(.audioSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.audio.cellular.outgoing))) - entries.append(.audioReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.audio.cellular.incoming))) + entries.append(.audioSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.audio.cellular.outgoing, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) + entries.append(.audioReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.audio.cellular.incoming, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) entries.append(.fileHeader(presentationData.theme, presentationData.strings.NetworkUsageSettings_MediaDocumentDataSection)) - entries.append(.fileSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.file.cellular.outgoing))) - entries.append(.fileReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.file.cellular.incoming))) + entries.append(.fileSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.file.cellular.outgoing, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) + entries.append(.fileReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.file.cellular.incoming, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) entries.append(.callHeader(presentationData.theme, presentationData.strings.NetworkUsageSettings_CallDataSection)) - entries.append(.callSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.call.cellular.outgoing))) - entries.append(.callReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.call.cellular.incoming))) + entries.append(.callSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.call.cellular.outgoing, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) + entries.append(.callReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.call.cellular.incoming, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) entries.append(.reset(presentationData.theme, section, presentationData.strings.NetworkUsageSettings_ResetStats)) @@ -337,28 +337,28 @@ private func networkUsageStatsControllerEntries(presentationData: PresentationDa } 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))) - entries.append(.messagesReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.generic.wifi.incoming))) + entries.append(.messagesSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.generic.wifi.outgoing, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) + entries.append(.messagesReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.generic.wifi.incoming, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) entries.append(.imageHeader(presentationData.theme, presentationData.strings.NetworkUsageSettings_MediaImageDataSection)) - entries.append(.imageSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.image.wifi.outgoing))) - entries.append(.imageReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.image.wifi.incoming))) + entries.append(.imageSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.image.wifi.outgoing, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) + entries.append(.imageReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.image.wifi.incoming, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) entries.append(.videoHeader(presentationData.theme, presentationData.strings.NetworkUsageSettings_MediaVideoDataSection)) - entries.append(.videoSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.video.wifi.outgoing))) - entries.append(.videoReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.video.wifi.incoming))) + entries.append(.videoSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.video.wifi.outgoing, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) + entries.append(.videoReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.video.wifi.incoming, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) entries.append(.audioHeader(presentationData.theme, presentationData.strings.NetworkUsageSettings_MediaAudioDataSection)) - entries.append(.audioSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.audio.wifi.outgoing))) - entries.append(.audioReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.audio.wifi.incoming))) + entries.append(.audioSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.audio.wifi.outgoing, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) + entries.append(.audioReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.audio.wifi.incoming, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) entries.append(.fileHeader(presentationData.theme, presentationData.strings.NetworkUsageSettings_MediaDocumentDataSection)) - entries.append(.fileSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.file.wifi.outgoing))) - entries.append(.fileReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.file.wifi.incoming))) + entries.append(.fileSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.file.wifi.outgoing, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) + entries.append(.fileReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.file.wifi.incoming, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) entries.append(.callHeader(presentationData.theme, presentationData.strings.NetworkUsageSettings_CallDataSection)) - entries.append(.callSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.call.wifi.outgoing))) - entries.append(.callReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.call.wifi.incoming))) + entries.append(.callSent(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesSent, dataSizeString(stats.call.wifi.outgoing, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) + entries.append(.callReceived(presentationData.theme, presentationData.strings.NetworkUsageSettings_BytesReceived, dataSizeString(stats.call.wifi.incoming, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) entries.append(.reset(presentationData.theme, section, presentationData.strings.NetworkUsageSettings_ResetStats)) if stats.resetWifiTimestamp != 0 { diff --git a/TelegramUI/PresentationData.swift b/TelegramUI/PresentationData.swift index 5aeacf7334..5b52addb25 100644 --- a/TelegramUI/PresentationData.swift +++ b/TelegramUI/PresentationData.swift @@ -9,6 +9,7 @@ public struct PresentationDateTimeFormat: Equatable { let timeFormat: PresentationTimeFormat let dateFormat: PresentationDateFormat let dateSeparator: String + let decimalSeparator: String } public struct PresentationVolumeControlStatusBarIcons: Equatable { @@ -102,8 +103,8 @@ private func volumeControlStatusBarIcons() -> PresentationVolumeControlStatusBar return PresentationVolumeControlStatusBarIcons(offIcon: UIImage(bundleImageName: "Components/Volume/VolumeOff")!, halfIcon: UIImage(bundleImageName: "Components/Volume/VolumeHalf")!, fullIcon: UIImage(bundleImageName: "Components/Volume/VolumeFull")!) } -private func currentDateTimeFormat() -> PresentationDateTimeFormat { - let locale = Locale.current +private func currentDateTimeFormat(strings: PresentationStrings) -> PresentationDateTimeFormat { + let locale = Locale(identifier: strings.baseLanguageCode) let dateFormatter = DateFormatter() dateFormatter.locale = locale dateFormatter.dateStyle = .none @@ -141,7 +142,9 @@ private func currentDateTimeFormat() -> PresentationDateTimeFormat { dateFormat = .dayFirst } - return PresentationDateTimeFormat(timeFormat: timeFormat, dateFormat: dateFormat, dateSeparator: dateSeparator) + let decimalSeparator = locale.decimalSeparator ?? "." + + return PresentationDateTimeFormat(timeFormat: timeFormat, dateFormat: dateFormat, dateSeparator: dateSeparator, decimalSeparator: decimalSeparator) } private func currentPersonNameSortOrder() -> PresentationPersonNameOrder { @@ -270,7 +273,7 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager) - } else { stringsValue = defaultPresentationStrings } - let dateTimeFormat = currentDateTimeFormat() + let dateTimeFormat = currentDateTimeFormat(strings: stringsValue) let nameDisplayOrder = contactSettings.nameDisplayOrder let nameSortOrder = currentPersonNameSortOrder() return InitialPresentationDataAndSettings(presentationData: PresentationData(strings: stringsValue, theme: themeValue, chatWallpaper: effectiveChatWallpaper, volumeControlStatusBarIcons: volumeControlStatusBarIcons(), fontSize: themeSettings.fontSize, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, nameSortOrder: nameSortOrder, disableAnimations: themeSettings.disableAnimations), automaticMediaDownloadSettings: automaticMediaDownloadSettings, callListSettings: callListSettings, inAppNotificationSettings: inAppNotificationSettings, mediaInputSettings: mediaInputSettings, experimentalUISettings: experimentalUISettings) @@ -426,7 +429,7 @@ public func updatedPresentationData(accountManager: AccountManager, applicationB stringsValue = defaultPresentationStrings } - let dateTimeFormat = currentDateTimeFormat() + let dateTimeFormat = currentDateTimeFormat(strings: stringsValue) let nameDisplayOrder = contactSettings.nameDisplayOrder let nameSortOrder = currentPersonNameSortOrder() @@ -441,7 +444,7 @@ public func updatedPresentationData(accountManager: AccountManager, applicationB } public func defaultPresentationData() -> PresentationData { - let dateTimeFormat = currentDateTimeFormat() + let dateTimeFormat = currentDateTimeFormat(strings: defaultPresentationStrings) let nameDisplayOrder: PresentationPersonNameOrder = .firstLast let nameSortOrder = currentPersonNameSortOrder() diff --git a/TelegramUI/SettingsController.swift b/TelegramUI/SettingsController.swift index ff69fd91db..599aa32d60 100644 --- a/TelegramUI/SettingsController.swift +++ b/TelegramUI/SettingsController.swift @@ -343,7 +343,7 @@ private enum SettingsEntry: ItemListNodeEntry { label = .badge("\(badgeCount)") } } - return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: PresentationDateTimeFormat(timeFormat: .regular, dateFormat: .dayFirst, dateSeparator: "."), nameDisplayOrder: .firstLast, account: account, peer: peer, aliasHandling: .standard, nameStyle: .plain, presence: nil, text: .none, label: label, editing: ItemListPeerItemEditing(editable: true, editing: false, revealed: revealed), revealOptions: nil, switchValue: nil, enabled: true, sectionId: self.section, action: { + return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: PresentationDateTimeFormat(timeFormat: .regular, dateFormat: .dayFirst, dateSeparator: ".", decimalSeparator: "."), nameDisplayOrder: .firstLast, account: account, peer: peer, aliasHandling: .standard, nameStyle: .plain, presence: nil, text: .none, label: label, editing: ItemListPeerItemEditing(editable: true, editing: false, revealed: revealed), revealOptions: nil, switchValue: nil, enabled: true, sectionId: self.section, action: { arguments.switchToAccount(account.id) }, setPeerIdWithRevealedOptions: { lhs, rhs in var lhsAccountId: AccountRecordId? diff --git a/TelegramUI/StorageUsageController.swift b/TelegramUI/StorageUsageController.swift index ca4a931f0d..0f0a5e625e 100644 --- a/TelegramUI/StorageUsageController.swift +++ b/TelegramUI/StorageUsageController.swift @@ -193,7 +193,7 @@ private func storageUsageControllerEntries(presentationData: PresentationData, c var addedHeader = false if let cacheStats = cacheStats, case let .result(stats) = cacheStats { - entries.append(.immutableSize(presentationData.theme, presentationData.strings.Cache_ServiceFiles, dataSizeString(stats.immutableSize))) + entries.append(.immutableSize(presentationData.theme, presentationData.strings.Cache_ServiceFiles, dataSizeString(stats.immutableSize, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) var peerSizes: Int64 = 0 var statsByPeerId: [(PeerId, Int64)] = [] @@ -220,7 +220,7 @@ private func storageUsageControllerEntries(presentationData: PresentationData, c let totalSize = Int64(peerSizes + stats.otherSize + stats.cacheSize + stats.tempSize) - entries.append(.clearAll(presentationData.theme, presentationData.strings.Cache_ClearCache, totalSize > 0 ? dataSizeString(totalSize) : presentationData.strings.Cache_ClearEmpty, totalSize > 0)) + entries.append(.clearAll(presentationData.theme, presentationData.strings.Cache_ClearCache, totalSize > 0 ? dataSizeString(totalSize, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator) : presentationData.strings.Cache_ClearEmpty, totalSize > 0)) var index: Int32 = 0 for (peerId, size) in statsByPeerId.sorted(by: { $0.1 > $1.1 }) { @@ -236,7 +236,7 @@ private func storageUsageControllerEntries(presentationData: PresentationData, c chatPeer = mainPeer mainPeer = associatedPeer } - entries.append(.peer(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, mainPeer, chatPeer, dataSizeString(size))) + entries.append(.peer(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, mainPeer, chatPeer, dataSizeString(size, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))) index += 1 } } @@ -374,7 +374,7 @@ func storageUsageController(context: AccountContext, isModal: Bool = false) -> V if filteredSize == 0 { title = presentationData.strings.Cache_ClearNone } else { - title = presentationData.strings.Cache_Clear("\(dataSizeString(filteredSize))").0 + title = presentationData.strings.Cache_Clear("\(dataSizeString(filteredSize, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))").0 } if let item = item as? ActionSheetButtonItem { @@ -411,7 +411,7 @@ func storageUsageController(context: AccountContext, isModal: Bool = false) -> V let categorySize: Int64 = size totalSize += categorySize let index = itemIndex - items.append(ActionSheetCheckboxItem(title: stringForCategory(strings: presentationData.strings, category: categoryId), label: dataSizeString(categorySize), value: true, action: { value in + items.append(ActionSheetCheckboxItem(title: stringForCategory(strings: presentationData.strings, category: categoryId), label: dataSizeString(categorySize, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator), value: true, action: { value in toggleCheck(categoryId, index) })) itemIndex += 1 @@ -421,14 +421,14 @@ func storageUsageController(context: AccountContext, isModal: Bool = false) -> V if otherSize.1 != 0 { totalSize += otherSize.1 let index = itemIndex - items.append(ActionSheetCheckboxItem(title: presentationData.strings.Localization_LanguageOther, label: dataSizeString(otherSize.1), value: true, action: { value in + items.append(ActionSheetCheckboxItem(title: presentationData.strings.Localization_LanguageOther, label: dataSizeString(otherSize.1, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator), value: true, action: { value in toggleCheck(nil, index) })) itemIndex += 1 } if !items.isEmpty { - items.append(ActionSheetButtonItem(title: presentationData.strings.Cache_Clear("\(dataSizeString(totalSize))").0, action: { + items.append(ActionSheetButtonItem(title: presentationData.strings.Cache_Clear("\(dataSizeString(totalSize, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))").0, action: { if let statsPromise = statsPromise { let clearCategories = sizeIndex.keys.filter({ sizeIndex[$0]!.0 }) @@ -572,7 +572,7 @@ func storageUsageController(context: AccountContext, isModal: Bool = false) -> V if filteredSize == 0 { title = presentationData.strings.Cache_ClearNone } else { - title = presentationData.strings.Cache_Clear("\(dataSizeString(filteredSize))").0 + title = presentationData.strings.Cache_Clear("\(dataSizeString(filteredSize, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))").0 } if let item = item as? ActionSheetButtonItem { @@ -610,7 +610,7 @@ func storageUsageController(context: AccountContext, isModal: Bool = false) -> V totalSize += categorySize if categorySize > 1024 { let index = itemIndex - items.append(ActionSheetCheckboxItem(title: stringForCategory(strings: presentationData.strings, category: categoryId), label: dataSizeString(categorySize), value: true, action: { value in + items.append(ActionSheetCheckboxItem(title: stringForCategory(strings: presentationData.strings, category: categoryId), label: dataSizeString(categorySize, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator), value: true, action: { value in toggleCheck(categoryId, index) })) itemIndex += 1 @@ -619,7 +619,7 @@ func storageUsageController(context: AccountContext, isModal: Bool = false) -> V } if !items.isEmpty { - items.append(ActionSheetButtonItem(title: presentationData.strings.Cache_Clear("\(dataSizeString(totalSize))").0, action: { + items.append(ActionSheetButtonItem(title: presentationData.strings.Cache_Clear("\(dataSizeString(totalSize, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))").0, action: { if let statsPromise = statsPromise { let clearCategories = sizeIndex.keys.filter({ sizeIndex[$0]!.0 }) var clearMediaIds = Set() diff --git a/TelegramUI/UniversalVideoGalleryItem.swift b/TelegramUI/UniversalVideoGalleryItem.swift index 5190fc2d31..1d86922446 100644 --- a/TelegramUI/UniversalVideoGalleryItem.swift +++ b/TelegramUI/UniversalVideoGalleryItem.swift @@ -139,7 +139,7 @@ private struct FetchControls { final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { private let context: AccountContext - private let strings: PresentationStrings + private let presentationData: PresentationData fileprivate let _ready = Promise() fileprivate let _title = Promise() @@ -178,7 +178,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { init(context: AccountContext, presentationData: PresentationData, performAction: @escaping (GalleryControllerInteractionTapAction) -> Void, openActionOptions: @escaping (GalleryControllerInteractionTapAction) -> Void) { self.context = context - self.strings = presentationData.strings + self.presentationData = presentationData self.scrubberView = ChatVideoGalleryItemScrubberView() self.footerContentNode = ChatItemGalleryFooterContentNode(context: context, presentationData: presentationData) @@ -363,7 +363,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { if let file = file { let status = messageMediaFileStatus(context: item.context, messageId: message.id, file: file) if !isWebpage { - self.scrubberView.setFetchStatusSignal(status, strings: self.strings, fileSize: file.size) + self.scrubberView.setFetchStatusSignal(status, strings: self.presentationData.strings, decimalSeparator: self.presentationData.dateTimeFormat.decimalSeparator, fileSize: file.size) } self.requiresDownload = !isMediaStreamable(message: message, media: file) @@ -511,7 +511,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { private func updateDisplayPlaceholder(_ displayPlaceholder: Bool) { if displayPlaceholder { if self.pictureInPictureNode == nil { - let pictureInPictureNode = UniversalVideoGalleryItemPictureInPictureNode(strings: self.strings) + let pictureInPictureNode = UniversalVideoGalleryItemPictureInPictureNode(strings: self.presentationData.strings) pictureInPictureNode.isUserInteractionEnabled = false self.pictureInPictureNode = pictureInPictureNode self.insertSubnode(pictureInPictureNode, aboveSubnode: self.scrollNode)