From 929b0747fc6b74030d2c9b1ff1fad3ef6625a5d5 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Thu, 11 Apr 2019 23:04:33 +0400 Subject: [PATCH 1/2] Draw white outline around large emojis --- .../CachedResourceRepresentations.swift | 14 +++++ TelegramUI/ChatMessageItem.swift | 2 +- TelegramUI/ChatMessageStickerItemNode.swift | 30 +++++---- .../ChatMessageTextBubbleContentNode.swift | 20 +----- TelegramUI/FetchCachedRepresentations.swift | 62 +++++++++++++++++++ TelegramUI/LargeEmojiResource.swift | 57 +++++++++++++++++ TelegramUI/PhotoResources.swift | 25 ++++++++ TelegramUI/UndoOverlayControllerNode.swift | 21 ++++--- .../WallpaperGalleryDecorationNode.swift | 2 +- 9 files changed, 192 insertions(+), 41 deletions(-) create mode 100644 TelegramUI/LargeEmojiResource.swift diff --git a/TelegramUI/CachedResourceRepresentations.swift b/TelegramUI/CachedResourceRepresentations.swift index 0bcdbf14f3..8fe68b74fe 100644 --- a/TelegramUI/CachedResourceRepresentations.swift +++ b/TelegramUI/CachedResourceRepresentations.swift @@ -171,3 +171,17 @@ final class CachedAlbumArtworkRepresentation: CachedMediaResourceRepresentation } } } + +final class CachedLargeEmojiRepresentation: CachedMediaResourceRepresentation { + var uniqueId: String { + return "large-emoji" + } + + func isEqual(to: CachedMediaResourceRepresentation) -> Bool { + if let to = to as? CachedLargeEmojiRepresentation { + return true + } else { + return false + } + } +} diff --git a/TelegramUI/ChatMessageItem.swift b/TelegramUI/ChatMessageItem.swift index 2c62839092..8d2cdc0a2b 100644 --- a/TelegramUI/ChatMessageItem.swift +++ b/TelegramUI/ChatMessageItem.swift @@ -352,7 +352,7 @@ public final class ChatMessageItem: ListViewItem, CustomStringConvertible { } } - if viewClassName == ChatMessageBubbleItemNode.self, !self.message.text.isEmpty && self.message.text.containsOnlyEmoji && self.presentationData.largeEmoji, self.message.text.emojis.count < 4 { + if viewClassName == ChatMessageBubbleItemNode.self && self.message.media.isEmpty && !self.message.text.isEmpty && self.message.text.containsOnlyEmoji && self.presentationData.largeEmoji, self.message.text.emojis.count < 4 { viewClassName = ChatMessageStickerItemNode.self } diff --git a/TelegramUI/ChatMessageStickerItemNode.swift b/TelegramUI/ChatMessageStickerItemNode.swift index debd189394..797272171e 100644 --- a/TelegramUI/ChatMessageStickerItemNode.swift +++ b/TelegramUI/ChatMessageStickerItemNode.swift @@ -98,6 +98,23 @@ class ChatMessageStickerItemNode: ChatMessageItemView { break } } + + if self.telegramFile == nil && !item.message.text.isEmpty && item.message.text.containsOnlyEmoji && item.presentationData.largeEmoji { + var textFont = item.presentationData.messageFont + let emojis = item.message.text.emojis + switch emojis.count { + case 1: + textFont = item.presentationData.messageEmojiFont1 + case 2: + textFont = item.presentationData.messageEmojiFont2 + case 3: + textFont = item.presentationData.messageEmojiFont3 + default: + break + } + + self.imageNode.setSignal(largeEmoji(postbox: item.context.account.postbox, emoji: item.message.text, fontSize: textFont.pointSize)) + } } override func asyncLayout() -> (_ item: ChatMessageItem, _ params: ListViewItemLayoutParams, _ mergedTop: ChatMessageMerge, _ mergedBottom: ChatMessageMerge, _ dateHeaderAtBottom: Bool) -> (ListViewItemNodeLayout, (ListViewItemUpdateAnimation, Bool) -> Void) { @@ -144,7 +161,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { let attributedText = NSAttributedString(string: item.message.text, font: textFont, textColor: .black) textLayoutAndApply = textLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: 120.0, height: 60.0), alignment: .natural)) - imageSize = CGSize(width: textLayoutAndApply!.0.size.width, height: 100.0) + imageSize = CGSize(width: textLayoutAndApply!.0.size.width, height: max(90.0, textLayoutAndApply!.0.size.height)) } let avatarInset: CGFloat @@ -366,20 +383,9 @@ class ChatMessageStickerItemNode: ChatMessageItemView { } let updatedImageFrame = imageFrame.offsetBy(dx: 0.0, dy: floor((contentHeight - imageSize.height) / 2.0)) - transition.updateFrame(node: strongSelf.imageNode, frame: updatedImageFrame) imageApply() - if let (textLayout, textApply) = textLayoutAndApply { - let textNode = textApply() - if textNode !== strongSelf.textNode { - strongSelf.textNode?.removeFromSupernode() - strongSelf.addSubnode(textNode) - strongSelf.textNode = textNode - } - transition.updateFrame(node: textNode, frame: CGRect(x: updatedImageFrame.maxX - textLayout.size.width - 10.0, y: updatedImageFrame.maxY - textLayout.size.height - 30.0, width: textLayout.size.width, height: textLayout.size.height)) - } - if let updatedShareButtonNode = updatedShareButtonNode { if updatedShareButtonNode !== strongSelf.shareButtonNode { if let shareButtonNode = strongSelf.shareButtonNode { diff --git a/TelegramUI/ChatMessageTextBubbleContentNode.swift b/TelegramUI/ChatMessageTextBubbleContentNode.swift index 6aa45f3068..5b57ccbe6f 100644 --- a/TelegramUI/ChatMessageTextBubbleContentNode.swift +++ b/TelegramUI/ChatMessageTextBubbleContentNode.swift @@ -215,24 +215,8 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { let bubbleTheme = item.presentationData.theme.theme.chat.bubble - var textFont = item.presentationData.messageFont - var forceStatusNewline = false - if rawText.containsOnlyEmoji && item.presentationData.largeEmoji { - let emojis = rawText.emojis - switch emojis.count { - case 1: - textFont = item.presentationData.messageEmojiFont1 - forceStatusNewline = true - case 2: - textFont = item.presentationData.messageEmojiFont2 - forceStatusNewline = true - case 3: - textFont = item.presentationData.messageEmojiFont3 - forceStatusNewline = true - default: - break - } - } + let textFont = item.presentationData.messageFont + let forceStatusNewline = false if let entities = entities { attributedText = stringWithAppliedEntities(rawText, entities: entities, baseColor: incoming ? bubbleTheme.incomingPrimaryTextColor : bubbleTheme.outgoingPrimaryTextColor, linkColor: incoming ? bubbleTheme.incomingLinkTextColor : bubbleTheme.outgoingLinkTextColor, baseFont: textFont, linkFont: textFont, boldFont: item.presentationData.messageBoldFont, italicFont: item.presentationData.messageItalicFont, fixedFont: item.presentationData.messageFixedFont) diff --git a/TelegramUI/FetchCachedRepresentations.swift b/TelegramUI/FetchCachedRepresentations.swift index 705838acc2..ab39966d65 100644 --- a/TelegramUI/FetchCachedRepresentations.swift +++ b/TelegramUI/FetchCachedRepresentations.swift @@ -101,6 +101,8 @@ public func fetchCachedResourceRepresentation(account: Account, resource: MediaR return .complete() } } + } else if let representation = representation as? CachedLargeEmojiRepresentation { + return fetchLargeEmojiRepresentation(account: account, resource: resource, representation: representation) } return .never() } @@ -671,3 +673,63 @@ private func fetchCachedAlbumArtworkRepresentation(account: Account, resource: M return EmptyDisposable }) |> runOn(Queue.concurrentDefaultQueue()) } + +private func fetchLargeEmojiRepresentation(account: Account, resource: MediaResource, representation: CachedLargeEmojiRepresentation) -> Signal { + guard let resource = resource as? LargeEmojiResource else { + return .never() + } + return Signal({ subscriber in + var randomId: Int64 = 0 + arc4random_buf(&randomId, 8) + let path = NSTemporaryDirectory() + "\(randomId)" + let url = URL(fileURLWithPath: path) + + let nsString = (resource.emoji as NSString) + let font = Font.regular(resource.fontSize) + let stringAttributes = [NSAttributedStringKey.font: font] + var emojiSize = nsString.size(withAttributes: stringAttributes) + emojiSize = CGSize(width: ceil(emojiSize.width), height: ceil(emojiSize.height)) + + let image = generateImage(emojiSize, contextGenerator: { size, context in + let bounds = CGRect(origin: CGPoint(), size: size) + + context.clear(CGRect(origin: CGPoint(), size: size)) + context.textMatrix = .identity + + let path = CGMutablePath() + path.addRect(bounds) + let string = NSAttributedString(string: resource.emoji, font: font, textColor: .black) + let framesetter = CTFramesetterCreateWithAttributedString(string as CFAttributedString) + let frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, string.length), path, nil) + CTFrameDraw(frame, context) + })! + + let borderImage = generateTintedImage(image: image, color: .white)! + + let lineWidth: CGFloat = 1.0 + let colorImage = generateImage(CGSize(width: emojiSize.width + lineWidth * 2.0, height: emojiSize.height + lineWidth * 2.0), contextGenerator: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + let vectors: [CGPoint] = [CGPoint(x: -1.0, y: -1.0), CGPoint(x: -1.0, y: 0.0), CGPoint(x: -1.0, y: 1.0), CGPoint(x: 0.0, y: 1.0), CGPoint(x: 1.0, y: 1.0), CGPoint(x: 1.0, y: 0.0), CGPoint(x: 1.0, y: -1.0), CGPoint(x: 0.0, y: -1.0)] + if let image = image.cgImage, let borderImage = borderImage.cgImage { + let rect = CGRect(x: lineWidth, y: lineWidth, width: emojiSize.width, height: emojiSize.height) + let step = UIScreenPixel + for vector in vectors { + for i in stride(from: step, through: lineWidth, by: step) { + drawImage(context: context, image: borderImage, orientation: .up, in: rect.offsetBy(dx: vector.x * i, dy: vector.y * i)) + } + } + drawImage(context: context, image: image, orientation: .up, in: rect) + } + })! + + if let colorDestination = CGImageDestinationCreateWithURL(url as CFURL, kUTTypePNG, 1, nil) { + let options = NSMutableDictionary() + CGImageDestinationAddImage(colorDestination, colorImage.cgImage!, options as CFDictionary) + if CGImageDestinationFinalize(colorDestination) { + subscriber.putNext(CachedMediaResourceRepresentationResult(temporaryPath: path)) + } + } + subscriber.putCompletion() + return EmptyDisposable + }) |> runOn(Queue.concurrentDefaultQueue()) +} diff --git a/TelegramUI/LargeEmojiResource.swift b/TelegramUI/LargeEmojiResource.swift new file mode 100644 index 0000000000..76445943e5 --- /dev/null +++ b/TelegramUI/LargeEmojiResource.swift @@ -0,0 +1,57 @@ +import Foundation +import TelegramCore +import SwiftSignalKit +import Postbox + +public struct LargeEmojiResourceId: MediaResourceId { + public let emoji: String + public let fontSize: CGFloat + + public var uniqueId: String { + return "large-emoji-\(emoji)-\(fontSize)" + } + + public var hashValue: Int { + return self.emoji.hashValue &* 31 &+ self.fontSize.hashValue + } + + public func isEqual(to: MediaResourceId) -> Bool { + if let to = to as? LargeEmojiResourceId { + return self.emoji == to.emoji && self.fontSize == to.fontSize + } else { + return false + } + } +} + +public class LargeEmojiResource: TelegramMediaResource { + public let emoji: String + public let fontSize: CGFloat + + public init(emoji: String, fontSize: CGFloat) { + self.emoji = emoji + self.fontSize = fontSize + } + + public required init(decoder: PostboxDecoder) { + self.emoji = decoder.decodeStringForKey("e", orElse: "") + self.fontSize = CGFloat(decoder.decodeDoubleForKey("s", orElse: 0.0)) + } + + public func encode(_ encoder: PostboxEncoder) { + encoder.encodeString(self.emoji, forKey: "e") + encoder.encodeDouble(Double(self.fontSize), forKey: "s") + } + + public var id: MediaResourceId { + return LargeEmojiResourceId(emoji: self.emoji, fontSize: self.fontSize) + } + + public func isEqual(to: MediaResource) -> Bool { + if let to = to as? LargeEmojiResource { + return self.emoji == to.emoji && self.fontSize == to.fontSize + } else { + return false + } + } +} diff --git a/TelegramUI/PhotoResources.swift b/TelegramUI/PhotoResources.swift index f067de1c0f..b74ce3b0a3 100644 --- a/TelegramUI/PhotoResources.swift +++ b/TelegramUI/PhotoResources.swift @@ -2995,3 +2995,28 @@ func callDefaultBackground() -> Signal<(TransformImageArguments) -> DrawingConte return context }) } + +func largeEmoji(postbox: Postbox, emoji: String, fontSize: CGFloat) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { + let resource = LargeEmojiResource(emoji: emoji, fontSize: fontSize) + let representation = CachedLargeEmojiRepresentation() + return postbox.mediaBox.cachedResourceRepresentation(resource, representation: representation, complete: true, fetch: true) + |> map { data in + return { arguments in + let context = DrawingContext(size: arguments.drawingSize, clear: true) + + var sourceImage: UIImage? + if let data = try? Data(contentsOf: URL(fileURLWithPath: data.path), options: []), let image = UIImage(data: data, scale: UIScreen.main.scale) { + sourceImage = image + } + + if let sourceImage = sourceImage, let cgImage = sourceImage.cgImage { + let imageSize = sourceImage.size + context.withFlippedContext { c in + c.draw(cgImage, in: CGRect(origin: CGPoint(x: floor((arguments.drawingSize.width - imageSize.width) / 2.0), y: floor((arguments.drawingSize.height - imageSize.height) / 2.0)), size: imageSize)) + } + } + + return context + } + } +} diff --git a/TelegramUI/UndoOverlayControllerNode.swift b/TelegramUI/UndoOverlayControllerNode.swift index 739190ce28..a479d518d9 100644 --- a/TelegramUI/UndoOverlayControllerNode.swift +++ b/TelegramUI/UndoOverlayControllerNode.swift @@ -125,24 +125,26 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { let contentHeight: CGFloat = 49.0 let margin: CGFloat = 16.0 - let panelFrame = CGRect(origin: CGPoint(x: margin, y: layout.size.height - contentHeight - layout.intrinsicInsets.bottom - margin - 49.0), size: CGSize(width: layout.size.width - margin * 2.0, height: contentHeight)) - let panelWrapperFrame = CGRect(origin: CGPoint(x: margin, y: layout.size.height - contentHeight - layout.intrinsicInsets.bottom - margin - 49.0), size: CGSize(width: layout.size.width - margin * 2.0 + margin, height: contentHeight)) + let insets = layout.insets(options: [.input]) + + let panelFrame = CGRect(origin: CGPoint(x: margin + layout.safeInsets.left, y: layout.size.height - contentHeight - insets.bottom - margin - 49.0), size: CGSize(width: layout.size.width - margin * 2.0 - layout.safeInsets.left - layout.safeInsets.right, height: contentHeight)) + let panelWrapperFrame = CGRect(origin: CGPoint(x: margin + layout.safeInsets.left, y: layout.size.height - contentHeight - insets.bottom - margin - 49.0), size: CGSize(width: layout.size.width - margin * 2.0 - layout.safeInsets.left - layout.safeInsets.right, height: contentHeight)) transition.updateFrame(node: self.panelNode, frame: panelFrame) transition.updateFrame(node: self.panelWrapperNode, frame: panelWrapperFrame) - self.effectView.frame = CGRect(x: 0.0, y: 0.0, width: layout.size.width - margin * 2.0, height: contentHeight) + self.effectView.frame = CGRect(x: 0.0, y: 0.0, width: layout.size.width - margin * 2.0 - layout.safeInsets.left - layout.safeInsets.right, height: contentHeight) let buttonTextSize = self.buttonTextNode.updateLayout(CGSize(width: 200.0, height: .greatestFiniteMagnitude)) - let buttonTextFrame = CGRect(origin: CGPoint(x: layout.size.width - layout.safeInsets.right - rightInset - buttonTextSize.width - margin * 2.0, y: floor((contentHeight - buttonTextSize.height) / 2.0)), size: buttonTextSize) + let buttonTextFrame = CGRect(origin: CGPoint(x: layout.size.width - layout.safeInsets.left - layout.safeInsets.right - rightInset - buttonTextSize.width - margin * 2.0, y: floor((contentHeight - buttonTextSize.height) / 2.0)), size: buttonTextSize) transition.updateFrame(node: self.buttonTextNode, frame: buttonTextFrame) - self.buttonNode.frame = CGRect(origin: CGPoint(x: layout.size.width - layout.safeInsets.right - rightInset - buttonTextSize.width - 8.0 - margin, y: 0.0), size: CGSize(width: layout.safeInsets.right + rightInset + buttonTextSize.width + 8.0 + margin, height: contentHeight)) + self.buttonNode.frame = CGRect(origin: CGPoint(x: layout.size.width - layout.safeInsets.left - layout.safeInsets.right - rightInset - buttonTextSize.width - 8.0 - margin * 2.0, y: 0.0), size: CGSize(width: layout.safeInsets.right + rightInset + buttonTextSize.width + 8.0 + margin, height: contentHeight)) let textSize = self.textNode.updateLayout(CGSize(width: buttonTextFrame.minX - 8.0 - leftInset - layout.safeInsets.left - layout.safeInsets.right - margin * 2.0, height: .greatestFiniteMagnitude)) - transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + leftInset, y: floor((contentHeight - textSize.height) / 2.0)), size: textSize)) + transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: leftInset, y: floor((contentHeight - textSize.height) / 2.0)), size: textSize)) let timerTextSize = self.timerTextNode.updateLayout(CGSize(width: 100.0, height: 100.0)) - transition.updateFrame(node: self.timerTextNode, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + floor((leftInset - timerTextSize.width) / 2.0), y: floor((contentHeight - timerTextSize.height) / 2.0)), size: timerTextSize)) + transition.updateFrame(node: self.timerTextNode, frame: CGRect(origin: CGPoint(x: floor((leftInset - timerTextSize.width) / 2.0), y: floor((contentHeight - timerTextSize.height) / 2.0)), size: timerTextSize)) let statusSize: CGFloat = 30.0 - transition.updateFrame(node: self.statusNode, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + floor((leftInset - statusSize) / 2.0), y: floor((contentHeight - statusSize) / 2.0)), size: CGSize(width: statusSize, height: statusSize))) + transition.updateFrame(node: self.statusNode, frame: CGRect(origin: CGPoint(x: floor((leftInset - statusSize) / 2.0), y: floor((contentHeight - statusSize) / 2.0)), size: CGSize(width: statusSize, height: statusSize))) if firstLayout { self.statusNode.transitionToState(.secretTimeout(color: .white, icon: nil, beginTime: CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970, timeout: Double(self.remainingSeconds), sparks: false), completion: {}) } @@ -150,6 +152,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { func animateIn() { self.panelNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3) + self.panelWrapperNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3) } func animateOut(completion: @escaping () -> Void) { @@ -160,7 +163,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { } override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { - if !self.panelNode.frame.contains(point) { + if !self.panelNode.frame.insetBy(dx: -60.0, dy: 0.0).contains(point) { return nil } return super.hitTest(point, with: event) diff --git a/TelegramUI/WallpaperGalleryDecorationNode.swift b/TelegramUI/WallpaperGalleryDecorationNode.swift index b4f9505c34..40acae875e 100644 --- a/TelegramUI/WallpaperGalleryDecorationNode.swift +++ b/TelegramUI/WallpaperGalleryDecorationNode.swift @@ -129,7 +129,7 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode { } func setSelected(_ selected: Bool, animated: Bool = false) { - self.isSelected = selected + self._value = .check(selected) self.checkNode.setSelected(selected, animated: animated) } From 1c4500fcf89d52a7f1a00334065d5402ca829e37 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Fri, 12 Apr 2019 21:52:59 +0400 Subject: [PATCH 2/2] Chat list item content animations --- TelegramUI.xcodeproj/project.pbxproj | 4 + TelegramUI/BlockedPeersController.swift | 2 +- TelegramUI/ChannelAdminsController.swift | 2 +- TelegramUI/ChannelBlacklistController.swift | 2 +- TelegramUI/ChannelInfoController.swift | 12 + TelegramUI/ChannelMembersController.swift | 2 +- TelegramUI/ChannelPermissionsController.swift | 2 +- TelegramUI/ChannelVisibilityController.swift | 2 +- .../ChatInterfaceStateInputPanels.swift | 4 +- TelegramUI/ChatListBadgeNode.swift | 173 +- TelegramUI/ChatListController.swift | 8 +- TelegramUI/ChatListItem.swift | 159 +- TelegramUI/ChatListOnlineNode.swift | 2 +- TelegramUI/ChatListStatusNode.swift | 404 ++- TelegramUI/ChatListTypingNode.swift | 24 +- TelegramUI/ChatMessageStickerItemNode.swift | 28 +- .../ChatPlayingActivityContentNode.swift | 4 +- .../ChatRecentActionsFilterController.swift | 2 +- TelegramUI/ChatTitleActivityNode.swift | 3 + .../ChatTypingActivityContentNode.swift | 7 +- .../ChatUploadingActivityContentNode.swift | 8 +- TelegramUI/CreateGroupController.swift | 2 +- TelegramUI/DefaultDarkPresentationTheme.swift | 2 +- TelegramUI/EditSettingsController.swift | 15 + TelegramUI/FeedGroupingControllerNode.swift | 2 +- TelegramUI/FetchCachedRepresentations.swift | 2 +- TelegramUI/GroupInfoController.swift | 35 +- TelegramUI/GroupsInCommonController.swift | 2 +- TelegramUI/ItemListPeerItem.swift | 6 +- .../NotificationExceptionControllerNode.swift | 2 +- TelegramUI/PresentationResourceKey.swift | 2 + .../PresentationResourcesChatList.swift | 33 + TelegramUI/PresentationStrings.swift | 2277 +++++++++-------- .../Resources/PresentationStrings.mapping | Bin 110403 -> 110427 bytes ...ectivePrivacySettingsPeersController.swift | 2 +- TelegramUI/SettingsController.swift | 24 +- TelegramUI/StorageUsageController.swift | 2 +- .../TabBarAccountSwitchControllerNode.swift | 7 +- 38 files changed, 1897 insertions(+), 1372 deletions(-) diff --git a/TelegramUI.xcodeproj/project.pbxproj b/TelegramUI.xcodeproj/project.pbxproj index 0898432591..8f38f516ef 100644 --- a/TelegramUI.xcodeproj/project.pbxproj +++ b/TelegramUI.xcodeproj/project.pbxproj @@ -143,6 +143,7 @@ 09F21565225C83E100AEDF6D /* ChatListStatusNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09F21564225C83E100AEDF6D /* ChatListStatusNode.swift */; }; 09F21567225C8EF500AEDF6D /* ChatListOnlineNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09F21566225C8EF500AEDF6D /* ChatListOnlineNode.swift */; }; 09F2158D225CF5BC00AEDF6D /* Pasteboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09F2158C225CF5BC00AEDF6D /* Pasteboard.swift */; }; + 09F21594225F20D300AEDF6D /* LargeEmojiResource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09F21593225F20D300AEDF6D /* LargeEmojiResource.swift */; }; 09F664C021EAAFAF00AB7E26 /* ThemeColorsGridController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09F664BF21EAAFAF00AB7E26 /* ThemeColorsGridController.swift */; }; 09F664C221EAAFCB00AB7E26 /* ThemeColorsGridControllerNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09F664C121EAAFCB00AB7E26 /* ThemeColorsGridControllerNode.swift */; }; 09F664C421EAB98300AB7E26 /* ThemeColorsGridControllerItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09F664C321EAB98300AB7E26 /* ThemeColorsGridControllerItem.swift */; }; @@ -1309,6 +1310,7 @@ 09F21564225C83E100AEDF6D /* ChatListStatusNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatListStatusNode.swift; sourceTree = ""; }; 09F21566225C8EF500AEDF6D /* ChatListOnlineNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatListOnlineNode.swift; sourceTree = ""; }; 09F2158C225CF5BC00AEDF6D /* Pasteboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Pasteboard.swift; sourceTree = ""; }; + 09F21593225F20D300AEDF6D /* LargeEmojiResource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LargeEmojiResource.swift; sourceTree = ""; }; 09F664BF21EAAFAF00AB7E26 /* ThemeColorsGridController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeColorsGridController.swift; sourceTree = ""; }; 09F664C121EAAFCB00AB7E26 /* ThemeColorsGridControllerNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeColorsGridControllerNode.swift; sourceTree = ""; }; 09F664C321EAB98300AB7E26 /* ThemeColorsGridControllerItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeColorsGridControllerItem.swift; sourceTree = ""; }; @@ -4916,6 +4918,7 @@ 099529AB21CDBBB200805E13 /* QRCode.swift */, 0910B0EE21FA532D00F8F87D /* WallpaperResources.swift */, D0CCD61A222E8B4500EE1E08 /* TimeBasedVideoPreload.swift */, + 09F21593225F20D300AEDF6D /* LargeEmojiResource.swift */, ); name = Resources; sourceTree = ""; @@ -6121,6 +6124,7 @@ D01776B31F1D69A80044446D /* RadialStatusNode.swift in Sources */, D084023420E295F000065674 /* GroupStickerPackSetupController.swift in Sources */, D01C06BE1FBCAF06001561AB /* ChatMessageBubbleMosaicLayout.swift in Sources */, + 09F21594225F20D300AEDF6D /* LargeEmojiResource.swift in Sources */, 0900678D21ED5EA800530762 /* WallpaperColorPanelNode.swift in Sources */, D0EC6E451EB9F58900EBF1C3 /* ItemListMultilineTextItem.swift in Sources */, 091417F421EF4F5F00C8325A /* WallpaperGalleryItem.swift in Sources */, diff --git a/TelegramUI/BlockedPeersController.swift b/TelegramUI/BlockedPeersController.swift index 8a2ee326dd..3cde519943 100644 --- a/TelegramUI/BlockedPeersController.swift +++ b/TelegramUI/BlockedPeersController.swift @@ -119,7 +119,7 @@ private enum BlockedPeersEntry: ItemListNodeEntry { arguments.addPeer() }) case let .peerItem(_, theme, strings, dateTimeFormat, nameDisplayOrder, peer, editing, enabled): - return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, presence: nil, text: .none, label: .none, editing: editing, switchValue: nil, enabled: enabled, sectionId: self.section, action: { + return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, presence: nil, text: .none, label: .none, editing: editing, switchValue: nil, enabled: enabled, selectable: true, sectionId: self.section, action: { arguments.openPeer(peer) }, setPeerIdWithRevealedOptions: { previousId, id in arguments.setPeerIdWithRevealedOptions(previousId, id) diff --git a/TelegramUI/ChannelAdminsController.swift b/TelegramUI/ChannelAdminsController.swift index 21bb3cc0d9..24d493adac 100644 --- a/TelegramUI/ChannelAdminsController.swift +++ b/TelegramUI/ChannelAdminsController.swift @@ -214,7 +214,7 @@ private enum ChannelAdminsEntry: ItemListNodeEntry { arguments.openAdmin(participant.participant) } } - return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: participant.peer, presence: nil, text: .text(peerText), label: .none, editing: editing, switchValue: nil, enabled: enabled, sectionId: self.section, action: action, setPeerIdWithRevealedOptions: { previousId, id in + return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: participant.peer, presence: nil, text: .text(peerText), label: .none, editing: editing, switchValue: nil, enabled: enabled, selectable: true, sectionId: self.section, action: action, setPeerIdWithRevealedOptions: { previousId, id in arguments.setPeerIdWithRevealedOptions(previousId, id) }, removePeer: { peerId in arguments.removeAdmin(peerId) diff --git a/TelegramUI/ChannelBlacklistController.swift b/TelegramUI/ChannelBlacklistController.swift index 19d635772e..35f2496079 100644 --- a/TelegramUI/ChannelBlacklistController.swift +++ b/TelegramUI/ChannelBlacklistController.swift @@ -157,7 +157,7 @@ private enum ChannelBlacklistEntry: ItemListNodeEntry { default: break } - return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: participant.peer, presence: nil, text: text, label: .none, editing: editing, switchValue: nil, enabled: enabled, sectionId: self.section, action: { + return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: participant.peer, presence: nil, text: text, label: .none, editing: editing, switchValue: nil, enabled: enabled, selectable: true, sectionId: self.section, action: { arguments.openPeer(participant) }, setPeerIdWithRevealedOptions: { previousId, id in arguments.setPeerIdWithRevealedOptions(previousId, id) diff --git a/TelegramUI/ChannelInfoController.swift b/TelegramUI/ChannelInfoController.swift index d34586668a..5cc819775c 100644 --- a/TelegramUI/ChannelInfoController.swift +++ b/TelegramUI/ChannelInfoController.swift @@ -851,6 +851,8 @@ public func channelInfoController(context: AccountContext, peerId: PeerId) -> Vi actionsDisposable.add(toggleShouldChannelMessagesSignatures(account: context.account, peerId: peerId, enabled: enabled).start()) }) + let hapticFeedback = HapticFeedback() + let globalNotificationsKey: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.globalNotifications])) let signal = combineLatest(context.sharedContext.presentationData, statePromise.get(), context.account.viewTracker.peerView(peerId), context.account.postbox.combinedView(keys: [globalNotificationsKey])) |> map { presentationData, state, view, combinedView -> (ItemListControllerState, (ItemListNodeState, ChannelInfoEntry.ItemGenerationArguments)) in @@ -901,15 +903,25 @@ public func channelInfoController(context: AccountContext, peerId: PeerId) -> Vi } else { rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Done), style: .bold, enabled: doneEnabled, action: { var updateValues: (title: String?, description: String?) = (nil, nil) + var failed = false updateState { state in updateValues = valuesRequiringUpdate(state: state, view: view) if updateValues.0 != nil || updateValues.1 != nil { + if (updateValues.description?.count ?? 0) > 255 { + failed = true + return state + } return state.withUpdatedSavingData(true) } else { return state.withUpdatedEditingState(nil) } } + guard !failed else { + hapticFeedback.error() + return + } + let updateTitle: Signal if let titleValue = updateValues.title { updateTitle = updatePeerTitle(account: context.account, peerId: peerId, title: titleValue) diff --git a/TelegramUI/ChannelMembersController.swift b/TelegramUI/ChannelMembersController.swift index bfb0cd50ce..6d92bf1859 100644 --- a/TelegramUI/ChannelMembersController.swift +++ b/TelegramUI/ChannelMembersController.swift @@ -181,7 +181,7 @@ private enum ChannelMembersEntry: ItemListNodeEntry { case let .addMemberInfo(theme, text): return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section) case let .peerItem(_, theme, strings, dateTimeFormat, nameDisplayOrder, participant, editing, enabled): - return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: participant.peer, presence: participant.presences[participant.peer.id], text: .presence, label: .none, editing: editing, switchValue: nil, enabled: enabled, sectionId: self.section, action: { + return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: participant.peer, presence: participant.presences[participant.peer.id], text: .presence, label: .none, editing: editing, switchValue: nil, enabled: enabled, selectable: true, sectionId: self.section, action: { arguments.openPeer(participant.peer) }, setPeerIdWithRevealedOptions: { previousId, id in arguments.setPeerIdWithRevealedOptions(previousId, id) diff --git a/TelegramUI/ChannelPermissionsController.swift b/TelegramUI/ChannelPermissionsController.swift index 0bf6cda9f7..ab27fcbee0 100644 --- a/TelegramUI/ChannelPermissionsController.swift +++ b/TelegramUI/ChannelPermissionsController.swift @@ -213,7 +213,7 @@ private enum ChannelPermissionsEntry: ItemListNodeEntry { default: break } - return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: participant.peer, presence: nil, text: text, label: .none, editing: editing, switchValue: nil, enabled: enabled, sectionId: self.section, action: canOpen ? { + return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: participant.peer, presence: nil, text: text, label: .none, editing: editing, switchValue: nil, enabled: enabled, selectable: true, sectionId: self.section, action: canOpen ? { arguments.openPeer(participant.participant) } : { arguments.openPeerInfo(participant.peer) diff --git a/TelegramUI/ChannelVisibilityController.swift b/TelegramUI/ChannelVisibilityController.swift index b9c9843e5e..d7ddb49fde 100644 --- a/TelegramUI/ChannelVisibilityController.swift +++ b/TelegramUI/ChannelVisibilityController.swift @@ -315,7 +315,7 @@ private enum ChannelVisibilityEntry: ItemListNodeEntry { if let addressName = peer.addressName { label = "t.me/" + addressName } - return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, presence: nil, text: .text(label), label: .none, editing: editing, switchValue: nil, enabled: enabled, sectionId: self.section, action: nil, setPeerIdWithRevealedOptions: { previousId, id in + return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, presence: nil, text: .text(label), label: .none, editing: editing, switchValue: nil, enabled: enabled, selectable: true, sectionId: self.section, action: nil, setPeerIdWithRevealedOptions: { previousId, id in arguments.setPeerIdWithRevealedOptions(previousId, id) }, removePeer: { peerId in arguments.revokePeerId(peerId) diff --git a/TelegramUI/ChatInterfaceStateInputPanels.swift b/TelegramUI/ChatInterfaceStateInputPanels.swift index c3fe8505b8..abae69f035 100644 --- a/TelegramUI/ChatInterfaceStateInputPanels.swift +++ b/TelegramUI/ChatInterfaceStateInputPanels.swift @@ -179,7 +179,9 @@ func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState var displayBotStartPanel = false if let _ = chatPresentationInterfaceState.botStartPayload { - displayBotStartPanel = true + if let user = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramUser, user.botInfo != nil { + displayBotStartPanel = true + } } else if let chatHistoryState = chatPresentationInterfaceState.chatHistoryState, case .loaded(true) = chatHistoryState { if let user = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramUser, user.botInfo != nil { displayBotStartPanel = true diff --git a/TelegramUI/ChatListBadgeNode.swift b/TelegramUI/ChatListBadgeNode.swift index cc56f9c1e1..dcc0bfcb2d 100644 --- a/TelegramUI/ChatListBadgeNode.swift +++ b/TelegramUI/ChatListBadgeNode.swift @@ -2,9 +2,45 @@ import Foundation import AsyncDisplayKit import Display +enum ChatListBadgeContent: Equatable { + case none + case blank + case text(NSAttributedString) + case mention + + var text: String? { + if case let .text(text) = self { + return text.string + } + return nil + } + + var isEmpty: Bool { + if case .none = self { + return true + } + return false + } +} + +private func measureString(_ string: String) -> String { + let wideChar = "8" + if string.count < 2 { + return wideChar + } else { + return string[string.startIndex ..< string.index(string.endIndex, offsetBy: -1)] + wideChar + } +} + +private let badgeFont = Font.regular(14.0) + final class ChatListBadgeNode: ASDisplayNode { private let backgroundNode: ASImageNode private let textNode: TextNode + private let measureTextNode: TextNode + + private var text: String? + private var content: ChatListBadgeContent? override init() { self.backgroundNode = ASImageNode() @@ -16,46 +52,139 @@ final class ChatListBadgeNode: ASDisplayNode { self.textNode.isUserInteractionEnabled = false self.textNode.displaysAsynchronously = true + self.measureTextNode = TextNode() + super.init() self.addSubnode(self.backgroundNode) self.addSubnode(self.textNode) } - func asyncLayout() -> (CGSize, UIImage?, NSAttributedString?) -> (CGSize, () -> Void) { + func asyncLayout() -> (CGSize, UIImage?, ChatListBadgeContent) -> (CGSize, (Bool) -> Void) { let textLayout = TextNode.asyncLayout(self.textNode) + let measureTextLayout = TextNode.asyncLayout(self.measureTextNode) - return { [weak self] boundingSize, backgroundImage, text in - let (layout, apply) = textLayout(TextNodeLayoutArguments(attributedString: text, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: boundingSize, alignment: .natural, cutout: nil, insets: UIEdgeInsets())) + let currentContent = self.content + + return { [weak self] boundingSize, backgroundImage, content in + var badgeWidth: CGFloat = 0.0 - var badgeSize: CGFloat = 0.0 - if let backgroundImage = backgroundImage { - badgeSize += max(backgroundImage.size.width, layout.size.width + 10.0) + 5.0 + var textLayoutAndApply: (TextNodeLayout, () -> TextNode)? + switch content { + case let .text(text): + textLayoutAndApply = textLayout(TextNodeLayoutArguments(attributedString: text, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: boundingSize, alignment: .natural, cutout: nil, insets: UIEdgeInsets())) + + let (measureLayout, _) = measureTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: measureString(text.string), font: badgeFont, textColor: .black), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: boundingSize, alignment: .natural, cutout: nil, insets: UIEdgeInsets())) + + badgeWidth = max(20.0, measureLayout.size.width + 10.0) + case .mention, .blank: + badgeWidth = 20.0 + case .none: + badgeWidth = 0.0 } -// if let currentMentionBadgeImage = currentMentionBadgeImage { -// if !badgeSize.isZero { -// badgeSize += currentMentionBadgeImage.size.width + 4.0 -// } else { -// badgeSize += currentMentionBadgeImage.size.width + 5.0 -// } -// } - //badgeSize = max(badgeSize, reorderInset) - - return (CGSize(width: badgeSize, height: 20.0), { + return (CGSize(width: badgeWidth, height: 20.0), { animated in if let strongSelf = self { - let _ = apply() + strongSelf.content = content + if let backgroundImage = backgroundImage { strongSelf.backgroundNode.image = backgroundImage } - strongSelf.backgroundNode.isHidden = backgroundImage == nil - let backgroundWidth = max(layout.size.width + 10.0, strongSelf.backgroundNode.image?.size.width ?? 0.0) - let backgroundFrame = CGRect(x: 0.0, y: 0.0, width: backgroundWidth, height: strongSelf.backgroundNode.image?.size.height ?? 0.0) - let badgeTextFrame = CGRect(origin: CGPoint(x: backgroundFrame.midX - layout.size.width / 2.0, y: backgroundFrame.minY + 2.0), size: layout.size) + if content == currentContent { + return + } - strongSelf.textNode.frame = badgeTextFrame + let badgeWidth = max(20.0, badgeWidth) + let previousBadgeWidth = !strongSelf.backgroundNode.frame.width.isZero ? strongSelf.backgroundNode.frame.width : badgeWidth + + var animateTextNode = false + if animated { + strongSelf.isHidden = false + + let currentIsEmpty = currentContent?.isEmpty ?? true + let nextIsEmpty = content.isEmpty + + if !nextIsEmpty { + if case .text = content { + strongSelf.textNode.alpha = 1.0 + } else { + strongSelf.textNode.alpha = 0.0 + } + } + + if currentIsEmpty && !nextIsEmpty { + strongSelf.layer.animateScale(from: 0.0001, to: 1.2, duration: 0.2, removeOnCompletion: false, completion: { [weak self] finished in + if let strongSelf = self { + strongSelf.layer.animateScale(from: 1.15, to: 1.0, duration: 0.12, removeOnCompletion: false) + } + }) + } else if !currentIsEmpty && !nextIsEmpty && currentContent?.text != content.text { + var animateScale = true + if let currentText = currentContent?.text, let currentValue = Int(currentText), let text = content.text, let value = Int(text) { + if value < currentValue { + animateScale = false + } + } + + if animateScale { + strongSelf.layer.animateScale(from: 1.0, to: 1.2, duration: 0.12, removeOnCompletion: false, completion: { [weak self] finished in + if let strongSelf = self { + strongSelf.layer.animateScale(from: 1.2, to: 1.0, duration: 0.12, removeOnCompletion: false) + } + }) + } + + var animateSnapshot = true + if let currentContent = currentContent, case .blank = currentContent { + animateSnapshot = false + } + if animateSnapshot, let snapshotView = strongSelf.textNode.view.snapshotContentTree() { + snapshotView.frame = strongSelf.textNode.frame + strongSelf.textNode.view.superview?.insertSubview(snapshotView, aboveSubview: strongSelf.textNode.view) + snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false, completion: { [weak snapshotView] _ in + snapshotView?.removeFromSuperview() + }) + snapshotView.layer.animatePosition(from: CGPoint(), to: CGPoint(x: (badgeWidth - previousBadgeWidth) / 2.0, y: -8.0), duration: 0.15, timingFunction: kCAMediaTimingFunctionEaseInEaseOut, removeOnCompletion: false, additive: true) + } + animateTextNode = true + } else if !currentIsEmpty && nextIsEmpty { + strongSelf.layer.animateScale(from: 1.0, to: 0.0001, duration: 0.12, removeOnCompletion: true, completion: { [weak self] finished in + if let strongSelf = self { + strongSelf.isHidden = true + } + }) + } + } else { + if case .none = content { + strongSelf.isHidden = true + } else { + strongSelf.isHidden = false + } + if case .text = content { + strongSelf.textNode.alpha = 1.0 + } else { + strongSelf.textNode.alpha = 0.0 + } + } + + let _ = textLayoutAndApply?.1() + + let backgroundFrame = CGRect(x: 0.0, y: 0.0, width: badgeWidth, height: strongSelf.backgroundNode.image?.size.height ?? 0.0) + if let (textLayout, _) = textLayoutAndApply { + let badgeTextFrame = CGRect(origin: CGPoint(x: backgroundFrame.midX - textLayout.size.width / 2.0, y: backgroundFrame.minY + 2.0), size: textLayout.size) + strongSelf.textNode.frame = badgeTextFrame + if animateTextNode { + strongSelf.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15) + strongSelf.textNode.layer.animatePosition(from: CGPoint(x: (previousBadgeWidth - badgeWidth) / 2.0, y: 8.0), to: CGPoint(), duration: 0.15, timingFunction: kCAMediaTimingFunctionEaseInEaseOut, removeOnCompletion: false, additive: true) + } + } strongSelf.backgroundNode.frame = backgroundFrame + + if animated && badgeWidth != previousBadgeWidth { + let previousBackgroundFrame = CGRect(x: 0.0, y: 0.0, width: previousBadgeWidth, height: backgroundFrame.height) + strongSelf.backgroundNode.layer.animateFrame(from: previousBackgroundFrame, to: backgroundFrame, duration: 0.15, timingFunction: kCAMediaTimingFunctionEaseInEaseOut) + } } }) } diff --git a/TelegramUI/ChatListController.swift b/TelegramUI/ChatListController.swift index bb43831f38..6e093d3737 100644 --- a/TelegramUI/ChatListController.swift +++ b/TelegramUI/ChatListController.swift @@ -216,16 +216,12 @@ public class ChatListController: TelegramController, KeyShortcutResponder, UIVie }) } - self.badgeDisposable = (renderedTotalUnreadCount(accountManager: context.sharedContext.accountManager, postbox: context.account.postbox) |> deliverOnMainQueue).start(next: { [weak self] count in + self.badgeDisposable = (combineLatest(renderedTotalUnreadCount(accountManager: context.sharedContext.accountManager, postbox: context.account.postbox), self.presentationDataValue.get()) |> deliverOnMainQueue).start(next: { [weak self] count, presentationData in if let strongSelf = self { if count.0 == 0 { strongSelf.tabBarItem.badgeValue = "" } else { - if count.0 > 1000 { - strongSelf.tabBarItem.badgeValue = "\(count.0 / 1000)K" - } else { - strongSelf.tabBarItem.badgeValue = "\(count.0)" - } + strongSelf.tabBarItem.badgeValue = compactNumericCountString(Int(count.0), decimalSeparator: presentationData.dateTimeFormat.decimalSeparator) } } }) diff --git a/TelegramUI/ChatListItem.swift b/TelegramUI/ChatListItem.swift index b9a5b5f2c1..db69705392 100644 --- a/TelegramUI/ChatListItem.swift +++ b/TelegramUI/ChatListItem.swift @@ -226,11 +226,12 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { let textNode: TextNode let inputActivitiesNode: ChatListInputActivitiesNode let dateNode: TextNode - let statusNode: ASImageNode let separatorNode: ASDisplayNode + let statusNode: ChatListStatusNode let badgeNode: ChatListBadgeNode + let mentionBadgeNode: ChatListBadgeNode let onlineNode: ChatListOnlineNode - let mentionBadgeNode: ASImageNode + let pinnedIconNode: ASImageNode var secretIconNode: ASImageNode? var verificationIconNode: ASImageNode? let mutedIconNode: ASImageNode @@ -352,17 +353,15 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { self.dateNode.isUserInteractionEnabled = false self.dateNode.displaysAsynchronously = true - self.statusNode = ASImageNode() - self.statusNode.displaysAsynchronously = false - self.statusNode.displayWithoutProcessing = true - + self.statusNode = ChatListStatusNode() self.badgeNode = ChatListBadgeNode() + self.mentionBadgeNode = ChatListBadgeNode() self.onlineNode = ChatListOnlineNode() - self.mentionBadgeNode = ASImageNode() - self.mentionBadgeNode.isLayerBacked = true - self.mentionBadgeNode.displaysAsynchronously = false - self.mentionBadgeNode.displayWithoutProcessing = true + self.pinnedIconNode = ASImageNode() + self.pinnedIconNode.isLayerBacked = true + self.pinnedIconNode.displaysAsynchronously = false + self.pinnedIconNode.displayWithoutProcessing = true self.mutedIconNode = ASImageNode() self.mutedIconNode.isLayerBacked = true @@ -386,6 +385,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { self.addSubnode(self.textNode) self.addSubnode(self.dateNode) self.addSubnode(self.statusNode) + self.addSubnode(self.pinnedIconNode) self.addSubnode(self.badgeNode) self.addSubnode(self.mentionBadgeNode) self.addSubnode(self.mutedIconNode) @@ -496,6 +496,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { let authorLayout = TextNode.asyncLayout(self.authorNode) let inputActivitiesLayout = self.inputActivitiesNode.asyncLayout() let badgeLayout = self.badgeNode.asyncLayout() + let mentionBadgeLayout = self.mentionBadgeNode.asyncLayout() let onlineLayout = self.onlineNode.asyncLayout() let selectableControlLayout = ItemListSelectableControlNode.asyncLayout(self.selectableControlNode) let reorderControlLayout = ItemListEditableReorderControlNode.asyncLayout(self.reorderControlNode) @@ -586,11 +587,14 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { var textAttributedString: NSAttributedString? var dateAttributedString: NSAttributedString? var titleAttributedString: NSAttributedString? - var badgeAttributedString: NSAttributedString? + var badgeContent = ChatListBadgeContent.none + var mentionBadgeContent = ChatListBadgeContent.none + var statusState = ChatListStatusNodeState.none var statusImage: UIImage? var currentBadgeBackgroundImage: UIImage? var currentMentionBadgeImage: UIImage? + var currentPinnedIconImage: UIImage? var currentMutedIconImage: UIImage? var currentVerificationIconImage: UIImage? var currentSecretIconImage: UIImage? @@ -681,12 +685,12 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { if let message = message, message.author?.id == account.peerId && !hasDraft { if message.flags.isSending && !message.isSentOrAcknowledged { - statusImage = PresentationResourcesChatList.pendingImage(item.presentationData.theme) + statusState = .clock(PresentationResourcesChatList.clockFrameImage(item.presentationData.theme), PresentationResourcesChatList.clockMinImage(item.presentationData.theme)) } else { if let combinedReadState = combinedReadState, combinedReadState.isOutgoingMessageIndexRead(message.index) { - statusImage = PresentationResourcesChatList.doubleCheckImage(item.presentationData.theme) + statusState = .read(item.presentationData.theme.chatList.checkmarkColor) } else { - statusImage = PresentationResourcesChatList.singleCheckImage(item.presentationData.theme) + statusState = .delivered(item.presentationData.theme.chatList.checkmarkColor) } } } @@ -702,14 +706,12 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { currentBadgeBackgroundImage = PresentationResourcesChatList.badgeBackgroundActive(item.presentationData.theme) badgeTextColor = theme.unreadBadgeActiveTextColor } - let unreadCountText: String - if unreadCount.count > 1000 { - unreadCountText = "\(unreadCount.count / 1000)K" + let unreadCountText = compactNumericCountString(Int(unreadCount.count), decimalSeparator: item.presentationData.dateTimeFormat.decimalSeparator) + if unreadCount.count > 0 { + badgeContent = .text(NSAttributedString(string: unreadCountText, font: badgeFont, textColor: badgeTextColor)) } else { - unreadCountText = "\(unreadCount.count)" + badgeContent = .blank } - - badgeAttributedString = NSAttributedString(string: unreadCount.count > 0 ? unreadCountText : " ", font: badgeFont, textColor: badgeTextColor) } } @@ -718,8 +720,9 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { let totalMentionCount = tagSummaryCount - actionsSummaryCount if totalMentionCount > 0 { currentMentionBadgeImage = PresentationResourcesChatList.badgeBackgroundMention(item.presentationData.theme) + mentionBadgeContent = .mention } else if item.index.pinningIndex != nil && !isAd && currentBadgeBackgroundImage == nil { - currentMentionBadgeImage = PresentationResourcesChatList.badgeBackgroundPinned(item.presentationData.theme) + currentPinnedIconImage = PresentationResourcesChatList.badgeBackgroundPinned(item.presentationData.theme) } if let notificationSettings = notificationSettings as? TelegramPeerNotificationSettings { @@ -774,18 +777,21 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { let (dateLayout, dateApply) = dateLayout(TextNodeLayoutArguments(attributedString: dateAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: rawContentRect.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) - let (badgeLayout, badgeApply) = badgeLayout(CGSize(width: rawContentRect.width, height: CGFloat.greatestFiniteMagnitude), currentBadgeBackgroundImage, badgeAttributedString) + let (badgeLayout, badgeApply) = badgeLayout(CGSize(width: rawContentRect.width, height: CGFloat.greatestFiniteMagnitude), currentBadgeBackgroundImage, badgeContent) + + let (mentionBadgeLayout, mentionBadgeApply) = mentionBadgeLayout(CGSize(width: rawContentRect.width, height: CGFloat.greatestFiniteMagnitude), currentMentionBadgeImage, mentionBadgeContent) var badgeSize: CGFloat = 0.0 - badgeSize += badgeLayout.width - if let currentMentionBadgeImage = currentMentionBadgeImage { + if !badgeLayout.width.isZero { + badgeSize += badgeLayout.width + 5.0 + } + if !mentionBadgeLayout.width.isZero { if !badgeSize.isZero { - badgeSize += currentMentionBadgeImage.size.width + 4.0 + badgeSize += badgeLayout.width + 4.0 } else { - badgeSize += currentMentionBadgeImage.size.width + 5.0 + badgeSize += badgeLayout.width + 5.0 } } - badgeSize = max(badgeSize, reorderInset) let (authorLayout, authorApply) = authorLayout(TextNodeLayoutArguments(attributedString: hideAuthor ? nil : authorAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: rawContentRect.width - badgeSize, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets(top: 2.0, left: 1.0, bottom: 2.0, right: 1.0))) @@ -851,9 +857,9 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { } let (onlineLayout, onlineApply) = onlineLayout(online) - var animateOnline = false + var animateContent = false if let currentItem = currentItem, currentItem.content.chatLocation == item.content.chatLocation { - animateOnline = true + animateContent = true } let insets = ChatListItemNode.insets(first: first, last: last, firstWithHeader: firstWithHeader) @@ -918,6 +924,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { transition.updateAlpha(node: strongSelf.dateNode, alpha: 0.0) transition.updateAlpha(node: strongSelf.badgeNode, alpha: 0.0) transition.updateAlpha(node: strongSelf.mentionBadgeNode, alpha: 0.0) + transition.updateAlpha(node: strongSelf.pinnedIconNode, alpha: 0.0) transition.updateAlpha(node: strongSelf.statusNode, alpha: 0.0) } else if let reorderControlNode = strongSelf.reorderControlNode { let _ = reorderControlSizeAndApply.1(false) @@ -931,6 +938,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { transition.updateAlpha(node: strongSelf.dateNode, alpha: 1.0) transition.updateAlpha(node: strongSelf.badgeNode, alpha: 1.0) transition.updateAlpha(node: strongSelf.mentionBadgeNode, alpha: 1.0) + transition.updateAlpha(node: strongSelf.pinnedIconNode, alpha: 1.0) transition.updateAlpha(node: strongSelf.statusNode, alpha: 1.0) } @@ -970,64 +978,59 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { let _ = textApply() let _ = authorApply() let _ = titleApply() - let _ = badgeApply() - let _ = onlineApply(animateOnline) + let _ = badgeApply(animateContent) + let _ = mentionBadgeApply(animateContent) + let _ = onlineApply(animateContent) let contentRect = rawContentRect.offsetBy(dx: editingOffset + leftInset + revealOffset, dy: 0.0) strongSelf.dateNode.frame = CGRect(origin: CGPoint(x: contentRect.origin.x + contentRect.size.width - dateLayout.size.width, y: contentRect.origin.y + 2.0), size: dateLayout.size) - if let statusImage = statusImage { - strongSelf.statusNode.image = statusImage - strongSelf.statusNode.isHidden = false - let statusSize = statusImage.size - strongSelf.statusNode.frame = CGRect(origin: CGPoint(x: contentRect.origin.x + contentRect.size.width - dateLayout.size.width - 2.0 - statusSize.width, y: contentRect.origin.y + 2.0 + floor((dateLayout.size.height - statusSize.height) / 2.0)), size: statusSize) - } else { - strongSelf.statusNode.image = nil - strongSelf.statusNode.isHidden = true - } + let statusSize = CGSize(width: 24.0, height: 24.0) + strongSelf.statusNode.frame = CGRect(origin: CGPoint(x: contentRect.origin.x + contentRect.size.width - dateLayout.size.width - statusSize.width, y: contentRect.origin.y + 2.0 - UIScreenPixel + floor((dateLayout.size.height - statusSize.height) / 2.0)), size: statusSize) + let _ = strongSelf.statusNode.transitionToState(statusState, animated: animateContent) - let badgeWidth = badgeLayout.width if let _ = currentBadgeBackgroundImage { - let badgeFrame = CGRect(x: contentRect.maxX - badgeWidth, y: contentRect.maxY - badgeLayout.height - 2.0, width: badgeWidth, height: badgeLayout.height) + let previousBadgeFrame = strongSelf.badgeNode.frame + let badgeFrame = CGRect(x: contentRect.maxX - badgeLayout.width, y: contentRect.maxY - badgeLayout.height - 2.0, width: badgeLayout.width, height: badgeLayout.height) strongSelf.badgeNode.frame = badgeFrame - } - //: CGFloat -// if let currentBadgeBackgroundImage = currentBadgeBackgroundImage { -// strongSelf.badgeBackgroundNode.image = currentBadgeBackgroundImage -// strongSelf.badgeBackgroundNode.isHidden = false -// -// badgeBackgroundWidth = max(badgeLayout.size.width + 10.0, currentBadgeBackgroundImage.size.width) -// let badgeBackgroundFrame = CGRect(x: contentRect.maxX - badgeBackgroundWidth, y: contentRect.maxY - currentBadgeBackgroundImage.size.height - 2.0, width: badgeBackgroundWidth, height: currentBadgeBackgroundImage.size.height) -// let badgeTextFrame = CGRect(origin: CGPoint(x: badgeBackgroundFrame.midX - badgeLayout.size.width / 2.0, y: badgeBackgroundFrame.minY + 2.0), size: badgeLayout.size) -// -// strongSelf.badgeTextNode.frame = badgeTextFrame -// strongSelf.badgeBackgroundNode.frame = badgeBackgroundFrame -// } else { -// badgeBackgroundWidth = 0.0 -// strongSelf.badgeBackgroundNode.image = nil -// strongSelf.badgeBackgroundNode.isHidden = true -// } - - if let currentMentionBadgeImage = currentMentionBadgeImage { - strongSelf.mentionBadgeNode.image = currentMentionBadgeImage - strongSelf.mentionBadgeNode.isHidden = false - let mentionBadgeSize = currentMentionBadgeImage.size + if animateContent && !previousBadgeFrame.width.isZero && !badgeFrame.width.isZero && badgeFrame != previousBadgeFrame { + strongSelf.badgeNode.layer.animateFrame(from: previousBadgeFrame, to: badgeFrame, duration: 0.15, timingFunction: kCAMediaTimingFunctionEaseInEaseOut) + } + } + + if currentMentionBadgeImage != nil || currentBadgeBackgroundImage != nil { + let previousBadgeFrame = strongSelf.mentionBadgeNode.frame + let mentionBadgeOffset: CGFloat - if badgeWidth.isZero { - mentionBadgeOffset = contentRect.maxX - mentionBadgeSize.width + if badgeLayout.width.isZero { + mentionBadgeOffset = contentRect.maxX - mentionBadgeLayout.width } else { - mentionBadgeOffset = contentRect.maxX - badgeWidth - 6.0 - mentionBadgeSize.width + mentionBadgeOffset = contentRect.maxX - badgeLayout.width - 6.0 - mentionBadgeLayout.height } - let badgeBackgroundWidth = mentionBadgeSize.width - let badgeBackgroundFrame = CGRect(x: mentionBadgeOffset, y: contentRect.maxY - mentionBadgeSize.height - 2.0, width: badgeBackgroundWidth, height: mentionBadgeSize.height) + let badgeFrame = CGRect(x: mentionBadgeOffset, y: contentRect.maxY - mentionBadgeLayout.height - 2.0, width: mentionBadgeLayout.height, height: mentionBadgeLayout.height) + strongSelf.mentionBadgeNode.position = badgeFrame.center + strongSelf.mentionBadgeNode.bounds = CGRect(origin: CGPoint(), size: badgeFrame.size) - strongSelf.mentionBadgeNode.frame = badgeBackgroundFrame + if animateContent && !previousBadgeFrame.width.isZero && !badgeFrame.width.isZero && badgeFrame != previousBadgeFrame { + strongSelf.mentionBadgeNode.layer.animatePosition(from: previousBadgeFrame.center, to: badgeFrame.center, duration: 0.15, timingFunction: kCAMediaTimingFunctionEaseInEaseOut) + strongSelf.mentionBadgeNode.layer.animateBounds(from: CGRect(origin: CGPoint(), size: previousBadgeFrame.size), to: CGRect(origin: CGPoint(), size: badgeFrame.size), duration: 0.15, timingFunction: kCAMediaTimingFunctionEaseInEaseOut) + } + } + + if let currentPinnedIconImage = currentPinnedIconImage { + strongSelf.pinnedIconNode.image = currentPinnedIconImage + strongSelf.pinnedIconNode.isHidden = false + + let pinnedIconSize = currentPinnedIconImage.size + let pinnedIconFrame = CGRect(x: contentRect.maxX - pinnedIconSize.width, y: contentRect.maxY - pinnedIconSize.height - 2.0, width: pinnedIconSize.width, height: pinnedIconSize.height) + + strongSelf.pinnedIconNode.frame = pinnedIconFrame } else { - strongSelf.mentionBadgeNode.image = nil - strongSelf.mentionBadgeNode.isHidden = true + strongSelf.pinnedIconNode.image = nil + strongSelf.pinnedIconNode.isHidden = true } var titleOffset: CGFloat = 0.0 @@ -1103,7 +1106,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { strongSelf.textNode.alpha = 0.0 strongSelf.authorNode.alpha = 0.0 - if animated { + if animated || animateContent { strongSelf.inputActivitiesNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15) strongSelf.textNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15) strongSelf.authorNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15) @@ -1114,7 +1117,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { strongSelf.inputActivitiesNode.alpha = 0.0 strongSelf.textNode.alpha = 1.0 strongSelf.authorNode.alpha = 1.0 - if animated { + if animated || animateContent { strongSelf.inputActivitiesNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, completion: { value in if let strongSelf = self, value { strongSelf.inputActivitiesNode.removeFromSupernode() @@ -1269,7 +1272,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { transition.updateFrame(node: self.dateNode, frame: CGRect(origin: CGPoint(x: contentRect.origin.x + contentRect.size.width - dateFrame.size.width, y: dateFrame.minY), size: dateFrame.size)) let statusFrame = self.statusNode.frame - transition.updateFrame(node: self.statusNode, frame: CGRect(origin: CGPoint(x: contentRect.origin.x + contentRect.size.width - dateFrame.size.width - 2.0 - statusFrame.size.width, y: statusFrame.minY), size: statusFrame.size)) + transition.updateFrame(node: self.statusNode, frame: CGRect(origin: CGPoint(x: contentRect.origin.x + contentRect.size.width - dateFrame.size.width - statusFrame.size.width, y: statusFrame.minY), size: statusFrame.size)) var nextTitleIconOrigin: CGFloat = contentRect.origin.x + titleFrame.size.width + 3.0 + titleOffset @@ -1286,7 +1289,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { let updatedBadgeFrame = CGRect(origin: CGPoint(x: contentRect.maxX - badgeFrame.size.width, y: contentRect.maxY - badgeFrame.size.height - 2.0), size: badgeFrame.size) transition.updateFrame(node: self.badgeNode, frame: updatedBadgeFrame) - let mentionBadgeSize = self.mentionBadgeNode.bounds.size + let mentionBadgeSize = self.pinnedIconNode.bounds.size if mentionBadgeSize != CGSize.zero { let mentionBadgeOffset: CGFloat if updatedBadgeFrame.size.width.isZero { @@ -1296,8 +1299,8 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { } let badgeBackgroundWidth = mentionBadgeSize.width - let badgeBackgroundFrame = CGRect(x: mentionBadgeOffset, y: self.mentionBadgeNode.frame.origin.y, width: badgeBackgroundWidth, height: mentionBadgeSize.height) - transition.updateFrame(node: self.mentionBadgeNode, frame: badgeBackgroundFrame) + let badgeBackgroundFrame = CGRect(x: mentionBadgeOffset, y: self.pinnedIconNode.frame.origin.y, width: badgeBackgroundWidth, height: mentionBadgeSize.height) + transition.updateFrame(node: self.pinnedIconNode, frame: badgeBackgroundFrame) } // let badgeTextFrame = self.badgeTextNode.frame diff --git a/TelegramUI/ChatListOnlineNode.swift b/TelegramUI/ChatListOnlineNode.swift index 49c6bd668e..d5f327435a 100644 --- a/TelegramUI/ChatListOnlineNode.swift +++ b/TelegramUI/ChatListOnlineNode.swift @@ -29,7 +29,7 @@ final class ChatListOnlineNode: ASDisplayNode { strongSelf.iconNode.frame = CGRect(x: 0.0, y: 0.0, width: 14.0, height: 14.0) if animated { - let initialScale: CGFloat = CGFloat((strongSelf.iconNode.value(forKeyPath: "layer.presentationLayer.transform.scale.x") as? NSNumber)?.floatValue ?? 1.0) + let initialScale: CGFloat = strongSelf.iconNode.isHidden ? 0.0 : CGFloat((strongSelf.iconNode.value(forKeyPath: "layer.presentationLayer.transform.scale.x") as? NSNumber)?.floatValue ?? 1.0) let targetScale: CGFloat = online ? 1.0 : 0.0 strongSelf.iconNode.isHidden = false strongSelf.iconNode.layer.animateScale(from: initialScale, to: targetScale, duration: 0.2, removeOnCompletion: false, completion: { [weak self] finished in diff --git a/TelegramUI/ChatListStatusNode.swift b/TelegramUI/ChatListStatusNode.swift index 85fc3e86a4..6fd75f8858 100644 --- a/TelegramUI/ChatListStatusNode.swift +++ b/TelegramUI/ChatListStatusNode.swift @@ -1,59 +1,363 @@ import Foundation import AsyncDisplayKit import Display +import LegacyComponents -enum ChatListStatusNodeState { +enum ChatListStatusNodeState: Equatable { case none - case clock - case delivered - case read - case progress(CGFloat) -} - -final class ChatListStatusNode: ASDisplayNode { - private let iconNode: ASImageNode - private let checksNode: ASImageNode - private let clockNode: ASImageNode - private let progressNode: RadialStatusNode + case clock(UIImage?, UIImage?) + case delivered(UIColor) + case read(UIColor) + case progress(UIColor, CGFloat) - override init() { - self.iconNode = ASImageNode() - self.iconNode.isLayerBacked = true - self.iconNode.displaysAsynchronously = false - self.iconNode.displayWithoutProcessing = true - - self.checksNode = ASImageNode() - self.clockNode = ASImageNode() - self.progressNode = RadialStatusNode(backgroundNodeColor: .clear) - - super.init() - - self.addSubnode(self.iconNode) - self.addSubnode(self.checksNode) - self.addSubnode(self.clockNode) - self.addSubnode(self.progressNode) - } - - func asyncLayout() -> (CGSize) -> (CGSize, (Bool) -> Void) { - return { [weak self] constrainedSize in - return (CGSize(width: 14.0, height: 14.0), { animated in - if let strongSelf = self { - strongSelf.iconNode.frame = CGRect(x: 0.0, y: 0.0, width: 14.0, height: 14.0) - - if animated { - let initialScale: CGFloat = CGFloat((strongSelf.iconNode.value(forKeyPath: "layer.presentationLayer.transform.scale.x") as? NSNumber)?.floatValue ?? 1.0) - let targetScale: CGFloat = 1.0 - strongSelf.iconNode.isHidden = false - strongSelf.iconNode.layer.animateScale(from: initialScale, to: targetScale, duration: 0.2, removeOnCompletion: false, completion: { [weak self] finished in - if let strongSelf = self, finished { - - } - }) - } else { - - } - } - }) + func contentNode() -> ChatListStatusContentNode? { + switch self { + case .none: + return nil + case let .clock(frameImage, minImage): + return ChatListStatusClockNode(frameImage: frameImage, minImage: minImage) + case let .delivered(color): + return ChatListStatusChecksNode(color: color) + case let .read(color): + return ChatListStatusChecksNode(color: color) + case let .progress(color, progress): + return ChatListStatusProgressNode(color: color, progress: progress) } } } + +private let transitionDuration = 0.2 + +class ChatListStatusContentNode: ASDisplayNode { + override init() { + super.init() + + self.isOpaque = false + } + + func updateWithState(_ state: ChatListStatusNodeState, animated: Bool) { + + } + + func animateOut(to: ChatListStatusNodeState, completion: @escaping () -> Void) { + self.layer.animateAlpha(from: 1.0, to: 0.0, duration: transitionDuration, removeOnCompletion: false, completion: { _ in + completion() + }) + } + + func animateIn(from: ChatListStatusNodeState) { + self.layer.animateAlpha(from: 0.0, to: 1.0, duration: transitionDuration) + } +} + +final class ChatListStatusNode: ASDisplayNode { + private(set) var state: ChatListStatusNodeState = .none + + private var contentNode: ChatListStatusContentNode? + private var nextContentNode: ChatListStatusContentNode? + + public func transitionToState(_ state: ChatListStatusNodeState, animated: Bool = false, completion: @escaping () -> Void = {}) -> Bool { + if self.state != state { + let currentState = self.state + self.state = state + + let contentNode = state.contentNode() + if contentNode?.classForCoder != self.contentNode?.classForCoder { + contentNode?.updateWithState(state, animated: animated) + self.transitionToContentNode(contentNode, state: state, fromState: currentState, animated: animated, completion: completion) + } else { + self.contentNode?.updateWithState(state, animated: animated) + } + return true + } else { + completion() + return false + } + } + + private func transitionToContentNode(_ node: ChatListStatusContentNode?, state: ChatListStatusNodeState, fromState: ChatListStatusNodeState, animated: Bool, completion: @escaping () -> Void) { + if let previousContentNode = self.contentNode { + if !animated { + previousContentNode.removeFromSupernode() + self.contentNode = node + if let contentNode = self.contentNode { + self.addSubnode(contentNode) + } + } else { + self.contentNode = node + if let contentNode = self.contentNode { + self.addSubnode(contentNode) + contentNode.frame = self.bounds + if self.isNodeLoaded { + contentNode.animateIn(from: fromState) + contentNode.layout() + } + } + previousContentNode.animateOut(to: state) { + previousContentNode.removeFromSupernode() + } + } + } else { + self.contentNode = node + if let contentNode = self.contentNode { + contentNode.frame = self.bounds + self.addSubnode(contentNode) + if self.isNodeLoaded { + contentNode.layout() + } + } + } + } + + override public func layout() { + if let contentNode = self.contentNode { + contentNode.frame = self.bounds + } + } +} + +class ChatListStatusClockNode: ChatListStatusContentNode { + private var clockFrameNode: ASImageNode + private var clockMinNode: ASImageNode + + init(frameImage: UIImage?, minImage: UIImage?) { + self.clockFrameNode = ASImageNode() + self.clockMinNode = ASImageNode() + + super.init() + + self.clockFrameNode.image = frameImage + self.clockMinNode.image = minImage + + self.addSubnode(self.clockFrameNode) + self.addSubnode(self.clockMinNode) + } + + override func updateWithState(_ state: ChatListStatusNodeState, animated: Bool) { + if case let .clock(frameImage, minImage) = state { + self.clockFrameNode.image = frameImage + self.clockMinNode.image = minImage + } + } + + override func didEnterHierarchy() { + super.didEnterHierarchy() + + maybeAddRotationAnimation(self.clockFrameNode.layer, duration: 6.0) + maybeAddRotationAnimation(self.clockMinNode.layer, duration: 1.0) + } + + override func didExitHierarchy() { + super.didExitHierarchy() + + self.clockFrameNode.layer.removeAllAnimations() + self.clockMinNode.layer.removeAllAnimations() + } + + override func layout() { + super.layout() + + let bounds = self.bounds + if let frameImage = self.clockFrameNode.image { + self.clockFrameNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((bounds.width - frameImage.size.width) / 2.0), y: floorToScreenPixels((bounds.height - frameImage.size.height) / 2.0)), size: frameImage.size) + } + if let minImage = self.clockMinNode.image { + self.clockMinNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((bounds.width - minImage.size.width) / 2.0), y: floorToScreenPixels((bounds.height - minImage.size.height) / 2.0)), size: minImage.size) + } + } +} + +private func maybeAddRotationAnimation(_ layer: CALayer, duration: Double) { + if let _ = layer.animation(forKey: "clockFrameAnimation") { + return + } + + let basicAnimation = CABasicAnimation(keyPath: "transform.rotation.z") + basicAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) + basicAnimation.duration = duration + basicAnimation.fromValue = NSNumber(value: Float(0.0)) + basicAnimation.toValue = NSNumber(value: Float(Double.pi * 2.0)) + basicAnimation.repeatCount = Float.infinity + basicAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) + basicAnimation.beginTime = 1.0 + layer.add(basicAnimation, forKey: "clockFrameAnimation") +} + +private final class StatusChecksNodeParameters: NSObject { + let color: UIColor + let progress: CGFloat + + init(color: UIColor, progress: CGFloat) { + self.color = color + self.progress = progress + + super.init() + } +} + +private class ChatListStatusChecksNode: ChatListStatusContentNode { + private var state: ChatListStatusNodeState? + + var color: UIColor { + didSet { + self.setNeedsDisplay() + } + } + + private var effectiveProgress: CGFloat = 1.0 { + didSet { + self.setNeedsDisplay() + } + } + + init(color: UIColor) { + self.color = color + + super.init() + } + + func animateProgress(from: CGFloat, to: CGFloat) { + self.pop_removeAllAnimations() + + let animation = POPBasicAnimation() + animation.property = POPAnimatableProperty.property(withName: "progress", initializer: { property in + property?.readBlock = { node, values in + values?.pointee = (node as! ChatListStatusChecksNode).effectiveProgress + } + property?.writeBlock = { node, values in + (node as! ChatListStatusChecksNode).effectiveProgress = values!.pointee + } + property?.threshold = 0.01 + }) as! POPAnimatableProperty + animation.fromValue = from as NSNumber + animation.toValue = to as NSNumber + animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) + animation.duration = 0.2 + self.pop_add(animation, forKey: "progress") + } + + override func drawParameters(forAsyncLayer layer: _ASDisplayLayer) -> NSObjectProtocol? { + return StatusChecksNodeParameters(color: self.color, progress: self.effectiveProgress) + } + + @objc override class func draw(_ bounds: CGRect, withParameters parameters: Any?, isCancelled: () -> Bool, isRasterizing: Bool) { + let context = UIGraphicsGetCurrentContext()! + + if !isRasterizing { + context.setBlendMode(.copy) + context.setFillColor(UIColor.clear.cgColor) + context.fill(bounds) + } + + guard let parameters = parameters as? StatusChecksNodeParameters else { + return + } + + let progress = parameters.progress + + context.setStrokeColor(parameters.color.cgColor) + context.setLineWidth(1.0 + UIScreenPixel) + context.setLineCap(.round) + context.setLineJoin(.round) + context.setMiterLimit(10.0) + + context.saveGState() + var s1 = CGPoint(x: 9.0, y: 13.0) + var s2 = CGPoint(x: 5.0, y: 13.0) + let p1 = CGPoint(x: 3.5, y: 3.5) + let p2 = CGPoint(x: 7.5 - UIScreenPixel, y: -8.0) + + let check1FirstSegment: CGFloat = max(0.0, min(1.0, progress * 3.0)) + let check2FirstSegment: CGFloat = max(0.0, min(1.0, (progress - 1.0) * 3.0)) + + let firstProgress = max(0.0, min(1.0, progress)) + let secondProgress = max(0.0, min(1.0, progress - 1.0)) + + let scale: CGFloat = 1.2 + context.translateBy(x: 16.0, y: 13.0) + context.scaleBy(x: scale - abs((scale - 1.0) * (firstProgress - 0.5) / 0.5), y: scale - abs((scale - 1.0) * (firstProgress - 0.5) / 0.5)) + s1 = s1.offsetBy(dx: -16.0, dy: -13.0) + + if !check1FirstSegment.isZero { + if check1FirstSegment < 1.0 { + context.move(to: CGPoint(x: s1.x + p1.x * check1FirstSegment, y: s1.y + p1.y * check1FirstSegment)) + context.addLine(to: s1) + } else { + let secondSegment = (min(1.0, progress) - 0.33) * 1.5 + context.move(to: CGPoint(x: s1.x + p1.x + p2.x * secondSegment, y: s1.y + p1.y + p2.y * secondSegment)) + context.addLine(to: CGPoint(x: s1.x + p1.x, y: s1.y + p1.y)) + context.addLine(to: CGPoint(x: s1.x + p1.x * min(1.0, check2FirstSegment), y: s1.y + p1.y * min(1.0, check2FirstSegment))) + } + } + context.strokePath() + + context.restoreGState() + + context.translateBy(x: 12.0, y: 13.0) + context.scaleBy(x: scale - abs((scale - 1.0) * (secondProgress - 0.5) / 0.5), y: scale - abs((scale - 1.0) * (secondProgress - 0.5) / 0.5)) + s2 = s2.offsetBy(dx: -12.0, dy: -13.0) + + if !check2FirstSegment.isZero { + if check2FirstSegment < 1.0 { + context.move(to: CGPoint(x: s2.x + p1.x * check2FirstSegment, y: s2.y + p1.y * check2FirstSegment)) + context.addLine(to: s2) + } else { + let secondSegment = (max(0.0, (progress - 1.0)) - 0.33) * 1.5 + context.move(to: CGPoint(x: s2.x + p1.x + p2.x * secondSegment, y: s2.y + p1.y + p2.y * secondSegment)) + context.addLine(to: CGPoint(x: s2.x + p1.x, y: s2.y + p1.y)) + context.addLine(to: s2) + } + } + context.strokePath() + } + + override func updateWithState(_ state: ChatListStatusNodeState, animated: Bool) { + if let previousState = self.state, case .delivered = previousState, case .read = state, animated { + self.animateProgress(from: 1.0, to: 2.0) + } + if !animated { + if case .delivered = state { + self.effectiveProgress = 1.0 + } else if case .read = state { + self.effectiveProgress = 2.0 + } + } + self.state = state + } + + override func animateIn(from: ChatListStatusNodeState) { + if let state = self.state, case .delivered = state { + self.animateProgress(from: 0.0, to: 1.0) + } else { + super.animateIn(from: from) + } + } +} + +private class ChatListStatusProgressNode: ChatListStatusContentNode { + private let statusNode: RadialStatusNode + + init(color: UIColor, progress: CGFloat) { + self.statusNode = RadialStatusNode(backgroundNodeColor: .clear) + + super.init() + + self.statusNode.transitionToState(.progress(color: color, lineWidth: 1.0, value: progress, cancelEnabled: false)) + + self.addSubnode(self.statusNode) + } + + override func updateWithState(_ state: ChatListStatusNodeState, animated: Bool) { + if case let .progress(color, progress) = state { + self.statusNode.transitionToState(.progress(color: color, lineWidth: 1.0, value: progress, cancelEnabled: false), animated: animated, completion: {}) + } + } + + override func layout() { + super.layout() + + let bounds = self.bounds + let size = CGSize(width: 12.0, height: 12.0) + self.statusNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((bounds.width - size.width) / 2.0), y: floorToScreenPixels((bounds.height - size.height) / 2.0)), size: size) + } +} diff --git a/TelegramUI/ChatListTypingNode.swift b/TelegramUI/ChatListTypingNode.swift index 22fe4a2051..231352c987 100644 --- a/TelegramUI/ChatListTypingNode.swift +++ b/TelegramUI/ChatListTypingNode.swift @@ -31,6 +31,8 @@ final class ChatListInputActivitiesNode: ASDisplayNode { } } + let lightColor = color.withAlphaComponent(0.85) + if activities.count == 1 { if activities[0].0.id == peerId { let text: String @@ -56,15 +58,15 @@ final class ChatListInputActivitiesNode: ASDisplayNode { switch activities[0].1 { case .typingText: - state = .typingText(string, color) + state = .typingText(string, lightColor) case .recordingVoice: - state = .recordingVoice(string, color) + state = .recordingVoice(string, lightColor) case .recordingInstantVideo: - state = .recordingVideo(string, color) + state = .recordingVideo(string, lightColor) case .uploadingFile, .uploadingInstantVideo, .uploadingPhoto, .uploadingVideo: - state = .uploading(string, color) + state = .uploading(string, lightColor) case .playingGame: - state = .playingGame(string, color) + state = .playingGame(string, lightColor) } } else { let text: String @@ -95,15 +97,15 @@ final class ChatListInputActivitiesNode: ASDisplayNode { switch activities[0].1 { case .typingText: - state = .typingText(string, color) + state = .typingText(string, lightColor) case .recordingVoice: - state = .recordingVoice(string, color) + state = .recordingVoice(string, lightColor) case .recordingInstantVideo: - state = .recordingVideo(string, color) + state = .recordingVideo(string, lightColor) case .uploadingFile, .uploadingInstantVideo, .uploadingPhoto, .uploadingVideo: - state = .uploading(string, color) + state = .uploading(string, lightColor) case .playingGame: - state = .playingGame(string, color) + state = .playingGame(string, lightColor) } } } else { @@ -114,7 +116,7 @@ final class ChatListInputActivitiesNode: ASDisplayNode { } else { string = NSAttributedString(string: strings.DialogList_MultipleTypingSuffix(activities.count).0, font: textFont, textColor: color) } - state = .typingText(string, color) + state = .typingText(string, lightColor) } } diff --git a/TelegramUI/ChatMessageStickerItemNode.swift b/TelegramUI/ChatMessageStickerItemNode.swift index 797272171e..6e22be4fea 100644 --- a/TelegramUI/ChatMessageStickerItemNode.swift +++ b/TelegramUI/ChatMessageStickerItemNode.swift @@ -21,11 +21,15 @@ class ChatMessageStickerItemNode: ChatMessageItemView { private var deliveryFailedNode: ChatMessageDeliveryFailedNode? private var shareButtonNode: HighlightableButtonNode? - var telegramFile: TelegramMediaFile? private let fetchDisposable = MetaDisposable() + private var appliedForwardInfo: (Peer?, String?)? + + private var forwardInfoNode: ChatMessageForwardInfoNode? + private var forwardBackgroundNode: ASImageNode? + private var viaBotNode: TextNode? private let dateAndStatusNode: ChatMessageDateAndStatusNode private var replyInfoNode: ChatMessageReplyInfoNode? @@ -101,7 +105,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { if self.telegramFile == nil && !item.message.text.isEmpty && item.message.text.containsOnlyEmoji && item.presentationData.largeEmoji { var textFont = item.presentationData.messageFont - let emojis = item.message.text.emojis + let emojis = item.message.text.emojiString switch emojis.count { case 1: textFont = item.presentationData.messageEmojiFont1 @@ -144,6 +148,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { } var textLayoutAndApply: (TextNodeLayout, () -> TextNode)? + var isEmoji = false if !item.message.text.isEmpty && item.message.text.containsOnlyEmoji && item.presentationData.largeEmoji { var textFont = item.presentationData.messageFont let emojis = item.message.text.emojis @@ -159,9 +164,10 @@ class ChatMessageStickerItemNode: ChatMessageItemView { } let attributedText = NSAttributedString(string: item.message.text, font: textFont, textColor: .black) - textLayoutAndApply = textLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: 120.0, height: 60.0), alignment: .natural)) + textLayoutAndApply = textLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: 180.0, height: 90.0), alignment: .natural)) - imageSize = CGSize(width: textLayoutAndApply!.0.size.width, height: max(90.0, textLayoutAndApply!.0.size.height)) + imageSize = CGSize(width: textLayoutAndApply!.0.size.width, height: textLayoutAndApply!.0.size.height) + isEmoji = true } let avatarInset: CGFloat @@ -310,7 +316,6 @@ class ChatMessageStickerItemNode: ChatMessageItemView { } } if let replyAttribute = attribute as? ReplyMessageAttribute, let replyMessage = item.message.associatedMessages[replyAttribute.messageId] { - replyInfoApply = makeReplyInfoLayout(item.presentationData, item.presentationData.strings, item.context, .standalone, replyMessage, CGSize(width: availableWidth, height: CGFloat.greatestFiniteMagnitude)) } else if let attribute = attribute as? ReplyMarkupMessageAttribute, attribute.flags.contains(.inline), !attribute.rows.isEmpty { replyMarkup = attribute @@ -371,6 +376,9 @@ class ChatMessageStickerItemNode: ChatMessageItemView { } var layoutSize = CGSize(width: params.width, height: contentHeight) + if isEmoji && !incoming { + layoutSize.height += dateAndStatusSize.height + } if let actionButtonsSizeAndApply = actionButtonsSizeAndApply { layoutSize.height += actionButtonsSizeAndApply.0.height } @@ -408,7 +416,15 @@ class ChatMessageStickerItemNode: ChatMessageItemView { } dateAndStatusApply(false) - transition.updateFrame(node: strongSelf.dateAndStatusNode, frame: CGRect(origin: CGPoint(x: max(displayLeftInset, updatedImageFrame.maxX - dateAndStatusSize.width - 4.0), y: updatedImageFrame.maxY - dateAndStatusSize.height - 16.0), size: dateAndStatusSize)) + var dateOffset: CGPoint = CGPoint(x: dateAndStatusSize.width + 4.0, y: dateAndStatusSize.height + 16.0) + if isEmoji { + if incoming { + dateOffset.x = 12.0 + } else { + dateOffset.y = 12.0 + } + } + transition.updateFrame(node: strongSelf.dateAndStatusNode, frame: CGRect(origin: CGPoint(x: max(displayLeftInset, updatedImageFrame.maxX - dateOffset.x), y: updatedImageFrame.maxY - dateOffset.y), size: dateAndStatusSize)) if let updatedReplyBackgroundNode = updatedReplyBackgroundNode { if strongSelf.replyBackgroundNode == nil { diff --git a/TelegramUI/ChatPlayingActivityContentNode.swift b/TelegramUI/ChatPlayingActivityContentNode.swift index 95c322359a..0ec60eba1f 100644 --- a/TelegramUI/ChatPlayingActivityContentNode.swift +++ b/TelegramUI/ChatPlayingActivityContentNode.swift @@ -43,8 +43,8 @@ private class ChatPlayingActivityIndicatorNode: ChatTitleActivityIndicatorNode { return } - let dotsColor = parameters.color.withAlphaComponent(0.5) - context.setFillColor(dotsColor.cgColor) + let color = parameters.color.withAlphaComponent(parameters.color.alpha * 0.5) + context.setFillColor(color.cgColor) let distance: CGFloat = 4.0 var origin = CGPoint(x: (bounds.size.width - distance * 2.0) / 2.0 + 4.0, y: bounds.size.height / 2.0 + 1.0) diff --git a/TelegramUI/ChatRecentActionsFilterController.swift b/TelegramUI/ChatRecentActionsFilterController.swift index b5c351ec63..276c093085 100644 --- a/TelegramUI/ChatRecentActionsFilterController.swift +++ b/TelegramUI/ChatRecentActionsFilterController.swift @@ -224,7 +224,7 @@ private enum ChatRecentActionsFilterEntry: ItemListNodeEntry { case .member: peerText = strings.ChatAdmins_AdminLabel.capitalized } - return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: participant.peer, presence: nil, text: .text(peerText), label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), switchValue: ItemListPeerItemSwitch(value: checked, style: .check), enabled: true, sectionId: self.section, action: { + return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: participant.peer, presence: nil, text: .text(peerText), label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), switchValue: ItemListPeerItemSwitch(value: checked, style: .check), enabled: true, selectable: true, sectionId: self.section, action: { arguments.toggleAdmin(participant.peer.id) }, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in }) diff --git a/TelegramUI/ChatTitleActivityNode.swift b/TelegramUI/ChatTitleActivityNode.swift index 1dfe5c82e6..92c5cf3e0c 100644 --- a/TelegramUI/ChatTitleActivityNode.swift +++ b/TelegramUI/ChatTitleActivityNode.swift @@ -86,6 +86,9 @@ class ChatTitleActivityNode: ASDisplayNode { if case let .info(_, fromType) = fromState, case let .info(_, toType) = state, fromType == toType { animation = .none } + if case .typingText = fromState, case .typingText = state { + animation = .none + } self.contentNode = node if let contentNode = self.contentNode { diff --git a/TelegramUI/ChatTypingActivityContentNode.swift b/TelegramUI/ChatTypingActivityContentNode.swift index 0f33646368..59359e1dc0 100644 --- a/TelegramUI/ChatTypingActivityContentNode.swift +++ b/TelegramUI/ChatTypingActivityContentNode.swift @@ -70,7 +70,8 @@ private class ChatTypingActivityIndicatorNode: ChatTitleActivityIndicatorNode { radius = (max(minDiameter, radius) - minDiameter) / (maxDiameter - minDiameter) radius = radius * 1.5 - var dotsColor = parameters.color.withAlphaComponent(radius * deltaAlpha + minAlpha) + let initialAlpha = parameters.color.alpha + var dotsColor = parameters.color.withAlphaComponent((radius * deltaAlpha + minAlpha) * initialAlpha) context.setFillColor(dotsColor.cgColor) context.fillEllipse(in: CGRect(x: leftPadding - minDiameter / 2.0 - radius / 2.0, y: topPadding - minDiameter / 2.0 - radius / 2.0, width: minDiameter + radius, height: minDiameter + radius)) @@ -79,7 +80,7 @@ private class ChatTypingActivityIndicatorNode: ChatTitleActivityIndicatorNode { radius = (max(minDiameter, radius) - minDiameter) / (maxDiameter - minDiameter) radius = radius * 1.5 - dotsColor = parameters.color.withAlphaComponent(radius * deltaAlpha + minAlpha) + dotsColor = parameters.color.withAlphaComponent((radius * deltaAlpha + minAlpha) * initialAlpha) context.setFillColor(dotsColor.cgColor) context.fillEllipse(in: CGRect(x: leftPadding + distance - minDiameter / 2.0 - radius / 2.0, y: topPadding - minDiameter / 2.0 - radius / 2.0, width: minDiameter + radius, height: minDiameter + radius)) @@ -88,7 +89,7 @@ private class ChatTypingActivityIndicatorNode: ChatTitleActivityIndicatorNode { radius = (max(minDiameter, radius) - minDiameter) / (maxDiameter - minDiameter) radius = radius * 1.5 - dotsColor = parameters.color.withAlphaComponent(radius * deltaAlpha + minAlpha) + dotsColor = parameters.color.withAlphaComponent((radius * deltaAlpha + minAlpha) * initialAlpha) context.setFillColor(dotsColor.cgColor) context.fillEllipse(in: CGRect(x: leftPadding + distance * 2.0 - minDiameter / 2.0 - radius / 2.0, y: topPadding - minDiameter / 2.0 - radius / 2.0, width: minDiameter + radius, height: minDiameter + radius)) diff --git a/TelegramUI/ChatUploadingActivityContentNode.swift b/TelegramUI/ChatUploadingActivityContentNode.swift index 2a8084059e..3cfa056801 100644 --- a/TelegramUI/ChatUploadingActivityContentNode.swift +++ b/TelegramUI/ChatUploadingActivityContentNode.swift @@ -51,8 +51,8 @@ private class ChatUploadingActivityIndicatorNode: ChatTitleActivityIndicatorNode let size = CGSize(width: 13.0, height: 4.0) let radius: CGFloat = 1.25 - var dotsColor = parameters.color.withAlphaComponent(0.3) - context.setFillColor(dotsColor.cgColor) + var color = parameters.color.withAlphaComponent(parameters.color.alpha * 0.3) + context.setFillColor(color.cgColor) var path = UIBezierPath(roundedRect: CGRect(origin: origin, size: size), cornerRadius: radius) path.fill(with: .normal, alpha: 1.0) @@ -60,8 +60,8 @@ private class ChatUploadingActivityIndicatorNode: ChatTitleActivityIndicatorNode let progress = interpolate(from: 0.0, to: size.width * 2.0, value: parameters.progress) - dotsColor = parameters.color - context.setFillColor(dotsColor.cgColor) + color = parameters.color + context.setFillColor(color.cgColor) path = UIBezierPath(roundedRect: CGRect(origin: origin.offsetBy(dx: -size.width + progress, dy: 0.0), size: size), cornerRadius: radius) path.fill(with: .normal, alpha: 1.0) diff --git a/TelegramUI/CreateGroupController.swift b/TelegramUI/CreateGroupController.swift index 22099d6f75..2c7390c40c 100644 --- a/TelegramUI/CreateGroupController.swift +++ b/TelegramUI/CreateGroupController.swift @@ -150,7 +150,7 @@ private enum CreateGroupEntry: ItemListNodeEntry { arguments.changeProfilePhoto() }) case let .member(_, theme, strings, dateTimeFormat, nameDisplayOrder, peer, presence): - return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, presence: presence, text: .presence, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), switchValue: nil, enabled: true, sectionId: self.section, action: nil, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in }) + return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, presence: presence, text: .presence, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), switchValue: nil, enabled: true, selectable: true, sectionId: self.section, action: nil, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in }) } } } diff --git a/TelegramUI/DefaultDarkPresentationTheme.swift b/TelegramUI/DefaultDarkPresentationTheme.swift index ef000dfc15..092fbc0582 100644 --- a/TelegramUI/DefaultDarkPresentationTheme.swift +++ b/TelegramUI/DefaultDarkPresentationTheme.swift @@ -121,7 +121,7 @@ private let chatList = PresentationThemeChatList( itemHighlightedBackgroundColor: UIColor(rgb: 0x191919), itemSelectedBackgroundColor: UIColor(rgb: 0x191919), titleColor: UIColor(rgb: 0xffffff), - secretTitleColor: UIColor(rgb: 0xb2b2b2), //!!! + secretTitleColor: secretColor, //!!! dateTextColor: UIColor(rgb: 0x8e8e93), authorNameColor: UIColor(rgb: 0xffffff), messageTextColor: UIColor(rgb: 0x8e8e93), diff --git a/TelegramUI/EditSettingsController.swift b/TelegramUI/EditSettingsController.swift index aa0fea3075..2bdc5e8e63 100644 --- a/TelegramUI/EditSettingsController.swift +++ b/TelegramUI/EditSettingsController.swift @@ -328,6 +328,8 @@ func editSettingsController(context: AccountContext, currentName: ItemListAvatar var changeProfilePhotoImpl: (() -> Void)? var getNavigationController: (() -> NavigationController?)? + + let hapticFeedback = HapticFeedback() let arguments = EditSettingsItemArguments(context: context, accountManager: accountManager, avatarAndNameInfoContext: avatarAndNameInfoContext, avatarTapAction: { var updating = false @@ -356,6 +358,7 @@ func editSettingsController(context: AccountContext, currentName: ItemListAvatar }, saveEditingState: { var updateName: ItemListAvatarAndNameInfoItemName? var updateBio: String? + var failed = false updateState { state in if state.editingName != currentName { updateName = state.editingName @@ -363,12 +366,24 @@ func editSettingsController(context: AccountContext, currentName: ItemListAvatar if state.editingBioText != currentBioText { updateBio = state.editingBioText } + + if (updateBio?.count ?? 0) > 70 { + failed = true + return state + } + if updateName != nil || updateBio != nil { return state.withUpdatedUpdatingName(state.editingName).withUpdatedUpdatingBioText(true) } else { return state } } + + guard !failed else { + hapticFeedback.error() + return + } + var updateNameSignal: Signal = .complete() if let updateName = updateName, case let .personName(firstName, lastName) = updateName { updateNameSignal = updateAccountPeerName(account: context.account, firstName: firstName, lastName: lastName) diff --git a/TelegramUI/FeedGroupingControllerNode.swift b/TelegramUI/FeedGroupingControllerNode.swift index 8797e0f971..e5ca5d3729 100644 --- a/TelegramUI/FeedGroupingControllerNode.swift +++ b/TelegramUI/FeedGroupingControllerNode.swift @@ -170,7 +170,7 @@ private enum FeedGroupingEntry: ItemListNodeEntry { case let .groupHeader(theme, text): return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section) case let .peer(theme, strings, dateTimeFormat, nameDisplayOrder, _, peer, value): - return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, presence: nil, text: .none, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), switchValue: ItemListPeerItemSwitch(value: value, style: .standard), enabled: true, sectionId: self.section, action: nil, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in }, toggleUpdated: { value in + return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, presence: nil, text: .none, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), switchValue: ItemListPeerItemSwitch(value: value, style: .standard), enabled: true, selectable: true, sectionId: self.section, action: nil, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in }, toggleUpdated: { value in arguments.togglePeer(peer, value) }) case let .ungroup(theme, text): diff --git a/TelegramUI/FetchCachedRepresentations.swift b/TelegramUI/FetchCachedRepresentations.swift index ab39966d65..f0556668b5 100644 --- a/TelegramUI/FetchCachedRepresentations.swift +++ b/TelegramUI/FetchCachedRepresentations.swift @@ -688,7 +688,7 @@ private func fetchLargeEmojiRepresentation(account: Account, resource: MediaReso let font = Font.regular(resource.fontSize) let stringAttributes = [NSAttributedStringKey.font: font] var emojiSize = nsString.size(withAttributes: stringAttributes) - emojiSize = CGSize(width: ceil(emojiSize.width), height: ceil(emojiSize.height)) + emojiSize = CGSize(width: ceil(emojiSize.width) + 2.0, height: ceil(emojiSize.height) + 2.0) let image = generateImage(emojiSize, contextGenerator: { size, context in let bounds = CGRect(origin: CGPoint(), size: size) diff --git a/TelegramUI/GroupInfoController.swift b/TelegramUI/GroupInfoController.swift index 30e3e42ebb..51d0b77992 100644 --- a/TelegramUI/GroupInfoController.swift +++ b/TelegramUI/GroupInfoController.swift @@ -142,7 +142,7 @@ private enum GroupInfoEntry: ItemListNodeEntry { case administrators(PresentationTheme, String, String) case permissions(PresentationTheme, String, String) case addMember(PresentationTheme, String, editing: Bool) - case member(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, index: Int, peerId: PeerId, peer: Peer, participant: RenderedChannelParticipant?, presence: PeerPresence?, memberStatus: GroupInfoMemberStatus, editing: ItemListPeerItemEditing, revealActions: [ParticipantRevealAction], enabled: Bool) + case member(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, index: Int, peerId: PeerId, peer: Peer, participant: RenderedChannelParticipant?, presence: PeerPresence?, memberStatus: GroupInfoMemberStatus, editing: ItemListPeerItemEditing, revealActions: [ParticipantRevealAction], enabled: Bool, selectable: Bool) case leave(PresentationTheme, String) var section: ItemListSectionId { @@ -303,8 +303,8 @@ private enum GroupInfoEntry: ItemListNodeEntry { } else { return false } - case let .member(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsNameDisplayOrder, lhsIndex, lhsPeerId, lhsPeer, lhsParticipant, lhsPresence, lhsMemberStatus, lhsEditing, lhsActions, lhsEnabled): - if case let .member(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsNameDisplayOrder, rhsIndex, rhsPeerId, rhsPeer, rhsParticipant, rhsPresence, rhsMemberStatus, rhsEditing, rhsActions, rhsEnabled) = rhs { + case let .member(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsNameDisplayOrder, lhsIndex, lhsPeerId, lhsPeer, lhsParticipant, lhsPresence, lhsMemberStatus, lhsEditing, lhsActions, lhsEnabled, lhsSelectable): + if case let .member(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsNameDisplayOrder, rhsIndex, rhsPeerId, rhsPeer, rhsParticipant, rhsPresence, rhsMemberStatus, rhsEditing, rhsActions, rhsEnabled, rhsSelectable) = rhs { if lhsTheme !== rhsTheme { return false } @@ -348,6 +348,9 @@ private enum GroupInfoEntry: ItemListNodeEntry { if lhsEnabled != rhsEnabled { return false } + if lhsSelectable != rhsSelectable { + return false + } return true } else { return false @@ -357,7 +360,7 @@ private enum GroupInfoEntry: ItemListNodeEntry { var stableId: GroupEntryStableId { switch self { - case let .member(_, _, _, _, _, peerId, _, _, _, _, _, _, _): + case let .member(_, _, _, _, _, peerId, _, _, _, _, _, _, _, _): return .peer(peerId) default: return .index(self.sortIndex) @@ -394,7 +397,7 @@ private enum GroupInfoEntry: ItemListNodeEntry { return 15 case .addMember: return 17 - case let .member(_, _, _, _, index, _, _, _, _, _, _, _, _): + case let .member(_, _, _, _, index, _, _, _, _, _, _, _, _, _): return 20 + index case .leave: return 100000 + 1 @@ -469,7 +472,7 @@ private enum GroupInfoEntry: ItemListNodeEntry { return ItemListDisclosureItem(theme: theme, icon: PresentationResourcesChat.groupInfoAdminsIcon(theme), title: title, label: text, sectionId: self.section, style: .blocks, action: { arguments.openAdministrators() }) - case let .member(theme, strings, dateTimeFormat, nameDisplayOrder, _, _, peer, participant, presence, memberStatus, editing, actions, enabled): + case let .member(theme, strings, dateTimeFormat, nameDisplayOrder, _, _, peer, participant, presence, memberStatus, editing, actions, enabled, selectable): let label: String? switch memberStatus { case .admin: @@ -494,8 +497,8 @@ private enum GroupInfoEntry: ItemListNodeEntry { } })) } - return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.context.account, peer: peer, presence: presence, text: .presence, label: label == nil ? .none : .text(label!), editing: editing, revealOptions: ItemListPeerItemRevealOptions(options: options), switchValue: nil, enabled: enabled, sectionId: self.section, action: { - if let infoController = peerInfoController(context: arguments.context, peer: peer) { + return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.context.account, peer: peer, presence: presence, text: .presence, label: label == nil ? .none : .text(label!), editing: editing, revealOptions: ItemListPeerItemRevealOptions(options: options), switchValue: nil, enabled: enabled, selectable: selectable, sectionId: self.section, action: { + if let infoController = peerInfoController(context: arguments.context, peer: peer), selectable { arguments.pushController(infoController) } }, setPeerIdWithRevealedOptions: { peerId, fromPeerId in @@ -973,7 +976,7 @@ private func groupInfoEntries(account: Account, presentationData: PresentationDa peerActions.append(ParticipantRevealAction(type: .destructive, title: presentationData.strings.Common_Delete, action: .remove)) } - entries.append(GroupInfoEntry.member(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, index: i, peerId: peer.id, peer: peer, participant: RenderedChannelParticipant(participant: participant, peer: peer), presence: peerPresences[peer.id], memberStatus: memberStatus, editing: ItemListPeerItemEditing(editable: canRemoveParticipant(account: account, isAdmin: canEditMembers, participantId: peer.id, invitedBy: sortedParticipants[i].invitedBy), editing: state.editingState != nil && canRemoveAnyMember, revealed: state.peerIdWithRevealedOptions == peer.id), revealActions: peerActions, enabled: !disabledPeerIds.contains(peer.id))) + entries.append(GroupInfoEntry.member(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, index: i, peerId: peer.id, peer: peer, participant: RenderedChannelParticipant(participant: participant, peer: peer), presence: peerPresences[peer.id], memberStatus: memberStatus, editing: ItemListPeerItemEditing(editable: canRemoveParticipant(account: account, isAdmin: canEditMembers, participantId: peer.id, invitedBy: sortedParticipants[i].invitedBy), editing: state.editingState != nil && canRemoveAnyMember, revealed: state.peerIdWithRevealedOptions == peer.id), revealActions: peerActions, enabled: !disabledPeerIds.contains(peer.id), selectable: peer.id != account.peerId)) } } } else if let channel = view.peers[view.peerId] as? TelegramChannel, let cachedChannelData = view.cachedData as? CachedChannelData, let memberCount = cachedChannelData.participantsSummary.memberCount { @@ -1095,7 +1098,7 @@ private func groupInfoEntries(account: Account, presentationData: PresentationDa peerActions.append(ParticipantRevealAction(type: .destructive, title: presentationData.strings.Common_Delete, action: .remove)) } - entries.append(GroupInfoEntry.member(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, index: i, peerId: participant.peer.id, peer: participant.peer, participant: participant, presence: participant.presences[participant.peer.id], memberStatus: memberStatus, editing: ItemListPeerItemEditing(editable: !peerActions.isEmpty, editing: state.editingState != nil && canRemoveAnyMember, revealed: state.peerIdWithRevealedOptions == participant.peer.id), revealActions: peerActions, enabled: true)) + entries.append(GroupInfoEntry.member(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, index: i, peerId: participant.peer.id, peer: participant.peer, participant: participant, presence: participant.presences[participant.peer.id], memberStatus: memberStatus, editing: ItemListPeerItemEditing(editable: !peerActions.isEmpty, editing: state.editingState != nil && canRemoveAnyMember, revealed: state.peerIdWithRevealedOptions == participant.peer.id), revealActions: peerActions, enabled: true, selectable: participant.peer.id != account.peerId)) } } @@ -1892,6 +1895,8 @@ public func groupInfoController(context: AccountContext, peerId originalPeerId: let searchContext = GroupMembersSearchContext(context: context, peerId: originalPeerId) + let hapticFeedback = HapticFeedback() + let globalNotificationsKey: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.globalNotifications])) let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, statePromise.get(), peerView.get(), context.account.postbox.combinedView(keys: [globalNotificationsKey]), channelMembersPromise.get()) |> map { presentationData, state, view, combinedView, channelMembers -> (ItemListControllerState, (ItemListNodeState, GroupInfoEntry.ItemGenerationArguments)) in @@ -1942,15 +1947,25 @@ public func groupInfoController(context: AccountContext, peerId originalPeerId: } else { rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Done), style: .bold, enabled: doneEnabled, action: { var updateValues: (title: String?, description: String?) = (nil, nil) + var failed = false updateState { state in updateValues = valuesRequiringUpdate(state: state, view: view) if updateValues.0 != nil || updateValues.1 != nil { + if (updateValues.description?.count ?? 0) > 255 { + failed = true + return state + } return state.withUpdatedSavingData(true) } else { return state.withUpdatedEditingState(nil) } } + guard !failed else { + hapticFeedback.error() + return + } + let updateTitle: Signal if let titleValue = updateValues.title { updateTitle = updatePeerTitle(account: context.account, peerId: view.peerId, title: titleValue) diff --git a/TelegramUI/GroupsInCommonController.swift b/TelegramUI/GroupsInCommonController.swift index ccd0e53ed3..9c9b5d5e7f 100644 --- a/TelegramUI/GroupsInCommonController.swift +++ b/TelegramUI/GroupsInCommonController.swift @@ -100,7 +100,7 @@ private enum GroupsInCommonEntry: ItemListNodeEntry { func item(_ arguments: GroupsInCommonControllerArguments) -> ListViewItem { switch self { case let .peerItem(_, theme, strings, dateTimeFormat, nameDisplayOrder, peer): - return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, presence: nil, text: .none, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), switchValue: nil, enabled: true, sectionId: self.section, action: { + return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, presence: nil, text: .none, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), switchValue: nil, enabled: true, selectable: true, sectionId: self.section, action: { arguments.openPeer(peer.id) }, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in diff --git a/TelegramUI/ItemListPeerItem.swift b/TelegramUI/ItemListPeerItem.swift index 7f9f730c91..126d14de46 100644 --- a/TelegramUI/ItemListPeerItem.swift +++ b/TelegramUI/ItemListPeerItem.swift @@ -82,6 +82,7 @@ final class ItemListPeerItem: ListViewItem, ItemListItem { let revealOptions: ItemListPeerItemRevealOptions? let switchValue: ItemListPeerItemSwitch? let enabled: Bool + let selectable: Bool let sectionId: ItemListSectionId let action: (() -> Void)? let setPeerIdWithRevealedOptions: (PeerId?, PeerId?) -> Void @@ -91,7 +92,7 @@ final class ItemListPeerItem: ListViewItem, ItemListItem { let hasTopGroupInset: Bool let tag: ItemListItemTag? - init(theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, account: Account, peer: Peer, aliasHandling: ItemListPeerItemAliasHandling = .standard, nameColor: ItemListPeerItemNameColor = .primary, nameStyle: ItemListPeerItemNameStyle = .distinctBold, presence: PeerPresence?, text: ItemListPeerItemText, label: ItemListPeerItemLabel, editing: ItemListPeerItemEditing, revealOptions: ItemListPeerItemRevealOptions? = nil, switchValue: ItemListPeerItemSwitch?, enabled: Bool, sectionId: ItemListSectionId, action: (() -> Void)?, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, removePeer: @escaping (PeerId) -> Void, toggleUpdated: ((Bool) -> Void)? = nil, hasTopStripe: Bool = true, hasTopGroupInset: Bool = true, tag: ItemListItemTag? = nil) { + init(theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, account: Account, peer: Peer, aliasHandling: ItemListPeerItemAliasHandling = .standard, nameColor: ItemListPeerItemNameColor = .primary, nameStyle: ItemListPeerItemNameStyle = .distinctBold, presence: PeerPresence?, text: ItemListPeerItemText, label: ItemListPeerItemLabel, editing: ItemListPeerItemEditing, revealOptions: ItemListPeerItemRevealOptions? = nil, switchValue: ItemListPeerItemSwitch?, enabled: Bool, selectable: Bool, sectionId: ItemListSectionId, action: (() -> Void)?, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, removePeer: @escaping (PeerId) -> Void, toggleUpdated: ((Bool) -> Void)? = nil, hasTopStripe: Bool = true, hasTopGroupInset: Bool = true, tag: ItemListItemTag? = nil) { self.theme = theme self.strings = strings self.dateTimeFormat = dateTimeFormat @@ -108,6 +109,7 @@ final class ItemListPeerItem: ListViewItem, ItemListItem { self.revealOptions = revealOptions self.switchValue = switchValue self.enabled = enabled + self.selectable = selectable self.sectionId = sectionId self.action = action self.setPeerIdWithRevealedOptions = setPeerIdWithRevealedOptions @@ -156,8 +158,6 @@ final class ItemListPeerItem: ListViewItem, ItemListItem { } } - var selectable: Bool = true - func selected(listView: ListView){ listView.clearHighlightAnimated(true) self.action?() diff --git a/TelegramUI/NotificationExceptionControllerNode.swift b/TelegramUI/NotificationExceptionControllerNode.swift index f21c8a3c55..3a9b2ab0e4 100644 --- a/TelegramUI/NotificationExceptionControllerNode.swift +++ b/TelegramUI/NotificationExceptionControllerNode.swift @@ -384,7 +384,7 @@ private enum NotificationExceptionEntry : ItemListNodeEntry { arguments.selectPeer() }) case let .peer(_, peer, theme, strings, dateTimeFormat, nameDisplayOrder, value, _, revealed, editing): - return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, presence: nil, text: .text(value), label: .none, editing: ItemListPeerItemEditing(editable: true, editing: editing, revealed: revealed), switchValue: nil, enabled: true, sectionId: self.section, action: { + return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, presence: nil, text: .text(value), label: .none, editing: ItemListPeerItemEditing(editable: true, editing: editing, revealed: revealed), switchValue: nil, enabled: true, selectable: true, sectionId: self.section, action: { arguments.openPeer(peer) }, setPeerIdWithRevealedOptions: { peerId, fromPeerId in arguments.updateRevealedPeerId(peerId) diff --git a/TelegramUI/PresentationResourceKey.swift b/TelegramUI/PresentationResourceKey.swift index 07b30b4e56..4e8badc591 100644 --- a/TelegramUI/PresentationResourceKey.swift +++ b/TelegramUI/PresentationResourceKey.swift @@ -59,6 +59,8 @@ enum PresentationResourceKey: Int32 { case chatListLockTopUnlockedImage case chatListLockBottomUnlockedImage case chatListPending + case chatListClockFrame + case chatListClockMin case chatListSingleCheck case chatListDoubleCheck case chatListBadgeBackgroundActive diff --git a/TelegramUI/PresentationResourcesChatList.swift b/TelegramUI/PresentationResourcesChatList.swift index 41da02c712..e5b9707ceb 100644 --- a/TelegramUI/PresentationResourcesChatList.swift +++ b/TelegramUI/PresentationResourcesChatList.swift @@ -32,6 +32,27 @@ private func generateBadgeBackgroundImage(theme: PresentationTheme, active: Bool })?.stretchableImage(withLeftCapWidth: 10, topCapHeight: 10) } +private func generateClockFrameImage(color: UIColor) -> UIImage? { + return generateImage(CGSize(width: 11.0, height: 11.0), contextGenerator: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + context.setStrokeColor(color.cgColor) + context.setFillColor(color.cgColor) + let strokeWidth: CGFloat = 1.0 + context.setLineWidth(strokeWidth) + context.strokeEllipse(in: CGRect(x: strokeWidth / 2.0, y: strokeWidth / 2.0, width: size.width - strokeWidth, height: size.height - strokeWidth)) + context.fill(CGRect(x: (11.0 - strokeWidth) / 2.0, y: strokeWidth * 3.0, width: strokeWidth, height: 11.0 / 2.0 - strokeWidth * 3.0)) + }) +} + +private func generateClockMinImage(color: UIColor) -> UIImage? { + return generateImage(CGSize(width: 11.0, height: 11.0), contextGenerator: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + context.setFillColor(color.cgColor) + let strokeWidth: CGFloat = 1.0 + context.fill(CGRect(x: (11.0 - strokeWidth) / 2.0, y: (11.0 - strokeWidth) / 2.0, width: 11.0 / 2.0 - strokeWidth, height: strokeWidth)) + }) +} + enum RecentStatusOnlineIconState { case regular case highlighted @@ -66,6 +87,18 @@ struct PresentationResourcesChatList { }) } + static func clockFrameImage(_ theme: PresentationTheme) -> UIImage? { + return theme.image(PresentationResourceKey.chatListClockFrame.rawValue, { theme in + return generateClockFrameImage(color: theme.chatList.pendingIndicatorColor) + }) + } + + static func clockMinImage(_ theme: PresentationTheme) -> UIImage? { + return theme.image(PresentationResourceKey.chatListClockMin.rawValue, { theme in + return generateClockMinImage(color: theme.chatList.pendingIndicatorColor) + }) + } + static func lockTopLockedImage(_ theme: PresentationTheme) -> UIImage? { return theme.image(PresentationResourceKey.chatListLockTopLockedImage.rawValue, { theme in return generateImage(CGSize(width: 7.0, height: 6.0), rotatedContext: { size, context in diff --git a/TelegramUI/PresentationStrings.swift b/TelegramUI/PresentationStrings.swift index d7ff4b7218..7d22cc57d7 100644 --- a/TelegramUI/PresentationStrings.swift +++ b/TelegramUI/PresentationStrings.swift @@ -2328,9 +2328,9 @@ public final class PresentationStrings { public var Bot_Unblock: String { return self._s[2022]! } public var TextFormat_Italic: String { return self._s[2023]! } public var WallpaperSearch_ColorPink: String { return self._s[2024]! } - public var Weekday_Wednesday: String { return self._s[2025]! } - public var Settings_About_Help: String { return self._s[2026]! } - public var SearchImages_Title: String { return self._s[2027]! } + public var Settings_About_Help: String { return self._s[2025]! } + public var SearchImages_Title: String { return self._s[2026]! } + public var Weekday_Wednesday: String { return self._s[2027]! } public var Conversation_ClousStorageInfo_Description1: String { return self._s[2028]! } public var ExplicitContent_AlertTitle: String { return self._s[2029]! } public func Time_PreciseDate_m5(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { @@ -2787,1421 +2787,1422 @@ public final class PresentationStrings { public var Notification_CallOutgoing: String { return self._s[2472]! } public var PrivacySettings_PasscodeAndFaceId: String { return self._s[2473]! } public var Call_RecordingDisabledMessage: String { return self._s[2474]! } - public var Conversation_PressVolumeButtonForSound: String { return self._s[2475]! } - public var PrivacyLastSeenSettings_CustomHelp: String { return self._s[2476]! } - public var Channel_EditAdmin_PermissionAddAdmins: String { return self._s[2477]! } - public var Date_DialogDateFormat: String { return self._s[2478]! } - public var WallpaperColors_SetCustomColor: String { return self._s[2479]! } - public var Notifications_InAppNotifications: String { return self._s[2480]! } + public var Message_Game: String { return self._s[2475]! } + public var Conversation_PressVolumeButtonForSound: String { return self._s[2476]! } + public var PrivacyLastSeenSettings_CustomHelp: String { return self._s[2477]! } + public var Channel_EditAdmin_PermissionAddAdmins: String { return self._s[2478]! } + public var Date_DialogDateFormat: String { return self._s[2479]! } + public var WallpaperColors_SetCustomColor: String { return self._s[2480]! } + public var Notifications_InAppNotifications: String { return self._s[2481]! } public func Channel_Management_RemovedBy(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2481]!, self._r[2481]!, [_0]) + return formatWithArgumentRanges(self._s[2482]!, self._r[2482]!, [_0]) } public func Settings_ApplyProxyAlert(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2482]!, self._r[2482]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2483]!, self._r[2483]!, [_1, _2]) } - public var NewContact_Title: String { return self._s[2483]! } + public var NewContact_Title: String { return self._s[2484]! } public func AutoDownloadSettings_UpToForAll(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2484]!, self._r[2484]!, [_0]) + return formatWithArgumentRanges(self._s[2485]!, self._r[2485]!, [_0]) } - public var Conversation_ViewContactDetails: String { return self._s[2485]! } + public var Conversation_ViewContactDetails: String { return self._s[2486]! } public func PUSH_CHANNEL_MESSAGE_CONTACT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2487]!, self._r[2487]!, [_1]) + return formatWithArgumentRanges(self._s[2488]!, self._r[2488]!, [_1]) } - public var Checkout_NewCard_CardholderNameTitle: String { return self._s[2488]! } - public var Passport_Identity_ExpiryDateNone: String { return self._s[2489]! } - public var PrivacySettings_Title: String { return self._s[2490]! } - public var Conversation_SilentBroadcastTooltipOff: String { return self._s[2493]! } - public var GroupRemoved_UsersSectionTitle: String { return self._s[2494]! } - public var Contacts_PhoneNumber: String { return self._s[2495]! } - public var Map_ShowPlaces: String { return self._s[2497]! } - public var ChatAdmins_Title: String { return self._s[2498]! } - public var InstantPage_Reference: String { return self._s[2500]! } + public var Checkout_NewCard_CardholderNameTitle: String { return self._s[2489]! } + public var Passport_Identity_ExpiryDateNone: String { return self._s[2490]! } + public var PrivacySettings_Title: String { return self._s[2491]! } + public var Conversation_SilentBroadcastTooltipOff: String { return self._s[2494]! } + public var GroupRemoved_UsersSectionTitle: String { return self._s[2495]! } + public var Contacts_PhoneNumber: String { return self._s[2496]! } + public var Map_ShowPlaces: String { return self._s[2498]! } + public var ChatAdmins_Title: String { return self._s[2499]! } + public var InstantPage_Reference: String { return self._s[2501]! } public func PUSH_CHAT_MESSAGE_FWD(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2501]!, self._r[2501]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2502]!, self._r[2502]!, [_1, _2]) } - public var Camera_FlashOff: String { return self._s[2502]! } - public var Watch_UserInfo_Block: String { return self._s[2503]! } - public var ChatSettings_Stickers: String { return self._s[2504]! } - public var ChatSettings_DownloadInBackground: String { return self._s[2505]! } + public var Camera_FlashOff: String { return self._s[2503]! } + public var Watch_UserInfo_Block: String { return self._s[2504]! } + public var ChatSettings_Stickers: String { return self._s[2505]! } + public var ChatSettings_DownloadInBackground: String { return self._s[2506]! } public func UserInfo_BlockConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2506]!, self._r[2506]!, [_0]) + return formatWithArgumentRanges(self._s[2507]!, self._r[2507]!, [_0]) } - public var Settings_ViewPhoto: String { return self._s[2507]! } - public var Login_CheckOtherSessionMessages: String { return self._s[2508]! } - public var AutoDownloadSettings_Cellular: String { return self._s[2509]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsExceptions: String { return self._s[2510]! } + public var Settings_ViewPhoto: String { return self._s[2508]! } + public var Login_CheckOtherSessionMessages: String { return self._s[2509]! } + public var AutoDownloadSettings_Cellular: String { return self._s[2510]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsExceptions: String { return self._s[2511]! } public func Target_InviteToGroupConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2512]!, self._r[2512]!, [_0]) + return formatWithArgumentRanges(self._s[2513]!, self._r[2513]!, [_0]) } - public var Privacy_DeleteDrafts: String { return self._s[2513]! } - public var Wallpaper_SetCustomBackgroundInfo: String { return self._s[2514]! } + public var Privacy_DeleteDrafts: String { return self._s[2514]! } + public var Wallpaper_SetCustomBackgroundInfo: String { return self._s[2515]! } public func LastSeen_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2515]!, self._r[2515]!, [_0]) + return formatWithArgumentRanges(self._s[2516]!, self._r[2516]!, [_0]) } - public var DialogList_SavedMessagesHelp: String { return self._s[2516]! } - public var DialogList_SavedMessages: String { return self._s[2517]! } - public var GroupInfo_UpgradeButton: String { return self._s[2518]! } - public var DialogList_Pin: String { return self._s[2520]! } + public var DialogList_SavedMessagesHelp: String { return self._s[2517]! } + public var DialogList_SavedMessages: String { return self._s[2518]! } + public var GroupInfo_UpgradeButton: String { return self._s[2519]! } + public var DialogList_Pin: String { return self._s[2521]! } public func ForwardedAuthors2(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2521]!, self._r[2521]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2522]!, self._r[2522]!, [_0, _1]) } public func Login_PhoneGenericEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2522]!, self._r[2522]!, [_0]) + return formatWithArgumentRanges(self._s[2523]!, self._r[2523]!, [_0]) } - public var Notification_Exceptions_AlwaysOn: String { return self._s[2523]! } - public var UserInfo_NotificationsDisable: String { return self._s[2524]! } - public var Paint_Outlined: String { return self._s[2525]! } - public var Activity_PlayingGame: String { return self._s[2526]! } - public var SearchImages_NoImagesFound: String { return self._s[2527]! } - public var SocksProxySetup_ProxyType: String { return self._s[2528]! } - public var AppleWatch_ReplyPresetsHelp: String { return self._s[2530]! } - public var Conversation_ContextMenuCancelSending: String { return self._s[2531]! } - public var Settings_AppLanguage: String { return self._s[2532]! } - public var TwoStepAuth_ResetAccountHelp: String { return self._s[2533]! } - public var Common_ChoosePhoto: String { return self._s[2534]! } - public var CallFeedback_ReasonEcho: String { return self._s[2535]! } + public var Notification_Exceptions_AlwaysOn: String { return self._s[2524]! } + public var UserInfo_NotificationsDisable: String { return self._s[2525]! } + public var Paint_Outlined: String { return self._s[2526]! } + public var Activity_PlayingGame: String { return self._s[2527]! } + public var SearchImages_NoImagesFound: String { return self._s[2528]! } + public var SocksProxySetup_ProxyType: String { return self._s[2529]! } + public var AppleWatch_ReplyPresetsHelp: String { return self._s[2531]! } + public var Conversation_ContextMenuCancelSending: String { return self._s[2532]! } + public var Settings_AppLanguage: String { return self._s[2533]! } + public var TwoStepAuth_ResetAccountHelp: String { return self._s[2534]! } + public var Common_ChoosePhoto: String { return self._s[2535]! } + public var CallFeedback_ReasonEcho: String { return self._s[2536]! } public func PUSH_PINNED_AUDIO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2536]!, self._r[2536]!, [_1]) + return formatWithArgumentRanges(self._s[2537]!, self._r[2537]!, [_1]) } - public var Privacy_Calls_AlwaysAllow: String { return self._s[2537]! } - public var Activity_UploadingVideo: String { return self._s[2538]! } - public var ChannelInfo_DeleteChannelConfirmation: String { return self._s[2539]! } - public var NetworkUsageSettings_Wifi: String { return self._s[2540]! } - public var Channel_BanUser_PermissionReadMessages: String { return self._s[2541]! } - public var Checkout_PayWithTouchId: String { return self._s[2542]! } - public var Wallpaper_ResetWallpapersConfirmation: String { return self._s[2543]! } + public var Privacy_Calls_AlwaysAllow: String { return self._s[2538]! } + public var Activity_UploadingVideo: String { return self._s[2539]! } + public var ChannelInfo_DeleteChannelConfirmation: String { return self._s[2540]! } + public var NetworkUsageSettings_Wifi: String { return self._s[2541]! } + public var Channel_BanUser_PermissionReadMessages: String { return self._s[2542]! } + public var Checkout_PayWithTouchId: String { return self._s[2543]! } + public var Wallpaper_ResetWallpapersConfirmation: String { return self._s[2544]! } public func PUSH_LOCKED_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2545]!, self._r[2545]!, [_1]) + return formatWithArgumentRanges(self._s[2546]!, self._r[2546]!, [_1]) } - public var Notifications_ExceptionsNone: String { return self._s[2546]! } + public var Notifications_ExceptionsNone: String { return self._s[2547]! } public func Message_ForwardedMessageShort(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2547]!, self._r[2547]!, [_0]) + return formatWithArgumentRanges(self._s[2548]!, self._r[2548]!, [_0]) } public func PUSH_PINNED_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2548]!, self._r[2548]!, [_1]) + return formatWithArgumentRanges(self._s[2549]!, self._r[2549]!, [_1]) } - public var AuthSessions_IncompleteAttempts: String { return self._s[2550]! } - public var Passport_Address_Region: String { return self._s[2553]! } - public var ChatList_DeleteChat: String { return self._s[2554]! } - public var LogoutOptions_ClearCacheTitle: String { return self._s[2555]! } - public var PhotoEditor_TiltShift: String { return self._s[2556]! } - public var Settings_FAQ_URL: String { return self._s[2557]! } - public var Passport_Language_sl: String { return self._s[2558]! } - public var Settings_PrivacySettings: String { return self._s[2560]! } - public var SharedMedia_TitleLink: String { return self._s[2561]! } - public var Passport_Identity_TypePassportUploadScan: String { return self._s[2562]! } - public var Settings_SetProfilePhoto: String { return self._s[2563]! } - public var Channel_About_Help: String { return self._s[2564]! } - public var Contacts_PermissionsEnable: String { return self._s[2565]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsAlert: String { return self._s[2566]! } - public var AttachmentMenu_SendAsFiles: String { return self._s[2567]! } - public var CallFeedback_ReasonInterruption: String { return self._s[2569]! } - public var Passport_Address_AddTemporaryRegistration: String { return self._s[2570]! } - public var AutoDownloadSettings_AutodownloadVideos: String { return self._s[2571]! } - public var ChatSettings_AutoDownloadSettings_Delimeter: String { return self._s[2572]! } - public var PrivacySettings_DeleteAccountTitle: String { return self._s[2573]! } - public var AccessDenied_VideoMessageCamera: String { return self._s[2575]! } - public var Map_OpenInYandexMaps: String { return self._s[2577]! } - public var PhotoEditor_SaturationTool: String { return self._s[2578]! } + public var AuthSessions_IncompleteAttempts: String { return self._s[2551]! } + public var Passport_Address_Region: String { return self._s[2554]! } + public var ChatList_DeleteChat: String { return self._s[2555]! } + public var LogoutOptions_ClearCacheTitle: String { return self._s[2556]! } + public var PhotoEditor_TiltShift: String { return self._s[2557]! } + public var Settings_FAQ_URL: String { return self._s[2558]! } + public var Passport_Language_sl: String { return self._s[2559]! } + public var Settings_PrivacySettings: String { return self._s[2561]! } + public var SharedMedia_TitleLink: String { return self._s[2562]! } + public var Passport_Identity_TypePassportUploadScan: String { return self._s[2563]! } + public var Settings_SetProfilePhoto: String { return self._s[2564]! } + public var Channel_About_Help: String { return self._s[2565]! } + public var Contacts_PermissionsEnable: String { return self._s[2566]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsAlert: String { return self._s[2567]! } + public var AttachmentMenu_SendAsFiles: String { return self._s[2568]! } + public var CallFeedback_ReasonInterruption: String { return self._s[2570]! } + public var Passport_Address_AddTemporaryRegistration: String { return self._s[2571]! } + public var AutoDownloadSettings_AutodownloadVideos: String { return self._s[2572]! } + public var ChatSettings_AutoDownloadSettings_Delimeter: String { return self._s[2573]! } + public var PrivacySettings_DeleteAccountTitle: String { return self._s[2574]! } + public var AccessDenied_VideoMessageCamera: String { return self._s[2576]! } + public var Map_OpenInYandexMaps: String { return self._s[2578]! } + public var PhotoEditor_SaturationTool: String { return self._s[2579]! } public func PUSH_MESSAGE_STICKER(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2579]!, self._r[2579]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2580]!, self._r[2580]!, [_1, _2]) } - public var Notification_Exceptions_NewException_NotificationHeader: String { return self._s[2580]! } - public var Appearance_TextSize: String { return self._s[2581]! } + public var Notification_Exceptions_NewException_NotificationHeader: String { return self._s[2581]! } + public var Appearance_TextSize: String { return self._s[2582]! } public func LOCAL_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2582]!, self._r[2582]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[2583]!, self._r[2583]!, [_1, "\(_2)"]) } - public var Channel_Username_InvalidTooShort: String { return self._s[2584]! } + public var Channel_Username_InvalidTooShort: String { return self._s[2585]! } public func PUSH_CHAT_MESSAGE_GAME(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2585]!, self._r[2585]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2586]!, self._r[2586]!, [_1, _2, _3]) } - public var Passport_PassportInformation: String { return self._s[2588]! } - public var WatchRemote_AlertTitle: String { return self._s[2589]! } - public var Privacy_GroupsAndChannels_NeverAllow: String { return self._s[2590]! } - public var ConvertToSupergroup_HelpText: String { return self._s[2592]! } + public var Passport_PassportInformation: String { return self._s[2589]! } + public var WatchRemote_AlertTitle: String { return self._s[2590]! } + public var Privacy_GroupsAndChannels_NeverAllow: String { return self._s[2591]! } + public var ConvertToSupergroup_HelpText: String { return self._s[2593]! } public func Time_MonthOfYear_m7(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2593]!, self._r[2593]!, [_0]) + return formatWithArgumentRanges(self._s[2594]!, self._r[2594]!, [_0]) } public func PUSH_PHONE_CALL_REQUEST(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2594]!, self._r[2594]!, [_1]) + return formatWithArgumentRanges(self._s[2595]!, self._r[2595]!, [_1]) } - public var Privacy_GroupsAndChannels_CustomHelp: String { return self._s[2595]! } - public var TwoStepAuth_RecoveryCodeInvalid: String { return self._s[2597]! } - public var AccessDenied_CameraDisabled: String { return self._s[2598]! } + public var Privacy_GroupsAndChannels_CustomHelp: String { return self._s[2596]! } + public var TwoStepAuth_RecoveryCodeInvalid: String { return self._s[2598]! } + public var AccessDenied_CameraDisabled: String { return self._s[2599]! } public func Channel_Username_UsernameIsAvailable(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2599]!, self._r[2599]!, [_0]) + return formatWithArgumentRanges(self._s[2600]!, self._r[2600]!, [_0]) } - public var PhotoEditor_ContrastTool: String { return self._s[2602]! } + public var PhotoEditor_ContrastTool: String { return self._s[2603]! } public func PUSH_PINNED_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2603]!, self._r[2603]!, [_1]) + return formatWithArgumentRanges(self._s[2604]!, self._r[2604]!, [_1]) } - public var DialogList_Draft: String { return self._s[2604]! } - public var Privacy_TopPeersDelete: String { return self._s[2606]! } - public var LoginPassword_PasswordPlaceholder: String { return self._s[2607]! } - public var Passport_Identity_TypeIdentityCardUploadScan: String { return self._s[2608]! } - public var WebSearch_RecentSectionClear: String { return self._s[2609]! } - public var Watch_ChatList_NoConversationsTitle: String { return self._s[2611]! } - public var Common_Done: String { return self._s[2613]! } - public var AuthSessions_EmptyText: String { return self._s[2614]! } - public var Conversation_ShareBotContactConfirmation: String { return self._s[2615]! } - public var Tour_Title5: String { return self._s[2616]! } + public var DialogList_Draft: String { return self._s[2605]! } + public var Privacy_TopPeersDelete: String { return self._s[2607]! } + public var LoginPassword_PasswordPlaceholder: String { return self._s[2608]! } + public var Passport_Identity_TypeIdentityCardUploadScan: String { return self._s[2609]! } + public var WebSearch_RecentSectionClear: String { return self._s[2610]! } + public var Watch_ChatList_NoConversationsTitle: String { return self._s[2612]! } + public var Common_Done: String { return self._s[2614]! } + public var AuthSessions_EmptyText: String { return self._s[2615]! } + public var Conversation_ShareBotContactConfirmation: String { return self._s[2616]! } + public var Tour_Title5: String { return self._s[2617]! } public func Map_DirectionsDriveEta(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2617]!, self._r[2617]!, [_0]) + return formatWithArgumentRanges(self._s[2618]!, self._r[2618]!, [_0]) } - public var ApplyLanguage_UnsufficientDataTitle: String { return self._s[2618]! } - public var Conversation_LinkDialogSave: String { return self._s[2619]! } - public var GroupInfo_ActionRestrict: String { return self._s[2620]! } - public var Checkout_Title: String { return self._s[2621]! } - public var Channel_AdminLog_CanChangeInfo: String { return self._s[2624]! } - public var Notification_RenamedGroup: String { return self._s[2625]! } - public var Checkout_PayWithFaceId: String { return self._s[2626]! } - public var Channel_BanList_BlockedTitle: String { return self._s[2627]! } - public var SettingsSearch_Synonyms_Notifications_InAppNotificationsSound: String { return self._s[2629]! } - public var Checkout_WebConfirmation_Title: String { return self._s[2630]! } - public var Notifications_MessageNotificationsAlert: String { return self._s[2631]! } - public var Profile_AddToExisting: String { return self._s[2633]! } + public var ApplyLanguage_UnsufficientDataTitle: String { return self._s[2619]! } + public var Conversation_LinkDialogSave: String { return self._s[2620]! } + public var GroupInfo_ActionRestrict: String { return self._s[2621]! } + public var Checkout_Title: String { return self._s[2622]! } + public var Channel_AdminLog_CanChangeInfo: String { return self._s[2625]! } + public var Notification_RenamedGroup: String { return self._s[2626]! } + public var Checkout_PayWithFaceId: String { return self._s[2627]! } + public var Channel_BanList_BlockedTitle: String { return self._s[2628]! } + public var SettingsSearch_Synonyms_Notifications_InAppNotificationsSound: String { return self._s[2630]! } + public var Checkout_WebConfirmation_Title: String { return self._s[2631]! } + public var Notifications_MessageNotificationsAlert: String { return self._s[2632]! } + public var Profile_AddToExisting: String { return self._s[2634]! } public func Profile_CreateEncryptedChatOutdatedError(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2634]!, self._r[2634]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2635]!, self._r[2635]!, [_0, _1]) } - public var Cache_Files: String { return self._s[2636]! } - public var Permissions_PrivacyPolicy: String { return self._s[2637]! } - public var SocksProxySetup_ConnectAndSave: String { return self._s[2638]! } - public var UserInfo_NotificationsDefaultDisabled: String { return self._s[2639]! } - public var AutoDownloadSettings_TypeContacts: String { return self._s[2641]! } - public var Calls_NoCallsPlaceholder: String { return self._s[2643]! } - public var Channel_Username_RevokeExistingUsernamesInfo: String { return self._s[2644]! } - public var Notifications_ExceptionsGroupPlaceholder: String { return self._s[2646]! } + public var Cache_Files: String { return self._s[2637]! } + public var Permissions_PrivacyPolicy: String { return self._s[2638]! } + public var SocksProxySetup_ConnectAndSave: String { return self._s[2639]! } + public var UserInfo_NotificationsDefaultDisabled: String { return self._s[2640]! } + public var AutoDownloadSettings_TypeContacts: String { return self._s[2642]! } + public var Calls_NoCallsPlaceholder: String { return self._s[2644]! } + public var Channel_Username_RevokeExistingUsernamesInfo: String { return self._s[2645]! } + public var Notifications_ExceptionsGroupPlaceholder: String { return self._s[2647]! } public func PUSH_CHAT_MESSAGE_INVOICE(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2647]!, self._r[2647]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2648]!, self._r[2648]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsSound: String { return self._s[2648]! } - public var Passport_FieldAddressHelp: String { return self._s[2649]! } - public var Privacy_GroupsAndChannels_InviteToChannelMultipleError: String { return self._s[2650]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsSound: String { return self._s[2649]! } + public var Passport_FieldAddressHelp: String { return self._s[2650]! } + public var Privacy_GroupsAndChannels_InviteToChannelMultipleError: String { return self._s[2651]! } public func Login_TermsOfService_ProceedBot(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2651]!, self._r[2651]!, [_0]) + return formatWithArgumentRanges(self._s[2652]!, self._r[2652]!, [_0]) } - public var Channel_AdminLog_EmptyTitle: String { return self._s[2652]! } - public var Privacy_Calls_NeverAllow_Title: String { return self._s[2654]! } - public var Login_UnknownError: String { return self._s[2655]! } - public var Group_UpgradeNoticeText2: String { return self._s[2657]! } - public var Watch_Compose_AddContact: String { return self._s[2658]! } - public var Web_Error: String { return self._s[2659]! } - public var Gif_Search: String { return self._s[2660]! } - public var Profile_MessageLifetime1h: String { return self._s[2661]! } - public var CheckoutInfo_ReceiverInfoEmailPlaceholder: String { return self._s[2662]! } - public var Channel_Username_CheckingUsername: String { return self._s[2663]! } - public var CallFeedback_ReasonSilentRemote: String { return self._s[2664]! } - public var AutoDownloadSettings_TypeChannels: String { return self._s[2665]! } - public var Channel_AboutItem: String { return self._s[2666]! } - public var Privacy_GroupsAndChannels_AlwaysAllow_Placeholder: String { return self._s[2668]! } - public var GroupInfo_SharedMedia: String { return self._s[2669]! } + public var Channel_AdminLog_EmptyTitle: String { return self._s[2653]! } + public var Privacy_Calls_NeverAllow_Title: String { return self._s[2655]! } + public var Login_UnknownError: String { return self._s[2656]! } + public var Group_UpgradeNoticeText2: String { return self._s[2658]! } + public var Watch_Compose_AddContact: String { return self._s[2659]! } + public var Web_Error: String { return self._s[2660]! } + public var Gif_Search: String { return self._s[2661]! } + public var Profile_MessageLifetime1h: String { return self._s[2662]! } + public var CheckoutInfo_ReceiverInfoEmailPlaceholder: String { return self._s[2663]! } + public var Channel_Username_CheckingUsername: String { return self._s[2664]! } + public var CallFeedback_ReasonSilentRemote: String { return self._s[2665]! } + public var AutoDownloadSettings_TypeChannels: String { return self._s[2666]! } + public var Channel_AboutItem: String { return self._s[2667]! } + public var Privacy_GroupsAndChannels_AlwaysAllow_Placeholder: String { return self._s[2669]! } + public var GroupInfo_SharedMedia: String { return self._s[2670]! } public func Channel_AdminLog_MessagePromotedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2670]!, self._r[2670]!, [_1]) + return formatWithArgumentRanges(self._s[2671]!, self._r[2671]!, [_1]) } - public var Call_PhoneCallInProgressMessage: String { return self._s[2671]! } + public var Call_PhoneCallInProgressMessage: String { return self._s[2672]! } public func PUSH_CHANNEL_ALBUM(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2672]!, self._r[2672]!, [_1]) + return formatWithArgumentRanges(self._s[2673]!, self._r[2673]!, [_1]) } - public var GroupInfo_InviteLink_RevokeAlert_Text: String { return self._s[2673]! } - public var Conversation_SearchByName_Placeholder: String { return self._s[2674]! } - public var CreatePoll_AddOption: String { return self._s[2675]! } - public var GroupInfo_Permissions_SearchPlaceholder: String { return self._s[2676]! } - public var Group_UpgradeNoticeHeader: String { return self._s[2677]! } - public var Channel_Management_AddModerator: String { return self._s[2678]! } - public var AutoDownloadSettings_MaxFileSize: String { return self._s[2679]! } - public var StickerPacksSettings_ShowStickersButton: String { return self._s[2680]! } - public var NotificationsSound_Hello: String { return self._s[2681]! } - public var SocksProxySetup_SavedProxies: String { return self._s[2682]! } - public var Channel_Stickers_Placeholder: String { return self._s[2684]! } + public var GroupInfo_InviteLink_RevokeAlert_Text: String { return self._s[2674]! } + public var Conversation_SearchByName_Placeholder: String { return self._s[2675]! } + public var CreatePoll_AddOption: String { return self._s[2676]! } + public var GroupInfo_Permissions_SearchPlaceholder: String { return self._s[2677]! } + public var Group_UpgradeNoticeHeader: String { return self._s[2678]! } + public var Channel_Management_AddModerator: String { return self._s[2679]! } + public var AutoDownloadSettings_MaxFileSize: String { return self._s[2680]! } + public var StickerPacksSettings_ShowStickersButton: String { return self._s[2681]! } + public var NotificationsSound_Hello: String { return self._s[2682]! } + public var SocksProxySetup_SavedProxies: String { return self._s[2683]! } + public var Channel_Stickers_Placeholder: String { return self._s[2685]! } public func Login_EmailCodeBody(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2685]!, self._r[2685]!, [_0]) + return formatWithArgumentRanges(self._s[2686]!, self._r[2686]!, [_0]) } - public var PrivacyPolicy_DeclineDeclineAndDelete: String { return self._s[2686]! } - public var Channel_Management_AddModeratorHelp: String { return self._s[2687]! } - public var ContactInfo_BirthdayLabel: String { return self._s[2688]! } - public var ChangePhoneNumberCode_RequestingACall: String { return self._s[2689]! } - public var AutoDownloadSettings_Channels: String { return self._s[2690]! } - public var Passport_Language_mn: String { return self._s[2691]! } - public var Notifications_ResetAllNotificationsHelp: String { return self._s[2694]! } - public var Passport_Language_ja: String { return self._s[2696]! } - public var Settings_About_Title: String { return self._s[2697]! } - public var Settings_NotificationsAndSounds: String { return self._s[2698]! } - public var ChannelInfo_DeleteGroup: String { return self._s[2699]! } - public var Settings_BlockedUsers: String { return self._s[2700]! } + public var PrivacyPolicy_DeclineDeclineAndDelete: String { return self._s[2687]! } + public var Channel_Management_AddModeratorHelp: String { return self._s[2688]! } + public var ContactInfo_BirthdayLabel: String { return self._s[2689]! } + public var ChangePhoneNumberCode_RequestingACall: String { return self._s[2690]! } + public var AutoDownloadSettings_Channels: String { return self._s[2691]! } + public var Passport_Language_mn: String { return self._s[2692]! } + public var Notifications_ResetAllNotificationsHelp: String { return self._s[2695]! } + public var Passport_Language_ja: String { return self._s[2697]! } + public var Settings_About_Title: String { return self._s[2698]! } + public var Settings_NotificationsAndSounds: String { return self._s[2699]! } + public var ChannelInfo_DeleteGroup: String { return self._s[2700]! } + public var Settings_BlockedUsers: String { return self._s[2701]! } public func Time_MonthOfYear_m4(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2701]!, self._r[2701]!, [_0]) + return formatWithArgumentRanges(self._s[2702]!, self._r[2702]!, [_0]) } - public var AutoDownloadSettings_PreloadVideo: String { return self._s[2702]! } - public var Passport_Address_AddResidentialAddress: String { return self._s[2703]! } - public var Channel_Username_Title: String { return self._s[2704]! } + public var AutoDownloadSettings_PreloadVideo: String { return self._s[2703]! } + public var Passport_Address_AddResidentialAddress: String { return self._s[2704]! } + public var Channel_Username_Title: String { return self._s[2705]! } public func Notification_RemovedGroupPhoto(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2705]!, self._r[2705]!, [_0]) + return formatWithArgumentRanges(self._s[2706]!, self._r[2706]!, [_0]) } - public var AttachmentMenu_File: String { return self._s[2707]! } - public var AppleWatch_Title: String { return self._s[2708]! } - public var Activity_RecordingVideoMessage: String { return self._s[2709]! } - public var Weekday_Saturday: String { return self._s[2710]! } - public var WallpaperPreview_SwipeColorsTopText: String { return self._s[2711]! } - public var Profile_CreateEncryptedChatError: String { return self._s[2712]! } - public var Common_Next: String { return self._s[2714]! } - public var Channel_Stickers_YourStickers: String { return self._s[2716]! } - public var Call_AudioRouteHeadphones: String { return self._s[2717]! } - public var TwoStepAuth_EnterPasswordForgot: String { return self._s[2719]! } - public var Watch_Contacts_NoResults: String { return self._s[2721]! } - public var PhotoEditor_TintTool: String { return self._s[2724]! } - public var LoginPassword_ResetAccount: String { return self._s[2726]! } - public var Settings_SavedMessages: String { return self._s[2727]! } - public var SettingsSearch_Synonyms_Appearance_Animations: String { return self._s[2728]! } - public var Bot_GenericSupportStatus: String { return self._s[2729]! } - public var StickerPack_Add: String { return self._s[2730]! } - public var Checkout_TotalAmount: String { return self._s[2731]! } - public var Your_cards_number_is_invalid: String { return self._s[2732]! } - public var SettingsSearch_Synonyms_Appearance_AutoNightTheme: String { return self._s[2733]! } + public var AttachmentMenu_File: String { return self._s[2708]! } + public var AppleWatch_Title: String { return self._s[2709]! } + public var Activity_RecordingVideoMessage: String { return self._s[2710]! } + public var Weekday_Saturday: String { return self._s[2711]! } + public var WallpaperPreview_SwipeColorsTopText: String { return self._s[2712]! } + public var Profile_CreateEncryptedChatError: String { return self._s[2713]! } + public var Common_Next: String { return self._s[2715]! } + public var Channel_Stickers_YourStickers: String { return self._s[2717]! } + public var Call_AudioRouteHeadphones: String { return self._s[2718]! } + public var TwoStepAuth_EnterPasswordForgot: String { return self._s[2720]! } + public var Watch_Contacts_NoResults: String { return self._s[2722]! } + public var PhotoEditor_TintTool: String { return self._s[2725]! } + public var LoginPassword_ResetAccount: String { return self._s[2727]! } + public var Settings_SavedMessages: String { return self._s[2728]! } + public var SettingsSearch_Synonyms_Appearance_Animations: String { return self._s[2729]! } + public var Bot_GenericSupportStatus: String { return self._s[2730]! } + public var StickerPack_Add: String { return self._s[2731]! } + public var Checkout_TotalAmount: String { return self._s[2732]! } + public var Your_cards_number_is_invalid: String { return self._s[2733]! } + public var SettingsSearch_Synonyms_Appearance_AutoNightTheme: String { return self._s[2734]! } public func ChangePhoneNumberCode_CallTimer(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2734]!, self._r[2734]!, [_0]) + return formatWithArgumentRanges(self._s[2735]!, self._r[2735]!, [_0]) } public func GroupPermission_AddedInfo(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2735]!, self._r[2735]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2736]!, self._r[2736]!, [_1, _2]) } - public var ChatSettings_ConnectionType_UseSocks5: String { return self._s[2736]! } + public var ChatSettings_ConnectionType_UseSocks5: String { return self._s[2737]! } public func PUSH_CHAT_PHOTO_EDITED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2738]!, self._r[2738]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2739]!, self._r[2739]!, [_1, _2]) } public func Conversation_RestrictedTextTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2739]!, self._r[2739]!, [_0]) + return formatWithArgumentRanges(self._s[2740]!, self._r[2740]!, [_0]) } - public var GroupInfo_InviteLink_ShareLink: String { return self._s[2740]! } - public var StickerPack_Share: String { return self._s[2741]! } - public var Passport_DeleteAddress: String { return self._s[2742]! } - public var Settings_Passport: String { return self._s[2743]! } - public var SharedMedia_EmptyFilesText: String { return self._s[2744]! } - public var Conversation_DeleteMessagesForMe: String { return self._s[2745]! } - public var PasscodeSettings_AutoLock_IfAwayFor_1hour: String { return self._s[2746]! } - public var Contacts_PermissionsText: String { return self._s[2747]! } - public var Group_Setup_HistoryVisible: String { return self._s[2748]! } - public var Passport_Address_AddRentalAgreement: String { return self._s[2750]! } - public var SocksProxySetup_Title: String { return self._s[2751]! } - public var Notification_Mute1h: String { return self._s[2752]! } + public var GroupInfo_InviteLink_ShareLink: String { return self._s[2741]! } + public var StickerPack_Share: String { return self._s[2742]! } + public var Passport_DeleteAddress: String { return self._s[2743]! } + public var Settings_Passport: String { return self._s[2744]! } + public var SharedMedia_EmptyFilesText: String { return self._s[2745]! } + public var Conversation_DeleteMessagesForMe: String { return self._s[2746]! } + public var PasscodeSettings_AutoLock_IfAwayFor_1hour: String { return self._s[2747]! } + public var Contacts_PermissionsText: String { return self._s[2748]! } + public var Group_Setup_HistoryVisible: String { return self._s[2749]! } + public var Passport_Address_AddRentalAgreement: String { return self._s[2751]! } + public var SocksProxySetup_Title: String { return self._s[2752]! } + public var Notification_Mute1h: String { return self._s[2753]! } public func Passport_Email_CodeHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2753]!, self._r[2753]!, [_0]) + return formatWithArgumentRanges(self._s[2754]!, self._r[2754]!, [_0]) } - public var NotificationSettings_ShowNotificationsAllAccountsInfoOff: String { return self._s[2754]! } + public var NotificationSettings_ShowNotificationsAllAccountsInfoOff: String { return self._s[2755]! } public func PUSH_PINNED_GEOLIVE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2755]!, self._r[2755]!, [_1]) + return formatWithArgumentRanges(self._s[2756]!, self._r[2756]!, [_1]) } - public var FastTwoStepSetup_PasswordSection: String { return self._s[2756]! } - public var NetworkUsageSettings_ResetStatsConfirmation: String { return self._s[2759]! } - public var InfoPlist_NSFaceIDUsageDescription: String { return self._s[2761]! } - public var DialogList_NoMessagesText: String { return self._s[2762]! } - public var Privacy_ContactsResetConfirmation: String { return self._s[2763]! } - public var Privacy_Calls_P2PHelp: String { return self._s[2764]! } - public var Your_cards_expiration_year_is_invalid: String { return self._s[2766]! } - public var Common_TakePhotoOrVideo: String { return self._s[2767]! } - public var Call_StatusBusy: String { return self._s[2768]! } - public var Conversation_PinnedMessage: String { return self._s[2769]! } - public var AutoDownloadSettings_VoiceMessagesTitle: String { return self._s[2770]! } - public var TwoStepAuth_SetupPasswordConfirmFailed: String { return self._s[2771]! } - public var Undo_ChatCleared: String { return self._s[2772]! } - public var AppleWatch_ReplyPresets: String { return self._s[2773]! } - public var Passport_DiscardMessageDescription: String { return self._s[2775]! } - public var Login_NetworkError: String { return self._s[2776]! } + public var FastTwoStepSetup_PasswordSection: String { return self._s[2757]! } + public var NetworkUsageSettings_ResetStatsConfirmation: String { return self._s[2760]! } + public var InfoPlist_NSFaceIDUsageDescription: String { return self._s[2762]! } + public var DialogList_NoMessagesText: String { return self._s[2763]! } + public var Privacy_ContactsResetConfirmation: String { return self._s[2764]! } + public var Privacy_Calls_P2PHelp: String { return self._s[2765]! } + public var Your_cards_expiration_year_is_invalid: String { return self._s[2767]! } + public var Common_TakePhotoOrVideo: String { return self._s[2768]! } + public var Call_StatusBusy: String { return self._s[2769]! } + public var Conversation_PinnedMessage: String { return self._s[2770]! } + public var AutoDownloadSettings_VoiceMessagesTitle: String { return self._s[2771]! } + public var TwoStepAuth_SetupPasswordConfirmFailed: String { return self._s[2772]! } + public var Undo_ChatCleared: String { return self._s[2773]! } + public var AppleWatch_ReplyPresets: String { return self._s[2774]! } + public var Passport_DiscardMessageDescription: String { return self._s[2776]! } + public var Login_NetworkError: String { return self._s[2777]! } public func Notification_PinnedRoundMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2777]!, self._r[2777]!, [_0]) - } - public func Channel_AdminLog_MessageRemovedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2778]!, self._r[2778]!, [_0]) } - public var SocksProxySetup_PasswordPlaceholder: String { return self._s[2779]! } - public var Login_ResetAccountProtected_LimitExceeded: String { return self._s[2781]! } + public func Channel_AdminLog_MessageRemovedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2779]!, self._r[2779]!, [_0]) + } + public var SocksProxySetup_PasswordPlaceholder: String { return self._s[2780]! } + public var Login_ResetAccountProtected_LimitExceeded: String { return self._s[2782]! } public func Watch_LastSeen_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2783]!, self._r[2783]!, [_0]) + return formatWithArgumentRanges(self._s[2784]!, self._r[2784]!, [_0]) } - public var Call_ConnectionErrorMessage: String { return self._s[2784]! } - public var SettingsSearch_Synonyms_Notifications_MessageNotificationsSound: String { return self._s[2785]! } - public var Compose_GroupTokenListPlaceholder: String { return self._s[2787]! } - public var ConversationMedia_Title: String { return self._s[2788]! } - public var EncryptionKey_Title: String { return self._s[2790]! } - public var TwoStepAuth_EnterPasswordTitle: String { return self._s[2791]! } - public var Notification_Exceptions_AddException: String { return self._s[2792]! } - public var Profile_MessageLifetime1m: String { return self._s[2793]! } + public var Call_ConnectionErrorMessage: String { return self._s[2785]! } + public var SettingsSearch_Synonyms_Notifications_MessageNotificationsSound: String { return self._s[2786]! } + public var Compose_GroupTokenListPlaceholder: String { return self._s[2788]! } + public var ConversationMedia_Title: String { return self._s[2789]! } + public var EncryptionKey_Title: String { return self._s[2791]! } + public var TwoStepAuth_EnterPasswordTitle: String { return self._s[2792]! } + public var Notification_Exceptions_AddException: String { return self._s[2793]! } + public var Profile_MessageLifetime1m: String { return self._s[2794]! } public func Channel_AdminLog_MessageUnkickedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2794]!, self._r[2794]!, [_1]) + return formatWithArgumentRanges(self._s[2795]!, self._r[2795]!, [_1]) } - public var Month_GenMay: String { return self._s[2795]! } + public var Month_GenMay: String { return self._s[2796]! } public func LiveLocationUpdated_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2796]!, self._r[2796]!, [_0]) + return formatWithArgumentRanges(self._s[2797]!, self._r[2797]!, [_0]) } - public var ChannelMembers_WhoCanAddMembersAllHelp: String { return self._s[2797]! } - public var AutoDownloadSettings_ResetSettings: String { return self._s[2798]! } - public var Conversation_EmptyPlaceholder: String { return self._s[2800]! } - public var Passport_Address_AddPassportRegistration: String { return self._s[2801]! } - public var Notifications_ChannelNotificationsAlert: String { return self._s[2802]! } - public var ChatSettings_AutoDownloadUsingCellular: String { return self._s[2803]! } - public var Camera_TapAndHoldForVideo: String { return self._s[2804]! } - public var Channel_JoinChannel: String { return self._s[2806]! } - public var Appearance_Animations: String { return self._s[2809]! } + public var ChannelMembers_WhoCanAddMembersAllHelp: String { return self._s[2798]! } + public var AutoDownloadSettings_ResetSettings: String { return self._s[2799]! } + public var Conversation_EmptyPlaceholder: String { return self._s[2801]! } + public var Passport_Address_AddPassportRegistration: String { return self._s[2802]! } + public var Notifications_ChannelNotificationsAlert: String { return self._s[2803]! } + public var ChatSettings_AutoDownloadUsingCellular: String { return self._s[2804]! } + public var Camera_TapAndHoldForVideo: String { return self._s[2805]! } + public var Channel_JoinChannel: String { return self._s[2807]! } + public var Appearance_Animations: String { return self._s[2810]! } public func Notification_MessageLifetimeChanged(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2810]!, self._r[2810]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2811]!, self._r[2811]!, [_1, _2]) } - public var Stickers_GroupStickers: String { return self._s[2812]! } - public var ConvertToSupergroup_HelpTitle: String { return self._s[2814]! } - public var Passport_Address_Street: String { return self._s[2815]! } - public var Conversation_AddContact: String { return self._s[2816]! } - public var Login_PhonePlaceholder: String { return self._s[2817]! } - public var Channel_Members_InviteLink: String { return self._s[2819]! } - public var Bot_Stop: String { return self._s[2820]! } - public var SettingsSearch_Synonyms_Proxy_UseForCalls: String { return self._s[2822]! } - public var Notification_PassportValueAddress: String { return self._s[2823]! } - public var Month_ShortJuly: String { return self._s[2824]! } - public var Passport_Address_TypeTemporaryRegistrationUploadScan: String { return self._s[2825]! } - public var Channel_AdminLog_BanSendMedia: String { return self._s[2826]! } - public var Passport_Identity_ReverseSide: String { return self._s[2827]! } - public var Watch_Stickers_Recents: String { return self._s[2830]! } - public var PrivacyLastSeenSettings_EmpryUsersPlaceholder: String { return self._s[2832]! } - public var Map_SendThisLocation: String { return self._s[2833]! } + public var Stickers_GroupStickers: String { return self._s[2813]! } + public var ConvertToSupergroup_HelpTitle: String { return self._s[2815]! } + public var Passport_Address_Street: String { return self._s[2816]! } + public var Conversation_AddContact: String { return self._s[2817]! } + public var Login_PhonePlaceholder: String { return self._s[2818]! } + public var Channel_Members_InviteLink: String { return self._s[2820]! } + public var Bot_Stop: String { return self._s[2821]! } + public var SettingsSearch_Synonyms_Proxy_UseForCalls: String { return self._s[2823]! } + public var Notification_PassportValueAddress: String { return self._s[2824]! } + public var Month_ShortJuly: String { return self._s[2825]! } + public var Passport_Address_TypeTemporaryRegistrationUploadScan: String { return self._s[2826]! } + public var Channel_AdminLog_BanSendMedia: String { return self._s[2827]! } + public var Passport_Identity_ReverseSide: String { return self._s[2828]! } + public var Watch_Stickers_Recents: String { return self._s[2831]! } + public var PrivacyLastSeenSettings_EmpryUsersPlaceholder: String { return self._s[2833]! } + public var Map_SendThisLocation: String { return self._s[2834]! } public func Time_MonthOfYear_m1(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2834]!, self._r[2834]!, [_0]) - } - public func InviteText_SingleContact(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2835]!, self._r[2835]!, [_0]) } - public var ConvertToSupergroup_Note: String { return self._s[2836]! } + public func InviteText_SingleContact(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2836]!, self._r[2836]!, [_0]) + } + public var ConvertToSupergroup_Note: String { return self._s[2837]! } public func FileSize_MB(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2837]!, self._r[2837]!, [_0]) + return formatWithArgumentRanges(self._s[2838]!, self._r[2838]!, [_0]) } - public var NetworkUsageSettings_GeneralDataSection: String { return self._s[2838]! } + public var NetworkUsageSettings_GeneralDataSection: String { return self._s[2839]! } public func Compatibility_SecretMediaVersionTooLow(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2839]!, self._r[2839]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2840]!, self._r[2840]!, [_0, _1]) } - public var Login_CallRequestState3: String { return self._s[2841]! } - public var Wallpaper_SearchShort: String { return self._s[2842]! } - public var SettingsSearch_Synonyms_Appearance_ColorTheme: String { return self._s[2844]! } - public var PasscodeSettings_UnlockWithFaceId: String { return self._s[2845]! } + public var Login_CallRequestState3: String { return self._s[2842]! } + public var Wallpaper_SearchShort: String { return self._s[2843]! } + public var SettingsSearch_Synonyms_Appearance_ColorTheme: String { return self._s[2845]! } + public var PasscodeSettings_UnlockWithFaceId: String { return self._s[2846]! } public func PUSH_CHAT_MESSAGE_GEOLIVE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2846]!, self._r[2846]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2847]!, self._r[2847]!, [_1, _2]) } - public var Channel_AdminLogFilter_Title: String { return self._s[2847]! } - public var Notifications_GroupNotificationsExceptions: String { return self._s[2851]! } + public var Channel_AdminLogFilter_Title: String { return self._s[2848]! } + public var Notifications_GroupNotificationsExceptions: String { return self._s[2852]! } public func FileSize_B(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2852]!, self._r[2852]!, [_0]) + return formatWithArgumentRanges(self._s[2853]!, self._r[2853]!, [_0]) } - public var Passport_CorrectErrors: String { return self._s[2853]! } + public var Passport_CorrectErrors: String { return self._s[2854]! } public func Channel_MessageTitleUpdated(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2854]!, self._r[2854]!, [_0]) + return formatWithArgumentRanges(self._s[2855]!, self._r[2855]!, [_0]) } - public var Map_SendMyCurrentLocation: String { return self._s[2855]! } + public var Map_SendMyCurrentLocation: String { return self._s[2856]! } public func PUSH_PINNED_CONTACT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2856]!, self._r[2856]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2857]!, self._r[2857]!, [_1, _2]) } - public var SharedMedia_SearchNoResults: String { return self._s[2857]! } - public var Permissions_NotificationsText_v0: String { return self._s[2858]! } - public var LoginPassword_FloodError: String { return self._s[2859]! } - public var Group_Setup_HistoryHiddenHelp: String { return self._s[2861]! } + public var SharedMedia_SearchNoResults: String { return self._s[2858]! } + public var Permissions_NotificationsText_v0: String { return self._s[2859]! } + public var LoginPassword_FloodError: String { return self._s[2860]! } + public var Group_Setup_HistoryHiddenHelp: String { return self._s[2862]! } public func TwoStepAuth_PendingEmailHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2862]!, self._r[2862]!, [_0]) + return formatWithArgumentRanges(self._s[2863]!, self._r[2863]!, [_0]) } - public var Passport_Language_bn: String { return self._s[2863]! } + public var Passport_Language_bn: String { return self._s[2864]! } public func DialogList_SingleUploadingPhotoSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2864]!, self._r[2864]!, [_0]) - } - public func Notification_PinnedAudioMessage(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2865]!, self._r[2865]!, [_0]) } - public func Channel_AdminLog_MessageChangedGroupStickerPack(_ _0: String) -> (String, [(Int, NSRange)]) { + public func Notification_PinnedAudioMessage(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2866]!, self._r[2866]!, [_0]) } - public var GroupInfo_InvitationLinkGroupFull: String { return self._s[2869]! } - public var Group_EditAdmin_PermissionChangeInfo: String { return self._s[2871]! } - public var Contacts_PermissionsAllow: String { return self._s[2872]! } - public var ReportPeer_ReasonCopyright: String { return self._s[2873]! } - public var Channel_EditAdmin_PermissinAddAdminOn: String { return self._s[2874]! } - public var WallpaperPreview_Pattern: String { return self._s[2875]! } - public var Paint_Duplicate: String { return self._s[2876]! } - public var Passport_Address_Country: String { return self._s[2877]! } - public var Notification_RenamedChannel: String { return self._s[2879]! } - public var CheckoutInfo_ErrorPostcodeInvalid: String { return self._s[2880]! } - public var Group_MessagePhotoUpdated: String { return self._s[2881]! } - public var Channel_BanUser_PermissionSendMedia: String { return self._s[2882]! } - public var Conversation_ContextMenuBan: String { return self._s[2883]! } - public var TwoStepAuth_EmailSent: String { return self._s[2884]! } - public var MessagePoll_NoVotes: String { return self._s[2885]! } - public var Passport_Language_is: String { return self._s[2886]! } - public var Tour_Text5: String { return self._s[2888]! } + public func Channel_AdminLog_MessageChangedGroupStickerPack(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2867]!, self._r[2867]!, [_0]) + } + public var GroupInfo_InvitationLinkGroupFull: String { return self._s[2870]! } + public var Group_EditAdmin_PermissionChangeInfo: String { return self._s[2872]! } + public var Contacts_PermissionsAllow: String { return self._s[2873]! } + public var ReportPeer_ReasonCopyright: String { return self._s[2874]! } + public var Channel_EditAdmin_PermissinAddAdminOn: String { return self._s[2875]! } + public var WallpaperPreview_Pattern: String { return self._s[2876]! } + public var Paint_Duplicate: String { return self._s[2877]! } + public var Passport_Address_Country: String { return self._s[2878]! } + public var Notification_RenamedChannel: String { return self._s[2880]! } + public var CheckoutInfo_ErrorPostcodeInvalid: String { return self._s[2881]! } + public var Group_MessagePhotoUpdated: String { return self._s[2882]! } + public var Channel_BanUser_PermissionSendMedia: String { return self._s[2883]! } + public var Conversation_ContextMenuBan: String { return self._s[2884]! } + public var TwoStepAuth_EmailSent: String { return self._s[2885]! } + public var MessagePoll_NoVotes: String { return self._s[2886]! } + public var Passport_Language_is: String { return self._s[2887]! } + public var Tour_Text5: String { return self._s[2889]! } public func Call_GroupFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2890]!, self._r[2890]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2891]!, self._r[2891]!, [_1, _2]) } - public var Undo_SecretChatDeleted: String { return self._s[2891]! } - public var SocksProxySetup_ShareQRCode: String { return self._s[2892]! } - public var LogoutOptions_ChangePhoneNumberText: String { return self._s[2893]! } - public var Paint_Edit: String { return self._s[2895]! } - public var Undo_DeletedGroup: String { return self._s[2898]! } - public var LoginPassword_ForgotPassword: String { return self._s[2899]! } - public var GroupInfo_GroupNamePlaceholder: String { return self._s[2900]! } + public var Undo_SecretChatDeleted: String { return self._s[2892]! } + public var SocksProxySetup_ShareQRCode: String { return self._s[2893]! } + public var LogoutOptions_ChangePhoneNumberText: String { return self._s[2894]! } + public var Paint_Edit: String { return self._s[2896]! } + public var Undo_DeletedGroup: String { return self._s[2899]! } + public var LoginPassword_ForgotPassword: String { return self._s[2900]! } + public var GroupInfo_GroupNamePlaceholder: String { return self._s[2901]! } public func Notification_Kicked(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2901]!, self._r[2901]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2902]!, self._r[2902]!, [_0, _1]) } - public var Conversation_InputTextCaptionPlaceholder: String { return self._s[2902]! } - public var AutoDownloadSettings_VideoMessagesTitle: String { return self._s[2903]! } - public var Passport_Language_uz: String { return self._s[2904]! } - public var Conversation_PinMessageAlertGroup: String { return self._s[2905]! } - public var SettingsSearch_Synonyms_Privacy_GroupsAndChannels: String { return self._s[2906]! } - public var Map_StopLiveLocation: String { return self._s[2908]! } - public var PasscodeSettings_Help: String { return self._s[2910]! } - public var NotificationsSound_Input: String { return self._s[2911]! } - public var Share_Title: String { return self._s[2914]! } - public var LogoutOptions_Title: String { return self._s[2915]! } - public var Login_TermsOfServiceAgree: String { return self._s[2916]! } - public var Compose_NewEncryptedChatTitle: String { return self._s[2917]! } - public var Channel_AdminLog_TitleSelectedEvents: String { return self._s[2918]! } - public var Channel_EditAdmin_PermissionEditMessages: String { return self._s[2919]! } - public var EnterPasscode_EnterTitle: String { return self._s[2920]! } + public var Conversation_InputTextCaptionPlaceholder: String { return self._s[2903]! } + public var AutoDownloadSettings_VideoMessagesTitle: String { return self._s[2904]! } + public var Passport_Language_uz: String { return self._s[2905]! } + public var Conversation_PinMessageAlertGroup: String { return self._s[2906]! } + public var SettingsSearch_Synonyms_Privacy_GroupsAndChannels: String { return self._s[2907]! } + public var Map_StopLiveLocation: String { return self._s[2909]! } + public var PasscodeSettings_Help: String { return self._s[2911]! } + public var NotificationsSound_Input: String { return self._s[2912]! } + public var Share_Title: String { return self._s[2915]! } + public var LogoutOptions_Title: String { return self._s[2916]! } + public var Login_TermsOfServiceAgree: String { return self._s[2917]! } + public var Compose_NewEncryptedChatTitle: String { return self._s[2918]! } + public var Channel_AdminLog_TitleSelectedEvents: String { return self._s[2919]! } + public var Channel_EditAdmin_PermissionEditMessages: String { return self._s[2920]! } + public var EnterPasscode_EnterTitle: String { return self._s[2921]! } public func Call_PrivacyErrorMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2921]!, self._r[2921]!, [_0]) + return formatWithArgumentRanges(self._s[2922]!, self._r[2922]!, [_0]) } - public var Settings_CopyPhoneNumber: String { return self._s[2922]! } - public var NotificationsSound_Keys: String { return self._s[2923]! } + public var Settings_CopyPhoneNumber: String { return self._s[2923]! } + public var NotificationsSound_Keys: String { return self._s[2924]! } public func Call_ParticipantVersionOutdatedError(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2924]!, self._r[2924]!, [_0]) + return formatWithArgumentRanges(self._s[2925]!, self._r[2925]!, [_0]) } - public var Notification_MessageLifetime1w: String { return self._s[2925]! } - public var Message_Video: String { return self._s[2926]! } - public var AutoDownloadSettings_CellularTitle: String { return self._s[2927]! } + public var Notification_MessageLifetime1w: String { return self._s[2926]! } + public var Message_Video: String { return self._s[2927]! } + public var AutoDownloadSettings_CellularTitle: String { return self._s[2928]! } public func PUSH_CHANNEL_MESSAGE_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2928]!, self._r[2928]!, [_1]) + return formatWithArgumentRanges(self._s[2929]!, self._r[2929]!, [_1]) } public func Notification_JoinedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2931]!, self._r[2931]!, [_0]) - } - public func PrivacySettings_LastSeenContactsPlus(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2932]!, self._r[2932]!, [_0]) } - public var Passport_Language_mk: String { return self._s[2933]! } - public var CreatePoll_CancelConfirmation: String { return self._s[2934]! } - public var Conversation_SilentBroadcastTooltipOn: String { return self._s[2936]! } - public var PrivacyPolicy_Decline: String { return self._s[2937]! } - public var Passport_Identity_DoesNotExpire: String { return self._s[2938]! } - public var Channel_AdminLogFilter_EventsRestrictions: String { return self._s[2939]! } - public var Permissions_SiriAllow_v0: String { return self._s[2941]! } + public func PrivacySettings_LastSeenContactsPlus(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2933]!, self._r[2933]!, [_0]) + } + public var Passport_Language_mk: String { return self._s[2934]! } + public var CreatePoll_CancelConfirmation: String { return self._s[2935]! } + public var Conversation_SilentBroadcastTooltipOn: String { return self._s[2937]! } + public var PrivacyPolicy_Decline: String { return self._s[2938]! } + public var Passport_Identity_DoesNotExpire: String { return self._s[2939]! } + public var Channel_AdminLogFilter_EventsRestrictions: String { return self._s[2940]! } + public var Permissions_SiriAllow_v0: String { return self._s[2942]! } public func LOCAL_CHAT_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2942]!, self._r[2942]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[2943]!, self._r[2943]!, [_1, "\(_2)"]) } public func Notification_RenamedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2943]!, self._r[2943]!, [_0]) + return formatWithArgumentRanges(self._s[2944]!, self._r[2944]!, [_0]) } - public var Paint_Regular: String { return self._s[2944]! } - public var ChatSettings_AutoDownloadReset: String { return self._s[2945]! } - public var SocksProxySetup_ShareLink: String { return self._s[2946]! } - public var BlockedUsers_SelectUserTitle: String { return self._s[2947]! } - public var GroupInfo_InviteByLink: String { return self._s[2949]! } - public var MessageTimer_Custom: String { return self._s[2950]! } - public var UserInfo_NotificationsDefaultEnabled: String { return self._s[2951]! } - public var Passport_Address_TypeTemporaryRegistration: String { return self._s[2953]! } - public var ChatSettings_AutoDownloadUsingWiFi: String { return self._s[2954]! } - public var Channel_Username_InvalidTaken: String { return self._s[2955]! } - public var Conversation_ClousStorageInfo_Description3: String { return self._s[2956]! } - public var Settings_ChatBackground: String { return self._s[2957]! } - public var Channel_Subscribers_Title: String { return self._s[2958]! } - public var ApplyLanguage_ChangeLanguageTitle: String { return self._s[2959]! } - public var Watch_ConnectionDescription: String { return self._s[2960]! } - public var Wallpaper_ResetWallpapers: String { return self._s[2964]! } - public var EditProfile_Title: String { return self._s[2965]! } - public var NotificationsSound_Bamboo: String { return self._s[2967]! } - public var Channel_AdminLog_MessagePreviousMessage: String { return self._s[2969]! } - public var Login_SmsRequestState2: String { return self._s[2970]! } - public var Passport_Language_ar: String { return self._s[2971]! } - public var SettingsSearch_Synonyms_EditProfile_Title: String { return self._s[2972]! } - public var Conversation_MessageDialogEdit: String { return self._s[2973]! } + public var Paint_Regular: String { return self._s[2945]! } + public var ChatSettings_AutoDownloadReset: String { return self._s[2946]! } + public var SocksProxySetup_ShareLink: String { return self._s[2947]! } + public var BlockedUsers_SelectUserTitle: String { return self._s[2948]! } + public var GroupInfo_InviteByLink: String { return self._s[2950]! } + public var MessageTimer_Custom: String { return self._s[2951]! } + public var UserInfo_NotificationsDefaultEnabled: String { return self._s[2952]! } + public var Passport_Address_TypeTemporaryRegistration: String { return self._s[2954]! } + public var ChatSettings_AutoDownloadUsingWiFi: String { return self._s[2955]! } + public var Channel_Username_InvalidTaken: String { return self._s[2956]! } + public var Conversation_ClousStorageInfo_Description3: String { return self._s[2957]! } + public var Settings_ChatBackground: String { return self._s[2958]! } + public var Channel_Subscribers_Title: String { return self._s[2959]! } + public var ApplyLanguage_ChangeLanguageTitle: String { return self._s[2960]! } + public var Watch_ConnectionDescription: String { return self._s[2961]! } + public var Wallpaper_ResetWallpapers: String { return self._s[2965]! } + public var EditProfile_Title: String { return self._s[2966]! } + public var NotificationsSound_Bamboo: String { return self._s[2968]! } + public var Channel_AdminLog_MessagePreviousMessage: String { return self._s[2970]! } + public var Login_SmsRequestState2: String { return self._s[2971]! } + public var Passport_Language_ar: String { return self._s[2972]! } + public var SettingsSearch_Synonyms_EditProfile_Title: String { return self._s[2973]! } + public var Conversation_MessageDialogEdit: String { return self._s[2974]! } public func PUSH_AUTH_UNKNOWN(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2974]!, self._r[2974]!, [_1]) + return formatWithArgumentRanges(self._s[2975]!, self._r[2975]!, [_1]) } - public var Common_Close: String { return self._s[2975]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsPreview: String { return self._s[2976]! } + public var Common_Close: String { return self._s[2976]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsPreview: String { return self._s[2977]! } public func Channel_AdminLog_MessageToggleInvitesOff(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2980]!, self._r[2980]!, [_0]) + return formatWithArgumentRanges(self._s[2981]!, self._r[2981]!, [_0]) } - public var UserInfo_About_Placeholder: String { return self._s[2981]! } + public var UserInfo_About_Placeholder: String { return self._s[2982]! } public func Conversation_FileHowToText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2982]!, self._r[2982]!, [_0]) + return formatWithArgumentRanges(self._s[2983]!, self._r[2983]!, [_0]) } - public var GroupInfo_Permissions_SectionTitle: String { return self._s[2983]! } - public var Channel_Info_Banned: String { return self._s[2985]! } + public var GroupInfo_Permissions_SectionTitle: String { return self._s[2984]! } + public var Channel_Info_Banned: String { return self._s[2986]! } public func Time_MonthOfYear_m11(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2986]!, self._r[2986]!, [_0]) + return formatWithArgumentRanges(self._s[2987]!, self._r[2987]!, [_0]) } - public var Appearance_Other: String { return self._s[2987]! } - public var Passport_Language_my: String { return self._s[2988]! } - public var Group_Setup_BasicHistoryHiddenHelp: String { return self._s[2989]! } + public var Appearance_Other: String { return self._s[2988]! } + public var Passport_Language_my: String { return self._s[2989]! } + public var Group_Setup_BasicHistoryHiddenHelp: String { return self._s[2990]! } public func Time_PreciseDate_m9(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2990]!, self._r[2990]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2991]!, self._r[2991]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_Privacy_PasscodeAndFaceId: String { return self._s[2991]! } - public var Preview_CopyAddress: String { return self._s[2992]! } + public var SettingsSearch_Synonyms_Privacy_PasscodeAndFaceId: String { return self._s[2992]! } + public var Preview_CopyAddress: String { return self._s[2993]! } public func DialogList_SinglePlayingGameSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2993]!, self._r[2993]!, [_0]) + return formatWithArgumentRanges(self._s[2994]!, self._r[2994]!, [_0]) } - public var KeyCommand_JumpToPreviousChat: String { return self._s[2994]! } - public var UserInfo_BotSettings: String { return self._s[2995]! } - public var LiveLocation_MenuStopAll: String { return self._s[2997]! } - public var Passport_PasswordCreate: String { return self._s[2998]! } - public var StickerSettings_MaskContextInfo: String { return self._s[2999]! } - public var Message_PinnedLocationMessage: String { return self._s[3000]! } - public var Map_Satellite: String { return self._s[3001]! } - public var Watch_Message_Unsupported: String { return self._s[3002]! } - public var Username_TooManyPublicUsernamesError: String { return self._s[3003]! } - public var TwoStepAuth_EnterPasswordInvalid: String { return self._s[3004]! } + public var KeyCommand_JumpToPreviousChat: String { return self._s[2995]! } + public var UserInfo_BotSettings: String { return self._s[2996]! } + public var LiveLocation_MenuStopAll: String { return self._s[2998]! } + public var Passport_PasswordCreate: String { return self._s[2999]! } + public var StickerSettings_MaskContextInfo: String { return self._s[3000]! } + public var Message_PinnedLocationMessage: String { return self._s[3001]! } + public var Map_Satellite: String { return self._s[3002]! } + public var Watch_Message_Unsupported: String { return self._s[3003]! } + public var Username_TooManyPublicUsernamesError: String { return self._s[3004]! } + public var TwoStepAuth_EnterPasswordInvalid: String { return self._s[3005]! } public func Notification_PinnedTextMessage(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3005]!, self._r[3005]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3006]!, self._r[3006]!, [_0, _1]) } - public var Notifications_ChannelNotificationsHelp: String { return self._s[3006]! } - public var Privacy_Calls_P2PContacts: String { return self._s[3007]! } - public var NotificationsSound_None: String { return self._s[3008]! } - public var AccessDenied_VoiceMicrophone: String { return self._s[3010]! } + public var Notifications_ChannelNotificationsHelp: String { return self._s[3007]! } + public var Privacy_Calls_P2PContacts: String { return self._s[3008]! } + public var NotificationsSound_None: String { return self._s[3009]! } + public var AccessDenied_VoiceMicrophone: String { return self._s[3011]! } public func ApplyLanguage_ChangeLanguageAlreadyActive(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3011]!, self._r[3011]!, [_1]) + return formatWithArgumentRanges(self._s[3012]!, self._r[3012]!, [_1]) } - public var Cache_Indexing: String { return self._s[3012]! } - public var DialogList_RecentTitlePeople: String { return self._s[3014]! } - public var DialogList_EncryptionRejected: String { return self._s[3015]! } - public var GroupInfo_Administrators: String { return self._s[3016]! } - public var Passport_ScanPassportHelp: String { return self._s[3017]! } - public var Application_Name: String { return self._s[3018]! } - public var Channel_AdminLogFilter_ChannelEventsInfo: String { return self._s[3019]! } - public var Passport_Identity_TranslationHelp: String { return self._s[3021]! } + public var Cache_Indexing: String { return self._s[3013]! } + public var DialogList_RecentTitlePeople: String { return self._s[3015]! } + public var DialogList_EncryptionRejected: String { return self._s[3016]! } + public var GroupInfo_Administrators: String { return self._s[3017]! } + public var Passport_ScanPassportHelp: String { return self._s[3018]! } + public var Application_Name: String { return self._s[3019]! } + public var Channel_AdminLogFilter_ChannelEventsInfo: String { return self._s[3020]! } + public var Passport_Identity_TranslationHelp: String { return self._s[3022]! } public func Notification_JoinedGroupByLink(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3022]!, self._r[3022]!, [_0]) - } - public func DialogList_EncryptedChatStartedOutgoing(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3023]!, self._r[3023]!, [_0]) } - public var Channel_EditAdmin_PermissionDeleteMessages: String { return self._s[3024]! } - public var Privacy_ChatsTitle: String { return self._s[3025]! } - public var DialogList_ClearHistoryConfirmation: String { return self._s[3026]! } - public var SettingsSearch_Synonyms_Data_Storage_ClearCache: String { return self._s[3027]! } - public var Watch_Suggestion_HoldOn: String { return self._s[3028]! } - public var SocksProxySetup_RequiredCredentials: String { return self._s[3029]! } - public var Passport_Address_TypeRentalAgreementUploadScan: String { return self._s[3030]! } - public var TwoStepAuth_EmailSkipAlert: String { return self._s[3031]! } - public var Channel_Setup_TypePublic: String { return self._s[3034]! } + public func DialogList_EncryptedChatStartedOutgoing(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3024]!, self._r[3024]!, [_0]) + } + public var Channel_EditAdmin_PermissionDeleteMessages: String { return self._s[3025]! } + public var Privacy_ChatsTitle: String { return self._s[3026]! } + public var DialogList_ClearHistoryConfirmation: String { return self._s[3027]! } + public var SettingsSearch_Synonyms_Data_Storage_ClearCache: String { return self._s[3028]! } + public var Watch_Suggestion_HoldOn: String { return self._s[3029]! } + public var SocksProxySetup_RequiredCredentials: String { return self._s[3030]! } + public var Passport_Address_TypeRentalAgreementUploadScan: String { return self._s[3031]! } + public var TwoStepAuth_EmailSkipAlert: String { return self._s[3032]! } + public var Channel_Setup_TypePublic: String { return self._s[3035]! } public func Channel_AdminLog_MessageToggleInvitesOn(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3035]!, self._r[3035]!, [_0]) + return formatWithArgumentRanges(self._s[3036]!, self._r[3036]!, [_0]) } - public var Channel_TypeSetup_Title: String { return self._s[3037]! } - public var Map_OpenInMaps: String { return self._s[3039]! } + public var Channel_TypeSetup_Title: String { return self._s[3038]! } + public var Map_OpenInMaps: String { return self._s[3040]! } public func PUSH_PINNED_NOTEXT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3040]!, self._r[3040]!, [_1]) + return formatWithArgumentRanges(self._s[3041]!, self._r[3041]!, [_1]) } - public var NotificationsSound_Tremolo: String { return self._s[3042]! } + public var NotificationsSound_Tremolo: String { return self._s[3043]! } public func Date_ChatDateHeaderYear(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3043]!, self._r[3043]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3044]!, self._r[3044]!, [_1, _2, _3]) } - public var ConversationProfile_UnknownAddMemberError: String { return self._s[3044]! } - public var Passport_PasswordHelp: String { return self._s[3045]! } - public var Login_CodeExpiredError: String { return self._s[3046]! } - public var Channel_EditAdmin_PermissionChangeInfo: String { return self._s[3047]! } - public var Conversation_TitleUnmute: String { return self._s[3048]! } - public var Passport_Identity_ScansHelp: String { return self._s[3049]! } - public var Passport_Language_lo: String { return self._s[3050]! } - public var Camera_FlashAuto: String { return self._s[3051]! } - public var Common_Cancel: String { return self._s[3052]! } - public var DialogList_SavedMessagesTooltip: String { return self._s[3053]! } - public var TwoStepAuth_SetupPasswordTitle: String { return self._s[3054]! } + public var ConversationProfile_UnknownAddMemberError: String { return self._s[3045]! } + public var Passport_PasswordHelp: String { return self._s[3046]! } + public var Login_CodeExpiredError: String { return self._s[3047]! } + public var Channel_EditAdmin_PermissionChangeInfo: String { return self._s[3048]! } + public var Conversation_TitleUnmute: String { return self._s[3049]! } + public var Passport_Identity_ScansHelp: String { return self._s[3050]! } + public var Passport_Language_lo: String { return self._s[3051]! } + public var Camera_FlashAuto: String { return self._s[3052]! } + public var Common_Cancel: String { return self._s[3053]! } + public var DialogList_SavedMessagesTooltip: String { return self._s[3054]! } + public var TwoStepAuth_SetupPasswordTitle: String { return self._s[3055]! } public func PUSH_MESSAGE_FWD(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3055]!, self._r[3055]!, [_1]) + return formatWithArgumentRanges(self._s[3056]!, self._r[3056]!, [_1]) } - public var Conversation_ReportSpamConfirmation: String { return self._s[3056]! } - public var ChatSettings_Title: String { return self._s[3058]! } - public var Passport_PasswordReset: String { return self._s[3059]! } - public var SocksProxySetup_TypeNone: String { return self._s[3060]! } - public var PhoneNumberHelp_Help: String { return self._s[3062]! } - public var Checkout_EnterPassword: String { return self._s[3063]! } - public var Share_AuthTitle: String { return self._s[3065]! } - public var Activity_UploadingDocument: String { return self._s[3066]! } - public var State_Connecting: String { return self._s[3067]! } - public var Profile_MessageLifetime1w: String { return self._s[3068]! } - public var Conversation_ContextMenuReport: String { return self._s[3069]! } - public var CheckoutInfo_ReceiverInfoPhone: String { return self._s[3070]! } - public var AutoNightTheme_ScheduledTo: String { return self._s[3071]! } - public var AuthSessions_Terminate: String { return self._s[3072]! } - public var Checkout_NewCard_CardholderNamePlaceholder: String { return self._s[3073]! } - public var KeyCommand_JumpToPreviousUnreadChat: String { return self._s[3074]! } - public var PhotoEditor_Set: String { return self._s[3075]! } - public var EmptyGroupInfo_Title: String { return self._s[3076]! } - public var Login_PadPhoneHelp: String { return self._s[3077]! } - public var AutoDownloadSettings_TypeGroupChats: String { return self._s[3079]! } - public var PrivacyPolicy_DeclineLastWarning: String { return self._s[3081]! } - public var NotificationsSound_Complete: String { return self._s[3082]! } - public var SettingsSearch_Synonyms_Privacy_Data_Title: String { return self._s[3083]! } - public var Group_Info_AdminLog: String { return self._s[3084]! } - public var GroupPermission_NotAvailableInPublicGroups: String { return self._s[3085]! } - public var Channel_AdminLog_InfoPanelAlertText: String { return self._s[3086]! } - public var Conversation_Admin: String { return self._s[3088]! } - public var Conversation_GifTooltip: String { return self._s[3089]! } - public var Passport_NotLoggedInMessage: String { return self._s[3090]! } + public var Conversation_ReportSpamConfirmation: String { return self._s[3057]! } + public var ChatSettings_Title: String { return self._s[3059]! } + public var Passport_PasswordReset: String { return self._s[3060]! } + public var SocksProxySetup_TypeNone: String { return self._s[3061]! } + public var PhoneNumberHelp_Help: String { return self._s[3063]! } + public var Checkout_EnterPassword: String { return self._s[3064]! } + public var Share_AuthTitle: String { return self._s[3066]! } + public var Activity_UploadingDocument: String { return self._s[3067]! } + public var State_Connecting: String { return self._s[3068]! } + public var Profile_MessageLifetime1w: String { return self._s[3069]! } + public var Conversation_ContextMenuReport: String { return self._s[3070]! } + public var CheckoutInfo_ReceiverInfoPhone: String { return self._s[3071]! } + public var AutoNightTheme_ScheduledTo: String { return self._s[3072]! } + public var AuthSessions_Terminate: String { return self._s[3073]! } + public var Checkout_NewCard_CardholderNamePlaceholder: String { return self._s[3074]! } + public var KeyCommand_JumpToPreviousUnreadChat: String { return self._s[3075]! } + public var PhotoEditor_Set: String { return self._s[3076]! } + public var EmptyGroupInfo_Title: String { return self._s[3077]! } + public var Login_PadPhoneHelp: String { return self._s[3078]! } + public var AutoDownloadSettings_TypeGroupChats: String { return self._s[3080]! } + public var PrivacyPolicy_DeclineLastWarning: String { return self._s[3082]! } + public var NotificationsSound_Complete: String { return self._s[3083]! } + public var SettingsSearch_Synonyms_Privacy_Data_Title: String { return self._s[3084]! } + public var Group_Info_AdminLog: String { return self._s[3085]! } + public var GroupPermission_NotAvailableInPublicGroups: String { return self._s[3086]! } + public var Channel_AdminLog_InfoPanelAlertText: String { return self._s[3087]! } + public var Conversation_Admin: String { return self._s[3089]! } + public var Conversation_GifTooltip: String { return self._s[3090]! } + public var Passport_NotLoggedInMessage: String { return self._s[3091]! } public func AutoDownloadSettings_OnFor(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3091]!, self._r[3091]!, [_0]) + return formatWithArgumentRanges(self._s[3092]!, self._r[3092]!, [_0]) } - public var Profile_MessageLifetimeForever: String { return self._s[3092]! } - public var SharedMedia_EmptyTitle: String { return self._s[3094]! } - public var Channel_Edit_PrivatePublicLinkAlert: String { return self._s[3096]! } - public var Username_Help: String { return self._s[3097]! } - public var DialogList_LanguageTooltip: String { return self._s[3099]! } - public var Map_LoadError: String { return self._s[3100]! } - public var Login_PhoneNumberAlreadyAuthorized: String { return self._s[3101]! } - public var Channel_AdminLog_AddMembers: String { return self._s[3102]! } - public var Notification_Exceptions_NewException: String { return self._s[3103]! } - public var TwoStepAuth_EmailTitle: String { return self._s[3104]! } - public var WatchRemote_AlertText: String { return self._s[3105]! } - public var ChatSettings_ConnectionType_Title: String { return self._s[3108]! } + public var Profile_MessageLifetimeForever: String { return self._s[3093]! } + public var SharedMedia_EmptyTitle: String { return self._s[3095]! } + public var Channel_Edit_PrivatePublicLinkAlert: String { return self._s[3097]! } + public var Username_Help: String { return self._s[3098]! } + public var DialogList_LanguageTooltip: String { return self._s[3100]! } + public var Map_LoadError: String { return self._s[3101]! } + public var Login_PhoneNumberAlreadyAuthorized: String { return self._s[3102]! } + public var Channel_AdminLog_AddMembers: String { return self._s[3103]! } + public var Notification_Exceptions_NewException: String { return self._s[3104]! } + public var TwoStepAuth_EmailTitle: String { return self._s[3105]! } + public var WatchRemote_AlertText: String { return self._s[3106]! } + public var ChatSettings_ConnectionType_Title: String { return self._s[3109]! } public func Settings_CheckPhoneNumberTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3109]!, self._r[3109]!, [_0]) + return formatWithArgumentRanges(self._s[3110]!, self._r[3110]!, [_0]) } - public var SettingsSearch_Synonyms_Calls_CallTab: String { return self._s[3110]! } - public var Passport_Address_CountryPlaceholder: String { return self._s[3111]! } + public var SettingsSearch_Synonyms_Calls_CallTab: String { return self._s[3111]! } + public var Passport_Address_CountryPlaceholder: String { return self._s[3112]! } public func DialogList_AwaitingEncryption(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3112]!, self._r[3112]!, [_0]) + return formatWithArgumentRanges(self._s[3113]!, self._r[3113]!, [_0]) } public func Time_PreciseDate_m6(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3113]!, self._r[3113]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3114]!, self._r[3114]!, [_1, _2, _3]) } - public var Group_AdminLog_EmptyText: String { return self._s[3114]! } - public var SettingsSearch_Synonyms_Appearance_Title: String { return self._s[3115]! } - public var AccessDenied_VideoMicrophone: String { return self._s[3117]! } - public var Conversation_ContextMenuStickerPackAdd: String { return self._s[3118]! } - public var Cache_ClearNone: String { return self._s[3119]! } - public var SocksProxySetup_FailedToConnect: String { return self._s[3120]! } - public var Permissions_NotificationsTitle_v0: String { return self._s[3121]! } + public var Group_AdminLog_EmptyText: String { return self._s[3115]! } + public var SettingsSearch_Synonyms_Appearance_Title: String { return self._s[3116]! } + public var AccessDenied_VideoMicrophone: String { return self._s[3118]! } + public var Conversation_ContextMenuStickerPackAdd: String { return self._s[3119]! } + public var Cache_ClearNone: String { return self._s[3120]! } + public var SocksProxySetup_FailedToConnect: String { return self._s[3121]! } + public var Permissions_NotificationsTitle_v0: String { return self._s[3122]! } public func Channel_AdminLog_MessageEdited(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3122]!, self._r[3122]!, [_0]) + return formatWithArgumentRanges(self._s[3123]!, self._r[3123]!, [_0]) } - public var Passport_Identity_Country: String { return self._s[3123]! } + public var Passport_Identity_Country: String { return self._s[3124]! } public func ChatSettings_AutoDownloadSettings_TypeFile(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3124]!, self._r[3124]!, [_0]) - } - public func Notification_CreatedChat(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3125]!, self._r[3125]!, [_0]) } - public var AccessDenied_Settings: String { return self._s[3126]! } - public var Passport_Address_TypeUtilityBillUploadScan: String { return self._s[3127]! } - public var Month_ShortMay: String { return self._s[3128]! } - public var Compose_NewGroup: String { return self._s[3129]! } - public var Group_Setup_TypePrivate: String { return self._s[3131]! } - public var Login_PadPhoneHelpTitle: String { return self._s[3133]! } - public var Appearance_ThemeDayClassic: String { return self._s[3134]! } - public var Channel_AdminLog_MessagePreviousCaption: String { return self._s[3135]! } - public var AutoDownloadSettings_OffForAll: String { return self._s[3136]! } - public var Privacy_GroupsAndChannels_WhoCanAddMe: String { return self._s[3137]! } - public var Conversation_typing: String { return self._s[3139]! } - public var Paint_Masks: String { return self._s[3140]! } - public var Username_InvalidTaken: String { return self._s[3141]! } - public var Call_StatusNoAnswer: String { return self._s[3142]! } - public var TwoStepAuth_EmailAddSuccess: String { return self._s[3143]! } - public var SettingsSearch_Synonyms_Privacy_BlockedUsers: String { return self._s[3144]! } - public var Passport_Identity_Selfie: String { return self._s[3145]! } - public var Login_InfoLastNamePlaceholder: String { return self._s[3146]! } - public var Privacy_SecretChatsLinkPreviewsHelp: String { return self._s[3147]! } - public var Conversation_ClearSecretHistory: String { return self._s[3148]! } - public var NetworkUsageSettings_Title: String { return self._s[3150]! } - public var Your_cards_security_code_is_invalid: String { return self._s[3152]! } + public func Notification_CreatedChat(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3126]!, self._r[3126]!, [_0]) + } + public var AccessDenied_Settings: String { return self._s[3127]! } + public var Passport_Address_TypeUtilityBillUploadScan: String { return self._s[3128]! } + public var Month_ShortMay: String { return self._s[3129]! } + public var Compose_NewGroup: String { return self._s[3130]! } + public var Group_Setup_TypePrivate: String { return self._s[3132]! } + public var Login_PadPhoneHelpTitle: String { return self._s[3134]! } + public var Appearance_ThemeDayClassic: String { return self._s[3135]! } + public var Channel_AdminLog_MessagePreviousCaption: String { return self._s[3136]! } + public var AutoDownloadSettings_OffForAll: String { return self._s[3137]! } + public var Privacy_GroupsAndChannels_WhoCanAddMe: String { return self._s[3138]! } + public var Conversation_typing: String { return self._s[3140]! } + public var Paint_Masks: String { return self._s[3141]! } + public var Username_InvalidTaken: String { return self._s[3142]! } + public var Call_StatusNoAnswer: String { return self._s[3143]! } + public var TwoStepAuth_EmailAddSuccess: String { return self._s[3144]! } + public var SettingsSearch_Synonyms_Privacy_BlockedUsers: String { return self._s[3145]! } + public var Passport_Identity_Selfie: String { return self._s[3146]! } + public var Login_InfoLastNamePlaceholder: String { return self._s[3147]! } + public var Privacy_SecretChatsLinkPreviewsHelp: String { return self._s[3148]! } + public var Conversation_ClearSecretHistory: String { return self._s[3149]! } + public var NetworkUsageSettings_Title: String { return self._s[3151]! } + public var Your_cards_security_code_is_invalid: String { return self._s[3153]! } public func Notification_LeftChannel(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3154]!, self._r[3154]!, [_0]) + return formatWithArgumentRanges(self._s[3155]!, self._r[3155]!, [_0]) } public func Call_CallInProgressMessage(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3155]!, self._r[3155]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3156]!, self._r[3156]!, [_1, _2]) } - public var SaveIncomingPhotosSettings_From: String { return self._s[3157]! } - public var Map_LiveLocationTitle: String { return self._s[3158]! } - public var Login_InfoAvatarAdd: String { return self._s[3159]! } - public var Passport_Identity_FilesView: String { return self._s[3160]! } - public var UserInfo_GenericPhoneLabel: String { return self._s[3161]! } - public var Privacy_Calls_NeverAllow: String { return self._s[3162]! } + public var SaveIncomingPhotosSettings_From: String { return self._s[3158]! } + public var Map_LiveLocationTitle: String { return self._s[3159]! } + public var Login_InfoAvatarAdd: String { return self._s[3160]! } + public var Passport_Identity_FilesView: String { return self._s[3161]! } + public var UserInfo_GenericPhoneLabel: String { return self._s[3162]! } + public var Privacy_Calls_NeverAllow: String { return self._s[3163]! } public func Contacts_AddPhoneNumber(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3163]!, self._r[3163]!, [_0]) + return formatWithArgumentRanges(self._s[3164]!, self._r[3164]!, [_0]) } - public var TwoStepAuth_ConfirmationText: String { return self._s[3164]! } - public var ChatSettings_AutomaticVideoMessageDownload: String { return self._s[3165]! } + public var TwoStepAuth_ConfirmationText: String { return self._s[3165]! } + public var ChatSettings_AutomaticVideoMessageDownload: String { return self._s[3166]! } public func PUSH_CHAT_MESSAGE_VIDEOS(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3166]!, self._r[3166]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3167]!, self._r[3167]!, [_1, _2, _3]) } - public var Channel_AdminLogFilter_AdminsAll: String { return self._s[3167]! } - public var Tour_Title2: String { return self._s[3168]! } - public var Conversation_FileOpenIn: String { return self._s[3169]! } - public var Checkout_ErrorPrecheckoutFailed: String { return self._s[3170]! } - public var Wallpaper_Set: String { return self._s[3171]! } - public var Passport_Identity_Translations: String { return self._s[3173]! } + public var Channel_AdminLogFilter_AdminsAll: String { return self._s[3168]! } + public var Tour_Title2: String { return self._s[3169]! } + public var Conversation_FileOpenIn: String { return self._s[3170]! } + public var Checkout_ErrorPrecheckoutFailed: String { return self._s[3171]! } + public var Wallpaper_Set: String { return self._s[3172]! } + public var Passport_Identity_Translations: String { return self._s[3174]! } public func Channel_AdminLog_MessageChangedChannelAbout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3174]!, self._r[3174]!, [_0]) + return formatWithArgumentRanges(self._s[3175]!, self._r[3175]!, [_0]) } - public var Channel_LeaveChannel: String { return self._s[3175]! } + public var Channel_LeaveChannel: String { return self._s[3176]! } public func PINNED_INVOICE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3176]!, self._r[3176]!, [_1]) + return formatWithArgumentRanges(self._s[3177]!, self._r[3177]!, [_1]) } - public var SettingsSearch_Synonyms_Proxy_AddProxy: String { return self._s[3177]! } - public var PhotoEditor_HighlightsTint: String { return self._s[3178]! } - public var Passport_Email_Delete: String { return self._s[3179]! } - public var Conversation_Mute: String { return self._s[3181]! } - public var Channel_AdminLog_CanSendMessages: String { return self._s[3183]! } + public var SettingsSearch_Synonyms_Proxy_AddProxy: String { return self._s[3178]! } + public var PhotoEditor_HighlightsTint: String { return self._s[3179]! } + public var Passport_Email_Delete: String { return self._s[3180]! } + public var Conversation_Mute: String { return self._s[3182]! } + public var Channel_AdminLog_CanSendMessages: String { return self._s[3184]! } public func Notification_PassportValuesSentMessage(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3185]!, self._r[3185]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3186]!, self._r[3186]!, [_1, _2]) } - public var Calls_CallTabDescription: String { return self._s[3186]! } - public var Passport_Identity_NativeNameHelp: String { return self._s[3187]! } - public var Common_No: String { return self._s[3188]! } - public var Weekday_Sunday: String { return self._s[3189]! } - public var Notification_Reply: String { return self._s[3190]! } - public var Conversation_ViewMessage: String { return self._s[3191]! } + public var Calls_CallTabDescription: String { return self._s[3187]! } + public var Passport_Identity_NativeNameHelp: String { return self._s[3188]! } + public var Common_No: String { return self._s[3189]! } + public var Weekday_Sunday: String { return self._s[3190]! } + public var Notification_Reply: String { return self._s[3191]! } + public var Conversation_ViewMessage: String { return self._s[3192]! } public func Checkout_SavePasswordTimeoutAndFaceId(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3192]!, self._r[3192]!, [_0]) - } - public func Map_LiveLocationPrivateDescription(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3193]!, self._r[3193]!, [_0]) } - public var SettingsSearch_Synonyms_EditProfile_AddAccount: String { return self._s[3194]! } - public var Message_PinnedDocumentMessage: String { return self._s[3195]! } - public var DialogList_TabTitle: String { return self._s[3197]! } - public var ChatSettings_AutoPlayTitle: String { return self._s[3198]! } - public var Passport_FieldEmail: String { return self._s[3199]! } - public var Conversation_UnpinMessageAlert: String { return self._s[3200]! } - public var Passport_Address_TypeBankStatement: String { return self._s[3201]! } - public var Passport_Identity_ExpiryDate: String { return self._s[3202]! } - public var Privacy_Calls_P2P: String { return self._s[3203]! } + public func Map_LiveLocationPrivateDescription(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3194]!, self._r[3194]!, [_0]) + } + public var SettingsSearch_Synonyms_EditProfile_AddAccount: String { return self._s[3195]! } + public var Message_PinnedDocumentMessage: String { return self._s[3196]! } + public var DialogList_TabTitle: String { return self._s[3198]! } + public var ChatSettings_AutoPlayTitle: String { return self._s[3199]! } + public var Passport_FieldEmail: String { return self._s[3200]! } + public var Conversation_UnpinMessageAlert: String { return self._s[3201]! } + public var Passport_Address_TypeBankStatement: String { return self._s[3202]! } + public var Passport_Identity_ExpiryDate: String { return self._s[3203]! } + public var Privacy_Calls_P2P: String { return self._s[3204]! } public func CancelResetAccount_Success(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3205]!, self._r[3205]!, [_0]) + return formatWithArgumentRanges(self._s[3206]!, self._r[3206]!, [_0]) } - public var SocksProxySetup_UseForCallsHelp: String { return self._s[3206]! } + public var SocksProxySetup_UseForCallsHelp: String { return self._s[3207]! } public func PUSH_CHAT_ALBUM(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3207]!, self._r[3207]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3208]!, self._r[3208]!, [_1, _2]) } - public var Stickers_ClearRecent: String { return self._s[3208]! } - public var EnterPasscode_ChangeTitle: String { return self._s[3209]! } - public var Passport_InfoText: String { return self._s[3210]! } - public var Checkout_NewCard_SaveInfoEnableHelp: String { return self._s[3211]! } + public var Stickers_ClearRecent: String { return self._s[3209]! } + public var EnterPasscode_ChangeTitle: String { return self._s[3210]! } + public var Passport_InfoText: String { return self._s[3211]! } + public var Checkout_NewCard_SaveInfoEnableHelp: String { return self._s[3212]! } public func Login_InvalidPhoneEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3212]!, self._r[3212]!, [_0]) + return formatWithArgumentRanges(self._s[3213]!, self._r[3213]!, [_0]) } public func Time_PreciseDate_m3(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3213]!, self._r[3213]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3214]!, self._r[3214]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChannels: String { return self._s[3214]! } - public var Passport_Identity_EditDriversLicense: String { return self._s[3215]! } - public var Conversation_TapAndHoldToRecord: String { return self._s[3217]! } - public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChats: String { return self._s[3218]! } + public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChannels: String { return self._s[3215]! } + public var Passport_Identity_EditDriversLicense: String { return self._s[3216]! } + public var Conversation_TapAndHoldToRecord: String { return self._s[3218]! } + public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChats: String { return self._s[3219]! } public func Notification_CallTimeFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3219]!, self._r[3219]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3220]!, self._r[3220]!, [_1, _2]) } - public var Channel_EditAdmin_PermissionInviteViaLink: String { return self._s[3221]! } + public var Channel_EditAdmin_PermissionInviteViaLink: String { return self._s[3222]! } public func Generic_OpenHiddenLinkAlert(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3223]!, self._r[3223]!, [_0]) + return formatWithArgumentRanges(self._s[3224]!, self._r[3224]!, [_0]) } - public var DialogList_Unread: String { return self._s[3224]! } + public var DialogList_Unread: String { return self._s[3225]! } public func PUSH_CHAT_MESSAGE_GIF(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3225]!, self._r[3225]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3226]!, self._r[3226]!, [_1, _2]) } - public var User_DeletedAccount: String { return self._s[3226]! } + public var User_DeletedAccount: String { return self._s[3227]! } public func Watch_Time_ShortYesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3227]!, self._r[3227]!, [_0]) + return formatWithArgumentRanges(self._s[3228]!, self._r[3228]!, [_0]) } - public var UserInfo_NotificationsDefault: String { return self._s[3228]! } - public var SharedMedia_CategoryMedia: String { return self._s[3229]! } - public var SocksProxySetup_ProxyStatusUnavailable: String { return self._s[3230]! } - public var Channel_AdminLog_MessageRestrictedForever: String { return self._s[3231]! } - public var Watch_ChatList_Compose: String { return self._s[3232]! } - public var Notifications_MessageNotificationsExceptionsHelp: String { return self._s[3233]! } - public var AutoDownloadSettings_Delimeter: String { return self._s[3234]! } - public var Watch_Microphone_Access: String { return self._s[3235]! } - public var Group_Setup_HistoryHeader: String { return self._s[3236]! } - public var Activity_UploadingPhoto: String { return self._s[3237]! } - public var Conversation_Edit: String { return self._s[3239]! } - public var Group_ErrorSendRestrictedMedia: String { return self._s[3240]! } - public var Login_TermsOfServiceDecline: String { return self._s[3241]! } - public var Message_PinnedContactMessage: String { return self._s[3242]! } + public var UserInfo_NotificationsDefault: String { return self._s[3229]! } + public var SharedMedia_CategoryMedia: String { return self._s[3230]! } + public var SocksProxySetup_ProxyStatusUnavailable: String { return self._s[3231]! } + public var Channel_AdminLog_MessageRestrictedForever: String { return self._s[3232]! } + public var Watch_ChatList_Compose: String { return self._s[3233]! } + public var Notifications_MessageNotificationsExceptionsHelp: String { return self._s[3234]! } + public var AutoDownloadSettings_Delimeter: String { return self._s[3235]! } + public var Watch_Microphone_Access: String { return self._s[3236]! } + public var Group_Setup_HistoryHeader: String { return self._s[3237]! } + public var Activity_UploadingPhoto: String { return self._s[3238]! } + public var Conversation_Edit: String { return self._s[3240]! } + public var Group_ErrorSendRestrictedMedia: String { return self._s[3241]! } + public var Login_TermsOfServiceDecline: String { return self._s[3242]! } + public var Message_PinnedContactMessage: String { return self._s[3243]! } public func Channel_AdminLog_MessageRestrictedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3243]!, self._r[3243]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3244]!, self._r[3244]!, [_1, _2]) } public func Login_PhoneBannedEmailBody(_ _1: String, _ _2: String, _ _3: String, _ _4: String, _ _5: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3244]!, self._r[3244]!, [_1, _2, _3, _4, _5]) + return formatWithArgumentRanges(self._s[3245]!, self._r[3245]!, [_1, _2, _3, _4, _5]) } - public var Appearance_LargeEmoji: String { return self._s[3245]! } - public var TwoStepAuth_AdditionalPassword: String { return self._s[3247]! } + public var Appearance_LargeEmoji: String { return self._s[3246]! } + public var TwoStepAuth_AdditionalPassword: String { return self._s[3248]! } public func PUSH_CHAT_DELETE_YOU(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3248]!, self._r[3248]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3249]!, self._r[3249]!, [_1, _2]) } - public var Passport_Phone_EnterOtherNumber: String { return self._s[3249]! } - public var Message_PinnedPhotoMessage: String { return self._s[3250]! } - public var Passport_FieldPhone: String { return self._s[3251]! } - public var TwoStepAuth_RecoveryEmailAddDescription: String { return self._s[3252]! } - public var ChatSettings_AutoPlayGifs: String { return self._s[3253]! } - public var InfoPlist_NSCameraUsageDescription: String { return self._s[3255]! } - public var Conversation_Call: String { return self._s[3256]! } - public var Common_TakePhoto: String { return self._s[3258]! } - public var Channel_NotificationLoading: String { return self._s[3259]! } + public var Passport_Phone_EnterOtherNumber: String { return self._s[3250]! } + public var Message_PinnedPhotoMessage: String { return self._s[3251]! } + public var Passport_FieldPhone: String { return self._s[3252]! } + public var TwoStepAuth_RecoveryEmailAddDescription: String { return self._s[3253]! } + public var ChatSettings_AutoPlayGifs: String { return self._s[3254]! } + public var InfoPlist_NSCameraUsageDescription: String { return self._s[3256]! } + public var Conversation_Call: String { return self._s[3257]! } + public var Common_TakePhoto: String { return self._s[3259]! } + public var Channel_NotificationLoading: String { return self._s[3260]! } public func Notification_Exceptions_Sound(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3260]!, self._r[3260]!, [_0]) + return formatWithArgumentRanges(self._s[3261]!, self._r[3261]!, [_0]) } public func PUSH_CHANNEL_MESSAGE_VIDEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3261]!, self._r[3261]!, [_1]) + return formatWithArgumentRanges(self._s[3262]!, self._r[3262]!, [_1]) } - public var Permissions_SiriTitle_v0: String { return self._s[3262]! } + public var Permissions_SiriTitle_v0: String { return self._s[3263]! } public func Login_ResetAccountProtected_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3263]!, self._r[3263]!, [_0]) + return formatWithArgumentRanges(self._s[3264]!, self._r[3264]!, [_0]) } - public var Channel_MessagePhotoRemoved: String { return self._s[3264]! } - public var Common_edit: String { return self._s[3265]! } - public var PrivacySettings_AuthSessions: String { return self._s[3266]! } - public var Month_ShortJune: String { return self._s[3267]! } - public var PrivacyLastSeenSettings_AlwaysShareWith_Placeholder: String { return self._s[3268]! } - public var Call_ReportSend: String { return self._s[3269]! } - public var Watch_LastSeen_JustNow: String { return self._s[3270]! } - public var Notifications_MessageNotifications: String { return self._s[3271]! } - public var WallpaperSearch_ColorGreen: String { return self._s[3272]! } - public var BroadcastListInfo_AddRecipient: String { return self._s[3274]! } - public var Group_Status: String { return self._s[3275]! } + public var Channel_MessagePhotoRemoved: String { return self._s[3265]! } + public var Common_edit: String { return self._s[3266]! } + public var PrivacySettings_AuthSessions: String { return self._s[3267]! } + public var Month_ShortJune: String { return self._s[3268]! } + public var PrivacyLastSeenSettings_AlwaysShareWith_Placeholder: String { return self._s[3269]! } + public var Call_ReportSend: String { return self._s[3270]! } + public var Watch_LastSeen_JustNow: String { return self._s[3271]! } + public var Notifications_MessageNotifications: String { return self._s[3272]! } + public var WallpaperSearch_ColorGreen: String { return self._s[3273]! } + public var BroadcastListInfo_AddRecipient: String { return self._s[3275]! } + public var Group_Status: String { return self._s[3276]! } public func AutoNightTheme_LocationHelp(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3276]!, self._r[3276]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3277]!, self._r[3277]!, [_0, _1]) } - public var ShareMenu_ShareTo: String { return self._s[3277]! } - public var Conversation_Moderate_Ban: String { return self._s[3278]! } + public var ShareMenu_ShareTo: String { return self._s[3278]! } + public var Conversation_Moderate_Ban: String { return self._s[3279]! } public func Conversation_DeleteMessagesFor(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3279]!, self._r[3279]!, [_0]) + return formatWithArgumentRanges(self._s[3280]!, self._r[3280]!, [_0]) } - public var SharedMedia_ViewInChat: String { return self._s[3280]! } - public var Map_LiveLocationFor8Hours: String { return self._s[3281]! } + public var SharedMedia_ViewInChat: String { return self._s[3281]! } + public var Map_LiveLocationFor8Hours: String { return self._s[3282]! } public func PUSH_PINNED_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3282]!, self._r[3282]!, [_1]) + return formatWithArgumentRanges(self._s[3283]!, self._r[3283]!, [_1]) } public func PUSH_PINNED_POLL(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3283]!, self._r[3283]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3284]!, self._r[3284]!, [_1, _2]) } public func Map_AccurateTo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3285]!, self._r[3285]!, [_0]) + return formatWithArgumentRanges(self._s[3286]!, self._r[3286]!, [_0]) } - public var Map_OpenInHereMaps: String { return self._s[3286]! } - public var Appearance_ReduceMotion: String { return self._s[3287]! } + public var Map_OpenInHereMaps: String { return self._s[3287]! } + public var Appearance_ReduceMotion: String { return self._s[3288]! } public func PUSH_MESSAGE_TEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3288]!, self._r[3288]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3289]!, self._r[3289]!, [_1, _2]) } - public var Channel_Setup_TypePublicHelp: String { return self._s[3289]! } - public var Passport_Identity_EditInternalPassport: String { return self._s[3290]! } - public var PhotoEditor_Skip: String { return self._s[3291]! } - public func MessageTimer_ShortHours(_ value: Int32) -> String { + public var Channel_Setup_TypePublicHelp: String { return self._s[3290]! } + public var Passport_Identity_EditInternalPassport: String { return self._s[3291]! } + public var PhotoEditor_Skip: String { return self._s[3292]! } + public func Call_ShortSeconds(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_Weeks(_ value: Int32) -> String { + public func MuteFor_Hours(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedPolls(_ value: Int32) -> String { + public func Conversation_StatusMembers(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[2 * 6 + Int(form.rawValue)]!, stringValue) } - public func CreatePoll_AddMoreOptions(_ value: Int32) -> String { + public func LiveLocationUpdated_MinutesAgo(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[3 * 6 + Int(form.rawValue)]!, stringValue) } - public func ChatList_DeleteConfirmation(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[4 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_ShortWeeks(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[5 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Forward_ConfirmMultipleFiles(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[6 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGE_FWDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, selector) - return String(format: self._ps[7 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func ServiceMessage_GameScoreExtended(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[8 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGES(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, selector) - return String(format: self._ps[9 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func PUSH_CHAT_MESSAGE_PHOTOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, selector) - return String(format: self._ps[10 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func Map_ETAHours(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[11 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, selector) - return String(format: self._ps[12 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func Map_ETAMinutes(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[13 * 6 + Int(form.rawValue)]!, stringValue) - } - public func AttachmentMenu_SendItem(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[14 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessagePoll_VotedCount(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[15 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedStickers(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[16 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Contacts_ImportersCount(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[17 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedContacts(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[18 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHANNEL_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, selector) - return String(format: self._ps[19 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func Conversation_StatusMembers(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[20 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedAudios(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[21 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notifications_Exceptions(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[22 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notification_GameScoreSelfExtended(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[23 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedMessages(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[24 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGE_ROUNDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, selector) - return String(format: self._ps[25 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func MessageTimer_ShortSeconds(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[26 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notification_GameScoreExtended(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[27 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ServiceMessage_GameScoreSimple(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[28 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHANNEL_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, selector) - return String(format: self._ps[29 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func MessageTimer_ShortMinutes(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[30 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notification_GameScoreSelfSimple(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[31 * 6 + Int(form.rawValue)]!, stringValue) - } - public func SharedMedia_Photo(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[32 * 6 + Int(form.rawValue)]!, stringValue) - } - public func SharedMedia_File(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[33 * 6 + Int(form.rawValue)]!, stringValue) - } public func PUSH_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, selector) - return String(format: self._ps[34 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func MessageTimer_ShortDays(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[35 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MuteExpires_Days(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[36 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Hours(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[37 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Days(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[38 * 6 + Int(form.rawValue)]!, stringValue) - } - public func LastSeen_MinutesAgo(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[39 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Call_Seconds(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[40 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PrivacyLastSeenSettings_AddUsers(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[41 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Months(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[42 * 6 + Int(form.rawValue)]!, stringValue) - } - public func AttachmentMenu_SendPhoto(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[43 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Media_SharePhoto(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[44 * 6 + Int(form.rawValue)]!, stringValue) - } - public func LiveLocation_MenuChatsCount(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[45 * 6 + Int(form.rawValue)]!, stringValue) - } - public func SharedMedia_DeleteItemsConfirmation(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[46 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MuteFor_Days(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[47 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Call_ShortMinutes(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[48 * 6 + Int(form.rawValue)]!, stringValue) - } - public func DialogList_LiveLocationChatsCount(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[49 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedFiles(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[50 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Media_ShareVideo(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[51 * 6 + Int(form.rawValue)]!, stringValue) - } - public func UserCount(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[52 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Minutes(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[53 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MuteExpires_Minutes(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[54 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Chat_DeleteMessagesConfirmation(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[55 * 6 + Int(form.rawValue)]!, stringValue) - } - public func SharedMedia_Generic(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[56 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PasscodeSettings_FailedAttempts(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[57 * 6 + Int(form.rawValue)]!, stringValue) - } - public func StickerPack_AddStickerCount(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[58 * 6 + Int(form.rawValue)]!, stringValue) - } - public func SharedMedia_Link(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[59 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notifications_ExceptionMuteExpires_Minutes(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[60 * 6 + Int(form.rawValue)]!, stringValue) - } - public func StickerPack_RemoveMaskCount(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[61 * 6 + Int(form.rawValue)]!, stringValue) - } - public func AttachmentMenu_SendVideo(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[62 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Passport_Scans(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[63 * 6 + Int(form.rawValue)]!, stringValue) - } - public func SharedMedia_Video(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[64 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Call_Minutes(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[65 * 6 + Int(form.rawValue)]!, stringValue) - } - public func StickerPack_RemoveStickerCount(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[66 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedVideos(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[67 * 6 + Int(form.rawValue)]!, stringValue) - } - public func AttachmentMenu_SendGif(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[68 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHANNEL_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, selector) - return String(format: self._ps[69 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func Wallpaper_DeleteConfirmation(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[70 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedGifs(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[71 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Watch_LastSeen_HoursAgo(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[72 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ChatList_SelectedChats(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[73 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MuteFor_Hours(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[74 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, selector) - return String(format: self._ps[75 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func QuickSend_Photos(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[76 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Invitation_Members(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[77 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGE_VIDEOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, selector) - return String(format: self._ps[78 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func PUSH_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, selector) - return String(format: self._ps[79 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func PUSH_CHANNEL_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, selector) - return String(format: self._ps[80 * 6 + Int(form.rawValue)]!, _1, _2) + return String(format: self._ps[4 * 6 + Int(form.rawValue)]!, _1, _2) } public func Notification_GameScoreSimple(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[81 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notifications_ExceptionMuteExpires_Hours(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[82 * 6 + Int(form.rawValue)]!, stringValue) - } - public func StickerPack_AddMaskCount(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[83 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedLocations(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[84 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Media_ShareItem(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[85 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, selector) - return String(format: self._ps[86 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func ForwardedVideoMessages(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[87 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[5 * 6 + Int(form.rawValue)]!, stringValue) } public func MessageTimer_Years(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[88 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[6 * 6 + Int(form.rawValue)]!, stringValue) } - public func Conversation_StatusOnline(_ value: Int32) -> String { + public func Notification_GameScoreSelfSimple(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[89 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHANNEL_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, selector) - return String(format: self._ps[90 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func Call_ShortSeconds(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[91 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ServiceMessage_GameScoreSelfExtended(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[92 * 6 + Int(form.rawValue)]!, stringValue) - } - public func GroupInfo_ParticipantCount(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[93 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedPhotos(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[94 * 6 + Int(form.rawValue)]!, stringValue) - } - public func LastSeen_HoursAgo(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[95 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notifications_ExceptionMuteExpires_Days(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[96 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Seconds(_ value: Int32) -> String { - let form = presentationStringsPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[97 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[7 * 6 + Int(form.rawValue)]!, stringValue) } public func Watch_LastSeen_MinutesAgo(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[98 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[8 * 6 + Int(form.rawValue)]!, stringValue) } - public func MuteExpires_Hours(_ value: Int32) -> String { + public func PrivacyLastSeenSettings_AddUsers(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[99 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[9 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Call_Minutes(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[10 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortHours(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[11 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Call_ShortMinutes(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[12 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ServiceMessage_GameScoreSelfExtended(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[13 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notification_GameScoreExtended(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[14 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Chat_DeleteMessagesConfirmation(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[15 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedAuthorsOthers(_ selector: Int32, _ _0: String, _ _1: String) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[16 * 6 + Int(form.rawValue)]!, _0, _1) + } + public func ForwardedPhotos(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[17 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortDays(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[18 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[19 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func PUSH_CHANNEL_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[20 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func Notifications_ExceptionMuteExpires_Minutes(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[21 * 6 + Int(form.rawValue)]!, stringValue) } public func Conversation_LiveLocationMembersCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[100 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[22 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedAuthorsOthers(_ selector: Int32, _ _0: String, _ _1: String) -> String { + public func PUSH_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, selector) - return String(format: self._ps[101 * 6 + Int(form.rawValue)]!, _0, _1) + return String(format: self._ps[23 * 6 + Int(form.rawValue)]!, _1, _2) } - public func StickerPack_StickerCount(_ value: Int32) -> String { + public func DialogList_LiveLocationChatsCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[102 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[24 * 6 + Int(form.rawValue)]!, stringValue) } - public func LiveLocationUpdated_MinutesAgo(_ value: Int32) -> String { + public func PUSH_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[25 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func PUSH_CHAT_MESSAGE_ROUNDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[26 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func Map_ETAHours(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[103 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[27 * 6 + Int(form.rawValue)]!, stringValue) } - public func ServiceMessage_GameScoreSelfSimple(_ value: Int32) -> String { + public func MessageTimer_Minutes(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[104 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[28 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[29 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func Conversation_StatusOnline(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[30 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortSeconds(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[31 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MuteExpires_Days(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[32 * 6 + Int(form.rawValue)]!, stringValue) + } + public func LiveLocation_MenuChatsCount(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[33 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Watch_LastSeen_HoursAgo(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[34 * 6 + Int(form.rawValue)]!, stringValue) } public func Conversation_StatusSubscribers(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[105 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[35 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Wallpaper_DeleteConfirmation(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[36 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[37 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func ForwardedVideoMessages(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[38 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedGifs(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[39 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notifications_ExceptionMuteExpires_Hours(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[40 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedVideos(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[41 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ChatList_SelectedChats(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[42 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Invitation_Members(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[43 * 6 + Int(form.rawValue)]!, stringValue) + } + public func StickerPack_AddMaskCount(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[44 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notification_GameScoreSelfExtended(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[45 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[46 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func LastSeen_HoursAgo(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[47 * 6 + Int(form.rawValue)]!, stringValue) + } + public func StickerPack_RemoveMaskCount(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[48 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedMessages(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[49 * 6 + Int(form.rawValue)]!, stringValue) + } + public func StickerPack_AddStickerCount(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[50 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ServiceMessage_GameScoreSimple(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[51 * 6 + Int(form.rawValue)]!, stringValue) + } + public func SharedMedia_Photo(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[52 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Seconds(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[53 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MuteFor_Days(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[54 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Hours(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[55 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ChatList_DeleteConfirmation(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[56 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Passport_Scans(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[57 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notifications_ExceptionMuteExpires_Days(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[58 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortMinutes(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[59 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MuteExpires_Hours(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[60 * 6 + Int(form.rawValue)]!, stringValue) + } + public func LastSeen_MinutesAgo(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[61 * 6 + Int(form.rawValue)]!, stringValue) + } + public func GroupInfo_ParticipantCount(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[62 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedPolls(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[63 * 6 + Int(form.rawValue)]!, stringValue) + } + public func SharedMedia_Link(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[64 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHAT_MESSAGE_PHOTOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[65 * 6 + Int(form.rawValue)]!, _2, _1, _3) } public func InviteText_ContactsCountText(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[106 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[66 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MuteExpires_Minutes(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[67 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Map_ETAMinutes(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[68 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Media_ShareItem(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[69 * 6 + Int(form.rawValue)]!, stringValue) } public func Watch_UserInfo_Mute(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[70 * 6 + Int(form.rawValue)]!, stringValue) + } + public func AttachmentMenu_SendVideo(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[71 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHAT_MESSAGE_VIDEOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[72 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func ForwardedLocations(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[73 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Weeks(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[74 * 6 + Int(form.rawValue)]!, stringValue) + } + public func SharedMedia_File(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[75 * 6 + Int(form.rawValue)]!, stringValue) + } + public func SharedMedia_DeleteItemsConfirmation(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[76 * 6 + Int(form.rawValue)]!, stringValue) + } + public func CreatePoll_AddMoreOptions(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[77 * 6 + Int(form.rawValue)]!, stringValue) + } + public func QuickSend_Photos(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[78 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHAT_MESSAGES(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[79 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func StickerPack_StickerCount(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[80 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Contacts_ImportersCount(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[81 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[82 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func ForwardedContacts(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[83 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessagePoll_VotedCount(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[84 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notifications_Exceptions(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[85 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Days(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[86 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Months(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[87 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHAT_MESSAGE_FWDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[88 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func Forward_ConfirmMultipleFiles(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[89 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedStickers(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[90 * 6 + Int(form.rawValue)]!, stringValue) + } + public func UserCount(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[91 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[92 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func ForwardedFiles(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[93 * 6 + Int(form.rawValue)]!, stringValue) + } + public func AttachmentMenu_SendGif(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[94 * 6 + Int(form.rawValue)]!, stringValue) + } + public func AttachmentMenu_SendItem(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[95 * 6 + Int(form.rawValue)]!, stringValue) + } + public func StickerPack_RemoveStickerCount(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[96 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedAudios(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[97 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortWeeks(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[98 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PasscodeSettings_FailedAttempts(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[99 * 6 + Int(form.rawValue)]!, stringValue) + } + public func SharedMedia_Generic(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[100 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Media_SharePhoto(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[101 * 6 + Int(form.rawValue)]!, stringValue) + } + public func SharedMedia_Video(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[102 * 6 + Int(form.rawValue)]!, stringValue) + } + public func AttachmentMenu_SendPhoto(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[103 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Call_Seconds(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[104 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Media_ShareVideo(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[105 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ServiceMessage_GameScoreExtended(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[106 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ServiceMessage_GameScoreSelfSimple(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[107 * 6 + Int(form.rawValue)]!, stringValue) diff --git a/TelegramUI/Resources/PresentationStrings.mapping b/TelegramUI/Resources/PresentationStrings.mapping index c181e222681d7c0a30d7661449ba3e9c21f64cba..e96185d9244174a068d25fe79becc3db865ba9e8 100644 GIT binary patch delta 10030 zcmZWv33!uL*6xXHWcL8;D6lIywaa<6X(SPP=M*ZJ=lNR-V9(dY&@43r&&pGdT&$)f+ zQs~7?p|ou!JwvoeGbuJCB&0_1`yH-EpS56~yVY+Ur#L<64f!%GB&3fVwt4HD%35rV ziqBf>@H-VT`V~fF@N=r7G}~>9ty2}dOYz~i-@Kur1;gSE7^_fxKFqR~+FInCBRqTr zH+~=p^45Nb#K9i~4BA zzQ5vvkIX|gw9{{hLM!4eFmMW>dLX^sIhKufzv65o|SzC>G6DRB*oBk z{3E7oo)1^A982UeqbO1H+i>-Al94^5s87c4ARUic)m}%Nt$uOO&GdZsDSmtu<dn=TpY8578TmdBqN!)7@C^@cFIP4wqQzBa8?Gf~pqUymrN2(CTk;dwq8btzG1T z0^IM%++0Apnoq)2ccj@+?C{y<1+4E9pDDnVU*?YrpnxlUs{l7}mD36-i~hShFBVe2)X%Z0u<0UqON-lOEoySReM)tc+b=)v?|erQWn_F2JX!VR znsIZh%PK2Nisu$gE-tGQC;JkECN+A7S$^eL+=LnQH9t~>y{_>KML57We6StL#b-z zD;aXrTbxpYh5y6(C1j!h^4t>YPv7%HCGeUb_+SYoYkmw@ujU&0QVE3;@n7G$>$5*Io># z-W*kmZXMrU3X9WoT`AqAHDINF@Ij+G>b!wpEG3;LLZ|Ls)1UP_;M|e?V<`=yXdW~U zbNcYKaZpYyFB*r1;&``c#q+6gR7eR-W%#^APAh|1n|O2?D$G;-IPAi|zz;3ty=Lx;or0pS7gL<6qqUO~WA3U!7BJzN;UoOW~Dz8O=*8$fPOIsmJ@7_;>|HQ6ZnMfMFN$rxlo0 z%%PPy=~!V7D=s@xDsBlg9IVl`z8z{9PptHCA+gg{{6xv5s{(6$vYqoL@y* znkt=I`AGsVtD-(s%^g+nl1Us>L+J*$%Wta>Ku|4TtHPlsb4)eetC_0fn};cd8-c5u zX*xCEWmFFx)6?`G(@drr{8cp$JCma)Qh|0Bj*zOJj7;Q~iTIM)eE&r1tDTEpi+bK` z*7YEJ9lt#hhBlACo{0VGIeHRh4zfc|SkP2up0&j5b$i9-Dd@z%kWxp3wMG%aQS>(G zIOajJgvmyuPQB@gRU?aI_~0ap(l$XpU0TeANfbv8{@Wy&|9tVa1F4xu*N~Z7cxDZa z)Vd%VuWqb2hKg0)I`xd2sCMp%m4VK~U)0cm%mt7U?kb_8Xj}mxs(fxidEw*=VQpTF zX0t7oj9ghuaax~ft5MG+sF!c_9_qB!D@|^vU6J47$C!u!MP9|`SE}7k_`cm<hl>@qRpb2_^HpwG^vuL)*kRCQ?GwIK>uRWFb0J)w7Q#s2@IIkPf#9J!t|3Vk&Hl zgx+f$OC;7U)~RQ8$=p7f60}PoWaOJ(xcZ676s}pSQ)ysAe2uM5u~&QDiyQ%KxgTO? z^}^0LzBL&dT+X^F0Md5!W~<+HC2{E#P=gg{W(JQCM=SZ^DKLRmd~6C0(LA8zt}$fh z|4t#jX0=WrV_1v)y0yY+2Mt)%qX| zdpa)jQOru?|E(m8uE$V!@CgiQcInjfFC_Bi=@d=7`Nnk0((Z*cm{OcskMP^*mT0)2 z^Jh?I`V$zEoIpgy61&6i7Qo^1*Sg(KalEH^^$dXZ0X{T?(lrNlyutx?@jo*VOb)Sj zCS{I1j1>eB1}RImt-e_pm6&`axOh>MQr|4dX06+Aa~8C?TV3)DN7+6TV15i@d8(~F znRh!7Se~5;4If8eDqqPZQ=cN6(^=~Pj}q5@0{tfSY)35XXHkUqB%0ak#Ig(?GmCWe zG>@M}>DphTH%-0y7YlEkMd8|K(6mSo$*pO!d6ja9OERx#(Jwg3Pfsod#Myttm$4KW zB+Z7mKF^lfl&$@(T=?x?>0uR8dB0=NY(&8q&}~%fpqw+askin;G?O@g2PGJ$IDC#E zi8;;JX9IoDuw@P)^DK{l|AG^gmraqe?`66Bxev^S z8l}G5Wnbm!xpWV`&ZTn^Y2V=1xls6%HhB<`Mh z*zPLNnn!&#f6=jRF%9Gs^RULJ{PsNHK(KC!M)>CxS*ASM82?9)$wN!Cc*cJ=9YdZDP{3K4blOF6X*Dl%H zY o+yq{|9?N^|z|ntTc7N&7Z`u*f|0%(PzqeD0=3AYbb~cqqC`d8B;|hhc(*6Z$ zp*mcWq*UYG4p;DZvE?o9QlNqVKq^zs`&(ZL@89!P1=ji_I#VQFVM_ySS}=h`^(H52 z#Z2O=2Fl3Npi@wRa(AP{Wd(T1fYXbfMdCt?|2Mf)~bb zH_%<0-g@<_CT{CyG8o{cUa$(WOE?c{1ku-F-d$?mlSV$;2JBnbNRb-7UOoRwVtk>^ zRin7<6^h*<0n-4{6fnzpeyb5U9mStC!d+tc$3_|krZ=pKQZ=!9$++@_SNz(I%Y%+%q6~{{EISx2W3b#9GnAUzlzKaxpQDuRlU5day}r+YoWOfjp;~GPPEW zr3iOV0fC>?=r znO3L7xS-bpdyB(WCAS`_XM9y6FKr=x+9-%g)@lRBTZ>ygPDeeMfcTox7&1zG|1Bi7 z`DiAyr0LQa}{!u3w*9fub#}w()Sodv7YlPK<-x*0>d}BC`?;|CF0cu zkHzs(7xe~%eAY!4O{u&W{>DY2iDi%w`Uvn<+^nRl6Ikzt$CYzGH)2kOUj1=S0@t}= zWtHr414FBMkDKBxHJB~%TcT4SnYEXC-L2BxYxx~FXzOIY<))mhDG(LzS?TsW8pJ1q z@K`5^9NRARFcri7)m^WcxXuH!oTlgHbqMa!`d+-vLou4^^2}kaOCTFEgJ1XH8fJ3( zQrL`T0mWy}#(WV)D{LO=Z{?0QrQ99ZMogKD@px&u&IJe%b!Y~uP{#raH`b$#e<3pX z+z$VCKCu8MsPMT3!1M-4q^KXQN!Irmc%xp>MZVh$Ty5eCFAW9PT&F3e?k7j-i zKQvCgI`J)2_ylFKboLgG_95$WalVgoEN-kDAw4M1d9T6s?uq*-A#uD!qF4 zR;qrI;!~vYKcMGykwU^ow0yl4wziu8-3slm;j}hNPg{%4g!Y4$t0p?$$m6;SBYpC62F@BI*6S4UoJZeE>V8fDsGvfgALEK|_NB7`2gW7vh8+ zyl^34qmy?ogmHB7YYX9ZTlfY#Q@3KeFjT>>Ky@2H{cdY{n_jI>Fmd@Jfq>5UcLw+Y6q`d1V7jrz!RG!^1JkE$4U#&+CqlgIn8dS#h{COICn9bO?$Da zh<@G04<~9LXol?Ly2UhJ`vivjt7lu{kZpu<^Gb>gYiJPKe3CCOMr3}9wM+2h0Ou}2 zct6C`m%w)q>s9iaG9{oN!2*ICfVhGa*j)9BwaVWV$TN-xEkK6bWBeYL&>YvR*V>Jt z!^Ivagzt<*wQtT+82GRF{-xOCX+FG^`ltUI>k40*>{Gm=4rN6U>#mETJLFmZb}3Nz zHxNtY^Ja?I$z(}j$Mn?J_A6N#(yufcQgOXq5@0X#*bPADa zaI9L@6snFbh|-)!jN23^f_t1u4M5T!ydMyER{D*uyK?iAUQLgP<*WB2Gx`Iz&r#2K zQrWniVv=7*GZH5#lBsW*%dRX!ja8iK6)s*5OMI1`%WUwYMO6i09r98v9X=vQP;D!(?HERd0KX(OLHD!{#-U6ZYP8G0;C57YN;37kygLM z-?W23y~~CbWYxZh(ZPaNtIwT0;@cVs|;+* zBjM&MzpxUd>926w)h0u&S7~uOCBS^Tbrof3Kf}ZvHD8y=qgSC2@i)DCGa->ZtKh|- z^Ws$?NPmY!-@s>{T7|^p3w~=Az~D>1xeDCzD`{&Z1517lQDKxtKdHN-dLp;GhA{zj z-3}p4R>rk&xa9#Peb+H=Q5S@p`}P3rjo@;UkXMw{)D)DK%pE(mSlIAQzVrZM(LXt2 zH7@R3NWyW=6n7hzzSFC93lbt~7kiX$6Z#h~SdBFE-`usD(#^LpNkroS?u#l<&(8nh zw^vhk%723gsPQ98TZ`NX#bEvc%le+9AB185AiO?KhF!xX#pCu$Nc<73VU;LJ7`XjG zINkvvR1%+fh^$FT=oPvbpyGmU^gMf*`PxI2os<$B7uH+u zw%L1(2)1~oO`!t>XGTl6>ZjoIL5o7aH^=kVcm)L%2eAh5E}J;Kg%v5FBt zC9_fUe2JQY2G#Ah$Yl987qA*6IL&{Wa+aUA! z%p*wH?lh>Uvr<{Vo(!6y2DRfuOO#N1fF0e1=_X0_XRZe`yc^8{-2pO&J23~8b=P{h z-`$8kGJ0!A$Hvj7WEdwIDoME0u*k1a2f(Zh+!P z^8)Oe!CNFVg`Q)5$#MYV?;GGS>}hc zcuW`WXEr*`YUcnHSi1n+bI_DJQmguF`Kd0%!MS{<3;WdZX%*HcGbNcN`0#Xw>j<%N z^d?x~Jnpv%*Iv)#H_?D3JJu0?GZi%$kIkcaQ391P(7+ov!H^pbeA7slEte=#C*Ko= z#WwNvO@IgoN2vhx`LOj97S%E&lq*%3N;A(?@u5y$sZyH7g$)EX0<^(_eF0)#(HZ~_ zk2q_t)(aWb*1k$%!)7SJ$0?ifA$~5{Ou0i^F(?wFAgWhNbZbMWu(Ue-YU@n zI=XW+g3%&_Iyybk5F~_RU@>3XjFR*cj@kk)vXn<{q2b`73%4L@FXz2mpoVrny@j&V zS733$CaY~epMYCbx)rCrq{ZfNiiK7h)O`nI*|-()b`@K<0zDqU46|?`HU9%$h7ekf z9`V`TPjRBg<+E1bSuF3Mp|!#_6Zz6siZwq3c?rnkkqRZ?+S~QthdF|A+v|7` zQlow-ZmJg${V&(sdh8AN>*2ZH(lF?huy7c<^-a2>Z9QC+c@u08117x?NPw| zc8mreNH;!8VIZ|zAH|jKA-H-j5CSTwgcw(U?yNQnv7~^ zb10W@N7-jD%+3#&JKvl77=8l&`?za62*Z9%8KTa8JR6CBA9_pxLJmF7rX4WsCwSxz zM9nAJhL-jKBxAUsA3Rsw{6XHg168I&=uH-{2!>*%-suRu+a2bA>_A$7#2`ysm$vC* zDiKJ!1B$rBqg=ZadOOBTcEWd0@Q$6>_9VZ&6YBXDf3_1>_cTZEf(!o|8^p55fKRC2 zMZL7opxsZ+d)~~gyHNam7EKcn))aT;>~`yO(lIZ(_lcDSa0)1cfm+AmMb4+;7aj-cx`R88fphf2u*3l2(?21X zHClf2FtilPUHd6cHyzoP4}X4v`qTNtct}>94K)ryu6pyAM-glV_@zNd<}|xqSfhCV z2_$~vOcf3nPT&&(FOl~=N%5ibBnFN?fS3@$=|^D*ksuwP4=-8dN10EtNAar% zU`NqB@ffZphTTVD9esGmlW4_q`yr$eaUtr;ZOK~j;hK1M9>m{zhze!4dTWe1BFK@7 zM5#ZK7aXCuFsY3iBj+3dq?%+O-*}8dHAx|S77;3WQq|;LWF@N9bDIe90n@10_ytv2C$0osT^Q&1Ue$ zL&#(^Lj+2z(Y{dr-(yI!vv~g@%1p?{M4`5y68@ULy#5HKB=if8L7jm=VGz#QpKlzd z!Nwen34HDulT{So0KRpIQj&8qA|CL{Tx|~6zoRGCDK>f%5~?;u5E*&fc|7I`sP;}Vn1Pbw=_i0m zck#q0QDN;oK=J0_J>7#PVctC!D(>iBzVIY`VHp2qKjseSs|OLp?&Cd2kxq_)Y~ZFx z290VYdc?tgdec%}qtGcLWY39%6L99yTyd1rhm66f2+%$ECEg-^`REa(>SO>>%KS>pSagYl1>V_&x5x^E z_<&MAdk`h-adImQm2v(N+{Ad{gC^4i%=zWPL=Cx|FFXZQui&%$Da}+Fl$zLz!lEda zi#omE?W^LAk72E9b|0hEw26>P#D6dz`Rr{i1NZg%;kZ(LlZ0=X(*nLw137WSJ=fGd zsg?&mj;wPs#_+dH`1_J%-;|*2&x%|^sZ)98Q^4|R7!Uk0h4k3zob?#MYesNZ&ko&x zc{CFP0$Ri+$%D<32UBm{5t=v~{Xf&5xC`GLw!zrJGb0{HWUu3_LohrWUwRzxmGdwo zfIne^llkgH)UNLmqsD?W;ZK45P>sj$v-5Rm)TBUGIinGK?`LsY5UQJrb$WCmc4+8EJ6!c zI4Zj!$X;|*+*n2(SG3HG!Ne=+8KQ-ngx*0xK~;*mvo+i6b@}1y2Mp8fO;_n7h44dwxK3EYHbP|7>#kogg!zU|E z?pCEPZxLboDPB2}(h{ErH4?*8r7hp>^4V*Be!=9*-|@MT)L;7ySS-Sp62sb2)LZ+U zy5HbWjE4NO(n?!?rQGclj~PYT^gO#q(ExgZw~wM^dYLDUplI$MMTvBpua1InXV^HJ zEW^%Wk8mt2u{T>Q8r*H=PJ6B5m1q7wAWwdS-Dj(7a<~GDlC)RZH5%K##vStK58O4H z66kf_J)B~7c}{n2qhxx6zn0WD*)WC%(px-y3}w*UTs;Otyu-`JP=C$&P|=~7!txcT zv&Cum$W`z1g)vk@-E7H){1bCy^0-PpS9fKk|%x$N^jo0pQ3{Al3RVm({0pG z`!S}IdFMJZh1r~K_C?+@mHQJuVWX@Op9Z!ow>w-uYgvoW>2N7^a=VM5MB~?1>vOa^ ze2c75=^}@#ew@8Yk@QR4Cyz3;m%$d#DUoChtz6WsQvSxX^C(mMcTh5T(gS4TeRh{B$*lcSo*^PI7O z6;NOL7yqGvvgqG@O>+K+b%pTEAF)18^u8mSSKLLx>Ty5uv_h=ILP*9fGoSDM)V=0{O;MTDq-pP-R#Z|Q+ zCh)o06sIqA*=wAt+JgDwSQ<|u+;FmY}cWcg(R8MJ*dP8XZkM~fjvanzshn+Syt;5idvzJa`GBALj_ zTPNcDY<_Mc4biRGb)EVQ*DejAVBSrI|-zKM6wl z4N7gJyX7|E%hmDVhbWF;D?uRG_=6Hkr#$|-1Uu$)QYl0#l-3`lf~+|GLMV;pj#9we zIL@u27}2~xT73I*C>8NHrEtFq999O=irH2M(Mot)8TKpXWo3x>G6<0&+*1?ywKD2M zlh`(m%>3^%ilhqGmQ$LxQq>C-$+mL%!&J7H)7_dXoyc_=`FJ_$X_^#fjFdw=9nA4O zCyk73nMA#`GcX>??r_+;XcGKjnvI~0pgH`~Bv-yFqVlcAG(zAzd1+#utoKRNu@F07!))cM#=CRAhqmrHS4Z8fk>kxyxo zTR1@+Ebo)WyTMFN+*N_yTzsJdF6?Hi#BR+zuoBU*0K6G&w~$fHxZ4m~sVr2(!NW@` z0WV%YS_yUf_?=3+i(2?bC8cXyvBV;CC6Ath-P^cq3JuUK)QNLClWROeHIL?^H_Htkm(D95}__r&5$=mCm2L{K`?GwdToI4$Q+{TkI zOUzBvQRh4YB2cOfz;k*!g&H5j__nw%4cKW1Uz!dG-^smZAY69ypc#;KFHf5R$J@_K zXW+^Qc*hLNNI!@TVsF2t4D`AZ#p{)Y76?I4>cr(AlDKpO={bBRkmV33&cr^4*)|h+ zbcAQk#CAt{=}aKtF&#%PfN(1JyE74$$N9=kq?;2sCtjTEhzhsW)hTsFu6b^$qb?pi zi*out6_BEQO2zo<{PDKR>hkerm1Wh11x1yG1(NY;a3qWG|CWSkYf|du)bF@!7I5Pk z{%97N=~@2oEMUxY96uY0wV0|u|1Cx)B@rI3{yqvhy<>(Qw05$ z>+J~q4>4;I_V`%dZHGV~ahIKjYd+R(xgIP2aygDZ<@g%9hc0nx4KnLx_SI0P=8A6H zBQ#J{Pmfjs{qOum4IKY7j;cjue8EF&DM|YeY@8%kMw`V*eJK5t+iL+jUrK~ar>`Ug zS%f3akR%QJHCPS!EkRM;U>&EpO8hT^Z*=0~{DjC#H(m%fpXB@&oS9<4d#UWGBfa)2 zhN)uZSYy;=#jBv;^hYijgT4a}y%ojJ)lszed$47x#{R4hq4mQy1+o7xok%`s;Tx@_ z6=Uu(pjuKCi1r^|ufUc+@*xE&;3uq16NA6V)XLL;<{uTf+;uk1qb%(W(Bj1RoS-^M z5ZBMc<%!qNL)71)7w_$iO-IUi_>^LYORcu=MBw(qHhFFz?CMtEE5Ulvu`-G03JPX@ zJw<3j^x}#pnse$YF1Z&LNKf$VMXgaLv^Z5y2nFdLG5COy+v|a^I=$%rG>%`a2fpe- zN6#N%ZEw>AP42JvH!fKMyG(g;k;h6x53d)26qi5xwbXQJL4=tK!H7<>DJ zWvY`RHFxPnmpzHEZGo5@op7`vpr?opOHAS8Jnoj}u`N!ud>+Q{IVoFnuU^=nP7sm3 zwQ4*L2XlhB@*)N@!x}d>)tTL%jmR@;wb-MyS<^uK< z^1Cid(u`FvJ=~%C$9OQqyMrp-Egq|^1%_Y{Gy${n`Ktnx|AOj!TDrkR9^-~7irMal z7$v;cP1d-wz&8FDSYe$*ttlq+c{lL5g1>U3IIQG8%>eZ&JhBj%VK%@bZnL)zJ1@KQ;(KYGdN-ajigyzya4Vyhn)-HZq<4|F@@rFMXu%+^}HHB zxd5ePEx&<8rLDs@@v^AX+3G!tBDYc4;GrzdJiRz8;<&^^aoT!tWx*I0Uh6?fHDG8I z7ca)%D*YV%vIm|spReFY)2J7d&d0OGOTEa+SzbV06Wf;IL7$vL5$S{5TXC{d-_r+J$>&;7m9GLl9=X#P+5>d=b7U*^)jj}1 ztgI=cxU7|QD7t2}!U7LsI$f>exfLR;!?1r3lEtW4x}Gn!B4uviur}D`Aw6HvPK?_kHuwInM#_RL!O*L-y z`TZ!n7sA6H(~HozOd)s4t+)Hb-rwWcq2jXGe!##HizrmHQ!n-&iV|lc!ZLgOcozrMq;hv9nIh1gaJz24H4gED#fXr@+_@OeeuTRgpnf6g2-F)x9EMuXc<}|X@7W5yMA^gwq&Sik8v;M&OWEu6+{9Z3o!lL-cWfVoP zaM*IX$Mh<83&$Dx_Sy!;TI8xz7NRtlr~ZLwEr*Z24u(YD+m6Tm&gH0T-r!@)agR6o z!g5Mac?(pDShnV7r=!*`^=T~)Gy}3d{MmX58wwu)x3v% z{$55Hnn?9-2p~1v&E4%Z#Bu@a`e0b@akScN7g_NV^LcL??T?(k0#*Ed@{q_IEqrWMfk`+O2i=z?8dLBq8lfH#3px+o^B(a~&kD*ndAN1VG77yDTH zt%dJj2_1dPXsV{(cL@umj%0tZtXXjtp?qpqVf=EBY_iG@q{7m&%ED=C8}e^@ac*@y z8&=^}{C7640=|5P1^q;>E{>~vK+IGz@jEAk|0jRG3T48V zm^I02BfO&4?(+6@_P*kr`{7n!bNT(KxV~ZM{bbaB3to%b0W?&)-Aqf3X^|_CGeDcc=MT&s`{0LsWGBMU8Mila89n`2guO z*O9JQsV{ItczHvhfpP;UCWz&gCO-Rs?4qG;jTPUz;?;~!81)z3eWJN)6oqrd8aSke zEo)%hJGgWWC1~z6h?R$8xP1+Ul9t!4p+rrHL3G|Q@hfYnk2Vw=B=cDx8KY$bwaV^s z1>9W+iitNPk+JzfGHCP$J{f{{*Dj*4Ti9pd>IV_wVZ8i78lnxy8oZQ&HC-X0;<50t-1FwK#_|!V2!({cS1^c4IZ-!M0ree6eh++(ZE2U#5MNBHPaQ1psI~f=ziR-T> z>g0z5DR-tpSaOqMW$og%%0DaZHS)H7!Rdbp9$k+rA&XyG4^-^Oml?@)s9f2f^&1d* z12}sFdP#!}DoC|$peU^sYcu_A;KLj6^v&j%H^9kq_|i5M#Mi*08Eg<|(k)@C;YNY^U4BWgBRr8M< zNw3K@h-*)n#2ahEP&H<6!ZS3V=Wc=%6>$3|yo?L6NsKuASu`KtgyLo_KL?_A9A-@d zHsPzAfCc0EmrXQGTZCDo`tm64fEW{adIzeIiI`2}vlh7Sjt=CzVm{e{?nEhn(t%Jc zXH6%(X0p6-8j8XxotT`$OFF?al@D|Rf2#QPPMkSSJyX7GZgk?6Kb^xiBVW!?&+PV? z)XHHdS8c}4XJOJTI{U|ltG?aS&6+K>YZPT!T0XOxjG8%6#9?&*%8pQQurzhGL1dQ) z-W>^BD9kt)8zJHYg|PG`wN$Xn5Q&bEPa!|zO10K-%@zn<%Nw@<>lCa^LOw}R<(kLc zThPI-=MX^_Qv+xcu>+7?R64b+C|`Z}IM^o8JDSg40W~!8qXPGD;ui#J7`GG-ZYAJ( z3$R0`=>2sfr$3Ck&BH?;MiuJCeMaFvo`DwXh@WL7osBZilTc3HV49%mKx})AT>A)sV6*hnXx@asYqwzSNO?E@ZVZKs zj-^^*-Dc3KsU9i|68!BW_$ss&Z2i;(IqXq%VVH{^MIrhKH$MvNJ!;_2(PZp3u4t_E zw8!}Pqd0gwp9ha-hk?6nlxR@q*;}0Iqh%-H%9#*eqSQI;@`zp7J5&7@B{~~}qo=s+ zt!R(-d|%nEo*bwu#l=T-yz?<+^*wy(G336z{PtrsLi4y9=^Q#9!LyGCZ%3T$$GUjl z)d;k5Z%6)o!oVx@$tcsEPxY6BVCc=Zz7(x$|49s!MDMF+G2rb`?IDazYJdFtcAR#Y zbvy8SK7!0-r(|*YkzPD=2b}XLJ9kh<>M?N3PqL`R@MYKTs#UDTc2B)h*yNt?kXJmx zPw#+9y7-YSj)jS&yEh&088~0+z3w+;RDDaP5y%)TH z;-!1ZH2i%C(o;v;YHM3ODDo@SrtM!qk=Ssn!W^%7l%6W{1Mc2SshYnUnD$XrXis_h zAxAzAclgL4+P^gNq{mSce9ZG7#|N@Y`(P2`<|9a88nzwA)8r05e*{Q(C)XT8>7nI; z$6@VY9&ijfA%w$@;d^v1)}27XFa5BONXd`ZROr}!m@H$Z4IrQ@U16ndJbD&hIgY~r z>f5ZOu%f~?uCRJ?*_6_P3R#WxToddi4p)m$@rHBvF&r7e+mGU`NG>}Dd3$s2QA#q& zt4jw%1=MEupqbtC_Kpe?D<3h1j;$)Fhz31@Cmo>Jv=XJM233{xb?E>%SJ_(X9B!}d zy`yP&5XGQ3juW1Q0gb%#Nt_lhuM;2QmokA}2cQsqB;1cAXU3u=4nIMrkP1grvr|dr z%lpX;j}7MH15i!N0qSE2T*U%re4l)h5(CW1d;|N(r(j+_hAJBD9@+5+vRGvXOWn2) z`6>;RSiZau7>sJco6a2v;8YpXO3|gNPBXzF)evZ3$hN%4DtY^2QY!oAH~)Yjwt9CK zrll=Z=dMs{-L5)sKi;#C`kMO(R{d%_wbSVxz^9J`0tWKN|j@%)6eTtah2arR{IpMBd+fH)f<_{3=n^ zqqb)5!JKrrDPF~+w%TMDOd9&vBKsX^DCVUSq&S5On;jnftChgv!!Rw4lFzRFl$3aH zfb(`cpy#c49JRxP#OD7O7cmyluGHDk_-ktRdGF(ApQO~p5m@&Bn@=`eMq<9dbf`=& zeS$(z{4EAMjg~sZ+x7@)HDiKA?%`-_E;yxjZa-MPs11`htrQSCkFOo0jG_4;{mP5| zU*!uhEj<}B;$_~XxO^pwtHmmTYn)?Vq4dsF)QS-Y@x^l-_+-%CR601kMirxNZf_DmL zrFw329r^WjDyDvO=+vTu!m^4g9)A!BGffSw;OR((-sxN-V||7i)9L>BpNSoQ?a6`Y znFT_+3I$=%)x5%mKImMjo6VNPlwzC%>aWbDW^!*e+kpU@xj}5JLKt-&qWDBRSbyWp zfkSGzeIF$!$k&1t;&z`_ZBWNkpFo>g;f?!omwB9g6#v{pwq@`gbADXJt@xLpvQt%Q m4N_V^csYX9URtC#*ig|@ACvM*iPnO87qnaA*kt diff --git a/TelegramUI/SelectivePrivacySettingsPeersController.swift b/TelegramUI/SelectivePrivacySettingsPeersController.swift index 53cedb9c0d..6b528a6560 100644 --- a/TelegramUI/SelectivePrivacySettingsPeersController.swift +++ b/TelegramUI/SelectivePrivacySettingsPeersController.swift @@ -135,7 +135,7 @@ private enum SelectivePrivacyPeersEntry: ItemListNodeEntry { func item(_ arguments: SelectivePrivacyPeersControllerArguments) -> ListViewItem { switch self { case let .peerItem(_, theme, strings, dateTimeFormat, nameDisplayOrder, peer, editing, enabled): - return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, presence: nil, text: .none, label: .none, editing: editing, switchValue: nil, enabled: enabled, sectionId: self.section, action: nil, setPeerIdWithRevealedOptions: { previousId, id in + return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, presence: nil, text: .none, label: .none, editing: editing, switchValue: nil, enabled: enabled, selectable: true, sectionId: self.section, action: nil, setPeerIdWithRevealedOptions: { previousId, id in arguments.setPeerIdWithRevealedOptions(previousId, id) }, removePeer: { peerId in arguments.removePeer(peerId) diff --git a/TelegramUI/SettingsController.swift b/TelegramUI/SettingsController.swift index 4178478592..045ca893d7 100644 --- a/TelegramUI/SettingsController.swift +++ b/TelegramUI/SettingsController.swift @@ -74,7 +74,7 @@ private enum SettingsEntry: ItemListNodeEntry { case keepPhone(PresentationTheme, String) case changePhone(PresentationTheme, String) - case account(Int, Account, PresentationTheme, PresentationStrings, Peer, Int32, Bool) + case account(Int, Account, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, Peer, Int32, Bool) case addAccount(PresentationTheme, String) case proxy(PresentationTheme, UIImage?, String, String) @@ -202,8 +202,8 @@ private enum SettingsEntry: ItemListNodeEntry { } else { return false } - case let .account(lhsIndex, lhsAccount, lhsTheme, lhsStrings, lhsPeer, lhsBadgeCount, lhsRevealed): - if case let .account(rhsIndex, rhsAccount, rhsTheme, rhsStrings, rhsPeer, rhsBadgeCount, rhsRevealed) = rhs, lhsIndex == rhsIndex, lhsAccount === rhsAccount, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsPeer.isEqual(rhsPeer), lhsBadgeCount == rhsBadgeCount, lhsRevealed == rhsRevealed { + case let .account(lhsIndex, lhsAccount, lhsTheme, lhsStrings, lhsDateTimeFormat, lhsPeer, lhsBadgeCount, lhsRevealed): + if case let .account(rhsIndex, rhsAccount, rhsTheme, rhsStrings, rhsDateTimeFormat, rhsPeer, rhsBadgeCount, rhsRevealed) = rhs, lhsIndex == rhsIndex, lhsAccount === rhsAccount, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, lhsPeer.isEqual(rhsPeer), lhsBadgeCount == rhsBadgeCount, lhsRevealed == rhsRevealed { return true } else { return false @@ -362,16 +362,12 @@ private enum SettingsEntry: ItemListNodeEntry { return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: ItemListSectionId(self.section), style: .blocks, action: { arguments.openPhoneNumberChange() }) - case let .account(_, account, theme, strings, peer, badgeCount, revealed): + case let .account(_, account, theme, strings, dateTimeFormat, peer, badgeCount, revealed): var label: ItemListPeerItemLabel = .none if badgeCount > 0 { - if badgeCount > 1000 { - label = .badge("\(badgeCount / 1000)K") - } else { - label = .badge("\(badgeCount)") - } + label = .badge(compactNumericCountString(Int(badgeCount), decimalSeparator: dateTimeFormat.decimalSeparator)) } - return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: PresentationDateTimeFormat(timeFormat: .regular, dateFormat: .dayFirst, dateSeparator: ".", decimalSeparator: ".", groupingSeparator: ""), 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: ".", groupingSeparator: ""), 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, selectable: true, sectionId: self.section, action: { arguments.switchToAccount(account.id) }, setPeerIdWithRevealedOptions: { lhs, rhs in var lhsAccountId: AccountRecordId? @@ -475,7 +471,7 @@ private func settingsEntries(account: Account, presentationData: PresentationDat if !accountsAndPeers.isEmpty { var index = 0 for (peerAccount, peer, badgeCount) in accountsAndPeers { - entries.append(.account(index, peerAccount, presentationData.theme, presentationData.strings, peer, inAppNotificationSettings.displayNotificationsFromAllAccounts ? badgeCount : 0, state.accountIdWithRevealedOptions == peerAccount.id)) + entries.append(.account(index, peerAccount, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer, inAppNotificationSettings.displayNotificationsFromAllAccounts ? badgeCount : 0, state.accountIdWithRevealedOptions == peerAccount.id)) index += 1 } if accountsAndPeers.count + 1 < maximumNumberOfAccounts { @@ -1234,11 +1230,7 @@ public func settingsController(context: AccountContext, accountManager: AccountM let notificationsWarning = shouldDisplayNotificationsPermissionWarning(status: notificationsAuthorizationStatus, suppressed: notificationsWarningSuppressed) var otherAccountsBadge: String? if accountTabBarAvatarBadge > 0 { - if accountTabBarAvatarBadge > 1000 { - otherAccountsBadge = "\(accountTabBarAvatarBadge / 1000)K" - } else { - otherAccountsBadge = "\(accountTabBarAvatarBadge)" - } + otherAccountsBadge = compactNumericCountString(Int(accountTabBarAvatarBadge), decimalSeparator: presentationData.dateTimeFormat.decimalSeparator) } return ItemListControllerTabBarItem(title: presentationData.strings.Settings_Title, image: accountTabBarAvatar ?? icon, selectedImage: accountTabBarAvatar ?? icon, tintImages: accountTabBarAvatar == nil, badgeValue: notificationsWarning ? "!" : otherAccountsBadge) } diff --git a/TelegramUI/StorageUsageController.swift b/TelegramUI/StorageUsageController.swift index 0f0a5e625e..b42bc8d994 100644 --- a/TelegramUI/StorageUsageController.swift +++ b/TelegramUI/StorageUsageController.swift @@ -164,7 +164,7 @@ private enum StorageUsageEntry: ItemListNodeEntry { arguments.openClearAll() }) case let .peer(_, theme, strings, dateTimeFormat, nameDisplayOrder, peer, chatPeer, value): - return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, aliasHandling: .threatSelfAsSaved, nameColor: chatPeer == nil ? .primary : .secret, presence: nil, text: .none, label: .disclosure(value), editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), switchValue: nil, enabled: true, sectionId: self.section, action: { + return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, aliasHandling: .threatSelfAsSaved, nameColor: chatPeer == nil ? .primary : .secret, presence: nil, text: .none, label: .disclosure(value), editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), switchValue: nil, enabled: true, selectable: true, sectionId: self.section, action: { let resolvedPeer = chatPeer ?? peer arguments.openPeerMedia(resolvedPeer.id) }, setPeerIdWithRevealedOptions: { previousId, id in diff --git a/TelegramUI/TabBarAccountSwitchControllerNode.swift b/TelegramUI/TabBarAccountSwitchControllerNode.swift index df9d11c7e6..436215c26c 100644 --- a/TelegramUI/TabBarAccountSwitchControllerNode.swift +++ b/TelegramUI/TabBarAccountSwitchControllerNode.swift @@ -135,12 +135,7 @@ private final class SwitchAccountItemNode: ASDisplayNode, AbstractSwitchAccountI self.badgeBackgroundNode.image = generateStretchableFilledCircleImage(diameter: 20.0, color: presentationData.theme.list.itemCheckColors.fillColor) self.badgeTitleNode = ImmediateTextNode() if unreadCount > 0 { - let countString: String - if unreadCount > 1000 { - countString = "\(unreadCount / 1000)K" - } else { - countString = "\(unreadCount)" - } + let countString = compactNumericCountString(Int(unreadCount), decimalSeparator: presentationData.dateTimeFormat.decimalSeparator) self.badgeTitleNode.attributedText = NSAttributedString(string: countString, font: Font.regular(14.0), textColor: presentationData.theme.list.itemCheckColors.foregroundColor) } else { self.badgeBackgroundNode.isHidden = true