diff --git a/TelegramUI.xcodeproj/project.pbxproj b/TelegramUI.xcodeproj/project.pbxproj index 1875d98eb8..fd62f89092 100644 --- a/TelegramUI.xcodeproj/project.pbxproj +++ b/TelegramUI.xcodeproj/project.pbxproj @@ -130,6 +130,8 @@ 09DD88FA21BFD70B000766BC /* ThemedTextAlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09DD88F921BFD70B000766BC /* ThemedTextAlertController.swift */; }; 09E4A801223AE1B30038140F /* PeerType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09E4A800223AE1B30038140F /* PeerType.swift */; }; 09E4A803223B833B0038140F /* ForwardPrivacyChatPreviewItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09E4A802223B833B0038140F /* ForwardPrivacyChatPreviewItem.swift */; }; + 09E4A805223D4A5A0038140F /* OpenSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09E4A804223D4A5A0038140F /* OpenSettings.swift */; }; + 09E4A807223D4B860038140F /* AccountUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09E4A806223D4B860038140F /* AccountUtils.swift */; }; 09EDAD26220D30980012A50B /* AutodownloadConnectionTypeController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09EDAD25220D30980012A50B /* AutodownloadConnectionTypeController.swift */; }; 09EDAD2A220DA6A40012A50B /* VolumeButtons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09EDAD29220DA6A40012A50B /* VolumeButtons.swift */; }; 09EDAD2C2211552F0012A50B /* AutodownloadMediaCategoryController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09EDAD2B2211552F0012A50B /* AutodownloadMediaCategoryController.swift */; }; @@ -1289,6 +1291,8 @@ 09DD88F921BFD70B000766BC /* ThemedTextAlertController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemedTextAlertController.swift; sourceTree = ""; }; 09E4A800223AE1B30038140F /* PeerType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PeerType.swift; sourceTree = ""; }; 09E4A802223B833B0038140F /* ForwardPrivacyChatPreviewItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForwardPrivacyChatPreviewItem.swift; sourceTree = ""; }; + 09E4A804223D4A5A0038140F /* OpenSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenSettings.swift; sourceTree = ""; }; + 09E4A806223D4B860038140F /* AccountUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountUtils.swift; sourceTree = ""; }; 09EDAD25220D30980012A50B /* AutodownloadConnectionTypeController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutodownloadConnectionTypeController.swift; sourceTree = ""; }; 09EDAD29220DA6A40012A50B /* VolumeButtons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VolumeButtons.swift; sourceTree = ""; }; 09EDAD2B2211552F0012A50B /* AutodownloadMediaCategoryController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutodownloadMediaCategoryController.swift; sourceTree = ""; }; @@ -2640,6 +2644,7 @@ D04ECD711FFBF22B00DE9029 /* OpenUrl.swift */, D0FC194C201F82A000FEDBB2 /* OpenResolvedUrl.swift */, D023836F1DDF0462004018B6 /* UrlHandling.swift */, + 09E4A804223D4A5A0038140F /* OpenSettings.swift */, ); name = Routing; sourceTree = ""; @@ -4861,6 +4866,7 @@ 090B48C72200BCA8005083FA /* WallpaperUploadManager.swift */, 09D96898221DE92600B1458A /* ID3ArtworkReader.swift */, 09E4A800223AE1B30038140F /* PeerType.swift */, + 09E4A806223D4B860038140F /* AccountUtils.swift */, ); name = Utils; sourceTree = ""; @@ -5415,6 +5421,7 @@ D093D7DF2062F3F000BC3599 /* SecureIdDocumentFormController.swift in Sources */, D0E9BA371F05585000F079A4 /* STPPhoneNumberValidator.m in Sources */, 0910B0EF21FA532D00F8F87D /* WallpaperResources.swift in Sources */, + 09E4A807223D4B860038140F /* AccountUtils.swift in Sources */, D069F5D0212700B90000565A /* StickerPanePeerSpecificSetupGridItem.swift in Sources */, D0EC6D041EB9F58800EBF1C3 /* opusenc.m in Sources */, D0A8998D217A294100759EE6 /* SaveIncomingMediaController.swift in Sources */, @@ -5634,6 +5641,7 @@ D0EC6D681EB9F58800EBF1C3 /* AuthorizationSequenceController.swift in Sources */, 09F664C021EAAFAF00AB7E26 /* ThemeColorsGridController.swift in Sources */, D0EC6D691EB9F58800EBF1C3 /* AuthorizationSequenceSplashController.swift in Sources */, + 09E4A805223D4A5A0038140F /* OpenSettings.swift in Sources */, D0EC6D6A1EB9F58800EBF1C3 /* AuthorizationSequenceSplashControllerNode.swift in Sources */, D0C683FC21AD797F00A6CAD5 /* ChatListSelection.swift in Sources */, D0EC6D6B1EB9F58800EBF1C3 /* AuthorizationSequenceCountrySelectionController.swift in Sources */, diff --git a/TelegramUI/AccountUtils.swift b/TelegramUI/AccountUtils.swift new file mode 100644 index 0000000000..875895197e --- /dev/null +++ b/TelegramUI/AccountUtils.swift @@ -0,0 +1,40 @@ +import Foundation +import SwiftSignalKit +import Postbox +import TelegramCore + +func activeAccountsAndPeers(context: AccountContext) -> Signal<((Account, Peer)?, [(Account, Peer, Int32)]), NoError> { + let sharedContext = context.sharedContext + return context.sharedContext.activeAccounts + |> mapToSignal { primary, activeAccounts, _ -> Signal<((Account, Peer)?, [(Account, Peer, Int32)]), NoError> in + var accounts: [Signal<(Account, Peer, Int32)?, NoError>] = [] + func accountWithPeer(_ account: Account) -> Signal<(Account, Peer, Int32)?, NoError> { + return combineLatest(account.postbox.peerView(id: account.peerId), renderedTotalUnreadCount(accountManager: sharedContext.accountManager, postbox: account.postbox)) + |> map { view, totalUnreadCount -> (Peer?, Int32) in + return (view.peers[view.peerId], totalUnreadCount.0) + } + |> distinctUntilChanged { lhs, rhs in + return arePeersEqual(lhs.0, rhs.0) && lhs.1 == rhs.1 + } + |> map { peer, totalUnreadCount -> (Account, Peer, Int32)? in + if let peer = peer { + return (account, peer, totalUnreadCount) + } else { + return nil + } + } + } + for (_, account, _) in activeAccounts { + accounts.append(accountWithPeer(account)) + } + + return combineLatest(accounts) + |> map { accounts -> ((Account, Peer)?, [(Account, Peer, Int32)]) in + var primaryRecord: (Account, Peer)? + if let first = accounts.filter({ $0?.0.id == primary?.id }).first, let (account, peer, _) = first { + primaryRecord = (account, peer) + } + return (primaryRecord, accounts.filter({ $0?.0.id != primary?.id }).compactMap({ $0 })) + } + } +} diff --git a/TelegramUI/CachedFaqInstantPage.swift b/TelegramUI/CachedFaqInstantPage.swift index 67994415e3..a69c3346f5 100644 --- a/TelegramUI/CachedFaqInstantPage.swift +++ b/TelegramUI/CachedFaqInstantPage.swift @@ -21,6 +21,8 @@ private func extractAnchor(string: String) -> (String, String?) { return (trimmedUrl, anchorValue) } +private let refreshTimeout: Int32 = 60 * 60 * 12 + func cachedFaqInstantPage(context: AccountContext) -> Signal { var faqUrl = context.sharedContext.currentPresentationData.with { $0 }.strings.Settings_FAQ_URL if faqUrl == "Settings.FAQ_URL" || faqUrl.isEmpty { @@ -31,27 +33,36 @@ func cachedFaqInstantPage(context: AccountContext) -> Signal mapToSignal { cachedInstantPage -> Signal in - if let webPage = cachedInstantPage?.webPage, case let .Loaded(content) = webPage.content, let instantPage = content.instantPage, instantPage.isComplete { - return .single(.instantView(webPage, anchor)) - } else { - return resolveInstantViewUrl(account: context.account, url: faqUrl) - |> afterNext { result in - if case let .instantView(webPage, _) = result, case let .Loaded(content) = webPage.content, let instantPage = content.instantPage { - if instantPage.isComplete { - let _ = updateCachedInstantPage(postbox: context.account.postbox, url: cachedUrl, webPage: webPage).start() - } else { - let _ = (actualizedWebpage(postbox: context.account.postbox, network: context.account.network, webpage: webPage) - |> mapToSignal { webPage -> Signal in - if case let .Loaded(content) = webPage.content, let instantPage = content.instantPage, instantPage.isComplete { - return updateCachedInstantPage(postbox: context.account.postbox, url: cachedUrl, webPage: webPage) - } else { - return .complete() - } - }).start() - } + let updated = resolveInstantViewUrl(account: context.account, url: faqUrl) + |> afterNext { result in + if case let .instantView(webPage, _) = result, case let .Loaded(content) = webPage.content, let instantPage = content.instantPage { + if instantPage.isComplete { + let _ = updateCachedInstantPage(postbox: context.account.postbox, url: cachedUrl, webPage: webPage).start() + } else { + let _ = (actualizedWebpage(postbox: context.account.postbox, network: context.account.network, webpage: webPage) + |> mapToSignal { webPage -> Signal in + if case let .Loaded(content) = webPage.content, let instantPage = content.instantPage, instantPage.isComplete { + return updateCachedInstantPage(postbox: context.account.postbox, url: cachedUrl, webPage: webPage) + } else { + return .complete() + } + }).start() } } } + + let now = Int32(CFAbsoluteTimeGetCurrent()) + if let cachedInstantPage = cachedInstantPage, case let .Loaded(content) = cachedInstantPage.webPage.content, let instantPage = content.instantPage, instantPage.isComplete { + let current: Signal = .single(.instantView(cachedInstantPage.webPage, anchor)) + if now > cachedInstantPage.timestamp + refreshTimeout { + return current + |> then(updated) + } else { + return current + } + } else { + return updated + } } } @@ -76,7 +87,7 @@ func faqSearchableItems(context: AccountContext) -> Signal<[SettingsSearchableIt currentAnchor = anchor case let .header(text): if let anchor = currentAnchor { - results.append(SettingsSearchableItem(id: .faq(results.count + 1), title: text.plainText, alternate: [], icon: .faq, breadcrumbs: [strings.SettingsSearch_FAQ], present: { context, present in + results.append(SettingsSearchableItem(id: .faq(results.count + 1), title: text.plainText, alternate: [], icon: .faq, breadcrumbs: [strings.SettingsSearch_FAQ], present: { context, _, present in present(.push, InstantPageController(context: context, webPage: webPage, sourcePeerType: .channel, anchor: anchor)) })) } @@ -96,7 +107,7 @@ func faqSearchableItems(context: AccountContext) -> Signal<[SettingsSearchableIt for item in items { if case let .text(itemText, _) = item, case let .url(text, url, _) = itemText { let (_, anchor) = extractAnchor(string: url) - results.append(SettingsSearchableItem(id: .faq(results.count + 1), title: text.plainText, alternate: [], icon: .faq, breadcrumbs: [strings.SettingsSearch_FAQ, currentSection], present: { context, present in + results.append(SettingsSearchableItem(id: .faq(results.count + 1), title: text.plainText, alternate: [], icon: .faq, breadcrumbs: [strings.SettingsSearch_FAQ, currentSection], present: { context, _, present in present(.push, InstantPageController(context: context, webPage: webPage, sourcePeerType: .channel, anchor: anchor)) })) } diff --git a/TelegramUI/CachedInstantPages.swift b/TelegramUI/CachedInstantPages.swift index 169264e62a..36dbff0633 100644 --- a/TelegramUI/CachedInstantPages.swift +++ b/TelegramUI/CachedInstantPages.swift @@ -5,17 +5,21 @@ import TelegramCore final class CachedInstantPage: PostboxCoding { let webPage: TelegramMediaWebpage + let timestamp: Int32 - init(webPage: TelegramMediaWebpage) { + init(webPage: TelegramMediaWebpage, timestamp: Int32) { self.webPage = webPage + self.timestamp = timestamp } init(decoder: PostboxDecoder) { self.webPage = decoder.decodeObjectForKey("webpage", decoder: { TelegramMediaWebpage(decoder: $0) }) as! TelegramMediaWebpage + self.timestamp = decoder.decodeInt32ForKey("timestamp", orElse: 0) } func encode(_ encoder: PostboxEncoder) { encoder.encodeObject(self.webPage, forKey: "webpage") + encoder.encodeInt32(self.timestamp, forKey: "timestamp") } } @@ -39,7 +43,7 @@ func updateCachedInstantPage(postbox: Postbox, url: String, webPage: TelegramMed key.setInt64(0, value: Int64(url.hashValue)) let id = ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.cachedInstantPages, key: key) if let webPage = webPage { - transaction.putItemCacheEntry(id: id, entry: CachedInstantPage(webPage: webPage), collectionSpec: collectionSpec) + transaction.putItemCacheEntry(id: id, entry: CachedInstantPage(webPage: webPage, timestamp: Int32(CFAbsoluteTimeGetCurrent())), collectionSpec: collectionSpec) } else { transaction.removeItemCacheEntry(id: id) } diff --git a/TelegramUI/ChatController.swift b/TelegramUI/ChatController.swift index c53ce0a883..b301e795c7 100644 --- a/TelegramUI/ChatController.swift +++ b/TelegramUI/ChatController.swift @@ -296,6 +296,7 @@ public final class ChatController: TelegramController, KeyShortcutResponder, Gal return false } strongSelf.commitPurposefulAction() + strongSelf.videoUnmuteTooltipController?.dismiss() var openMessageByAction: Bool = false @@ -1101,6 +1102,10 @@ public final class ChatController: TelegramController, KeyShortcutResponder, Gal if let strongSelf = self { openAddContact(context: strongSelf.context, phoneNumber: phoneNumber, present: { [weak self] controller, arguments in self?.present(controller, in: .window(.root), with: arguments) + }, pushController: { [weak self] controller in + if let strongSelf = self { + (strongSelf.navigationController as? NavigationController)?.pushViewController(controller) + } }) } }, rateCall: { [weak self] message, callId in @@ -2232,6 +2237,8 @@ public final class ChatController: TelegramController, KeyShortcutResponder, Gal } if isAction && (actions.options == .deleteGlobally || actions.options == .deleteLocally) { let _ = deleteMessagesInteractively(postbox: strongSelf.context.account.postbox, messageIds: Array(messageIds), type: actions.options == .deleteLocally ? .forLocalPeer : .forEveryone).start() + } else if actions.options == .cancelSending { + let _ = deleteMessagesInteractively(postbox: strongSelf.context.account.postbox, messageIds: Array(messageIds), type: .forEveryone).start() } else { var options = actions.options if messages.first?.flags.isSending ?? false { @@ -2699,7 +2706,7 @@ public final class ChatController: TelegramController, KeyShortcutResponder, Gal } if let location = location, let icon = icon { strongSelf.mediaRestrictedTooltipController?.dismiss() - let tooltipController = TooltipController(content: .iconAndText(icon, strongSelf.presentationInterfaceState.strings.Conversation_PressVolumeButtonForSound), timeout: 3.5, dismissImmediatelyOnLayoutUpdate: true) + let tooltipController = TooltipController(content: .iconAndText(icon, strongSelf.presentationInterfaceState.strings.Conversation_PressVolumeButtonForSound), timeout: 3.5, dismissByTapOutside: true, dismissImmediatelyOnLayoutUpdate: true) strongSelf.videoUnmuteTooltipController = tooltipController tooltipController.dismissed = { [weak tooltipController] in if let strongSelf = self, let tooltipController = tooltipController, strongSelf.videoUnmuteTooltipController === tooltipController { @@ -3240,8 +3247,6 @@ public final class ChatController: TelegramController, KeyShortcutResponder, Gal guard let strongSelf = self, strongSelf.traceVisibility() && isTopmostChatController(strongSelf) else { return } - ApplicationSpecificNotice.setVolumeButtonToUnmute(accountManager: strongSelf.context.sharedContext.accountManager) - strongSelf.videoUnmuteTooltipController?.dismiss() strongSelf.chatDisplayNode.playFirstMediaWithSound() }) @@ -6112,9 +6117,6 @@ public final class ChatController: TelegramController, KeyShortcutResponder, Gal }) } }), - KeyShortcut(input: "W", modifiers: [.command], action: { [weak self] in - - }) ] return inputShortcuts + otherShortcuts diff --git a/TelegramUI/ChatListController.swift b/TelegramUI/ChatListController.swift index 4c0a707595..d2d1982649 100644 --- a/TelegramUI/ChatListController.swift +++ b/TelegramUI/ChatListController.swift @@ -597,6 +597,8 @@ public class ChatListController: TelegramController, KeyShortcutResponder, UIVie strongSelf.view.endEditing(true) openAddContact(context: strongSelf.context, phoneNumber: phoneNumber, present: { [weak self] controller, arguments in self?.present(controller, in: .window(.root), with: arguments) + }, pushController: { [weak self] controller in + (self?.navigationController as? NavigationController)?.pushViewController(controller) }, completed: { self?.deactivateSearch(animated: false) }) diff --git a/TelegramUI/ChatMediaInputGifPane.swift b/TelegramUI/ChatMediaInputGifPane.swift index 2108ce0ac7..d4db9ae58b 100644 --- a/TelegramUI/ChatMediaInputGifPane.swift +++ b/TelegramUI/ChatMediaInputGifPane.swift @@ -116,6 +116,10 @@ final class ChatMediaInputGifPane: ChatMediaInputPane, UIScrollViewDelegate { } } + override var isEmpty: Bool { + return self.multiplexedNode?.files.isEmpty ?? true + } + override func willEnterHierarchy() { super.willEnterHierarchy() diff --git a/TelegramUI/ChatMediaInputNode.swift b/TelegramUI/ChatMediaInputNode.swift index 38c32e045c..ca2be687ae 100644 --- a/TelegramUI/ChatMediaInputNode.swift +++ b/TelegramUI/ChatMediaInputNode.swift @@ -871,9 +871,9 @@ final class ChatMediaInputNode: ChatInputNode { strongSelf.controllerInteraction.sendGif(file) } }), - PeekControllerMenuItem(title: strongSelf.strings.Common_Delete, color: .destructive, action: { + PeekControllerMenuItem(title: strongSelf.strings.Preview_SaveGif, color: .accent, action: { if let strongSelf = self { - let _ = removeSavedGif(postbox: strongSelf.context.account.postbox, mediaId: file.media.fileId).start() + let _ = addSavedGif(postbox: strongSelf.context.account.postbox, fileReference: file).start() } }) ]))) @@ -1375,11 +1375,13 @@ final class ChatMediaInputNode: ChatInputNode { self.searchContainerNode = nil self.searchContainerNodeLoadedDisposable.set(nil) + var paneIsEmpty = false var placeholderNode: PaneSearchBarPlaceholderNode? if let searchMode = searchMode { switch searchMode { case .gif: placeholderNode = self.gifPane.searchPlaceholderNode + paneIsEmpty = self.gifPane.isEmpty case .sticker: self.stickerPane.gridNode.forEachItemNode { itemNode in if let itemNode = itemNode as? PaneSearchBarPlaceholderNode { @@ -1389,7 +1391,7 @@ final class ChatMediaInputNode: ChatInputNode { } } if let placeholderNode = placeholderNode { - searchContainerNode.animateOut(to: placeholderNode, transition: transition, completion: { [weak searchContainerNode] in + searchContainerNode.animateOut(to: placeholderNode, animateOutSearchBar: !paneIsEmpty, transition: transition, completion: { [weak searchContainerNode] in searchContainerNode?.removeFromSupernode() }) } else { diff --git a/TelegramUI/ChatMediaInputPane.swift b/TelegramUI/ChatMediaInputPane.swift index 3de19e7a07..667942a7ed 100644 --- a/TelegramUI/ChatMediaInputPane.swift +++ b/TelegramUI/ChatMediaInputPane.swift @@ -10,6 +10,9 @@ struct ChatMediaInputPaneScrollState { class ChatMediaInputPane: ASDisplayNode { var inputNodeInteraction: ChatMediaInputNodeInteraction? var collectionListPanelOffset: CGFloat = 0.0 + var isEmpty: Bool { + return false + } func updateLayout(size: CGSize, topInset: CGFloat, bottomInset: CGFloat, isExpanded: Bool, isVisible: Bool, transition: ContainedViewLayoutTransition) { } diff --git a/TelegramUI/ChatMediaInputStickerPackItem.swift b/TelegramUI/ChatMediaInputStickerPackItem.swift index 477dc58e75..d373f3959f 100644 --- a/TelegramUI/ChatMediaInputStickerPackItem.swift +++ b/TelegramUI/ChatMediaInputStickerPackItem.swift @@ -115,7 +115,7 @@ final class ChatMediaInputStickerPackItemNode: ListViewItemNode { resourceReference = MediaResourceReference.standalone(resource: thumbnail.resource) } else if let item = item, let dimensions = item.file.dimensions, let resource = chatMessageStickerResource(file: item.file, small: true) as? TelegramMediaResource { thumbnailItem = TelegramMediaImageRepresentation(dimensions: dimensions, resource: resource) - resourceReference = MediaResourceReference.standalone(resource: resource) + resourceReference = MediaResourceReference.media(media: .standalone(media: item.file), resource: resource) } if self.currentThumbnailItem != thumbnailItem { diff --git a/TelegramUI/ChatMessageBubbleItemNode.swift b/TelegramUI/ChatMessageBubbleItemNode.swift index 5ae25483e8..a28fd8f725 100644 --- a/TelegramUI/ChatMessageBubbleItemNode.swift +++ b/TelegramUI/ChatMessageBubbleItemNode.swift @@ -150,6 +150,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView { private var currentSwipeToReplyTranslation: CGFloat = 0.0 private var appliedItem: ChatMessageItem? + private var appliedForwardInfo: (Peer?, String?)? override var visibility: ListViewItemNodeVisibility { didSet { @@ -314,6 +315,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView { let layoutConstants = self.layoutConstants let currentItem = self.appliedItem + let currentForwardInfo = self.appliedForwardInfo return { item, params, mergedTop, mergedBottom, dateHeaderAtBottom in let accessibilityData = ChatMessageAccessibilityData(item: item) @@ -746,6 +748,9 @@ class ChatMessageBubbleItemNode: ChatMessageItemView { var forwardInfoOriginY: CGFloat = 0.0 var forwardInfoSizeApply: (CGSize, () -> ChatMessageForwardInfoNode?) = (CGSize(), { nil }) + var forwardSource: Peer? + var forwardAuthorSignature: String? + if displayHeader { if authorNameString != nil || inlineBotNameString != nil { if headerSize.height.isZero { @@ -790,13 +795,11 @@ class ChatMessageBubbleItemNode: ChatMessageItemView { headerSize.width = max(headerSize.width, nameNodeSizeApply.0.width + adminBadgeSizeAndApply.0.size.width + layoutConstants.text.bubbleInsets.left + layoutConstants.text.bubbleInsets.right) headerSize.height += nameNodeSizeApply.0.height } - + if !ignoreForward, let forwardInfo = firstMessage.forwardInfo { if headerSize.height.isZero { headerSize.height += 5.0 } - let forwardSource: Peer? - let forwardAuthorSignature: String? if let source = forwardInfo.source { forwardSource = source @@ -808,8 +811,13 @@ class ChatMessageBubbleItemNode: ChatMessageItemView { forwardAuthorSignature = nil } } else { - forwardSource = forwardInfo.author - forwardAuthorSignature = forwardInfo.authorSignature + if let currentForwardInfo = currentForwardInfo, forwardInfo.author == nil && currentForwardInfo.0 != nil { + forwardSource = currentForwardInfo.0 + forwardAuthorSignature = currentForwardInfo.1 + } else { + forwardSource = forwardInfo.author + forwardAuthorSignature = forwardInfo.authorSignature + } } let sizeAndApply = forwardInfoLayout(item.presentationData, item.presentationData.strings, .bubble(incoming: incoming), forwardSource, forwardAuthorSignature, CGSize(width: maximumNodeWidth - layoutConstants.text.bubbleInsets.left - layoutConstants.text.bubbleInsets.right, height: CGFloat.greatestFiniteMagnitude)) forwardInfoSizeApply = (sizeAndApply.0, { sizeAndApply.1() }) @@ -1148,6 +1156,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView { return (layout, { [weak self] animation, synchronousLoads in if let strongSelf = self { strongSelf.appliedItem = item + strongSelf.appliedForwardInfo = (forwardSource, forwardAuthorSignature) strongSelf.accessibilityLabel = accessibilityData.label strongSelf.accessibilityValue = accessibilityData.value @@ -1597,7 +1606,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView { item.controllerInteraction.navigateToMessage(item.message.id, sourceMessageId) } else if let id = forwardInfo.source?.id ?? forwardInfo.author?.id { item.controllerInteraction.openPeer(id, .info, nil) - } else if let authorSignature = forwardInfo.authorSignature { + } else if let _ = forwardInfo.authorSignature { item.controllerInteraction.displayMessageTooltip(item.message.id, item.presentationData.strings.Conversation_ForwardAuthorHiddenTooltip, forwardInfoNode) } return diff --git a/TelegramUI/ChatMessageInstantVideoItemNode.swift b/TelegramUI/ChatMessageInstantVideoItemNode.swift index 1f0bbf2fde..4e0a67a3c3 100644 --- a/TelegramUI/ChatMessageInstantVideoItemNode.swift +++ b/TelegramUI/ChatMessageInstantVideoItemNode.swift @@ -20,6 +20,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView { private var swipeToReplyFeedback: HapticFeedback? private var appliedItem: ChatMessageItem? + private var appliedForwardInfo: (Peer?, String?)? private var forwardInfoNode: ChatMessageForwardInfoNode? private var forwardBackgroundNode: ASImageNode? @@ -95,9 +96,9 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView { let actionButtonsLayout = ChatMessageActionButtonsNode.asyncLayout(self.actionButtonsNode) let currentItem = self.appliedItem + let currentForwardInfo = self.appliedForwardInfo return { item, params, mergedTop, mergedBottom, dateHeaderAtBottom in - let baseWidth = params.width - params.leftInset - params.rightInset let incoming = item.message.effectivelyIncoming(item.context.account.peerId) let avatarInset: CGFloat @@ -268,13 +269,13 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView { let availableContentWidth = params.width - params.leftInset - params.rightInset - layoutConstants.bubble.edgeInset * 2.0 - avatarInset - layoutConstants.bubble.contentInsets.left + var forwardSource: Peer? + var forwardAuthorSignature: String? + var forwardInfoSizeApply: (CGSize, () -> ChatMessageForwardInfoNode)? var updatedForwardBackgroundNode: ASImageNode? var forwardBackgroundImage: UIImage? if let forwardInfo = item.message.forwardInfo { - let forwardSource: Peer? - let forwardAuthorSignature: String? - if let source = forwardInfo.source { forwardSource = source if let authorSignature = forwardInfo.authorSignature { @@ -285,8 +286,13 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView { forwardAuthorSignature = nil } } else { - forwardSource = forwardInfo.author - forwardAuthorSignature = forwardInfo.authorSignature + if let currentForwardInfo = currentForwardInfo, forwardInfo.author == nil && currentForwardInfo.0 != nil { + forwardSource = currentForwardInfo.0 + forwardAuthorSignature = currentForwardInfo.1 + } else { + forwardSource = forwardInfo.author + forwardAuthorSignature = forwardInfo.authorSignature + } } let availableWidth = max(60.0, availableContentWidth - videoLayout.contentSize.width + 6.0) forwardInfoSizeApply = makeForwardInfoLayout(item.presentationData, item.presentationData.strings, .standalone, forwardSource, forwardAuthorSignature, CGSize(width: availableWidth, height: CGFloat.greatestFiniteMagnitude)) @@ -322,7 +328,8 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView { return (ListViewItemNodeLayout(contentSize: layoutSize, insets: layoutInsets), { [weak self] animation, _ in if let strongSelf = self { strongSelf.appliedItem = item - + strongSelf.appliedForwardInfo = (forwardSource, forwardAuthorSignature) + let transition: ContainedViewLayoutTransition if animation.isAnimated { transition = .animated(duration: 0.2, curve: .spring) @@ -508,7 +515,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView { item.controllerInteraction.navigateToMessage(item.message.id, sourceMessageId) } else if let id = forwardInfo.source?.id ?? forwardInfo.author?.id { item.controllerInteraction.openPeer(id, .chat(textInputState: nil, messageId: nil), nil) - } else if let authorSignature = forwardInfo.authorSignature { + } else if let _ = forwardInfo.authorSignature { item.controllerInteraction.displayMessageTooltip(item.message.id, item.presentationData.strings.Conversation_ForwardAuthorHiddenTooltip, forwardInfoNode) } return diff --git a/TelegramUI/ChatMessageInteractiveFileNode.swift b/TelegramUI/ChatMessageInteractiveFileNode.swift index 14ff614119..662388dfcc 100644 --- a/TelegramUI/ChatMessageInteractiveFileNode.swift +++ b/TelegramUI/ChatMessageInteractiveFileNode.swift @@ -747,7 +747,10 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { statusForegroundColor = presentationData.wallpaper.isEmpty ? bubbleTheme.outgoing.withoutWallpaper.fill : bubbleTheme.outgoing.withWallpaper.fill } switch resourceStatus.mediaStatus { - case let .fetchStatus(fetchStatus): + case var .fetchStatus(fetchStatus): + if self.message?.forwardInfo != nil { + fetchStatus = resourceStatus.fetchStatus + } self.waveformScrubbingNode?.enableScrubbing = false switch fetchStatus { case let .Fetching(_, progress): @@ -822,8 +825,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { } }) } else { - streamingStatusNode.transitionToState(streamingState, completion: { - }) + streamingStatusNode.transitionToState(streamingState) } } diff --git a/TelegramUI/ChatMessageInteractiveInstantVideoNode.swift b/TelegramUI/ChatMessageInteractiveInstantVideoNode.swift index bfc532e795..8131324e9d 100644 --- a/TelegramUI/ChatMessageInteractiveInstantVideoNode.swift +++ b/TelegramUI/ChatMessageInteractiveInstantVideoNode.swift @@ -45,8 +45,16 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { private let infoBackgroundNode: ASImageNode private let muteIconNode: ASImageNode - private var status: FileMediaResourceMediaStatus? + private var status: FileMediaResourceStatus? + private var playerStatus: MediaPlayerStatus? { + didSet { + if self.playerStatus != oldValue { + self.updateStatus() + } + } + } private let playbackStatusDisposable = MetaDisposable() + private let playerStatusDisposable = MetaDisposable() private let fetchedThumbnailDisposable = MetaDisposable() private var shouldAcquireVideoContext: Bool { @@ -98,6 +106,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { deinit { self.fetchDisposable.dispose() self.playbackStatusDisposable.dispose() + self.playerStatusDisposable.dispose() self.fetchedThumbnailDisposable.dispose() } @@ -293,17 +302,6 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { transition.updateFrame(node: strongSelf.muteIconNode, frame: muteIconFrame) } - if let updatedPlaybackStatus = updatedPlaybackStatus { - strongSelf.playbackStatusDisposable.set((updatedPlaybackStatus - |> deliverOnMainQueue).start(next: { status in - guard let strongSelf = self else { - return - } - strongSelf.status = status.mediaStatus - strongSelf.updateStatus() - })) - } - if let updatedFile = updatedFile, updatedMedia { if let resource = updatedFile.previewRepresentations.first?.resource { strongSelf.fetchedThumbnailDisposable.set(fetchedMediaResource(postbox: item.context.account.postbox, reference: FileMediaReference.message(message: MessageReference(item.message), media: updatedFile).resourceReference(resource)).start()) @@ -326,6 +324,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { strongSelf.dateAndStatusNode.frame = CGRect(origin: CGPoint(x: min(floor(videoFrame.midX) + 55.0, videoFrame.maxX + right - dateAndStatusSize.width - 4.0), y: videoFrame.maxY - dateAndStatusSize.height), size: dateAndStatusSize) } + var updatedPlayerStatusSignal: Signal? if let telegramFile = updatedFile, updatedMedia { let durationTextColor: UIColor let durationFillColor: UIColor @@ -353,7 +352,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { } durationNode.defaultDuration = telegramFile.duration.flatMap(Double.init) - let streamVideo = isMediaStreamable(message: item.message, media: telegramFile) + let streamVideo = automaticDownload && isMediaStreamable(message: item.message, media: telegramFile) if let videoNode = strongSelf.videoNode { videoNode.layer.allowsGroupOpacity = true videoNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.5, delay: 0.2, removeOnCompletion: false, completion: { [weak videoNode] _ in @@ -371,7 +370,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { } } } - }), content: NativeVideoContent(id: .message(item.message.id, item.message.stableId, telegramFile.fileId), fileReference: .message(message: MessageReference(item.message), media: telegramFile), streamVideo: streamVideo, enableSound: false, fetchAutomatically: false), priority: .embedded, autoplay: true) + }), content: NativeVideoContent(id: .message(item.message.id, item.message.stableId, telegramFile.fileId), fileReference: .message(message: MessageReference(item.message), media: telegramFile), streamVideo: streamVideo ? .earlierStart : .none, enableSound: false, fetchAutomatically: false), priority: .embedded, autoplay: true) let previousVideoNode = strongSelf.videoNode strongSelf.videoNode = videoNode strongSelf.insertSubnode(videoNode, belowSubnode: previousVideoNode ?? strongSelf.dateAndStatusNode) @@ -385,6 +384,36 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { strongSelf.insertSubnode(strongSelf.secretVideoPlaceholder, belowSubnode: videoNode) } } + + updatedPlayerStatusSignal = videoNode.status + |> mapToSignal { status -> Signal in + if let status = status, case .buffering = status.status { + return .single(status) |> delay(1.0, queue: Queue.mainQueue()) + } else { + return .single(status) + } + } + } + + if let updatedPlaybackStatus = updatedPlaybackStatus { + strongSelf.playbackStatusDisposable.set((updatedPlaybackStatus + |> deliverOnMainQueue).start(next: { status in + if let strongSelf = self { + strongSelf.status = status + strongSelf.updateStatus() + } + })) + } + + if let updatedPlayerStatusSignal = updatedPlayerStatusSignal { + strongSelf.playerStatusDisposable.set((updatedPlayerStatusSignal + |> deliverOnMainQueue).start(next: { [weak self] status in + displayLinkDispatcher.dispatch { + if let strongSelf = self { + strongSelf.playerStatus = status + } + } + })) } if let durationNode = strongSelf.durationNode { @@ -448,7 +477,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { } let displayMute: Bool - switch status { + switch status.mediaStatus { case let .fetchStatus(fetchStatus): switch fetchStatus { case .Local: @@ -472,7 +501,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { } var progressRequired = false - if case let .fetchStatus(fetchStatus) = status { + if case let .fetchStatus(fetchStatus) = status.mediaStatus { if case .Local = fetchStatus { if file.isVideo { progressRequired = true @@ -484,10 +513,6 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { } } - if item.message.flags.isSending && item.message.forwardInfo != nil { - progressRequired = false - } - if progressRequired { if self.statusNode == nil { let statusNode = RadialStatusNode(backgroundNodeColor: item.presentationData.theme.theme.chat.bubble.mediaOverlayControlBackgroundColor) @@ -505,13 +530,34 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { } } + var isBuffering: Bool? + if let message = self.item?.message, let media = self.media, let size = media.size, (isMediaStreamable(message: message, media: media) || size <= 256 * 1024) && (self.automaticDownload ?? false) { + if let playerStatus = self.playerStatus, case .buffering = playerStatus.status { + isBuffering = true + } else { + isBuffering = false + } + } + var state: RadialStatusNodeState - switch status { - case let .fetchStatus(fetchStatus): + switch status.mediaStatus { + case var .fetchStatus(fetchStatus): + if item.message.forwardInfo != nil { + fetchStatus = status.fetchStatus + } + switch fetchStatus { case let .Fetching(_, progress): - let adjustedProgress = max(progress, 0.027) - state = .progress(color: bubbleTheme.mediaOverlayControlForegroundColor, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true) + if let isBuffering = isBuffering { + if isBuffering { + state = .progress(color: bubbleTheme.mediaOverlayControlForegroundColor, lineWidth: nil, value: nil, cancelEnabled: false) + } else { + state = .none + } + } else { + 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 { if let (beginTime, timeout) = secretBeginTimeAndTimeout { @@ -526,7 +572,11 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { state = .download(bubbleTheme.mediaOverlayControlForegroundColor) } default: - state = .none + if isBuffering ?? false { + state = .progress(color: bubbleTheme.mediaOverlayControlForegroundColor, lineWidth: nil, value: nil, cancelEnabled: false) + } else { + state = .none + } } if let statusNode = self.statusNode { if state == .none { @@ -539,7 +589,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { }) } - if case .playbackStatus = status { + if case .playbackStatus = status.mediaStatus { let playbackStatusNode: InstantVideoRadialStatusNode if let current = self.playbackStatusNode { playbackStatusNode = current @@ -608,7 +658,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { return } if self.infoBackgroundNode.alpha.isZero { - if let status = self.status, case let .fetchStatus(fetchStatus) = status, case .Remote = fetchStatus { + if let status = self.status, case let .fetchStatus(fetchStatus) = status.mediaStatus, case .Remote = fetchStatus { item.context.sharedContext.mediaManager.playlistControl(.playback(.pause), type: .voice) self.videoNode?.fetchControl(.fetch) } else { @@ -638,7 +688,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { return } if let status = self.status { - switch status { + switch status.mediaStatus { case let .fetchStatus(fetchStatus): switch fetchStatus { case .Fetching: diff --git a/TelegramUI/ChatMessageInteractiveMediaBadge.swift b/TelegramUI/ChatMessageInteractiveMediaBadge.swift index 41a6359b8b..e8f5d227de 100644 --- a/TelegramUI/ChatMessageInteractiveMediaBadge.swift +++ b/TelegramUI/ChatMessageInteractiveMediaBadge.swift @@ -82,7 +82,7 @@ final class ChatMessageInteractiveMediaBadge: ASDisplayNode { return self.measureNode.measure(CGSize(width: 240.0, height: 160.0)).width } - func update(theme: PresentationTheme, content: ChatMessageInteractiveMediaBadgeContent?, mediaDownloadState: ChatMessageInteractiveMediaDownloadState?, alignment: NSTextAlignment = .left, animated: Bool) { + func update(theme: PresentationTheme, content: ChatMessageInteractiveMediaBadgeContent?, mediaDownloadState: ChatMessageInteractiveMediaDownloadState?, alignment: NSTextAlignment = .left, animated: Bool, badgeAnimated: Bool = true) { var transition: ContainedViewLayoutTransition = animated ? .animated(duration: 0.2, curve: .easeInOut) : .immediate let previousContentSize = self.previousContentSize @@ -285,9 +285,9 @@ final class ChatMessageInteractiveMediaBadge: ASDisplayNode { mediaStatusFrame = CGRect(origin: CGPoint(x: 7.0 + originX, y: originY), size: CGSize(width: 28.0, height: 28.0)) } mediaDownloadStatusNode.frame = mediaStatusFrame - mediaDownloadStatusNode.transitionToState(state, animated: true, completion: {}) + mediaDownloadStatusNode.transitionToState(state, animated: badgeAnimated, completion: {}) } else if let mediaDownloadStatusNode = self.mediaDownloadStatusNode { - mediaDownloadStatusNode.transitionToState(.none, animated: true, completion: {}) + mediaDownloadStatusNode.transitionToState(.none, animated: badgeAnimated, completion: {}) } } } diff --git a/TelegramUI/ChatMessageInteractiveMediaNode.swift b/TelegramUI/ChatMessageInteractiveMediaNode.swift index f3507e4c02..ec5b2862da 100644 --- a/TelegramUI/ChatMessageInteractiveMediaNode.swift +++ b/TelegramUI/ChatMessageInteractiveMediaNode.swift @@ -41,6 +41,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { private let imageNode: TransformImageNode private var currentImageArguments: TransformImageArguments? private var videoNode: UniversalVideoNode? + private var videoContent: NativeVideoContent? private var statusNode: RadialStatusNode? var videoNodeDecoration: ChatBubbleVideoDecoration? private var badgeNode: ChatMessageInteractiveMediaBadge? @@ -73,7 +74,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { } else { self.stopTimer() } - self.updateFetchStatus() + self.updateStatus() } } } @@ -176,7 +177,11 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { if case .ended = recognizer.state { let point = recognizer.location(in: self.imageNode.view) if let fetchStatus = self.fetchStatus, case .Local = fetchStatus { - self.activateLocalContent((self.automaticPlayback ?? false) ? .automaticPlayback : .default) + var videoContentMatch = true + if let content = self.videoContent, case let .message(id, _, _) = content.nativeId { + videoContentMatch = self.message?.id == id + } + self.activateLocalContent((self.automaticPlayback ?? false) && videoContentMatch ? .automaticPlayback : .default) } else { if let message = self.message, message.flags.isSending { if let statusNode = self.statusNode, statusNode.frame.contains(point) { @@ -594,13 +599,15 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { let mediaManager = context.sharedContext.mediaManager let streamVideo = isMediaStreamable(message: message, media: updatedVideoFile) - let videoNode = UniversalVideoNode(postbox: context.account.postbox, audioSession: mediaManager.audioSession, manager: mediaManager.universalVideoManager, decoration: decoration, content: NativeVideoContent(id: .message(message.id, message.stableId, updatedVideoFile.fileId), fileReference: .message(message: MessageReference(message), media: updatedVideoFile), streamVideo: streamVideo, enableSound: false, fetchAutomatically: false, onlyFullSizeThumbnail: (onlyFullSizeVideoThumbnail ?? false), continuePlayingWithoutSoundOnLostAudioSession: isInlinePlayableVideo, placeholderColor: emptyColor), priority: .embedded) + let videoContent = NativeVideoContent(id: .message(message.id, message.stableId, updatedVideoFile.fileId), fileReference: .message(message: MessageReference(message), media: updatedVideoFile), streamVideo: streamVideo ? .earlierStart : .none, enableSound: false, fetchAutomatically: false, onlyFullSizeThumbnail: (onlyFullSizeVideoThumbnail ?? false), continuePlayingWithoutSoundOnLostAudioSession: isInlinePlayableVideo, placeholderColor: emptyColor) + let videoNode = UniversalVideoNode(postbox: context.account.postbox, audioSession: mediaManager.audioSession, manager: mediaManager.universalVideoManager, decoration: decoration, content: videoContent, priority: .embedded) videoNode.isUserInteractionEnabled = false videoNode.ownsContentNodeUpdated = { [weak self] owns in if let strongSelf = self { strongSelf.videoNode?.isHidden = !owns } } + strongSelf.videoContent = videoContent strongSelf.videoNode = videoNode updatedVideoNodeReadySignal = videoNode.ready @@ -649,19 +656,21 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { } if let updatedStatusSignal = updatedStatusSignal { - strongSelf.statusDisposable.set((updatedStatusSignal |> deliverOnMainQueue).start(next: { [weak strongSelf] status, actualFetchStatus in + strongSelf.statusDisposable.set((updatedStatusSignal + |> deliverOnMainQueue).start(next: { [weak strongSelf] status, actualFetchStatus in displayLinkDispatcher.dispatch { if let strongSelf = strongSelf { strongSelf.fetchStatus = status strongSelf.actualFetchStatus = actualFetchStatus - strongSelf.updateFetchStatus() + strongSelf.updateStatus() } } })) } if let updatedVideoNodeReadySignal = updatedVideoNodeReadySignal { - strongSelf.videoNodeReadyDisposable.set((updatedVideoNodeReadySignal |> deliverOnMainQueue).start(next: { [weak strongSelf] status in + strongSelf.videoNodeReadyDisposable.set((updatedVideoNodeReadySignal + |> deliverOnMainQueue).start(next: { [weak strongSelf] status in displayLinkDispatcher.dispatch { if let strongSelf = strongSelf, let videoNode = strongSelf.videoNode { strongSelf.insertSubnode(videoNode, aboveSubnode: strongSelf.imageNode) @@ -671,7 +680,8 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { } if let updatedPlayerStatusSignal = updatedPlayerStatusSignal { - strongSelf.playerStatusDisposable.set((updatedPlayerStatusSignal |> deliverOnMainQueue).start(next: { [weak strongSelf] status in + strongSelf.playerStatusDisposable.set((updatedPlayerStatusSignal + |> deliverOnMainQueue).start(next: { [weak strongSelf] status in displayLinkDispatcher.dispatch { if let strongSelf = strongSelf { strongSelf.playerStatus = status @@ -731,7 +741,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { strongSelf.fetchControls.with({ $0 })?.fetch(false) } - strongSelf.updateFetchStatus() + strongSelf.updateStatus() } }) }) @@ -742,7 +752,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { private func ensureHasTimer() { if self.playerUpdateTimer == nil { let timer = SwiftSignalKit.Timer(timeout: 0.5, repeat: true, completion: { [weak self] in - self?.updateFetchStatus() + self?.updateStatus() }, queue: Queue.mainQueue()) self.playerUpdateTimer = timer timer.start() @@ -754,11 +764,18 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { self.playerUpdateTimer = nil } - private func updateFetchStatus() { + private func updateStatus() { guard let (theme, strings, decimalSeparator) = self.themeAndStrings, let sizeCalculation = self.sizeCalculation, let message = self.message, var automaticPlayback = self.automaticPlayback, let wideLayout = self.wideLayout else { return } + let automaticDownload: Bool + if let autoDownload = self.automaticDownload, case .full = autoDownload { + automaticDownload = true + } else { + automaticDownload = false + } + var secretBeginTimeAndTimeout: (Double?, Double)? let isSecretMedia = message.containsSecretMedia if isSecretMedia { @@ -814,10 +831,6 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { progressRequired = true } } - - if message.flags.isSending && message.forwardInfo != nil { - progressRequired = false - } } let radialStatusSize: CGFloat = wideLayout ? 50.0 : 32.0 @@ -893,7 +906,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { automaticPlayback = false } - if let actualFetchStatus = self.actualFetchStatus, automaticPlayback { + if let actualFetchStatus = self.actualFetchStatus, automaticPlayback || message.forwardInfo != nil { fetchStatus = actualFetchStatus } @@ -913,9 +926,12 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { if let file = self.media as? TelegramMediaFile { if wideLayout { if let size = file.size { - if let duration = file.duration, !message.flags.contains(.Unsent) { + let sizeString = "\(dataSizeString(Int(Float(size) * progress), forceDecimal: true, decimalSeparator: decimalSeparator)) / \(dataSizeString(size, forceDecimal: true, decimalSeparator: decimalSeparator))" + if file.isAnimated && !automaticDownload { + badgeContent = .mediaDownload(backgroundColor: bubbleTheme.mediaDateAndStatusFillColor, foregroundColor: bubbleTheme.mediaDateAndStatusTextColor, duration: "GIF " + sizeString, size: nil, muted: false, active: false) + } + else if let duration = file.duration, !message.flags.contains(.Unsent) { let durationString = file.isAnimated ? "GIF" : stringForDuration(playerDuration > 0 ? playerDuration : duration, position: playerPosition) - let sizeString = "\(dataSizeString(Int(Float(size) * progress), forceDecimal: true, decimalSeparator: decimalSeparator)) / \(dataSizeString(size, forceDecimal: true, decimalSeparator: decimalSeparator))" if isMediaStreamable(message: message, media: file) { badgeContent = .mediaDownload(backgroundColor: bubbleTheme.mediaDateAndStatusFillColor, foregroundColor: bubbleTheme.mediaDateAndStatusTextColor, duration: durationString, size: active ? sizeString : nil, muted: muted, active: active) mediaDownloadState = .fetching(progress: automaticPlayback ? nil : adjustedProgress) @@ -1015,24 +1031,29 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { case .Remote: state = .download(bubbleTheme.mediaOverlayControlForegroundColor) if let file = self.media as? TelegramMediaFile { - let durationString = file.isAnimated ? "GIF" : stringForDuration(playerDuration > 0 ? playerDuration : (file.duration ?? 0), position: playerPosition) - if wideLayout { - if isMediaStreamable(message: message, media: file) { - state = automaticPlayback ? .none : .play(bubbleTheme.mediaOverlayControlForegroundColor) - badgeContent = .mediaDownload(backgroundColor: bubbleTheme.mediaDateAndStatusFillColor, foregroundColor: bubbleTheme.mediaDateAndStatusTextColor, duration: durationString, size: dataSizeString(file.size ?? 0, decimalSeparator: decimalSeparator), muted: muted, active: true) - mediaDownloadState = .remote - } else { - state = automaticPlayback ? .none : state - badgeContent = .mediaDownload(backgroundColor: bubbleTheme.mediaDateAndStatusFillColor, foregroundColor: bubbleTheme.mediaDateAndStatusTextColor, duration: durationString, size: nil, muted: muted, active: false) - } + if file.isAnimated && !automaticDownload { + let string = "GIF " + dataSizeString(file.size ?? 0, decimalSeparator: decimalSeparator) + badgeContent = .mediaDownload(backgroundColor: bubbleTheme.mediaDateAndStatusFillColor, foregroundColor: bubbleTheme.mediaDateAndStatusTextColor, duration: string, size: nil, muted: false, active: false) } else { - if isMediaStreamable(message: message, media: file) { - state = automaticPlayback ? .none : .play(bubbleTheme.mediaOverlayControlForegroundColor) - badgeContent = .text(inset: 12.0, backgroundColor: bubbleTheme.mediaDateAndStatusFillColor, foregroundColor: bubbleTheme.mediaDateAndStatusTextColor, text: NSAttributedString(string: durationString)) - mediaDownloadState = .compactRemote + let durationString = file.isAnimated ? "GIF" : stringForDuration(playerDuration > 0 ? playerDuration : (file.duration ?? 0), position: playerPosition) + if wideLayout { + if isMediaStreamable(message: message, media: file) { + state = automaticPlayback ? .none : .play(bubbleTheme.mediaOverlayControlForegroundColor) + badgeContent = .mediaDownload(backgroundColor: bubbleTheme.mediaDateAndStatusFillColor, foregroundColor: bubbleTheme.mediaDateAndStatusTextColor, duration: durationString, size: dataSizeString(file.size ?? 0, decimalSeparator: decimalSeparator), muted: muted, active: true) + mediaDownloadState = .remote + } else { + state = automaticPlayback ? .none : state + badgeContent = .mediaDownload(backgroundColor: bubbleTheme.mediaDateAndStatusFillColor, foregroundColor: bubbleTheme.mediaDateAndStatusTextColor, duration: durationString, size: nil, muted: muted, active: false) + } } else { - state = automaticPlayback ? .none : state - badgeContent = .text(inset: 0.0, backgroundColor: bubbleTheme.mediaDateAndStatusFillColor, foregroundColor: bubbleTheme.mediaDateAndStatusTextColor, text: NSAttributedString(string: durationString)) + if isMediaStreamable(message: message, media: file) { + state = automaticPlayback ? .none : .play(bubbleTheme.mediaOverlayControlForegroundColor) + badgeContent = .text(inset: 12.0, backgroundColor: bubbleTheme.mediaDateAndStatusFillColor, foregroundColor: bubbleTheme.mediaDateAndStatusTextColor, text: NSAttributedString(string: durationString)) + mediaDownloadState = .compactRemote + } else { + state = automaticPlayback ? .none : state + badgeContent = .text(inset: 0.0, backgroundColor: bubbleTheme.mediaDateAndStatusFillColor, foregroundColor: bubbleTheme.mediaDateAndStatusTextColor, text: NSAttributedString(string: durationString)) + } } } } else if let webpage = webpage, let automaticDownload = self.automaticDownload, case .full = automaticDownload, case let .Loaded(content) = webpage.content, content.type != "telegram_background" { @@ -1092,7 +1113,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { if isSecretMedia, secretBeginTimeAndTimeout?.0 != nil { if self.secretTimer == nil { self.secretTimer = SwiftSignalKit.Timer(timeout: 0.3, repeat: true, completion: { [weak self] in - self?.updateFetchStatus() + self?.updateStatus() }, queue: Queue.mainQueue()) self.secretTimer?.start() } diff --git a/TelegramUI/ChatRecordingPreviewInputPanelNode.swift b/TelegramUI/ChatRecordingPreviewInputPanelNode.swift index dce082ba39..ac30eaa36a 100644 --- a/TelegramUI/ChatRecordingPreviewInputPanelNode.swift +++ b/TelegramUI/ChatRecordingPreviewInputPanelNode.swift @@ -111,7 +111,7 @@ final class ChatRecordingPreviewInputPanelNode: ChatInputPanelNode { } if let context = self.context { let mediaManager = context.sharedContext.mediaManager - let mediaPlayer = MediaPlayer(audioSessionManager: mediaManager.audioSession, postbox: context.account.postbox, resourceReference: .standalone(resource: recordedMediaPreview.resource), streamable: false, video: false, preferSoftwareDecoding: false, enableSound: true, fetchAutomatically: true) + let mediaPlayer = MediaPlayer(audioSessionManager: mediaManager.audioSession, postbox: context.account.postbox, resourceReference: .standalone(resource: recordedMediaPreview.resource), streamable: .none, video: false, preferSoftwareDecoding: false, enableSound: true, fetchAutomatically: true) self.mediaPlayer = mediaPlayer self.durationLabel.defaultDuration = Double(recordedMediaPreview.duration) self.durationLabel.status = mediaPlayer.status diff --git a/TelegramUI/DefaultDarkPresentationTheme.swift b/TelegramUI/DefaultDarkPresentationTheme.swift index 8ccdaa86d9..ef000dfc15 100644 --- a/TelegramUI/DefaultDarkPresentationTheme.swift +++ b/TelegramUI/DefaultDarkPresentationTheme.swift @@ -27,7 +27,7 @@ private let rootNavigationBar = PresentationThemeRootNavigationBar( disabledButtonColor: UIColor(rgb: 0x525252), primaryTextColor: accentColor, secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.5), - controlColor: accentColor, + controlColor: UIColor(rgb: 0x767677), accentTextColor: accentColor, backgroundColor: UIColor(rgb: 0x1c1c1d), separatorColor: UIColor(rgb: 0x000000), diff --git a/TelegramUI/EditSettingsController.swift b/TelegramUI/EditSettingsController.swift index 7efd2ad8e9..5029595eda 100644 --- a/TelegramUI/EditSettingsController.swift +++ b/TelegramUI/EditSettingsController.swift @@ -29,6 +29,19 @@ private enum SettingsSection: Int32 { case logOut } +public enum EditSettingsEntryTag: ItemListItemTag { + case bio + + func isEqual(to other: ItemListItemTag) -> Bool { + if let other = other as? EditSettingsEntryTag, self == other { + return true + } else { + return false + } + } +} + + private enum SettingsEntry: ItemListNodeEntry { case userInfo(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, Peer?, CachedPeerData?, ItemListAvatarAndNameInfoItemState, ItemListAvatarAndNameInfoItemUpdatingAvatar?) case userInfoNotice(PresentationTheme, String) @@ -177,8 +190,7 @@ private enum SettingsEntry: ItemListNodeEntry { case let .bioText(theme, currentText, placeholder): return ItemListMultilineInputItem(theme: theme, text: currentText, placeholder: placeholder, maxLength: ItemListMultilineInputItemTextLimit(value: 70, display: true), sectionId: self.section, style: .blocks, textUpdated: { updatedText in arguments.updateBioText(currentText, updatedText) - }, action: { - + }, tag: EditSettingsEntryTag.bio, action: { }) case let .bioInfo(theme, text): return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section) @@ -282,7 +294,7 @@ private func editSettingsEntries(presentationData: PresentationData, state: Edit return entries } -func editSettingsController(context: AccountContext, currentName: ItemListAvatarAndNameInfoItemName, currentBioText: String, accountManager: AccountManager, canAddAccounts: Bool) -> ViewController { +func editSettingsController(context: AccountContext, currentName: ItemListAvatarAndNameInfoItemName, currentBioText: String, accountManager: AccountManager, canAddAccounts: Bool, focusOnItemTag: EditSettingsEntryTag? = nil) -> ViewController { let initialState = EditSettingsState(editingName: currentName, editingBioText: currentBioText) let statePromise = ValuePromise(initialState, ignoreRepeated: true) let stateValue = Atomic(value: initialState) @@ -399,7 +411,7 @@ func editSettingsController(context: AccountContext, currentName: ItemListAvatar } let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.EditProfile_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back)) - let listState = ItemListNodeState(entries: editSettingsEntries(presentationData: presentationData, state: state, view: view, canAddAccounts: canAddAccounts), style: .blocks) + let listState = ItemListNodeState(entries: editSettingsEntries(presentationData: presentationData, state: state, view: view, canAddAccounts: canAddAccounts), style: .blocks, ensureVisibleItemTag: focusOnItemTag) return (controllerState, (listState, arguments)) } |> afterDisposed { diff --git a/TelegramUI/FFMpegMediaFrameSource.swift b/TelegramUI/FFMpegMediaFrameSource.swift index ade6297caa..ac3d5fc70b 100644 --- a/TelegramUI/FFMpegMediaFrameSource.swift +++ b/TelegramUI/FFMpegMediaFrameSource.swift @@ -71,6 +71,9 @@ final class FFMpegMediaFrameSource: NSObject, MediaFrameSource { private let resourceReference: MediaResourceReference private let tempFilePath: String? private let streamable: Bool + private let stallDuration: Double + private let lowWaterDuration: Double + private let highWaterDuration: Double private let video: Bool private let preferSoftwareDecoding: Bool private let fetchAutomatically: Bool @@ -95,7 +98,7 @@ final class FFMpegMediaFrameSource: NSObject, MediaFrameSource { } } - init(queue: Queue, postbox: Postbox, resourceReference: MediaResourceReference, tempFilePath: String?, streamable: Bool, video: Bool, preferSoftwareDecoding: Bool, fetchAutomatically: Bool, maximumFetchSize: Int? = nil) { + init(queue: Queue, postbox: Postbox, resourceReference: MediaResourceReference, tempFilePath: String?, streamable: Bool, video: Bool, preferSoftwareDecoding: Bool, fetchAutomatically: Bool, maximumFetchSize: Int? = nil, stallDuration: Double = 1.0, lowWaterDuration: Double = 2.0, highWaterDuration: Double = 3.0) { self.queue = queue self.postbox = postbox self.resourceReference = resourceReference @@ -105,6 +108,9 @@ final class FFMpegMediaFrameSource: NSObject, MediaFrameSource { self.preferSoftwareDecoding = preferSoftwareDecoding self.fetchAutomatically = fetchAutomatically self.maximumFetchSize = maximumFetchSize + self.stallDuration = stallDuration + self.lowWaterDuration = lowWaterDuration + self.highWaterDuration = highWaterDuration self.taskQueue = ThreadTaskQueue() @@ -252,12 +258,12 @@ final class FFMpegMediaFrameSource: NSObject, MediaFrameSource { var videoBuffer: MediaTrackFrameBuffer? if let audio = streamDescriptions.audio { - audioBuffer = MediaTrackFrameBuffer(frameSource: strongSelf, decoder: audio.decoder, type: .audio, duration: audio.duration, rotationAngle: 0.0, aspect: 1.0) + audioBuffer = MediaTrackFrameBuffer(frameSource: strongSelf, decoder: audio.decoder, type: .audio, duration: audio.duration, rotationAngle: 0.0, aspect: 1.0, stallDuration: strongSelf.stallDuration, lowWaterDuration: strongSelf.lowWaterDuration, highWaterDuration: strongSelf.highWaterDuration) } var extraDecodedVideoFrames: [MediaTrackFrame] = [] if let video = streamDescriptions.video { - videoBuffer = MediaTrackFrameBuffer(frameSource: strongSelf, decoder: video.decoder, type: .video, duration: video.duration, rotationAngle: video.rotationAngle, aspect: video.aspect) + videoBuffer = MediaTrackFrameBuffer(frameSource: strongSelf, decoder: video.decoder, type: .video, duration: video.duration, rotationAngle: video.rotationAngle, aspect: video.aspect, stallDuration: strongSelf.stallDuration, lowWaterDuration: strongSelf.lowWaterDuration, highWaterDuration: strongSelf.highWaterDuration) for videoFrame in streamDescriptions.extraVideoFrames { if let decodedFrame = video.decoder.decode(frame: videoFrame) { extraDecodedVideoFrames.append(decodedFrame) diff --git a/TelegramUI/ForwardPrivacyChatPreviewItem.swift b/TelegramUI/ForwardPrivacyChatPreviewItem.swift index 620451da0e..955949e9e0 100644 --- a/TelegramUI/ForwardPrivacyChatPreviewItem.swift +++ b/TelegramUI/ForwardPrivacyChatPreviewItem.swift @@ -5,7 +5,6 @@ import SwiftSignalKit import TelegramCore import Postbox - class ForwardPrivacyChatPreviewItem: ListViewItem, ItemListItem { let context: AccountContext let theme: PresentationTheme @@ -15,10 +14,11 @@ class ForwardPrivacyChatPreviewItem: ListViewItem, ItemListItem { let wallpaper: TelegramWallpaper let dateTimeFormat: PresentationDateTimeFormat let nameDisplayOrder: PresentationPersonNameOrder + let peerName: String let linkEnabled: Bool let tooltipText: String - init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, sectionId: ItemListSectionId, fontSize: PresentationFontSize, wallpaper: TelegramWallpaper, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, linkEnabled: Bool, tooltipText: String) { + init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, sectionId: ItemListSectionId, fontSize: PresentationFontSize, wallpaper: TelegramWallpaper, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, peerName: String, linkEnabled: Bool, tooltipText: String) { self.context = context self.theme = theme self.strings = strings @@ -27,6 +27,7 @@ class ForwardPrivacyChatPreviewItem: ListViewItem, ItemListItem { self.wallpaper = wallpaper self.dateTimeFormat = dateTimeFormat self.nameDisplayOrder = nameDisplayOrder + self.peerName = peerName self.linkEnabled = linkEnabled self.tooltipText = tooltipText } @@ -140,9 +141,9 @@ class ForwardPrivacyChatPreviewItemNode: ListViewItemNode { var peers = SimpleDictionary() let messages = SimpleDictionary() - peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: item.strings.Privacy_Forwards_PreviewForwardAuthor, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: []) + peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: item.peerName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: []) - let forwardInfo = MessageForwardInfo(author: item.linkEnabled ? peers[peerId] : nil, source: nil, sourceMessageId: nil, date: 0, authorSignature: item.linkEnabled ? nil : item.strings.Privacy_Forwards_PreviewForwardAuthor) + let forwardInfo = MessageForwardInfo(author: item.linkEnabled ? peers[peerId] : nil, source: nil, sourceMessageId: nil, date: 0, authorSignature: item.linkEnabled ? nil : item.peerName) let chatPresentationData = ChatPresentationData(theme: ChatPresentationThemeData(theme: item.theme, wallpaper: item.wallpaper), fontSize: item.fontSize, strings: item.strings, dateTimeFormat: item.dateTimeFormat, nameDisplayOrder: item.nameDisplayOrder, disableAnimations: false) @@ -186,7 +187,7 @@ class ForwardPrivacyChatPreviewItemNode: ListViewItemNode { fromString = String(from) } } - let authorString = item.strings.Privacy_Forwards_PreviewForwardAuthor + let authorString = item.peerName if let fromString = fromString { var attributedMeasureText = NSAttributedString(string: fromString, font: Font.regular(13.0), textColor: .black) diff --git a/TelegramUI/GalleryController.swift b/TelegramUI/GalleryController.swift index 092d9f3fff..7d08fc94ea 100644 --- a/TelegramUI/GalleryController.swift +++ b/TelegramUI/GalleryController.swift @@ -141,10 +141,10 @@ func galleryItemForEntry(context: AccountContext, presentationData: Presentation if file.isVideo { let content: UniversalVideoContent if file.isAnimated { - content = NativeVideoContent(id: .message(message.id, message.stableId, file.fileId), fileReference: .message(message: MessageReference(message), media: file), imageReference: mediaImage.flatMap({ ImageMediaReference.message(message: MessageReference(message), media: $0) }), streamVideo: false, loopVideo: true, enableSound: false, tempFilePath: tempFilePath) + content = NativeVideoContent(id: .message(message.id, message.stableId, file.fileId), fileReference: .message(message: MessageReference(message), media: file), imageReference: mediaImage.flatMap({ ImageMediaReference.message(message: MessageReference(message), media: $0) }), loopVideo: true, enableSound: false, tempFilePath: tempFilePath) } else { if true || (file.mimeType == "video/mpeg4" || file.mimeType == "video/mov" || file.mimeType == "video/mp4") { - content = NativeVideoContent(id: .message(message.id, message.stableId, file.fileId), fileReference: .message(message: MessageReference(message), media: file), imageReference: mediaImage.flatMap({ ImageMediaReference.message(message: MessageReference(message), media: $0) }), streamVideo: true, loopVideo: loopVideos, tempFilePath: tempFilePath) + content = NativeVideoContent(id: .message(message.id, message.stableId, file.fileId), fileReference: .message(message: MessageReference(message), media: file), imageReference: mediaImage.flatMap({ ImageMediaReference.message(message: MessageReference(message), media: $0) }), streamVideo: .conservative, loopVideo: loopVideos, tempFilePath: tempFilePath) } else { content = PlatformVideoContent(id: .message(message.id, message.stableId, file.fileId), fileReference: .message(message: MessageReference(message), media: file), streamVideo: streamVideos, loopVideo: loopVideos) } @@ -180,11 +180,11 @@ func galleryItemForEntry(context: AccountContext, presentationData: Presentation var content: UniversalVideoContent? switch websiteType(of: webpageContent) { case .instagram where webpageContent.file != nil && webpageContent.image != nil && webpageContent.file!.isVideo: - content = NativeVideoContent(id: .message(message.id, message.stableId, webpageContent.file?.id ?? webpage.webpageId), fileReference: .message(message: MessageReference(message), media: webpageContent.file!), imageReference: webpageContent.image.flatMap({ ImageMediaReference.message(message: MessageReference(message), media: $0) }), streamVideo: true, enableSound: true) + content = NativeVideoContent(id: .message(message.id, message.stableId, webpageContent.file?.id ?? webpage.webpageId), fileReference: .message(message: MessageReference(message), media: webpageContent.file!), imageReference: webpageContent.image.flatMap({ ImageMediaReference.message(message: MessageReference(message), media: $0) }), streamVideo: .conservative, enableSound: true) default: if let embedUrl = webpageContent.embedUrl, let image = webpageContent.image { if let file = webpageContent.file, file.isVideo { - content = NativeVideoContent(id: .message(message.id, message.stableId, file.fileId), fileReference: .message(message: MessageReference(message), media: file), imageReference: mediaImage.flatMap({ ImageMediaReference.message(message: MessageReference(message), media: $0) }), streamVideo: true, loopVideo: loopVideos, tempFilePath: tempFilePath) + content = NativeVideoContent(id: .message(message.id, message.stableId, file.fileId), fileReference: .message(message: MessageReference(message), media: file), imageReference: mediaImage.flatMap({ ImageMediaReference.message(message: MessageReference(message), media: $0) }), streamVideo: .conservative, loopVideo: loopVideos, tempFilePath: tempFilePath) } else if URL(string: embedUrl)?.pathExtension == "mp4" { content = SystemVideoContent(url: embedUrl, imageReference: .webPage(webPage: WebpageReference(webpage), media: image), dimensions: webpageContent.embedSize ?? CGSize(width: 640.0, height: 640.0), duration: Int32(webpageContent.duration ?? 0)) } diff --git a/TelegramUI/InstantPageControllerNode.swift b/TelegramUI/InstantPageControllerNode.swift index af1bef6688..122e95513e 100644 --- a/TelegramUI/InstantPageControllerNode.swift +++ b/TelegramUI/InstantPageControllerNode.swift @@ -1021,11 +1021,29 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate { return nil } - private func presentReferenceView(item: InstantPageTextItem) { + private func presentReferenceView(item: InstantPageTextItem, referenceAnchor: String) { guard let theme = self.theme, let webPage = self.webPage else { return } - let controller = InstantPageReferenceController(context: self.context, theme: theme, webPage: webPage, item: item, openUrl: { [weak self] url in + + var targetAnchor: InstantPageTextAnchorItem? + for (name, (line, _)) in item.anchors { + if name == referenceAnchor { + let anchors = item.lines[line].anchorItems + for anchor in anchors { + if anchor.name == referenceAnchor { + targetAnchor = anchor + break + } + } + } + } + + guard let anchorText = targetAnchor?.anchorText else { + return + } + + let controller = InstantPageReferenceController(context: self.context, theme: theme, webPage: webPage, anchorText: anchorText, openUrl: { [weak self] url in self?.openUrl(url) }, openUrlIn: { [weak self] url in self?.openUrlIn(url) @@ -1043,7 +1061,7 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate { if !anchor.isEmpty { if let (item, lineOffset, reference, detailsItems) = findAnchorItem(String(anchor), items: items) { if let item = item as? InstantPageTextItem, reference { - self.presentReferenceView(item: item) + self.presentReferenceView(item: item, referenceAnchor: anchor) } else { var previousDetailsNode: InstantPageDetailsNode? var containerOffset: CGFloat = 0.0 diff --git a/TelegramUI/InstantPageGalleryController.swift b/TelegramUI/InstantPageGalleryController.swift index e318026335..8b4815817d 100644 --- a/TelegramUI/InstantPageGalleryController.swift +++ b/TelegramUI/InstantPageGalleryController.swift @@ -28,7 +28,7 @@ struct InstantPageGalleryEntry: Equatable { return lhs.index == rhs.index && lhs.pageId == rhs.pageId && lhs.media == rhs.media && lhs.caption == rhs.caption && lhs.credit == rhs.credit && lhs.location == rhs.location } - func item(context: AccountContext, webPage: TelegramMediaWebpage, message: Message?, presentationData: PresentationData, fromPlayingVideo: Bool, openUrl: @escaping (InstantPageUrlItem) -> Void, openUrlOptions: @escaping (InstantPageUrlItem) -> Void) -> GalleryItem { + func item(context: AccountContext, webPage: TelegramMediaWebpage, message: Message?, presentationData: PresentationData, fromPlayingVideo: Bool, landscape: Bool, openUrl: @escaping (InstantPageUrlItem) -> Void, openUrlOptions: @escaping (InstantPageUrlItem) -> Void) -> GalleryItem { let caption: NSAttributedString let credit: NSAttributedString @@ -91,10 +91,10 @@ struct InstantPageGalleryEntry: Equatable { nativeId = .instantPage(self.pageId, file.fileId) } - return UniversalVideoGalleryItem(context: context, presentationData: presentationData, content: NativeVideoContent(id: nativeId, fileReference: .webPage(webPage: WebpageReference(webPage), media: file), streamVideo: isMediaStreamable(media: file)), originData: nil, indexData: indexData, contentInfo: .webPage(webPage, file), caption: caption, credit: credit, fromPlayingVideo: fromPlayingVideo, performAction: { _ in }, openActionOptions: { _ in }) + return UniversalVideoGalleryItem(context: context, presentationData: presentationData, content: NativeVideoContent(id: nativeId, fileReference: .webPage(webPage: WebpageReference(webPage), media: file), streamVideo: isMediaStreamable(media: file) ? .conservative : .none), originData: nil, indexData: indexData, contentInfo: .webPage(webPage, file), caption: caption, credit: credit, fromPlayingVideo: fromPlayingVideo, landscape: landscape, performAction: { _ in }, openActionOptions: { _ in }) } else if let embedWebpage = self.media.media as? TelegramMediaWebpage, case let .Loaded(webpageContent) = embedWebpage.content { if let content = WebEmbedVideoContent(webPage: embedWebpage, webpageContent: webpageContent) { - return UniversalVideoGalleryItem(context: context, presentationData: presentationData, content: content, originData: nil, indexData: nil, contentInfo: .webPage(webPage, embedWebpage), caption: NSAttributedString(string: ""), fromPlayingVideo: fromPlayingVideo, performAction: { _ in }, openActionOptions: { _ in }) + return UniversalVideoGalleryItem(context: context, presentationData: presentationData, content: content, originData: nil, indexData: nil, contentInfo: .webPage(webPage, embedWebpage), caption: NSAttributedString(string: ""), fromPlayingVideo: fromPlayingVideo, landscape: landscape, performAction: { _ in }, openActionOptions: { _ in }) } else { preconditionFailure() } @@ -133,6 +133,7 @@ class InstantPageGalleryController: ViewController { private var entries: [InstantPageGalleryEntry] = [] private var centralEntryIndex: Int? private let fromPlayingVideo: Bool + private let landscape: Bool private let centralItemTitle = Promise() private let centralItemTitleView = Promise() @@ -152,11 +153,12 @@ class InstantPageGalleryController: ViewController { private var innerOpenUrl: (InstantPageUrlItem) -> Void private var openUrlOptions: (InstantPageUrlItem) -> Void - init(context: AccountContext, webPage: TelegramMediaWebpage, message: Message? = nil, entries: [InstantPageGalleryEntry], centralIndex: Int, fromPlayingVideo: Bool = false, replaceRootController: @escaping (ViewController, ValuePromise?) -> Void, baseNavigationController: NavigationController?) { + init(context: AccountContext, webPage: TelegramMediaWebpage, message: Message? = nil, entries: [InstantPageGalleryEntry], centralIndex: Int, fromPlayingVideo: Bool = false, landscape: Bool = false, replaceRootController: @escaping (ViewController, ValuePromise?) -> Void, baseNavigationController: NavigationController?) { self.context = context self.webPage = webPage self.message = message self.fromPlayingVideo = fromPlayingVideo + self.landscape = landscape self.replaceRootController = replaceRootController self.baseNavigationController = baseNavigationController @@ -186,7 +188,7 @@ class InstantPageGalleryController: ViewController { strongSelf.centralEntryIndex = centralIndex if strongSelf.isViewLoaded { strongSelf.galleryNode.pager.replaceItems(strongSelf.entries.map({ - $0.item(context: context, webPage: webPage, message: message, presentationData: strongSelf.presentationData, fromPlayingVideo: fromPlayingVideo, openUrl: strongSelf.innerOpenUrl, openUrlOptions: strongSelf.openUrlOptions) + $0.item(context: context, webPage: webPage, message: message, presentationData: strongSelf.presentationData, fromPlayingVideo: fromPlayingVideo, landscape: landscape, openUrl: strongSelf.innerOpenUrl, openUrlOptions: strongSelf.openUrlOptions) }), centralItemIndex: centralIndex, keepFirst: false) let ready = strongSelf.galleryNode.pager.ready() |> timeout(2.0, queue: Queue.mainQueue(), alternate: .single(Void())) |> afterNext { [weak strongSelf] _ in @@ -325,7 +327,7 @@ class InstantPageGalleryController: ViewController { } self.galleryNode.pager.replaceItems(self.entries.map({ - $0.item(context: self.context, webPage: self.webPage, message: self.message, presentationData: self.presentationData, fromPlayingVideo: self.fromPlayingVideo, openUrl: self.innerOpenUrl, openUrlOptions: self.openUrlOptions) + $0.item(context: self.context, webPage: self.webPage, message: self.message, presentationData: self.presentationData, fromPlayingVideo: self.fromPlayingVideo, landscape: self.landscape, openUrl: self.innerOpenUrl, openUrlOptions: self.openUrlOptions) }), centralItemIndex: self.centralEntryIndex) self.galleryNode.pager.centralItemIndexUpdated = { [weak self] index in diff --git a/TelegramUI/InstantPageLayout.swift b/TelegramUI/InstantPageLayout.swift index 5013e51920..159e1ddb4c 100644 --- a/TelegramUI/InstantPageLayout.swift +++ b/TelegramUI/InstantPageLayout.swift @@ -173,7 +173,7 @@ func layoutInstantPageBlock(webpage: TelegramMediaWebpage, rtl: Bool, block: Ins let styleStack = InstantPageTextStyleStack() setupStyleStack(styleStack, theme: theme, category: .paragraph, link: false) let backgroundInset: CGFloat = 14.0 - let (_, items, contentSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0 - backgroundInset * 2.0, offset: CGPoint(x: 17.0, y: backgroundInset), media: media, webpage: webpage) + let (_, items, contentSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0 - backgroundInset * 2.0, offset: CGPoint(x: 17.0, y: backgroundInset), media: media, webpage: webpage, opaqueBackground: true) let backgroundItem = InstantPageShapeItem(frame: CGRect(origin: CGPoint(), size: CGSize(width: boundingWidth, height: contentSize.height + backgroundInset * 2.0)), shapeFrame: CGRect(origin: CGPoint(), size: CGSize(width: boundingWidth, height: contentSize.height + backgroundInset * 2.0)), shape: .rect, color: theme.codeBlockBackgroundColor) var allItems: [InstantPageItem] = [backgroundItem] allItems.append(contentsOf: items) @@ -751,7 +751,7 @@ func layoutInstantPageBlock(webpage: TelegramMediaWebpage, rtl: Bool, block: Ins setupStyleStack(styleStack, theme: theme, category: .paragraph, link: false) styleStack.push(.bold) let backgroundInset: CGFloat = 14.0 - let (_, textItems, textContentSize) = layoutTextItemWithString(attributedStringForRichText(title, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0 - backgroundInset * 2.0, offset: CGPoint(x: horizontalInset, y: backgroundInset), media: media, webpage: webpage) + let (_, textItems, textContentSize) = layoutTextItemWithString(attributedStringForRichText(title, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0 - backgroundInset * 2.0, offset: CGPoint(x: horizontalInset, y: backgroundInset), media: media, webpage: webpage, opaqueBackground: true) let backgroundItem = InstantPageShapeItem(frame: CGRect(origin: CGPoint(), size: CGSize(width: boundingWidth, height: textContentSize.height + backgroundInset * 2.0)), shapeFrame: CGRect(origin: CGPoint(), size: CGSize(width: boundingWidth, height: textContentSize.height + backgroundInset * 2.0)), shape: .rect, color: theme.panelBackgroundColor) items.append(backgroundItem) items.append(contentsOf: textItems) diff --git a/TelegramUI/InstantPagePlayableVideoNode.swift b/TelegramUI/InstantPagePlayableVideoNode.swift index 6f998b6d63..7306f7913b 100644 --- a/TelegramUI/InstantPagePlayableVideoNode.swift +++ b/TelegramUI/InstantPagePlayableVideoNode.swift @@ -45,7 +45,7 @@ final class InstantPagePlayableVideoNode: ASDisplayNode, InstantPageNode { streamVideo = isMediaStreamable(media: file) } - self.videoNode = UniversalVideoNode(postbox: context.account.postbox, audioSession: context.sharedContext.mediaManager.audioSession, manager: context.sharedContext.mediaManager.universalVideoManager, decoration: GalleryVideoDecoration(), content: NativeVideoContent(id: .instantPage(webPage.webpageId, media.media.id!), fileReference: .webPage(webPage: WebpageReference(webPage), media: media.media as! TelegramMediaFile), imageReference: imageReference, streamVideo: streamVideo, loopVideo: true, enableSound: false, fetchAutomatically: true, placeholderColor: theme.pageBackgroundColor), priority: .embedded, autoplay: true) + self.videoNode = UniversalVideoNode(postbox: context.account.postbox, audioSession: context.sharedContext.mediaManager.audioSession, manager: context.sharedContext.mediaManager.universalVideoManager, decoration: GalleryVideoDecoration(), content: NativeVideoContent(id: .instantPage(webPage.webpageId, media.media.id!), fileReference: .webPage(webPage: WebpageReference(webPage), media: media.media as! TelegramMediaFile), imageReference: imageReference, streamVideo: streamVideo ? .earlierStart : .none, loopVideo: true, enableSound: false, fetchAutomatically: true, placeholderColor: theme.pageBackgroundColor), priority: .embedded, autoplay: true) self.videoNode.isUserInteractionEnabled = false self.statusNode = RadialStatusNode(backgroundNodeColor: UIColor(white: 0.0, alpha: 0.6)) diff --git a/TelegramUI/InstantPageReferenceController.swift b/TelegramUI/InstantPageReferenceController.swift index a12b0421ac..a5d5600c3f 100644 --- a/TelegramUI/InstantPageReferenceController.swift +++ b/TelegramUI/InstantPageReferenceController.swift @@ -15,16 +15,16 @@ final class InstantPageReferenceController: ViewController { private let context: AccountContext private let theme: InstantPageTheme private let webPage: TelegramMediaWebpage - private let item: InstantPageTextItem + private let anchorText: NSAttributedString private let openUrl: (InstantPageUrlItem) -> Void private let openUrlIn: (InstantPageUrlItem) -> Void private let present: (ViewController, Any?) -> Void - init(context: AccountContext, theme: InstantPageTheme, webPage: TelegramMediaWebpage, item: InstantPageTextItem, openUrl: @escaping (InstantPageUrlItem) -> Void, openUrlIn: @escaping (InstantPageUrlItem) -> Void, present: @escaping (ViewController, Any?) -> Void) { + init(context: AccountContext, theme: InstantPageTheme, webPage: TelegramMediaWebpage, anchorText: NSAttributedString, openUrl: @escaping (InstantPageUrlItem) -> Void, openUrlIn: @escaping (InstantPageUrlItem) -> Void, present: @escaping (ViewController, Any?) -> Void) { self.context = context self.theme = theme self.webPage = webPage - self.item = item + self.anchorText = anchorText self.openUrl = openUrl self.openUrlIn = openUrlIn self.present = present @@ -39,7 +39,7 @@ final class InstantPageReferenceController: ViewController { } override public func loadDisplayNode() { - self.displayNode = InstantPageReferenceControllerNode(context: self.context, theme: self.theme, webPage: self.webPage, item: self.item, openUrl: self.openUrl, openUrlIn: self.openUrlIn, present: self.present) + self.displayNode = InstantPageReferenceControllerNode(context: self.context, theme: self.theme, webPage: self.webPage, anchorText: self.anchorText, openUrl: self.openUrl, openUrlIn: self.openUrlIn, present: self.present) self.controllerNode.dismiss = { [weak self] in self?.presentingViewController?.dismiss(animated: false, completion: nil) } diff --git a/TelegramUI/InstantPageReferenceControllerNode.swift b/TelegramUI/InstantPageReferenceControllerNode.swift index 85e8000476..a4ab9000e3 100644 --- a/TelegramUI/InstantPageReferenceControllerNode.swift +++ b/TelegramUI/InstantPageReferenceControllerNode.swift @@ -10,7 +10,7 @@ class InstantPageReferenceControllerNode: ViewControllerTracingNode, UIScrollVie private let theme: InstantPageTheme private var presentationData: PresentationData private let webPage: TelegramMediaWebpage - private let item: InstantPageTextItem + private let anchorText: NSAttributedString private let dimNode: ASDisplayNode private let wrappingScrollNode: ASScrollNode @@ -32,12 +32,12 @@ class InstantPageReferenceControllerNode: ViewControllerTracingNode, UIScrollVie var dismiss: (() -> Void)? var close: (() -> Void)? - init(context: AccountContext, theme: InstantPageTheme, webPage: TelegramMediaWebpage, item: InstantPageTextItem, openUrl: @escaping (InstantPageUrlItem) -> Void, openUrlIn: @escaping (InstantPageUrlItem) -> Void, present: @escaping (ViewController, Any?) -> Void) { + init(context: AccountContext, theme: InstantPageTheme, webPage: TelegramMediaWebpage, anchorText: NSAttributedString, openUrl: @escaping (InstantPageUrlItem) -> Void, openUrlIn: @escaping (InstantPageUrlItem) -> Void, present: @escaping (ViewController, Any?) -> Void) { self.context = context self.presentationData = context.sharedContext.currentPresentationData.with { $0 } self.theme = theme self.webPage = webPage - self.item = item + self.anchorText = anchorText self.openUrl = openUrl self.openUrlIn = openUrlIn self.present = present @@ -195,7 +195,7 @@ class InstantPageReferenceControllerNode: ViewControllerTracingNode, UIScrollVie } let sideInset: CGFloat = 16.0 - let (_, items, contentSize) = layoutTextItemWithString(self.item.attributedString, boundingWidth: width - sideInset * 2.0, offset: CGPoint(x: sideInset, y: sideInset), media: media, webpage: self.webPage) + let (_, items, contentSize) = layoutTextItemWithString(self.anchorText, boundingWidth: width - sideInset * 2.0, offset: CGPoint(x: sideInset, y: sideInset), media: media, webpage: self.webPage) let contentNode = InstantPageContentNode(context: self.context, strings: self.presentationData.strings, theme: self.theme, items: items, contentSize: CGSize(width: width, height: contentSize.height), inOverlayPanel: true, openMedia: { _ in }, longPressMedia: { _ in }, openPeer: { _ in }, openUrl: { _ in }) transition.updateFrame(node: contentNode, frame: CGRect(origin: CGPoint(x: 0.0, y: titleAreaHeight), size: CGSize(width: width, height: contentSize.height))) self.contentContainerNode.insertSubnode(contentNode, at: 0) diff --git a/TelegramUI/InstantPageTextItem.swift b/TelegramUI/InstantPageTextItem.swift index d641c2d081..8983d7ed94 100644 --- a/TelegramUI/InstantPageTextItem.swift +++ b/TelegramUI/InstantPageTextItem.swift @@ -35,6 +35,7 @@ struct InstantPageTextImageItem { struct InstantPageTextAnchorItem { let name: String + let anchorText: NSAttributedString? let empty: Bool } @@ -76,6 +77,7 @@ final class InstantPageTextItem: InstantPageItem { let rtlLineIndices: Set var frame: CGRect let alignment: NSTextAlignment + let opaqueBackground: Bool let medias: [InstantPageMedia] = [] let anchors: [String: (Int, Bool)] let wantsNode: Bool = false @@ -86,10 +88,11 @@ final class InstantPageTextItem: InstantPageItem { return !self.rtlLineIndices.isEmpty } - init(frame: CGRect, attributedString: NSAttributedString, alignment: NSTextAlignment, lines: [InstantPageTextLine]) { + init(frame: CGRect, attributedString: NSAttributedString, alignment: NSTextAlignment, opaqueBackground: Bool, lines: [InstantPageTextLine]) { self.attributedString = attributedString self.alignment = alignment self.frame = frame + self.opaqueBackground = opaqueBackground self.lines = lines var index = 0 var rtlLineIndices = Set() @@ -111,7 +114,7 @@ final class InstantPageTextItem: InstantPageItem { context.saveGState() context.textMatrix = CGAffineTransform(scaleX: 1.0, y: -1.0) context.translateBy(x: self.frame.minX, y: self.frame.minY) - + let clipRect = context.boundingBoxOfClipPath let upperOriginBound = clipRect.minY - 10.0 @@ -143,7 +146,13 @@ final class InstantPageTextItem: InstantPageItem { context.restoreGState() } + if self.opaqueBackground { + context.setBlendMode(.normal) + } CTLineDraw(line.line, context) + if self.opaqueBackground { + context.setBlendMode(.copy) + } if !line.strikethroughItems.isEmpty { for item in line.strikethroughItems { @@ -494,7 +503,6 @@ func attributedStringForRichText(_ text: RichText, styleStack: InstantPageTextSt let descent: CGFloat let width: CGFloat } - var dimensions = dimensions if let boundingWidth = boundingWidth { dimensions = dimensions.fittedToWidthOrSmaller(boundingWidth) @@ -517,7 +525,6 @@ func attributedStringForRichText(_ text: RichText, styleStack: InstantPageTextSt let mutableAttributedString = attributedStringForRichText(.plain(" "), styleStack: styleStack, url: url).mutableCopy() as! NSMutableAttributedString mutableAttributedString.addAttributes(attrDictionaryDelegate, range: NSMakeRange(0, mutableAttributedString.length)) return mutableAttributedString - //return NSAttributedString(string: " ", attributes: attrDictionaryDelegate) case let .anchor(text, name): var empty = false var text = text @@ -525,14 +532,15 @@ func attributedStringForRichText(_ text: RichText, styleStack: InstantPageTextSt empty = true text = .plain("\u{200b}") } - styleStack.push(.anchor(name, empty)) + let anchorText = !empty ? attributedStringForRichText(text, styleStack: styleStack, url: url) : nil + styleStack.push(.anchor(name, anchorText, empty)) let result = attributedStringForRichText(text, styleStack: styleStack, url: url) styleStack.pop() return result } } -func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFloat, horizontalInset: CGFloat = 0.0, alignment: NSTextAlignment = .natural, offset: CGPoint, media: [MediaId: Media] = [:], webpage: TelegramMediaWebpage? = nil, minimizeWidth: Bool = false, maxNumberOfLines: Int = 0) -> (InstantPageTextItem?, [InstantPageItem], CGSize) { +func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFloat, horizontalInset: CGFloat = 0.0, alignment: NSTextAlignment = .natural, offset: CGPoint, media: [MediaId: Media] = [:], webpage: TelegramMediaWebpage? = nil, minimizeWidth: Bool = false, maxNumberOfLines: Int = 0, opaqueBackground: Bool = false) -> (InstantPageTextItem?, [InstantPageItem], CGSize) { if string.length == 0 { return (nil, [], CGSize()) } @@ -694,7 +702,7 @@ func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFlo markedItems.append(InstantPageTextMarkedItem(frame: CGRect(x: workingLineOrigin.x + x, y: workingLineOrigin.y + delta, width: abs(upperX - lowerX), height: lineHeight), color: color)) } if let item = attributes[NSAttributedStringKey.init(rawValue: InstantPageAnchorAttribute)] as? Dictionary, let name = item["name"] as? String, let empty = item["empty"] as? Bool { - anchorItems.append(InstantPageTextAnchorItem(name: name, empty: empty)) + anchorItems.append(InstantPageTextAnchorItem(name: name, anchorText: item["text"] as? NSAttributedString, empty: empty)) } } @@ -742,7 +750,7 @@ func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFlo requiresScroll = true } - let textItem = InstantPageTextItem(frame: CGRect(x: 0.0, y: 0.0, width: textWidth, height: height), attributedString: string, alignment: alignment, lines: lines) + let textItem = InstantPageTextItem(frame: CGRect(x: 0.0, y: 0.0, width: textWidth, height: height), attributedString: string, alignment: alignment, opaqueBackground: opaqueBackground, lines: lines) if !requiresScroll { textItem.frame = textItem.frame.offsetBy(dx: offset.x, dy: offset.y) } diff --git a/TelegramUI/InstantPageTextStyleStack.swift b/TelegramUI/InstantPageTextStyleStack.swift index 6628dc172d..79a0b6f279 100644 --- a/TelegramUI/InstantPageTextStyleStack.swift +++ b/TelegramUI/InstantPageTextStyleStack.swift @@ -16,7 +16,7 @@ enum InstantPageTextStyle { case superscript case markerColor(UIColor) case marker - case anchor(String, Bool) + case anchor(String, NSAttributedString?, Bool) case linkColor(UIColor) case linkMarkerColor(UIColor) case link(Bool) @@ -32,12 +32,12 @@ final class InstantPageTextStyleStack { private var items: [InstantPageTextStyle] = [] func push(_ item: InstantPageTextStyle) { - items.append(item) + self.items.append(item) } func pop() { - if !items.isEmpty { - items.removeLast() + if !self.items.isEmpty { + self.items.removeLast() } } @@ -114,9 +114,13 @@ final class InstantPageTextStyleStack { if marker == nil { marker = true } - case let .anchor(name, empty): + case let .anchor(name, anchorText, empty): if anchor == nil { - anchor = ["name": name, "empty": empty] + if let anchorText = anchorText { + anchor = ["name": name, "text": anchorText, "empty": empty] + } else { + anchor = ["name": name, "empty": empty] + } } case let .linkColor(color): if linkColor == nil { diff --git a/TelegramUI/InstantPageTile.swift b/TelegramUI/InstantPageTile.swift index ac991e2f01..c8ce9afd13 100644 --- a/TelegramUI/InstantPageTile.swift +++ b/TelegramUI/InstantPageTile.swift @@ -9,19 +9,8 @@ final class InstantPageTile { self.frame = frame } - func getRandomColor() -> UIColor { - //Generate between 0 to 1 - let red:CGFloat = CGFloat(drand48()) - let green:CGFloat = CGFloat(drand48()) - let blue:CGFloat = CGFloat(drand48()) - - return UIColor(red:red, green: green, blue: blue, alpha: 1.0) - } - func draw(context: CGContext) { context.translateBy(x: -self.frame.minX, y: -self.frame.minY) - //context.setFillColor(getRandomColor().cgColor) - //context.fill(self.frame) for item in self.items { item.drawInTile(context: context) } diff --git a/TelegramUI/IsMediaStreamable.swift b/TelegramUI/IsMediaStreamable.swift index 0e447552b9..a2528758e8 100644 --- a/TelegramUI/IsMediaStreamable.swift +++ b/TelegramUI/IsMediaStreamable.swift @@ -12,7 +12,7 @@ func isMediaStreamable(message: Message, media: TelegramMediaFile) -> Bool { guard let size = media.size else { return false } - if size < 1 * 1024 * 1024 { + if size < 256 * 1024 { return false } for attribute in media.attributes { diff --git a/TelegramUI/ItemListController.swift b/TelegramUI/ItemListController.swift index f22f2b3ecb..36fdaae8eb 100644 --- a/TelegramUI/ItemListController.swift +++ b/TelegramUI/ItemListController.swift @@ -480,7 +480,7 @@ class ItemListController: ViewController { if let presentationArguments = self.presentationArguments as? ViewControllerPresentationArguments, !self.didPlayPresentationAnimation { self.didPlayPresentationAnimation = true if case .modalSheet = presentationArguments.presentationAnimation { - (self.displayNode as! ItemListControllerNode).animateIn() + (self.displayNode as! ItemListControllerNode).animateIn(completion: presentationArguments.completion) } } diff --git a/TelegramUI/ItemListControllerNode.swift b/TelegramUI/ItemListControllerNode.swift index 8f87a25765..98b06bfa61 100644 --- a/TelegramUI/ItemListControllerNode.swift +++ b/TelegramUI/ItemListControllerNode.swift @@ -304,8 +304,10 @@ class ItemListControllerNode: ASDisplayNode, UIScrollV } } - func animateIn() { - self.layer.animatePosition(from: CGPoint(x: self.layer.position.x, y: self.layer.position.y + self.layer.bounds.size.height), to: self.layer.position, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring) + func animateIn(completion: (() -> Void)? = nil) { + self.layer.animatePosition(from: CGPoint(x: self.layer.position.x, y: self.layer.position.y + self.layer.bounds.size.height), to: self.layer.position, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring, completion: { _ in + completion?() + }) } func animateOut(completion: (() -> Void)? = nil) { diff --git a/TelegramUI/MediaNavigationAccessoryContainerNode.swift b/TelegramUI/MediaNavigationAccessoryContainerNode.swift index 49d4656cea..006c9556b8 100644 --- a/TelegramUI/MediaNavigationAccessoryContainerNode.swift +++ b/TelegramUI/MediaNavigationAccessoryContainerNode.swift @@ -23,12 +23,6 @@ final class MediaNavigationAccessoryContainerNode: ASDisplayNode, UIGestureRecog self.addSubnode(self.backgroundNode) self.addSubnode(self.headerNode) - - self.headerNode.tapAction = { [weak self] in - if let strongSelf = self { - - } - } } func updatePresentationData(_ presentationData: PresentationData) { diff --git a/TelegramUI/MediaNavigationAccessoryHeaderNode.swift b/TelegramUI/MediaNavigationAccessoryHeaderNode.swift index 3dfb4e73eb..82a70a74e5 100644 --- a/TelegramUI/MediaNavigationAccessoryHeaderNode.swift +++ b/TelegramUI/MediaNavigationAccessoryHeaderNode.swift @@ -207,6 +207,18 @@ final class MediaNavigationAccessoryHeaderNode: ASDisplayNode { self.actionPauseNode.image = PresentationResourcesRootController.navigationPlayerPauseIcon(self.theme) self.separatorNode.backgroundColor = self.theme.rootController.navigationBar.separatorColor self.scrubbingNode.updateContent(.standard(lineHeight: 2.0, lineCap: .square, scrubberHandle: .none, backgroundColor: .clear, foregroundColor: self.theme.rootController.navigationBar.accentTextColor)) + + if let voiceBaseRate = self.voiceBaseRate { + switch voiceBaseRate { + case .x1: + self.rateButton.setImage(PresentationResourcesRootController.navigationPlayerRateInactiveIcon(self.theme), for: []) + case .x2: + self.rateButton.setImage(PresentationResourcesRootController.navigationPlayerRateActiveIcon(self.theme), for: []) + } + } + if let (size, leftInset, rightInset) = self.validLayout { + self.updateLayout(size: size, leftInset: leftInset, rightInset: rightInset, transition: .immediate) + } } func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) { diff --git a/TelegramUI/MediaPlayer.swift b/TelegramUI/MediaPlayer.swift index 558b40feee..52a1b23467 100644 --- a/TelegramUI/MediaPlayer.swift +++ b/TelegramUI/MediaPlayer.swift @@ -60,6 +60,29 @@ enum MediaPlayerPlayOnceWithSoundSeek { case automatic } +enum MediaPlayerStreaming { + case none + case conservative + case earlierStart + + var enabled: Bool { + if case .none = self { + return false + } else { + return true + } + } + + var parameters: (Double, Double, Double) { + switch self { + case .none, .conservative: + return (1.0, 2.0, 3.0) + case .earlierStart: + return (0.5, 0.5, 1.0) + } + } +} + private final class MediaPlayerAudioRendererContext { let renderer: MediaPlayerAudioRenderer var requestedFrames = false @@ -76,7 +99,7 @@ private final class MediaPlayerContext { private let postbox: Postbox private let resourceReference: MediaResourceReference private let tempFilePath: String? - private let streamable: Bool + private let streamable: MediaPlayerStreaming private let video: Bool private let preferSoftwareDecoding: Bool private var enableSound: Bool @@ -102,7 +125,7 @@ private final class MediaPlayerContext { private var stoppedAtEnd = false - init(queue: Queue, audioSessionManager: ManagedAudioSession, playerStatus: Promise, postbox: Postbox, resourceReference: MediaResourceReference, tempFilePath: String?, streamable: Bool, video: Bool, preferSoftwareDecoding: Bool, playAutomatically: Bool, enableSound: Bool, baseRate: Double, fetchAutomatically: Bool, playAndRecord: Bool, keepAudioSessionWhilePaused: Bool, continuePlayingWithoutSoundOnLostAudioSession: Bool) { + init(queue: Queue, audioSessionManager: ManagedAudioSession, playerStatus: Promise, postbox: Postbox, resourceReference: MediaResourceReference, tempFilePath: String?, streamable: MediaPlayerStreaming, video: Bool, preferSoftwareDecoding: Bool, playAutomatically: Bool, enableSound: Bool, baseRate: Double, fetchAutomatically: Bool, playAndRecord: Bool, keepAudioSessionWhilePaused: Bool, continuePlayingWithoutSoundOnLostAudioSession: Bool) { assert(queue.isCurrent()) self.queue = queue @@ -135,12 +158,6 @@ private final class MediaPlayerContext { case .paused: if value { strongSelf.play() -// if strongSelf.enableSound { -// strongSelf.play() -// //strongSelf.continuePlayingWithoutSound() -// } else { -// strongSelf.play() -// } } case .playing: if !value { @@ -151,11 +168,6 @@ private final class MediaPlayerContext { case .pause: if value { strongSelf.play() -// if strongSelf.enableSound { -// strongSelf.continuePlayingWithoutSound() -// } else { -// strongSelf.play() -// } } case .play: if !value { @@ -280,7 +292,7 @@ private final class MediaPlayerContext { self.playerStatus.set(.single(status)) } - let frameSource = FFMpegMediaFrameSource(queue: self.queue, postbox: self.postbox, resourceReference: self.resourceReference, tempFilePath: self.tempFilePath, streamable: self.streamable, video: self.video, preferSoftwareDecoding: self.preferSoftwareDecoding, fetchAutomatically: self.fetchAutomatically) + let frameSource = FFMpegMediaFrameSource(queue: self.queue, postbox: self.postbox, resourceReference: self.resourceReference, tempFilePath: self.tempFilePath, streamable: self.streamable.enabled, video: self.video, preferSoftwareDecoding: self.preferSoftwareDecoding, fetchAutomatically: self.fetchAutomatically, stallDuration: self.streamable.parameters.0, lowWaterDuration: self.streamable.parameters.1, highWaterDuration: self.streamable.parameters.2) let disposable = MetaDisposable() let updatedSeekState: MediaPlayerSeekState? if let loadedDuration = loadedDuration { @@ -930,7 +942,7 @@ final class MediaPlayer { } } - init(audioSessionManager: ManagedAudioSession, postbox: Postbox, resourceReference: MediaResourceReference, tempFilePath: String? = nil, streamable: Bool, video: Bool, preferSoftwareDecoding: Bool, playAutomatically: Bool = false, enableSound: Bool, baseRate: Double = 1.0, fetchAutomatically: Bool, playAndRecord: Bool = false, keepAudioSessionWhilePaused: Bool = true, continuePlayingWithoutSoundOnLostAudioSession: Bool = false) { + init(audioSessionManager: ManagedAudioSession, postbox: Postbox, resourceReference: MediaResourceReference, tempFilePath: String? = nil, streamable: MediaPlayerStreaming, video: Bool, preferSoftwareDecoding: Bool, playAutomatically: Bool = false, enableSound: Bool, baseRate: Double = 1.0, fetchAutomatically: Bool, playAndRecord: Bool = false, keepAudioSessionWhilePaused: Bool = true, continuePlayingWithoutSoundOnLostAudioSession: Bool = false) { self.queue.async { let context = MediaPlayerContext(queue: self.queue, audioSessionManager: audioSessionManager, playerStatus: self.statusValue, postbox: postbox, resourceReference: resourceReference, tempFilePath: tempFilePath, streamable: streamable, video: video, preferSoftwareDecoding: preferSoftwareDecoding, playAutomatically: playAutomatically, enableSound: enableSound, baseRate: baseRate, fetchAutomatically: fetchAutomatically, playAndRecord: playAndRecord, keepAudioSessionWhilePaused: keepAudioSessionWhilePaused, continuePlayingWithoutSoundOnLostAudioSession: continuePlayingWithoutSoundOnLostAudioSession) self.contextRef = Unmanaged.passRetained(context) diff --git a/TelegramUI/MediaTrackFrameBuffer.swift b/TelegramUI/MediaTrackFrameBuffer.swift index a850f09739..63419f843a 100644 --- a/TelegramUI/MediaTrackFrameBuffer.swift +++ b/TelegramUI/MediaTrackFrameBuffer.swift @@ -19,9 +19,9 @@ enum MediaTrackFrameResult { private let traceEvents = false final class MediaTrackFrameBuffer { - private let stallDuration: Double = 1.0 - private let lowWaterDuration: Double = 2.0 - private let highWaterDuration: Double = 3.0 + private let stallDuration: Double + private let lowWaterDuration: Double + private let highWaterDuration: Double private let frameSource: MediaFrameSource private let decoder: MediaTrackFrameDecoder @@ -38,13 +38,16 @@ final class MediaTrackFrameBuffer { private var endOfStream = false private var bufferedUntilTime: CMTime? - init(frameSource: MediaFrameSource, decoder: MediaTrackFrameDecoder, type: MediaTrackFrameType, duration: CMTime, rotationAngle: Double, aspect: Double) { + init(frameSource: MediaFrameSource, decoder: MediaTrackFrameDecoder, type: MediaTrackFrameType, duration: CMTime, rotationAngle: Double, aspect: Double, stallDuration: Double = 1.0, lowWaterDuration: Double = 2.0, highWaterDuration: Double = 3.0) { self.frameSource = frameSource self.type = type self.decoder = decoder self.duration = duration self.rotationAngle = rotationAngle self.aspect = aspect + self.stallDuration = stallDuration + self.lowWaterDuration = lowWaterDuration + self.highWaterDuration = highWaterDuration self.frameSourceSinkIndex = self.frameSource.addEventSink { [weak self] event in if let strongSelf = self { diff --git a/TelegramUI/NativeVideoContent.swift b/TelegramUI/NativeVideoContent.swift index 993c75cd1e..52809eb558 100644 --- a/TelegramUI/NativeVideoContent.swift +++ b/TelegramUI/NativeVideoContent.swift @@ -52,7 +52,7 @@ final class NativeVideoContent: UniversalVideoContent { let imageReference: ImageMediaReference? let dimensions: CGSize let duration: Int32 - let streamVideo: Bool + let streamVideo: MediaPlayerStreaming let loopVideo: Bool let enableSound: Bool let baseRate: Double @@ -62,7 +62,7 @@ final class NativeVideoContent: UniversalVideoContent { let placeholderColor: UIColor let tempFilePath: String? - init(id: NativeVideoContentId, fileReference: FileMediaReference, imageReference: ImageMediaReference? = nil, streamVideo: Bool = false, loopVideo: Bool = false, enableSound: Bool = true, baseRate: Double = 1.0, fetchAutomatically: Bool = true, onlyFullSizeThumbnail: Bool = false, continuePlayingWithoutSoundOnLostAudioSession: Bool = false, placeholderColor: UIColor = .white, tempFilePath: String? = nil) { + init(id: NativeVideoContentId, fileReference: FileMediaReference, imageReference: ImageMediaReference? = nil, streamVideo: MediaPlayerStreaming = .none, loopVideo: Bool = false, enableSound: Bool = true, baseRate: Double = 1.0, fetchAutomatically: Bool = true, onlyFullSizeThumbnail: Bool = false, continuePlayingWithoutSoundOnLostAudioSession: Bool = false, placeholderColor: UIColor = .white, tempFilePath: String? = nil) { self.id = id self.nativeId = id self.fileReference = fileReference @@ -143,7 +143,7 @@ private final class NativeVideoContentNode: ASDisplayNode, UniversalVideoContent private var validLayout: CGSize? - init(postbox: Postbox, audioSessionManager: ManagedAudioSession, fileReference: FileMediaReference, imageReference: ImageMediaReference?, streamVideo: Bool, loopVideo: Bool, enableSound: Bool, baseRate: Double, fetchAutomatically: Bool, onlyFullSizeThumbnail: Bool, continuePlayingWithoutSoundOnLostAudioSession: Bool = false, placeholderColor: UIColor, tempFilePath: String?) { + init(postbox: Postbox, audioSessionManager: ManagedAudioSession, fileReference: FileMediaReference, imageReference: ImageMediaReference?, streamVideo: MediaPlayerStreaming, loopVideo: Bool, enableSound: Bool, baseRate: Double, fetchAutomatically: Bool, onlyFullSizeThumbnail: Bool, continuePlayingWithoutSoundOnLostAudioSession: Bool = false, placeholderColor: UIColor, tempFilePath: String?) { self.postbox = postbox self.fileReference = fileReference self.placeholderColor = placeholderColor diff --git a/TelegramUI/OpenAddContact.swift b/TelegramUI/OpenAddContact.swift index 9545791ddd..30d9deb8cf 100644 --- a/TelegramUI/OpenAddContact.swift +++ b/TelegramUI/OpenAddContact.swift @@ -3,14 +3,22 @@ import SwiftSignalKit import TelegramCore import Display -func openAddContact(context: AccountContext, firstName: String = "", lastName: String = "", phoneNumber: String, label: String = "_$!!$_", present: @escaping (ViewController, Any?) -> Void, completed: @escaping () -> Void = {}) { +func openAddContact(context: AccountContext, firstName: String = "", lastName: String = "", phoneNumber: String, label: String = "_$!!$_", present: @escaping (ViewController, Any?) -> Void, pushController: @escaping (ViewController) -> Void, completed: @escaping () -> Void = {}) { let _ = (DeviceAccess.authorizationStatus(context: context, subject: .contacts) |> take(1) |> deliverOnMainQueue).start(next: { value in switch value { case .allowed: let contactData = DeviceContactExtendedData(basicData: DeviceContactBasicData(firstName: firstName, lastName: lastName, phoneNumbers: [DeviceContactPhoneNumberData(label: label, value: phoneNumber)]), middleName: "", prefix: "", suffix: "", organization: "", jobTitle: "", department: "", emailAddresses: [], urls: [], addresses: [], birthdayDate: nil, socialProfiles: [], instantMessagingProfiles: []) - present(deviceContactInfoController(context: context, subject: .create(peer: nil, contactData: contactData, completion: { _, _,_ in }), completed: completed), ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) + present(deviceContactInfoController(context: context, subject: .create(peer: nil, contactData: contactData, completion: { peer, stableId, contactData in + if let peer = peer { + if let infoController = peerInfoController(context: context, peer: peer) { + pushController(infoController) + } + } else { + pushController(deviceContactInfoController(context: context, subject: .vcard(nil, stableId, contactData))) + } + }), completed: completed), ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) case .notDetermined: DeviceAccess.authorizeAccess(to: .contacts) default: diff --git a/TelegramUI/OpenChatMessage.swift b/TelegramUI/OpenChatMessage.swift index c07fed7181..b1f938015c 100644 --- a/TelegramUI/OpenChatMessage.swift +++ b/TelegramUI/OpenChatMessage.swift @@ -93,7 +93,7 @@ private func chatMessageGalleryControllerData(context: AccountContext, message: } } - let gallery = InstantPageGalleryController(context: context, webPage: webPage, message: message, entries: instantPageMedia, centralIndex: centralIndex, fromPlayingVideo: fromPlayingVideo, replaceRootController: { [weak navigationController] controller, ready in + let gallery = InstantPageGalleryController(context: context, webPage: webPage, message: message, entries: instantPageMedia, centralIndex: centralIndex, fromPlayingVideo: fromPlayingVideo, landscape: landscape, replaceRootController: { [weak navigationController] controller, ready in if let navigationController = navigationController { navigationController.replaceTopController(controller, animated: false, ready: ready) } diff --git a/TelegramUI/OpenSettings.swift b/TelegramUI/OpenSettings.swift new file mode 100644 index 0000000000..9c1b10095a --- /dev/null +++ b/TelegramUI/OpenSettings.swift @@ -0,0 +1,54 @@ +import Foundation +import Display +import SwiftSignalKit +import Postbox +import TelegramCore + +private let maximumNumberOfAccounts = 3 + +func openEditSettings(context: AccountContext, accountsAndPeers: Signal<((Account, Peer)?, [(Account, Peer, Int32)]), NoError>, focusOnItemTag: EditSettingsEntryTag? = nil, presentController: @escaping (ViewController, Any?) -> Void, pushController: @escaping (ViewController) -> Void) -> Disposable { + let openEditingDisposable = MetaDisposable() + var cancelImpl: (() -> Void)? + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + let progressSignal = Signal { subscriber in + let controller = OverlayStatusController(theme: presentationData.theme, strings: presentationData.strings, type: .loading(cancelled: { + cancelImpl?() + })) + presentController(controller, nil) + return ActionDisposable { [weak controller] in + Queue.mainQueue().async() { + controller?.dismiss() + } + } + } + |> runOn(Queue.mainQueue()) + |> delay(0.15, queue: Queue.mainQueue()) + let progressDisposable = progressSignal.start() + + let peerKey: PostboxViewKey = .peer(peerId: context.account.peerId, components: []) + let cachedDataKey: PostboxViewKey = .cachedPeerData(peerId: context.account.peerId) + let signal = (combineLatest(accountsAndPeers |> take(1), context.account.postbox.combinedView(keys: [peerKey, cachedDataKey])) + |> mapToSignal { accountsAndPeers, view -> Signal<(TelegramUser, CachedUserData, Bool), NoError> in + guard let cachedDataView = view.views[cachedDataKey] as? CachedPeerDataView, let cachedData = cachedDataView.cachedPeerData as? CachedUserData else { + return .complete() + } + guard let peerView = view.views[peerKey] as? PeerView, let peer = peerView.peers[context.account.peerId] as? TelegramUser else { + return .complete() + } + return .single((peer, cachedData, accountsAndPeers.1.count + 1 < maximumNumberOfAccounts)) + } + |> take(1)) + |> afterDisposed { + Queue.mainQueue().async { + progressDisposable.dispose() + } + } + cancelImpl = { + openEditingDisposable.set(nil) + } + openEditingDisposable.set((signal + |> deliverOnMainQueue).start(next: { peer, cachedData, canAddAccounts in + pushController(editSettingsController(context: context, currentName: .personName(firstName: peer.firstName ?? "", lastName: peer.lastName ?? ""), currentBioText: cachedData.about ?? "", accountManager: context.sharedContext.accountManager, canAddAccounts: canAddAccounts, focusOnItemTag: focusOnItemTag)) + })) + return openEditingDisposable +} diff --git a/TelegramUI/OverlayUniversalVideoNode.swift b/TelegramUI/OverlayUniversalVideoNode.swift index bd6cecd461..296e0cd170 100644 --- a/TelegramUI/OverlayUniversalVideoNode.swift +++ b/TelegramUI/OverlayUniversalVideoNode.swift @@ -53,6 +53,9 @@ final class OverlayUniversalVideoNode: OverlayMediaItemNode { } closeImpl = { [weak self] in if let strongSelf = self { + if strongSelf.videoNode.hasAttachedContext { + strongSelf.videoNode.continuePlayingWithoutSound() + } strongSelf.layer.animateScale(from: 1.0, to: 0.1, duration: 0.25, removeOnCompletion: false, completion: { _ in self?.dismiss() close() diff --git a/TelegramUI/PaneSearchContainerNode.swift b/TelegramUI/PaneSearchContainerNode.swift index 980b9be403..1e6577b8f3 100644 --- a/TelegramUI/PaneSearchContainerNode.swift +++ b/TelegramUI/PaneSearchContainerNode.swift @@ -56,6 +56,8 @@ final class PaneSearchContainerNode: ASDisplayNode { super.init() + self.clipsToBounds = true + self.addSubnode(self.backgroundNode) self.addSubnode(self.contentNode) self.addSubnode(self.searchBar) @@ -133,7 +135,7 @@ final class PaneSearchContainerNode: ASDisplayNode { } } - func animateOut(to placeholder: PaneSearchBarPlaceholderNode, transition: ContainedViewLayoutTransition, completion: @escaping () -> Void) { + func animateOut(to placeholder: PaneSearchBarPlaceholderNode, animateOutSearchBar: Bool, transition: ContainedViewLayoutTransition, completion: @escaping () -> Void) { if case let .animated(duration, curve) = transition { if let size = self.validLayout { let placeholderFrame = placeholder.view.convert(placeholder.bounds, to: self.view) @@ -144,8 +146,10 @@ final class PaneSearchContainerNode: ASDisplayNode { self.searchBar.transitionOut(to: placeholder, transition: transition, completion: { completion() }) - transition.updateAlpha(node: self.backgroundNode, alpha: 0.0, completion: { _ in - }) + transition.updateAlpha(node: self.backgroundNode, alpha: 0.0) + if animateOutSearchBar { + transition.updateAlpha(node: self.searchBar, alpha: 0.0) + } self.contentNode.animateOut(transition: transition) self.deactivate() } diff --git a/TelegramUI/PresentationStrings.swift b/TelegramUI/PresentationStrings.swift index 061116e687..2e313e9ad3 100644 --- a/TelegramUI/PresentationStrings.swift +++ b/TelegramUI/PresentationStrings.swift @@ -874,50 +874,50 @@ public final class PresentationStrings { public func DialogList_SingleUploadingFileSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[647]!, self._r[647]!, [_0]) } - public var Privacy_Forwards_PreviewForwardAuthor: String { return self._s[648]! } - public var AutoNightTheme_ScheduledFrom: String { return self._s[649]! } - public var PhotoEditor_WarmthTool: String { return self._s[650]! } - public var Passport_Language_tr: String { return self._s[651]! } - public var Login_ResetAccountProtected_Reset: String { return self._s[653]! } - public var Watch_PhotoView_Title: String { return self._s[654]! } - public var Passport_Phone_Delete: String { return self._s[655]! } - public var Conversation_EditingMessageMediaEditCurrentPhoto: String { return self._s[656]! } - public var GroupInfo_Permissions: String { return self._s[657]! } - public var PasscodeSettings_TurnPasscodeOff: String { return self._s[658]! } - public var Profile_ShareContactButton: String { return self._s[659]! } - public var ChatSettings_Other: String { return self._s[660]! } - public var UserInfo_NotificationsDisabled: String { return self._s[661]! } - public var CheckoutInfo_ShippingInfoCity: String { return self._s[662]! } + public var AutoNightTheme_ScheduledFrom: String { return self._s[648]! } + public var PhotoEditor_WarmthTool: String { return self._s[649]! } + public var Passport_Language_tr: String { return self._s[650]! } + public var Login_ResetAccountProtected_Reset: String { return self._s[652]! } + public var Watch_PhotoView_Title: String { return self._s[653]! } + public var Passport_Phone_Delete: String { return self._s[654]! } + public var Conversation_EditingMessageMediaEditCurrentPhoto: String { return self._s[655]! } + public var GroupInfo_Permissions: String { return self._s[656]! } + public var PasscodeSettings_TurnPasscodeOff: String { return self._s[657]! } + public var Profile_ShareContactButton: String { return self._s[658]! } + public var ChatSettings_Other: String { return self._s[659]! } + public var UserInfo_NotificationsDisabled: String { return self._s[660]! } + public var CheckoutInfo_ShippingInfoCity: String { return self._s[661]! } public func PUSH_CHAT_MESSAGE_PHOTOS(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[663]!, self._r[663]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[662]!, self._r[662]!, [_1, _2, _3]) } - public var LastSeen_WithinAMonth: String { return self._s[664]! } - public var Conversation_EncryptionCanceled: String { return self._s[665]! } - public var MediaPicker_GroupDescription: String { return self._s[666]! } - public var WebSearch_Images: String { return self._s[667]! } + public var LastSeen_WithinAMonth: String { return self._s[663]! } + public var Conversation_EncryptionCanceled: String { return self._s[664]! } + public var MediaPicker_GroupDescription: String { return self._s[665]! } + public var WebSearch_Images: String { return self._s[666]! } public func Channel_Management_PromotedBy(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[668]!, self._r[668]!, [_0]) + return formatWithArgumentRanges(self._s[667]!, self._r[667]!, [_0]) } - public var Message_Photo: String { return self._s[669]! } - public var PasscodeSettings_HelpBottom: String { return self._s[670]! } - public var AutoDownloadSettings_VideosTitle: String { return self._s[671]! } - public var Passport_Identity_AddDriversLicense: String { return self._s[672]! } - public var TwoStepAuth_EnterPasswordPassword: String { return self._s[673]! } - public var NotificationsSound_Calypso: String { return self._s[674]! } - public var Map_Map: String { return self._s[675]! } - public var CheckoutInfo_ReceiverInfoTitle: String { return self._s[677]! } - public var ChatSettings_TextSizeUnits: String { return self._s[678]! } - public var Common_of: String { return self._s[679]! } - public var Conversation_ForwardContacts: String { return self._s[681]! } + public var Message_Photo: String { return self._s[668]! } + public var PasscodeSettings_HelpBottom: String { return self._s[669]! } + public var AutoDownloadSettings_VideosTitle: String { return self._s[670]! } + public var Passport_Identity_AddDriversLicense: String { return self._s[671]! } + public var TwoStepAuth_EnterPasswordPassword: String { return self._s[672]! } + public var NotificationsSound_Calypso: String { return self._s[673]! } + public var Map_Map: String { return self._s[674]! } + public var CheckoutInfo_ReceiverInfoTitle: String { return self._s[676]! } + public var ChatSettings_TextSizeUnits: String { return self._s[677]! } + public var Common_of: String { return self._s[678]! } + public var Conversation_ForwardContacts: String { return self._s[680]! } public func Call_AnsweringWithAccount(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[683]!, self._r[683]!, [_0]) + return formatWithArgumentRanges(self._s[682]!, self._r[682]!, [_0]) } - public var Passport_Language_hy: String { return self._s[684]! } - public var Notifications_MessageNotificationsHelp: String { return self._s[685]! } - public var AutoDownloadSettings_Reset: String { return self._s[686]! } - public var Paint_ClearConfirm: String { return self._s[687]! } - public var Camera_VideoMode: String { return self._s[688]! } + public var Passport_Language_hy: String { return self._s[683]! } + public var Notifications_MessageNotificationsHelp: String { return self._s[684]! } + public var AutoDownloadSettings_Reset: String { return self._s[685]! } + public var Paint_ClearConfirm: String { return self._s[686]! } + public var Camera_VideoMode: String { return self._s[687]! } public func Conversation_RestrictedStickersTimed(_ _0: String) -> (String, [(Int, NSRange)]) { +<<<<<<< HEAD return formatWithArgumentRanges(self._s[689]!, self._r[689]!, [_0]) } public var Privacy_Calls_AlwaysAllow_Placeholder: String { return self._s[690]! } @@ -3748,6 +3748,2834 @@ public final class PresentationStrings { return String(format: self._ps[50 * 6 + Int(form.rawValue)]!, _1, _2) } public func MessagePoll_VotedCount(_ value: Int32) -> String { +======= + return formatWithArgumentRanges(self._s[688]!, self._r[688]!, [_0]) + } + public var Privacy_Calls_AlwaysAllow_Placeholder: String { return self._s[689]! } + public var Conversation_ViewBackground: String { return self._s[690]! } + public var Passport_Language_el: String { return self._s[691]! } + public var PhotoEditor_Original: String { return self._s[692]! } + public var Settings_FAQ_Button: String { return self._s[694]! } + public var Channel_Setup_PublicNoLink: String { return self._s[696]! } + public var Conversation_UnsupportedMedia: String { return self._s[697]! } + public var Conversation_SlideToCancel: String { return self._s[698]! } + public var Passport_Identity_OneOfTypeInternalPassport: String { return self._s[699]! } + public var CheckoutInfo_ShippingInfoPostcode: String { return self._s[700]! } + public var AutoNightTheme_NotAvailable: String { return self._s[701]! } + public var Common_Create: String { return self._s[702]! } + public var Settings_ApplyProxyAlertEnable: String { return self._s[703]! } + public var Localization_ChooseLanguage: String { return self._s[705]! } + public var Settings_Proxy: String { return self._s[708]! } + public var Privacy_TopPeersHelp: String { return self._s[709]! } + public var CheckoutInfo_ShippingInfoCountryPlaceholder: String { return self._s[710]! } + public var TwoStepAuth_ConfirmationAbort: String { return self._s[711]! } + public func Contacts_AccessDeniedHelpPortrait(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[713]!, self._r[713]!, [_0]) + } + public var Contacts_SortedByPresence: String { return self._s[714]! } + public var Passport_Identity_SurnamePlaceholder: String { return self._s[715]! } + public var Cache_Title: String { return self._s[716]! } + public func Login_PhoneBannedEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[717]!, self._r[717]!, [_0]) + } + public var TwoStepAuth_EmailCodeExpired: String { return self._s[718]! } + public var Channel_Moderator_Title: String { return self._s[719]! } + public var InstantPage_AutoNightTheme: String { return self._s[721]! } + public func PUSH_MESSAGE_POLL(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[724]!, self._r[724]!, [_1]) + } + public var Passport_Scans_Upload: String { return self._s[725]! } + public var Undo_Undo: String { return self._s[727]! } + public var Contacts_AccessDeniedHelpON: String { return self._s[728]! } + public var TwoStepAuth_RemovePassword: String { return self._s[729]! } + public var Common_Delete: String { return self._s[730]! } + public var Conversation_ContextMenuDelete: String { return self._s[732]! } + public var SocksProxySetup_Credentials: String { return self._s[733]! } + public var PasscodeSettings_AutoLock_Disabled: String { return self._s[735]! } + public var Passport_Address_OneOfTypeRentalAgreement: String { return self._s[738]! } + public var Conversation_ShareBotContactConfirmationTitle: String { return self._s[739]! } + public var Passport_Language_id: String { return self._s[741]! } + public var WallpaperSearch_ColorTeal: String { return self._s[742]! } + public var ChannelIntro_Title: String { return self._s[743]! } + public func Channel_AdminLog_MessageToggleSignaturesOff(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[744]!, self._r[744]!, [_0]) + } + public var Channel_Info_Description: String { return self._s[746]! } + public var Stickers_FavoriteStickers: String { return self._s[747]! } + public var Channel_BanUser_PermissionAddMembers: String { return self._s[748]! } + public var Notifications_DisplayNamesOnLockScreen: String { return self._s[749]! } + public var Calls_NoMissedCallsPlacehoder: String { return self._s[750]! } + public var Notifications_ExceptionsDefaultSound: String { return self._s[751]! } + public func PUSH_CHANNEL_MESSAGE_POLL(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[752]!, self._r[752]!, [_1]) + } + public func DialogList_SearchSubtitleFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[753]!, self._r[753]!, [_1, _2]) + } + public func Channel_AdminLog_MessageRemovedGroupStickerPack(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[754]!, self._r[754]!, [_0]) + } + public var GroupPermission_Delete: String { return self._s[755]! } + public var Passport_Language_uk: String { return self._s[756]! } + public var StickerPack_HideStickers: String { return self._s[758]! } + public var ChangePhoneNumberNumber_NumberPlaceholder: String { return self._s[759]! } + public func PUSH_CHAT_MESSAGE_PHOTO(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[760]!, self._r[760]!, [_1, _2]) + } + public var Activity_UploadingVideoMessage: String { return self._s[761]! } + public func GroupPermission_ApplyAlertText(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[762]!, self._r[762]!, [_0]) + } + public var Channel_TitleInfo: String { return self._s[763]! } + public var StickerPacksSettings_ArchivedPacks_Info: String { return self._s[764]! } + public var Settings_CallSettings: String { return self._s[765]! } + public var Camera_SquareMode: String { return self._s[766]! } + public var GroupInfo_SharedMediaNone: String { return self._s[767]! } + public func PUSH_MESSAGE_VIDEO_SECRET(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[768]!, self._r[768]!, [_1]) + } + public var Bot_GenericBotStatus: String { return self._s[769]! } + public var Application_Update: String { return self._s[771]! } + public var Month_ShortJanuary: String { return self._s[772]! } + public var Contacts_PermissionsKeepDisabled: String { return self._s[773]! } + public var Channel_AdminLog_BanReadMessages: String { return self._s[774]! } + public var Settings_AppLanguage_Unofficial: String { return self._s[775]! } + public var Passport_Address_Street2Placeholder: String { return self._s[776]! } + public func Map_LiveLocationShortHour(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[777]!, self._r[777]!, [_0]) + } + public var NetworkUsageSettings_Cellular: String { return self._s[778]! } + public var Appearance_PreviewOutgoingText: String { return self._s[779]! } + public var Notifications_PermissionsAllowInSettings: String { return self._s[780]! } + public var AutoDownloadSettings_OnForAll: String { return self._s[782]! } + public var Map_Directions: String { return self._s[783]! } + public var Passport_FieldIdentityTranslationHelp: String { return self._s[785]! } + public var Appearance_ThemeDay: String { return self._s[786]! } + public var LogoutOptions_LogOut: String { return self._s[787]! } + public var Passport_Identity_AddPassport: String { return self._s[789]! } + public var Call_Message: String { return self._s[790]! } + public var PhotoEditor_ExposureTool: String { return self._s[791]! } + public var Passport_FieldOneOf_Delimeter: String { return self._s[793]! } + public var Channel_AdminLog_CanBanUsers: String { return self._s[795]! } + public var Appearance_Preview: String { return self._s[796]! } + public var Compose_ChannelMembers: String { return self._s[797]! } + public var Conversation_DeleteManyMessages: String { return self._s[798]! } + public var ReportPeer_ReasonOther_Title: String { return self._s[799]! } + public var Checkout_ErrorProviderAccountTimeout: String { return self._s[800]! } + public var TwoStepAuth_ResetAccountConfirmation: String { return self._s[801]! } + public var Channel_Stickers_CreateYourOwn: String { return self._s[804]! } + public var Conversation_UpdateTelegram: String { return self._s[805]! } + public func Notification_PinnedPhotoMessage(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[806]!, self._r[806]!, [_0]) + } + public func PUSH_PINNED_GIF(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[807]!, self._r[807]!, [_1]) + } + public var GroupInfo_Administrators_Title: String { return self._s[808]! } + public var Privacy_Forwards_PreviewMessageText: String { return self._s[809]! } + public func PrivacySettings_LastSeenNobodyPlus(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[810]!, self._r[810]!, [_0]) + } + public var Tour_Title3: String { return self._s[811]! } + public var Channel_EditAdmin_PermissionInviteSubscribers: String { return self._s[812]! } + public var Clipboard_SendPhoto: String { return self._s[816]! } + public var MediaPicker_Videos: String { return self._s[817]! } + public var Passport_Email_Title: String { return self._s[818]! } + public func PrivacySettings_LastSeenEverybodyMinus(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[819]!, self._r[819]!, [_0]) + } + public var StickerPacksSettings_Title: String { return self._s[820]! } + public var Conversation_MessageDialogDelete: String { return self._s[821]! } + public var Privacy_Calls_CustomHelp: String { return self._s[823]! } + public var Message_Wallpaper: String { return self._s[824]! } + public var GroupInfo_SetSound: String { return self._s[825]! } + public var Core_ServiceUserStatus: String { return self._s[826]! } + public var LiveLocationUpdated_JustNow: String { return self._s[827]! } + public var Call_StatusFailed: String { return self._s[828]! } + public var TwoStepAuth_SetupPasswordDescription: String { return self._s[829]! } + public var TwoStepAuth_SetPassword: String { return self._s[830]! } + public func SocksProxySetup_ProxyStatusPing(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[832]!, self._r[832]!, [_0]) + } + public var Calls_SubmitRating: String { return self._s[833]! } + public var Profile_Username: String { return self._s[834]! } + public var Bot_DescriptionTitle: String { return self._s[835]! } + public var MaskStickerSettings_Title: String { return self._s[836]! } + public var SharedMedia_CategoryOther: String { return self._s[837]! } + public var GroupInfo_SetGroupPhoto: String { return self._s[838]! } + public var Common_NotNow: String { return self._s[839]! } + public var CallFeedback_IncludeLogsInfo: String { return self._s[840]! } + public var Map_Location: String { return self._s[841]! } + public var Invitation_JoinGroup: String { return self._s[842]! } + public var AutoDownloadSettings_Title: String { return self._s[844]! } + public var Conversation_DiscardVoiceMessageDescription: String { return self._s[845]! } + public var Channel_ErrorAddBlocked: String { return self._s[846]! } + public var Conversation_UnblockUser: String { return self._s[847]! } + public var Watch_Bot_Restart: String { return self._s[848]! } + public var TwoStepAuth_Title: String { return self._s[849]! } + public var Channel_AdminLog_BanSendMessages: String { return self._s[850]! } + public var Checkout_ShippingMethod: String { return self._s[851]! } + public var Passport_Identity_OneOfTypeIdentityCard: String { return self._s[852]! } + public func PUSH_CHAT_MESSAGE_STICKER(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[853]!, self._r[853]!, [_1, _2, _3]) + } + public func Channel_Username_LinkHint(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[855]!, self._r[855]!, [_0]) + } + public var AuthSessions_TerminateOtherSessions: String { return self._s[856]! } + public var Contacts_FailedToSendInvitesMessage: String { return self._s[857]! } + public var PrivacySettings_TwoStepAuth: String { return self._s[858]! } + public var Conversation_EditingMessagePanelMedia: String { return self._s[859]! } + public var Checkout_PaymentMethod_Title: String { return self._s[860]! } + public var SocksProxySetup_Connection: String { return self._s[861]! } + public var Group_MessagePhotoRemoved: String { return self._s[862]! } + public var Channel_Stickers_NotFound: String { return self._s[864]! } + public var Group_About_Help: String { return self._s[865]! } + public var Notification_PassportValueProofOfIdentity: String { return self._s[866]! } + public func ApplyLanguage_ChangeLanguageOfficialText(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[868]!, self._r[868]!, [_1]) + } + public var CheckoutInfo_ShippingInfoStatePlaceholder: String { return self._s[870]! } + public var Notifications_GroupNotificationsExceptionsHelp: String { return self._s[871]! } + public var SocksProxySetup_Password: String { return self._s[872]! } + public var Notifications_PermissionsEnable: String { return self._s[873]! } + public var TwoStepAuth_ChangeEmail: String { return self._s[875]! } + public func Channel_AdminLog_MessageInvitedName(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[876]!, self._r[876]!, [_1]) + } + public func Time_MonthOfYear_m10(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[878]!, self._r[878]!, [_0]) + } + public var Passport_Identity_TypeDriversLicense: String { return self._s[879]! } + public var ArchivedPacksAlert_Title: String { return self._s[880]! } + public func Time_PreciseDate_m7(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[881]!, self._r[881]!, [_1, _2, _3]) + } + public var PrivacyLastSeenSettings_GroupsAndChannelsHelp: String { return self._s[882]! } + public var Privacy_Calls_NeverAllow_Placeholder: String { return self._s[884]! } + public var Conversation_StatusTyping: String { return self._s[885]! } + public var Broadcast_AdminLog_EmptyText: String { return self._s[886]! } + public var Notification_PassportValueProofOfAddress: String { return self._s[887]! } + public var UserInfo_CreateNewContact: String { return self._s[888]! } + public var Passport_Identity_FrontSide: String { return self._s[889]! } + public var Login_PhoneNumberAlreadyAuthorizedSwitch: String { return self._s[890]! } + public var Calls_CallTabTitle: String { return self._s[891]! } + public var Channel_AdminLog_ChannelEmptyText: String { return self._s[892]! } + public func Login_BannedPhoneBody(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[893]!, self._r[893]!, [_0]) + } + public var Watch_UserInfo_MuteTitle: String { return self._s[894]! } + public var SharedMedia_EmptyMusicText: String { return self._s[895]! } + public var PasscodeSettings_AutoLock_IfAwayFor_1minute: String { return self._s[896]! } + public var Paint_Stickers: String { return self._s[897]! } + public var Privacy_GroupsAndChannels: String { return self._s[898]! } + public var UserInfo_AddContact: String { return self._s[900]! } + public func Conversation_MessageViaUser(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[901]!, self._r[901]!, [_0]) + } + public var PhoneNumberHelp_ChangeNumber: String { return self._s[903]! } + public var DialogList_NoMessagesTitle: String { return self._s[905]! } + public var EditProfile_NameAndPhotoHelp: String { return self._s[906]! } + public var BlockedUsers_BlockUser: String { return self._s[907]! } + public var Notifications_PermissionsOpenSettings: String { return self._s[908]! } + public var MediaPicker_UngroupDescription: String { return self._s[909]! } + public var Watch_NoConnection: String { return self._s[910]! } + public var Month_GenSeptember: String { return self._s[911]! } + public var Conversation_ViewGroup: String { return self._s[912]! } + public var Channel_AdminLogFilter_EventsLeavingSubscribers: String { return self._s[915]! } + public var Privacy_Forwards_AlwaysLink: String { return self._s[916]! } + public var Passport_FieldOneOf_FinalDelimeter: String { return self._s[917]! } + public var MediaPicker_CameraRoll: String { return self._s[919]! } + public var Month_GenAugust: String { return self._s[920]! } + public var AccessDenied_VideoMessageMicrophone: String { return self._s[921]! } + public var SharedMedia_EmptyText: String { return self._s[922]! } + public var Map_ShareLiveLocation: String { return self._s[923]! } + public var Calls_All: String { return self._s[924]! } + public var Appearance_ThemeNight: String { return self._s[927]! } + public var Conversation_HoldForAudio: String { return self._s[928]! } + public var GroupInfo_GroupHistoryHidden: String { return self._s[931]! } + public var SocksProxySetup_Secret: String { return self._s[932]! } + public var Channel_BanList_RestrictedTitle: String { return self._s[934]! } + public var Conversation_Location: String { return self._s[935]! } + public func AutoDownloadSettings_UpToFor(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[936]!, self._r[936]!, [_0, _1]) + } + public var ChatSettings_AutoDownloadPhotos: String { return self._s[938]! } + public var Notifications_PermissionsText: String { return self._s[939]! } + public var SocksProxySetup_ProxyStatusConnecting: String { return self._s[940]! } + public var Channel_EditAdmin_PermissionPinMessages: String { return self._s[942]! } + public var TwoStepAuth_ReEnterPasswordDescription: String { return self._s[944]! } + public var Passport_DeletePassportConfirmation: String { return self._s[946]! } + public var Login_InvalidCodeError: String { return self._s[947]! } + public var StickerPacksSettings_FeaturedPacks: String { return self._s[948]! } + public func ChatList_DeleteSecretChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[949]!, self._r[949]!, [_0]) + } + public func GroupInfo_InvitationLinkAcceptChannel(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[950]!, self._r[950]!, [_0]) + } + public var Call_CallInProgressTitle: String { return self._s[951]! } + public var Month_ShortSeptember: String { return self._s[952]! } + public var Watch_ChannelInfo_Title: String { return self._s[953]! } + public var ChatList_DeleteSavedMessagesConfirmation: String { return self._s[956]! } + public var DialogList_PasscodeLockHelp: String { return self._s[957]! } + public var Notifications_Badge_IncludePublicGroups: String { return self._s[958]! } + public var Channel_AdminLogFilter_EventsTitle: String { return self._s[959]! } + public var PhotoEditor_CropReset: String { return self._s[960]! } + public var Group_Username_CreatePrivateLinkHelp: String { return self._s[962]! } + public var Channel_Management_LabelEditor: String { return self._s[963]! } + public var Passport_Identity_LatinNameHelp: String { return self._s[965]! } + public var PhotoEditor_HighlightsTool: String { return self._s[966]! } + public var UserInfo_Title: String { return self._s[967]! } + public var AccessDenied_Title: String { return self._s[968]! } + public var DialogList_SearchLabel: String { return self._s[969]! } + public var Group_Setup_HistoryHidden: String { return self._s[970]! } + public var TwoStepAuth_PasswordChangeSuccess: String { return self._s[971]! } + public var State_Updating: String { return self._s[973]! } + public var Contacts_TabTitle: String { return self._s[974]! } + public var Notifications_Badge_CountUnreadMessages: String { return self._s[976]! } + public var GroupInfo_GroupHistory: String { return self._s[977]! } + public var Conversation_UnsupportedMediaPlaceholder: String { return self._s[978]! } + public var Wallpaper_SetColor: String { return self._s[979]! } + public var CheckoutInfo_ShippingInfoCountry: String { return self._s[980]! } + public var Passport_Identity_OneOfTypeDriversLicense: String { return self._s[981]! } + public var Contacts_NotRegisteredSection: String { return self._s[982]! } + public func Time_PreciseDate_m4(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[983]!, self._r[983]!, [_1, _2, _3]) + } + public var Paint_Clear: String { return self._s[984]! } + public var StickerPacksSettings_ArchivedMasks: String { return self._s[985]! } + public var SocksProxySetup_Connecting: String { return self._s[986]! } + public var ExplicitContent_AlertChannel: String { return self._s[987]! } + public var CreatePoll_AllOptionsAdded: String { return self._s[988]! } + public var Conversation_Contact: String { return self._s[989]! } + public var Login_CodeExpired: String { return self._s[990]! } + public var Passport_DiscardMessageAction: String { return self._s[991]! } + public var Channel_AdminLog_MessagePreviousDescription: String { return self._s[992]! } + public var Channel_AdminLog_EmptyMessageText: String { return self._s[993]! } + public var Month_ShortApril: String { return self._s[994]! } + public var AuthSessions_CurrentSession: String { return self._s[995]! } + public var WallpaperPreview_CropTopText: String { return self._s[999]! } + public var PrivacySettings_DeleteAccountIfAwayFor: String { return self._s[1000]! } + public var CheckoutInfo_ShippingInfoTitle: String { return self._s[1001]! } + public var Channel_Setup_TypePrivate: String { return self._s[1003]! } + public var Forward_ChannelReadOnly: String { return self._s[1006]! } + public var PhotoEditor_CurvesBlue: String { return self._s[1007]! } + public var UserInfo_BotPrivacy: String { return self._s[1008]! } + public var Notification_PassportValueEmail: String { return self._s[1009]! } + public var EmptyGroupInfo_Subtitle: String { return self._s[1010]! } + public var GroupPermission_NewTitle: String { return self._s[1011]! } + public var CallFeedback_ReasonDropped: String { return self._s[1012]! } + public var GroupInfo_Permissions_AddException: String { return self._s[1013]! } + public var Channel_SignMessages_Help: String { return self._s[1015]! } + public var Undo_ChatDeleted: String { return self._s[1017]! } + public var Conversation_ChatBackground: String { return self._s[1018]! } + public var ChannelMembers_WhoCanAddMembers_Admins: String { return self._s[1019]! } + public var FastTwoStepSetup_EmailPlaceholder: String { return self._s[1020]! } + public var Passport_Language_pt: String { return self._s[1021]! } + public var NotificationsSound_Popcorn: String { return self._s[1024]! } + public var AutoNightTheme_Disabled: String { return self._s[1025]! } + public var BlockedUsers_LeavePrefix: String { return self._s[1026]! } + public var WallpaperPreview_CustomColorTopText: String { return self._s[1027]! } + public var Contacts_PermissionsSuppressWarningText: String { return self._s[1028]! } + public var WallpaperSearch_ColorBlue: String { return self._s[1029]! } + public func CancelResetAccount_TextSMS(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1030]!, self._r[1030]!, [_0]) + } + public var CheckoutInfo_ErrorNameInvalid: String { return self._s[1031]! } + public var SocksProxySetup_UseForCalls: String { return self._s[1032]! } + public var Passport_DeleteDocumentConfirmation: String { return self._s[1034]! } + public func Conversation_Megabytes(_ _0: Float) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1035]!, self._r[1035]!, ["\(_0)"]) + } + public var SocksProxySetup_Hostname: String { return self._s[1038]! } + public var ChatSettings_AutoDownloadSettings_OffForAll: String { return self._s[1039]! } + public var Compose_NewEncryptedChat: String { return self._s[1040]! } + public var Login_CodeFloodError: String { return self._s[1041]! } + public var Calls_TabTitle: String { return self._s[1042]! } + public var Privacy_ProfilePhoto: String { return self._s[1043]! } + public var Passport_Language_he: String { return self._s[1044]! } + public var GroupPermission_Title: String { return self._s[1045]! } + public func Channel_AdminLog_MessageGroupPreHistoryHidden(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1046]!, self._r[1046]!, [_0]) + } + public var GroupPermission_NoChangeInfo: String { return self._s[1047]! } + public var Tour_Text1: String { return self._s[1048]! } + public var Month_ShortFebruary: String { return self._s[1049]! } + public var TwoStepAuth_EmailSkip: String { return self._s[1050]! } + public var NotificationsSound_Glass: String { return self._s[1051]! } + public var Appearance_ThemeNightBlue: String { return self._s[1052]! } + public var CheckoutInfo_Pay: String { return self._s[1053]! } + public var Invite_LargeRecipientsCountWarning: String { return self._s[1055]! } + public var Call_CallAgain: String { return self._s[1057]! } + public var AttachmentMenu_SendAsFile: String { return self._s[1058]! } + public var Watch_Message_Game: String { return self._s[1059]! } + public var AccessDenied_MicrophoneRestricted: String { return self._s[1060]! } + public var Passport_InvalidPasswordError: String { return self._s[1061]! } + public var Stickers_Install: String { return self._s[1062]! } + public var PrivacyLastSeenSettings_NeverShareWith: String { return self._s[1063]! } + public var Passport_Identity_ResidenceCountry: String { return self._s[1065]! } + public var Notifications_GroupNotificationsHelp: String { return self._s[1066]! } + public var AuthSessions_OtherSessions: String { return self._s[1067]! } + public var Channel_Username_Help: String { return self._s[1068]! } + public var Camera_Title: String { return self._s[1069]! } + public var GroupInfo_SetGroupPhotoDelete: String { return self._s[1071]! } + public var Privacy_ProfilePhoto_NeverShareWith_Title: String { return self._s[1072]! } + public var Channel_AdminLog_SendPolls: String { return self._s[1073]! } + public var Channel_AdminLog_TitleAllEvents: String { return self._s[1074]! } + public var Channel_EditAdmin_PermissionInviteMembers: String { return self._s[1075]! } + public var Contacts_MemberSearchSectionTitleGroup: String { return self._s[1076]! } + public var Conversation_RestrictedStickers: String { return self._s[1077]! } + public var Notifications_ExceptionsResetToDefaults: String { return self._s[1079]! } + public var UserInfo_TelegramCall: String { return self._s[1081]! } + public var TwoStepAuth_SetupResendEmailCode: String { return self._s[1082]! } + public var CreatePoll_OptionsHeader: String { return self._s[1083]! } + public var Privacy_GroupsAndChannels_AlwaysAllow_Title: String { return self._s[1084]! } + public var Passport_Identity_EditPersonalDetails: String { return self._s[1085]! } + public func Time_PreciseDate_m1(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1086]!, self._r[1086]!, [_1, _2, _3]) + } + public var Settings_SaveEditedPhotos: String { return self._s[1087]! } + public var TwoStepAuth_ConfirmationTitle: String { return self._s[1088]! } + public var Privacy_GroupsAndChannels_NeverAllow_Title: String { return self._s[1089]! } + public var Conversation_MessageDialogRetry: String { return self._s[1090]! } + public var Conversation_DiscardVoiceMessageAction: String { return self._s[1091]! } + public var Group_Setup_TypeHeader: String { return self._s[1092]! } + public var Paint_RecentStickers: String { return self._s[1093]! } + public var PhotoEditor_GrainTool: String { return self._s[1094]! } + public var CheckoutInfo_ShippingInfoState: String { return self._s[1095]! } + public var EmptyGroupInfo_Line4: String { return self._s[1096]! } + public var Watch_AuthRequired: String { return self._s[1098]! } + public func Passport_Email_UseTelegramEmail(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1099]!, self._r[1099]!, [_0]) + } + public var Conversation_EncryptedDescriptionTitle: String { return self._s[1100]! } + public var ChannelIntro_Text: String { return self._s[1101]! } + public var DialogList_DeleteBotConfirmation: String { return self._s[1102]! } + public var GroupPermission_NoSendMedia: String { return self._s[1103]! } + public var Calls_AddTab: String { return self._s[1104]! } + public var Message_ReplyActionButtonShowReceipt: String { return self._s[1105]! } + public var Channel_AdminLog_EmptyFilterText: String { return self._s[1106]! } + public var Notification_MessageLifetime1d: String { return self._s[1107]! } + public var Notifications_ChannelNotificationsExceptionsHelp: String { return self._s[1108]! } + public var Channel_BanUser_PermissionsHeader: String { return self._s[1109]! } + public var Passport_Identity_GenderFemale: String { return self._s[1110]! } + public var BlockedUsers_BlockTitle: String { return self._s[1111]! } + public func PUSH_CHANNEL_MESSAGE_GIF(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1112]!, self._r[1112]!, [_1]) + } + public var Weekday_Yesterday: String { return self._s[1113]! } + public var WallpaperSearch_ColorBlack: String { return self._s[1114]! } + public var AutoNightTheme_Scheduled: String { return self._s[1115]! } + public func Login_PhoneGenericEmailBody(_ _1: String, _ _2: String, _ _3: String, _ _4: String, _ _5: String, _ _6: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1116]!, self._r[1116]!, [_1, _2, _3, _4, _5, _6]) + } + public var PrivacyPolicy_DeclineDeleteNow: String { return self._s[1117]! } + public func PUSH_CHAT_JOINED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1118]!, self._r[1118]!, [_1, _2]) + } + public var CreatePoll_Create: String { return self._s[1119]! } + public var Channel_Members_AddBannedErrorAdmin: String { return self._s[1120]! } + public func Notification_CallFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1121]!, self._r[1121]!, [_1, _2]) + } + public var Checkout_ErrorProviderAccountInvalid: String { return self._s[1122]! } + public var Notifications_InAppNotificationsSounds: String { return self._s[1124]! } + public var Preview_OpenInInstagram: String { return self._s[1125]! } + public var Notification_MessageLifetimeRemovedOutgoing: String { return self._s[1126]! } + public func PUSH_CHAT_ADD_MEMBER(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1127]!, self._r[1127]!, [_1, _2, _3]) + } + public func Passport_PrivacyPolicy(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1128]!, self._r[1128]!, [_1, _2]) + } + public var Channel_AdminLog_InfoPanelAlertTitle: String { return self._s[1129]! } + public var NetworkUsageSettings_TotalSection: String { return self._s[1130]! } + public var Channel_Setup_TypePrivateHelp: String { return self._s[1131]! } + public func PUSH_CHAT_MESSAGE_POLL(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1132]!, self._r[1132]!, [_1, _2]) + } + public var Privacy_GroupsAndChannels_NeverAllow_Placeholder: String { return self._s[1134]! } + public var FastTwoStepSetup_HintSection: String { return self._s[1135]! } + public var Wallpaper_PhotoLibrary: String { return self._s[1136]! } + public var TwoStepAuth_SetupResendEmailCodeAlert: String { return self._s[1137]! } + public var Gif_NoGifsFound: String { return self._s[1138]! } + public var Watch_LastSeen_WithinAMonth: String { return self._s[1139]! } + public var GroupInfo_ActionPromote: String { return self._s[1140]! } + public var PasscodeSettings_SimplePasscode: String { return self._s[1141]! } + public var GroupInfo_Permissions_Title: String { return self._s[1142]! } + public var Permissions_ContactsText_v0: String { return self._s[1143]! } + public var PrivacySettings_DataSettingsHelp: String { return self._s[1146]! } + public var Passport_FieldEmailHelp: String { return self._s[1147]! } + public var Passport_Identity_GenderPlaceholder: String { return self._s[1148]! } + public var Weekday_ShortSaturday: String { return self._s[1149]! } + public var ContactInfo_PhoneLabelMain: String { return self._s[1150]! } + public var Watch_Conversation_UserInfo: String { return self._s[1151]! } + public var CheckoutInfo_ShippingInfoCityPlaceholder: String { return self._s[1152]! } + public var PrivacyLastSeenSettings_Title: String { return self._s[1153]! } + public var Conversation_ShareBotLocationConfirmation: String { return self._s[1154]! } + public var PhotoEditor_VignetteTool: String { return self._s[1155]! } + public var Passport_Address_Street1Placeholder: String { return self._s[1156]! } + public var Passport_Language_et: String { return self._s[1157]! } + public var Passport_Language_bg: String { return self._s[1159]! } + public var Stickers_NoStickersFound: String { return self._s[1161]! } + public func PUSH_CHANNEL_MESSAGE_TEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1163]!, self._r[1163]!, [_1, _2]) + } + public var Settings_About: String { return self._s[1164]! } + public func Channel_AdminLog_MessageRestricted(_ _0: String, _ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1165]!, self._r[1165]!, [_0, _1, _2]) + } + public var KeyCommand_NewMessage: String { return self._s[1167]! } + public var Group_ErrorAddBlocked: String { return self._s[1168]! } + public func Message_PaymentSent(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1169]!, self._r[1169]!, [_0]) + } + public var Map_LocationTitle: String { return self._s[1170]! } + public var CallSettings_UseLessDataLongDescription: String { return self._s[1171]! } + public var Cache_ClearProgress: String { return self._s[1172]! } + public func Channel_Management_ErrorNotMember(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1173]!, self._r[1173]!, [_0]) + } + public var GroupRemoved_AddToGroup: String { return self._s[1174]! } + public var Passport_UpdateRequiredError: String { return self._s[1175]! } + public func PUSH_MESSAGE_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1176]!, self._r[1176]!, [_1]) + } + public var Notifications_PermissionsSuppressWarningText: String { return self._s[1178]! } + public var Passport_Identity_MainPageHelp: String { return self._s[1179]! } + public var Conversation_StatusKickedFromGroup: String { return self._s[1180]! } + public var Passport_Language_ka: String { return self._s[1181]! } + public var Call_Decline: String { return self._s[1182]! } + public var SocksProxySetup_ProxyEnabled: String { return self._s[1183]! } + public func AuthCode_Alert(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1186]!, self._r[1186]!, [_0]) + } + public var CallFeedback_Send: String { return self._s[1187]! } + public func Channel_AdminLog_MessagePromotedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1188]!, self._r[1188]!, [_1, _2]) + } + public var Passport_Phone_UseTelegramNumberHelp: String { return self._s[1189]! } + public var Passport_DeletePassport: String { return self._s[1191]! } + public var Privacy_Calls_P2PAlways: String { return self._s[1192]! } + public var Month_ShortDecember: String { return self._s[1193]! } + public var Channel_AdminLog_CanEditMessages: String { return self._s[1195]! } + public func Contacts_AccessDeniedHelpLandscape(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1196]!, self._r[1196]!, [_0]) + } + public var Channel_Stickers_Searching: String { return self._s[1197]! } + public var Conversation_EncryptedDescription1: String { return self._s[1198]! } + public var Conversation_EncryptedDescription2: String { return self._s[1199]! } + public var Conversation_EncryptedDescription3: String { return self._s[1200]! } + public var PhotoEditor_SharpenTool: String { return self._s[1201]! } + public var Conversation_EncryptedDescription4: String { return self._s[1203]! } + public var Channel_Members_AddMembers: String { return self._s[1204]! } + public var Wallpaper_Search: String { return self._s[1205]! } + public var Weekday_Friday: String { return self._s[1206]! } + public var Privacy_ContactsSync: String { return self._s[1207]! } + public var ApplyLanguage_ChangeLanguageAction: String { return self._s[1208]! } + public func Channel_Management_RestrictedBy(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1209]!, self._r[1209]!, [_0]) + } + public var GroupInfo_Permissions_Removed: String { return self._s[1210]! } + public var Passport_Identity_GenderMale: String { return self._s[1211]! } + public func Call_StatusBar(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1212]!, self._r[1212]!, [_0]) + } + public var Notifications_PermissionsKeepDisabled: String { return self._s[1213]! } + public var Conversation_JumpToDate: String { return self._s[1214]! } + public var Contacts_GlobalSearch: String { return self._s[1215]! } + public var AutoDownloadSettings_ResetHelp: String { return self._s[1216]! } + public var Profile_MessageLifetime1d: String { return self._s[1217]! } + public func MESSAGE_INVOICE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1218]!, self._r[1218]!, [_1, _2]) + } + public var StickerPack_BuiltinPackName: String { return self._s[1221]! } + public func PUSH_CHAT_MESSAGE_AUDIO(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1222]!, self._r[1222]!, [_1, _2]) + } + public var Passport_InfoTitle: String { return self._s[1224]! } + public var Notifications_PermissionsUnreachableText: String { return self._s[1225]! } + public func NetworkUsageSettings_CellularUsageSince(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1229]!, self._r[1229]!, [_0]) + } + public func PUSH_CHAT_MESSAGE_GEO(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1230]!, self._r[1230]!, [_1, _2]) + } + public var Passport_Address_TypePassportRegistrationUploadScan: String { return self._s[1231]! } + public var Profile_BotInfo: String { return self._s[1232]! } + public var Watch_Compose_CreateMessage: String { return self._s[1233]! } + public var AutoDownloadSettings_VoiceMessagesInfo: String { return self._s[1234]! } + public var Month_ShortNovember: String { return self._s[1235]! } + public var Wallpaper_SetCustomBackground: String { return self._s[1236]! } + public var Passport_Identity_TranslationsHelp: String { return self._s[1237]! } + public var NotificationsSound_Chime: String { return self._s[1238]! } + public var Passport_Language_ko: String { return self._s[1240]! } + public var InviteText_URL: String { return self._s[1241]! } + public var TextFormat_Monospace: String { return self._s[1242]! } + public func Time_PreciseDate_m11(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1243]!, self._r[1243]!, [_1, _2, _3]) + } + public func Login_WillSendSms(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1244]!, self._r[1244]!, [_0]) + } + public func Watch_Time_ShortWeekdayAt(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1245]!, self._r[1245]!, [_1, _2]) + } + public var Passport_InfoLearnMore: String { return self._s[1247]! } + public var TwoStepAuth_EmailPlaceholder: String { return self._s[1248]! } + public var Passport_Identity_AddIdentityCard: String { return self._s[1249]! } + public var Your_card_has_expired: String { return self._s[1250]! } + public var StickerPacksSettings_StickerPacksSection: String { return self._s[1251]! } + public var GroupInfo_InviteLink_Help: String { return self._s[1252]! } + public var Conversation_Report: String { return self._s[1255]! } + public var Notifications_MessageNotificationsSound: String { return self._s[1256]! } + public var Notification_MessageLifetime1m: String { return self._s[1257]! } + public var Privacy_ContactsTitle: String { return self._s[1258]! } + public var Conversation_ShareMyContactInfo: String { return self._s[1259]! } + public var ChannelMembers_WhoCanAddMembersAdminsHelp: String { return self._s[1260]! } + public var Channel_Members_Title: String { return self._s[1261]! } + public var Map_OpenInWaze: String { return self._s[1262]! } + public var Login_PhoneBannedError: String { return self._s[1263]! } + public func LiveLocationUpdated_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1264]!, self._r[1264]!, [_0]) + } + public var Group_Management_AddModeratorHelp: String { return self._s[1265]! } + public var AutoDownloadSettings_WifiTitle: String { return self._s[1266]! } + public var Common_OK: String { return self._s[1267]! } + public var Passport_Address_TypeBankStatementUploadScan: String { return self._s[1268]! } + public var Cache_Music: String { return self._s[1269]! } + public var PasscodeSettings_UnlockWithTouchId: String { return self._s[1270]! } + public var TwoStepAuth_HintPlaceholder: String { return self._s[1271]! } + public func PUSH_PINNED_INVOICE(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1272]!, self._r[1272]!, [_1]) + } + public func Passport_RequestHeader(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1273]!, self._r[1273]!, [_0]) + } + public var Watch_MessageView_ViewOnPhone: String { return self._s[1275]! } + public var Privacy_Calls_CustomShareHelp: String { return self._s[1276]! } + public var ChangePhoneNumberNumber_Title: String { return self._s[1278]! } + public var State_ConnectingToProxyInfo: String { return self._s[1279]! } + public var Message_VideoMessage: String { return self._s[1281]! } + public var ChannelInfo_DeleteChannel: String { return self._s[1282]! } + public var ContactInfo_PhoneLabelOther: String { return self._s[1283]! } + public var Channel_EditAdmin_CannotEdit: String { return self._s[1284]! } + public var Passport_DeleteAddressConfirmation: String { return self._s[1285]! } + public var WallpaperPreview_SwipeBottomText: String { return self._s[1286]! } + public var Activity_RecordingAudio: String { return self._s[1287]! } + public var PasscodeSettings_TryAgainIn1Minute: String { return self._s[1288]! } + public func Notification_ChangedGroupName(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1290]!, self._r[1290]!, [_0, _1]) + } + public func EmptyGroupInfo_Line1(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1294]!, self._r[1294]!, [_0]) + } + public var Conversation_ApplyLocalization: String { return self._s[1295]! } + public var UserInfo_AddPhone: String { return self._s[1296]! } + public var Map_ShareLiveLocationHelp: String { return self._s[1297]! } + public func Passport_Identity_NativeNameGenericHelp(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1298]!, self._r[1298]!, [_0]) + } + public var Passport_Scans: String { return self._s[1300]! } + public var BlockedUsers_Unblock: String { return self._s[1301]! } + public func PUSH_ENCRYPTION_REQUEST(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1302]!, self._r[1302]!, [_1]) + } + public var Channel_Management_LabelCreator: String { return self._s[1303]! } + public var Passport_Identity_NativeNameGenericTitle: String { return self._s[1304]! } + public func Login_EmailPhoneBody(_ _0: String, _ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1305]!, self._r[1305]!, [_0, _1, _2]) + } + public var Login_PhoneNumberHelp: String { return self._s[1306]! } + public var LastSeen_ALongTimeAgo: String { return self._s[1307]! } + public var Channel_AdminLog_CanPinMessages: String { return self._s[1308]! } + public var ChannelIntro_CreateChannel: String { return self._s[1309]! } + public var Conversation_UnreadMessages: String { return self._s[1310]! } + public var Channel_AdminLog_EmptyText: String { return self._s[1311]! } + public var Notification_GroupActivated: String { return self._s[1312]! } + public var NotificationSettings_ContactJoinedInfo: String { return self._s[1313]! } + public func Notification_PinnedContactMessage(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1314]!, self._r[1314]!, [_0]) + } + public func DownloadingStatus(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1315]!, self._r[1315]!, [_0, _1]) + } + public var GroupInfo_ConvertToSupergroup: String { return self._s[1317]! } + public func PrivacyPolicy_AgeVerificationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1318]!, self._r[1318]!, [_0]) + } + public var Undo_DeletedChannel: String { return self._s[1319]! } + public var CallFeedback_AddComment: String { return self._s[1320]! } + public var Document_TargetConfirmationFormat: String { return self._s[1321]! } + public func Call_StatusOngoing(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1322]!, self._r[1322]!, [_0]) + } + public var LogoutOptions_SetPasscodeTitle: String { return self._s[1323]! } + public var Contacts_SortByName: String { return self._s[1324]! } + public func CHAT_MESSAGE_INVOICE(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1326]!, self._r[1326]!, [_1, _2, _3]) + } + public var Conversation_ClearSelfHistory: String { return self._s[1327]! } + public var Checkout_NewCard_PostcodePlaceholder: String { return self._s[1328]! } + public var Stickers_SuggestNone: String { return self._s[1329]! } + public var ChatSettings_Cache: String { return self._s[1330]! } + public var Settings_SaveIncomingPhotos: String { return self._s[1331]! } + public var Media_ShareThisPhoto: String { return self._s[1332]! } + public var InfoPlist_NSContactsUsageDescription: String { return self._s[1333]! } + public var Conversation_ContextMenuCopyLink: String { return self._s[1334]! } + public var PrivacyPolicy_AgeVerificationTitle: String { return self._s[1335]! } + public var TwoStepAuth_SetupPasswordEnterPasswordNew: String { return self._s[1336]! } + public var Permissions_CellularDataTitle_v0: String { return self._s[1337]! } + public var WallpaperSearch_ColorWhite: String { return self._s[1339]! } + public var Channel_AdminLog_DefaultRestrictionsUpdated: String { return self._s[1340]! } + public var Map_OpenIn: String { return self._s[1341]! } + public func PUSH_PHONE_CALL_MISSED(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1344]!, self._r[1344]!, [_1]) + } + public func ChannelInfo_AddParticipantConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1345]!, self._r[1345]!, [_0]) + } + public var MessagePoll_LabelClosed: String { return self._s[1346]! } + public var GroupPermission_PermissionGloballyDisabled: String { return self._s[1348]! } + public var Passport_Identity_MiddleNamePlaceholder: String { return self._s[1349]! } + public var UserInfo_FirstNamePlaceholder: String { return self._s[1350]! } + public var PrivacyLastSeenSettings_WhoCanSeeMyTimestamp: String { return self._s[1351]! } + public var Login_SelectCountry_Title: String { return self._s[1352]! } + public var Channel_EditAdmin_PermissionBanUsers: String { return self._s[1353]! } + public var Channel_AdminLog_ChangeInfo: String { return self._s[1354]! } + public var Watch_Suggestion_BRB: String { return self._s[1355]! } + public var Passport_Identity_EditIdentityCard: String { return self._s[1356]! } + public var Contacts_PermissionsTitle: String { return self._s[1357]! } + public var Conversation_RestrictedInline: String { return self._s[1358]! } + public var StickerPack_ViewPack: String { return self._s[1360]! } + public func Update_AppVersion(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1361]!, self._r[1361]!, [_0]) + } + public var Compose_NewChannel: String { return self._s[1363]! } + public var ChatSettings_AutoDownloadSettings_TypePhoto: String { return self._s[1366]! } + public var Channel_Info_Stickers: String { return self._s[1368]! } + public var AutoNightTheme_PreferredTheme: String { return self._s[1369]! } + public var PrivacyPolicy_AgeVerificationAgree: String { return self._s[1370]! } + public var Passport_DeletePersonalDetails: String { return self._s[1371]! } + public var LogoutOptions_AddAccountTitle: String { return self._s[1372]! } + public var Conversation_SearchNoResults: String { return self._s[1374]! } + public var MessagePoll_LabelAnonymous: String { return self._s[1375]! } + public var Channel_Members_AddAdminErrorNotAMember: String { return self._s[1376]! } + public var Login_Code: String { return self._s[1377]! } + public var Watch_Suggestion_WhatsUp: String { return self._s[1378]! } + public var Weekday_ShortThursday: String { return self._s[1379]! } + public var Resolve_ErrorNotFound: String { return self._s[1381]! } + public var LastSeen_Offline: String { return self._s[1382]! } + public var GroupPermission_AddMembersNotAvailable: String { return self._s[1383]! } + public var Privacy_Calls_AlwaysAllow_Title: String { return self._s[1384]! } + public var GroupInfo_Title: String { return self._s[1385]! } + public var NotificationsSound_Note: String { return self._s[1386]! } + public var Conversation_EditingMessagePanelTitle: String { return self._s[1387]! } + public var Watch_Message_Poll: String { return self._s[1388]! } + public var Privacy_Calls: String { return self._s[1389]! } + public var Month_ShortAugust: String { return self._s[1390]! } + public var TwoStepAuth_SetPasswordHelp: String { return self._s[1391]! } + public var Notifications_Reset: String { return self._s[1392]! } + public var Conversation_Pin: String { return self._s[1393]! } + public var Passport_Language_lv: String { return self._s[1394]! } + public var BlockedUsers_Info: String { return self._s[1395]! } + public var Watch_Conversation_Unblock: String { return self._s[1398]! } + public func Time_MonthOfYear_m9(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1399]!, self._r[1399]!, [_0]) + } + public var CloudStorage_Title: String { return self._s[1400]! } + public var GroupInfo_DeleteAndExitConfirmation: String { return self._s[1401]! } + public func NetworkUsageSettings_WifiUsageSince(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1402]!, self._r[1402]!, [_0]) + } + public var Channel_AdminLogFilter_AdminsTitle: String { return self._s[1403]! } + public var Watch_Suggestion_OnMyWay: String { return self._s[1404]! } + public var TwoStepAuth_RecoveryEmailTitle: String { return self._s[1405]! } + public var Passport_Address_EditBankStatement: String { return self._s[1406]! } + public var ChatSettings_DownloadInBackgroundInfo: String { return self._s[1407]! } + public var ShareMenu_Comment: String { return self._s[1408]! } + public var Permissions_ContactsTitle_v0: String { return self._s[1409]! } + public var Notifications_PermissionsTitle: String { return self._s[1410]! } + public var GroupPermission_NoSendLinks: String { return self._s[1411]! } + public var Privacy_Forwards_NeverAllow_Title: String { return self._s[1412]! } + public var Settings_Support: String { return self._s[1413]! } + public var Notifications_ChannelNotificationsSound: String { return self._s[1414]! } + public var Privacy_Forwards_Preview: String { return self._s[1415]! } + public var GroupPermission_ApplyAlertAction: String { return self._s[1416]! } + public var Watch_Stickers_StickerPacks: String { return self._s[1417]! } + public var Common_Select: String { return self._s[1419]! } + public var CheckoutInfo_ErrorEmailInvalid: String { return self._s[1420]! } + public var WallpaperSearch_ColorGray: String { return self._s[1422]! } + public var ChatAdmins_AllMembersAreAdminsOffHelp: String { return self._s[1423]! } + public var PasscodeSettings_AutoLock_IfAwayFor_5hours: String { return self._s[1424]! } + public var Appearance_PreviewReplyAuthor: String { return self._s[1425]! } + public var TwoStepAuth_RecoveryTitle: String { return self._s[1426]! } + public var Widget_AuthRequired: String { return self._s[1427]! } + public var Camera_FlashOn: String { return self._s[1428]! } + public var Channel_Stickers_NotFoundHelp: String { return self._s[1429]! } + public var Watch_Suggestion_OK: String { return self._s[1430]! } + public func Username_LinkHint(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1432]!, self._r[1432]!, [_0]) + } + public func Notification_PinnedLiveLocationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1434]!, self._r[1434]!, [_0]) + } + public var DialogList_AdLabel: String { return self._s[1435]! } + public var WatchRemote_NotificationText: String { return self._s[1436]! } + public var Conversation_ReportSpam: String { return self._s[1437]! } + public var Settings_LogoutConfirmationTitle: String { return self._s[1439]! } + public var PhoneLabel_Title: String { return self._s[1440]! } + public var Passport_Address_EditRentalAgreement: String { return self._s[1441]! } + public var Notifications_ExceptionsTitle: String { return self._s[1442]! } + public var Notifications_AlertTones: String { return self._s[1443]! } + public var Call_ReportIncludeLogDescription: String { return self._s[1444]! } + public var AutoDownloadSettings_PrivateChats: String { return self._s[1445]! } + public var TwoStepAuth_AddHintTitle: String { return self._s[1447]! } + public var ReportPeer_ReasonOther: String { return self._s[1448]! } + public var KeyCommand_ScrollDown: String { return self._s[1450]! } + public func Login_BannedPhoneSubject(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1451]!, self._r[1451]!, [_0]) + } + public var NetworkUsageSettings_MediaVideoDataSection: String { return self._s[1452]! } + public var ChannelInfo_DeleteGroupConfirmation: String { return self._s[1453]! } + public var AuthSessions_LogOut: String { return self._s[1454]! } + public var Passport_Identity_TypeInternalPassport: String { return self._s[1455]! } + public var ChatSettings_AutoDownloadVoiceMessages: String { return self._s[1456]! } + public var Passport_Phone_Title: String { return self._s[1457]! } + public var Settings_PhoneNumber: String { return self._s[1458]! } + public var NotificationsSound_Alert: String { return self._s[1459]! } + public var WebSearch_SearchNoResults: String { return self._s[1460]! } + public var Privacy_ProfilePhoto_AlwaysShareWith_Title: String { return self._s[1462]! } + public var LogoutOptions_AlternativeOptionsSection: String { return self._s[1463]! } + public var PhotoEditor_CurvesTool: String { return self._s[1464]! } + public var Checkout_PaymentMethod: String { return self._s[1466]! } + public func PUSH_CHAT_ADD_YOU(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1467]!, self._r[1467]!, [_1, _2]) + } + public var Contacts_AccessDeniedError: String { return self._s[1468]! } + public var Camera_PhotoMode: String { return self._s[1471]! } + public var Passport_Address_AddUtilityBill: String { return self._s[1472]! } + public var CallSettings_OnMobile: String { return self._s[1473]! } + public var Tour_Text2: String { return self._s[1474]! } + public func PUSH_CHAT_MESSAGE_ROUND(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1475]!, self._r[1475]!, [_1, _2]) + } + public var DialogList_EncryptionProcessing: String { return self._s[1477]! } + public var Permissions_Skip: String { return self._s[1478]! } + public var SecretImage_Title: String { return self._s[1479]! } + public var Watch_MessageView_Title: String { return self._s[1480]! } + public var AttachmentMenu_Poll: String { return self._s[1481]! } + public func Notification_GroupInviter(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1482]!, self._r[1482]!, [_0]) + } + public var Notification_CallCanceled: String { return self._s[1483]! } + public var WallpaperPreview_Title: String { return self._s[1484]! } + public var Privacy_PaymentsClear_PaymentInfo: String { return self._s[1485]! } + public var Settings_ProxyConnecting: String { return self._s[1486]! } + public var Profile_MessageLifetime5s: String { return self._s[1488]! } + public var Username_InvalidCharacters: String { return self._s[1489]! } + public var WallpaperPreview_CropBottomText: String { return self._s[1490]! } + public var AutoDownloadSettings_LimitBySize: String { return self._s[1491]! } + public var Settings_AddAccount: String { return self._s[1492]! } + public var Notification_CreatedChannel: String { return self._s[1495]! } + public func PUSH_CHAT_DELETE_MEMBER(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1496]!, self._r[1496]!, [_1, _2, _3]) + } + public var Passcode_AppLockedAlert: String { return self._s[1498]! } + public var Contacts_TopSection: String { return self._s[1499]! } + public func Time_MonthOfYear_m6(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1500]!, self._r[1500]!, [_0]) + } + public var ReportPeer_ReasonSpam: String { return self._s[1501]! } + public var UserInfo_TapToCall: String { return self._s[1502]! } + public var Conversation_ForwardAuthorHiddenTooltip: String { return self._s[1504]! } + public var AutoDownloadSettings_DataUsageCustom: String { return self._s[1505]! } + public var Common_Search: String { return self._s[1506]! } + public var AuthSessions_IncompleteAttemptsInfo: String { return self._s[1507]! } + public var Message_InvoiceLabel: String { return self._s[1508]! } + public var Conversation_InputTextPlaceholder: String { return self._s[1509]! } + public var NetworkUsageSettings_MediaImageDataSection: String { return self._s[1510]! } + public func Passport_Address_UploadOneOfScan(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1511]!, self._r[1511]!, [_0]) + } + public var Conversation_Info: String { return self._s[1512]! } + public var Login_InfoDeletePhoto: String { return self._s[1513]! } + public var Passport_Language_vi: String { return self._s[1515]! } + public var Conversation_Search: String { return self._s[1516]! } + public var DialogList_DeleteBotConversationConfirmation: String { return self._s[1517]! } + public var ReportPeer_ReasonPornography: String { return self._s[1518]! } + public var AutoDownloadSettings_PhotosTitle: String { return self._s[1519]! } + public var Conversation_SendMessageErrorGroupRestricted: String { return self._s[1520]! } + public var Map_LiveLocationGroupDescription: String { return self._s[1521]! } + public var Channel_Setup_TypeHeader: String { return self._s[1522]! } + public var AuthSessions_LoggedIn: String { return self._s[1523]! } + public var Privacy_Forwards_AlwaysAllow_Title: String { return self._s[1524]! } + public var Login_SmsRequestState3: String { return self._s[1525]! } + public var Passport_Address_EditUtilityBill: String { return self._s[1526]! } + public var Appearance_ReduceMotionInfo: String { return self._s[1527]! } + public var Channel_Edit_LinkItem: String { return self._s[1528]! } + public var Privacy_Calls_P2PNever: String { return self._s[1529]! } + public var Conversation_AddToReadingList: String { return self._s[1531]! } + public var Message_Animation: String { return self._s[1532]! } + public var Conversation_DefaultRestrictedMedia: String { return self._s[1533]! } + public var Map_Unknown: String { return self._s[1534]! } + public var AutoDownloadSettings_LastDelimeter: String { return self._s[1535]! } + public func PUSH_PINNED_TEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1536]!, self._r[1536]!, [_1, _2]) + } + public func Passport_FieldOneOf_Or(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1537]!, self._r[1537]!, [_1, _2]) + } + public var Call_StatusRequesting: String { return self._s[1538]! } + public var Conversation_SecretChatContextBotAlert: String { return self._s[1539]! } + public var SocksProxySetup_ProxyStatusChecking: String { return self._s[1540]! } + public func PUSH_CHAT_MESSAGE_DOC(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1541]!, self._r[1541]!, [_1, _2]) + } + public var Weekday_Monday: String { return self._s[1542]! } + public var Update_Skip: String { return self._s[1543]! } + public var Group_Username_RemoveExistingUsernamesInfo: String { return self._s[1544]! } + public var Message_PinnedPollMessage: String { return self._s[1545]! } + public var BlockedUsers_Title: String { return self._s[1546]! } + public func PUSH_CHANNEL_MESSAGE_AUDIO(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1547]!, self._r[1547]!, [_1]) + } + public var Username_CheckingUsername: String { return self._s[1548]! } + public var NotificationsSound_Bell: String { return self._s[1549]! } + public var Conversation_SendMessageErrorFlood: String { return self._s[1550]! } + public func Notification_PinnedLocationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1551]!, self._r[1551]!, [_0]) + } + public var ChannelMembers_ChannelAdminsTitle: String { return self._s[1552]! } + public var ChatSettings_Groups: String { return self._s[1553]! } + public var Your_card_was_declined: String { return self._s[1554]! } + public var TwoStepAuth_EnterPasswordHelp: String { return self._s[1556]! } + public var ChatList_Unmute: String { return self._s[1557]! } + public var PhotoEditor_CurvesAll: String { return self._s[1558]! } + public var Weekday_ShortTuesday: String { return self._s[1559]! } + public var DialogList_Read: String { return self._s[1560]! } + public var ChannelMembers_WhoCanAddMembers_AllMembers: String { return self._s[1561]! } + public var Passport_Identity_Gender: String { return self._s[1562]! } + public func Target_ShareGameConfirmationPrivate(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1563]!, self._r[1563]!, [_0]) + } + public var Target_SelectGroup: String { return self._s[1564]! } + public func DialogList_EncryptedChatStartedIncoming(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1566]!, self._r[1566]!, [_0]) + } + public var Passport_Language_en: String { return self._s[1567]! } + public var AutoDownloadSettings_AutodownloadPhotos: String { return self._s[1568]! } + public var Channel_Username_CreatePublicLinkHelp: String { return self._s[1569]! } + public var Login_CancelPhoneVerificationContinue: String { return self._s[1570]! } + public var Checkout_NewCard_PaymentCard: String { return self._s[1572]! } + public var Login_InfoHelp: String { return self._s[1573]! } + public var Contacts_PermissionsSuppressWarningTitle: String { return self._s[1574]! } + public var SocksProxySetup_AddProxy: String { return self._s[1577]! } + public var CreatePoll_Title: String { return self._s[1578]! } + public var PasscodeSettings_SimplePasscodeHelp: String { return self._s[1579]! } + public var UserInfo_GroupsInCommon: String { return self._s[1580]! } + public var Call_AudioRouteHide: String { return self._s[1581]! } + public var ContactInfo_PhoneLabelMobile: String { return self._s[1583]! } + public func ChatList_LeaveGroupConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1584]!, self._r[1584]!, [_0]) + } + public var TextFormat_Bold: String { return self._s[1585]! } + public var FastTwoStepSetup_EmailSection: String { return self._s[1586]! } + public var Notifications_Title: String { return self._s[1587]! } + public var Group_Username_InvalidTooShort: String { return self._s[1588]! } + public var Channel_ErrorAddTooMuch: String { return self._s[1589]! } + public func DialogList_MultipleTypingSuffix(_ _0: Int) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1590]!, self._r[1590]!, ["\(_0)"]) + } + public var Stickers_SuggestAdded: String { return self._s[1592]! } + public var Login_CountryCode: String { return self._s[1593]! } + public var ChatSettings_AutoPlayVideos: String { return self._s[1594]! } + public var Map_GetDirections: String { return self._s[1595]! } + public var Login_PhoneFloodError: String { return self._s[1596]! } + public func Time_MonthOfYear_m3(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1597]!, self._r[1597]!, [_0]) + } + public var Settings_SetUsername: String { return self._s[1599]! } + public var Notification_GroupInviterSelf: String { return self._s[1600]! } + public var InstantPage_TapToOpenLink: String { return self._s[1601]! } + public func Notification_ChannelInviter(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1602]!, self._r[1602]!, [_0]) + } + public var Watch_Suggestion_TalkLater: String { return self._s[1603]! } + public var SecretChat_Title: String { return self._s[1604]! } + public var Group_UpgradeNoticeText1: String { return self._s[1605]! } + public var AuthSessions_Title: String { return self._s[1606]! } + public var PhotoEditor_CropAuto: String { return self._s[1607]! } + public var Channel_About_Title: String { return self._s[1608]! } + public var FastTwoStepSetup_EmailHelp: String { return self._s[1609]! } + public func Conversation_Bytes(_ _0: Int) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1611]!, self._r[1611]!, ["\(_0)"]) + } + public var Conversation_PinMessageAlert_OnlyPin: String { return self._s[1613]! } + public var Group_Setup_HistoryVisibleHelp: String { return self._s[1614]! } + public func PUSH_MESSAGE_GIF(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1615]!, self._r[1615]!, [_1]) + } + public func SharedMedia_SearchNoResultsDescription(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1617]!, self._r[1617]!, [_0]) + } + public func TwoStepAuth_RecoveryEmailUnavailable(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1618]!, self._r[1618]!, [_0]) + } + public var Privacy_PaymentsClearInfoHelp: String { return self._s[1619]! } + public var Undo_MessagesDeleted: String { return self._s[1620]! } + public var Presence_online: String { return self._s[1622]! } + public var PasscodeSettings_Title: String { return self._s[1623]! } + public var Passport_Identity_ExpiryDatePlaceholder: String { return self._s[1624]! } + public var Web_OpenExternal: String { return self._s[1625]! } + public var AutoDownloadSettings_AutoDownload: String { return self._s[1627]! } + public func AutoNightTheme_AutomaticHelp(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1628]!, self._r[1628]!, [_0]) + } + public var FastTwoStepSetup_PasswordConfirmationPlaceholder: String { return self._s[1629]! } + public var Map_YouAreHere: String { return self._s[1630]! } + public func AuthSessions_Message(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1631]!, self._r[1631]!, [_0]) + } + public func ChatList_DeleteChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1632]!, self._r[1632]!, [_0]) + } + public var PrivacyLastSeenSettings_AlwaysShareWith: String { return self._s[1633]! } + public var Target_InviteToGroupErrorAlreadyInvited: String { return self._s[1634]! } + public func AuthSessions_AppUnofficial(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1635]!, self._r[1635]!, [_0]) + } + public func DialogList_LiveLocationSharingTo(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1636]!, self._r[1636]!, [_0]) + } + public var SocksProxySetup_Username: String { return self._s[1637]! } + public var Bot_Start: String { return self._s[1638]! } + public func Channel_AdminLog_EmptyFilterQueryText(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1639]!, self._r[1639]!, [_0]) + } + public func Channel_AdminLog_MessagePinned(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1640]!, self._r[1640]!, [_0]) + } + public var Contacts_SortByPresence: String { return self._s[1641]! } + public var Conversation_DiscardVoiceMessageTitle: String { return self._s[1643]! } + public func PUSH_CHAT_CREATED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1644]!, self._r[1644]!, [_1, _2]) + } + public func PrivacySettings_LastSeenContactsMinus(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1645]!, self._r[1645]!, [_0]) + } + public var Passport_Email_EnterOtherEmail: String { return self._s[1646]! } + public var Login_InfoAvatarPhoto: String { return self._s[1647]! } + public var Privacy_PaymentsClear_ShippingInfo: String { return self._s[1648]! } + public var Tour_Title4: String { return self._s[1649]! } + public var Passport_Identity_Translation: String { return self._s[1650]! } + public var Login_TermsOfServiceLabel: String { return self._s[1652]! } + public var Passport_Language_it: String { return self._s[1653]! } + public var KeyCommand_JumpToNextUnreadChat: String { return self._s[1654]! } + public var Passport_Identity_SelfieHelp: String { return self._s[1655]! } + public var Conversation_ClearAll: String { return self._s[1657]! } + public var TwoStepAuth_FloodError: String { return self._s[1659]! } + public func PUSH_CHANNEL_MESSAGE_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1660]!, self._r[1660]!, [_1]) + } + public var Paint_Delete: String { return self._s[1661]! } + public var LogoutOptions_SetPasscodeText: String { return self._s[1662]! } + public func Passport_AcceptHelp(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1663]!, self._r[1663]!, [_1, _2]) + } + public var Message_PinnedAudioMessage: String { return self._s[1664]! } + public func Watch_Time_ShortTodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1665]!, self._r[1665]!, [_0]) + } + public var Notification_Mute1hMin: String { return self._s[1666]! } + public var Notifications_GroupNotificationsSound: String { return self._s[1667]! } + public var SocksProxySetup_ShareProxyList: String { return self._s[1668]! } + public var Conversation_MessageEditedLabel: String { return self._s[1669]! } + public var Notification_Exceptions_AlwaysOff: String { return self._s[1670]! } + public func Channel_AdminLog_MessageAdmin(_ _0: String, _ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1671]!, self._r[1671]!, [_0, _1, _2]) + } + public var NetworkUsageSettings_ResetStats: String { return self._s[1672]! } + public func PUSH_MESSAGE_GEOLIVE(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1673]!, self._r[1673]!, [_1]) + } + public var AccessDenied_LocationTracking: String { return self._s[1674]! } + public var Month_GenOctober: String { return self._s[1675]! } + public var GroupInfo_InviteLink_RevokeAlert_Revoke: String { return self._s[1676]! } + public var EnterPasscode_EnterPasscode: String { return self._s[1677]! } + public var MediaPicker_TimerTooltip: String { return self._s[1679]! } + public var SharedMedia_TitleAll: String { return self._s[1680]! } + public var Conversation_RestrictedMedia: String { return self._s[1683]! } + public var AccessDenied_PhotosRestricted: String { return self._s[1684]! } + public var Privacy_Forwards_WhoCanForward: String { return self._s[1686]! } + public var ChangePhoneNumberCode_Called: String { return self._s[1687]! } + public func Notification_PinnedDocumentMessage(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1688]!, self._r[1688]!, [_0]) + } + public var Conversation_SavedMessages: String { return self._s[1691]! } + public var Your_cards_expiration_month_is_invalid: String { return self._s[1693]! } + public var FastTwoStepSetup_PasswordPlaceholder: String { return self._s[1694]! } + public func Target_ShareGameConfirmationGroup(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1696]!, self._r[1696]!, [_0]) + } + public var ReportPeer_AlertSuccess: String { return self._s[1697]! } + public var PhotoEditor_CropAspectRatioOriginal: String { return self._s[1698]! } + public func InstantPage_RelatedArticleAuthorAndDateTitle(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1699]!, self._r[1699]!, [_1, _2]) + } + public var Checkout_PasswordEntry_Title: String { return self._s[1700]! } + public var PhotoEditor_FadeTool: String { return self._s[1701]! } + public var Privacy_ContactsReset: String { return self._s[1702]! } + public func Channel_AdminLog_MessageRestrictedUntil(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1704]!, self._r[1704]!, [_0]) + } + public var Message_PinnedVideoMessage: String { return self._s[1705]! } + public var ChatList_Mute: String { return self._s[1706]! } + public var Permissions_CellularDataText_v0: String { return self._s[1707]! } + public var ShareMenu_SelectChats: String { return self._s[1709]! } + public var MusicPlayer_VoiceNote: String { return self._s[1710]! } + public var Conversation_RestrictedText: String { return self._s[1711]! } + public var TwoStepAuth_DisableSuccess: String { return self._s[1712]! } + public var Cache_Videos: String { return self._s[1713]! } + public var FeatureDisabled_Oops: String { return self._s[1715]! } + public var Passport_Address_PostcodePlaceholder: String { return self._s[1716]! } + public var Stickers_GroupStickersHelp: String { return self._s[1717]! } + public var GroupPermission_NoSendPolls: String { return self._s[1718]! } + public var Message_VideoExpired: String { return self._s[1720]! } + public var Notifications_Badge: String { return self._s[1721]! } + public var GroupInfo_GroupHistoryVisible: String { return self._s[1722]! } + public var CreatePoll_OptionPlaceholder: String { return self._s[1723]! } + public var Username_InvalidTooShort: String { return self._s[1724]! } + public var EnterPasscode_EnterNewPasscodeChange: String { return self._s[1725]! } + public var Channel_AdminLog_PinMessages: String { return self._s[1726]! } + public func Notification_MessageLifetimeRemoved(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1727]!, self._r[1727]!, [_1]) + } + public var Permissions_SiriAllowInSettings_v0: String { return self._s[1728]! } + public var Conversation_DefaultRestrictedText: String { return self._s[1729]! } + public var SharedMedia_CategoryDocs: String { return self._s[1732]! } + public func PUSH_MESSAGE_CONTACT(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1733]!, self._r[1733]!, [_1]) + } + public var Privacy_Forwards_NeverLink: String { return self._s[1735]! } + public func Notification_MessageLifetimeChangedOutgoing(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1736]!, self._r[1736]!, [_1]) + } + public var CheckoutInfo_ErrorShippingNotAvailable: String { return self._s[1737]! } + public func Time_MonthOfYear_m12(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1738]!, self._r[1738]!, [_0]) + } + public var ChatSettings_PrivateChats: String { return self._s[1739]! } + public var Channel_UpdatePhotoItem: String { return self._s[1740]! } + public var GroupInfo_LeftStatus: String { return self._s[1741]! } + public var Watch_MessageView_Forward: String { return self._s[1743]! } + public var ReportPeer_ReasonChildAbuse: String { return self._s[1744]! } + public var Cache_ClearEmpty: String { return self._s[1746]! } + public var Localization_LanguageName: String { return self._s[1747]! } + public var WebSearch_GIFs: String { return self._s[1748]! } + public var Notifications_DisplayNamesOnLockScreenInfoWithLink: String { return self._s[1749]! } + public var Username_InvalidStartsWithNumber: String { return self._s[1750]! } + public var Common_Back: String { return self._s[1751]! } + public var Passport_Identity_DateOfBirthPlaceholder: String { return self._s[1752]! } + public func PUSH_CHANNEL_MESSAGE_STICKER(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1753]!, self._r[1753]!, [_1, _2]) + } + public var Passport_Email_Help: String { return self._s[1754]! } + public var Watch_Conversation_Reply: String { return self._s[1756]! } + public var Conversation_EditingMessageMediaChange: String { return self._s[1758]! } + public var Passport_Identity_IssueDatePlaceholder: String { return self._s[1759]! } + public var Channel_BanUser_Unban: String { return self._s[1761]! } + public var Channel_EditAdmin_PermissionPostMessages: String { return self._s[1762]! } + public var Group_Username_CreatePublicLinkHelp: String { return self._s[1763]! } + public var TwoStepAuth_ConfirmEmailCodePlaceholder: String { return self._s[1765]! } + public var Passport_Identity_Name: String { return self._s[1766]! } + public var GroupRemoved_ViewUserInfo: String { return self._s[1767]! } + public var Conversation_BlockUser: String { return self._s[1768]! } + public var Month_GenJanuary: String { return self._s[1769]! } + public var ChatSettings_TextSize: String { return self._s[1770]! } + public var Notification_PassportValuePhone: String { return self._s[1771]! } + public var Passport_Language_ne: String { return self._s[1772]! } + public var Notification_CallBack: String { return self._s[1773]! } + public var TwoStepAuth_EmailHelp: String { return self._s[1774]! } + public func Time_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1775]!, self._r[1775]!, [_0]) + } + public var Channel_Info_Management: String { return self._s[1776]! } + public var Passport_FieldIdentityUploadHelp: String { return self._s[1777]! } + public var Stickers_FrequentlyUsed: String { return self._s[1778]! } + public var Channel_BanUser_PermissionSendMessages: String { return self._s[1779]! } + public var Passport_Address_OneOfTypeUtilityBill: String { return self._s[1781]! } + public func LOCAL_CHANNEL_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1782]!, self._r[1782]!, [_1, "\(_2)"]) + } + public var Passport_Address_EditResidentialAddress: String { return self._s[1783]! } + public var PrivacyPolicy_DeclineTitle: String { return self._s[1784]! } + public var CreatePoll_TextHeader: String { return self._s[1785]! } + public func Checkout_SavePasswordTimeoutAndTouchId(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1786]!, self._r[1786]!, [_0]) + } + public var PhotoEditor_QualityMedium: String { return self._s[1787]! } + public var InfoPlist_NSMicrophoneUsageDescription: String { return self._s[1788]! } + public var Conversation_StatusKickedFromChannel: String { return self._s[1790]! } + public var CheckoutInfo_ReceiverInfoName: String { return self._s[1791]! } + public var Group_ErrorSendRestrictedStickers: String { return self._s[1792]! } + public func Conversation_RestrictedInlineTimed(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1793]!, self._r[1793]!, [_0]) + } + public var Conversation_LinkDialogOpen: String { return self._s[1795]! } + public func PUSH_CHAT_MESSAGES(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1796]!, self._r[1796]!, [_1, _2, _3]) + } + public var Settings_Username: String { return self._s[1797]! } + public var Wallpaper_Wallpaper: String { return self._s[1799]! } + public var SocksProxySetup_UseProxy: String { return self._s[1801]! } + public var UserInfo_ShareMyContactInfo: String { return self._s[1802]! } + public var MessageTimer_Forever: String { return self._s[1803]! } + public var Privacy_Calls_WhoCanCallMe: String { return self._s[1804]! } + public var PhotoEditor_DiscardChanges: String { return self._s[1805]! } + public var AuthSessions_TerminateOtherSessionsHelp: String { return self._s[1806]! } + public var Passport_Language_da: String { return self._s[1807]! } + public var SocksProxySetup_PortPlaceholder: String { return self._s[1808]! } + public func SecretGIF_NotViewedYet(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1809]!, self._r[1809]!, [_0]) + } + public var Passport_Address_EditPassportRegistration: String { return self._s[1810]! } + public func Channel_AdminLog_MessageChangedGroupAbout(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1812]!, self._r[1812]!, [_0]) + } + public var Passport_Identity_ResidenceCountryPlaceholder: String { return self._s[1814]! } + public var Conversation_SearchByName_Prefix: String { return self._s[1815]! } + public var Conversation_PinnedPoll: String { return self._s[1816]! } + public var Conversation_EmptyGifPanelPlaceholder: String { return self._s[1817]! } + public func PUSH_ENCRYPTION_ACCEPT(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1818]!, self._r[1818]!, [_1]) + } + public var WallpaperSearch_ColorPurple: String { return self._s[1819]! } + public var Cache_ByPeerHeader: String { return self._s[1820]! } + public func Conversation_EncryptedPlaceholderTitleIncoming(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1821]!, self._r[1821]!, [_0]) + } + public var ChatSettings_AutoDownloadDocuments: String { return self._s[1822]! } + public var Notification_PinnedMessage: String { return self._s[1825]! } + public var Contacts_SortBy: String { return self._s[1827]! } + public func PUSH_CHANNEL_MESSAGE_NOTEXT(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1828]!, self._r[1828]!, [_1]) + } + public func PUSH_MESSAGE_GAME(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1830]!, self._r[1830]!, [_1, _2]) + } + public var Call_EncryptionKey_Title: String { return self._s[1831]! } + public var Watch_UserInfo_Service: String { return self._s[1832]! } + public var Conversation_Unpin: String { return self._s[1835]! } + public var CancelResetAccount_Title: String { return self._s[1836]! } + public var Map_LiveLocationFor15Minutes: String { return self._s[1837]! } + public func Time_PreciseDate_m8(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1839]!, self._r[1839]!, [_1, _2, _3]) + } + public var Group_Members_AddMemberBotErrorNotAllowed: String { return self._s[1840]! } + public var CallSettings_Title: String { return self._s[1841]! } + public var PasscodeSettings_EncryptDataHelp: String { return self._s[1843]! } + public var AutoDownloadSettings_Contacts: String { return self._s[1844]! } + public var Passport_Identity_DocumentDetails: String { return self._s[1845]! } + public var LoginPassword_PasswordHelp: String { return self._s[1846]! } + public var PrivacyLastSeenSettings_CustomShareSettings_Delete: String { return self._s[1847]! } + public var Checkout_TotalPaidAmount: String { return self._s[1848]! } + public func FileSize_KB(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1849]!, self._r[1849]!, [_0]) + } + public var PasscodeSettings_ChangePasscode: String { return self._s[1850]! } + public var Conversation_SecretLinkPreviewAlert: String { return self._s[1852]! } + public var Privacy_SecretChatsLinkPreviews: String { return self._s[1853]! } + public func PUSH_CHANNEL_MESSAGE_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1854]!, self._r[1854]!, [_1]) + } + public var Contacts_InviteFriends: String { return self._s[1856]! } + public var Map_ChooseLocationTitle: String { return self._s[1857]! } + public var Conversation_StopPoll: String { return self._s[1859]! } + public func WebSearch_SearchNoResultsDescription(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1860]!, self._r[1860]!, [_0]) + } + public var LogoutOptions_ChangePhoneNumberTitle: String { return self._s[1861]! } + public var Calls_RatingFeedback: String { return self._s[1862]! } + public var GroupInfo_BroadcastListNamePlaceholder: String { return self._s[1863]! } + public var NotificationsSound_Pulse: String { return self._s[1864]! } + public var Watch_LastSeen_Lately: String { return self._s[1865]! } + public var Widget_NoUsers: String { return self._s[1868]! } + public var Conversation_UnvotePoll: String { return self._s[1869]! } + public var Privacy_ProfilePhoto_WhoCanSeeMyPhoto: String { return self._s[1871]! } + public var NotificationsSound_Circles: String { return self._s[1872]! } + public var PrivacyLastSeenSettings_AlwaysShareWith_Title: String { return self._s[1874]! } + public var TwoStepAuth_RecoveryCodeExpired: String { return self._s[1875]! } + public var Proxy_TooltipUnavailable: String { return self._s[1876]! } + public var Passport_Identity_CountryPlaceholder: String { return self._s[1878]! } + public var Conversation_FileDropbox: String { return self._s[1880]! } + public var Notifications_ExceptionsUnmuted: String { return self._s[1881]! } + public var Tour_Text3: String { return self._s[1883]! } + public var Login_ResetAccountProtected_Title: String { return self._s[1885]! } + public var GroupPermission_NoSendMessages: String { return self._s[1886]! } + public var WallpaperSearch_ColorTitle: String { return self._s[1887]! } + public var ChatAdmins_AllMembersAreAdminsOnHelp: String { return self._s[1888]! } + public func Conversation_LiveLocationYouAnd(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1890]!, self._r[1890]!, [_0]) + } + public var GroupInfo_AddParticipantTitle: String { return self._s[1891]! } + public var Checkout_ShippingOption_Title: String { return self._s[1892]! } + public var ChatSettings_AutoDownloadTitle: String { return self._s[1893]! } + public func DialogList_SingleTypingSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1894]!, self._r[1894]!, [_0]) + } + public func ChatSettings_AutoDownloadSettings_TypeVideo(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1895]!, self._r[1895]!, [_0]) + } + public var PrivacyLastSeenSettings_NeverShareWith_Placeholder: String { return self._s[1896]! } + public var AutoDownloadSettings_Photos: String { return self._s[1898]! } + public var Appearance_PreviewIncomingText: String { return self._s[1899]! } + public var ChannelInfo_ConfirmLeave: String { return self._s[1900]! } + public var MediaPicker_MomentsDateRangeSameMonthYearFormat: String { return self._s[1901]! } + public var Passport_Identity_DocumentNumberPlaceholder: String { return self._s[1902]! } + public var Channel_AdminLogFilter_EventsNewMembers: String { return self._s[1903]! } + public var PasscodeSettings_AutoLock_IfAwayFor_5minutes: String { return self._s[1904]! } + public var GroupInfo_SetGroupPhotoStop: String { return self._s[1905]! } + public var Notification_SecretChatScreenshot: String { return self._s[1906]! } + public var AccessDenied_Wallpapers: String { return self._s[1907]! } + public var Passport_Address_City: String { return self._s[1909]! } + public var InfoPlist_NSPhotoLibraryAddUsageDescription: String { return self._s[1910]! } + public var SocksProxySetup_SecretPlaceholder: String { return self._s[1911]! } + public var AccessDenied_LocationDisabled: String { return self._s[1912]! } + public var SocksProxySetup_HostnamePlaceholder: String { return self._s[1914]! } + public var GroupInfo_Sound: String { return self._s[1915]! } + public var Stickers_RemoveFromFavorites: String { return self._s[1916]! } + public var Contacts_Title: String { return self._s[1917]! } + public var Passport_Language_fr: String { return self._s[1918]! } + public var Notifications_ResetAllNotifications: String { return self._s[1919]! } + public var PrivacySettings_SecurityTitle: String { return self._s[1922]! } + public var Checkout_NewCard_Title: String { return self._s[1923]! } + public var Login_HaveNotReceivedCodeInternal: String { return self._s[1924]! } + public var Conversation_ForwardChats: String { return self._s[1925]! } + public var Settings_FAQ: String { return self._s[1928]! } + public var AutoDownloadSettings_DocumentsTitle: String { return self._s[1929]! } + public var Conversation_ContextMenuForward: String { return self._s[1930]! } + public var PrivacyPolicy_Title: String { return self._s[1935]! } + public var Notifications_TextTone: String { return self._s[1936]! } + public var Profile_CreateNewContact: String { return self._s[1937]! } + public var AutoNightTheme_AutomaticSection: String { return self._s[1939]! } + public var Channel_Username_InvalidCharacters: String { return self._s[1941]! } + public func Channel_AdminLog_MessageChangedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1942]!, self._r[1942]!, [_0]) + } + public var AutoDownloadSettings_AutodownloadFiles: String { return self._s[1943]! } + public var PrivacySettings_LastSeenTitle: String { return self._s[1944]! } + public var Channel_AdminLog_CanInviteUsers: String { return self._s[1945]! } + public var Conversation_MessageDeliveryFailed: String { return self._s[1946]! } + public var Watch_ChatList_NoConversationsText: String { return self._s[1947]! } + public var Bot_Unblock: String { return self._s[1948]! } + public var TextFormat_Italic: String { return self._s[1949]! } + public var WallpaperSearch_ColorPink: String { return self._s[1950]! } + public var Weekday_Wednesday: String { return self._s[1951]! } + public var Settings_About_Help: String { return self._s[1952]! } + public var SearchImages_Title: String { return self._s[1953]! } + public var Conversation_ClousStorageInfo_Description1: String { return self._s[1954]! } + public var ExplicitContent_AlertTitle: String { return self._s[1955]! } + public func Time_PreciseDate_m5(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1956]!, self._r[1956]!, [_1, _2, _3]) + } + public var Weekday_Thursday: String { return self._s[1957]! } + public var Channel_BanUser_PermissionChangeGroupInfo: String { return self._s[1958]! } + public var Channel_Members_AddMembersHelp: String { return self._s[1959]! } + public func Checkout_SavePasswordTimeout(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1960]!, self._r[1960]!, [_0]) + } + public var Passport_RequestedInformation: String { return self._s[1961]! } + public var Login_PhoneAndCountryHelp: String { return self._s[1962]! } + public var Conversation_EncryptionProcessing: String { return self._s[1964]! } + public var Notifications_PermissionsSuppressWarningTitle: String { return self._s[1965]! } + public var PhotoEditor_EnhanceTool: String { return self._s[1967]! } + public var Channel_Setup_Title: String { return self._s[1968]! } + public var Conversation_SearchPlaceholder: String { return self._s[1969]! } + public var AccessDenied_LocationAlwaysDenied: String { return self._s[1970]! } + public var Checkout_ErrorGeneric: String { return self._s[1971]! } + public var Passport_Language_hu: String { return self._s[1972]! } + public func Passport_Identity_UploadOneOfScan(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1974]!, self._r[1974]!, [_0]) + } + public func PUSH_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1977]!, self._r[1977]!, [_1]) + } + public var Conversation_CloudStorageInfo_Title: String { return self._s[1978]! } + public var PhotoEditor_CropAspectRatioSquare: String { return self._s[1979]! } + public func Notification_Exceptions_MutedUntil(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1980]!, self._r[1980]!, [_0]) + } + public var Conversation_ClearPrivateHistory: String { return self._s[1981]! } + public var ContactInfo_PhoneLabelHome: String { return self._s[1982]! } + public var PrivacySettings_LastSeenContacts: String { return self._s[1983]! } + public func ChangePhone_ErrorOccupied(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1984]!, self._r[1984]!, [_0]) + } + public var Passport_Language_cs: String { return self._s[1985]! } + public var Message_PinnedAnimationMessage: String { return self._s[1987]! } + public var Passport_Identity_ReverseSideHelp: String { return self._s[1989]! } + public var Embed_PlayingInPIP: String { return self._s[1991]! } + public var AutoNightTheme_ScheduleSection: String { return self._s[1992]! } + public func Call_EmojiDescription(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1993]!, self._r[1993]!, [_0]) + } + public var MediaPicker_LivePhotoDescription: String { return self._s[1994]! } + public func Channel_AdminLog_MessageRestrictedName(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1995]!, self._r[1995]!, [_1]) + } + public var Notification_PaymentSent: String { return self._s[1996]! } + public var PhotoEditor_CurvesGreen: String { return self._s[1997]! } + public var SaveIncomingPhotosSettings_Title: String { return self._s[1998]! } + public var NotificationSettings_ShowNotificationsAllAccounts: String { return self._s[1999]! } + public func PUSH_MESSAGE_SCREENSHOT(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2002]!, self._r[2002]!, [_1]) + } + public func PUSH_MESSAGE_PHOTO_SECRET(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2003]!, self._r[2003]!, [_1]) + } + public func ApplyLanguage_UnsufficientDataText(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2004]!, self._r[2004]!, [_1]) + } + public var NetworkUsageSettings_CallDataSection: String { return self._s[2006]! } + public var PasscodeSettings_HelpTop: String { return self._s[2007]! } + public var Passport_Address_TypeRentalAgreement: String { return self._s[2008]! } + public var ReportPeer_ReasonOther_Placeholder: String { return self._s[2009]! } + public var CheckoutInfo_ErrorPhoneInvalid: String { return self._s[2010]! } + public var Call_Accept: String { return self._s[2012]! } + public var GroupRemoved_RemoveInfo: String { return self._s[2013]! } + public var Month_GenMarch: String { return self._s[2015]! } + public var PhotoEditor_ShadowsTool: String { return self._s[2016]! } + public var LoginPassword_Title: String { return self._s[2017]! } + public var Watch_Conversation_GroupInfo: String { return self._s[2018]! } + public var CallSettings_Always: String { return self._s[2019]! } + public var CallFeedback_Success: String { return self._s[2020]! } + public var TwoStepAuth_SetupHint: String { return self._s[2021]! } + public var ConversationProfile_UsersTooMuchError: String { return self._s[2022]! } + public var Login_PhoneTitle: String { return self._s[2023]! } + public var Passport_FieldPhoneHelp: String { return self._s[2024]! } + public var Weekday_ShortSunday: String { return self._s[2025]! } + public var Passport_InfoFAQ_URL: String { return self._s[2026]! } + public var ContactInfo_Job: String { return self._s[2028]! } + public var UserInfo_InviteBotToGroup: String { return self._s[2029]! } + public var TwoStepAuth_PasswordRemovePassportConfirmation: String { return self._s[2030]! } + public var Passport_DeletePersonalDetailsConfirmation: String { return self._s[2031]! } + public var CallFeedback_ReasonNoise: String { return self._s[2032]! } + public var Passport_Identity_AddInternalPassport: String { return self._s[2034]! } + public var MediaPicker_AddCaption: String { return self._s[2035]! } + public var CallSettings_TabIconDescription: String { return self._s[2036]! } + public var Privacy_GroupsAndChannels_AlwaysAllow: String { return self._s[2037]! } + public var Passport_Identity_TypePersonalDetails: String { return self._s[2038]! } + public var DialogList_SearchSectionRecent: String { return self._s[2039]! } + public var PrivacyPolicy_DeclineMessage: String { return self._s[2040]! } + public var LogoutOptions_ClearCacheText: String { return self._s[2043]! } + public var LastSeen_WithinAWeek: String { return self._s[2044]! } + public var ChannelMembers_GroupAdminsTitle: String { return self._s[2045]! } + public var Conversation_CloudStorage_ChatStatus: String { return self._s[2047]! } + public var Passport_Address_TypeResidentialAddress: String { return self._s[2048]! } + public var Conversation_StatusLeftGroup: String { return self._s[2049]! } + public var SocksProxySetup_ProxyDetailsTitle: String { return self._s[2050]! } + public var GroupPermission_AddSuccess: String { return self._s[2052]! } + public var PhotoEditor_BlurToolRadial: String { return self._s[2054]! } + public var Conversation_ContextMenuCopy: String { return self._s[2055]! } + public var AccessDenied_CallMicrophone: String { return self._s[2056]! } + public func Time_PreciseDate_m2(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2057]!, self._r[2057]!, [_1, _2, _3]) + } + public var Login_InvalidFirstNameError: String { return self._s[2058]! } + public var Notifications_Badge_CountUnreadMessages_InfoOn: String { return self._s[2059]! } + public var Checkout_PaymentMethod_New: String { return self._s[2060]! } + public var ShareMenu_CopyShareLinkGame: String { return self._s[2061]! } + public var PhotoEditor_QualityTool: String { return self._s[2062]! } + public var Login_SendCodeViaSms: String { return self._s[2063]! } + public var Login_EmailNotConfiguredError: String { return self._s[2064]! } + public var SocksProxySetup_Status: String { return self._s[2065]! } + public var PrivacyPolicy_Accept: String { return self._s[2066]! } + public var Notifications_ExceptionsMessagePlaceholder: String { return self._s[2067]! } + public func PUSH_CHAT_MESSAGE_TEXT(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2068]!, self._r[2068]!, [_1, _2, _3]) + } + public var InfoPlist_NSLocationAlwaysUsageDescription: String { return self._s[2069]! } + public var AutoNightTheme_Automatic: String { return self._s[2070]! } + public var Channel_Username_InvalidStartsWithNumber: String { return self._s[2071]! } + public var Privacy_ContactsSyncHelp: String { return self._s[2072]! } + public var Cache_Help: String { return self._s[2073]! } + public var Passport_Language_fa: String { return self._s[2074]! } + public var Login_ResetAccountProtected_TimerTitle: String { return self._s[2075]! } + public var PrivacySettings_LastSeen: String { return self._s[2076]! } + public func DialogList_MultipleTyping(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2077]!, self._r[2077]!, [_0, _1]) + } + public var Preview_SaveGif: String { return self._s[2081]! } + public var Profile_About: String { return self._s[2082]! } + public var Channel_About_Placeholder: String { return self._s[2083]! } + public var Login_InfoTitle: String { return self._s[2084]! } + public func TwoStepAuth_SetupPendingEmail(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2085]!, self._r[2085]!, [_0]) + } + public var Watch_Suggestion_CantTalk: String { return self._s[2087]! } + public var ContactInfo_Title: String { return self._s[2088]! } + public var Media_ShareThisVideo: String { return self._s[2089]! } + public var Weekday_ShortFriday: String { return self._s[2090]! } + public var AccessDenied_Contacts: String { return self._s[2091]! } + public var Notification_CallIncomingShort: String { return self._s[2092]! } + public var Group_Setup_TypePublic: String { return self._s[2093]! } + public var Notifications_MessageNotificationsExceptions: String { return self._s[2094]! } + public var Notifications_Badge_IncludeChannels: String { return self._s[2095]! } + public var Notifications_MessageNotificationsPreview: String { return self._s[2098]! } + public var ConversationProfile_ErrorCreatingConversation: String { return self._s[2099]! } + public var Group_ErrorAddTooMuchBots: String { return self._s[2100]! } + public var Privacy_GroupsAndChannels_CustomShareHelp: String { return self._s[2101]! } + public var Permissions_CellularDataAllowInSettings_v0: String { return self._s[2102]! } + public var DialogList_Typing: String { return self._s[2103]! } + public var CallFeedback_IncludeLogs: String { return self._s[2105]! } + public var Checkout_Phone: String { return self._s[2107]! } + public var Login_InfoFirstNamePlaceholder: String { return self._s[2110]! } + public var Privacy_Calls_Integration: String { return self._s[2111]! } + public var Notifications_PermissionsAllow: String { return self._s[2112]! } + public var TwoStepAuth_AddHintDescription: String { return self._s[2116]! } + public var Settings_ChatSettings: String { return self._s[2117]! } + public func Channel_AdminLog_MessageInvitedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2118]!, self._r[2118]!, [_1, _2]) + } + public var GroupRemoved_DeleteUser: String { return self._s[2120]! } + public func Channel_AdminLog_PollStopped(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2121]!, self._r[2121]!, [_0]) + } + public func PUSH_MESSAGE_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2122]!, self._r[2122]!, [_1]) + } + public var Login_ContinueWithLocalization: String { return self._s[2123]! } + public var Watch_Message_ForwardedFrom: String { return self._s[2124]! } + public var TwoStepAuth_EnterEmailCode: String { return self._s[2126]! } + public var Conversation_Unblock: String { return self._s[2127]! } + public var PrivacySettings_DataSettings: String { return self._s[2128]! } + public var Notifications_InAppNotificationsVibrate: String { return self._s[2129]! } + public func Privacy_GroupsAndChannels_InviteToChannelError(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2130]!, self._r[2130]!, [_0, _1]) + } + public var PrivacySettings_Passcode: String { return self._s[2133]! } + public var Passport_Language_dz: String { return self._s[2134]! } + public var Passport_Language_tk: String { return self._s[2135]! } + public func Login_EmailCodeSubject(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2136]!, self._r[2136]!, [_0]) + } + public var InfoPlist_NSPhotoLibraryUsageDescription: String { return self._s[2137]! } + public var Conversation_ContextMenuReply: String { return self._s[2138]! } + public var WallpaperSearch_ColorBrown: String { return self._s[2139]! } + public var Tour_Title1: String { return self._s[2140]! } + public var Conversation_ClearGroupHistory: String { return self._s[2142]! } + public var WallpaperPreview_Motion: String { return self._s[2143]! } + public func Checkout_PasswordEntry_Text(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2144]!, self._r[2144]!, [_0]) + } + public var Call_RateCall: String { return self._s[2145]! } + public var Channel_AdminLog_BanSendStickersAndGifs: String { return self._s[2146]! } + public var Passport_PasswordCompleteSetup: String { return self._s[2147]! } + public var Conversation_InputTextSilentBroadcastPlaceholder: String { return self._s[2148]! } + public var UserInfo_LastNamePlaceholder: String { return self._s[2150]! } + public func Login_WillCallYou(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2152]!, self._r[2152]!, [_0]) + } + public var Compose_Create: String { return self._s[2153]! } + public var Contacts_InviteToTelegram: String { return self._s[2154]! } + public var GroupInfo_Notifications: String { return self._s[2155]! } + public var Message_PinnedLiveLocationMessage: String { return self._s[2157]! } + public var Month_GenApril: String { return self._s[2158]! } + public var Appearance_AutoNightTheme: String { return self._s[2159]! } + public var ChatSettings_AutomaticAudioDownload: String { return self._s[2161]! } + public var Login_CodeSentSms: String { return self._s[2163]! } + public func UserInfo_UnblockConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2164]!, self._r[2164]!, [_0]) + } + public var EmptyGroupInfo_Line3: String { return self._s[2165]! } + public var LogoutOptions_ContactSupportText: String { return self._s[2166]! } + public var Passport_Language_hr: String { return self._s[2167]! } + public func Channel_AdminLog_MessageRestrictedNewSetting(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2168]!, self._r[2168]!, [_0]) + } + public var GroupInfo_InviteLink_CopyLink: String { return self._s[2169]! } + public var Conversation_InputTextBroadcastPlaceholder: String { return self._s[2170]! } + public var Privacy_SecretChatsTitle: String { return self._s[2171]! } + public var Notification_SecretChatMessageScreenshotSelf: String { return self._s[2173]! } + public var GroupInfo_AddUserLeftError: String { return self._s[2174]! } + public var AutoDownloadSettings_TypePrivateChats: String { return self._s[2175]! } + public var LogoutOptions_ContactSupportTitle: String { return self._s[2176]! } + public var Preview_DeleteGif: String { return self._s[2177]! } + public var GroupInfo_Permissions_Exceptions: String { return self._s[2178]! } + public var Group_ErrorNotMutualContact: String { return self._s[2179]! } + public var Notification_MessageLifetime5s: String { return self._s[2180]! } + public func Watch_LastSeen_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2181]!, self._r[2181]!, [_0]) + } + public var Passport_Address_AddBankStatement: String { return self._s[2183]! } + public var Notification_CallIncoming: String { return self._s[2184]! } + public var Compose_NewGroupTitle: String { return self._s[2185]! } + public var TwoStepAuth_RecoveryCodeHelp: String { return self._s[2187]! } + public var Passport_Address_Postcode: String { return self._s[2189]! } + public func LastSeen_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2190]!, self._r[2190]!, [_0]) + } + public var Checkout_NewCard_SaveInfoHelp: String { return self._s[2191]! } + public var WallpaperColors_Title: String { return self._s[2192]! } + public var SocksProxySetup_ShareQRCodeInfo: String { return self._s[2193]! } + public var GroupPermission_Duration: String { return self._s[2194]! } + public func Cache_Clear(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2195]!, self._r[2195]!, [_0]) + } + public var Bot_GroupStatusDoesNotReadHistory: String { return self._s[2196]! } + public var Username_Placeholder: String { return self._s[2197]! } + public var CallFeedback_WhatWentWrong: String { return self._s[2198]! } + public var Passport_FieldAddressUploadHelp: String { return self._s[2199]! } + public var Permissions_NotificationsAllowInSettings_v0: String { return self._s[2200]! } + public var Passport_PasswordDescription: String { return self._s[2202]! } + public var Channel_MessagePhotoUpdated: String { return self._s[2203]! } + public var MediaPicker_TapToUngroupDescription: String { return self._s[2204]! } + public var AttachmentMenu_PhotoOrVideo: String { return self._s[2205]! } + public var Conversation_ContextMenuMore: String { return self._s[2206]! } + public var Privacy_PaymentsClearInfo: String { return self._s[2207]! } + public var CallSettings_TabIcon: String { return self._s[2208]! } + public var KeyCommand_Find: String { return self._s[2209]! } + public var Message_PinnedGame: String { return self._s[2210]! } + public var Notifications_Badge_CountUnreadMessages_InfoOff: String { return self._s[2212]! } + public var Login_CallRequestState2: String { return self._s[2214]! } + public var CheckoutInfo_ReceiverInfoNamePlaceholder: String { return self._s[2216]! } + public func Checkout_PayPrice(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2218]!, self._r[2218]!, [_0]) + } + public var WallpaperPreview_Blurred: String { return self._s[2219]! } + public var Conversation_InstantPagePreview: String { return self._s[2220]! } + public func DialogList_SingleUploadingVideoSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2221]!, self._r[2221]!, [_0]) + } + public var SecretTimer_VideoDescription: String { return self._s[2224]! } + public var WallpaperSearch_ColorRed: String { return self._s[2225]! } + public var GroupPermission_NoPinMessages: String { return self._s[2226]! } + public var Passport_Language_es: String { return self._s[2227]! } + public var Permissions_ContactsAllow_v0: String { return self._s[2229]! } + public var Conversation_EditingMessageMediaEditCurrentVideo: String { return self._s[2230]! } + public func PUSH_CHAT_MESSAGE_CONTACT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2231]!, self._r[2231]!, [_1, _2]) + } + public var Privacy_Forwards_CustomHelp: String { return self._s[2232]! } + public var WebPreview_GettingLinkInfo: String { return self._s[2233]! } + public var Watch_UserInfo_Unmute: String { return self._s[2234]! } + public var GroupInfo_ChannelListNamePlaceholder: String { return self._s[2235]! } + public var AccessDenied_CameraRestricted: String { return self._s[2237]! } + public func Conversation_Kilobytes(_ _0: Int) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2238]!, self._r[2238]!, ["\(_0)"]) + } + public var ChatList_ReadAll: String { return self._s[2240]! } + public var Settings_CopyUsername: String { return self._s[2241]! } + public var Contacts_SearchLabel: String { return self._s[2242]! } + public var Map_OpenInYandexNavigator: String { return self._s[2244]! } + public var PasscodeSettings_EncryptData: String { return self._s[2245]! } + public var WallpaperSearch_ColorPrefix: String { return self._s[2246]! } + public var Notifications_GroupNotificationsPreview: String { return self._s[2247]! } + public var DialogList_AdNoticeAlert: String { return self._s[2248]! } + public var CheckoutInfo_ShippingInfoAddress1: String { return self._s[2250]! } + public var CheckoutInfo_ShippingInfoAddress2: String { return self._s[2251]! } + public var Localization_LanguageCustom: String { return self._s[2252]! } + public var Passport_Identity_TypeDriversLicenseUploadScan: String { return self._s[2253]! } + public var CallFeedback_Title: String { return self._s[2254]! } + public var Passport_Address_OneOfTypePassportRegistration: String { return self._s[2257]! } + public var Conversation_InfoGroup: String { return self._s[2258]! } + public var Compose_NewMessage: String { return self._s[2259]! } + public var FastTwoStepSetup_HintPlaceholder: String { return self._s[2260]! } + public var ChatSettings_AutoDownloadVideoMessages: String { return self._s[2261]! } + public func Passport_Scans_ScanIndex(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2262]!, self._r[2262]!, [_0]) + } + public var Channel_AdminLog_CanDeleteMessages: String { return self._s[2263]! } + public var Login_CancelSignUpConfirmation: String { return self._s[2264]! } + public var ChangePhoneNumberCode_Help: String { return self._s[2265]! } + public var PrivacySettings_DeleteAccountHelp: String { return self._s[2266]! } + public var Channel_BlackList_Title: String { return self._s[2267]! } + public var UserInfo_PhoneCall: String { return self._s[2268]! } + public var Passport_Address_OneOfTypeBankStatement: String { return self._s[2270]! } + public var State_connecting: String { return self._s[2271]! } + public func DialogList_SingleRecordingAudioSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2272]!, self._r[2272]!, [_0]) + } + public var Notifications_GroupNotifications: String { return self._s[2273]! } + public var Passport_Identity_EditPassport: String { return self._s[2274]! } + public var EnterPasscode_RepeatNewPasscode: String { return self._s[2276]! } + public var Localization_EnglishLanguageName: String { return self._s[2277]! } + public var Share_AuthDescription: String { return self._s[2278]! } + public var Passport_Identity_Surname: String { return self._s[2279]! } + public var Compose_TokenListPlaceholder: String { return self._s[2280]! } + public var Passport_Identity_OneOfTypePassport: String { return self._s[2281]! } + public var Settings_AboutEmpty: String { return self._s[2282]! } + public var Conversation_Unmute: String { return self._s[2283]! } + public func PUSH_CONTACT_JOINED(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2285]!, self._r[2285]!, [_1]) + } + public var Login_CodeSentCall: String { return self._s[2286]! } + public var ContactInfo_PhoneLabelHomeFax: String { return self._s[2288]! } + public var ChatSettings_Appearance: String { return self._s[2289]! } + public var Appearance_PickAccentColor: String { return self._s[2290]! } + public func PUSH_CHAT_MESSAGE_NOTEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2291]!, self._r[2291]!, [_1, _2]) + } + public func PUSH_MESSAGE_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2292]!, self._r[2292]!, [_1]) + } + public var Notification_CallMissed: String { return self._s[2293]! } + public var Channel_AdminLogFilter_EventsInfo: String { return self._s[2294]! } + public var ChatAdmins_AdminLabel: String { return self._s[2296]! } + public var KeyCommand_JumpToNextChat: String { return self._s[2297]! } + public var Conversation_StopPollConfirmationTitle: String { return self._s[2299]! } + public var ChangePhoneNumberCode_CodePlaceholder: String { return self._s[2300]! } + public var Month_GenJune: String { return self._s[2301]! } + public var Watch_Location_Current: String { return self._s[2302]! } + public var Conversation_TitleMute: String { return self._s[2303]! } + public func PUSH_CHANNEL_MESSAGE_ROUND(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2304]!, self._r[2304]!, [_1]) + } + public var GroupInfo_DeleteAndExit: String { return self._s[2305]! } + public func Conversation_Moderate_DeleteAllMessages(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2306]!, self._r[2306]!, [_0]) + } + public var Call_ReportPlaceholder: String { return self._s[2307]! } + public var MaskStickerSettings_Info: String { return self._s[2308]! } + public func GroupInfo_AddParticipantConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2309]!, self._r[2309]!, [_0]) + } + public var Checkout_NewCard_PostcodeTitle: String { return self._s[2310]! } + public var Passport_Address_RegionPlaceholder: String { return self._s[2312]! } + public var Contacts_ShareTelegram: String { return self._s[2313]! } + public var EnterPasscode_EnterNewPasscodeNew: String { return self._s[2314]! } + public var Channel_ErrorAccessDenied: String { return self._s[2315]! } + public var Stickers_GroupChooseStickerPack: String { return self._s[2317]! } + public var Call_ConnectionErrorTitle: String { return self._s[2318]! } + public var UserInfo_NotificationsEnable: String { return self._s[2319]! } + public var Tour_Text4: String { return self._s[2322]! } + public var WallpaperSearch_Recent: String { return self._s[2323]! } + public var Profile_MessageLifetime2s: String { return self._s[2325]! } + public var Notification_MessageLifetime2s: String { return self._s[2326]! } + public func Time_PreciseDate_m10(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2327]!, self._r[2327]!, [_1, _2, _3]) + } + public var Cache_ClearCache: String { return self._s[2328]! } + public var AutoNightTheme_UpdateLocation: String { return self._s[2329]! } + public var Permissions_NotificationsUnreachableText_v0: String { return self._s[2330]! } + public func Channel_AdminLog_MessageChangedGroupUsername(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2334]!, self._r[2334]!, [_0]) + } + public var Channel_AdminLog_EmptyFilterTitle: String { return self._s[2336]! } + public var SocksProxySetup_TypeSocks: String { return self._s[2337]! } + public var AutoNightTheme_Title: String { return self._s[2338]! } + public var InstantPage_FeedbackButton: String { return self._s[2339]! } + public var Passport_FieldAddress: String { return self._s[2340]! } + public var Month_ShortMarch: String { return self._s[2341]! } + public func PUSH_MESSAGE_INVOICE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2342]!, self._r[2342]!, [_1, _2]) + } + public var SocksProxySetup_UsernamePlaceholder: String { return self._s[2343]! } + public var Conversation_ShareInlineBotLocationConfirmation: String { return self._s[2344]! } + public var Passport_FloodError: String { return self._s[2345]! } + public var SecretGif_Title: String { return self._s[2346]! } + public var NotificationSettings_ShowNotificationsAllAccountsInfoOn: String { return self._s[2347]! } + public var Passport_Language_th: String { return self._s[2349]! } + public var Passport_Address_Address: String { return self._s[2350]! } + public var Login_InvalidLastNameError: String { return self._s[2351]! } + public var Notifications_InAppNotificationsPreview: String { return self._s[2352]! } + public var Notifications_PermissionsUnreachableTitle: String { return self._s[2353]! } + public var SettingsSearch_FAQ: String { return self._s[2354]! } + public var ShareMenu_Send: String { return self._s[2355]! } + public var WallpaperSearch_ColorYellow: String { return self._s[2357]! } + public var Month_GenNovember: String { return self._s[2359]! } + public var Checkout_Email: String { return self._s[2361]! } + public var NotificationsSound_Tritone: String { return self._s[2362]! } + public var StickerPacksSettings_ManagingHelp: String { return self._s[2364]! } + public func PUSH_PINNED_ROUND(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2367]!, self._r[2367]!, [_1]) + } + public var ChangePhoneNumberNumber_Help: String { return self._s[2368]! } + public func Checkout_LiabilityAlert(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2369]!, self._r[2369]!, [_1, _1, _1, _2]) + } + public var DialogList_You: String { return self._s[2370]! } + public var MediaPicker_Send: String { return self._s[2373]! } + public var Call_AudioRouteSpeaker: String { return self._s[2374]! } + public var Watch_UserInfo_Title: String { return self._s[2375]! } + public var Appearance_AccentColor: String { return self._s[2376]! } + public func Login_EmailPhoneSubject(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2377]!, self._r[2377]!, [_0]) + } + public var Permissions_ContactsAllowInSettings_v0: String { return self._s[2378]! } + public func PUSH_CHANNEL_MESSAGE_GAME(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2379]!, self._r[2379]!, [_1, _2]) + } + public var Conversation_ClousStorageInfo_Description2: String { return self._s[2380]! } + public var WebSearch_RecentClearConfirmation: String { return self._s[2381]! } + public var Notification_CallOutgoing: String { return self._s[2382]! } + public var PrivacySettings_PasscodeAndFaceId: String { return self._s[2383]! } + public var Call_RecordingDisabledMessage: String { return self._s[2384]! } + public var Conversation_PressVolumeButtonForSound: String { return self._s[2385]! } + public var PrivacyLastSeenSettings_CustomHelp: String { return self._s[2386]! } + public var Channel_EditAdmin_PermissionAddAdmins: String { return self._s[2387]! } + public var Date_DialogDateFormat: String { return self._s[2388]! } + public var WallpaperColors_SetCustomColor: String { return self._s[2389]! } + public var Notifications_InAppNotifications: String { return self._s[2390]! } + public func Channel_Management_RemovedBy(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2391]!, self._r[2391]!, [_0]) + } + public func Settings_ApplyProxyAlert(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2392]!, self._r[2392]!, [_1, _2]) + } + public var NewContact_Title: String { return self._s[2393]! } + public func AutoDownloadSettings_UpToForAll(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2394]!, self._r[2394]!, [_0]) + } + public var Conversation_ViewContactDetails: String { return self._s[2395]! } + public func PUSH_CHANNEL_MESSAGE_CONTACT(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2397]!, self._r[2397]!, [_1]) + } + public var Checkout_NewCard_CardholderNameTitle: String { return self._s[2398]! } + public var Passport_Identity_ExpiryDateNone: String { return self._s[2399]! } + public var PrivacySettings_Title: String { return self._s[2400]! } + public var Conversation_SilentBroadcastTooltipOff: String { return self._s[2403]! } + public var GroupRemoved_UsersSectionTitle: String { return self._s[2404]! } + public var Contacts_PhoneNumber: String { return self._s[2405]! } + public var Map_ShowPlaces: String { return self._s[2407]! } + public var ChatAdmins_Title: String { return self._s[2408]! } + public var InstantPage_Reference: String { return self._s[2410]! } + public func PUSH_CHAT_MESSAGE_FWD(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2411]!, self._r[2411]!, [_1, _2]) + } + public var Camera_FlashOff: String { return self._s[2412]! } + public var Watch_UserInfo_Block: String { return self._s[2413]! } + public var ChatSettings_Stickers: String { return self._s[2414]! } + public var ChatSettings_DownloadInBackground: String { return self._s[2415]! } + public func UserInfo_BlockConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2416]!, self._r[2416]!, [_0]) + } + public var Settings_ViewPhoto: String { return self._s[2417]! } + public var Login_CheckOtherSessionMessages: String { return self._s[2418]! } + public var AutoDownloadSettings_Cellular: String { return self._s[2419]! } + public func Target_InviteToGroupConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2421]!, self._r[2421]!, [_0]) + } + public var Privacy_DeleteDrafts: String { return self._s[2422]! } + public var Wallpaper_SetCustomBackgroundInfo: String { return self._s[2423]! } + public func LastSeen_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2424]!, self._r[2424]!, [_0]) + } + public var DialogList_SavedMessagesHelp: String { return self._s[2425]! } + public var DialogList_SavedMessages: String { return self._s[2426]! } + public var GroupInfo_UpgradeButton: String { return self._s[2427]! } + public var DialogList_Pin: String { return self._s[2428]! } + public func ForwardedAuthors2(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2429]!, self._r[2429]!, [_0, _1]) + } + public func Login_PhoneGenericEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2430]!, self._r[2430]!, [_0]) + } + public var Notification_Exceptions_AlwaysOn: String { return self._s[2431]! } + public var UserInfo_NotificationsDisable: String { return self._s[2432]! } + public var Paint_Outlined: String { return self._s[2433]! } + public var Activity_PlayingGame: String { return self._s[2434]! } + public var SearchImages_NoImagesFound: String { return self._s[2435]! } + public var SocksProxySetup_ProxyType: String { return self._s[2436]! } + public var AppleWatch_ReplyPresetsHelp: String { return self._s[2438]! } + public var Conversation_ContextMenuCancelSending: String { return self._s[2439]! } + public var Settings_AppLanguage: String { return self._s[2440]! } + public var TwoStepAuth_ResetAccountHelp: String { return self._s[2441]! } + public var Common_ChoosePhoto: String { return self._s[2442]! } + public var CallFeedback_ReasonEcho: String { return self._s[2443]! } + public func PUSH_PINNED_AUDIO(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2444]!, self._r[2444]!, [_1]) + } + public var Privacy_Calls_AlwaysAllow: String { return self._s[2445]! } + public var Activity_UploadingVideo: String { return self._s[2446]! } + public var ChannelInfo_DeleteChannelConfirmation: String { return self._s[2447]! } + public var NetworkUsageSettings_Wifi: String { return self._s[2448]! } + public var Channel_BanUser_PermissionReadMessages: String { return self._s[2449]! } + public var Checkout_PayWithTouchId: String { return self._s[2450]! } + public var Wallpaper_ResetWallpapersConfirmation: String { return self._s[2451]! } + public func PUSH_LOCKED_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2453]!, self._r[2453]!, [_1]) + } + public var Notifications_ExceptionsNone: String { return self._s[2454]! } + public func Message_ForwardedMessageShort(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2455]!, self._r[2455]!, [_0]) + } + public func PUSH_PINNED_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2456]!, self._r[2456]!, [_1]) + } + public var AuthSessions_IncompleteAttempts: String { return self._s[2458]! } + public var Passport_Address_Region: String { return self._s[2461]! } + public var ChatList_DeleteChat: String { return self._s[2462]! } + public var LogoutOptions_ClearCacheTitle: String { return self._s[2463]! } + public var PhotoEditor_TiltShift: String { return self._s[2464]! } + public var Settings_FAQ_URL: String { return self._s[2465]! } + public var Passport_Language_sl: String { return self._s[2466]! } + public var Settings_PrivacySettings: String { return self._s[2468]! } + public var SharedMedia_TitleLink: String { return self._s[2469]! } + public var Passport_Identity_TypePassportUploadScan: String { return self._s[2470]! } + public var Settings_SetProfilePhoto: String { return self._s[2471]! } + public var Channel_About_Help: String { return self._s[2472]! } + public var Contacts_PermissionsEnable: String { return self._s[2473]! } + public var AttachmentMenu_SendAsFiles: String { return self._s[2474]! } + public var CallFeedback_ReasonInterruption: String { return self._s[2476]! } + public var Passport_Address_AddTemporaryRegistration: String { return self._s[2477]! } + public var AutoDownloadSettings_AutodownloadVideos: String { return self._s[2478]! } + public var ChatSettings_AutoDownloadSettings_Delimeter: String { return self._s[2479]! } + public var PrivacySettings_DeleteAccountTitle: String { return self._s[2480]! } + public var AccessDenied_VideoMessageCamera: String { return self._s[2482]! } + public var Map_OpenInYandexMaps: String { return self._s[2484]! } + public var PhotoEditor_SaturationTool: String { return self._s[2485]! } + public func PUSH_MESSAGE_STICKER(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2486]!, self._r[2486]!, [_1, _2]) + } + public var Notification_Exceptions_NewException_NotificationHeader: String { return self._s[2487]! } + public var Appearance_TextSize: String { return self._s[2488]! } + public func LOCAL_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2489]!, self._r[2489]!, [_1, "\(_2)"]) + } + public var Channel_Username_InvalidTooShort: String { return self._s[2491]! } + public func PUSH_CHAT_MESSAGE_GAME(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2492]!, self._r[2492]!, [_1, _2, _3]) + } + public var Passport_PassportInformation: String { return self._s[2495]! } + public var WatchRemote_AlertTitle: String { return self._s[2496]! } + public var Privacy_GroupsAndChannels_NeverAllow: String { return self._s[2497]! } + public var ConvertToSupergroup_HelpText: String { return self._s[2499]! } + public func Time_MonthOfYear_m7(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2500]!, self._r[2500]!, [_0]) + } + public func PUSH_PHONE_CALL_REQUEST(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2501]!, self._r[2501]!, [_1]) + } + public var Privacy_GroupsAndChannels_CustomHelp: String { return self._s[2502]! } + public var TwoStepAuth_RecoveryCodeInvalid: String { return self._s[2504]! } + public var AccessDenied_CameraDisabled: String { return self._s[2505]! } + public func Channel_Username_UsernameIsAvailable(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2506]!, self._r[2506]!, [_0]) + } + public var PhotoEditor_ContrastTool: String { return self._s[2509]! } + public func PUSH_PINNED_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2510]!, self._r[2510]!, [_1]) + } + public var DialogList_Draft: String { return self._s[2511]! } + public var Privacy_TopPeersDelete: String { return self._s[2513]! } + public var LoginPassword_PasswordPlaceholder: String { return self._s[2514]! } + public var Passport_Identity_TypeIdentityCardUploadScan: String { return self._s[2515]! } + public var WebSearch_RecentSectionClear: String { return self._s[2516]! } + public var Watch_ChatList_NoConversationsTitle: String { return self._s[2518]! } + public var Common_Done: String { return self._s[2520]! } + public var AuthSessions_EmptyText: String { return self._s[2521]! } + public var Conversation_ShareBotContactConfirmation: String { return self._s[2522]! } + public var Tour_Title5: String { return self._s[2523]! } + public func Map_DirectionsDriveEta(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2524]!, self._r[2524]!, [_0]) + } + public var ApplyLanguage_UnsufficientDataTitle: String { return self._s[2525]! } + public var Conversation_LinkDialogSave: String { return self._s[2526]! } + public var GroupInfo_ActionRestrict: String { return self._s[2527]! } + public var Checkout_Title: String { return self._s[2528]! } + public var Channel_AdminLog_CanChangeInfo: String { return self._s[2531]! } + public var Notification_RenamedGroup: String { return self._s[2532]! } + public var Checkout_PayWithFaceId: String { return self._s[2533]! } + public var Channel_BanList_BlockedTitle: String { return self._s[2534]! } + public var Checkout_WebConfirmation_Title: String { return self._s[2536]! } + public var Notifications_MessageNotificationsAlert: String { return self._s[2537]! } + public var Profile_AddToExisting: String { return self._s[2539]! } + public func Profile_CreateEncryptedChatOutdatedError(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2540]!, self._r[2540]!, [_0, _1]) + } + public var Cache_Files: String { return self._s[2542]! } + public var Permissions_PrivacyPolicy: String { return self._s[2543]! } + public var SocksProxySetup_ConnectAndSave: String { return self._s[2544]! } + public var UserInfo_NotificationsDefaultDisabled: String { return self._s[2545]! } + public var AutoDownloadSettings_TypeContacts: String { return self._s[2547]! } + public var Calls_NoCallsPlaceholder: String { return self._s[2549]! } + public var Channel_Username_RevokeExistingUsernamesInfo: String { return self._s[2550]! } + public var Notifications_ExceptionsGroupPlaceholder: String { return self._s[2552]! } + public func PUSH_CHAT_MESSAGE_INVOICE(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2553]!, self._r[2553]!, [_1, _2, _3]) + } + public var Passport_FieldAddressHelp: String { return self._s[2554]! } + public var Privacy_GroupsAndChannels_InviteToChannelMultipleError: String { return self._s[2555]! } + public func Login_TermsOfService_ProceedBot(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2556]!, self._r[2556]!, [_0]) + } + public var Channel_AdminLog_EmptyTitle: String { return self._s[2557]! } + public var Privacy_Calls_NeverAllow_Title: String { return self._s[2559]! } + public var Login_UnknownError: String { return self._s[2560]! } + public var Group_UpgradeNoticeText2: String { return self._s[2562]! } + public var Watch_Compose_AddContact: String { return self._s[2563]! } + public var Web_Error: String { return self._s[2564]! } + public var Gif_Search: String { return self._s[2565]! } + public var Profile_MessageLifetime1h: String { return self._s[2566]! } + public var CheckoutInfo_ReceiverInfoEmailPlaceholder: String { return self._s[2567]! } + public var Channel_Username_CheckingUsername: String { return self._s[2568]! } + public var CallFeedback_ReasonSilentRemote: String { return self._s[2569]! } + public var AutoDownloadSettings_TypeChannels: String { return self._s[2570]! } + public var Channel_AboutItem: String { return self._s[2571]! } + public var Privacy_GroupsAndChannels_AlwaysAllow_Placeholder: String { return self._s[2573]! } + public var GroupInfo_SharedMedia: String { return self._s[2574]! } + public func Channel_AdminLog_MessagePromotedName(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2575]!, self._r[2575]!, [_1]) + } + public var Call_PhoneCallInProgressMessage: String { return self._s[2576]! } + public var GroupInfo_InviteLink_RevokeAlert_Text: String { return self._s[2577]! } + public var Conversation_SearchByName_Placeholder: String { return self._s[2578]! } + public var CreatePoll_AddOption: String { return self._s[2579]! } + public var GroupInfo_Permissions_SearchPlaceholder: String { return self._s[2580]! } + public var Group_UpgradeNoticeHeader: String { return self._s[2581]! } + public var Channel_Management_AddModerator: String { return self._s[2582]! } + public var AutoDownloadSettings_MaxFileSize: String { return self._s[2583]! } + public var StickerPacksSettings_ShowStickersButton: String { return self._s[2584]! } + public var NotificationsSound_Hello: String { return self._s[2585]! } + public var SocksProxySetup_SavedProxies: String { return self._s[2586]! } + public var Channel_Stickers_Placeholder: String { return self._s[2588]! } + public func Login_EmailCodeBody(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2589]!, self._r[2589]!, [_0]) + } + public var PrivacyPolicy_DeclineDeclineAndDelete: String { return self._s[2590]! } + public var Channel_Management_AddModeratorHelp: String { return self._s[2591]! } + public var ContactInfo_BirthdayLabel: String { return self._s[2592]! } + public var ChangePhoneNumberCode_RequestingACall: String { return self._s[2593]! } + public var AutoDownloadSettings_Channels: String { return self._s[2594]! } + public var Passport_Language_mn: String { return self._s[2595]! } + public var Notifications_ResetAllNotificationsHelp: String { return self._s[2598]! } + public var Passport_Language_ja: String { return self._s[2600]! } + public var Settings_About_Title: String { return self._s[2601]! } + public var Settings_NotificationsAndSounds: String { return self._s[2602]! } + public var ChannelInfo_DeleteGroup: String { return self._s[2603]! } + public var Settings_BlockedUsers: String { return self._s[2604]! } + public func Time_MonthOfYear_m4(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2605]!, self._r[2605]!, [_0]) + } + public var AutoDownloadSettings_PreloadVideo: String { return self._s[2606]! } + public var Passport_Address_AddResidentialAddress: String { return self._s[2607]! } + public var Channel_Username_Title: String { return self._s[2608]! } + public func Notification_RemovedGroupPhoto(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2609]!, self._r[2609]!, [_0]) + } + public var AttachmentMenu_File: String { return self._s[2611]! } + public var AppleWatch_Title: String { return self._s[2612]! } + public var Activity_RecordingVideoMessage: String { return self._s[2613]! } + public var Weekday_Saturday: String { return self._s[2614]! } + public var WallpaperPreview_SwipeColorsTopText: String { return self._s[2615]! } + public var Profile_CreateEncryptedChatError: String { return self._s[2616]! } + public var Common_Next: String { return self._s[2618]! } + public var Channel_Stickers_YourStickers: String { return self._s[2620]! } + public var Call_AudioRouteHeadphones: String { return self._s[2621]! } + public var TwoStepAuth_EnterPasswordForgot: String { return self._s[2623]! } + public var Watch_Contacts_NoResults: String { return self._s[2625]! } + public var PhotoEditor_TintTool: String { return self._s[2628]! } + public var LoginPassword_ResetAccount: String { return self._s[2630]! } + public var Settings_SavedMessages: String { return self._s[2631]! } + public var Bot_GenericSupportStatus: String { return self._s[2632]! } + public var StickerPack_Add: String { return self._s[2633]! } + public var Checkout_TotalAmount: String { return self._s[2634]! } + public var Your_cards_number_is_invalid: String { return self._s[2635]! } + public func ChangePhoneNumberCode_CallTimer(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2636]!, self._r[2636]!, [_0]) + } + public func GroupPermission_AddedInfo(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2637]!, self._r[2637]!, [_1, _2]) + } + public var ChatSettings_ConnectionType_UseSocks5: String { return self._s[2638]! } + public func PUSH_CHAT_PHOTO_EDITED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2640]!, self._r[2640]!, [_1, _2]) + } + public func Conversation_RestrictedTextTimed(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2641]!, self._r[2641]!, [_0]) + } + public var GroupInfo_InviteLink_ShareLink: String { return self._s[2642]! } + public var StickerPack_Share: String { return self._s[2643]! } + public var Passport_DeleteAddress: String { return self._s[2644]! } + public var Settings_Passport: String { return self._s[2645]! } + public var SharedMedia_EmptyFilesText: String { return self._s[2646]! } + public var Conversation_DeleteMessagesForMe: String { return self._s[2647]! } + public var PasscodeSettings_AutoLock_IfAwayFor_1hour: String { return self._s[2648]! } + public var Contacts_PermissionsText: String { return self._s[2649]! } + public var Group_Setup_HistoryVisible: String { return self._s[2650]! } + public var Passport_Address_AddRentalAgreement: String { return self._s[2652]! } + public var SocksProxySetup_Title: String { return self._s[2653]! } + public var Notification_Mute1h: String { return self._s[2654]! } + public func Passport_Email_CodeHelp(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2655]!, self._r[2655]!, [_0]) + } + public var NotificationSettings_ShowNotificationsAllAccountsInfoOff: String { return self._s[2656]! } + public func PUSH_PINNED_GEOLIVE(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2657]!, self._r[2657]!, [_1]) + } + public var FastTwoStepSetup_PasswordSection: String { return self._s[2658]! } + public var NetworkUsageSettings_ResetStatsConfirmation: String { return self._s[2661]! } + public var InfoPlist_NSFaceIDUsageDescription: String { return self._s[2663]! } + public var DialogList_NoMessagesText: String { return self._s[2664]! } + public var Privacy_ContactsResetConfirmation: String { return self._s[2665]! } + public var Privacy_Calls_P2PHelp: String { return self._s[2666]! } + public var Your_cards_expiration_year_is_invalid: String { return self._s[2668]! } + public var Common_TakePhotoOrVideo: String { return self._s[2669]! } + public var Call_StatusBusy: String { return self._s[2670]! } + public var Conversation_PinnedMessage: String { return self._s[2671]! } + public var AutoDownloadSettings_VoiceMessagesTitle: String { return self._s[2672]! } + public var TwoStepAuth_SetupPasswordConfirmFailed: String { return self._s[2673]! } + public var AppleWatch_ReplyPresets: String { return self._s[2674]! } + public var Passport_DiscardMessageDescription: String { return self._s[2676]! } + public var Login_NetworkError: String { return self._s[2677]! } + public func Notification_PinnedRoundMessage(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2678]!, self._r[2678]!, [_0]) + } + public func Channel_AdminLog_MessageRemovedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2679]!, self._r[2679]!, [_0]) + } + public var SocksProxySetup_PasswordPlaceholder: String { return self._s[2680]! } + public var Login_ResetAccountProtected_LimitExceeded: String { return self._s[2682]! } + public func Watch_LastSeen_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2684]!, self._r[2684]!, [_0]) + } + public var Call_ConnectionErrorMessage: String { return self._s[2685]! } + public var Compose_GroupTokenListPlaceholder: String { return self._s[2687]! } + public var ConversationMedia_Title: String { return self._s[2688]! } + public var EncryptionKey_Title: String { return self._s[2690]! } + public var TwoStepAuth_EnterPasswordTitle: String { return self._s[2691]! } + public var Notification_Exceptions_AddException: String { return self._s[2692]! } + public var Profile_MessageLifetime1m: String { return self._s[2693]! } + public func Channel_AdminLog_MessageUnkickedName(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2694]!, self._r[2694]!, [_1]) + } + public var Month_GenMay: String { return self._s[2695]! } + public func LiveLocationUpdated_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2696]!, self._r[2696]!, [_0]) + } + public var ChannelMembers_WhoCanAddMembersAllHelp: String { return self._s[2697]! } + public var AutoDownloadSettings_ResetSettings: String { return self._s[2698]! } + public var Conversation_EmptyPlaceholder: String { return self._s[2700]! } + public var Passport_Address_AddPassportRegistration: String { return self._s[2701]! } + public var Notifications_ChannelNotificationsAlert: String { return self._s[2702]! } + public var ChatSettings_AutoDownloadUsingCellular: String { return self._s[2703]! } + public var Camera_TapAndHoldForVideo: String { return self._s[2704]! } + public var Channel_JoinChannel: String { return self._s[2706]! } + public var Appearance_Animations: String { return self._s[2709]! } + public func Notification_MessageLifetimeChanged(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2710]!, self._r[2710]!, [_1, _2]) + } + public var Stickers_GroupStickers: String { return self._s[2712]! } + public var ConvertToSupergroup_HelpTitle: String { return self._s[2714]! } + public var Passport_Address_Street: String { return self._s[2715]! } + public var Conversation_AddContact: String { return self._s[2716]! } + public var Login_PhonePlaceholder: String { return self._s[2717]! } + public var Channel_Members_InviteLink: String { return self._s[2719]! } + public var Bot_Stop: String { return self._s[2720]! } + public var Notification_PassportValueAddress: String { return self._s[2722]! } + public var Month_ShortJuly: String { return self._s[2723]! } + public var Passport_Address_TypeTemporaryRegistrationUploadScan: String { return self._s[2724]! } + public var Channel_AdminLog_BanSendMedia: String { return self._s[2725]! } + public var Passport_Identity_ReverseSide: String { return self._s[2726]! } + public var Watch_Stickers_Recents: String { return self._s[2729]! } + public var PrivacyLastSeenSettings_EmpryUsersPlaceholder: String { return self._s[2731]! } + public var Map_SendThisLocation: String { return self._s[2732]! } + public func Time_MonthOfYear_m1(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2733]!, self._r[2733]!, [_0]) + } + public func InviteText_SingleContact(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2734]!, self._r[2734]!, [_0]) + } + public var ConvertToSupergroup_Note: String { return self._s[2735]! } + public func FileSize_MB(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2736]!, self._r[2736]!, [_0]) + } + public var NetworkUsageSettings_GeneralDataSection: String { return self._s[2737]! } + public func Compatibility_SecretMediaVersionTooLow(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2738]!, self._r[2738]!, [_0, _1]) + } + public var Login_CallRequestState3: String { return self._s[2740]! } + public var Wallpaper_SearchShort: String { return self._s[2741]! } + public var PasscodeSettings_UnlockWithFaceId: String { return self._s[2743]! } + public func PUSH_CHAT_MESSAGE_GEOLIVE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2744]!, self._r[2744]!, [_1, _2]) + } + public var Channel_AdminLogFilter_Title: String { return self._s[2745]! } + public var Notifications_GroupNotificationsExceptions: String { return self._s[2749]! } + public func FileSize_B(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2750]!, self._r[2750]!, [_0]) + } + public var Passport_CorrectErrors: String { return self._s[2751]! } + public func Channel_MessageTitleUpdated(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2752]!, self._r[2752]!, [_0]) + } + public var Map_SendMyCurrentLocation: String { return self._s[2753]! } + public func PUSH_PINNED_CONTACT(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2754]!, self._r[2754]!, [_1]) + } + public var SharedMedia_SearchNoResults: String { return self._s[2755]! } + public var Permissions_NotificationsText_v0: String { return self._s[2756]! } + public var LoginPassword_FloodError: String { return self._s[2757]! } + public var Group_Setup_HistoryHiddenHelp: String { return self._s[2759]! } + public func TwoStepAuth_PendingEmailHelp(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2760]!, self._r[2760]!, [_0]) + } + public var Passport_Language_bn: String { return self._s[2761]! } + public func DialogList_SingleUploadingPhotoSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2762]!, self._r[2762]!, [_0]) + } + public func Notification_PinnedAudioMessage(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2763]!, self._r[2763]!, [_0]) + } + public func Channel_AdminLog_MessageChangedGroupStickerPack(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2764]!, self._r[2764]!, [_0]) + } + public var GroupInfo_InvitationLinkGroupFull: String { return self._s[2767]! } + public var Group_EditAdmin_PermissionChangeInfo: String { return self._s[2769]! } + public var Contacts_PermissionsAllow: String { return self._s[2770]! } + public var ReportPeer_ReasonCopyright: String { return self._s[2771]! } + public var Channel_EditAdmin_PermissinAddAdminOn: String { return self._s[2772]! } + public var WallpaperPreview_Pattern: String { return self._s[2773]! } + public var Paint_Duplicate: String { return self._s[2774]! } + public var Passport_Address_Country: String { return self._s[2775]! } + public var Notification_RenamedChannel: String { return self._s[2777]! } + public var CheckoutInfo_ErrorPostcodeInvalid: String { return self._s[2778]! } + public var Group_MessagePhotoUpdated: String { return self._s[2779]! } + public var Channel_BanUser_PermissionSendMedia: String { return self._s[2780]! } + public var Conversation_ContextMenuBan: String { return self._s[2781]! } + public var TwoStepAuth_EmailSent: String { return self._s[2782]! } + public var MessagePoll_NoVotes: String { return self._s[2783]! } + public var Passport_Language_is: String { return self._s[2784]! } + public var Tour_Text5: String { return self._s[2786]! } + public func Call_GroupFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2788]!, self._r[2788]!, [_1, _2]) + } + public var Undo_SecretChatDeleted: String { return self._s[2789]! } + public var SocksProxySetup_ShareQRCode: String { return self._s[2790]! } + public var LogoutOptions_ChangePhoneNumberText: String { return self._s[2791]! } + public var Paint_Edit: String { return self._s[2793]! } + public var Undo_DeletedGroup: String { return self._s[2796]! } + public var LoginPassword_ForgotPassword: String { return self._s[2797]! } + public var GroupInfo_GroupNamePlaceholder: String { return self._s[2798]! } + public func Notification_Kicked(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2799]!, self._r[2799]!, [_0, _1]) + } + public var Conversation_InputTextCaptionPlaceholder: String { return self._s[2800]! } + public var AutoDownloadSettings_VideoMessagesTitle: String { return self._s[2801]! } + public var Passport_Language_uz: String { return self._s[2802]! } + public var Conversation_PinMessageAlertGroup: String { return self._s[2803]! } + public var Map_StopLiveLocation: String { return self._s[2805]! } + public var PasscodeSettings_Help: String { return self._s[2807]! } + public var NotificationsSound_Input: String { return self._s[2808]! } + public var Share_Title: String { return self._s[2811]! } + public var LogoutOptions_Title: String { return self._s[2812]! } + public var Login_TermsOfServiceAgree: String { return self._s[2813]! } + public var Compose_NewEncryptedChatTitle: String { return self._s[2814]! } + public var Channel_AdminLog_TitleSelectedEvents: String { return self._s[2815]! } + public var Channel_EditAdmin_PermissionEditMessages: String { return self._s[2816]! } + public var EnterPasscode_EnterTitle: String { return self._s[2817]! } + public func Call_PrivacyErrorMessage(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2818]!, self._r[2818]!, [_0]) + } + public var Settings_CopyPhoneNumber: String { return self._s[2819]! } + public var NotificationsSound_Keys: String { return self._s[2820]! } + public func Call_ParticipantVersionOutdatedError(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2821]!, self._r[2821]!, [_0]) + } + public var Notification_MessageLifetime1w: String { return self._s[2822]! } + public var Message_Video: String { return self._s[2823]! } + public var AutoDownloadSettings_CellularTitle: String { return self._s[2824]! } + public func PUSH_CHANNEL_MESSAGE_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2825]!, self._r[2825]!, [_1]) + } + public func Notification_JoinedChat(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2828]!, self._r[2828]!, [_0]) + } + public func PrivacySettings_LastSeenContactsPlus(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2829]!, self._r[2829]!, [_0]) + } + public var Passport_Language_mk: String { return self._s[2830]! } + public var CreatePoll_CancelConfirmation: String { return self._s[2831]! } + public var Conversation_SilentBroadcastTooltipOn: String { return self._s[2833]! } + public var PrivacyPolicy_Decline: String { return self._s[2834]! } + public var Passport_Identity_DoesNotExpire: String { return self._s[2835]! } + public var Channel_AdminLogFilter_EventsRestrictions: String { return self._s[2836]! } + public var Permissions_SiriAllow_v0: String { return self._s[2838]! } + public func LOCAL_CHAT_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2839]!, self._r[2839]!, [_1, "\(_2)"]) + } + public func Notification_RenamedChat(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2840]!, self._r[2840]!, [_0]) + } + public var Paint_Regular: String { return self._s[2841]! } + public var ChatSettings_AutoDownloadReset: String { return self._s[2842]! } + public var SocksProxySetup_ShareLink: String { return self._s[2843]! } + public var BlockedUsers_SelectUserTitle: String { return self._s[2844]! } + public var GroupInfo_InviteByLink: String { return self._s[2846]! } + public var MessageTimer_Custom: String { return self._s[2847]! } + public var UserInfo_NotificationsDefaultEnabled: String { return self._s[2848]! } + public var Passport_Address_TypeTemporaryRegistration: String { return self._s[2850]! } + public var ChatSettings_AutoDownloadUsingWiFi: String { return self._s[2851]! } + public var Channel_Username_InvalidTaken: String { return self._s[2852]! } + public var Conversation_ClousStorageInfo_Description3: String { return self._s[2853]! } + public var Settings_ChatBackground: String { return self._s[2854]! } + public var Channel_Subscribers_Title: String { return self._s[2855]! } + public var ApplyLanguage_ChangeLanguageTitle: String { return self._s[2856]! } + public var Watch_ConnectionDescription: String { return self._s[2857]! } + public var Wallpaper_ResetWallpapers: String { return self._s[2861]! } + public var EditProfile_Title: String { return self._s[2862]! } + public var NotificationsSound_Bamboo: String { return self._s[2864]! } + public var Channel_AdminLog_MessagePreviousMessage: String { return self._s[2866]! } + public var Login_SmsRequestState2: String { return self._s[2867]! } + public var Passport_Language_ar: String { return self._s[2868]! } + public var Conversation_MessageDialogEdit: String { return self._s[2869]! } + public func PUSH_AUTH_UNKNOWN(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2870]!, self._r[2870]!, [_1]) + } + public var Common_Close: String { return self._s[2871]! } + public func Channel_AdminLog_MessageToggleInvitesOff(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2875]!, self._r[2875]!, [_0]) + } + public var UserInfo_About_Placeholder: String { return self._s[2876]! } + public func Conversation_FileHowToText(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2877]!, self._r[2877]!, [_0]) + } + public var GroupInfo_Permissions_SectionTitle: String { return self._s[2878]! } + public var Channel_Info_Banned: String { return self._s[2880]! } + public func Time_MonthOfYear_m11(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2881]!, self._r[2881]!, [_0]) + } + public var Passport_Language_my: String { return self._s[2882]! } + public var Group_Setup_BasicHistoryHiddenHelp: String { return self._s[2883]! } + public func Time_PreciseDate_m9(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2884]!, self._r[2884]!, [_1, _2, _3]) + } + public var Preview_CopyAddress: String { return self._s[2885]! } + public func DialogList_SinglePlayingGameSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2886]!, self._r[2886]!, [_0]) + } + public var KeyCommand_JumpToPreviousChat: String { return self._s[2887]! } + public var UserInfo_BotSettings: String { return self._s[2888]! } + public var LiveLocation_MenuStopAll: String { return self._s[2890]! } + public var Passport_PasswordCreate: String { return self._s[2891]! } + public var StickerSettings_MaskContextInfo: String { return self._s[2892]! } + public var Message_PinnedLocationMessage: String { return self._s[2893]! } + public var Map_Satellite: String { return self._s[2894]! } + public var Watch_Message_Unsupported: String { return self._s[2895]! } + public var Username_TooManyPublicUsernamesError: String { return self._s[2896]! } + public var TwoStepAuth_EnterPasswordInvalid: String { return self._s[2897]! } + public func Notification_PinnedTextMessage(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2898]!, self._r[2898]!, [_0, _1]) + } + public var Notifications_ChannelNotificationsHelp: String { return self._s[2899]! } + public var Privacy_Calls_P2PContacts: String { return self._s[2900]! } + public var NotificationsSound_None: String { return self._s[2901]! } + public var AccessDenied_VoiceMicrophone: String { return self._s[2903]! } + public func ApplyLanguage_ChangeLanguageAlreadyActive(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2904]!, self._r[2904]!, [_1]) + } + public var Cache_Indexing: String { return self._s[2905]! } + public var DialogList_RecentTitlePeople: String { return self._s[2907]! } + public var DialogList_EncryptionRejected: String { return self._s[2908]! } + public var GroupInfo_Administrators: String { return self._s[2909]! } + public var Passport_ScanPassportHelp: String { return self._s[2910]! } + public var Application_Name: String { return self._s[2911]! } + public var Channel_AdminLogFilter_ChannelEventsInfo: String { return self._s[2912]! } + public var Passport_Identity_TranslationHelp: String { return self._s[2914]! } + public func Notification_JoinedGroupByLink(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2915]!, self._r[2915]!, [_0]) + } + public func DialogList_EncryptedChatStartedOutgoing(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2916]!, self._r[2916]!, [_0]) + } + public var Channel_EditAdmin_PermissionDeleteMessages: String { return self._s[2917]! } + public var Privacy_ChatsTitle: String { return self._s[2918]! } + public var DialogList_ClearHistoryConfirmation: String { return self._s[2919]! } + public var Watch_Suggestion_HoldOn: String { return self._s[2920]! } + public var SocksProxySetup_RequiredCredentials: String { return self._s[2921]! } + public var Passport_Address_TypeRentalAgreementUploadScan: String { return self._s[2922]! } + public var TwoStepAuth_EmailSkipAlert: String { return self._s[2923]! } + public var Channel_Setup_TypePublic: String { return self._s[2926]! } + public func Channel_AdminLog_MessageToggleInvitesOn(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2927]!, self._r[2927]!, [_0]) + } + public var Channel_TypeSetup_Title: String { return self._s[2929]! } + public var Map_OpenInMaps: String { return self._s[2931]! } + public func PUSH_PINNED_NOTEXT(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2932]!, self._r[2932]!, [_1]) + } + public var NotificationsSound_Tremolo: String { return self._s[2934]! } + public func Date_ChatDateHeaderYear(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2935]!, self._r[2935]!, [_1, _2, _3]) + } + public var ConversationProfile_UnknownAddMemberError: String { return self._s[2936]! } + public var Passport_PasswordHelp: String { return self._s[2937]! } + public var Login_CodeExpiredError: String { return self._s[2938]! } + public var Channel_EditAdmin_PermissionChangeInfo: String { return self._s[2939]! } + public var Conversation_TitleUnmute: String { return self._s[2940]! } + public var Passport_Identity_ScansHelp: String { return self._s[2941]! } + public var Passport_Language_lo: String { return self._s[2942]! } + public var Camera_FlashAuto: String { return self._s[2943]! } + public var Common_Cancel: String { return self._s[2944]! } + public var DialogList_SavedMessagesTooltip: String { return self._s[2945]! } + public var TwoStepAuth_SetupPasswordTitle: String { return self._s[2946]! } + public func PUSH_MESSAGE_FWD(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2947]!, self._r[2947]!, [_1]) + } + public var Conversation_ReportSpamConfirmation: String { return self._s[2948]! } + public var ChatSettings_Title: String { return self._s[2950]! } + public var Passport_PasswordReset: String { return self._s[2951]! } + public var SocksProxySetup_TypeNone: String { return self._s[2952]! } + public var PhoneNumberHelp_Help: String { return self._s[2954]! } + public var Checkout_EnterPassword: String { return self._s[2955]! } + public var Share_AuthTitle: String { return self._s[2957]! } + public var Activity_UploadingDocument: String { return self._s[2958]! } + public var State_Connecting: String { return self._s[2959]! } + public var Profile_MessageLifetime1w: String { return self._s[2960]! } + public var Conversation_ContextMenuReport: String { return self._s[2961]! } + public var CheckoutInfo_ReceiverInfoPhone: String { return self._s[2962]! } + public var AutoNightTheme_ScheduledTo: String { return self._s[2963]! } + public var AuthSessions_Terminate: String { return self._s[2964]! } + public var Checkout_NewCard_CardholderNamePlaceholder: String { return self._s[2965]! } + public var KeyCommand_JumpToPreviousUnreadChat: String { return self._s[2966]! } + public var PhotoEditor_Set: String { return self._s[2967]! } + public var EmptyGroupInfo_Title: String { return self._s[2968]! } + public var Login_PadPhoneHelp: String { return self._s[2969]! } + public var AutoDownloadSettings_TypeGroupChats: String { return self._s[2971]! } + public var PrivacyPolicy_DeclineLastWarning: String { return self._s[2973]! } + public var NotificationsSound_Complete: String { return self._s[2974]! } + public var Group_Info_AdminLog: String { return self._s[2975]! } + public var GroupPermission_NotAvailableInPublicGroups: String { return self._s[2976]! } + public var Channel_AdminLog_InfoPanelAlertText: String { return self._s[2977]! } + public var Conversation_Admin: String { return self._s[2979]! } + public var Conversation_GifTooltip: String { return self._s[2980]! } + public var Passport_NotLoggedInMessage: String { return self._s[2981]! } + public func AutoDownloadSettings_OnFor(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2982]!, self._r[2982]!, [_0]) + } + public var Profile_MessageLifetimeForever: String { return self._s[2983]! } + public var SharedMedia_EmptyTitle: String { return self._s[2985]! } + public var Channel_Edit_PrivatePublicLinkAlert: String { return self._s[2987]! } + public var Username_Help: String { return self._s[2988]! } + public var DialogList_LanguageTooltip: String { return self._s[2990]! } + public var Map_LoadError: String { return self._s[2991]! } + public var Login_PhoneNumberAlreadyAuthorized: String { return self._s[2992]! } + public var Channel_AdminLog_AddMembers: String { return self._s[2993]! } + public var Notification_Exceptions_NewException: String { return self._s[2994]! } + public var TwoStepAuth_EmailTitle: String { return self._s[2995]! } + public var WatchRemote_AlertText: String { return self._s[2996]! } + public var ChatSettings_ConnectionType_Title: String { return self._s[2999]! } + public var Passport_Address_CountryPlaceholder: String { return self._s[3000]! } + public func DialogList_AwaitingEncryption(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3001]!, self._r[3001]!, [_0]) + } + public func Time_PreciseDate_m6(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3002]!, self._r[3002]!, [_1, _2, _3]) + } + public var Group_AdminLog_EmptyText: String { return self._s[3003]! } + public var AccessDenied_VideoMicrophone: String { return self._s[3005]! } + public var Conversation_ContextMenuStickerPackAdd: String { return self._s[3006]! } + public var Cache_ClearNone: String { return self._s[3007]! } + public var SocksProxySetup_FailedToConnect: String { return self._s[3008]! } + public var Permissions_NotificationsTitle_v0: String { return self._s[3009]! } + public func Channel_AdminLog_MessageEdited(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3010]!, self._r[3010]!, [_0]) + } + public var Passport_Identity_Country: String { return self._s[3011]! } + public func ChatSettings_AutoDownloadSettings_TypeFile(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3012]!, self._r[3012]!, [_0]) + } + public func Notification_CreatedChat(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3013]!, self._r[3013]!, [_0]) + } + public var AccessDenied_Settings: String { return self._s[3014]! } + public var Passport_Address_TypeUtilityBillUploadScan: String { return self._s[3015]! } + public var Month_ShortMay: String { return self._s[3016]! } + public var Compose_NewGroup: String { return self._s[3017]! } + public var Group_Setup_TypePrivate: String { return self._s[3019]! } + public var Login_PadPhoneHelpTitle: String { return self._s[3021]! } + public var Appearance_ThemeDayClassic: String { return self._s[3022]! } + public var Channel_AdminLog_MessagePreviousCaption: String { return self._s[3023]! } + public var AutoDownloadSettings_OffForAll: String { return self._s[3024]! } + public var Privacy_GroupsAndChannels_WhoCanAddMe: String { return self._s[3025]! } + public var Conversation_typing: String { return self._s[3027]! } + public var Paint_Masks: String { return self._s[3028]! } + public var Username_InvalidTaken: String { return self._s[3029]! } + public var Call_StatusNoAnswer: String { return self._s[3030]! } + public var TwoStepAuth_EmailAddSuccess: String { return self._s[3031]! } + public var Passport_Identity_Selfie: String { return self._s[3032]! } + public var Login_InfoLastNamePlaceholder: String { return self._s[3033]! } + public var Privacy_SecretChatsLinkPreviewsHelp: String { return self._s[3034]! } + public var Conversation_ClearSecretHistory: String { return self._s[3035]! } + public var NetworkUsageSettings_Title: String { return self._s[3037]! } + public var Your_cards_security_code_is_invalid: String { return self._s[3039]! } + public func Notification_LeftChannel(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3041]!, self._r[3041]!, [_0]) + } + public func Call_CallInProgressMessage(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3042]!, self._r[3042]!, [_1, _2]) + } + public var SaveIncomingPhotosSettings_From: String { return self._s[3044]! } + public var Map_LiveLocationTitle: String { return self._s[3045]! } + public var Login_InfoAvatarAdd: String { return self._s[3046]! } + public var Passport_Identity_FilesView: String { return self._s[3047]! } + public var UserInfo_GenericPhoneLabel: String { return self._s[3048]! } + public var Privacy_Calls_NeverAllow: String { return self._s[3049]! } + public func Contacts_AddPhoneNumber(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3050]!, self._r[3050]!, [_0]) + } + public var TwoStepAuth_ConfirmationText: String { return self._s[3051]! } + public var ChatSettings_AutomaticVideoMessageDownload: String { return self._s[3052]! } + public var Channel_AdminLogFilter_AdminsAll: String { return self._s[3053]! } + public var Tour_Title2: String { return self._s[3054]! } + public var Conversation_FileOpenIn: String { return self._s[3055]! } + public var Checkout_ErrorPrecheckoutFailed: String { return self._s[3056]! } + public var Wallpaper_Set: String { return self._s[3057]! } + public var Passport_Identity_Translations: String { return self._s[3059]! } + public func Channel_AdminLog_MessageChangedChannelAbout(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3060]!, self._r[3060]!, [_0]) + } + public var Channel_LeaveChannel: String { return self._s[3061]! } + public func PINNED_INVOICE(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3062]!, self._r[3062]!, [_1]) + } + public var PhotoEditor_HighlightsTint: String { return self._s[3063]! } + public var Passport_Email_Delete: String { return self._s[3064]! } + public var Conversation_Mute: String { return self._s[3066]! } + public var Channel_AdminLog_CanSendMessages: String { return self._s[3068]! } + public func Notification_PassportValuesSentMessage(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3070]!, self._r[3070]!, [_1, _2]) + } + public var Calls_CallTabDescription: String { return self._s[3071]! } + public var Passport_Identity_NativeNameHelp: String { return self._s[3072]! } + public var Common_No: String { return self._s[3073]! } + public var Weekday_Sunday: String { return self._s[3074]! } + public var Notification_Reply: String { return self._s[3075]! } + public var Conversation_ViewMessage: String { return self._s[3076]! } + public func Checkout_SavePasswordTimeoutAndFaceId(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3077]!, self._r[3077]!, [_0]) + } + public func Map_LiveLocationPrivateDescription(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3078]!, self._r[3078]!, [_0]) + } + public var Message_PinnedDocumentMessage: String { return self._s[3079]! } + public var DialogList_TabTitle: String { return self._s[3081]! } + public var ChatSettings_AutoPlayTitle: String { return self._s[3082]! } + public var Passport_FieldEmail: String { return self._s[3083]! } + public var Conversation_UnpinMessageAlert: String { return self._s[3084]! } + public var Passport_Address_TypeBankStatement: String { return self._s[3085]! } + public var Passport_Identity_ExpiryDate: String { return self._s[3086]! } + public var Privacy_Calls_P2P: String { return self._s[3087]! } + public func CancelResetAccount_Success(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3089]!, self._r[3089]!, [_0]) + } + public var SocksProxySetup_UseForCallsHelp: String { return self._s[3090]! } + public var EnterPasscode_ChangeTitle: String { return self._s[3091]! } + public var Passport_InfoText: String { return self._s[3092]! } + public var Checkout_NewCard_SaveInfoEnableHelp: String { return self._s[3093]! } + public func Login_InvalidPhoneEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3094]!, self._r[3094]!, [_0]) + } + public func Time_PreciseDate_m3(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3095]!, self._r[3095]!, [_1, _2, _3]) + } + public var Passport_Identity_EditDriversLicense: String { return self._s[3096]! } + public var Conversation_TapAndHoldToRecord: String { return self._s[3098]! } + public func Notification_CallTimeFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3099]!, self._r[3099]!, [_1, _2]) + } + public var Channel_EditAdmin_PermissionInviteViaLink: String { return self._s[3101]! } + public func Generic_OpenHiddenLinkAlert(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3103]!, self._r[3103]!, [_0]) + } + public var DialogList_Unread: String { return self._s[3104]! } + public func PUSH_CHAT_MESSAGE_GIF(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3105]!, self._r[3105]!, [_1, _2]) + } + public var User_DeletedAccount: String { return self._s[3106]! } + public func Watch_Time_ShortYesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3107]!, self._r[3107]!, [_0]) + } + public var UserInfo_NotificationsDefault: String { return self._s[3108]! } + public var SharedMedia_CategoryMedia: String { return self._s[3109]! } + public var SocksProxySetup_ProxyStatusUnavailable: String { return self._s[3110]! } + public var Channel_AdminLog_MessageRestrictedForever: String { return self._s[3111]! } + public var Watch_ChatList_Compose: String { return self._s[3112]! } + public var Notifications_MessageNotificationsExceptionsHelp: String { return self._s[3113]! } + public var AutoDownloadSettings_Delimeter: String { return self._s[3114]! } + public var Watch_Microphone_Access: String { return self._s[3115]! } + public var Group_Setup_HistoryHeader: String { return self._s[3116]! } + public var Activity_UploadingPhoto: String { return self._s[3117]! } + public var Conversation_Edit: String { return self._s[3119]! } + public var Group_ErrorSendRestrictedMedia: String { return self._s[3120]! } + public var Login_TermsOfServiceDecline: String { return self._s[3121]! } + public var Message_PinnedContactMessage: String { return self._s[3122]! } + public func Channel_AdminLog_MessageRestrictedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3123]!, self._r[3123]!, [_1, _2]) + } + public func Login_PhoneBannedEmailBody(_ _1: String, _ _2: String, _ _3: String, _ _4: String, _ _5: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3124]!, self._r[3124]!, [_1, _2, _3, _4, _5]) + } + public var TwoStepAuth_AdditionalPassword: String { return self._s[3126]! } + public func PUSH_CHAT_DELETE_YOU(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3127]!, self._r[3127]!, [_1, _2]) + } + public var Passport_Phone_EnterOtherNumber: String { return self._s[3128]! } + public var Message_PinnedPhotoMessage: String { return self._s[3129]! } + public var Passport_FieldPhone: String { return self._s[3130]! } + public var TwoStepAuth_RecoveryEmailAddDescription: String { return self._s[3131]! } + public var ChatSettings_AutoPlayGifs: String { return self._s[3132]! } + public var InfoPlist_NSCameraUsageDescription: String { return self._s[3134]! } + public var Conversation_Call: String { return self._s[3135]! } + public var Common_TakePhoto: String { return self._s[3137]! } + public var Channel_NotificationLoading: String { return self._s[3138]! } + public func Notification_Exceptions_Sound(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3139]!, self._r[3139]!, [_0]) + } + public func PUSH_CHANNEL_MESSAGE_VIDEO(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3140]!, self._r[3140]!, [_1]) + } + public var Permissions_SiriTitle_v0: String { return self._s[3141]! } + public func Login_ResetAccountProtected_Text(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3142]!, self._r[3142]!, [_0]) + } + public var Channel_MessagePhotoRemoved: String { return self._s[3143]! } + public var Common_edit: String { return self._s[3144]! } + public var PrivacySettings_AuthSessions: String { return self._s[3145]! } + public var Month_ShortJune: String { return self._s[3146]! } + public var PrivacyLastSeenSettings_AlwaysShareWith_Placeholder: String { return self._s[3147]! } + public var Call_ReportSend: String { return self._s[3148]! } + public var Watch_LastSeen_JustNow: String { return self._s[3149]! } + public var Notifications_MessageNotifications: String { return self._s[3150]! } + public var WallpaperSearch_ColorGreen: String { return self._s[3151]! } + public var BroadcastListInfo_AddRecipient: String { return self._s[3153]! } + public var Group_Status: String { return self._s[3154]! } + public func AutoNightTheme_LocationHelp(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3155]!, self._r[3155]!, [_0, _1]) + } + public var ShareMenu_ShareTo: String { return self._s[3156]! } + public var Conversation_Moderate_Ban: String { return self._s[3157]! } + public func Conversation_DeleteMessagesFor(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3158]!, self._r[3158]!, [_0]) + } + public var SharedMedia_ViewInChat: String { return self._s[3159]! } + public var Map_LiveLocationFor8Hours: String { return self._s[3160]! } + public func PUSH_PINNED_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3161]!, self._r[3161]!, [_1]) + } + public func PUSH_PINNED_POLL(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3162]!, self._r[3162]!, [_1]) + } + public func Map_AccurateTo(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3164]!, self._r[3164]!, [_0]) + } + public var Map_OpenInHereMaps: String { return self._s[3165]! } + public var Appearance_ReduceMotion: String { return self._s[3166]! } + public func PUSH_MESSAGE_TEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3167]!, self._r[3167]!, [_1, _2]) + } + public var Channel_Setup_TypePublicHelp: String { return self._s[3168]! } + public var Passport_Identity_EditInternalPassport: String { return self._s[3169]! } + public var PhotoEditor_Skip: String { return self._s[3170]! } + public func SharedMedia_Link(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func LiveLocationUpdated_MinutesAgo(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func ForwardedAudios(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[2 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Watch_LastSeen_MinutesAgo(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[3 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func PUSH_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[4 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func StickerPack_AddStickerCount(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[5 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func ForwardedAuthorsOthers(_ selector: Int32, _ _0: String, _ _1: String) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[6 * 6 + Int(form.rawValue)]!, _0, _1) + } + public func PUSH_CHANNEL_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[7 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func Map_ETAHours(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[8 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Call_ShortSeconds(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[9 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Notifications_ExceptionMuteExpires_Days(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[10 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func PUSH_CHAT_MESSAGE_PHOTOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[11 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func AttachmentMenu_SendPhoto(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[12 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func ForwardedPolls(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[13 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func ForwardedVideos(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[14 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func ServiceMessage_GameScoreSimple(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[15 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func ForwardedMessages(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[16 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func SharedMedia_Generic(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[17 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Notifications_ExceptionMuteExpires_Minutes(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[18 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Notification_GameScoreSimple(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[19 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Notifications_ExceptionMuteExpires_Hours(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[20 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func UserCount(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[21 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func PUSH_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[22 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func ChatList_SelectedChats(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[23 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func ForwardedLocations(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[24 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func SharedMedia_DeleteItemsConfirmation(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[25 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Watch_UserInfo_Mute(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[26 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Media_SharePhoto(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[27 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func DialogList_LiveLocationChatsCount(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[28 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func AttachmentMenu_SendItem(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[29 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func LastSeen_HoursAgo(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[30 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func MessageTimer_Hours(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[31 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func PUSH_CHAT_MESSAGE_VIDEOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[32 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func CreatePoll_AddMoreOptions(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[33 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Conversation_StatusMembers(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[34 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func MessageTimer_ShortSeconds(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[35 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Conversation_LiveLocationMembersCount(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[36 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func LiveLocation_MenuChatsCount(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[37 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func MessageTimer_ShortMinutes(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[38 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func PUSH_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[39 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func ForwardedGifs(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[40 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func ServiceMessage_GameScoreExtended(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[41 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func InviteText_ContactsCountText(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[42 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func PrivacyLastSeenSettings_AddUsers(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[43 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func MuteExpires_Minutes(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[44 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func MessageTimer_ShortWeeks(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[45 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func MessageTimer_Months(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[46 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Call_Minutes(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[47 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func LastSeen_MinutesAgo(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[48 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Passport_Scans(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[49 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Forward_ConfirmMultipleFiles(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[50 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func ForwardedContacts(_ value: Int32) -> String { +>>>>>>> 340319811cb2fb58f7afb2b5fc7d74967c89ae9a let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[51 * 6 + Int(form.rawValue)]!, "\(value)") } @@ -3755,6 +6583,7 @@ public final class PresentationStrings { let form = presentationStringsPluralizationForm(self.lc, selector) return String(format: self._ps[52 * 6 + Int(form.rawValue)]!, _1, _2) } +<<<<<<< HEAD public func UserCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[53 * 6 + Int(form.rawValue)]!, "\(value)") @@ -3844,13 +6673,105 @@ public final class PresentationStrings { return String(format: self._ps[74 * 6 + Int(form.rawValue)]!, "\(value)") } public func LastSeen_MinutesAgo(_ value: Int32) -> String { +======= + public func PUSH_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[53 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func StickerPack_RemoveMaskCount(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[54 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Call_ShortMinutes(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[55 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func ForwardedPhotos(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[56 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func PasscodeSettings_FailedAttempts(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[57 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func SharedMedia_File(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[58 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func MessageTimer_Minutes(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[59 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func StickerPack_RemoveStickerCount(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[60 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func ServiceMessage_GameScoreSelfExtended(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[61 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func MessagePoll_VotedCount(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[62 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func ChatList_DeleteConfirmation(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[63 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Invitation_Members(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[64 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Media_ShareItem(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[65 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func SharedMedia_Video(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[66 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func PUSH_CHAT_MESSAGE_ROUNDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[67 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func MessageTimer_Years(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[68 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func MuteFor_Days(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[69 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func ForwardedStickers(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[70 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func MuteFor_Hours(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[71 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Contacts_ImportersCount(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[72 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Media_ShareVideo(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[73 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func MessageTimer_Seconds(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[74 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func MessageTimer_ShortHours(_ value: Int32) -> String { +>>>>>>> 340319811cb2fb58f7afb2b5fc7d74967c89ae9a let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[75 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedAuthorsOthers(_ selector: Int32, _ _0: String, _ _1: String) -> String { - let form = presentationStringsPluralizationForm(self.lc, selector) - return String(format: self._ps[76 * 6 + Int(form.rawValue)]!, _0, _1) + public func AttachmentMenu_SendVideo(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[76 * 6 + Int(form.rawValue)]!, "\(value)") } +<<<<<<< HEAD public func ForwardedPhotos(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[77 * 6 + Int(form.rawValue)]!, "\(value)") @@ -3968,6 +6889,125 @@ public final class PresentationStrings { return String(format: self._ps[105 * 6 + Int(form.rawValue)]!, "\(value)") } public func Call_Seconds(_ value: Int32) -> String { +======= + public func MessageTimer_Weeks(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[77 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func SharedMedia_Photo(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[78 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func MessageTimer_ShortDays(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[79 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func MuteExpires_Hours(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[80 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func ForwardedFiles(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[81 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func StickerPack_StickerCount(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[82 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func GroupInfo_ParticipantCount(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[83 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func PUSH_CHAT_MESSAGES(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[84 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func StickerPack_AddMaskCount(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[85 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func ForwardedVideoMessages(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[86 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Conversation_StatusOnline(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[87 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Notifications_Exceptions(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[88 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func MuteExpires_Days(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[89 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Wallpaper_DeleteConfirmation(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[90 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Map_ETAMinutes(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[91 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func PUSH_CHANNEL_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[92 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func Notification_GameScoreSelfSimple(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[93 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Notification_GameScoreSelfExtended(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[94 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func ServiceMessage_GameScoreSelfSimple(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[95 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func PUSH_CHANNEL_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[96 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func Notification_GameScoreExtended(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[97 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func PUSH_CHANNEL_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[98 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func AttachmentMenu_SendGif(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[99 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Conversation_StatusSubscribers(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[100 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func PUSH_CHANNEL_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[101 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func Call_Seconds(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[102 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func PUSH_CHAT_MESSAGE_FWDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, selector) + return String(format: self._ps[103 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func MessageTimer_Days(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[104 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func QuickSend_Photos(_ value: Int32) -> String { + let form = presentationStringsPluralizationForm(self.lc, value) + return String(format: self._ps[105 * 6 + Int(form.rawValue)]!, "\(value)") + } + public func Watch_LastSeen_HoursAgo(_ value: Int32) -> String { +>>>>>>> 340319811cb2fb58f7afb2b5fc7d74967c89ae9a let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[106 * 6 + Int(form.rawValue)]!, "\(value)") } diff --git a/TelegramUI/PrivacyAndSecurityController.swift b/TelegramUI/PrivacyAndSecurityController.swift index 7d7ffb3e4c..f751c3e812 100644 --- a/TelegramUI/PrivacyAndSecurityController.swift +++ b/TelegramUI/PrivacyAndSecurityController.swift @@ -383,7 +383,7 @@ private func privacyAndSecurityControllerEntries(presentationData: PresentationD return entries } -public func privacyAndSecurityController(context: AccountContext) -> ViewController { +public func privacyAndSecurityController(context: AccountContext, initialSettings: AccountPrivacySettings? = nil, updatedSettings: ((AccountPrivacySettings?) -> Void)? = nil) -> ViewController { let statePromise = ValuePromise(PrivacyAndSecurityControllerState(), ignoreRepeated: true) let stateValue = Atomic(value: PrivacyAndSecurityControllerState()) let updateState: ((PrivacyAndSecurityControllerState) -> PrivacyAndSecurityControllerState) -> Void = { f in @@ -403,7 +403,7 @@ public func privacyAndSecurityController(context: AccountContext) -> ViewControl actionsDisposable.add(updateAccountTimeoutDisposable) let privacySettingsPromise = Promise() - privacySettingsPromise.set(.single(nil) |> then(requestAccountPrivacySettings(account: context.account) |> map(Optional.init))) + privacySettingsPromise.set(.single(initialSettings) |> then(requestAccountPrivacySettings(account: context.account) |> map(Optional.init))) let arguments = PrivacyAndSecurityControllerArguments(account: context.account, openBlockedUsers: { pushControllerImpl?(blockedPeersController(context: context)) @@ -615,6 +615,11 @@ public func privacyAndSecurityController(context: AccountContext) -> ViewControl }) actionsDisposable.add(managedUpdatedRecentPeers(accountPeerId: context.account.peerId, postbox: context.account.postbox, network: context.account.network).start()) + + actionsDisposable.add((privacySettingsPromise.get() + |> deliverOnMainQueue).start(next: { settings in + updatedSettings?(settings) + })) let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, statePromise.get(), privacySettingsPromise.get(), context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.secretChatLinkPreviewsKey()), context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.contactSynchronizationSettings]), recentPeers(account: context.account)) |> map { presentationData, state, privacySettings, noticeView, sharedData, recentPeers -> (ItemListControllerState, (ItemListNodeState, PrivacyAndSecurityEntry.ItemGenerationArguments)) in diff --git a/TelegramUI/RadialStatusNode.swift b/TelegramUI/RadialStatusNode.swift index 54437f022a..545e4bc03f 100644 --- a/TelegramUI/RadialStatusNode.swift +++ b/TelegramUI/RadialStatusNode.swift @@ -143,7 +143,7 @@ public final class RadialStatusNode: ASControlNode { super.init() } - public func transitionToState(_ state: RadialStatusNodeState, animated: Bool = true, completion: @escaping () -> Void) { + public func transitionToState(_ state: RadialStatusNodeState, animated: Bool = true, completion: @escaping () -> Void = {}) { if self.state != state { let fromState = self.state self.state = state diff --git a/TelegramUI/SelectivePrivacySettingsController.swift b/TelegramUI/SelectivePrivacySettingsController.swift index bbb398050a..a3421b6067 100644 --- a/TelegramUI/SelectivePrivacySettingsController.swift +++ b/TelegramUI/SelectivePrivacySettingsController.swift @@ -74,7 +74,7 @@ private func stringForUserCount(_ count: Int, strings: PresentationStrings) -> S private enum SelectivePrivacySettingsEntry: ItemListNodeEntry { case forwardsPreviewHeader(PresentationTheme, String) - case forwardsPreview(PresentationTheme, TelegramWallpaper, PresentationFontSize, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, Bool, String) + case forwardsPreview(PresentationTheme, TelegramWallpaper, PresentationFontSize, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, String, Bool, String) case settingHeader(PresentationTheme, String) case everybody(PresentationTheme, String, Bool) case contacts(PresentationTheme, String, Bool) @@ -164,8 +164,8 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry { } else { return false } - case let .forwardsPreview(lhsTheme, lhsWallpaper, lhsFontSize, lhsStrings, lhsTimeFormat, lhsNameOrder, lhsLinkEnabled, lhsTooltipText): - if case let .forwardsPreview(rhsTheme, rhsWallpaper, rhsFontSize, rhsStrings, rhsTimeFormat, rhsNameOrder, rhsLinkEnabled, rhsTooltipText) = rhs, lhsTheme === rhsTheme, lhsWallpaper == rhsWallpaper, lhsFontSize == rhsFontSize, lhsStrings === rhsStrings, lhsTimeFormat == rhsTimeFormat, lhsNameOrder == rhsNameOrder, lhsLinkEnabled == rhsLinkEnabled, lhsTooltipText == rhsTooltipText { + case let .forwardsPreview(lhsTheme, lhsWallpaper, lhsFontSize, lhsStrings, lhsTimeFormat, lhsNameOrder, lhsPeerName, lhsLinkEnabled, lhsTooltipText): + if case let .forwardsPreview(rhsTheme, rhsWallpaper, rhsFontSize, rhsStrings, rhsTimeFormat, rhsNameOrder, rhsPeerName, rhsLinkEnabled, rhsTooltipText) = rhs, lhsTheme === rhsTheme, lhsWallpaper == rhsWallpaper, lhsFontSize == rhsFontSize, lhsStrings === rhsStrings, lhsTimeFormat == rhsTimeFormat, lhsNameOrder == rhsNameOrder, lhsPeerName == rhsPeerName, lhsLinkEnabled == rhsLinkEnabled, lhsTooltipText == rhsTooltipText { return true } else { return false @@ -289,8 +289,8 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry { switch self { case let .forwardsPreviewHeader(theme, text): return ItemListSectionHeaderItem(theme: theme, text: text, multiline: true, sectionId: self.section) - case let .forwardsPreview(theme, wallpaper, fontSize, strings, dateTimeFormat, nameDisplayOrder, linkEnabled, tooltipText): - return ForwardPrivacyChatPreviewItem(context: arguments.context, theme: theme, strings: strings, sectionId: self.section, fontSize: fontSize, wallpaper: wallpaper, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, linkEnabled: linkEnabled, tooltipText: tooltipText) + case let .forwardsPreview(theme, wallpaper, fontSize, strings, dateTimeFormat, nameDisplayOrder, peerName, linkEnabled, tooltipText): + return ForwardPrivacyChatPreviewItem(context: arguments.context, theme: theme, strings: strings, sectionId: self.section, fontSize: fontSize, wallpaper: wallpaper, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, peerName: peerName, linkEnabled: linkEnabled, tooltipText: tooltipText) case let .settingHeader(theme, text): return ItemListSectionHeaderItem(theme: theme, text: text, multiline: true, sectionId: self.section) case let .everybody(theme, text, value): @@ -448,7 +448,7 @@ private struct SelectivePrivacySettingsControllerState: Equatable { } } -private func selectivePrivacySettingsControllerEntries(presentationData: PresentationData, kind: SelectivePrivacySettingsKind, state: SelectivePrivacySettingsControllerState) -> [SelectivePrivacySettingsEntry] { +private func selectivePrivacySettingsControllerEntries(presentationData: PresentationData, kind: SelectivePrivacySettingsKind, state: SelectivePrivacySettingsControllerState, peerName: String) -> [SelectivePrivacySettingsEntry] { var entries: [SelectivePrivacySettingsEntry] = [] let settingTitle: String @@ -498,7 +498,7 @@ private func selectivePrivacySettingsControllerEntries(presentationData: Present linkEnabled = false } entries.append(.forwardsPreviewHeader(presentationData.theme, presentationData.strings.Privacy_Forwards_Preview)) - entries.append(.forwardsPreview(presentationData.theme, presentationData.chatWallpaper, presentationData.fontSize, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, linkEnabled, tootipText)) + entries.append(.forwardsPreview(presentationData.theme, presentationData.chatWallpaper, presentationData.fontSize, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, peerName, linkEnabled, tootipText)) } entries.append(.settingHeader(presentationData.theme, settingTitle)) @@ -693,8 +693,12 @@ func selectivePrivacySettingsController(context: AccountContext, kind: Selective }).start() }) - let signal = combineLatest(context.sharedContext.presentationData, statePromise.get()) |> deliverOnMainQueue - |> map { presentationData, state -> (ItemListControllerState, (ItemListNodeState, SelectivePrivacySettingsEntry.ItemGenerationArguments)) in + let peerName = context.account.postbox.transaction { transaction -> String in + return (transaction.getPeer(context.account.peerId) as? TelegramUser)?.displayTitle ?? "" + } + + let signal = combineLatest(context.sharedContext.presentationData, statePromise.get(), peerName) |> deliverOnMainQueue + |> map { presentationData, state, peerName -> (ItemListControllerState, (ItemListNodeState, SelectivePrivacySettingsEntry.ItemGenerationArguments)) in let title: String switch kind { @@ -710,7 +714,7 @@ func selectivePrivacySettingsController(context: AccountContext, kind: Selective title = presentationData.strings.Privacy_Forwards } let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false) - let listState = ItemListNodeState(entries: selectivePrivacySettingsControllerEntries(presentationData: presentationData, kind: kind, state: state), style: .blocks, animateChanges: false) + let listState = ItemListNodeState(entries: selectivePrivacySettingsControllerEntries(presentationData: presentationData, kind: kind, state: state, peerName: peerName), style: .blocks, animateChanges: false) return (controllerState, (listState, arguments)) } |> afterDisposed { diff --git a/TelegramUI/SettingsController.swift b/TelegramUI/SettingsController.swift index 4a4b48e38a..60a7c83037 100644 --- a/TelegramUI/SettingsController.swift +++ b/TelegramUI/SettingsController.swift @@ -556,6 +556,7 @@ public func settingsController(context: AccountContext, accountManager: AccountM var pushControllerImpl: ((ViewController) -> Void)? var presentControllerImpl: ((ViewController, Any?) -> Void)? + var dismissInputImpl: (() -> Void)? var setDisplayNavigationBarImpl: ((Bool) -> Void)? var getNavigationControllerImpl: (() -> NavigationController?)? @@ -588,47 +589,10 @@ public func settingsController(context: AccountContext, accountManager: AccountM let archivedPacks = Promise<[ArchivedStickerPackItem]?>() let contextValue = Promise() - - let networkArguments = context.account.networkArguments - let auxiliaryMethods = context.account.auxiliaryMethods - let rootPath = rootPathForBasePath(context.sharedContext.applicationBindings.containerPath) - - let sharedContext = context.sharedContext - let accountsAndPeersSignal: Signal<((Account, Peer)?, [(Account, Peer, Int32)]), NoError> = context.sharedContext.activeAccounts - |> mapToSignal { primary, activeAccounts, _ -> Signal<((Account, Peer)?, [(Account, Peer, Int32)]), NoError> in - var accounts: [Signal<(Account, Peer, Int32)?, NoError>] = [] - func accountWithPeer(_ account: Account) -> Signal<(Account, Peer, Int32)?, NoError> { - return combineLatest(account.postbox.peerView(id: account.peerId), renderedTotalUnreadCount(accountManager: sharedContext.accountManager, postbox: account.postbox)) - |> map { view, totalUnreadCount -> (Peer?, Int32) in - return (view.peers[view.peerId], totalUnreadCount.0) - } - |> distinctUntilChanged { lhs, rhs in - return arePeersEqual(lhs.0, rhs.0) && lhs.1 == rhs.1 - } - |> map { peer, totalUnreadCount -> (Account, Peer, Int32)? in - if let peer = peer { - return (account, peer, totalUnreadCount) - } else { - return nil - } - } - } - for (_, account, _) in activeAccounts { - accounts.append(accountWithPeer(account)) - } - - return combineLatest(accounts) - |> map { accounts -> ((Account, Peer)?, [(Account, Peer, Int32)]) in - var primaryRecord: (Account, Peer)? - if let first = accounts.filter({ $0?.0.id == primary?.id }).first, let (account, peer, _) = first { - primaryRecord = (account, peer) - } - return (primaryRecord, accounts.filter({ $0?.0.id != primary?.id }).compactMap({ $0 })) - } - } - let accountsAndPeers = Promise<((Account, Peer)?, [(Account, Peer, Int32)])>() - accountsAndPeers.set(accountsAndPeersSignal) + accountsAndPeers.set(activeAccountsAndPeers(context: context)) + + let privacySettings = Promise<[PeerId: AccountPrivacySettings]>([:]) let openFaq: (Promise) -> Void = { resolvedUrl in let _ = (contextValue.get() @@ -717,7 +681,19 @@ public func settingsController(context: AccountContext, accountManager: AccountM let _ = (contextValue.get() |> deliverOnMainQueue |> take(1)).start(next: { context in - pushControllerImpl?(privacyAndSecurityController(context: context)) + let _ = (privacySettings.get() + |> take(1) + |> deliverOnMainQueue).start(next: { settings in + pushControllerImpl?(privacyAndSecurityController(context: context, initialSettings: settings[context.account.peerId], updatedSettings: { settings in + let _ = ((privacySettings.get() + |> take(1) + |> deliverOnMainQueue).start(next: { currentPrivacySettings in + var updatedPrivacySettings = currentPrivacySettings + updatedPrivacySettings[context.account.peerId] = settings + privacySettings.set(.single(updatedPrivacySettings)) + })) + })) + }) }) }, openDataAndStorage: { let _ = (contextValue.get() @@ -798,48 +774,9 @@ public func settingsController(context: AccountContext, accountManager: AccountM let _ = (contextValue.get() |> deliverOnMainQueue |> take(1)).start(next: { context in - var cancelImpl: (() -> Void)? - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - let progressSignal = Signal { subscriber in - let controller = OverlayStatusController(theme: presentationData.theme, strings: presentationData.strings, type: .loading(cancelled: { - cancelImpl?() - })) - presentControllerImpl?(controller, nil) - return ActionDisposable { [weak controller] in - Queue.mainQueue().async() { - controller?.dismiss() - } - } + if let presentControllerImpl = presentControllerImpl, let pushControllerImpl = pushControllerImpl { + openEditingDisposable.set(openEditSettings(context: context, accountsAndPeers: accountsAndPeers.get(), presentController: presentControllerImpl, pushController: pushControllerImpl)) } - |> runOn(Queue.mainQueue()) - |> delay(0.15, queue: Queue.mainQueue()) - let progressDisposable = progressSignal.start() - - let peerKey: PostboxViewKey = .peer(peerId: context.account.peerId, components: []) - let cachedDataKey: PostboxViewKey = .cachedPeerData(peerId: context.account.peerId) - let signal = (combineLatest(accountsAndPeers.get() |> take(1), context.account.postbox.combinedView(keys: [peerKey, cachedDataKey])) - |> mapToSignal { accountsAndPeers, view -> Signal<(TelegramUser, CachedUserData, Bool), NoError> in - guard let cachedDataView = view.views[cachedDataKey] as? CachedPeerDataView, let cachedData = cachedDataView.cachedPeerData as? CachedUserData else { - return .complete() - } - guard let peerView = view.views[peerKey] as? PeerView, let peer = peerView.peers[context.account.peerId] as? TelegramUser else { - return .complete() - } - return .single((peer, cachedData, accountsAndPeers.1.count + 1 < maximumNumberOfAccounts)) - } - |> take(1)) - |> afterDisposed { - Queue.mainQueue().async { - progressDisposable.dispose() - } - } - cancelImpl = { - openEditingDisposable.set(nil) - } - openEditingDisposable.set((signal - |> deliverOnMainQueue).start(next: { peer, cachedData, canAddAccounts in - pushControllerImpl?(editSettingsController(context: context, currentName: .personName(firstName: peer.firstName ?? "", lastName: peer.lastName ?? ""), currentBioText: cachedData.about ?? "", accountManager: accountManager, canAddAccounts: canAddAccounts)) - })) }) }, displayCopyContextMenu: { let _ = (contextValue.get() @@ -1137,10 +1074,11 @@ public func settingsController(context: AccountContext, accountManager: AccountM return state } }, presentController: { v, a in + dismissInputImpl?() presentControllerImpl?(v, a) }, pushController: { v in pushControllerImpl?(v) - }) + }, getNavigationController: getNavigationControllerImpl) let (hasPassport, hasWatchApp) = hasPassportAndWatch let listState = ItemListNodeState(entries: settingsEntries(account: context.account, presentationData: presentationData, state: state, view: view, proxySettings: proxySettings, notifyExceptions: preferencesAndExceptions.1, notificationsAuthorizationStatus: preferencesAndExceptions.2, notificationsWarningSuppressed: preferencesAndExceptions.3, unreadTrendingStickerPacks: unreadTrendingStickerPacks, archivedPacks: featuredAndArchived.1, hasPassport: hasPassport, hasWatchApp: hasWatchApp, accountsAndPeers: accountsAndPeers.1, inAppNotificationSettings: inAppNotificationSettings), style: .blocks, searchItem: searchItem, initialScrollToItem: ListViewScrollToItem(index: 0, position: .top(-navigationBarSearchContentHeight), animated: false, curve: .Default(duration: 0.0), directionHint: .Up)) @@ -1243,7 +1181,9 @@ public func settingsController(context: AccountContext, accountManager: AccountM } presentControllerImpl = { [weak controller] value, arguments in controller?.present(value, in: .window(.root), with: arguments ?? ViewControllerPresentationArguments(presentationAnimation: .modalSheet), blockInteraction: true) - + } + dismissInputImpl = { [weak controller] in + controller?.view.window?.endEditing(true) } getNavigationControllerImpl = { [weak controller] in return (controller?.navigationController as? NavigationController) @@ -1285,7 +1225,7 @@ public func settingsController(context: AccountContext, accountManager: AccountM let _ = (contextValue.get() |> take(1) |> deliverOnMainQueue).start(next: { accountContext in - pushControllerImpl?(debugController(sharedContext: sharedContext, context: accountContext)) + pushControllerImpl?(debugController(sharedContext: accountContext.sharedContext, context: accountContext)) }) } diff --git a/TelegramUI/SettingsSearchItem.swift b/TelegramUI/SettingsSearchItem.swift index 5678e14773..3a4d0aaebb 100644 --- a/TelegramUI/SettingsSearchItem.swift +++ b/TelegramUI/SettingsSearchItem.swift @@ -19,32 +19,32 @@ extension NavigationBarSearchContentNode: ItemListControllerSearchNavigationCont extension SettingsSearchableItemIcon { func image() -> UIImage? { switch self { - case .proxy: - return PresentationResourcesSettings.proxy - case .savedMessages: - return PresentationResourcesSettings.savedMessages - case .calls: - return PresentationResourcesSettings.recentCalls - case .stickers: - return PresentationResourcesSettings.stickers - case .notifications: - return PresentationResourcesSettings.notifications - case .privacy: - return PresentationResourcesSettings.security - case .data: - return PresentationResourcesSettings.dataAndStorage - case .appearance: - return PresentationResourcesSettings.appearance - case .language: - return PresentationResourcesSettings.language - case .watch: - return PresentationResourcesSettings.watch - case .passport: - return PresentationResourcesSettings.passport - case .support: - return PresentationResourcesSettings.support - case .faq: - return PresentationResourcesSettings.faq + case .proxy: + return PresentationResourcesSettings.proxy + case .savedMessages: + return PresentationResourcesSettings.savedMessages + case .calls: + return PresentationResourcesSettings.recentCalls + case .stickers: + return PresentationResourcesSettings.stickers + case .notifications: + return PresentationResourcesSettings.notifications + case .privacy: + return PresentationResourcesSettings.security + case .data: + return PresentationResourcesSettings.dataAndStorage + case .appearance: + return PresentationResourcesSettings.appearance + case .language: + return PresentationResourcesSettings.language + case .watch: + return PresentationResourcesSettings.watch + case .passport: + return PresentationResourcesSettings.passport + case .support: + return PresentationResourcesSettings.support + case .faq: + return PresentationResourcesSettings.faq } } } @@ -57,12 +57,13 @@ final class SettingsSearchItem: ItemListControllerSearch { let updateActivated: (Bool) -> Void let presentController: (ViewController, Any?) -> Void let pushController: (ViewController) -> Void + let getNavigationController: (() -> NavigationController?)? private var updateActivity: ((Bool) -> Void)? private var activity: ValuePromise = ValuePromise(ignoreRepeated: false) private let activityDisposable = MetaDisposable() - init(context: AccountContext, theme: PresentationTheme, placeholder: String, activated: Bool, updateActivated: @escaping (Bool) -> Void, presentController: @escaping (ViewController, Any?) -> Void, pushController: @escaping (ViewController) -> Void) { + init(context: AccountContext, theme: PresentationTheme, placeholder: String, activated: Bool, updateActivated: @escaping (Bool) -> Void, presentController: @escaping (ViewController, Any?) -> Void, pushController: @escaping (ViewController) -> Void, getNavigationController: (() -> NavigationController?)?) { self.context = context self.theme = theme self.placeholder = placeholder @@ -70,6 +71,7 @@ final class SettingsSearchItem: ItemListControllerSearch { self.updateActivated = updateActivated self.presentController = presentController self.pushController = pushController + self.getNavigationController = getNavigationController self.activityDisposable.set((activity.get() |> mapToSignal { value -> Signal in if value { return .single(value) |> delay(0.2, queue: Queue.mainQueue()) @@ -133,7 +135,7 @@ final class SettingsSearchItem: ItemListControllerSearch { pushController(c) }, presentController: { c, a in presentController(c, a) - }) + }, getNavigationController: self.getNavigationController) } } } @@ -401,15 +403,16 @@ private final class SettingsSearchItemNode: ItemListControllerSearchNode { let pushController: (ViewController) -> Void let presentController: (ViewController, Any?) -> Void + let getNavigationController: (() -> NavigationController?)? var cancel: () -> Void - init(context: AccountContext, cancel: @escaping () -> Void, updateActivity: @escaping(Bool) -> Void, pushController: @escaping (ViewController) -> Void, presentController: @escaping (ViewController, Any?) -> Void) { + init(context: AccountContext, cancel: @escaping () -> Void, updateActivity: @escaping(Bool) -> Void, pushController: @escaping (ViewController) -> Void, presentController: @escaping (ViewController, Any?) -> Void, getNavigationController: (() -> NavigationController?)?) { self.context = context self.presentationData = context.sharedContext.currentPresentationData.with { $0 } self.pushController = pushController self.presentController = presentController - + self.getNavigationController = getNavigationController self.cancel = cancel super.init() @@ -417,6 +420,7 @@ private final class SettingsSearchItemNode: ItemListControllerSearchNode { func updatePresentationData(_ presentationData: PresentationData) { self.presentationData = presentationData + self.searchDisplayController?.updatePresentationData(presentationData) } func activateSearch(placeholderNode: SearchBarPlaceholderNode) { @@ -426,13 +430,15 @@ private final class SettingsSearchItemNode: ItemListControllerSearchNode { self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, contentNode: SettingsSearchContainerNode(context: self.context, listState: LocalizationListState.defaultSettings, openResult: { [weak self] result in if let strongSelf = self { - result.present(strongSelf.context, { [weak self] mode, controller in + result.present(strongSelf.context, strongSelf.getNavigationController?(), { [weak self] mode, controller in if let strongSelf = self { switch mode { case .push: strongSelf.pushController(controller) case .modal: - strongSelf.presentController(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) + strongSelf.presentController(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet, completion: { [weak self] in + self?.cancel() + })) case .immediate: strongSelf.presentController(controller, nil) } diff --git a/TelegramUI/SettingsSearchableItems.swift b/TelegramUI/SettingsSearchableItems.swift index b83e410c04..acbb4208ae 100644 --- a/TelegramUI/SettingsSearchableItems.swift +++ b/TelegramUI/SettingsSearchableItems.swift @@ -4,6 +4,8 @@ import SwiftSignalKit import Postbox import TelegramCore +private let maximumNumberOfAccounts = 3 + enum SettingsSearchableItemIcon { case proxy case savedMessages @@ -21,6 +23,7 @@ enum SettingsSearchableItemIcon { } enum SettingsSearchableItemId: Hashable { + case profile(Int) case proxy(Int) case savedMessages(Int) case calls(Int) @@ -48,7 +51,57 @@ struct SettingsSearchableItem { let alternate: [String] let icon: SettingsSearchableItemIcon let breadcrumbs: [String] - let present: (AccountContext, @escaping (SettingsSearchableItemPresentation, ViewController) -> Void) -> Void + let present: (AccountContext, NavigationController?, @escaping (SettingsSearchableItemPresentation, ViewController) -> Void) -> Void +} + +private func profileSearchableItems(context: AccountContext, canAddAccount: Bool) -> [SettingsSearchableItem] { + let icon: SettingsSearchableItemIcon = .calls + let strings = context.sharedContext.currentPresentationData.with { $0 }.strings + + let presentProfileSettings: (AccountContext, @escaping (SettingsSearchableItemPresentation, ViewController) -> Void, EditSettingsEntryTag?) -> Void = { context, present, itemTag in + let _ = openEditSettings(context: context, accountsAndPeers: activeAccountsAndPeers(context: context), focusOnItemTag: itemTag, presentController: { controller, _ in + present(.immediate, controller) + }, pushController: { controller in + present(.push, controller) + }) + } + + var items: [SettingsSearchableItem] = [] + items.append(SettingsSearchableItem(id: .profile(0), title: strings.EditProfile_Title, alternate: [], icon: icon, breadcrumbs: [], present: { context, _, present in + presentProfileSettings(context, present, nil) + })) + + items.append(SettingsSearchableItem(id: .profile(1), title: strings.UserInfo_About_Placeholder, alternate: [], icon: icon, breadcrumbs: [strings.EditProfile_Title], present: { context, _, present in + presentProfileSettings(context, present, .bio) + })) + items.append(SettingsSearchableItem(id: .profile(2), title: strings.Settings_PhoneNumber, alternate: [], icon: icon, breadcrumbs: [strings.EditProfile_Title], present: { context, _, present in + let _ = (context.account.postbox.transaction { transaction -> String in + return (transaction.getPeer(context.account.peerId) as? TelegramUser)?.phone ?? "" + } + |> deliverOnMainQueue).start(next: { phoneNumber in + present(.push, ChangePhoneNumberIntroController(context: context, phoneNumber: formatPhoneNumber(phoneNumber))) + }) + })) + items.append(SettingsSearchableItem(id: .profile(3), title: strings.Settings_Username, alternate: [], icon: icon, breadcrumbs: [strings.EditProfile_Title], present: { context, _, present in + present(.modal, usernameSetupController(context: context)) + })) + if canAddAccount { + items.append(SettingsSearchableItem(id: .profile(4), title: strings.Settings_AddAccount, alternate: [], icon: icon, breadcrumbs: [strings.EditProfile_Title], present: { context, _, present in + let isTestingEnvironment = context.account.testingEnvironment + context.sharedContext.beginNewAuth(testingEnvironment: isTestingEnvironment) + })) + } + items.append(SettingsSearchableItem(id: .profile(5), title: strings.Settings_Logout, alternate: [], icon: icon, breadcrumbs: [strings.EditProfile_Title], present: { context, navigationController, present in + let _ = (context.account.postbox.transaction { transaction -> String in + return (transaction.getPeer(context.account.peerId) as? TelegramUser)?.phone ?? "" + } + |> deliverOnMainQueue).start(next: { phoneNumber in + if let navigationController = navigationController { + present(.modal, logoutOptionsController(context: context, navigationController: navigationController, canAddAccounts: canAddAccount, phoneNumber: phoneNumber)) + } + }) + })) + return items } private func callSearchableItems(context: AccountContext) -> [SettingsSearchableItem] { @@ -60,10 +113,10 @@ private func callSearchableItems(context: AccountContext) -> [SettingsSearchable } return [ - SettingsSearchableItem(id: .calls(0), title: strings.CallSettings_RecentCalls, alternate: [], icon: icon, breadcrumbs: [], present: { context, present in + SettingsSearchableItem(id: .calls(0), title: strings.CallSettings_RecentCalls, alternate: [], icon: icon, breadcrumbs: [], present: { context, _, present in presentCallSettings(context, present) }), - SettingsSearchableItem(id: .calls(1), title: strings.CallSettings_TabIcon, alternate: [], icon: icon, breadcrumbs: [strings.CallSettings_RecentCalls], present: { context, present in + SettingsSearchableItem(id: .calls(1), title: strings.CallSettings_TabIcon, alternate: [], icon: icon, breadcrumbs: [strings.CallSettings_RecentCalls], present: { context, _, present in presentCallSettings(context, present) }) ] @@ -79,23 +132,23 @@ private func stickerSearchableItems(context: AccountContext) -> [SettingsSearcha } return [ - SettingsSearchableItem(id: .stickers(0), title: strings.ChatSettings_Stickers, alternate: [], icon: icon, breadcrumbs: [], present: { context, present in + SettingsSearchableItem(id: .stickers(0), title: strings.ChatSettings_Stickers, alternate: [], icon: icon, breadcrumbs: [], present: { context, _, present in presentStickerSettings(context, present, nil) }), - SettingsSearchableItem(id: .stickers(1), title: strings.Stickers_SuggestStickers, alternate: [], icon: icon, breadcrumbs: [strings.ChatSettings_Stickers], present: { context, present in + SettingsSearchableItem(id: .stickers(1), title: strings.Stickers_SuggestStickers, alternate: [], icon: icon, breadcrumbs: [strings.ChatSettings_Stickers], present: { context, _, present in presentStickerSettings(context, present, .suggestOptions) }), - SettingsSearchableItem(id: .stickers(2), title: strings.StickerPacksSettings_FeaturedPacks, alternate: [], icon: icon, breadcrumbs: [strings.ChatSettings_Stickers], present: { context, present in + SettingsSearchableItem(id: .stickers(2), title: strings.StickerPacksSettings_FeaturedPacks, alternate: [], icon: icon, breadcrumbs: [strings.ChatSettings_Stickers], present: { context, _, present in present(.push, featuredStickerPacksController(context: context)) }), - SettingsSearchableItem(id: .stickers(3), title: strings.StickerPacksSettings_ArchivedPacks, alternate: [], icon: icon, breadcrumbs: [strings.ChatSettings_Stickers], present: { context, present in + SettingsSearchableItem(id: .stickers(3), title: strings.StickerPacksSettings_ArchivedPacks, alternate: [], icon: icon, breadcrumbs: [strings.ChatSettings_Stickers], present: { context, _, present in present(.push, archivedStickerPacksController(context: context, mode: .stickers, archived: nil, updatedPacks: { _ in })) }), - SettingsSearchableItem(id: .stickers(4), title: strings.MaskStickerSettings_Title, alternate: [], icon: icon, breadcrumbs: [strings.ChatSettings_Stickers], present: { context, present in + SettingsSearchableItem(id: .stickers(4), title: strings.MaskStickerSettings_Title, alternate: [], icon: icon, breadcrumbs: [strings.ChatSettings_Stickers], present: { context, _, present in present(.push, installedStickerPacksController(context: context, mode: .masks, archivedPacks: nil, updatedPacks: { _ in})) }), - SettingsSearchableItem(id: .stickers(5), title: strings.StickerPacksSettings_ArchivedMasks, alternate: [], icon: icon, breadcrumbs: [strings.ChatSettings_Stickers, strings.MaskStickerSettings_Title], present: { context, present in + SettingsSearchableItem(id: .stickers(5), title: strings.StickerPacksSettings_ArchivedMasks, alternate: [], icon: icon, breadcrumbs: [strings.ChatSettings_Stickers, strings.MaskStickerSettings_Title], present: { context, _, present in present(.push, archivedStickerPacksController(context: context, mode: .masks, archived: nil, updatedPacks: { _ in })) }) @@ -111,64 +164,64 @@ private func notificationSearchableItems(context: AccountContext, notifyExceptio } return [ - SettingsSearchableItem(id: .notifications(0), title: strings.Settings_NotificationsAndSounds, alternate: [], icon: icon, breadcrumbs: [], present: { context, present in + SettingsSearchableItem(id: .notifications(0), title: strings.Settings_NotificationsAndSounds, alternate: [], icon: icon, breadcrumbs: [], present: { context, _, present in presentNotificationSettings(context, present, nil) }), - SettingsSearchableItem(id: .notifications(1), title: strings.Notifications_MessageNotificationsAlert, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_MessageNotifications.capitalized], present: { context, present in + SettingsSearchableItem(id: .notifications(1), title: strings.Notifications_MessageNotificationsAlert, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_MessageNotifications.capitalized], present: { context, _, present in presentNotificationSettings(context, present, .messageAlerts) }), - SettingsSearchableItem(id: .notifications(2), title: strings.Notifications_MessageNotificationsPreview, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_MessageNotifications.capitalized], present: { context, present in + SettingsSearchableItem(id: .notifications(2), title: strings.Notifications_MessageNotificationsPreview, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_MessageNotifications.capitalized], present: { context, _, present in presentNotificationSettings(context, present, .messagePreviews) }), - SettingsSearchableItem(id: .notifications(3), title: strings.Notifications_MessageNotificationsSound, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_MessageNotifications.capitalized], present: { context, present in + SettingsSearchableItem(id: .notifications(3), title: strings.Notifications_MessageNotificationsSound, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_MessageNotifications.capitalized], present: { context, _, present in presentNotificationSettings(context, present, nil) }), - SettingsSearchableItem(id: .notifications(4), title: strings.Notifications_GroupNotificationsAlert, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_GroupNotifications.capitalized], present: { context, present in + SettingsSearchableItem(id: .notifications(4), title: strings.Notifications_GroupNotificationsAlert, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_GroupNotifications.capitalized], present: { context, _, present in presentNotificationSettings(context, present, .groupAlerts) }), - SettingsSearchableItem(id: .notifications(5), title: strings.Notifications_GroupNotificationsPreview, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_GroupNotifications.capitalized], present: { context, present in + SettingsSearchableItem(id: .notifications(5), title: strings.Notifications_GroupNotificationsPreview, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_GroupNotifications.capitalized], present: { context, _, present in presentNotificationSettings(context, present, .groupPreviews) }), - SettingsSearchableItem(id: .notifications(6), title: strings.Notifications_GroupNotificationsSound, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_GroupNotifications.capitalized], present: { context, present in + SettingsSearchableItem(id: .notifications(6), title: strings.Notifications_GroupNotificationsSound, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_GroupNotifications.capitalized], present: { context, _, present in presentNotificationSettings(context, present, nil) }), - SettingsSearchableItem(id: .notifications(7), title: strings.Notifications_ChannelNotificationsAlert, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_ChannelNotifications.capitalized], present: { context, present in + SettingsSearchableItem(id: .notifications(7), title: strings.Notifications_ChannelNotificationsAlert, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_ChannelNotifications.capitalized], present: { context, _, present in presentNotificationSettings(context, present, .channelAlerts) }), - SettingsSearchableItem(id: .notifications(8), title: strings.Notifications_ChannelNotificationsPreview, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_ChannelNotifications.capitalized], present: { context, present in + SettingsSearchableItem(id: .notifications(8), title: strings.Notifications_ChannelNotificationsPreview, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_ChannelNotifications.capitalized], present: { context, _, present in presentNotificationSettings(context, present, .channelPreviews) }), - SettingsSearchableItem(id: .notifications(9), title: strings.Notifications_ChannelNotificationsSound, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_ChannelNotifications.capitalized], present: { context, present in + SettingsSearchableItem(id: .notifications(9), title: strings.Notifications_ChannelNotificationsSound, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_ChannelNotifications.capitalized], present: { context, _, present in presentNotificationSettings(context, present, nil) }), - SettingsSearchableItem(id: .notifications(10), title: strings.Notifications_InAppNotificationsSounds, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_InAppNotifications.capitalized], present: { context, present in + SettingsSearchableItem(id: .notifications(10), title: strings.Notifications_InAppNotificationsSounds, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_InAppNotifications.capitalized], present: { context, _, present in presentNotificationSettings(context, present, .inAppSounds) }), - SettingsSearchableItem(id: .notifications(11), title: strings.Notifications_InAppNotificationsVibrate, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_InAppNotifications.capitalized], present: { context, present in + SettingsSearchableItem(id: .notifications(11), title: strings.Notifications_InAppNotificationsVibrate, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_InAppNotifications.capitalized], present: { context, _, present in presentNotificationSettings(context, present, .inAppVibrate) }), - SettingsSearchableItem(id: .notifications(12), title: strings.Notifications_InAppNotificationsPreview, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_InAppNotifications.capitalized], present: { context, present in + SettingsSearchableItem(id: .notifications(12), title: strings.Notifications_InAppNotificationsPreview, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_InAppNotifications.capitalized], present: { context, _, present in presentNotificationSettings(context, present, .inAppPreviews) }), - SettingsSearchableItem(id: .notifications(13), title: strings.Notifications_DisplayNamesOnLockScreen, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds], present: { context, present in + SettingsSearchableItem(id: .notifications(13), title: strings.Notifications_DisplayNamesOnLockScreen, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds], present: { context, _, present in presentNotificationSettings(context, present, .displayNamesOnLockscreen) }), - SettingsSearchableItem(id: .notifications(14), title: strings.Notifications_Badge_IncludeMutedChats, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_Badge.capitalized], present: { context, present in + SettingsSearchableItem(id: .notifications(14), title: strings.Notifications_Badge_IncludeMutedChats, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_Badge.capitalized], present: { context, _, present in presentNotificationSettings(context, present, .unreadCountStyle) }), - SettingsSearchableItem(id: .notifications(15), title: strings.Notifications_Badge_IncludePublicGroups, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_Badge.capitalized], present: { context, present in + SettingsSearchableItem(id: .notifications(15), title: strings.Notifications_Badge_IncludePublicGroups, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_Badge.capitalized], present: { context, _, present in presentNotificationSettings(context, present, .includePublicGroups) }), - SettingsSearchableItem(id: .notifications(16), title: strings.Notifications_Badge_IncludeChannels, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_Badge.capitalized], present: { context, present in + SettingsSearchableItem(id: .notifications(16), title: strings.Notifications_Badge_IncludeChannels, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_Badge.capitalized], present: { context, _, present in presentNotificationSettings(context, present, .includeChannels) }), - SettingsSearchableItem(id: .notifications(17), title: strings.Notifications_Badge_CountUnreadMessages, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_Badge.capitalized], present: { context, present in + SettingsSearchableItem(id: .notifications(17), title: strings.Notifications_Badge_CountUnreadMessages, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_Badge.capitalized], present: { context, _, present in presentNotificationSettings(context, present, .unreadCountCategory) }), - SettingsSearchableItem(id: .notifications(18), title: strings.NotificationSettings_ContactJoined, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds], present: { context, present in + SettingsSearchableItem(id: .notifications(18), title: strings.NotificationSettings_ContactJoined, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds], present: { context, _, present in presentNotificationSettings(context, present, .joinedNotifications) }), - SettingsSearchableItem(id: .notifications(19), title: strings.Notifications_ResetAllNotifications, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds], present: { context, present in + SettingsSearchableItem(id: .notifications(19), title: strings.Notifications_ResetAllNotifications, alternate: [], icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds], present: { context, _, present in presentNotificationSettings(context, present, .reset) }) ] @@ -240,28 +293,28 @@ private func privacySearchableItems(context: AccountContext) -> [SettingsSearcha } return [ - SettingsSearchableItem(id: .privacy(0), title: strings.Settings_PrivacySettings, alternate: [], icon: icon, breadcrumbs: [], present: { context, present in + SettingsSearchableItem(id: .privacy(0), title: strings.Settings_PrivacySettings, alternate: [], icon: icon, breadcrumbs: [], present: { context, _, present in presentPrivacySettings(context, present) }), - SettingsSearchableItem(id: .privacy(1), title: strings.Settings_BlockedUsers, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, present in + SettingsSearchableItem(id: .privacy(1), title: strings.Settings_BlockedUsers, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, _, present in present(.push, blockedPeersController(context: context)) }), - SettingsSearchableItem(id: .privacy(2), title: strings.PrivacySettings_LastSeen, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, present in + SettingsSearchableItem(id: .privacy(2), title: strings.PrivacySettings_LastSeen, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, _, present in presentSelectivePrivacySettings(context, .presence, present) }), - SettingsSearchableItem(id: .privacy(3), title: strings.Privacy_ProfilePhoto, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, present in + SettingsSearchableItem(id: .privacy(3), title: strings.Privacy_ProfilePhoto, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, _, present in presentSelectivePrivacySettings(context, .profilePhoto, present) }), - SettingsSearchableItem(id: .privacy(4), title: strings.Privacy_Forwards, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, present in + SettingsSearchableItem(id: .privacy(4), title: strings.Privacy_Forwards, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, _, present in presentSelectivePrivacySettings(context, .forwards, present) }), - SettingsSearchableItem(id: .privacy(5), title: strings.Privacy_Calls, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, present in + SettingsSearchableItem(id: .privacy(5), title: strings.Privacy_Calls, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, _, present in presentSelectivePrivacySettings(context, .voiceCalls, present) }), - SettingsSearchableItem(id: .privacy(6), title: strings.Privacy_GroupsAndChannels, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, present in + SettingsSearchableItem(id: .privacy(6), title: strings.Privacy_GroupsAndChannels, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, _, present in presentSelectivePrivacySettings(context, .groupInvitations, present) }), - SettingsSearchableItem(id: .privacy(7), title: passcodeTitle, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, present in + SettingsSearchableItem(id: .privacy(7), title: passcodeTitle, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, _, present in let _ = passcodeOptionsAccessController(context: context, completion: { animated in let controller = passcodeOptionsController(context: context) if animated { @@ -275,35 +328,35 @@ private func privacySearchableItems(context: AccountContext) -> [SettingsSearcha } }) }), - SettingsSearchableItem(id: .privacy(8), title: strings.PrivacySettings_TwoStepAuth, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, present in + SettingsSearchableItem(id: .privacy(8), title: strings.PrivacySettings_TwoStepAuth, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, _, present in present(.modal, twoStepVerificationUnlockSettingsController(context: context, mode: .access)) }), - SettingsSearchableItem(id: .privacy(9), title: strings.PrivacySettings_AuthSessions, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, present in + SettingsSearchableItem(id: .privacy(9), title: strings.PrivacySettings_AuthSessions, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, _, present in present(.push, recentSessionsController(context: context)) }), - SettingsSearchableItem(id: .privacy(10), title: strings.PrivacySettings_DeleteAccountTitle.capitalized, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, present in + SettingsSearchableItem(id: .privacy(10), title: strings.PrivacySettings_DeleteAccountTitle.capitalized, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, _, present in presentPrivacySettings(context, present) }), - SettingsSearchableItem(id: .privacy(11), title: strings.PrivacySettings_DataSettings, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, present in + SettingsSearchableItem(id: .privacy(11), title: strings.PrivacySettings_DataSettings, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, _, present in presentDataPrivacySettings(context, present) }), - SettingsSearchableItem(id: .privacy(12), title: strings.Privacy_ContactsReset, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings, strings.PrivacySettings_DataSettings], present: { context, present in + SettingsSearchableItem(id: .privacy(12), title: strings.Privacy_ContactsReset, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings, strings.PrivacySettings_DataSettings], present: { context, _, present in presentDataPrivacySettings(context, present) }), - SettingsSearchableItem(id: .privacy(13), title: strings.Privacy_ContactsSync, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings, strings.PrivacySettings_DataSettings], present: { context, present in + SettingsSearchableItem(id: .privacy(13), title: strings.Privacy_ContactsSync, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings, strings.PrivacySettings_DataSettings], present: { context, _, present in presentDataPrivacySettings(context, present) }), - SettingsSearchableItem(id: .privacy(14), title: strings.Privacy_TopPeers, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings, strings.PrivacySettings_DataSettings], present: { context, present in + SettingsSearchableItem(id: .privacy(14), title: strings.Privacy_TopPeers, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings, strings.PrivacySettings_DataSettings], present: { context, _, present in presentDataPrivacySettings(context, present) }), - SettingsSearchableItem(id: .privacy(15), title: strings.Privacy_DeleteDrafts, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings, strings.PrivacySettings_DataSettings], present: { context, present in + SettingsSearchableItem(id: .privacy(15), title: strings.Privacy_DeleteDrafts, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings, strings.PrivacySettings_DataSettings], present: { context, _, present in presentDataPrivacySettings(context, present) }), - SettingsSearchableItem(id: .privacy(16), title: strings.Privacy_PaymentsClearInfo, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings, strings.PrivacySettings_DataSettings], present: { context, present in + SettingsSearchableItem(id: .privacy(16), title: strings.Privacy_PaymentsClearInfo, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings, strings.PrivacySettings_DataSettings], present: { context, _, present in presentDataPrivacySettings(context, present) }), - SettingsSearchableItem(id: .privacy(17), title: strings.Privacy_SecretChatsLinkPreviews, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings, strings.PrivacySettings_DataSettings, strings.Privacy_SecretChatsTitle], present: { context, present in + SettingsSearchableItem(id: .privacy(17), title: strings.Privacy_SecretChatsLinkPreviews, alternate: [], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings, strings.PrivacySettings_DataSettings, strings.Privacy_SecretChatsTitle], present: { context, _, present in presentDataPrivacySettings(context, present) }) ] @@ -318,46 +371,46 @@ private func dataSearchableItems(context: AccountContext) -> [SettingsSearchable } return [ - SettingsSearchableItem(id: .data(0), title: strings.Settings_ChatSettings, alternate: [], icon: icon, breadcrumbs: [], present: { context, present in + SettingsSearchableItem(id: .data(0), title: strings.Settings_ChatSettings, alternate: [], icon: icon, breadcrumbs: [], present: { context, _, present in presentDataSettings(context, present, nil) }), - SettingsSearchableItem(id: .data(1), title: strings.ChatSettings_Cache, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings], present: { context, present in + SettingsSearchableItem(id: .data(1), title: strings.ChatSettings_Cache, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings], present: { context, _, present in present(.push, storageUsageController(context: context)) }), - SettingsSearchableItem(id: .data(2), title: strings.Cache_KeepMedia, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings, strings.ChatSettings_Cache], present: { context, present in + SettingsSearchableItem(id: .data(2), title: strings.Cache_KeepMedia, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings, strings.ChatSettings_Cache], present: { context, _, present in present(.push, storageUsageController(context: context)) }), - SettingsSearchableItem(id: .data(3), title: strings.Cache_ClearCache, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings, strings.ChatSettings_Cache], present: { context, present in + SettingsSearchableItem(id: .data(3), title: strings.Cache_ClearCache, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings, strings.ChatSettings_Cache], present: { context, _, present in present(.push, storageUsageController(context: context)) }), - SettingsSearchableItem(id: .data(4), title: strings.NetworkUsageSettings_Title, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings], present: { context, present in + SettingsSearchableItem(id: .data(4), title: strings.NetworkUsageSettings_Title, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings], present: { context, _, present in present(.push, networkUsageStatsController(context: context)) }), - SettingsSearchableItem(id: .data(5), title: strings.ChatSettings_AutoDownloadUsingCellular, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings, strings.ChatSettings_AutoDownloadTitle.capitalized], present: { context, present in + SettingsSearchableItem(id: .data(5), title: strings.ChatSettings_AutoDownloadUsingCellular, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings, strings.ChatSettings_AutoDownloadTitle.capitalized], present: { context, _, present in present(.push, autodownloadMediaConnectionTypeController(context: context, connectionType: .cellular)) }), - SettingsSearchableItem(id: .data(6), title: strings.ChatSettings_AutoDownloadUsingWiFi, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings, strings.ChatSettings_AutoDownloadTitle.capitalized], present: { context, present in + SettingsSearchableItem(id: .data(6), title: strings.ChatSettings_AutoDownloadUsingWiFi, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings, strings.ChatSettings_AutoDownloadTitle.capitalized], present: { context, _, present in present(.push, autodownloadMediaConnectionTypeController(context: context, connectionType: .wifi)) }), - SettingsSearchableItem(id: .data(7), title: strings.ChatSettings_AutoDownloadReset, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings], present: { context, present in + SettingsSearchableItem(id: .data(7), title: strings.ChatSettings_AutoDownloadReset, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings], present: { context, _, present in presentDataSettings(context, present, .automaticDownloadReset) }), - SettingsSearchableItem(id: .data(8), title: strings.ChatSettings_AutoPlayGifs, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings, strings.ChatSettings_AutoPlayTitle], present: { context, present in + SettingsSearchableItem(id: .data(8), title: strings.ChatSettings_AutoPlayGifs, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings, strings.ChatSettings_AutoPlayTitle], present: { context, _, present in presentDataSettings(context, present, .autoplayGifs) }), - SettingsSearchableItem(id: .data(9), title: strings.ChatSettings_AutoPlayVideos, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings, strings.ChatSettings_AutoPlayTitle], present: { context, present in + SettingsSearchableItem(id: .data(9), title: strings.ChatSettings_AutoPlayVideos, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings, strings.ChatSettings_AutoPlayTitle], present: { context, _, present in presentDataSettings(context, present, .autoplayVideos) }), - SettingsSearchableItem(id: .data(10), title: strings.CallSettings_UseLessData, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings, strings.Settings_CallSettings], present: { context, present in + SettingsSearchableItem(id: .data(10), title: strings.CallSettings_UseLessData, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings, strings.Settings_CallSettings], present: { context, _, present in present(.push, voiceCallDataSavingController(context: context)) }), - SettingsSearchableItem(id: .data(11), title: strings.Settings_SaveIncomingPhotos, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings], present: { context, present in + SettingsSearchableItem(id: .data(11), title: strings.Settings_SaveIncomingPhotos, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings], present: { context, _, present in present(.push, saveIncomingMediaController(context: context)) }), - SettingsSearchableItem(id: .data(12), title: strings.Settings_SaveEditedPhotos, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings], present: { context, present in + SettingsSearchableItem(id: .data(12), title: strings.Settings_SaveEditedPhotos, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings], present: { context, _, present in presentDataSettings(context, present, .saveEditedPhotos) }), - SettingsSearchableItem(id: .data(13), title: strings.ChatSettings_DownloadInBackground, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings], present: { context, present in + SettingsSearchableItem(id: .data(13), title: strings.ChatSettings_DownloadInBackground, alternate: [], icon: icon, breadcrumbs: [strings.Settings_ChatSettings], present: { context, _, present in presentDataSettings(context, present, .downloadInBackground) }) ] @@ -372,13 +425,13 @@ private func proxySearchableItems(context: AccountContext) -> [SettingsSearchabl } return [ - SettingsSearchableItem(id: .proxy(0), title: strings.Settings_Proxy, alternate: [], icon: icon, breadcrumbs: [], present: { context, present in + SettingsSearchableItem(id: .proxy(0), title: strings.Settings_Proxy, alternate: [], icon: icon, breadcrumbs: [], present: { context, _, present in presentProxySettings(context, present) }), - SettingsSearchableItem(id: .proxy(1), title: strings.SocksProxySetup_AddProxy, alternate: [], icon: icon, breadcrumbs: [strings.Settings_Proxy], present: { context, present in + SettingsSearchableItem(id: .proxy(1), title: strings.SocksProxySetup_AddProxy, alternate: [], icon: icon, breadcrumbs: [strings.Settings_Proxy], present: { context, _, present in present(.modal, proxyServerSettingsController(context: context)) }), - SettingsSearchableItem(id: .proxy(2), title: strings.SocksProxySetup_UseForCalls, alternate: [], icon: icon, breadcrumbs: [strings.Settings_Proxy], present: { context, present in + SettingsSearchableItem(id: .proxy(2), title: strings.SocksProxySetup_UseForCalls, alternate: [], icon: icon, breadcrumbs: [strings.Settings_Proxy], present: { context, _, present in presentProxySettings(context, present) }) ] @@ -393,45 +446,53 @@ private func appearanceSearchableItems(context: AccountContext) -> [SettingsSear } return [ - SettingsSearchableItem(id: .appearance(0), title: strings.Settings_Appearance, alternate: [], icon: icon, breadcrumbs: [], present: { context, present in + SettingsSearchableItem(id: .appearance(0), title: strings.Settings_Appearance, alternate: [], icon: icon, breadcrumbs: [], present: { context, _, present in presentAppearanceSettings(context, present, nil) }), - SettingsSearchableItem(id: .appearance(1), title: strings.Appearance_TextSize.capitalized, alternate: [], icon: icon, breadcrumbs: [strings.Settings_Appearance], present: { context, present in + SettingsSearchableItem(id: .appearance(1), title: strings.Appearance_TextSize.capitalized, alternate: [], icon: icon, breadcrumbs: [strings.Settings_Appearance], present: { context, _, present in presentAppearanceSettings(context, present, .fontSize) }), - SettingsSearchableItem(id: .appearance(2), title: strings.Settings_ChatBackground, alternate: ["Wallpaper"], icon: icon, breadcrumbs: [strings.Settings_Appearance], present: { context, present in + SettingsSearchableItem(id: .appearance(2), title: strings.Settings_ChatBackground, alternate: ["Wallpaper"], icon: icon, breadcrumbs: [strings.Settings_Appearance], present: { context, _, present in present(.push, ThemeGridController(context: context)) }), - SettingsSearchableItem(id: .appearance(3), title: strings.Wallpaper_SetColor, alternate: [], icon: icon, breadcrumbs: [strings.Settings_Appearance, strings.Settings_ChatBackground], present: { context, present in + SettingsSearchableItem(id: .appearance(3), title: strings.Wallpaper_SetColor, alternate: [], icon: icon, breadcrumbs: [strings.Settings_Appearance, strings.Settings_ChatBackground], present: { context, _, present in present(.push, ThemeColorsGridController(context: context)) }), - SettingsSearchableItem(id: .appearance(4), title: strings.Wallpaper_SetCustomBackground, alternate: [], icon: icon, breadcrumbs: [strings.Settings_Appearance, strings.Settings_ChatBackground], present: { context, present in + SettingsSearchableItem(id: .appearance(4), title: strings.Wallpaper_SetCustomBackground, alternate: [], icon: icon, breadcrumbs: [strings.Settings_Appearance, strings.Settings_ChatBackground], present: { context, _, present in presentCustomWallpaperPicker(context: context, present: { controller in present(.immediate, controller) }) }), - SettingsSearchableItem(id: .appearance(5), title: strings.Appearance_AutoNightTheme, alternate: [], icon: icon, breadcrumbs: [strings.Settings_Appearance], present: { context, present in + SettingsSearchableItem(id: .appearance(5), title: strings.Appearance_AutoNightTheme, alternate: [], icon: icon, breadcrumbs: [strings.Settings_Appearance], present: { context, _, present in present(.push, themeAutoNightSettingsController(context: context)) }), - SettingsSearchableItem(id: .appearance(6), title: strings.Appearance_ColorTheme.capitalized, alternate: [], icon: icon, breadcrumbs: [strings.Settings_Appearance], present: { context, present in + SettingsSearchableItem(id: .appearance(6), title: strings.Appearance_ColorTheme.capitalized, alternate: [], icon: icon, breadcrumbs: [strings.Settings_Appearance], present: { context, _, present in presentAppearanceSettings(context, present, .accentColor) }), - SettingsSearchableItem(id: .appearance(7), title: strings.Appearance_ReduceMotion, alternate: ["Animations"], icon: icon, breadcrumbs: [strings.Settings_Appearance, strings.Appearance_Animations.capitalized], present: { context, present in + SettingsSearchableItem(id: .appearance(7), title: strings.Appearance_ReduceMotion, alternate: ["Animations"], icon: icon, breadcrumbs: [strings.Settings_Appearance, strings.Appearance_Animations.capitalized], present: { context, _, present in presentAppearanceSettings(context, present, .animations) }), ] } func settingsSearchableItems(context: AccountContext) -> Signal<[SettingsSearchableItem], NoError> { - let watchAppInstalled = context.watchManager?.watchAppInstalled ?? .single(false) - return watchAppInstalled + let watchAppInstalled = (context.watchManager?.watchAppInstalled ?? .single(false)) |> take(1) - |> map { watchAppInstalled in + let canAddAccount = activeAccountsAndPeers(context: context) + |> take(1) + |> map { accountsAndPeers -> Bool in + return accountsAndPeers.1.count + 1 < maximumNumberOfAccounts + } + return combineLatest(watchAppInstalled, canAddAccount) + |> map { watchAppInstalled, canAddAccount in let strings = context.sharedContext.currentPresentationData.with { $0 }.strings var allItems: [SettingsSearchableItem] = [] - let savedMessages = SettingsSearchableItem(id: .savedMessages(0), title: strings.Settings_SavedMessages, alternate: [], icon: .savedMessages, breadcrumbs: [], present: { context, present in + let profileItems = profileSearchableItems(context: context, canAddAccount: canAddAccount) + allItems.append(contentsOf: profileItems) + + let savedMessages = SettingsSearchableItem(id: .savedMessages(0), title: strings.Settings_SavedMessages, alternate: [], icon: .savedMessages, breadcrumbs: [], present: { context, _, present in present(.push, ChatController(context: context, chatLocation: .peer(context.account.peerId))) }) allItems.append(savedMessages) @@ -457,22 +518,29 @@ func settingsSearchableItems(context: AccountContext) -> Signal<[SettingsSearcha let appearanceItems = appearanceSearchableItems(context: context) allItems.append(contentsOf: appearanceItems) - let language = SettingsSearchableItem(id: .language(0), title: strings.Settings_AppLanguage, alternate: [], icon: .language, breadcrumbs: [], present: { context, present in + let language = SettingsSearchableItem(id: .language(0), title: strings.Settings_AppLanguage, alternate: [], icon: .language, breadcrumbs: [], present: { context, _, present in present(.push, LocalizationListController(context: context)) }) allItems.append(language) - let passport = SettingsSearchableItem(id: .passport(0), title: strings.Settings_Passport, alternate: [], icon: .passport, breadcrumbs: [], present: { context, present in + if watchAppInstalled { + let watch = SettingsSearchableItem(id: .watch(0), title: strings.Settings_AppleWatch, alternate: [], icon: .watch, breadcrumbs: [], present: { context, _, present in + present(.push, watchSettingsController(context: context)) + }) + allItems.append(watch) + } + + let passport = SettingsSearchableItem(id: .passport(0), title: strings.Settings_Passport, alternate: [], icon: .passport, breadcrumbs: [], present: { context, _, present in present(.modal, SecureIdAuthController(context: context, mode: .list)) }) allItems.append(passport) - let support = SettingsSearchableItem(id: .support(0), title: strings.Settings_Support, alternate: ["Support"], icon: .support, breadcrumbs: [], present: { context, present in + let support = SettingsSearchableItem(id: .support(0), title: strings.Settings_Support, alternate: ["Support"], icon: .support, breadcrumbs: [], present: { context, _, present in //return .push(ChatController(context: context, chatLocation: .peer(context.account.peerId))) }) allItems.append(support) - let faq = SettingsSearchableItem(id: .faq(0), title: strings.Settings_FAQ, alternate: [], icon: .faq, breadcrumbs: [], present: { context, present in + let faq = SettingsSearchableItem(id: .faq(0), title: strings.Settings_FAQ, alternate: [], icon: .faq, breadcrumbs: [], present: { context, _, present in //return .push(ChatController(context: context, chatLocation: .peer(context.account.peerId))) }) allItems.append(faq) @@ -535,7 +603,6 @@ private func matchStringTokens(_ tokens: [ValueBoxKey], with other: [ValueBoxKey return false } - func searchSettingsItems(items: [SettingsSearchableItem], query: String) -> [SettingsSearchableItem] { let queryTokens = stringTokens(query.lowercased()) diff --git a/TelegramUI/SharedMediaPlayer.swift b/TelegramUI/SharedMediaPlayer.swift index 6c11d91e74..8484a670a2 100644 --- a/TelegramUI/SharedMediaPlayer.swift +++ b/TelegramUI/SharedMediaPlayer.swift @@ -466,13 +466,13 @@ final class SharedMediaPlayer { case .voice, .music: switch playbackData.source { case let .telegramFile(fileReference): - strongSelf.playbackItem = .audio(MediaPlayer(audioSessionManager: strongSelf.audioSession, postbox: strongSelf.account.postbox, resourceReference: fileReference.resourceReference(fileReference.media.resource), streamable: playbackData.type == .music, video: false, preferSoftwareDecoding: false, enableSound: true, baseRate: rateValue, fetchAutomatically: true, playAndRecord: controlPlaybackWithProximity)) + strongSelf.playbackItem = .audio(MediaPlayer(audioSessionManager: strongSelf.audioSession, postbox: strongSelf.account.postbox, resourceReference: fileReference.resourceReference(fileReference.media.resource), streamable: playbackData.type == .music ? .conservative : .none, video: false, preferSoftwareDecoding: false, enableSound: true, baseRate: rateValue, fetchAutomatically: true, playAndRecord: controlPlaybackWithProximity)) } case .instantVideo: if let mediaManager = strongSelf.mediaManager, let item = item as? MessageMediaPlaylistItem { switch playbackData.source { case let .telegramFile(fileReference): - let videoNode = OverlayInstantVideoNode(postbox: strongSelf.account.postbox, audioSession: strongSelf.audioSession, manager: mediaManager.universalVideoManager, content: NativeVideoContent(id: .message(item.message.id, item.message.stableId, fileReference.media.fileId), fileReference: fileReference, streamVideo: false, enableSound: false, baseRate: rateValue), close: { [weak mediaManager] in + let videoNode = OverlayInstantVideoNode(postbox: strongSelf.account.postbox, audioSession: strongSelf.audioSession, manager: mediaManager.universalVideoManager, content: NativeVideoContent(id: .message(item.message.id, item.message.stableId, fileReference.media.fileId), fileReference: fileReference, enableSound: false, baseRate: rateValue), close: { [weak mediaManager] in mediaManager?.setPlaylist(nil, type: .voice) }) strongSelf.playbackItem = .instantVideo(videoNode) diff --git a/TelegramUI/ThemeSettingsController.swift b/TelegramUI/ThemeSettingsController.swift index 7fdb0dd491..12c29ed9fa 100644 --- a/TelegramUI/ThemeSettingsController.swift +++ b/TelegramUI/ThemeSettingsController.swift @@ -189,7 +189,7 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry { case let .fontSize(theme, fontSize): return ThemeSettingsFontSizeItem(theme: theme, fontSize: fontSize, sectionId: self.section, updated: { value in arguments.selectFontSize(value) - }) + }, tag: ThemeSettingsEntryTag.fontSize) case let .chatPreviewHeader(theme, text): return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section) case let .chatPreview(theme, componentTheme, wallpaper, fontSize, strings, dateTimeFormat, nameDisplayOrder): @@ -201,7 +201,7 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry { case let .accentColor(theme, text, color): return ItemListDisclosureItem(theme: theme, icon: nil, title: text, label: "", labelStyle: .color(UIColor(rgb: UInt32(bitPattern: color))), sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { arguments.openAccentColor(color) - }) + }, tag: ThemeSettingsEntryTag.accentColor) case let .autoNightTheme(theme, text, value): return ItemListDisclosureItem(theme: theme, icon: nil, title: text, label: value, labelStyle: .text, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { arguments.openAutoNightTheme() @@ -217,7 +217,7 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry { case let .animations(theme, title, value): return ItemListSwitchItem(theme: theme, title: title, value: value, sectionId: self.section, style: .blocks, updated: { value in arguments.disableAnimations(value) - }) + }, tag: ThemeSettingsEntryTag.animations) case let .animationsInfo(theme, text): return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section) } diff --git a/TelegramUI/ThemeSettingsFontSizeItem.swift b/TelegramUI/ThemeSettingsFontSizeItem.swift index 0c3782a16c..3d0d1f2e0a 100644 --- a/TelegramUI/ThemeSettingsFontSizeItem.swift +++ b/TelegramUI/ThemeSettingsFontSizeItem.swift @@ -64,7 +64,7 @@ private func generateKnobImage() -> UIImage? { }) } -class ThemeSettingsFontSizeItemNode: ListViewItemNode { +class ThemeSettingsFontSizeItemNode: ListViewItemNode, ItemListItemNode { private let backgroundNode: ASDisplayNode private let topStripeNode: ASDisplayNode private let bottomStripeNode: ASDisplayNode @@ -76,7 +76,7 @@ class ThemeSettingsFontSizeItemNode: ListViewItemNode { private var item: ThemeSettingsFontSizeItem? private var layoutParams: ListViewItemLayoutParams? - var tag: Any? { + var tag: ItemListItemTag? { return self.item?.tag } diff --git a/TelegramUI/UniversalVideoContentManager.swift b/TelegramUI/UniversalVideoContentManager.swift index ef475c4a02..e5fa3b9c28 100644 --- a/TelegramUI/UniversalVideoContentManager.swift +++ b/TelegramUI/UniversalVideoContentManager.swift @@ -302,6 +302,6 @@ final class UniversalVideoContentManager { } } } - } |> runOn(Queue.mainQueue()) + } |> runOn(Queue.mainQueue()) } } diff --git a/TelegramUI/UniversalVideoGalleryItem.swift b/TelegramUI/UniversalVideoGalleryItem.swift index 5fb353bfdb..0ed9afabf7 100644 --- a/TelegramUI/UniversalVideoGalleryItem.swift +++ b/TelegramUI/UniversalVideoGalleryItem.swift @@ -418,7 +418,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { } } default: - if let content = item.content as? NativeVideoContent, !content.streamVideo { + if let content = item.content as? NativeVideoContent, !content.streamVideo.enabled { if !content.enableSound { isPaused = false } @@ -557,10 +557,21 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { if let videoNode = self.videoNode { if isCentral { + var isAnimated = false + if let item = self.item, let content = item.content as? NativeVideoContent { + isAnimated = content.fileReference.media.isAnimated + } + self.hideStatusNodeUntilCentrality = false - if self.shouldAutoplayOnCentrality() { - self.initiallyActivated = true - videoNode.playOnceWithSound(playAndRecord: false, actionAtEnd: .stop) + if videoNode.ownsContentNode { + if isAnimated { + videoNode.seek(0.0) + videoNode.play() + } + else if self.shouldAutoplayOnCentrality() { + self.initiallyActivated = true + videoNode.playOnceWithSound(playAndRecord: false, actionAtEnd: .stop) + } } } else { self.dismissOnOrientationChange = false @@ -604,7 +615,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { override func activateAsInitial() { if let videoNode = self.videoNode, self.isCentral { self.initiallyActivated = true - + var isAnimated = false if let item = self.item, let content = item.content as? NativeVideoContent { isAnimated = content.fileReference.media.isAnimated @@ -708,9 +719,11 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { videoNode.layer.animate(from: NSValue(caTransform3D: transform), to: NSValue(caTransform3D: videoNode.layer.transform), keyPath: "transform", timingFunction: kCAMediaTimingFunctionSpring, duration: 0.25) - Queue.mainQueue().after(0.001) { - videoNode.canAttachContent = true - self.updateDisplayPlaceholder(!videoNode.ownsContentNode) + if self.item?.fromPlayingVideo ?? false { + Queue.mainQueue().after(0.001) { + videoNode.canAttachContent = true + self.updateDisplayPlaceholder(!videoNode.ownsContentNode) + } } if let pictureInPictureNode = self.pictureInPictureNode { diff --git a/TelegramUI/WebSearchGalleryController.swift b/TelegramUI/WebSearchGalleryController.swift index 9ab0b014f3..0f6c97e90d 100644 --- a/TelegramUI/WebSearchGalleryController.swift +++ b/TelegramUI/WebSearchGalleryController.swift @@ -33,11 +33,11 @@ struct WebSearchGalleryEntry: Equatable { case let .externalReference(_, _, type, _, _, _, content, thumbnail, _): if let content = content, type == "gif", let thumbnailResource = thumbnail?.resource, let dimensions = content.dimensions { let fileReference = FileMediaReference.standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: 0), partialReference: nil, resource: content.resource, previewRepresentations: [TelegramMediaImageRepresentation(dimensions: dimensions, resource: thumbnailResource)], immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: [.Animated, .Video(duration: 0, size: dimensions, flags: [])])) - return WebSearchVideoGalleryItem(context: context, presentationData: presentationData, result: self.result, content: NativeVideoContent(id: .contextResult(self.result.queryId, self.result.id), fileReference: fileReference, streamVideo: false, loopVideo: true, enableSound: false, fetchAutomatically: true), controllerInteraction: controllerInteraction) + return WebSearchVideoGalleryItem(context: context, presentationData: presentationData, result: self.result, content: NativeVideoContent(id: .contextResult(self.result.queryId, self.result.id), fileReference: fileReference, loopVideo: true, enableSound: false, fetchAutomatically: true), controllerInteraction: controllerInteraction) } case let .internalReference(_, _, _, _, _, _, file, _): if let file = file { - return WebSearchVideoGalleryItem(context: context, presentationData: presentationData, result: self.result, content: NativeVideoContent(id: .contextResult(self.result.queryId, self.result.id), fileReference: .standalone(media: file), streamVideo: false, loopVideo: true, enableSound: false, fetchAutomatically: true), controllerInteraction: controllerInteraction) + return WebSearchVideoGalleryItem(context: context, presentationData: presentationData, result: self.result, content: NativeVideoContent(id: .contextResult(self.result.queryId, self.result.id), fileReference: .standalone(media: file), loopVideo: true, enableSound: false, fetchAutomatically: true), controllerInteraction: controllerInteraction) } } preconditionFailure() diff --git a/TelegramUI/WebSearchVideoGalleryItem.swift b/TelegramUI/WebSearchVideoGalleryItem.swift index a5ab708537..c30cf430b1 100644 --- a/TelegramUI/WebSearchVideoGalleryItem.swift +++ b/TelegramUI/WebSearchVideoGalleryItem.swift @@ -203,7 +203,7 @@ final class WebSearchVideoGalleryItemNode: ZoomableContentGalleryItemNode { } } default: - if let content = item.content as? NativeVideoContent, !content.streamVideo { + if let content = item.content as? NativeVideoContent, !content.streamVideo.enabled { if !content.enableSound { isPaused = false }