From 603145971cdca116ca67260b250fe7e3da115ce4 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Thu, 3 Jan 2019 21:44:27 +0400 Subject: [PATCH] Put search bar into navigation bar --- TelegramUI.xcodeproj/project.pbxproj | 8 + TelegramUI/ChannelInfoController.swift | 3 +- .../ChannelMembersSearchControllerNode.swift | 2 +- TelegramUI/ChatBotInfoItem.swift | 4 + TelegramUI/ChatButtonKeyboardInputNode.swift | 6 +- TelegramUI/ChatDocumentGalleryItem.swift | 7 +- TelegramUI/ChatExternalFileGalleryItem.swift | 7 +- TelegramUI/ChatImageGalleryItem.swift | 7 +- .../ChatItemGalleryFooterContentNode.swift | 5 +- TelegramUI/ChatListController.swift | 53 +- TelegramUI/ChatListControllerNode.swift | 74 +- TelegramUI/ChatListNode.swift | 17 +- TelegramUI/ChatListNodeEntries.swift | 12 +- TelegramUI/ChatListSearchItem.swift | 2 +- TelegramUI/ChatListViewTransition.swift | 6 +- .../ChatMessageInteractiveFileNode.swift | 12 +- ...atMessageInteractiveInstantVideoNode.swift | 5 +- .../ChatMessageInteractiveMediaNode.swift | 21 +- TelegramUI/ChatMessageStickerItemNode.swift | 19 +- .../CommandChatInputContextPanelNode.swift | 25 +- TelegramUI/ComposeController.swift | 16 +- TelegramUI/ComposeControllerNode.swift | 55 +- TelegramUI/ContactListActionItem.swift | 99 +- TelegramUI/ContactListNode.swift | 106 +- TelegramUI/ContactSelectionController.swift | 16 +- .../ContactSelectionControllerNode.swift | 67 +- TelegramUI/ContactsController.swift | 59 +- TelegramUI/ContactsControllerNode.swift | 61 +- TelegramUI/CreateChannelController.swift | 6 +- TelegramUI/CreateGroupController.swift | 6 +- TelegramUI/EditSettingsController.swift | 2 +- .../FixSearchableListNodeScrolling.swift | 19 + TelegramUI/GridMessageItem.swift | 21 +- TelegramUI/GroupInfoController.swift | 7 +- TelegramUI/InstantPageImageNode.swift | 5 +- TelegramUI/InviteContactsController.swift | 16 +- TelegramUI/InviteContactsControllerNode.swift | 57 +- TelegramUI/ItemListPeerActionItem.swift | 16 +- TelegramUI/ListMessageFileItemNode.swift | 14 +- TelegramUI/LocalizationListController.swift | 16 +- .../LocalizationListControllerNode.swift | 55 +- TelegramUI/LocalizationListItem.swift | 4 +- .../NavigationBarSearchContentNode.swift | 109 + .../NotificationExceptionControllerNode.swift | 67 +- TelegramUI/NotificationExceptions.swift | 39 +- TelegramUI/NotificationSearchItem.swift | 2 +- TelegramUI/NotificationsAndSounds.swift | 18 +- TelegramUI/PeerAvatarImageGalleryItem.swift | 7 +- .../PeerMediaCollectionControllerNode.swift | 2 +- TelegramUI/PeerSelectionController.swift | 16 +- TelegramUI/PeerSelectionControllerNode.swift | 139 +- TelegramUI/PresentationStrings.swift | 2939 +++++++++-------- TelegramUI/QRCode.swift | 20 +- TelegramUI/RadialDownloadContentNode.swift | 13 +- TelegramUI/RadialPlayPauseContentNode.swift | 60 + TelegramUI/RadialProgressContentNode.swift | 19 +- .../Resources/PresentationStrings.mapping | Bin 93498 -> 93548 bytes TelegramUI/SearchBarNode.swift | 91 +- TelegramUI/SearchBarPlaceholderNode.swift | 70 +- TelegramUI/SearchDisplayController.swift | 80 +- TelegramUI/SettingsController.swift | 2 +- ...hareProxyServerActionSheetController.swift | 38 +- TelegramUI/TelegramRootController.swift | 44 + TelegramUI/UIImage+WebP.m | 5 +- TelegramUI/WebP.swift | 19 +- TelegramUI/WebSearchController.swift | 24 +- .../WebSearchNavigationContentNode.swift | 3 +- TelegramUI/WebSearchVideoGalleryItem.swift | 2 +- 68 files changed, 2658 insertions(+), 2188 deletions(-) create mode 100644 TelegramUI/NavigationBarSearchContentNode.swift create mode 100644 TelegramUI/RadialPlayPauseContentNode.swift diff --git a/TelegramUI.xcodeproj/project.pbxproj b/TelegramUI.xcodeproj/project.pbxproj index 980688657f..04696bbcb9 100644 --- a/TelegramUI.xcodeproj/project.pbxproj +++ b/TelegramUI.xcodeproj/project.pbxproj @@ -73,6 +73,8 @@ 099529B021D2123E00805E13 /* ChatMessageUnsupportedBubbleContentNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 099529AF21D2123E00805E13 /* ChatMessageUnsupportedBubbleContentNode.swift */; }; 099529B221D24F5800805E13 /* RadialDownloadContentNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 099529B121D24F5800805E13 /* RadialDownloadContentNode.swift */; }; 099529B421D3E5D800805E13 /* CheckDiskSpace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 099529B321D3E5D800805E13 /* CheckDiskSpace.swift */; }; + 099529F321D8FE8300805E13 /* RadialPlayPauseContentNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 099529F221D8FE8300805E13 /* RadialPlayPauseContentNode.swift */; }; + 099529FA21DD8A3100805E13 /* NavigationBarSearchContentNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 099529F921DD8A3100805E13 /* NavigationBarSearchContentNode.swift */; }; 09AE3823214C110900850BFD /* LegacySecureIdScanController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09AE3822214C110800850BFD /* LegacySecureIdScanController.swift */; }; 09B4EE4721A6D33F00847FA6 /* RecentSessionsEmptyStateItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09B4EE4621A6D33F00847FA6 /* RecentSessionsEmptyStateItem.swift */; }; 09B4EE4D21A7B73800847FA6 /* PermissionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09B4EE4C21A7B73800847FA6 /* PermissionController.swift */; }; @@ -1178,6 +1180,8 @@ 099529AF21D2123E00805E13 /* ChatMessageUnsupportedBubbleContentNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatMessageUnsupportedBubbleContentNode.swift; sourceTree = ""; }; 099529B121D24F5800805E13 /* RadialDownloadContentNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadialDownloadContentNode.swift; sourceTree = ""; }; 099529B321D3E5D800805E13 /* CheckDiskSpace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckDiskSpace.swift; sourceTree = ""; }; + 099529F221D8FE8300805E13 /* RadialPlayPauseContentNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadialPlayPauseContentNode.swift; sourceTree = ""; }; + 099529F921DD8A3100805E13 /* NavigationBarSearchContentNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationBarSearchContentNode.swift; sourceTree = ""; }; 09AE3822214C110800850BFD /* LegacySecureIdScanController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacySecureIdScanController.swift; sourceTree = ""; }; 09B4EE4621A6D33F00847FA6 /* RecentSessionsEmptyStateItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentSessionsEmptyStateItem.swift; sourceTree = ""; }; 09B4EE4C21A7B73800847FA6 /* PermissionController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionController.swift; sourceTree = ""; }; @@ -2543,6 +2547,7 @@ D01776B91F1D704F0044446D /* RadialStatusIconContentNode.swift */, D0380DAA204EA72F000414AB /* RadialStatusSecretTimeoutContentNode.swift */, 099529B121D24F5800805E13 /* RadialDownloadContentNode.swift */, + 099529F221D8FE8300805E13 /* RadialPlayPauseContentNode.swift */, ); name = "Radial Status"; sourceTree = ""; @@ -4259,6 +4264,7 @@ D0F69DCC1D6B8A0D0046BCD6 /* SearchBarPlaceholderNode.swift */, D0F69DCD1D6B8A0D0046BCD6 /* SearchDisplayController.swift */, D0F69DCE1D6B8A0D0046BCD6 /* SearchDisplayControllerContentNode.swift */, + 099529F921DD8A3100805E13 /* NavigationBarSearchContentNode.swift */, ); name = Search; sourceTree = ""; @@ -5356,6 +5362,7 @@ 0962E67921B67A9800245FD9 /* ChatMessageAnimatedStickerItemNode.swift in Sources */, D0EC6D4E1EB9F58800EBF1C3 /* ChatListItem.swift in Sources */, D0B2F76A2052920D00D3BFB9 /* UserInfoEditingPhoneItem.swift in Sources */, + 099529FA21DD8A3100805E13 /* NavigationBarSearchContentNode.swift in Sources */, D0AEAE272080D6970013176E /* StickerPaneSearchBarNode.swift in Sources */, D0EC6D4F1EB9F58800EBF1C3 /* ChatListSearchItem.swift in Sources */, D0EC6D501EB9F58800EBF1C3 /* ChatListNodeEntries.swift in Sources */, @@ -5721,6 +5728,7 @@ D0EC6E031EB9F58900EBF1C3 /* GalleryFooterContentNode.swift in Sources */, D0E9BA0A1F0457DD00F079A4 /* BotCheckoutWebInteractionController.swift in Sources */, D0EC6E041EB9F58900EBF1C3 /* SecretMediaPreviewController.swift in Sources */, + 099529F321D8FE8300805E13 /* RadialPlayPauseContentNode.swift in Sources */, D0C26D571FDF2388004ABF18 /* OpenChatMessage.swift in Sources */, D0FA08BE20481EA300DD23FC /* Locale.swift in Sources */, D0E412CE206A707400BEE4A2 /* FormControllerTextItem.swift in Sources */, diff --git a/TelegramUI/ChannelInfoController.swift b/TelegramUI/ChannelInfoController.swift index a030b16554..7e3ed686b3 100644 --- a/TelegramUI/ChannelInfoController.swift +++ b/TelegramUI/ChannelInfoController.swift @@ -677,7 +677,7 @@ public func channelInfoController(account: Account, peerId: PeerId) -> ViewContr let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: hasPhotos, hasViewButton: false, personalPhoto: false, saveEditedPhotos: false, saveCapturedMedia: false, signup: false)! let _ = currentAvatarMixin.swap(mixin) mixin.requestSearchController = { assetsController in - let controller = WebSearchController(account: account, peer: peer, configuration: searchBotsConfiguration, mode: .avatar(completion: { result in + let controller = WebSearchController(account: account, peer: peer, configuration: searchBotsConfiguration, mode: .avatar(initialQuery: peer?.displayTitle, completion: { result in assetsController?.dismiss() completedImpl(result) })) @@ -739,7 +739,6 @@ public func channelInfoController(account: Account, peerId: PeerId) -> ViewContr }, changeNotificationMuteSettings: { let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 } actionsDisposable.add((account.postbox.preferencesView(keys: [PreferencesKeys.globalNotifications]) |> take(1) |> deliverOnMainQueue).start(next: { view in - let viewSettings: GlobalNotificationSettingsSet if let settings = view.values[PreferencesKeys.globalNotifications] as? GlobalNotificationSettings { viewSettings = settings.effective diff --git a/TelegramUI/ChannelMembersSearchControllerNode.swift b/TelegramUI/ChannelMembersSearchControllerNode.swift index 50fc68e8b7..0102b0150d 100644 --- a/TelegramUI/ChannelMembersSearchControllerNode.swift +++ b/TelegramUI/ChannelMembersSearchControllerNode.swift @@ -302,7 +302,7 @@ class ChannelMembersSearchControllerNode: ASDisplayNode { }) self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate) - self.searchDisplayController?.activate(insertSubnode: { subnode in + self.searchDisplayController?.activate(insertSubnode: { subnode, isSearchBar in self.insertSubnode(subnode, belowSubnode: navigationBar) }, placeholder: placeholderNode) } diff --git a/TelegramUI/ChatBotInfoItem.swift b/TelegramUI/ChatBotInfoItem.swift index c59158f101..5518a51690 100644 --- a/TelegramUI/ChatBotInfoItem.swift +++ b/TelegramUI/ChatBotInfoItem.swift @@ -287,6 +287,8 @@ final class ChatBotInfoItemNode: ListViewItemNode { self.item?.controllerInteraction.openPeer(peerId, .chat(textInputState: nil, messageId: nil), nil) case let .textMention(name): self.item?.controllerInteraction.openPeerMention(name) + case let .botCommand(command): + self.item?.controllerInteraction.sendBotCommand(nil, command) case let .hashtag(peerName, hashtag): self.item?.controllerInteraction.openHashtag(peerName, hashtag) default: @@ -304,6 +306,8 @@ final class ChatBotInfoItemNode: ListViewItemNode { item.controllerInteraction.longTap(.peerMention(peerId, mention)) case let .textMention(name): item.controllerInteraction.longTap(.mention(name)) + case let .botCommand(command): + item.controllerInteraction.longTap(.command(command)) case let .hashtag(_, hashtag): item.controllerInteraction.longTap(.hashtag(hashtag)) default: diff --git a/TelegramUI/ChatButtonKeyboardInputNode.swift b/TelegramUI/ChatButtonKeyboardInputNode.swift index 34f4a425b4..818b170140 100644 --- a/TelegramUI/ChatButtonKeyboardInputNode.swift +++ b/TelegramUI/ChatButtonKeyboardInputNode.swift @@ -99,6 +99,7 @@ final class ChatButtonKeyboardInputNode: ChatInputNode { var panelHeight = standardInputHeight + let previousRowsHeight = self.scrollNode.view.contentSize.height let rowsHeight = verticalInset + CGFloat(markup.rows.count) * buttonHeight + CGFloat(max(0, markup.rows.count - 1)) * rowSpacing + verticalInset if !markup.flags.contains(.fit) && rowsHeight < panelHeight { buttonHeight = floor((panelHeight - bottomInset - verticalInset * 2.0 - CGFloat(max(0, markup.rows.count - 1)) * rowSpacing) / CGFloat(markup.rows.count)) @@ -144,7 +145,10 @@ final class ChatButtonKeyboardInputNode: ChatInputNode { transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: panelHeight))) self.scrollNode.view.contentSize = CGSize(width: width, height: rowsHeight) - self.scrollNode.view.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: bottomInset, right: 0) + self.scrollNode.view.contentInset = UIEdgeInsets(top: 0.0, left: 0.0, bottom: bottomInset, right: 0.0) + if previousRowsHeight != rowsHeight { + self.scrollNode.view.setContentOffset(CGPoint(), animated: false) + } return (panelHeight, 0.0) } else { diff --git a/TelegramUI/ChatDocumentGalleryItem.swift b/TelegramUI/ChatDocumentGalleryItem.swift index f2a093f650..a1a3711f9f 100644 --- a/TelegramUI/ChatDocumentGalleryItem.swift +++ b/TelegramUI/ChatDocumentGalleryItem.swift @@ -192,11 +192,8 @@ class ChatDocumentGalleryItemNode: GalleryItemNode, WKNavigationDelegate { strongSelf.statusNode.isHidden = false strongSelf.statusNode.alpha = 1.0 strongSelf.statusNodeContainer.isUserInteractionEnabled = true - var actualProgress = progress - if isActive { - actualProgress = max(actualProgress, 0.027) - } - strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: CGFloat(actualProgress), cancelEnabled: true), completion: {}) + let adjustedProgress = max(progress, 0.027) + strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true), completion: {}) case .Local: if let previousStatus = previousStatus, case .Fetching = previousStatus { strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: 1.0, cancelEnabled: true), completion: { diff --git a/TelegramUI/ChatExternalFileGalleryItem.swift b/TelegramUI/ChatExternalFileGalleryItem.swift index 795102a4e1..9bcadbee48 100644 --- a/TelegramUI/ChatExternalFileGalleryItem.swift +++ b/TelegramUI/ChatExternalFileGalleryItem.swift @@ -189,11 +189,8 @@ class ChatExternalFileGalleryItemNode: GalleryItemNode { strongSelf.statusNode.isHidden = false strongSelf.statusNode.alpha = 1.0 strongSelf.statusNodeContainer.isUserInteractionEnabled = true - var actualProgress = progress - if isActive { - actualProgress = max(actualProgress, 0.027) - } - strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: CGFloat(actualProgress), cancelEnabled: true), completion: {}) + let adjustedProgress = max(progress, 0.027) + strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true), completion: {}) case .Local: if let previousStatus = previousStatus, case .Fetching = previousStatus { strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: 1.0, cancelEnabled: true), completion: { diff --git a/TelegramUI/ChatImageGalleryItem.swift b/TelegramUI/ChatImageGalleryItem.swift index 7febceeb63..6465a03489 100644 --- a/TelegramUI/ChatImageGalleryItem.swift +++ b/TelegramUI/ChatImageGalleryItem.swift @@ -266,11 +266,8 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode { strongSelf.statusNode.isHidden = false strongSelf.statusNode.alpha = 1.0 strongSelf.statusNodeContainer.isUserInteractionEnabled = true - var actualProgress = progress - if isActive { - actualProgress = max(actualProgress, 0.027) - } - strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: CGFloat(actualProgress), cancelEnabled: true), completion: {}) + let adjustedProgress = max(progress, 0.027) + strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true), completion: {}) case .Local: if let previousStatus = previousStatus, case .Fetching = previousStatus { strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: 1.0, cancelEnabled: true), completion: { diff --git a/TelegramUI/ChatItemGalleryFooterContentNode.swift b/TelegramUI/ChatItemGalleryFooterContentNode.swift index e73749153f..ccaeb35cad 100644 --- a/TelegramUI/ChatItemGalleryFooterContentNode.swift +++ b/TelegramUI/ChatItemGalleryFooterContentNode.swift @@ -163,10 +163,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode { var statusState: RadialStatusNodeState = .none switch status { case let .Fetching(isActive, progress): - var adjustedProgress = progress - if isActive { - adjustedProgress = max(adjustedProgress, 0.027) - } + let adjustedProgress = max(progress, 0.027) statusState = .cloudProgress(color: UIColor.white, strokeBackgroundColor: UIColor.white.withAlphaComponent(0.5), lineWidth: 2.0, value: CGFloat(adjustedProgress)) case .Local: break diff --git a/TelegramUI/ChatListController.swift b/TelegramUI/ChatListController.swift index f67334ef81..abb235df54 100644 --- a/TelegramUI/ChatListController.swift +++ b/TelegramUI/ChatListController.swift @@ -46,6 +46,8 @@ public class ChatListController: TelegramController, KeyShortcutResponder, UIVie private let stateDisposable = MetaDisposable() + private var searchContentNode: NavigationBarSearchContentNode? + public init(account: Account, groupId: PeerGroupId?, controlsHistoryPreload: Bool) { self.account = account self.controlsHistoryPreload = controlsHistoryPreload @@ -88,7 +90,12 @@ public class ChatListController: TelegramController, KeyShortcutResponder, UIVie self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.DialogList_Title, style: .plain, target: nil, action: nil) self.scrollToTop = { [weak self] in - self?.chatListDisplayNode.scrollToTop() + if let strongSelf = self { + if let searchContentNode = strongSelf.searchContentNode { + searchContentNode.updateExpansionProgress(1.0, animated: true) + } + strongSelf.chatListDisplayNode.scrollToTop() + } } self.scrollToTopWithTabBar = { [weak self] in guard let strongSelf = self else { @@ -234,6 +241,11 @@ public class ChatListController: TelegramController, KeyShortcutResponder, UIVie } } }) + + self.searchContentNode = NavigationBarSearchContentNode(theme: self.presentationData.theme, placeholder: self.presentationData.strings.DialogList_SearchLabel, activate: { [weak self] in + self?.activateSearch() + }) + self.navigationBar?.setContentNode(self.searchContentNode, animated: false) } required public init(coder aDecoder: NSCoder) { @@ -254,6 +266,7 @@ public class ChatListController: TelegramController, KeyShortcutResponder, UIVie private func updateThemeAndStrings() { self.tabBarItem.title = self.presentationData.strings.DialogList_Title self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.DialogList_Title, style: .plain, target: nil, action: nil) + self.searchContentNode?.updateThemeAndPlaceholder(theme: self.presentationData.theme, placeholder: self.presentationData.strings.DialogList_SearchLabel) var editing = false self.chatListDisplayNode.chatListNode.updateState { state in editing = state.editing @@ -499,6 +512,27 @@ public class ChatListController: TelegramController, KeyShortcutResponder, UIVie } } + self.chatListDisplayNode.chatListNode.contentOffsetChanged = { [weak self] offset in + if let strongSelf = self, let searchContentNode = strongSelf.searchContentNode, searchContentNode.nominalHeight > 0.0 { + var progress: CGFloat = 0.0 + switch offset { + case let .known(offset): + progress = max(0.0, (searchContentNode.nominalHeight - offset)) / searchContentNode.nominalHeight + default: + break + } + searchContentNode.updateExpansionProgress(progress) + } + } + + self.chatListDisplayNode.chatListNode.contentScrollingEnded = { [weak self] listView in + if let strongSelf = self, let searchContentNode = strongSelf.searchContentNode { + return fixNavigationSearchableListNodeScrolling(listView, searchNode: searchContentNode) + } else { + return false + } + } + let account = self.account let peerIdsAndOptions: Signal<(ChatListSelectionOptions, Set)?, NoError> = self.chatListDisplayNode.chatListNode.state |> map { state -> Set? in @@ -680,6 +714,7 @@ public class ChatListController: TelegramController, KeyShortcutResponder, UIVie } else { self.navigationItem.rightBarButtonItem = editItem } + self.searchContentNode?.setIsEnabled(false, animated: true) self.chatListDisplayNode.chatListNode.updateState { state in var state = state state.editing = true @@ -695,6 +730,7 @@ public class ChatListController: TelegramController, KeyShortcutResponder, UIVie } else { self.navigationItem.rightBarButtonItem = editItem } + self.searchContentNode?.setIsEnabled(true, animated: true) self.chatListDisplayNode.chatListNode.updateState { state in var state = state state.editing = false @@ -715,7 +751,9 @@ public class ChatListController: TelegramController, KeyShortcutResponder, UIVie if let scrollToTop = strongSelf.scrollToTop { scrollToTop() } - strongSelf.chatListDisplayNode.activateSearch() + if let searchContentNode = strongSelf.searchContentNode { + strongSelf.chatListDisplayNode.activateSearch(placeholderNode: searchContentNode.placeholderNode) + } strongSelf.setDisplayNavigationBar(false, transition: .animated(duration: 0.5, curve: .spring)) }) } @@ -724,7 +762,9 @@ public class ChatListController: TelegramController, KeyShortcutResponder, UIVie func deactivateSearch(animated: Bool) { if !self.displayNavigationBar { self.setDisplayNavigationBar(true, transition: animated ? .animated(duration: 0.5, curve: .spring) : .immediate) - self.chatListDisplayNode.deactivateSearch(animated: animated) + if let searchContentNode = self.searchContentNode { + self.chatListDisplayNode.deactivateSearch(placeholderNode: searchContentNode.placeholderNode, animated: animated) + } } } @@ -765,13 +805,6 @@ public class ChatListController: TelegramController, KeyShortcutResponder, UIVie sourceRect.size.height -= UIScreenPixel let chatController = ChatController(account: self.account, chatLocation: .peer(peerId), mode: .standard(previewing: true)) -// chatController.peekActions = .remove({ [weak self] in -// if let strongSelf = self { -// let _ = removeRecentPeer(account: strongSelf.account, peerId: peerId).start() -// let searchContainer = strongSelf.chatListDisplayNode.searchDisplayController?.contentNode as? ChatListSearchContainerNode -// searchContainer?.removePeerFromTopPeers(peerId) -// } -// }) chatController.canReadHistory.set(false) chatController.containerLayoutUpdated(ContainerViewLayout(size: contentSize, metrics: LayoutMetrics(), intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, standardInputHeight: 216.0, inputHeightIsInteractivellyChanging: false), transition: .immediate) return (chatController, sourceRect) diff --git a/TelegramUI/ChatListControllerNode.swift b/TelegramUI/ChatListControllerNode.swift index 8639ab6c05..df409c0e96 100644 --- a/TelegramUI/ChatListControllerNode.swift +++ b/TelegramUI/ChatListControllerNode.swift @@ -97,7 +97,7 @@ class ChatListControllerNode: ASDisplayNode { self.containerLayout = (layout, navigationBarHeight) var insets = layout.insets(options: [.input]) - insets.top += max(navigationBarHeight, layout.insets(options: [.statusBar]).top) + insets.top += navigationBarHeight insets.left += layout.safeInsets.left insets.right += layout.safeInsets.right @@ -142,58 +142,44 @@ class ChatListControllerNode: ASDisplayNode { } } - func activateSearch() { - guard let (containerLayout, navigationBarHeight) = self.containerLayout, let navigationBar = self.navigationBar else { + func activateSearch(placeholderNode: SearchBarPlaceholderNode) { + guard let (containerLayout, navigationBarHeight) = self.containerLayout, let navigationBar = self.navigationBar, self.searchDisplayController == nil else { return } - var maybePlaceholderNode: SearchBarPlaceholderNode? - self.chatListNode.forEachItemNode { node in - if let node = node as? ChatListSearchItemNode { - maybePlaceholderNode = node.searchBarNode + self.searchDisplayController = SearchDisplayController(theme: self.themeAndStrings.0, strings: self.themeAndStrings.1, mode: .navigation, contentNode: ChatListSearchContainerNode(account: self.account, filter: [], groupId: self.groupId, openPeer: { [weak self] peer, dismissSearch in + self?.requestOpenPeerFromSearch?(peer, dismissSearch) + }, openRecentPeerOptions: { [weak self] peer in + self?.requestOpenRecentPeerOptions?(peer) + }, openMessage: { [weak self] peer, messageId in + if let requestOpenMessageFromSearch = self?.requestOpenMessageFromSearch { + requestOpenMessageFromSearch(peer, messageId) } - } + }, addContact: { [weak self] phoneNumber in + if let requestAddContact = self?.requestAddContact { + requestAddContact(phoneNumber) + } + }), cancel: { [weak self] in + if let requestDeactivateSearch = self?.requestDeactivateSearch { + requestDeactivateSearch() + } + }) - if let _ = self.searchDisplayController { - return - } - - if let placeholderNode = maybePlaceholderNode { - self.searchDisplayController = SearchDisplayController(theme: self.themeAndStrings.0, strings: self.themeAndStrings.1, contentNode: ChatListSearchContainerNode(account: self.account, filter: [], groupId: self.groupId, openPeer: { [weak self] peer, dismissSearch in - self?.requestOpenPeerFromSearch?(peer, dismissSearch) - }, openRecentPeerOptions: { [weak self] peer in - self?.requestOpenRecentPeerOptions?(peer) - }, openMessage: { [weak self] peer, messageId in - if let requestOpenMessageFromSearch = self?.requestOpenMessageFromSearch { - requestOpenMessageFromSearch(peer, messageId) + self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate) + self.searchDisplayController?.activate(insertSubnode: { [weak self, weak placeholderNode] subnode, isSearchBar in + if let strongSelf = self, let strongPlaceholderNode = placeholderNode { + if isSearchBar { + strongPlaceholderNode.supernode?.insertSubnode(subnode, aboveSubnode: strongPlaceholderNode) + } else { + strongSelf.insertSubnode(subnode, belowSubnode: navigationBar) } - }, addContact: { [weak self] phoneNumber in - if let requestAddContact = self?.requestAddContact { - requestAddContact(phoneNumber) - } - }), cancel: { [weak self] in - if let requestDeactivateSearch = self?.requestDeactivateSearch { - requestDeactivateSearch() - } - }) - - self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate) - self.searchDisplayController?.activate(insertSubnode: { subnode in - self.insertSubnode(subnode, belowSubnode: navigationBar) - }, placeholder: placeholderNode) - } + } + }, placeholder: placeholderNode) } - func deactivateSearch(animated: Bool) { + func deactivateSearch(placeholderNode: SearchBarPlaceholderNode, animated: Bool) { if let searchDisplayController = self.searchDisplayController { - var maybePlaceholderNode: SearchBarPlaceholderNode? - self.chatListNode.forEachItemNode { node in - if let node = node as? ChatListSearchItemNode { - maybePlaceholderNode = node.searchBarNode - } - } - - searchDisplayController.deactivate(placeholder: maybePlaceholderNode, animated: animated) + searchDisplayController.deactivate(placeholder: placeholderNode, animated: animated) self.searchDisplayController = nil } } diff --git a/TelegramUI/ChatListNode.swift b/TelegramUI/ChatListNode.swift index f49fcbe229..d92e05bb80 100644 --- a/TelegramUI/ChatListNode.swift +++ b/TelegramUI/ChatListNode.swift @@ -324,6 +324,9 @@ final class ChatListNode: ListView { } } + var contentOffsetChanged: ((ListViewVisibleContentOffset) -> Void)? + var contentScrollingEnded: ((ListView) -> Bool)? + private let visibleUnreadCounts = ValuePromise(ChatListVisibleUnreadCounts()) private var visibleUnreadCountsValue = ChatListVisibleUnreadCounts() { didSet { @@ -842,10 +845,9 @@ final class ChatListNode: ListView { return .single(false) } self.didEndScrolling = { [weak self] in - guard let strongSelf = self else { - return + if let strongSelf = self { + let _ = strongSelf.contentScrollingEnded?(strongSelf) } - fixSearchableListNodeScrolling(strongSelf) } self.scrollToTopOptionPromise.set(combineLatest( @@ -884,6 +886,7 @@ final class ChatListNode: ListView { atTop = value <= 0.0 } strongSelf.scrolledAtTopValue = atTop + strongSelf.contentOffsetChanged?(offset) } } } @@ -955,11 +958,9 @@ final class ChatListNode: ListView { var pinnedOverscroll = false if case .chatList = strongSelf.mode { let entryCount = transition.chatListView.filteredEntries.count - if entryCount >= 2 { - if case .SearchEntry = transition.chatListView.filteredEntries[entryCount - 1] { - if transition.chatListView.filteredEntries[entryCount - 2].index.pinningIndex != nil { - pinnedOverscroll = true - } + if entryCount >= 1 { + if transition.chatListView.filteredEntries[entryCount - 1].index.pinningIndex != nil { + pinnedOverscroll = true } } } diff --git a/TelegramUI/ChatListNodeEntries.swift b/TelegramUI/ChatListNodeEntries.swift index 1cd883e5ae..247f73ca2b 100644 --- a/TelegramUI/ChatListNodeEntries.swift +++ b/TelegramUI/ChatListNodeEntries.swift @@ -258,12 +258,12 @@ func chatListNodeEntriesForView(_ view: ChatListView, state: ChatListNodeState, } } } - switch mode { - case .chatList: - result.append(.SearchEntry(theme: state.presentationData.theme, text: view.groupId == nil ? state.presentationData.strings.DialogList_SearchLabel : "Search this feed", isEnabled: !state.editing)) - case .peers: - result.append(.SearchEntry(theme: state.presentationData.theme, text: state.presentationData.strings.Common_Search, isEnabled: !state.editing)) - } +// switch mode { +// case .chatList: +// result.append(.SearchEntry(theme: state.presentationData.theme, text: view.groupId == nil ? state.presentationData.strings.DialogList_SearchLabel : "Search this feed", isEnabled: !state.editing)) +// case .peers: +// result.append(.SearchEntry(theme: state.presentationData.theme, text: state.presentationData.strings.Common_Search, isEnabled: !state.editing)) +// } } if result.count >= 2, case .SearchEntry = result[result.count - 1], case .HoleEntry = result[result.count - 2] { return [] diff --git a/TelegramUI/ChatListSearchItem.swift b/TelegramUI/ChatListSearchItem.swift index 59295fc96d..0c80907ca3 100644 --- a/TelegramUI/ChatListSearchItem.swift +++ b/TelegramUI/ChatListSearchItem.swift @@ -110,7 +110,7 @@ class ChatListSearchItemNode: ListViewItemNode { let backgroundColor = nextIsPinned ? item.theme.chatList.pinnedItemBackgroundColor : item.theme.chatList.itemBackgroundColor - let searchBarApply = searchBarNodeLayout(NSAttributedString(string: placeholder ?? "", font: searchBarFont, textColor: UIColor(rgb: 0x8e8e93)), CGSize(width: baseWidth - 16.0, height: CGFloat.greatestFiniteMagnitude), UIColor(rgb: 0x8e8e93), nextIsPinned ? item.theme.chatList.pinnedSearchBarColor : item.theme.chatList.regularSearchBarColor, backgroundColor) + let searchBarApply = searchBarNodeLayout(NSAttributedString(string: placeholder ?? "", font: searchBarFont, textColor: UIColor(rgb: 0x8e8e93)), CGSize(width: baseWidth - 16.0, height: 28.0), 1.0, UIColor(rgb: 0x8e8e93), nextIsPinned ? item.theme.chatList.pinnedSearchBarColor : item.theme.chatList.regularSearchBarColor, backgroundColor, .immediate) let layout = ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: 44.0), insets: UIEdgeInsets()) diff --git a/TelegramUI/ChatListViewTransition.swift b/TelegramUI/ChatListViewTransition.swift index 293c9be198..a8f0c34919 100644 --- a/TelegramUI/ChatListViewTransition.swift +++ b/TelegramUI/ChatListViewTransition.swift @@ -194,10 +194,8 @@ func preparedChatListNodeViewTransition(from fromView: ChatListNodeView?, to toV fromEmptyView = true } - if !searchMode && fromEmptyView && scrollToItem == nil && toView.filteredEntries.count >= 2 { - if case .SearchEntry = toView.filteredEntries[toView.filteredEntries.count - 1] { - scrollToItem = ListViewScrollToItem(index: 1, position: .top(0.0), animated: false, curve: .Default(duration: 0.0), directionHint: .Up) - } + if !searchMode && fromEmptyView && scrollToItem == nil && toView.filteredEntries.count >= 1 { + scrollToItem = ListViewScrollToItem(index: 0, position: .top(-navigationBarSearchContentHeight), animated: false, curve: .Default(duration: 0.0), directionHint: .Up) } subscriber.putNext(ChatListNodeViewTransition(chatListView: toView, deleteItems: adjustedDeleteIndices, insertEntries: adjustedIndicesAndItems, updateEntries: adjustedUpdateItems, options: options, scrollToItem: scrollToItem, stationaryItemRange: stationaryItemRange)) diff --git a/TelegramUI/ChatMessageInteractiveFileNode.swift b/TelegramUI/ChatMessageInteractiveFileNode.swift index 017eba71b3..e88f7f9231 100644 --- a/TelegramUI/ChatMessageInteractiveFileNode.swift +++ b/TelegramUI/ChatMessageInteractiveFileNode.swift @@ -681,11 +681,8 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { let streamingStatusForegroundColor: UIColor = incoming ? bubbleTheme.incomingAccentControlColor : bubbleTheme.outgoingAccentControlColor let streamingStatusBackgroundColor: UIColor = incoming ? bubbleTheme.incomingMediaInactiveControlColor : bubbleTheme.outgoingMediaInactiveControlColor switch resourceStatus.fetchStatus { - case let .Fetching(isActive, progress): - var adjustedProgress = progress - if isActive { - adjustedProgress = max(adjustedProgress, 0.027) - } + case let .Fetching(_, progress): + let adjustedProgress = max(progress, 0.027) streamingState = .cloudProgress(color: streamingStatusForegroundColor, strokeBackgroundColor: streamingStatusBackgroundColor, lineWidth: 2.0, value: CGFloat(adjustedProgress)) case .Local: if let cloudFetchedIconImage = self.cloudFetchedIconImage { @@ -717,10 +714,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { self.waveformScrubbingNode?.enableScrubbing = false switch fetchStatus { case let .Fetching(isActive, progress): - var adjustedProgress = progress - if isActive { - adjustedProgress = max(adjustedProgress, 0.027) - } + let adjustedProgress = max(progress, 0.027) state = .progress(color: statusForegroundColor, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true) case .Local: if isAudio { diff --git a/TelegramUI/ChatMessageInteractiveInstantVideoNode.swift b/TelegramUI/ChatMessageInteractiveInstantVideoNode.swift index 64adabeb1c..ce4ce0bfd8 100644 --- a/TelegramUI/ChatMessageInteractiveInstantVideoNode.swift +++ b/TelegramUI/ChatMessageInteractiveInstantVideoNode.swift @@ -508,10 +508,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { case let .fetchStatus(fetchStatus): switch fetchStatus { case let .Fetching(isActive, progress): - var adjustedProgress = progress - if isActive { - adjustedProgress = max(adjustedProgress, 0.027) - } + let adjustedProgress = max(progress, 0.027) state = .progress(color: bubbleTheme.mediaOverlayControlForegroundColor, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true) case .Local: if isSecretMedia && self.secretProgressIcon != nil { diff --git a/TelegramUI/ChatMessageInteractiveMediaNode.swift b/TelegramUI/ChatMessageInteractiveMediaNode.swift index 515f0323f9..17e9d1d7ae 100644 --- a/TelegramUI/ChatMessageInteractiveMediaNode.swift +++ b/TelegramUI/ChatMessageInteractiveMediaNode.swift @@ -379,11 +379,8 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { updatedStatusSignal = combineLatest(chatMessagePhotoStatus(account: account, messageId: message.id, photoReference: .message(message: MessageReference(message), media: image)), account.pendingMessageManager.pendingMessageStatus(message.id)) |> map { resourceStatus, pendingStatus -> MediaResourceStatus in if let pendingStatus = pendingStatus { - var progress = pendingStatus.progress - if pendingStatus.isRunning { - progress = max(progress, 0.027) - } - return .Fetching(isActive: pendingStatus.isRunning, progress: progress) + let adjustedProgress = max(pendingStatus.progress, 0.027) + return .Fetching(isActive: pendingStatus.isRunning, progress: adjustedProgress) } else { return resourceStatus } @@ -395,11 +392,8 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { updatedStatusSignal = combineLatest(messageMediaFileStatus(account: account, messageId: message.id, file: file), account.pendingMessageManager.pendingMessageStatus(message.id)) |> map { resourceStatus, pendingStatus -> MediaResourceStatus in if let pendingStatus = pendingStatus { - var progress = pendingStatus.progress - if pendingStatus.isRunning { - progress = max(progress, 0.027) - } - return .Fetching(isActive: pendingStatus.isRunning, progress: progress) + let adjustedProgress = max(pendingStatus.progress, 0.027) + return .Fetching(isActive: pendingStatus.isRunning, progress: adjustedProgress) } else { return resourceStatus } @@ -631,11 +625,8 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { } if let fetchStatus = self.fetchStatus { switch fetchStatus { - case let .Fetching(isActive, progress): - var adjustedProgress = progress - if isActive { - adjustedProgress = max(adjustedProgress, 0.027) - } + case let .Fetching(_, progress): + let adjustedProgress = max(progress, 0.027) var wasCheck = false if let statusNode = self.statusNode, case .check = statusNode.state { wasCheck = true diff --git a/TelegramUI/ChatMessageStickerItemNode.swift b/TelegramUI/ChatMessageStickerItemNode.swift index 6889ef1507..21d37d3896 100644 --- a/TelegramUI/ChatMessageStickerItemNode.swift +++ b/TelegramUI/ChatMessageStickerItemNode.swift @@ -199,12 +199,13 @@ class ChatMessageStickerItemNode: ChatMessageItemView { let displayLeftInset = params.leftInset + layoutConstants.bubble.edgeInset + avatarInset - let imageInset: CGFloat = 10.0 - let innerImageSize = imageSize - imageSize = CGSize(width: imageSize.width + imageInset * 2.0, height: imageSize.height + imageInset * 2.0) - let imageFrame = CGRect(origin: CGPoint(x: 0.0 + (incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + avatarInset + layoutConstants.bubble.contentInsets.left) : (params.width - params.rightInset - imageSize.width - layoutConstants.bubble.edgeInset - layoutConstants.bubble.contentInsets.left)), y: 0.0), size: CGSize(width: imageSize.width, height: imageSize.height)) + let innerImageInset: CGFloat = 10.0 + let imageInset: CGFloat = 2.0 + let innerImageSize = CGSize(width: imageSize.width + innerImageInset * 2.0, height: imageSize.height + innerImageInset * 2.0) + let imageFrame = CGRect(origin: CGPoint(x: 0.0 + (incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + avatarInset + layoutConstants.bubble.contentInsets.left) : (params.width - params.rightInset - innerImageSize.width - layoutConstants.bubble.edgeInset - layoutConstants.bubble.contentInsets.left)), y: -imageInset), size: innerImageSize) - let arguments = TransformImageArguments(corners: ImageCorners(), imageSize: innerImageSize, boundingSize: innerImageSize, intrinsicInsets: UIEdgeInsets(top: imageInset, left: imageInset, bottom: imageInset, right: imageInset)) + let arguments = TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets(top: innerImageInset, left: innerImageInset, bottom: innerImageInset, right: innerImageInset)) + imageSize.height += imageInset * 2.0 let imageApply = imageLayout(arguments) @@ -229,14 +230,12 @@ class ChatMessageStickerItemNode: ChatMessageItemView { // edited = true } else if let attribute = attribute as? ViewCountMessageAttribute { viewCount = attribute.count - }// else if let _ = attribute as? InlineBotMessageAttribute { - // sentViaBot = true - // } + } } let dateText = stringForMessageTimestampStatus(message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, format: .regular) - let (dateAndStatusSize, dateAndStatusApply) = makeDateAndStatusLayout(item.presentationData.theme, item.presentationData.strings, edited && !sentViaBot, viewCount, dateText, statusType, CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude)) + let (dateAndStatusSize, dateAndStatusApply) = makeDateAndStatusLayout(item.presentationData.theme, item.presentationData.strings, edited, viewCount, dateText, statusType, CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude)) var viaBotApply: (TextNodeLayout, () -> TextNode)? var replyInfoApply: (CGSize, () -> ChatMessageReplyInfoNode)? @@ -361,7 +360,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { } dateAndStatusApply(false) - strongSelf.dateAndStatusNode.frame = CGRect(origin: CGPoint(x: max(displayLeftInset, updatedImageFrame.maxX - dateAndStatusSize.width - 4.0), y: updatedImageFrame.maxY - dateAndStatusSize.height - 4.0), size: dateAndStatusSize) + strongSelf.dateAndStatusNode.frame = CGRect(origin: CGPoint(x: max(displayLeftInset, updatedImageFrame.maxX - dateAndStatusSize.width - 4.0), y: updatedImageFrame.maxY - dateAndStatusSize.height - 16.0), size: dateAndStatusSize) if let updatedReplyBackgroundNode = updatedReplyBackgroundNode { if strongSelf.replyBackgroundNode == nil { diff --git a/TelegramUI/CommandChatInputContextPanelNode.swift b/TelegramUI/CommandChatInputContextPanelNode.swift index c2f797b3ad..5e304831a9 100644 --- a/TelegramUI/CommandChatInputContextPanelNode.swift +++ b/TelegramUI/CommandChatInputContextPanelNode.swift @@ -96,8 +96,7 @@ final class CommandChatInputContextPanelNode: ChatInputContextPanelNode { entries.append(entry) index += 1 } - prepareTransition(from: self.currentEntries ?? [], to: entries) - + self.prepareTransition(from: self.currentEntries ?? [], to: entries) } private func prepareTransition(from: [CommandChatInputContextPanelEntry]? , to: [CommandChatInputContextPanelEntry]) { @@ -120,7 +119,6 @@ final class CommandChatInputContextPanelNode: ChatInputContextPanelNode { let inputText = NSMutableAttributedString(attributedString: textInputState.inputText) let replacementText = command.command.text + " " - inputText.replaceCharacters(in: range, with: replacementText) let selectionPosition = range.lowerBound + (replacementText as NSString).length @@ -185,8 +183,7 @@ final class CommandChatInputContextPanelNode: ChatInputContextPanelNode { } private func topInsetForLayout(size: CGSize) -> CGFloat { - var minimumItemHeights: CGFloat = floor(MentionChatInputPanelItemNode.itemHeight * 3.5) - + let minimumItemHeights: CGFloat = floor(MentionChatInputPanelItemNode.itemHeight * 3.5) return max(size.height - minimumItemHeights, 0.0) } @@ -204,16 +201,16 @@ final class CommandChatInputContextPanelNode: ChatInputContextPanelNode { var duration: Double = 0.0 var curve: UInt = 0 switch transition { - case .immediate: - break - case let .animated(animationDuration, animationCurve): - duration = animationDuration - switch animationCurve { - case .easeInOut: + case .immediate: break - case .spring: - curve = 7 - } + case let .animated(animationDuration, animationCurve): + duration = animationDuration + switch animationCurve { + case .easeInOut: + break + case .spring: + curve = 7 + } } let listViewCurve: ListViewAnimationCurve diff --git a/TelegramUI/ComposeController.swift b/TelegramUI/ComposeController.swift index 6b94c9f492..8710ce647b 100644 --- a/TelegramUI/ComposeController.swift +++ b/TelegramUI/ComposeController.swift @@ -24,6 +24,8 @@ public class ComposeController: ViewController { private var presentationData: PresentationData private var presentationDataDisposable: Disposable? + private var searchContentNode: NavigationBarSearchContentNode? + public init(account: Account) { self.account = account @@ -56,6 +58,11 @@ public class ComposeController: ViewController { } } }) + + self.searchContentNode = NavigationBarSearchContentNode(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Common_Search, activate: { [weak self] in + self?.activateSearch() + }) + self.navigationBar?.setContentNode(self.searchContentNode, animated: false) } required public init(coder aDecoder: NSCoder) { @@ -70,6 +77,7 @@ public class ComposeController: ViewController { private func updateThemeAndStrings() { self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBar.style.style self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData)) + self.searchContentNode?.updateThemeAndPlaceholder(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Common_Search) self.title = self.presentationData.strings.Compose_NewMessage self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil) } @@ -178,7 +186,9 @@ public class ComposeController: ViewController { if let scrollToTop = self.scrollToTop { scrollToTop() } - self.contactsNode.activateSearch() + if let searchContentNode = self.searchContentNode { + self.contactsNode.activateSearch(placeholderNode: searchContentNode.placeholderNode) + } self.setDisplayNavigationBar(false, transition: .animated(duration: 0.5, curve: .spring)) } } @@ -186,7 +196,9 @@ public class ComposeController: ViewController { private func deactivateSearch() { if !self.displayNavigationBar { self.setDisplayNavigationBar(true, transition: .animated(duration: 0.5, curve: .spring)) - self.contactsNode.deactivateSearch() + if let searchContentNode = self.searchContentNode { + self.contactsNode.deactivateSearch(placeholderNode: searchContentNode.placeholderNode) + } } } diff --git a/TelegramUI/ComposeControllerNode.swift b/TelegramUI/ComposeControllerNode.swift index acaeb98531..44493071aa 100644 --- a/TelegramUI/ComposeControllerNode.swift +++ b/TelegramUI/ComposeControllerNode.swift @@ -97,9 +97,6 @@ final class ComposeControllerNode: ASDisplayNode { if let searchDisplayController = self.searchDisplayController { searchDisplayController.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: transition) - if !searchDisplayController.isDeactivating { - insets.top += layout.statusBarHeight ?? 0.0 - } } self.contactListNode.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: layout.metrics, intrinsicInsets: insets, safeInsets: layout.safeInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, standardInputHeight: layout.standardInputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging), transition: transition) @@ -107,48 +104,34 @@ final class ComposeControllerNode: ASDisplayNode { self.contactListNode.frame = CGRect(origin: CGPoint(), size: layout.size) } - func activateSearch() { - guard let (containerLayout, navigationBarHeight) = self.containerLayout, let navigationBar = self.navigationBar else { + func activateSearch(placeholderNode: SearchBarPlaceholderNode) { + guard let (containerLayout, navigationBarHeight) = self.containerLayout, let navigationBar = self.navigationBar, self.searchDisplayController == nil else { return } - var maybePlaceholderNode: SearchBarPlaceholderNode? - self.contactListNode.listNode.forEachItemNode { node in - if let node = node as? ChatListSearchItemNode { - maybePlaceholderNode = node.searchBarNode + self.searchDisplayController = SearchDisplayController(theme: self.presentationData.theme, strings: self.presentationData.strings, mode: .navigation, contentNode: ContactsSearchContainerNode(account: self.account, onlyWriteable: false, categories: [.cloudContacts, .global], openPeer: { [weak self] peer in + if let requestOpenPeerFromSearch = self?.requestOpenPeerFromSearch, case let .peer(peer, _) = peer { + requestOpenPeerFromSearch(peer.id) } - } + }), cancel: { [weak self] in + self?.requestDeactivateSearch?() + }) - if let _ = self.searchDisplayController { - return - } - - if let placeholderNode = maybePlaceholderNode { - self.searchDisplayController = SearchDisplayController(theme: self.presentationData.theme, strings: self.presentationData.strings, contentNode: ContactsSearchContainerNode(account: self.account, onlyWriteable: false, categories: [.cloudContacts, .global], openPeer: { [weak self] peer in - if let requestOpenPeerFromSearch = self?.requestOpenPeerFromSearch, case let .peer(peer, _) = peer { - requestOpenPeerFromSearch(peer.id) + self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate) + self.searchDisplayController?.activate(insertSubnode: { [weak self, weak placeholderNode] subnode, isSearchBar in + if let strongSelf = self, let strongPlaceholderNode = placeholderNode { + if isSearchBar { + strongPlaceholderNode.supernode?.insertSubnode(subnode, aboveSubnode: strongPlaceholderNode) + } else { + strongSelf.insertSubnode(subnode, belowSubnode: navigationBar) } - }), cancel: { [weak self] in - self?.requestDeactivateSearch?() - }) - - self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate) - self.searchDisplayController?.activate(insertSubnode: { subnode in - self.insertSubnode(subnode, belowSubnode: navigationBar) - }, placeholder: placeholderNode) - } + } + }, placeholder: placeholderNode) } - func deactivateSearch() { + func deactivateSearch(placeholderNode: SearchBarPlaceholderNode) { if let searchDisplayController = self.searchDisplayController { - var maybePlaceholderNode: SearchBarPlaceholderNode? - self.contactListNode.listNode.forEachItemNode { node in - if let node = node as? ChatListSearchItemNode { - maybePlaceholderNode = node.searchBarNode - } - } - - searchDisplayController.deactivate(placeholder: maybePlaceholderNode) + searchDisplayController.deactivate(placeholder: placeholderNode) self.searchDisplayController = nil } } diff --git a/TelegramUI/ContactListActionItem.swift b/TelegramUI/ContactListActionItem.swift index 47e09d4212..440c7ecad6 100644 --- a/TelegramUI/ContactListActionItem.swift +++ b/TelegramUI/ContactListActionItem.swift @@ -8,6 +8,11 @@ public enum ContactListActionItemInlineIconPosition { case right } +public enum ContactListActionItemHighlight { + case cell + case alpha +} + public enum ContactListActionItemIcon : Equatable { case none case generic(UIImage) @@ -52,13 +57,15 @@ class ContactListActionItem: ListViewItem { let theme: PresentationTheme let title: String let icon: ContactListActionItemIcon + let highlight: ContactListActionItemHighlight let action: () -> Void let header: ListViewItemHeader? - init(theme: PresentationTheme, title: String, icon: ContactListActionItemIcon, header: ListViewItemHeader?, action: @escaping () -> Void) { + init(theme: PresentationTheme, title: String, icon: ContactListActionItemIcon, highlight: ContactListActionItemHighlight = .cell, header: ListViewItemHeader?, action: @escaping () -> Void) { self.theme = theme self.title = title self.icon = icon + self.highlight = highlight self.header = header self.action = action } @@ -225,8 +232,27 @@ class ContactListActionItemNode: ListViewItemNode { let _ = titleApply() + var titleOffset = leftInset + var hideBottomStripe: Bool = false if let image = item.icon.image { - strongSelf.iconNode.frame = CGRect(origin: CGPoint(x: params.leftInset + floor((leftInset - params.leftInset - image.size.width) / 2.0), y: floor((contentSize.height - image.size.height) / 2.0)), size: image.size) + var iconFrame: CGRect + switch item.icon { + case let .inline(_, position): + hideBottomStripe = true + let iconSpacing: CGFloat = 4.0 + let totalWidth: CGFloat = titleLayout.size.width + image.size.width + iconSpacing + switch position { + case .left: + iconFrame = CGRect(origin: CGPoint(x: params.leftInset + floor((contentSize.width - params.leftInset - params.rightInset - totalWidth) / 2.0), y: floor((contentSize.height - image.size.height) / 2.0)), size: image.size) + titleOffset = iconFrame.minX + iconSpacing + case .right: + iconFrame = CGRect(origin: CGPoint(x: params.leftInset + floor((contentSize.width - params.leftInset - params.rightInset - totalWidth) / 2.0) + totalWidth - image.size.width, y: floor((contentSize.height - image.size.height) / 2.0)), size: image.size) + titleOffset = iconFrame.maxX - totalWidth + } + default: + iconFrame = CGRect(origin: CGPoint(x: params.leftInset + floor((leftInset - params.leftInset - image.size.width) / 2.0), y: floor((contentSize.height - image.size.height) / 2.0)), size: image.size) + } + strongSelf.iconNode.frame = iconFrame } if strongSelf.backgroundNode.supernode == nil { @@ -240,10 +266,11 @@ class ContactListActionItemNode: ListViewItemNode { } strongSelf.topStripeNode.isHidden = true + strongSelf.bottomStripeNode.isHidden = hideBottomStripe strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: leftInset, y: contentSize.height), size: CGSize(width: params.width - leftInset, height: separatorHeight)) - strongSelf.titleNode.frame = CGRect(origin: CGPoint(x: leftInset, y: floor((contentSize.height - titleLayout.size.height) / 2.0)), size: titleLayout.size) + strongSelf.titleNode.frame = CGRect(origin: CGPoint(x: titleOffset, y: floor((contentSize.height - titleLayout.size.height) / 2.0)), size: titleLayout.size) strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: 50.0 + UIScreenPixel + UIScreenPixel)) } @@ -254,36 +281,50 @@ class ContactListActionItemNode: ListViewItemNode { override func setHighlighted(_ highlighted: Bool, at point: CGPoint, animated: Bool) { super.setHighlighted(highlighted, at: point, animated: animated) - if highlighted { - self.highlightedBackgroundNode.alpha = 1.0 - if self.highlightedBackgroundNode.supernode == nil { - var anchorNode: ASDisplayNode? - if self.bottomStripeNode.supernode != nil { - anchorNode = self.bottomStripeNode - } else if self.topStripeNode.supernode != nil { - anchorNode = self.topStripeNode - } else if self.backgroundNode.supernode != nil { - anchorNode = self.backgroundNode - } - if let anchorNode = anchorNode { - self.insertSubnode(self.highlightedBackgroundNode, aboveSubnode: anchorNode) - } else { - self.addSubnode(self.highlightedBackgroundNode) + if let item = self.item, case .alpha = item.highlight { + if highlighted { + self.titleNode.alpha = 0.4 + self.iconNode.alpha = 0.4 + } else { + if animated { + self.titleNode.layer.animateAlpha(from: self.titleNode.alpha, to: 1.0, duration: 0.2) + self.iconNode.layer.animateAlpha(from: self.iconNode.alpha, to: 1.0, duration: 0.2) } + self.titleNode.alpha = 1.0 + self.iconNode.alpha = 1.0 } } else { - if self.highlightedBackgroundNode.supernode != nil { - if animated { - self.highlightedBackgroundNode.layer.animateAlpha(from: self.highlightedBackgroundNode.alpha, to: 0.0, duration: 0.4, completion: { [weak self] completed in - if let strongSelf = self { - if completed { - strongSelf.highlightedBackgroundNode.removeFromSupernode() + if highlighted { + self.highlightedBackgroundNode.alpha = 1.0 + if self.highlightedBackgroundNode.supernode == nil { + var anchorNode: ASDisplayNode? + if self.bottomStripeNode.supernode != nil { + anchorNode = self.bottomStripeNode + } else if self.topStripeNode.supernode != nil { + anchorNode = self.topStripeNode + } else if self.backgroundNode.supernode != nil { + anchorNode = self.backgroundNode + } + if let anchorNode = anchorNode { + self.insertSubnode(self.highlightedBackgroundNode, aboveSubnode: anchorNode) + } else { + self.addSubnode(self.highlightedBackgroundNode) + } + } + } else { + if self.highlightedBackgroundNode.supernode != nil { + if animated { + self.highlightedBackgroundNode.layer.animateAlpha(from: self.highlightedBackgroundNode.alpha, to: 0.0, duration: 0.4, completion: { [weak self] completed in + if let strongSelf = self { + if completed { + strongSelf.highlightedBackgroundNode.removeFromSupernode() + } } - } - }) - self.highlightedBackgroundNode.alpha = 0.0 - } else { - self.highlightedBackgroundNode.removeFromSupernode() + }) + self.highlightedBackgroundNode.alpha = 0.0 + } else { + self.highlightedBackgroundNode.removeFromSupernode() + } } } } diff --git a/TelegramUI/ContactListNode.swift b/TelegramUI/ContactListNode.swift index f6e4d1c547..a7d33cd0ee 100644 --- a/TelegramUI/ContactListNode.swift +++ b/TelegramUI/ContactListNode.swift @@ -5,8 +5,23 @@ import SwiftSignalKit import Postbox import TelegramCore +private let dropDownIcon = { () -> UIImage in + UIGraphicsBeginImageContextWithOptions(CGSize(width: 12.0, height: 12.0), false, 0.0) + let context = UIGraphicsGetCurrentContext()! + context.setBlendMode(.copy) + context.setFillColor(UIColor.black.cgColor) + context.move(to: CGPoint(x: 0.0, y: 3.0)) + context.addLine(to: CGPoint(x: 12.0, y: 3.0)) + context.addLine(to: CGPoint(x: 6.0, y: 9.0)) + context.fillPath() + let image = UIGraphicsGetImageFromCurrentImageContext()! + UIGraphicsEndImageContext() + return image +}() + private enum ContactListNodeEntryId: Hashable { case search + case sort case permission(action: Bool) case option(index: Int) case peerId(Int64) @@ -16,6 +31,8 @@ private enum ContactListNodeEntryId: Hashable { switch self { case .search: return 0 + case .sort: + return 1 case let .permission(action): return (action ? 3 : 2).hashValue case let .option(index): @@ -40,6 +57,13 @@ private enum ContactListNodeEntryId: Hashable { default: return false } + case .sort: + switch rhs { + case .sort: + return true + default: + return false + } case let .permission(action): if case .permission(action) = rhs { return true @@ -71,12 +95,14 @@ private enum ContactListNodeEntryId: Hashable { private final class ContactListNodeInteraction { let activateSearch: () -> Void + let openSortMenu: () -> Void let authorize: () -> Void let suppressWarning: () -> Void let openPeer: (ContactListPeer) -> Void - init(activateSearch: @escaping () -> Void, authorize: @escaping () -> Void, suppressWarning: @escaping () -> Void, openPeer: @escaping (ContactListPeer) -> Void) { + init(activateSearch: @escaping () -> Void, openSortMenu: @escaping () -> Void, authorize: @escaping () -> Void, suppressWarning: @escaping () -> Void, openPeer: @escaping (ContactListPeer) -> Void) { self.activateSearch = activateSearch + self.openSortMenu = openSortMenu self.authorize = authorize self.suppressWarning = suppressWarning self.openPeer = openPeer @@ -136,6 +162,7 @@ enum ContactListPeer: Equatable { private enum ContactListNodeEntry: Comparable, Identifiable { case search(PresentationTheme, PresentationStrings) + case sort(PresentationTheme, PresentationStrings, ContactsSortOrder) case permissionInfo(PresentationTheme, PresentationStrings, Bool) case permissionEnable(PresentationTheme, String) case option(Int, ContactListAdditionalOption, ListViewItemHeader?, PresentationTheme, PresentationStrings) @@ -145,6 +172,8 @@ private enum ContactListNodeEntry: Comparable, Identifiable { switch self { case .search: return .search + case .sort: + return .sort case .permissionInfo: return .permission(action: false) case .permissionEnable: @@ -167,6 +196,14 @@ private enum ContactListNodeEntry: Comparable, Identifiable { return ChatListSearchItem(theme: theme, placeholder: strings.Contacts_SearchLabel, activate: { interaction.activateSearch() }) + case let .sort(theme, strings, sortOrder): + var text = strings.Contacts_SortedByName + if case .presence = sortOrder { + text = strings.Contacts_SortedByPresence + } + return ContactListActionItem(theme: theme, title: text, icon: .inline(dropDownIcon, .right), highlight: .alpha, header: nil, action: { + interaction.openSortMenu() + }) case let .permissionInfo(theme, strings, suppressed): return PermissionInfoItem(theme: theme, strings: strings, subject: .contacts, type: .denied, style: .plain, suppressed: suppressed, close: { interaction.suppressWarning() @@ -207,6 +244,12 @@ private enum ContactListNodeEntry: Comparable, Identifiable { } else { return false } + case let .sort(lhsTheme, lhsStrings, lhsSortOrder): + if case let .sort(rhsTheme, rhsStrings, rhsSortOrder) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsSortOrder == rhsSortOrder { + return true + } else { + return false + } case let .permissionInfo(lhsTheme, lhsStrings, lhsSuppressed): if case let .permissionInfo(rhsTheme, rhsStrings, rhsSuppressed) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsSuppressed == rhsSuppressed { return true @@ -276,23 +319,30 @@ private enum ContactListNodeEntry: Comparable, Identifiable { switch lhs { case .search: return true - case .permissionInfo: + case .sort: switch rhs { case .search: return false default: return true } + case .permissionInfo: + switch rhs { + case .search, .sort: + return false + default: + return true + } case .permissionEnable: switch rhs { - case .search, .permissionInfo: + case .search, .sort, .permissionInfo: return false default: return true } case let .option(lhsIndex, _, _, _, _): switch rhs { - case .search, .permissionInfo, .permissionEnable: + case .search, .sort, .permissionInfo, .permissionEnable: return false case let .option(rhsIndex, _, _, _, _): return lhsIndex < rhsIndex @@ -301,7 +351,7 @@ private enum ContactListNodeEntry: Comparable, Identifiable { } case let .peer(lhsIndex, _, _, _, _, _, _, _, _, _, _): switch rhs { - case .search, .permissionInfo, .permissionEnable, .option: + case .search, .sort, .permissionInfo, .permissionEnable, .option: return false case let .peer(rhsIndex, _, _, _, _, _, _, _, _, _, _): return lhsIndex < rhsIndex @@ -376,7 +426,7 @@ private extension PeerIndexNameRepresentation { } } -private func contactListNodeEntries(accountPeer: Peer?, peers: [ContactListPeer], presences: [PeerId: PeerPresence], presentation: ContactListPresentation, selectionState: ContactListNodeGroupSelectionState?, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, sortOrder: PresentationPersonNameOrder, displayOrder: PresentationPersonNameOrder, disabledPeerIds:Set, authorizationStatus: AccessType, warningSuppressed: (Bool, Bool)) -> [ContactListNodeEntry] { +private func contactListNodeEntries(accountPeer: Peer?, peers: [ContactListPeer], presences: [PeerId: PeerPresence], presentation: ContactListPresentation, selectionState: ContactListNodeGroupSelectionState?, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, sortOrder: PresentationPersonNameOrder, displayOrder: PresentationPersonNameOrder, disabledPeerIds:Set, authorizationStatus: AccessType, warningSuppressed: (Bool, Bool), displaySortOptions: Bool) -> [ContactListNodeEntry] { var entries: [ContactListNodeEntry] = [] var commonHeader: ListViewItemHeader? @@ -385,8 +435,9 @@ private func contactListNodeEntries(accountPeer: Peer?, peers: [ContactListPeer] switch presentation { case let .orderedByPresence(options): - entries.append(.search(theme, strings)) - + if displaySortOptions, let sortOrder = presentation.sortOrder { + entries.append(.sort(theme, strings, sortOrder)) + } var addHeader = false if #available(iOSApplicationExtension 10.0, *) { let (suppressed, syncDisabled) = warningSuppressed @@ -436,6 +487,10 @@ private func contactListNodeEntries(accountPeer: Peer?, peers: [ContactListPeer] entries.append(.option(i, options[i], commonHeader, theme, strings)) } case let .natural(displaySearch, options): + if displaySortOptions, let sortOrder = presentation.sortOrder { + entries.append(.sort(theme, strings, sortOrder)) + } + orderedPeers = peers.sorted(by: { lhs, rhs in let result = lhs.indexName.isLessThan(other: rhs.indexName, ordering: sortOrder) if result == .orderedSame { @@ -490,9 +545,6 @@ private func contactListNodeEntries(accountPeer: Peer?, peers: [ContactListPeer] } headers[peer.id] = header } - if displaySearch { - entries.append(.search(theme, strings)) - } for i in 0 ..< options.count { entries.append(.option(i, options[i], commonHeader, theme, strings)) } @@ -607,6 +659,17 @@ enum ContactListPresentation { case orderedByPresence(options: [ContactListAdditionalOption]) case natural(displaySearch: Bool, options: [ContactListAdditionalOption]) case search(signal: Signal, searchChatList: Bool, searchDeviceContacts: Bool) + + var sortOrder: ContactsSortOrder? { + switch self { + case .orderedByPresence: + return .presence + case .natural: + return .natural + default: + return nil + } + } } struct ContactListNodeGroupSelectionState: Equatable { @@ -687,6 +750,7 @@ final class ContactListNode: ASDisplayNode { } var activateSearch: (() -> Void)? + var openSortMenu: (() -> Void)? var openPeer: ((ContactListPeer) -> Void)? var openPrivacyPolicy: (() -> Void)? var suppressPermissionWarning: (() -> Void)? @@ -701,7 +765,7 @@ final class ContactListNode: ASDisplayNode { private var authorizationNode: PermissionContentNode private let displayPermissionPlaceholder: Bool - init(account: Account, presentation: Signal, filters: [ContactListFilter] = [.excludeSelf], selectionState: ContactListNodeGroupSelectionState? = nil, displayPermissionPlaceholder: Bool = true) { + init(account: Account, presentation: Signal, filters: [ContactListFilter] = [.excludeSelf], selectionState: ContactListNodeGroupSelectionState? = nil, displayPermissionPlaceholder: Bool = true, displaySortOptions: Bool = false) { self.account = account self.filters = filters self.displayPermissionPlaceholder = displayPermissionPlaceholder @@ -763,6 +827,8 @@ final class ContactListNode: ASDisplayNode { let interaction = ContactListNodeInteraction(activateSearch: { [weak self] in self?.activateSearch?() + }, openSortMenu: { [weak self] in + self?.openSortMenu?() }, authorize: { authorizeImpl?() }, suppressWarning: { [weak self] in @@ -919,7 +985,7 @@ final class ContactListNode: ASDisplayNode { peers.append(.deviceContact(stableId, contact)) } - let entries = contactListNodeEntries(accountPeer: nil, peers: peers, presences: localPeersAndStatuses.1, presentation: presentation, selectionState: selectionState, theme: themeAndStrings.0, strings: themeAndStrings.1, dateTimeFormat: themeAndStrings.2, sortOrder: themeAndStrings.3, displayOrder: themeAndStrings.4, disabledPeerIds: disabledPeerIds, authorizationStatus: .allowed, warningSuppressed: (true, true)) + let entries = contactListNodeEntries(accountPeer: nil, peers: peers, presences: localPeersAndStatuses.1, presentation: presentation, selectionState: selectionState, theme: themeAndStrings.0, strings: themeAndStrings.1, dateTimeFormat: themeAndStrings.2, sortOrder: themeAndStrings.3, displayOrder: themeAndStrings.4, disabledPeerIds: disabledPeerIds, authorizationStatus: .allowed, warningSuppressed: (true, true), displaySortOptions: false) let previous = previousEntries.swap(entries) return .single(preparedContactListNodeTransition(account: account, from: previous ?? [], to: entries, interaction: interaction, firstTime: previous == nil, isEmpty: false, generateIndexSections: generateSections, animation: .none)) } @@ -962,7 +1028,7 @@ final class ContactListNode: ASDisplayNode { if (authorizationStatus == .notDetermined || authorizationStatus == .denied) && peers.isEmpty { isEmpty = true } - let entries = contactListNodeEntries(accountPeer: view.accountPeer, peers: peers, presences: view.peerPresences, presentation: presentation, selectionState: selectionState, theme: themeAndStrings.0, strings: themeAndStrings.1, dateTimeFormat: themeAndStrings.2, sortOrder: themeAndStrings.3, displayOrder: themeAndStrings.4, disabledPeerIds: disabledPeerIds, authorizationStatus: authorizationStatus, warningSuppressed: warningSuppressed) + let entries = contactListNodeEntries(accountPeer: view.accountPeer, peers: peers, presences: view.peerPresences, presentation: presentation, selectionState: selectionState, theme: themeAndStrings.0, strings: themeAndStrings.1, dateTimeFormat: themeAndStrings.2, sortOrder: themeAndStrings.3, displayOrder: themeAndStrings.4, disabledPeerIds: disabledPeerIds, authorizationStatus: authorizationStatus, warningSuppressed: warningSuppressed, displaySortOptions: displaySortOptions) let previous = previousEntries.swap(entries) var hadPermissionInfo = false @@ -1062,6 +1128,18 @@ final class ContactListNode: ASDisplayNode { fixSearchableListNodeScrolling(strongSelf.listNode) } + self.listNode.visibleContentOffsetChanged = { [weak self] offset in + if let strongSelf = self { + let atTop: Bool + switch offset { + case .none, .unknown: + atTop = false + case let .known(value): + atTop = value <= 0.0 + } + } + } + authorizeImpl = { let _ = (DeviceAccess.authorizationStatus(account: account, subject: .contacts) |> take(1) diff --git a/TelegramUI/ContactSelectionController.swift b/TelegramUI/ContactSelectionController.swift index 5c5a01d0b3..6015b3d611 100644 --- a/TelegramUI/ContactSelectionController.swift +++ b/TelegramUI/ContactSelectionController.swift @@ -47,6 +47,8 @@ class ContactSelectionController: ViewController { private var presentationData: PresentationData private var presentationDataDisposable: Disposable? + private var searchContentNode: NavigationBarSearchContentNode? + var displayNavigationActivity: Bool = false { didSet { if self.displayNavigationActivity != oldValue { @@ -96,6 +98,11 @@ class ContactSelectionController: ViewController { } } }) + + self.searchContentNode = NavigationBarSearchContentNode(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Common_Search, activate: { [weak self] in + self?.activateSearch() + }) + self.navigationBar?.setContentNode(self.searchContentNode, animated: false) } required init(coder aDecoder: NSCoder) { @@ -110,6 +117,7 @@ class ContactSelectionController: ViewController { private func updateThemeAndStrings() { self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBar.style.style self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData)) + self.searchContentNode?.updateThemeAndPlaceholder(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Common_Search) self.title = self.titleProducer(self.presentationData.strings) self.tabBarItem.title = self.presentationData.strings.Contacts_Title self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil) @@ -195,7 +203,9 @@ class ContactSelectionController: ViewController { if let scrollToTop = self.scrollToTop { scrollToTop() } - self.contactsNode.activateSearch() + if let searchContentNode = self.searchContentNode { + self.contactsNode.activateSearch(placeholderNode: searchContentNode.placeholderNode) + } self.setDisplayNavigationBar(false, transition: .animated(duration: 0.5, curve: .spring)) } } @@ -204,7 +214,9 @@ class ContactSelectionController: ViewController { if !self.displayNavigationBar { self.contactsNode.prepareDeactivateSearch() self.setDisplayNavigationBar(true, transition: .animated(duration: 0.5, curve: .spring)) - self.contactsNode.deactivateSearch() + if let searchContentNode = self.searchContentNode { + self.contactsNode.deactivateSearch(placeholderNode: searchContentNode.placeholderNode) + } } } diff --git a/TelegramUI/ContactSelectionControllerNode.swift b/TelegramUI/ContactSelectionControllerNode.swift index 249dc7d2b6..0567e22421 100644 --- a/TelegramUI/ContactSelectionControllerNode.swift +++ b/TelegramUI/ContactSelectionControllerNode.swift @@ -90,9 +90,6 @@ final class ContactSelectionControllerNode: ASDisplayNode { if let searchDisplayController = self.searchDisplayController { searchDisplayController.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: transition) - if !searchDisplayController.isDeactivating { - insets.top += layout.statusBarHeight ?? 0.0 - } } self.contactListNode.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: layout.metrics, intrinsicInsets: insets, safeInsets: layout.safeInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, standardInputHeight: layout.standardInputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging), transition: transition) @@ -104,58 +101,44 @@ final class ContactSelectionControllerNode: ASDisplayNode { } } - func activateSearch() { - guard let (containerLayout, navigationBarHeight) = self.containerLayout, let navigationBar = self.navigationBar else { + func activateSearch(placeholderNode: SearchBarPlaceholderNode) { + guard let (containerLayout, navigationBarHeight) = self.containerLayout, let navigationBar = self.navigationBar, self.searchDisplayController == nil else { return } - var maybePlaceholderNode: SearchBarPlaceholderNode? - self.contactListNode.listNode.forEachItemNode { node in - if let node = node as? ChatListSearchItemNode { - maybePlaceholderNode = node.searchBarNode - } + var categories: ContactsSearchCategories = [.cloudContacts] + if self.displayDeviceContacts { + categories.insert(.deviceContacts) + } else { + categories.insert(.global) } - - if let _ = self.searchDisplayController { - return - } - - if let placeholderNode = maybePlaceholderNode { - var categories: ContactsSearchCategories = [.cloudContacts] - if self.displayDeviceContacts { - categories.insert(.deviceContacts) - } else { - categories.insert(.global) + self.searchDisplayController = SearchDisplayController(theme: self.presentationData.theme, strings: self.presentationData.strings, mode: .navigation, contentNode: ContactsSearchContainerNode(account: self.account, onlyWriteable: false, categories: categories, openPeer: { [weak self] peer in + self?.requestOpenPeerFromSearch?(peer) + }), cancel: { [weak self] in + if let requestDeactivateSearch = self?.requestDeactivateSearch { + requestDeactivateSearch() } - self.searchDisplayController = SearchDisplayController(theme: self.presentationData.theme, strings: self.presentationData.strings, contentNode: ContactsSearchContainerNode(account: self.account, onlyWriteable: false, categories: categories, openPeer: { [weak self] peer in - self?.requestOpenPeerFromSearch?(peer) - }), cancel: { [weak self] in - if let requestDeactivateSearch = self?.requestDeactivateSearch { - requestDeactivateSearch() + }) + + self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate) + self.searchDisplayController?.activate(insertSubnode: { [weak self, weak placeholderNode] subnode, isSearchBar in + if let strongSelf = self, let strongPlaceholderNode = placeholderNode { + if isSearchBar { + strongPlaceholderNode.supernode?.insertSubnode(subnode, aboveSubnode: strongPlaceholderNode) + } else { + strongSelf.insertSubnode(subnode, belowSubnode: navigationBar) } - }) - - self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate) - self.searchDisplayController?.activate(insertSubnode: { subnode in - self.insertSubnode(subnode, belowSubnode: self.dimNode) - }, placeholder: placeholderNode) - } + } + }, placeholder: placeholderNode) } func prepareDeactivateSearch() { self.searchDisplayController?.isDeactivating = true } - func deactivateSearch() { + func deactivateSearch(placeholderNode: SearchBarPlaceholderNode) { if let searchDisplayController = self.searchDisplayController { - var maybePlaceholderNode: SearchBarPlaceholderNode? - self.contactListNode.listNode.forEachItemNode { node in - if let node = node as? ChatListSearchItemNode { - maybePlaceholderNode = node.searchBarNode - } - } - - searchDisplayController.deactivate(placeholder: maybePlaceholderNode) + searchDisplayController.deactivate(placeholder: placeholderNode) self.searchDisplayController = nil } } diff --git a/TelegramUI/ContactsController.swift b/TelegramUI/ContactsController.swift index 2b7c86000f..c502dcf3d6 100644 --- a/TelegramUI/ContactsController.swift +++ b/TelegramUI/ContactsController.swift @@ -24,6 +24,8 @@ public class ContactsController: ViewController { private var authorizationDisposable: Disposable? private let sortOrderPromise = Promise() + private var searchContentNode: NavigationBarSearchContentNode? + public init(account: Account) { self.account = account @@ -47,11 +49,13 @@ public class ContactsController: ViewController { self.tabBarItem.selectedImage = icon self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil) - self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Sort", style: .plain, target: self, action: #selector(self.sortPressed)) self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: PresentationResourcesRootController.navigationAddIcon(self.presentationData.theme), style: .plain, target: self, action: #selector(self.addPressed)) self.scrollToTop = { [weak self] in if let strongSelf = self { + if let searchContentNode = strongSelf.searchContentNode { + searchContentNode.updateExpansionProgress(1.0, animated: true) + } strongSelf.contactsNode.contactListNode.scrollToTop() } } @@ -102,6 +106,11 @@ public class ContactsController: ViewController { return settings?.sortOrder ?? .presence }) } + + self.searchContentNode = NavigationBarSearchContentNode(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Common_Search, activate: { [weak self] in + self?.activateSearch() + }) + self.navigationBar?.setContentNode(self.searchContentNode, animated: false) } required public init(coder aDecoder: NSCoder) { @@ -116,6 +125,7 @@ public class ContactsController: ViewController { private func updateThemeAndStrings() { self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBar.style.style self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData)) + self.searchContentNode?.updateThemeAndPlaceholder(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Common_Search) self.title = self.presentationData.strings.Contacts_Title self.tabBarItem.title = self.presentationData.strings.Contacts_Title self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil) @@ -200,6 +210,10 @@ public class ContactsController: ViewController { } } + self.contactsNode.contactListNode.openSortMenu = { [weak self] in + self?.presentSortMenu() + } + self.displayNodeDidLoad() } @@ -226,7 +240,9 @@ public class ContactsController: ViewController { if let scrollToTop = self.scrollToTop { scrollToTop() } - self.contactsNode.activateSearch() + if let searchContentNode = self.searchContentNode { + self.contactsNode.activateSearch(placeholderNode: searchContentNode.placeholderNode) + } self.setDisplayNavigationBar(false, transition: .animated(duration: 0.5, curve: .spring)) } } @@ -234,35 +250,34 @@ public class ContactsController: ViewController { private func deactivateSearch() { if !self.displayNavigationBar { self.setDisplayNavigationBar(true, transition: .animated(duration: 0.5, curve: .spring)) - self.contactsNode.deactivateSearch() + if let searchContentNode = self.searchContentNode { + self.contactsNode.deactivateSearch(placeholderNode: searchContentNode.placeholderNode) + } } } - func updateSortOrder(_ sortOrder: ContactsSortOrder) { - self.sortOrderPromise.set(.single(sortOrder)) - let _ = updateContactSettingsInteractively(postbox: self.account.postbox) { current -> ContactSynchronizationSettings in - var updated = current - updated.sortOrder = sortOrder - return updated - }.start() - } - - @objc func sortPressed() { - let actionSheet = ActionSheetController(presentationTheme: self.presentationData.theme) + private func presentSortMenu() { + let updateSortOrder: (ContactsSortOrder) -> Void = { [weak self] sortOrder in + if let strongSelf = self { + strongSelf.sortOrderPromise.set(.single(sortOrder)) + let _ = updateContactSettingsInteractively(postbox: strongSelf.account.postbox) { current -> ContactSynchronizationSettings in + var updated = current + updated.sortOrder = sortOrder + return updated + }.start() + } + } + let actionSheet = ActionSheetController(presentationTheme: self.presentationData.theme) var items: [ActionSheetItem] = [] items.append(ActionSheetTextItem(title: self.presentationData.strings.Contacts_SortBy)) - items.append(ActionSheetButtonItem(title: self.presentationData.strings.Contacts_SortByName, color: .accent, action: { [weak self, weak actionSheet] in + items.append(ActionSheetButtonItem(title: self.presentationData.strings.Contacts_SortByName, color: .accent, action: { [weak actionSheet] in actionSheet?.dismissAnimated() - if let strongSelf = self { - strongSelf.updateSortOrder(.natural) - } + updateSortOrder(.natural) })) - items.append(ActionSheetButtonItem(title: self.presentationData.strings.Contacts_SortByPresence, color: .accent, action: { [weak self, weak actionSheet] in + items.append(ActionSheetButtonItem(title: self.presentationData.strings.Contacts_SortByPresence, color: .accent, action: { [weak actionSheet] in actionSheet?.dismissAnimated() - if let strongSelf = self { - strongSelf.updateSortOrder(.presence) - } + updateSortOrder(.presence) })) actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ ActionSheetButtonItem(title: self.presentationData.strings.Common_Cancel, color: .accent, action: { [weak actionSheet] in diff --git a/TelegramUI/ContactsControllerNode.swift b/TelegramUI/ContactsControllerNode.swift index 4e732f16ce..25b57070ad 100644 --- a/TelegramUI/ContactsControllerNode.swift +++ b/TelegramUI/ContactsControllerNode.swift @@ -42,7 +42,7 @@ final class ContactsControllerNode: ASDisplayNode { } } - self.contactListNode = ContactListNode(account: account, presentation: presentation) + self.contactListNode = ContactListNode(account: account, presentation: presentation, displaySortOptions: true) super.init() @@ -109,9 +109,6 @@ final class ContactsControllerNode: ASDisplayNode { if let searchDisplayController = self.searchDisplayController { searchDisplayController.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: transition) - if !searchDisplayController.isDeactivating { - insets.top += layout.statusBarHeight ?? 0.0 - } } self.contactListNode.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: layout.metrics, intrinsicInsets: insets, safeInsets: layout.safeInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, standardInputHeight: layout.standardInputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging), transition: transition) @@ -119,51 +116,37 @@ final class ContactsControllerNode: ASDisplayNode { self.contactListNode.frame = CGRect(origin: CGPoint(), size: layout.size) } - func activateSearch() { - guard let (containerLayout, navigationBarHeight) = self.containerLayout, let navigationBar = self.navigationBar else { + func activateSearch(placeholderNode: SearchBarPlaceholderNode) { + guard let (containerLayout, navigationBarHeight) = self.containerLayout, let navigationBar = self.navigationBar, self.searchDisplayController == nil else { return } - var maybePlaceholderNode: SearchBarPlaceholderNode? - self.contactListNode.listNode.forEachItemNode { node in - if let node = node as? ChatListSearchItemNode { - maybePlaceholderNode = node.searchBarNode + self.searchDisplayController = SearchDisplayController(theme: self.presentationData.theme, strings: self.presentationData.strings, mode: .navigation, contentNode: ContactsSearchContainerNode(account: self.account, onlyWriteable: false, categories: [.cloudContacts, .global, .deviceContacts], openPeer: { [weak self] peer in + if let requestOpenPeerFromSearch = self?.requestOpenPeerFromSearch { + requestOpenPeerFromSearch(peer) } - } + }), cancel: { [weak self] in + if let requestDeactivateSearch = self?.requestDeactivateSearch { + requestDeactivateSearch() + } + }) - if let _ = self.searchDisplayController { - return - } - - if let placeholderNode = maybePlaceholderNode { - self.searchDisplayController = SearchDisplayController(theme: self.presentationData.theme, strings: self.presentationData.strings, contentNode: ContactsSearchContainerNode(account: self.account, onlyWriteable: false, categories: [.cloudContacts, .global, .deviceContacts], openPeer: { [weak self] peer in - if let requestOpenPeerFromSearch = self?.requestOpenPeerFromSearch { - requestOpenPeerFromSearch(peer) + self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate) + self.searchDisplayController?.activate(insertSubnode: { [weak self, weak placeholderNode] subnode, isSearchBar in + if let strongSelf = self, let strongPlaceholderNode = placeholderNode { + if isSearchBar { + strongPlaceholderNode.supernode?.insertSubnode(subnode, aboveSubnode: strongPlaceholderNode) + } else { + strongSelf.insertSubnode(subnode, belowSubnode: navigationBar) } - }), cancel: { [weak self] in - if let requestDeactivateSearch = self?.requestDeactivateSearch { - requestDeactivateSearch() - } - }) - - self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate) - self.searchDisplayController?.activate(insertSubnode: { subnode in - self.insertSubnode(subnode, belowSubnode: navigationBar) - }, placeholder: placeholderNode) - } + } + }, placeholder: placeholderNode) } - func deactivateSearch() { + func deactivateSearch(placeholderNode: SearchBarPlaceholderNode) { if let searchDisplayController = self.searchDisplayController { + searchDisplayController.deactivate(placeholder: placeholderNode) self.searchDisplayController = nil - var maybePlaceholderNode: SearchBarPlaceholderNode? - self.contactListNode.listNode.forEachItemNode { node in - if let node = node as? ChatListSearchItemNode { - maybePlaceholderNode = node.searchBarNode - } - } - - searchDisplayController.deactivate(placeholder: maybePlaceholderNode) } } } diff --git a/TelegramUI/CreateChannelController.swift b/TelegramUI/CreateChannelController.swift index 230fb95010..88285a2185 100644 --- a/TelegramUI/CreateChannelController.swift +++ b/TelegramUI/CreateChannelController.swift @@ -260,6 +260,10 @@ public func createChannelController(account: Account) -> ViewController { }, changeProfilePhoto: { endEditingImpl?() + let title = stateValue.with { state -> String in + return state.editingName.composedTitle + } + let _ = (account.postbox.transaction { transaction -> (Peer?, SearchBotsConfiguration) in return (transaction.getPeer(account.peerId), currentSearchBotsConfiguration(transaction: transaction)) } |> deliverOnMainQueue).start(next: { peer, searchBotsConfiguration in @@ -295,7 +299,7 @@ public func createChannelController(account: Account) -> ViewController { let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: stateValue.with({ $0.avatar }) != nil, hasViewButton: false, personalPhoto: false, saveEditedPhotos: false, saveCapturedMedia: false, signup: false)! let _ = currentAvatarMixin.swap(mixin) mixin.requestSearchController = { assetsController in - let controller = WebSearchController(account: account, peer: peer, configuration: searchBotsConfiguration, mode: .avatar(completion: { result in + let controller = WebSearchController(account: account, peer: peer, configuration: searchBotsConfiguration, mode: .avatar(initialQuery: title, completion: { result in assetsController?.dismiss() completedImpl(result) })) diff --git a/TelegramUI/CreateGroupController.swift b/TelegramUI/CreateGroupController.swift index 3609458cd6..4bda9bce35 100644 --- a/TelegramUI/CreateGroupController.swift +++ b/TelegramUI/CreateGroupController.swift @@ -279,6 +279,10 @@ public func createGroupController(account: Account, peerIds: [PeerId]) -> ViewCo }, changeProfilePhoto: { endEditingImpl?() + let title = stateValue.with { state -> String in + return state.editingName.composedTitle + } + let _ = (account.postbox.transaction { transaction -> (Peer?, SearchBotsConfiguration) in return (transaction.getPeer(account.peerId), currentSearchBotsConfiguration(transaction: transaction)) } |> deliverOnMainQueue).start(next: { peer, searchBotsConfiguration in @@ -314,7 +318,7 @@ public func createGroupController(account: Account, peerIds: [PeerId]) -> ViewCo let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: stateValue.with({ $0.avatar }) != nil, hasViewButton: false, personalPhoto: false, saveEditedPhotos: false, saveCapturedMedia: false, signup: false)! let _ = currentAvatarMixin.swap(mixin) mixin.requestSearchController = { assetsController in - let controller = WebSearchController(account: account, peer: peer, configuration: searchBotsConfiguration, mode: .avatar(completion: { result in + let controller = WebSearchController(account: account, peer: peer, configuration: searchBotsConfiguration, mode: .avatar(initialQuery: title, completion: { result in assetsController?.dismiss() completedImpl(result) })) diff --git a/TelegramUI/EditSettingsController.swift b/TelegramUI/EditSettingsController.swift index a620c406af..053b50807f 100644 --- a/TelegramUI/EditSettingsController.swift +++ b/TelegramUI/EditSettingsController.swift @@ -468,7 +468,7 @@ func editSettingsController(account: Account, currentName: ItemListAvatarAndName let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: hasPhotos, hasViewButton: hasPhotos, personalPhoto: true, saveEditedPhotos: false, saveCapturedMedia: false, signup: false)! let _ = currentAvatarMixin.swap(mixin) mixin.requestSearchController = { assetsController in - let controller = WebSearchController(account: account, peer: peer, configuration: searchBotsConfiguration, mode: .avatar(completion: { result in + let controller = WebSearchController(account: account, peer: peer, configuration: searchBotsConfiguration, mode: .avatar(initialQuery: nil, completion: { result in assetsController?.dismiss() completedImpl(result) })) diff --git a/TelegramUI/FixSearchableListNodeScrolling.swift b/TelegramUI/FixSearchableListNodeScrolling.swift index ddfca1b98c..43acd9bcd9 100644 --- a/TelegramUI/FixSearchableListNodeScrolling.swift +++ b/TelegramUI/FixSearchableListNodeScrolling.swift @@ -27,3 +27,22 @@ func fixSearchableListNodeScrolling(_ listNode: ListView) { } } } + +func fixNavigationSearchableListNodeScrolling(_ listNode: ListView, searchNode: NavigationBarSearchContentNode) -> Bool { + if searchNode.expansionProgress > 0.0 && searchNode.expansionProgress < 1.0 { + let scrollToItem: ListViewScrollToItem + let targetProgress: CGFloat + if searchNode.expansionProgress < 0.6 { + scrollToItem = ListViewScrollToItem(index: 0, position: .top(-navigationBarSearchContentHeight), animated: true, curve: .Default(duration: 0.25), directionHint: .Up) + targetProgress = 0.0 + } else { + scrollToItem = ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: .Default(duration: 0.25), directionHint: .Up) + targetProgress = 1.0 + } + searchNode.updateExpansionProgress(targetProgress, animated: true) + + listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: ListViewDeleteAndInsertOptions(), scrollToItem: scrollToItem, updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in }) + return true + } + return false +} diff --git a/TelegramUI/GridMessageItem.swift b/TelegramUI/GridMessageItem.swift index ec86b2a1b7..666ef90e34 100644 --- a/TelegramUI/GridMessageItem.swift +++ b/TelegramUI/GridMessageItem.swift @@ -18,8 +18,8 @@ private final class GridMessageVideoAccessoryNode : ASDisplayNode { self.textNode.isUserInteractionEnabled = false self.textNode.textAlignment = .left self.textNode.lineSpacing = 0.1 - addSubnode(self.textNode) - backgroundColor = UIColor(white: 0.0, alpha: 0.6) + self.addSubnode(self.textNode) + self.backgroundColor = UIColor(white: 0.0, alpha: 0.6) } var contentSize: CGSize { @@ -28,17 +28,15 @@ private final class GridMessageVideoAccessoryNode : ASDisplayNode { private var textSize: CGSize = CGSize() func setup(_ duration: String) { - textNode.attributedText = NSAttributedString(string: duration, font: videoAccessoryFont, textColor: .white, paragraphAlignment: nil) - textSize = self.textNode.updateLayout(CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)) + self.textNode.attributedText = NSAttributedString(string: duration, font: videoAccessoryFont, textColor: .white, paragraphAlignment: nil) + self.textSize = self.textNode.updateLayout(CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)) } override func layout() { if let _ = self.textNode.attributedText { - self.textNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((frame.width - textSize.width) / 2.0), y: floorToScreenPixels((frame.height - textSize.height) / 2.0) + 0.5), size: textSize) + self.textNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((self.frame.width - self.textSize.width) / 2.0), y: floorToScreenPixels((self.frame.height - self.textSize.height) / 2.0) + 0.5), size: self.textSize) } } - - } private func mediaForMessage(_ message: Message) -> Media? { @@ -195,6 +193,8 @@ final class GridMessageItemNode: GridItemNode { override init() { self.imageNode = TransformImageNode() self.statusNode = RadialStatusNode(backgroundNodeColor: UIColor(white: 0.0, alpha: 0.6)) + let progressDiameter: CGFloat = 40.0 + self.statusNode.frame = CGRect(x: 0.0, y: 0.0, width: progressDiameter, height: progressDiameter) self.statusNode.isUserInteractionEnabled = false super.init() @@ -249,11 +249,8 @@ final class GridMessageItemNode: GridItemNode { strongSelf.resourceStatus = status let statusState: RadialStatusNodeState switch status { - case let .Fetching(isActive, progress): - var adjustedProgress = progress - if isActive { - adjustedProgress = max(adjustedProgress, 0.027) - } + case let .Fetching(_, progress): + let adjustedProgress = max(progress, 0.027) statusState = .progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true) case .Local: statusState = .play(.white) diff --git a/TelegramUI/GroupInfoController.swift b/TelegramUI/GroupInfoController.swift index 4ff8b4cf0b..7bfdd237ca 100644 --- a/TelegramUI/GroupInfoController.swift +++ b/TelegramUI/GroupInfoController.swift @@ -1187,7 +1187,9 @@ public func groupInfoController(account: Account, peerId: PeerId) -> ViewControl var aboutLinkActionImpl: ((TextLinkItemActionType, TextLinkItem) -> Void)? let arguments = GroupInfoArguments(account: account, peerId: peerId, avatarAndNameInfoContext: avatarAndNameInfoContext, tapAvatarAction: { - let _ = (account.postbox.loadedPeerWithId(peerId) |> take(1) |> deliverOnMainQueue).start(next: { peer in + let _ = (account.postbox.loadedPeerWithId(peerId) + |> take(1) + |> deliverOnMainQueue).start(next: { peer in if peer.profileImageRepresentations.isEmpty { return } @@ -1252,7 +1254,7 @@ public func groupInfoController(account: Account, peerId: PeerId) -> ViewControl let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: hasPhotos, hasViewButton: false, personalPhoto: false, saveEditedPhotos: false, saveCapturedMedia: false, signup: false)! let _ = currentAvatarMixin.swap(mixin) mixin.requestSearchController = { assetsController in - let controller = WebSearchController(account: account, peer: peer, configuration: searchBotsConfiguration, mode: .avatar(completion: { result in + let controller = WebSearchController(account: account, peer: peer, configuration: searchBotsConfiguration, mode: .avatar(initialQuery: peer?.displayTitle, completion: { result in assetsController?.dismiss() completedImpl(result) })) @@ -1301,7 +1303,6 @@ public func groupInfoController(account: Account, peerId: PeerId) -> ViewControl }, changeNotificationMuteSettings: { let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 } actionsDisposable.add((account.postbox.preferencesView(keys: [PreferencesKeys.globalNotifications]) |> take(1) |> deliverOnMainQueue).start(next: { view in - let viewSettings: GlobalNotificationSettingsSet if let settings = view.values[PreferencesKeys.globalNotifications] as? GlobalNotificationSettings { viewSettings = settings.effective diff --git a/TelegramUI/InstantPageImageNode.swift b/TelegramUI/InstantPageImageNode.swift index 628dbcce69..c89841416b 100644 --- a/TelegramUI/InstantPageImageNode.swift +++ b/TelegramUI/InstantPageImageNode.swift @@ -140,10 +140,7 @@ final class InstantPageImageNode: ASDisplayNode, InstantPageNode { if let fetchStatus = self.fetchStatus { switch fetchStatus { case let .Fetching(isActive, progress): - var adjustedProgress = progress - if isActive { - adjustedProgress = max(adjustedProgress, 0.027) - } + let adjustedProgress = max(progress, 0.027) state = .progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: false) default: break diff --git a/TelegramUI/InviteContactsController.swift b/TelegramUI/InviteContactsController.swift index ae689151b3..dd11c593b0 100644 --- a/TelegramUI/InviteContactsController.swift +++ b/TelegramUI/InviteContactsController.swift @@ -23,6 +23,8 @@ public class InviteContactsController: ViewController, MFMessageComposeViewContr private var composer: MFMessageComposeViewController? + private var searchContentNode: NavigationBarSearchContentNode? + public init(account: Account) { self.account = account @@ -56,6 +58,11 @@ public class InviteContactsController: ViewController, MFMessageComposeViewContr } } }) + + self.searchContentNode = NavigationBarSearchContentNode(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Common_Search, activate: { [weak self] in + self?.activateSearch() + }) + self.navigationBar?.setContentNode(self.searchContentNode, animated: false) } required public init(coder aDecoder: NSCoder) { @@ -69,6 +76,7 @@ public class InviteContactsController: ViewController, MFMessageComposeViewContr private func updateThemeAndStrings() { self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBar.style.style self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData)) + self.searchContentNode?.updateThemeAndPlaceholder(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Common_Search) self.title = self.presentationData.strings.Contacts_InviteFriends self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil) } @@ -150,7 +158,9 @@ public class InviteContactsController: ViewController, MFMessageComposeViewContr if let scrollToTop = self.scrollToTop { scrollToTop() } - self.contactsNode.activateSearch() + if let searchContentNode = self.searchContentNode { + self.contactsNode.activateSearch(placeholderNode: searchContentNode.placeholderNode) + } self.setDisplayNavigationBar(false, transition: .animated(duration: 0.5, curve: .spring)) } } @@ -158,7 +168,9 @@ public class InviteContactsController: ViewController, MFMessageComposeViewContr private func deactivateSearch() { if !self.displayNavigationBar { self.setDisplayNavigationBar(true, transition: .animated(duration: 0.5, curve: .spring)) - self.contactsNode.deactivateSearch() + if let searchContentNode = self.searchContentNode { + self.contactsNode.deactivateSearch(placeholderNode: searchContentNode.placeholderNode) + } } } diff --git a/TelegramUI/InviteContactsControllerNode.swift b/TelegramUI/InviteContactsControllerNode.swift index d1b02c48d1..87396f0581 100644 --- a/TelegramUI/InviteContactsControllerNode.swift +++ b/TelegramUI/InviteContactsControllerNode.swift @@ -222,9 +222,7 @@ struct InviteContactsGroupSelectionState: Equatable { private func inviteContactsEntries(accountPeer: Peer?, sortedContacts: [(DeviceContactStableId, DeviceContactBasicData, Int32)], selectionState: InviteContactsGroupSelectionState, theme: PresentationTheme, strings: PresentationStrings, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, interaction: InviteContactsInteraction) -> [InviteContactsEntry] { var entries: [InviteContactsEntry] = [] - - entries.append(.search(theme, strings)) - + entries.append(.option(0, ContactListAdditionalOption(title: strings.Contacts_ShareTelegram, icon: .generic(UIImage(bundleImageName: "Contact List/InviteActionIcon")!), action: { interaction.shareTelegram() }), theme, strings)) @@ -505,9 +503,6 @@ final class InviteContactsControllerNode: ASDisplayNode { if let searchDisplayController = self.searchDisplayController { searchDisplayController.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: transition) - if !searchDisplayController.isDeactivating { - insets.top += layout.statusBarHeight ?? 0.0 - } } insets.left += layout.safeInsets.left @@ -555,48 +550,34 @@ final class InviteContactsControllerNode: ASDisplayNode { } } - func activateSearch() { - guard let (containerLayout, navigationBarHeight) = self.validLayout, let navigationBar = self.navigationBar else { + func activateSearch(placeholderNode: SearchBarPlaceholderNode) { + guard let (containerLayout, navigationBarHeight) = self.validLayout, let navigationBar = self.navigationBar, self.searchDisplayController == nil else { return } - var maybePlaceholderNode: SearchBarPlaceholderNode? - self.listNode.forEachItemNode { node in - if let node = node as? ChatListSearchItemNode { - maybePlaceholderNode = node.searchBarNode + self.searchDisplayController = SearchDisplayController(theme: self.presentationData.theme, strings: self.presentationData.strings, mode: .navigation, contentNode: ContactsSearchContainerNode(account: self.account, onlyWriteable: false, categories: [.deviceContacts], openPeer: { [weak self] peerId in + }), cancel: { [weak self] in + if let requestDeactivateSearch = self?.requestDeactivateSearch { + requestDeactivateSearch() } - } + }) - if let _ = self.searchDisplayController { - return - } - - if let placeholderNode = maybePlaceholderNode { - self.searchDisplayController = SearchDisplayController(theme: self.presentationData.theme, strings: self.presentationData.strings, contentNode: ContactsSearchContainerNode(account: self.account, onlyWriteable: false, categories: [.deviceContacts], openPeer: { [weak self] peerId in - }), cancel: { [weak self] in - if let requestDeactivateSearch = self?.requestDeactivateSearch { - requestDeactivateSearch() + self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate) + self.searchDisplayController?.activate(insertSubnode: { [weak self, weak placeholderNode] subnode, isSearchBar in + if let strongSelf = self, let strongPlaceholderNode = placeholderNode { + if isSearchBar { + strongPlaceholderNode.supernode?.insertSubnode(subnode, aboveSubnode: strongPlaceholderNode) + } else { + strongSelf.insertSubnode(subnode, belowSubnode: navigationBar) } - }) - - self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate) - self.searchDisplayController?.activate(insertSubnode: { subnode in - self.insertSubnode(subnode, belowSubnode: navigationBar) - }, placeholder: placeholderNode) - } + } + }, placeholder: placeholderNode) } - func deactivateSearch() { + func deactivateSearch(placeholderNode: SearchBarPlaceholderNode) { if let searchDisplayController = self.searchDisplayController { self.searchDisplayController = nil - var maybePlaceholderNode: SearchBarPlaceholderNode? - self.listNode.forEachItemNode { node in - if let node = node as? ChatListSearchItemNode { - maybePlaceholderNode = node.searchBarNode - } - } - - searchDisplayController.deactivate(placeholder: maybePlaceholderNode) + searchDisplayController.deactivate(placeholder: placeholderNode) } } diff --git a/TelegramUI/ItemListPeerActionItem.swift b/TelegramUI/ItemListPeerActionItem.swift index 9d4c32f9e4..0516d054cc 100644 --- a/TelegramUI/ItemListPeerActionItem.swift +++ b/TelegramUI/ItemListPeerActionItem.swift @@ -7,14 +7,16 @@ class ItemListPeerActionItem: ListViewItem, ItemListItem { let theme: PresentationTheme let icon: UIImage? let title: String + let alwaysPlain: Bool let editing: Bool let sectionId: ItemListSectionId let action: () -> Void - init(theme: PresentationTheme, icon: UIImage?, title: String, sectionId: ItemListSectionId, editing: Bool, action: @escaping () -> Void) { + init(theme: PresentationTheme, icon: UIImage?, title: String, alwaysPlain: Bool = false, sectionId: ItemListSectionId, editing: Bool, action: @escaping () -> Void) { self.theme = theme self.icon = icon self.title = title + self.alwaysPlain = alwaysPlain self.editing = editing self.sectionId = sectionId self.action = action @@ -23,7 +25,11 @@ class ItemListPeerActionItem: ListViewItem, ItemListItem { func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal?, (ListViewItemApply) -> Void)) -> Void) { async { let node = ItemListPeerActionItemNode() - let (layout, apply) = node.asyncLayout()(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem)) + var neighbors = itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem) + if self.alwaysPlain { + neighbors.top = .sameSection(alwaysPlain: false) + } + let (layout, apply) = node.asyncLayout()(self, params, neighbors) node.contentSize = layout.contentSize node.insets = layout.insets @@ -47,7 +53,11 @@ class ItemListPeerActionItem: ListViewItem, ItemListItem { } async { - let (layout, apply) = makeLayout(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem)) + var neighbors = itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem) + if self.alwaysPlain { + neighbors.top = .sameSection(alwaysPlain: false) + } + let (layout, apply) = makeLayout(self, params, neighbors) Queue.mainQueue().async { completion(layout, { _ in apply(animated) diff --git a/TelegramUI/ListMessageFileItemNode.swift b/TelegramUI/ListMessageFileItemNode.swift index c03ef3e4ef..d920e3533b 100644 --- a/TelegramUI/ListMessageFileItemNode.swift +++ b/TelegramUI/ListMessageFileItemNode.swift @@ -647,11 +647,8 @@ final class ListMessageFileItemNode: ListMessageNode { self.updateProgressFrame(size: contentSize, leftInset: layoutParams.leftInset, rightInset: layoutParams.rightInset, transition: .immediate) } else { switch fetchStatus { - case let .Fetching(isActive, progress): - var adjustedProgress = progress - if isActive { - adjustedProgress = max(adjustedProgress, 0.027) - } + case let .Fetching(_, progress): + let adjustedProgress = max(progress, 0.027) statusState = .cloudProgress(color: item.theme.list.itemAccentColor, strokeBackgroundColor: item.theme.list.itemAccentColor.withAlphaComponent(0.5), lineWidth: 2.0, value: CGFloat(adjustedProgress)) case .Local: break @@ -666,11 +663,8 @@ final class ListMessageFileItemNode: ListMessageNode { switch status { case let .fetchStatus(fetchStatus): switch fetchStatus { - case let .Fetching(isActive, progress): - var adjustedProgress = progress - if isActive { - adjustedProgress = max(adjustedProgress, 0.027) - } + case let .Fetching(_, progress): + let adjustedProgress = max(progress, 0.027) self.progressNode.state = .Fetching(progress: adjustedProgress) case .Local: if isAudio { diff --git a/TelegramUI/LocalizationListController.swift b/TelegramUI/LocalizationListController.swift index fbac46f09e..2a67959015 100644 --- a/TelegramUI/LocalizationListController.swift +++ b/TelegramUI/LocalizationListController.swift @@ -23,6 +23,8 @@ public class LocalizationListController: ViewController { private var editItem: UIBarButtonItem! private var doneItem: UIBarButtonItem! + private var searchContentNode: NavigationBarSearchContentNode? + public init(account: Account) { self.account = account @@ -56,6 +58,11 @@ public class LocalizationListController: ViewController { } } }) + + self.searchContentNode = NavigationBarSearchContentNode(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Common_Search, activate: { [weak self] in + self?.activateSearch() + }) + self.navigationBar?.setContentNode(self.searchContentNode, animated: false) } required public init(coder aDecoder: NSCoder) { @@ -69,6 +76,7 @@ public class LocalizationListController: ViewController { private func updateThemeAndStrings() { self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBar.style.style self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData)) + self.searchContentNode?.updateThemeAndPlaceholder(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Common_Search) self.title = self.presentationData.strings.Settings_AppLanguage self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil) self.controllerNode.updatePresentationData(self.presentationData) @@ -126,7 +134,9 @@ public class LocalizationListController: ViewController { if let scrollToTop = self.scrollToTop { scrollToTop() } - self.controllerNode.activateSearch() + if let searchContentNode = self.searchContentNode { + self.controllerNode.activateSearch(placeholderNode: searchContentNode.placeholderNode) + } self.setDisplayNavigationBar(false, transition: .animated(duration: 0.5, curve: .spring)) } } @@ -134,7 +144,9 @@ public class LocalizationListController: ViewController { private func deactivateSearch() { if !self.displayNavigationBar { self.setDisplayNavigationBar(true, transition: .animated(duration: 0.5, curve: .spring)) - self.controllerNode.deactivateSearch() + if let searchContentNode = self.searchContentNode { + self.controllerNode.deactivateSearch(placeholderNode: searchContentNode.placeholderNode) + } } } } diff --git a/TelegramUI/LocalizationListControllerNode.swift b/TelegramUI/LocalizationListControllerNode.swift index fa7be02839..446807434d 100644 --- a/TelegramUI/LocalizationListControllerNode.swift +++ b/TelegramUI/LocalizationListControllerNode.swift @@ -380,7 +380,7 @@ final class LocalizationListControllerNode: ViewControllerTracingNode { var existingIds = Set() if let localizationListState = (view.views[preferencesKey] as? PreferencesView)?.values[PreferencesKeys.localizationListState] as? LocalizationListState, !localizationListState.availableOfficialLocalizations.isEmpty { strongSelf.currentListState = localizationListState - entries.append(.search(entries.count)) + //entries.append(.search(entries.count)) let availableSavedLocalizations = localizationListState.availableSavedLocalizations.filter({ info in !localizationListState.availableOfficialLocalizations.contains(where: { $0.languageCode == info.languageCode }) }) if availableSavedLocalizations.isEmpty { updateCanStartEditing(nil) @@ -435,9 +435,6 @@ final class LocalizationListControllerNode: ViewControllerTracingNode { listInsets.right += layout.safeInsets.right if let searchDisplayController = self.searchDisplayController { searchDisplayController.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: transition) - if !searchDisplayController.isDeactivating { - listInsets.top += layout.statusBarHeight ?? 0.0 - } } self.listNode.bounds = CGRect(x: 0.0, y: 0.0, width: layout.size.width, height: layout.size.height) @@ -553,44 +550,30 @@ final class LocalizationListControllerNode: ViewControllerTracingNode { self.isEditingValue = !self.isEditingValue } - func activateSearch() { - guard let (containerLayout, navigationBarHeight) = self.containerLayout else { + func activateSearch(placeholderNode: SearchBarPlaceholderNode) { + guard let (containerLayout, navigationBarHeight) = self.containerLayout, self.searchDisplayController == nil else { return } - var maybePlaceholderNode: SearchBarPlaceholderNode? - self.listNode.forEachItemNode { node in - if let node = node as? ChatListSearchItemNode { - maybePlaceholderNode = node.searchBarNode - } - } + self.searchDisplayController = SearchDisplayController(theme: self.presentationData.theme, strings: self.presentationData.strings, mode: .navigation, contentNode: LocalizationListSearchContainerNode(account: self.account, listState: self.currentListState ?? LocalizationListState.defaultSettings, selectLocalization: { [weak self] info in self?.selectLocalization(info) }, applyingCode: self.applyingCode.get()), cancel: { [weak self] in + self?.requestDeactivateSearch() + }) - if let _ = self.searchDisplayController { - return - } - - if let placeholderNode = maybePlaceholderNode { - self.searchDisplayController = SearchDisplayController(theme: self.presentationData.theme, strings: self.presentationData.strings, contentNode: LocalizationListSearchContainerNode(account: self.account, listState: self.currentListState ?? LocalizationListState.defaultSettings, selectLocalization: { [weak self] info in self?.selectLocalization(info) }, applyingCode: self.applyingCode.get()), cancel: { [weak self] in - self?.requestDeactivateSearch() - }) - - self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate) - self.searchDisplayController?.activate(insertSubnode: { subnode in - self.insertSubnode(subnode, belowSubnode: self.navigationBar) - }, placeholder: placeholderNode) - } - } - - func deactivateSearch() { - if let searchDisplayController = self.searchDisplayController { - var maybePlaceholderNode: SearchBarPlaceholderNode? - self.listNode.forEachItemNode { node in - if let node = node as? ChatListSearchItemNode { - maybePlaceholderNode = node.searchBarNode + self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate) + self.searchDisplayController?.activate(insertSubnode: { [weak self, weak placeholderNode] subnode, isSearchBar in + if let strongSelf = self, let strongPlaceholderNode = placeholderNode { + if isSearchBar { + strongPlaceholderNode.supernode?.insertSubnode(subnode, aboveSubnode: strongPlaceholderNode) + } else { + strongSelf.insertSubnode(subnode, belowSubnode: navigationBar) } } - - searchDisplayController.deactivate(placeholder: maybePlaceholderNode) + }, placeholder: placeholderNode) + } + + func deactivateSearch(placeholderNode: SearchBarPlaceholderNode) { + if let searchDisplayController = self.searchDisplayController { + searchDisplayController.deactivate(placeholder: placeholderNode) self.searchDisplayController = nil } } diff --git a/TelegramUI/LocalizationListItem.swift b/TelegramUI/LocalizationListItem.swift index 2a3e5c7841..0640bf8a66 100644 --- a/TelegramUI/LocalizationListItem.swift +++ b/TelegramUI/LocalizationListItem.swift @@ -45,7 +45,7 @@ class LocalizationListItem: ListViewItem, ItemListItem { async { let node = LocalizationListItemNode() var neighbors = itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem) - if previousItem is ChatListSearchItem || self.alwaysPlain { + if previousItem == nil || previousItem is ChatListSearchItem || self.alwaysPlain { neighbors.top = .sameSection(alwaysPlain: false) } let (layout, apply) = node.asyncLayout()(self, params, neighbors) @@ -68,7 +68,7 @@ class LocalizationListItem: ListViewItem, ItemListItem { async { var neighbors = itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem) - if previousItem is ChatListSearchItem || self.alwaysPlain { + if previousItem == nil || previousItem is ChatListSearchItem || self.alwaysPlain { neighbors.top = .sameSection(alwaysPlain: false) } let (layout, apply) = makeLayout(self, params, neighbors) diff --git a/TelegramUI/NavigationBarSearchContentNode.swift b/TelegramUI/NavigationBarSearchContentNode.swift new file mode 100644 index 0000000000..c0cc38c225 --- /dev/null +++ b/TelegramUI/NavigationBarSearchContentNode.swift @@ -0,0 +1,109 @@ +import Foundation +import AsyncDisplayKit +import Display + +private let searchBarFont = Font.regular(17.0) +let navigationBarSearchContentHeight: CGFloat = 54.0 + +class NavigationBarSearchContentNode: NavigationBarContentNode { + var theme: PresentationTheme? + var placeholder: String + + let placeholderNode: SearchBarPlaceholderNode + private var disabledOverlay: ASDisplayNode? + + private(set) var expansionProgress: CGFloat = 1.0 + + init(theme: PresentationTheme, placeholder: String, activate: @escaping () -> Void) { + self.theme = theme + self.placeholder = placeholder + self.placeholderNode = SearchBarPlaceholderNode(fieldStyle: .modern) + + super.init() + + self.addSubnode(self.placeholderNode) + self.placeholderNode.activate = activate + } + + func updateThemeAndPlaceholder(theme: PresentationTheme, placeholder: String) { + self.theme = theme + self.placeholder = placeholder + if let disabledOverlay = self.disabledOverlay { + disabledOverlay.backgroundColor = theme.rootController.navigationBar.backgroundColor.withAlphaComponent(0.5) + } + self.setNeedsLayout() + } + + func updateExpansionProgress(_ progress: CGFloat, animated: Bool = false) { + let newProgress = max(0.0, min(1.0, progress)) + if newProgress != self.expansionProgress { + self.expansionProgress = newProgress + + let transition: ContainedViewLayoutTransition = animated ? .animated(duration: 0.25, curve: .easeInOut) : .immediate + if animated { + self.updatePlaceholder(self.expansionProgress, transition: transition) + } + self.requestContainerLayout(transition) + } + } + + func setIsEnabled(_ enabled: Bool, animated: Bool = false) { + if !enabled { + if self.disabledOverlay == nil { + let disabledOverlay = ASDisplayNode() + self.addSubnode(disabledOverlay) + self.disabledOverlay = disabledOverlay + if animated { + disabledOverlay.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25) + } + } + if let disabledOverlay = self.disabledOverlay { + disabledOverlay.backgroundColor = self.theme?.rootController.navigationBar.backgroundColor.withAlphaComponent(0.4) + disabledOverlay.frame = placeholderNode.frame + } + } else if let disabledOverlay = self.disabledOverlay { + self.disabledOverlay = nil + if animated { + disabledOverlay.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak disabledOverlay] _ in + disabledOverlay?.removeFromSupernode() + }) + } else { + disabledOverlay.removeFromSupernode() + } + } + } + + private func updatePlaceholder(_ progress: CGFloat, transition: ContainedViewLayoutTransition) { + let padding: CGFloat = 10.0 + let baseWidth = self.bounds.width - padding * 2.0 + + let fieldHeight: CGFloat = 36.0 + let fraction = fieldHeight / self.nominalHeight + let visibleProgress = max(0.0, self.expansionProgress - 1.0 + fraction) / fraction + + let makeLayout = self.placeholderNode.asyncLayout() + let applyLayout = makeLayout(NSAttributedString(string: self.placeholder, font: searchBarFont, textColor: self.theme?.rootController.activeNavigationSearchBar.inputPlaceholderTextColor ?? UIColor(rgb: 0x8e8e93)), CGSize(width: baseWidth, height: fieldHeight), visibleProgress, self.theme?.rootController.activeNavigationSearchBar.inputPlaceholderTextColor ?? UIColor(rgb: 0x8e8e93), self.theme?.rootController.activeNavigationSearchBar.inputFillColor ?? .clear, self.theme?.rootController.navigationBar.backgroundColor ?? .clear, transition) + applyLayout() + + let searchBarFrame = CGRect(origin: CGPoint(x: padding, y: 8.0), size: CGSize(width: baseWidth, height: fieldHeight)) + transition.updateFrame(node: self.placeholderNode, frame: searchBarFrame) + } + + override func layout() { + super.layout() + + self.updatePlaceholder(self.expansionProgress, transition: .immediate) + } + + override var height: CGFloat { + return self.nominalHeight * self.expansionProgress + } + + override var nominalHeight: CGFloat { + return navigationBarSearchContentHeight + } + + override var mode: NavigationBarContentMode { + return .expansion + } +} diff --git a/TelegramUI/NotificationExceptionControllerNode.swift b/TelegramUI/NotificationExceptionControllerNode.swift index 5c9cae2a7e..b26ba35490 100644 --- a/TelegramUI/NotificationExceptionControllerNode.swift +++ b/TelegramUI/NotificationExceptionControllerNode.swift @@ -147,7 +147,6 @@ public enum NotificationExceptionMode : Equatable { } func withUpdatedPeerMuteInterval(_ peer: Peer, _ muteInterval: Int32?) -> NotificationExceptionMode { - let apply:([PeerId : NotificationExceptionWrapper], PeerId, PeerMuteState) -> [PeerId : NotificationExceptionWrapper] = { values, peerId, muteState in var values = values if let value = values[peerId] { @@ -219,9 +218,9 @@ private func notificationsExceptionEntries(presentationData: PresentationData, s var entries: [NotificationExceptionEntry] = [] if !state.isSearchMode { - if !state.mode.settings.isEmpty { - entries.append(.search(presentationData.theme, presentationData.strings)) - } + //if !state.mode.settings.isEmpty { + // entries.append(.search(presentationData.theme, presentationData.strings)) + //} entries.append(.addException(presentationData.theme, presentationData.strings, state.editing)) } @@ -388,7 +387,7 @@ private enum NotificationExceptionEntry : ItemListNodeEntry { arguments.activateSearch() }) case let .addException(theme, strings, editing): - return ItemListPeerActionItem(theme: theme, icon: PresentationResourcesItemList.addExceptionIcon(theme), title: strings.Notification_Exceptions_AddException, sectionId: self.section, editing: editing, action: { + return ItemListPeerActionItem(theme: theme, icon: PresentationResourcesItemList.addExceptionIcon(theme), title: strings.Notification_Exceptions_AddException, alwaysPlain: true, sectionId: self.section, editing: editing, action: { arguments.selectPeer() }) case let .peer(_, peer, theme, strings, dateTimeFormat, nameDisplayOrder, value, _, revealed, editing): @@ -719,11 +718,6 @@ final class NotificationExceptionsControllerNode: ViewControllerTracingNode { self?.enqueueTransition(transition) }) - - - - //listdi - } deinit { @@ -750,9 +744,6 @@ final class NotificationExceptionsControllerNode: ViewControllerTracingNode { listInsets.right += layout.safeInsets.right if let searchDisplayController = self.searchDisplayController { searchDisplayController.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: transition) - if !searchDisplayController.isDeactivating { - listInsets.top += layout.statusBarHeight ?? 0.0 - } } self.listNode.bounds = CGRect(x: 0.0, y: 0.0, width: layout.size.width, height: layout.size.height) @@ -828,44 +819,30 @@ final class NotificationExceptionsControllerNode: ViewControllerTracingNode { statePromise.set(stateValue.modify({$0.withUpdatedEditing(!$0.editing).withUpdatedRevealedPeerId(nil)})) } - func activateSearch() { - guard let (containerLayout, navigationBarHeight) = self.containerLayout else { + func activateSearch(placeholderNode: SearchBarPlaceholderNode) { + guard let (containerLayout, navigationBarHeight) = self.containerLayout, self.searchDisplayController == nil else { return } - var maybePlaceholderNode: SearchBarPlaceholderNode? - self.listNode.forEachItemNode { node in - if let node = node as? NotificationSearchItemNode { - maybePlaceholderNode = node.searchBarNode - } - } + self.searchDisplayController = SearchDisplayController(theme: self.presentationData.theme, strings: self.presentationData.strings, mode: .navigation, contentNode: NotificationExceptionsSearchContainerNode(account: self.account, mode: self.stateValue.modify {$0}.mode, arguments: self.arguments!), cancel: { [weak self] in + self?.requestDeactivateSearch() + }) - if let _ = self.searchDisplayController { - return - } - - if let placeholderNode = maybePlaceholderNode { - self.searchDisplayController = SearchDisplayController(theme: self.presentationData.theme, strings: self.presentationData.strings, contentNode: NotificationExceptionsSearchContainerNode(account: self.account, mode: self.stateValue.modify {$0}.mode, arguments: self.arguments!), cancel: { [weak self] in - self?.requestDeactivateSearch() - }) - - self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate) - self.searchDisplayController?.activate(insertSubnode: { subnode in - self.insertSubnode(subnode, belowSubnode: self.navigationBar) - }, placeholder: placeholderNode) - } - } - - func deactivateSearch() { - if let searchDisplayController = self.searchDisplayController { - var maybePlaceholderNode: SearchBarPlaceholderNode? - self.listNode.forEachItemNode { node in - if let node = node as? NotificationSearchItemNode { - maybePlaceholderNode = node.searchBarNode + self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate) + self.searchDisplayController?.activate(insertSubnode: { [weak self, weak placeholderNode] subnode, isSearchBar in + if let strongSelf = self, let strongPlaceholderNode = placeholderNode { + if isSearchBar { + strongPlaceholderNode.supernode?.insertSubnode(subnode, aboveSubnode: strongPlaceholderNode) + } else { + strongSelf.insertSubnode(subnode, belowSubnode: navigationBar) } } - - searchDisplayController.deactivate(placeholder: maybePlaceholderNode) + }, placeholder: placeholderNode) + } + + func deactivateSearch(placeholderNode: SearchBarPlaceholderNode) { + if let searchDisplayController = self.searchDisplayController { + searchDisplayController.deactivate(placeholder: placeholderNode) self.searchDisplayController = nil } } diff --git a/TelegramUI/NotificationExceptions.swift b/TelegramUI/NotificationExceptions.swift index 15daf6c967..4f9e95f6d4 100644 --- a/TelegramUI/NotificationExceptions.swift +++ b/TelegramUI/NotificationExceptions.swift @@ -24,6 +24,9 @@ public class NotificationExceptionsController: ViewController { private let mode: NotificationExceptionMode private let updatedMode: (NotificationExceptionMode) -> Void + + private var searchContentNode: NavigationBarSearchContentNode? + public init(account: Account, mode: NotificationExceptionMode, updatedMode: @escaping(NotificationExceptionMode)->Void) { self.account = account self.mode = mode @@ -46,18 +49,23 @@ public class NotificationExceptionsController: ViewController { } self.presentationDataDisposable = (account.telegramApplicationContext.presentationData - |> deliverOnMainQueue).start(next: { [weak self] presentationData in - if let strongSelf = self { - let previousTheme = strongSelf.presentationData.theme - let previousStrings = strongSelf.presentationData.strings - - strongSelf.presentationData = presentationData - - if previousTheme !== presentationData.theme || previousStrings !== presentationData.strings { - strongSelf.updateThemeAndStrings() - } + |> deliverOnMainQueue).start(next: { [weak self] presentationData in + if let strongSelf = self { + let previousTheme = strongSelf.presentationData.theme + let previousStrings = strongSelf.presentationData.strings + + strongSelf.presentationData = presentationData + + if previousTheme !== presentationData.theme || previousStrings !== presentationData.strings { + strongSelf.updateThemeAndStrings() } - }) + } + }) + + self.searchContentNode = NavigationBarSearchContentNode(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Common_Search, activate: { [weak self] in + self?.activateSearch() + }) + self.navigationBar?.setContentNode(self.searchContentNode, animated: false) } required public init(coder aDecoder: NSCoder) { @@ -71,6 +79,7 @@ public class NotificationExceptionsController: ViewController { private func updateThemeAndStrings() { self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBar.style.style self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData)) + self.searchContentNode?.updateThemeAndPlaceholder(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Common_Search) self.title = self.presentationData.strings.Notifications_ExceptionsTitle self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil) self.controllerNode.updatePresentationData(self.presentationData) @@ -130,7 +139,9 @@ public class NotificationExceptionsController: ViewController { if let scrollToTop = self.scrollToTop { scrollToTop() } - self.controllerNode.activateSearch() + if let searchContentNode = self.searchContentNode { + self.controllerNode.activateSearch(placeholderNode: searchContentNode.placeholderNode) + } self.setDisplayNavigationBar(false, transition: .animated(duration: 0.5, curve: .spring)) } } @@ -138,7 +149,9 @@ public class NotificationExceptionsController: ViewController { private func deactivateSearch() { if !self.displayNavigationBar { self.setDisplayNavigationBar(true, transition: .animated(duration: 0.5, curve: .spring)) - self.controllerNode.deactivateSearch() + if let searchContentNode = self.searchContentNode { + self.controllerNode.deactivateSearch(placeholderNode: searchContentNode.placeholderNode) + } } } } diff --git a/TelegramUI/NotificationSearchItem.swift b/TelegramUI/NotificationSearchItem.swift index 7f8475bd6c..e853d5f99d 100644 --- a/TelegramUI/NotificationSearchItem.swift +++ b/TelegramUI/NotificationSearchItem.swift @@ -108,7 +108,7 @@ class NotificationSearchItemNode: ListViewItemNode { let backgroundColor = item.theme.chatList.itemBackgroundColor - let searchBarApply = searchBarNodeLayout(NSAttributedString(string: placeholder ?? "", font: searchBarFont, textColor: UIColor(rgb: 0x8e8e93)), CGSize(width: baseWidth - 16.0, height: CGFloat.greatestFiniteMagnitude), UIColor(rgb: 0x8e8e93), item.theme.chatList.regularSearchBarColor, backgroundColor) + let searchBarApply = searchBarNodeLayout(NSAttributedString(string: placeholder ?? "", font: searchBarFont, textColor: UIColor(rgb: 0x8e8e93)), CGSize(width: baseWidth - 16.0, height: 28.0), 1.0, UIColor(rgb: 0x8e8e93), item.theme.chatList.regularSearchBarColor, backgroundColor, .immediate) let layout = ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: 44.0), insets: UIEdgeInsets()) diff --git a/TelegramUI/NotificationsAndSounds.swift b/TelegramUI/NotificationsAndSounds.swift index fe8192dfe1..ea264fa6ee 100644 --- a/TelegramUI/NotificationsAndSounds.swift +++ b/TelegramUI/NotificationsAndSounds.swift @@ -126,6 +126,7 @@ private enum NotificationsAndSoundsEntry: ItemListNodeEntry { case unreadCountCategoryInfo(PresentationTheme, String) case joinedNotifications(PresentationTheme, String, Bool) + case joinedNotificationsInfo(PresentationTheme, String) case reset(PresentationTheme, String) case resetNotice(PresentationTheme, String) @@ -146,7 +147,7 @@ private enum NotificationsAndSoundsEntry: ItemListNodeEntry { return NotificationsAndSoundsSection.displayNamesOnLockscreen.rawValue case .badgeHeader, .unreadCountStyle, .includePublicGroups, .includeChannels, .unreadCountCategory, .unreadCountCategoryInfo: return NotificationsAndSoundsSection.badge.rawValue - case .joinedNotifications: + case .joinedNotifications, .joinedNotificationsInfo: return NotificationsAndSoundsSection.joinedNotifications.rawValue case .reset, .resetNotice: return NotificationsAndSoundsSection.reset.rawValue @@ -221,10 +222,12 @@ private enum NotificationsAndSoundsEntry: ItemListNodeEntry { return 31 case .joinedNotifications: return 32 - case .reset: + case .joinedNotificationsInfo: return 33 - case .resetNotice: + case .reset: return 34 + case .resetNotice: + return 35 } } @@ -428,6 +431,12 @@ private enum NotificationsAndSoundsEntry: ItemListNodeEntry { } else { return false } + case let .joinedNotificationsInfo(lhsTheme, lhsText): + if case let .joinedNotificationsInfo(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { + return true + } else { + return false + } case let .reset(lhsTheme, lhsText): if case let .reset(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { return true @@ -575,6 +584,8 @@ private enum NotificationsAndSoundsEntry: ItemListNodeEntry { return ItemListSwitchItem(theme: theme, title: text, value: value, sectionId: self.section, style: .blocks, updated: { updatedValue in arguments.updateJoinedNotifications(updatedValue) }) + case let .joinedNotificationsInfo(theme, text): + return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section) case let .reset(theme, text): return ItemListActionItem(theme: theme, title: text, kind: .destructive, alignment: .natural, sectionId: self.section, style: .blocks, action: { arguments.resetNotifications() @@ -660,6 +671,7 @@ private func notificationsAndSoundsEntries(authorizationStatus: AccessType, warn entries.append(.unreadCountCategory(presentationData.theme, presentationData.strings.Notifications_Badge_CountUnreadMessages, inAppSettings.totalUnreadCountDisplayCategory == .messages)) entries.append(.unreadCountCategoryInfo(presentationData.theme, inAppSettings.totalUnreadCountDisplayCategory == .chats ? presentationData.strings.Notifications_Badge_CountUnreadMessages_InfoOff : presentationData.strings.Notifications_Badge_CountUnreadMessages_InfoOn)) entries.append(.joinedNotifications(presentationData.theme, presentationData.strings.NotificationSettings_ContactJoined, globalSettings.contactsJoined)) + entries.append(.joinedNotificationsInfo(presentationData.theme, presentationData.strings.NotificationSettings_ContactJoinedInfo)) entries.append(.reset(presentationData.theme, presentationData.strings.Notifications_ResetAllNotifications)) entries.append(.resetNotice(presentationData.theme, presentationData.strings.Notifications_ResetAllNotificationsHelp)) diff --git a/TelegramUI/PeerAvatarImageGalleryItem.swift b/TelegramUI/PeerAvatarImageGalleryItem.swift index 320363fb45..5a249b3e7c 100644 --- a/TelegramUI/PeerAvatarImageGalleryItem.swift +++ b/TelegramUI/PeerAvatarImageGalleryItem.swift @@ -188,11 +188,8 @@ final class PeerAvatarImageGalleryItemNode: ZoomableContentGalleryItemNode { case let .Fetching(isActive, progress): strongSelf.statusNode.isHidden = false strongSelf.statusNodeContainer.isUserInteractionEnabled = true - var actualProgress = progress - if isActive { - actualProgress = max(actualProgress, 0.027) - } - strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: CGFloat(actualProgress), cancelEnabled: true), completion: {}) + let adjustedProgress = max(progress, 0.027) + strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true), completion: {}) case .Local: if let previousStatus = previousStatus, case .Fetching = previousStatus { strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: 1.0, cancelEnabled: true), completion: { diff --git a/TelegramUI/PeerMediaCollectionControllerNode.swift b/TelegramUI/PeerMediaCollectionControllerNode.swift index ae44025d28..42983d1e31 100644 --- a/TelegramUI/PeerMediaCollectionControllerNode.swift +++ b/TelegramUI/PeerMediaCollectionControllerNode.swift @@ -379,7 +379,7 @@ class PeerMediaCollectionControllerNode: ASDisplayNode { }) self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate) - self.searchDisplayController?.activate(insertSubnode: { subnode in + self.searchDisplayController?.activate(insertSubnode: { subnode, isSearchBar in self.insertSubnode(subnode, belowSubnode: navigationBar) }, placeholder: placeholderNode) } diff --git a/TelegramUI/PeerSelectionController.swift b/TelegramUI/PeerSelectionController.swift index 2a3e0776a7..0dd3472884 100644 --- a/TelegramUI/PeerSelectionController.swift +++ b/TelegramUI/PeerSelectionController.swift @@ -42,6 +42,8 @@ public final class PeerSelectionController: ViewController { private let hasContactSelector: Bool + private var searchContentNode: NavigationBarSearchContentNode? + public init(account: Account, filter: ChatListNodePeersFilter = [.onlyWriteable], hasContactSelector: Bool = true, title: String? = nil) { self.account = account self.filter = filter @@ -74,6 +76,11 @@ public final class PeerSelectionController: ViewController { } } }) + + self.searchContentNode = NavigationBarSearchContentNode(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Common_Search, activate: { [weak self] in + self?.activateSearch() + }) + self.navigationBar?.setContentNode(self.searchContentNode, animated: false) } required public init(coder aDecoder: NSCoder) { @@ -88,6 +95,7 @@ public final class PeerSelectionController: ViewController { private func updateThemeAndStrings() { self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBar.style.style self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData)) + self.searchContentNode?.updateThemeAndPlaceholder(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Common_Search) self.title = self.presentationData.strings.Conversation_ForwardTitle self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil) } @@ -164,7 +172,9 @@ public final class PeerSelectionController: ViewController { if let scrollToTop = self.scrollToTop { scrollToTop() } - self.peerSelectionNode.activateSearch() + if let searchContentNode = self.searchContentNode { + self.peerSelectionNode.activateSearch(placeholderNode: searchContentNode.placeholderNode) + } self.setDisplayNavigationBar(false, transition: .animated(duration: 0.5, curve: .spring)) } } @@ -172,7 +182,9 @@ public final class PeerSelectionController: ViewController { private func deactivateSearch() { if !self.displayNavigationBar { self.setDisplayNavigationBar(true, transition: .animated(duration: 0.5, curve: .spring)) - self.peerSelectionNode.deactivateSearch() + if let searchContentNode = self.searchContentNode { + self.peerSelectionNode.deactivateSearch(placeholderNode: searchContentNode.placeholderNode) + } } } diff --git a/TelegramUI/PeerSelectionControllerNode.swift b/TelegramUI/PeerSelectionControllerNode.swift index 96a5d86a21..dd7e94110e 100644 --- a/TelegramUI/PeerSelectionControllerNode.swift +++ b/TelegramUI/PeerSelectionControllerNode.swift @@ -145,7 +145,7 @@ final class PeerSelectionControllerNode: ASDisplayNode { } var insets = layout.insets(options: [.input]) - insets.top += max(navigationBarHeight, layout.insets(options: [.statusBar]).top) + insets.top += navigationBarHeight insets.bottom = max(insets.bottom, cleanInsets.bottom) insets.left += layout.safeInsets.left insets.right += layout.safeInsets.right @@ -193,107 +193,80 @@ final class PeerSelectionControllerNode: ASDisplayNode { } } - func activateSearch() { + func activateSearch(placeholderNode: SearchBarPlaceholderNode) { guard let (containerLayout, navigationBarHeight) = self.containerLayout, let navigationBar = self.navigationBar else { return } if self.chatListNode.supernode != nil { - var maybePlaceholderNode: SearchBarPlaceholderNode? - self.chatListNode.forEachItemNode { node in - if let node = node as? ChatListSearchItemNode { - maybePlaceholderNode = node.searchBarNode + self.searchDisplayController = SearchDisplayController(theme: self.presentationData.theme, strings: self.presentationData.strings, mode: .navigation, contentNode: ChatListSearchContainerNode(account: self.account, filter: self.filter, groupId: nil, openPeer: { [weak self] peer, _ in + if let requestOpenPeerFromSearch = self?.requestOpenPeerFromSearch { + requestOpenPeerFromSearch(peer) } - } + }, openRecentPeerOptions: { _ in + }, openMessage: { [weak self] peer, messageId in + if let requestOpenMessageFromSearch = self?.requestOpenMessageFromSearch { + requestOpenMessageFromSearch(peer, messageId) + } + }, addContact: nil), cancel: { [weak self] in + if let requestDeactivateSearch = self?.requestDeactivateSearch { + requestDeactivateSearch() + } + }) - if let _ = self.searchDisplayController { - return - } + self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate) + self.searchDisplayController?.activate(insertSubnode: { [weak self, weak placeholderNode] subnode, isSearchBar in + if let strongSelf = self, let strongPlaceholderNode = placeholderNode { + if isSearchBar { + strongPlaceholderNode.supernode?.insertSubnode(subnode, aboveSubnode: strongPlaceholderNode) + } else { + strongSelf.insertSubnode(subnode, belowSubnode: navigationBar) + } + } + }, placeholder: placeholderNode) - if let placeholderNode = maybePlaceholderNode { - self.searchDisplayController = SearchDisplayController(theme: self.presentationData.theme, strings: self.presentationData.strings, contentNode: ChatListSearchContainerNode(account: self.account, filter: self.filter, groupId: nil, openPeer: { [weak self] peer, _ in - if let requestOpenPeerFromSearch = self?.requestOpenPeerFromSearch { - requestOpenPeerFromSearch(peer) - } - }, openRecentPeerOptions: { _ in - }, openMessage: { [weak self] peer, messageId in - if let requestOpenMessageFromSearch = self?.requestOpenMessageFromSearch { - requestOpenMessageFromSearch(peer, messageId) - } - }, addContact: nil), cancel: { [weak self] in - if let requestDeactivateSearch = self?.requestDeactivateSearch { - requestDeactivateSearch() - } - }) - - self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate) - self.searchDisplayController?.activate(insertSubnode: { subnode in - self.insertSubnode(subnode, belowSubnode: navigationBar) - }, placeholder: placeholderNode) - } } else if let contactListNode = self.contactListNode, contactListNode.supernode != nil { - var maybePlaceholderNode: SearchBarPlaceholderNode? - contactListNode.listNode.forEachItemNode { node in - if let node = node as? ChatListSearchItemNode { - maybePlaceholderNode = node.searchBarNode + self.searchDisplayController = SearchDisplayController(theme: self.presentationData.theme, strings: self.presentationData.strings, mode: .navigation, contentNode: ContactsSearchContainerNode(account: self.account, onlyWriteable: true, categories: [.cloudContacts, .global], openPeer: { [weak self] peer in + if let strongSelf = self { + switch peer { + case let .peer(peer, _): + let _ = (strongSelf.account.postbox.transaction { transaction -> Peer? in + return transaction.getPeer(peer.id) + } |> deliverOnMainQueue).start(next: { peer in + if let strongSelf = self, let peer = peer { + strongSelf.requestOpenPeerFromSearch?(peer) + } + }) + case let .deviceContact(stableId, contact): + break + } } - } + }), cancel: { [weak self] in + if let requestDeactivateSearch = self?.requestDeactivateSearch { + requestDeactivateSearch() + } + }) - if let _ = self.searchDisplayController { - return - } - - if let placeholderNode = maybePlaceholderNode { - self.searchDisplayController = SearchDisplayController(theme: self.presentationData.theme, strings: self.presentationData.strings, contentNode: ContactsSearchContainerNode(account: self.account, onlyWriteable: true, categories: [.cloudContacts, .global], openPeer: { [weak self] peer in - if let strongSelf = self { - switch peer { - case let .peer(peer, _): - let _ = (strongSelf.account.postbox.transaction { transaction -> Peer? in - return transaction.getPeer(peer.id) - } |> deliverOnMainQueue).start(next: { peer in - if let strongSelf = self, let peer = peer { - strongSelf.requestOpenPeerFromSearch?(peer) - } - }) - case let .deviceContact(stableId, contact): - break - } + self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate) + self.searchDisplayController?.activate(insertSubnode: { [weak self, weak placeholderNode] subnode, isSearchBar in + if let strongSelf = self, let strongPlaceholderNode = placeholderNode { + if isSearchBar { + strongPlaceholderNode.supernode?.insertSubnode(subnode, aboveSubnode: strongPlaceholderNode) + } else { + strongSelf.insertSubnode(subnode, belowSubnode: navigationBar) } - }), cancel: { [weak self] in - if let requestDeactivateSearch = self?.requestDeactivateSearch { - requestDeactivateSearch() - } - }) - - self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate) - self.searchDisplayController?.activate(insertSubnode: { subnode in - self.insertSubnode(subnode, belowSubnode: navigationBar) - }, placeholder: placeholderNode) - } + } + }, placeholder: placeholderNode) } } - func deactivateSearch() { + func deactivateSearch(placeholderNode: SearchBarPlaceholderNode) { if let searchDisplayController = self.searchDisplayController { if self.chatListNode.supernode != nil { - var maybePlaceholderNode: SearchBarPlaceholderNode? - self.chatListNode.forEachItemNode { node in - if let node = node as? ChatListSearchItemNode { - maybePlaceholderNode = node.searchBarNode - } - } - - searchDisplayController.deactivate(placeholder: maybePlaceholderNode) + searchDisplayController.deactivate(placeholder: placeholderNode) self.searchDisplayController = nil } else if let contactListNode = self.contactListNode, contactListNode.supernode != nil { - var maybePlaceholderNode: SearchBarPlaceholderNode? - contactListNode.listNode.forEachItemNode { node in - if let node = node as? ChatListSearchItemNode { - maybePlaceholderNode = node.searchBarNode - } - } - - searchDisplayController.deactivate(placeholder: maybePlaceholderNode) + searchDisplayController.deactivate(placeholder: placeholderNode) self.searchDisplayController = nil } } diff --git a/TelegramUI/PresentationStrings.swift b/TelegramUI/PresentationStrings.swift index 1cff90888a..aeff2f85f2 100644 --- a/TelegramUI/PresentationStrings.swift +++ b/TelegramUI/PresentationStrings.swift @@ -1466,1979 +1466,1980 @@ public final class PresentationStrings { public var Conversation_UnreadMessages: String { return self._s[1203]! } public var Channel_AdminLog_EmptyText: String { return self._s[1204]! } public var Notification_GroupActivated: String { return self._s[1205]! } + public var NotificationSettings_ContactJoinedInfo: String { return self._s[1206]! } public func Notification_PinnedContactMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1206]!, self._r[1206]!, [_0]) + return formatWithArgumentRanges(self._s[1207]!, self._r[1207]!, [_0]) } public func DownloadingStatus(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1207]!, self._r[1207]!, [_0, _1]) + return formatWithArgumentRanges(self._s[1208]!, self._r[1208]!, [_0, _1]) } - public var GroupInfo_ConvertToSupergroup: String { return self._s[1209]! } + public var GroupInfo_ConvertToSupergroup: String { return self._s[1210]! } public func PrivacyPolicy_AgeVerificationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1210]!, self._r[1210]!, [_0]) + return formatWithArgumentRanges(self._s[1211]!, self._r[1211]!, [_0]) } - public var Document_TargetConfirmationFormat: String { return self._s[1211]! } + public var Document_TargetConfirmationFormat: String { return self._s[1212]! } public func Call_StatusOngoing(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1212]!, self._r[1212]!, [_0]) + return formatWithArgumentRanges(self._s[1213]!, self._r[1213]!, [_0]) } - public var Contacts_SortByName: String { return self._s[1213]! } + public var Contacts_SortByName: String { return self._s[1214]! } public func CHAT_MESSAGE_INVOICE(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1215]!, self._r[1215]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1216]!, self._r[1216]!, [_1, _2, _3]) } - public var Conversation_ClearSelfHistory: String { return self._s[1216]! } - public var Checkout_NewCard_PostcodePlaceholder: String { return self._s[1217]! } - public var Stickers_SuggestNone: String { return self._s[1218]! } - public var ChatSettings_Cache: String { return self._s[1219]! } - public var Settings_SaveIncomingPhotos: String { return self._s[1220]! } - public var Media_ShareThisPhoto: String { return self._s[1221]! } - public var InfoPlist_NSContactsUsageDescription: String { return self._s[1222]! } - public var Conversation_ContextMenuCopyLink: String { return self._s[1223]! } - public var PrivacyPolicy_AgeVerificationTitle: String { return self._s[1224]! } - public var TwoStepAuth_SetupPasswordEnterPasswordNew: String { return self._s[1225]! } - public var Permissions_CellularDataTitle_v0: String { return self._s[1226]! } - public var Map_OpenIn: String { return self._s[1227]! } + public var Conversation_ClearSelfHistory: String { return self._s[1217]! } + public var Checkout_NewCard_PostcodePlaceholder: String { return self._s[1218]! } + public var Stickers_SuggestNone: String { return self._s[1219]! } + public var ChatSettings_Cache: String { return self._s[1220]! } + public var Settings_SaveIncomingPhotos: String { return self._s[1221]! } + public var Media_ShareThisPhoto: String { return self._s[1222]! } + public var InfoPlist_NSContactsUsageDescription: String { return self._s[1223]! } + public var Conversation_ContextMenuCopyLink: String { return self._s[1224]! } + public var PrivacyPolicy_AgeVerificationTitle: String { return self._s[1225]! } + public var TwoStepAuth_SetupPasswordEnterPasswordNew: String { return self._s[1226]! } + public var Permissions_CellularDataTitle_v0: String { return self._s[1227]! } + public var Map_OpenIn: String { return self._s[1228]! } public func ChannelInfo_AddParticipantConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1230]!, self._r[1230]!, [_0]) + return formatWithArgumentRanges(self._s[1231]!, self._r[1231]!, [_0]) } - public var MessagePoll_LabelClosed: String { return self._s[1231]! } - public var Passport_Identity_MiddleNamePlaceholder: String { return self._s[1233]! } - public var UserInfo_FirstNamePlaceholder: String { return self._s[1234]! } - public var PrivacyLastSeenSettings_WhoCanSeeMyTimestamp: String { return self._s[1235]! } - public var Login_SelectCountry_Title: String { return self._s[1236]! } - public var Channel_EditAdmin_PermissionBanUsers: String { return self._s[1237]! } - public var Watch_Suggestion_BRB: String { return self._s[1238]! } - public var Contacts_PermissionsTitle: String { return self._s[1239]! } - public var Passport_Identity_EditIdentityCard: String { return self._s[1240]! } - public var Conversation_RestrictedInline: String { return self._s[1241]! } - public var StickerPack_ViewPack: String { return self._s[1243]! } + public var MessagePoll_LabelClosed: String { return self._s[1232]! } + public var Passport_Identity_MiddleNamePlaceholder: String { return self._s[1234]! } + public var UserInfo_FirstNamePlaceholder: String { return self._s[1235]! } + public var PrivacyLastSeenSettings_WhoCanSeeMyTimestamp: String { return self._s[1236]! } + public var Login_SelectCountry_Title: String { return self._s[1237]! } + public var Channel_EditAdmin_PermissionBanUsers: String { return self._s[1238]! } + public var Watch_Suggestion_BRB: String { return self._s[1239]! } + public var Contacts_PermissionsTitle: String { return self._s[1240]! } + public var Passport_Identity_EditIdentityCard: String { return self._s[1241]! } + public var Conversation_RestrictedInline: String { return self._s[1242]! } + public var StickerPack_ViewPack: String { return self._s[1244]! } public func Update_AppVersion(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1244]!, self._r[1244]!, [_0]) + return formatWithArgumentRanges(self._s[1245]!, self._r[1245]!, [_0]) } - public var Compose_NewChannel: String { return self._s[1246]! } - public var Channel_Info_Stickers: String { return self._s[1250]! } - public var AutoNightTheme_PreferredTheme: String { return self._s[1251]! } - public var PrivacyPolicy_AgeVerificationAgree: String { return self._s[1252]! } - public var Passport_DeletePersonalDetails: String { return self._s[1253]! } - public var Conversation_SearchNoResults: String { return self._s[1255]! } - public var MessagePoll_LabelAnonymous: String { return self._s[1256]! } - public var Channel_Members_AddAdminErrorNotAMember: String { return self._s[1257]! } - public var Login_Code: String { return self._s[1258]! } - public var Watch_Suggestion_WhatsUp: String { return self._s[1259]! } - public var Weekday_ShortThursday: String { return self._s[1260]! } - public var Resolve_ErrorNotFound: String { return self._s[1262]! } - public var LastSeen_Offline: String { return self._s[1263]! } - public var Privacy_Calls_AlwaysAllow_Title: String { return self._s[1264]! } - public var Channel_AdminLog_CanChangeInviteLink: String { return self._s[1265]! } - public var GroupInfo_Title: String { return self._s[1266]! } - public var NotificationsSound_Note: String { return self._s[1267]! } - public var Conversation_EditingMessagePanelTitle: String { return self._s[1268]! } - public var Watch_Message_Poll: String { return self._s[1269]! } - public var Privacy_Calls: String { return self._s[1270]! } - public var Month_ShortAugust: String { return self._s[1271]! } - public var TwoStepAuth_SetPasswordHelp: String { return self._s[1272]! } - public var Notifications_Reset: String { return self._s[1273]! } - public var Conversation_Pin: String { return self._s[1274]! } - public var Passport_Language_lv: String { return self._s[1275]! } - public var BlockedUsers_Info: String { return self._s[1276]! } - public var Watch_Conversation_Unblock: String { return self._s[1279]! } + public var Compose_NewChannel: String { return self._s[1247]! } + public var Channel_Info_Stickers: String { return self._s[1251]! } + public var AutoNightTheme_PreferredTheme: String { return self._s[1252]! } + public var PrivacyPolicy_AgeVerificationAgree: String { return self._s[1253]! } + public var Passport_DeletePersonalDetails: String { return self._s[1254]! } + public var Conversation_SearchNoResults: String { return self._s[1256]! } + public var MessagePoll_LabelAnonymous: String { return self._s[1257]! } + public var Channel_Members_AddAdminErrorNotAMember: String { return self._s[1258]! } + public var Login_Code: String { return self._s[1259]! } + public var Watch_Suggestion_WhatsUp: String { return self._s[1260]! } + public var Weekday_ShortThursday: String { return self._s[1261]! } + public var Resolve_ErrorNotFound: String { return self._s[1263]! } + public var LastSeen_Offline: String { return self._s[1264]! } + public var Privacy_Calls_AlwaysAllow_Title: String { return self._s[1265]! } + public var Channel_AdminLog_CanChangeInviteLink: String { return self._s[1266]! } + public var GroupInfo_Title: String { return self._s[1267]! } + public var NotificationsSound_Note: String { return self._s[1268]! } + public var Conversation_EditingMessagePanelTitle: String { return self._s[1269]! } + public var Watch_Message_Poll: String { return self._s[1270]! } + public var Privacy_Calls: String { return self._s[1271]! } + public var Month_ShortAugust: String { return self._s[1272]! } + public var TwoStepAuth_SetPasswordHelp: String { return self._s[1273]! } + public var Notifications_Reset: String { return self._s[1274]! } + public var Conversation_Pin: String { return self._s[1275]! } + public var Passport_Language_lv: String { return self._s[1276]! } + public var BlockedUsers_Info: String { return self._s[1277]! } + public var Watch_Conversation_Unblock: String { return self._s[1280]! } public func Time_MonthOfYear_m9(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1280]!, self._r[1280]!, [_0]) + return formatWithArgumentRanges(self._s[1281]!, self._r[1281]!, [_0]) } - public var CloudStorage_Title: String { return self._s[1281]! } - public var GroupInfo_DeleteAndExitConfirmation: String { return self._s[1282]! } - public var TwoStepAuth_RecoveryEmailTitle: String { return self._s[1283]! } + public var CloudStorage_Title: String { return self._s[1282]! } + public var GroupInfo_DeleteAndExitConfirmation: String { return self._s[1283]! } + public var TwoStepAuth_RecoveryEmailTitle: String { return self._s[1284]! } public func NetworkUsageSettings_WifiUsageSince(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1284]!, self._r[1284]!, [_0]) + return formatWithArgumentRanges(self._s[1285]!, self._r[1285]!, [_0]) } - public var Watch_Suggestion_OnMyWay: String { return self._s[1285]! } - public var Channel_AdminLogFilter_AdminsTitle: String { return self._s[1286]! } - public var Passport_Address_EditBankStatement: String { return self._s[1287]! } - public var ChatSettings_DownloadInBackgroundInfo: String { return self._s[1288]! } - public var ShareMenu_Comment: String { return self._s[1289]! } - public var Permissions_ContactsTitle_v0: String { return self._s[1290]! } - public var Notifications_PermissionsTitle: String { return self._s[1291]! } - public var Settings_Support: String { return self._s[1292]! } - public var Notifications_ChannelNotificationsSound: String { return self._s[1293]! } - public var Channel_AdminLog_BanSendGifs: String { return self._s[1294]! } - public var Watch_Stickers_StickerPacks: String { return self._s[1295]! } - public var Common_Select: String { return self._s[1297]! } - public var CheckoutInfo_ErrorEmailInvalid: String { return self._s[1298]! } - public var ChatAdmins_AllMembersAreAdminsOffHelp: String { return self._s[1300]! } - public var PasscodeSettings_AutoLock_IfAwayFor_5hours: String { return self._s[1301]! } - public var Appearance_PreviewReplyAuthor: String { return self._s[1302]! } - public var TwoStepAuth_RecoveryTitle: String { return self._s[1303]! } - public var Widget_AuthRequired: String { return self._s[1304]! } - public var Camera_FlashOn: String { return self._s[1305]! } - public var Channel_Stickers_NotFoundHelp: String { return self._s[1306]! } - public var Watch_Suggestion_OK: String { return self._s[1307]! } + public var Watch_Suggestion_OnMyWay: String { return self._s[1286]! } + public var Channel_AdminLogFilter_AdminsTitle: String { return self._s[1287]! } + public var Passport_Address_EditBankStatement: String { return self._s[1288]! } + public var ChatSettings_DownloadInBackgroundInfo: String { return self._s[1289]! } + public var ShareMenu_Comment: String { return self._s[1290]! } + public var Permissions_ContactsTitle_v0: String { return self._s[1291]! } + public var Notifications_PermissionsTitle: String { return self._s[1292]! } + public var Settings_Support: String { return self._s[1293]! } + public var Notifications_ChannelNotificationsSound: String { return self._s[1294]! } + public var Channel_AdminLog_BanSendGifs: String { return self._s[1295]! } + public var Watch_Stickers_StickerPacks: String { return self._s[1296]! } + public var Common_Select: String { return self._s[1298]! } + public var CheckoutInfo_ErrorEmailInvalid: String { return self._s[1299]! } + public var ChatAdmins_AllMembersAreAdminsOffHelp: String { return self._s[1301]! } + public var PasscodeSettings_AutoLock_IfAwayFor_5hours: String { return self._s[1302]! } + public var Appearance_PreviewReplyAuthor: String { return self._s[1303]! } + public var TwoStepAuth_RecoveryTitle: String { return self._s[1304]! } + public var Widget_AuthRequired: String { return self._s[1305]! } + public var Camera_FlashOn: String { return self._s[1306]! } + public var Channel_Stickers_NotFoundHelp: String { return self._s[1307]! } + public var Watch_Suggestion_OK: String { return self._s[1308]! } public func Username_LinkHint(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1309]!, self._r[1309]!, [_0]) - } - public func Notification_PinnedLiveLocationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[1310]!, self._r[1310]!, [_0]) } - public var DialogList_AdLabel: String { return self._s[1311]! } - public var WatchRemote_NotificationText: String { return self._s[1312]! } - public var Conversation_ReportSpam: String { return self._s[1313]! } - public var Settings_LogoutConfirmationTitle: String { return self._s[1315]! } - public var PhoneLabel_Title: String { return self._s[1316]! } - public var Passport_Address_EditRentalAgreement: String { return self._s[1317]! } - public var Notifications_ExceptionsTitle: String { return self._s[1318]! } + public func Notification_PinnedLiveLocationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1311]!, self._r[1311]!, [_0]) + } + public var DialogList_AdLabel: String { return self._s[1312]! } + public var WatchRemote_NotificationText: String { return self._s[1313]! } + public var Conversation_ReportSpam: String { return self._s[1314]! } + public var Settings_LogoutConfirmationTitle: String { return self._s[1316]! } + public var PhoneLabel_Title: String { return self._s[1317]! } + public var Passport_Address_EditRentalAgreement: String { return self._s[1318]! } + public var Notifications_ExceptionsTitle: String { return self._s[1319]! } public func CHANNEL_MESSAGE_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1319]!, self._r[1319]!, [_1]) + return formatWithArgumentRanges(self._s[1320]!, self._r[1320]!, [_1]) } - public var Notifications_AlertTones: String { return self._s[1320]! } - public var Call_ReportIncludeLogDescription: String { return self._s[1321]! } + public var Notifications_AlertTones: String { return self._s[1321]! } + public var Call_ReportIncludeLogDescription: String { return self._s[1322]! } public func CHAT_ADD_MEMBER(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1322]!, self._r[1322]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1323]!, self._r[1323]!, [_1, _2, _3]) } - public var AutoDownloadSettings_PrivateChats: String { return self._s[1323]! } - public var TwoStepAuth_AddHintTitle: String { return self._s[1325]! } - public var ReportPeer_ReasonOther: String { return self._s[1326]! } - public var KeyCommand_ScrollDown: String { return self._s[1328]! } + public var AutoDownloadSettings_PrivateChats: String { return self._s[1324]! } + public var TwoStepAuth_AddHintTitle: String { return self._s[1326]! } + public var ReportPeer_ReasonOther: String { return self._s[1327]! } + public var KeyCommand_ScrollDown: String { return self._s[1329]! } public func Login_BannedPhoneSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1329]!, self._r[1329]!, [_0]) + return formatWithArgumentRanges(self._s[1330]!, self._r[1330]!, [_0]) } - public var NetworkUsageSettings_MediaVideoDataSection: String { return self._s[1330]! } - public var ChannelInfo_DeleteGroupConfirmation: String { return self._s[1331]! } - public var AuthSessions_LogOut: String { return self._s[1332]! } - public var Passport_Identity_TypeInternalPassport: String { return self._s[1333]! } - public var ChatSettings_AutoDownloadVoiceMessages: String { return self._s[1334]! } + public var NetworkUsageSettings_MediaVideoDataSection: String { return self._s[1331]! } + public var ChannelInfo_DeleteGroupConfirmation: String { return self._s[1332]! } + public var AuthSessions_LogOut: String { return self._s[1333]! } + public var Passport_Identity_TypeInternalPassport: String { return self._s[1334]! } + public var ChatSettings_AutoDownloadVoiceMessages: String { return self._s[1335]! } public func CHAT_MESSAGE_DOC(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1335]!, self._r[1335]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1336]!, self._r[1336]!, [_1, _2]) } - public var Passport_Phone_Title: String { return self._s[1336]! } - public var Settings_PhoneNumber: String { return self._s[1337]! } - public var NotificationsSound_Alert: String { return self._s[1338]! } - public var PhotoEditor_CurvesTool: String { return self._s[1340]! } - public var Checkout_PaymentMethod: String { return self._s[1342]! } - public var Contacts_AccessDeniedError: String { return self._s[1343]! } - public var Camera_PhotoMode: String { return self._s[1346]! } - public var Passport_Address_AddUtilityBill: String { return self._s[1347]! } - public var CallSettings_OnMobile: String { return self._s[1348]! } - public var Tour_Text2: String { return self._s[1349]! } - public var DialogList_EncryptionProcessing: String { return self._s[1351]! } - public var Permissions_Skip: String { return self._s[1352]! } - public var SecretImage_Title: String { return self._s[1353]! } - public var Watch_MessageView_Title: String { return self._s[1354]! } - public var AttachmentMenu_Poll: String { return self._s[1355]! } + public var Passport_Phone_Title: String { return self._s[1337]! } + public var Settings_PhoneNumber: String { return self._s[1338]! } + public var NotificationsSound_Alert: String { return self._s[1339]! } + public var PhotoEditor_CurvesTool: String { return self._s[1341]! } + public var Checkout_PaymentMethod: String { return self._s[1343]! } + public var Contacts_AccessDeniedError: String { return self._s[1344]! } + public var Camera_PhotoMode: String { return self._s[1347]! } + public var Passport_Address_AddUtilityBill: String { return self._s[1348]! } + public var CallSettings_OnMobile: String { return self._s[1349]! } + public var Tour_Text2: String { return self._s[1350]! } + public var DialogList_EncryptionProcessing: String { return self._s[1352]! } + public var Permissions_Skip: String { return self._s[1353]! } + public var SecretImage_Title: String { return self._s[1354]! } + public var Watch_MessageView_Title: String { return self._s[1355]! } + public var AttachmentMenu_Poll: String { return self._s[1356]! } public func Notification_GroupInviter(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1356]!, self._r[1356]!, [_0]) + return formatWithArgumentRanges(self._s[1357]!, self._r[1357]!, [_0]) } - public var Notification_CallCanceled: String { return self._s[1357]! } - public var Privacy_PaymentsClear_PaymentInfo: String { return self._s[1358]! } + public var Notification_CallCanceled: String { return self._s[1358]! } + public var Privacy_PaymentsClear_PaymentInfo: String { return self._s[1359]! } public func MESSAGE_SCREENSHOT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1359]!, self._r[1359]!, [_1]) + return formatWithArgumentRanges(self._s[1360]!, self._r[1360]!, [_1]) } - public var Settings_ProxyConnecting: String { return self._s[1360]! } - public var Profile_MessageLifetime5s: String { return self._s[1362]! } - public var Username_InvalidCharacters: String { return self._s[1363]! } - public var AutoDownloadSettings_LimitBySize: String { return self._s[1364]! } - public var Notification_CreatedChannel: String { return self._s[1366]! } - public var Passcode_AppLockedAlert: String { return self._s[1368]! } - public var Contacts_TopSection: String { return self._s[1369]! } + public var Settings_ProxyConnecting: String { return self._s[1361]! } + public var Profile_MessageLifetime5s: String { return self._s[1363]! } + public var Username_InvalidCharacters: String { return self._s[1364]! } + public var AutoDownloadSettings_LimitBySize: String { return self._s[1365]! } + public var Notification_CreatedChannel: String { return self._s[1367]! } + public var Passcode_AppLockedAlert: String { return self._s[1369]! } + public var Contacts_TopSection: String { return self._s[1370]! } public func Time_MonthOfYear_m6(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1370]!, self._r[1370]!, [_0]) + return formatWithArgumentRanges(self._s[1371]!, self._r[1371]!, [_0]) } - public var ReportPeer_ReasonSpam: String { return self._s[1371]! } - public var UserInfo_TapToCall: String { return self._s[1372]! } - public var Common_Search: String { return self._s[1374]! } - public var AuthSessions_IncompleteAttemptsInfo: String { return self._s[1375]! } - public var Message_InvoiceLabel: String { return self._s[1376]! } - public var Conversation_InputTextPlaceholder: String { return self._s[1377]! } - public var NetworkUsageSettings_MediaImageDataSection: String { return self._s[1378]! } + public var ReportPeer_ReasonSpam: String { return self._s[1372]! } + public var UserInfo_TapToCall: String { return self._s[1373]! } + public var Common_Search: String { return self._s[1375]! } + public var AuthSessions_IncompleteAttemptsInfo: String { return self._s[1376]! } + public var Message_InvoiceLabel: String { return self._s[1377]! } + public var Conversation_InputTextPlaceholder: String { return self._s[1378]! } + public var NetworkUsageSettings_MediaImageDataSection: String { return self._s[1379]! } public func Passport_Address_UploadOneOfScan(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1379]!, self._r[1379]!, [_0]) + return formatWithArgumentRanges(self._s[1380]!, self._r[1380]!, [_0]) } public func MESSAGE_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1380]!, self._r[1380]!, [_1]) + return formatWithArgumentRanges(self._s[1381]!, self._r[1381]!, [_1]) } - public var Conversation_Info: String { return self._s[1381]! } - public var Login_InfoDeletePhoto: String { return self._s[1382]! } - public var Passport_Language_vi: String { return self._s[1384]! } - public var Conversation_Search: String { return self._s[1385]! } - public var DialogList_DeleteBotConversationConfirmation: String { return self._s[1386]! } - public var ReportPeer_ReasonPornography: String { return self._s[1387]! } - public var AutoDownloadSettings_PhotosTitle: String { return self._s[1388]! } - public var Conversation_SendMessageErrorGroupRestricted: String { return self._s[1389]! } - public var Map_LiveLocationGroupDescription: String { return self._s[1390]! } - public var Channel_Setup_TypeHeader: String { return self._s[1391]! } - public var AuthSessions_LoggedIn: String { return self._s[1392]! } - public var Login_SmsRequestState3: String { return self._s[1393]! } - public var Passport_Address_EditUtilityBill: String { return self._s[1394]! } - public var Appearance_ReduceMotionInfo: String { return self._s[1395]! } - public var Channel_Edit_LinkItem: String { return self._s[1396]! } - public var Privacy_Calls_P2PNever: String { return self._s[1397]! } - public var Conversation_AddToReadingList: String { return self._s[1399]! } + public var Conversation_Info: String { return self._s[1382]! } + public var Login_InfoDeletePhoto: String { return self._s[1383]! } + public var Passport_Language_vi: String { return self._s[1385]! } + public var Conversation_Search: String { return self._s[1386]! } + public var DialogList_DeleteBotConversationConfirmation: String { return self._s[1387]! } + public var ReportPeer_ReasonPornography: String { return self._s[1388]! } + public var AutoDownloadSettings_PhotosTitle: String { return self._s[1389]! } + public var Conversation_SendMessageErrorGroupRestricted: String { return self._s[1390]! } + public var Map_LiveLocationGroupDescription: String { return self._s[1391]! } + public var Channel_Setup_TypeHeader: String { return self._s[1392]! } + public var AuthSessions_LoggedIn: String { return self._s[1393]! } + public var Login_SmsRequestState3: String { return self._s[1394]! } + public var Passport_Address_EditUtilityBill: String { return self._s[1395]! } + public var Appearance_ReduceMotionInfo: String { return self._s[1396]! } + public var Channel_Edit_LinkItem: String { return self._s[1397]! } + public var Privacy_Calls_P2PNever: String { return self._s[1398]! } + public var Conversation_AddToReadingList: String { return self._s[1400]! } public func MESSAGE_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1400]!, self._r[1400]!, [_1]) + return formatWithArgumentRanges(self._s[1401]!, self._r[1401]!, [_1]) } - public var Message_Animation: String { return self._s[1401]! } - public var Map_Unknown: String { return self._s[1402]! } - public var Call_StatusRequesting: String { return self._s[1403]! } + public var Message_Animation: String { return self._s[1402]! } + public var Map_Unknown: String { return self._s[1403]! } + public var Call_StatusRequesting: String { return self._s[1404]! } public func Passport_FieldOneOf_Or(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1404]!, self._r[1404]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1405]!, self._r[1405]!, [_1, _2]) } - public var Conversation_SecretChatContextBotAlert: String { return self._s[1405]! } - public var SocksProxySetup_ProxyStatusChecking: String { return self._s[1406]! } + public var Conversation_SecretChatContextBotAlert: String { return self._s[1406]! } + public var SocksProxySetup_ProxyStatusChecking: String { return self._s[1407]! } public func MESSAGE_PHOTO_SECRET(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1407]!, self._r[1407]!, [_1]) + return formatWithArgumentRanges(self._s[1408]!, self._r[1408]!, [_1]) } - public var Weekday_Monday: String { return self._s[1408]! } - public var Update_Skip: String { return self._s[1409]! } - public var Group_Username_RemoveExistingUsernamesInfo: String { return self._s[1410]! } - public var Message_PinnedPollMessage: String { return self._s[1411]! } - public var BlockedUsers_Title: String { return self._s[1412]! } + public var Weekday_Monday: String { return self._s[1409]! } + public var Update_Skip: String { return self._s[1410]! } + public var Group_Username_RemoveExistingUsernamesInfo: String { return self._s[1411]! } + public var Message_PinnedPollMessage: String { return self._s[1412]! } + public var BlockedUsers_Title: String { return self._s[1413]! } public func Notification_PinnedLocationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1413]!, self._r[1413]!, [_0]) + return formatWithArgumentRanges(self._s[1414]!, self._r[1414]!, [_0]) } - public var Username_CheckingUsername: String { return self._s[1414]! } - public var NotificationsSound_Bell: String { return self._s[1415]! } - public var Conversation_SendMessageErrorFlood: String { return self._s[1416]! } - public var ChannelMembers_ChannelAdminsTitle: String { return self._s[1417]! } - public var ChatSettings_Groups: String { return self._s[1418]! } - public var Your_card_was_declined: String { return self._s[1419]! } - public var TwoStepAuth_EnterPasswordHelp: String { return self._s[1421]! } - public var ChatList_Unmute: String { return self._s[1422]! } + public var Username_CheckingUsername: String { return self._s[1415]! } + public var NotificationsSound_Bell: String { return self._s[1416]! } + public var Conversation_SendMessageErrorFlood: String { return self._s[1417]! } + public var ChannelMembers_ChannelAdminsTitle: String { return self._s[1418]! } + public var ChatSettings_Groups: String { return self._s[1419]! } + public var Your_card_was_declined: String { return self._s[1420]! } + public var TwoStepAuth_EnterPasswordHelp: String { return self._s[1422]! } + public var ChatList_Unmute: String { return self._s[1423]! } public func PINNED_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1423]!, self._r[1423]!, [_1]) + return formatWithArgumentRanges(self._s[1424]!, self._r[1424]!, [_1]) } - public var PhotoEditor_CurvesAll: String { return self._s[1424]! } - public var Weekday_ShortTuesday: String { return self._s[1425]! } - public var DialogList_Read: String { return self._s[1426]! } + public var PhotoEditor_CurvesAll: String { return self._s[1425]! } + public var Weekday_ShortTuesday: String { return self._s[1426]! } + public var DialogList_Read: String { return self._s[1427]! } public func PINNED_TEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1427]!, self._r[1427]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1428]!, self._r[1428]!, [_1, _2]) } - public var ChannelMembers_WhoCanAddMembers_AllMembers: String { return self._s[1428]! } - public var Passport_Identity_Gender: String { return self._s[1429]! } + public var ChannelMembers_WhoCanAddMembers_AllMembers: String { return self._s[1429]! } + public var Passport_Identity_Gender: String { return self._s[1430]! } public func Target_ShareGameConfirmationPrivate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1430]!, self._r[1430]!, [_0]) + return formatWithArgumentRanges(self._s[1431]!, self._r[1431]!, [_0]) } - public var Target_SelectGroup: String { return self._s[1431]! } + public var Target_SelectGroup: String { return self._s[1432]! } public func DialogList_EncryptedChatStartedIncoming(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1433]!, self._r[1433]!, [_0]) + return formatWithArgumentRanges(self._s[1434]!, self._r[1434]!, [_0]) } - public var Passport_Language_en: String { return self._s[1434]! } - public var Channel_Username_CreatePublicLinkHelp: String { return self._s[1435]! } - public var Login_CancelPhoneVerificationContinue: String { return self._s[1436]! } + public var Passport_Language_en: String { return self._s[1435]! } + public var Channel_Username_CreatePublicLinkHelp: String { return self._s[1436]! } + public var Login_CancelPhoneVerificationContinue: String { return self._s[1437]! } public func AUTH_REGION(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1437]!, self._r[1437]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1438]!, self._r[1438]!, [_1, _2]) } - public var Checkout_NewCard_PaymentCard: String { return self._s[1439]! } - public var Login_InfoHelp: String { return self._s[1440]! } - public var Contacts_PermissionsSuppressWarningTitle: String { return self._s[1441]! } - public var SocksProxySetup_AddProxy: String { return self._s[1444]! } - public var CreatePoll_Title: String { return self._s[1445]! } - public var PasscodeSettings_SimplePasscodeHelp: String { return self._s[1446]! } - public var UserInfo_GroupsInCommon: String { return self._s[1447]! } - public var Call_AudioRouteHide: String { return self._s[1448]! } - public var ContactInfo_PhoneLabelMobile: String { return self._s[1450]! } - public var TextFormat_Bold: String { return self._s[1451]! } - public var FastTwoStepSetup_EmailSection: String { return self._s[1452]! } - public var Notifications_Title: String { return self._s[1453]! } - public var Group_Username_InvalidTooShort: String { return self._s[1454]! } - public var Channel_ErrorAddTooMuch: String { return self._s[1455]! } + public var Checkout_NewCard_PaymentCard: String { return self._s[1440]! } + public var Login_InfoHelp: String { return self._s[1441]! } + public var Contacts_PermissionsSuppressWarningTitle: String { return self._s[1442]! } + public var SocksProxySetup_AddProxy: String { return self._s[1445]! } + public var CreatePoll_Title: String { return self._s[1446]! } + public var PasscodeSettings_SimplePasscodeHelp: String { return self._s[1447]! } + public var UserInfo_GroupsInCommon: String { return self._s[1448]! } + public var Call_AudioRouteHide: String { return self._s[1449]! } + public var ContactInfo_PhoneLabelMobile: String { return self._s[1451]! } + public var TextFormat_Bold: String { return self._s[1452]! } + public var FastTwoStepSetup_EmailSection: String { return self._s[1453]! } + public var Notifications_Title: String { return self._s[1454]! } + public var Group_Username_InvalidTooShort: String { return self._s[1455]! } + public var Channel_ErrorAddTooMuch: String { return self._s[1456]! } public func DialogList_MultipleTypingSuffix(_ _0: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1456]!, self._r[1456]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[1457]!, self._r[1457]!, ["\(_0)"]) } - public var Stickers_SuggestAdded: String { return self._s[1458]! } - public var Login_CountryCode: String { return self._s[1459]! } - public var Map_GetDirections: String { return self._s[1460]! } - public var Login_PhoneFloodError: String { return self._s[1461]! } + public var Stickers_SuggestAdded: String { return self._s[1459]! } + public var Login_CountryCode: String { return self._s[1460]! } + public var Map_GetDirections: String { return self._s[1461]! } + public var Login_PhoneFloodError: String { return self._s[1462]! } public func Time_MonthOfYear_m3(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1462]!, self._r[1462]!, [_0]) + return formatWithArgumentRanges(self._s[1463]!, self._r[1463]!, [_0]) } - public var Settings_SetUsername: String { return self._s[1464]! } - public var Notification_GroupInviterSelf: String { return self._s[1465]! } - public var InstantPage_TapToOpenLink: String { return self._s[1466]! } + public var Settings_SetUsername: String { return self._s[1465]! } + public var Notification_GroupInviterSelf: String { return self._s[1466]! } + public var InstantPage_TapToOpenLink: String { return self._s[1467]! } public func Notification_ChannelInviter(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1467]!, self._r[1467]!, [_0]) + return formatWithArgumentRanges(self._s[1468]!, self._r[1468]!, [_0]) } - public var Watch_Suggestion_TalkLater: String { return self._s[1468]! } - public var SecretChat_Title: String { return self._s[1469]! } - public var Group_UpgradeNoticeText1: String { return self._s[1470]! } - public var AuthSessions_Title: String { return self._s[1471]! } - public var PhotoEditor_CropAuto: String { return self._s[1472]! } - public var Channel_About_Title: String { return self._s[1473]! } - public var FastTwoStepSetup_EmailHelp: String { return self._s[1474]! } + public var Watch_Suggestion_TalkLater: String { return self._s[1469]! } + public var SecretChat_Title: String { return self._s[1470]! } + public var Group_UpgradeNoticeText1: String { return self._s[1471]! } + public var AuthSessions_Title: String { return self._s[1472]! } + public var PhotoEditor_CropAuto: String { return self._s[1473]! } + public var Channel_About_Title: String { return self._s[1474]! } + public var FastTwoStepSetup_EmailHelp: String { return self._s[1475]! } public func CHAT_ADD_YOU(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1475]!, self._r[1475]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1476]!, self._r[1476]!, [_1, _2]) } public func Conversation_Bytes(_ _0: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1476]!, self._r[1476]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[1477]!, self._r[1477]!, ["\(_0)"]) } - public var Conversation_PinMessageAlert_OnlyPin: String { return self._s[1479]! } - public var Group_Setup_HistoryVisibleHelp: String { return self._s[1480]! } + public var Conversation_PinMessageAlert_OnlyPin: String { return self._s[1480]! } + public var Group_Setup_HistoryVisibleHelp: String { return self._s[1481]! } public func SharedMedia_SearchNoResultsDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1482]!, self._r[1482]!, [_0]) - } - public func TwoStepAuth_RecoveryEmailUnavailable(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[1483]!, self._r[1483]!, [_0]) } - public var Privacy_PaymentsClearInfoHelp: String { return self._s[1484]! } - public var Presence_online: String { return self._s[1486]! } - public var PasscodeSettings_Title: String { return self._s[1487]! } - public var Passport_Identity_ExpiryDatePlaceholder: String { return self._s[1488]! } - public var Web_OpenExternal: String { return self._s[1489]! } - public func AutoNightTheme_AutomaticHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1491]!, self._r[1491]!, [_0]) + public func TwoStepAuth_RecoveryEmailUnavailable(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1484]!, self._r[1484]!, [_0]) } - public var FastTwoStepSetup_PasswordConfirmationPlaceholder: String { return self._s[1492]! } - public var Map_YouAreHere: String { return self._s[1493]! } + public var Privacy_PaymentsClearInfoHelp: String { return self._s[1485]! } + public var Presence_online: String { return self._s[1487]! } + public var PasscodeSettings_Title: String { return self._s[1488]! } + public var Passport_Identity_ExpiryDatePlaceholder: String { return self._s[1489]! } + public var Web_OpenExternal: String { return self._s[1490]! } + public func AutoNightTheme_AutomaticHelp(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1492]!, self._r[1492]!, [_0]) + } + public var FastTwoStepSetup_PasswordConfirmationPlaceholder: String { return self._s[1493]! } + public var Map_YouAreHere: String { return self._s[1494]! } public func MESSAGE_GIF(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1494]!, self._r[1494]!, [_1]) + return formatWithArgumentRanges(self._s[1495]!, self._r[1495]!, [_1]) } public func AuthSessions_Message(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1495]!, self._r[1495]!, [_0]) + return formatWithArgumentRanges(self._s[1496]!, self._r[1496]!, [_0]) } - public var PrivacyLastSeenSettings_AlwaysShareWith: String { return self._s[1496]! } - public var Target_InviteToGroupErrorAlreadyInvited: String { return self._s[1497]! } + public var PrivacyLastSeenSettings_AlwaysShareWith: String { return self._s[1497]! } + public var Target_InviteToGroupErrorAlreadyInvited: String { return self._s[1498]! } public func AuthSessions_AppUnofficial(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1498]!, self._r[1498]!, [_0]) - } - public func DialogList_LiveLocationSharingTo(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[1499]!, self._r[1499]!, [_0]) } - public var SocksProxySetup_Username: String { return self._s[1500]! } - public var Bot_Start: String { return self._s[1501]! } - public func Channel_AdminLog_EmptyFilterQueryText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1502]!, self._r[1502]!, [_0]) + public func DialogList_LiveLocationSharingTo(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1500]!, self._r[1500]!, [_0]) } - public func Channel_AdminLog_MessagePinned(_ _0: String) -> (String, [(Int, NSRange)]) { + public var SocksProxySetup_Username: String { return self._s[1501]! } + public var Bot_Start: String { return self._s[1502]! } + public func Channel_AdminLog_EmptyFilterQueryText(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[1503]!, self._r[1503]!, [_0]) } - public var Contacts_SortByPresence: String { return self._s[1504]! } + public func Channel_AdminLog_MessagePinned(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1504]!, self._r[1504]!, [_0]) + } + public var Contacts_SortByPresence: String { return self._s[1505]! } public func PINNED_GEOLIVE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1506]!, self._r[1506]!, [_1]) + return formatWithArgumentRanges(self._s[1507]!, self._r[1507]!, [_1]) } - public var Conversation_DiscardVoiceMessageTitle: String { return self._s[1507]! } + public var Conversation_DiscardVoiceMessageTitle: String { return self._s[1508]! } public func PrivacySettings_LastSeenContactsMinus(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1508]!, self._r[1508]!, [_0]) + return formatWithArgumentRanges(self._s[1509]!, self._r[1509]!, [_0]) } - public var Passport_Email_EnterOtherEmail: String { return self._s[1509]! } - public var Login_InfoAvatarPhoto: String { return self._s[1510]! } - public var Privacy_PaymentsClear_ShippingInfo: String { return self._s[1511]! } - public var Tour_Title4: String { return self._s[1512]! } - public var Passport_Identity_Translation: String { return self._s[1513]! } - public var Login_TermsOfServiceLabel: String { return self._s[1515]! } - public var Passport_Language_it: String { return self._s[1516]! } - public var KeyCommand_JumpToNextUnreadChat: String { return self._s[1517]! } - public var Passport_Identity_SelfieHelp: String { return self._s[1518]! } - public var Conversation_ClearAll: String { return self._s[1520]! } + public var Passport_Email_EnterOtherEmail: String { return self._s[1510]! } + public var Login_InfoAvatarPhoto: String { return self._s[1511]! } + public var Privacy_PaymentsClear_ShippingInfo: String { return self._s[1512]! } + public var Tour_Title4: String { return self._s[1513]! } + public var Passport_Identity_Translation: String { return self._s[1514]! } + public var Login_TermsOfServiceLabel: String { return self._s[1516]! } + public var Passport_Language_it: String { return self._s[1517]! } + public var KeyCommand_JumpToNextUnreadChat: String { return self._s[1518]! } + public var Passport_Identity_SelfieHelp: String { return self._s[1519]! } + public var Conversation_ClearAll: String { return self._s[1521]! } public func MESSAGE_PHOTOS(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1522]!, self._r[1522]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1523]!, self._r[1523]!, [_1, _2]) } - public var TwoStepAuth_FloodError: String { return self._s[1523]! } - public var Paint_Delete: String { return self._s[1524]! } + public var TwoStepAuth_FloodError: String { return self._s[1524]! } + public var Paint_Delete: String { return self._s[1525]! } public func Passport_AcceptHelp(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1525]!, self._r[1525]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1526]!, self._r[1526]!, [_1, _2]) } - public var Message_PinnedAudioMessage: String { return self._s[1526]! } + public var Message_PinnedAudioMessage: String { return self._s[1527]! } public func Watch_Time_ShortTodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1527]!, self._r[1527]!, [_0]) + return formatWithArgumentRanges(self._s[1528]!, self._r[1528]!, [_0]) } - public var Notification_Mute1hMin: String { return self._s[1528]! } - public var Notifications_GroupNotificationsSound: String { return self._s[1529]! } - public var SocksProxySetup_ShareProxyList: String { return self._s[1530]! } - public var Conversation_MessageEditedLabel: String { return self._s[1531]! } - public var Notification_Exceptions_AlwaysOff: String { return self._s[1532]! } + public var Notification_Mute1hMin: String { return self._s[1529]! } + public var Notifications_GroupNotificationsSound: String { return self._s[1530]! } + public var SocksProxySetup_ShareProxyList: String { return self._s[1531]! } + public var Conversation_MessageEditedLabel: String { return self._s[1532]! } + public var Notification_Exceptions_AlwaysOff: String { return self._s[1533]! } public func Channel_AdminLog_MessageAdmin(_ _0: String, _ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1533]!, self._r[1533]!, [_0, _1, _2]) + return formatWithArgumentRanges(self._s[1534]!, self._r[1534]!, [_0, _1, _2]) } - public var NetworkUsageSettings_ResetStats: String { return self._s[1534]! } - public var AccessDenied_LocationTracking: String { return self._s[1535]! } - public var Month_GenOctober: String { return self._s[1536]! } - public var GroupInfo_InviteLink_RevokeAlert_Revoke: String { return self._s[1537]! } - public var EnterPasscode_EnterPasscode: String { return self._s[1538]! } - public var MediaPicker_TimerTooltip: String { return self._s[1540]! } - public var SharedMedia_TitleAll: String { return self._s[1541]! } - public var Conversation_RestrictedMedia: String { return self._s[1543]! } - public var AccessDenied_PhotosRestricted: String { return self._s[1544]! } - public var ChangePhoneNumberCode_Called: String { return self._s[1546]! } + public var NetworkUsageSettings_ResetStats: String { return self._s[1535]! } + public var AccessDenied_LocationTracking: String { return self._s[1536]! } + public var Month_GenOctober: String { return self._s[1537]! } + public var GroupInfo_InviteLink_RevokeAlert_Revoke: String { return self._s[1538]! } + public var EnterPasscode_EnterPasscode: String { return self._s[1539]! } + public var MediaPicker_TimerTooltip: String { return self._s[1541]! } + public var SharedMedia_TitleAll: String { return self._s[1542]! } + public var Conversation_RestrictedMedia: String { return self._s[1544]! } + public var AccessDenied_PhotosRestricted: String { return self._s[1545]! } + public var ChangePhoneNumberCode_Called: String { return self._s[1547]! } public func Notification_PinnedDocumentMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1547]!, self._r[1547]!, [_0]) + return formatWithArgumentRanges(self._s[1548]!, self._r[1548]!, [_0]) } - public var Conversation_SavedMessages: String { return self._s[1550]! } - public var Your_cards_expiration_month_is_invalid: String { return self._s[1552]! } - public var FastTwoStepSetup_PasswordPlaceholder: String { return self._s[1553]! } + public var Conversation_SavedMessages: String { return self._s[1551]! } + public var Your_cards_expiration_month_is_invalid: String { return self._s[1553]! } + public var FastTwoStepSetup_PasswordPlaceholder: String { return self._s[1554]! } public func Target_ShareGameConfirmationGroup(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1555]!, self._r[1555]!, [_0]) + return formatWithArgumentRanges(self._s[1556]!, self._r[1556]!, [_0]) } - public var ReportPeer_AlertSuccess: String { return self._s[1556]! } + public var ReportPeer_AlertSuccess: String { return self._s[1557]! } public func InstantPage_RelatedArticleAuthorAndDateTitle(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1557]!, self._r[1557]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1558]!, self._r[1558]!, [_1, _2]) } - public var PhotoEditor_CropAspectRatioOriginal: String { return self._s[1558]! } - public var Checkout_PasswordEntry_Title: String { return self._s[1559]! } - public var PhotoEditor_FadeTool: String { return self._s[1560]! } - public var Privacy_ContactsReset: String { return self._s[1561]! } + public var PhotoEditor_CropAspectRatioOriginal: String { return self._s[1559]! } + public var Checkout_PasswordEntry_Title: String { return self._s[1560]! } + public var PhotoEditor_FadeTool: String { return self._s[1561]! } + public var Privacy_ContactsReset: String { return self._s[1562]! } public func Channel_AdminLog_MessageRestrictedUntil(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1563]!, self._r[1563]!, [_0]) + return formatWithArgumentRanges(self._s[1564]!, self._r[1564]!, [_0]) } - public var Message_PinnedVideoMessage: String { return self._s[1564]! } - public var ChatList_Mute: String { return self._s[1565]! } - public var Permissions_CellularDataText_v0: String { return self._s[1566]! } - public var ShareMenu_SelectChats: String { return self._s[1568]! } - public var MusicPlayer_VoiceNote: String { return self._s[1569]! } - public var Conversation_RestrictedText: String { return self._s[1570]! } - public var TwoStepAuth_DisableSuccess: String { return self._s[1571]! } - public var Cache_Videos: String { return self._s[1572]! } - public var FeatureDisabled_Oops: String { return self._s[1574]! } - public var Passport_Address_PostcodePlaceholder: String { return self._s[1575]! } + public var Message_PinnedVideoMessage: String { return self._s[1565]! } + public var ChatList_Mute: String { return self._s[1566]! } + public var Permissions_CellularDataText_v0: String { return self._s[1567]! } + public var ShareMenu_SelectChats: String { return self._s[1569]! } + public var MusicPlayer_VoiceNote: String { return self._s[1570]! } + public var Conversation_RestrictedText: String { return self._s[1571]! } + public var TwoStepAuth_DisableSuccess: String { return self._s[1572]! } + public var Cache_Videos: String { return self._s[1573]! } + public var FeatureDisabled_Oops: String { return self._s[1575]! } + public var Passport_Address_PostcodePlaceholder: String { return self._s[1576]! } public func CHAT_MESSAGE_VIDEO(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1576]!, self._r[1576]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1577]!, self._r[1577]!, [_1, _2]) } - public var Stickers_GroupStickersHelp: String { return self._s[1577]! } - public var Message_VideoExpired: String { return self._s[1579]! } - public var Notifications_Badge: String { return self._s[1580]! } - public var GroupInfo_GroupHistoryVisible: String { return self._s[1581]! } - public var CreatePoll_OptionPlaceholder: String { return self._s[1582]! } - public var Username_InvalidTooShort: String { return self._s[1583]! } - public var EnterPasscode_EnterNewPasscodeChange: String { return self._s[1584]! } + public var Stickers_GroupStickersHelp: String { return self._s[1578]! } + public var Message_VideoExpired: String { return self._s[1580]! } + public var Notifications_Badge: String { return self._s[1581]! } + public var GroupInfo_GroupHistoryVisible: String { return self._s[1582]! } + public var CreatePoll_OptionPlaceholder: String { return self._s[1583]! } + public var Username_InvalidTooShort: String { return self._s[1584]! } + public var EnterPasscode_EnterNewPasscodeChange: String { return self._s[1585]! } public func Notification_MessageLifetimeRemoved(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1585]!, self._r[1585]!, [_1]) + return formatWithArgumentRanges(self._s[1586]!, self._r[1586]!, [_1]) } - public var Permissions_SiriAllowInSettings_v0: String { return self._s[1586]! } - public var SharedMedia_CategoryDocs: String { return self._s[1589]! } + public var Permissions_SiriAllowInSettings_v0: String { return self._s[1587]! } + public var SharedMedia_CategoryDocs: String { return self._s[1590]! } public func Notification_MessageLifetimeChangedOutgoing(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1591]!, self._r[1591]!, [_1]) + return formatWithArgumentRanges(self._s[1592]!, self._r[1592]!, [_1]) } - public var CheckoutInfo_ErrorShippingNotAvailable: String { return self._s[1592]! } + public var CheckoutInfo_ErrorShippingNotAvailable: String { return self._s[1593]! } public func Time_MonthOfYear_m12(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1593]!, self._r[1593]!, [_0]) + return formatWithArgumentRanges(self._s[1594]!, self._r[1594]!, [_0]) } - public var ChatSettings_PrivateChats: String { return self._s[1594]! } - public var Channel_UpdatePhotoItem: String { return self._s[1595]! } - public var GroupInfo_LeftStatus: String { return self._s[1596]! } - public var Watch_MessageView_Forward: String { return self._s[1598]! } - public var ReportPeer_ReasonChildAbuse: String { return self._s[1599]! } - public var Cache_ClearEmpty: String { return self._s[1601]! } - public var Localization_LanguageName: String { return self._s[1602]! } - public var WebSearch_GIFs: String { return self._s[1603]! } - public var Notifications_DisplayNamesOnLockScreenInfoWithLink: String { return self._s[1604]! } - public var Username_InvalidStartsWithNumber: String { return self._s[1605]! } - public var Common_Back: String { return self._s[1606]! } - public var Passport_Identity_DateOfBirthPlaceholder: String { return self._s[1607]! } + public var ChatSettings_PrivateChats: String { return self._s[1595]! } + public var Channel_UpdatePhotoItem: String { return self._s[1596]! } + public var GroupInfo_LeftStatus: String { return self._s[1597]! } + public var Watch_MessageView_Forward: String { return self._s[1599]! } + public var ReportPeer_ReasonChildAbuse: String { return self._s[1600]! } + public var Cache_ClearEmpty: String { return self._s[1602]! } + public var Localization_LanguageName: String { return self._s[1603]! } + public var WebSearch_GIFs: String { return self._s[1604]! } + public var Notifications_DisplayNamesOnLockScreenInfoWithLink: String { return self._s[1605]! } + public var Username_InvalidStartsWithNumber: String { return self._s[1606]! } + public var Common_Back: String { return self._s[1607]! } + public var Passport_Identity_DateOfBirthPlaceholder: String { return self._s[1608]! } public func CHANNEL_MESSAGE_AUDIO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1608]!, self._r[1608]!, [_1]) - } - public func CHANNEL_MESSAGE_ROUND(_ _1: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[1609]!, self._r[1609]!, [_1]) } - public var Passport_Email_Help: String { return self._s[1610]! } - public var Watch_Conversation_Reply: String { return self._s[1611]! } - public var Conversation_EditingMessageMediaChange: String { return self._s[1613]! } - public var Passport_Identity_IssueDatePlaceholder: String { return self._s[1614]! } - public var Channel_BanUser_Unban: String { return self._s[1616]! } - public var Channel_EditAdmin_PermissionPostMessages: String { return self._s[1617]! } - public var Group_Username_CreatePublicLinkHelp: String { return self._s[1618]! } - public var TwoStepAuth_ConfirmEmailCodePlaceholder: String { return self._s[1619]! } - public var Passport_Identity_Name: String { return self._s[1621]! } - public var Conversation_BlockUser: String { return self._s[1622]! } - public var Month_GenJanuary: String { return self._s[1623]! } - public var ChatSettings_TextSize: String { return self._s[1624]! } - public var Notification_PassportValuePhone: String { return self._s[1625]! } - public var Passport_Language_ne: String { return self._s[1626]! } - public var Notification_CallBack: String { return self._s[1627]! } - public var TwoStepAuth_EmailHelp: String { return self._s[1628]! } + public func CHANNEL_MESSAGE_ROUND(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1610]!, self._r[1610]!, [_1]) + } + public var Passport_Email_Help: String { return self._s[1611]! } + public var Watch_Conversation_Reply: String { return self._s[1612]! } + public var Conversation_EditingMessageMediaChange: String { return self._s[1614]! } + public var Passport_Identity_IssueDatePlaceholder: String { return self._s[1615]! } + public var Channel_BanUser_Unban: String { return self._s[1617]! } + public var Channel_EditAdmin_PermissionPostMessages: String { return self._s[1618]! } + public var Group_Username_CreatePublicLinkHelp: String { return self._s[1619]! } + public var TwoStepAuth_ConfirmEmailCodePlaceholder: String { return self._s[1620]! } + public var Passport_Identity_Name: String { return self._s[1622]! } + public var Conversation_BlockUser: String { return self._s[1623]! } + public var Month_GenJanuary: String { return self._s[1624]! } + public var ChatSettings_TextSize: String { return self._s[1625]! } + public var Notification_PassportValuePhone: String { return self._s[1626]! } + public var Passport_Language_ne: String { return self._s[1627]! } + public var Notification_CallBack: String { return self._s[1628]! } + public var TwoStepAuth_EmailHelp: String { return self._s[1629]! } public func Time_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1629]!, self._r[1629]!, [_0]) + return formatWithArgumentRanges(self._s[1630]!, self._r[1630]!, [_0]) } - public var Channel_Info_Management: String { return self._s[1630]! } - public var Passport_FieldIdentityUploadHelp: String { return self._s[1631]! } - public var Stickers_FrequentlyUsed: String { return self._s[1632]! } - public var Channel_BanUser_PermissionSendMessages: String { return self._s[1633]! } - public var Passport_Address_OneOfTypeUtilityBill: String { return self._s[1635]! } - public var Passport_Address_EditResidentialAddress: String { return self._s[1636]! } - public var PrivacyPolicy_DeclineTitle: String { return self._s[1637]! } - public var CreatePoll_TextHeader: String { return self._s[1638]! } + public var Channel_Info_Management: String { return self._s[1631]! } + public var Passport_FieldIdentityUploadHelp: String { return self._s[1632]! } + public var Stickers_FrequentlyUsed: String { return self._s[1633]! } + public var Channel_BanUser_PermissionSendMessages: String { return self._s[1634]! } + public var Passport_Address_OneOfTypeUtilityBill: String { return self._s[1636]! } + public var Passport_Address_EditResidentialAddress: String { return self._s[1637]! } + public var PrivacyPolicy_DeclineTitle: String { return self._s[1638]! } + public var CreatePoll_TextHeader: String { return self._s[1639]! } public func Checkout_SavePasswordTimeoutAndTouchId(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1639]!, self._r[1639]!, [_0]) + return formatWithArgumentRanges(self._s[1640]!, self._r[1640]!, [_0]) } - public var PhotoEditor_QualityMedium: String { return self._s[1640]! } - public var InfoPlist_NSMicrophoneUsageDescription: String { return self._s[1641]! } + public var PhotoEditor_QualityMedium: String { return self._s[1641]! } + public var InfoPlist_NSMicrophoneUsageDescription: String { return self._s[1642]! } public func Conversation_RestrictedInlineTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1642]!, self._r[1642]!, [_0]) + return formatWithArgumentRanges(self._s[1643]!, self._r[1643]!, [_0]) } - public var Conversation_StatusKickedFromChannel: String { return self._s[1643]! } - public var CheckoutInfo_ReceiverInfoName: String { return self._s[1644]! } - public var Group_ErrorSendRestrictedStickers: String { return self._s[1645]! } - public var Conversation_LinkDialogOpen: String { return self._s[1647]! } - public var Settings_Username: String { return self._s[1648]! } - public var Wallpaper_Wallpaper: String { return self._s[1650]! } + public var Conversation_StatusKickedFromChannel: String { return self._s[1644]! } + public var CheckoutInfo_ReceiverInfoName: String { return self._s[1645]! } + public var Group_ErrorSendRestrictedStickers: String { return self._s[1646]! } + public var Conversation_LinkDialogOpen: String { return self._s[1648]! } + public var Settings_Username: String { return self._s[1649]! } + public var Wallpaper_Wallpaper: String { return self._s[1651]! } public func PINNED_GIF(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1652]!, self._r[1652]!, [_1]) + return formatWithArgumentRanges(self._s[1653]!, self._r[1653]!, [_1]) } - public var SocksProxySetup_UseProxy: String { return self._s[1653]! } - public var UserInfo_ShareMyContactInfo: String { return self._s[1654]! } - public var MessageTimer_Forever: String { return self._s[1655]! } - public var Privacy_Calls_WhoCanCallMe: String { return self._s[1656]! } - public var PhotoEditor_DiscardChanges: String { return self._s[1657]! } - public var AuthSessions_TerminateOtherSessionsHelp: String { return self._s[1658]! } - public var Passport_Language_da: String { return self._s[1659]! } - public var SocksProxySetup_PortPlaceholder: String { return self._s[1660]! } + public var SocksProxySetup_UseProxy: String { return self._s[1654]! } + public var UserInfo_ShareMyContactInfo: String { return self._s[1655]! } + public var MessageTimer_Forever: String { return self._s[1656]! } + public var Privacy_Calls_WhoCanCallMe: String { return self._s[1657]! } + public var PhotoEditor_DiscardChanges: String { return self._s[1658]! } + public var AuthSessions_TerminateOtherSessionsHelp: String { return self._s[1659]! } + public var Passport_Language_da: String { return self._s[1660]! } + public var SocksProxySetup_PortPlaceholder: String { return self._s[1661]! } public func SecretGIF_NotViewedYet(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1661]!, self._r[1661]!, [_0]) + return formatWithArgumentRanges(self._s[1662]!, self._r[1662]!, [_0]) } - public var Passport_Address_EditPassportRegistration: String { return self._s[1662]! } + public var Passport_Address_EditPassportRegistration: String { return self._s[1663]! } public func Channel_AdminLog_MessageChangedGroupAbout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1664]!, self._r[1664]!, [_0]) + return formatWithArgumentRanges(self._s[1665]!, self._r[1665]!, [_0]) } - public var Passport_Identity_ResidenceCountryPlaceholder: String { return self._s[1666]! } - public var Conversation_SearchByName_Prefix: String { return self._s[1667]! } + public var Passport_Identity_ResidenceCountryPlaceholder: String { return self._s[1667]! } + public var Conversation_SearchByName_Prefix: String { return self._s[1668]! } public func PINNED_AUDIO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1668]!, self._r[1668]!, [_1]) + return formatWithArgumentRanges(self._s[1669]!, self._r[1669]!, [_1]) } - public var Conversation_PinnedPoll: String { return self._s[1669]! } - public var Conversation_EmptyGifPanelPlaceholder: String { return self._s[1670]! } - public var Cache_ByPeerHeader: String { return self._s[1671]! } + public var Conversation_PinnedPoll: String { return self._s[1670]! } + public var Conversation_EmptyGifPanelPlaceholder: String { return self._s[1671]! } + public var Cache_ByPeerHeader: String { return self._s[1672]! } public func Conversation_EncryptedPlaceholderTitleIncoming(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1672]!, self._r[1672]!, [_0]) + return formatWithArgumentRanges(self._s[1673]!, self._r[1673]!, [_0]) } - public var ChatSettings_AutoDownloadDocuments: String { return self._s[1673]! } - public var Notification_PinnedMessage: String { return self._s[1676]! } - public var Contacts_SortBy: String { return self._s[1678]! } - public var Call_EncryptionKey_Title: String { return self._s[1680]! } - public var Watch_UserInfo_Service: String { return self._s[1681]! } - public var Conversation_Unpin: String { return self._s[1684]! } - public var CancelResetAccount_Title: String { return self._s[1685]! } - public var Map_LiveLocationFor15Minutes: String { return self._s[1686]! } + public var ChatSettings_AutoDownloadDocuments: String { return self._s[1674]! } + public var Notification_PinnedMessage: String { return self._s[1677]! } + public var Contacts_SortBy: String { return self._s[1679]! } + public var Call_EncryptionKey_Title: String { return self._s[1681]! } + public var Watch_UserInfo_Service: String { return self._s[1682]! } + public var Conversation_Unpin: String { return self._s[1685]! } + public var CancelResetAccount_Title: String { return self._s[1686]! } + public var Map_LiveLocationFor15Minutes: String { return self._s[1687]! } public func Time_PreciseDate_m8(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1688]!, self._r[1688]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1689]!, self._r[1689]!, [_1, _2, _3]) } - public var Group_Members_AddMemberBotErrorNotAllowed: String { return self._s[1689]! } - public var CallSettings_Title: String { return self._s[1690]! } - public var PasscodeSettings_EncryptDataHelp: String { return self._s[1692]! } - public var AutoDownloadSettings_Contacts: String { return self._s[1693]! } - public var Passport_Identity_DocumentDetails: String { return self._s[1694]! } - public var LoginPassword_PasswordHelp: String { return self._s[1695]! } - public var PrivacyLastSeenSettings_CustomShareSettings_Delete: String { return self._s[1696]! } - public var Checkout_TotalPaidAmount: String { return self._s[1697]! } + public var Group_Members_AddMemberBotErrorNotAllowed: String { return self._s[1690]! } + public var CallSettings_Title: String { return self._s[1691]! } + public var PasscodeSettings_EncryptDataHelp: String { return self._s[1693]! } + public var AutoDownloadSettings_Contacts: String { return self._s[1694]! } + public var Passport_Identity_DocumentDetails: String { return self._s[1695]! } + public var LoginPassword_PasswordHelp: String { return self._s[1696]! } + public var PrivacyLastSeenSettings_CustomShareSettings_Delete: String { return self._s[1697]! } + public var Checkout_TotalPaidAmount: String { return self._s[1698]! } public func FileSize_KB(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1698]!, self._r[1698]!, [_0]) + return formatWithArgumentRanges(self._s[1699]!, self._r[1699]!, [_0]) } - public var PasscodeSettings_ChangePasscode: String { return self._s[1699]! } - public var Conversation_SecretLinkPreviewAlert: String { return self._s[1701]! } - public var Privacy_SecretChatsLinkPreviews: String { return self._s[1702]! } - public var Contacts_InviteFriends: String { return self._s[1704]! } - public var Map_ChooseLocationTitle: String { return self._s[1705]! } - public var Conversation_StopPoll: String { return self._s[1707]! } - public var Calls_RatingFeedback: String { return self._s[1708]! } - public var GroupInfo_BroadcastListNamePlaceholder: String { return self._s[1709]! } - public var NotificationsSound_Pulse: String { return self._s[1710]! } - public var Watch_LastSeen_Lately: String { return self._s[1711]! } - public var Widget_NoUsers: String { return self._s[1714]! } - public var Conversation_UnvotePoll: String { return self._s[1715]! } - public var NotificationsSound_Circles: String { return self._s[1717]! } - public var PrivacyLastSeenSettings_AlwaysShareWith_Title: String { return self._s[1719]! } + public var PasscodeSettings_ChangePasscode: String { return self._s[1700]! } + public var Conversation_SecretLinkPreviewAlert: String { return self._s[1702]! } + public var Privacy_SecretChatsLinkPreviews: String { return self._s[1703]! } + public var Contacts_InviteFriends: String { return self._s[1705]! } + public var Map_ChooseLocationTitle: String { return self._s[1706]! } + public var Conversation_StopPoll: String { return self._s[1708]! } + public var Calls_RatingFeedback: String { return self._s[1709]! } + public var GroupInfo_BroadcastListNamePlaceholder: String { return self._s[1710]! } + public var NotificationsSound_Pulse: String { return self._s[1711]! } + public var Watch_LastSeen_Lately: String { return self._s[1712]! } + public var Widget_NoUsers: String { return self._s[1715]! } + public var Conversation_UnvotePoll: String { return self._s[1716]! } + public var NotificationsSound_Circles: String { return self._s[1718]! } + public var PrivacyLastSeenSettings_AlwaysShareWith_Title: String { return self._s[1720]! } public func CHANNEL_MESSAGE_GEOLIVE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1720]!, self._r[1720]!, [_1]) + return formatWithArgumentRanges(self._s[1721]!, self._r[1721]!, [_1]) } - public var TwoStepAuth_RecoveryCodeExpired: String { return self._s[1721]! } + public var TwoStepAuth_RecoveryCodeExpired: String { return self._s[1722]! } public func CHAT_MESSAGE_GIF(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1722]!, self._r[1722]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1723]!, self._r[1723]!, [_1, _2]) } - public var Passport_Identity_CountryPlaceholder: String { return self._s[1724]! } - public var Conversation_FileDropbox: String { return self._s[1726]! } - public var Notifications_ExceptionsUnmuted: String { return self._s[1727]! } - public var Tour_Text3: String { return self._s[1729]! } - public var Login_ResetAccountProtected_Title: String { return self._s[1731]! } - public var ChatAdmins_AllMembersAreAdminsOnHelp: String { return self._s[1732]! } + public var Passport_Identity_CountryPlaceholder: String { return self._s[1725]! } + public var Conversation_FileDropbox: String { return self._s[1727]! } + public var Notifications_ExceptionsUnmuted: String { return self._s[1728]! } + public var Tour_Text3: String { return self._s[1730]! } + public var Login_ResetAccountProtected_Title: String { return self._s[1732]! } + public var ChatAdmins_AllMembersAreAdminsOnHelp: String { return self._s[1733]! } public func Conversation_LiveLocationYouAnd(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1734]!, self._r[1734]!, [_0]) + return formatWithArgumentRanges(self._s[1735]!, self._r[1735]!, [_0]) } - public var GroupInfo_AddParticipantTitle: String { return self._s[1735]! } - public var Checkout_ShippingOption_Title: String { return self._s[1736]! } - public var ChatSettings_AutoDownloadTitle: String { return self._s[1737]! } + public var GroupInfo_AddParticipantTitle: String { return self._s[1736]! } + public var Checkout_ShippingOption_Title: String { return self._s[1737]! } + public var ChatSettings_AutoDownloadTitle: String { return self._s[1738]! } public func DialogList_SingleTypingSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1738]!, self._r[1738]!, [_0]) + return formatWithArgumentRanges(self._s[1739]!, self._r[1739]!, [_0]) } public func CHAT_MESSAGE_ROUND(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1739]!, self._r[1739]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1740]!, self._r[1740]!, [_1, _2]) } - public var PrivacyLastSeenSettings_NeverShareWith_Placeholder: String { return self._s[1740]! } - public var Appearance_PreviewIncomingText: String { return self._s[1742]! } - public var ChannelInfo_ConfirmLeave: String { return self._s[1743]! } - public var MediaPicker_MomentsDateRangeSameMonthYearFormat: String { return self._s[1744]! } - public var Passport_Identity_DocumentNumberPlaceholder: String { return self._s[1745]! } - public var Channel_AdminLogFilter_EventsNewMembers: String { return self._s[1746]! } - public var PasscodeSettings_AutoLock_IfAwayFor_5minutes: String { return self._s[1747]! } - public var GroupInfo_SetGroupPhotoStop: String { return self._s[1748]! } - public var Notification_SecretChatScreenshot: String { return self._s[1749]! } - public var Passport_Address_City: String { return self._s[1751]! } - public var InfoPlist_NSPhotoLibraryAddUsageDescription: String { return self._s[1752]! } - public var SocksProxySetup_SecretPlaceholder: String { return self._s[1753]! } - public var AccessDenied_LocationDisabled: String { return self._s[1754]! } - public var SocksProxySetup_HostnamePlaceholder: String { return self._s[1756]! } - public var GroupInfo_Sound: String { return self._s[1757]! } - public var Stickers_RemoveFromFavorites: String { return self._s[1758]! } - public var Contacts_Title: String { return self._s[1759]! } - public var Passport_Language_fr: String { return self._s[1760]! } + public var PrivacyLastSeenSettings_NeverShareWith_Placeholder: String { return self._s[1741]! } + public var Appearance_PreviewIncomingText: String { return self._s[1743]! } + public var ChannelInfo_ConfirmLeave: String { return self._s[1744]! } + public var MediaPicker_MomentsDateRangeSameMonthYearFormat: String { return self._s[1745]! } + public var Passport_Identity_DocumentNumberPlaceholder: String { return self._s[1746]! } + public var Channel_AdminLogFilter_EventsNewMembers: String { return self._s[1747]! } + public var PasscodeSettings_AutoLock_IfAwayFor_5minutes: String { return self._s[1748]! } + public var GroupInfo_SetGroupPhotoStop: String { return self._s[1749]! } + public var Notification_SecretChatScreenshot: String { return self._s[1750]! } + public var Passport_Address_City: String { return self._s[1752]! } + public var InfoPlist_NSPhotoLibraryAddUsageDescription: String { return self._s[1753]! } + public var SocksProxySetup_SecretPlaceholder: String { return self._s[1754]! } + public var AccessDenied_LocationDisabled: String { return self._s[1755]! } + public var SocksProxySetup_HostnamePlaceholder: String { return self._s[1757]! } + public var GroupInfo_Sound: String { return self._s[1758]! } + public var Stickers_RemoveFromFavorites: String { return self._s[1759]! } + public var Contacts_Title: String { return self._s[1760]! } + public var Passport_Language_fr: String { return self._s[1761]! } public func CHAT_TITLE_EDITED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1761]!, self._r[1761]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1762]!, self._r[1762]!, [_1, _2]) } - public var Notifications_ResetAllNotifications: String { return self._s[1762]! } - public var PrivacySettings_SecurityTitle: String { return self._s[1765]! } - public var Checkout_NewCard_Title: String { return self._s[1766]! } - public var Login_HaveNotReceivedCodeInternal: String { return self._s[1767]! } - public var Conversation_ForwardChats: String { return self._s[1768]! } - public var Settings_FAQ: String { return self._s[1771]! } - public var AutoDownloadSettings_DocumentsTitle: String { return self._s[1772]! } - public var Conversation_ContextMenuForward: String { return self._s[1773]! } - public var PrivacyPolicy_Title: String { return self._s[1778]! } - public var Notifications_TextTone: String { return self._s[1779]! } - public var Profile_CreateNewContact: String { return self._s[1780]! } - public var AutoNightTheme_AutomaticSection: String { return self._s[1782]! } - public var Channel_Username_InvalidCharacters: String { return self._s[1784]! } + public var Notifications_ResetAllNotifications: String { return self._s[1763]! } + public var PrivacySettings_SecurityTitle: String { return self._s[1766]! } + public var Checkout_NewCard_Title: String { return self._s[1767]! } + public var Login_HaveNotReceivedCodeInternal: String { return self._s[1768]! } + public var Conversation_ForwardChats: String { return self._s[1769]! } + public var Settings_FAQ: String { return self._s[1772]! } + public var AutoDownloadSettings_DocumentsTitle: String { return self._s[1773]! } + public var Conversation_ContextMenuForward: String { return self._s[1774]! } + public var PrivacyPolicy_Title: String { return self._s[1779]! } + public var Notifications_TextTone: String { return self._s[1780]! } + public var Profile_CreateNewContact: String { return self._s[1781]! } + public var AutoNightTheme_AutomaticSection: String { return self._s[1783]! } + public var Channel_Username_InvalidCharacters: String { return self._s[1785]! } public func Channel_AdminLog_MessageChangedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1785]!, self._r[1785]!, [_0]) + return formatWithArgumentRanges(self._s[1786]!, self._r[1786]!, [_0]) } - public var PrivacySettings_LastSeenTitle: String { return self._s[1786]! } - public var Channel_AdminLog_CanInviteUsers: String { return self._s[1787]! } - public var Conversation_MessageDeliveryFailed: String { return self._s[1788]! } - public var TextFormat_Italic: String { return self._s[1789]! } - public var Bot_Unblock: String { return self._s[1790]! } - public var Watch_ChatList_NoConversationsText: String { return self._s[1791]! } - public var Weekday_Wednesday: String { return self._s[1792]! } - public var Settings_About_Help: String { return self._s[1793]! } - public var SearchImages_Title: String { return self._s[1794]! } - public var Conversation_ClousStorageInfo_Description1: String { return self._s[1795]! } - public var ExplicitContent_AlertTitle: String { return self._s[1796]! } + public var PrivacySettings_LastSeenTitle: String { return self._s[1787]! } + public var Channel_AdminLog_CanInviteUsers: String { return self._s[1788]! } + public var Conversation_MessageDeliveryFailed: String { return self._s[1789]! } + public var TextFormat_Italic: String { return self._s[1790]! } + public var Bot_Unblock: String { return self._s[1791]! } + public var Watch_ChatList_NoConversationsText: String { return self._s[1792]! } + public var Weekday_Wednesday: String { return self._s[1793]! } + public var Settings_About_Help: String { return self._s[1794]! } + public var SearchImages_Title: String { return self._s[1795]! } + public var Conversation_ClousStorageInfo_Description1: String { return self._s[1796]! } + public var ExplicitContent_AlertTitle: String { return self._s[1797]! } public func Time_PreciseDate_m5(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1797]!, self._r[1797]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1798]!, self._r[1798]!, [_1, _2, _3]) } - public var Weekday_Thursday: String { return self._s[1798]! } - public var Channel_Members_AddMembersHelp: String { return self._s[1799]! } + public var Weekday_Thursday: String { return self._s[1799]! } + public var Channel_Members_AddMembersHelp: String { return self._s[1800]! } public func Checkout_SavePasswordTimeout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1800]!, self._r[1800]!, [_0]) + return formatWithArgumentRanges(self._s[1801]!, self._r[1801]!, [_0]) } - public var Passport_RequestedInformation: String { return self._s[1801]! } - public var Login_PhoneAndCountryHelp: String { return self._s[1802]! } + public var Passport_RequestedInformation: String { return self._s[1802]! } + public var Login_PhoneAndCountryHelp: String { return self._s[1803]! } public func CHAT_MESSAGE_AUDIO(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1803]!, self._r[1803]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1804]!, self._r[1804]!, [_1, _2]) } - public var Conversation_EncryptionProcessing: String { return self._s[1804]! } - public var PhotoEditor_EnhanceTool: String { return self._s[1807]! } - public var Notifications_PermissionsSuppressWarningTitle: String { return self._s[1808]! } - public var Channel_Setup_Title: String { return self._s[1809]! } - public var Conversation_SearchPlaceholder: String { return self._s[1810]! } - public var AccessDenied_LocationAlwaysDenied: String { return self._s[1811]! } - public var Checkout_ErrorGeneric: String { return self._s[1812]! } - public var Passport_Language_hu: String { return self._s[1813]! } + public var Conversation_EncryptionProcessing: String { return self._s[1805]! } + public var PhotoEditor_EnhanceTool: String { return self._s[1808]! } + public var Notifications_PermissionsSuppressWarningTitle: String { return self._s[1809]! } + public var Channel_Setup_Title: String { return self._s[1810]! } + public var Conversation_SearchPlaceholder: String { return self._s[1811]! } + public var AccessDenied_LocationAlwaysDenied: String { return self._s[1812]! } + public var Checkout_ErrorGeneric: String { return self._s[1813]! } + public var Passport_Language_hu: String { return self._s[1814]! } public func Passport_Identity_UploadOneOfScan(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1815]!, self._r[1815]!, [_0]) + return formatWithArgumentRanges(self._s[1816]!, self._r[1816]!, [_0]) } - public var Conversation_CloudStorageInfo_Title: String { return self._s[1818]! } - public var PhotoEditor_CropAspectRatioSquare: String { return self._s[1819]! } + public var Conversation_CloudStorageInfo_Title: String { return self._s[1819]! } + public var PhotoEditor_CropAspectRatioSquare: String { return self._s[1820]! } public func Notification_Exceptions_MutedUntil(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1820]!, self._r[1820]!, [_0]) + return formatWithArgumentRanges(self._s[1821]!, self._r[1821]!, [_0]) } - public var Conversation_ClearPrivateHistory: String { return self._s[1821]! } - public var ContactInfo_PhoneLabelHome: String { return self._s[1822]! } - public var PrivacySettings_LastSeenContacts: String { return self._s[1823]! } + public var Conversation_ClearPrivateHistory: String { return self._s[1822]! } + public var ContactInfo_PhoneLabelHome: String { return self._s[1823]! } + public var PrivacySettings_LastSeenContacts: String { return self._s[1824]! } public func ChangePhone_ErrorOccupied(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1824]!, self._r[1824]!, [_0]) + return formatWithArgumentRanges(self._s[1825]!, self._r[1825]!, [_0]) } - public var Passport_Language_cs: String { return self._s[1825]! } - public var Message_PinnedAnimationMessage: String { return self._s[1826]! } - public var Passport_Identity_ReverseSideHelp: String { return self._s[1828]! } - public var Embed_PlayingInPIP: String { return self._s[1830]! } - public var AutoNightTheme_ScheduleSection: String { return self._s[1831]! } + public var Passport_Language_cs: String { return self._s[1826]! } + public var Message_PinnedAnimationMessage: String { return self._s[1827]! } + public var Passport_Identity_ReverseSideHelp: String { return self._s[1829]! } + public var Embed_PlayingInPIP: String { return self._s[1831]! } + public var AutoNightTheme_ScheduleSection: String { return self._s[1832]! } public func Call_EmojiDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1832]!, self._r[1832]!, [_0]) + return formatWithArgumentRanges(self._s[1833]!, self._r[1833]!, [_0]) } - public var MediaPicker_LivePhotoDescription: String { return self._s[1833]! } + public var MediaPicker_LivePhotoDescription: String { return self._s[1834]! } public func Channel_AdminLog_MessageRestrictedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1834]!, self._r[1834]!, [_1]) + return formatWithArgumentRanges(self._s[1835]!, self._r[1835]!, [_1]) } - public var Notification_PaymentSent: String { return self._s[1835]! } - public var PhotoEditor_CurvesGreen: String { return self._s[1836]! } - public var SaveIncomingPhotosSettings_Title: String { return self._s[1837]! } + public var Notification_PaymentSent: String { return self._s[1836]! } + public var PhotoEditor_CurvesGreen: String { return self._s[1837]! } + public var SaveIncomingPhotosSettings_Title: String { return self._s[1838]! } public func ApplyLanguage_UnsufficientDataText(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1838]!, self._r[1838]!, [_1]) + return formatWithArgumentRanges(self._s[1839]!, self._r[1839]!, [_1]) } public func CHAT_MESSAGE_GEOLIVE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1839]!, self._r[1839]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1840]!, self._r[1840]!, [_1, _2]) } - public var NetworkUsageSettings_CallDataSection: String { return self._s[1840]! } - public var PasscodeSettings_HelpTop: String { return self._s[1841]! } - public var Passport_Address_TypeRentalAgreement: String { return self._s[1843]! } - public var ReportPeer_ReasonOther_Placeholder: String { return self._s[1844]! } - public var CheckoutInfo_ErrorPhoneInvalid: String { return self._s[1845]! } - public var Call_Accept: String { return self._s[1847]! } - public var Month_GenMarch: String { return self._s[1848]! } - public var PhotoEditor_ShadowsTool: String { return self._s[1849]! } - public var LoginPassword_Title: String { return self._s[1850]! } - public var Watch_Conversation_GroupInfo: String { return self._s[1851]! } - public var CallSettings_Always: String { return self._s[1852]! } - public var TwoStepAuth_SetupHint: String { return self._s[1853]! } - public var ConversationProfile_UsersTooMuchError: String { return self._s[1854]! } - public var Login_PhoneTitle: String { return self._s[1855]! } - public var Passport_FieldPhoneHelp: String { return self._s[1856]! } - public var Weekday_ShortSunday: String { return self._s[1857]! } - public var Passport_InfoFAQ_URL: String { return self._s[1858]! } - public var ContactInfo_Job: String { return self._s[1860]! } - public var UserInfo_InviteBotToGroup: String { return self._s[1861]! } - public var TwoStepAuth_PasswordRemovePassportConfirmation: String { return self._s[1862]! } - public var Passport_DeletePersonalDetailsConfirmation: String { return self._s[1863]! } - public var Passport_Identity_AddInternalPassport: String { return self._s[1865]! } - public var MediaPicker_AddCaption: String { return self._s[1866]! } - public var CallSettings_TabIconDescription: String { return self._s[1867]! } - public var Privacy_GroupsAndChannels_AlwaysAllow: String { return self._s[1868]! } - public var Passport_Identity_TypePersonalDetails: String { return self._s[1869]! } - public var DialogList_SearchSectionRecent: String { return self._s[1870]! } - public var PrivacyPolicy_DeclineMessage: String { return self._s[1871]! } - public var LastSeen_WithinAWeek: String { return self._s[1874]! } - public var ChannelMembers_GroupAdminsTitle: String { return self._s[1875]! } - public var Conversation_CloudStorage_ChatStatus: String { return self._s[1877]! } - public var Passport_Address_TypeResidentialAddress: String { return self._s[1878]! } - public var Conversation_StatusLeftGroup: String { return self._s[1879]! } - public var SocksProxySetup_ProxyDetailsTitle: String { return self._s[1880]! } - public var PhotoEditor_BlurToolRadial: String { return self._s[1883]! } - public var Conversation_ContextMenuCopy: String { return self._s[1884]! } - public var AccessDenied_CallMicrophone: String { return self._s[1885]! } + public var NetworkUsageSettings_CallDataSection: String { return self._s[1841]! } + public var PasscodeSettings_HelpTop: String { return self._s[1842]! } + public var Passport_Address_TypeRentalAgreement: String { return self._s[1844]! } + public var ReportPeer_ReasonOther_Placeholder: String { return self._s[1845]! } + public var CheckoutInfo_ErrorPhoneInvalid: String { return self._s[1846]! } + public var Call_Accept: String { return self._s[1848]! } + public var Month_GenMarch: String { return self._s[1849]! } + public var PhotoEditor_ShadowsTool: String { return self._s[1850]! } + public var LoginPassword_Title: String { return self._s[1851]! } + public var Watch_Conversation_GroupInfo: String { return self._s[1852]! } + public var CallSettings_Always: String { return self._s[1853]! } + public var TwoStepAuth_SetupHint: String { return self._s[1854]! } + public var ConversationProfile_UsersTooMuchError: String { return self._s[1855]! } + public var Login_PhoneTitle: String { return self._s[1856]! } + public var Passport_FieldPhoneHelp: String { return self._s[1857]! } + public var Weekday_ShortSunday: String { return self._s[1858]! } + public var Passport_InfoFAQ_URL: String { return self._s[1859]! } + public var ContactInfo_Job: String { return self._s[1861]! } + public var UserInfo_InviteBotToGroup: String { return self._s[1862]! } + public var TwoStepAuth_PasswordRemovePassportConfirmation: String { return self._s[1863]! } + public var Passport_DeletePersonalDetailsConfirmation: String { return self._s[1864]! } + public var Passport_Identity_AddInternalPassport: String { return self._s[1866]! } + public var MediaPicker_AddCaption: String { return self._s[1867]! } + public var CallSettings_TabIconDescription: String { return self._s[1868]! } + public var Privacy_GroupsAndChannels_AlwaysAllow: String { return self._s[1869]! } + public var Passport_Identity_TypePersonalDetails: String { return self._s[1870]! } + public var DialogList_SearchSectionRecent: String { return self._s[1871]! } + public var PrivacyPolicy_DeclineMessage: String { return self._s[1872]! } + public var LastSeen_WithinAWeek: String { return self._s[1875]! } + public var ChannelMembers_GroupAdminsTitle: String { return self._s[1876]! } + public var Conversation_CloudStorage_ChatStatus: String { return self._s[1878]! } + public var Passport_Address_TypeResidentialAddress: String { return self._s[1879]! } + public var Conversation_StatusLeftGroup: String { return self._s[1880]! } + public var SocksProxySetup_ProxyDetailsTitle: String { return self._s[1881]! } + public var PhotoEditor_BlurToolRadial: String { return self._s[1884]! } + public var Conversation_ContextMenuCopy: String { return self._s[1885]! } + public var AccessDenied_CallMicrophone: String { return self._s[1886]! } public func Time_PreciseDate_m2(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1886]!, self._r[1886]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1887]!, self._r[1887]!, [_1, _2, _3]) } - public var Login_InvalidFirstNameError: String { return self._s[1887]! } - public var Notifications_Badge_CountUnreadMessages_InfoOn: String { return self._s[1888]! } - public var Checkout_PaymentMethod_New: String { return self._s[1889]! } - public var ShareMenu_CopyShareLinkGame: String { return self._s[1890]! } - public var PhotoEditor_QualityTool: String { return self._s[1891]! } - public var Login_SendCodeViaSms: String { return self._s[1892]! } + public var Login_InvalidFirstNameError: String { return self._s[1888]! } + public var Notifications_Badge_CountUnreadMessages_InfoOn: String { return self._s[1889]! } + public var Checkout_PaymentMethod_New: String { return self._s[1890]! } + public var ShareMenu_CopyShareLinkGame: String { return self._s[1891]! } + public var PhotoEditor_QualityTool: String { return self._s[1892]! } + public var Login_SendCodeViaSms: String { return self._s[1893]! } public func CHAT_MESSAGE_CONTACT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1893]!, self._r[1893]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1894]!, self._r[1894]!, [_1, _2]) } - public var Login_EmailNotConfiguredError: String { return self._s[1894]! } - public var PrivacyPolicy_Accept: String { return self._s[1895]! } - public var Notifications_ExceptionsMessagePlaceholder: String { return self._s[1896]! } - public var InfoPlist_NSLocationAlwaysUsageDescription: String { return self._s[1897]! } - public var AutoNightTheme_Automatic: String { return self._s[1898]! } - public var Channel_Username_InvalidStartsWithNumber: String { return self._s[1899]! } - public var Privacy_ContactsSyncHelp: String { return self._s[1900]! } - public var Cache_Help: String { return self._s[1901]! } - public var Passport_Language_fa: String { return self._s[1902]! } - public var Login_ResetAccountProtected_TimerTitle: String { return self._s[1903]! } - public var PrivacySettings_LastSeen: String { return self._s[1904]! } + public var Login_EmailNotConfiguredError: String { return self._s[1895]! } + public var PrivacyPolicy_Accept: String { return self._s[1896]! } + public var Notifications_ExceptionsMessagePlaceholder: String { return self._s[1897]! } + public var InfoPlist_NSLocationAlwaysUsageDescription: String { return self._s[1898]! } + public var AutoNightTheme_Automatic: String { return self._s[1899]! } + public var Channel_Username_InvalidStartsWithNumber: String { return self._s[1900]! } + public var Privacy_ContactsSyncHelp: String { return self._s[1901]! } + public var Cache_Help: String { return self._s[1902]! } + public var Passport_Language_fa: String { return self._s[1903]! } + public var Login_ResetAccountProtected_TimerTitle: String { return self._s[1904]! } + public var PrivacySettings_LastSeen: String { return self._s[1905]! } public func DialogList_MultipleTyping(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1905]!, self._r[1905]!, [_0, _1]) + return formatWithArgumentRanges(self._s[1906]!, self._r[1906]!, [_0, _1]) } - public var Channel_EditAdmin_PermissionInviteUsers: String { return self._s[1907]! } - public var Preview_SaveGif: String { return self._s[1909]! } - public var Profile_About: String { return self._s[1910]! } - public var Channel_About_Placeholder: String { return self._s[1911]! } - public var Login_InfoTitle: String { return self._s[1912]! } + public var Channel_EditAdmin_PermissionInviteUsers: String { return self._s[1908]! } + public var Preview_SaveGif: String { return self._s[1910]! } + public var Profile_About: String { return self._s[1911]! } + public var Channel_About_Placeholder: String { return self._s[1912]! } + public var Login_InfoTitle: String { return self._s[1913]! } public func TwoStepAuth_SetupPendingEmail(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1913]!, self._r[1913]!, [_0]) + return formatWithArgumentRanges(self._s[1914]!, self._r[1914]!, [_0]) } - public var Watch_Suggestion_CantTalk: String { return self._s[1915]! } - public var ContactInfo_Title: String { return self._s[1916]! } - public var Media_ShareThisVideo: String { return self._s[1917]! } - public var Weekday_ShortFriday: String { return self._s[1918]! } - public var AccessDenied_Contacts: String { return self._s[1919]! } - public var Notification_CallIncomingShort: String { return self._s[1920]! } - public var Group_Setup_TypePublic: String { return self._s[1921]! } - public var Notifications_MessageNotificationsExceptions: String { return self._s[1922]! } - public var Notifications_Badge_IncludeChannels: String { return self._s[1923]! } - public var Notifications_MessageNotificationsPreview: String { return self._s[1926]! } - public var ConversationProfile_ErrorCreatingConversation: String { return self._s[1927]! } - public var Group_ErrorAddTooMuchBots: String { return self._s[1928]! } - public var Privacy_GroupsAndChannels_CustomShareHelp: String { return self._s[1929]! } - public var Permissions_CellularDataAllowInSettings_v0: String { return self._s[1930]! } - public var DialogList_Typing: String { return self._s[1931]! } - public var Checkout_Phone: String { return self._s[1934]! } - public var Login_InfoFirstNamePlaceholder: String { return self._s[1937]! } + public var Watch_Suggestion_CantTalk: String { return self._s[1916]! } + public var ContactInfo_Title: String { return self._s[1917]! } + public var Media_ShareThisVideo: String { return self._s[1918]! } + public var Weekday_ShortFriday: String { return self._s[1919]! } + public var AccessDenied_Contacts: String { return self._s[1920]! } + public var Notification_CallIncomingShort: String { return self._s[1921]! } + public var Group_Setup_TypePublic: String { return self._s[1922]! } + public var Notifications_MessageNotificationsExceptions: String { return self._s[1923]! } + public var Notifications_Badge_IncludeChannels: String { return self._s[1924]! } + public var Notifications_MessageNotificationsPreview: String { return self._s[1927]! } + public var ConversationProfile_ErrorCreatingConversation: String { return self._s[1928]! } + public var Group_ErrorAddTooMuchBots: String { return self._s[1929]! } + public var Privacy_GroupsAndChannels_CustomShareHelp: String { return self._s[1930]! } + public var Permissions_CellularDataAllowInSettings_v0: String { return self._s[1931]! } + public var DialogList_Typing: String { return self._s[1932]! } + public var Checkout_Phone: String { return self._s[1935]! } + public var Login_InfoFirstNamePlaceholder: String { return self._s[1938]! } public func PINNED_POLL(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1938]!, self._r[1938]!, [_1]) + return formatWithArgumentRanges(self._s[1939]!, self._r[1939]!, [_1]) } - public var Privacy_Calls_Integration: String { return self._s[1939]! } - public var Notifications_PermissionsAllow: String { return self._s[1941]! } - public var TwoStepAuth_AddHintDescription: String { return self._s[1944]! } - public var Settings_ChatSettings: String { return self._s[1945]! } + public var Privacy_Calls_Integration: String { return self._s[1940]! } + public var Notifications_PermissionsAllow: String { return self._s[1942]! } + public var TwoStepAuth_AddHintDescription: String { return self._s[1945]! } + public var Settings_ChatSettings: String { return self._s[1946]! } public func Channel_AdminLog_MessageInvitedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1946]!, self._r[1946]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1947]!, self._r[1947]!, [_1, _2]) } - public var Login_ContinueWithLocalization: String { return self._s[1948]! } - public var Watch_Message_ForwardedFrom: String { return self._s[1949]! } - public var TwoStepAuth_EnterEmailCode: String { return self._s[1951]! } - public var Conversation_Unblock: String { return self._s[1952]! } - public var PrivacySettings_DataSettings: String { return self._s[1953]! } - public var Notifications_InAppNotificationsVibrate: String { return self._s[1954]! } + public var Login_ContinueWithLocalization: String { return self._s[1949]! } + public var Watch_Message_ForwardedFrom: String { return self._s[1950]! } + public var TwoStepAuth_EnterEmailCode: String { return self._s[1952]! } + public var Conversation_Unblock: String { return self._s[1953]! } + public var PrivacySettings_DataSettings: String { return self._s[1954]! } + public var Notifications_InAppNotificationsVibrate: String { return self._s[1955]! } public func Privacy_GroupsAndChannels_InviteToChannelError(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1955]!, self._r[1955]!, [_0, _1]) + return formatWithArgumentRanges(self._s[1956]!, self._r[1956]!, [_0, _1]) } - public var PrivacySettings_Passcode: String { return self._s[1958]! } + public var PrivacySettings_Passcode: String { return self._s[1959]! } public func ENCRYPTION_ACCEPT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1959]!, self._r[1959]!, [_1]) + return formatWithArgumentRanges(self._s[1960]!, self._r[1960]!, [_1]) } - public var Passport_Language_dz: String { return self._s[1960]! } - public var Passport_Language_tk: String { return self._s[1961]! } + public var Passport_Language_dz: String { return self._s[1961]! } + public var Passport_Language_tk: String { return self._s[1962]! } public func Login_EmailCodeSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1962]!, self._r[1962]!, [_0]) + return formatWithArgumentRanges(self._s[1963]!, self._r[1963]!, [_0]) } - public var InfoPlist_NSPhotoLibraryUsageDescription: String { return self._s[1963]! } - public var Conversation_ContextMenuReply: String { return self._s[1964]! } - public var Tour_Title1: String { return self._s[1965]! } + public var InfoPlist_NSPhotoLibraryUsageDescription: String { return self._s[1964]! } + public var Conversation_ContextMenuReply: String { return self._s[1965]! } + public var Tour_Title1: String { return self._s[1966]! } public func MESSAGE_STICKER(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1966]!, self._r[1966]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1967]!, self._r[1967]!, [_1, _2]) } - public var Conversation_ClearGroupHistory: String { return self._s[1968]! } + public var Conversation_ClearGroupHistory: String { return self._s[1969]! } public func Checkout_PasswordEntry_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1969]!, self._r[1969]!, [_0]) + return formatWithArgumentRanges(self._s[1970]!, self._r[1970]!, [_0]) } - public var Call_RateCall: String { return self._s[1970]! } - public var Passport_PasswordCompleteSetup: String { return self._s[1971]! } - public var Conversation_InputTextSilentBroadcastPlaceholder: String { return self._s[1972]! } - public var UserInfo_LastNamePlaceholder: String { return self._s[1974]! } + public var Call_RateCall: String { return self._s[1971]! } + public var Passport_PasswordCompleteSetup: String { return self._s[1972]! } + public var Conversation_InputTextSilentBroadcastPlaceholder: String { return self._s[1973]! } + public var UserInfo_LastNamePlaceholder: String { return self._s[1975]! } public func Login_WillCallYou(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1976]!, self._r[1976]!, [_0]) + return formatWithArgumentRanges(self._s[1977]!, self._r[1977]!, [_0]) } - public var Compose_Create: String { return self._s[1977]! } - public var Contacts_InviteToTelegram: String { return self._s[1978]! } - public var GroupInfo_Notifications: String { return self._s[1979]! } - public var Message_PinnedLiveLocationMessage: String { return self._s[1981]! } - public var Month_GenApril: String { return self._s[1982]! } - public var Appearance_AutoNightTheme: String { return self._s[1983]! } - public var ChatSettings_AutomaticAudioDownload: String { return self._s[1985]! } - public var Login_CodeSentSms: String { return self._s[1987]! } + public var Compose_Create: String { return self._s[1978]! } + public var Contacts_InviteToTelegram: String { return self._s[1979]! } + public var GroupInfo_Notifications: String { return self._s[1980]! } + public var Message_PinnedLiveLocationMessage: String { return self._s[1982]! } + public var Month_GenApril: String { return self._s[1983]! } + public var Appearance_AutoNightTheme: String { return self._s[1984]! } + public var ChatSettings_AutomaticAudioDownload: String { return self._s[1986]! } + public var Login_CodeSentSms: String { return self._s[1988]! } public func UserInfo_UnblockConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1988]!, self._r[1988]!, [_0]) + return formatWithArgumentRanges(self._s[1989]!, self._r[1989]!, [_0]) } - public var Passport_Language_hr: String { return self._s[1989]! } + public var Passport_Language_hr: String { return self._s[1990]! } public func Channel_AdminLog_MessageRestrictedNewSetting(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1990]!, self._r[1990]!, [_0]) + return formatWithArgumentRanges(self._s[1991]!, self._r[1991]!, [_0]) } - public var GroupInfo_InviteLink_CopyLink: String { return self._s[1991]! } - public var Conversation_InputTextBroadcastPlaceholder: String { return self._s[1992]! } - public var Privacy_SecretChatsTitle: String { return self._s[1993]! } - public var Notification_SecretChatMessageScreenshotSelf: String { return self._s[1995]! } - public var GroupInfo_AddUserLeftError: String { return self._s[1996]! } - public var Preview_DeleteGif: String { return self._s[1997]! } - public var Group_ErrorNotMutualContact: String { return self._s[1998]! } - public var Notification_MessageLifetime5s: String { return self._s[1999]! } + public var GroupInfo_InviteLink_CopyLink: String { return self._s[1992]! } + public var Conversation_InputTextBroadcastPlaceholder: String { return self._s[1993]! } + public var Privacy_SecretChatsTitle: String { return self._s[1994]! } + public var Notification_SecretChatMessageScreenshotSelf: String { return self._s[1996]! } + public var GroupInfo_AddUserLeftError: String { return self._s[1997]! } + public var Preview_DeleteGif: String { return self._s[1998]! } + public var Group_ErrorNotMutualContact: String { return self._s[1999]! } + public var Notification_MessageLifetime5s: String { return self._s[2000]! } public func Watch_LastSeen_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2000]!, self._r[2000]!, [_0]) + return formatWithArgumentRanges(self._s[2001]!, self._r[2001]!, [_0]) } - public var Passport_Address_AddBankStatement: String { return self._s[2002]! } - public var Notification_CallIncoming: String { return self._s[2003]! } - public var Compose_NewGroupTitle: String { return self._s[2004]! } - public var TwoStepAuth_RecoveryCodeHelp: String { return self._s[2006]! } - public var Passport_Address_Postcode: String { return self._s[2008]! } + public var Passport_Address_AddBankStatement: String { return self._s[2003]! } + public var Notification_CallIncoming: String { return self._s[2004]! } + public var Compose_NewGroupTitle: String { return self._s[2005]! } + public var TwoStepAuth_RecoveryCodeHelp: String { return self._s[2007]! } + public var Passport_Address_Postcode: String { return self._s[2009]! } public func LastSeen_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2009]!, self._r[2009]!, [_0]) + return formatWithArgumentRanges(self._s[2010]!, self._r[2010]!, [_0]) } - public var Checkout_NewCard_SaveInfoHelp: String { return self._s[2010]! } + public var Checkout_NewCard_SaveInfoHelp: String { return self._s[2011]! } public func Cache_Clear(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2011]!, self._r[2011]!, [_0]) + return formatWithArgumentRanges(self._s[2012]!, self._r[2012]!, [_0]) } - public var Bot_GroupStatusDoesNotReadHistory: String { return self._s[2012]! } - public var Username_Placeholder: String { return self._s[2013]! } - public var Passport_FieldAddressUploadHelp: String { return self._s[2014]! } - public var Permissions_NotificationsAllowInSettings_v0: String { return self._s[2015]! } - public var Passport_PasswordDescription: String { return self._s[2017]! } - public var Channel_MessagePhotoUpdated: String { return self._s[2018]! } - public var MediaPicker_TapToUngroupDescription: String { return self._s[2019]! } - public var AttachmentMenu_PhotoOrVideo: String { return self._s[2020]! } - public var Conversation_ContextMenuMore: String { return self._s[2021]! } - public var Privacy_PaymentsClearInfo: String { return self._s[2022]! } - public var CallSettings_TabIcon: String { return self._s[2023]! } - public var KeyCommand_Find: String { return self._s[2024]! } - public var Message_PinnedGame: String { return self._s[2025]! } - public var Notifications_Badge_CountUnreadMessages_InfoOff: String { return self._s[2026]! } - public var Login_CallRequestState2: String { return self._s[2028]! } - public var CheckoutInfo_ReceiverInfoNamePlaceholder: String { return self._s[2030]! } + public var Bot_GroupStatusDoesNotReadHistory: String { return self._s[2013]! } + public var Username_Placeholder: String { return self._s[2014]! } + public var Passport_FieldAddressUploadHelp: String { return self._s[2015]! } + public var Permissions_NotificationsAllowInSettings_v0: String { return self._s[2016]! } + public var Passport_PasswordDescription: String { return self._s[2018]! } + public var Channel_MessagePhotoUpdated: String { return self._s[2019]! } + public var MediaPicker_TapToUngroupDescription: String { return self._s[2020]! } + public var AttachmentMenu_PhotoOrVideo: String { return self._s[2021]! } + public var Conversation_ContextMenuMore: String { return self._s[2022]! } + public var Privacy_PaymentsClearInfo: String { return self._s[2023]! } + public var CallSettings_TabIcon: String { return self._s[2024]! } + public var KeyCommand_Find: String { return self._s[2025]! } + public var Message_PinnedGame: String { return self._s[2026]! } + public var Notifications_Badge_CountUnreadMessages_InfoOff: String { return self._s[2027]! } + public var Login_CallRequestState2: String { return self._s[2029]! } + public var CheckoutInfo_ReceiverInfoNamePlaceholder: String { return self._s[2031]! } public func Checkout_PayPrice(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2032]!, self._r[2032]!, [_0]) + return formatWithArgumentRanges(self._s[2033]!, self._r[2033]!, [_0]) } - public var Conversation_InstantPagePreview: String { return self._s[2033]! } + public var Conversation_InstantPagePreview: String { return self._s[2034]! } public func DialogList_SingleUploadingVideoSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2034]!, self._r[2034]!, [_0]) + return formatWithArgumentRanges(self._s[2035]!, self._r[2035]!, [_0]) } - public var SecretTimer_VideoDescription: String { return self._s[2037]! } - public var Passport_Language_es: String { return self._s[2038]! } - public var Permissions_ContactsAllow_v0: String { return self._s[2040]! } - public var Conversation_EditingMessageMediaEditCurrentVideo: String { return self._s[2041]! } - public var WebPreview_GettingLinkInfo: String { return self._s[2042]! } - public var Watch_UserInfo_Unmute: String { return self._s[2043]! } - public var GroupInfo_ChannelListNamePlaceholder: String { return self._s[2044]! } - public var AccessDenied_CameraRestricted: String { return self._s[2046]! } + public var SecretTimer_VideoDescription: String { return self._s[2038]! } + public var Passport_Language_es: String { return self._s[2039]! } + public var Permissions_ContactsAllow_v0: String { return self._s[2041]! } + public var Conversation_EditingMessageMediaEditCurrentVideo: String { return self._s[2042]! } + public var WebPreview_GettingLinkInfo: String { return self._s[2043]! } + public var Watch_UserInfo_Unmute: String { return self._s[2044]! } + public var GroupInfo_ChannelListNamePlaceholder: String { return self._s[2045]! } + public var AccessDenied_CameraRestricted: String { return self._s[2047]! } public func Conversation_Kilobytes(_ _0: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2047]!, self._r[2047]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[2048]!, self._r[2048]!, ["\(_0)"]) } - public var ChatList_ReadAll: String { return self._s[2049]! } - public var Settings_CopyUsername: String { return self._s[2050]! } - public var Contacts_SearchLabel: String { return self._s[2051]! } + public var ChatList_ReadAll: String { return self._s[2050]! } + public var Settings_CopyUsername: String { return self._s[2051]! } + public var Contacts_SearchLabel: String { return self._s[2052]! } public func MESSAGE_GEOLIVE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2053]!, self._r[2053]!, [_1]) + return formatWithArgumentRanges(self._s[2054]!, self._r[2054]!, [_1]) } - public var Map_OpenInYandexNavigator: String { return self._s[2054]! } - public var PasscodeSettings_EncryptData: String { return self._s[2055]! } - public var Notifications_GroupNotificationsPreview: String { return self._s[2056]! } - public var DialogList_AdNoticeAlert: String { return self._s[2057]! } + public var Map_OpenInYandexNavigator: String { return self._s[2055]! } + public var PasscodeSettings_EncryptData: String { return self._s[2056]! } + public var Notifications_GroupNotificationsPreview: String { return self._s[2057]! } + public var DialogList_AdNoticeAlert: String { return self._s[2058]! } public func CHAT_DELETE_MEMBER(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2059]!, self._r[2059]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2060]!, self._r[2060]!, [_1, _2, _3]) } - public var CheckoutInfo_ShippingInfoAddress1: String { return self._s[2060]! } - public var CheckoutInfo_ShippingInfoAddress2: String { return self._s[2061]! } - public var Localization_LanguageCustom: String { return self._s[2062]! } - public var Passport_Identity_TypeDriversLicenseUploadScan: String { return self._s[2063]! } + public var CheckoutInfo_ShippingInfoAddress1: String { return self._s[2061]! } + public var CheckoutInfo_ShippingInfoAddress2: String { return self._s[2062]! } + public var Localization_LanguageCustom: String { return self._s[2063]! } + public var Passport_Identity_TypeDriversLicenseUploadScan: String { return self._s[2064]! } public func CHAT_CREATED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2065]!, self._r[2065]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2066]!, self._r[2066]!, [_1, _2]) } - public var Passport_Address_OneOfTypePassportRegistration: String { return self._s[2067]! } - public var Conversation_InfoGroup: String { return self._s[2068]! } - public var Compose_NewMessage: String { return self._s[2069]! } - public var FastTwoStepSetup_HintPlaceholder: String { return self._s[2070]! } - public var ChatSettings_AutoDownloadVideoMessages: String { return self._s[2071]! } + public var Passport_Address_OneOfTypePassportRegistration: String { return self._s[2068]! } + public var Conversation_InfoGroup: String { return self._s[2069]! } + public var Compose_NewMessage: String { return self._s[2070]! } + public var FastTwoStepSetup_HintPlaceholder: String { return self._s[2071]! } + public var ChatSettings_AutoDownloadVideoMessages: String { return self._s[2072]! } public func Passport_Scans_ScanIndex(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2072]!, self._r[2072]!, [_0]) + return formatWithArgumentRanges(self._s[2073]!, self._r[2073]!, [_0]) } - public var Channel_AdminLog_CanDeleteMessages: String { return self._s[2073]! } - public var Login_CancelSignUpConfirmation: String { return self._s[2074]! } - public var ChangePhoneNumberCode_Help: String { return self._s[2075]! } - public var PrivacySettings_DeleteAccountHelp: String { return self._s[2076]! } - public var Channel_BlackList_Title: String { return self._s[2077]! } - public var UserInfo_PhoneCall: String { return self._s[2078]! } - public var Passport_Address_OneOfTypeBankStatement: String { return self._s[2080]! } - public var State_connecting: String { return self._s[2081]! } + public var Channel_AdminLog_CanDeleteMessages: String { return self._s[2074]! } + public var Login_CancelSignUpConfirmation: String { return self._s[2075]! } + public var ChangePhoneNumberCode_Help: String { return self._s[2076]! } + public var PrivacySettings_DeleteAccountHelp: String { return self._s[2077]! } + public var Channel_BlackList_Title: String { return self._s[2078]! } + public var UserInfo_PhoneCall: String { return self._s[2079]! } + public var Passport_Address_OneOfTypeBankStatement: String { return self._s[2081]! } + public var State_connecting: String { return self._s[2082]! } public func DialogList_SingleRecordingAudioSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2082]!, self._r[2082]!, [_0]) + return formatWithArgumentRanges(self._s[2083]!, self._r[2083]!, [_0]) } - public var Notifications_GroupNotifications: String { return self._s[2083]! } - public var Passport_Identity_EditPassport: String { return self._s[2084]! } - public var EnterPasscode_RepeatNewPasscode: String { return self._s[2086]! } - public var Localization_EnglishLanguageName: String { return self._s[2087]! } - public var Share_AuthDescription: String { return self._s[2088]! } - public var Passport_Identity_Surname: String { return self._s[2089]! } - public var Compose_TokenListPlaceholder: String { return self._s[2090]! } - public var Passport_Identity_OneOfTypePassport: String { return self._s[2091]! } - public var Settings_AboutEmpty: String { return self._s[2092]! } - public var Conversation_Unmute: String { return self._s[2093]! } - public var Login_CodeSentCall: String { return self._s[2096]! } - public var ContactInfo_PhoneLabelHomeFax: String { return self._s[2097]! } - public var ChatSettings_Appearance: String { return self._s[2098]! } - public var Appearance_PickAccentColor: String { return self._s[2099]! } - public var Notification_CallMissed: String { return self._s[2100]! } - public var Channel_AdminLogFilter_EventsInfo: String { return self._s[2101]! } - public var ChatAdmins_AdminLabel: String { return self._s[2103]! } - public var KeyCommand_JumpToNextChat: String { return self._s[2104]! } - public var Conversation_StopPollConfirmationTitle: String { return self._s[2106]! } - public var ChangePhoneNumberCode_CodePlaceholder: String { return self._s[2107]! } - public var Month_GenJune: String { return self._s[2108]! } - public var Watch_Location_Current: String { return self._s[2109]! } - public var Conversation_TitleMute: String { return self._s[2110]! } + public var Notifications_GroupNotifications: String { return self._s[2084]! } + public var Passport_Identity_EditPassport: String { return self._s[2085]! } + public var EnterPasscode_RepeatNewPasscode: String { return self._s[2087]! } + public var Localization_EnglishLanguageName: String { return self._s[2088]! } + public var Share_AuthDescription: String { return self._s[2089]! } + public var Passport_Identity_Surname: String { return self._s[2090]! } + public var Compose_TokenListPlaceholder: String { return self._s[2091]! } + public var Passport_Identity_OneOfTypePassport: String { return self._s[2092]! } + public var Settings_AboutEmpty: String { return self._s[2093]! } + public var Conversation_Unmute: String { return self._s[2094]! } + public var Login_CodeSentCall: String { return self._s[2097]! } + public var ContactInfo_PhoneLabelHomeFax: String { return self._s[2098]! } + public var ChatSettings_Appearance: String { return self._s[2099]! } + public var Appearance_PickAccentColor: String { return self._s[2100]! } + public var Notification_CallMissed: String { return self._s[2101]! } + public var Channel_AdminLogFilter_EventsInfo: String { return self._s[2102]! } + public var ChatAdmins_AdminLabel: String { return self._s[2104]! } + public var KeyCommand_JumpToNextChat: String { return self._s[2105]! } + public var Conversation_StopPollConfirmationTitle: String { return self._s[2107]! } + public var ChangePhoneNumberCode_CodePlaceholder: String { return self._s[2108]! } + public var Month_GenJune: String { return self._s[2109]! } + public var Watch_Location_Current: String { return self._s[2110]! } + public var Conversation_TitleMute: String { return self._s[2111]! } public func PINNED_ROUND(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2111]!, self._r[2111]!, [_1]) + return formatWithArgumentRanges(self._s[2112]!, self._r[2112]!, [_1]) } - public var GroupInfo_DeleteAndExit: String { return self._s[2112]! } + public var GroupInfo_DeleteAndExit: String { return self._s[2113]! } public func Conversation_Moderate_DeleteAllMessages(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2113]!, self._r[2113]!, [_0]) + return formatWithArgumentRanges(self._s[2114]!, self._r[2114]!, [_0]) } - public var Call_ReportPlaceholder: String { return self._s[2114]! } - public var MaskStickerSettings_Info: String { return self._s[2115]! } + public var Call_ReportPlaceholder: String { return self._s[2115]! } + public var MaskStickerSettings_Info: String { return self._s[2116]! } public func GroupInfo_AddParticipantConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2116]!, self._r[2116]!, [_0]) + return formatWithArgumentRanges(self._s[2117]!, self._r[2117]!, [_0]) } - public var Checkout_NewCard_PostcodeTitle: String { return self._s[2117]! } - public var Passport_Address_RegionPlaceholder: String { return self._s[2119]! } - public var Contacts_ShareTelegram: String { return self._s[2120]! } - public var EnterPasscode_EnterNewPasscodeNew: String { return self._s[2121]! } - public var Channel_ErrorAccessDenied: String { return self._s[2122]! } - public var Stickers_GroupChooseStickerPack: String { return self._s[2124]! } - public var Call_ConnectionErrorTitle: String { return self._s[2125]! } - public var UserInfo_NotificationsEnable: String { return self._s[2126]! } - public var Tour_Text4: String { return self._s[2129]! } + public var Checkout_NewCard_PostcodeTitle: String { return self._s[2118]! } + public var Passport_Address_RegionPlaceholder: String { return self._s[2120]! } + public var Contacts_ShareTelegram: String { return self._s[2121]! } + public var EnterPasscode_EnterNewPasscodeNew: String { return self._s[2122]! } + public var Channel_ErrorAccessDenied: String { return self._s[2123]! } + public var Stickers_GroupChooseStickerPack: String { return self._s[2125]! } + public var Call_ConnectionErrorTitle: String { return self._s[2126]! } + public var UserInfo_NotificationsEnable: String { return self._s[2127]! } + public var Tour_Text4: String { return self._s[2130]! } public func CHANNEL_MESSAGE_NOTEXT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2131]!, self._r[2131]!, [_1]) + return formatWithArgumentRanges(self._s[2132]!, self._r[2132]!, [_1]) } - public var Profile_MessageLifetime2s: String { return self._s[2132]! } - public var Notification_MessageLifetime2s: String { return self._s[2133]! } + public var Profile_MessageLifetime2s: String { return self._s[2133]! } + public var Notification_MessageLifetime2s: String { return self._s[2134]! } public func Time_PreciseDate_m10(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2134]!, self._r[2134]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2135]!, self._r[2135]!, [_1, _2, _3]) } - public var Cache_ClearCache: String { return self._s[2135]! } - public var AutoNightTheme_UpdateLocation: String { return self._s[2136]! } - public var Permissions_NotificationsUnreachableText_v0: String { return self._s[2137]! } + public var Cache_ClearCache: String { return self._s[2136]! } + public var AutoNightTheme_UpdateLocation: String { return self._s[2137]! } + public var Permissions_NotificationsUnreachableText_v0: String { return self._s[2138]! } public func Channel_AdminLog_MessageChangedGroupUsername(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2139]!, self._r[2139]!, [_0]) + return formatWithArgumentRanges(self._s[2140]!, self._r[2140]!, [_0]) } - public var Channel_AdminLog_EmptyFilterTitle: String { return self._s[2141]! } - public var SocksProxySetup_TypeSocks: String { return self._s[2142]! } - public var AutoNightTheme_Title: String { return self._s[2143]! } - public var InstantPage_FeedbackButton: String { return self._s[2144]! } - public var Passport_FieldAddress: String { return self._s[2145]! } - public var Month_ShortMarch: String { return self._s[2146]! } - public var SocksProxySetup_UsernamePlaceholder: String { return self._s[2147]! } - public var Conversation_ShareInlineBotLocationConfirmation: String { return self._s[2148]! } - public var Passport_FloodError: String { return self._s[2149]! } - public var SecretGif_Title: String { return self._s[2150]! } - public var Passport_Language_th: String { return self._s[2152]! } - public var Passport_Address_Address: String { return self._s[2153]! } - public var Login_InvalidLastNameError: String { return self._s[2154]! } - public var Notifications_InAppNotificationsPreview: String { return self._s[2155]! } - public var Notifications_PermissionsUnreachableTitle: String { return self._s[2156]! } - public var ShareMenu_Send: String { return self._s[2157]! } - public var Month_GenNovember: String { return self._s[2160]! } - public var Checkout_Email: String { return self._s[2162]! } - public var NotificationsSound_Tritone: String { return self._s[2163]! } - public var StickerPacksSettings_ManagingHelp: String { return self._s[2165]! } - public var ChangePhoneNumberNumber_Help: String { return self._s[2168]! } + public var Channel_AdminLog_EmptyFilterTitle: String { return self._s[2142]! } + public var SocksProxySetup_TypeSocks: String { return self._s[2143]! } + public var AutoNightTheme_Title: String { return self._s[2144]! } + public var InstantPage_FeedbackButton: String { return self._s[2145]! } + public var Passport_FieldAddress: String { return self._s[2146]! } + public var Month_ShortMarch: String { return self._s[2147]! } + public var SocksProxySetup_UsernamePlaceholder: String { return self._s[2148]! } + public var Conversation_ShareInlineBotLocationConfirmation: String { return self._s[2149]! } + public var Passport_FloodError: String { return self._s[2150]! } + public var SecretGif_Title: String { return self._s[2151]! } + public var Passport_Language_th: String { return self._s[2153]! } + public var Passport_Address_Address: String { return self._s[2154]! } + public var Login_InvalidLastNameError: String { return self._s[2155]! } + public var Notifications_InAppNotificationsPreview: String { return self._s[2156]! } + public var Notifications_PermissionsUnreachableTitle: String { return self._s[2157]! } + public var ShareMenu_Send: String { return self._s[2158]! } + public var Month_GenNovember: String { return self._s[2161]! } + public var Checkout_Email: String { return self._s[2163]! } + public var NotificationsSound_Tritone: String { return self._s[2164]! } + public var StickerPacksSettings_ManagingHelp: String { return self._s[2166]! } + public var ChangePhoneNumberNumber_Help: String { return self._s[2169]! } public func Checkout_LiabilityAlert(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2169]!, self._r[2169]!, [_1, _1, _1, _2]) + return formatWithArgumentRanges(self._s[2170]!, self._r[2170]!, [_1, _1, _1, _2]) } - public var DialogList_You: String { return self._s[2170]! } - public var MediaPicker_Send: String { return self._s[2173]! } - public var Call_AudioRouteSpeaker: String { return self._s[2174]! } - public var Watch_UserInfo_Title: String { return self._s[2175]! } - public var Appearance_AccentColor: String { return self._s[2176]! } + public var DialogList_You: String { return self._s[2171]! } + public var MediaPicker_Send: String { return self._s[2174]! } + public var Call_AudioRouteSpeaker: String { return self._s[2175]! } + public var Watch_UserInfo_Title: String { return self._s[2176]! } + public var Appearance_AccentColor: String { return self._s[2177]! } public func Login_EmailPhoneSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2177]!, self._r[2177]!, [_0]) + return formatWithArgumentRanges(self._s[2178]!, self._r[2178]!, [_0]) } - public var Permissions_ContactsAllowInSettings_v0: String { return self._s[2178]! } - public var Conversation_ClousStorageInfo_Description2: String { return self._s[2179]! } - public var WebSearch_RecentClearConfirmation: String { return self._s[2180]! } - public var Notification_CallOutgoing: String { return self._s[2181]! } - public var PrivacySettings_PasscodeAndFaceId: String { return self._s[2182]! } - public var Call_RecordingDisabledMessage: String { return self._s[2183]! } - public var PrivacyLastSeenSettings_CustomHelp: String { return self._s[2184]! } - public var Channel_EditAdmin_PermissionAddAdmins: String { return self._s[2185]! } - public var Date_DialogDateFormat: String { return self._s[2186]! } - public var Notifications_InAppNotifications: String { return self._s[2187]! } + public var Permissions_ContactsAllowInSettings_v0: String { return self._s[2179]! } + public var Conversation_ClousStorageInfo_Description2: String { return self._s[2180]! } + public var WebSearch_RecentClearConfirmation: String { return self._s[2181]! } + public var Notification_CallOutgoing: String { return self._s[2182]! } + public var PrivacySettings_PasscodeAndFaceId: String { return self._s[2183]! } + public var Call_RecordingDisabledMessage: String { return self._s[2184]! } + public var PrivacyLastSeenSettings_CustomHelp: String { return self._s[2185]! } + public var Channel_EditAdmin_PermissionAddAdmins: String { return self._s[2186]! } + public var Date_DialogDateFormat: String { return self._s[2187]! } + public var Notifications_InAppNotifications: String { return self._s[2188]! } public func Settings_ApplyProxyAlert(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2188]!, self._r[2188]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2189]!, self._r[2189]!, [_1, _2]) } - public var NewContact_Title: String { return self._s[2189]! } - public var Conversation_ViewContactDetails: String { return self._s[2190]! } - public var Checkout_NewCard_CardholderNameTitle: String { return self._s[2192]! } - public var Passport_Identity_ExpiryDateNone: String { return self._s[2193]! } - public var PrivacySettings_Title: String { return self._s[2194]! } - public var Conversation_SilentBroadcastTooltipOff: String { return self._s[2197]! } + public var NewContact_Title: String { return self._s[2190]! } + public var Conversation_ViewContactDetails: String { return self._s[2191]! } + public var Checkout_NewCard_CardholderNameTitle: String { return self._s[2193]! } + public var Passport_Identity_ExpiryDateNone: String { return self._s[2194]! } + public var PrivacySettings_Title: String { return self._s[2195]! } + public var Conversation_SilentBroadcastTooltipOff: String { return self._s[2198]! } public func CHANNEL_MESSAGE_CONTACT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2198]!, self._r[2198]!, [_1]) + return formatWithArgumentRanges(self._s[2199]!, self._r[2199]!, [_1]) } - public var Contacts_PhoneNumber: String { return self._s[2199]! } - public var Map_ShowPlaces: String { return self._s[2201]! } - public var ChatAdmins_Title: String { return self._s[2202]! } - public var InstantPage_Reference: String { return self._s[2204]! } - public var Camera_FlashOff: String { return self._s[2205]! } - public var Watch_UserInfo_Block: String { return self._s[2206]! } - public var ChatSettings_Stickers: String { return self._s[2207]! } - public var ChatSettings_DownloadInBackground: String { return self._s[2208]! } + public var Contacts_PhoneNumber: String { return self._s[2200]! } + public var Map_ShowPlaces: String { return self._s[2202]! } + public var ChatAdmins_Title: String { return self._s[2203]! } + public var InstantPage_Reference: String { return self._s[2205]! } + public var Camera_FlashOff: String { return self._s[2206]! } + public var Watch_UserInfo_Block: String { return self._s[2207]! } + public var ChatSettings_Stickers: String { return self._s[2208]! } + public var ChatSettings_DownloadInBackground: String { return self._s[2209]! } public func UserInfo_BlockConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2209]!, self._r[2209]!, [_0]) + return formatWithArgumentRanges(self._s[2210]!, self._r[2210]!, [_0]) } - public var Login_CheckOtherSessionMessages: String { return self._s[2210]! } - public var Settings_ViewPhoto: String { return self._s[2211]! } - public var AutoDownloadSettings_Cellular: String { return self._s[2212]! } + public var Login_CheckOtherSessionMessages: String { return self._s[2211]! } + public var Settings_ViewPhoto: String { return self._s[2212]! } + public var AutoDownloadSettings_Cellular: String { return self._s[2213]! } public func Target_InviteToGroupConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2214]!, self._r[2214]!, [_0]) + return formatWithArgumentRanges(self._s[2215]!, self._r[2215]!, [_0]) } - public var Privacy_DeleteDrafts: String { return self._s[2215]! } + public var Privacy_DeleteDrafts: String { return self._s[2216]! } public func LastSeen_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2216]!, self._r[2216]!, [_0]) + return formatWithArgumentRanges(self._s[2217]!, self._r[2217]!, [_0]) } - public var DialogList_SavedMessagesHelp: String { return self._s[2217]! } - public var DialogList_SavedMessages: String { return self._s[2218]! } - public var GroupInfo_UpgradeButton: String { return self._s[2219]! } + public var DialogList_SavedMessagesHelp: String { return self._s[2218]! } + public var DialogList_SavedMessages: String { return self._s[2219]! } + public var GroupInfo_UpgradeButton: String { return self._s[2220]! } public func CHAT_MESSAGE_GAME(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2220]!, self._r[2220]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2221]!, self._r[2221]!, [_1, _2, _3]) } - public var DialogList_Pin: String { return self._s[2221]! } + public var DialogList_Pin: String { return self._s[2222]! } public func ForwardedAuthors2(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2222]!, self._r[2222]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2223]!, self._r[2223]!, [_0, _1]) } public func Login_PhoneGenericEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2223]!, self._r[2223]!, [_0]) + return formatWithArgumentRanges(self._s[2224]!, self._r[2224]!, [_0]) } - public var Notification_Exceptions_AlwaysOn: String { return self._s[2224]! } - public var UserInfo_NotificationsDisable: String { return self._s[2225]! } - public var Paint_Outlined: String { return self._s[2226]! } - public var Activity_PlayingGame: String { return self._s[2227]! } - public var SearchImages_NoImagesFound: String { return self._s[2228]! } - public var SocksProxySetup_ProxyType: String { return self._s[2229]! } - public var AppleWatch_ReplyPresetsHelp: String { return self._s[2231]! } - public var Settings_AppLanguage: String { return self._s[2232]! } - public var TwoStepAuth_ResetAccountHelp: String { return self._s[2233]! } - public var Common_ChoosePhoto: String { return self._s[2234]! } - public var Privacy_Calls_AlwaysAllow: String { return self._s[2235]! } - public var Activity_UploadingVideo: String { return self._s[2236]! } - public var ChannelInfo_DeleteChannelConfirmation: String { return self._s[2237]! } - public var NetworkUsageSettings_Wifi: String { return self._s[2238]! } - public var Channel_BanUser_PermissionReadMessages: String { return self._s[2239]! } - public var Checkout_PayWithTouchId: String { return self._s[2240]! } - public var Notifications_ExceptionsNone: String { return self._s[2242]! } + public var Notification_Exceptions_AlwaysOn: String { return self._s[2225]! } + public var UserInfo_NotificationsDisable: String { return self._s[2226]! } + public var Paint_Outlined: String { return self._s[2227]! } + public var Activity_PlayingGame: String { return self._s[2228]! } + public var SearchImages_NoImagesFound: String { return self._s[2229]! } + public var SocksProxySetup_ProxyType: String { return self._s[2230]! } + public var AppleWatch_ReplyPresetsHelp: String { return self._s[2232]! } + public var Settings_AppLanguage: String { return self._s[2233]! } + public var TwoStepAuth_ResetAccountHelp: String { return self._s[2234]! } + public var Common_ChoosePhoto: String { return self._s[2235]! } + public var Privacy_Calls_AlwaysAllow: String { return self._s[2236]! } + public var Activity_UploadingVideo: String { return self._s[2237]! } + public var ChannelInfo_DeleteChannelConfirmation: String { return self._s[2238]! } + public var NetworkUsageSettings_Wifi: String { return self._s[2239]! } + public var Channel_BanUser_PermissionReadMessages: String { return self._s[2240]! } + public var Checkout_PayWithTouchId: String { return self._s[2241]! } + public var Notifications_ExceptionsNone: String { return self._s[2243]! } public func Message_ForwardedMessageShort(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2243]!, self._r[2243]!, [_0]) + return formatWithArgumentRanges(self._s[2244]!, self._r[2244]!, [_0]) } - public var AuthSessions_IncompleteAttempts: String { return self._s[2244]! } - public var Passport_Address_Region: String { return self._s[2248]! } - public var PhotoEditor_TiltShift: String { return self._s[2249]! } - public var Settings_FAQ_URL: String { return self._s[2250]! } - public var Passport_Language_sl: String { return self._s[2251]! } - public var Settings_PrivacySettings: String { return self._s[2253]! } - public var SharedMedia_TitleLink: String { return self._s[2254]! } - public var Passport_Identity_TypePassportUploadScan: String { return self._s[2255]! } - public var Settings_SetProfilePhoto: String { return self._s[2256]! } - public var Channel_About_Help: String { return self._s[2257]! } - public var Contacts_PermissionsEnable: String { return self._s[2258]! } - public var AttachmentMenu_SendAsFiles: String { return self._s[2259]! } - public var Passport_Address_AddTemporaryRegistration: String { return self._s[2261]! } - public var PrivacySettings_DeleteAccountTitle: String { return self._s[2262]! } - public var AccessDenied_VideoMessageCamera: String { return self._s[2264]! } - public var Map_OpenInYandexMaps: String { return self._s[2266]! } - public var PhotoEditor_SaturationTool: String { return self._s[2267]! } - public var Notification_Exceptions_NewException_NotificationHeader: String { return self._s[2268]! } - public var Appearance_TextSize: String { return self._s[2269]! } - public var Channel_Username_InvalidTooShort: String { return self._s[2271]! } - public var Passport_PassportInformation: String { return self._s[2274]! } - public var WatchRemote_AlertTitle: String { return self._s[2275]! } - public var Privacy_GroupsAndChannels_NeverAllow: String { return self._s[2276]! } - public var ConvertToSupergroup_HelpText: String { return self._s[2278]! } + public var AuthSessions_IncompleteAttempts: String { return self._s[2245]! } + public var Passport_Address_Region: String { return self._s[2249]! } + public var PhotoEditor_TiltShift: String { return self._s[2250]! } + public var Settings_FAQ_URL: String { return self._s[2251]! } + public var Passport_Language_sl: String { return self._s[2252]! } + public var Settings_PrivacySettings: String { return self._s[2254]! } + public var SharedMedia_TitleLink: String { return self._s[2255]! } + public var Passport_Identity_TypePassportUploadScan: String { return self._s[2256]! } + public var Settings_SetProfilePhoto: String { return self._s[2257]! } + public var Channel_About_Help: String { return self._s[2258]! } + public var Contacts_PermissionsEnable: String { return self._s[2259]! } + public var AttachmentMenu_SendAsFiles: String { return self._s[2260]! } + public var Passport_Address_AddTemporaryRegistration: String { return self._s[2262]! } + public var PrivacySettings_DeleteAccountTitle: String { return self._s[2263]! } + public var AccessDenied_VideoMessageCamera: String { return self._s[2265]! } + public var Map_OpenInYandexMaps: String { return self._s[2267]! } + public var PhotoEditor_SaturationTool: String { return self._s[2268]! } + public var Notification_Exceptions_NewException_NotificationHeader: String { return self._s[2269]! } + public var Appearance_TextSize: String { return self._s[2270]! } + public var Channel_Username_InvalidTooShort: String { return self._s[2272]! } + public var Passport_PassportInformation: String { return self._s[2275]! } + public var WatchRemote_AlertTitle: String { return self._s[2276]! } + public var Privacy_GroupsAndChannels_NeverAllow: String { return self._s[2277]! } + public var ConvertToSupergroup_HelpText: String { return self._s[2279]! } public func Time_MonthOfYear_m7(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2279]!, self._r[2279]!, [_0]) + return formatWithArgumentRanges(self._s[2280]!, self._r[2280]!, [_0]) } - public var Privacy_GroupsAndChannels_CustomHelp: String { return self._s[2280]! } - public var TwoStepAuth_RecoveryCodeInvalid: String { return self._s[2282]! } - public var AccessDenied_CameraDisabled: String { return self._s[2283]! } + public var Privacy_GroupsAndChannels_CustomHelp: String { return self._s[2281]! } + public var TwoStepAuth_RecoveryCodeInvalid: String { return self._s[2283]! } + public var AccessDenied_CameraDisabled: String { return self._s[2284]! } public func Channel_Username_UsernameIsAvailable(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2284]!, self._r[2284]!, [_0]) + return formatWithArgumentRanges(self._s[2285]!, self._r[2285]!, [_0]) } - public var PhotoEditor_ContrastTool: String { return self._s[2287]! } - public var DialogList_Draft: String { return self._s[2288]! } - public var Privacy_TopPeersDelete: String { return self._s[2290]! } - public var LoginPassword_PasswordPlaceholder: String { return self._s[2291]! } - public var Passport_Identity_TypeIdentityCardUploadScan: String { return self._s[2292]! } - public var WebSearch_RecentSectionClear: String { return self._s[2293]! } - public var Watch_ChatList_NoConversationsTitle: String { return self._s[2295]! } - public var Common_Done: String { return self._s[2296]! } - public var AuthSessions_EmptyText: String { return self._s[2297]! } - public var Conversation_ShareBotContactConfirmation: String { return self._s[2298]! } - public var Tour_Title5: String { return self._s[2299]! } + public var PhotoEditor_ContrastTool: String { return self._s[2288]! } + public var DialogList_Draft: String { return self._s[2289]! } + public var Privacy_TopPeersDelete: String { return self._s[2291]! } + public var LoginPassword_PasswordPlaceholder: String { return self._s[2292]! } + public var Passport_Identity_TypeIdentityCardUploadScan: String { return self._s[2293]! } + public var WebSearch_RecentSectionClear: String { return self._s[2294]! } + public var Watch_ChatList_NoConversationsTitle: String { return self._s[2296]! } + public var Common_Done: String { return self._s[2297]! } + public var AuthSessions_EmptyText: String { return self._s[2298]! } + public var Conversation_ShareBotContactConfirmation: String { return self._s[2299]! } + public var Tour_Title5: String { return self._s[2300]! } public func Map_DirectionsDriveEta(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2300]!, self._r[2300]!, [_0]) + return formatWithArgumentRanges(self._s[2301]!, self._r[2301]!, [_0]) } - public var ApplyLanguage_UnsufficientDataTitle: String { return self._s[2301]! } - public var Conversation_LinkDialogSave: String { return self._s[2302]! } - public var GroupInfo_ActionRestrict: String { return self._s[2303]! } - public var Checkout_Title: String { return self._s[2304]! } - public var Channel_AdminLog_CanChangeInfo: String { return self._s[2307]! } - public var Notification_RenamedGroup: String { return self._s[2308]! } - public var Checkout_PayWithFaceId: String { return self._s[2309]! } - public var Channel_BanList_BlockedTitle: String { return self._s[2310]! } - public var Checkout_WebConfirmation_Title: String { return self._s[2312]! } - public var Notifications_MessageNotificationsAlert: String { return self._s[2313]! } - public var Profile_AddToExisting: String { return self._s[2315]! } + public var ApplyLanguage_UnsufficientDataTitle: String { return self._s[2302]! } + public var Conversation_LinkDialogSave: String { return self._s[2303]! } + public var GroupInfo_ActionRestrict: String { return self._s[2304]! } + public var Checkout_Title: String { return self._s[2305]! } + public var Channel_AdminLog_CanChangeInfo: String { return self._s[2308]! } + public var Notification_RenamedGroup: String { return self._s[2309]! } + public var Checkout_PayWithFaceId: String { return self._s[2310]! } + public var Channel_BanList_BlockedTitle: String { return self._s[2311]! } + public var Checkout_WebConfirmation_Title: String { return self._s[2313]! } + public var Notifications_MessageNotificationsAlert: String { return self._s[2314]! } + public var Profile_AddToExisting: String { return self._s[2316]! } public func Profile_CreateEncryptedChatOutdatedError(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2316]!, self._r[2316]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2317]!, self._r[2317]!, [_0, _1]) } - public var Cache_Files: String { return self._s[2318]! } - public var Permissions_PrivacyPolicy: String { return self._s[2319]! } - public var SocksProxySetup_ConnectAndSave: String { return self._s[2320]! } - public var UserInfo_NotificationsDefaultDisabled: String { return self._s[2321]! } + public var Cache_Files: String { return self._s[2319]! } + public var Permissions_PrivacyPolicy: String { return self._s[2320]! } + public var SocksProxySetup_ConnectAndSave: String { return self._s[2321]! } + public var UserInfo_NotificationsDefaultDisabled: String { return self._s[2322]! } public func MESSAGE_POLL(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2323]!, self._r[2323]!, [_1]) + return formatWithArgumentRanges(self._s[2324]!, self._r[2324]!, [_1]) } - public var Calls_NoCallsPlaceholder: String { return self._s[2325]! } - public var Channel_Username_RevokeExistingUsernamesInfo: String { return self._s[2326]! } - public var Notifications_ExceptionsGroupPlaceholder: String { return self._s[2328]! } - public var Passport_FieldAddressHelp: String { return self._s[2329]! } - public var Privacy_GroupsAndChannels_InviteToChannelMultipleError: String { return self._s[2330]! } + public var Calls_NoCallsPlaceholder: String { return self._s[2326]! } + public var Channel_Username_RevokeExistingUsernamesInfo: String { return self._s[2327]! } + public var Notifications_ExceptionsGroupPlaceholder: String { return self._s[2329]! } + public var Passport_FieldAddressHelp: String { return self._s[2330]! } + public var Privacy_GroupsAndChannels_InviteToChannelMultipleError: String { return self._s[2331]! } public func Login_TermsOfService_ProceedBot(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2331]!, self._r[2331]!, [_0]) + return formatWithArgumentRanges(self._s[2332]!, self._r[2332]!, [_0]) } - public var Channel_AdminLog_EmptyTitle: String { return self._s[2332]! } - public var Privacy_Calls_NeverAllow_Title: String { return self._s[2334]! } - public var Login_UnknownError: String { return self._s[2335]! } - public var Group_UpgradeNoticeText2: String { return self._s[2337]! } - public var Watch_Compose_AddContact: String { return self._s[2338]! } - public var Web_Error: String { return self._s[2339]! } - public var Profile_MessageLifetime1h: String { return self._s[2340]! } - public var CheckoutInfo_ReceiverInfoEmailPlaceholder: String { return self._s[2341]! } - public var Channel_Username_CheckingUsername: String { return self._s[2342]! } + public var Channel_AdminLog_EmptyTitle: String { return self._s[2333]! } + public var Privacy_Calls_NeverAllow_Title: String { return self._s[2335]! } + public var Login_UnknownError: String { return self._s[2336]! } + public var Group_UpgradeNoticeText2: String { return self._s[2338]! } + public var Watch_Compose_AddContact: String { return self._s[2339]! } + public var Web_Error: String { return self._s[2340]! } + public var Profile_MessageLifetime1h: String { return self._s[2341]! } + public var CheckoutInfo_ReceiverInfoEmailPlaceholder: String { return self._s[2342]! } + public var Channel_Username_CheckingUsername: String { return self._s[2343]! } public func PINNED_GAME(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2343]!, self._r[2343]!, [_1]) + return formatWithArgumentRanges(self._s[2344]!, self._r[2344]!, [_1]) } - public var Channel_AboutItem: String { return self._s[2344]! } - public var Privacy_GroupsAndChannels_AlwaysAllow_Placeholder: String { return self._s[2346]! } - public var GroupInfo_SharedMedia: String { return self._s[2347]! } + public var Channel_AboutItem: String { return self._s[2345]! } + public var Privacy_GroupsAndChannels_AlwaysAllow_Placeholder: String { return self._s[2347]! } + public var GroupInfo_SharedMedia: String { return self._s[2348]! } public func Channel_AdminLog_MessagePromotedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2348]!, self._r[2348]!, [_1]) + return formatWithArgumentRanges(self._s[2349]!, self._r[2349]!, [_1]) } - public var Call_PhoneCallInProgressMessage: String { return self._s[2349]! } - public var GroupInfo_InviteLink_RevokeAlert_Text: String { return self._s[2350]! } - public var Conversation_SearchByName_Placeholder: String { return self._s[2351]! } - public var CreatePoll_AddOption: String { return self._s[2352]! } - public var Group_UpgradeNoticeHeader: String { return self._s[2353]! } - public var Channel_Management_AddModerator: String { return self._s[2354]! } - public var StickerPacksSettings_ShowStickersButton: String { return self._s[2355]! } - public var NotificationsSound_Hello: String { return self._s[2356]! } + public var Call_PhoneCallInProgressMessage: String { return self._s[2350]! } + public var GroupInfo_InviteLink_RevokeAlert_Text: String { return self._s[2351]! } + public var Conversation_SearchByName_Placeholder: String { return self._s[2352]! } + public var CreatePoll_AddOption: String { return self._s[2353]! } + public var Group_UpgradeNoticeHeader: String { return self._s[2354]! } + public var Channel_Management_AddModerator: String { return self._s[2355]! } + public var StickerPacksSettings_ShowStickersButton: String { return self._s[2356]! } + public var NotificationsSound_Hello: String { return self._s[2357]! } public func CHAT_MESSAGE_GEO(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2357]!, self._r[2357]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2358]!, self._r[2358]!, [_1, _2]) } - public var SocksProxySetup_SavedProxies: String { return self._s[2358]! } - public var Channel_Stickers_Placeholder: String { return self._s[2360]! } + public var SocksProxySetup_SavedProxies: String { return self._s[2359]! } + public var Channel_Stickers_Placeholder: String { return self._s[2361]! } public func Login_EmailCodeBody(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2361]!, self._r[2361]!, [_0]) + return formatWithArgumentRanges(self._s[2362]!, self._r[2362]!, [_0]) } - public var PrivacyPolicy_DeclineDeclineAndDelete: String { return self._s[2362]! } - public var Channel_Management_AddModeratorHelp: String { return self._s[2363]! } - public var ContactInfo_BirthdayLabel: String { return self._s[2364]! } - public var ChangePhoneNumberCode_RequestingACall: String { return self._s[2365]! } - public var AutoDownloadSettings_Channels: String { return self._s[2366]! } - public var Passport_Language_mn: String { return self._s[2367]! } - public var Notifications_ResetAllNotificationsHelp: String { return self._s[2370]! } - public var Passport_Language_ja: String { return self._s[2372]! } - public var Settings_About_Title: String { return self._s[2373]! } - public var Settings_NotificationsAndSounds: String { return self._s[2374]! } - public var ChannelInfo_DeleteGroup: String { return self._s[2375]! } - public var Settings_BlockedUsers: String { return self._s[2376]! } + public var PrivacyPolicy_DeclineDeclineAndDelete: String { return self._s[2363]! } + public var Channel_Management_AddModeratorHelp: String { return self._s[2364]! } + public var ContactInfo_BirthdayLabel: String { return self._s[2365]! } + public var ChangePhoneNumberCode_RequestingACall: String { return self._s[2366]! } + public var AutoDownloadSettings_Channels: String { return self._s[2367]! } + public var Passport_Language_mn: String { return self._s[2368]! } + public var Notifications_ResetAllNotificationsHelp: String { return self._s[2371]! } + public var Passport_Language_ja: String { return self._s[2373]! } + public var Settings_About_Title: String { return self._s[2374]! } + public var Settings_NotificationsAndSounds: String { return self._s[2375]! } + public var ChannelInfo_DeleteGroup: String { return self._s[2376]! } + public var Settings_BlockedUsers: String { return self._s[2377]! } public func Time_MonthOfYear_m4(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2377]!, self._r[2377]!, [_0]) + return formatWithArgumentRanges(self._s[2378]!, self._r[2378]!, [_0]) } - public var Passport_Address_AddResidentialAddress: String { return self._s[2378]! } - public var Channel_Username_Title: String { return self._s[2379]! } + public var Passport_Address_AddResidentialAddress: String { return self._s[2379]! } + public var Channel_Username_Title: String { return self._s[2380]! } public func Notification_RemovedGroupPhoto(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2380]!, self._r[2380]!, [_0]) + return formatWithArgumentRanges(self._s[2381]!, self._r[2381]!, [_0]) } - public var AttachmentMenu_File: String { return self._s[2382]! } - public var AppleWatch_Title: String { return self._s[2383]! } - public var Activity_RecordingVideoMessage: String { return self._s[2384]! } - public var Weekday_Saturday: String { return self._s[2385]! } - public var Profile_CreateEncryptedChatError: String { return self._s[2386]! } - public var Common_Next: String { return self._s[2388]! } - public var Channel_Stickers_YourStickers: String { return self._s[2390]! } - public var Call_AudioRouteHeadphones: String { return self._s[2391]! } - public var TwoStepAuth_EnterPasswordForgot: String { return self._s[2393]! } - public var Watch_Contacts_NoResults: String { return self._s[2395]! } - public var PhotoEditor_TintTool: String { return self._s[2397]! } - public var LoginPassword_ResetAccount: String { return self._s[2399]! } - public var Settings_SavedMessages: String { return self._s[2400]! } - public var StickerPack_Add: String { return self._s[2401]! } - public var Your_cards_number_is_invalid: String { return self._s[2402]! } - public var Checkout_TotalAmount: String { return self._s[2403]! } + public var AttachmentMenu_File: String { return self._s[2383]! } + public var AppleWatch_Title: String { return self._s[2384]! } + public var Activity_RecordingVideoMessage: String { return self._s[2385]! } + public var Weekday_Saturday: String { return self._s[2386]! } + public var Profile_CreateEncryptedChatError: String { return self._s[2387]! } + public var Common_Next: String { return self._s[2389]! } + public var Channel_Stickers_YourStickers: String { return self._s[2391]! } + public var Call_AudioRouteHeadphones: String { return self._s[2392]! } + public var TwoStepAuth_EnterPasswordForgot: String { return self._s[2394]! } + public var Watch_Contacts_NoResults: String { return self._s[2396]! } + public var PhotoEditor_TintTool: String { return self._s[2398]! } + public var LoginPassword_ResetAccount: String { return self._s[2400]! } + public var Settings_SavedMessages: String { return self._s[2401]! } + public var StickerPack_Add: String { return self._s[2402]! } + public var Your_cards_number_is_invalid: String { return self._s[2403]! } + public var Checkout_TotalAmount: String { return self._s[2404]! } public func ChangePhoneNumberCode_CallTimer(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2404]!, self._r[2404]!, [_0]) + return formatWithArgumentRanges(self._s[2405]!, self._r[2405]!, [_0]) } - public var ChatSettings_ConnectionType_UseSocks5: String { return self._s[2405]! } + public var ChatSettings_ConnectionType_UseSocks5: String { return self._s[2406]! } public func CHANNEL_MESSAGE_STICKER(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2407]!, self._r[2407]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2408]!, self._r[2408]!, [_1, _2]) } public func Conversation_RestrictedTextTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2408]!, self._r[2408]!, [_0]) + return formatWithArgumentRanges(self._s[2409]!, self._r[2409]!, [_0]) } - public var GroupInfo_InviteLink_ShareLink: String { return self._s[2409]! } - public var StickerPack_Share: String { return self._s[2410]! } - public var Passport_DeleteAddress: String { return self._s[2411]! } - public var Settings_Passport: String { return self._s[2412]! } - public var SharedMedia_EmptyFilesText: String { return self._s[2413]! } - public var Conversation_DeleteMessagesForMe: String { return self._s[2414]! } - public var PasscodeSettings_AutoLock_IfAwayFor_1hour: String { return self._s[2415]! } - public var Contacts_PermissionsText: String { return self._s[2416]! } - public var Group_Setup_HistoryVisible: String { return self._s[2417]! } - public var Passport_Address_AddRentalAgreement: String { return self._s[2419]! } - public var SocksProxySetup_Title: String { return self._s[2420]! } - public var Notification_Mute1h: String { return self._s[2421]! } + public var GroupInfo_InviteLink_ShareLink: String { return self._s[2410]! } + public var StickerPack_Share: String { return self._s[2411]! } + public var Passport_DeleteAddress: String { return self._s[2412]! } + public var Settings_Passport: String { return self._s[2413]! } + public var SharedMedia_EmptyFilesText: String { return self._s[2414]! } + public var Conversation_DeleteMessagesForMe: String { return self._s[2415]! } + public var PasscodeSettings_AutoLock_IfAwayFor_1hour: String { return self._s[2416]! } + public var Contacts_PermissionsText: String { return self._s[2417]! } + public var Group_Setup_HistoryVisible: String { return self._s[2418]! } + public var Passport_Address_AddRentalAgreement: String { return self._s[2420]! } + public var SocksProxySetup_Title: String { return self._s[2421]! } + public var Notification_Mute1h: String { return self._s[2422]! } public func Passport_Email_CodeHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2422]!, self._r[2422]!, [_0]) + return formatWithArgumentRanges(self._s[2423]!, self._r[2423]!, [_0]) } - public var FastTwoStepSetup_PasswordSection: String { return self._s[2423]! } - public var NetworkUsageSettings_ResetStatsConfirmation: String { return self._s[2426]! } - public var InfoPlist_NSFaceIDUsageDescription: String { return self._s[2428]! } - public var DialogList_NoMessagesText: String { return self._s[2429]! } - public var Privacy_ContactsResetConfirmation: String { return self._s[2430]! } - public var Privacy_Calls_P2PHelp: String { return self._s[2431]! } - public var Your_cards_expiration_year_is_invalid: String { return self._s[2433]! } - public var Common_TakePhotoOrVideo: String { return self._s[2434]! } - public var Call_StatusBusy: String { return self._s[2435]! } - public var Conversation_PinnedMessage: String { return self._s[2436]! } - public var AutoDownloadSettings_VoiceMessagesTitle: String { return self._s[2437]! } - public var TwoStepAuth_SetupPasswordConfirmFailed: String { return self._s[2438]! } - public var AppleWatch_ReplyPresets: String { return self._s[2439]! } - public var Passport_DiscardMessageDescription: String { return self._s[2441]! } - public var Login_NetworkError: String { return self._s[2442]! } + public var FastTwoStepSetup_PasswordSection: String { return self._s[2424]! } + public var NetworkUsageSettings_ResetStatsConfirmation: String { return self._s[2427]! } + public var InfoPlist_NSFaceIDUsageDescription: String { return self._s[2429]! } + public var DialogList_NoMessagesText: String { return self._s[2430]! } + public var Privacy_ContactsResetConfirmation: String { return self._s[2431]! } + public var Privacy_Calls_P2PHelp: String { return self._s[2432]! } + public var Your_cards_expiration_year_is_invalid: String { return self._s[2434]! } + public var Common_TakePhotoOrVideo: String { return self._s[2435]! } + public var Call_StatusBusy: String { return self._s[2436]! } + public var Conversation_PinnedMessage: String { return self._s[2437]! } + public var AutoDownloadSettings_VoiceMessagesTitle: String { return self._s[2438]! } + public var TwoStepAuth_SetupPasswordConfirmFailed: String { return self._s[2439]! } + public var AppleWatch_ReplyPresets: String { return self._s[2440]! } + public var Passport_DiscardMessageDescription: String { return self._s[2442]! } + public var Login_NetworkError: String { return self._s[2443]! } public func Notification_PinnedRoundMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2443]!, self._r[2443]!, [_0]) - } - public func Channel_AdminLog_MessageRemovedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2444]!, self._r[2444]!, [_0]) } - public var SocksProxySetup_PasswordPlaceholder: String { return self._s[2445]! } + public func Channel_AdminLog_MessageRemovedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2445]!, self._r[2445]!, [_0]) + } + public var SocksProxySetup_PasswordPlaceholder: String { return self._s[2446]! } public func CONTACT_JOINED(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2447]!, self._r[2447]!, [_1]) + return formatWithArgumentRanges(self._s[2448]!, self._r[2448]!, [_1]) } - public var Login_ResetAccountProtected_LimitExceeded: String { return self._s[2448]! } + public var Login_ResetAccountProtected_LimitExceeded: String { return self._s[2449]! } public func Watch_LastSeen_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2450]!, self._r[2450]!, [_0]) + return formatWithArgumentRanges(self._s[2451]!, self._r[2451]!, [_0]) } - public var Call_ConnectionErrorMessage: String { return self._s[2451]! } - public var Compose_GroupTokenListPlaceholder: String { return self._s[2453]! } - public var ConversationMedia_Title: String { return self._s[2454]! } - public var EncryptionKey_Title: String { return self._s[2456]! } - public var TwoStepAuth_EnterPasswordTitle: String { return self._s[2457]! } - public var Notification_Exceptions_AddException: String { return self._s[2458]! } - public var Profile_MessageLifetime1m: String { return self._s[2459]! } + public var Call_ConnectionErrorMessage: String { return self._s[2452]! } + public var Compose_GroupTokenListPlaceholder: String { return self._s[2454]! } + public var ConversationMedia_Title: String { return self._s[2455]! } + public var EncryptionKey_Title: String { return self._s[2457]! } + public var TwoStepAuth_EnterPasswordTitle: String { return self._s[2458]! } + public var Notification_Exceptions_AddException: String { return self._s[2459]! } + public var Profile_MessageLifetime1m: String { return self._s[2460]! } public func Channel_AdminLog_MessageUnkickedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2460]!, self._r[2460]!, [_1]) + return formatWithArgumentRanges(self._s[2461]!, self._r[2461]!, [_1]) } - public var Month_GenMay: String { return self._s[2461]! } + public var Month_GenMay: String { return self._s[2462]! } public func LiveLocationUpdated_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2462]!, self._r[2462]!, [_0]) + return formatWithArgumentRanges(self._s[2463]!, self._r[2463]!, [_0]) } - public var ChannelMembers_WhoCanAddMembersAllHelp: String { return self._s[2463]! } - public var Conversation_EmptyPlaceholder: String { return self._s[2465]! } - public var Passport_Address_AddPassportRegistration: String { return self._s[2466]! } - public var Notifications_ChannelNotificationsAlert: String { return self._s[2467]! } - public var Camera_TapAndHoldForVideo: String { return self._s[2468]! } - public var Channel_JoinChannel: String { return self._s[2470]! } - public var Appearance_Animations: String { return self._s[2473]! } + public var ChannelMembers_WhoCanAddMembersAllHelp: String { return self._s[2464]! } + public var Conversation_EmptyPlaceholder: String { return self._s[2466]! } + public var Passport_Address_AddPassportRegistration: String { return self._s[2467]! } + public var Notifications_ChannelNotificationsAlert: String { return self._s[2468]! } + public var Camera_TapAndHoldForVideo: String { return self._s[2469]! } + public var Channel_JoinChannel: String { return self._s[2471]! } + public var Appearance_Animations: String { return self._s[2474]! } public func Notification_MessageLifetimeChanged(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2474]!, self._r[2474]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2475]!, self._r[2475]!, [_1, _2]) } - public var Stickers_GroupStickers: String { return self._s[2476]! } - public var ConvertToSupergroup_HelpTitle: String { return self._s[2478]! } - public var Passport_Address_Street: String { return self._s[2479]! } - public var Conversation_AddContact: String { return self._s[2480]! } - public var Login_PhonePlaceholder: String { return self._s[2481]! } - public var Channel_Members_InviteLink: String { return self._s[2483]! } - public var Bot_Stop: String { return self._s[2484]! } - public var Notification_PassportValueAddress: String { return self._s[2486]! } - public var Month_ShortJuly: String { return self._s[2487]! } - public var Passport_Address_TypeTemporaryRegistrationUploadScan: String { return self._s[2488]! } - public var Channel_AdminLog_BanSendMedia: String { return self._s[2489]! } - public var Passport_Identity_ReverseSide: String { return self._s[2490]! } - public var Watch_Stickers_Recents: String { return self._s[2493]! } - public var PrivacyLastSeenSettings_EmpryUsersPlaceholder: String { return self._s[2495]! } - public var Map_SendThisLocation: String { return self._s[2496]! } + public var Stickers_GroupStickers: String { return self._s[2477]! } + public var ConvertToSupergroup_HelpTitle: String { return self._s[2479]! } + public var Passport_Address_Street: String { return self._s[2480]! } + public var Conversation_AddContact: String { return self._s[2481]! } + public var Login_PhonePlaceholder: String { return self._s[2482]! } + public var Channel_Members_InviteLink: String { return self._s[2484]! } + public var Bot_Stop: String { return self._s[2485]! } + public var Notification_PassportValueAddress: String { return self._s[2487]! } + public var Month_ShortJuly: String { return self._s[2488]! } + public var Passport_Address_TypeTemporaryRegistrationUploadScan: String { return self._s[2489]! } + public var Channel_AdminLog_BanSendMedia: String { return self._s[2490]! } + public var Passport_Identity_ReverseSide: String { return self._s[2491]! } + public var Watch_Stickers_Recents: String { return self._s[2494]! } + public var PrivacyLastSeenSettings_EmpryUsersPlaceholder: String { return self._s[2496]! } + public var Map_SendThisLocation: String { return self._s[2497]! } public func Time_MonthOfYear_m1(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2497]!, self._r[2497]!, [_0]) - } - public func InviteText_SingleContact(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2498]!, self._r[2498]!, [_0]) } - public var ConvertToSupergroup_Note: String { return self._s[2499]! } + public func InviteText_SingleContact(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2499]!, self._r[2499]!, [_0]) + } + public var ConvertToSupergroup_Note: String { return self._s[2500]! } public func FileSize_MB(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2500]!, self._r[2500]!, [_0]) + return formatWithArgumentRanges(self._s[2501]!, self._r[2501]!, [_0]) } - public var NetworkUsageSettings_GeneralDataSection: String { return self._s[2501]! } + public var NetworkUsageSettings_GeneralDataSection: String { return self._s[2502]! } public func Compatibility_SecretMediaVersionTooLow(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2502]!, self._r[2502]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2503]!, self._r[2503]!, [_0, _1]) } - public var Login_CallRequestState3: String { return self._s[2504]! } + public var Login_CallRequestState3: String { return self._s[2505]! } public func CHANNEL_MESSAGE_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2506]!, self._r[2506]!, [_1]) + return formatWithArgumentRanges(self._s[2507]!, self._r[2507]!, [_1]) } - public var PasscodeSettings_UnlockWithFaceId: String { return self._s[2507]! } - public var Channel_AdminLogFilter_Title: String { return self._s[2508]! } - public var Notifications_GroupNotificationsExceptions: String { return self._s[2512]! } + public var PasscodeSettings_UnlockWithFaceId: String { return self._s[2508]! } + public var Channel_AdminLogFilter_Title: String { return self._s[2509]! } + public var Notifications_GroupNotificationsExceptions: String { return self._s[2513]! } public func FileSize_B(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2513]!, self._r[2513]!, [_0]) + return formatWithArgumentRanges(self._s[2514]!, self._r[2514]!, [_0]) } - public var Passport_CorrectErrors: String { return self._s[2514]! } + public var Passport_CorrectErrors: String { return self._s[2515]! } public func Channel_MessageTitleUpdated(_ _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 Map_SendMyCurrentLocation: String { return self._s[2516]! } - public var SharedMedia_SearchNoResults: String { return self._s[2517]! } - public var Permissions_NotificationsText_v0: String { return self._s[2518]! } - public var LoginPassword_FloodError: String { return self._s[2519]! } - public var Group_Setup_HistoryHiddenHelp: String { return self._s[2521]! } + public var Map_SendMyCurrentLocation: String { return self._s[2517]! } + public var SharedMedia_SearchNoResults: String { return self._s[2518]! } + public var Permissions_NotificationsText_v0: String { return self._s[2519]! } + public var LoginPassword_FloodError: String { return self._s[2520]! } + public var Group_Setup_HistoryHiddenHelp: String { return self._s[2522]! } public func TwoStepAuth_PendingEmailHelp(_ _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 Passport_Language_bn: String { return self._s[2523]! } + public var Passport_Language_bn: String { return self._s[2524]! } public func DialogList_SingleUploadingPhotoSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2524]!, self._r[2524]!, [_0]) - } - public func Notification_PinnedAudioMessage(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2525]!, self._r[2525]!, [_0]) } - public func Channel_AdminLog_MessageChangedGroupStickerPack(_ _0: String) -> (String, [(Int, NSRange)]) { + public func Notification_PinnedAudioMessage(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2526]!, self._r[2526]!, [_0]) } - public var GroupInfo_InvitationLinkGroupFull: String { return self._s[2529]! } - public var Group_EditAdmin_PermissionChangeInfo: String { return self._s[2531]! } - public var Contacts_PermissionsAllow: String { return self._s[2532]! } - public var ReportPeer_ReasonCopyright: String { return self._s[2533]! } - public var Channel_EditAdmin_PermissinAddAdminOn: String { return self._s[2534]! } - public var Paint_Duplicate: String { return self._s[2535]! } - public var Notification_ChannelMigratedFrom: String { return self._s[2536]! } - public var Passport_Address_Country: String { return self._s[2537]! } - public var Notification_RenamedChannel: String { return self._s[2539]! } - public var CheckoutInfo_ErrorPostcodeInvalid: String { return self._s[2540]! } - public var Group_MessagePhotoUpdated: String { return self._s[2541]! } - public var Channel_BanUser_PermissionSendMedia: String { return self._s[2542]! } - public var Conversation_ContextMenuBan: String { return self._s[2543]! } - public var TwoStepAuth_EmailSent: String { return self._s[2544]! } - public var MessagePoll_NoVotes: String { return self._s[2545]! } - public var Passport_Language_is: String { return self._s[2546]! } - public var Tour_Text5: String { return self._s[2548]! } + public func Channel_AdminLog_MessageChangedGroupStickerPack(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2527]!, self._r[2527]!, [_0]) + } + public var GroupInfo_InvitationLinkGroupFull: String { return self._s[2530]! } + public var Group_EditAdmin_PermissionChangeInfo: String { return self._s[2532]! } + public var Contacts_PermissionsAllow: String { return self._s[2533]! } + public var ReportPeer_ReasonCopyright: String { return self._s[2534]! } + public var Channel_EditAdmin_PermissinAddAdminOn: String { return self._s[2535]! } + public var Paint_Duplicate: String { return self._s[2536]! } + public var Notification_ChannelMigratedFrom: String { return self._s[2537]! } + public var Passport_Address_Country: String { return self._s[2538]! } + public var Notification_RenamedChannel: String { return self._s[2540]! } + public var CheckoutInfo_ErrorPostcodeInvalid: String { return self._s[2541]! } + public var Group_MessagePhotoUpdated: String { return self._s[2542]! } + public var Channel_BanUser_PermissionSendMedia: String { return self._s[2543]! } + public var Conversation_ContextMenuBan: String { return self._s[2544]! } + public var TwoStepAuth_EmailSent: String { return self._s[2545]! } + public var MessagePoll_NoVotes: String { return self._s[2546]! } + public var Passport_Language_is: String { return self._s[2547]! } + public var Tour_Text5: String { return self._s[2549]! } public func Call_GroupFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2550]!, self._r[2550]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2551]!, self._r[2551]!, [_1, _2]) } - public var Paint_Edit: String { return self._s[2552]! } - public var LoginPassword_ForgotPassword: String { return self._s[2555]! } - public var GroupInfo_GroupNamePlaceholder: String { return self._s[2556]! } + public var Paint_Edit: String { return self._s[2553]! } + public var LoginPassword_ForgotPassword: String { return self._s[2556]! } + public var GroupInfo_GroupNamePlaceholder: String { return self._s[2557]! } public func Notification_Kicked(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2557]!, self._r[2557]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2558]!, self._r[2558]!, [_0, _1]) } - public var Conversation_InputTextCaptionPlaceholder: String { return self._s[2558]! } - public var AutoDownloadSettings_VideoMessagesTitle: String { return self._s[2559]! } - public var Passport_Language_uz: String { return self._s[2560]! } - public var Conversation_PinMessageAlertGroup: String { return self._s[2561]! } - public var Map_StopLiveLocation: String { return self._s[2563]! } - public var PasscodeSettings_Help: String { return self._s[2565]! } - public var NotificationsSound_Input: String { return self._s[2566]! } - public var Share_Title: String { return self._s[2568]! } - public var Login_TermsOfServiceAgree: String { return self._s[2569]! } - public var Compose_NewEncryptedChatTitle: String { return self._s[2570]! } - public var Channel_AdminLog_TitleSelectedEvents: String { return self._s[2571]! } - public var Channel_EditAdmin_PermissionEditMessages: String { return self._s[2572]! } - public var EnterPasscode_EnterTitle: String { return self._s[2573]! } + public var Conversation_InputTextCaptionPlaceholder: String { return self._s[2559]! } + public var AutoDownloadSettings_VideoMessagesTitle: String { return self._s[2560]! } + public var Passport_Language_uz: String { return self._s[2561]! } + public var Conversation_PinMessageAlertGroup: String { return self._s[2562]! } + public var Map_StopLiveLocation: String { return self._s[2564]! } + public var PasscodeSettings_Help: String { return self._s[2566]! } + public var NotificationsSound_Input: String { return self._s[2567]! } + public var Share_Title: String { return self._s[2569]! } + public var Login_TermsOfServiceAgree: String { return self._s[2570]! } + public var Compose_NewEncryptedChatTitle: String { return self._s[2571]! } + public var Channel_AdminLog_TitleSelectedEvents: String { return self._s[2572]! } + public var Channel_EditAdmin_PermissionEditMessages: String { return self._s[2573]! } + public var EnterPasscode_EnterTitle: String { return self._s[2574]! } public func Call_PrivacyErrorMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2574]!, self._r[2574]!, [_0]) + return formatWithArgumentRanges(self._s[2575]!, self._r[2575]!, [_0]) } - public var Settings_CopyPhoneNumber: String { return self._s[2575]! } - public var NotificationsSound_Keys: String { return self._s[2576]! } + public var Settings_CopyPhoneNumber: String { return self._s[2576]! } + public var NotificationsSound_Keys: String { return self._s[2577]! } public func Call_ParticipantVersionOutdatedError(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2577]!, self._r[2577]!, [_0]) + return formatWithArgumentRanges(self._s[2578]!, self._r[2578]!, [_0]) } - public var Notification_MessageLifetime1w: String { return self._s[2578]! } - public var Message_Video: String { return self._s[2579]! } + public var Notification_MessageLifetime1w: String { return self._s[2579]! } + public var Message_Video: String { return self._s[2580]! } public func Notification_JoinedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2582]!, self._r[2582]!, [_0]) - } - public func PrivacySettings_LastSeenContactsPlus(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2583]!, self._r[2583]!, [_0]) } - public var Passport_Language_mk: String { return self._s[2584]! } - public var CreatePoll_CancelConfirmation: String { return self._s[2585]! } - public var Conversation_SilentBroadcastTooltipOn: String { return self._s[2587]! } - public var PrivacyPolicy_Decline: String { return self._s[2588]! } - public var Passport_Identity_DoesNotExpire: String { return self._s[2589]! } - public var Channel_AdminLogFilter_EventsRestrictions: String { return self._s[2590]! } - public var Permissions_SiriAllow_v0: String { return self._s[2591]! } + public func PrivacySettings_LastSeenContactsPlus(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2584]!, self._r[2584]!, [_0]) + } + public var Passport_Language_mk: String { return self._s[2585]! } + public var CreatePoll_CancelConfirmation: String { return self._s[2586]! } + public var Conversation_SilentBroadcastTooltipOn: String { return self._s[2588]! } + public var PrivacyPolicy_Decline: String { return self._s[2589]! } + public var Passport_Identity_DoesNotExpire: String { return self._s[2590]! } + public var Channel_AdminLogFilter_EventsRestrictions: String { return self._s[2591]! } + public var Permissions_SiriAllow_v0: String { return self._s[2592]! } public func CHAT_MESSAGE_STICKER(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2592]!, self._r[2592]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2593]!, self._r[2593]!, [_1, _2, _3]) } public func CHANNEL_MESSAGES(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2593]!, self._r[2593]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2594]!, self._r[2594]!, [_1, _2]) } public func Notification_RenamedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2594]!, self._r[2594]!, [_0]) + return formatWithArgumentRanges(self._s[2595]!, self._r[2595]!, [_0]) } - public var Paint_Regular: String { return self._s[2595]! } - public var ChatSettings_AutoDownloadReset: String { return self._s[2596]! } - public var BlockedUsers_SelectUserTitle: String { return self._s[2597]! } - public var GroupInfo_InviteByLink: String { return self._s[2599]! } - public var MessageTimer_Custom: String { return self._s[2600]! } - public var UserInfo_NotificationsDefaultEnabled: String { return self._s[2601]! } - public var Passport_Address_TypeTemporaryRegistration: String { return self._s[2603]! } - public var Channel_Username_InvalidTaken: String { return self._s[2604]! } - public var Conversation_ClousStorageInfo_Description3: String { return self._s[2605]! } + public var Paint_Regular: String { return self._s[2596]! } + public var ChatSettings_AutoDownloadReset: String { return self._s[2597]! } + public var BlockedUsers_SelectUserTitle: String { return self._s[2598]! } + public var GroupInfo_InviteByLink: String { return self._s[2600]! } + public var MessageTimer_Custom: String { return self._s[2601]! } + public var UserInfo_NotificationsDefaultEnabled: String { return self._s[2602]! } + public var Passport_Address_TypeTemporaryRegistration: String { return self._s[2604]! } + public var Channel_Username_InvalidTaken: String { return self._s[2605]! } + public var Conversation_ClousStorageInfo_Description3: String { return self._s[2606]! } public func CHANNEL_MESSAGE_VIDEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2606]!, self._r[2606]!, [_1]) + return formatWithArgumentRanges(self._s[2607]!, self._r[2607]!, [_1]) } - public var Settings_ChatBackground: String { return self._s[2607]! } - public var Channel_Subscribers_Title: String { return self._s[2608]! } - public var ApplyLanguage_ChangeLanguageTitle: String { return self._s[2609]! } - public var Watch_ConnectionDescription: String { return self._s[2610]! } - public var EditProfile_Title: String { return self._s[2614]! } - public var NotificationsSound_Bamboo: String { return self._s[2616]! } - public var Channel_AdminLog_MessagePreviousMessage: String { return self._s[2618]! } - public var Login_SmsRequestState2: String { return self._s[2619]! } - public var Passport_Language_ar: String { return self._s[2620]! } - public var Conversation_MessageDialogEdit: String { return self._s[2621]! } - public var Common_Close: String { return self._s[2622]! } + public var Settings_ChatBackground: String { return self._s[2608]! } + public var Channel_Subscribers_Title: String { return self._s[2609]! } + public var ApplyLanguage_ChangeLanguageTitle: String { return self._s[2610]! } + public var Watch_ConnectionDescription: String { return self._s[2611]! } + public var EditProfile_Title: String { return self._s[2615]! } + public var NotificationsSound_Bamboo: String { return self._s[2617]! } + public var Channel_AdminLog_MessagePreviousMessage: String { return self._s[2619]! } + public var Login_SmsRequestState2: String { return self._s[2620]! } + public var Passport_Language_ar: String { return self._s[2621]! } + public var Conversation_MessageDialogEdit: String { return self._s[2622]! } + public var Common_Close: String { return self._s[2623]! } public func Channel_AdminLog_MessageToggleInvitesOff(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2626]!, self._r[2626]!, [_0]) + return formatWithArgumentRanges(self._s[2627]!, self._r[2627]!, [_0]) } - public var UserInfo_About_Placeholder: String { return self._s[2627]! } + public var UserInfo_About_Placeholder: String { return self._s[2628]! } public func Conversation_FileHowToText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2628]!, self._r[2628]!, [_0]) + return formatWithArgumentRanges(self._s[2629]!, self._r[2629]!, [_0]) } - public var Channel_Info_Banned: String { return self._s[2630]! } + public var Channel_Info_Banned: String { return self._s[2631]! } public func Time_MonthOfYear_m11(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2631]!, self._r[2631]!, [_0]) + return formatWithArgumentRanges(self._s[2632]!, self._r[2632]!, [_0]) } - public var Passport_Language_my: String { return self._s[2632]! } + public var Passport_Language_my: String { return self._s[2633]! } public func Time_PreciseDate_m9(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2633]!, self._r[2633]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2634]!, self._r[2634]!, [_1, _2, _3]) } - public var Preview_CopyAddress: String { return self._s[2634]! } + public var Preview_CopyAddress: String { return self._s[2635]! } public func DialogList_SinglePlayingGameSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2635]!, self._r[2635]!, [_0]) + return formatWithArgumentRanges(self._s[2636]!, self._r[2636]!, [_0]) } - public var KeyCommand_JumpToPreviousChat: String { return self._s[2636]! } - public var UserInfo_BotSettings: String { return self._s[2637]! } - public var LiveLocation_MenuStopAll: String { return self._s[2639]! } - public var Passport_PasswordCreate: String { return self._s[2640]! } - public var Watch_Message_Unsupported: String { return self._s[2641]! } - public var Message_PinnedLocationMessage: String { return self._s[2642]! } - public var Map_Satellite: String { return self._s[2643]! } - public var StickerSettings_MaskContextInfo: String { return self._s[2644]! } - public var Username_TooManyPublicUsernamesError: String { return self._s[2645]! } - public var TwoStepAuth_EnterPasswordInvalid: String { return self._s[2646]! } + public var KeyCommand_JumpToPreviousChat: String { return self._s[2637]! } + public var UserInfo_BotSettings: String { return self._s[2638]! } + public var LiveLocation_MenuStopAll: String { return self._s[2640]! } + public var Passport_PasswordCreate: String { return self._s[2641]! } + public var Watch_Message_Unsupported: String { return self._s[2642]! } + public var Message_PinnedLocationMessage: String { return self._s[2643]! } + public var Map_Satellite: String { return self._s[2644]! } + public var StickerSettings_MaskContextInfo: String { return self._s[2645]! } + public var Username_TooManyPublicUsernamesError: String { return self._s[2646]! } + public var TwoStepAuth_EnterPasswordInvalid: String { return self._s[2647]! } public func Notification_PinnedTextMessage(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2647]!, self._r[2647]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2648]!, self._r[2648]!, [_0, _1]) } - public var Notifications_ChannelNotificationsHelp: String { return self._s[2648]! } - public var Privacy_Calls_P2PContacts: String { return self._s[2649]! } - public var NotificationsSound_None: String { return self._s[2650]! } - public var AccessDenied_VoiceMicrophone: String { return self._s[2652]! } + public var Notifications_ChannelNotificationsHelp: String { return self._s[2649]! } + public var Privacy_Calls_P2PContacts: String { return self._s[2650]! } + public var NotificationsSound_None: String { return self._s[2651]! } + public var AccessDenied_VoiceMicrophone: String { return self._s[2653]! } public func ApplyLanguage_ChangeLanguageAlreadyActive(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2653]!, self._r[2653]!, [_1]) + return formatWithArgumentRanges(self._s[2654]!, self._r[2654]!, [_1]) } - public var Cache_Indexing: String { return self._s[2654]! } - public var DialogList_RecentTitlePeople: String { return self._s[2656]! } - public var DialogList_EncryptionRejected: String { return self._s[2657]! } - public var Passport_ScanPassportHelp: String { return self._s[2658]! } - public var Application_Name: String { return self._s[2659]! } - public var Channel_AdminLogFilter_ChannelEventsInfo: String { return self._s[2660]! } - public var Passport_Identity_TranslationHelp: String { return self._s[2662]! } + public var Cache_Indexing: String { return self._s[2655]! } + public var DialogList_RecentTitlePeople: String { return self._s[2657]! } + public var DialogList_EncryptionRejected: String { return self._s[2658]! } + public var Passport_ScanPassportHelp: String { return self._s[2659]! } + public var Application_Name: String { return self._s[2660]! } + public var Channel_AdminLogFilter_ChannelEventsInfo: String { return self._s[2661]! } + public var Passport_Identity_TranslationHelp: String { return self._s[2663]! } public func Notification_JoinedGroupByLink(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2663]!, self._r[2663]!, [_0]) - } - public func DialogList_EncryptedChatStartedOutgoing(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2664]!, self._r[2664]!, [_0]) } - public var Channel_EditAdmin_PermissionDeleteMessages: String { return self._s[2665]! } - public var Privacy_ChatsTitle: String { return self._s[2666]! } - public var DialogList_ClearHistoryConfirmation: String { return self._s[2667]! } - public var Watch_Suggestion_HoldOn: String { return self._s[2668]! } - public var SocksProxySetup_RequiredCredentials: String { return self._s[2669]! } - public var Passport_Address_TypeRentalAgreementUploadScan: String { return self._s[2670]! } - public var TwoStepAuth_EmailSkipAlert: String { return self._s[2671]! } - public var Channel_Setup_TypePublic: String { return self._s[2674]! } + public func DialogList_EncryptedChatStartedOutgoing(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2665]!, self._r[2665]!, [_0]) + } + public var Channel_EditAdmin_PermissionDeleteMessages: String { return self._s[2666]! } + public var Privacy_ChatsTitle: String { return self._s[2667]! } + public var DialogList_ClearHistoryConfirmation: String { return self._s[2668]! } + public var Watch_Suggestion_HoldOn: String { return self._s[2669]! } + public var SocksProxySetup_RequiredCredentials: String { return self._s[2670]! } + public var Passport_Address_TypeRentalAgreementUploadScan: String { return self._s[2671]! } + public var TwoStepAuth_EmailSkipAlert: String { return self._s[2672]! } + public var Channel_Setup_TypePublic: String { return self._s[2675]! } public func Channel_AdminLog_MessageToggleInvitesOn(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2675]!, self._r[2675]!, [_0]) + return formatWithArgumentRanges(self._s[2676]!, self._r[2676]!, [_0]) } - public var Channel_TypeSetup_Title: String { return self._s[2677]! } - public var Map_OpenInMaps: String { return self._s[2679]! } - public var NotificationsSound_Tremolo: String { return self._s[2681]! } + public var Channel_TypeSetup_Title: String { return self._s[2678]! } + public var Map_OpenInMaps: String { return self._s[2680]! } + public var NotificationsSound_Tremolo: String { return self._s[2682]! } public func Date_ChatDateHeaderYear(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2682]!, self._r[2682]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2683]!, self._r[2683]!, [_1, _2, _3]) } - public var ConversationProfile_UnknownAddMemberError: String { return self._s[2683]! } - public var Passport_PasswordHelp: String { return self._s[2684]! } - public var Login_CodeExpiredError: String { return self._s[2685]! } - public var Channel_EditAdmin_PermissionChangeInfo: String { return self._s[2686]! } - public var Conversation_TitleUnmute: String { return self._s[2687]! } - public var Passport_Identity_ScansHelp: String { return self._s[2688]! } - public var Passport_Language_lo: String { return self._s[2689]! } - public var Camera_FlashAuto: String { return self._s[2690]! } - public var Common_Cancel: String { return self._s[2691]! } - public var DialogList_SavedMessagesTooltip: String { return self._s[2692]! } - public var TwoStepAuth_SetupPasswordTitle: String { return self._s[2693]! } - public var Conversation_ReportSpamConfirmation: String { return self._s[2694]! } - public var ChatSettings_Title: String { return self._s[2696]! } - public var Passport_PasswordReset: String { return self._s[2697]! } - public var SocksProxySetup_TypeNone: String { return self._s[2698]! } - public var PhoneNumberHelp_Help: String { return self._s[2700]! } - public var Checkout_EnterPassword: String { return self._s[2701]! } - public var Share_AuthTitle: String { return self._s[2703]! } - public var Activity_UploadingDocument: String { return self._s[2704]! } - public var State_Connecting: String { return self._s[2705]! } - public var Profile_MessageLifetime1w: String { return self._s[2706]! } - public var Conversation_ContextMenuReport: String { return self._s[2707]! } - public var CheckoutInfo_ReceiverInfoPhone: String { return self._s[2708]! } - public var AutoNightTheme_ScheduledTo: String { return self._s[2709]! } - public var AuthSessions_Terminate: String { return self._s[2710]! } - public var Checkout_NewCard_CardholderNamePlaceholder: String { return self._s[2711]! } - public var KeyCommand_JumpToPreviousUnreadChat: String { return self._s[2712]! } - public var PhotoEditor_Set: String { return self._s[2713]! } - public var Login_PadPhoneHelp: String { return self._s[2714]! } - public var PrivacyPolicy_DeclineLastWarning: String { return self._s[2717]! } - public var NotificationsSound_Complete: String { return self._s[2718]! } - public var Group_Info_AdminLog: String { return self._s[2719]! } - public var Channel_AdminLog_InfoPanelAlertText: String { return self._s[2720]! } - public var Conversation_Admin: String { return self._s[2722]! } - public var Conversation_GifTooltip: String { return self._s[2723]! } - public var Passport_NotLoggedInMessage: String { return self._s[2724]! } - public var Profile_MessageLifetimeForever: String { return self._s[2725]! } - public var SharedMedia_EmptyTitle: String { return self._s[2727]! } - public var Channel_Edit_PrivatePublicLinkAlert: String { return self._s[2728]! } - public var Username_Help: String { return self._s[2729]! } - public var DialogList_LanguageTooltip: String { return self._s[2731]! } - public var Map_LoadError: String { return self._s[2732]! } - public var Notification_Exceptions_NewException: String { return self._s[2733]! } - public var TwoStepAuth_EmailTitle: String { return self._s[2734]! } - public var WatchRemote_AlertText: String { return self._s[2735]! } - public var ChatSettings_ConnectionType_Title: String { return self._s[2737]! } + public var ConversationProfile_UnknownAddMemberError: String { return self._s[2684]! } + public var Passport_PasswordHelp: String { return self._s[2685]! } + public var Login_CodeExpiredError: String { return self._s[2686]! } + public var Channel_EditAdmin_PermissionChangeInfo: String { return self._s[2687]! } + public var Conversation_TitleUnmute: String { return self._s[2688]! } + public var Passport_Identity_ScansHelp: String { return self._s[2689]! } + public var Passport_Language_lo: String { return self._s[2690]! } + public var Camera_FlashAuto: String { return self._s[2691]! } + public var Common_Cancel: String { return self._s[2692]! } + public var DialogList_SavedMessagesTooltip: String { return self._s[2693]! } + public var TwoStepAuth_SetupPasswordTitle: String { return self._s[2694]! } + public var Conversation_ReportSpamConfirmation: String { return self._s[2695]! } + public var ChatSettings_Title: String { return self._s[2697]! } + public var Passport_PasswordReset: String { return self._s[2698]! } + public var SocksProxySetup_TypeNone: String { return self._s[2699]! } + public var PhoneNumberHelp_Help: String { return self._s[2701]! } + public var Checkout_EnterPassword: String { return self._s[2702]! } + public var Share_AuthTitle: String { return self._s[2704]! } + public var Activity_UploadingDocument: String { return self._s[2705]! } + public var State_Connecting: String { return self._s[2706]! } + public var Profile_MessageLifetime1w: String { return self._s[2707]! } + public var Conversation_ContextMenuReport: String { return self._s[2708]! } + public var CheckoutInfo_ReceiverInfoPhone: String { return self._s[2709]! } + public var AutoNightTheme_ScheduledTo: String { return self._s[2710]! } + public var AuthSessions_Terminate: String { return self._s[2711]! } + public var Checkout_NewCard_CardholderNamePlaceholder: String { return self._s[2712]! } + public var KeyCommand_JumpToPreviousUnreadChat: String { return self._s[2713]! } + public var PhotoEditor_Set: String { return self._s[2714]! } + public var Login_PadPhoneHelp: String { return self._s[2715]! } + public var PrivacyPolicy_DeclineLastWarning: String { return self._s[2718]! } + public var NotificationsSound_Complete: String { return self._s[2719]! } + public var Group_Info_AdminLog: String { return self._s[2720]! } + public var Channel_AdminLog_InfoPanelAlertText: String { return self._s[2721]! } + public var Conversation_Admin: String { return self._s[2723]! } + public var Conversation_GifTooltip: String { return self._s[2724]! } + public var Passport_NotLoggedInMessage: String { return self._s[2725]! } + public var Profile_MessageLifetimeForever: String { return self._s[2726]! } + public var SharedMedia_EmptyTitle: String { return self._s[2728]! } + public var Channel_Edit_PrivatePublicLinkAlert: String { return self._s[2729]! } + public var Username_Help: String { return self._s[2730]! } + public var DialogList_LanguageTooltip: String { return self._s[2732]! } + public var Map_LoadError: String { return self._s[2733]! } + public var Notification_Exceptions_NewException: String { return self._s[2734]! } + public var TwoStepAuth_EmailTitle: String { return self._s[2735]! } + public var WatchRemote_AlertText: String { return self._s[2736]! } + public var ChatSettings_ConnectionType_Title: String { return self._s[2738]! } public func LOCKED_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2738]!, self._r[2738]!, [_1]) + return formatWithArgumentRanges(self._s[2739]!, self._r[2739]!, [_1]) } - public var Passport_Address_CountryPlaceholder: String { return self._s[2739]! } + public var Passport_Address_CountryPlaceholder: String { return self._s[2740]! } public func DialogList_AwaitingEncryption(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2740]!, self._r[2740]!, [_0]) + return formatWithArgumentRanges(self._s[2741]!, self._r[2741]!, [_0]) } public func Time_PreciseDate_m6(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2741]!, self._r[2741]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2742]!, self._r[2742]!, [_1, _2, _3]) } - public var Group_AdminLog_EmptyText: String { return self._s[2742]! } - public var AccessDenied_VideoMicrophone: String { return self._s[2744]! } - public var Conversation_ContextMenuStickerPackAdd: String { return self._s[2745]! } - public var Cache_ClearNone: String { return self._s[2746]! } - public var SocksProxySetup_FailedToConnect: String { return self._s[2747]! } - public var Permissions_NotificationsTitle_v0: String { return self._s[2748]! } + public var Group_AdminLog_EmptyText: String { return self._s[2743]! } + public var AccessDenied_VideoMicrophone: String { return self._s[2745]! } + public var Conversation_ContextMenuStickerPackAdd: String { return self._s[2746]! } + public var Cache_ClearNone: String { return self._s[2747]! } + public var SocksProxySetup_FailedToConnect: String { return self._s[2748]! } + public var Permissions_NotificationsTitle_v0: String { return self._s[2749]! } public func Channel_AdminLog_MessageEdited(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2749]!, self._r[2749]!, [_0]) + return formatWithArgumentRanges(self._s[2750]!, self._r[2750]!, [_0]) } - public var Passport_Identity_Country: String { return self._s[2750]! } + public var Passport_Identity_Country: String { return self._s[2751]! } public func Notification_CreatedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2751]!, self._r[2751]!, [_0]) + return formatWithArgumentRanges(self._s[2752]!, self._r[2752]!, [_0]) } - public var AccessDenied_Settings: String { return self._s[2752]! } - public var Passport_Address_TypeUtilityBillUploadScan: String { return self._s[2753]! } - public var Month_ShortMay: String { return self._s[2754]! } - public var Compose_NewGroup: String { return self._s[2755]! } - public var Group_Setup_TypePrivate: String { return self._s[2757]! } - public var Login_PadPhoneHelpTitle: String { return self._s[2758]! } - public var Appearance_ThemeDayClassic: String { return self._s[2759]! } - public var Channel_AdminLog_MessagePreviousCaption: String { return self._s[2760]! } - public var Privacy_GroupsAndChannels_WhoCanAddMe: String { return self._s[2761]! } - public var Conversation_typing: String { return self._s[2763]! } - public var Paint_Masks: String { return self._s[2764]! } - public var Username_InvalidTaken: String { return self._s[2765]! } - public var TwoStepAuth_EmailAddSuccess: String { return self._s[2766]! } + public var AccessDenied_Settings: String { return self._s[2753]! } + public var Passport_Address_TypeUtilityBillUploadScan: String { return self._s[2754]! } + public var Month_ShortMay: String { return self._s[2755]! } + public var Compose_NewGroup: String { return self._s[2756]! } + public var Group_Setup_TypePrivate: String { return self._s[2758]! } + public var Login_PadPhoneHelpTitle: String { return self._s[2759]! } + public var Appearance_ThemeDayClassic: String { return self._s[2760]! } + public var Channel_AdminLog_MessagePreviousCaption: String { return self._s[2761]! } + public var Privacy_GroupsAndChannels_WhoCanAddMe: String { return self._s[2762]! } + public var Conversation_typing: String { return self._s[2764]! } + public var Paint_Masks: String { return self._s[2765]! } + public var Username_InvalidTaken: String { return self._s[2766]! } + public var TwoStepAuth_EmailAddSuccess: String { return self._s[2767]! } public func CHAT_PHOTO_EDITED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2767]!, self._r[2767]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2768]!, self._r[2768]!, [_1, _2]) } - public var Call_StatusNoAnswer: String { return self._s[2768]! } - public var Passport_Identity_Selfie: String { return self._s[2769]! } - public var Login_InfoLastNamePlaceholder: String { return self._s[2770]! } - public var Privacy_SecretChatsLinkPreviewsHelp: String { return self._s[2771]! } - public var Conversation_ClearSecretHistory: String { return self._s[2772]! } - public var NetworkUsageSettings_Title: String { return self._s[2774]! } - public var Your_cards_security_code_is_invalid: String { return self._s[2776]! } + public var Call_StatusNoAnswer: String { return self._s[2769]! } + public var Passport_Identity_Selfie: String { return self._s[2770]! } + public var Login_InfoLastNamePlaceholder: String { return self._s[2771]! } + public var Privacy_SecretChatsLinkPreviewsHelp: String { return self._s[2772]! } + public var Conversation_ClearSecretHistory: String { return self._s[2773]! } + public var NetworkUsageSettings_Title: String { return self._s[2775]! } + public var Your_cards_security_code_is_invalid: String { return self._s[2777]! } public func Notification_LeftChannel(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2778]!, self._r[2778]!, [_0]) + return formatWithArgumentRanges(self._s[2779]!, self._r[2779]!, [_0]) } public func Call_CallInProgressMessage(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2779]!, self._r[2779]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2780]!, self._r[2780]!, [_1, _2]) } - public var SaveIncomingPhotosSettings_From: String { return self._s[2781]! } - public var Map_LiveLocationTitle: String { return self._s[2782]! } - public var Login_InfoAvatarAdd: String { return self._s[2783]! } - public var Passport_Identity_FilesView: String { return self._s[2784]! } - public var UserInfo_GenericPhoneLabel: String { return self._s[2785]! } - public var Privacy_Calls_NeverAllow: String { return self._s[2786]! } + public var SaveIncomingPhotosSettings_From: String { return self._s[2782]! } + public var Map_LiveLocationTitle: String { return self._s[2783]! } + public var Login_InfoAvatarAdd: String { return self._s[2784]! } + public var Passport_Identity_FilesView: String { return self._s[2785]! } + public var UserInfo_GenericPhoneLabel: String { return self._s[2786]! } + public var Privacy_Calls_NeverAllow: String { return self._s[2787]! } public func Contacts_AddPhoneNumber(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2787]!, self._r[2787]!, [_0]) + return formatWithArgumentRanges(self._s[2788]!, self._r[2788]!, [_0]) } - public var TwoStepAuth_ConfirmationText: String { return self._s[2788]! } - public var ChatSettings_AutomaticVideoMessageDownload: String { return self._s[2789]! } - public var Channel_AdminLogFilter_AdminsAll: String { return self._s[2790]! } - public var Tour_Title2: String { return self._s[2791]! } - public var Conversation_FileOpenIn: String { return self._s[2792]! } - public var Checkout_ErrorPrecheckoutFailed: String { return self._s[2793]! } - public var Wallpaper_Set: String { return self._s[2794]! } - public var Passport_Identity_Translations: String { return self._s[2796]! } + public var TwoStepAuth_ConfirmationText: String { return self._s[2789]! } + public var ChatSettings_AutomaticVideoMessageDownload: String { return self._s[2790]! } + public var Channel_AdminLogFilter_AdminsAll: String { return self._s[2791]! } + public var Tour_Title2: String { return self._s[2792]! } + public var Conversation_FileOpenIn: String { return self._s[2793]! } + public var Checkout_ErrorPrecheckoutFailed: String { return self._s[2794]! } + public var Wallpaper_Set: String { return self._s[2795]! } + public var Passport_Identity_Translations: String { return self._s[2797]! } public func Channel_AdminLog_MessageChangedChannelAbout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2797]!, self._r[2797]!, [_0]) + return formatWithArgumentRanges(self._s[2798]!, self._r[2798]!, [_0]) } - public var Channel_LeaveChannel: String { return self._s[2798]! } + public var Channel_LeaveChannel: String { return self._s[2799]! } public func PINNED_INVOICE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2799]!, self._r[2799]!, [_1]) + return formatWithArgumentRanges(self._s[2800]!, self._r[2800]!, [_1]) } - public var PhotoEditor_HighlightsTint: String { return self._s[2800]! } - public var Passport_Email_Delete: String { return self._s[2801]! } - public var Conversation_Mute: String { return self._s[2803]! } - public var Channel_AdminLog_CanSendMessages: String { return self._s[2805]! } + public var PhotoEditor_HighlightsTint: String { return self._s[2801]! } + public var Passport_Email_Delete: String { return self._s[2802]! } + public var Conversation_Mute: String { return self._s[2804]! } + public var Channel_AdminLog_CanSendMessages: String { return self._s[2806]! } public func Notification_PassportValuesSentMessage(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2806]!, self._r[2806]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2807]!, self._r[2807]!, [_1, _2]) } - public var Calls_CallTabDescription: String { return self._s[2807]! } - public var Passport_Identity_NativeNameHelp: String { return self._s[2808]! } - public var Common_No: String { return self._s[2809]! } - public var Weekday_Sunday: String { return self._s[2810]! } - public var Notification_Reply: String { return self._s[2811]! } - public var Conversation_ViewMessage: String { return self._s[2812]! } + public var Calls_CallTabDescription: String { return self._s[2808]! } + public var Passport_Identity_NativeNameHelp: String { return self._s[2809]! } + public var Common_No: String { return self._s[2810]! } + public var Weekday_Sunday: String { return self._s[2811]! } + public var Notification_Reply: String { return self._s[2812]! } + public var Conversation_ViewMessage: String { return self._s[2813]! } public func Checkout_SavePasswordTimeoutAndFaceId(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2813]!, self._r[2813]!, [_0]) - } - public func Map_LiveLocationPrivateDescription(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2814]!, self._r[2814]!, [_0]) } - public var Message_PinnedDocumentMessage: String { return self._s[2815]! } - public var DialogList_TabTitle: String { return self._s[2817]! } - public var Passport_FieldEmail: String { return self._s[2818]! } - public var Conversation_UnpinMessageAlert: String { return self._s[2819]! } - public var Passport_Address_TypeBankStatement: String { return self._s[2820]! } - public var Passport_Identity_ExpiryDate: String { return self._s[2821]! } - public var Privacy_Calls_P2P: String { return self._s[2822]! } - public func CancelResetAccount_Success(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2824]!, self._r[2824]!, [_0]) + public func Map_LiveLocationPrivateDescription(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2815]!, self._r[2815]!, [_0]) } - public var SocksProxySetup_UseForCallsHelp: String { return self._s[2825]! } - public var EnterPasscode_ChangeTitle: String { return self._s[2826]! } - public var Passport_InfoText: String { return self._s[2827]! } - public var Checkout_NewCard_SaveInfoEnableHelp: String { return self._s[2828]! } + public var Message_PinnedDocumentMessage: String { return self._s[2816]! } + public var DialogList_TabTitle: String { return self._s[2818]! } + public var Passport_FieldEmail: String { return self._s[2819]! } + public var Conversation_UnpinMessageAlert: String { return self._s[2820]! } + public var Passport_Address_TypeBankStatement: String { return self._s[2821]! } + public var Passport_Identity_ExpiryDate: String { return self._s[2822]! } + public var Privacy_Calls_P2P: String { return self._s[2823]! } + public func CancelResetAccount_Success(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2825]!, self._r[2825]!, [_0]) + } + public var SocksProxySetup_UseForCallsHelp: String { return self._s[2826]! } + public var EnterPasscode_ChangeTitle: String { return self._s[2827]! } + public var Passport_InfoText: String { return self._s[2828]! } + public var Checkout_NewCard_SaveInfoEnableHelp: String { return self._s[2829]! } public func Login_InvalidPhoneEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2829]!, self._r[2829]!, [_0]) + return formatWithArgumentRanges(self._s[2830]!, self._r[2830]!, [_0]) } public func Time_PreciseDate_m3(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2830]!, self._r[2830]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2831]!, self._r[2831]!, [_1, _2, _3]) } - public var Passport_Identity_EditDriversLicense: String { return self._s[2831]! } - public var Conversation_TapAndHoldToRecord: String { return self._s[2833]! } + public var Passport_Identity_EditDriversLicense: String { return self._s[2832]! } + public var Conversation_TapAndHoldToRecord: String { return self._s[2834]! } public func Notification_CallTimeFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2834]!, self._r[2834]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2835]!, self._r[2835]!, [_1, _2]) } public func Generic_OpenHiddenLinkAlert(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2836]!, self._r[2836]!, [_0]) + return formatWithArgumentRanges(self._s[2837]!, self._r[2837]!, [_0]) } - public var DialogList_Unread: String { return self._s[2837]! } - public var User_DeletedAccount: String { return self._s[2838]! } + public var DialogList_Unread: String { return self._s[2838]! } + public var User_DeletedAccount: String { return self._s[2839]! } public func Watch_Time_ShortYesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2839]!, self._r[2839]!, [_0]) + return formatWithArgumentRanges(self._s[2840]!, self._r[2840]!, [_0]) } - public var UserInfo_NotificationsDefault: String { return self._s[2840]! } - public var SharedMedia_CategoryMedia: String { return self._s[2841]! } - public var SocksProxySetup_ProxyStatusUnavailable: String { return self._s[2842]! } - public var Channel_AdminLog_MessageRestrictedForever: String { return self._s[2843]! } - public var Watch_ChatList_Compose: String { return self._s[2844]! } - public var Notifications_MessageNotificationsExceptionsHelp: String { return self._s[2845]! } - public var Watch_Microphone_Access: String { return self._s[2846]! } - public var Group_Setup_HistoryHeader: String { return self._s[2847]! } - public var Activity_UploadingPhoto: String { return self._s[2848]! } - public var Conversation_Edit: String { return self._s[2850]! } - public var Group_ErrorSendRestrictedMedia: String { return self._s[2851]! } - public var Login_TermsOfServiceDecline: String { return self._s[2852]! } - public var Message_PinnedContactMessage: String { return self._s[2853]! } + public var UserInfo_NotificationsDefault: String { return self._s[2841]! } + public var SharedMedia_CategoryMedia: String { return self._s[2842]! } + public var SocksProxySetup_ProxyStatusUnavailable: String { return self._s[2843]! } + public var Channel_AdminLog_MessageRestrictedForever: String { return self._s[2844]! } + public var Watch_ChatList_Compose: String { return self._s[2845]! } + public var Notifications_MessageNotificationsExceptionsHelp: String { return self._s[2846]! } + public var Watch_Microphone_Access: String { return self._s[2847]! } + public var Group_Setup_HistoryHeader: String { return self._s[2848]! } + public var Activity_UploadingPhoto: String { return self._s[2849]! } + public var Conversation_Edit: String { return self._s[2851]! } + public var Group_ErrorSendRestrictedMedia: String { return self._s[2852]! } + public var Login_TermsOfServiceDecline: String { return self._s[2853]! } + public var Message_PinnedContactMessage: String { return self._s[2854]! } public func Channel_AdminLog_MessageRestrictedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2854]!, self._r[2854]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2855]!, self._r[2855]!, [_1, _2]) } public func Login_PhoneBannedEmailBody(_ _1: String, _ _2: String, _ _3: String, _ _4: String, _ _5: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2855]!, self._r[2855]!, [_1, _2, _3, _4, _5]) + return formatWithArgumentRanges(self._s[2856]!, self._r[2856]!, [_1, _2, _3, _4, _5]) } - public var TwoStepAuth_AdditionalPassword: String { return self._s[2857]! } - public var Passport_Phone_EnterOtherNumber: String { return self._s[2858]! } - public var TwoStepAuth_RecoveryEmailAddDescription: String { return self._s[2859]! } - public var Passport_FieldPhone: String { return self._s[2860]! } - public var Message_PinnedPhotoMessage: String { return self._s[2861]! } - public var InfoPlist_NSCameraUsageDescription: String { return self._s[2863]! } - public var Conversation_Call: String { return self._s[2864]! } - public var Common_TakePhoto: String { return self._s[2866]! } - public var Channel_NotificationLoading: String { return self._s[2867]! } + public var TwoStepAuth_AdditionalPassword: String { return self._s[2858]! } + public var Passport_Phone_EnterOtherNumber: String { return self._s[2859]! } + public var TwoStepAuth_RecoveryEmailAddDescription: String { return self._s[2860]! } + public var Passport_FieldPhone: String { return self._s[2861]! } + public var Message_PinnedPhotoMessage: String { return self._s[2862]! } + public var InfoPlist_NSCameraUsageDescription: String { return self._s[2864]! } + public var Conversation_Call: String { return self._s[2865]! } + public var Common_TakePhoto: String { return self._s[2867]! } + public var Channel_NotificationLoading: String { return self._s[2868]! } public func Notification_Exceptions_Sound(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2868]!, self._r[2868]!, [_0]) + return formatWithArgumentRanges(self._s[2869]!, self._r[2869]!, [_0]) } - public var Permissions_SiriTitle_v0: String { return self._s[2869]! } + public var Permissions_SiriTitle_v0: String { return self._s[2870]! } public func Login_ResetAccountProtected_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2870]!, self._r[2870]!, [_0]) + return formatWithArgumentRanges(self._s[2871]!, self._r[2871]!, [_0]) } - public var Channel_MessagePhotoRemoved: String { return self._s[2871]! } - public var Common_edit: String { return self._s[2872]! } - public var PrivacySettings_AuthSessions: String { return self._s[2873]! } - public var Month_ShortJune: String { return self._s[2874]! } - public var PrivacyLastSeenSettings_AlwaysShareWith_Placeholder: String { return self._s[2875]! } - public var Call_ReportSend: String { return self._s[2876]! } - public var Watch_LastSeen_JustNow: String { return self._s[2877]! } - public var Notifications_MessageNotifications: String { return self._s[2878]! } - public var BroadcastListInfo_AddRecipient: String { return self._s[2880]! } - public var Group_Status: String { return self._s[2881]! } + public var Channel_MessagePhotoRemoved: String { return self._s[2872]! } + public var Common_edit: String { return self._s[2873]! } + public var PrivacySettings_AuthSessions: String { return self._s[2874]! } + public var Month_ShortJune: String { return self._s[2875]! } + public var PrivacyLastSeenSettings_AlwaysShareWith_Placeholder: String { return self._s[2876]! } + public var Call_ReportSend: String { return self._s[2877]! } + public var Watch_LastSeen_JustNow: String { return self._s[2878]! } + public var Notifications_MessageNotifications: String { return self._s[2879]! } + public var BroadcastListInfo_AddRecipient: String { return self._s[2881]! } + public var Group_Status: String { return self._s[2882]! } public func AutoNightTheme_LocationHelp(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2882]!, self._r[2882]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2883]!, self._r[2883]!, [_0, _1]) } - public var ShareMenu_ShareTo: String { return self._s[2883]! } - public var Conversation_Moderate_Ban: String { return self._s[2884]! } + public var ShareMenu_ShareTo: String { return self._s[2884]! } + public var Conversation_Moderate_Ban: String { return self._s[2885]! } public func Conversation_DeleteMessagesFor(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2885]!, self._r[2885]!, [_0]) + return formatWithArgumentRanges(self._s[2886]!, self._r[2886]!, [_0]) } - public var SharedMedia_ViewInChat: String { return self._s[2886]! } - public var Map_LiveLocationFor8Hours: String { return self._s[2887]! } + public var SharedMedia_ViewInChat: String { return self._s[2887]! } + public var Map_LiveLocationFor8Hours: String { return self._s[2888]! } public func Map_AccurateTo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2889]!, self._r[2889]!, [_0]) + return formatWithArgumentRanges(self._s[2890]!, self._r[2890]!, [_0]) } - public var Appearance_ReduceMotion: String { return self._s[2890]! } - public var Map_OpenInHereMaps: String { return self._s[2891]! } - public var Channel_Setup_TypePublicHelp: String { return self._s[2892]! } - public var Passport_Identity_EditInternalPassport: String { return self._s[2893]! } - public var PhotoEditor_Skip: String { return self._s[2894]! } - public func MessagePoll_VotedCount(_ value: Int32) -> String { + public var Appearance_ReduceMotion: String { return self._s[2891]! } + public var Map_OpenInHereMaps: String { return self._s[2892]! } + public var Channel_Setup_TypePublicHelp: String { return self._s[2893]! } + public var Passport_Identity_EditInternalPassport: String { return self._s[2894]! } + public var PhotoEditor_Skip: String { return self._s[2895]! } + public func StickerPack_RemoveStickerCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, "\(value)") } - public func SharedMedia_Generic(_ value: Int32) -> String { + public func AttachmentMenu_SendGif(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Notification_GameScoreSelfExtended(_ value: Int32) -> String { + public func ServiceMessage_GameScoreSimple(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[2 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Conversation_StatusOnline(_ value: Int32) -> String { + public func MessageTimer_Months(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[3 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedGifs(_ value: Int32) -> String { + public func LiveLocation_MenuChatsCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[4 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessageTimer_ShortSeconds(_ value: Int32) -> String { + public func Forward_ConfirmMultipleFiles(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[5 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Map_ETAMinutes(_ value: Int32) -> String { + public func LiveLocationUpdated_MinutesAgo(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[6 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedLocations(_ value: Int32) -> String { + public func ForwardedStickers(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[7 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ChatList_DeleteConfirmation(_ value: Int32) -> String { + public func LastSeen_HoursAgo(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[8 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedVideos(_ value: Int32) -> String { + public func StickerPack_AddMaskCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[9 * 6 + Int(form.rawValue)]!, "\(value)") } - public func AttachmentMenu_SendItem(_ value: Int32) -> String { + public func UserCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[10 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Notifications_ExceptionMuteExpires_Minutes(_ value: Int32) -> String { + public func SharedMedia_DeleteItemsConfirmation(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[11 * 6 + Int(form.rawValue)]!, "\(value)") } - public func UserCount(_ value: Int32) -> String { + public func Notifications_Exceptions(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[12 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Conversation_LiveLocationMembersCount(_ value: Int32) -> String { + public func InviteText_ContactsCountText(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[13 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MuteFor_Days(_ value: Int32) -> String { + public func Notification_GameScoreSelfExtended(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[14 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedAuthorsOthers(_ value: Int32) -> String { + public func SharedMedia_File(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[15 * 6 + Int(form.rawValue)]!, "\(value)") } - public func StickerPack_AddStickerCount(_ value: Int32) -> String { + public func Notifications_ExceptionMuteExpires_Hours(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[16 * 6 + Int(form.rawValue)]!, "\(value)") } - public func QuickSend_Photos(_ value: Int32) -> String { + public func MessageTimer_ShortMinutes(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[17 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MuteFor_Hours(_ value: Int32) -> String { + public func Watch_UserInfo_Mute(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[18 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Call_Minutes(_ value: Int32) -> String { + public func MessageTimer_ShortDays(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[19 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Call_ShortMinutes(_ value: Int32) -> String { + public func SharedMedia_Photo(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[20 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Notifications_ExceptionMuteExpires_Days(_ value: Int32) -> String { + public func Invitation_Members(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[21 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessageTimer_ShortDays(_ value: Int32) -> String { + public func MessageTimer_ShortSeconds(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[22 * 6 + Int(form.rawValue)]!, "\(value)") } - public func SharedMedia_Link(_ value: Int32) -> String { + public func PasscodeSettings_FailedAttempts(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[23 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessageTimer_Minutes(_ value: Int32) -> String { + public func ForwardedMessages(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[24 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedFiles(_ value: Int32) -> String { + public func MessageTimer_Minutes(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[25 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessageTimer_Days(_ value: Int32) -> String { + public func MuteExpires_Days(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[26 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessageTimer_ShortWeeks(_ value: Int32) -> String { + public func MessageTimer_Hours(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[27 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Map_ETAHours(_ value: Int32) -> String { + public func Conversation_LiveLocationMembersCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[28 * 6 + Int(form.rawValue)]!, "\(value)") } - public func LiveLocationUpdated_MinutesAgo(_ value: Int32) -> String { + public func LastSeen_MinutesAgo(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[29 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Watch_LastSeen_MinutesAgo(_ value: Int32) -> String { + public func ForwardedAuthorsOthers(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[30 * 6 + Int(form.rawValue)]!, "\(value)") } - public func PasscodeSettings_FailedAttempts(_ value: Int32) -> String { + public func MuteExpires_Minutes(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[31 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedAudios(_ value: Int32) -> String { + public func Notification_GameScoreSelfSimple(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[32 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ServiceMessage_GameScoreSelfSimple(_ value: Int32) -> String { + public func Conversation_StatusMembers(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[33 * 6 + Int(form.rawValue)]!, "\(value)") } - public func AttachmentMenu_SendGif(_ value: Int32) -> String { + public func QuickSend_Photos(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[34 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Conversation_StatusSubscribers(_ value: Int32) -> String { + public func ForwardedVideos(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[35 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Notification_GameScoreSimple(_ value: Int32) -> String { + public func StickerPack_AddStickerCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[36 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Media_ShareItem(_ value: Int32) -> String { + public func Watch_LastSeen_HoursAgo(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[37 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Passport_Scans(_ value: Int32) -> String { + public func Map_ETAMinutes(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[38 * 6 + Int(form.rawValue)]!, "\(value)") } - public func AttachmentMenu_SendPhoto(_ value: Int32) -> String { + public func ForwardedVideoMessages(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[39 * 6 + Int(form.rawValue)]!, "\(value)") } - public func SharedMedia_DeleteItemsConfirmation(_ value: Int32) -> String { + public func MuteFor_Hours(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[40 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedVideoMessages(_ value: Int32) -> String { + public func MessageTimer_Days(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[41 * 6 + Int(form.rawValue)]!, "\(value)") } - public func LiveLocation_MenuChatsCount(_ value: Int32) -> String { + public func Media_ShareVideo(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[42 * 6 + Int(form.rawValue)]!, "\(value)") } - public func StickerPack_RemoveMaskCount(_ value: Int32) -> String { + public func SharedMedia_Generic(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[43 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Notifications_ExceptionMuteExpires_Hours(_ value: Int32) -> String { + public func AttachmentMenu_SendItem(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[44 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Notifications_Exceptions(_ value: Int32) -> String { + public func Notifications_ExceptionMuteExpires_Days(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[45 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessageTimer_ShortMinutes(_ value: Int32) -> String { + public func GroupInfo_ParticipantCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[46 * 6 + Int(form.rawValue)]!, "\(value)") } @@ -3446,155 +3447,155 @@ public final class PresentationStrings { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[47 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MuteExpires_Minutes(_ value: Int32) -> String { + public func MessageTimer_Seconds(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[48 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Contacts_ImportersCount(_ value: Int32) -> String { + public func StickerPack_RemoveMaskCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[49 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MuteExpires_Days(_ value: Int32) -> String { + public func ServiceMessage_GameScoreSelfSimple(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[50 * 6 + Int(form.rawValue)]!, "\(value)") } - public func GroupInfo_ParticipantCount(_ value: Int32) -> String { + public func SharedMedia_Video(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[51 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessageTimer_Months(_ value: Int32) -> String { + public func MessageTimer_Weeks(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[52 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Invitation_Members(_ value: Int32) -> String { + public func ForwardedPolls(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[53 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Media_SharePhoto(_ value: Int32) -> String { + public func SharedMedia_Link(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[54 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Media_ShareVideo(_ value: Int32) -> String { + public func ForwardedAudios(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[55 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedMessages(_ value: Int32) -> String { + public func Notification_GameScoreSimple(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[56 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ServiceMessage_GameScoreExtended(_ value: Int32) -> String { + public func DialogList_LiveLocationChatsCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[57 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedPhotos(_ value: Int32) -> String { + public func ForwardedGifs(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[58 * 6 + Int(form.rawValue)]!, "\(value)") } - public func LastSeen_HoursAgo(_ value: Int32) -> String { + public func ForwardedPhotos(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[59 * 6 + Int(form.rawValue)]!, "\(value)") } - public func DialogList_LiveLocationChatsCount(_ value: Int32) -> String { + public func CreatePoll_AddMoreOptions(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[60 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessageTimer_ShortHours(_ value: Int32) -> String { + public func ServiceMessage_GameScoreExtended(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[61 * 6 + Int(form.rawValue)]!, "\(value)") } - public func StickerPack_StickerCount(_ value: Int32) -> String { + public func ForwardedLocations(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[62 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ServiceMessage_GameScoreSelfExtended(_ value: Int32) -> String { + public func Watch_LastSeen_MinutesAgo(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[63 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Watch_LastSeen_HoursAgo(_ value: Int32) -> String { + public func Passport_Scans(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[64 * 6 + Int(form.rawValue)]!, "\(value)") } - public func SharedMedia_Photo(_ value: Int32) -> String { + public func Conversation_StatusSubscribers(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[65 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ServiceMessage_GameScoreSimple(_ value: Int32) -> String { + public func Contacts_ImportersCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[66 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Call_ShortSeconds(_ value: Int32) -> String { + public func Media_ShareItem(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[67 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Forward_ConfirmMultipleFiles(_ value: Int32) -> String { + public func MessageTimer_ShortHours(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[68 * 6 + Int(form.rawValue)]!, "\(value)") } - public func CreatePoll_AddMoreOptions(_ value: Int32) -> String { + public func Notifications_ExceptionMuteExpires_Minutes(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[69 * 6 + Int(form.rawValue)]!, "\(value)") } - public func StickerPack_AddMaskCount(_ value: Int32) -> String { + public func ForwardedContacts(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[70 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedContacts(_ value: Int32) -> String { + public func ChatList_DeleteConfirmation(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[71 * 6 + Int(form.rawValue)]!, "\(value)") } - public func SharedMedia_Video(_ value: Int32) -> String { + public func Call_Minutes(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[72 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessageTimer_Seconds(_ value: Int32) -> String { + public func ServiceMessage_GameScoreSelfExtended(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[73 * 6 + Int(form.rawValue)]!, "\(value)") } - public func LastSeen_MinutesAgo(_ value: Int32) -> String { + public func Notification_GameScoreExtended(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[74 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessageTimer_Weeks(_ value: Int32) -> String { + public func MessageTimer_ShortWeeks(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[75 * 6 + Int(form.rawValue)]!, "\(value)") } - public func SharedMedia_File(_ value: Int32) -> String { + public func StickerPack_StickerCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[76 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Conversation_StatusMembers(_ value: Int32) -> String { + public func Call_ShortMinutes(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[77 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Watch_UserInfo_Mute(_ value: Int32) -> String { + public func Media_SharePhoto(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[78 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessageTimer_Hours(_ value: Int32) -> String { + public func MessageTimer_Years(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[79 * 6 + Int(form.rawValue)]!, "\(value)") } - public func InviteText_ContactsCountText(_ value: Int32) -> String { + public func MessagePoll_VotedCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[80 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Notification_GameScoreSelfSimple(_ value: Int32) -> String { + public func AttachmentMenu_SendPhoto(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[81 * 6 + Int(form.rawValue)]!, "\(value)") } - public func PrivacyLastSeenSettings_AddUsers(_ value: Int32) -> String { + public func Call_ShortSeconds(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[82 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Notification_GameScoreExtended(_ value: Int32) -> String { + public func PrivacyLastSeenSettings_AddUsers(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[83 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessageTimer_Years(_ value: Int32) -> String { + public func Conversation_StatusOnline(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[84 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedPolls(_ value: Int32) -> String { + public func ForwardedFiles(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[85 * 6 + Int(form.rawValue)]!, "\(value)") } @@ -3602,15 +3603,15 @@ public final class PresentationStrings { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[86 * 6 + Int(form.rawValue)]!, "\(value)") } - public func StickerPack_RemoveStickerCount(_ value: Int32) -> String { + public func Call_Seconds(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[87 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Call_Seconds(_ value: Int32) -> String { + public func MuteFor_Days(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[88 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedStickers(_ value: Int32) -> String { + public func Map_ETAHours(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[89 * 6 + Int(form.rawValue)]!, "\(value)") } diff --git a/TelegramUI/QRCode.swift b/TelegramUI/QRCode.swift index c657dd3cd6..3d1168a7b2 100644 --- a/TelegramUI/QRCode.swift +++ b/TelegramUI/QRCode.swift @@ -3,7 +3,7 @@ import CoreImage import SwiftSignalKit import Display -func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = nil) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { +func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = nil, scale: CGFloat = 0.0) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { return Signal { subscriber in if let data = string.data(using: .isoLatin1, allowLossyConversion: false), let filter = CIFilter(name: "CIQRCodeGenerator") { filter.setValue(data, forKey: "inputMessage") @@ -18,7 +18,7 @@ func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = nil) -> } |> map { inputImage in return { arguments in - let context = DrawingContext(size: arguments.drawingSize, clear: true) + let context = DrawingContext(size: arguments.drawingSize, scale: scale, clear: true) let drawingRect = arguments.drawingRect let fittedSize = arguments.imageSize.aspectFilled(arguments.boundingSize).fitted(arguments.imageSize) @@ -56,8 +56,12 @@ func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = nil) -> c.fill(fittedRect) c.restoreGState() } - c.setBlendMode(.clear) - c.setFillColor(UIColor.clear.cgColor) + if let backgroundColor = backgroundColor { + c.setFillColor(backgroundColor.cgColor) + } else { + c.setBlendMode(.clear) + c.setFillColor(UIColor.clear.cgColor) + } let clipOrigin = 93.0 * fittedRect.width / 267.0 let clipSide = 81.0 * fittedRect.width / 267.0 @@ -72,8 +76,12 @@ func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = nil) -> c.setFillColor(color.cgColor) let _ = try? drawSvgPath(c, path: "M0.0,40 C0,20.3664202 20.1230605,0.0 32.5,0.0 C44.8769395,0.0 65,20.3664202 65,40 C65,47.217934 65,55.5505326 65,64.9977957 L32.5,79 L0.0,64.9977957 C0.0,55.0825772 0.0,46.7499786 0.0,40 Z") - c.setBlendMode(.clear) - c.setFillColor(UIColor.clear.cgColor) + if false, let backgroundColor = backgroundColor { + c.setFillColor(backgroundColor.cgColor) + } else { + c.setBlendMode(.clear) + c.setFillColor(UIColor.clear.cgColor) + } let _ = try? drawSvgPath(c, path: "M7.03608247,43.556701 L18.9836689,32.8350515 L32.5,39.871134 L45.8888139,32.8350515 L57.9639175,43.556701 L57.9639175,60.0 L32.5,71.0 L7.03608247,60.0 Z") c.setBlendMode(.normal) diff --git a/TelegramUI/RadialDownloadContentNode.swift b/TelegramUI/RadialDownloadContentNode.swift index 39f906f7f1..ec0bc70d36 100644 --- a/TelegramUI/RadialDownloadContentNode.swift +++ b/TelegramUI/RadialDownloadContentNode.swift @@ -188,14 +188,15 @@ final class RadialDownloadContentNode: RadialStatusContentNode { override func animateIn(from: RadialStatusNodeState) { if case .progress = from { - self.arrowBody.animateStrokeStart(from: 0.0, to: 0.62, duration: 0.5, removeOnCompletion: false, completion: nil) - self.arrowBody.animateStrokeEnd(from: 0.0, to: 1.0, duration: 0.5, removeOnCompletion: false, completion: nil) + self.arrowBody.animateStrokeStart(from: 0.62, to: 0.62, duration: 0.25, removeOnCompletion: false, completion: nil) + self.arrowBody.animateStrokeEnd(from: 0.62, to: 1.0, duration: 0.25, removeOnCompletion: false, completion: nil) - self.leftLine.animateStrokeEnd(from: 0.0, to: 1.0, duration: 0.2, delay: 0.3, removeOnCompletion: false) - self.rightLine.animateStrokeEnd(from: 0.0, to: 1.0, duration: 0.2, delay: 0.3, removeOnCompletion: false) + self.leftLine.animateStrokeEnd(from: 0.0, to: 1.0, duration: 0.25, delay: 0.0, removeOnCompletion: false) + self.rightLine.animateStrokeEnd(from: 0.0, to: 1.0, duration: 0.25, delay: 0.0, removeOnCompletion: false) - self.leftLine.animateAlpha(from: 0.0, to: 1.0, duration: 0.2, delay: 0.1, removeOnCompletion: false) - self.rightLine.animateAlpha(from: 0.0, to: 1.0, duration: 0.2, delay: 0.1, removeOnCompletion: false) + self.arrowBody.animateAlpha(from: 0.0, to: 1.0, duration: 0.25, delay: 0.0, removeOnCompletion: false) + self.leftLine.animateAlpha(from: 0.0, to: 1.0, duration: 0.25, delay: 0.0, removeOnCompletion: false) + self.rightLine.animateAlpha(from: 0.0, to: 1.0, duration: 0.25, delay: 0.0, removeOnCompletion: false) } else { self.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration) self.layer.animateScale(from: 0.7, to: 1.0, duration: duration) diff --git a/TelegramUI/RadialPlayPauseContentNode.swift b/TelegramUI/RadialPlayPauseContentNode.swift new file mode 100644 index 0000000000..65fe53d3e8 --- /dev/null +++ b/TelegramUI/RadialPlayPauseContentNode.swift @@ -0,0 +1,60 @@ +import Foundation +import Display +import AsyncDisplayKit +import LegacyComponents +import SwiftSignalKit + +enum RadialPlayPauseMode { + case play + case pause +} + +class RadialPlayPauseContentNode: RadialStatusContentNode { + var color: UIColor { + didSet { + self.leftShape.fillColor = self.color.cgColor + self.rightShape.fillColor = self.color.cgColor + self.setNeedsDisplay() + } + } + + private var effectiveProgress: CGFloat = 1.0 { + didSet { + self.setNeedsDisplay() + } + } + + private var animationCompletionTimer: SwiftSignalKit.Timer? + + private var isAnimatingProgress: Bool { + return self.pop_animation(forKey: "progress") != nil || self.animationCompletionTimer != nil + } + + private var enqueuedReadyForTransition: (() -> Void)? + + private let leftShape = CAShapeLayer() + private let rightShape = CAShapeLayer() + + init(color: UIColor, mode: RadialPlayPauseMode) { + self.color = color + + super.init() + + self.leftShape.fillColor = self.color.cgColor + self.rightShape.fillColor = self.color.cgColor + + self.isLayerBacked = true + self.isOpaque = false + + self.layer.addSublayer(self.leftShape) + self.layer.addSublayer(self.rightShape) + } + + override func enqueueReadyForTransition(_ f: @escaping () -> Void) { + if self.isAnimatingProgress { + self.enqueuedReadyForTransition = f + } else { + f() + } + } +} diff --git a/TelegramUI/RadialProgressContentNode.swift b/TelegramUI/RadialProgressContentNode.swift index 935f837354..4317777ad8 100644 --- a/TelegramUI/RadialProgressContentNode.swift +++ b/TelegramUI/RadialProgressContentNode.swift @@ -291,14 +291,16 @@ final class RadialProgressContentNode: RadialStatusContentNode { self.cancelNode.frame = bounds } - private let duration: Double = 0.2 - - override func animateOut(to: RadialStatusNodeState, completion: @escaping () -> Void) { - self.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration, removeOnCompletion: false, completion: { _ in + override func prepareAnimateOut(completion: @escaping () -> Void) { + self.cancelNode.layer.animateScale(from: 1.0, to: 0.2, duration: 0.15, removeOnCompletion: false, completion: { _ in + completion() + }) + } + + override func animateOut(to: RadialStatusNodeState, completion: @escaping () -> Void) { + self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false, completion: { _ in completion() }) - self.cancelNode.layer.animateScale(from: 1.0, to: 0.2, duration: duration, removeOnCompletion: false) - self.cancelNode.layer.animateRotation(from: 0.0, to: CGFloat.pi / 3.0, duration: duration) } override func prepareAnimateIn(from: RadialStatusNodeState?) { @@ -309,9 +311,8 @@ final class RadialProgressContentNode: RadialStatusContentNode { override func animateIn(from: RadialStatusNodeState) { if case .download = from { } else { - self.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration) + self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) } - self.cancelNode.layer.animateScale(from: 0.2, to: 1.0, duration: duration) - self.cancelNode.layer.animateRotation(from: -CGFloat.pi / 3.0, to: 0.0, duration: duration) + self.cancelNode.layer.animateScale(from: 0.2, to: 1.0, duration: 0.2) } } diff --git a/TelegramUI/Resources/PresentationStrings.mapping b/TelegramUI/Resources/PresentationStrings.mapping index 40d51fae036b9321f740ef66e52080273d4d7d1e..b5aa8c7b1a203d92d49b046cae8b559e280d9bb7 100644 GIT binary patch delta 17485 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 L)v>(8Cldc3p~4^+ delta 17351 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 UIImage? { return generateTintedImage(image: UIImage(bundleImageName: "Components/Search Bar/Clear"), color: color) } -private func generateBackground(backgroundColor: UIColor, foregroundColor: UIColor) -> UIImage? { - let diameter: CGFloat = 14.0 +private func generateBackground(backgroundColor: UIColor, foregroundColor: UIColor, diameter: CGFloat) -> UIImage? { return generateImage(CGSize(width: diameter, height: diameter), contextGenerator: { size, context in context.setFillColor(backgroundColor.cgColor) context.fill(CGRect(origin: CGPoint(), size: size)) @@ -103,11 +102,16 @@ private class SearchBarTextField: UITextField { return } - let constrainedSize = self.textRect(forBounds: self.bounds).size - let labelSize = self.placeholderLabel.measure(constrainedSize) - self.placeholderLabel.frame = CGRect(origin: CGPoint(x: self.textRect(forBounds: bounds).minX, y: self.textRect(forBounds: bounds).minY + 1.0), size: labelSize) + var textOffset: CGFloat = 1.0 + if bounds.height >= 36.0 { + textOffset += 2.0 + } - let prefixSize = self.prefixLabel.measure(constrainedSize) + let textRect = self.textRect(forBounds: bounds) + let labelSize = self.placeholderLabel.measure(textRect.size) + self.placeholderLabel.frame = CGRect(origin: CGPoint(x: textRect.minX, y: textRect.minY + textOffset), size: labelSize) + + let prefixSize = self.prefixLabel.measure(textRect.size) let prefixBounds = bounds.insetBy(dx: 4.0, dy: 4.0) self.prefixLabel.frame = CGRect(origin: CGPoint(x: prefixBounds.minX, y: prefixBounds.minY + 1.0), size: prefixSize) } @@ -187,6 +191,47 @@ final class SearchBarNodeTheme: Equatable { } } +enum SearchBarStyle { + case modern + case legacy + + var font: UIFont { + switch self { + case .modern: + return Font.regular(17.0) + case .legacy: + return Font.regular(14.0) + } + } + + var cornerDiameter: CGFloat { + switch self { + case .modern: + return 21.0 + case .legacy: + return 14.0 + } + } + + var height: CGFloat { + switch self { + case .modern: + return 36.0 + case .legacy: + return 28.0 + } + } + + var padding: CGFloat { + switch self { + case .modern: + return 10.0 + case .legacy: + return 8.0 + } + } +} + class SearchBarNode: ASDisplayNode, UITextFieldDelegate { var cancel: (() -> Void)? var textUpdated: ((String) -> Void)? @@ -272,10 +317,13 @@ class SearchBarNode: ASDisplayNode, UITextFieldDelegate { private var validLayout: (CGSize, CGFloat, CGFloat)? + private let fieldStyle: SearchBarStyle private var theme: SearchBarNodeTheme? private var strings: PresentationStrings? - init(theme: SearchBarNodeTheme, strings: PresentationStrings) { + init(theme: SearchBarNodeTheme, strings: PresentationStrings, fieldStyle: SearchBarStyle = .legacy) { + self.fieldStyle = fieldStyle + self.backgroundNode = ASDisplayNode() self.backgroundNode.isLayerBacked = true @@ -295,7 +343,7 @@ class SearchBarNode: ASDisplayNode, UITextFieldDelegate { self.textField = SearchBarTextField() self.textField.autocorrectionType = .no self.textField.returnKeyType = .search - self.textField.font = Font.regular(14.0) + self.textField.font = self.fieldStyle.font self.clearButton = HighlightableButtonNode() self.clearButton.imageNode.displaysAsynchronously = false @@ -338,7 +386,7 @@ class SearchBarNode: ASDisplayNode, UITextFieldDelegate { if self.theme != theme { self.backgroundNode.backgroundColor = theme.background self.separatorNode.backgroundColor = theme.separator - self.textBackgroundNode.image = generateBackground(backgroundColor: theme.background, foregroundColor: theme.inputFill) + self.textBackgroundNode.image = generateBackground(backgroundColor: theme.background, foregroundColor: theme.inputFill, diameter: self.fieldStyle.cornerDiameter) self.textField.textColor = theme.primaryText self.clearButton.setImage(generateClearIcon(color: theme.inputClear), for: []) self.iconNode.image = generateLoupeIcon(color: theme.inputIcon) @@ -366,13 +414,15 @@ class SearchBarNode: ASDisplayNode, UITextFieldDelegate { let contentFrame = CGRect(origin: CGPoint(x: leftInset, y: 0.0), size: CGSize(width: boundingSize.width - leftInset - rightInset, height: boundingSize.height)) + let textBackgroundHeight = self.fieldStyle.height let cancelButtonSize = self.cancelButton.measure(CGSize(width: 100.0, height: CGFloat.infinity)) - transition.updateFrame(node: self.cancelButton, frame: CGRect(origin: CGPoint(x: contentFrame.maxX - 8.0 - cancelButtonSize.width, y: verticalOffset + 31.0), size: cancelButtonSize)) + transition.updateFrame(node: self.cancelButton, frame: CGRect(origin: CGPoint(x: contentFrame.maxX - 8.0 - cancelButtonSize.width, y: verticalOffset + textBackgroundHeight + floorToScreenPixels((textBackgroundHeight - cancelButtonSize.height) / 2.0)), size: cancelButtonSize)) - let textBackgroundFrame = CGRect(origin: CGPoint(x: contentFrame.minX + 8.0, y: verticalOffset + 28.0), size: CGSize(width: contentFrame.width - 16.0 - (self.hasCancelButton ? cancelButtonSize.width + 11.0 : 0.0), height: 28.0)) + let padding = self.fieldStyle.padding + let textBackgroundFrame = CGRect(origin: CGPoint(x: contentFrame.minX + padding, y: verticalOffset + textBackgroundHeight), size: CGSize(width: contentFrame.width - padding * 2.0 - (self.hasCancelButton ? cancelButtonSize.width + 11.0 : 0.0), height: textBackgroundHeight)) transition.updateFrame(node: self.textBackgroundNode, frame: textBackgroundFrame) - let textFrame = CGRect(origin: CGPoint(x: textBackgroundFrame.minX + 23.0, y: textBackgroundFrame.minY), size: CGSize(width: max(1.0, textBackgroundFrame.size.width - 23.0 - 20.0), height: textBackgroundFrame.size.height)) + let textFrame = CGRect(origin: CGPoint(x: textBackgroundFrame.minX + 24.0, y: textBackgroundFrame.minY), size: CGSize(width: max(1.0, textBackgroundFrame.size.width - 24.0 - 20.0), height: textBackgroundFrame.size.height)) if let iconImage = self.iconNode.image { let iconSize = iconImage.size @@ -428,7 +478,7 @@ class SearchBarNode: ASDisplayNode, UITextFieldDelegate { self.iconNode.layer.animateFrame(from: initialIconFrame, to: self.iconNode.frame, duration: duration, timingFunction: timingFunction) let cancelButtonFrame = self.cancelButton.frame - self.cancelButton.layer.animatePosition(from: CGPoint(x: self.bounds.size.width + cancelButtonFrame.size.width / 2.0, y: initialTextBackgroundFrame.minY + 2.0 + cancelButtonFrame.size.height / 2.0), to: self.cancelButton.layer.position, duration: duration, timingFunction: timingFunction) + self.cancelButton.layer.animatePosition(from: CGPoint(x: self.bounds.size.width + cancelButtonFrame.size.width / 2.0, y: initialTextBackgroundFrame.midY), to: self.cancelButton.layer.position, duration: duration, timingFunction: timingFunction) node.isHidden = true } @@ -483,11 +533,11 @@ class SearchBarNode: ASDisplayNode, UITextFieldDelegate { intermediateCompletion() }) - let transitionBackgroundNode = ASImageNode() + let transitionBackgroundNode = ASDisplayNode() transitionBackgroundNode.isLayerBacked = true transitionBackgroundNode.displaysAsynchronously = false - transitionBackgroundNode.displayWithoutProcessing = true - transitionBackgroundNode.image = node.backgroundNode.image + transitionBackgroundNode.backgroundColor = node.backgroundNode.backgroundColor + transitionBackgroundNode.cornerRadius = node.backgroundNode.cornerRadius self.insertSubnode(transitionBackgroundNode, aboveSubnode: self.textBackgroundNode) transitionBackgroundNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration / 2.0, removeOnCompletion: false) transitionBackgroundNode.layer.animateFrame(from: self.textBackgroundNode.frame, to: targetTextBackgroundFrame, duration: duration, timingFunction: timingFunction, removeOnCompletion: false) @@ -509,7 +559,7 @@ class SearchBarNode: ASDisplayNode, UITextFieldDelegate { self.iconNode.layer.animateFrame(from: self.iconNode.frame, to: targetIconFrame, duration: duration, timingFunction: timingFunction, removeOnCompletion: false) let cancelButtonFrame = self.cancelButton.frame - self.cancelButton.layer.animatePosition(from: self.cancelButton.layer.position, to: CGPoint(x: self.bounds.size.width + cancelButtonFrame.size.width / 2.0, y: targetTextBackgroundFrame.minY + 2.0 + cancelButtonFrame.size.height / 2.0), duration: duration, timingFunction: timingFunction, removeOnCompletion: false) + self.cancelButton.layer.animatePosition(from: self.cancelButton.layer.position, to: CGPoint(x: self.bounds.size.width + cancelButtonFrame.size.width / 2.0, y: targetTextBackgroundFrame.midY), duration: duration, timingFunction: timingFunction, removeOnCompletion: false) } func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { @@ -534,8 +584,13 @@ class SearchBarNode: ASDisplayNode, UITextFieldDelegate { } } + func selectAll() { + self.textField.becomeFirstResponder() + self.textField.selectAll(nil) + } + private func updateIsEmpty() { - let isEmpty = !(textField.text?.isEmpty ?? true) + let isEmpty = !(self.textField.text?.isEmpty ?? true) if isEmpty != self.textField.placeholderLabel.isHidden { self.textField.placeholderLabel.isHidden = isEmpty } diff --git a/TelegramUI/SearchBarPlaceholderNode.swift b/TelegramUI/SearchBarPlaceholderNode.swift index 09310f7bdc..73915eda0f 100644 --- a/TelegramUI/SearchBarPlaceholderNode.swift +++ b/TelegramUI/SearchBarPlaceholderNode.swift @@ -10,8 +10,7 @@ private func generateLoupeIcon(color: UIColor) -> UIImage? { return generateTintedImage(image: templateLoupeIcon, color: color) } -private func generateBackground(backgroundColor: UIColor, foregroundColor: UIColor) -> UIImage? { - let diameter: CGFloat = 10.0 +private func generateBackground(backgroundColor: UIColor, foregroundColor: UIColor, diameter: CGFloat) -> UIImage? { return generateImage(CGSize(width: diameter, height: diameter), contextGenerator: { size, context in context.setFillColor(backgroundColor.cgColor) context.fill(CGRect(origin: CGPoint(), size: size)) @@ -29,10 +28,11 @@ private class SearchBarPlaceholderNodeView: UIView { } } -class SearchBarPlaceholderNode: ASDisplayNode, ASEditableTextNodeDelegate { +class SearchBarPlaceholderNode: ASDisplayNode { var activate: (() -> Void)? - let backgroundNode: ASImageNode + private let fieldStyle: SearchBarStyle + let backgroundNode: ASDisplayNode private var fillBackgroundColor: UIColor private var foregroundColor: UIColor private var iconColor: UIColor @@ -41,17 +41,23 @@ class SearchBarPlaceholderNode: ASDisplayNode, ASEditableTextNodeDelegate { private(set) var placeholderString: NSAttributedString? - override init() { - self.backgroundNode = ASImageNode() + convenience override init() { + self.init(fieldStyle: .legacy) + } + + init(fieldStyle: SearchBarStyle = .legacy) { + self.fieldStyle = fieldStyle + + self.backgroundNode = ASDisplayNode() self.backgroundNode.isLayerBacked = false self.backgroundNode.displaysAsynchronously = false - self.backgroundNode.displayWithoutProcessing = true self.fillBackgroundColor = UIColor.white self.foregroundColor = UIColor(rgb: 0xededed) self.iconColor = UIColor(rgb: 0x000000, alpha: 0.0) - self.backgroundNode.image = generateBackground(backgroundColor: self.fillBackgroundColor, foregroundColor: self.foregroundColor) + self.backgroundNode.backgroundColor = self.foregroundColor + self.backgroundNode.cornerRadius = self.fieldStyle.cornerDiameter / 2.0 self.iconNode = ASImageNode() self.iconNode.isLayerBacked = true @@ -78,19 +84,18 @@ class SearchBarPlaceholderNode: ASDisplayNode, ASEditableTextNodeDelegate { self.backgroundNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(backgroundTap(_:)))) } - func asyncLayout() -> (_ placeholderString: NSAttributedString?, _ constrainedSize: CGSize, _ iconColor: UIColor, _ foregroundColor: UIColor, _ backgroundColor: UIColor) -> (() -> Void) { + func asyncLayout() -> (_ placeholderString: NSAttributedString?, _ constrainedSize: CGSize, _ expansionProgress: CGFloat, _ iconColor: UIColor, _ foregroundColor: UIColor, _ backgroundColor: UIColor, _ transition: ContainedViewLayoutTransition) -> (() -> Void) { let labelLayout = TextNode.asyncLayout(self.labelNode) - let currentFillBackgroundColor = self.fillBackgroundColor let currentForegroundColor = self.foregroundColor let currentIconColor = self.iconColor - return { placeholderString, constrainedSize, iconColor, foregroundColor, backgroundColor in + return { placeholderString, constrainedSize, expansionProgress, iconColor, foregroundColor, backgroundColor, transition in let (labelLayoutResult, labelApply) = labelLayout(TextNodeLayoutArguments(attributedString: placeholderString, backgroundColor: foregroundColor, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: constrainedSize, alignment: .natural, cutout: nil, insets: UIEdgeInsets())) - var updatedBackgroundImage: UIImage? + var updatedColor: UIColor? var updatedIconImage: UIImage? - if !currentFillBackgroundColor.isEqual(backgroundColor) || !currentForegroundColor.isEqual(foregroundColor) { - updatedBackgroundImage = generateBackground(backgroundColor: backgroundColor, foregroundColor: foregroundColor) + if !currentForegroundColor.isEqual(foregroundColor) { + updatedColor = foregroundColor } if !currentIconColor.isEqual(iconColor) { updatedIconImage = generateLoupeIcon(color: iconColor) @@ -103,9 +108,10 @@ class SearchBarPlaceholderNode: ASDisplayNode, ASEditableTextNodeDelegate { strongSelf.fillBackgroundColor = backgroundColor strongSelf.foregroundColor = foregroundColor strongSelf.iconColor = iconColor - if let updatedBackgroundImage = updatedBackgroundImage { - strongSelf.backgroundNode.image = updatedBackgroundImage - strongSelf.labelNode.backgroundColor = foregroundColor + strongSelf.backgroundNode.isUserInteractionEnabled = expansionProgress > 1.0 - CGFloat.ulpOfOne + + if let updatedColor = updatedColor { + strongSelf.backgroundNode.backgroundColor = updatedColor } if let updatedIconImage = updatedIconImage { strongSelf.iconNode.image = updatedIconImage @@ -113,14 +119,32 @@ class SearchBarPlaceholderNode: ASDisplayNode, ASEditableTextNodeDelegate { strongSelf.placeholderString = placeholderString - let labelFrame = CGRect(origin: CGPoint(x: floor((constrainedSize.width - labelLayoutResult.size.width) / 2.0), y: floorToScreenPixels((28.0 - labelLayoutResult.size.height) / 2.0)), size: labelLayoutResult.size) - strongSelf.labelNode.frame = labelFrame + var iconSize = CGSize() + var totalWidth = labelLayoutResult.size.width + let spacing: CGFloat = 7.0 + let height = constrainedSize.height * expansionProgress + if let iconImage = strongSelf.iconNode.image { - let iconSize = iconImage.size - strongSelf.iconNode.frame = CGRect(origin: CGPoint(x: labelFrame.minX - 4.0 - iconSize.width, y: floorToScreenPixels((28.0 - iconSize.height) / 2.0)), size: iconSize) + iconSize = iconImage.size + totalWidth += iconSize.width + spacing + transition.updateFrame(node: strongSelf.iconNode, frame: CGRect(origin: CGPoint(x: floor((constrainedSize.width - totalWidth) / 2.0), y: floorToScreenPixels((height - iconSize.height) / 2.0)), size: iconSize)) } - strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: constrainedSize.width, height: 28.0)) - strongSelf.backgroundColor = backgroundColor + var textOffset: CGFloat = 0.0 + if constrainedSize.height >= 36.0 { + textOffset += UIScreenPixel + } + let labelFrame = CGRect(origin: CGPoint(x: floor((constrainedSize.width - totalWidth) / 2.0) + iconSize.width + spacing, y: floorToScreenPixels((height - labelLayoutResult.size.height) / 2.0) + textOffset), size: labelLayoutResult.size) + transition.updateFrame(node: strongSelf.labelNode, frame: labelFrame) + + let innerAlpha = max(0.0, expansionProgress - 0.77) / 0.23 + transition.updateAlpha(node: strongSelf.labelNode, alpha: innerAlpha) + transition.updateAlpha(node: strongSelf.iconNode, alpha: innerAlpha) + let outerAlpha = min(0.3, expansionProgress) / 0.3 + + let cornerRadius = min(strongSelf.fieldStyle.cornerDiameter / 2.0, height / 2.0) + strongSelf.backgroundNode.cornerRadius = cornerRadius + transition.updateAlpha(node: strongSelf.backgroundNode, alpha: outerAlpha) + transition.updateFrame(node: strongSelf.backgroundNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: constrainedSize.width, height: height))) } } } diff --git a/TelegramUI/SearchDisplayController.swift b/TelegramUI/SearchDisplayController.swift index dd11bf2cba..9dea04e88b 100644 --- a/TelegramUI/SearchDisplayController.swift +++ b/TelegramUI/SearchDisplayController.swift @@ -3,8 +3,14 @@ import AsyncDisplayKit import SwiftSignalKit import Display +enum SearchDisplayControllerMode { + case standalone + case navigation +} + final class SearchDisplayController { private let searchBar: SearchBarNode + private let mode: SearchDisplayControllerMode let contentNode: SearchDisplayControllerContentNode private var containerLayout: (ContainerViewLayout, CGFloat)? @@ -13,8 +19,19 @@ final class SearchDisplayController { private var isSearchingDisposable: Disposable? - init(theme: PresentationTheme, strings: PresentationStrings, contentNode: SearchDisplayControllerContentNode, cancel: @escaping () -> Void) { - self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: theme), strings: strings) + init(theme: PresentationTheme, strings: PresentationStrings, mode: SearchDisplayControllerMode = .standalone, contentNode: SearchDisplayControllerContentNode, cancel: @escaping () -> Void) { + let active: Bool + let searchBarStyle: SearchBarStyle + switch mode { + case .standalone: + active = true + searchBarStyle = .legacy + case .navigation: + active = false + searchBarStyle = .modern + } + self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: theme, active: active), strings: strings, fieldStyle: searchBarStyle) + self.mode = mode self.contentNode = contentNode self.searchBar.textUpdated = { [weak contentNode] text in @@ -39,7 +56,14 @@ final class SearchDisplayController { } func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings) { - self.searchBar.updateThemeAndStrings(theme: SearchBarNodeTheme(theme: theme), strings: strings) + let active: Bool + switch mode { + case .standalone: + active = true + case .navigation: + active = false + } + self.searchBar.updateThemeAndStrings(theme: SearchBarNodeTheme(theme: theme, active: active), strings: strings) } func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) { @@ -56,8 +80,15 @@ final class SearchDisplayController { navigationBarFrame.size.height = 64.0 } - transition.updateFrame(node: self.searchBar, frame: navigationBarFrame) - self.searchBar.updateLayout(boundingSize: navigationBarFrame.size, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, transition: transition) + let searchBarFrame: CGRect + if case .navigation = self.mode { + searchBarFrame = CGRect(x: 0.0, y: 0.0, width: layout.size.width, height: 36.0) + navigationBarFrame.size.height += 10.0 + } else { + searchBarFrame = navigationBarFrame + } + transition.updateFrame(node: self.searchBar, frame: searchBarFrame) + self.searchBar.updateLayout(boundingSize: searchBarFrame.size, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, transition: transition) self.containerLayout = (layout, navigationBarFrame.maxY) @@ -65,17 +96,17 @@ final class SearchDisplayController { self.contentNode.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: LayoutMetrics(), intrinsicInsets: layout.intrinsicInsets, safeInsets: layout.safeInsets, statusBarHeight: nil, inputHeight: layout.inputHeight, standardInputHeight: layout.standardInputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging), navigationBarHeight: navigationBarFrame.maxY, transition: transition) } - func activate(insertSubnode: (ASDisplayNode) -> Void, placeholder: SearchBarPlaceholderNode) { + func activate(insertSubnode: (ASDisplayNode, Bool) -> Void, placeholder: SearchBarPlaceholderNode) { guard let (layout, navigationBarHeight) = self.containerLayout else { return } - insertSubnode(self.contentNode) + insertSubnode(self.contentNode, false) self.contentNode.frame = CGRect(origin: CGPoint(), size: layout.size) self.contentNode.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: LayoutMetrics(), intrinsicInsets: UIEdgeInsets(), safeInsets: layout.safeInsets, statusBarHeight: nil, inputHeight: nil, standardInputHeight: layout.standardInputHeight, inputHeightIsInteractivellyChanging: false), navigationBarHeight: navigationBarHeight, transition: .immediate) - let initialTextBackgroundFrame = placeholder.convert(placeholder.backgroundNode.frame, to: self.contentNode.supernode) + let initialTextBackgroundFrame = placeholder.convert(placeholder.backgroundNode.frame, to: nil)//self.contentNode.supernode) let contentNodePosition = self.contentNode.layer.position self.contentNode.layer.animatePosition(from: CGPoint(x: contentNodePosition.x, y: contentNodePosition.y + (initialTextBackgroundFrame.maxY + 8.0 - navigationBarHeight)), to: contentNodePosition, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring) @@ -83,21 +114,28 @@ final class SearchDisplayController { self.searchBar.placeholderString = placeholder.placeholderString - let statusBarHeight: CGFloat = layout.statusBarHeight ?? 0.0 - let searchBarHeight: CGFloat = max(20.0, statusBarHeight) + 44.0 - let navigationBarOffset: CGFloat - if statusBarHeight.isZero { - navigationBarOffset = -20.0 - } else { - navigationBarOffset = 0.0 - } - var navigationBarFrame = CGRect(origin: CGPoint(x: 0.0, y: navigationBarOffset), size: CGSize(width: layout.size.width, height: searchBarHeight)) - if layout.statusBarHeight == nil { - navigationBarFrame.size.height = 64.0 + let navigationBarFrame: CGRect + switch self.mode { + case .standalone: + let statusBarHeight: CGFloat = layout.statusBarHeight ?? 0.0 + let searchBarHeight: CGFloat = max(20.0, statusBarHeight) + 44.0 + let navigationBarOffset: CGFloat + if statusBarHeight.isZero { + navigationBarOffset = -20.0 + } else { + navigationBarOffset = 0.0 + } + var frame = CGRect(origin: CGPoint(x: 0.0, y: navigationBarOffset), size: CGSize(width: layout.size.width, height: searchBarHeight)) + if layout.statusBarHeight == nil { + frame.size.height = 64.0 + } + navigationBarFrame = frame + case .navigation: + navigationBarFrame = CGRect(x: 0.0, y: 0.0, width: layout.size.width, height: 36.0) } self.searchBar.frame = navigationBarFrame - insertSubnode(searchBar) + insertSubnode(self.searchBar, true) self.searchBar.layout() self.searchBar.activate() @@ -119,7 +157,7 @@ final class SearchDisplayController { if animated { if let placeholder = placeholder, let (_, navigationBarHeight) = self.containerLayout { let contentNodePosition = self.contentNode.layer.position - let targetTextBackgroundFrame = placeholder.convert(placeholder.backgroundNode.frame, to: self.contentNode.supernode) + let targetTextBackgroundFrame = placeholder.convert(placeholder.backgroundNode.frame, to: nil) //self.contentNode.supernode) self.contentNode.layer.animatePosition(from: contentNodePosition, to: CGPoint(x: contentNodePosition.x, y: contentNodePosition.y + (targetTextBackgroundFrame.maxY + 8.0 - navigationBarHeight)), duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false) } diff --git a/TelegramUI/SettingsController.swift b/TelegramUI/SettingsController.swift index d72344e44b..f378bd28bd 100644 --- a/TelegramUI/SettingsController.swift +++ b/TelegramUI/SettingsController.swift @@ -663,7 +663,7 @@ public func settingsController(account: Account, accountManager: AccountManager) let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: hasPhotos, hasViewButton: false, personalPhoto: true, saveEditedPhotos: false, saveCapturedMedia: false, signup: false)! let _ = currentAvatarMixin.swap(mixin) mixin.requestSearchController = { assetsController in - let controller = WebSearchController(account: account, peer: peer, configuration: searchBotsConfiguration, mode: .avatar(completion: { result in + let controller = WebSearchController(account: account, peer: peer, configuration: searchBotsConfiguration, mode: .avatar(initialQuery: nil, completion: { result in assetsController?.dismiss() completedImpl(result) })) diff --git a/TelegramUI/ShareProxyServerActionSheetController.swift b/TelegramUI/ShareProxyServerActionSheetController.swift index aa08be0c95..ef4d7b62b9 100644 --- a/TelegramUI/ShareProxyServerActionSheetController.swift +++ b/TelegramUI/ShareProxyServerActionSheetController.swift @@ -20,8 +20,6 @@ public final class ShareProxyServerActionSheetController: ActionSheetController let sheetTheme = ActionSheetControllerTheme(presentationTheme: theme) super.init(theme: sheetTheme) - self._ready.set(.single(true)) - let presentActivityController: (Any) -> Void = { [weak self] item in let activityController = UIActivityViewController(activityItems: [item], applicationActivities: nil) if let window = self?.view.window, let rootViewController = window.rootViewController { @@ -32,10 +30,12 @@ public final class ShareProxyServerActionSheetController: ActionSheetController } var items: [ActionSheetItem] = [] - items.append(ProxyServerQRCodeItem(strings: strings, link: link)) + items.append(ProxyServerQRCodeItem(strings: strings, link: link, ready: { [weak self] in + self?._ready.set(.single(true)) + })) items.append(ActionSheetButtonItem(title: "Share QR Code", action: { [weak self] in self?.dismissAnimated() - let _ = (qrCode(string: link, color: .black, backgroundColor: .white) + let _ = (qrCode(string: link, color: .black, backgroundColor: .white, scale: 1.0) |> map { generator -> UIImage? in let imageSize = CGSize(width: 512.0, height: 512.0) let context = generator(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets())) @@ -79,14 +79,16 @@ public final class ShareProxyServerActionSheetController: ActionSheetController private final class ProxyServerQRCodeItem: ActionSheetItem { private let strings: PresentationStrings private let link: String + private let ready: () -> Void - init(strings: PresentationStrings, link: String) { + init(strings: PresentationStrings, link: String, ready: @escaping () -> Void = {}) { self.strings = strings self.link = link + self.ready = ready } func node(theme: ActionSheetControllerTheme) -> ActionSheetItemNode { - return ProxyServerQRCodeItemNode(theme: theme, strings: self.strings, link: self.link) + return ProxyServerQRCodeItemNode(theme: theme, strings: self.strings, link: self.link, ready: self.ready) } func updateNode(_ node: ActionSheetItemNode) { @@ -101,10 +103,13 @@ private final class ProxyServerQRCodeItemNode: ActionSheetItemNode { private let label: ASTextNode private let imageNode: TransformImageNode - init(theme: ActionSheetControllerTheme, strings: PresentationStrings, link: String) { + private let ready: () -> Void + + init(theme: ActionSheetControllerTheme, strings: PresentationStrings, link: String, ready: @escaping () -> Void = {}) { self.theme = theme self.strings = strings self.link = link + self.ready = ready self.label = ASTextNode() self.label.isUserInteractionEnabled = false @@ -115,8 +120,8 @@ private final class ProxyServerQRCodeItemNode: ActionSheetItemNode { self.label.attributedText = NSAttributedString(string: "Your friends can add this proxy by scanning this code with phone or in-app camera.", font: ActionSheetTextNode.defaultFont, textColor: self.theme.secondaryTextColor, paragraphAlignment: .center) self.imageNode = TransformImageNode() - self.imageNode.setSignal(qrCode(string: link, color: self.theme.primaryTextColor)) - + self.imageNode.setSignal(qrCode(string: link, color: self.theme.primaryTextColor), attemptSynchronously: true) + super.init(theme: theme) self.addSubnode(self.label) @@ -124,6 +129,16 @@ private final class ProxyServerQRCodeItemNode: ActionSheetItemNode { } override func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize { + let imageInset: CGFloat = 44.0 + let side = constrainedSize.width - imageInset * 2.0 + let imageSize = CGSize(width: side, height: side) + + let makeLayout = self.imageNode.asyncLayout() + let apply = makeLayout(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets(), emptyColor: nil)) + apply() + + self.ready() + let labelSize = self.label.measure(CGSize(width: max(1.0, constrainedSize.width - 64.0), height: constrainedSize.height)) return CGSize(width: constrainedSize.width, height: 14.0 + labelSize.height + 14.0 + constrainedSize.width - 88.0 + 14.0) } @@ -140,11 +155,6 @@ private final class ProxyServerQRCodeItemNode: ActionSheetItemNode { self.label.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - labelSize.width) / 2.0), y: spacing), size: labelSize) let imageFrame = CGRect(x: imageInset, y: self.label.frame.maxY + spacing - 4.0, width: size.width - imageInset * 2.0, height: size.width - imageInset * 2.0) - - let makeLayout = self.imageNode.asyncLayout() - let apply = makeLayout(TransformImageArguments(corners: ImageCorners(), imageSize: imageFrame.size, boundingSize: imageFrame.size, intrinsicInsets: UIEdgeInsets(), emptyColor: nil)) - apply() - self.imageNode.frame = imageFrame } } diff --git a/TelegramUI/TelegramRootController.swift b/TelegramUI/TelegramRootController.swift index 7997c16ee3..2ed4ebb866 100644 --- a/TelegramUI/TelegramRootController.swift +++ b/TelegramUI/TelegramRootController.swift @@ -75,6 +75,50 @@ public final class TelegramRootController: NavigationController { self.accountSettingsController = accountSettingsController self.rootTabController = tabBarController self.pushViewController(tabBarController, animated: false) + + ///TESTBED + + guard let controller = self.viewControllers.last as? ViewController else { + return + } + + DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.5) { + let wrapperNode = ASDisplayNode() + let bounds = controller.displayNode.bounds + wrapperNode.frame = bounds + wrapperNode.backgroundColor = .gray + //controller.displayNode.addSubnode(wrapperNode) + + let radialStatusSize: CGFloat = 50.0 + let statusNode = RadialStatusNode(backgroundNodeColor: UIColor(rgb: 0x000000, alpha: 0.6)) + statusNode.frame = CGRect(origin: CGPoint(x: floor(bounds.midX - radialStatusSize / 2.0), y: floor(bounds.midY - radialStatusSize / 2.0)), size: CGSize(width: radialStatusSize, height: radialStatusSize)) + wrapperNode.addSubnode(statusNode) + + let color = UIColor.white + var smth = false + let button = HighlightTrackingButtonNode() + button.frame = CGRect(origin: CGPoint(x: floor(bounds.midX - radialStatusSize / 2.0), y: floor(bounds.midY - radialStatusSize / 2.0)), size: CGSize(width: radialStatusSize, height: radialStatusSize)) + wrapperNode.addSubnode(button) + button.highligthedChanged = { value in + if value { + if smth { + smth = false + //statusNode.transitionToState(.play(color), animated: true, completion: {}) + statusNode.transitionToState(.download(.white), animated: true, completion: {}) + //statusNode.transitionToState(.none, animated: true, completion: {}) + } else { + smth = true + statusNode.transitionToState(.progress(color: color, lineWidth: nil, value: 0.3, cancelEnabled: true), animated: true, completion: {}) + } + } + } + button.addTarget(self, action: #selector(self.mock), forControlEvents: .touchUpInside) + statusNode.transitionToState(.download(.white), animated: false, completion: {}) + } + } + + @objc func mock() { + } public func updateRootControllers(showCallsTab: Bool) { diff --git a/TelegramUI/UIImage+WebP.m b/TelegramUI/UIImage+WebP.m index 89623f9750..96d71dba86 100644 --- a/TelegramUI/UIImage+WebP.m +++ b/TelegramUI/UIImage+WebP.m @@ -78,7 +78,6 @@ + (NSData *)convertToWebP:(UIImage *)image quality:(CGFloat)quality error:(NSError **)error { WebPPreset preset = WEBP_PRESET_DEFAULT; CGImageRef webPImageRef = image.CGImage; - size_t webPBytesPerRow = CGImageGetBytesPerRow(webPImageRef); size_t webPImageWidth = CGImageGetWidth(webPImageRef); @@ -126,8 +125,8 @@ pic.height = (int)webPImageHeight; pic.colorspace = WEBP_YUV420; - WebPPictureImportBGRA(&pic, webPImageData, (int)webPBytesPerRow); - //WebPPictureImportRGBA(&pic, webPImageData, (int)webPBytesPerRow); + //WebPPictureImportBGRA(&pic, webPImageData, (int)webPBytesPerRow); + WebPPictureImportRGBA(&pic, webPImageData, (int)webPBytesPerRow); WebPPictureARGBToYUVA(&pic, WEBP_YUV420); WebPCleanupTransparentArea(&pic); diff --git a/TelegramUI/WebP.swift b/TelegramUI/WebP.swift index 3ea07e86e1..28fd97f741 100644 --- a/TelegramUI/WebP.swift +++ b/TelegramUI/WebP.swift @@ -23,14 +23,17 @@ func convertToWebP(image: UIImage, targetSize: CGSize?, quality: CGFloat) -> Sig } return Signal { subscriber in - let context = DrawingContext(size: image.size, scale: 0.0, clear: true) - context.withFlippedContext({ context in - if let cgImage = image.cgImage { - context.draw(cgImage, in: CGRect(x: 0.0, y: 0.0, width: image.size.width, height: image.size.height)) - } - }) - let processedImage = context.generateImage()! - if let data = try? UIImage.convert(toWebP: processedImage, quality: quality * 100.0) { +// let context = DrawingContext(size: image.size, scale: 0.0, clear: true) +// context.withFlippedContext({ context in +// if let cgImage = image.cgImage { +// context.draw(cgImage, in: CGRect(x: 0.0, y: 0.0, width: image.size.width, height: image.size.height)) +// } +// }) +// let processedImage = context.generateImage()! +// if let data = try? UIImage.convert(toWebP: processedImage, quality: quality * 100.0) { +// subscriber.putNext(data) +// } + if let data = try? UIImage.convert(toWebP: image, quality: quality * 100.0) { subscriber.putNext(data) } subscriber.putCompletion() diff --git a/TelegramUI/WebSearchController.swift b/TelegramUI/WebSearchController.swift index 0b72e569c3..0e094ba418 100644 --- a/TelegramUI/WebSearchController.swift +++ b/TelegramUI/WebSearchController.swift @@ -48,7 +48,7 @@ enum WebSearchMode { enum WebSearchControllerMode { case media(completion: (ChatContextResultCollection, TGMediaSelectionContext, TGMediaEditingContext) -> Void) - case avatar(completion: (UIImage) -> Void) + case avatar(initialQuery: String?, completion: (UIImage) -> Void) var mode: WebSearchMode { switch self { @@ -132,6 +132,12 @@ final class WebSearchController: ViewController { let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 } self.interfaceState = WebSearchInterfaceState(presentationData: presentationData) + var searchQuery: String? + if case let .avatar(initialQuery, _) = mode, let query = initialQuery { + searchQuery = query + self.interfaceState = self.interfaceState.withUpdatedQuery(query) + } + super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: presentationData.theme).withUpdatedSeparatorColor(presentationData.theme.rootController.navigationBar.backgroundColor), strings: NavigationBarStrings(presentationStrings: presentationData.strings))) self.statusBar.statusBarStyle = presentationData.theme.rootController.statusBar.style.style @@ -170,12 +176,14 @@ final class WebSearchController: ViewController { let navigationContentNode = WebSearchNavigationContentNode(theme: presentationData.theme, strings: presentationData.strings) self.navigationContentNode = navigationContentNode navigationContentNode.setQueryUpdated { [weak self] query in - guard let strongSelf = self, strongSelf.isNodeLoaded else { - return + if let strongSelf = self, strongSelf.isNodeLoaded { + strongSelf.updateSearchQuery(query) } - strongSelf.updateSearchQuery(query) } self.navigationBar?.setContentNode(navigationContentNode, animated: false) + if let query = searchQuery { + navigationContentNode.setQuery(query) + } let selectionState: TGMediaSelectionContext? switch self.mode { @@ -219,7 +227,7 @@ final class WebSearchController: ViewController { } } }, avatarCompleted: { result in - if case let .avatar(avatarCompleted) = mode { + if case let .avatar(_, avatarCompleted) = mode { avatarCompleted(result) } }, selectionState: selectionState, editingState: editingState) @@ -258,7 +266,11 @@ final class WebSearchController: ViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - self.navigationContentNode?.activate() + var select = false + if case let .avatar(initialQuery, _) = mode, let _ = initialQuery { + select = true + } + self.navigationContentNode?.activate(select: select) } override public func loadDisplayNode() { diff --git a/TelegramUI/WebSearchNavigationContentNode.swift b/TelegramUI/WebSearchNavigationContentNode.swift index 92c6fa6cbf..80c91aa142 100644 --- a/TelegramUI/WebSearchNavigationContentNode.swift +++ b/TelegramUI/WebSearchNavigationContentNode.swift @@ -58,8 +58,9 @@ final class WebSearchNavigationContentNode: NavigationBarContentNode { self.searchBar.updateLayout(boundingSize: size, leftInset: 0.0, rightInset: 0.0, transition: .immediate) } - func activate() { + func activate(select: Bool = false) { self.searchBar.activate() + self.searchBar.selectAll() } func deactivate() { diff --git a/TelegramUI/WebSearchVideoGalleryItem.swift b/TelegramUI/WebSearchVideoGalleryItem.swift index 1f89fdbfb9..882df3c5b4 100644 --- a/TelegramUI/WebSearchVideoGalleryItem.swift +++ b/TelegramUI/WebSearchVideoGalleryItem.swift @@ -225,7 +225,7 @@ final class WebSearchVideoGalleryItemNode: ZoomableContentGalleryItemNode { case let .Fetching(_, progress): fetching = true isPaused = true - state = .progress(color: .white, lineWidth: nil, value: CGFloat(max(0.0027, progress)), cancelEnabled: false) + state = .progress(color: .white, lineWidth: nil, value: CGFloat(max(0.027, progress)), cancelEnabled: false) default: break }