From 1c98c58138a51fa04c9906896041753eddac5e34 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 17 Jan 2020 21:48:45 +0400 Subject: [PATCH 01/50] Ignore holes in gallery message lists --- .../GalleryUI/Sources/GalleryController.swift | 2 +- .../Postbox/Sources/MessageHistoryView.swift | 12 +++++++----- .../Sources/MessageHistoryViewState.swift | 14 +++++++------- .../Sources/MessageOfInterestHolesView.swift | 6 +++--- submodules/Postbox/Sources/Postbox.swift | 16 ++++++++-------- 5 files changed, 26 insertions(+), 24 deletions(-) diff --git a/submodules/GalleryUI/Sources/GalleryController.swift b/submodules/GalleryUI/Sources/GalleryController.swift index 53b10ecb22..bdc0a7b29c 100644 --- a/submodules/GalleryUI/Sources/GalleryController.swift +++ b/submodules/GalleryUI/Sources/GalleryController.swift @@ -396,7 +396,7 @@ public class GalleryController: ViewController, StandalonePresentableController } else { namespaces = .not(Namespaces.Message.allScheduled) } - return context.account.postbox.aroundMessageHistoryViewForLocation(.peer(message!.id.peerId), anchor: .index(message!.index), count: 50, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tagMask: tags, namespaces: namespaces, orderStatistics: [.combinedLocation]) + return context.account.postbox.aroundMessageHistoryViewForLocation(.peer(message!.id.peerId), anchor: .index(message!.index), count: 50, clipHoles: false, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tagMask: tags, namespaces: namespaces, orderStatistics: [.combinedLocation]) |> mapToSignal { (view, _, _) -> Signal in let mapped = GalleryMessageHistoryView.view(view) return .single(mapped) diff --git a/submodules/Postbox/Sources/MessageHistoryView.swift b/submodules/Postbox/Sources/MessageHistoryView.swift index bc62626fe2..615ef4082c 100644 --- a/submodules/Postbox/Sources/MessageHistoryView.swift +++ b/submodules/Postbox/Sources/MessageHistoryView.swift @@ -258,6 +258,7 @@ final class MutableMessageHistoryView { let tag: MessageTags? let namespaces: MessageIdNamespaces private let orderStatistics: MessageHistoryViewOrderStatistics + private let clipHoles: Bool private let anchor: HistoryViewInputAnchor fileprivate var combinedReadStates: MessageHistoryViewReadState? @@ -271,10 +272,11 @@ final class MutableMessageHistoryView { fileprivate(set) var sampledState: HistoryViewSample - init(postbox: Postbox, orderStatistics: MessageHistoryViewOrderStatistics, peerIds: MessageHistoryViewPeerIds, anchor inputAnchor: HistoryViewInputAnchor, combinedReadStates: MessageHistoryViewReadState?, transientReadStates: MessageHistoryViewReadState?, tag: MessageTags?, namespaces: MessageIdNamespaces, count: Int, topTaggedMessages: [MessageId.Namespace: MessageHistoryTopTaggedMessage?], additionalDatas: [AdditionalMessageHistoryViewDataEntry], getMessageCountInRange: (MessageIndex, MessageIndex) -> Int32) { + init(postbox: Postbox, orderStatistics: MessageHistoryViewOrderStatistics, clipHoles: Bool, peerIds: MessageHistoryViewPeerIds, anchor inputAnchor: HistoryViewInputAnchor, combinedReadStates: MessageHistoryViewReadState?, transientReadStates: MessageHistoryViewReadState?, tag: MessageTags?, namespaces: MessageIdNamespaces, count: Int, topTaggedMessages: [MessageId.Namespace: MessageHistoryTopTaggedMessage?], additionalDatas: [AdditionalMessageHistoryViewDataEntry], getMessageCountInRange: (MessageIndex, MessageIndex) -> Int32) { self.anchor = inputAnchor self.orderStatistics = orderStatistics + self.clipHoles = clipHoles self.peerIds = peerIds self.combinedReadStates = combinedReadStates self.transientReadStates = transientReadStates @@ -290,12 +292,12 @@ final class MutableMessageHistoryView { switch sampledState { case let .ready(anchor, holes): self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: tag, namespaces: namespaces, statistics: self.orderStatistics, halfLimit: count + 1, locations: peerIds, postbox: postbox, holes: holes)) - self.sampledState = self.state.sample(postbox: postbox) + self.sampledState = self.state.sample(postbox: postbox, clipHoles: self.clipHoles) case .loadHole: break } } - self.sampledState = self.state.sample(postbox: postbox) + self.sampledState = self.state.sample(postbox: postbox, clipHoles: self.clipHoles) self.render(postbox: postbox) } @@ -320,7 +322,7 @@ final class MutableMessageHistoryView { break } } - self.sampledState = self.state.sample(postbox: postbox) + self.sampledState = self.state.sample(postbox: postbox, clipHoles: self.clipHoles) } func refreshDueToExternalTransaction(postbox: Postbox) -> Bool { @@ -509,7 +511,7 @@ final class MutableMessageHistoryView { break } } - self.sampledState = self.state.sample(postbox: postbox) + self.sampledState = self.state.sample(postbox: postbox, clipHoles: self.clipHoles) } for operationSet in operations { diff --git a/submodules/Postbox/Sources/MessageHistoryViewState.swift b/submodules/Postbox/Sources/MessageHistoryViewState.swift index 3ca9492b0c..10dd22b484 100644 --- a/submodules/Postbox/Sources/MessageHistoryViewState.swift +++ b/submodules/Postbox/Sources/MessageHistoryViewState.swift @@ -1134,7 +1134,7 @@ final class HistoryViewLoadedState { return updated } - func completeAndSample(postbox: Postbox) -> HistoryViewLoadedSample { + func completeAndSample(postbox: Postbox, clipHoles: Bool) -> HistoryViewLoadedSample { if !self.spacesWithRemovals.isEmpty { for space in self.spacesWithRemovals { self.fillSpace(space: space, postbox: postbox) @@ -1165,7 +1165,7 @@ final class HistoryViewLoadedState { entry = self.orderedEntriesBySpace[space]!.higherThanAnchor[index] } - if !clipRanges.isEmpty { + if clipHoles && !clipRanges.isEmpty { let entryIndex = entry.index for range in clipRanges { if range.contains(entryIndex) { @@ -1373,12 +1373,12 @@ enum HistoryViewState { } } - func sample(postbox: Postbox) -> HistoryViewSample { + func sample(postbox: Postbox, clipHoles: Bool) -> HistoryViewSample { switch self { - case let .loading(loadingState): - return .loading(loadingState.checkAndSample(postbox: postbox)) - case let .loaded(loadedState): - return .loaded(loadedState.completeAndSample(postbox: postbox)) + case let .loading(loadingState): + return .loading(loadingState.checkAndSample(postbox: postbox)) + case let .loaded(loadedState): + return .loaded(loadedState.completeAndSample(postbox: postbox, clipHoles: clipHoles)) } } } diff --git a/submodules/Postbox/Sources/MessageOfInterestHolesView.swift b/submodules/Postbox/Sources/MessageOfInterestHolesView.swift index efa86ca1ec..caa7f03362 100644 --- a/submodules/Postbox/Sources/MessageOfInterestHolesView.swift +++ b/submodules/Postbox/Sources/MessageOfInterestHolesView.swift @@ -60,7 +60,7 @@ final class MutableMessageOfInterestHolesView: MutablePostboxView { } } self.anchor = anchor - self.wrappedView = MutableMessageHistoryView(postbox: postbox, orderStatistics: [], peerIds: peerIds, anchor: self.anchor, combinedReadStates: nil, transientReadStates: nil, tag: nil, namespaces: .all, count: self.count, topTaggedMessages: [:], additionalDatas: [], getMessageCountInRange: { _, _ in return 0}) + self.wrappedView = MutableMessageHistoryView(postbox: postbox, orderStatistics: [], clipHoles: true, peerIds: peerIds, anchor: self.anchor, combinedReadStates: nil, transientReadStates: nil, tag: nil, namespaces: .all, count: self.count, topTaggedMessages: [:], additionalDatas: [], getMessageCountInRange: { _, _ in return 0}) let _ = self.updateFromView() } @@ -132,7 +132,7 @@ final class MutableMessageOfInterestHolesView: MutablePostboxView { case let .peer(id): peerIds = postbox.peerIdsForLocation(.peer(id), tagMask: nil) } - self.wrappedView = MutableMessageHistoryView(postbox: postbox, orderStatistics: [], peerIds: peerIds, anchor: self.anchor, combinedReadStates: nil, transientReadStates: nil, tag: nil, namespaces: .all, count: self.count, topTaggedMessages: [:], additionalDatas: [], getMessageCountInRange: { _, _ in return 0}) + self.wrappedView = MutableMessageHistoryView(postbox: postbox, orderStatistics: [], clipHoles: true, peerIds: peerIds, anchor: self.anchor, combinedReadStates: nil, transientReadStates: nil, tag: nil, namespaces: .all, count: self.count, topTaggedMessages: [:], additionalDatas: [], getMessageCountInRange: { _, _ in return 0}) return self.updateFromView() } else if self.wrappedView.replay(postbox: postbox, transaction: transaction) { var reloadView = false @@ -160,7 +160,7 @@ final class MutableMessageOfInterestHolesView: MutablePostboxView { case let .peer(id): peerIds = postbox.peerIdsForLocation(.peer(id), tagMask: nil) } - self.wrappedView = MutableMessageHistoryView(postbox: postbox, orderStatistics: [], peerIds: peerIds, anchor: self.anchor, combinedReadStates: nil, transientReadStates: nil, tag: nil, namespaces: .all, count: self.count, topTaggedMessages: [:], additionalDatas: [], getMessageCountInRange: { _, _ in return 0}) + self.wrappedView = MutableMessageHistoryView(postbox: postbox, orderStatistics: [], clipHoles: true, peerIds: peerIds, anchor: self.anchor, combinedReadStates: nil, transientReadStates: nil, tag: nil, namespaces: .all, count: self.count, topTaggedMessages: [:], additionalDatas: [], getMessageCountInRange: { _, _ in return 0}) } return self.updateFromView() diff --git a/submodules/Postbox/Sources/Postbox.swift b/submodules/Postbox/Sources/Postbox.swift index fc19228729..187939b9ab 100644 --- a/submodules/Postbox/Sources/Postbox.swift +++ b/submodules/Postbox/Sources/Postbox.swift @@ -2266,7 +2266,7 @@ public final class Postbox { return peerIds } - public func aroundMessageOfInterestHistoryViewForChatLocation(_ chatLocation: ChatLocation, count: Int, topTaggedMessageIdNamespaces: Set, tagMask: MessageTags?, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData]) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { + public func aroundMessageOfInterestHistoryViewForChatLocation(_ chatLocation: ChatLocation, count: Int, clipHoles: Bool = true, topTaggedMessageIdNamespaces: Set, tagMask: MessageTags?, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData]) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { return self.transactionSignal(userInteractive: true, { subscriber, transaction in let peerIds = self.peerIdsForLocation(chatLocation, tagMask: tagMask) @@ -2312,26 +2312,26 @@ public final class Postbox { } } } - return self.syncAroundMessageHistoryViewForPeerId(subscriber: subscriber, peerIds: peerIds, count: count, anchor: anchor, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: topTaggedMessageIdNamespaces, tagMask: tagMask, namespaces: namespaces, orderStatistics: orderStatistics, additionalData: additionalData) + return self.syncAroundMessageHistoryViewForPeerId(subscriber: subscriber, peerIds: peerIds, count: count, clipHoles: clipHoles, anchor: anchor, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: topTaggedMessageIdNamespaces, tagMask: tagMask, namespaces: namespaces, orderStatistics: orderStatistics, additionalData: additionalData) }) } - public func aroundIdMessageHistoryViewForLocation(_ chatLocation: ChatLocation, count: Int, messageId: MessageId, topTaggedMessageIdNamespaces: Set, tagMask: MessageTags?, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { + public func aroundIdMessageHistoryViewForLocation(_ chatLocation: ChatLocation, count: Int, clipHoles: Bool = true, messageId: MessageId, topTaggedMessageIdNamespaces: Set, tagMask: MessageTags?, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { return self.transactionSignal { subscriber, transaction in let peerIds = self.peerIdsForLocation(chatLocation, tagMask: tagMask) - return self.syncAroundMessageHistoryViewForPeerId(subscriber: subscriber, peerIds: peerIds, count: count, anchor: .message(messageId), fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: topTaggedMessageIdNamespaces, tagMask: tagMask, namespaces: namespaces, orderStatistics: orderStatistics, additionalData: additionalData) + return self.syncAroundMessageHistoryViewForPeerId(subscriber: subscriber, peerIds: peerIds, count: count, clipHoles: clipHoles, anchor: .message(messageId), fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: topTaggedMessageIdNamespaces, tagMask: tagMask, namespaces: namespaces, orderStatistics: orderStatistics, additionalData: additionalData) } } - public func aroundMessageHistoryViewForLocation(_ chatLocation: ChatLocation, anchor: HistoryViewInputAnchor, count: Int, fixedCombinedReadStates: MessageHistoryViewReadState?, topTaggedMessageIdNamespaces: Set, tagMask: MessageTags?, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { + public func aroundMessageHistoryViewForLocation(_ chatLocation: ChatLocation, anchor: HistoryViewInputAnchor, count: Int, clipHoles: Bool = true, fixedCombinedReadStates: MessageHistoryViewReadState?, topTaggedMessageIdNamespaces: Set, tagMask: MessageTags?, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { return self.transactionSignal { subscriber, transaction in let peerIds = self.peerIdsForLocation(chatLocation, tagMask: tagMask) - return self.syncAroundMessageHistoryViewForPeerId(subscriber: subscriber, peerIds: peerIds, count: count, anchor: anchor, fixedCombinedReadStates: fixedCombinedReadStates, topTaggedMessageIdNamespaces: topTaggedMessageIdNamespaces, tagMask: tagMask, namespaces: namespaces, orderStatistics: orderStatistics, additionalData: additionalData) + return self.syncAroundMessageHistoryViewForPeerId(subscriber: subscriber, peerIds: peerIds, count: count, clipHoles: clipHoles, anchor: anchor, fixedCombinedReadStates: fixedCombinedReadStates, topTaggedMessageIdNamespaces: topTaggedMessageIdNamespaces, tagMask: tagMask, namespaces: namespaces, orderStatistics: orderStatistics, additionalData: additionalData) } } - private func syncAroundMessageHistoryViewForPeerId(subscriber: Subscriber<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError>, peerIds: MessageHistoryViewPeerIds, count: Int, anchor: HistoryViewInputAnchor, fixedCombinedReadStates: MessageHistoryViewReadState?, topTaggedMessageIdNamespaces: Set, tagMask: MessageTags?, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData]) -> Disposable { + private func syncAroundMessageHistoryViewForPeerId(subscriber: Subscriber<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError>, peerIds: MessageHistoryViewPeerIds, count: Int, clipHoles: Bool, anchor: HistoryViewInputAnchor, fixedCombinedReadStates: MessageHistoryViewReadState?, topTaggedMessageIdNamespaces: Set, tagMask: MessageTags?, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData]) -> Disposable { var topTaggedMessages: [MessageId.Namespace: MessageHistoryTopTaggedMessage?] = [:] var mainPeerId: PeerId? switch peerIds { @@ -2420,7 +2420,7 @@ public final class Postbox { readStates = transientReadStates } - let mutableView = MutableMessageHistoryView(postbox: self, orderStatistics: orderStatistics, peerIds: peerIds, anchor: anchor, combinedReadStates: readStates, transientReadStates: transientReadStates, tag: tagMask, namespaces: namespaces, count: count, topTaggedMessages: topTaggedMessages, additionalDatas: additionalDataEntries, getMessageCountInRange: { lowerBound, upperBound in + let mutableView = MutableMessageHistoryView(postbox: self, orderStatistics: orderStatistics, clipHoles: clipHoles, peerIds: peerIds, anchor: anchor, combinedReadStates: readStates, transientReadStates: transientReadStates, tag: tagMask, namespaces: namespaces, count: count, topTaggedMessages: topTaggedMessages, additionalDatas: additionalDataEntries, getMessageCountInRange: { lowerBound, upperBound in if let tagMask = tagMask { return Int32(self.messageHistoryTable.getMessageCountInRange(peerId: lowerBound.id.peerId, namespace: lowerBound.id.namespace, tag: tagMask, lowerBound: lowerBound, upperBound: upperBound)) } else { From bdf2133b645bc956d6b32e40f3fc355154dc323b Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 17 Jan 2020 21:49:14 +0400 Subject: [PATCH 02/50] Don't display progress on message media if no media is being changed --- .../TelegramUI/TelegramUI/ChatMessageInteractiveMediaNode.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveMediaNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveMediaNode.swift index 90aaeaa6e8..42c76d580f 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveMediaNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveMediaNode.swift @@ -954,7 +954,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio } var progressRequired = false - if attributes.updatingMedia != nil { + if let updatingMedia = attributes.updatingMedia, case .update = updatingMedia.media { progressRequired = true } else if secretBeginTimeAndTimeout?.0 != nil { progressRequired = true From 8d64864f5e82c35267627aa88ccf2d9f6ffcf5a7 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 17 Jan 2020 21:49:50 +0400 Subject: [PATCH 03/50] Allow interaction with polls in scheduled messages --- .../ChatMessagePollBubbleContentNode.swift | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessagePollBubbleContentNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessagePollBubbleContentNode.swift index 174ca9909a..fdd12e66a8 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessagePollBubbleContentNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessagePollBubbleContentNode.swift @@ -539,7 +539,7 @@ private final class ChatMessagePollOptionNode: ASDisplayNode { let shouldHaveRadioNode = optionResult == nil let isSelectable: Bool - if shouldHaveRadioNode, case .poll(multipleAnswers: true) = poll.kind { + if shouldHaveRadioNode, case .poll(multipleAnswers: true) = poll.kind, !Namespaces.Message.allScheduled.contains(message.id.namespace) { isSelectable = true } else { isSelectable = false @@ -1155,7 +1155,7 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode { boundingSize.width = max(boundingSize.width, min(270.0, constrainedSize.width)) var canVote = false - if item.message.id.namespace == Namespaces.Message.Cloud, let poll = poll, poll.pollId.namespace == Namespaces.Media.CloudPoll, !poll.isClosed { + if (item.message.id.namespace == Namespaces.Message.Cloud || Namespaces.Message.allScheduled.contains(item.message.id.namespace)), let poll = poll, poll.pollId.namespace == Namespaces.Media.CloudPoll, !poll.isClosed { var hasVoted = false if let voters = poll.results.voters { for voter in voters { @@ -1169,9 +1169,6 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode { canVote = true } } - if Namespaces.Message.allScheduled.contains(item.message.id.namespace) { - canVote = false - } return (boundingSize.width, { boundingWidth in var resultSize = CGSize(width: max(boundingSize.width, boundingWidth), height: boundingSize.height) @@ -1349,10 +1346,7 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode { return } - var disableAllActions = false - if Namespaces.Message.allScheduled.contains(item.message.id.namespace) { - disableAllActions = true - } + let disableAllActions = false var hasSelection = false switch poll.kind { From 8be897ea6c4d165ce6ff13bd6e4a07fe8e4bac8c Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 17 Jan 2020 22:04:48 +0400 Subject: [PATCH 04/50] Don't focus on option text when losing focus --- .../Sources/CreatePollController.swift | 18 +++++++++++------- .../Sources/CreatePollOptionItem.swift | 14 +++++++++----- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/submodules/ComposePollUI/Sources/CreatePollController.swift b/submodules/ComposePollUI/Sources/CreatePollController.swift index 2659b26e3b..af294cccda 100644 --- a/submodules/ComposePollUI/Sources/CreatePollController.swift +++ b/submodules/ComposePollUI/Sources/CreatePollController.swift @@ -148,7 +148,7 @@ private func processPollText(_ text: String) -> String { private final class CreatePollControllerArguments { let updatePollText: (String) -> Void - let updateOptionText: (Int, String) -> Void + let updateOptionText: (Int, String, Bool) -> Void let moveToNextOption: (Int) -> Void let moveToPreviousOption: (Int) -> Void let removeOption: (Int, Bool) -> Void @@ -160,7 +160,7 @@ private final class CreatePollControllerArguments { let displayMultipleChoiceDisabled: () -> Void let updateQuiz: (Bool) -> Void - init(updatePollText: @escaping (String) -> Void, updateOptionText: @escaping (Int, String) -> Void, moveToNextOption: @escaping (Int) -> Void, moveToPreviousOption: @escaping (Int) -> Void, removeOption: @escaping (Int, Bool) -> Void, optionFocused: @escaping (Int, Bool) -> Void, setItemIdWithRevealedOptions: @escaping (Int?, Int?) -> Void, toggleOptionSelected: @escaping (Int) -> Void, updateAnonymous: @escaping (Bool) -> Void, updateMultipleChoice: @escaping (Bool) -> Void, displayMultipleChoiceDisabled: @escaping () -> Void, updateQuiz: @escaping (Bool) -> Void) { + init(updatePollText: @escaping (String) -> Void, updateOptionText: @escaping (Int, String, Bool) -> Void, moveToNextOption: @escaping (Int) -> Void, moveToPreviousOption: @escaping (Int) -> Void, removeOption: @escaping (Int, Bool) -> Void, optionFocused: @escaping (Int, Bool) -> Void, setItemIdWithRevealedOptions: @escaping (Int?, Int?) -> Void, toggleOptionSelected: @escaping (Int) -> Void, updateAnonymous: @escaping (Bool) -> Void, updateMultipleChoice: @escaping (Bool) -> Void, displayMultipleChoiceDisabled: @escaping () -> Void, updateQuiz: @escaping (Bool) -> Void) { self.updatePollText = updatePollText self.updateOptionText = updateOptionText self.moveToNextOption = moveToNextOption @@ -317,8 +317,8 @@ private enum CreatePollEntry: ItemListNodeEntry { case let .option(id, _, placeholder, text, revealed, hasNext, isLast, isSelected): return CreatePollOptionItem(presentationData: presentationData, id: id, placeholder: placeholder, value: text, isSelected: isSelected, maxLength: maxOptionLength, editing: CreatePollOptionItemEditing(editable: true, hasActiveRevealControls: revealed), sectionId: self.section, setItemIdWithRevealedOptions: { id, fromId in arguments.setItemIdWithRevealedOptions(id, fromId) - }, updated: { value in - arguments.updateOptionText(id, value) + }, updated: { value, isFocused in + arguments.updateOptionText(id, value, isFocused) }, next: hasNext ? { arguments.moveToNextOption(id) } : nil, delete: { focused in @@ -456,13 +456,15 @@ public func createPollController(context: AccountContext, peer: Peer, isQuiz: Bo return state } ensureTextVisibleImpl?() - }, updateOptionText: { id, value in + }, updateOptionText: { id, value, isFocused in var ensureVisibleId = id updateState { state in var state = state for i in 0 ..< state.options.count { if state.options[i].item.id == id { - state.focusOptionId = id + if isFocused { + state.focusOptionId = id + } state.options.update(at: i, { option in option.text = value }) @@ -478,7 +480,9 @@ public func createPollController(context: AccountContext, peer: Peer, isQuiz: Bo } return state } - ensureOptionVisibleImpl?(ensureVisibleId) + if isFocused { + ensureOptionVisibleImpl?(ensureVisibleId) + } }, moveToNextOption: { id in var resetFocusOptionId: Int? updateState { state in diff --git a/submodules/ComposePollUI/Sources/CreatePollOptionItem.swift b/submodules/ComposePollUI/Sources/CreatePollOptionItem.swift index ad5046f164..233208574a 100644 --- a/submodules/ComposePollUI/Sources/CreatePollOptionItem.swift +++ b/submodules/ComposePollUI/Sources/CreatePollOptionItem.swift @@ -23,7 +23,7 @@ class CreatePollOptionItem: ListViewItem, ItemListItem { let editing: CreatePollOptionItemEditing let sectionId: ItemListSectionId let setItemIdWithRevealedOptions: (Int?, Int?) -> Void - let updated: (String) -> Void + let updated: (String, Bool) -> Void let next: (() -> Void)? let delete: (Bool) -> Void let canDelete: Bool @@ -31,7 +31,7 @@ class CreatePollOptionItem: ListViewItem, ItemListItem { let toggleSelected: () -> Void let tag: ItemListItemTag? - init(presentationData: ItemListPresentationData, id: Int, placeholder: String, value: String, isSelected: Bool?, maxLength: Int, editing: CreatePollOptionItemEditing, sectionId: ItemListSectionId, setItemIdWithRevealedOptions: @escaping (Int?, Int?) -> Void, updated: @escaping (String) -> Void, next: (() -> Void)?, delete: @escaping (Bool) -> Void, canDelete: Bool, focused: @escaping (Bool) -> Void, toggleSelected: @escaping () -> Void, tag: ItemListItemTag?) { + init(presentationData: ItemListPresentationData, id: Int, placeholder: String, value: String, isSelected: Bool?, maxLength: Int, editing: CreatePollOptionItemEditing, sectionId: ItemListSectionId, setItemIdWithRevealedOptions: @escaping (Int?, Int?) -> Void, updated: @escaping (String, Bool) -> Void, next: (() -> Void)?, delete: @escaping (Bool) -> Void, canDelete: Bool, focused: @escaping (Bool) -> Void, toggleSelected: @escaping () -> Void, tag: ItemListItemTag?) { self.presentationData = presentationData self.id = id self.placeholder = placeholder @@ -182,7 +182,7 @@ class CreatePollOptionItemNode: ItemListRevealOptionsItemNode, ItemListItemNode, } func editableTextNodeDidFinishEditing(_ editableTextNode: ASEditableTextNode) { - self.editableTextNodeDidUpdateText(editableTextNode) + self.internalEditableTextNodeDidUpdateText(editableTextNode, isLosingFocus: true) self.item?.focused(false) } @@ -213,6 +213,10 @@ class CreatePollOptionItemNode: ItemListRevealOptionsItemNode, ItemListItemNode, } func editableTextNodeDidUpdateText(_ editableTextNode: ASEditableTextNode) { + self.internalEditableTextNodeDidUpdateText(editableTextNode, isLosingFocus: false) + } + + private func internalEditableTextNodeDidUpdateText(_ editableTextNode: ASEditableTextNode, isLosingFocus: Bool) { if let item = self.item { let text = self.textNode.attributedText ?? NSAttributedString() @@ -226,11 +230,11 @@ class CreatePollOptionItemNode: ItemListRevealOptionsItemNode, ItemListItemNode, if text.string != updatedAttributedText.string { self.textNode.attributedText = updatedAttributedText } - item.updated(updatedText) + item.updated(updatedText, !isLosingFocus && editableTextNode.isFirstResponder()) if hadReturn { if let next = item.next { next() - } else { + } else if !isLosingFocus { editableTextNode.resignFirstResponder() } } From 23e59d4d76850e1a301bb921e35ee4f974944873 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 17 Jan 2020 23:24:01 +0400 Subject: [PATCH 05/50] Fix poll-related theme changes --- submodules/ComposePollUI/Sources/CreatePollOptionItem.swift | 2 +- submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/submodules/ComposePollUI/Sources/CreatePollOptionItem.swift b/submodules/ComposePollUI/Sources/CreatePollOptionItem.swift index 233208574a..6a658bac2a 100644 --- a/submodules/ComposePollUI/Sources/CreatePollOptionItem.swift +++ b/submodules/ComposePollUI/Sources/CreatePollOptionItem.swift @@ -326,7 +326,7 @@ class CreatePollOptionItemNode: ItemListRevealOptionsItemNode, ItemListItemNode, let _ = textApply() if let currentText = strongSelf.textNode.attributedText { - if currentText.string != attributedText.string { + if currentText.string != attributedText.string || updatedTheme != nil { strongSelf.textNode.attributedText = attributedText } } else { diff --git a/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift b/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift index 22666adab8..a40405c95f 100644 --- a/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift +++ b/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift @@ -1361,6 +1361,10 @@ public final class ItemListPeerItemHeaderNode: ListViewItemHeaderNode, ItemListH public func updateTheme(theme: PresentationTheme) { self.theme = theme + self.backgroundNode.backgroundColor = theme.list.blocksBackgroundColor + self.snappedBackgroundNode.backgroundColor = theme.rootController.navigationBar.backgroundColor + self.separatorNode.backgroundColor = theme.list.itemBlocksSeparatorColor + let titleFont = Font.regular(13.0) self.textNode.attributedText = NSAttributedString(string: self.textNode.attributedText?.string ?? "", font: titleFont, textColor: theme.list.sectionHeaderTextColor) From 8ed4efa9b36b1082eadee6235d050a037c32d92f Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 17 Jan 2020 23:24:24 +0400 Subject: [PATCH 06/50] Add Pinned Quiz to the localization --- Telegram-iOS/en.lproj/Localizable.strings | 1 + .../Sources/PresentationStrings.swift | 4217 +++++++++-------- .../ChatPinnedMessageTitlePanelNode.swift | 9 +- .../Resources/PresentationStrings.mapping | Bin 144171 -> 144206 bytes .../WalletUI/Resources/WalletStrings.mapping | Bin 8384 -> 8384 bytes .../WalletUI/Sources/WalletStrings.swift | 4 +- 6 files changed, 2119 insertions(+), 2112 deletions(-) diff --git a/Telegram-iOS/en.lproj/Localizable.strings b/Telegram-iOS/en.lproj/Localizable.strings index 0fdd4b8f34..acc869faab 100644 --- a/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram-iOS/en.lproj/Localizable.strings @@ -3793,6 +3793,7 @@ Unused sets are archived when you add more."; "MessagePoll.VotedCount_any" = "%@ votes"; "AttachmentMenu.Poll" = "Poll"; "Conversation.PinnedPoll" = "Pinned Poll"; +"Conversation.PinnedQuiz" = "Pinned Quiz"; "CreatePoll.Title" = "New Poll"; "CreatePoll.Create" = "Send"; diff --git a/submodules/TelegramPresentationData/Sources/PresentationStrings.swift b/submodules/TelegramPresentationData/Sources/PresentationStrings.swift index 08c5862b4c..dd3b469226 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationStrings.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationStrings.swift @@ -2615,2294 +2615,2290 @@ public final class PresentationStrings: Equatable { return formatWithArgumentRanges(self._s[2223]!, self._r[2223]!, [_1, _2, _3]) } public var Permissions_CellularDataText_v0: String { return self._s[2224]! } - public var ShareMenu_SelectChats: String { return self._s[2227]! } - public var ChatList_Context_Unarchive: String { return self._s[2228]! } - public var MusicPlayer_VoiceNote: String { return self._s[2229]! } - public var Conversation_RestrictedText: String { return self._s[2230]! } - public var SettingsSearch_Synonyms_Privacy_Data_DeleteDrafts: String { return self._s[2231]! } - public var Wallet_Month_GenApril: String { return self._s[2232]! } - public var Wallet_Month_ShortMarch: String { return self._s[2233]! } - public var TwoStepAuth_DisableSuccess: String { return self._s[2234]! } - public var Cache_Videos: String { return self._s[2235]! } - public var PrivacySettings_PhoneNumber: String { return self._s[2236]! } - public var Wallet_Month_GenFebruary: String { return self._s[2237]! } - public var FeatureDisabled_Oops: String { return self._s[2239]! } - public var Passport_Address_PostcodePlaceholder: String { return self._s[2240]! } + public var Conversation_PinnedQuiz: String { return self._s[2226]! } + public var ShareMenu_SelectChats: String { return self._s[2228]! } + public var ChatList_Context_Unarchive: String { return self._s[2229]! } + public var MusicPlayer_VoiceNote: String { return self._s[2230]! } + public var Conversation_RestrictedText: String { return self._s[2231]! } + public var SettingsSearch_Synonyms_Privacy_Data_DeleteDrafts: String { return self._s[2232]! } + public var Wallet_Month_GenApril: String { return self._s[2233]! } + public var Wallet_Month_ShortMarch: String { return self._s[2234]! } + public var TwoStepAuth_DisableSuccess: String { return self._s[2235]! } + public var Cache_Videos: String { return self._s[2236]! } + public var PrivacySettings_PhoneNumber: String { return self._s[2237]! } + public var Wallet_Month_GenFebruary: String { return self._s[2238]! } + public var FeatureDisabled_Oops: String { return self._s[2240]! } + public var Passport_Address_PostcodePlaceholder: String { return self._s[2241]! } public func AddContact_StatusSuccess(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2241]!, self._r[2241]!, [_0]) + return formatWithArgumentRanges(self._s[2242]!, self._r[2242]!, [_0]) } - public var Stickers_GroupStickersHelp: String { return self._s[2242]! } - public var GroupPermission_NoSendPolls: String { return self._s[2243]! } - public var Wallet_Qr_ScanCode: String { return self._s[2244]! } - public var Message_VideoExpired: String { return self._s[2246]! } - public var GroupInfo_GroupHistoryVisible: String { return self._s[2247]! } - public var Notifications_Badge: String { return self._s[2248]! } - public var Wallet_Receive_AddressCopied: String { return self._s[2249]! } - public var CreatePoll_OptionPlaceholder: String { return self._s[2250]! } - public var Username_InvalidTooShort: String { return self._s[2251]! } - public var EnterPasscode_EnterNewPasscodeChange: String { return self._s[2252]! } - public var Channel_AdminLog_PinMessages: String { return self._s[2253]! } - public var ArchivedChats_IntroTitle3: String { return self._s[2254]! } + public var Stickers_GroupStickersHelp: String { return self._s[2243]! } + public var GroupPermission_NoSendPolls: String { return self._s[2244]! } + public var Wallet_Qr_ScanCode: String { return self._s[2245]! } + public var Message_VideoExpired: String { return self._s[2247]! } + public var GroupInfo_GroupHistoryVisible: String { return self._s[2248]! } + public var Notifications_Badge: String { return self._s[2249]! } + public var Wallet_Receive_AddressCopied: String { return self._s[2250]! } + public var CreatePoll_OptionPlaceholder: String { return self._s[2251]! } + public var Username_InvalidTooShort: String { return self._s[2252]! } + public var EnterPasscode_EnterNewPasscodeChange: String { return self._s[2253]! } + public var Channel_AdminLog_PinMessages: String { return self._s[2254]! } + public var ArchivedChats_IntroTitle3: String { return self._s[2255]! } public func Notification_MessageLifetimeRemoved(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2255]!, self._r[2255]!, [_1]) + return formatWithArgumentRanges(self._s[2256]!, self._r[2256]!, [_1]) } - public var Permissions_SiriAllowInSettings_v0: String { return self._s[2256]! } - public var Conversation_DefaultRestrictedText: String { return self._s[2257]! } - public var SharedMedia_CategoryDocs: String { return self._s[2260]! } + public var Permissions_SiriAllowInSettings_v0: String { return self._s[2257]! } + public var Conversation_DefaultRestrictedText: String { return self._s[2258]! } + public var SharedMedia_CategoryDocs: String { return self._s[2261]! } public func PUSH_MESSAGE_CONTACT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2261]!, self._r[2261]!, [_1]) + return formatWithArgumentRanges(self._s[2262]!, self._r[2262]!, [_1]) } - public var Wallet_Send_UninitializedTitle: String { return self._s[2262]! } - public var StickerPackActionInfo_ArchivedTitle: String { return self._s[2263]! } - public var Privacy_Forwards_NeverLink: String { return self._s[2265]! } + public var Wallet_Send_UninitializedTitle: String { return self._s[2263]! } + public var StickerPackActionInfo_ArchivedTitle: String { return self._s[2264]! } + public var Privacy_Forwards_NeverLink: String { return self._s[2266]! } public func Notification_MessageLifetimeChangedOutgoing(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2266]!, self._r[2266]!, [_1]) + return formatWithArgumentRanges(self._s[2267]!, self._r[2267]!, [_1]) } - public var CheckoutInfo_ErrorShippingNotAvailable: String { return self._s[2267]! } + public var CheckoutInfo_ErrorShippingNotAvailable: String { return self._s[2268]! } public func Time_MonthOfYear_m12(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2268]!, self._r[2268]!, [_0]) + return formatWithArgumentRanges(self._s[2269]!, self._r[2269]!, [_0]) } - public var ChatSettings_PrivateChats: String { return self._s[2269]! } - public var SettingsSearch_Synonyms_EditProfile_Logout: String { return self._s[2270]! } - public var Conversation_PrivateMessageLinkCopied: String { return self._s[2271]! } - public var Channel_UpdatePhotoItem: String { return self._s[2272]! } - public var GroupInfo_LeftStatus: String { return self._s[2273]! } - public var Watch_MessageView_Forward: String { return self._s[2275]! } - public var ReportPeer_ReasonChildAbuse: String { return self._s[2276]! } - public var Cache_ClearEmpty: String { return self._s[2278]! } - public var Localization_LanguageName: String { return self._s[2279]! } - public var Wallet_AccessDenied_Title: String { return self._s[2280]! } - public var WebSearch_GIFs: String { return self._s[2281]! } - public var Notifications_DisplayNamesOnLockScreenInfoWithLink: String { return self._s[2282]! } - public var Wallet_AccessDenied_Settings: String { return self._s[2283]! } - public var Username_InvalidStartsWithNumber: String { return self._s[2284]! } - public var Common_Back: String { return self._s[2285]! } - public var GroupInfo_Permissions_EditingDisabled: String { return self._s[2286]! } - public var Passport_Identity_DateOfBirthPlaceholder: String { return self._s[2287]! } - public var Wallet_Send_Send: String { return self._s[2288]! } + public var ChatSettings_PrivateChats: String { return self._s[2270]! } + public var SettingsSearch_Synonyms_EditProfile_Logout: String { return self._s[2271]! } + public var Conversation_PrivateMessageLinkCopied: String { return self._s[2272]! } + public var Channel_UpdatePhotoItem: String { return self._s[2273]! } + public var GroupInfo_LeftStatus: String { return self._s[2274]! } + public var Watch_MessageView_Forward: String { return self._s[2276]! } + public var ReportPeer_ReasonChildAbuse: String { return self._s[2277]! } + public var Cache_ClearEmpty: String { return self._s[2279]! } + public var Localization_LanguageName: String { return self._s[2280]! } + public var Wallet_AccessDenied_Title: String { return self._s[2281]! } + public var WebSearch_GIFs: String { return self._s[2282]! } + public var Notifications_DisplayNamesOnLockScreenInfoWithLink: String { return self._s[2283]! } + public var Wallet_AccessDenied_Settings: String { return self._s[2284]! } + public var Username_InvalidStartsWithNumber: String { return self._s[2285]! } + public var Common_Back: String { return self._s[2286]! } + public var GroupInfo_Permissions_EditingDisabled: String { return self._s[2287]! } + public var Passport_Identity_DateOfBirthPlaceholder: String { return self._s[2288]! } + public var Wallet_Send_Send: String { return self._s[2289]! } public func PUSH_CHANNEL_MESSAGE_STICKER(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2290]!, self._r[2290]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2291]!, self._r[2291]!, [_1, _2]) } - public var Wallet_Info_RefreshErrorTitle: String { return self._s[2291]! } - public var Wallet_Month_GenJune: String { return self._s[2292]! } - public var Passport_Email_Help: String { return self._s[2293]! } - public var Watch_Conversation_Reply: String { return self._s[2295]! } - public var Conversation_EditingMessageMediaChange: String { return self._s[2298]! } - public var Passport_Identity_IssueDatePlaceholder: String { return self._s[2299]! } - public var Channel_BanUser_Unban: String { return self._s[2301]! } - public var Channel_EditAdmin_PermissionPostMessages: String { return self._s[2302]! } - public var Group_Username_CreatePublicLinkHelp: String { return self._s[2303]! } - public var TwoStepAuth_ConfirmEmailCodePlaceholder: String { return self._s[2305]! } - public var Wallet_Send_AddressHeader: String { return self._s[2306]! } - public var Passport_Identity_Name: String { return self._s[2307]! } + public var Wallet_Info_RefreshErrorTitle: String { return self._s[2292]! } + public var Wallet_Month_GenJune: String { return self._s[2293]! } + public var Passport_Email_Help: String { return self._s[2294]! } + public var Watch_Conversation_Reply: String { return self._s[2296]! } + public var Conversation_EditingMessageMediaChange: String { return self._s[2299]! } + public var Passport_Identity_IssueDatePlaceholder: String { return self._s[2300]! } + public var Channel_BanUser_Unban: String { return self._s[2302]! } + public var Channel_EditAdmin_PermissionPostMessages: String { return self._s[2303]! } + public var Group_Username_CreatePublicLinkHelp: String { return self._s[2304]! } + public var TwoStepAuth_ConfirmEmailCodePlaceholder: String { return self._s[2306]! } + public var Wallet_Send_AddressHeader: String { return self._s[2307]! } + public var Passport_Identity_Name: String { return self._s[2308]! } public func Channel_DiscussionGroup_HeaderGroupSet(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2308]!, self._r[2308]!, [_0]) + return formatWithArgumentRanges(self._s[2309]!, self._r[2309]!, [_0]) } - public var GroupRemoved_ViewUserInfo: String { return self._s[2309]! } - public var Conversation_BlockUser: String { return self._s[2310]! } - public var Month_GenJanuary: String { return self._s[2311]! } - public var ChatSettings_TextSize: String { return self._s[2312]! } - public var Notification_PassportValuePhone: String { return self._s[2313]! } - public var MediaPlayer_UnknownArtist: String { return self._s[2314]! } - public var Passport_Language_ne: String { return self._s[2315]! } - public var Notification_CallBack: String { return self._s[2316]! } - public var Wallet_SecureStorageReset_BiometryTouchId: String { return self._s[2317]! } - public var TwoStepAuth_EmailHelp: String { return self._s[2318]! } + public var GroupRemoved_ViewUserInfo: String { return self._s[2310]! } + public var Conversation_BlockUser: String { return self._s[2311]! } + public var Month_GenJanuary: String { return self._s[2312]! } + public var ChatSettings_TextSize: String { return self._s[2313]! } + public var Notification_PassportValuePhone: String { return self._s[2314]! } + public var MediaPlayer_UnknownArtist: String { return self._s[2315]! } + public var Passport_Language_ne: String { return self._s[2316]! } + public var Notification_CallBack: String { return self._s[2317]! } + public var Wallet_SecureStorageReset_BiometryTouchId: String { return self._s[2318]! } + public var TwoStepAuth_EmailHelp: String { return self._s[2319]! } public func Time_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2319]!, self._r[2319]!, [_0]) + return formatWithArgumentRanges(self._s[2320]!, self._r[2320]!, [_0]) } - public var Channel_Info_Management: String { return self._s[2320]! } - public var Passport_FieldIdentityUploadHelp: String { return self._s[2321]! } - public var Stickers_FrequentlyUsed: String { return self._s[2322]! } - public var Channel_BanUser_PermissionSendMessages: String { return self._s[2323]! } - public var Passport_Address_OneOfTypeUtilityBill: String { return self._s[2325]! } + public var Channel_Info_Management: String { return self._s[2321]! } + public var Passport_FieldIdentityUploadHelp: String { return self._s[2322]! } + public var Stickers_FrequentlyUsed: String { return self._s[2323]! } + public var Channel_BanUser_PermissionSendMessages: String { return self._s[2324]! } + public var Passport_Address_OneOfTypeUtilityBill: String { return self._s[2326]! } public func LOCAL_CHANNEL_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2326]!, self._r[2326]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[2327]!, self._r[2327]!, [_1, "\(_2)"]) } - public var TwoFactorSetup_Password_Title: String { return self._s[2327]! } - public var Passport_Address_EditResidentialAddress: String { return self._s[2328]! } - public var PrivacyPolicy_DeclineTitle: String { return self._s[2329]! } - public var CreatePoll_TextHeader: String { return self._s[2330]! } + public var TwoFactorSetup_Password_Title: String { return self._s[2328]! } + public var Passport_Address_EditResidentialAddress: String { return self._s[2329]! } + public var PrivacyPolicy_DeclineTitle: String { return self._s[2330]! } + public var CreatePoll_TextHeader: String { return self._s[2331]! } public func Checkout_SavePasswordTimeoutAndTouchId(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2331]!, self._r[2331]!, [_0]) + return formatWithArgumentRanges(self._s[2332]!, self._r[2332]!, [_0]) } - public var PhotoEditor_QualityMedium: String { return self._s[2332]! } - public var InfoPlist_NSMicrophoneUsageDescription: String { return self._s[2333]! } - public var Conversation_StatusKickedFromChannel: String { return self._s[2335]! } - public var CheckoutInfo_ReceiverInfoName: String { return self._s[2336]! } - public var Group_ErrorSendRestrictedStickers: String { return self._s[2337]! } + public var PhotoEditor_QualityMedium: String { return self._s[2333]! } + public var InfoPlist_NSMicrophoneUsageDescription: String { return self._s[2334]! } + public var Conversation_StatusKickedFromChannel: String { return self._s[2336]! } + public var CheckoutInfo_ReceiverInfoName: String { return self._s[2337]! } + public var Group_ErrorSendRestrictedStickers: String { return self._s[2338]! } public func Conversation_RestrictedInlineTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2338]!, self._r[2338]!, [_0]) + return formatWithArgumentRanges(self._s[2339]!, self._r[2339]!, [_0]) } public func Channel_AdminLog_MessageTransferedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2339]!, self._r[2339]!, [_1]) + return formatWithArgumentRanges(self._s[2340]!, self._r[2340]!, [_1]) } - public var LogoutOptions_LogOutWalletInfo: String { return self._s[2340]! } - public var TwoFactorSetup_Email_SkipConfirmationTitle: String { return self._s[2341]! } - public var Conversation_LinkDialogOpen: String { return self._s[2343]! } - public var TwoFactorSetup_Hint_Title: String { return self._s[2344]! } - public var VoiceOver_Chat_PollNoVotes: String { return self._s[2345]! } - public var Settings_Username: String { return self._s[2347]! } - public var Conversation_Block: String { return self._s[2349]! } - public var Wallpaper_Wallpaper: String { return self._s[2350]! } - public var SocksProxySetup_UseProxy: String { return self._s[2352]! } - public var Wallet_Send_Confirmation: String { return self._s[2353]! } - public var EditTheme_UploadEditedTheme: String { return self._s[2354]! } - public var UserInfo_ShareMyContactInfo: String { return self._s[2355]! } - public var MessageTimer_Forever: String { return self._s[2356]! } - public var Privacy_Calls_WhoCanCallMe: String { return self._s[2357]! } - public var PhotoEditor_DiscardChanges: String { return self._s[2358]! } - public var AuthSessions_TerminateOtherSessionsHelp: String { return self._s[2359]! } - public var Passport_Language_da: String { return self._s[2360]! } - public var SocksProxySetup_PortPlaceholder: String { return self._s[2361]! } + public var LogoutOptions_LogOutWalletInfo: String { return self._s[2341]! } + public var TwoFactorSetup_Email_SkipConfirmationTitle: String { return self._s[2342]! } + public var Conversation_LinkDialogOpen: String { return self._s[2344]! } + public var TwoFactorSetup_Hint_Title: String { return self._s[2345]! } + public var VoiceOver_Chat_PollNoVotes: String { return self._s[2346]! } + public var Settings_Username: String { return self._s[2348]! } + public var Conversation_Block: String { return self._s[2350]! } + public var Wallpaper_Wallpaper: String { return self._s[2351]! } + public var SocksProxySetup_UseProxy: String { return self._s[2353]! } + public var Wallet_Send_Confirmation: String { return self._s[2354]! } + public var EditTheme_UploadEditedTheme: String { return self._s[2355]! } + public var UserInfo_ShareMyContactInfo: String { return self._s[2356]! } + public var MessageTimer_Forever: String { return self._s[2357]! } + public var Privacy_Calls_WhoCanCallMe: String { return self._s[2358]! } + public var PhotoEditor_DiscardChanges: String { return self._s[2359]! } + public var AuthSessions_TerminateOtherSessionsHelp: String { return self._s[2360]! } + public var Passport_Language_da: String { return self._s[2361]! } + public var SocksProxySetup_PortPlaceholder: String { return self._s[2362]! } public func SecretGIF_NotViewedYet(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2362]!, self._r[2362]!, [_0]) + return formatWithArgumentRanges(self._s[2363]!, self._r[2363]!, [_0]) } - public var Passport_Address_EditPassportRegistration: String { return self._s[2363]! } + public var Passport_Address_EditPassportRegistration: String { return self._s[2364]! } public func Channel_AdminLog_MessageChangedGroupAbout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2365]!, self._r[2365]!, [_0]) + return formatWithArgumentRanges(self._s[2366]!, self._r[2366]!, [_0]) } - public var Settings_AddDevice: String { return self._s[2366]! } - public var Passport_Identity_ResidenceCountryPlaceholder: String { return self._s[2368]! } - public var AuthSessions_AddDeviceIntro_Text1: String { return self._s[2369]! } - public var Conversation_SearchByName_Prefix: String { return self._s[2370]! } - public var Conversation_PinnedPoll: String { return self._s[2371]! } - public var AuthSessions_AddDeviceIntro_Text2: String { return self._s[2372]! } - public var Conversation_EmptyGifPanelPlaceholder: String { return self._s[2373]! } - public var AuthSessions_AddDeviceIntro_Text3: String { return self._s[2374]! } + public var Settings_AddDevice: String { return self._s[2367]! } + public var Passport_Identity_ResidenceCountryPlaceholder: String { return self._s[2369]! } + public var AuthSessions_AddDeviceIntro_Text1: String { return self._s[2370]! } + public var Conversation_SearchByName_Prefix: String { return self._s[2371]! } + public var Conversation_PinnedPoll: String { return self._s[2372]! } + public var AuthSessions_AddDeviceIntro_Text2: String { return self._s[2373]! } + public var Conversation_EmptyGifPanelPlaceholder: String { return self._s[2374]! } + public var AuthSessions_AddDeviceIntro_Text3: String { return self._s[2375]! } public func PUSH_ENCRYPTION_ACCEPT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2375]!, self._r[2375]!, [_1]) + return formatWithArgumentRanges(self._s[2376]!, self._r[2376]!, [_1]) } - public var WallpaperSearch_ColorPurple: String { return self._s[2376]! } - public var Cache_ByPeerHeader: String { return self._s[2377]! } + public var WallpaperSearch_ColorPurple: String { return self._s[2377]! } + public var Cache_ByPeerHeader: String { return self._s[2378]! } public func Conversation_EncryptedPlaceholderTitleIncoming(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2378]!, self._r[2378]!, [_0]) + return formatWithArgumentRanges(self._s[2379]!, self._r[2379]!, [_0]) } - public var ChatSettings_AutoDownloadDocuments: String { return self._s[2379]! } - public var Appearance_ThemePreview_Chat_3_Text: String { return self._s[2382]! } - public var Wallet_Completed_Title: String { return self._s[2383]! } - public var Notification_PinnedMessage: String { return self._s[2384]! } - public var TwoFactorSetup_EmailVerification_Placeholder: String { return self._s[2385]! } - public var VoiceOver_Chat_RecordModeVideoMessage: String { return self._s[2387]! } - public var Contacts_SortBy: String { return self._s[2388]! } + public var ChatSettings_AutoDownloadDocuments: String { return self._s[2380]! } + public var Appearance_ThemePreview_Chat_3_Text: String { return self._s[2383]! } + public var Wallet_Completed_Title: String { return self._s[2384]! } + public var Notification_PinnedMessage: String { return self._s[2385]! } + public var TwoFactorSetup_EmailVerification_Placeholder: String { return self._s[2386]! } + public var VoiceOver_Chat_RecordModeVideoMessage: String { return self._s[2388]! } + public var Contacts_SortBy: String { return self._s[2389]! } public func PUSH_CHANNEL_MESSAGE_NOTEXT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2389]!, self._r[2389]!, [_1]) + return formatWithArgumentRanges(self._s[2390]!, self._r[2390]!, [_1]) } - public var Appearance_ColorThemeNight: String { return self._s[2391]! } + public var Appearance_ColorThemeNight: String { return self._s[2392]! } public func PUSH_MESSAGE_GAME(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2392]!, self._r[2392]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2393]!, self._r[2393]!, [_1, _2]) } - public var Call_EncryptionKey_Title: String { return self._s[2393]! } - public var Watch_UserInfo_Service: String { return self._s[2394]! } - public var SettingsSearch_Synonyms_Data_SaveEditedPhotos: String { return self._s[2396]! } - public var Conversation_Unpin: String { return self._s[2398]! } - public var CancelResetAccount_Title: String { return self._s[2399]! } - public var Map_LiveLocationFor15Minutes: String { return self._s[2400]! } + public var Call_EncryptionKey_Title: String { return self._s[2394]! } + public var Watch_UserInfo_Service: String { return self._s[2395]! } + public var SettingsSearch_Synonyms_Data_SaveEditedPhotos: String { return self._s[2397]! } + public var Conversation_Unpin: String { return self._s[2399]! } + public var CancelResetAccount_Title: String { return self._s[2400]! } + public var Map_LiveLocationFor15Minutes: String { return self._s[2401]! } public func Time_PreciseDate_m8(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2402]!, self._r[2402]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2403]!, self._r[2403]!, [_1, _2, _3]) } - public var Group_Members_AddMemberBotErrorNotAllowed: String { return self._s[2403]! } - public var CallSettings_Title: String { return self._s[2404]! } - public var SettingsSearch_Synonyms_Appearance_ChatBackground: String { return self._s[2405]! } - public var PasscodeSettings_EncryptDataHelp: String { return self._s[2407]! } - public var AutoDownloadSettings_Contacts: String { return self._s[2408]! } + public var Group_Members_AddMemberBotErrorNotAllowed: String { return self._s[2404]! } + public var CallSettings_Title: String { return self._s[2405]! } + public var SettingsSearch_Synonyms_Appearance_ChatBackground: String { return self._s[2406]! } + public var PasscodeSettings_EncryptDataHelp: String { return self._s[2408]! } + public var AutoDownloadSettings_Contacts: String { return self._s[2409]! } public func Channel_AdminLog_MessageRankName(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2409]!, self._r[2409]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2410]!, self._r[2410]!, [_1, _2]) } - public var Passport_Identity_DocumentDetails: String { return self._s[2410]! } - public var LoginPassword_PasswordHelp: String { return self._s[2411]! } - public var SettingsSearch_Synonyms_Data_AutoDownloadUsingWifi: String { return self._s[2412]! } - public var PrivacyLastSeenSettings_CustomShareSettings_Delete: String { return self._s[2413]! } - public var ChatContextMenu_TextSelectionTip: String { return self._s[2414]! } - public var Checkout_TotalPaidAmount: String { return self._s[2415]! } + public var Passport_Identity_DocumentDetails: String { return self._s[2411]! } + public var LoginPassword_PasswordHelp: String { return self._s[2412]! } + public var SettingsSearch_Synonyms_Data_AutoDownloadUsingWifi: String { return self._s[2413]! } + public var PrivacyLastSeenSettings_CustomShareSettings_Delete: String { return self._s[2414]! } + public var ChatContextMenu_TextSelectionTip: String { return self._s[2415]! } + public var Checkout_TotalPaidAmount: String { return self._s[2416]! } public func FileSize_KB(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2416]!, self._r[2416]!, [_0]) + return formatWithArgumentRanges(self._s[2417]!, self._r[2417]!, [_0]) } - public var PasscodeSettings_ChangePasscode: String { return self._s[2417]! } - public var Conversation_SecretLinkPreviewAlert: String { return self._s[2419]! } - public var Privacy_SecretChatsLinkPreviews: String { return self._s[2420]! } + public var PasscodeSettings_ChangePasscode: String { return self._s[2418]! } + public var Conversation_SecretLinkPreviewAlert: String { return self._s[2420]! } + public var Privacy_SecretChatsLinkPreviews: String { return self._s[2421]! } public func PUSH_CHANNEL_MESSAGE_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2421]!, self._r[2421]!, [_1]) + return formatWithArgumentRanges(self._s[2422]!, self._r[2422]!, [_1]) } - public var VoiceOver_Chat_ReplyToYourMessage: String { return self._s[2422]! } - public var Contacts_InviteFriends: String { return self._s[2424]! } - public var Map_ChooseLocationTitle: String { return self._s[2425]! } - public var Conversation_StopPoll: String { return self._s[2427]! } + public var VoiceOver_Chat_ReplyToYourMessage: String { return self._s[2423]! } + public var Contacts_InviteFriends: String { return self._s[2425]! } + public var Map_ChooseLocationTitle: String { return self._s[2426]! } + public var Conversation_StopPoll: String { return self._s[2428]! } public func WebSearch_SearchNoResultsDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2428]!, self._r[2428]!, [_0]) + return formatWithArgumentRanges(self._s[2429]!, self._r[2429]!, [_0]) } - public var Call_Camera: String { return self._s[2429]! } - public var LogoutOptions_ChangePhoneNumberTitle: String { return self._s[2430]! } - public var AppWallet_Intro_Text: String { return self._s[2431]! } - public var Calls_RatingFeedback: String { return self._s[2432]! } - public var GroupInfo_BroadcastListNamePlaceholder: String { return self._s[2434]! } - public var Wallet_Alert_OK: String { return self._s[2435]! } - public var NotificationsSound_Pulse: String { return self._s[2436]! } - public var Watch_LastSeen_Lately: String { return self._s[2437]! } - public var ReportGroupLocation_Report: String { return self._s[2440]! } - public var Widget_NoUsers: String { return self._s[2441]! } - public var Conversation_UnvotePoll: String { return self._s[2442]! } - public var SettingsSearch_Synonyms_Privacy_ProfilePhoto: String { return self._s[2444]! } - public var Privacy_ProfilePhoto_WhoCanSeeMyPhoto: String { return self._s[2445]! } - public var NotificationsSound_Circles: String { return self._s[2446]! } - public var PrivacyLastSeenSettings_AlwaysShareWith_Title: String { return self._s[2449]! } - public var Wallet_Settings_DeleteWallet: String { return self._s[2450]! } - public var TwoStepAuth_RecoveryCodeExpired: String { return self._s[2451]! } - public var Proxy_TooltipUnavailable: String { return self._s[2452]! } - public var Passport_Identity_CountryPlaceholder: String { return self._s[2454]! } - public var GroupInfo_Permissions_SlowmodeInfo: String { return self._s[2456]! } - public var Conversation_FileDropbox: String { return self._s[2457]! } - public var Notifications_ExceptionsUnmuted: String { return self._s[2458]! } - public var Tour_Text3: String { return self._s[2460]! } - public var Login_ResetAccountProtected_Title: String { return self._s[2462]! } - public var GroupPermission_NoSendMessages: String { return self._s[2463]! } - public var WallpaperSearch_ColorTitle: String { return self._s[2464]! } - public var ChatAdmins_AllMembersAreAdminsOnHelp: String { return self._s[2465]! } + public var Call_Camera: String { return self._s[2430]! } + public var LogoutOptions_ChangePhoneNumberTitle: String { return self._s[2431]! } + public var AppWallet_Intro_Text: String { return self._s[2432]! } + public var Calls_RatingFeedback: String { return self._s[2433]! } + public var GroupInfo_BroadcastListNamePlaceholder: String { return self._s[2435]! } + public var Wallet_Alert_OK: String { return self._s[2436]! } + public var NotificationsSound_Pulse: String { return self._s[2437]! } + public var Watch_LastSeen_Lately: String { return self._s[2438]! } + public var ReportGroupLocation_Report: String { return self._s[2441]! } + public var Widget_NoUsers: String { return self._s[2442]! } + public var Conversation_UnvotePoll: String { return self._s[2443]! } + public var SettingsSearch_Synonyms_Privacy_ProfilePhoto: String { return self._s[2445]! } + public var Privacy_ProfilePhoto_WhoCanSeeMyPhoto: String { return self._s[2446]! } + public var NotificationsSound_Circles: String { return self._s[2447]! } + public var PrivacyLastSeenSettings_AlwaysShareWith_Title: String { return self._s[2450]! } + public var Wallet_Settings_DeleteWallet: String { return self._s[2451]! } + public var TwoStepAuth_RecoveryCodeExpired: String { return self._s[2452]! } + public var Proxy_TooltipUnavailable: String { return self._s[2453]! } + public var Passport_Identity_CountryPlaceholder: String { return self._s[2455]! } + public var GroupInfo_Permissions_SlowmodeInfo: String { return self._s[2457]! } + public var Conversation_FileDropbox: String { return self._s[2458]! } + public var Notifications_ExceptionsUnmuted: String { return self._s[2459]! } + public var Tour_Text3: String { return self._s[2461]! } + public var Login_ResetAccountProtected_Title: String { return self._s[2463]! } + public var GroupPermission_NoSendMessages: String { return self._s[2464]! } + public var WallpaperSearch_ColorTitle: String { return self._s[2465]! } + public var ChatAdmins_AllMembersAreAdminsOnHelp: String { return self._s[2466]! } public func Conversation_LiveLocationYouAnd(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2467]!, self._r[2467]!, [_0]) + return formatWithArgumentRanges(self._s[2468]!, self._r[2468]!, [_0]) } - public var GroupInfo_AddParticipantTitle: String { return self._s[2468]! } - public var Checkout_ShippingOption_Title: String { return self._s[2469]! } - public var ChatSettings_AutoDownloadTitle: String { return self._s[2470]! } + public var GroupInfo_AddParticipantTitle: String { return self._s[2469]! } + public var Checkout_ShippingOption_Title: String { return self._s[2470]! } + public var ChatSettings_AutoDownloadTitle: String { return self._s[2471]! } public func DialogList_SingleTypingSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2471]!, self._r[2471]!, [_0]) - } - public func ChatSettings_AutoDownloadSettings_TypeVideo(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2472]!, self._r[2472]!, [_0]) } - public var Channel_Management_LabelAdministrator: String { return self._s[2473]! } - public var EditTheme_FileReadError: String { return self._s[2474]! } - public var OwnershipTransfer_ComeBackLater: String { return self._s[2475]! } - public var PrivacyLastSeenSettings_NeverShareWith_Placeholder: String { return self._s[2476]! } - public var AutoDownloadSettings_Photos: String { return self._s[2478]! } - public var Appearance_PreviewIncomingText: String { return self._s[2479]! } - public var ChatList_Context_MarkAllAsRead: String { return self._s[2480]! } - public var ChannelInfo_ConfirmLeave: String { return self._s[2481]! } - public var MediaPicker_MomentsDateRangeSameMonthYearFormat: String { return self._s[2482]! } - public var Passport_Identity_DocumentNumberPlaceholder: String { return self._s[2483]! } - public var Channel_AdminLogFilter_EventsNewMembers: String { return self._s[2484]! } - public var PasscodeSettings_AutoLock_IfAwayFor_5minutes: String { return self._s[2485]! } - public var GroupInfo_SetGroupPhotoStop: String { return self._s[2486]! } - public var Notification_SecretChatScreenshot: String { return self._s[2487]! } - public var AccessDenied_Wallpapers: String { return self._s[2488]! } - public var ChatList_Context_Mute: String { return self._s[2490]! } - public var Passport_Address_City: String { return self._s[2491]! } - public var InfoPlist_NSPhotoLibraryAddUsageDescription: String { return self._s[2492]! } - public var Appearance_ThemeCarouselClassic: String { return self._s[2493]! } - public var SocksProxySetup_SecretPlaceholder: String { return self._s[2494]! } - public var AccessDenied_LocationDisabled: String { return self._s[2495]! } - public var Group_Location_Title: String { return self._s[2496]! } - public var SocksProxySetup_HostnamePlaceholder: String { return self._s[2498]! } - public var GroupInfo_Sound: String { return self._s[2499]! } - public var SettingsSearch_Synonyms_ChatSettings_OpenLinksIn: String { return self._s[2500]! } - public var ChannelInfo_ScamChannelWarning: String { return self._s[2501]! } - public var Stickers_RemoveFromFavorites: String { return self._s[2502]! } - public var Contacts_Title: String { return self._s[2503]! } - public var EditTheme_ThemeTemplateAlertText: String { return self._s[2504]! } - public var Passport_Language_fr: String { return self._s[2505]! } - public var TwoFactorSetup_EmailVerification_Action: String { return self._s[2506]! } - public var Notifications_ResetAllNotifications: String { return self._s[2507]! } - public var IntentsSettings_SuggestedChats: String { return self._s[2509]! } - public var PrivacySettings_SecurityTitle: String { return self._s[2511]! } - public var Checkout_NewCard_Title: String { return self._s[2512]! } - public var Login_HaveNotReceivedCodeInternal: String { return self._s[2513]! } - public var Conversation_ForwardChats: String { return self._s[2514]! } - public var Wallet_SecureStorageReset_PasscodeText: String { return self._s[2516]! } - public var PasscodeSettings_4DigitCode: String { return self._s[2517]! } - public var Settings_FAQ: String { return self._s[2519]! } - public var AutoDownloadSettings_DocumentsTitle: String { return self._s[2520]! } - public var Conversation_ContextMenuForward: String { return self._s[2521]! } - public var VoiceOver_Chat_YourPhoto: String { return self._s[2524]! } - public var PrivacyPolicy_Title: String { return self._s[2527]! } - public var Notifications_TextTone: String { return self._s[2528]! } - public var Profile_CreateNewContact: String { return self._s[2529]! } - public var PrivacyPhoneNumberSettings_WhoCanSeeMyPhoneNumber: String { return self._s[2530]! } - public var TwoFactorSetup_EmailVerification_Title: String { return self._s[2532]! } - public var Call_Speaker: String { return self._s[2533]! } - public var AutoNightTheme_AutomaticSection: String { return self._s[2534]! } - public var Channel_OwnershipTransfer_EnterPassword: String { return self._s[2536]! } - public var Channel_Username_InvalidCharacters: String { return self._s[2537]! } + public func ChatSettings_AutoDownloadSettings_TypeVideo(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2473]!, self._r[2473]!, [_0]) + } + public var Channel_Management_LabelAdministrator: String { return self._s[2474]! } + public var EditTheme_FileReadError: String { return self._s[2475]! } + public var OwnershipTransfer_ComeBackLater: String { return self._s[2476]! } + public var PrivacyLastSeenSettings_NeverShareWith_Placeholder: String { return self._s[2477]! } + public var AutoDownloadSettings_Photos: String { return self._s[2479]! } + public var Appearance_PreviewIncomingText: String { return self._s[2480]! } + public var ChatList_Context_MarkAllAsRead: String { return self._s[2481]! } + public var ChannelInfo_ConfirmLeave: String { return self._s[2482]! } + public var MediaPicker_MomentsDateRangeSameMonthYearFormat: String { return self._s[2483]! } + public var Passport_Identity_DocumentNumberPlaceholder: String { return self._s[2484]! } + public var Channel_AdminLogFilter_EventsNewMembers: String { return self._s[2485]! } + public var PasscodeSettings_AutoLock_IfAwayFor_5minutes: String { return self._s[2486]! } + public var GroupInfo_SetGroupPhotoStop: String { return self._s[2487]! } + public var Notification_SecretChatScreenshot: String { return self._s[2488]! } + public var AccessDenied_Wallpapers: String { return self._s[2489]! } + public var ChatList_Context_Mute: String { return self._s[2491]! } + public var Passport_Address_City: String { return self._s[2492]! } + public var InfoPlist_NSPhotoLibraryAddUsageDescription: String { return self._s[2493]! } + public var Appearance_ThemeCarouselClassic: String { return self._s[2494]! } + public var SocksProxySetup_SecretPlaceholder: String { return self._s[2495]! } + public var AccessDenied_LocationDisabled: String { return self._s[2496]! } + public var Group_Location_Title: String { return self._s[2497]! } + public var SocksProxySetup_HostnamePlaceholder: String { return self._s[2499]! } + public var GroupInfo_Sound: String { return self._s[2500]! } + public var SettingsSearch_Synonyms_ChatSettings_OpenLinksIn: String { return self._s[2501]! } + public var ChannelInfo_ScamChannelWarning: String { return self._s[2502]! } + public var Stickers_RemoveFromFavorites: String { return self._s[2503]! } + public var Contacts_Title: String { return self._s[2504]! } + public var EditTheme_ThemeTemplateAlertText: String { return self._s[2505]! } + public var Passport_Language_fr: String { return self._s[2506]! } + public var TwoFactorSetup_EmailVerification_Action: String { return self._s[2507]! } + public var Notifications_ResetAllNotifications: String { return self._s[2508]! } + public var IntentsSettings_SuggestedChats: String { return self._s[2510]! } + public var PrivacySettings_SecurityTitle: String { return self._s[2512]! } + public var Checkout_NewCard_Title: String { return self._s[2513]! } + public var Login_HaveNotReceivedCodeInternal: String { return self._s[2514]! } + public var Conversation_ForwardChats: String { return self._s[2515]! } + public var Wallet_SecureStorageReset_PasscodeText: String { return self._s[2517]! } + public var PasscodeSettings_4DigitCode: String { return self._s[2518]! } + public var Settings_FAQ: String { return self._s[2520]! } + public var AutoDownloadSettings_DocumentsTitle: String { return self._s[2521]! } + public var Conversation_ContextMenuForward: String { return self._s[2522]! } + public var VoiceOver_Chat_YourPhoto: String { return self._s[2525]! } + public var PrivacyPolicy_Title: String { return self._s[2528]! } + public var Notifications_TextTone: String { return self._s[2529]! } + public var Profile_CreateNewContact: String { return self._s[2530]! } + public var PrivacyPhoneNumberSettings_WhoCanSeeMyPhoneNumber: String { return self._s[2531]! } + public var TwoFactorSetup_EmailVerification_Title: String { return self._s[2533]! } + public var Call_Speaker: String { return self._s[2534]! } + public var AutoNightTheme_AutomaticSection: String { return self._s[2535]! } + public var Channel_OwnershipTransfer_EnterPassword: String { return self._s[2537]! } + public var Channel_Username_InvalidCharacters: String { return self._s[2538]! } public func Channel_AdminLog_MessageChangedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2538]!, self._r[2538]!, [_0]) + return formatWithArgumentRanges(self._s[2539]!, self._r[2539]!, [_0]) } - public var AutoDownloadSettings_AutodownloadFiles: String { return self._s[2539]! } - public var PrivacySettings_LastSeenTitle: String { return self._s[2540]! } - public var Channel_AdminLog_CanInviteUsers: String { return self._s[2541]! } - public var SettingsSearch_Synonyms_Privacy_Data_ClearPaymentsInfo: String { return self._s[2542]! } - public var OwnershipTransfer_SecurityCheck: String { return self._s[2543]! } - public var Conversation_MessageDeliveryFailed: String { return self._s[2544]! } - public var Watch_ChatList_NoConversationsText: String { return self._s[2545]! } - public var Bot_Unblock: String { return self._s[2546]! } - public var TextFormat_Italic: String { return self._s[2547]! } - public var WallpaperSearch_ColorPink: String { return self._s[2548]! } - public var Settings_About_Help: String { return self._s[2550]! } - public var SearchImages_Title: String { return self._s[2551]! } - public var Weekday_Wednesday: String { return self._s[2552]! } - public var Conversation_ClousStorageInfo_Description1: String { return self._s[2553]! } - public var ExplicitContent_AlertTitle: String { return self._s[2554]! } + public var AutoDownloadSettings_AutodownloadFiles: String { return self._s[2540]! } + public var PrivacySettings_LastSeenTitle: String { return self._s[2541]! } + public var Channel_AdminLog_CanInviteUsers: String { return self._s[2542]! } + public var SettingsSearch_Synonyms_Privacy_Data_ClearPaymentsInfo: String { return self._s[2543]! } + public var OwnershipTransfer_SecurityCheck: String { return self._s[2544]! } + public var Conversation_MessageDeliveryFailed: String { return self._s[2545]! } + public var Watch_ChatList_NoConversationsText: String { return self._s[2546]! } + public var Bot_Unblock: String { return self._s[2547]! } + public var TextFormat_Italic: String { return self._s[2548]! } + public var WallpaperSearch_ColorPink: String { return self._s[2549]! } + public var Settings_About_Help: String { return self._s[2551]! } + public var SearchImages_Title: String { return self._s[2552]! } + public var Weekday_Wednesday: String { return self._s[2553]! } + public var Conversation_ClousStorageInfo_Description1: String { return self._s[2554]! } + public var ExplicitContent_AlertTitle: String { return self._s[2555]! } public func Time_PreciseDate_m5(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2555]!, self._r[2555]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2556]!, self._r[2556]!, [_1, _2, _3]) } - public var Channel_DiscussionGroup_Create: String { return self._s[2556]! } - public var Weekday_Thursday: String { return self._s[2557]! } - public var Channel_BanUser_PermissionChangeGroupInfo: String { return self._s[2558]! } - public var Channel_Members_AddMembersHelp: String { return self._s[2559]! } + public var Channel_DiscussionGroup_Create: String { return self._s[2557]! } + public var Weekday_Thursday: String { return self._s[2558]! } + public var Channel_BanUser_PermissionChangeGroupInfo: String { return self._s[2559]! } + public var Channel_Members_AddMembersHelp: String { return self._s[2560]! } public func Checkout_SavePasswordTimeout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2560]!, self._r[2560]!, [_0]) + return formatWithArgumentRanges(self._s[2561]!, self._r[2561]!, [_0]) } - public var Channel_DiscussionGroup_LinkGroup: String { return self._s[2561]! } - public var SettingsSearch_Synonyms_Notifications_InAppNotificationsVibrate: String { return self._s[2562]! } - public var Passport_RequestedInformation: String { return self._s[2563]! } - public var Login_PhoneAndCountryHelp: String { return self._s[2564]! } - public var Conversation_EncryptionProcessing: String { return self._s[2566]! } - public var Notifications_PermissionsSuppressWarningTitle: String { return self._s[2567]! } - public var PhotoEditor_EnhanceTool: String { return self._s[2569]! } - public var Channel_Setup_Title: String { return self._s[2570]! } - public var Conversation_SearchPlaceholder: String { return self._s[2571]! } - public var OldChannels_GroupEmptyFormat: String { return self._s[2572]! } - public var AccessDenied_LocationAlwaysDenied: String { return self._s[2573]! } - public var Checkout_ErrorGeneric: String { return self._s[2574]! } - public var Passport_Language_hu: String { return self._s[2575]! } - public var GroupPermission_EditingDisabled: String { return self._s[2576]! } - public var Wallet_Month_ShortSeptember: String { return self._s[2578]! } + public var Channel_DiscussionGroup_LinkGroup: String { return self._s[2562]! } + public var SettingsSearch_Synonyms_Notifications_InAppNotificationsVibrate: String { return self._s[2563]! } + public var Passport_RequestedInformation: String { return self._s[2564]! } + public var Login_PhoneAndCountryHelp: String { return self._s[2565]! } + public var Conversation_EncryptionProcessing: String { return self._s[2567]! } + public var Notifications_PermissionsSuppressWarningTitle: String { return self._s[2568]! } + public var PhotoEditor_EnhanceTool: String { return self._s[2570]! } + public var Channel_Setup_Title: String { return self._s[2571]! } + public var Conversation_SearchPlaceholder: String { return self._s[2572]! } + public var OldChannels_GroupEmptyFormat: String { return self._s[2573]! } + public var AccessDenied_LocationAlwaysDenied: String { return self._s[2574]! } + public var Checkout_ErrorGeneric: String { return self._s[2575]! } + public var Passport_Language_hu: String { return self._s[2576]! } + public var GroupPermission_EditingDisabled: String { return self._s[2577]! } + public var Wallet_Month_ShortSeptember: String { return self._s[2579]! } public func Passport_Identity_UploadOneOfScan(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2579]!, self._r[2579]!, [_0]) + return formatWithArgumentRanges(self._s[2580]!, self._r[2580]!, [_0]) } public func PUSH_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2582]!, self._r[2582]!, [_1]) + return formatWithArgumentRanges(self._s[2583]!, self._r[2583]!, [_1]) } - public var ChatList_DeleteSavedMessagesConfirmationTitle: String { return self._s[2583]! } + public var ChatList_DeleteSavedMessagesConfirmationTitle: String { return self._s[2584]! } public func UserInfo_BlockConfirmationTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2584]!, self._r[2584]!, [_0]) + return formatWithArgumentRanges(self._s[2585]!, self._r[2585]!, [_0]) } - public var Conversation_CloudStorageInfo_Title: String { return self._s[2585]! } - public var Group_Location_Info: String { return self._s[2586]! } - public var PhotoEditor_CropAspectRatioSquare: String { return self._s[2587]! } - public var Permissions_PeopleNearbyAllow_v0: String { return self._s[2588]! } + public var Conversation_CloudStorageInfo_Title: String { return self._s[2586]! } + public var Group_Location_Info: String { return self._s[2587]! } + public var PhotoEditor_CropAspectRatioSquare: String { return self._s[2588]! } + public var Permissions_PeopleNearbyAllow_v0: String { return self._s[2589]! } public func Notification_Exceptions_MutedUntil(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2589]!, self._r[2589]!, [_0]) + return formatWithArgumentRanges(self._s[2590]!, self._r[2590]!, [_0]) } - public var Conversation_ClearPrivateHistory: String { return self._s[2590]! } - public var ContactInfo_PhoneLabelHome: String { return self._s[2591]! } - public var Appearance_RemoveThemeConfirmation: String { return self._s[2592]! } - public var PrivacySettings_LastSeenContacts: String { return self._s[2593]! } + public var Conversation_ClearPrivateHistory: String { return self._s[2591]! } + public var ContactInfo_PhoneLabelHome: String { return self._s[2592]! } + public var Appearance_RemoveThemeConfirmation: String { return self._s[2593]! } + public var PrivacySettings_LastSeenContacts: String { return self._s[2594]! } public func ChangePhone_ErrorOccupied(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2594]!, self._r[2594]!, [_0]) + return formatWithArgumentRanges(self._s[2595]!, self._r[2595]!, [_0]) } - public var Passport_Language_cs: String { return self._s[2595]! } - public var Message_PinnedAnimationMessage: String { return self._s[2597]! } - public var Passport_Identity_ReverseSideHelp: String { return self._s[2599]! } - public var SettingsSearch_Synonyms_Data_Storage_Title: String { return self._s[2600]! } - public var Wallet_Info_TransactionTo: String { return self._s[2602]! } - public var ChatList_DeleteForEveryoneConfirmationText: String { return self._s[2603]! } - public var SettingsSearch_Synonyms_Privacy_PasscodeAndTouchId: String { return self._s[2604]! } - public var Embed_PlayingInPIP: String { return self._s[2605]! } - public var Appearance_ThemePreview_Chat_3_TextWithLink: String { return self._s[2606]! } - public var AutoNightTheme_ScheduleSection: String { return self._s[2607]! } + public var Passport_Language_cs: String { return self._s[2596]! } + public var Message_PinnedAnimationMessage: String { return self._s[2598]! } + public var Passport_Identity_ReverseSideHelp: String { return self._s[2600]! } + public var SettingsSearch_Synonyms_Data_Storage_Title: String { return self._s[2601]! } + public var Wallet_Info_TransactionTo: String { return self._s[2603]! } + public var ChatList_DeleteForEveryoneConfirmationText: String { return self._s[2604]! } + public var SettingsSearch_Synonyms_Privacy_PasscodeAndTouchId: String { return self._s[2605]! } + public var Embed_PlayingInPIP: String { return self._s[2606]! } + public var Appearance_ThemePreview_Chat_3_TextWithLink: String { return self._s[2607]! } + public var AutoNightTheme_ScheduleSection: String { return self._s[2608]! } public func Call_EmojiDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2608]!, self._r[2608]!, [_0]) + return formatWithArgumentRanges(self._s[2609]!, self._r[2609]!, [_0]) } - public var MediaPicker_LivePhotoDescription: String { return self._s[2609]! } + public var MediaPicker_LivePhotoDescription: String { return self._s[2610]! } public func Channel_AdminLog_MessageRestrictedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2610]!, self._r[2610]!, [_1]) + return formatWithArgumentRanges(self._s[2611]!, self._r[2611]!, [_1]) } - public var Notification_PaymentSent: String { return self._s[2611]! } - public var PhotoEditor_CurvesGreen: String { return self._s[2612]! } - public var Notification_Exceptions_PreviewAlwaysOff: String { return self._s[2613]! } - public var AutoNightTheme_System: String { return self._s[2614]! } - public var SaveIncomingPhotosSettings_Title: String { return self._s[2615]! } - public var CreatePoll_QuizTitle: String { return self._s[2616]! } - public var NotificationSettings_ShowNotificationsAllAccounts: String { return self._s[2617]! } - public var VoiceOver_Chat_PagePreview: String { return self._s[2618]! } + public var Notification_PaymentSent: String { return self._s[2612]! } + public var PhotoEditor_CurvesGreen: String { return self._s[2613]! } + public var Notification_Exceptions_PreviewAlwaysOff: String { return self._s[2614]! } + public var AutoNightTheme_System: String { return self._s[2615]! } + public var SaveIncomingPhotosSettings_Title: String { return self._s[2616]! } + public var CreatePoll_QuizTitle: String { return self._s[2617]! } + public var NotificationSettings_ShowNotificationsAllAccounts: String { return self._s[2618]! } + public var VoiceOver_Chat_PagePreview: String { return self._s[2619]! } public func PUSH_MESSAGE_SCREENSHOT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2621]!, self._r[2621]!, [_1]) - } - public func PUSH_MESSAGE_PHOTO_SECRET(_ _1: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2622]!, self._r[2622]!, [_1]) } - public func ApplyLanguage_UnsufficientDataText(_ _1: String) -> (String, [(Int, NSRange)]) { + public func PUSH_MESSAGE_PHOTO_SECRET(_ _1: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2623]!, self._r[2623]!, [_1]) } - public var NetworkUsageSettings_CallDataSection: String { return self._s[2625]! } - public var PasscodeSettings_HelpTop: String { return self._s[2626]! } - public var Conversation_WalletRequiredTitle: String { return self._s[2627]! } - public var Group_OwnershipTransfer_ErrorAdminsTooMuch: String { return self._s[2628]! } - public var Passport_Address_TypeRentalAgreement: String { return self._s[2629]! } - public var EditTheme_ShortLink: String { return self._s[2630]! } - public var Theme_Colors_ColorWallpaperWarning: String { return self._s[2631]! } - public var ProxyServer_VoiceOver_Active: String { return self._s[2632]! } - public var ReportPeer_ReasonOther_Placeholder: String { return self._s[2633]! } - public var CheckoutInfo_ErrorPhoneInvalid: String { return self._s[2634]! } - public var Call_Accept: String { return self._s[2636]! } - public var GroupRemoved_RemoveInfo: String { return self._s[2637]! } - public var Month_GenMarch: String { return self._s[2639]! } - public var PhotoEditor_ShadowsTool: String { return self._s[2640]! } - public var LoginPassword_Title: String { return self._s[2641]! } - public var Call_End: String { return self._s[2642]! } - public var Watch_Conversation_GroupInfo: String { return self._s[2643]! } - public var VoiceOver_Chat_Contact: String { return self._s[2644]! } - public var EditTheme_Create_Preview_IncomingText: String { return self._s[2645]! } - public var CallSettings_Always: String { return self._s[2646]! } - public var CallFeedback_Success: String { return self._s[2647]! } - public var TwoStepAuth_SetupHint: String { return self._s[2648]! } + public func ApplyLanguage_UnsufficientDataText(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2624]!, self._r[2624]!, [_1]) + } + public var NetworkUsageSettings_CallDataSection: String { return self._s[2626]! } + public var PasscodeSettings_HelpTop: String { return self._s[2627]! } + public var Conversation_WalletRequiredTitle: String { return self._s[2628]! } + public var Group_OwnershipTransfer_ErrorAdminsTooMuch: String { return self._s[2629]! } + public var Passport_Address_TypeRentalAgreement: String { return self._s[2630]! } + public var EditTheme_ShortLink: String { return self._s[2631]! } + public var Theme_Colors_ColorWallpaperWarning: String { return self._s[2632]! } + public var ProxyServer_VoiceOver_Active: String { return self._s[2633]! } + public var ReportPeer_ReasonOther_Placeholder: String { return self._s[2634]! } + public var CheckoutInfo_ErrorPhoneInvalid: String { return self._s[2635]! } + public var Call_Accept: String { return self._s[2637]! } + public var GroupRemoved_RemoveInfo: String { return self._s[2638]! } + public var Month_GenMarch: String { return self._s[2640]! } + public var PhotoEditor_ShadowsTool: String { return self._s[2641]! } + public var LoginPassword_Title: String { return self._s[2642]! } + public var Call_End: String { return self._s[2643]! } + public var Watch_Conversation_GroupInfo: String { return self._s[2644]! } + public var VoiceOver_Chat_Contact: String { return self._s[2645]! } + public var EditTheme_Create_Preview_IncomingText: String { return self._s[2646]! } + public var CallSettings_Always: String { return self._s[2647]! } + public var CallFeedback_Success: String { return self._s[2648]! } + public var TwoStepAuth_SetupHint: String { return self._s[2649]! } public func AddContact_ContactWillBeSharedAfterMutual(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2649]!, self._r[2649]!, [_1]) + return formatWithArgumentRanges(self._s[2650]!, self._r[2650]!, [_1]) } - public var ConversationProfile_UsersTooMuchError: String { return self._s[2650]! } - public var Login_PhoneTitle: String { return self._s[2651]! } - public var Passport_FieldPhoneHelp: String { return self._s[2652]! } - public var Weekday_ShortSunday: String { return self._s[2653]! } - public var Passport_InfoFAQ_URL: String { return self._s[2654]! } - public var ContactInfo_Job: String { return self._s[2656]! } - public var UserInfo_InviteBotToGroup: String { return self._s[2657]! } - public var Appearance_ThemeCarouselNightBlue: String { return self._s[2658]! } - public var CreatePoll_QuizTip: String { return self._s[2659]! } - public var TwoFactorSetup_Email_Text: String { return self._s[2660]! } - public var TwoStepAuth_PasswordRemovePassportConfirmation: String { return self._s[2661]! } - public var Invite_ChannelsTooMuch: String { return self._s[2662]! } - public var Wallet_Send_ConfirmationConfirm: String { return self._s[2663]! } - public var Wallet_TransactionInfo_OtherFeeInfo: String { return self._s[2664]! } - public var SettingsSearch_Synonyms_Notifications_InAppNotificationsPreview: String { return self._s[2665]! } - public var Wallet_Receive_AmountText: String { return self._s[2666]! } - public var Passport_DeletePersonalDetailsConfirmation: String { return self._s[2667]! } - public var CallFeedback_ReasonNoise: String { return self._s[2668]! } - public var Appearance_AppIconDefault: String { return self._s[2670]! } - public var Passport_Identity_AddInternalPassport: String { return self._s[2671]! } - public var MediaPicker_AddCaption: String { return self._s[2672]! } - public var CallSettings_TabIconDescription: String { return self._s[2673]! } + public var ConversationProfile_UsersTooMuchError: String { return self._s[2651]! } + public var Login_PhoneTitle: String { return self._s[2652]! } + public var Passport_FieldPhoneHelp: String { return self._s[2653]! } + public var Weekday_ShortSunday: String { return self._s[2654]! } + public var Passport_InfoFAQ_URL: String { return self._s[2655]! } + public var ContactInfo_Job: String { return self._s[2657]! } + public var UserInfo_InviteBotToGroup: String { return self._s[2658]! } + public var Appearance_ThemeCarouselNightBlue: String { return self._s[2659]! } + public var CreatePoll_QuizTip: String { return self._s[2660]! } + public var TwoFactorSetup_Email_Text: String { return self._s[2661]! } + public var TwoStepAuth_PasswordRemovePassportConfirmation: String { return self._s[2662]! } + public var Invite_ChannelsTooMuch: String { return self._s[2663]! } + public var Wallet_Send_ConfirmationConfirm: String { return self._s[2664]! } + public var Wallet_TransactionInfo_OtherFeeInfo: String { return self._s[2665]! } + public var SettingsSearch_Synonyms_Notifications_InAppNotificationsPreview: String { return self._s[2666]! } + public var Wallet_Receive_AmountText: String { return self._s[2667]! } + public var Passport_DeletePersonalDetailsConfirmation: String { return self._s[2668]! } + public var CallFeedback_ReasonNoise: String { return self._s[2669]! } + public var Appearance_AppIconDefault: String { return self._s[2671]! } + public var Passport_Identity_AddInternalPassport: String { return self._s[2672]! } + public var MediaPicker_AddCaption: String { return self._s[2673]! } + public var CallSettings_TabIconDescription: String { return self._s[2674]! } public func VoiceOver_Chat_Caption(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2674]!, self._r[2674]!, [_0]) + return formatWithArgumentRanges(self._s[2675]!, self._r[2675]!, [_0]) } - public var IntentsSettings_SuggestedChatsGroups: String { return self._s[2675]! } + public var IntentsSettings_SuggestedChatsGroups: String { return self._s[2676]! } public func Map_SearchNoResultsDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2676]!, self._r[2676]!, [_0]) + return formatWithArgumentRanges(self._s[2677]!, self._r[2677]!, [_0]) } - public var ChatList_UndoArchiveHiddenTitle: String { return self._s[2677]! } - public var Privacy_GroupsAndChannels_AlwaysAllow: String { return self._s[2678]! } - public var Passport_Identity_TypePersonalDetails: String { return self._s[2679]! } - public var DialogList_SearchSectionRecent: String { return self._s[2680]! } - public var PrivacyPolicy_DeclineMessage: String { return self._s[2681]! } - public var CreatePoll_Anonymous: String { return self._s[2682]! } - public var LogoutOptions_ClearCacheText: String { return self._s[2685]! } - public var LastSeen_WithinAWeek: String { return self._s[2686]! } - public var ChannelMembers_GroupAdminsTitle: String { return self._s[2687]! } - public var Conversation_CloudStorage_ChatStatus: String { return self._s[2689]! } - public var VoiceOver_Media_PlaybackRateNormal: String { return self._s[2690]! } + public var ChatList_UndoArchiveHiddenTitle: String { return self._s[2678]! } + public var Privacy_GroupsAndChannels_AlwaysAllow: String { return self._s[2679]! } + public var Passport_Identity_TypePersonalDetails: String { return self._s[2680]! } + public var DialogList_SearchSectionRecent: String { return self._s[2681]! } + public var PrivacyPolicy_DeclineMessage: String { return self._s[2682]! } + public var CreatePoll_Anonymous: String { return self._s[2683]! } + public var LogoutOptions_ClearCacheText: String { return self._s[2686]! } + public var LastSeen_WithinAWeek: String { return self._s[2687]! } + public var ChannelMembers_GroupAdminsTitle: String { return self._s[2688]! } + public var Conversation_CloudStorage_ChatStatus: String { return self._s[2690]! } + public var VoiceOver_Media_PlaybackRateNormal: String { return self._s[2691]! } public func AddContact_SharedContactExceptionInfo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2691]!, self._r[2691]!, [_0]) + return formatWithArgumentRanges(self._s[2692]!, self._r[2692]!, [_0]) } - public var Passport_Address_TypeResidentialAddress: String { return self._s[2692]! } - public var Conversation_StatusLeftGroup: String { return self._s[2693]! } - public var SocksProxySetup_ProxyDetailsTitle: String { return self._s[2694]! } - public var SettingsSearch_Synonyms_Calls_Title: String { return self._s[2696]! } - public var GroupPermission_AddSuccess: String { return self._s[2697]! } - public var PhotoEditor_BlurToolRadial: String { return self._s[2699]! } - public var Conversation_ContextMenuCopy: String { return self._s[2700]! } - public var AccessDenied_CallMicrophone: String { return self._s[2701]! } + public var Passport_Address_TypeResidentialAddress: String { return self._s[2693]! } + public var Conversation_StatusLeftGroup: String { return self._s[2694]! } + public var SocksProxySetup_ProxyDetailsTitle: String { return self._s[2695]! } + public var SettingsSearch_Synonyms_Calls_Title: String { return self._s[2697]! } + public var GroupPermission_AddSuccess: String { return self._s[2698]! } + public var PhotoEditor_BlurToolRadial: String { return self._s[2700]! } + public var Conversation_ContextMenuCopy: String { return self._s[2701]! } + public var AccessDenied_CallMicrophone: String { return self._s[2702]! } public func Time_PreciseDate_m2(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2702]!, self._r[2702]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2703]!, self._r[2703]!, [_1, _2, _3]) } - public var Login_InvalidFirstNameError: String { return self._s[2703]! } - public var Notifications_Badge_CountUnreadMessages_InfoOn: String { return self._s[2704]! } - public var Checkout_PaymentMethod_New: String { return self._s[2705]! } - public var ShareMenu_CopyShareLinkGame: String { return self._s[2706]! } - public var PhotoEditor_QualityTool: String { return self._s[2707]! } - public var Login_SendCodeViaSms: String { return self._s[2708]! } - public var SettingsSearch_Synonyms_Privacy_DeleteAccountIfAwayFor: String { return self._s[2709]! } - public var Chat_SlowmodeAttachmentLimitReached: String { return self._s[2710]! } - public var Wallet_Receive_CopyAddress: String { return self._s[2711]! } - public var Login_EmailNotConfiguredError: String { return self._s[2712]! } - public var SocksProxySetup_Status: String { return self._s[2713]! } - public var Conversation_ScheduleMessage_SendWhenOnline: String { return self._s[2714]! } - public var PrivacyPolicy_Accept: String { return self._s[2715]! } - public var Notifications_ExceptionsMessagePlaceholder: String { return self._s[2716]! } - public var Appearance_AppIconClassicX: String { return self._s[2717]! } + public var Login_InvalidFirstNameError: String { return self._s[2704]! } + public var Notifications_Badge_CountUnreadMessages_InfoOn: String { return self._s[2705]! } + public var Checkout_PaymentMethod_New: String { return self._s[2706]! } + public var ShareMenu_CopyShareLinkGame: String { return self._s[2707]! } + public var PhotoEditor_QualityTool: String { return self._s[2708]! } + public var Login_SendCodeViaSms: String { return self._s[2709]! } + public var SettingsSearch_Synonyms_Privacy_DeleteAccountIfAwayFor: String { return self._s[2710]! } + public var Chat_SlowmodeAttachmentLimitReached: String { return self._s[2711]! } + public var Wallet_Receive_CopyAddress: String { return self._s[2712]! } + public var Login_EmailNotConfiguredError: String { return self._s[2713]! } + public var SocksProxySetup_Status: String { return self._s[2714]! } + public var Conversation_ScheduleMessage_SendWhenOnline: String { return self._s[2715]! } + public var PrivacyPolicy_Accept: String { return self._s[2716]! } + public var Notifications_ExceptionsMessagePlaceholder: String { return self._s[2717]! } + public var Appearance_AppIconClassicX: String { return self._s[2718]! } public func PUSH_CHAT_MESSAGE_TEXT(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2718]!, self._r[2718]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2719]!, self._r[2719]!, [_1, _2, _3]) } - public var OwnershipTransfer_SecurityRequirements: String { return self._s[2719]! } - public var InfoPlist_NSLocationAlwaysUsageDescription: String { return self._s[2721]! } - public var AutoNightTheme_Automatic: String { return self._s[2722]! } - public var Channel_Username_InvalidStartsWithNumber: String { return self._s[2723]! } - public var Privacy_ContactsSyncHelp: String { return self._s[2724]! } - public var Cache_Help: String { return self._s[2725]! } - public var Group_ErrorAccessDenied: String { return self._s[2726]! } - public var Passport_Language_fa: String { return self._s[2727]! } - public var Wallet_Intro_Text: String { return self._s[2728]! } - public var Login_ResetAccountProtected_TimerTitle: String { return self._s[2729]! } - public var VoiceOver_Chat_YourVideoMessage: String { return self._s[2730]! } - public var PrivacySettings_LastSeen: String { return self._s[2731]! } + public var OwnershipTransfer_SecurityRequirements: String { return self._s[2720]! } + public var InfoPlist_NSLocationAlwaysUsageDescription: String { return self._s[2722]! } + public var AutoNightTheme_Automatic: String { return self._s[2723]! } + public var Channel_Username_InvalidStartsWithNumber: String { return self._s[2724]! } + public var Privacy_ContactsSyncHelp: String { return self._s[2725]! } + public var Cache_Help: String { return self._s[2726]! } + public var Group_ErrorAccessDenied: String { return self._s[2727]! } + public var Passport_Language_fa: String { return self._s[2728]! } + public var Wallet_Intro_Text: String { return self._s[2729]! } + public var Login_ResetAccountProtected_TimerTitle: String { return self._s[2730]! } + public var VoiceOver_Chat_YourVideoMessage: String { return self._s[2731]! } + public var PrivacySettings_LastSeen: String { return self._s[2732]! } public func DialogList_MultipleTyping(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2732]!, self._r[2732]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2733]!, self._r[2733]!, [_0, _1]) } - public var Wallet_Configuration_Apply: String { return self._s[2736]! } - public var Preview_SaveGif: String { return self._s[2737]! } - public var SettingsSearch_Synonyms_Privacy_TwoStepAuth: String { return self._s[2738]! } - public var Profile_About: String { return self._s[2739]! } - public var Channel_About_Placeholder: String { return self._s[2740]! } - public var Login_InfoTitle: String { return self._s[2741]! } + public var Wallet_Configuration_Apply: String { return self._s[2737]! } + public var Preview_SaveGif: String { return self._s[2738]! } + public var SettingsSearch_Synonyms_Privacy_TwoStepAuth: String { return self._s[2739]! } + public var Profile_About: String { return self._s[2740]! } + public var Channel_About_Placeholder: String { return self._s[2741]! } + public var Login_InfoTitle: String { return self._s[2742]! } public func TwoStepAuth_SetupPendingEmail(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2742]!, self._r[2742]!, [_0]) + return formatWithArgumentRanges(self._s[2743]!, self._r[2743]!, [_0]) } - public var EditTheme_Expand_Preview_IncomingReplyText: String { return self._s[2743]! } - public var Watch_Suggestion_CantTalk: String { return self._s[2745]! } - public var ContactInfo_Title: String { return self._s[2746]! } - public var Media_ShareThisVideo: String { return self._s[2747]! } - public var Weekday_ShortFriday: String { return self._s[2748]! } - public var AccessDenied_Contacts: String { return self._s[2750]! } - public var Notification_CallIncomingShort: String { return self._s[2751]! } - public var Group_Setup_TypePublic: String { return self._s[2752]! } - public var Notifications_MessageNotificationsExceptions: String { return self._s[2753]! } - public var Notifications_Badge_IncludeChannels: String { return self._s[2754]! } - public var Notifications_MessageNotificationsPreview: String { return self._s[2757]! } - public var ConversationProfile_ErrorCreatingConversation: String { return self._s[2758]! } - public var Group_ErrorAddTooMuchBots: String { return self._s[2759]! } - public var Privacy_GroupsAndChannels_CustomShareHelp: String { return self._s[2760]! } - public var Permissions_CellularDataAllowInSettings_v0: String { return self._s[2761]! } + public var EditTheme_Expand_Preview_IncomingReplyText: String { return self._s[2744]! } + public var Watch_Suggestion_CantTalk: String { return self._s[2746]! } + public var ContactInfo_Title: String { return self._s[2747]! } + public var Media_ShareThisVideo: String { return self._s[2748]! } + public var Weekday_ShortFriday: String { return self._s[2749]! } + public var AccessDenied_Contacts: String { return self._s[2751]! } + public var Notification_CallIncomingShort: String { return self._s[2752]! } + public var Group_Setup_TypePublic: String { return self._s[2753]! } + public var Notifications_MessageNotificationsExceptions: String { return self._s[2754]! } + public var Notifications_Badge_IncludeChannels: String { return self._s[2755]! } + public var Notifications_MessageNotificationsPreview: String { return self._s[2758]! } + public var ConversationProfile_ErrorCreatingConversation: String { return self._s[2759]! } + public var Group_ErrorAddTooMuchBots: String { return self._s[2760]! } + public var Privacy_GroupsAndChannels_CustomShareHelp: String { return self._s[2761]! } + public var Permissions_CellularDataAllowInSettings_v0: String { return self._s[2762]! } public func Wallet_SecureStorageChanged_BiometryText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2762]!, self._r[2762]!, [_0]) + return formatWithArgumentRanges(self._s[2763]!, self._r[2763]!, [_0]) } - public var DialogList_Typing: String { return self._s[2763]! } - public var CallFeedback_IncludeLogs: String { return self._s[2765]! } - public var Checkout_Phone: String { return self._s[2767]! } - public var Login_InfoFirstNamePlaceholder: String { return self._s[2770]! } - public var Privacy_Calls_Integration: String { return self._s[2771]! } - public var Notifications_PermissionsAllow: String { return self._s[2772]! } - public var TwoStepAuth_AddHintDescription: String { return self._s[2776]! } - public var Settings_ChatSettings: String { return self._s[2777]! } - public var Conversation_SendingOptionsTooltip: String { return self._s[2778]! } + public var DialogList_Typing: String { return self._s[2764]! } + public var CallFeedback_IncludeLogs: String { return self._s[2766]! } + public var Checkout_Phone: String { return self._s[2768]! } + public var Login_InfoFirstNamePlaceholder: String { return self._s[2771]! } + public var Privacy_Calls_Integration: String { return self._s[2772]! } + public var Notifications_PermissionsAllow: String { return self._s[2773]! } + public var TwoStepAuth_AddHintDescription: String { return self._s[2777]! } + public var Settings_ChatSettings: String { return self._s[2778]! } + public var Conversation_SendingOptionsTooltip: String { return self._s[2779]! } public func UserInfo_StartSecretChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2780]!, self._r[2780]!, [_0]) + return formatWithArgumentRanges(self._s[2781]!, self._r[2781]!, [_0]) } public func Channel_AdminLog_MessageInvitedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2781]!, self._r[2781]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2782]!, self._r[2782]!, [_1, _2]) } - public var GroupRemoved_DeleteUser: String { return self._s[2783]! } + public var GroupRemoved_DeleteUser: String { return self._s[2784]! } public func Channel_AdminLog_PollStopped(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2784]!, self._r[2784]!, [_0]) + return formatWithArgumentRanges(self._s[2785]!, self._r[2785]!, [_0]) } public func PUSH_MESSAGE_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2785]!, self._r[2785]!, [_1]) + return formatWithArgumentRanges(self._s[2786]!, self._r[2786]!, [_1]) } - public var Login_ContinueWithLocalization: String { return self._s[2786]! } - public var Watch_Message_ForwardedFrom: String { return self._s[2787]! } - public var TwoStepAuth_EnterEmailCode: String { return self._s[2789]! } - public var Conversation_Unblock: String { return self._s[2790]! } - public var PrivacySettings_DataSettings: String { return self._s[2791]! } - public var WallpaperPreview_PatternPaternApply: String { return self._s[2792]! } - public var Group_PublicLink_Info: String { return self._s[2793]! } + public var Login_ContinueWithLocalization: String { return self._s[2787]! } + public var Watch_Message_ForwardedFrom: String { return self._s[2788]! } + public var TwoStepAuth_EnterEmailCode: String { return self._s[2790]! } + public var Conversation_Unblock: String { return self._s[2791]! } + public var PrivacySettings_DataSettings: String { return self._s[2792]! } + public var WallpaperPreview_PatternPaternApply: String { return self._s[2793]! } + public var Group_PublicLink_Info: String { return self._s[2794]! } public func Wallet_Time_PreciseDate_m1(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2794]!, self._r[2794]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2795]!, self._r[2795]!, [_1, _2, _3]) } - public var Notifications_InAppNotificationsVibrate: String { return self._s[2795]! } + public var Notifications_InAppNotificationsVibrate: String { return self._s[2796]! } public func Privacy_GroupsAndChannels_InviteToChannelError(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2796]!, self._r[2796]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2797]!, self._r[2797]!, [_0, _1]) } - public var OldChannels_ChannelsHeader: String { return self._s[2798]! } - public var Wallet_RestoreFailed_CreateWallet: String { return self._s[2799]! } - public var PrivacySettings_Passcode: String { return self._s[2801]! } - public var Call_Mute: String { return self._s[2802]! } - public var Wallet_Weekday_Yesterday: String { return self._s[2803]! } - public var Passport_Language_dz: String { return self._s[2804]! } - public var Wallet_Receive_AmountHeader: String { return self._s[2805]! } - public var Wallet_TransactionInfo_OtherFeeInfoUrl: String { return self._s[2806]! } - public var Passport_Language_tk: String { return self._s[2807]! } + public var OldChannels_ChannelsHeader: String { return self._s[2799]! } + public var Wallet_RestoreFailed_CreateWallet: String { return self._s[2800]! } + public var PrivacySettings_Passcode: String { return self._s[2802]! } + public var Call_Mute: String { return self._s[2803]! } + public var Wallet_Weekday_Yesterday: String { return self._s[2804]! } + public var Passport_Language_dz: String { return self._s[2805]! } + public var Wallet_Receive_AmountHeader: String { return self._s[2806]! } + public var Wallet_TransactionInfo_OtherFeeInfoUrl: String { return self._s[2807]! } + public var Passport_Language_tk: String { return self._s[2808]! } public func Login_EmailCodeSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2808]!, self._r[2808]!, [_0]) + return formatWithArgumentRanges(self._s[2809]!, self._r[2809]!, [_0]) } - public var Settings_Search: String { return self._s[2809]! } - public var Wallet_Month_ShortFebruary: String { return self._s[2810]! } - public var InfoPlist_NSPhotoLibraryUsageDescription: String { return self._s[2811]! } - public var Wallet_Configuration_SourceJSON: String { return self._s[2812]! } - public var Conversation_ContextMenuReply: String { return self._s[2813]! } - public var WallpaperSearch_ColorBrown: String { return self._s[2814]! } - public var Chat_AttachmentMultipleForwardDisabled: String { return self._s[2815]! } - public var Tour_Title1: String { return self._s[2816]! } - public var Wallet_Alert_Cancel: String { return self._s[2817]! } - public var Conversation_ClearGroupHistory: String { return self._s[2819]! } - public var Wallet_TransactionInfo_RecipientHeader: String { return self._s[2820]! } - public var WallpaperPreview_Motion: String { return self._s[2821]! } + public var Settings_Search: String { return self._s[2810]! } + public var Wallet_Month_ShortFebruary: String { return self._s[2811]! } + public var InfoPlist_NSPhotoLibraryUsageDescription: String { return self._s[2812]! } + public var Wallet_Configuration_SourceJSON: String { return self._s[2813]! } + public var Conversation_ContextMenuReply: String { return self._s[2814]! } + public var WallpaperSearch_ColorBrown: String { return self._s[2815]! } + public var Chat_AttachmentMultipleForwardDisabled: String { return self._s[2816]! } + public var Tour_Title1: String { return self._s[2817]! } + public var Wallet_Alert_Cancel: String { return self._s[2818]! } + public var Conversation_ClearGroupHistory: String { return self._s[2820]! } + public var Wallet_TransactionInfo_RecipientHeader: String { return self._s[2821]! } + public var WallpaperPreview_Motion: String { return self._s[2822]! } public func Checkout_PasswordEntry_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2822]!, self._r[2822]!, [_0]) + return formatWithArgumentRanges(self._s[2823]!, self._r[2823]!, [_0]) } - public var Wallet_Configuration_ApplyErrorTextJSONInvalidData: String { return self._s[2823]! } - public var Call_RateCall: String { return self._s[2824]! } - public var Channel_AdminLog_BanSendStickersAndGifs: String { return self._s[2825]! } - public var Passport_PasswordCompleteSetup: String { return self._s[2826]! } - public var Conversation_InputTextSilentBroadcastPlaceholder: String { return self._s[2827]! } - public var UserInfo_LastNamePlaceholder: String { return self._s[2829]! } + public var Wallet_Configuration_ApplyErrorTextJSONInvalidData: String { return self._s[2824]! } + public var Call_RateCall: String { return self._s[2825]! } + public var Channel_AdminLog_BanSendStickersAndGifs: String { return self._s[2826]! } + public var Passport_PasswordCompleteSetup: String { return self._s[2827]! } + public var Conversation_InputTextSilentBroadcastPlaceholder: String { return self._s[2828]! } + public var UserInfo_LastNamePlaceholder: String { return self._s[2830]! } public func Login_WillCallYou(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2831]!, self._r[2831]!, [_0]) + return formatWithArgumentRanges(self._s[2832]!, self._r[2832]!, [_0]) } - public var Compose_Create: String { return self._s[2832]! } - public var Contacts_InviteToTelegram: String { return self._s[2833]! } - public var GroupInfo_Notifications: String { return self._s[2834]! } - public var ChatList_DeleteSavedMessagesConfirmationAction: String { return self._s[2836]! } - public var Message_PinnedLiveLocationMessage: String { return self._s[2837]! } - public var Month_GenApril: String { return self._s[2838]! } - public var Appearance_AutoNightTheme: String { return self._s[2839]! } - public var ChatSettings_AutomaticAudioDownload: String { return self._s[2841]! } - public var Login_CodeSentSms: String { return self._s[2843]! } + public var Compose_Create: String { return self._s[2833]! } + public var Contacts_InviteToTelegram: String { return self._s[2834]! } + public var GroupInfo_Notifications: String { return self._s[2835]! } + public var ChatList_DeleteSavedMessagesConfirmationAction: String { return self._s[2837]! } + public var Message_PinnedLiveLocationMessage: String { return self._s[2838]! } + public var Month_GenApril: String { return self._s[2839]! } + public var Appearance_AutoNightTheme: String { return self._s[2840]! } + public var ChatSettings_AutomaticAudioDownload: String { return self._s[2842]! } + public var Login_CodeSentSms: String { return self._s[2844]! } public func UserInfo_UnblockConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2844]!, self._r[2844]!, [_0]) + return formatWithArgumentRanges(self._s[2845]!, self._r[2845]!, [_0]) } - public var EmptyGroupInfo_Line3: String { return self._s[2845]! } - public var LogoutOptions_ContactSupportText: String { return self._s[2846]! } - public var Passport_Language_hr: String { return self._s[2847]! } - public var Common_ActionNotAllowedError: String { return self._s[2848]! } + public var EmptyGroupInfo_Line3: String { return self._s[2846]! } + public var LogoutOptions_ContactSupportText: String { return self._s[2847]! } + public var Passport_Language_hr: String { return self._s[2848]! } + public var Common_ActionNotAllowedError: String { return self._s[2849]! } public func Channel_AdminLog_MessageRestrictedNewSetting(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2849]!, self._r[2849]!, [_0]) + return formatWithArgumentRanges(self._s[2850]!, self._r[2850]!, [_0]) } - public var GroupInfo_InviteLink_CopyLink: String { return self._s[2850]! } - public var Wallet_Info_TransactionFrom: String { return self._s[2851]! } - public var Wallet_Send_ErrorDecryptionFailed: String { return self._s[2852]! } - public var Conversation_InputTextBroadcastPlaceholder: String { return self._s[2853]! } - public var Privacy_SecretChatsTitle: String { return self._s[2854]! } - public var Notification_SecretChatMessageScreenshotSelf: String { return self._s[2856]! } - public var GroupInfo_AddUserLeftError: String { return self._s[2857]! } - public var AutoDownloadSettings_TypePrivateChats: String { return self._s[2858]! } - public var LogoutOptions_ContactSupportTitle: String { return self._s[2859]! } - public var Appearance_ThemePreview_Chat_7_Text: String { return self._s[2860]! } - public var Channel_AddBotErrorHaveRights: String { return self._s[2861]! } - public var Preview_DeleteGif: String { return self._s[2862]! } - public var GroupInfo_Permissions_Exceptions: String { return self._s[2863]! } - public var Group_ErrorNotMutualContact: String { return self._s[2864]! } - public var Notification_MessageLifetime5s: String { return self._s[2865]! } - public var Wallet_Send_OwnAddressAlertText: String { return self._s[2866]! } - public var OldChannels_ChannelFormat: String { return self._s[2867]! } + public var GroupInfo_InviteLink_CopyLink: String { return self._s[2851]! } + public var Wallet_Info_TransactionFrom: String { return self._s[2852]! } + public var Wallet_Send_ErrorDecryptionFailed: String { return self._s[2853]! } + public var Conversation_InputTextBroadcastPlaceholder: String { return self._s[2854]! } + public var Privacy_SecretChatsTitle: String { return self._s[2855]! } + public var Notification_SecretChatMessageScreenshotSelf: String { return self._s[2857]! } + public var GroupInfo_AddUserLeftError: String { return self._s[2858]! } + public var AutoDownloadSettings_TypePrivateChats: String { return self._s[2859]! } + public var LogoutOptions_ContactSupportTitle: String { return self._s[2860]! } + public var Appearance_ThemePreview_Chat_7_Text: String { return self._s[2861]! } + public var Channel_AddBotErrorHaveRights: String { return self._s[2862]! } + public var Preview_DeleteGif: String { return self._s[2863]! } + public var GroupInfo_Permissions_Exceptions: String { return self._s[2864]! } + public var Group_ErrorNotMutualContact: String { return self._s[2865]! } + public var Notification_MessageLifetime5s: String { return self._s[2866]! } + public var Wallet_Send_OwnAddressAlertText: String { return self._s[2867]! } + public var OldChannels_ChannelFormat: String { return self._s[2868]! } public func Watch_LastSeen_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2868]!, self._r[2868]!, [_0]) + return formatWithArgumentRanges(self._s[2869]!, self._r[2869]!, [_0]) } - public var VoiceOver_Chat_Video: String { return self._s[2869]! } - public var Channel_OwnershipTransfer_ErrorPublicChannelsTooMuch: String { return self._s[2871]! } - public var ReportSpam_DeleteThisChat: String { return self._s[2872]! } - public var Passport_Address_AddBankStatement: String { return self._s[2873]! } - public var Notification_CallIncoming: String { return self._s[2874]! } - public var Wallet_Words_NotDoneTitle: String { return self._s[2875]! } - public var Compose_NewGroupTitle: String { return self._s[2876]! } - public var TwoStepAuth_RecoveryCodeHelp: String { return self._s[2878]! } - public var Passport_Address_Postcode: String { return self._s[2880]! } + public var VoiceOver_Chat_Video: String { return self._s[2870]! } + public var Channel_OwnershipTransfer_ErrorPublicChannelsTooMuch: String { return self._s[2872]! } + public var ReportSpam_DeleteThisChat: String { return self._s[2873]! } + public var Passport_Address_AddBankStatement: String { return self._s[2874]! } + public var Notification_CallIncoming: String { return self._s[2875]! } + public var Wallet_Words_NotDoneTitle: String { return self._s[2876]! } + public var Compose_NewGroupTitle: String { return self._s[2877]! } + public var TwoStepAuth_RecoveryCodeHelp: String { return self._s[2879]! } + public var Passport_Address_Postcode: String { return self._s[2881]! } public func LastSeen_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2881]!, self._r[2881]!, [_0]) + return formatWithArgumentRanges(self._s[2882]!, self._r[2882]!, [_0]) } - public var Checkout_NewCard_SaveInfoHelp: String { return self._s[2882]! } - public var Wallet_Month_ShortOctober: String { return self._s[2883]! } - public var VoiceOver_Chat_YourMusic: String { return self._s[2884]! } - public var WallpaperColors_Title: String { return self._s[2885]! } - public var SocksProxySetup_ShareQRCodeInfo: String { return self._s[2886]! } - public var VoiceOver_MessageContextForward: String { return self._s[2887]! } - public var GroupPermission_Duration: String { return self._s[2888]! } + public var Checkout_NewCard_SaveInfoHelp: String { return self._s[2883]! } + public var Wallet_Month_ShortOctober: String { return self._s[2884]! } + public var VoiceOver_Chat_YourMusic: String { return self._s[2885]! } + public var WallpaperColors_Title: String { return self._s[2886]! } + public var SocksProxySetup_ShareQRCodeInfo: String { return self._s[2887]! } + public var VoiceOver_MessageContextForward: String { return self._s[2888]! } + public var GroupPermission_Duration: String { return self._s[2889]! } public func Cache_Clear(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2889]!, self._r[2889]!, [_0]) + return formatWithArgumentRanges(self._s[2890]!, self._r[2890]!, [_0]) } - public var Bot_GroupStatusDoesNotReadHistory: String { return self._s[2890]! } - public var Username_Placeholder: String { return self._s[2891]! } - public var CallFeedback_WhatWentWrong: String { return self._s[2892]! } - public var Passport_FieldAddressUploadHelp: String { return self._s[2893]! } - public var Permissions_NotificationsAllowInSettings_v0: String { return self._s[2894]! } + public var Bot_GroupStatusDoesNotReadHistory: String { return self._s[2891]! } + public var Username_Placeholder: String { return self._s[2892]! } + public var CallFeedback_WhatWentWrong: String { return self._s[2893]! } + public var Passport_FieldAddressUploadHelp: String { return self._s[2894]! } + public var Permissions_NotificationsAllowInSettings_v0: String { return self._s[2895]! } public func Channel_AdminLog_MessageChangedUnlinkedChannel(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2896]!, self._r[2896]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2897]!, self._r[2897]!, [_1, _2]) } - public var Passport_PasswordDescription: String { return self._s[2897]! } - public var Channel_MessagePhotoUpdated: String { return self._s[2898]! } - public var MediaPicker_TapToUngroupDescription: String { return self._s[2899]! } - public var SettingsSearch_Synonyms_Notifications_BadgeCountUnreadMessages: String { return self._s[2900]! } - public var AttachmentMenu_PhotoOrVideo: String { return self._s[2901]! } - public var Conversation_ContextMenuMore: String { return self._s[2902]! } - public var Privacy_PaymentsClearInfo: String { return self._s[2903]! } - public var CallSettings_TabIcon: String { return self._s[2904]! } - public var KeyCommand_Find: String { return self._s[2905]! } - public var ClearCache_FreeSpaceDescription: String { return self._s[2906]! } - public var Appearance_ThemePreview_ChatList_7_Text: String { return self._s[2907]! } - public var EditTheme_Edit_Preview_IncomingText: String { return self._s[2908]! } - public var Message_PinnedGame: String { return self._s[2909]! } - public var VoiceOver_Chat_ForwardedFromYou: String { return self._s[2910]! } - public var Notifications_Badge_CountUnreadMessages_InfoOff: String { return self._s[2912]! } - public var Login_CallRequestState2: String { return self._s[2914]! } - public var CheckoutInfo_ReceiverInfoNamePlaceholder: String { return self._s[2916]! } + public var Passport_PasswordDescription: String { return self._s[2898]! } + public var Channel_MessagePhotoUpdated: String { return self._s[2899]! } + public var MediaPicker_TapToUngroupDescription: String { return self._s[2900]! } + public var SettingsSearch_Synonyms_Notifications_BadgeCountUnreadMessages: String { return self._s[2901]! } + public var AttachmentMenu_PhotoOrVideo: String { return self._s[2902]! } + public var Conversation_ContextMenuMore: String { return self._s[2903]! } + public var Privacy_PaymentsClearInfo: String { return self._s[2904]! } + public var CallSettings_TabIcon: String { return self._s[2905]! } + public var KeyCommand_Find: String { return self._s[2906]! } + public var ClearCache_FreeSpaceDescription: String { return self._s[2907]! } + public var Appearance_ThemePreview_ChatList_7_Text: String { return self._s[2908]! } + public var EditTheme_Edit_Preview_IncomingText: String { return self._s[2909]! } + public var Message_PinnedGame: String { return self._s[2910]! } + public var VoiceOver_Chat_ForwardedFromYou: String { return self._s[2911]! } + public var Notifications_Badge_CountUnreadMessages_InfoOff: String { return self._s[2913]! } + public var Login_CallRequestState2: String { return self._s[2915]! } + public var CheckoutInfo_ReceiverInfoNamePlaceholder: String { return self._s[2917]! } public func VoiceOver_Chat_PhotoFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2917]!, self._r[2917]!, [_0]) + return formatWithArgumentRanges(self._s[2918]!, self._r[2918]!, [_0]) } public func Checkout_PayPrice(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2919]!, self._r[2919]!, [_0]) + return formatWithArgumentRanges(self._s[2920]!, self._r[2920]!, [_0]) } - public var AuthSessions_AddDevice: String { return self._s[2920]! } - public var WallpaperPreview_Blurred: String { return self._s[2921]! } - public var Conversation_InstantPagePreview: String { return self._s[2922]! } + public var AuthSessions_AddDevice: String { return self._s[2921]! } + public var WallpaperPreview_Blurred: String { return self._s[2922]! } + public var Conversation_InstantPagePreview: String { return self._s[2923]! } public func DialogList_SingleUploadingVideoSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2923]!, self._r[2923]!, [_0]) + return formatWithArgumentRanges(self._s[2924]!, self._r[2924]!, [_0]) } - public var SecretTimer_VideoDescription: String { return self._s[2926]! } - public var WallpaperSearch_ColorRed: String { return self._s[2927]! } - public var GroupPermission_NoPinMessages: String { return self._s[2928]! } - public var Passport_Language_es: String { return self._s[2929]! } - public var Permissions_ContactsAllow_v0: String { return self._s[2931]! } - public var Conversation_EditingMessageMediaEditCurrentVideo: String { return self._s[2932]! } + public var SecretTimer_VideoDescription: String { return self._s[2927]! } + public var WallpaperSearch_ColorRed: String { return self._s[2928]! } + public var GroupPermission_NoPinMessages: String { return self._s[2929]! } + public var Passport_Language_es: String { return self._s[2930]! } + public var Permissions_ContactsAllow_v0: String { return self._s[2932]! } + public var Conversation_EditingMessageMediaEditCurrentVideo: String { return self._s[2933]! } public func PUSH_CHAT_MESSAGE_CONTACT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2933]!, self._r[2933]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2934]!, self._r[2934]!, [_1, _2]) } - public var Privacy_Forwards_CustomHelp: String { return self._s[2934]! } - public var WebPreview_GettingLinkInfo: String { return self._s[2935]! } - public var Watch_UserInfo_Unmute: String { return self._s[2936]! } - public var GroupInfo_ChannelListNamePlaceholder: String { return self._s[2937]! } - public var AccessDenied_CameraRestricted: String { return self._s[2939]! } + public var Privacy_Forwards_CustomHelp: String { return self._s[2935]! } + public var WebPreview_GettingLinkInfo: String { return self._s[2936]! } + public var Watch_UserInfo_Unmute: String { return self._s[2937]! } + public var GroupInfo_ChannelListNamePlaceholder: String { return self._s[2938]! } + public var AccessDenied_CameraRestricted: String { return self._s[2940]! } public func Conversation_Kilobytes(_ _0: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2940]!, self._r[2940]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[2941]!, self._r[2941]!, ["\(_0)"]) } - public var ChatList_ReadAll: String { return self._s[2942]! } - public var Settings_CopyUsername: String { return self._s[2943]! } - public var Contacts_SearchLabel: String { return self._s[2944]! } - public var Map_OpenInYandexNavigator: String { return self._s[2946]! } - public var PasscodeSettings_EncryptData: String { return self._s[2947]! } - public var Settings_Wallet: String { return self._s[2948]! } - public var Group_ErrorSupergroupConversionNotPossible: String { return self._s[2949]! } - public var WallpaperSearch_ColorPrefix: String { return self._s[2950]! } - public var Notifications_GroupNotificationsPreview: String { return self._s[2951]! } - public var DialogList_AdNoticeAlert: String { return self._s[2952]! } - public var Wallet_Month_GenMay: String { return self._s[2954]! } - public var CheckoutInfo_ShippingInfoAddress1: String { return self._s[2955]! } - public var CheckoutInfo_ShippingInfoAddress2: String { return self._s[2956]! } - public var Localization_LanguageCustom: String { return self._s[2957]! } - public var Passport_Identity_TypeDriversLicenseUploadScan: String { return self._s[2958]! } - public var CallFeedback_Title: String { return self._s[2959]! } - public var VoiceOver_Chat_RecordPreviewVoiceMessage: String { return self._s[2962]! } - public var Passport_Address_OneOfTypePassportRegistration: String { return self._s[2963]! } - public var Wallet_Intro_CreateErrorTitle: String { return self._s[2964]! } - public var Conversation_InfoGroup: String { return self._s[2965]! } - public var Compose_NewMessage: String { return self._s[2966]! } - public var FastTwoStepSetup_HintPlaceholder: String { return self._s[2967]! } - public var ChatSettings_AutoDownloadVideoMessages: String { return self._s[2968]! } - public var Wallet_SecureStorageReset_BiometryFaceId: String { return self._s[2969]! } - public var Channel_DiscussionGroup_UnlinkChannel: String { return self._s[2970]! } + public var ChatList_ReadAll: String { return self._s[2943]! } + public var Settings_CopyUsername: String { return self._s[2944]! } + public var Contacts_SearchLabel: String { return self._s[2945]! } + public var Map_OpenInYandexNavigator: String { return self._s[2947]! } + public var PasscodeSettings_EncryptData: String { return self._s[2948]! } + public var Settings_Wallet: String { return self._s[2949]! } + public var Group_ErrorSupergroupConversionNotPossible: String { return self._s[2950]! } + public var WallpaperSearch_ColorPrefix: String { return self._s[2951]! } + public var Notifications_GroupNotificationsPreview: String { return self._s[2952]! } + public var DialogList_AdNoticeAlert: String { return self._s[2953]! } + public var Wallet_Month_GenMay: String { return self._s[2955]! } + public var CheckoutInfo_ShippingInfoAddress1: String { return self._s[2956]! } + public var CheckoutInfo_ShippingInfoAddress2: String { return self._s[2957]! } + public var Localization_LanguageCustom: String { return self._s[2958]! } + public var Passport_Identity_TypeDriversLicenseUploadScan: String { return self._s[2959]! } + public var CallFeedback_Title: String { return self._s[2960]! } + public var VoiceOver_Chat_RecordPreviewVoiceMessage: String { return self._s[2963]! } + public var Passport_Address_OneOfTypePassportRegistration: String { return self._s[2964]! } + public var Wallet_Intro_CreateErrorTitle: String { return self._s[2965]! } + public var Conversation_InfoGroup: String { return self._s[2966]! } + public var Compose_NewMessage: String { return self._s[2967]! } + public var FastTwoStepSetup_HintPlaceholder: String { return self._s[2968]! } + public var ChatSettings_AutoDownloadVideoMessages: String { return self._s[2969]! } + public var Wallet_SecureStorageReset_BiometryFaceId: String { return self._s[2970]! } + public var Channel_DiscussionGroup_UnlinkChannel: String { return self._s[2971]! } public func Passport_Scans_ScanIndex(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2971]!, self._r[2971]!, [_0]) + return formatWithArgumentRanges(self._s[2972]!, self._r[2972]!, [_0]) } - public var Channel_AdminLog_CanDeleteMessages: String { return self._s[2972]! } - public var Login_CancelSignUpConfirmation: String { return self._s[2973]! } - public var ChangePhoneNumberCode_Help: String { return self._s[2974]! } - public var PrivacySettings_DeleteAccountHelp: String { return self._s[2975]! } - public var Channel_BlackList_Title: String { return self._s[2976]! } - public var UserInfo_PhoneCall: String { return self._s[2977]! } - public var Passport_Address_OneOfTypeBankStatement: String { return self._s[2979]! } - public var Wallet_Month_ShortJanuary: String { return self._s[2980]! } - public var State_connecting: String { return self._s[2981]! } - public var Appearance_ThemePreview_ChatList_6_Text: String { return self._s[2982]! } - public var Wallet_Month_GenMarch: String { return self._s[2983]! } - public var EditTheme_Expand_BottomInfo: String { return self._s[2984]! } - public var AuthSessions_AddedDeviceTerminate: String { return self._s[2985]! } + public var Channel_AdminLog_CanDeleteMessages: String { return self._s[2973]! } + public var Login_CancelSignUpConfirmation: String { return self._s[2974]! } + public var ChangePhoneNumberCode_Help: String { return self._s[2975]! } + public var PrivacySettings_DeleteAccountHelp: String { return self._s[2976]! } + public var Channel_BlackList_Title: String { return self._s[2977]! } + public var UserInfo_PhoneCall: String { return self._s[2978]! } + public var Passport_Address_OneOfTypeBankStatement: String { return self._s[2980]! } + public var Wallet_Month_ShortJanuary: String { return self._s[2981]! } + public var State_connecting: String { return self._s[2982]! } + public var Appearance_ThemePreview_ChatList_6_Text: String { return self._s[2983]! } + public var Wallet_Month_GenMarch: String { return self._s[2984]! } + public var EditTheme_Expand_BottomInfo: String { return self._s[2985]! } + public var AuthSessions_AddedDeviceTerminate: String { return self._s[2986]! } public func LastSeen_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2986]!, self._r[2986]!, [_0]) - } - public func DialogList_SingleRecordingAudioSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2987]!, self._r[2987]!, [_0]) } - public var Notifications_GroupNotifications: String { return self._s[2988]! } - public var Conversation_SendMessageErrorTooMuchScheduled: String { return self._s[2989]! } - public var Passport_Identity_EditPassport: String { return self._s[2990]! } - public var EnterPasscode_RepeatNewPasscode: String { return self._s[2992]! } - public var Localization_EnglishLanguageName: String { return self._s[2993]! } - public var Share_AuthDescription: String { return self._s[2994]! } - public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsAlert: String { return self._s[2995]! } - public var Passport_Identity_Surname: String { return self._s[2996]! } - public var Compose_TokenListPlaceholder: String { return self._s[2997]! } - public var Wallet_AccessDenied_Camera: String { return self._s[2998]! } - public var Passport_Identity_OneOfTypePassport: String { return self._s[2999]! } - public var Settings_AboutEmpty: String { return self._s[3000]! } - public var Conversation_Unmute: String { return self._s[3001]! } - public var CreateGroup_ChannelsTooMuch: String { return self._s[3003]! } - public var Wallet_Sending_Text: String { return self._s[3004]! } - public func PUSH_CONTACT_JOINED(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3005]!, self._r[3005]!, [_1]) + public func DialogList_SingleRecordingAudioSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2988]!, self._r[2988]!, [_0]) } - public var Login_CodeSentCall: String { return self._s[3006]! } - public var ContactInfo_PhoneLabelHomeFax: String { return self._s[3008]! } - public var ChatSettings_Appearance: String { return self._s[3009]! } - public var ClearCache_StorageUsage: String { return self._s[3010]! } - public var Appearance_PickAccentColor: String { return self._s[3011]! } + public var Notifications_GroupNotifications: String { return self._s[2989]! } + public var Conversation_SendMessageErrorTooMuchScheduled: String { return self._s[2990]! } + public var Passport_Identity_EditPassport: String { return self._s[2991]! } + public var EnterPasscode_RepeatNewPasscode: String { return self._s[2993]! } + public var Localization_EnglishLanguageName: String { return self._s[2994]! } + public var Share_AuthDescription: String { return self._s[2995]! } + public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsAlert: String { return self._s[2996]! } + public var Passport_Identity_Surname: String { return self._s[2997]! } + public var Compose_TokenListPlaceholder: String { return self._s[2998]! } + public var Wallet_AccessDenied_Camera: String { return self._s[2999]! } + public var Passport_Identity_OneOfTypePassport: String { return self._s[3000]! } + public var Settings_AboutEmpty: String { return self._s[3001]! } + public var Conversation_Unmute: String { return self._s[3002]! } + public var CreateGroup_ChannelsTooMuch: String { return self._s[3004]! } + public var Wallet_Sending_Text: String { return self._s[3005]! } + public func PUSH_CONTACT_JOINED(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3006]!, self._r[3006]!, [_1]) + } + public var Login_CodeSentCall: String { return self._s[3007]! } + public var ContactInfo_PhoneLabelHomeFax: String { return self._s[3009]! } + public var ChatSettings_Appearance: String { return self._s[3010]! } + public var ClearCache_StorageUsage: String { return self._s[3011]! } + public var Appearance_PickAccentColor: String { return self._s[3012]! } public func PUSH_CHAT_MESSAGE_NOTEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3012]!, self._r[3012]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3013]!, self._r[3013]!, [_1, _2]) } public func PUSH_MESSAGE_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3013]!, self._r[3013]!, [_1]) + return formatWithArgumentRanges(self._s[3014]!, self._r[3014]!, [_1]) } - public var Notification_CallMissed: String { return self._s[3014]! } - public var SettingsSearch_Synonyms_Appearance_ChatBackground_Custom: String { return self._s[3015]! } - public var Channel_AdminLogFilter_EventsInfo: String { return self._s[3016]! } - public var Wallet_Month_GenOctober: String { return self._s[3018]! } - public var ChatAdmins_AdminLabel: String { return self._s[3019]! } - public var KeyCommand_JumpToNextChat: String { return self._s[3020]! } - public var Conversation_StopPollConfirmationTitle: String { return self._s[3022]! } - public var ChangePhoneNumberCode_CodePlaceholder: String { return self._s[3023]! } - public var Month_GenJune: String { return self._s[3024]! } - public var IntentsSettings_MainAccountInfo: String { return self._s[3025]! } - public var Watch_Location_Current: String { return self._s[3026]! } - public var Wallet_Receive_CopyInvoiceUrl: String { return self._s[3027]! } - public var Conversation_TitleMute: String { return self._s[3028]! } - public var Map_PlacesInThisArea: String { return self._s[3029]! } + public var Notification_CallMissed: String { return self._s[3015]! } + public var SettingsSearch_Synonyms_Appearance_ChatBackground_Custom: String { return self._s[3016]! } + public var Channel_AdminLogFilter_EventsInfo: String { return self._s[3017]! } + public var Wallet_Month_GenOctober: String { return self._s[3019]! } + public var ChatAdmins_AdminLabel: String { return self._s[3020]! } + public var KeyCommand_JumpToNextChat: String { return self._s[3021]! } + public var Conversation_StopPollConfirmationTitle: String { return self._s[3023]! } + public var ChangePhoneNumberCode_CodePlaceholder: String { return self._s[3024]! } + public var Month_GenJune: String { return self._s[3025]! } + public var IntentsSettings_MainAccountInfo: String { return self._s[3026]! } + public var Watch_Location_Current: String { return self._s[3027]! } + public var Wallet_Receive_CopyInvoiceUrl: String { return self._s[3028]! } + public var Conversation_TitleMute: String { return self._s[3029]! } + public var Map_PlacesInThisArea: String { return self._s[3030]! } public func PUSH_CHANNEL_MESSAGE_ROUND(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3030]!, self._r[3030]!, [_1]) + return formatWithArgumentRanges(self._s[3031]!, self._r[3031]!, [_1]) } - public var GroupInfo_DeleteAndExit: String { return self._s[3031]! } + public var GroupInfo_DeleteAndExit: String { return self._s[3032]! } public func Conversation_Moderate_DeleteAllMessages(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3032]!, self._r[3032]!, [_0]) + return formatWithArgumentRanges(self._s[3033]!, self._r[3033]!, [_0]) } - public var Call_ReportPlaceholder: String { return self._s[3033]! } - public var Chat_SlowmodeSendError: String { return self._s[3034]! } - public var MaskStickerSettings_Info: String { return self._s[3035]! } - public var EditTheme_Expand_TopInfo: String { return self._s[3036]! } + public var Call_ReportPlaceholder: String { return self._s[3034]! } + public var Chat_SlowmodeSendError: String { return self._s[3035]! } + public var MaskStickerSettings_Info: String { return self._s[3036]! } + public var EditTheme_Expand_TopInfo: String { return self._s[3037]! } public func GroupInfo_AddParticipantConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3037]!, self._r[3037]!, [_0]) + return formatWithArgumentRanges(self._s[3038]!, self._r[3038]!, [_0]) } - public var Checkout_NewCard_PostcodeTitle: String { return self._s[3038]! } - public var Passport_Address_RegionPlaceholder: String { return self._s[3040]! } - public var Contacts_ShareTelegram: String { return self._s[3041]! } - public var EnterPasscode_EnterNewPasscodeNew: String { return self._s[3042]! } - public var Map_AddressOnMap: String { return self._s[3043]! } - public var Channel_ErrorAccessDenied: String { return self._s[3044]! } - public var UserInfo_ScamBotWarning: String { return self._s[3046]! } - public var Stickers_GroupChooseStickerPack: String { return self._s[3047]! } - public var Call_ConnectionErrorTitle: String { return self._s[3048]! } - public var UserInfo_NotificationsEnable: String { return self._s[3049]! } - public var ArchivedChats_IntroText1: String { return self._s[3050]! } - public var Tour_Text4: String { return self._s[3053]! } - public var WallpaperSearch_Recent: String { return self._s[3054]! } - public var GroupInfo_ScamGroupWarning: String { return self._s[3055]! } - public var Profile_MessageLifetime2s: String { return self._s[3057]! } - public var Appearance_ThemePreview_ChatList_5_Text: String { return self._s[3058]! } - public var Notification_MessageLifetime2s: String { return self._s[3059]! } + public var Checkout_NewCard_PostcodeTitle: String { return self._s[3039]! } + public var Passport_Address_RegionPlaceholder: String { return self._s[3041]! } + public var Contacts_ShareTelegram: String { return self._s[3042]! } + public var EnterPasscode_EnterNewPasscodeNew: String { return self._s[3043]! } + public var Map_AddressOnMap: String { return self._s[3044]! } + public var Channel_ErrorAccessDenied: String { return self._s[3045]! } + public var UserInfo_ScamBotWarning: String { return self._s[3047]! } + public var Stickers_GroupChooseStickerPack: String { return self._s[3048]! } + public var Call_ConnectionErrorTitle: String { return self._s[3049]! } + public var UserInfo_NotificationsEnable: String { return self._s[3050]! } + public var ArchivedChats_IntroText1: String { return self._s[3051]! } + public var Tour_Text4: String { return self._s[3054]! } + public var WallpaperSearch_Recent: String { return self._s[3055]! } + public var GroupInfo_ScamGroupWarning: String { return self._s[3056]! } + public var Profile_MessageLifetime2s: String { return self._s[3058]! } + public var Appearance_ThemePreview_ChatList_5_Text: String { return self._s[3059]! } + public var Notification_MessageLifetime2s: String { return self._s[3060]! } public func Time_PreciseDate_m10(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3060]!, self._r[3060]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3061]!, self._r[3061]!, [_1, _2, _3]) } - public var Cache_ClearCache: String { return self._s[3061]! } - public var AutoNightTheme_UpdateLocation: String { return self._s[3062]! } - public var Permissions_NotificationsUnreachableText_v0: String { return self._s[3063]! } + public var Cache_ClearCache: String { return self._s[3062]! } + public var AutoNightTheme_UpdateLocation: String { return self._s[3063]! } + public var Permissions_NotificationsUnreachableText_v0: String { return self._s[3064]! } public func Channel_AdminLog_MessageChangedGroupUsername(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3067]!, self._r[3067]!, [_0]) + return formatWithArgumentRanges(self._s[3068]!, self._r[3068]!, [_0]) } public func Conversation_ShareMyPhoneNumber_StatusSuccess(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3069]!, self._r[3069]!, [_0]) + return formatWithArgumentRanges(self._s[3070]!, self._r[3070]!, [_0]) } - public var LocalGroup_Text: String { return self._s[3070]! } - public var Channel_AdminLog_EmptyFilterTitle: String { return self._s[3071]! } - public var SocksProxySetup_TypeSocks: String { return self._s[3072]! } - public var ChatList_UnarchiveAction: String { return self._s[3073]! } - public var AutoNightTheme_Title: String { return self._s[3074]! } - public var InstantPage_FeedbackButton: String { return self._s[3075]! } - public var Passport_FieldAddress: String { return self._s[3076]! } + public var LocalGroup_Text: String { return self._s[3071]! } + public var Channel_AdminLog_EmptyFilterTitle: String { return self._s[3072]! } + public var SocksProxySetup_TypeSocks: String { return self._s[3073]! } + public var ChatList_UnarchiveAction: String { return self._s[3074]! } + public var AutoNightTheme_Title: String { return self._s[3075]! } + public var InstantPage_FeedbackButton: String { return self._s[3076]! } + public var Passport_FieldAddress: String { return self._s[3077]! } public func Channel_AdminLog_SetSlowmode(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3077]!, self._r[3077]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3078]!, self._r[3078]!, [_1, _2]) } - public var Month_ShortMarch: String { return self._s[3078]! } + public var Month_ShortMarch: String { return self._s[3079]! } public func PUSH_MESSAGE_INVOICE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3079]!, self._r[3079]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3080]!, self._r[3080]!, [_1, _2]) } - public var SocksProxySetup_UsernamePlaceholder: String { return self._s[3080]! } - public var Conversation_ShareInlineBotLocationConfirmation: String { return self._s[3081]! } - public var Passport_FloodError: String { return self._s[3082]! } - public var SecretGif_Title: String { return self._s[3083]! } - public var NotificationSettings_ShowNotificationsAllAccountsInfoOn: String { return self._s[3084]! } - public var ChatList_Context_UnhideArchive: String { return self._s[3085]! } - public var Passport_Language_th: String { return self._s[3087]! } - public var Passport_Address_Address: String { return self._s[3088]! } - public var Login_InvalidLastNameError: String { return self._s[3089]! } - public var Notifications_InAppNotificationsPreview: String { return self._s[3090]! } - public var Notifications_PermissionsUnreachableTitle: String { return self._s[3091]! } - public var ChatList_Context_Archive: String { return self._s[3092]! } - public var SettingsSearch_FAQ: String { return self._s[3093]! } - public var ShareMenu_Send: String { return self._s[3094]! } - public var WallpaperSearch_ColorYellow: String { return self._s[3096]! } - public var Month_GenNovember: String { return self._s[3098]! } - public var SettingsSearch_Synonyms_Appearance_LargeEmoji: String { return self._s[3100]! } + public var SocksProxySetup_UsernamePlaceholder: String { return self._s[3081]! } + public var Conversation_ShareInlineBotLocationConfirmation: String { return self._s[3082]! } + public var Passport_FloodError: String { return self._s[3083]! } + public var SecretGif_Title: String { return self._s[3084]! } + public var NotificationSettings_ShowNotificationsAllAccountsInfoOn: String { return self._s[3085]! } + public var ChatList_Context_UnhideArchive: String { return self._s[3086]! } + public var Passport_Language_th: String { return self._s[3088]! } + public var Passport_Address_Address: String { return self._s[3089]! } + public var Login_InvalidLastNameError: String { return self._s[3090]! } + public var Notifications_InAppNotificationsPreview: String { return self._s[3091]! } + public var Notifications_PermissionsUnreachableTitle: String { return self._s[3092]! } + public var ChatList_Context_Archive: String { return self._s[3093]! } + public var SettingsSearch_FAQ: String { return self._s[3094]! } + public var ShareMenu_Send: String { return self._s[3095]! } + public var WallpaperSearch_ColorYellow: String { return self._s[3097]! } + public var Month_GenNovember: String { return self._s[3099]! } + public var SettingsSearch_Synonyms_Appearance_LargeEmoji: String { return self._s[3101]! } public func Conversation_ShareMyPhoneNumberConfirmation(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3101]!, self._r[3101]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3102]!, self._r[3102]!, [_1, _2]) } - public var Conversation_SwipeToReplyHintText: String { return self._s[3102]! } - public var Checkout_Email: String { return self._s[3103]! } - public var NotificationsSound_Tritone: String { return self._s[3104]! } - public var StickerPacksSettings_ManagingHelp: String { return self._s[3106]! } - public var Wallet_ContextMenuCopy: String { return self._s[3108]! } + public var Conversation_SwipeToReplyHintText: String { return self._s[3103]! } + public var Checkout_Email: String { return self._s[3104]! } + public var NotificationsSound_Tritone: String { return self._s[3105]! } + public var StickerPacksSettings_ManagingHelp: String { return self._s[3107]! } + public var Wallet_ContextMenuCopy: String { return self._s[3109]! } public func Wallet_Time_PreciseDate_m6(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3110]!, self._r[3110]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3111]!, self._r[3111]!, [_1, _2, _3]) } - public var Appearance_TextSize_Automatic: String { return self._s[3111]! } + public var Appearance_TextSize_Automatic: String { return self._s[3112]! } public func PUSH_PINNED_ROUND(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3112]!, self._r[3112]!, [_1]) + return formatWithArgumentRanges(self._s[3113]!, self._r[3113]!, [_1]) } public func StickerPackActionInfo_AddedText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3113]!, self._r[3113]!, [_0]) + return formatWithArgumentRanges(self._s[3114]!, self._r[3114]!, [_0]) } - public var ChangePhoneNumberNumber_Help: String { return self._s[3114]! } + public var ChangePhoneNumberNumber_Help: String { return self._s[3115]! } public func Checkout_LiabilityAlert(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3115]!, self._r[3115]!, [_1, _1, _1, _2]) + return formatWithArgumentRanges(self._s[3116]!, self._r[3116]!, [_1, _1, _1, _2]) } - public var ChatList_UndoArchiveTitle: String { return self._s[3116]! } - public var Notification_Exceptions_Add: String { return self._s[3117]! } - public var DialogList_You: String { return self._s[3118]! } - public var MediaPicker_Send: String { return self._s[3121]! } - public var SettingsSearch_Synonyms_Stickers_Title: String { return self._s[3122]! } - public var Appearance_ThemePreview_ChatList_4_Text: String { return self._s[3123]! } - public var Call_AudioRouteSpeaker: String { return self._s[3124]! } - public var Watch_UserInfo_Title: String { return self._s[3125]! } - public var VoiceOver_Chat_PollFinalResults: String { return self._s[3126]! } - public var Appearance_AccentColor: String { return self._s[3128]! } + public var ChatList_UndoArchiveTitle: String { return self._s[3117]! } + public var Notification_Exceptions_Add: String { return self._s[3118]! } + public var DialogList_You: String { return self._s[3119]! } + public var MediaPicker_Send: String { return self._s[3122]! } + public var SettingsSearch_Synonyms_Stickers_Title: String { return self._s[3123]! } + public var Appearance_ThemePreview_ChatList_4_Text: String { return self._s[3124]! } + public var Call_AudioRouteSpeaker: String { return self._s[3125]! } + public var Watch_UserInfo_Title: String { return self._s[3126]! } + public var VoiceOver_Chat_PollFinalResults: String { return self._s[3127]! } + public var Appearance_AccentColor: String { return self._s[3129]! } public func Login_EmailPhoneSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3129]!, self._r[3129]!, [_0]) + return formatWithArgumentRanges(self._s[3130]!, self._r[3130]!, [_0]) } - public var Permissions_ContactsAllowInSettings_v0: String { return self._s[3130]! } + public var Permissions_ContactsAllowInSettings_v0: String { return self._s[3131]! } public func PUSH_CHANNEL_MESSAGE_GAME(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3131]!, self._r[3131]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3132]!, self._r[3132]!, [_1, _2]) } - public var Conversation_ClousStorageInfo_Description2: String { return self._s[3132]! } - public var WebSearch_RecentClearConfirmation: String { return self._s[3133]! } - public var Notification_CallOutgoing: String { return self._s[3134]! } - public var PrivacySettings_PasscodeAndFaceId: String { return self._s[3135]! } - public var Channel_DiscussionGroup_MakeHistoryPublic: String { return self._s[3136]! } - public var Call_RecordingDisabledMessage: String { return self._s[3137]! } - public var Message_Game: String { return self._s[3138]! } - public var Conversation_PressVolumeButtonForSound: String { return self._s[3139]! } - public var PrivacyLastSeenSettings_CustomHelp: String { return self._s[3140]! } - public var Channel_DiscussionGroup_PrivateGroup: String { return self._s[3141]! } - public var Channel_EditAdmin_PermissionAddAdmins: String { return self._s[3142]! } - public var Date_DialogDateFormat: String { return self._s[3144]! } - public var WallpaperColors_SetCustomColor: String { return self._s[3145]! } - public var Notifications_InAppNotifications: String { return self._s[3146]! } + public var Conversation_ClousStorageInfo_Description2: String { return self._s[3133]! } + public var WebSearch_RecentClearConfirmation: String { return self._s[3134]! } + public var Notification_CallOutgoing: String { return self._s[3135]! } + public var PrivacySettings_PasscodeAndFaceId: String { return self._s[3136]! } + public var Channel_DiscussionGroup_MakeHistoryPublic: String { return self._s[3137]! } + public var Call_RecordingDisabledMessage: String { return self._s[3138]! } + public var Message_Game: String { return self._s[3139]! } + public var Conversation_PressVolumeButtonForSound: String { return self._s[3140]! } + public var PrivacyLastSeenSettings_CustomHelp: String { return self._s[3141]! } + public var Channel_DiscussionGroup_PrivateGroup: String { return self._s[3142]! } + public var Channel_EditAdmin_PermissionAddAdmins: String { return self._s[3143]! } + public var Date_DialogDateFormat: String { return self._s[3145]! } + public var WallpaperColors_SetCustomColor: String { return self._s[3146]! } + public var Notifications_InAppNotifications: String { return self._s[3147]! } public func Channel_Management_RemovedBy(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3147]!, self._r[3147]!, [_0]) + return formatWithArgumentRanges(self._s[3148]!, self._r[3148]!, [_0]) } public func Settings_ApplyProxyAlert(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3148]!, self._r[3148]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3149]!, self._r[3149]!, [_1, _2]) } - public var NewContact_Title: String { return self._s[3149]! } + public var NewContact_Title: String { return self._s[3150]! } public func AutoDownloadSettings_UpToForAll(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3150]!, self._r[3150]!, [_0]) + return formatWithArgumentRanges(self._s[3151]!, self._r[3151]!, [_0]) } - public var Conversation_ViewContactDetails: String { return self._s[3151]! } + public var Conversation_ViewContactDetails: String { return self._s[3152]! } public func PUSH_CHANNEL_MESSAGE_CONTACT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3153]!, self._r[3153]!, [_1]) + return formatWithArgumentRanges(self._s[3154]!, self._r[3154]!, [_1]) } - public var Checkout_NewCard_CardholderNameTitle: String { return self._s[3154]! } - public var Passport_Identity_ExpiryDateNone: String { return self._s[3155]! } - public var PrivacySettings_Title: String { return self._s[3156]! } - public var Conversation_SilentBroadcastTooltipOff: String { return self._s[3159]! } - public var GroupRemoved_UsersSectionTitle: String { return self._s[3160]! } - public var VoiceOver_Chat_ContactEmail: String { return self._s[3161]! } - public var Contacts_PhoneNumber: String { return self._s[3162]! } - public var TwoFactorSetup_Password_PlaceholderConfirmPassword: String { return self._s[3164]! } - public var Map_ShowPlaces: String { return self._s[3165]! } - public var ChatAdmins_Title: String { return self._s[3166]! } - public var InstantPage_Reference: String { return self._s[3168]! } - public var Wallet_Info_Updating: String { return self._s[3169]! } - public var ReportGroupLocation_Text: String { return self._s[3170]! } + public var Checkout_NewCard_CardholderNameTitle: String { return self._s[3155]! } + public var Passport_Identity_ExpiryDateNone: String { return self._s[3156]! } + public var PrivacySettings_Title: String { return self._s[3157]! } + public var Conversation_SilentBroadcastTooltipOff: String { return self._s[3160]! } + public var GroupRemoved_UsersSectionTitle: String { return self._s[3161]! } + public var VoiceOver_Chat_ContactEmail: String { return self._s[3162]! } + public var Contacts_PhoneNumber: String { return self._s[3163]! } + public var TwoFactorSetup_Password_PlaceholderConfirmPassword: String { return self._s[3165]! } + public var Map_ShowPlaces: String { return self._s[3166]! } + public var ChatAdmins_Title: String { return self._s[3167]! } + public var InstantPage_Reference: String { return self._s[3169]! } + public var Wallet_Info_Updating: String { return self._s[3170]! } + public var ReportGroupLocation_Text: String { return self._s[3171]! } public func PUSH_CHAT_MESSAGE_FWD(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3171]!, self._r[3171]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3172]!, self._r[3172]!, [_1, _2]) } - public var Camera_FlashOff: String { return self._s[3172]! } - public var Watch_UserInfo_Block: String { return self._s[3173]! } - public var ChatSettings_Stickers: String { return self._s[3174]! } - public var ChatSettings_DownloadInBackground: String { return self._s[3175]! } - public var Appearance_ThemeCarouselTintedNight: String { return self._s[3176]! } + public var Camera_FlashOff: String { return self._s[3173]! } + public var Watch_UserInfo_Block: String { return self._s[3174]! } + public var ChatSettings_Stickers: String { return self._s[3175]! } + public var ChatSettings_DownloadInBackground: String { return self._s[3176]! } + public var Appearance_ThemeCarouselTintedNight: String { return self._s[3177]! } public func UserInfo_BlockConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3177]!, self._r[3177]!, [_0]) + return formatWithArgumentRanges(self._s[3178]!, self._r[3178]!, [_0]) } - public var Settings_ViewPhoto: String { return self._s[3178]! } - public var Login_CheckOtherSessionMessages: String { return self._s[3179]! } - public var AutoDownloadSettings_Cellular: String { return self._s[3180]! } - public var Wallet_Created_ExportErrorTitle: String { return self._s[3181]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsExceptions: String { return self._s[3182]! } - public var VoiceOver_MessageContextShare: String { return self._s[3183]! } + public var Settings_ViewPhoto: String { return self._s[3179]! } + public var Login_CheckOtherSessionMessages: String { return self._s[3180]! } + public var AutoDownloadSettings_Cellular: String { return self._s[3181]! } + public var Wallet_Created_ExportErrorTitle: String { return self._s[3182]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsExceptions: String { return self._s[3183]! } + public var VoiceOver_MessageContextShare: String { return self._s[3184]! } public func Target_InviteToGroupConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3185]!, self._r[3185]!, [_0]) + return formatWithArgumentRanges(self._s[3186]!, self._r[3186]!, [_0]) } - public var Privacy_DeleteDrafts: String { return self._s[3186]! } - public var Wallpaper_SetCustomBackgroundInfo: String { return self._s[3187]! } + public var Privacy_DeleteDrafts: String { return self._s[3187]! } + public var Wallpaper_SetCustomBackgroundInfo: String { return self._s[3188]! } public func LastSeen_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3188]!, self._r[3188]!, [_0]) + return formatWithArgumentRanges(self._s[3189]!, self._r[3189]!, [_0]) } - public var DialogList_SavedMessagesHelp: String { return self._s[3189]! } - public var Wallet_SecureStorageNotAvailable_Title: String { return self._s[3190]! } - public var DialogList_SavedMessages: String { return self._s[3191]! } - public var GroupInfo_UpgradeButton: String { return self._s[3192]! } - public var Appearance_ThemePreview_ChatList_3_Text: String { return self._s[3194]! } - public var DialogList_Pin: String { return self._s[3195]! } + public var DialogList_SavedMessagesHelp: String { return self._s[3190]! } + public var Wallet_SecureStorageNotAvailable_Title: String { return self._s[3191]! } + public var DialogList_SavedMessages: String { return self._s[3192]! } + public var GroupInfo_UpgradeButton: String { return self._s[3193]! } + public var Appearance_ThemePreview_ChatList_3_Text: String { return self._s[3195]! } + public var DialogList_Pin: String { return self._s[3196]! } public func ForwardedAuthors2(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3196]!, self._r[3196]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3197]!, self._r[3197]!, [_0, _1]) } public func Login_PhoneGenericEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3197]!, self._r[3197]!, [_0]) + return formatWithArgumentRanges(self._s[3198]!, self._r[3198]!, [_0]) } - public var Notification_Exceptions_AlwaysOn: String { return self._s[3198]! } - public var UserInfo_NotificationsDisable: String { return self._s[3199]! } - public var Conversation_ContextMenuCancelEditing: String { return self._s[3200]! } - public var Paint_Outlined: String { return self._s[3201]! } - public var Activity_PlayingGame: String { return self._s[3202]! } - public var SearchImages_NoImagesFound: String { return self._s[3203]! } - public var SocksProxySetup_ProxyType: String { return self._s[3204]! } - public var AppleWatch_ReplyPresetsHelp: String { return self._s[3206]! } - public var Conversation_ContextMenuCancelSending: String { return self._s[3207]! } - public var Settings_AppLanguage: String { return self._s[3208]! } - public var TwoStepAuth_ResetAccountHelp: String { return self._s[3209]! } - public var Common_ChoosePhoto: String { return self._s[3210]! } - public var AuthSessions_AddDevice_InvalidQRCode: String { return self._s[3211]! } - public var CallFeedback_ReasonEcho: String { return self._s[3212]! } + public var Notification_Exceptions_AlwaysOn: String { return self._s[3199]! } + public var UserInfo_NotificationsDisable: String { return self._s[3200]! } + public var Conversation_ContextMenuCancelEditing: String { return self._s[3201]! } + public var Paint_Outlined: String { return self._s[3202]! } + public var Activity_PlayingGame: String { return self._s[3203]! } + public var SearchImages_NoImagesFound: String { return self._s[3204]! } + public var SocksProxySetup_ProxyType: String { return self._s[3205]! } + public var AppleWatch_ReplyPresetsHelp: String { return self._s[3207]! } + public var Conversation_ContextMenuCancelSending: String { return self._s[3208]! } + public var Settings_AppLanguage: String { return self._s[3209]! } + public var TwoStepAuth_ResetAccountHelp: String { return self._s[3210]! } + public var Common_ChoosePhoto: String { return self._s[3211]! } + public var AuthSessions_AddDevice_InvalidQRCode: String { return self._s[3212]! } + public var CallFeedback_ReasonEcho: String { return self._s[3213]! } public func PUSH_PINNED_AUDIO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3213]!, self._r[3213]!, [_1]) + return formatWithArgumentRanges(self._s[3214]!, self._r[3214]!, [_1]) } - public var Privacy_Calls_AlwaysAllow: String { return self._s[3214]! } - public var PollResults_Collapse: String { return self._s[3215]! } - public var Activity_UploadingVideo: String { return self._s[3216]! } - public var Conversation_WalletRequiredNotNow: String { return self._s[3217]! } - public var ChannelInfo_DeleteChannelConfirmation: String { return self._s[3218]! } - public var NetworkUsageSettings_Wifi: String { return self._s[3219]! } - public var VoiceOver_Editing_ClearText: String { return self._s[3220]! } - public var PUSH_SENDER_YOU: String { return self._s[3221]! } - public var Channel_BanUser_PermissionReadMessages: String { return self._s[3222]! } - public var Checkout_PayWithTouchId: String { return self._s[3223]! } - public var Wallpaper_ResetWallpapersConfirmation: String { return self._s[3224]! } + public var Privacy_Calls_AlwaysAllow: String { return self._s[3215]! } + public var PollResults_Collapse: String { return self._s[3216]! } + public var Activity_UploadingVideo: String { return self._s[3217]! } + public var Conversation_WalletRequiredNotNow: String { return self._s[3218]! } + public var ChannelInfo_DeleteChannelConfirmation: String { return self._s[3219]! } + public var NetworkUsageSettings_Wifi: String { return self._s[3220]! } + public var VoiceOver_Editing_ClearText: String { return self._s[3221]! } + public var PUSH_SENDER_YOU: String { return self._s[3222]! } + public var Channel_BanUser_PermissionReadMessages: String { return self._s[3223]! } + public var Checkout_PayWithTouchId: String { return self._s[3224]! } + public var Wallpaper_ResetWallpapersConfirmation: String { return self._s[3225]! } public func PUSH_LOCKED_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3226]!, self._r[3226]!, [_1]) + return formatWithArgumentRanges(self._s[3227]!, self._r[3227]!, [_1]) } - public var Notifications_ExceptionsNone: String { return self._s[3227]! } + public var Notifications_ExceptionsNone: String { return self._s[3228]! } public func Message_ForwardedMessageShort(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3228]!, self._r[3228]!, [_0]) + return formatWithArgumentRanges(self._s[3229]!, self._r[3229]!, [_0]) } public func PUSH_PINNED_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3229]!, self._r[3229]!, [_1]) + return formatWithArgumentRanges(self._s[3230]!, self._r[3230]!, [_1]) } - public var AuthSessions_IncompleteAttempts: String { return self._s[3231]! } - public var Passport_Address_Region: String { return self._s[3234]! } - public var ChatList_DeleteChat: String { return self._s[3235]! } - public var LogoutOptions_ClearCacheTitle: String { return self._s[3236]! } - public var PhotoEditor_TiltShift: String { return self._s[3237]! } - public var Settings_FAQ_URL: String { return self._s[3238]! } - public var TwoFactorSetup_EmailVerification_ChangeAction: String { return self._s[3239]! } - public var Passport_Language_sl: String { return self._s[3240]! } - public var Settings_PrivacySettings: String { return self._s[3242]! } - public var SharedMedia_TitleLink: String { return self._s[3243]! } - public var Passport_Identity_TypePassportUploadScan: String { return self._s[3244]! } - public var Settings_SetProfilePhoto: String { return self._s[3245]! } - public var Channel_About_Help: String { return self._s[3246]! } - public var Contacts_PermissionsEnable: String { return self._s[3247]! } - public var Wallet_Sending_Title: String { return self._s[3248]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsAlert: String { return self._s[3249]! } - public var AttachmentMenu_SendAsFiles: String { return self._s[3250]! } - public var CallFeedback_ReasonInterruption: String { return self._s[3252]! } - public var Passport_Address_AddTemporaryRegistration: String { return self._s[3253]! } - public var AutoDownloadSettings_AutodownloadVideos: String { return self._s[3254]! } - public var ChatSettings_AutoDownloadSettings_Delimeter: String { return self._s[3255]! } - public var OldChannels_Title: String { return self._s[3256]! } - public var PrivacySettings_DeleteAccountTitle: String { return self._s[3257]! } - public var AccessDenied_VideoMessageCamera: String { return self._s[3259]! } - public var Map_OpenInYandexMaps: String { return self._s[3261]! } - public var CreateGroup_ErrorLocatedGroupsTooMuch: String { return self._s[3262]! } - public var VoiceOver_MessageContextReply: String { return self._s[3263]! } - public var PhotoEditor_SaturationTool: String { return self._s[3265]! } + public var AuthSessions_IncompleteAttempts: String { return self._s[3232]! } + public var Passport_Address_Region: String { return self._s[3235]! } + public var ChatList_DeleteChat: String { return self._s[3236]! } + public var LogoutOptions_ClearCacheTitle: String { return self._s[3237]! } + public var PhotoEditor_TiltShift: String { return self._s[3238]! } + public var Settings_FAQ_URL: String { return self._s[3239]! } + public var TwoFactorSetup_EmailVerification_ChangeAction: String { return self._s[3240]! } + public var Passport_Language_sl: String { return self._s[3241]! } + public var Settings_PrivacySettings: String { return self._s[3243]! } + public var SharedMedia_TitleLink: String { return self._s[3244]! } + public var Passport_Identity_TypePassportUploadScan: String { return self._s[3245]! } + public var Settings_SetProfilePhoto: String { return self._s[3246]! } + public var Channel_About_Help: String { return self._s[3247]! } + public var Contacts_PermissionsEnable: String { return self._s[3248]! } + public var Wallet_Sending_Title: String { return self._s[3249]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsAlert: String { return self._s[3250]! } + public var AttachmentMenu_SendAsFiles: String { return self._s[3251]! } + public var CallFeedback_ReasonInterruption: String { return self._s[3253]! } + public var Passport_Address_AddTemporaryRegistration: String { return self._s[3254]! } + public var AutoDownloadSettings_AutodownloadVideos: String { return self._s[3255]! } + public var ChatSettings_AutoDownloadSettings_Delimeter: String { return self._s[3256]! } + public var OldChannels_Title: String { return self._s[3257]! } + public var PrivacySettings_DeleteAccountTitle: String { return self._s[3258]! } + public var AccessDenied_VideoMessageCamera: String { return self._s[3260]! } + public var Map_OpenInYandexMaps: String { return self._s[3262]! } + public var CreateGroup_ErrorLocatedGroupsTooMuch: String { return self._s[3263]! } + public var VoiceOver_MessageContextReply: String { return self._s[3264]! } + public var PhotoEditor_SaturationTool: String { return self._s[3266]! } public func PUSH_MESSAGE_STICKER(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3266]!, self._r[3266]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3267]!, self._r[3267]!, [_1, _2]) } - public var PrivacyPhoneNumberSettings_CustomHelp: String { return self._s[3267]! } - public var Notification_Exceptions_NewException_NotificationHeader: String { return self._s[3268]! } - public var Group_OwnershipTransfer_ErrorLocatedGroupsTooMuch: String { return self._s[3269]! } + public var PrivacyPhoneNumberSettings_CustomHelp: String { return self._s[3268]! } + public var Notification_Exceptions_NewException_NotificationHeader: String { return self._s[3269]! } + public var Group_OwnershipTransfer_ErrorLocatedGroupsTooMuch: String { return self._s[3270]! } public func LOCAL_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3270]!, self._r[3270]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[3271]!, self._r[3271]!, [_1, "\(_2)"]) } - public var Appearance_ThemePreview_ChatList_2_Text: String { return self._s[3271]! } - public var Channel_Username_InvalidTooShort: String { return self._s[3273]! } - public var SettingsSearch_Synonyms_Wallet: String { return self._s[3274]! } + public var Appearance_ThemePreview_ChatList_2_Text: String { return self._s[3272]! } + public var Channel_Username_InvalidTooShort: String { return self._s[3274]! } + public var SettingsSearch_Synonyms_Wallet: String { return self._s[3275]! } public func Group_OwnershipTransfer_DescriptionInfo(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3275]!, self._r[3275]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3276]!, self._r[3276]!, [_1, _2]) } - public var Forward_ErrorPublicPollDisabledInChannels: String { return self._s[3276]! } + public var Forward_ErrorPublicPollDisabledInChannels: String { return self._s[3277]! } public func PUSH_CHAT_MESSAGE_GAME(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3277]!, self._r[3277]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3278]!, self._r[3278]!, [_1, _2, _3]) } - public var WallpaperPreview_PatternTitle: String { return self._s[3278]! } - public var GroupInfo_PublicLinkAdd: String { return self._s[3279]! } - public var Passport_PassportInformation: String { return self._s[3282]! } - public var Theme_Unsupported: String { return self._s[3283]! } - public var WatchRemote_AlertTitle: String { return self._s[3284]! } - public var Privacy_GroupsAndChannels_NeverAllow: String { return self._s[3285]! } - public var ConvertToSupergroup_HelpText: String { return self._s[3287]! } + public var WallpaperPreview_PatternTitle: String { return self._s[3279]! } + public var GroupInfo_PublicLinkAdd: String { return self._s[3280]! } + public var Passport_PassportInformation: String { return self._s[3283]! } + public var Theme_Unsupported: String { return self._s[3284]! } + public var WatchRemote_AlertTitle: String { return self._s[3285]! } + public var Privacy_GroupsAndChannels_NeverAllow: String { return self._s[3286]! } + public var ConvertToSupergroup_HelpText: String { return self._s[3288]! } public func Time_MonthOfYear_m7(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3288]!, self._r[3288]!, [_0]) + return formatWithArgumentRanges(self._s[3289]!, self._r[3289]!, [_0]) } public func PUSH_PHONE_CALL_REQUEST(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3289]!, self._r[3289]!, [_1]) + return formatWithArgumentRanges(self._s[3290]!, self._r[3290]!, [_1]) } - public var Privacy_GroupsAndChannels_CustomHelp: String { return self._s[3290]! } - public var Wallet_Navigation_Done: String { return self._s[3292]! } - public var TwoStepAuth_RecoveryCodeInvalid: String { return self._s[3293]! } - public var AccessDenied_CameraDisabled: String { return self._s[3294]! } + public var Privacy_GroupsAndChannels_CustomHelp: String { return self._s[3291]! } + public var Wallet_Navigation_Done: String { return self._s[3293]! } + public var TwoStepAuth_RecoveryCodeInvalid: String { return self._s[3294]! } + public var AccessDenied_CameraDisabled: String { return self._s[3295]! } public func Channel_Username_UsernameIsAvailable(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3295]!, self._r[3295]!, [_0]) + return formatWithArgumentRanges(self._s[3296]!, self._r[3296]!, [_0]) } - public var ClearCache_Forever: String { return self._s[3296]! } - public var AuthSessions_AddDeviceIntro_Title: String { return self._s[3297]! } - public var CreatePoll_Quiz: String { return self._s[3298]! } - public var PhotoEditor_ContrastTool: String { return self._s[3301]! } + public var ClearCache_Forever: String { return self._s[3297]! } + public var AuthSessions_AddDeviceIntro_Title: String { return self._s[3298]! } + public var CreatePoll_Quiz: String { return self._s[3299]! } + public var PhotoEditor_ContrastTool: String { return self._s[3302]! } public func PUSH_PINNED_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3302]!, self._r[3302]!, [_1]) + return formatWithArgumentRanges(self._s[3303]!, self._r[3303]!, [_1]) } - public var DialogList_Draft: String { return self._s[3303]! } - public var Wallet_Configuration_BlockchainIdInfo: String { return self._s[3304]! } - public var Privacy_TopPeersDelete: String { return self._s[3306]! } - public var LoginPassword_PasswordPlaceholder: String { return self._s[3307]! } - public var Passport_Identity_TypeIdentityCardUploadScan: String { return self._s[3308]! } - public var WebSearch_RecentSectionClear: String { return self._s[3309]! } - public var EditTheme_ErrorInvalidCharacters: String { return self._s[3310]! } - public var Watch_ChatList_NoConversationsTitle: String { return self._s[3312]! } - public var Common_Done: String { return self._s[3314]! } - public var Shortcut_SwitchAccount: String { return self._s[3315]! } - public var AuthSessions_EmptyText: String { return self._s[3316]! } - public var Wallet_Configuration_BlockchainNameChangedTitle: String { return self._s[3317]! } - public var Conversation_ShareBotContactConfirmation: String { return self._s[3318]! } - public var Tour_Title5: String { return self._s[3319]! } - public var Wallet_Settings_Title: String { return self._s[3320]! } + public var DialogList_Draft: String { return self._s[3304]! } + public var Wallet_Configuration_BlockchainIdInfo: String { return self._s[3305]! } + public var Privacy_TopPeersDelete: String { return self._s[3307]! } + public var LoginPassword_PasswordPlaceholder: String { return self._s[3308]! } + public var Passport_Identity_TypeIdentityCardUploadScan: String { return self._s[3309]! } + public var WebSearch_RecentSectionClear: String { return self._s[3310]! } + public var EditTheme_ErrorInvalidCharacters: String { return self._s[3311]! } + public var Watch_ChatList_NoConversationsTitle: String { return self._s[3313]! } + public var Common_Done: String { return self._s[3315]! } + public var Shortcut_SwitchAccount: String { return self._s[3316]! } + public var AuthSessions_EmptyText: String { return self._s[3317]! } + public var Wallet_Configuration_BlockchainNameChangedTitle: String { return self._s[3318]! } + public var Conversation_ShareBotContactConfirmation: String { return self._s[3319]! } + public var Tour_Title5: String { return self._s[3320]! } + public var Wallet_Settings_Title: String { return self._s[3321]! } public func Map_DirectionsDriveEta(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3321]!, self._r[3321]!, [_0]) + return formatWithArgumentRanges(self._s[3322]!, self._r[3322]!, [_0]) } - public var ApplyLanguage_UnsufficientDataTitle: String { return self._s[3322]! } - public var Conversation_LinkDialogSave: String { return self._s[3323]! } - public var GroupInfo_ActionRestrict: String { return self._s[3324]! } - public var Checkout_Title: String { return self._s[3325]! } - public var Channel_DiscussionGroup_HeaderLabel: String { return self._s[3327]! } - public var Channel_AdminLog_CanChangeInfo: String { return self._s[3329]! } - public var Notification_RenamedGroup: String { return self._s[3330]! } - public var PeopleNearby_Groups: String { return self._s[3331]! } - public var Checkout_PayWithFaceId: String { return self._s[3332]! } - public var Channel_BanList_BlockedTitle: String { return self._s[3333]! } - public var SettingsSearch_Synonyms_Notifications_InAppNotificationsSound: String { return self._s[3335]! } - public var Checkout_WebConfirmation_Title: String { return self._s[3336]! } - public var Notifications_MessageNotificationsAlert: String { return self._s[3337]! } + public var ApplyLanguage_UnsufficientDataTitle: String { return self._s[3323]! } + public var Conversation_LinkDialogSave: String { return self._s[3324]! } + public var GroupInfo_ActionRestrict: String { return self._s[3325]! } + public var Checkout_Title: String { return self._s[3326]! } + public var Channel_DiscussionGroup_HeaderLabel: String { return self._s[3328]! } + public var Channel_AdminLog_CanChangeInfo: String { return self._s[3330]! } + public var Notification_RenamedGroup: String { return self._s[3331]! } + public var PeopleNearby_Groups: String { return self._s[3332]! } + public var Checkout_PayWithFaceId: String { return self._s[3333]! } + public var Channel_BanList_BlockedTitle: String { return self._s[3334]! } + public var SettingsSearch_Synonyms_Notifications_InAppNotificationsSound: String { return self._s[3336]! } + public var Checkout_WebConfirmation_Title: String { return self._s[3337]! } + public var Notifications_MessageNotificationsAlert: String { return self._s[3338]! } public func Activity_RemindAboutGroup(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3338]!, self._r[3338]!, [_0]) + return formatWithArgumentRanges(self._s[3339]!, self._r[3339]!, [_0]) } - public var Profile_AddToExisting: String { return self._s[3340]! } + public var Profile_AddToExisting: String { return self._s[3341]! } public func Profile_CreateEncryptedChatOutdatedError(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3341]!, self._r[3341]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3342]!, self._r[3342]!, [_0, _1]) } - public var Cache_Files: String { return self._s[3343]! } - public var Permissions_PrivacyPolicy: String { return self._s[3344]! } - public var SocksProxySetup_ConnectAndSave: String { return self._s[3345]! } - public var UserInfo_NotificationsDefaultDisabled: String { return self._s[3346]! } - public var AutoDownloadSettings_TypeContacts: String { return self._s[3348]! } - public var Appearance_ThemePreview_ChatList_1_Text: String { return self._s[3350]! } - public var Calls_NoCallsPlaceholder: String { return self._s[3351]! } + public var Cache_Files: String { return self._s[3344]! } + public var Permissions_PrivacyPolicy: String { return self._s[3345]! } + public var SocksProxySetup_ConnectAndSave: String { return self._s[3346]! } + public var UserInfo_NotificationsDefaultDisabled: String { return self._s[3347]! } + public var AutoDownloadSettings_TypeContacts: String { return self._s[3349]! } + public var Appearance_ThemePreview_ChatList_1_Text: String { return self._s[3351]! } + public var Calls_NoCallsPlaceholder: String { return self._s[3352]! } public func Wallet_Receive_ShareInvoiceUrlInfo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3352]!, self._r[3352]!, [_0]) + return formatWithArgumentRanges(self._s[3353]!, self._r[3353]!, [_0]) } - public var Channel_Username_RevokeExistingUsernamesInfo: String { return self._s[3353]! } - public var VoiceOver_AttachMedia: String { return self._s[3356]! } - public var Notifications_ExceptionsGroupPlaceholder: String { return self._s[3357]! } + public var Channel_Username_RevokeExistingUsernamesInfo: String { return self._s[3354]! } + public var VoiceOver_AttachMedia: String { return self._s[3357]! } + public var Notifications_ExceptionsGroupPlaceholder: String { return self._s[3358]! } public func PUSH_CHAT_MESSAGE_INVOICE(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3358]!, self._r[3358]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3359]!, self._r[3359]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsSound: String { return self._s[3359]! } - public var Conversation_SetReminder_Title: String { return self._s[3360]! } - public var Passport_FieldAddressHelp: String { return self._s[3361]! } - public var Privacy_GroupsAndChannels_InviteToChannelMultipleError: String { return self._s[3362]! } - public var PUSH_REMINDER_TITLE: String { return self._s[3363]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsSound: String { return self._s[3360]! } + public var Conversation_SetReminder_Title: String { return self._s[3361]! } + public var Passport_FieldAddressHelp: String { return self._s[3362]! } + public var Privacy_GroupsAndChannels_InviteToChannelMultipleError: String { return self._s[3363]! } + public var PUSH_REMINDER_TITLE: String { return self._s[3364]! } public func Login_TermsOfService_ProceedBot(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3364]!, self._r[3364]!, [_0]) + return formatWithArgumentRanges(self._s[3365]!, self._r[3365]!, [_0]) } - public var Channel_AdminLog_EmptyTitle: String { return self._s[3365]! } - public var Privacy_Calls_NeverAllow_Title: String { return self._s[3366]! } - public var Login_UnknownError: String { return self._s[3367]! } - public var Group_UpgradeNoticeText2: String { return self._s[3370]! } - public var Watch_Compose_AddContact: String { return self._s[3371]! } - public var ClearCache_StorageServiceFiles: String { return self._s[3372]! } - public var Web_Error: String { return self._s[3373]! } - public var Gif_Search: String { return self._s[3374]! } - public var Profile_MessageLifetime1h: String { return self._s[3375]! } - public var CheckoutInfo_ReceiverInfoEmailPlaceholder: String { return self._s[3376]! } - public var Channel_Username_CheckingUsername: String { return self._s[3377]! } - public var CallFeedback_ReasonSilentRemote: String { return self._s[3378]! } - public var AutoDownloadSettings_TypeChannels: String { return self._s[3379]! } - public var Channel_AboutItem: String { return self._s[3380]! } - public var Privacy_GroupsAndChannels_AlwaysAllow_Placeholder: String { return self._s[3382]! } - public var VoiceOver_Chat_VoiceMessage: String { return self._s[3383]! } - public var GroupInfo_SharedMedia: String { return self._s[3384]! } + public var Channel_AdminLog_EmptyTitle: String { return self._s[3366]! } + public var Privacy_Calls_NeverAllow_Title: String { return self._s[3367]! } + public var Login_UnknownError: String { return self._s[3368]! } + public var Group_UpgradeNoticeText2: String { return self._s[3371]! } + public var Watch_Compose_AddContact: String { return self._s[3372]! } + public var ClearCache_StorageServiceFiles: String { return self._s[3373]! } + public var Web_Error: String { return self._s[3374]! } + public var Gif_Search: String { return self._s[3375]! } + public var Profile_MessageLifetime1h: String { return self._s[3376]! } + public var CheckoutInfo_ReceiverInfoEmailPlaceholder: String { return self._s[3377]! } + public var Channel_Username_CheckingUsername: String { return self._s[3378]! } + public var CallFeedback_ReasonSilentRemote: String { return self._s[3379]! } + public var AutoDownloadSettings_TypeChannels: String { return self._s[3380]! } + public var Channel_AboutItem: String { return self._s[3381]! } + public var Privacy_GroupsAndChannels_AlwaysAllow_Placeholder: String { return self._s[3383]! } + public var VoiceOver_Chat_VoiceMessage: String { return self._s[3384]! } + public var GroupInfo_SharedMedia: String { return self._s[3385]! } public func Channel_AdminLog_MessagePromotedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3385]!, self._r[3385]!, [_1]) + return formatWithArgumentRanges(self._s[3386]!, self._r[3386]!, [_1]) } - public var Call_PhoneCallInProgressMessage: String { return self._s[3386]! } + public var Call_PhoneCallInProgressMessage: String { return self._s[3387]! } public func PUSH_CHANNEL_ALBUM(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3387]!, self._r[3387]!, [_1]) + return formatWithArgumentRanges(self._s[3388]!, self._r[3388]!, [_1]) } - public var ChatList_UndoArchiveRevealedText: String { return self._s[3388]! } - public var GroupInfo_InviteLink_RevokeAlert_Text: String { return self._s[3389]! } - public var Conversation_SearchByName_Placeholder: String { return self._s[3390]! } - public var CreatePoll_AddOption: String { return self._s[3391]! } - public var GroupInfo_Permissions_SearchPlaceholder: String { return self._s[3392]! } - public var Group_UpgradeNoticeHeader: String { return self._s[3393]! } - public var Channel_Management_AddModerator: String { return self._s[3394]! } - public var AutoDownloadSettings_MaxFileSize: String { return self._s[3395]! } - public var StickerPacksSettings_ShowStickersButton: String { return self._s[3396]! } - public var Wallet_Info_RefreshErrorNetworkText: String { return self._s[3397]! } - public var Theme_Colors_Background: String { return self._s[3398]! } - public var NotificationsSound_Hello: String { return self._s[3400]! } - public var SocksProxySetup_SavedProxies: String { return self._s[3401]! } - public var Channel_Stickers_Placeholder: String { return self._s[3403]! } + public var ChatList_UndoArchiveRevealedText: String { return self._s[3389]! } + public var GroupInfo_InviteLink_RevokeAlert_Text: String { return self._s[3390]! } + public var Conversation_SearchByName_Placeholder: String { return self._s[3391]! } + public var CreatePoll_AddOption: String { return self._s[3392]! } + public var GroupInfo_Permissions_SearchPlaceholder: String { return self._s[3393]! } + public var Group_UpgradeNoticeHeader: String { return self._s[3394]! } + public var Channel_Management_AddModerator: String { return self._s[3395]! } + public var AutoDownloadSettings_MaxFileSize: String { return self._s[3396]! } + public var StickerPacksSettings_ShowStickersButton: String { return self._s[3397]! } + public var Wallet_Info_RefreshErrorNetworkText: String { return self._s[3398]! } + public var Theme_Colors_Background: String { return self._s[3399]! } + public var NotificationsSound_Hello: String { return self._s[3401]! } + public var SocksProxySetup_SavedProxies: String { return self._s[3402]! } + public var Channel_Stickers_Placeholder: String { return self._s[3404]! } public func Login_EmailCodeBody(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3404]!, self._r[3404]!, [_0]) + return formatWithArgumentRanges(self._s[3405]!, self._r[3405]!, [_0]) } - public var PrivacyPolicy_DeclineDeclineAndDelete: String { return self._s[3405]! } - public var Channel_Management_AddModeratorHelp: String { return self._s[3406]! } - public var ContactInfo_BirthdayLabel: String { return self._s[3407]! } - public var ChangePhoneNumberCode_RequestingACall: String { return self._s[3408]! } - public var AutoDownloadSettings_Channels: String { return self._s[3409]! } - public var Passport_Language_mn: String { return self._s[3410]! } - public var Notifications_ResetAllNotificationsHelp: String { return self._s[3413]! } - public var GroupInfo_Permissions_SlowmodeValue_Off: String { return self._s[3414]! } - public var Passport_Language_ja: String { return self._s[3416]! } - public var Settings_About_Title: String { return self._s[3417]! } - public var Settings_NotificationsAndSounds: String { return self._s[3418]! } - public var ChannelInfo_DeleteGroup: String { return self._s[3419]! } - public var Settings_BlockedUsers: String { return self._s[3420]! } + public var PrivacyPolicy_DeclineDeclineAndDelete: String { return self._s[3406]! } + public var Channel_Management_AddModeratorHelp: String { return self._s[3407]! } + public var ContactInfo_BirthdayLabel: String { return self._s[3408]! } + public var ChangePhoneNumberCode_RequestingACall: String { return self._s[3409]! } + public var AutoDownloadSettings_Channels: String { return self._s[3410]! } + public var Passport_Language_mn: String { return self._s[3411]! } + public var Notifications_ResetAllNotificationsHelp: String { return self._s[3414]! } + public var GroupInfo_Permissions_SlowmodeValue_Off: String { return self._s[3415]! } + public var Passport_Language_ja: String { return self._s[3417]! } + public var Settings_About_Title: String { return self._s[3418]! } + public var Settings_NotificationsAndSounds: String { return self._s[3419]! } + public var ChannelInfo_DeleteGroup: String { return self._s[3420]! } + public var Settings_BlockedUsers: String { return self._s[3421]! } public func Time_MonthOfYear_m4(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3421]!, self._r[3421]!, [_0]) + return formatWithArgumentRanges(self._s[3422]!, self._r[3422]!, [_0]) } - public var EditTheme_Create_Preview_OutgoingText: String { return self._s[3422]! } - public var Wallet_Weekday_Today: String { return self._s[3423]! } - public var AutoDownloadSettings_PreloadVideo: String { return self._s[3424]! } - public var Widget_ApplicationLocked: String { return self._s[3425]! } - public var Passport_Address_AddResidentialAddress: String { return self._s[3426]! } - public var Channel_Username_Title: String { return self._s[3427]! } + public var EditTheme_Create_Preview_OutgoingText: String { return self._s[3423]! } + public var Wallet_Weekday_Today: String { return self._s[3424]! } + public var AutoDownloadSettings_PreloadVideo: String { return self._s[3425]! } + public var Widget_ApplicationLocked: String { return self._s[3426]! } + public var Passport_Address_AddResidentialAddress: String { return self._s[3427]! } + public var Channel_Username_Title: String { return self._s[3428]! } public func Notification_RemovedGroupPhoto(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3428]!, self._r[3428]!, [_0]) + return formatWithArgumentRanges(self._s[3429]!, self._r[3429]!, [_0]) } - public var AttachmentMenu_File: String { return self._s[3430]! } - public var AppleWatch_Title: String { return self._s[3431]! } - public var Activity_RecordingVideoMessage: String { return self._s[3432]! } + public var AttachmentMenu_File: String { return self._s[3431]! } + public var AppleWatch_Title: String { return self._s[3432]! } + public var Activity_RecordingVideoMessage: String { return self._s[3433]! } public func Channel_DiscussionGroup_PublicChannelLink(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3433]!, self._r[3433]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3434]!, self._r[3434]!, [_1, _2]) } - public var Theme_Colors_Messages: String { return self._s[3434]! } - public var Weekday_Saturday: String { return self._s[3435]! } - public var WallpaperPreview_SwipeColorsTopText: String { return self._s[3436]! } - public var Profile_CreateEncryptedChatError: String { return self._s[3437]! } - public var Common_Next: String { return self._s[3439]! } - public var Channel_Stickers_YourStickers: String { return self._s[3441]! } - public var Message_Theme: String { return self._s[3442]! } - public var Call_AudioRouteHeadphones: String { return self._s[3443]! } - public var TwoStepAuth_EnterPasswordForgot: String { return self._s[3445]! } - public var Watch_Contacts_NoResults: String { return self._s[3447]! } - public var PhotoEditor_TintTool: String { return self._s[3450]! } - public var LoginPassword_ResetAccount: String { return self._s[3452]! } - public var Settings_SavedMessages: String { return self._s[3453]! } - public var SettingsSearch_Synonyms_Appearance_Animations: String { return self._s[3454]! } - public var Bot_GenericSupportStatus: String { return self._s[3455]! } - public var StickerPack_Add: String { return self._s[3456]! } - public var Checkout_TotalAmount: String { return self._s[3457]! } - public var Your_cards_number_is_invalid: String { return self._s[3458]! } - public var SettingsSearch_Synonyms_Appearance_AutoNightTheme: String { return self._s[3459]! } - public var VoiceOver_Chat_VideoMessage: String { return self._s[3460]! } + public var Theme_Colors_Messages: String { return self._s[3435]! } + public var Weekday_Saturday: String { return self._s[3436]! } + public var WallpaperPreview_SwipeColorsTopText: String { return self._s[3437]! } + public var Profile_CreateEncryptedChatError: String { return self._s[3438]! } + public var Common_Next: String { return self._s[3440]! } + public var Channel_Stickers_YourStickers: String { return self._s[3442]! } + public var Message_Theme: String { return self._s[3443]! } + public var Call_AudioRouteHeadphones: String { return self._s[3444]! } + public var TwoStepAuth_EnterPasswordForgot: String { return self._s[3446]! } + public var Watch_Contacts_NoResults: String { return self._s[3448]! } + public var PhotoEditor_TintTool: String { return self._s[3451]! } + public var LoginPassword_ResetAccount: String { return self._s[3453]! } + public var Settings_SavedMessages: String { return self._s[3454]! } + public var SettingsSearch_Synonyms_Appearance_Animations: String { return self._s[3455]! } + public var Bot_GenericSupportStatus: String { return self._s[3456]! } + public var StickerPack_Add: String { return self._s[3457]! } + public var Checkout_TotalAmount: String { return self._s[3458]! } + public var Your_cards_number_is_invalid: String { return self._s[3459]! } + public var SettingsSearch_Synonyms_Appearance_AutoNightTheme: String { return self._s[3460]! } + public var VoiceOver_Chat_VideoMessage: String { return self._s[3461]! } public func ChangePhoneNumberCode_CallTimer(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3461]!, self._r[3461]!, [_0]) + return formatWithArgumentRanges(self._s[3462]!, self._r[3462]!, [_0]) } public func GroupPermission_AddedInfo(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3462]!, self._r[3462]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3463]!, self._r[3463]!, [_1, _2]) } - public var ChatSettings_ConnectionType_UseSocks5: String { return self._s[3463]! } + public var ChatSettings_ConnectionType_UseSocks5: String { return self._s[3464]! } public func PUSH_CHAT_PHOTO_EDITED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3465]!, self._r[3465]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3466]!, self._r[3466]!, [_1, _2]) } public func Conversation_RestrictedTextTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3466]!, self._r[3466]!, [_0]) + return formatWithArgumentRanges(self._s[3467]!, self._r[3467]!, [_0]) } - public var GroupInfo_InviteLink_ShareLink: String { return self._s[3467]! } - public var StickerPack_Share: String { return self._s[3468]! } - public var Passport_DeleteAddress: String { return self._s[3469]! } - public var Settings_Passport: String { return self._s[3470]! } - public var SharedMedia_EmptyFilesText: String { return self._s[3471]! } - public var Conversation_DeleteMessagesForMe: String { return self._s[3472]! } - public var PasscodeSettings_AutoLock_IfAwayFor_1hour: String { return self._s[3473]! } - public var Contacts_PermissionsText: String { return self._s[3474]! } - public var Group_Setup_HistoryVisible: String { return self._s[3475]! } - public var Wallet_Month_ShortDecember: String { return self._s[3477]! } - public var Channel_EditAdmin_PermissionEnabledByDefault: String { return self._s[3478]! } - public var Passport_Address_AddRentalAgreement: String { return self._s[3479]! } - public var SocksProxySetup_Title: String { return self._s[3480]! } - public var Notification_Mute1h: String { return self._s[3481]! } + public var GroupInfo_InviteLink_ShareLink: String { return self._s[3468]! } + public var StickerPack_Share: String { return self._s[3469]! } + public var Passport_DeleteAddress: String { return self._s[3470]! } + public var Settings_Passport: String { return self._s[3471]! } + public var SharedMedia_EmptyFilesText: String { return self._s[3472]! } + public var Conversation_DeleteMessagesForMe: String { return self._s[3473]! } + public var PasscodeSettings_AutoLock_IfAwayFor_1hour: String { return self._s[3474]! } + public var Contacts_PermissionsText: String { return self._s[3475]! } + public var Group_Setup_HistoryVisible: String { return self._s[3476]! } + public var Wallet_Month_ShortDecember: String { return self._s[3478]! } + public var Channel_EditAdmin_PermissionEnabledByDefault: String { return self._s[3479]! } + public var Passport_Address_AddRentalAgreement: String { return self._s[3480]! } + public var SocksProxySetup_Title: String { return self._s[3481]! } + public var Notification_Mute1h: String { return self._s[3482]! } public func Passport_Email_CodeHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3482]!, self._r[3482]!, [_0]) + return formatWithArgumentRanges(self._s[3483]!, self._r[3483]!, [_0]) } - public var NotificationSettings_ShowNotificationsAllAccountsInfoOff: String { return self._s[3483]! } + public var NotificationSettings_ShowNotificationsAllAccountsInfoOff: String { return self._s[3484]! } public func PUSH_PINNED_GEOLIVE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3484]!, self._r[3484]!, [_1]) + return formatWithArgumentRanges(self._s[3485]!, self._r[3485]!, [_1]) } - public var FastTwoStepSetup_PasswordSection: String { return self._s[3485]! } - public var NetworkUsageSettings_ResetStatsConfirmation: String { return self._s[3488]! } - public var InfoPlist_NSFaceIDUsageDescription: String { return self._s[3490]! } - public var DialogList_NoMessagesText: String { return self._s[3491]! } - public var Privacy_ContactsResetConfirmation: String { return self._s[3492]! } - public var Privacy_Calls_P2PHelp: String { return self._s[3493]! } - public var Channel_DiscussionGroup_SearchPlaceholder: String { return self._s[3495]! } - public var Your_cards_expiration_year_is_invalid: String { return self._s[3496]! } - public var Common_TakePhotoOrVideo: String { return self._s[3497]! } - public var Wallet_Words_Text: String { return self._s[3498]! } - public var Call_StatusBusy: String { return self._s[3499]! } - public var Conversation_PinnedMessage: String { return self._s[3500]! } - public var AutoDownloadSettings_VoiceMessagesTitle: String { return self._s[3501]! } - public var Wallet_Configuration_BlockchainNameChangedProceed: String { return self._s[3502]! } - public var TwoStepAuth_SetupPasswordConfirmFailed: String { return self._s[3503]! } - public var Undo_ChatCleared: String { return self._s[3504]! } - public var AppleWatch_ReplyPresets: String { return self._s[3505]! } - public var Passport_DiscardMessageDescription: String { return self._s[3507]! } - public var Login_NetworkError: String { return self._s[3508]! } + public var FastTwoStepSetup_PasswordSection: String { return self._s[3486]! } + public var NetworkUsageSettings_ResetStatsConfirmation: String { return self._s[3489]! } + public var InfoPlist_NSFaceIDUsageDescription: String { return self._s[3491]! } + public var DialogList_NoMessagesText: String { return self._s[3492]! } + public var Privacy_ContactsResetConfirmation: String { return self._s[3493]! } + public var Privacy_Calls_P2PHelp: String { return self._s[3494]! } + public var Channel_DiscussionGroup_SearchPlaceholder: String { return self._s[3496]! } + public var Your_cards_expiration_year_is_invalid: String { return self._s[3497]! } + public var Common_TakePhotoOrVideo: String { return self._s[3498]! } + public var Wallet_Words_Text: String { return self._s[3499]! } + public var Call_StatusBusy: String { return self._s[3500]! } + public var Conversation_PinnedMessage: String { return self._s[3501]! } + public var AutoDownloadSettings_VoiceMessagesTitle: String { return self._s[3502]! } + public var Wallet_Configuration_BlockchainNameChangedProceed: String { return self._s[3503]! } + public var TwoStepAuth_SetupPasswordConfirmFailed: String { return self._s[3504]! } + public var Undo_ChatCleared: String { return self._s[3505]! } + public var AppleWatch_ReplyPresets: String { return self._s[3506]! } + public var Passport_DiscardMessageDescription: String { return self._s[3508]! } + public var Login_NetworkError: String { return self._s[3509]! } public func Notification_PinnedRoundMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3509]!, self._r[3509]!, [_0]) - } - public func Channel_AdminLog_MessageRemovedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3510]!, self._r[3510]!, [_0]) } - public var SocksProxySetup_PasswordPlaceholder: String { return self._s[3511]! } - public var Wallet_WordCheck_ViewWords: String { return self._s[3513]! } - public var Login_ResetAccountProtected_LimitExceeded: String { return self._s[3514]! } + public func Channel_AdminLog_MessageRemovedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3511]!, self._r[3511]!, [_0]) + } + public var SocksProxySetup_PasswordPlaceholder: String { return self._s[3512]! } + public var Wallet_WordCheck_ViewWords: String { return self._s[3514]! } + public var Login_ResetAccountProtected_LimitExceeded: String { return self._s[3515]! } public func Watch_LastSeen_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3516]!, self._r[3516]!, [_0]) + return formatWithArgumentRanges(self._s[3517]!, self._r[3517]!, [_0]) } - public var Call_ConnectionErrorMessage: String { return self._s[3517]! } - public var VoiceOver_Chat_Music: String { return self._s[3518]! } - public var SettingsSearch_Synonyms_Notifications_MessageNotificationsSound: String { return self._s[3519]! } - public var Compose_GroupTokenListPlaceholder: String { return self._s[3521]! } - public var ConversationMedia_Title: String { return self._s[3522]! } - public var EncryptionKey_Title: String { return self._s[3524]! } - public var TwoStepAuth_EnterPasswordTitle: String { return self._s[3525]! } - public var Notification_Exceptions_AddException: String { return self._s[3526]! } - public var PrivacySettings_BlockedPeersEmpty: String { return self._s[3527]! } - public var Profile_MessageLifetime1m: String { return self._s[3528]! } + public var Call_ConnectionErrorMessage: String { return self._s[3518]! } + public var VoiceOver_Chat_Music: String { return self._s[3519]! } + public var SettingsSearch_Synonyms_Notifications_MessageNotificationsSound: String { return self._s[3520]! } + public var Compose_GroupTokenListPlaceholder: String { return self._s[3522]! } + public var ConversationMedia_Title: String { return self._s[3523]! } + public var EncryptionKey_Title: String { return self._s[3525]! } + public var TwoStepAuth_EnterPasswordTitle: String { return self._s[3526]! } + public var Notification_Exceptions_AddException: String { return self._s[3527]! } + public var PrivacySettings_BlockedPeersEmpty: String { return self._s[3528]! } + public var Profile_MessageLifetime1m: String { return self._s[3529]! } public func Channel_AdminLog_MessageUnkickedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3529]!, self._r[3529]!, [_1]) + return formatWithArgumentRanges(self._s[3530]!, self._r[3530]!, [_1]) } - public var Month_GenMay: String { return self._s[3530]! } + public var Month_GenMay: String { return self._s[3531]! } public func LiveLocationUpdated_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3531]!, self._r[3531]!, [_0]) + return formatWithArgumentRanges(self._s[3532]!, self._r[3532]!, [_0]) } - public var PeopleNearby_Users: String { return self._s[3532]! } - public var Wallet_Send_AddressInfo: String { return self._s[3533]! } - public var ChannelMembers_WhoCanAddMembersAllHelp: String { return self._s[3534]! } - public var AutoDownloadSettings_ResetSettings: String { return self._s[3535]! } + public var PeopleNearby_Users: String { return self._s[3533]! } + public var Wallet_Send_AddressInfo: String { return self._s[3534]! } + public var ChannelMembers_WhoCanAddMembersAllHelp: String { return self._s[3535]! } + public var AutoDownloadSettings_ResetSettings: String { return self._s[3536]! } public func Wallet_Updated_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3537]!, self._r[3537]!, [_0]) + return formatWithArgumentRanges(self._s[3538]!, self._r[3538]!, [_0]) } - public var Conversation_EmptyPlaceholder: String { return self._s[3538]! } - public var Passport_Address_AddPassportRegistration: String { return self._s[3539]! } - public var Notifications_ChannelNotificationsAlert: String { return self._s[3540]! } - public var ChatSettings_AutoDownloadUsingCellular: String { return self._s[3541]! } - public var Camera_TapAndHoldForVideo: String { return self._s[3542]! } - public var Channel_JoinChannel: String { return self._s[3544]! } - public var Appearance_Animations: String { return self._s[3547]! } + public var Conversation_EmptyPlaceholder: String { return self._s[3539]! } + public var Passport_Address_AddPassportRegistration: String { return self._s[3540]! } + public var Notifications_ChannelNotificationsAlert: String { return self._s[3541]! } + public var ChatSettings_AutoDownloadUsingCellular: String { return self._s[3542]! } + public var Camera_TapAndHoldForVideo: String { return self._s[3543]! } + public var Channel_JoinChannel: String { return self._s[3545]! } + public var Appearance_Animations: String { return self._s[3548]! } public func Notification_MessageLifetimeChanged(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3548]!, self._r[3548]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3549]!, self._r[3549]!, [_1, _2]) } - public var Stickers_GroupStickers: String { return self._s[3550]! } - public var Appearance_ShareTheme: String { return self._s[3551]! } - public var TwoFactorSetup_Hint_Placeholder: String { return self._s[3552]! } - public var ConvertToSupergroup_HelpTitle: String { return self._s[3554]! } - public var StickerPackActionInfo_RemovedTitle: String { return self._s[3555]! } - public var Passport_Address_Street: String { return self._s[3556]! } - public var Conversation_AddContact: String { return self._s[3557]! } - public var Login_PhonePlaceholder: String { return self._s[3558]! } - public var Channel_Members_InviteLink: String { return self._s[3560]! } - public var Bot_Stop: String { return self._s[3561]! } - public var SettingsSearch_Synonyms_Proxy_UseForCalls: String { return self._s[3563]! } - public var Notification_PassportValueAddress: String { return self._s[3564]! } - public var Month_ShortJuly: String { return self._s[3565]! } - public var Passport_Address_TypeTemporaryRegistrationUploadScan: String { return self._s[3566]! } - public var Channel_AdminLog_BanSendMedia: String { return self._s[3567]! } - public var Passport_Identity_ReverseSide: String { return self._s[3568]! } - public var Watch_Stickers_Recents: String { return self._s[3571]! } - public var PrivacyLastSeenSettings_EmpryUsersPlaceholder: String { return self._s[3573]! } - public var Map_SendThisLocation: String { return self._s[3574]! } + public var Stickers_GroupStickers: String { return self._s[3551]! } + public var Appearance_ShareTheme: String { return self._s[3552]! } + public var TwoFactorSetup_Hint_Placeholder: String { return self._s[3553]! } + public var ConvertToSupergroup_HelpTitle: String { return self._s[3555]! } + public var StickerPackActionInfo_RemovedTitle: String { return self._s[3556]! } + public var Passport_Address_Street: String { return self._s[3557]! } + public var Conversation_AddContact: String { return self._s[3558]! } + public var Login_PhonePlaceholder: String { return self._s[3559]! } + public var Channel_Members_InviteLink: String { return self._s[3561]! } + public var Bot_Stop: String { return self._s[3562]! } + public var SettingsSearch_Synonyms_Proxy_UseForCalls: String { return self._s[3564]! } + public var Notification_PassportValueAddress: String { return self._s[3565]! } + public var Month_ShortJuly: String { return self._s[3566]! } + public var Passport_Address_TypeTemporaryRegistrationUploadScan: String { return self._s[3567]! } + public var Channel_AdminLog_BanSendMedia: String { return self._s[3568]! } + public var Passport_Identity_ReverseSide: String { return self._s[3569]! } + public var Watch_Stickers_Recents: String { return self._s[3572]! } + public var PrivacyLastSeenSettings_EmpryUsersPlaceholder: String { return self._s[3574]! } + public var Map_SendThisLocation: String { return self._s[3575]! } public func Time_MonthOfYear_m1(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3575]!, self._r[3575]!, [_0]) - } - public func InviteText_SingleContact(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3576]!, self._r[3576]!, [_0]) } - public var ConvertToSupergroup_Note: String { return self._s[3577]! } - public var Wallet_Intro_NotNow: String { return self._s[3578]! } + public func InviteText_SingleContact(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3577]!, self._r[3577]!, [_0]) + } + public var ConvertToSupergroup_Note: String { return self._s[3578]! } + public var Wallet_Intro_NotNow: String { return self._s[3579]! } public func FileSize_MB(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3579]!, self._r[3579]!, [_0]) + return formatWithArgumentRanges(self._s[3580]!, self._r[3580]!, [_0]) } - public var NetworkUsageSettings_GeneralDataSection: String { return self._s[3580]! } + public var NetworkUsageSettings_GeneralDataSection: String { return self._s[3581]! } public func Compatibility_SecretMediaVersionTooLow(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3581]!, self._r[3581]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3582]!, self._r[3582]!, [_0, _1]) } - public var Login_CallRequestState3: String { return self._s[3583]! } - public var Wallpaper_SearchShort: String { return self._s[3584]! } - public var SettingsSearch_Synonyms_Appearance_ColorTheme: String { return self._s[3586]! } - public var PasscodeSettings_UnlockWithFaceId: String { return self._s[3587]! } - public var Channel_BotDoesntSupportGroups: String { return self._s[3588]! } + public var Login_CallRequestState3: String { return self._s[3584]! } + public var Wallpaper_SearchShort: String { return self._s[3585]! } + public var SettingsSearch_Synonyms_Appearance_ColorTheme: String { return self._s[3587]! } + public var PasscodeSettings_UnlockWithFaceId: String { return self._s[3588]! } + public var Channel_BotDoesntSupportGroups: String { return self._s[3589]! } public func PUSH_CHAT_MESSAGE_GEOLIVE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3589]!, self._r[3589]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3590]!, self._r[3590]!, [_1, _2]) } - public var Channel_AdminLogFilter_Title: String { return self._s[3590]! } - public var Appearance_ThemePreview_Chat_4_Text: String { return self._s[3592]! } - public var Notifications_GroupNotificationsExceptions: String { return self._s[3595]! } + public var Channel_AdminLogFilter_Title: String { return self._s[3591]! } + public var Appearance_ThemePreview_Chat_4_Text: String { return self._s[3593]! } + public var Notifications_GroupNotificationsExceptions: String { return self._s[3596]! } public func FileSize_B(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3596]!, self._r[3596]!, [_0]) + return formatWithArgumentRanges(self._s[3597]!, self._r[3597]!, [_0]) } - public var Passport_CorrectErrors: String { return self._s[3597]! } - public var VoiceOver_Chat_YourAnonymousPoll: String { return self._s[3598]! } + public var Passport_CorrectErrors: String { return self._s[3598]! } + public var VoiceOver_Chat_YourAnonymousPoll: String { return self._s[3599]! } public func Channel_MessageTitleUpdated(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3599]!, self._r[3599]!, [_0]) + return formatWithArgumentRanges(self._s[3600]!, self._r[3600]!, [_0]) } - public var Map_SendMyCurrentLocation: String { return self._s[3600]! } - public var Channel_DiscussionGroup: String { return self._s[3601]! } - public var TwoFactorSetup_Email_SkipConfirmationSkip: String { return self._s[3602]! } + public var Map_SendMyCurrentLocation: String { return self._s[3601]! } + public var Channel_DiscussionGroup: String { return self._s[3602]! } + public var TwoFactorSetup_Email_SkipConfirmationSkip: String { return self._s[3603]! } public func PUSH_PINNED_CONTACT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3603]!, self._r[3603]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3604]!, self._r[3604]!, [_1, _2]) } - public var SharedMedia_SearchNoResults: String { return self._s[3604]! } - public var Permissions_NotificationsText_v0: String { return self._s[3605]! } - public var Channel_EditAdmin_PermissionDeleteMessagesOfOthers: String { return self._s[3606]! } - public var Appearance_AppIcon: String { return self._s[3607]! } - public var Appearance_ThemePreview_ChatList_3_AuthorName: String { return self._s[3608]! } - public var LoginPassword_FloodError: String { return self._s[3609]! } - public var Wallet_Send_OwnAddressAlertProceed: String { return self._s[3611]! } - public var Group_Setup_HistoryHiddenHelp: String { return self._s[3612]! } + public var SharedMedia_SearchNoResults: String { return self._s[3605]! } + public var Permissions_NotificationsText_v0: String { return self._s[3606]! } + public var Channel_EditAdmin_PermissionDeleteMessagesOfOthers: String { return self._s[3607]! } + public var Appearance_AppIcon: String { return self._s[3608]! } + public var Appearance_ThemePreview_ChatList_3_AuthorName: String { return self._s[3609]! } + public var LoginPassword_FloodError: String { return self._s[3610]! } + public var Wallet_Send_OwnAddressAlertProceed: String { return self._s[3612]! } + public var Group_Setup_HistoryHiddenHelp: String { return self._s[3613]! } public func TwoStepAuth_PendingEmailHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3613]!, self._r[3613]!, [_0]) + return formatWithArgumentRanges(self._s[3614]!, self._r[3614]!, [_0]) } - public var Passport_Language_bn: String { return self._s[3614]! } + public var Passport_Language_bn: String { return self._s[3615]! } public func DialogList_SingleUploadingPhotoSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3615]!, self._r[3615]!, [_0]) + return formatWithArgumentRanges(self._s[3616]!, self._r[3616]!, [_0]) } - public var ChatList_Context_Pin: String { return self._s[3616]! } + public var ChatList_Context_Pin: String { return self._s[3617]! } public func Notification_PinnedAudioMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3617]!, self._r[3617]!, [_0]) - } - public func Channel_AdminLog_MessageChangedGroupStickerPack(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3618]!, self._r[3618]!, [_0]) } - public var Wallet_Navigation_Close: String { return self._s[3619]! } - public var GroupInfo_InvitationLinkGroupFull: String { return self._s[3623]! } - public var Group_EditAdmin_PermissionChangeInfo: String { return self._s[3625]! } - public var Wallet_Month_GenDecember: String { return self._s[3626]! } - public var Contacts_PermissionsAllow: String { return self._s[3627]! } - public var ReportPeer_ReasonCopyright: String { return self._s[3628]! } - public var Channel_EditAdmin_PermissinAddAdminOn: String { return self._s[3629]! } - public var WallpaperPreview_Pattern: String { return self._s[3630]! } - public var Paint_Duplicate: String { return self._s[3631]! } - public var Passport_Address_Country: String { return self._s[3632]! } - public var Notification_RenamedChannel: String { return self._s[3634]! } - public var ChatList_Context_Unmute: String { return self._s[3635]! } - public var CheckoutInfo_ErrorPostcodeInvalid: String { return self._s[3636]! } - public var Group_MessagePhotoUpdated: String { return self._s[3637]! } - public var Channel_BanUser_PermissionSendMedia: String { return self._s[3638]! } - public var Conversation_ContextMenuBan: String { return self._s[3639]! } - public var TwoStepAuth_EmailSent: String { return self._s[3640]! } - public var MessagePoll_NoVotes: String { return self._s[3641]! } - public var Wallet_Send_ErrorNotEnoughFundsTitle: String { return self._s[3642]! } - public var Passport_Language_is: String { return self._s[3644]! } - public var PeopleNearby_UsersEmpty: String { return self._s[3646]! } - public var Tour_Text5: String { return self._s[3647]! } + public func Channel_AdminLog_MessageChangedGroupStickerPack(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3619]!, self._r[3619]!, [_0]) + } + public var Wallet_Navigation_Close: String { return self._s[3620]! } + public var GroupInfo_InvitationLinkGroupFull: String { return self._s[3624]! } + public var Group_EditAdmin_PermissionChangeInfo: String { return self._s[3626]! } + public var Wallet_Month_GenDecember: String { return self._s[3627]! } + public var Contacts_PermissionsAllow: String { return self._s[3628]! } + public var ReportPeer_ReasonCopyright: String { return self._s[3629]! } + public var Channel_EditAdmin_PermissinAddAdminOn: String { return self._s[3630]! } + public var WallpaperPreview_Pattern: String { return self._s[3631]! } + public var Paint_Duplicate: String { return self._s[3632]! } + public var Passport_Address_Country: String { return self._s[3633]! } + public var Notification_RenamedChannel: String { return self._s[3635]! } + public var ChatList_Context_Unmute: String { return self._s[3636]! } + public var CheckoutInfo_ErrorPostcodeInvalid: String { return self._s[3637]! } + public var Group_MessagePhotoUpdated: String { return self._s[3638]! } + public var Channel_BanUser_PermissionSendMedia: String { return self._s[3639]! } + public var Conversation_ContextMenuBan: String { return self._s[3640]! } + public var TwoStepAuth_EmailSent: String { return self._s[3641]! } + public var MessagePoll_NoVotes: String { return self._s[3642]! } + public var Wallet_Send_ErrorNotEnoughFundsTitle: String { return self._s[3643]! } + public var Passport_Language_is: String { return self._s[3645]! } + public var PeopleNearby_UsersEmpty: String { return self._s[3647]! } + public var Tour_Text5: String { return self._s[3648]! } public func Call_GroupFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3650]!, self._r[3650]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3651]!, self._r[3651]!, [_1, _2]) } - public var Undo_SecretChatDeleted: String { return self._s[3651]! } - public var SocksProxySetup_ShareQRCode: String { return self._s[3652]! } + public var Undo_SecretChatDeleted: String { return self._s[3652]! } + public var SocksProxySetup_ShareQRCode: String { return self._s[3653]! } public func VoiceOver_Chat_Size(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3653]!, self._r[3653]!, [_0]) + return formatWithArgumentRanges(self._s[3654]!, self._r[3654]!, [_0]) } - public var Forward_ErrorDisabledForChat: String { return self._s[3654]! } - public var LogoutOptions_ChangePhoneNumberText: String { return self._s[3655]! } - public var Paint_Edit: String { return self._s[3657]! } - public var ScheduledMessages_ReminderNotification: String { return self._s[3659]! } - public var Undo_DeletedGroup: String { return self._s[3661]! } - public var LoginPassword_ForgotPassword: String { return self._s[3662]! } - public var Wallet_WordImport_IncorrectTitle: String { return self._s[3663]! } - public var GroupInfo_GroupNamePlaceholder: String { return self._s[3664]! } + public var Forward_ErrorDisabledForChat: String { return self._s[3655]! } + public var LogoutOptions_ChangePhoneNumberText: String { return self._s[3656]! } + public var Paint_Edit: String { return self._s[3658]! } + public var ScheduledMessages_ReminderNotification: String { return self._s[3660]! } + public var Undo_DeletedGroup: String { return self._s[3662]! } + public var LoginPassword_ForgotPassword: String { return self._s[3663]! } + public var Wallet_WordImport_IncorrectTitle: String { return self._s[3664]! } + public var GroupInfo_GroupNamePlaceholder: String { return self._s[3665]! } public func Notification_Kicked(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3665]!, self._r[3665]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3666]!, self._r[3666]!, [_0, _1]) } - public var AppWallet_TransactionInfo_FeeInfoURL: String { return self._s[3666]! } - public var Conversation_InputTextCaptionPlaceholder: String { return self._s[3667]! } - public var AutoDownloadSettings_VideoMessagesTitle: String { return self._s[3668]! } - public var Passport_Language_uz: String { return self._s[3669]! } - public var Conversation_PinMessageAlertGroup: String { return self._s[3670]! } - public var SettingsSearch_Synonyms_Privacy_GroupsAndChannels: String { return self._s[3671]! } - public var Map_StopLiveLocation: String { return self._s[3673]! } - public var VoiceOver_MessageContextSend: String { return self._s[3675]! } - public var PasscodeSettings_Help: String { return self._s[3676]! } - public var NotificationsSound_Input: String { return self._s[3677]! } - public var Share_Title: String { return self._s[3680]! } - public var LogoutOptions_Title: String { return self._s[3681]! } - public var Wallet_Send_AddressText: String { return self._s[3682]! } - public var Login_TermsOfServiceAgree: String { return self._s[3683]! } - public var Compose_NewEncryptedChatTitle: String { return self._s[3684]! } - public var Channel_AdminLog_TitleSelectedEvents: String { return self._s[3685]! } - public var Channel_EditAdmin_PermissionEditMessages: String { return self._s[3686]! } - public var EnterPasscode_EnterTitle: String { return self._s[3687]! } + public var AppWallet_TransactionInfo_FeeInfoURL: String { return self._s[3667]! } + public var Conversation_InputTextCaptionPlaceholder: String { return self._s[3668]! } + public var AutoDownloadSettings_VideoMessagesTitle: String { return self._s[3669]! } + public var Passport_Language_uz: String { return self._s[3670]! } + public var Conversation_PinMessageAlertGroup: String { return self._s[3671]! } + public var SettingsSearch_Synonyms_Privacy_GroupsAndChannels: String { return self._s[3672]! } + public var Map_StopLiveLocation: String { return self._s[3674]! } + public var VoiceOver_MessageContextSend: String { return self._s[3676]! } + public var PasscodeSettings_Help: String { return self._s[3677]! } + public var NotificationsSound_Input: String { return self._s[3678]! } + public var Share_Title: String { return self._s[3681]! } + public var LogoutOptions_Title: String { return self._s[3682]! } + public var Wallet_Send_AddressText: String { return self._s[3683]! } + public var Login_TermsOfServiceAgree: String { return self._s[3684]! } + public var Compose_NewEncryptedChatTitle: String { return self._s[3685]! } + public var Channel_AdminLog_TitleSelectedEvents: String { return self._s[3686]! } + public var Channel_EditAdmin_PermissionEditMessages: String { return self._s[3687]! } + public var EnterPasscode_EnterTitle: String { return self._s[3688]! } public func Call_PrivacyErrorMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3688]!, self._r[3688]!, [_0]) + return formatWithArgumentRanges(self._s[3689]!, self._r[3689]!, [_0]) } - public var Settings_CopyPhoneNumber: String { return self._s[3689]! } - public var Conversation_AddToContacts: String { return self._s[3690]! } + public var Settings_CopyPhoneNumber: String { return self._s[3690]! } + public var Conversation_AddToContacts: String { return self._s[3691]! } public func VoiceOver_Chat_ReplyFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3691]!, self._r[3691]!, [_0]) + return formatWithArgumentRanges(self._s[3692]!, self._r[3692]!, [_0]) } - public var NotificationsSound_Keys: String { return self._s[3692]! } + public var NotificationsSound_Keys: String { return self._s[3693]! } public func Call_ParticipantVersionOutdatedError(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3693]!, self._r[3693]!, [_0]) + return formatWithArgumentRanges(self._s[3694]!, self._r[3694]!, [_0]) } - public var Notification_MessageLifetime1w: String { return self._s[3694]! } - public var Message_Video: String { return self._s[3695]! } - public var AutoDownloadSettings_CellularTitle: String { return self._s[3696]! } + public var Notification_MessageLifetime1w: String { return self._s[3695]! } + public var Message_Video: String { return self._s[3696]! } + public var AutoDownloadSettings_CellularTitle: String { return self._s[3697]! } public func PUSH_CHANNEL_MESSAGE_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3697]!, self._r[3697]!, [_1]) + return formatWithArgumentRanges(self._s[3698]!, self._r[3698]!, [_1]) } - public var Wallet_Receive_AmountInfo: String { return self._s[3700]! } + public var Wallet_Receive_AmountInfo: String { return self._s[3701]! } public func Notification_JoinedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3701]!, self._r[3701]!, [_0]) - } - public func PrivacySettings_LastSeenContactsPlus(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3702]!, self._r[3702]!, [_0]) } - public var Passport_Language_mk: String { return self._s[3703]! } - public func Wallet_Time_PreciseDate_m2(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3704]!, self._r[3704]!, [_1, _2, _3]) + public func PrivacySettings_LastSeenContactsPlus(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3703]!, self._r[3703]!, [_0]) } - public var CreatePoll_CancelConfirmation: String { return self._s[3705]! } - public var MessagePoll_LabelAnonymousQuiz: String { return self._s[3706]! } - public var Conversation_SilentBroadcastTooltipOn: String { return self._s[3708]! } - public var PrivacyPolicy_Decline: String { return self._s[3709]! } - public var Passport_Identity_DoesNotExpire: String { return self._s[3710]! } - public var Channel_AdminLogFilter_EventsRestrictions: String { return self._s[3711]! } - public var AuthSessions_AddDeviceIntro_Action: String { return self._s[3712]! } - public var Permissions_SiriAllow_v0: String { return self._s[3714]! } - public var Wallet_Month_ShortAugust: String { return self._s[3715]! } - public var Appearance_ThemeCarouselNight: String { return self._s[3716]! } + public var Passport_Language_mk: String { return self._s[3704]! } + public func Wallet_Time_PreciseDate_m2(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3705]!, self._r[3705]!, [_1, _2, _3]) + } + public var CreatePoll_CancelConfirmation: String { return self._s[3706]! } + public var MessagePoll_LabelAnonymousQuiz: String { return self._s[3707]! } + public var Conversation_SilentBroadcastTooltipOn: String { return self._s[3709]! } + public var PrivacyPolicy_Decline: String { return self._s[3710]! } + public var Passport_Identity_DoesNotExpire: String { return self._s[3711]! } + public var Channel_AdminLogFilter_EventsRestrictions: String { return self._s[3712]! } + public var AuthSessions_AddDeviceIntro_Action: String { return self._s[3713]! } + public var Permissions_SiriAllow_v0: String { return self._s[3715]! } + public var Wallet_Month_ShortAugust: String { return self._s[3716]! } + public var Appearance_ThemeCarouselNight: String { return self._s[3717]! } public func LOCAL_CHAT_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3717]!, self._r[3717]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[3718]!, self._r[3718]!, [_1, "\(_2)"]) } public func Notification_RenamedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3718]!, self._r[3718]!, [_0]) + return formatWithArgumentRanges(self._s[3719]!, self._r[3719]!, [_0]) } - public var Paint_Regular: String { return self._s[3719]! } - public var ChatSettings_AutoDownloadReset: String { return self._s[3720]! } - public var SocksProxySetup_ShareLink: String { return self._s[3721]! } - public var Wallet_Qr_Title: String { return self._s[3722]! } - public var BlockedUsers_SelectUserTitle: String { return self._s[3723]! } - public var VoiceOver_Chat_RecordModeVoiceMessage: String { return self._s[3725]! } - public var Wallet_Settings_Configuration: String { return self._s[3726]! } - public var GroupInfo_InviteByLink: String { return self._s[3727]! } - public var MessageTimer_Custom: String { return self._s[3728]! } - public var UserInfo_NotificationsDefaultEnabled: String { return self._s[3729]! } - public var Conversation_StopQuizConfirmationTitle: String { return self._s[3730]! } - public var Passport_Address_TypeTemporaryRegistration: String { return self._s[3732]! } - public var Conversation_SendMessage_SetReminder: String { return self._s[3733]! } - public var VoiceOver_Chat_Selected: String { return self._s[3734]! } - public var ChatSettings_AutoDownloadUsingWiFi: String { return self._s[3735]! } - public var Channel_Username_InvalidTaken: String { return self._s[3736]! } - public var Conversation_ClousStorageInfo_Description3: String { return self._s[3737]! } - public var Wallet_WordCheck_TryAgain: String { return self._s[3738]! } - public var Wallet_Info_TransactionPendingHeader: String { return self._s[3739]! } - public var Settings_ChatBackground: String { return self._s[3740]! } - public var Channel_Subscribers_Title: String { return self._s[3741]! } - public var Wallet_Receive_InvoiceUrlHeader: String { return self._s[3742]! } - public var ApplyLanguage_ChangeLanguageTitle: String { return self._s[3743]! } - public var Watch_ConnectionDescription: String { return self._s[3744]! } - public var OldChannels_NoticeText: String { return self._s[3747]! } - public var Wallet_Configuration_ApplyErrorTitle: String { return self._s[3748]! } - public var IntentsSettings_SuggestBy: String { return self._s[3750]! } - public var Theme_ThemeChangedText: String { return self._s[3751]! } - public var ChatList_ArchivedChatsTitle: String { return self._s[3752]! } - public var Wallpaper_ResetWallpapers: String { return self._s[3753]! } - public var Wallet_Send_TransactionInProgress: String { return self._s[3754]! } - public var EditProfile_Title: String { return self._s[3755]! } - public var NotificationsSound_Bamboo: String { return self._s[3757]! } - public var Channel_AdminLog_MessagePreviousMessage: String { return self._s[3759]! } - public var Login_SmsRequestState2: String { return self._s[3760]! } - public var Passport_Language_ar: String { return self._s[3761]! } + public var Paint_Regular: String { return self._s[3720]! } + public var ChatSettings_AutoDownloadReset: String { return self._s[3721]! } + public var SocksProxySetup_ShareLink: String { return self._s[3722]! } + public var Wallet_Qr_Title: String { return self._s[3723]! } + public var BlockedUsers_SelectUserTitle: String { return self._s[3724]! } + public var VoiceOver_Chat_RecordModeVoiceMessage: String { return self._s[3726]! } + public var Wallet_Settings_Configuration: String { return self._s[3727]! } + public var GroupInfo_InviteByLink: String { return self._s[3728]! } + public var MessageTimer_Custom: String { return self._s[3729]! } + public var UserInfo_NotificationsDefaultEnabled: String { return self._s[3730]! } + public var Conversation_StopQuizConfirmationTitle: String { return self._s[3731]! } + public var Passport_Address_TypeTemporaryRegistration: String { return self._s[3733]! } + public var Conversation_SendMessage_SetReminder: String { return self._s[3734]! } + public var VoiceOver_Chat_Selected: String { return self._s[3735]! } + public var ChatSettings_AutoDownloadUsingWiFi: String { return self._s[3736]! } + public var Channel_Username_InvalidTaken: String { return self._s[3737]! } + public var Conversation_ClousStorageInfo_Description3: String { return self._s[3738]! } + public var Wallet_WordCheck_TryAgain: String { return self._s[3739]! } + public var Wallet_Info_TransactionPendingHeader: String { return self._s[3740]! } + public var Settings_ChatBackground: String { return self._s[3741]! } + public var Channel_Subscribers_Title: String { return self._s[3742]! } + public var Wallet_Receive_InvoiceUrlHeader: String { return self._s[3743]! } + public var ApplyLanguage_ChangeLanguageTitle: String { return self._s[3744]! } + public var Watch_ConnectionDescription: String { return self._s[3745]! } + public var OldChannels_NoticeText: String { return self._s[3748]! } + public var Wallet_Configuration_ApplyErrorTitle: String { return self._s[3749]! } + public var IntentsSettings_SuggestBy: String { return self._s[3751]! } + public var Theme_ThemeChangedText: String { return self._s[3752]! } + public var ChatList_ArchivedChatsTitle: String { return self._s[3753]! } + public var Wallpaper_ResetWallpapers: String { return self._s[3754]! } + public var Wallet_Send_TransactionInProgress: String { return self._s[3755]! } + public var EditProfile_Title: String { return self._s[3756]! } + public var NotificationsSound_Bamboo: String { return self._s[3758]! } + public var Channel_AdminLog_MessagePreviousMessage: String { return self._s[3760]! } + public var Login_SmsRequestState2: String { return self._s[3761]! } + public var Passport_Language_ar: String { return self._s[3762]! } public func Message_AuthorPinnedGame(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3762]!, self._r[3762]!, [_0]) + return formatWithArgumentRanges(self._s[3763]!, self._r[3763]!, [_0]) } - public var SettingsSearch_Synonyms_EditProfile_Title: String { return self._s[3763]! } - public var Wallet_Created_Text: String { return self._s[3764]! } - public var Conversation_MessageDialogEdit: String { return self._s[3766]! } - public var Wallet_Created_Proceed: String { return self._s[3767]! } - public var Wallet_Words_Done: String { return self._s[3768]! } - public var VoiceOver_Media_PlaybackPause: String { return self._s[3769]! } + public var SettingsSearch_Synonyms_EditProfile_Title: String { return self._s[3764]! } + public var Wallet_Created_Text: String { return self._s[3765]! } + public var Conversation_MessageDialogEdit: String { return self._s[3767]! } + public var Wallet_Created_Proceed: String { return self._s[3768]! } + public var Wallet_Words_Done: String { return self._s[3769]! } + public var VoiceOver_Media_PlaybackPause: String { return self._s[3770]! } public func PUSH_AUTH_UNKNOWN(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3770]!, self._r[3770]!, [_1]) + return formatWithArgumentRanges(self._s[3771]!, self._r[3771]!, [_1]) } - public var Common_Close: String { return self._s[3771]! } - public var GroupInfo_PublicLink: String { return self._s[3772]! } - public var Channel_OwnershipTransfer_ErrorPrivacyRestricted: String { return self._s[3773]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsPreview: String { return self._s[3774]! } + public var Common_Close: String { return self._s[3772]! } + public var GroupInfo_PublicLink: String { return self._s[3773]! } + public var Channel_OwnershipTransfer_ErrorPrivacyRestricted: String { return self._s[3774]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsPreview: String { return self._s[3775]! } public func Channel_AdminLog_MessageToggleInvitesOff(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3778]!, self._r[3778]!, [_0]) + return formatWithArgumentRanges(self._s[3779]!, self._r[3779]!, [_0]) } - public var UserInfo_About_Placeholder: String { return self._s[3779]! } + public var UserInfo_About_Placeholder: String { return self._s[3780]! } public func Conversation_FileHowToText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3780]!, self._r[3780]!, [_0]) + return formatWithArgumentRanges(self._s[3781]!, self._r[3781]!, [_0]) } - public var GroupInfo_Permissions_SectionTitle: String { return self._s[3781]! } - public var Channel_Info_Banned: String { return self._s[3783]! } + public var GroupInfo_Permissions_SectionTitle: String { return self._s[3782]! } + public var Channel_Info_Banned: String { return self._s[3784]! } public func Time_MonthOfYear_m11(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3784]!, self._r[3784]!, [_0]) + return formatWithArgumentRanges(self._s[3785]!, self._r[3785]!, [_0]) } - public var Appearance_Other: String { return self._s[3785]! } - public var Passport_Language_my: String { return self._s[3786]! } - public var Group_Setup_BasicHistoryHiddenHelp: String { return self._s[3787]! } + public var Appearance_Other: String { return self._s[3786]! } + public var Passport_Language_my: String { return self._s[3787]! } + public var Group_Setup_BasicHistoryHiddenHelp: String { return self._s[3788]! } public func Time_PreciseDate_m9(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3788]!, self._r[3788]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3789]!, self._r[3789]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_Privacy_PasscodeAndFaceId: String { return self._s[3789]! } - public var IntentsSettings_SuggestedAndSpotlightChatsInfo: String { return self._s[3790]! } - public var Preview_CopyAddress: String { return self._s[3791]! } + public var SettingsSearch_Synonyms_Privacy_PasscodeAndFaceId: String { return self._s[3790]! } + public var IntentsSettings_SuggestedAndSpotlightChatsInfo: String { return self._s[3791]! } + public var Preview_CopyAddress: String { return self._s[3792]! } public func DialogList_SinglePlayingGameSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3792]!, self._r[3792]!, [_0]) + return formatWithArgumentRanges(self._s[3793]!, self._r[3793]!, [_0]) } - public var KeyCommand_JumpToPreviousChat: String { return self._s[3793]! } - public var UserInfo_BotSettings: String { return self._s[3794]! } - public var LiveLocation_MenuStopAll: String { return self._s[3796]! } - public var Passport_PasswordCreate: String { return self._s[3797]! } - public var StickerSettings_MaskContextInfo: String { return self._s[3798]! } - public var Message_PinnedLocationMessage: String { return self._s[3799]! } - public var Map_Satellite: String { return self._s[3800]! } - public var Watch_Message_Unsupported: String { return self._s[3801]! } - public var Username_TooManyPublicUsernamesError: String { return self._s[3802]! } - public var TwoStepAuth_EnterPasswordInvalid: String { return self._s[3803]! } + public var KeyCommand_JumpToPreviousChat: String { return self._s[3794]! } + public var UserInfo_BotSettings: String { return self._s[3795]! } + public var LiveLocation_MenuStopAll: String { return self._s[3797]! } + public var Passport_PasswordCreate: String { return self._s[3798]! } + public var StickerSettings_MaskContextInfo: String { return self._s[3799]! } + public var Message_PinnedLocationMessage: String { return self._s[3800]! } + public var Map_Satellite: String { return self._s[3801]! } + public var Watch_Message_Unsupported: String { return self._s[3802]! } + public var Username_TooManyPublicUsernamesError: String { return self._s[3803]! } + public var TwoStepAuth_EnterPasswordInvalid: String { return self._s[3804]! } public func Notification_PinnedTextMessage(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3804]!, self._r[3804]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3805]!, self._r[3805]!, [_0, _1]) } public func Conversation_OpenBotLinkText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3805]!, self._r[3805]!, [_0]) + return formatWithArgumentRanges(self._s[3806]!, self._r[3806]!, [_0]) } - public var Wallet_WordImport_Continue: String { return self._s[3806]! } + public var Wallet_WordImport_Continue: String { return self._s[3807]! } public func TwoFactorSetup_EmailVerification_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3807]!, self._r[3807]!, [_0]) + return formatWithArgumentRanges(self._s[3808]!, self._r[3808]!, [_0]) } - public var Notifications_ChannelNotificationsHelp: String { return self._s[3808]! } - public var Privacy_Calls_P2PContacts: String { return self._s[3809]! } - public var NotificationsSound_None: String { return self._s[3810]! } - public var Wallet_TransactionInfo_StorageFeeHeader: String { return self._s[3811]! } - public var Channel_DiscussionGroup_UnlinkGroup: String { return self._s[3813]! } - public var AccessDenied_VoiceMicrophone: String { return self._s[3814]! } + public var Notifications_ChannelNotificationsHelp: String { return self._s[3809]! } + public var Privacy_Calls_P2PContacts: String { return self._s[3810]! } + public var NotificationsSound_None: String { return self._s[3811]! } + public var Wallet_TransactionInfo_StorageFeeHeader: String { return self._s[3812]! } + public var Channel_DiscussionGroup_UnlinkGroup: String { return self._s[3814]! } + public var AccessDenied_VoiceMicrophone: String { return self._s[3815]! } public func ApplyLanguage_ChangeLanguageAlreadyActive(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3815]!, self._r[3815]!, [_1]) + return formatWithArgumentRanges(self._s[3816]!, self._r[3816]!, [_1]) } - public var Cache_Indexing: String { return self._s[3816]! } - public var DialogList_RecentTitlePeople: String { return self._s[3818]! } - public var DialogList_EncryptionRejected: String { return self._s[3819]! } - public var GroupInfo_Administrators: String { return self._s[3820]! } - public var Passport_ScanPassportHelp: String { return self._s[3821]! } - public var Application_Name: String { return self._s[3822]! } - public var Channel_AdminLogFilter_ChannelEventsInfo: String { return self._s[3823]! } - public var Appearance_ThemeCarouselDay: String { return self._s[3825]! } - public var Passport_Identity_TranslationHelp: String { return self._s[3826]! } + public var Cache_Indexing: String { return self._s[3817]! } + public var DialogList_RecentTitlePeople: String { return self._s[3819]! } + public var DialogList_EncryptionRejected: String { return self._s[3820]! } + public var GroupInfo_Administrators: String { return self._s[3821]! } + public var Passport_ScanPassportHelp: String { return self._s[3822]! } + public var Application_Name: String { return self._s[3823]! } + public var Channel_AdminLogFilter_ChannelEventsInfo: String { return self._s[3824]! } + public var Appearance_ThemeCarouselDay: String { return self._s[3826]! } + public var Passport_Identity_TranslationHelp: String { return self._s[3827]! } public func VoiceOver_Chat_VideoMessageFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3827]!, self._r[3827]!, [_0]) - } - public func Notification_JoinedGroupByLink(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3828]!, self._r[3828]!, [_0]) } - public func DialogList_EncryptedChatStartedOutgoing(_ _0: String) -> (String, [(Int, NSRange)]) { + public func Notification_JoinedGroupByLink(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3829]!, self._r[3829]!, [_0]) } - public var Channel_EditAdmin_PermissionDeleteMessages: String { return self._s[3830]! } - public var Privacy_ChatsTitle: String { return self._s[3831]! } - public var DialogList_ClearHistoryConfirmation: String { return self._s[3832]! } - public var SettingsSearch_Synonyms_Data_Storage_ClearCache: String { return self._s[3833]! } - public var Watch_Suggestion_HoldOn: String { return self._s[3834]! } - public var Group_EditAdmin_TransferOwnership: String { return self._s[3835]! } - public var WebBrowser_Title: String { return self._s[3836]! } - public var Group_LinkedChannel: String { return self._s[3837]! } - public var VoiceOver_Chat_SeenByRecipient: String { return self._s[3838]! } - public var SocksProxySetup_RequiredCredentials: String { return self._s[3839]! } - public var Passport_Address_TypeRentalAgreementUploadScan: String { return self._s[3840]! } - public var Appearance_TextSize_UseSystem: String { return self._s[3841]! } - public var TwoStepAuth_EmailSkipAlert: String { return self._s[3842]! } - public var ScheduledMessages_RemindersTitle: String { return self._s[3844]! } - public var Channel_Setup_TypePublic: String { return self._s[3846]! } + public func DialogList_EncryptedChatStartedOutgoing(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3830]!, self._r[3830]!, [_0]) + } + public var Channel_EditAdmin_PermissionDeleteMessages: String { return self._s[3831]! } + public var Privacy_ChatsTitle: String { return self._s[3832]! } + public var DialogList_ClearHistoryConfirmation: String { return self._s[3833]! } + public var SettingsSearch_Synonyms_Data_Storage_ClearCache: String { return self._s[3834]! } + public var Watch_Suggestion_HoldOn: String { return self._s[3835]! } + public var Group_EditAdmin_TransferOwnership: String { return self._s[3836]! } + public var WebBrowser_Title: String { return self._s[3837]! } + public var Group_LinkedChannel: String { return self._s[3838]! } + public var VoiceOver_Chat_SeenByRecipient: String { return self._s[3839]! } + public var SocksProxySetup_RequiredCredentials: String { return self._s[3840]! } + public var Passport_Address_TypeRentalAgreementUploadScan: String { return self._s[3841]! } + public var Appearance_TextSize_UseSystem: String { return self._s[3842]! } + public var TwoStepAuth_EmailSkipAlert: String { return self._s[3843]! } + public var ScheduledMessages_RemindersTitle: String { return self._s[3845]! } + public var Channel_Setup_TypePublic: String { return self._s[3847]! } public func Channel_AdminLog_MessageToggleInvitesOn(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3847]!, self._r[3847]!, [_0]) + return formatWithArgumentRanges(self._s[3848]!, self._r[3848]!, [_0]) } - public var Channel_TypeSetup_Title: String { return self._s[3849]! } - public var MessagePoll_ViewResults: String { return self._s[3850]! } - public var Map_OpenInMaps: String { return self._s[3852]! } + public var Channel_TypeSetup_Title: String { return self._s[3850]! } + public var MessagePoll_ViewResults: String { return self._s[3851]! } + public var Map_OpenInMaps: String { return self._s[3853]! } public func PUSH_PINNED_NOTEXT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3853]!, self._r[3853]!, [_1]) + return formatWithArgumentRanges(self._s[3854]!, self._r[3854]!, [_1]) } - public var NotificationsSound_Tremolo: String { return self._s[3855]! } + public var NotificationsSound_Tremolo: String { return self._s[3856]! } public func Date_ChatDateHeaderYear(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3856]!, self._r[3856]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3857]!, self._r[3857]!, [_1, _2, _3]) } - public var ConversationProfile_UnknownAddMemberError: String { return self._s[3857]! } - public var Channel_OwnershipTransfer_PasswordPlaceholder: String { return self._s[3858]! } - public var Passport_PasswordHelp: String { return self._s[3859]! } - public var Login_CodeExpiredError: String { return self._s[3860]! } - public var Channel_EditAdmin_PermissionChangeInfo: String { return self._s[3861]! } - public var Conversation_TitleUnmute: String { return self._s[3862]! } - public var Passport_Identity_ScansHelp: String { return self._s[3863]! } - public var Passport_Language_lo: String { return self._s[3864]! } - public var Camera_FlashAuto: String { return self._s[3865]! } - public var Conversation_OpenBotLinkOpen: String { return self._s[3866]! } - public var Common_Cancel: String { return self._s[3867]! } - public var DialogList_SavedMessagesTooltip: String { return self._s[3868]! } - public var TwoStepAuth_SetupPasswordTitle: String { return self._s[3869]! } - public var Appearance_TintAllColors: String { return self._s[3870]! } + public var ConversationProfile_UnknownAddMemberError: String { return self._s[3858]! } + public var Channel_OwnershipTransfer_PasswordPlaceholder: String { return self._s[3859]! } + public var Passport_PasswordHelp: String { return self._s[3860]! } + public var Login_CodeExpiredError: String { return self._s[3861]! } + public var Channel_EditAdmin_PermissionChangeInfo: String { return self._s[3862]! } + public var Conversation_TitleUnmute: String { return self._s[3863]! } + public var Passport_Identity_ScansHelp: String { return self._s[3864]! } + public var Passport_Language_lo: String { return self._s[3865]! } + public var Camera_FlashAuto: String { return self._s[3866]! } + public var Conversation_OpenBotLinkOpen: String { return self._s[3867]! } + public var Common_Cancel: String { return self._s[3868]! } + public var DialogList_SavedMessagesTooltip: String { return self._s[3869]! } + public var TwoStepAuth_SetupPasswordTitle: String { return self._s[3870]! } + public var Appearance_TintAllColors: String { return self._s[3871]! } public func PUSH_MESSAGE_FWD(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3871]!, self._r[3871]!, [_1]) + return formatWithArgumentRanges(self._s[3872]!, self._r[3872]!, [_1]) } - public var Conversation_ReportSpamConfirmation: String { return self._s[3872]! } - public var ChatSettings_Title: String { return self._s[3874]! } - public var Passport_PasswordReset: String { return self._s[3875]! } - public var SocksProxySetup_TypeNone: String { return self._s[3876]! } - public var EditTheme_Title: String { return self._s[3879]! } - public var PhoneNumberHelp_Help: String { return self._s[3880]! } - public var Checkout_EnterPassword: String { return self._s[3881]! } - public var Share_AuthTitle: String { return self._s[3883]! } - public var Activity_UploadingDocument: String { return self._s[3884]! } - public var State_Connecting: String { return self._s[3885]! } - public var Profile_MessageLifetime1w: String { return self._s[3886]! } - public var Conversation_ContextMenuReport: String { return self._s[3887]! } - public var CheckoutInfo_ReceiverInfoPhone: String { return self._s[3888]! } - public var AutoNightTheme_ScheduledTo: String { return self._s[3889]! } + public var Conversation_ReportSpamConfirmation: String { return self._s[3873]! } + public var ChatSettings_Title: String { return self._s[3875]! } + public var Passport_PasswordReset: String { return self._s[3876]! } + public var SocksProxySetup_TypeNone: String { return self._s[3877]! } + public var EditTheme_Title: String { return self._s[3880]! } + public var PhoneNumberHelp_Help: String { return self._s[3881]! } + public var Checkout_EnterPassword: String { return self._s[3882]! } + public var Share_AuthTitle: String { return self._s[3884]! } + public var Activity_UploadingDocument: String { return self._s[3885]! } + public var State_Connecting: String { return self._s[3886]! } + public var Profile_MessageLifetime1w: String { return self._s[3887]! } + public var Conversation_ContextMenuReport: String { return self._s[3888]! } + public var CheckoutInfo_ReceiverInfoPhone: String { return self._s[3889]! } + public var AutoNightTheme_ScheduledTo: String { return self._s[3890]! } public func VoiceOver_Chat_AnonymousPollFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3890]!, self._r[3890]!, [_0]) + return formatWithArgumentRanges(self._s[3891]!, self._r[3891]!, [_0]) } - public var AuthSessions_Terminate: String { return self._s[3891]! } - public var Wallet_WordImport_CanNotRemember: String { return self._s[3892]! } - public var Checkout_NewCard_CardholderNamePlaceholder: String { return self._s[3894]! } - public var KeyCommand_JumpToPreviousUnreadChat: String { return self._s[3895]! } - public var PhotoEditor_Set: String { return self._s[3896]! } - public var EmptyGroupInfo_Title: String { return self._s[3897]! } - public var Login_PadPhoneHelp: String { return self._s[3898]! } - public var AutoDownloadSettings_TypeGroupChats: String { return self._s[3900]! } - public var PrivacyPolicy_DeclineLastWarning: String { return self._s[3902]! } - public var NotificationsSound_Complete: String { return self._s[3903]! } - public var SettingsSearch_Synonyms_Privacy_Data_Title: String { return self._s[3904]! } - public var Group_Info_AdminLog: String { return self._s[3905]! } - public var GroupPermission_NotAvailableInPublicGroups: String { return self._s[3906]! } + public var AuthSessions_Terminate: String { return self._s[3892]! } + public var Wallet_WordImport_CanNotRemember: String { return self._s[3893]! } + public var Checkout_NewCard_CardholderNamePlaceholder: String { return self._s[3895]! } + public var KeyCommand_JumpToPreviousUnreadChat: String { return self._s[3896]! } + public var PhotoEditor_Set: String { return self._s[3897]! } + public var EmptyGroupInfo_Title: String { return self._s[3898]! } + public var Login_PadPhoneHelp: String { return self._s[3899]! } + public var AutoDownloadSettings_TypeGroupChats: String { return self._s[3901]! } + public var PrivacyPolicy_DeclineLastWarning: String { return self._s[3903]! } + public var NotificationsSound_Complete: String { return self._s[3904]! } + public var SettingsSearch_Synonyms_Privacy_Data_Title: String { return self._s[3905]! } + public var Group_Info_AdminLog: String { return self._s[3906]! } + public var GroupPermission_NotAvailableInPublicGroups: String { return self._s[3907]! } public func Wallet_Time_PreciseDate_m11(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3907]!, self._r[3907]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3908]!, self._r[3908]!, [_1, _2, _3]) } - public var Channel_AdminLog_InfoPanelAlertText: String { return self._s[3908]! } - public var Group_Location_CreateInThisPlace: String { return self._s[3910]! } - public var Conversation_Admin: String { return self._s[3911]! } - public var Conversation_GifTooltip: String { return self._s[3912]! } - public var Passport_NotLoggedInMessage: String { return self._s[3913]! } + public var Channel_AdminLog_InfoPanelAlertText: String { return self._s[3909]! } + public var Group_Location_CreateInThisPlace: String { return self._s[3911]! } + public var Conversation_Admin: String { return self._s[3912]! } + public var Conversation_GifTooltip: String { return self._s[3913]! } + public var Passport_NotLoggedInMessage: String { return self._s[3914]! } public func AutoDownloadSettings_OnFor(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3915]!, self._r[3915]!, [_0]) + return formatWithArgumentRanges(self._s[3916]!, self._r[3916]!, [_0]) } - public var Profile_MessageLifetimeForever: String { return self._s[3916]! } - public var SharedMedia_EmptyTitle: String { return self._s[3918]! } - public var Channel_Edit_PrivatePublicLinkAlert: String { return self._s[3920]! } - public var Username_Help: String { return self._s[3921]! } - public var DialogList_LanguageTooltip: String { return self._s[3923]! } - public var Map_LoadError: String { return self._s[3924]! } - public var Login_PhoneNumberAlreadyAuthorized: String { return self._s[3925]! } - public var Channel_AdminLog_AddMembers: String { return self._s[3926]! } - public var ArchivedChats_IntroTitle2: String { return self._s[3927]! } - public var Notification_Exceptions_NewException: String { return self._s[3928]! } - public var TwoStepAuth_EmailTitle: String { return self._s[3929]! } - public var WatchRemote_AlertText: String { return self._s[3930]! } + public var Profile_MessageLifetimeForever: String { return self._s[3917]! } + public var SharedMedia_EmptyTitle: String { return self._s[3919]! } + public var Channel_Edit_PrivatePublicLinkAlert: String { return self._s[3921]! } + public var Username_Help: String { return self._s[3922]! } + public var DialogList_LanguageTooltip: String { return self._s[3924]! } + public var Map_LoadError: String { return self._s[3925]! } + public var Login_PhoneNumberAlreadyAuthorized: String { return self._s[3926]! } + public var Channel_AdminLog_AddMembers: String { return self._s[3927]! } + public var ArchivedChats_IntroTitle2: String { return self._s[3928]! } + public var Notification_Exceptions_NewException: String { return self._s[3929]! } + public var TwoStepAuth_EmailTitle: String { return self._s[3930]! } + public var WatchRemote_AlertText: String { return self._s[3931]! } public func Wallet_Send_ConfirmationText(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3931]!, self._r[3931]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3932]!, self._r[3932]!, [_1, _2, _3]) } - public var ChatSettings_ConnectionType_Title: String { return self._s[3935]! } - public var WebBrowser_DefaultBrowser: String { return self._s[3936]! } + public var ChatSettings_ConnectionType_Title: String { return self._s[3936]! } + public var WebBrowser_DefaultBrowser: String { return self._s[3937]! } public func Settings_CheckPhoneNumberTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3937]!, self._r[3937]!, [_0]) + return formatWithArgumentRanges(self._s[3938]!, self._r[3938]!, [_0]) } - public var SettingsSearch_Synonyms_Calls_CallTab: String { return self._s[3938]! } - public var Passport_Address_CountryPlaceholder: String { return self._s[3939]! } + public var SettingsSearch_Synonyms_Calls_CallTab: String { return self._s[3939]! } + public var Passport_Address_CountryPlaceholder: String { return self._s[3940]! } public func DialogList_AwaitingEncryption(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3940]!, self._r[3940]!, [_0]) + return formatWithArgumentRanges(self._s[3941]!, self._r[3941]!, [_0]) } public func Time_PreciseDate_m6(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3941]!, self._r[3941]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3942]!, self._r[3942]!, [_1, _2, _3]) } - public var Group_AdminLog_EmptyText: String { return self._s[3942]! } - public var SettingsSearch_Synonyms_Appearance_Title: String { return self._s[3943]! } - public var Conversation_PrivateChannelTooltip: String { return self._s[3945]! } - public var Wallet_Created_ExportErrorText: String { return self._s[3946]! } - public var ChatList_UndoArchiveText1: String { return self._s[3947]! } - public var AccessDenied_VideoMicrophone: String { return self._s[3948]! } - public var Conversation_ContextMenuStickerPackAdd: String { return self._s[3949]! } - public var Cache_ClearNone: String { return self._s[3950]! } - public var SocksProxySetup_FailedToConnect: String { return self._s[3951]! } - public var Permissions_NotificationsTitle_v0: String { return self._s[3952]! } + public var Group_AdminLog_EmptyText: String { return self._s[3943]! } + public var SettingsSearch_Synonyms_Appearance_Title: String { return self._s[3944]! } + public var Conversation_PrivateChannelTooltip: String { return self._s[3946]! } + public var Wallet_Created_ExportErrorText: String { return self._s[3947]! } + public var ChatList_UndoArchiveText1: String { return self._s[3948]! } + public var AccessDenied_VideoMicrophone: String { return self._s[3949]! } + public var Conversation_ContextMenuStickerPackAdd: String { return self._s[3950]! } + public var Cache_ClearNone: String { return self._s[3951]! } + public var SocksProxySetup_FailedToConnect: String { return self._s[3952]! } + public var Permissions_NotificationsTitle_v0: String { return self._s[3953]! } public func Channel_AdminLog_MessageEdited(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3953]!, self._r[3953]!, [_0]) + return formatWithArgumentRanges(self._s[3954]!, self._r[3954]!, [_0]) } - public var Passport_Identity_Country: String { return self._s[3954]! } + public var Passport_Identity_Country: String { return self._s[3955]! } public func ChatSettings_AutoDownloadSettings_TypeFile(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3955]!, self._r[3955]!, [_0]) - } - public func Notification_CreatedChat(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3956]!, self._r[3956]!, [_0]) } - public var Exceptions_AddToExceptions: String { return self._s[3957]! } - public var AccessDenied_Settings: String { return self._s[3958]! } - public var Passport_Address_TypeUtilityBillUploadScan: String { return self._s[3959]! } - public var Month_ShortMay: String { return self._s[3960]! } - public var Compose_NewGroup: String { return self._s[3962]! } - public var Group_Setup_TypePrivate: String { return self._s[3964]! } - public var Login_PadPhoneHelpTitle: String { return self._s[3966]! } - public var Appearance_ThemeDayClassic: String { return self._s[3967]! } - public var Channel_AdminLog_MessagePreviousCaption: String { return self._s[3968]! } - public var AutoDownloadSettings_OffForAll: String { return self._s[3969]! } - public var Privacy_GroupsAndChannels_WhoCanAddMe: String { return self._s[3970]! } - public var Conversation_typing: String { return self._s[3972]! } - public var Undo_ScheduledMessagesCleared: String { return self._s[3973]! } - public var Paint_Masks: String { return self._s[3974]! } - public var Contacts_DeselectAll: String { return self._s[3975]! } - public func Wallet_Updated_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3976]!, self._r[3976]!, [_0]) + public func Notification_CreatedChat(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3957]!, self._r[3957]!, [_0]) } - public var CreatePoll_MultipleChoiceQuizAlert: String { return self._s[3977]! } - public var Username_InvalidTaken: String { return self._s[3978]! } - public var Call_StatusNoAnswer: String { return self._s[3979]! } - public var TwoStepAuth_EmailAddSuccess: String { return self._s[3980]! } - public var SettingsSearch_Synonyms_Privacy_BlockedUsers: String { return self._s[3981]! } - public var Passport_Identity_Selfie: String { return self._s[3982]! } - public var Login_InfoLastNamePlaceholder: String { return self._s[3983]! } - public var Privacy_SecretChatsLinkPreviewsHelp: String { return self._s[3984]! } - public var Conversation_ClearSecretHistory: String { return self._s[3985]! } - public var PeopleNearby_Description: String { return self._s[3987]! } - public var NetworkUsageSettings_Title: String { return self._s[3988]! } - public var Your_cards_security_code_is_invalid: String { return self._s[3990]! } + public var Exceptions_AddToExceptions: String { return self._s[3958]! } + public var AccessDenied_Settings: String { return self._s[3959]! } + public var Passport_Address_TypeUtilityBillUploadScan: String { return self._s[3960]! } + public var Month_ShortMay: String { return self._s[3961]! } + public var Compose_NewGroup: String { return self._s[3963]! } + public var Group_Setup_TypePrivate: String { return self._s[3965]! } + public var Login_PadPhoneHelpTitle: String { return self._s[3967]! } + public var Appearance_ThemeDayClassic: String { return self._s[3968]! } + public var Channel_AdminLog_MessagePreviousCaption: String { return self._s[3969]! } + public var AutoDownloadSettings_OffForAll: String { return self._s[3970]! } + public var Privacy_GroupsAndChannels_WhoCanAddMe: String { return self._s[3971]! } + public var Conversation_typing: String { return self._s[3973]! } + public var Undo_ScheduledMessagesCleared: String { return self._s[3974]! } + public var Paint_Masks: String { return self._s[3975]! } + public var Contacts_DeselectAll: String { return self._s[3976]! } + public func Wallet_Updated_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3977]!, self._r[3977]!, [_0]) + } + public var CreatePoll_MultipleChoiceQuizAlert: String { return self._s[3978]! } + public var Username_InvalidTaken: String { return self._s[3979]! } + public var Call_StatusNoAnswer: String { return self._s[3980]! } + public var TwoStepAuth_EmailAddSuccess: String { return self._s[3981]! } + public var SettingsSearch_Synonyms_Privacy_BlockedUsers: String { return self._s[3982]! } + public var Passport_Identity_Selfie: String { return self._s[3983]! } + public var Login_InfoLastNamePlaceholder: String { return self._s[3984]! } + public var Privacy_SecretChatsLinkPreviewsHelp: String { return self._s[3985]! } + public var Conversation_ClearSecretHistory: String { return self._s[3986]! } + public var PeopleNearby_Description: String { return self._s[3988]! } + public var NetworkUsageSettings_Title: String { return self._s[3989]! } + public var Your_cards_security_code_is_invalid: String { return self._s[3991]! } public func Notification_LeftChannel(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3992]!, self._r[3992]!, [_0]) + return formatWithArgumentRanges(self._s[3993]!, self._r[3993]!, [_0]) } public func Call_CallInProgressMessage(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3993]!, self._r[3993]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3994]!, self._r[3994]!, [_1, _2]) } - public var SaveIncomingPhotosSettings_From: String { return self._s[3995]! } - public var VoiceOver_Navigation_Search: String { return self._s[3996]! } - public var Map_LiveLocationTitle: String { return self._s[3997]! } - public var Login_InfoAvatarAdd: String { return self._s[3998]! } - public var Passport_Identity_FilesView: String { return self._s[3999]! } - public var UserInfo_GenericPhoneLabel: String { return self._s[4000]! } - public var Privacy_Calls_NeverAllow: String { return self._s[4001]! } - public var VoiceOver_Chat_File: String { return self._s[4002]! } - public var Wallet_Settings_DeleteWalletInfo: String { return self._s[4003]! } + public var SaveIncomingPhotosSettings_From: String { return self._s[3996]! } + public var VoiceOver_Navigation_Search: String { return self._s[3997]! } + public var Map_LiveLocationTitle: String { return self._s[3998]! } + public var Login_InfoAvatarAdd: String { return self._s[3999]! } + public var Passport_Identity_FilesView: String { return self._s[4000]! } + public var UserInfo_GenericPhoneLabel: String { return self._s[4001]! } + public var Privacy_Calls_NeverAllow: String { return self._s[4002]! } + public var VoiceOver_Chat_File: String { return self._s[4003]! } + public var Wallet_Settings_DeleteWalletInfo: String { return self._s[4004]! } public func Contacts_AddPhoneNumber(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4004]!, self._r[4004]!, [_0]) + return formatWithArgumentRanges(self._s[4005]!, self._r[4005]!, [_0]) } - public var ContactInfo_PhoneNumberHidden: String { return self._s[4005]! } - public var TwoStepAuth_ConfirmationText: String { return self._s[4006]! } - public var ChatSettings_AutomaticVideoMessageDownload: String { return self._s[4007]! } + public var ContactInfo_PhoneNumberHidden: String { return self._s[4006]! } + public var TwoStepAuth_ConfirmationText: String { return self._s[4007]! } + public var ChatSettings_AutomaticVideoMessageDownload: String { return self._s[4008]! } public func PUSH_CHAT_MESSAGE_VIDEOS(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4008]!, self._r[4008]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[4009]!, self._r[4009]!, [_1, _2, _3]) } - public var Channel_AdminLogFilter_AdminsAll: String { return self._s[4009]! } - public var Wallet_Intro_CreateErrorText: String { return self._s[4010]! } - public var Tour_Title2: String { return self._s[4011]! } - public var Wallet_Sent_ViewWallet: String { return self._s[4012]! } - public var Conversation_FileOpenIn: String { return self._s[4013]! } - public var Checkout_ErrorPrecheckoutFailed: String { return self._s[4014]! } - public var Wallet_Send_ErrorInvalidAddress: String { return self._s[4015]! } - public var Wallpaper_Set: String { return self._s[4016]! } - public var Passport_Identity_Translations: String { return self._s[4018]! } + public var Channel_AdminLogFilter_AdminsAll: String { return self._s[4010]! } + public var Wallet_Intro_CreateErrorText: String { return self._s[4011]! } + public var Tour_Title2: String { return self._s[4012]! } + public var Wallet_Sent_ViewWallet: String { return self._s[4013]! } + public var Conversation_FileOpenIn: String { return self._s[4014]! } + public var Checkout_ErrorPrecheckoutFailed: String { return self._s[4015]! } + public var Wallet_Send_ErrorInvalidAddress: String { return self._s[4016]! } + public var Wallpaper_Set: String { return self._s[4017]! } + public var Passport_Identity_Translations: String { return self._s[4019]! } public func Channel_AdminLog_MessageChangedChannelAbout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4019]!, self._r[4019]!, [_0]) + return formatWithArgumentRanges(self._s[4020]!, self._r[4020]!, [_0]) } - public var Channel_LeaveChannel: String { return self._s[4020]! } + public var Channel_LeaveChannel: String { return self._s[4021]! } public func PINNED_INVOICE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4021]!, self._r[4021]!, [_1]) + return formatWithArgumentRanges(self._s[4022]!, self._r[4022]!, [_1]) } - public var SettingsSearch_Synonyms_Proxy_AddProxy: String { return self._s[4023]! } - public var PhotoEditor_HighlightsTint: String { return self._s[4024]! } - public var MessagePoll_LabelPoll: String { return self._s[4025]! } - public var Passport_Email_Delete: String { return self._s[4026]! } - public var Conversation_Mute: String { return self._s[4028]! } - public var Channel_AddBotAsAdmin: String { return self._s[4029]! } - public var Channel_AdminLog_CanSendMessages: String { return self._s[4031]! } - public var Wallet_Configuration_BlockchainNameChangedText: String { return self._s[4032]! } - public var ChatSettings_IntentsSettings: String { return self._s[4034]! } - public var Channel_Management_LabelOwner: String { return self._s[4035]! } + public var SettingsSearch_Synonyms_Proxy_AddProxy: String { return self._s[4024]! } + public var PhotoEditor_HighlightsTint: String { return self._s[4025]! } + public var MessagePoll_LabelPoll: String { return self._s[4026]! } + public var Passport_Email_Delete: String { return self._s[4027]! } + public var Conversation_Mute: String { return self._s[4029]! } + public var Channel_AddBotAsAdmin: String { return self._s[4030]! } + public var Channel_AdminLog_CanSendMessages: String { return self._s[4032]! } + public var Wallet_Configuration_BlockchainNameChangedText: String { return self._s[4033]! } + public var ChatSettings_IntentsSettings: String { return self._s[4035]! } + public var Channel_Management_LabelOwner: String { return self._s[4036]! } public func Notification_PassportValuesSentMessage(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4036]!, self._r[4036]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4037]!, self._r[4037]!, [_1, _2]) } - public var Calls_CallTabDescription: String { return self._s[4037]! } - public var Passport_Identity_NativeNameHelp: String { return self._s[4038]! } - public var Common_No: String { return self._s[4039]! } - public var Weekday_Sunday: String { return self._s[4040]! } - public var Notification_Reply: String { return self._s[4041]! } - public var Conversation_ViewMessage: String { return self._s[4042]! } + public var Calls_CallTabDescription: String { return self._s[4038]! } + public var Passport_Identity_NativeNameHelp: String { return self._s[4039]! } + public var Common_No: String { return self._s[4040]! } + public var Weekday_Sunday: String { return self._s[4041]! } + public var Notification_Reply: String { return self._s[4042]! } + public var Conversation_ViewMessage: String { return self._s[4043]! } public func Checkout_SavePasswordTimeoutAndFaceId(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4043]!, self._r[4043]!, [_0]) - } - public func Map_LiveLocationPrivateDescription(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[4044]!, self._r[4044]!, [_0]) } + public func Map_LiveLocationPrivateDescription(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[4045]!, self._r[4045]!, [_0]) + } public func Wallet_Time_PreciseDate_m7(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4045]!, self._r[4045]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[4046]!, self._r[4046]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_EditProfile_AddAccount: String { return self._s[4046]! } - public var Wallet_Send_Title: String { return self._s[4047]! } - public var Message_PinnedDocumentMessage: String { return self._s[4048]! } - public var Wallet_Info_RefreshErrorText: String { return self._s[4049]! } - public var DialogList_TabTitle: String { return self._s[4051]! } - public var ChatSettings_AutoPlayTitle: String { return self._s[4052]! } - public var Passport_FieldEmail: String { return self._s[4053]! } - public var Conversation_UnpinMessageAlert: String { return self._s[4054]! } - public var Passport_Address_TypeBankStatement: String { return self._s[4055]! } - public var Wallet_SecureStorageReset_Title: String { return self._s[4056]! } - public var Passport_Identity_ExpiryDate: String { return self._s[4057]! } - public var Privacy_Calls_P2P: String { return self._s[4058]! } + public var SettingsSearch_Synonyms_EditProfile_AddAccount: String { return self._s[4047]! } + public var Wallet_Send_Title: String { return self._s[4048]! } + public var Message_PinnedDocumentMessage: String { return self._s[4049]! } + public var Wallet_Info_RefreshErrorText: String { return self._s[4050]! } + public var DialogList_TabTitle: String { return self._s[4052]! } + public var ChatSettings_AutoPlayTitle: String { return self._s[4053]! } + public var Passport_FieldEmail: String { return self._s[4054]! } + public var Conversation_UnpinMessageAlert: String { return self._s[4055]! } + public var Passport_Address_TypeBankStatement: String { return self._s[4056]! } + public var Wallet_SecureStorageReset_Title: String { return self._s[4057]! } + public var Passport_Identity_ExpiryDate: String { return self._s[4058]! } + public var Privacy_Calls_P2P: String { return self._s[4059]! } public func CancelResetAccount_Success(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4060]!, self._r[4060]!, [_0]) + return formatWithArgumentRanges(self._s[4061]!, self._r[4061]!, [_0]) } - public var SocksProxySetup_UseForCallsHelp: String { return self._s[4061]! } + public var SocksProxySetup_UseForCallsHelp: String { return self._s[4062]! } public func PUSH_CHAT_ALBUM(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4062]!, self._r[4062]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4063]!, self._r[4063]!, [_1, _2]) } - public var Stickers_ClearRecent: String { return self._s[4063]! } - public var EnterPasscode_ChangeTitle: String { return self._s[4064]! } - public var TwoFactorSetup_Email_Title: String { return self._s[4065]! } - public var Passport_InfoText: String { return self._s[4066]! } - public var Checkout_NewCard_SaveInfoEnableHelp: String { return self._s[4067]! } + public var Stickers_ClearRecent: String { return self._s[4064]! } + public var EnterPasscode_ChangeTitle: String { return self._s[4065]! } + public var TwoFactorSetup_Email_Title: String { return self._s[4066]! } + public var Passport_InfoText: String { return self._s[4067]! } + public var Checkout_NewCard_SaveInfoEnableHelp: String { return self._s[4068]! } public func Login_InvalidPhoneEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4068]!, self._r[4068]!, [_0]) + return formatWithArgumentRanges(self._s[4069]!, self._r[4069]!, [_0]) } public func Time_PreciseDate_m3(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4069]!, self._r[4069]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[4070]!, self._r[4070]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChannels: String { return self._s[4070]! } - public var ScheduledMessages_PollUnavailable: String { return self._s[4071]! } - public var VoiceOver_Navigation_Compose: String { return self._s[4072]! } - public var Passport_Identity_EditDriversLicense: String { return self._s[4073]! } - public var Conversation_TapAndHoldToRecord: String { return self._s[4075]! } - public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChats: String { return self._s[4076]! } + public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChannels: String { return self._s[4071]! } + public var ScheduledMessages_PollUnavailable: String { return self._s[4072]! } + public var VoiceOver_Navigation_Compose: String { return self._s[4073]! } + public var Passport_Identity_EditDriversLicense: String { return self._s[4074]! } + public var Conversation_TapAndHoldToRecord: String { return self._s[4076]! } + public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChats: String { return self._s[4077]! } public func Notification_CallTimeFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4077]!, self._r[4077]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4078]!, self._r[4078]!, [_1, _2]) } - public var Channel_EditAdmin_PermissionInviteViaLink: String { return self._s[4079]! } - public var ChatSettings_OpenLinksIn: String { return self._s[4080]! } - public var Map_HomeAndWorkTitle: String { return self._s[4081]! } + public var Channel_EditAdmin_PermissionInviteViaLink: String { return self._s[4080]! } + public var ChatSettings_OpenLinksIn: String { return self._s[4081]! } + public var Map_HomeAndWorkTitle: String { return self._s[4082]! } public func Generic_OpenHiddenLinkAlert(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4083]!, self._r[4083]!, [_0]) + return formatWithArgumentRanges(self._s[4084]!, self._r[4084]!, [_0]) } - public var DialogList_Unread: String { return self._s[4084]! } + public var DialogList_Unread: String { return self._s[4085]! } public func PUSH_CHAT_MESSAGE_GIF(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4085]!, self._r[4085]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4086]!, self._r[4086]!, [_1, _2]) } - public var User_DeletedAccount: String { return self._s[4086]! } - public var OwnershipTransfer_SetupTwoStepAuth: String { return self._s[4087]! } + public var User_DeletedAccount: String { return self._s[4087]! } + public var OwnershipTransfer_SetupTwoStepAuth: String { return self._s[4088]! } public func Watch_Time_ShortYesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4088]!, self._r[4088]!, [_0]) + return formatWithArgumentRanges(self._s[4089]!, self._r[4089]!, [_0]) } - public var UserInfo_NotificationsDefault: String { return self._s[4089]! } - public var SharedMedia_CategoryMedia: String { return self._s[4090]! } - public var SocksProxySetup_ProxyStatusUnavailable: String { return self._s[4091]! } - public var Channel_AdminLog_MessageRestrictedForever: String { return self._s[4092]! } - public var Watch_ChatList_Compose: String { return self._s[4093]! } - public var Notifications_MessageNotificationsExceptionsHelp: String { return self._s[4094]! } - public var AutoDownloadSettings_Delimeter: String { return self._s[4095]! } - public var Watch_Microphone_Access: String { return self._s[4096]! } - public var Group_Setup_HistoryHeader: String { return self._s[4097]! } - public var Map_SetThisLocation: String { return self._s[4098]! } - public var Appearance_ThemePreview_Chat_2_ReplyName: String { return self._s[4099]! } - public var Activity_UploadingPhoto: String { return self._s[4100]! } - public var Conversation_Edit: String { return self._s[4102]! } - public var Group_ErrorSendRestrictedMedia: String { return self._s[4103]! } - public var Login_TermsOfServiceDecline: String { return self._s[4104]! } - public var Message_PinnedContactMessage: String { return self._s[4105]! } + public var UserInfo_NotificationsDefault: String { return self._s[4090]! } + public var SharedMedia_CategoryMedia: String { return self._s[4091]! } + public var SocksProxySetup_ProxyStatusUnavailable: String { return self._s[4092]! } + public var Channel_AdminLog_MessageRestrictedForever: String { return self._s[4093]! } + public var Watch_ChatList_Compose: String { return self._s[4094]! } + public var Notifications_MessageNotificationsExceptionsHelp: String { return self._s[4095]! } + public var AutoDownloadSettings_Delimeter: String { return self._s[4096]! } + public var Watch_Microphone_Access: String { return self._s[4097]! } + public var Group_Setup_HistoryHeader: String { return self._s[4098]! } + public var Map_SetThisLocation: String { return self._s[4099]! } + public var Appearance_ThemePreview_Chat_2_ReplyName: String { return self._s[4100]! } + public var Activity_UploadingPhoto: String { return self._s[4101]! } + public var Conversation_Edit: String { return self._s[4103]! } + public var Group_ErrorSendRestrictedMedia: String { return self._s[4104]! } + public var Login_TermsOfServiceDecline: String { return self._s[4105]! } + public var Message_PinnedContactMessage: String { return self._s[4106]! } public func Channel_AdminLog_MessageRestrictedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4106]!, self._r[4106]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4107]!, self._r[4107]!, [_1, _2]) } public func Login_PhoneBannedEmailBody(_ _1: String, _ _2: String, _ _3: String, _ _4: String, _ _5: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4107]!, self._r[4107]!, [_1, _2, _3, _4, _5]) + return formatWithArgumentRanges(self._s[4108]!, self._r[4108]!, [_1, _2, _3, _4, _5]) } - public var Appearance_LargeEmoji: String { return self._s[4108]! } - public var TwoStepAuth_AdditionalPassword: String { return self._s[4110]! } - public var EditTheme_Edit_Preview_IncomingReplyText: String { return self._s[4111]! } + public var Appearance_LargeEmoji: String { return self._s[4109]! } + public var TwoStepAuth_AdditionalPassword: String { return self._s[4111]! } + public var EditTheme_Edit_Preview_IncomingReplyText: String { return self._s[4112]! } public func PUSH_CHAT_DELETE_YOU(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4112]!, self._r[4112]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4113]!, self._r[4113]!, [_1, _2]) } - public var Passport_Phone_EnterOtherNumber: String { return self._s[4113]! } - public var Message_PinnedPhotoMessage: String { return self._s[4114]! } - public var Passport_FieldPhone: String { return self._s[4115]! } - public var TwoStepAuth_RecoveryEmailAddDescription: String { return self._s[4116]! } - public var ChatSettings_AutoPlayGifs: String { return self._s[4117]! } - public var InfoPlist_NSCameraUsageDescription: String { return self._s[4119]! } - public var Conversation_Call: String { return self._s[4120]! } - public var Common_TakePhoto: String { return self._s[4122]! } - public var Group_EditAdmin_RankTitle: String { return self._s[4123]! } - public var Wallet_Receive_CommentHeader: String { return self._s[4124]! } - public var Channel_NotificationLoading: String { return self._s[4125]! } + public var Passport_Phone_EnterOtherNumber: String { return self._s[4114]! } + public var Message_PinnedPhotoMessage: String { return self._s[4115]! } + public var Passport_FieldPhone: String { return self._s[4116]! } + public var TwoStepAuth_RecoveryEmailAddDescription: String { return self._s[4117]! } + public var ChatSettings_AutoPlayGifs: String { return self._s[4118]! } + public var InfoPlist_NSCameraUsageDescription: String { return self._s[4120]! } + public var Conversation_Call: String { return self._s[4121]! } + public var Common_TakePhoto: String { return self._s[4123]! } + public var Group_EditAdmin_RankTitle: String { return self._s[4124]! } + public var Wallet_Receive_CommentHeader: String { return self._s[4125]! } + public var Channel_NotificationLoading: String { return self._s[4126]! } public func Notification_Exceptions_Sound(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4126]!, self._r[4126]!, [_0]) - } - public func ScheduledMessages_ScheduledDate(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[4127]!, self._r[4127]!, [_0]) } + public func ScheduledMessages_ScheduledDate(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[4128]!, self._r[4128]!, [_0]) + } public func PUSH_CHANNEL_MESSAGE_VIDEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4128]!, self._r[4128]!, [_1]) + return formatWithArgumentRanges(self._s[4129]!, self._r[4129]!, [_1]) } - public var Permissions_SiriTitle_v0: String { return self._s[4129]! } + public var Permissions_SiriTitle_v0: String { return self._s[4130]! } public func VoiceOver_Chat_VoiceMessageFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4130]!, self._r[4130]!, [_0]) - } - public func Login_ResetAccountProtected_Text(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[4131]!, self._r[4131]!, [_0]) } - public var Channel_MessagePhotoRemoved: String { return self._s[4132]! } - public var Wallet_Info_ReceiveGrams: String { return self._s[4133]! } - public var ClearCache_FreeSpace: String { return self._s[4134]! } - public var Common_edit: String { return self._s[4135]! } - public var PrivacySettings_AuthSessions: String { return self._s[4136]! } - public var Month_ShortJune: String { return self._s[4137]! } - public var PrivacyLastSeenSettings_AlwaysShareWith_Placeholder: String { return self._s[4138]! } - public var Call_ReportSend: String { return self._s[4139]! } - public var Watch_LastSeen_JustNow: String { return self._s[4140]! } - public var Notifications_MessageNotifications: String { return self._s[4141]! } - public var WallpaperSearch_ColorGreen: String { return self._s[4142]! } - public var BroadcastListInfo_AddRecipient: String { return self._s[4144]! } - public var Group_Status: String { return self._s[4145]! } + public func Login_ResetAccountProtected_Text(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[4132]!, self._r[4132]!, [_0]) + } + public var Channel_MessagePhotoRemoved: String { return self._s[4133]! } + public var Wallet_Info_ReceiveGrams: String { return self._s[4134]! } + public var ClearCache_FreeSpace: String { return self._s[4135]! } + public var Common_edit: String { return self._s[4136]! } + public var PrivacySettings_AuthSessions: String { return self._s[4137]! } + public var Month_ShortJune: String { return self._s[4138]! } + public var PrivacyLastSeenSettings_AlwaysShareWith_Placeholder: String { return self._s[4139]! } + public var Call_ReportSend: String { return self._s[4140]! } + public var Watch_LastSeen_JustNow: String { return self._s[4141]! } + public var Notifications_MessageNotifications: String { return self._s[4142]! } + public var WallpaperSearch_ColorGreen: String { return self._s[4143]! } + public var BroadcastListInfo_AddRecipient: String { return self._s[4145]! } + public var Group_Status: String { return self._s[4146]! } public func AutoNightTheme_LocationHelp(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4146]!, self._r[4146]!, [_0, _1]) + return formatWithArgumentRanges(self._s[4147]!, self._r[4147]!, [_0, _1]) } - public var TextFormat_AddLinkTitle: String { return self._s[4147]! } - public var ShareMenu_ShareTo: String { return self._s[4148]! } - public var Conversation_Moderate_Ban: String { return self._s[4149]! } + public var TextFormat_AddLinkTitle: String { return self._s[4148]! } + public var ShareMenu_ShareTo: String { return self._s[4149]! } + public var Conversation_Moderate_Ban: String { return self._s[4150]! } public func Conversation_DeleteMessagesFor(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4150]!, self._r[4150]!, [_0]) + return formatWithArgumentRanges(self._s[4151]!, self._r[4151]!, [_0]) } - public var SharedMedia_ViewInChat: String { return self._s[4151]! } - public var Map_LiveLocationFor8Hours: String { return self._s[4152]! } + public var SharedMedia_ViewInChat: String { return self._s[4152]! } + public var Map_LiveLocationFor8Hours: String { return self._s[4153]! } public func PUSH_PINNED_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4153]!, self._r[4153]!, [_1]) + return formatWithArgumentRanges(self._s[4154]!, self._r[4154]!, [_1]) } public func PUSH_PINNED_POLL(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4154]!, self._r[4154]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4155]!, self._r[4155]!, [_1, _2]) } public func Map_AccurateTo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4156]!, self._r[4156]!, [_0]) + return formatWithArgumentRanges(self._s[4157]!, self._r[4157]!, [_0]) } - public var Map_OpenInHereMaps: String { return self._s[4157]! } - public var Appearance_ReduceMotion: String { return self._s[4158]! } + public var Map_OpenInHereMaps: String { return self._s[4158]! } + public var Appearance_ReduceMotion: String { return self._s[4159]! } public func PUSH_MESSAGE_TEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4159]!, self._r[4159]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4160]!, self._r[4160]!, [_1, _2]) } - public var Channel_Setup_TypePublicHelp: String { return self._s[4160]! } - public var Passport_Identity_EditInternalPassport: String { return self._s[4161]! } - public var PhotoEditor_Skip: String { return self._s[4162]! } - public func MuteExpires_Minutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, stringValue) - } - public func StickerPack_RemoveStickerCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ChatList_SelectedChats(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[2 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_ShortDays(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[3 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ChatList_DeleteConfirmation(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[4 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_ShortSeconds(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[5 * 6 + Int(form.rawValue)]!, stringValue) - } - public func VoiceOver_Chat_PollVotes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[6 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notification_GameScoreExtended(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[7 * 6 + Int(form.rawValue)]!, stringValue) - } - public func CreatePoll_AddMoreOptions(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[8 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notification_GameScoreSelfSimple(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[9 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notifications_ExceptionMuteExpires_Days(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[10 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Minutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[11 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedGifs(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[12 * 6 + Int(form.rawValue)]!, stringValue) + public var Channel_Setup_TypePublicHelp: String { return self._s[4161]! } + public var Passport_Identity_EditInternalPassport: String { return self._s[4162]! } + public var PhotoEditor_Skip: String { return self._s[4163]! } + public func PUSH_CHANNEL_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, _1, _2) } public func ForwardedPolls(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[13 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, stringValue) } - public func StickerPack_RemoveMaskCount(_ value: Int32) -> String { + public func Invitation_Members(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[14 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[2 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessagePoll_VotedCount(_ value: Int32) -> String { + public func Call_ShortSeconds(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[15 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[3 * 6 + Int(form.rawValue)]!, stringValue) } - public func Media_SharePhoto(_ value: Int32) -> String { + public func MuteFor_Days(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[16 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[4 * 6 + Int(form.rawValue)]!, stringValue) } - public func PasscodeSettings_FailedAttempts(_ value: Int32) -> String { + public func Notification_GameScoreSimple(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[17 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[5 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedLocations(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[6 * 6 + Int(form.rawValue)]!, stringValue) } public func MuteExpires_Days(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[18 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[19 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MuteExpires_Hours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[20 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Chat_DeleteMessagesConfirmation(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[21 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHANNEL_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[22 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func MuteFor_Hours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[23 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedMessages(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[24 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedPhotos(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[25 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Call_Minutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[26 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Conversation_LiveLocationMembersCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[27 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Contacts_ImportersCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[28 * 6 + Int(form.rawValue)]!, stringValue) - } - public func SharedMedia_DeleteItemsConfirmation(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[29 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedContacts(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[30 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Wallet_Updated_HoursAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[31 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Wallpaper_DeleteConfirmation(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[32 * 6 + Int(form.rawValue)]!, stringValue) - } - public func LiveLocationUpdated_MinutesAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[33 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Call_ShortMinutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[34 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ServiceMessage_GameScoreSelfExtended(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[35 * 6 + Int(form.rawValue)]!, stringValue) - } - public func VoiceOver_Chat_PollOptionCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[36 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHANNEL_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[37 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func Conversation_StatusOnline(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[38 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Watch_UserInfo_Mute(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[39 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGE_FWDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[40 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func InviteText_ContactsCountText(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[41 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[7 * 6 + Int(form.rawValue)]!, stringValue) } public func MessagePoll_QuizCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[8 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Map_ETAMinutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[9 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedAudios(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[10 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHAT_MESSAGE_FWDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[11 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func PrivacyLastSeenSettings_AddUsers(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[12 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedContacts(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[13 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHAT_MESSAGE_PHOTOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[14 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func SharedMedia_Generic(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[15 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedPhotos(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[16 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedGifs(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[17 * 6 + Int(form.rawValue)]!, stringValue) + } + public func AttachmentMenu_SendVideo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[18 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[19 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func VoiceOver_Chat_ContactEmailCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[20 * 6 + Int(form.rawValue)]!, stringValue) + } + public func StickerPack_AddStickerCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[21 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Media_SharePhoto(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[22 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Days(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[23 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[24 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Weeks(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[25 * 6 + Int(form.rawValue)]!, stringValue) + } + public func SharedMedia_File(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[26 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedStickers(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[27 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHAT_MESSAGE_VIDEOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[28 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func Map_ETAHours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[29 * 6 + Int(form.rawValue)]!, stringValue) + } + public func OldChannels_InactiveMonth(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[30 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ChatList_DeletedChats(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[31 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Years(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[32 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MuteFor_Hours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[33 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortMinutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[34 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[35 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func SharedMedia_Photo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[36 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Wallpaper_DeleteConfirmation(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[37 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Theme_UsersCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[38 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHAT_MESSAGE_ROUNDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[39 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func PUSH_CHANNEL_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[40 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func MuteExpires_Minutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[41 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Media_ShareItem(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[42 * 6 + Int(form.rawValue)]!, stringValue) } - public func SharedMedia_Video(_ value: Int32) -> String { + public func Contacts_ImportersCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[43 * 6 + Int(form.rawValue)]!, stringValue) } - public func AttachmentMenu_SendPhoto(_ value: Int32) -> String { + public func InviteText_ContactsCountText(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[44 * 6 + Int(form.rawValue)]!, stringValue) @@ -4912,389 +4908,394 @@ public final class PresentationStrings: Equatable { let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[45 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_ShortWeeks(_ value: Int32) -> String { + public func ServiceMessage_GameScoreExtended(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[46 * 6 + Int(form.rawValue)]!, stringValue) } - public func Notifications_Exceptions(_ value: Int32) -> String { + public func Call_ShortMinutes(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[47 * 6 + Int(form.rawValue)]!, stringValue) } - public func PUSH_CHAT_MESSAGE_PHOTOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + public func PUSH_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[48 * 6 + Int(form.rawValue)]!, _2, _1, _3) + return String(format: self._ps[48 * 6 + Int(form.rawValue)]!, _1, _2) } - public func PUSH_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[49 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func MessageTimer_Weeks(_ value: Int32) -> String { + public func Watch_UserInfo_Mute(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[50 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notifications_ExceptionMuteExpires_Hours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[51 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_ShortMinutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[52 * 6 + Int(form.rawValue)]!, stringValue) - } - public func DialogList_LiveLocationChatsCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[53 * 6 + Int(form.rawValue)]!, stringValue) - } - public func OldChannels_InactiveWeek(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[54 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Conversation_StatusSubscribers(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[55 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Forward_ConfirmMultipleFiles(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[56 * 6 + Int(form.rawValue)]!, stringValue) - } - public func AttachmentMenu_SendVideo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[57 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Watch_LastSeen_HoursAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[58 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Media_ShareVideo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[59 * 6 + Int(form.rawValue)]!, stringValue) - } - public func SharedMedia_File(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[60 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Watch_LastSeen_MinutesAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[61 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PrivacyLastSeenSettings_AddUsers(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[62 * 6 + Int(form.rawValue)]!, stringValue) - } - public func SharedMedia_Generic(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[63 * 6 + Int(form.rawValue)]!, stringValue) - } - public func VoiceOver_Chat_ContactEmailCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[64 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[65 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func PUSH_CHANNEL_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[66 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func ForwardedStickers(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[67 * 6 + Int(form.rawValue)]!, stringValue) - } - public func GroupInfo_ShowMoreMembers(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[68 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ChatList_DeletedChats(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[69 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Conversation_SelectedMessages(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[70 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notification_GameScoreSelfExtended(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[71 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[72 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func LiveLocation_MenuChatsCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[73 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Years(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[74 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notification_GameScoreSimple(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[75 * 6 + Int(form.rawValue)]!, stringValue) - } - public func OldChannels_Leave(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[76 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[49 * 6 + Int(form.rawValue)]!, stringValue) } public func ServiceMessage_GameScoreSelfSimple(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[77 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[50 * 6 + Int(form.rawValue)]!, stringValue) } - public func PollResults_ShowMore(_ value: Int32) -> String { + public func Media_ShareVideo(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[78 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[51 * 6 + Int(form.rawValue)]!, stringValue) } - public func OldChannels_InactiveMonth(_ value: Int32) -> String { + public func MessageTimer_Minutes(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[79 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[52 * 6 + Int(form.rawValue)]!, stringValue) } - public func PUSH_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + public func PUSH_CHANNEL_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[80 * 6 + Int(form.rawValue)]!, _1, _2) + return String(format: self._ps[53 * 6 + Int(form.rawValue)]!, _1, _2) } - public func SharedMedia_Link(_ value: Int32) -> String { + public func DialogList_LiveLocationChatsCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[81 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[54 * 6 + Int(form.rawValue)]!, stringValue) } - public func PUSH_CHAT_MESSAGES(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[82 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func ServiceMessage_GameScoreExtended(_ value: Int32) -> String { + public func Call_Minutes(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[83 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[55 * 6 + Int(form.rawValue)]!, stringValue) } - public func PUSH_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[84 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func MessageTimer_Seconds(_ value: Int32) -> String { + public func LiveLocationUpdated_MinutesAgo(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[85 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[56 * 6 + Int(form.rawValue)]!, stringValue) } - public func UserCount(_ value: Int32) -> String { + public func Forward_ConfirmMultipleFiles(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[86 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[57 * 6 + Int(form.rawValue)]!, stringValue) } - public func Map_ETAHours(_ value: Int32) -> String { + public func ChatList_SelectedChats(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[87 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notifications_ExceptionMuteExpires_Minutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[88 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGE_ROUNDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[89 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func MessageTimer_ShortHours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[90 * 6 + Int(form.rawValue)]!, stringValue) - } - public func StickerPack_AddMaskCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[91 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Call_Seconds(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[92 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedVideos(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[93 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Conversation_StatusMembers(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[94 * 6 + Int(form.rawValue)]!, stringValue) - } - public func StickerPack_AddStickerCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[95 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[58 * 6 + Int(form.rawValue)]!, stringValue) } public func OldChannels_InactiveYear(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[96 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedVideoMessages(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[97 * 6 + Int(form.rawValue)]!, stringValue) - } - public func AttachmentMenu_SendItem(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[98 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedAuthorsOthers(_ selector: Int32, _ _0: String, _ _1: String) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[99 * 6 + Int(form.rawValue)]!, _0, _1) + return String(format: self._ps[59 * 6 + Int(form.rawValue)]!, stringValue) } public func ForwardedFiles(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[100 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[60 * 6 + Int(form.rawValue)]!, stringValue) } - public func Contacts_InviteContacts(_ value: Int32) -> String { + public func ForwardedVideoMessages(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[101 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[61 * 6 + Int(form.rawValue)]!, stringValue) } - public func Invitation_Members(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[102 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Theme_UsersCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[103 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGE_VIDEOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + public func PUSH_CHANNEL_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[104 * 6 + Int(form.rawValue)]!, _2, _1, _3) + return String(format: self._ps[62 * 6 + Int(form.rawValue)]!, _1, _2) } - public func ServiceMessage_GameScoreSimple(_ value: Int32) -> String { + public func GroupInfo_ShowMoreMembers(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[105 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[63 * 6 + Int(form.rawValue)]!, stringValue) } - public func Call_ShortSeconds(_ value: Int32) -> String { + public func AttachmentMenu_SendItem(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[106 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[64 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_Months(_ value: Int32) -> String { + public func Watch_LastSeen_HoursAgo(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[107 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHANNEL_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[108 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func Map_ETAMinutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[109 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Days(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[110 * 6 + Int(form.rawValue)]!, stringValue) - } - public func QuickSend_Photos(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[111 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[65 * 6 + Int(form.rawValue)]!, stringValue) } public func LastSeen_MinutesAgo(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[112 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[66 * 6 + Int(form.rawValue)]!, stringValue) } - public func VoiceOver_Chat_ContactPhoneNumberCount(_ value: Int32) -> String { + public func PollResults_ShowMore(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[113 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[67 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedAudios(_ value: Int32) -> String { + public func PasscodeSettings_FailedAttempts(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[114 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[68 * 6 + Int(form.rawValue)]!, stringValue) } public func MessageTimer_Hours(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[115 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[69 * 6 + Int(form.rawValue)]!, stringValue) } - public func MuteFor_Days(_ value: Int32) -> String { + public func Notifications_Exceptions(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[116 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[70 * 6 + Int(form.rawValue)]!, stringValue) } - public func LastSeen_HoursAgo(_ value: Int32) -> String { + public func SharedMedia_Video(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[117 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[71 * 6 + Int(form.rawValue)]!, stringValue) } - public func AttachmentMenu_SendGif(_ value: Int32) -> String { + public func Notification_GameScoreExtended(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[118 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[72 * 6 + Int(form.rawValue)]!, stringValue) } - public func GroupInfo_ParticipantCount(_ value: Int32) -> String { + public func ChatList_DeleteConfirmation(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[119 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[73 * 6 + Int(form.rawValue)]!, stringValue) } - public func PUSH_CHANNEL_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + public func PUSH_CHAT_MESSAGES(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[120 * 6 + Int(form.rawValue)]!, _1, _2) + return String(format: self._ps[74 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func Conversation_SelectedMessages(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[75 * 6 + Int(form.rawValue)]!, stringValue) } public func StickerPack_StickerCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[121 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[76 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notifications_ExceptionMuteExpires_Minutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[77 * 6 + Int(form.rawValue)]!, stringValue) + } + public func StickerPack_RemoveMaskCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[78 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Watch_LastSeen_MinutesAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[79 * 6 + Int(form.rawValue)]!, stringValue) + } + public func CreatePoll_AddMoreOptions(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[80 * 6 + Int(form.rawValue)]!, stringValue) + } + public func LiveLocation_MenuChatsCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[81 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[82 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func SharedMedia_Link(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[83 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notification_GameScoreSelfSimple(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[84 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notifications_ExceptionMuteExpires_Days(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[85 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedMessages(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[86 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Wallet_Updated_HoursAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[87 * 6 + Int(form.rawValue)]!, stringValue) + } + public func VoiceOver_Chat_PollOptionCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[88 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Call_Seconds(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[89 * 6 + Int(form.rawValue)]!, stringValue) + } + public func LastSeen_HoursAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[90 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedVideos(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[91 * 6 + Int(form.rawValue)]!, stringValue) + } + public func OldChannels_InactiveWeek(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[92 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Conversation_StatusOnline(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[93 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Seconds(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[94 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notifications_ExceptionMuteExpires_Hours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[95 * 6 + Int(form.rawValue)]!, stringValue) + } + public func UserCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[96 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Conversation_LiveLocationMembersCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[97 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortDays(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[98 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Conversation_StatusSubscribers(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[99 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortHours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[100 * 6 + Int(form.rawValue)]!, stringValue) + } + public func StickerPack_RemoveStickerCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[101 * 6 + Int(form.rawValue)]!, stringValue) + } + public func VoiceOver_Chat_PollVotes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[102 * 6 + Int(form.rawValue)]!, stringValue) + } + public func SharedMedia_DeleteItemsConfirmation(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[103 * 6 + Int(form.rawValue)]!, stringValue) + } + public func StickerPack_AddMaskCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[104 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ServiceMessage_GameScoreSelfExtended(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[105 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Chat_DeleteMessagesConfirmation(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[106 * 6 + Int(form.rawValue)]!, stringValue) } public func OldChannels_GroupFormat(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[122 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[107 * 6 + Int(form.rawValue)]!, stringValue) } - public func Media_ShareItem(_ value: Int32) -> String { + public func VoiceOver_Chat_ContactPhoneNumberCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[108 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[109 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func AttachmentMenu_SendGif(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[110 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortWeeks(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[111 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessagePoll_VotedCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[112 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortSeconds(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[113 * 6 + Int(form.rawValue)]!, stringValue) + } + public func AttachmentMenu_SendPhoto(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[114 * 6 + Int(form.rawValue)]!, stringValue) + } + public func QuickSend_Photos(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[115 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Months(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[116 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedAuthorsOthers(_ selector: Int32, _ _0: String, _ _1: String) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[117 * 6 + Int(form.rawValue)]!, _0, _1) + } + public func OldChannels_Leave(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[118 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notification_GameScoreSelfExtended(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[119 * 6 + Int(form.rawValue)]!, stringValue) + } + public func GroupInfo_ParticipantCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[120 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Contacts_InviteContacts(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[121 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[122 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func ServiceMessage_GameScoreSimple(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[123 * 6 + Int(form.rawValue)]!, stringValue) } - public func SharedMedia_Photo(_ value: Int32) -> String { + public func MuteExpires_Hours(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[124 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedLocations(_ value: Int32) -> String { + public func Conversation_StatusMembers(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[125 * 6 + Int(form.rawValue)]!, stringValue) diff --git a/submodules/TelegramUI/TelegramUI/ChatPinnedMessageTitlePanelNode.swift b/submodules/TelegramUI/TelegramUI/ChatPinnedMessageTitlePanelNode.swift index e89377d3c9..96052f5d0b 100644 --- a/submodules/TelegramUI/TelegramUI/ChatPinnedMessageTitlePanelNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatPinnedMessageTitlePanelNode.swift @@ -211,8 +211,13 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { imageDimensions = representation.dimensions.cgSize } break - } else if let _ = media as? TelegramMediaPoll { - titleString = strings.Conversation_PinnedPoll + } else if let poll = media as? TelegramMediaPoll { + switch poll.kind { + case .poll: + titleString = strings.Conversation_PinnedPoll + case .quiz: + titleString = strings.Conversation_PinnedQuiz + } } } diff --git a/submodules/TelegramUI/TelegramUI/Resources/PresentationStrings.mapping b/submodules/TelegramUI/TelegramUI/Resources/PresentationStrings.mapping index 7adbe8a6e4e7f15e6e162ac5d7527016541fb600..0aedd8b408bd15f8fcb7fbf646f700074a5647a2 100644 GIT binary patch delta 21907 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 G{Qn29;C%Z4 delta 21970 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 PSSi1y2_+lNrMmwIE9_EP diff --git a/submodules/WalletUI/Resources/WalletStrings.mapping b/submodules/WalletUI/Resources/WalletStrings.mapping index 589c6fe85e4fa03a50b6adefffe67915bd39bf1c..9f7c34892095545bdfb3f1e1871a24394137ff12 100644 GIT binary patch delta 17 YcmX@$c))Q(i^Al^3bKrhlN%M}070t;9smFU delta 40 vcmX@$c))Q(i-L?e0|P^NVopwKiC$ String { + public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, stringValue) } - public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String { + public func Wallet_Updated_HoursAgo(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, stringValue) From ac30ca49cd9cfe1d084c822322b825670eea74e7 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sat, 18 Jan 2020 00:16:43 +0400 Subject: [PATCH 07/50] Extend .excludeChannels to recent peers --- .../Sources/ChatListControllerNode.swift | 1 + .../Sources/ChatListSearchContainerNode.swift | 22 ++++++++++++++----- .../PeerSelectionControllerNode.swift | 2 ++ 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/submodules/ChatListUI/Sources/ChatListControllerNode.swift b/submodules/ChatListUI/Sources/ChatListControllerNode.swift index 6065cc3b7c..3dd78330a6 100644 --- a/submodules/ChatListUI/Sources/ChatListControllerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListControllerNode.swift @@ -244,6 +244,7 @@ final class ChatListControllerNode: ASDisplayNode { self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, contentNode: ChatListSearchContainerNode(context: self.context, filter: [], groupId: self.groupId, openPeer: { [weak self] peer, dismissSearch in self?.requestOpenPeerFromSearch?(peer, dismissSearch) + }, openDisabledPeer: { _ in }, openRecentPeerOptions: { [weak self] peer in self?.requestOpenRecentPeerOptions?(peer) }, openMessage: { [weak self] peer, messageId in diff --git a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift index 22e250ef4a..79fa26f3f7 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift @@ -81,7 +81,7 @@ private enum ChatListRecentEntry: Comparable, Identifiable { } } - func item(context: AccountContext, presentationData: ChatListPresentationData, filter: ChatListNodePeersFilter, peerSelected: @escaping (Peer) -> Void, peerContextAction: ((Peer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?, clearRecentlySearchedPeers: @escaping () -> Void, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, deletePeer: @escaping (PeerId) -> Void) -> ListViewItem { + func item(context: AccountContext, presentationData: ChatListPresentationData, filter: ChatListNodePeersFilter, peerSelected: @escaping (Peer) -> Void, disaledPeerSelected: @escaping (Peer) -> Void, peerContextAction: ((Peer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?, clearRecentlySearchedPeers: @escaping () -> Void, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, deletePeer: @escaping (PeerId) -> Void) -> ListViewItem { switch self { case let .topPeers(peers, theme, strings): return ChatListRecentPeersListItem(theme: theme, strings: strings, context: context, peers: peers, peerSelected: { peer in @@ -133,6 +133,12 @@ private enum ChatListRecentEntry: Comparable, Identifiable { } } + if filter.contains(.excludeChannels) { + if let channel = primaryPeer as? TelegramChannel, case .broadcast = channel.info { + enabled = false + } + } + let status: ContactsPeerItemStatus if let user = primaryPeer as? TelegramUser { let servicePeer = isServicePeer(primaryPeer) @@ -181,6 +187,10 @@ private enum ChatListRecentEntry: Comparable, Identifiable { if let chatPeer = peer.peer.peers[peer.peer.peerId] { peerSelected(chatPeer) } + }, disabledAction: { _ in + if let chatPeer = peer.peer.peers[peer.peer.peerId] { + disaledPeerSelected(chatPeer) + } }, setPeerIdWithRevealedOptions: setPeerIdWithRevealedOptions, deletePeer: deletePeer, contextAction: peerContextAction.flatMap { peerContextAction in return { node, gesture in if let chatPeer = peer.peer.peers[peer.peer.peerId] { @@ -501,12 +511,12 @@ public struct ChatListSearchContainerTransition { } } -private func chatListSearchContainerPreparedRecentTransition(from fromEntries: [ChatListRecentEntry], to toEntries: [ChatListRecentEntry], context: AccountContext, presentationData: ChatListPresentationData, filter: ChatListNodePeersFilter, peerSelected: @escaping (Peer) -> Void, peerContextAction: ((Peer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?, clearRecentlySearchedPeers: @escaping () -> Void, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, deletePeer: @escaping (PeerId) -> Void) -> ChatListSearchContainerRecentTransition { +private func chatListSearchContainerPreparedRecentTransition(from fromEntries: [ChatListRecentEntry], to toEntries: [ChatListRecentEntry], context: AccountContext, presentationData: ChatListPresentationData, filter: ChatListNodePeersFilter, peerSelected: @escaping (Peer) -> Void, disaledPeerSelected: @escaping (Peer) -> Void, peerContextAction: ((Peer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?, clearRecentlySearchedPeers: @escaping () -> Void, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, deletePeer: @escaping (PeerId) -> Void) -> ChatListSearchContainerRecentTransition { let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries) let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) } - let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, filter: filter, peerSelected: peerSelected, peerContextAction: peerContextAction, clearRecentlySearchedPeers: clearRecentlySearchedPeers, setPeerIdWithRevealedOptions: setPeerIdWithRevealedOptions, deletePeer: deletePeer), directionHint: nil) } - let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, filter: filter, peerSelected: peerSelected, peerContextAction: peerContextAction, clearRecentlySearchedPeers: clearRecentlySearchedPeers, setPeerIdWithRevealedOptions: setPeerIdWithRevealedOptions, deletePeer: deletePeer), directionHint: nil) } + let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, filter: filter, peerSelected: peerSelected, disaledPeerSelected: disaledPeerSelected, peerContextAction: peerContextAction, clearRecentlySearchedPeers: clearRecentlySearchedPeers, setPeerIdWithRevealedOptions: setPeerIdWithRevealedOptions, deletePeer: deletePeer), directionHint: nil) } + let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, filter: filter, peerSelected: peerSelected, disaledPeerSelected: disaledPeerSelected, peerContextAction: peerContextAction, clearRecentlySearchedPeers: clearRecentlySearchedPeers, setPeerIdWithRevealedOptions: setPeerIdWithRevealedOptions, deletePeer: deletePeer), directionHint: nil) } return ChatListSearchContainerRecentTransition(deletions: deletions, insertions: insertions, updates: updates) } @@ -615,7 +625,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo private let filter: ChatListNodePeersFilter - public init(context: AccountContext, filter: ChatListNodePeersFilter, groupId: PeerGroupId, openPeer originalOpenPeer: @escaping (Peer, Bool) -> Void, openRecentPeerOptions: @escaping (Peer) -> Void, openMessage originalOpenMessage: @escaping (Peer, MessageId) -> Void, addContact: ((String) -> Void)?, peerContextAction: ((Peer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?) { + public init(context: AccountContext, filter: ChatListNodePeersFilter, groupId: PeerGroupId, openPeer originalOpenPeer: @escaping (Peer, Bool) -> Void, openDisabledPeer: @escaping (Peer) -> Void, openRecentPeerOptions: @escaping (Peer) -> Void, openMessage originalOpenMessage: @escaping (Peer, MessageId) -> Void, addContact: ((String) -> Void)?, peerContextAction: ((Peer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?) { self.context = context self.filter = filter self.dimNode = ASDisplayNode() @@ -1098,6 +1108,8 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo openPeer(peer, true) let _ = addRecentlySearchedPeer(postbox: context.account.postbox, peerId: peer.id).start() self?.recentListNode.clearHighlightAnimated(true) + }, disaledPeerSelected: { peer in + openDisabledPeer(peer) }, peerContextAction: peerContextAction, clearRecentlySearchedPeers: { self?.clearRecentSearch() diff --git a/submodules/TelegramUI/TelegramUI/PeerSelectionControllerNode.swift b/submodules/TelegramUI/TelegramUI/PeerSelectionControllerNode.swift index b41cc27c8e..45938193a8 100644 --- a/submodules/TelegramUI/TelegramUI/PeerSelectionControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/PeerSelectionControllerNode.swift @@ -216,6 +216,8 @@ final class PeerSelectionControllerNode: ASDisplayNode { if let requestOpenPeerFromSearch = self?.requestOpenPeerFromSearch { requestOpenPeerFromSearch(peer) } + }, openDisabledPeer: { [weak self] peer in + self?.requestOpenDisabledPeer?(peer) }, openRecentPeerOptions: { _ in }, openMessage: { [weak self] peer, messageId in if let requestOpenMessageFromSearch = self?.requestOpenMessageFromSearch { From 9235ff761653cfea1765fe3e3211b69d814c146c Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 19 Jan 2020 01:05:51 +0400 Subject: [PATCH 08/50] Update poll localizations --- Telegram-iOS/en.lproj/Localizable.strings | 10 +- .../Sources/PresentationStrings.swift | 7036 +++++++++-------- .../Sources/ServiceMessageStrings.swift | 15 +- .../ChatMessagePollBubbleContentNode.swift | 2 +- .../Resources/PresentationStrings.mapping | Bin 144206 -> 144339 bytes 5 files changed, 3545 insertions(+), 3518 deletions(-) diff --git a/Telegram-iOS/en.lproj/Localizable.strings b/Telegram-iOS/en.lproj/Localizable.strings index acc869faab..4af86fec1d 100644 --- a/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram-iOS/en.lproj/Localizable.strings @@ -22,6 +22,10 @@ "PUSH_CHANNEL_MESSAGE_POLL" = "%1$@|posted a poll %2$@"; "PUSH_PINNED_POLL" = "%1$@|pinned a poll"; +"PUSH_MESSAGE_QUIZ" = "%1$@|sent you a quiz %2$@"; +"PUSH_CHANNEL_MESSAGE_QUIZ" = "%1$@|posted a quiz %2$@"; +"PUSH_PINNED_QUIZ" = "%1$@|pinned a quiz"; + "PUSH_CHAT_MESSAGE_TEXT" = "%2$@|%1$@: %3$@"; "PUSH_CHAT_MESSAGE_NOTEXT" = "%2$@|%1$@ sent a message"; "PUSH_CHAT_MESSAGE_PHOTO" = "%2$@|%1$@ sent a photo"; @@ -93,6 +97,7 @@ "PUSH_MESSAGE_GEO" = "%1$@|sent you a map"; "PUSH_MESSAGE_GEOLIVE" = "%1$@|started sharing their live location"; "PUSH_MESSAGE_POLL" = "%1$@|sent you a poll"; +"PUSH_MESSAGE_QUIZ" = "%1$@|sent you a quiz"; "PUSH_MESSAGE_GIF" = "%1$@|sent you a GIF"; "PUSH_MESSAGE_GAME" = "%1$@|invited you to play %2$@"; "PUSH_MESSAGE_INVOICE" = "%1$@|sent you an invoice for %2$@"; @@ -125,6 +130,7 @@ "PUSH_CHANNEL_MESSAGE_GEO" = "%1$@|posted a map"; "PUSH_CHANNEL_MESSAGE_GEOLIVE" = "%1$@|posted a live location"; "PUSH_CHANNEL_MESSAGE_POLL" = "%1$@|posted a poll"; +"PUSH_CHANNEL_MESSAGE_QUIZ" = "%1$@|posted a quiz"; "PUSH_CHANNEL_MESSAGE_GIF" = "%1$@|posted a GIF"; "PUSH_CHANNEL_MESSAGE_GAME" = "%1$@|invited you to play %2$@"; "PUSH_CHANNEL_MESSAGE_FWD" = "%1$@|posted a forwarded message"; @@ -155,6 +161,7 @@ "PUSH_CHAT_MESSAGE_GEO" = "%2$@|%1$@ sent a map"; "PUSH_CHAT_MESSAGE_GEOLIVE" = "%2$@|%1$@ started sharing their live location"; "PUSH_CHAT_MESSAGE_POLL" = "%2$@|%1$@ sent a poll %3$@ to the group"; +"PUSH_CHAT_MESSAGE_QUIZ" = "%2$@|%1$@ sent a quiz %3$@ to the group"; "PUSH_CHAT_MESSAGE_GIF" = "%2$@|%1$@ sent a GIF"; "PUSH_CHAT_MESSAGE_GAME" = "%2$@|%1$@ invited the group to play %3$@"; "PUSH_CHAT_MESSAGE_INVOICE" = "%2$@|%1$@ sent an invoice for %3$@"; @@ -197,6 +204,7 @@ "PUSH_PINNED_GEO" = "%1$@|pinned a map"; "PUSH_PINNED_GEOLIVE" = "%1$@|pinned a live location"; "PUSH_PINNED_POLL" = "|%1$@|pinned a poll %2$@"; +"PUSH_PINNED_QUIZ" = "|%1$@|pinned a quiz %2$@"; "PUSH_PINNED_GAME" = "%1$@|pinned a game"; "PUSH_PINNED_INVOICE" = "%1$@|pinned an invoice"; "PUSH_PINNED_GIF" = "%1$@|pinned a GIF"; @@ -1927,6 +1935,7 @@ "Notification.PinnedContactMessage" = "%@ pinned a contact"; "Notification.PinnedDeletedMessage" = "%@ pinned deleted message"; "Notification.PinnedPollMessage" = "%@ pinned a poll"; +"Notification.PinnedQuizMessage" = "%@ pinned a quiz"; "Message.PinnedTextMessage" = "pinned \"%@\" "; "Message.PinnedPhotoMessage" = "pinned photo"; @@ -1937,7 +1946,6 @@ "Message.PinnedStickerMessage" = "pinned sticker"; "Message.PinnedLocationMessage" = "pinned location"; "Message.PinnedContactMessage" = "pinned contact"; -"Message.PinnedPollMessage" = "pinned poll"; "Notification.PinnedMessage" = "pinned message"; diff --git a/submodules/TelegramPresentationData/Sources/PresentationStrings.swift b/submodules/TelegramPresentationData/Sources/PresentationStrings.swift index dd3b469226..d4e4d3501b 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationStrings.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationStrings.swift @@ -865,4330 +865,4343 @@ public final class PresentationStrings: Equatable { public var VoiceOver_Chat_YourFile: String { return self._s[631]! } public var Map_Hybrid: String { return self._s[632]! } public var Contacts_SearchUsersAndGroupsLabel: String { return self._s[634]! } - public var ChatSettings_AutoDownloadVideos: String { return self._s[636]! } - public var Channel_BanUser_PermissionEmbedLinks: String { return self._s[637]! } - public var InfoPlist_NSLocationAlwaysAndWhenInUseUsageDescription: String { return self._s[638]! } - public var SocksProxySetup_ProxyTelegram: String { return self._s[641]! } + public func PUSH_MESSAGE_QUIZ(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[635]!, self._r[635]!, [_1]) + } + public var ChatSettings_AutoDownloadVideos: String { return self._s[637]! } + public var Channel_BanUser_PermissionEmbedLinks: String { return self._s[638]! } + public var InfoPlist_NSLocationAlwaysAndWhenInUseUsageDescription: String { return self._s[639]! } + public var SocksProxySetup_ProxyTelegram: String { return self._s[642]! } public func PUSH_MESSAGE_AUDIO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[642]!, self._r[642]!, [_1]) + return formatWithArgumentRanges(self._s[643]!, self._r[643]!, [_1]) } - public var Channel_Username_CreatePrivateLinkHelp: String { return self._s[644]! } - public var ScheduledMessages_ScheduledToday: String { return self._s[645]! } + public var Channel_Username_CreatePrivateLinkHelp: String { return self._s[645]! } + public var ScheduledMessages_ScheduledToday: String { return self._s[646]! } public func PUSH_CHAT_TITLE_EDITED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[646]!, self._r[646]!, [_1, _2]) + return formatWithArgumentRanges(self._s[647]!, self._r[647]!, [_1, _2]) } - public var Conversation_LiveLocationYou: String { return self._s[647]! } - public var SettingsSearch_Synonyms_Privacy_Calls: String { return self._s[648]! } - public var SettingsSearch_Synonyms_Notifications_MessageNotificationsPreview: String { return self._s[649]! } - public var UserInfo_ShareBot: String { return self._s[652]! } + public var Conversation_LiveLocationYou: String { return self._s[648]! } + public var SettingsSearch_Synonyms_Privacy_Calls: String { return self._s[649]! } + public var SettingsSearch_Synonyms_Notifications_MessageNotificationsPreview: String { return self._s[650]! } + public var UserInfo_ShareBot: String { return self._s[653]! } public func PUSH_AUTH_REGION(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[653]!, self._r[653]!, [_1, _2]) + return formatWithArgumentRanges(self._s[654]!, self._r[654]!, [_1, _2]) } - public var Conversation_ClearCache: String { return self._s[654]! } - public var PhotoEditor_ShadowsTint: String { return self._s[655]! } - public var Message_Audio: String { return self._s[656]! } - public var Passport_Language_lt: String { return self._s[657]! } + public var Conversation_ClearCache: String { return self._s[655]! } + public var PhotoEditor_ShadowsTint: String { return self._s[656]! } + public var Message_Audio: String { return self._s[657]! } + public var Passport_Language_lt: String { return self._s[658]! } public func Message_PinnedTextMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[658]!, self._r[658]!, [_0]) + return formatWithArgumentRanges(self._s[659]!, self._r[659]!, [_0]) } - public var Permissions_SiriText_v0: String { return self._s[659]! } - public var Conversation_FileICloudDrive: String { return self._s[660]! } - public var ChatList_DeleteForEveryoneConfirmationTitle: String { return self._s[661]! } - public var Notifications_Badge_IncludeMutedChats: String { return self._s[662]! } + public var Permissions_SiriText_v0: String { return self._s[660]! } + public var Conversation_FileICloudDrive: String { return self._s[661]! } + public var ChatList_DeleteForEveryoneConfirmationTitle: String { return self._s[662]! } + public var Notifications_Badge_IncludeMutedChats: String { return self._s[663]! } public func Notification_NewAuthDetected(_ _1: String, _ _2: String, _ _3: String, _ _4: String, _ _5: String, _ _6: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[663]!, self._r[663]!, [_1, _2, _3, _4, _5, _6]) + return formatWithArgumentRanges(self._s[664]!, self._r[664]!, [_1, _2, _3, _4, _5, _6]) } - public var DialogList_ProxyConnectionIssuesTooltip: String { return self._s[664]! } + public var DialogList_ProxyConnectionIssuesTooltip: String { return self._s[665]! } public func Time_MonthOfYear_m5(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[665]!, self._r[665]!, [_0]) + return formatWithArgumentRanges(self._s[666]!, self._r[666]!, [_0]) } - public var Channel_SignMessages: String { return self._s[666]! } + public var Channel_SignMessages: String { return self._s[667]! } public func PUSH_MESSAGE_NOTEXT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[667]!, self._r[667]!, [_1]) + return formatWithArgumentRanges(self._s[668]!, self._r[668]!, [_1]) } - public var Compose_ChannelTokenListPlaceholder: String { return self._s[668]! } - public var Passport_ScanPassport: String { return self._s[669]! } - public var Watch_Suggestion_Thanks: String { return self._s[670]! } - public var BlockedUsers_AddNew: String { return self._s[671]! } + public var Compose_ChannelTokenListPlaceholder: String { return self._s[669]! } + public var Passport_ScanPassport: String { return self._s[670]! } + public var Watch_Suggestion_Thanks: String { return self._s[671]! } + public var BlockedUsers_AddNew: String { return self._s[672]! } public func PUSH_CHAT_MESSAGE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[672]!, self._r[672]!, [_1, _2]) + return formatWithArgumentRanges(self._s[673]!, self._r[673]!, [_1, _2]) } - public var Watch_Message_Invoice: String { return self._s[673]! } - public var SettingsSearch_Synonyms_Privacy_LastSeen: String { return self._s[674]! } - public var Month_GenJuly: String { return self._s[675]! } - public var CreatePoll_QuizInfo: String { return self._s[676]! } - public var UserInfo_StartSecretChatStart: String { return self._s[677]! } - public var SocksProxySetup_ProxySocks5: String { return self._s[678]! } - public var IntentsSettings_SuggestByShare: String { return self._s[680]! } - public var Notification_Exceptions_DeleteAllConfirmation: String { return self._s[681]! } - public var Notification_ChannelInviterSelf: String { return self._s[682]! } - public var CheckoutInfo_ReceiverInfoEmail: String { return self._s[683]! } + public var Watch_Message_Invoice: String { return self._s[674]! } + public var SettingsSearch_Synonyms_Privacy_LastSeen: String { return self._s[675]! } + public var Month_GenJuly: String { return self._s[676]! } + public var CreatePoll_QuizInfo: String { return self._s[677]! } + public var UserInfo_StartSecretChatStart: String { return self._s[678]! } + public var SocksProxySetup_ProxySocks5: String { return self._s[679]! } + public var IntentsSettings_SuggestByShare: String { return self._s[681]! } + public var Notification_Exceptions_DeleteAllConfirmation: String { return self._s[682]! } + public var Notification_ChannelInviterSelf: String { return self._s[683]! } + public var CheckoutInfo_ReceiverInfoEmail: String { return self._s[684]! } public func ApplyLanguage_ChangeLanguageUnofficialText(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[684]!, self._r[684]!, [_1, _2]) + return formatWithArgumentRanges(self._s[685]!, self._r[685]!, [_1, _2]) } - public var CheckoutInfo_Title: String { return self._s[685]! } - public var Watch_Stickers_RecentPlaceholder: String { return self._s[686]! } + public var CheckoutInfo_Title: String { return self._s[686]! } + public var Watch_Stickers_RecentPlaceholder: String { return self._s[687]! } public func Map_DistanceAway(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[687]!, self._r[687]!, [_0]) + return formatWithArgumentRanges(self._s[688]!, self._r[688]!, [_0]) } - public var Passport_Identity_MainPage: String { return self._s[688]! } - public var TwoStepAuth_ConfirmEmailResendCode: String { return self._s[689]! } - public var Passport_Language_de: String { return self._s[690]! } - public var Update_Title: String { return self._s[691]! } - public var ContactInfo_PhoneLabelWorkFax: String { return self._s[692]! } - public var Channel_AdminLog_BanEmbedLinks: String { return self._s[693]! } - public var Passport_Email_UseTelegramEmailHelp: String { return self._s[694]! } - public var Notifications_ChannelNotificationsPreview: String { return self._s[695]! } - public var NotificationsSound_Telegraph: String { return self._s[696]! } - public var Watch_LastSeen_ALongTimeAgo: String { return self._s[697]! } - public var ChannelMembers_WhoCanAddMembers: String { return self._s[698]! } + public var Passport_Identity_MainPage: String { return self._s[689]! } + public var TwoStepAuth_ConfirmEmailResendCode: String { return self._s[690]! } + public var Passport_Language_de: String { return self._s[691]! } + public var Update_Title: String { return self._s[692]! } + public var ContactInfo_PhoneLabelWorkFax: String { return self._s[693]! } + public var Channel_AdminLog_BanEmbedLinks: String { return self._s[694]! } + public var Passport_Email_UseTelegramEmailHelp: String { return self._s[695]! } + public var Notifications_ChannelNotificationsPreview: String { return self._s[696]! } + public var NotificationsSound_Telegraph: String { return self._s[697]! } + public var Watch_LastSeen_ALongTimeAgo: String { return self._s[698]! } + public var ChannelMembers_WhoCanAddMembers: String { return self._s[699]! } public func AutoDownloadSettings_UpTo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[699]!, self._r[699]!, [_0]) + return formatWithArgumentRanges(self._s[700]!, self._r[700]!, [_0]) } - public var ClearCache_Description: String { return self._s[700]! } - public var Stickers_SuggestAll: String { return self._s[701]! } - public var Conversation_ForwardTitle: String { return self._s[702]! } - public var Appearance_ThemePreview_ChatList_7_Name: String { return self._s[703]! } + public var ClearCache_Description: String { return self._s[701]! } + public var Stickers_SuggestAll: String { return self._s[702]! } + public var Conversation_ForwardTitle: String { return self._s[703]! } + public var Appearance_ThemePreview_ChatList_7_Name: String { return self._s[704]! } public func Notification_JoinedChannel(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[704]!, self._r[704]!, [_0]) + return formatWithArgumentRanges(self._s[705]!, self._r[705]!, [_0]) } - public var Calls_NewCall: String { return self._s[705]! } - public var Call_StatusEnded: String { return self._s[706]! } - public var AutoDownloadSettings_DataUsageLow: String { return self._s[707]! } - public var Settings_ProxyConnected: String { return self._s[708]! } - public var Channel_AdminLogFilter_EventsPinned: String { return self._s[709]! } - public var PhotoEditor_QualityVeryLow: String { return self._s[710]! } - public var Channel_AdminLogFilter_EventsDeletedMessages: String { return self._s[711]! } - public var Passport_PasswordPlaceholder: String { return self._s[712]! } - public var Message_PinnedInvoice: String { return self._s[713]! } - public var Passport_Identity_IssueDate: String { return self._s[714]! } - public var Passport_Language_pl: String { return self._s[715]! } + public var Calls_NewCall: String { return self._s[706]! } + public var Call_StatusEnded: String { return self._s[707]! } + public var AutoDownloadSettings_DataUsageLow: String { return self._s[708]! } + public var Settings_ProxyConnected: String { return self._s[709]! } + public var Channel_AdminLogFilter_EventsPinned: String { return self._s[710]! } + public var PhotoEditor_QualityVeryLow: String { return self._s[711]! } + public var Channel_AdminLogFilter_EventsDeletedMessages: String { return self._s[712]! } + public var Passport_PasswordPlaceholder: String { return self._s[713]! } + public var Message_PinnedInvoice: String { return self._s[714]! } + public var Passport_Identity_IssueDate: String { return self._s[715]! } + public var Passport_Language_pl: String { return self._s[716]! } public func ChannelInfo_ChannelForbidden(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[716]!, self._r[716]!, [_0]) + return formatWithArgumentRanges(self._s[717]!, self._r[717]!, [_0]) } - public var SocksProxySetup_PasteFromClipboard: String { return self._s[717]! } - public var Call_StatusConnecting: String { return self._s[718]! } + public var SocksProxySetup_PasteFromClipboard: String { return self._s[718]! } + public var Call_StatusConnecting: String { return self._s[719]! } public func Username_UsernameIsAvailable(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[719]!, self._r[719]!, [_0]) + return formatWithArgumentRanges(self._s[720]!, self._r[720]!, [_0]) } - public var ChatSettings_ConnectionType_UseProxy: String { return self._s[721]! } - public var Common_Edit: String { return self._s[722]! } - public var PrivacySettings_LastSeenNobody: String { return self._s[723]! } + public var ChatSettings_ConnectionType_UseProxy: String { return self._s[722]! } + public var Common_Edit: String { return self._s[723]! } + public var PrivacySettings_LastSeenNobody: String { return self._s[724]! } public func Notification_LeftChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[724]!, self._r[724]!, [_0]) + return formatWithArgumentRanges(self._s[725]!, self._r[725]!, [_0]) } - public var GroupInfo_ChatAdmins: String { return self._s[725]! } - public var PrivateDataSettings_Title: String { return self._s[726]! } - public var Login_CancelPhoneVerificationStop: String { return self._s[727]! } - public var ChatList_Read: String { return self._s[728]! } - public var Wallet_WordImport_Text: String { return self._s[729]! } - public var Undo_ChatClearedForBothSides: String { return self._s[730]! } - public var GroupPermission_SectionTitle: String { return self._s[731]! } - public var TwoFactorSetup_Intro_Title: String { return self._s[733]! } + public var GroupInfo_ChatAdmins: String { return self._s[726]! } + public var PrivateDataSettings_Title: String { return self._s[727]! } + public var Login_CancelPhoneVerificationStop: String { return self._s[728]! } + public var ChatList_Read: String { return self._s[729]! } + public var Wallet_WordImport_Text: String { return self._s[730]! } + public var Undo_ChatClearedForBothSides: String { return self._s[731]! } + public var GroupPermission_SectionTitle: String { return self._s[732]! } + public var TwoFactorSetup_Intro_Title: String { return self._s[734]! } public func PUSH_CHAT_LEFT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[734]!, self._r[734]!, [_1, _2]) + return formatWithArgumentRanges(self._s[735]!, self._r[735]!, [_1, _2]) } - public var Checkout_ErrorPaymentFailed: String { return self._s[735]! } - public var Update_UpdateApp: String { return self._s[736]! } - public var Group_Username_RevokeExistingUsernamesInfo: String { return self._s[737]! } - public var Settings_Appearance: String { return self._s[738]! } - public var SettingsSearch_Synonyms_Stickers_SuggestStickers: String { return self._s[742]! } - public var Watch_Location_Access: String { return self._s[743]! } - public var ShareMenu_CopyShareLink: String { return self._s[745]! } - public var TwoStepAuth_SetupHintTitle: String { return self._s[746]! } - public var Conversation_Theme: String { return self._s[748]! } + public var Checkout_ErrorPaymentFailed: String { return self._s[736]! } + public var Update_UpdateApp: String { return self._s[737]! } + public var Group_Username_RevokeExistingUsernamesInfo: String { return self._s[738]! } + public var Settings_Appearance: String { return self._s[739]! } + public var SettingsSearch_Synonyms_Stickers_SuggestStickers: String { return self._s[743]! } + public var Watch_Location_Access: String { return self._s[744]! } + public var ShareMenu_CopyShareLink: String { return self._s[746]! } + public var TwoStepAuth_SetupHintTitle: String { return self._s[747]! } + public var Conversation_Theme: String { return self._s[749]! } public func DialogList_SingleRecordingVideoMessageSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[749]!, self._r[749]!, [_0]) + return formatWithArgumentRanges(self._s[750]!, self._r[750]!, [_0]) } - public var Notifications_ClassicTones: String { return self._s[750]! } - public var Weekday_ShortWednesday: String { return self._s[751]! } - public var WallpaperPreview_SwipeColorsBottomText: String { return self._s[752]! } - public var Undo_LeftGroup: String { return self._s[755]! } - public var Wallet_RestoreFailed_Text: String { return self._s[756]! } - public var Conversation_LinkDialogCopy: String { return self._s[757]! } - public var Wallet_TransactionInfo_NoAddress: String { return self._s[759]! } - public var Wallet_Navigation_Back: String { return self._s[760]! } - public var KeyCommand_FocusOnInputField: String { return self._s[761]! } - public var Contacts_SelectAll: String { return self._s[762]! } - public var Preview_SaveToCameraRoll: String { return self._s[763]! } - public var PrivacySettings_PasscodeOff: String { return self._s[764]! } - public var Appearance_ThemePreview_ChatList_6_Name: String { return self._s[765]! } - public var Wallpaper_Title: String { return self._s[766]! } - public var Conversation_FilePhotoOrVideo: String { return self._s[767]! } - public var AccessDenied_Camera: String { return self._s[768]! } - public var Watch_Compose_CurrentLocation: String { return self._s[769]! } - public var Channel_DiscussionGroup_MakeHistoryPublicProceed: String { return self._s[771]! } + public var Notifications_ClassicTones: String { return self._s[751]! } + public var Weekday_ShortWednesday: String { return self._s[752]! } + public var WallpaperPreview_SwipeColorsBottomText: String { return self._s[753]! } + public var Undo_LeftGroup: String { return self._s[756]! } + public var Wallet_RestoreFailed_Text: String { return self._s[757]! } + public var Conversation_LinkDialogCopy: String { return self._s[758]! } + public var Wallet_TransactionInfo_NoAddress: String { return self._s[760]! } + public var Wallet_Navigation_Back: String { return self._s[761]! } + public var KeyCommand_FocusOnInputField: String { return self._s[762]! } + public var Contacts_SelectAll: String { return self._s[763]! } + public var Preview_SaveToCameraRoll: String { return self._s[764]! } + public var PrivacySettings_PasscodeOff: String { return self._s[765]! } + public var Appearance_ThemePreview_ChatList_6_Name: String { return self._s[766]! } + public func PUSH_CHANNEL_MESSAGE_QUIZ(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[767]!, self._r[767]!, [_1]) + } + public var Wallpaper_Title: String { return self._s[768]! } + public var Conversation_FilePhotoOrVideo: String { return self._s[769]! } + public var AccessDenied_Camera: String { return self._s[770]! } + public var Watch_Compose_CurrentLocation: String { return self._s[771]! } + public var Channel_DiscussionGroup_MakeHistoryPublicProceed: String { return self._s[773]! } public func SecretImage_NotViewedYet(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[772]!, self._r[772]!, [_0]) + return formatWithArgumentRanges(self._s[774]!, self._r[774]!, [_0]) } - public var GroupInfo_InvitationLinkDoesNotExist: String { return self._s[773]! } - public var Passport_Language_ro: String { return self._s[774]! } - public var EditTheme_UploadNewTheme: String { return self._s[775]! } - public var CheckoutInfo_SaveInfoHelp: String { return self._s[776]! } - public var Wallet_Intro_Terms: String { return self._s[777]! } + public var GroupInfo_InvitationLinkDoesNotExist: String { return self._s[775]! } + public var Passport_Language_ro: String { return self._s[776]! } + public var EditTheme_UploadNewTheme: String { return self._s[777]! } + public var CheckoutInfo_SaveInfoHelp: String { return self._s[778]! } + public var Wallet_Intro_Terms: String { return self._s[779]! } public func Notification_SecretChatMessageScreenshot(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[778]!, self._r[778]!, [_0]) + return formatWithArgumentRanges(self._s[780]!, self._r[780]!, [_0]) } - public var Login_CancelPhoneVerification: String { return self._s[779]! } - public var State_ConnectingToProxy: String { return self._s[780]! } - public var Calls_RatingTitle: String { return self._s[781]! } - public var Generic_ErrorMoreInfo: String { return self._s[782]! } - public var ChatList_Search_ShowMore: String { return self._s[783]! } - public var Appearance_PreviewReplyText: String { return self._s[784]! } - public var CheckoutInfo_ShippingInfoPostcodePlaceholder: String { return self._s[785]! } + public var Login_CancelPhoneVerification: String { return self._s[781]! } + public var State_ConnectingToProxy: String { return self._s[782]! } + public var Calls_RatingTitle: String { return self._s[783]! } + public var Generic_ErrorMoreInfo: String { return self._s[784]! } + public var ChatList_Search_ShowMore: String { return self._s[785]! } + public var Appearance_PreviewReplyText: String { return self._s[786]! } + public var CheckoutInfo_ShippingInfoPostcodePlaceholder: String { return self._s[787]! } public func Wallet_Send_Balance(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[786]!, self._r[786]!, [_0]) + return formatWithArgumentRanges(self._s[788]!, self._r[788]!, [_0]) } - public var IntentsSettings_SuggestedChatsContacts: String { return self._s[787]! } - public var SharedMedia_CategoryLinks: String { return self._s[788]! } - public var Calls_Missed: String { return self._s[789]! } - public var Cache_Photos: String { return self._s[793]! } - public var GroupPermission_NoAddMembers: String { return self._s[794]! } - public var ScheduledMessages_Title: String { return self._s[795]! } + public var IntentsSettings_SuggestedChatsContacts: String { return self._s[789]! } + public var SharedMedia_CategoryLinks: String { return self._s[790]! } + public var Calls_Missed: String { return self._s[791]! } + public var Cache_Photos: String { return self._s[795]! } + public var GroupPermission_NoAddMembers: String { return self._s[796]! } + public var ScheduledMessages_Title: String { return self._s[797]! } public func Channel_AdminLog_MessageUnpinned(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[796]!, self._r[796]!, [_0]) + return formatWithArgumentRanges(self._s[798]!, self._r[798]!, [_0]) } - public var Conversation_ShareBotLocationConfirmationTitle: String { return self._s[797]! } - public var Settings_ProxyDisabled: String { return self._s[798]! } + public var Conversation_ShareBotLocationConfirmationTitle: String { return self._s[799]! } + public var Settings_ProxyDisabled: String { return self._s[800]! } public func Settings_ApplyProxyAlertCredentials(_ _1: String, _ _2: String, _ _3: String, _ _4: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[799]!, self._r[799]!, [_1, _2, _3, _4]) + return formatWithArgumentRanges(self._s[801]!, self._r[801]!, [_1, _2, _3, _4]) } public func Conversation_RestrictedMediaTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[800]!, self._r[800]!, [_0]) + return formatWithArgumentRanges(self._s[802]!, self._r[802]!, [_0]) } - public var ChatList_Context_RemoveFromRecents: String { return self._s[802]! } - public var Appearance_Title: String { return self._s[803]! } + public var ChatList_Context_RemoveFromRecents: String { return self._s[804]! } + public var Appearance_Title: String { return self._s[805]! } public func Time_MonthOfYear_m2(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[805]!, self._r[805]!, [_0]) + return formatWithArgumentRanges(self._s[807]!, self._r[807]!, [_0]) } - public var Conversation_WalletRequiredText: String { return self._s[806]! } - public var StickerPacksSettings_ShowStickersButtonHelp: String { return self._s[807]! } - public var OldChannels_NoticeCreateText: String { return self._s[808]! } - public var Channel_EditMessageErrorGeneric: String { return self._s[809]! } - public var Privacy_Calls_IntegrationHelp: String { return self._s[810]! } - public var Preview_DeletePhoto: String { return self._s[811]! } - public var Appearance_AppIconFilledX: String { return self._s[812]! } - public var PrivacySettings_PrivacyTitle: String { return self._s[813]! } + public var Conversation_WalletRequiredText: String { return self._s[808]! } + public var StickerPacksSettings_ShowStickersButtonHelp: String { return self._s[809]! } + public var OldChannels_NoticeCreateText: String { return self._s[810]! } + public var Channel_EditMessageErrorGeneric: String { return self._s[811]! } + public var Privacy_Calls_IntegrationHelp: String { return self._s[812]! } + public var Preview_DeletePhoto: String { return self._s[813]! } + public var Appearance_AppIconFilledX: String { return self._s[814]! } + public var PrivacySettings_PrivacyTitle: String { return self._s[815]! } public func Conversation_BotInteractiveUrlAlert(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[814]!, self._r[814]!, [_0]) + return formatWithArgumentRanges(self._s[816]!, self._r[816]!, [_0]) } - public var Coub_TapForSound: String { return self._s[817]! } - public var Map_LocatingError: String { return self._s[818]! } - public var TwoStepAuth_EmailChangeSuccess: String { return self._s[820]! } - public var Conversation_SendMessage_SendSilently: String { return self._s[821]! } - public var VoiceOver_MessageContextOpenMessageMenu: String { return self._s[822]! } + public var Coub_TapForSound: String { return self._s[819]! } + public var Map_LocatingError: String { return self._s[820]! } + public var TwoStepAuth_EmailChangeSuccess: String { return self._s[822]! } + public var Conversation_SendMessage_SendSilently: String { return self._s[823]! } + public var VoiceOver_MessageContextOpenMessageMenu: String { return self._s[824]! } public func Wallet_Time_PreciseDate_m8(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[823]!, self._r[823]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[825]!, self._r[825]!, [_1, _2, _3]) } - public var Passport_ForgottenPassword: String { return self._s[824]! } - public var GroupInfo_InviteLink_RevokeLink: String { return self._s[825]! } - public var StickerPacksSettings_ArchivedPacks: String { return self._s[826]! } - public var Login_TermsOfServiceSignupDecline: String { return self._s[828]! } - public var Channel_Moderator_AccessLevelRevoke: String { return self._s[829]! } - public var Message_Location: String { return self._s[830]! } - public var Passport_Identity_NamePlaceholder: String { return self._s[831]! } - public var Channel_Management_Title: String { return self._s[832]! } - public var DialogList_SearchSectionDialogs: String { return self._s[834]! } - public var Compose_NewChannel_Members: String { return self._s[835]! } + public var Passport_ForgottenPassword: String { return self._s[826]! } + public var GroupInfo_InviteLink_RevokeLink: String { return self._s[827]! } + public var StickerPacksSettings_ArchivedPacks: String { return self._s[828]! } + public var Login_TermsOfServiceSignupDecline: String { return self._s[830]! } + public var Channel_Moderator_AccessLevelRevoke: String { return self._s[831]! } + public var Message_Location: String { return self._s[832]! } + public var Passport_Identity_NamePlaceholder: String { return self._s[833]! } + public var Channel_Management_Title: String { return self._s[834]! } + public var DialogList_SearchSectionDialogs: String { return self._s[836]! } + public var Compose_NewChannel_Members: String { return self._s[837]! } public func DialogList_SingleUploadingFileSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[836]!, self._r[836]!, [_0]) + return formatWithArgumentRanges(self._s[838]!, self._r[838]!, [_0]) } - public var GroupInfo_Location: String { return self._s[837]! } - public var Appearance_ThemePreview_ChatList_5_Name: String { return self._s[838]! } - public var ClearCache_Clear: String { return self._s[839]! } - public var AutoNightTheme_ScheduledFrom: String { return self._s[840]! } - public var PhotoEditor_WarmthTool: String { return self._s[841]! } - public var Passport_Language_tr: String { return self._s[842]! } + public var GroupInfo_Location: String { return self._s[839]! } + public var Appearance_ThemePreview_ChatList_5_Name: String { return self._s[840]! } + public var ClearCache_Clear: String { return self._s[841]! } + public var AutoNightTheme_ScheduledFrom: String { return self._s[842]! } + public var PhotoEditor_WarmthTool: String { return self._s[843]! } + public var Passport_Language_tr: String { return self._s[844]! } public func PUSH_MESSAGE_GAME_SCORE(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[843]!, self._r[843]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[845]!, self._r[845]!, [_1, _2, _3]) } - public var OldChannels_NoticeUpgradeText: String { return self._s[844]! } - public var Login_ResetAccountProtected_Reset: String { return self._s[846]! } - public var Watch_PhotoView_Title: String { return self._s[847]! } - public var Passport_Phone_Delete: String { return self._s[848]! } - public var Undo_ChatDeletedForBothSides: String { return self._s[849]! } - public var Conversation_EditingMessageMediaEditCurrentPhoto: String { return self._s[850]! } - public var GroupInfo_Permissions: String { return self._s[851]! } - public var PasscodeSettings_TurnPasscodeOff: String { return self._s[852]! } - public var Profile_ShareContactButton: String { return self._s[853]! } - public var ChatSettings_Other: String { return self._s[854]! } - public var UserInfo_NotificationsDisabled: String { return self._s[855]! } - public var CheckoutInfo_ShippingInfoCity: String { return self._s[856]! } - public var LastSeen_WithinAMonth: String { return self._s[857]! } - public var VoiceOver_Chat_PlayHint: String { return self._s[858]! } - public var Conversation_ReportGroupLocation: String { return self._s[859]! } - public var Conversation_EncryptionCanceled: String { return self._s[860]! } - public var MediaPicker_GroupDescription: String { return self._s[861]! } - public var WebSearch_Images: String { return self._s[862]! } + public var OldChannels_NoticeUpgradeText: String { return self._s[846]! } + public var Login_ResetAccountProtected_Reset: String { return self._s[848]! } + public var Watch_PhotoView_Title: String { return self._s[849]! } + public var Passport_Phone_Delete: String { return self._s[850]! } + public var Undo_ChatDeletedForBothSides: String { return self._s[851]! } + public var Conversation_EditingMessageMediaEditCurrentPhoto: String { return self._s[852]! } + public var GroupInfo_Permissions: String { return self._s[853]! } + public var PasscodeSettings_TurnPasscodeOff: String { return self._s[854]! } + public var Profile_ShareContactButton: String { return self._s[855]! } + public var ChatSettings_Other: String { return self._s[856]! } + public var UserInfo_NotificationsDisabled: String { return self._s[857]! } + public var CheckoutInfo_ShippingInfoCity: String { return self._s[858]! } + public var LastSeen_WithinAMonth: String { return self._s[859]! } + public var VoiceOver_Chat_PlayHint: String { return self._s[860]! } + public var Conversation_ReportGroupLocation: String { return self._s[861]! } + public var Conversation_EncryptionCanceled: String { return self._s[862]! } + public var MediaPicker_GroupDescription: String { return self._s[863]! } + public var WebSearch_Images: String { return self._s[864]! } public func Channel_Management_PromotedBy(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[863]!, self._r[863]!, [_0]) + return formatWithArgumentRanges(self._s[865]!, self._r[865]!, [_0]) } - public var Message_Photo: String { return self._s[864]! } - public var PasscodeSettings_HelpBottom: String { return self._s[865]! } - public var AutoDownloadSettings_VideosTitle: String { return self._s[866]! } - public var VoiceOver_Media_PlaybackRateChange: String { return self._s[867]! } - public var Passport_Identity_AddDriversLicense: String { return self._s[868]! } - public var TwoStepAuth_EnterPasswordPassword: String { return self._s[869]! } - public var NotificationsSound_Calypso: String { return self._s[870]! } - public var Map_Map: String { return self._s[871]! } - public var CheckoutInfo_ReceiverInfoTitle: String { return self._s[873]! } - public var ChatSettings_TextSizeUnits: String { return self._s[874]! } + public var Message_Photo: String { return self._s[866]! } + public var PasscodeSettings_HelpBottom: String { return self._s[867]! } + public var AutoDownloadSettings_VideosTitle: String { return self._s[868]! } + public var VoiceOver_Media_PlaybackRateChange: String { return self._s[869]! } + public var Passport_Identity_AddDriversLicense: String { return self._s[870]! } + public var TwoStepAuth_EnterPasswordPassword: String { return self._s[871]! } + public var NotificationsSound_Calypso: String { return self._s[872]! } + public var Map_Map: String { return self._s[873]! } + public var CheckoutInfo_ReceiverInfoTitle: String { return self._s[875]! } + public var ChatSettings_TextSizeUnits: String { return self._s[876]! } public func VoiceOver_Chat_FileFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[875]!, self._r[875]!, [_0]) + return formatWithArgumentRanges(self._s[877]!, self._r[877]!, [_0]) } - public var Common_of: String { return self._s[876]! } - public var Conversation_ForwardContacts: String { return self._s[879]! } - public var IntentsSettings_SuggestByAll: String { return self._s[881]! } + public var Common_of: String { return self._s[878]! } + public var Conversation_ForwardContacts: String { return self._s[881]! } + public var IntentsSettings_SuggestByAll: String { return self._s[883]! } public func Call_AnsweringWithAccount(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[882]!, self._r[882]!, [_0]) + return formatWithArgumentRanges(self._s[884]!, self._r[884]!, [_0]) } - public var Passport_Language_hy: String { return self._s[883]! } - public var Notifications_MessageNotificationsHelp: String { return self._s[884]! } - public var AutoDownloadSettings_Reset: String { return self._s[885]! } - public var Wallet_TransactionInfo_AddressCopied: String { return self._s[886]! } - public var Paint_ClearConfirm: String { return self._s[887]! } - public var Camera_VideoMode: String { return self._s[888]! } + public var Passport_Language_hy: String { return self._s[885]! } + public var Notifications_MessageNotificationsHelp: String { return self._s[886]! } + public var AutoDownloadSettings_Reset: String { return self._s[887]! } + public var Wallet_TransactionInfo_AddressCopied: String { return self._s[888]! } + public var Paint_ClearConfirm: String { return self._s[889]! } + public var Camera_VideoMode: String { return self._s[890]! } public func Conversation_RestrictedStickersTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[889]!, self._r[889]!, [_0]) + return formatWithArgumentRanges(self._s[891]!, self._r[891]!, [_0]) } - public var Privacy_Calls_AlwaysAllow_Placeholder: String { return self._s[890]! } - public var Conversation_ViewBackground: String { return self._s[891]! } + public var Privacy_Calls_AlwaysAllow_Placeholder: String { return self._s[892]! } + public var Conversation_ViewBackground: String { return self._s[893]! } public func Wallet_Info_TransactionDateHeaderYear(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[892]!, self._r[892]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[894]!, self._r[894]!, [_1, _2, _3]) } - public var Passport_Language_el: String { return self._s[893]! } - public var PhotoEditor_Original: String { return self._s[894]! } - public var Settings_FAQ_Button: String { return self._s[896]! } - public var Channel_Setup_PublicNoLink: String { return self._s[898]! } - public var Conversation_UnsupportedMedia: String { return self._s[899]! } - public var Conversation_SlideToCancel: String { return self._s[900]! } - public var Appearance_ThemePreview_ChatList_4_Name: String { return self._s[901]! } - public var Passport_Identity_OneOfTypeInternalPassport: String { return self._s[902]! } - public var CheckoutInfo_ShippingInfoPostcode: String { return self._s[903]! } - public var Conversation_ReportSpamChannelConfirmation: String { return self._s[904]! } - public var AutoNightTheme_NotAvailable: String { return self._s[905]! } - public var Conversation_Owner: String { return self._s[906]! } - public var Common_Create: String { return self._s[907]! } - public var Settings_ApplyProxyAlertEnable: String { return self._s[908]! } - public var ContactList_Context_Call: String { return self._s[909]! } - public var Localization_ChooseLanguage: String { return self._s[911]! } - public var ChatList_Context_AddToContacts: String { return self._s[913]! } - public var OldChannels_NoticeTitle: String { return self._s[914]! } - public var Settings_Proxy: String { return self._s[916]! } - public var Privacy_TopPeersHelp: String { return self._s[917]! } - public var CheckoutInfo_ShippingInfoCountryPlaceholder: String { return self._s[918]! } - public var Chat_UnsendMyMessages: String { return self._s[919]! } + public var Passport_Language_el: String { return self._s[895]! } + public var PhotoEditor_Original: String { return self._s[896]! } + public var Settings_FAQ_Button: String { return self._s[898]! } + public var Channel_Setup_PublicNoLink: String { return self._s[900]! } + public var Conversation_UnsupportedMedia: String { return self._s[901]! } + public var Conversation_SlideToCancel: String { return self._s[902]! } + public var Appearance_ThemePreview_ChatList_4_Name: String { return self._s[903]! } + public var Passport_Identity_OneOfTypeInternalPassport: String { return self._s[904]! } + public var CheckoutInfo_ShippingInfoPostcode: String { return self._s[905]! } + public var Conversation_ReportSpamChannelConfirmation: String { return self._s[906]! } + public var AutoNightTheme_NotAvailable: String { return self._s[907]! } + public var Conversation_Owner: String { return self._s[908]! } + public var Common_Create: String { return self._s[909]! } + public var Settings_ApplyProxyAlertEnable: String { return self._s[910]! } + public var ContactList_Context_Call: String { return self._s[911]! } + public var Localization_ChooseLanguage: String { return self._s[913]! } + public var ChatList_Context_AddToContacts: String { return self._s[915]! } + public var OldChannels_NoticeTitle: String { return self._s[916]! } + public var Settings_Proxy: String { return self._s[918]! } + public var Privacy_TopPeersHelp: String { return self._s[919]! } + public var CheckoutInfo_ShippingInfoCountryPlaceholder: String { return self._s[920]! } + public var Chat_UnsendMyMessages: String { return self._s[921]! } public func VoiceOver_Chat_Duration(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[920]!, self._r[920]!, [_0]) + return formatWithArgumentRanges(self._s[922]!, self._r[922]!, [_0]) } - public var TwoStepAuth_ConfirmationAbort: String { return self._s[921]! } + public var TwoStepAuth_ConfirmationAbort: String { return self._s[923]! } public func Contacts_AccessDeniedHelpPortrait(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[923]!, self._r[923]!, [_0]) + return formatWithArgumentRanges(self._s[925]!, self._r[925]!, [_0]) } - public var Contacts_SortedByPresence: String { return self._s[924]! } - public var Passport_Identity_SurnamePlaceholder: String { return self._s[925]! } - public var Cache_Title: String { return self._s[926]! } + public var Contacts_SortedByPresence: String { return self._s[926]! } + public var Passport_Identity_SurnamePlaceholder: String { return self._s[927]! } + public var Cache_Title: String { return self._s[928]! } public func Login_PhoneBannedEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[927]!, self._r[927]!, [_0]) + return formatWithArgumentRanges(self._s[929]!, self._r[929]!, [_0]) } - public var TwoStepAuth_EmailCodeExpired: String { return self._s[928]! } - public var Channel_Moderator_Title: String { return self._s[929]! } - public var InstantPage_AutoNightTheme: String { return self._s[931]! } + public var TwoStepAuth_EmailCodeExpired: String { return self._s[930]! } + public var Channel_Moderator_Title: String { return self._s[931]! } + public var InstantPage_AutoNightTheme: String { return self._s[933]! } public func PUSH_MESSAGE_POLL(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[934]!, self._r[934]!, [_1]) + return formatWithArgumentRanges(self._s[936]!, self._r[936]!, [_1]) } - public var Passport_Scans_Upload: String { return self._s[935]! } - public var Undo_Undo: String { return self._s[937]! } - public var Contacts_AccessDeniedHelpON: String { return self._s[938]! } - public var TwoStepAuth_RemovePassword: String { return self._s[939]! } - public var Common_Delete: String { return self._s[940]! } - public var Contacts_AddPeopleNearby: String { return self._s[942]! } - public var Conversation_ContextMenuDelete: String { return self._s[943]! } - public var SocksProxySetup_Credentials: String { return self._s[944]! } - public var Appearance_EditTheme: String { return self._s[946]! } - public var ClearCache_StorageOtherApps: String { return self._s[947]! } - public var PasscodeSettings_AutoLock_Disabled: String { return self._s[948]! } - public var Wallet_Send_NetworkErrorText: String { return self._s[949]! } - public var AuthSessions_DevicesTitle: String { return self._s[951]! } - public var Passport_Address_OneOfTypeRentalAgreement: String { return self._s[953]! } - public var Conversation_ShareBotContactConfirmationTitle: String { return self._s[954]! } - public var Passport_Language_id: String { return self._s[956]! } - public var WallpaperSearch_ColorTeal: String { return self._s[957]! } - public var ChannelIntro_Title: String { return self._s[958]! } + public var Passport_Scans_Upload: String { return self._s[937]! } + public var Undo_Undo: String { return self._s[939]! } + public var Contacts_AccessDeniedHelpON: String { return self._s[940]! } + public var TwoStepAuth_RemovePassword: String { return self._s[941]! } + public var Common_Delete: String { return self._s[942]! } + public var Contacts_AddPeopleNearby: String { return self._s[944]! } + public var Conversation_ContextMenuDelete: String { return self._s[945]! } + public var SocksProxySetup_Credentials: String { return self._s[946]! } + public var Appearance_EditTheme: String { return self._s[948]! } + public var ClearCache_StorageOtherApps: String { return self._s[949]! } + public var PasscodeSettings_AutoLock_Disabled: String { return self._s[950]! } + public var Wallet_Send_NetworkErrorText: String { return self._s[951]! } + public var AuthSessions_DevicesTitle: String { return self._s[953]! } + public var Passport_Address_OneOfTypeRentalAgreement: String { return self._s[955]! } + public var Conversation_ShareBotContactConfirmationTitle: String { return self._s[956]! } + public var Passport_Language_id: String { return self._s[958]! } + public var WallpaperSearch_ColorTeal: String { return self._s[959]! } + public var ChannelIntro_Title: String { return self._s[960]! } public func Channel_AdminLog_MessageToggleSignaturesOff(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[959]!, self._r[959]!, [_0]) + return formatWithArgumentRanges(self._s[961]!, self._r[961]!, [_0]) } - public var VoiceOver_Chat_OpenLinkHint: String { return self._s[961]! } - public var VoiceOver_Chat_Reply: String { return self._s[962]! } - public var ScheduledMessages_BotActionUnavailable: String { return self._s[963]! } - public var Channel_Info_Description: String { return self._s[964]! } - public var Stickers_FavoriteStickers: String { return self._s[965]! } - public var Channel_BanUser_PermissionAddMembers: String { return self._s[966]! } - public var Notifications_DisplayNamesOnLockScreen: String { return self._s[967]! } - public var ChatSearch_ResultsTooltip: String { return self._s[968]! } - public var Wallet_VoiceOver_Editing_ClearText: String { return self._s[969]! } - public var Calls_NoMissedCallsPlacehoder: String { return self._s[970]! } - public var Group_PublicLink_Placeholder: String { return self._s[971]! } - public var Notifications_ExceptionsDefaultSound: String { return self._s[972]! } + public var VoiceOver_Chat_OpenLinkHint: String { return self._s[963]! } + public var VoiceOver_Chat_Reply: String { return self._s[964]! } + public var ScheduledMessages_BotActionUnavailable: String { return self._s[965]! } + public var Channel_Info_Description: String { return self._s[966]! } + public var Stickers_FavoriteStickers: String { return self._s[967]! } + public var Channel_BanUser_PermissionAddMembers: String { return self._s[968]! } + public var Notifications_DisplayNamesOnLockScreen: String { return self._s[969]! } + public var ChatSearch_ResultsTooltip: String { return self._s[970]! } + public var Wallet_VoiceOver_Editing_ClearText: String { return self._s[971]! } + public var Calls_NoMissedCallsPlacehoder: String { return self._s[972]! } + public var Group_PublicLink_Placeholder: String { return self._s[973]! } + public var Notifications_ExceptionsDefaultSound: String { return self._s[974]! } public func PUSH_CHANNEL_MESSAGE_POLL(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[973]!, self._r[973]!, [_1]) + return formatWithArgumentRanges(self._s[975]!, self._r[975]!, [_1]) } - public var TextFormat_Underline: String { return self._s[974]! } + public var TextFormat_Underline: String { return self._s[976]! } public func DialogList_SearchSubtitleFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[976]!, self._r[976]!, [_1, _2]) + return formatWithArgumentRanges(self._s[978]!, self._r[978]!, [_1, _2]) } public func Channel_AdminLog_MessageRemovedGroupStickerPack(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[977]!, self._r[977]!, [_0]) + return formatWithArgumentRanges(self._s[979]!, self._r[979]!, [_0]) } - public var Appearance_ThemePreview_ChatList_3_Name: String { return self._s[978]! } + public var Appearance_ThemePreview_ChatList_3_Name: String { return self._s[980]! } public func Channel_OwnershipTransfer_TransferCompleted(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[979]!, self._r[979]!, [_1, _2]) + return formatWithArgumentRanges(self._s[981]!, self._r[981]!, [_1, _2]) } - public var Wallet_Intro_ImportExisting: String { return self._s[980]! } - public var GroupPermission_Delete: String { return self._s[981]! } - public var Passport_Language_uk: String { return self._s[982]! } - public var StickerPack_HideStickers: String { return self._s[984]! } - public var ChangePhoneNumberNumber_NumberPlaceholder: String { return self._s[985]! } + public var Wallet_Intro_ImportExisting: String { return self._s[982]! } + public var GroupPermission_Delete: String { return self._s[983]! } + public var Passport_Language_uk: String { return self._s[984]! } + public var StickerPack_HideStickers: String { return self._s[986]! } + public var ChangePhoneNumberNumber_NumberPlaceholder: String { return self._s[987]! } public func PUSH_CHAT_MESSAGE_PHOTO(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[986]!, self._r[986]!, [_1, _2]) + return formatWithArgumentRanges(self._s[988]!, self._r[988]!, [_1, _2]) } - public var Activity_UploadingVideoMessage: String { return self._s[987]! } + public var Activity_UploadingVideoMessage: String { return self._s[989]! } public func GroupPermission_ApplyAlertText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[988]!, self._r[988]!, [_0]) + return formatWithArgumentRanges(self._s[990]!, self._r[990]!, [_0]) } - public var Channel_TitleInfo: String { return self._s[989]! } - public var StickerPacksSettings_ArchivedPacks_Info: String { return self._s[990]! } - public var Settings_CallSettings: String { return self._s[991]! } - public var Camera_SquareMode: String { return self._s[992]! } - public var Conversation_SendMessage_ScheduleMessage: String { return self._s[993]! } - public var GroupInfo_SharedMediaNone: String { return self._s[994]! } + public var Channel_TitleInfo: String { return self._s[991]! } + public var StickerPacksSettings_ArchivedPacks_Info: String { return self._s[992]! } + public var Settings_CallSettings: String { return self._s[993]! } + public var Camera_SquareMode: String { return self._s[994]! } + public var Conversation_SendMessage_ScheduleMessage: String { return self._s[995]! } + public var GroupInfo_SharedMediaNone: String { return self._s[996]! } public func PUSH_MESSAGE_VIDEO_SECRET(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[995]!, self._r[995]!, [_1]) + return formatWithArgumentRanges(self._s[997]!, self._r[997]!, [_1]) } - public var Bot_GenericBotStatus: String { return self._s[996]! } - public var Application_Update: String { return self._s[998]! } - public var Month_ShortJanuary: String { return self._s[999]! } - public var Contacts_PermissionsKeepDisabled: String { return self._s[1000]! } - public var Channel_AdminLog_BanReadMessages: String { return self._s[1001]! } - public var Settings_AppLanguage_Unofficial: String { return self._s[1002]! } - public var Passport_Address_Street2Placeholder: String { return self._s[1003]! } + public var Bot_GenericBotStatus: String { return self._s[998]! } + public var Application_Update: String { return self._s[1000]! } + public var Month_ShortJanuary: String { return self._s[1001]! } + public var Contacts_PermissionsKeepDisabled: String { return self._s[1002]! } + public var Channel_AdminLog_BanReadMessages: String { return self._s[1003]! } + public var Settings_AppLanguage_Unofficial: String { return self._s[1004]! } + public var Passport_Address_Street2Placeholder: String { return self._s[1005]! } public func Map_LiveLocationShortHour(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1004]!, self._r[1004]!, [_0]) + return formatWithArgumentRanges(self._s[1006]!, self._r[1006]!, [_0]) } - public var NetworkUsageSettings_Cellular: String { return self._s[1005]! } - public var Appearance_PreviewOutgoingText: String { return self._s[1006]! } + public var NetworkUsageSettings_Cellular: String { return self._s[1007]! } + public var Appearance_PreviewOutgoingText: String { return self._s[1008]! } public func StickerPackActionInfo_RemovedText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1007]!, self._r[1007]!, [_0]) + return formatWithArgumentRanges(self._s[1009]!, self._r[1009]!, [_0]) } - public var Notifications_PermissionsAllowInSettings: String { return self._s[1008]! } - public var AutoDownloadSettings_OnForAll: String { return self._s[1010]! } - public var Map_Directions: String { return self._s[1011]! } - public var Passport_FieldIdentityTranslationHelp: String { return self._s[1013]! } - public var Appearance_ThemeDay: String { return self._s[1014]! } - public var LogoutOptions_LogOut: String { return self._s[1015]! } - public var Group_PublicLink_Title: String { return self._s[1017]! } - public var Channel_AddBotErrorNoRights: String { return self._s[1018]! } - public var ChatList_Search_ShowLess: String { return self._s[1019]! } - public var Passport_Identity_AddPassport: String { return self._s[1020]! } - public var LocalGroup_ButtonTitle: String { return self._s[1021]! } - public var Call_Message: String { return self._s[1022]! } - public var PhotoEditor_ExposureTool: String { return self._s[1023]! } - public var Wallet_Receive_CommentInfo: String { return self._s[1025]! } - public var Passport_FieldOneOf_Delimeter: String { return self._s[1026]! } - public var Channel_AdminLog_CanBanUsers: String { return self._s[1028]! } - public var Appearance_ThemePreview_ChatList_2_Name: String { return self._s[1029]! } - public var Appearance_Preview: String { return self._s[1030]! } - public var Compose_ChannelMembers: String { return self._s[1031]! } - public var Conversation_DeleteManyMessages: String { return self._s[1032]! } - public var ReportPeer_ReasonOther_Title: String { return self._s[1033]! } - public var Checkout_ErrorProviderAccountTimeout: String { return self._s[1034]! } - public var TwoStepAuth_ResetAccountConfirmation: String { return self._s[1035]! } - public var Channel_Stickers_CreateYourOwn: String { return self._s[1038]! } - public var Conversation_UpdateTelegram: String { return self._s[1039]! } - public var EditTheme_Create_TopInfo: String { return self._s[1040]! } + public var Notifications_PermissionsAllowInSettings: String { return self._s[1010]! } + public var AutoDownloadSettings_OnForAll: String { return self._s[1012]! } + public var Map_Directions: String { return self._s[1013]! } + public var Passport_FieldIdentityTranslationHelp: String { return self._s[1015]! } + public var Appearance_ThemeDay: String { return self._s[1016]! } + public var LogoutOptions_LogOut: String { return self._s[1017]! } + public var Group_PublicLink_Title: String { return self._s[1019]! } + public var Channel_AddBotErrorNoRights: String { return self._s[1020]! } + public var ChatList_Search_ShowLess: String { return self._s[1021]! } + public var Passport_Identity_AddPassport: String { return self._s[1022]! } + public var LocalGroup_ButtonTitle: String { return self._s[1023]! } + public var Call_Message: String { return self._s[1024]! } + public var PhotoEditor_ExposureTool: String { return self._s[1025]! } + public var Wallet_Receive_CommentInfo: String { return self._s[1027]! } + public var Passport_FieldOneOf_Delimeter: String { return self._s[1028]! } + public var Channel_AdminLog_CanBanUsers: String { return self._s[1030]! } + public var Appearance_ThemePreview_ChatList_2_Name: String { return self._s[1031]! } + public var Appearance_Preview: String { return self._s[1032]! } + public var Compose_ChannelMembers: String { return self._s[1033]! } + public var Conversation_DeleteManyMessages: String { return self._s[1034]! } + public var ReportPeer_ReasonOther_Title: String { return self._s[1035]! } + public var Checkout_ErrorProviderAccountTimeout: String { return self._s[1036]! } + public var TwoStepAuth_ResetAccountConfirmation: String { return self._s[1037]! } + public var Channel_Stickers_CreateYourOwn: String { return self._s[1040]! } + public var Conversation_UpdateTelegram: String { return self._s[1041]! } + public var EditTheme_Create_TopInfo: String { return self._s[1042]! } public func Notification_PinnedPhotoMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1041]!, self._r[1041]!, [_0]) + return formatWithArgumentRanges(self._s[1043]!, self._r[1043]!, [_0]) } - public var Wallet_WordCheck_Continue: String { return self._s[1042]! } - public var TwoFactorSetup_Hint_Action: String { return self._s[1043]! } - public var IntentsSettings_ResetAll: String { return self._s[1044]! } + public var Wallet_WordCheck_Continue: String { return self._s[1044]! } + public var TwoFactorSetup_Hint_Action: String { return self._s[1045]! } + public var IntentsSettings_ResetAll: String { return self._s[1046]! } public func PUSH_PINNED_GIF(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1045]!, self._r[1045]!, [_1]) + return formatWithArgumentRanges(self._s[1047]!, self._r[1047]!, [_1]) } - public var GroupInfo_Administrators_Title: String { return self._s[1046]! } - public var Privacy_Forwards_PreviewMessageText: String { return self._s[1047]! } + public var GroupInfo_Administrators_Title: String { return self._s[1048]! } + public var Privacy_Forwards_PreviewMessageText: String { return self._s[1049]! } public func PrivacySettings_LastSeenNobodyPlus(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1048]!, self._r[1048]!, [_0]) + return formatWithArgumentRanges(self._s[1050]!, self._r[1050]!, [_0]) } - public var Tour_Title3: String { return self._s[1049]! } - public var Channel_EditAdmin_PermissionInviteSubscribers: String { return self._s[1050]! } - public var Clipboard_SendPhoto: String { return self._s[1054]! } - public var MediaPicker_Videos: String { return self._s[1055]! } - public var Passport_Email_Title: String { return self._s[1056]! } + public var Tour_Title3: String { return self._s[1051]! } + public var Channel_EditAdmin_PermissionInviteSubscribers: String { return self._s[1052]! } + public var Clipboard_SendPhoto: String { return self._s[1056]! } + public var MediaPicker_Videos: String { return self._s[1057]! } + public var Passport_Email_Title: String { return self._s[1058]! } public func PrivacySettings_LastSeenEverybodyMinus(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1057]!, self._r[1057]!, [_0]) + return formatWithArgumentRanges(self._s[1059]!, self._r[1059]!, [_0]) } - public var StickerPacksSettings_Title: String { return self._s[1058]! } - public var Conversation_MessageDialogDelete: String { return self._s[1059]! } - public var Privacy_Calls_CustomHelp: String { return self._s[1061]! } - public var Message_Wallpaper: String { return self._s[1062]! } - public var MemberSearch_BotSection: String { return self._s[1063]! } - public var GroupInfo_SetSound: String { return self._s[1064]! } - public var Core_ServiceUserStatus: String { return self._s[1065]! } - public var LiveLocationUpdated_JustNow: String { return self._s[1066]! } - public var Call_StatusFailed: String { return self._s[1067]! } - public var TwoFactorSetup_Email_Placeholder: String { return self._s[1068]! } - public var TwoStepAuth_SetupPasswordDescription: String { return self._s[1069]! } - public var TwoStepAuth_SetPassword: String { return self._s[1070]! } - public var Permissions_PeopleNearbyText_v0: String { return self._s[1071]! } + public var StickerPacksSettings_Title: String { return self._s[1060]! } + public var Conversation_MessageDialogDelete: String { return self._s[1061]! } + public var Privacy_Calls_CustomHelp: String { return self._s[1063]! } + public var Message_Wallpaper: String { return self._s[1064]! } + public var MemberSearch_BotSection: String { return self._s[1065]! } + public var GroupInfo_SetSound: String { return self._s[1066]! } + public var Core_ServiceUserStatus: String { return self._s[1067]! } + public var LiveLocationUpdated_JustNow: String { return self._s[1068]! } + public var Call_StatusFailed: String { return self._s[1069]! } + public var TwoFactorSetup_Email_Placeholder: String { return self._s[1070]! } + public var TwoStepAuth_SetupPasswordDescription: String { return self._s[1071]! } + public var TwoStepAuth_SetPassword: String { return self._s[1072]! } + public var Permissions_PeopleNearbyText_v0: String { return self._s[1073]! } public func SocksProxySetup_ProxyStatusPing(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1073]!, self._r[1073]!, [_0]) + return formatWithArgumentRanges(self._s[1075]!, self._r[1075]!, [_0]) } - public var Calls_SubmitRating: String { return self._s[1074]! } - public var Map_NoPlacesNearby: String { return self._s[1075]! } - public var Profile_Username: String { return self._s[1076]! } - public var Bot_DescriptionTitle: String { return self._s[1077]! } - public var MaskStickerSettings_Title: String { return self._s[1078]! } - public var SharedMedia_CategoryOther: String { return self._s[1079]! } - public var GroupInfo_SetGroupPhoto: String { return self._s[1080]! } - public var Common_NotNow: String { return self._s[1081]! } - public var CallFeedback_IncludeLogsInfo: String { return self._s[1082]! } - public var Conversation_ShareMyPhoneNumber: String { return self._s[1083]! } - public var Map_Location: String { return self._s[1084]! } - public var Invitation_JoinGroup: String { return self._s[1085]! } - public var AutoDownloadSettings_Title: String { return self._s[1087]! } - public var Conversation_DiscardVoiceMessageDescription: String { return self._s[1088]! } - public var Channel_ErrorAddBlocked: String { return self._s[1089]! } - public var Conversation_UnblockUser: String { return self._s[1090]! } - public var EditTheme_Edit_TopInfo: String { return self._s[1091]! } - public var Watch_Bot_Restart: String { return self._s[1092]! } - public var TwoStepAuth_Title: String { return self._s[1093]! } - public var Channel_AdminLog_BanSendMessages: String { return self._s[1094]! } - public var Checkout_ShippingMethod: String { return self._s[1095]! } - public var Passport_Identity_OneOfTypeIdentityCard: String { return self._s[1096]! } + public var Calls_SubmitRating: String { return self._s[1076]! } + public var Map_NoPlacesNearby: String { return self._s[1077]! } + public var Profile_Username: String { return self._s[1078]! } + public var Bot_DescriptionTitle: String { return self._s[1079]! } + public var MaskStickerSettings_Title: String { return self._s[1080]! } + public var SharedMedia_CategoryOther: String { return self._s[1081]! } + public var GroupInfo_SetGroupPhoto: String { return self._s[1082]! } + public var Common_NotNow: String { return self._s[1083]! } + public var CallFeedback_IncludeLogsInfo: String { return self._s[1084]! } + public var Conversation_ShareMyPhoneNumber: String { return self._s[1085]! } + public var Map_Location: String { return self._s[1086]! } + public var Invitation_JoinGroup: String { return self._s[1087]! } + public var AutoDownloadSettings_Title: String { return self._s[1089]! } + public var Conversation_DiscardVoiceMessageDescription: String { return self._s[1090]! } + public var Channel_ErrorAddBlocked: String { return self._s[1091]! } + public var Conversation_UnblockUser: String { return self._s[1092]! } + public var EditTheme_Edit_TopInfo: String { return self._s[1093]! } + public var Watch_Bot_Restart: String { return self._s[1094]! } + public var TwoStepAuth_Title: String { return self._s[1095]! } + public var Channel_AdminLog_BanSendMessages: String { return self._s[1096]! } + public var Checkout_ShippingMethod: String { return self._s[1097]! } + public var Passport_Identity_OneOfTypeIdentityCard: String { return self._s[1098]! } public func PUSH_CHAT_MESSAGE_STICKER(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1097]!, self._r[1097]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1099]!, self._r[1099]!, [_1, _2, _3]) } - public var EditTheme_ChangeColors: String { return self._s[1099]! } + public var EditTheme_ChangeColors: String { return self._s[1101]! } public func Chat_UnsendMyMessagesAlertTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1100]!, self._r[1100]!, [_0]) + return formatWithArgumentRanges(self._s[1102]!, self._r[1102]!, [_0]) } public func Channel_Username_LinkHint(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1101]!, self._r[1101]!, [_0]) + return formatWithArgumentRanges(self._s[1103]!, self._r[1103]!, [_0]) } - public var Appearance_ThemePreview_ChatList_1_Name: String { return self._s[1102]! } - public var SettingsSearch_Synonyms_Data_AutoplayGifs: String { return self._s[1103]! } - public var AuthSessions_TerminateOtherSessions: String { return self._s[1104]! } - public var Contacts_FailedToSendInvitesMessage: String { return self._s[1105]! } - public var PrivacySettings_TwoStepAuth: String { return self._s[1106]! } - public var Notification_Exceptions_PreviewAlwaysOn: String { return self._s[1107]! } - public var SettingsSearch_Synonyms_Privacy_Passcode: String { return self._s[1108]! } - public var Conversation_EditingMessagePanelMedia: String { return self._s[1109]! } - public var Checkout_PaymentMethod_Title: String { return self._s[1110]! } - public var SocksProxySetup_Connection: String { return self._s[1111]! } - public var Group_MessagePhotoRemoved: String { return self._s[1112]! } - public var Channel_Stickers_NotFound: String { return self._s[1115]! } - public var Group_About_Help: String { return self._s[1116]! } - public var Notification_PassportValueProofOfIdentity: String { return self._s[1117]! } - public var PeopleNearby_Title: String { return self._s[1119]! } + public var Appearance_ThemePreview_ChatList_1_Name: String { return self._s[1104]! } + public var SettingsSearch_Synonyms_Data_AutoplayGifs: String { return self._s[1105]! } + public var AuthSessions_TerminateOtherSessions: String { return self._s[1106]! } + public var Contacts_FailedToSendInvitesMessage: String { return self._s[1107]! } + public var PrivacySettings_TwoStepAuth: String { return self._s[1108]! } + public var Notification_Exceptions_PreviewAlwaysOn: String { return self._s[1109]! } + public var SettingsSearch_Synonyms_Privacy_Passcode: String { return self._s[1110]! } + public var Conversation_EditingMessagePanelMedia: String { return self._s[1111]! } + public var Checkout_PaymentMethod_Title: String { return self._s[1112]! } + public var SocksProxySetup_Connection: String { return self._s[1113]! } + public var Group_MessagePhotoRemoved: String { return self._s[1114]! } + public var Channel_Stickers_NotFound: String { return self._s[1117]! } + public var Group_About_Help: String { return self._s[1118]! } + public var Notification_PassportValueProofOfIdentity: String { return self._s[1119]! } + public var PeopleNearby_Title: String { return self._s[1121]! } public func ApplyLanguage_ChangeLanguageOfficialText(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1120]!, self._r[1120]!, [_1]) + return formatWithArgumentRanges(self._s[1122]!, self._r[1122]!, [_1]) } - public var Map_Home: String { return self._s[1121]! } - public var CheckoutInfo_ShippingInfoStatePlaceholder: String { return self._s[1123]! } - public var Notifications_GroupNotificationsExceptionsHelp: String { return self._s[1124]! } - public var SocksProxySetup_Password: String { return self._s[1125]! } - public var Notifications_PermissionsEnable: String { return self._s[1126]! } - public var TwoStepAuth_ChangeEmail: String { return self._s[1128]! } + public var Map_Home: String { return self._s[1123]! } + public var CheckoutInfo_ShippingInfoStatePlaceholder: String { return self._s[1125]! } + public var Notifications_GroupNotificationsExceptionsHelp: String { return self._s[1126]! } + public var SocksProxySetup_Password: String { return self._s[1127]! } + public var Notifications_PermissionsEnable: String { return self._s[1128]! } + public var TwoStepAuth_ChangeEmail: String { return self._s[1130]! } public func Channel_AdminLog_MessageInvitedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1129]!, self._r[1129]!, [_1]) + return formatWithArgumentRanges(self._s[1131]!, self._r[1131]!, [_1]) } public func Time_MonthOfYear_m10(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1131]!, self._r[1131]!, [_0]) + return formatWithArgumentRanges(self._s[1133]!, self._r[1133]!, [_0]) } - public var Passport_Identity_TypeDriversLicense: String { return self._s[1132]! } - public var ArchivedPacksAlert_Title: String { return self._s[1133]! } - public var Wallet_Receive_InvoiceUrlCopied: String { return self._s[1134]! } - public var Map_PlacesNearby: String { return self._s[1135]! } + public var Passport_Identity_TypeDriversLicense: String { return self._s[1134]! } + public var ArchivedPacksAlert_Title: String { return self._s[1135]! } + public var Wallet_Receive_InvoiceUrlCopied: String { return self._s[1136]! } + public var Map_PlacesNearby: String { return self._s[1137]! } public func Time_PreciseDate_m7(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1136]!, self._r[1136]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1138]!, self._r[1138]!, [_1, _2, _3]) } - public var PrivacyLastSeenSettings_GroupsAndChannelsHelp: String { return self._s[1137]! } - public var Privacy_Calls_NeverAllow_Placeholder: String { return self._s[1139]! } - public var Conversation_StatusTyping: String { return self._s[1140]! } - public var Broadcast_AdminLog_EmptyText: String { return self._s[1141]! } - public var Notification_PassportValueProofOfAddress: String { return self._s[1142]! } - public var UserInfo_CreateNewContact: String { return self._s[1143]! } - public var Passport_Identity_FrontSide: String { return self._s[1144]! } - public var Login_PhoneNumberAlreadyAuthorizedSwitch: String { return self._s[1145]! } - public var Calls_CallTabTitle: String { return self._s[1146]! } - public var Channel_AdminLog_ChannelEmptyText: String { return self._s[1147]! } + public var PrivacyLastSeenSettings_GroupsAndChannelsHelp: String { return self._s[1139]! } + public var Privacy_Calls_NeverAllow_Placeholder: String { return self._s[1141]! } + public var Conversation_StatusTyping: String { return self._s[1142]! } + public var Broadcast_AdminLog_EmptyText: String { return self._s[1143]! } + public var Notification_PassportValueProofOfAddress: String { return self._s[1144]! } + public var UserInfo_CreateNewContact: String { return self._s[1145]! } + public var Passport_Identity_FrontSide: String { return self._s[1146]! } + public var Login_PhoneNumberAlreadyAuthorizedSwitch: String { return self._s[1147]! } + public var Calls_CallTabTitle: String { return self._s[1148]! } + public var Channel_AdminLog_ChannelEmptyText: String { return self._s[1149]! } public func Login_BannedPhoneBody(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1149]!, self._r[1149]!, [_0]) + return formatWithArgumentRanges(self._s[1151]!, self._r[1151]!, [_0]) } - public var Watch_UserInfo_MuteTitle: String { return self._s[1150]! } - public var Group_EditAdmin_RankAdminPlaceholder: String { return self._s[1151]! } - public var SharedMedia_EmptyMusicText: String { return self._s[1152]! } - public var Wallet_Completed_Text: String { return self._s[1153]! } - public var PasscodeSettings_AutoLock_IfAwayFor_1minute: String { return self._s[1154]! } - public var Paint_Stickers: String { return self._s[1155]! } - public var Privacy_GroupsAndChannels: String { return self._s[1156]! } - public var ChatList_Context_Delete: String { return self._s[1158]! } - public var UserInfo_AddContact: String { return self._s[1159]! } + public var Watch_UserInfo_MuteTitle: String { return self._s[1152]! } + public var Group_EditAdmin_RankAdminPlaceholder: String { return self._s[1153]! } + public var SharedMedia_EmptyMusicText: String { return self._s[1154]! } + public var Wallet_Completed_Text: String { return self._s[1155]! } + public var PasscodeSettings_AutoLock_IfAwayFor_1minute: String { return self._s[1156]! } + public var Paint_Stickers: String { return self._s[1157]! } + public var Privacy_GroupsAndChannels: String { return self._s[1158]! } + public var ChatList_Context_Delete: String { return self._s[1160]! } + public var UserInfo_AddContact: String { return self._s[1161]! } public func Conversation_MessageViaUser(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1160]!, self._r[1160]!, [_0]) + return formatWithArgumentRanges(self._s[1162]!, self._r[1162]!, [_0]) } - public var PhoneNumberHelp_ChangeNumber: String { return self._s[1162]! } + public var PhoneNumberHelp_ChangeNumber: String { return self._s[1164]! } public func ChatList_ClearChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1164]!, self._r[1164]!, [_0]) + return formatWithArgumentRanges(self._s[1166]!, self._r[1166]!, [_0]) } - public var DialogList_NoMessagesTitle: String { return self._s[1165]! } - public var EditProfile_NameAndPhotoHelp: String { return self._s[1166]! } - public var BlockedUsers_BlockUser: String { return self._s[1167]! } - public var Notifications_PermissionsOpenSettings: String { return self._s[1168]! } - public var MediaPicker_UngroupDescription: String { return self._s[1170]! } - public var Watch_NoConnection: String { return self._s[1171]! } - public var Month_GenSeptember: String { return self._s[1172]! } - public var Conversation_ViewGroup: String { return self._s[1174]! } - public var Channel_AdminLogFilter_EventsLeavingSubscribers: String { return self._s[1177]! } - public var Privacy_Forwards_AlwaysLink: String { return self._s[1178]! } - public var Channel_OwnershipTransfer_ErrorAdminsTooMuch: String { return self._s[1179]! } - public var Passport_FieldOneOf_FinalDelimeter: String { return self._s[1180]! } - public var Wallet_WordCheck_IncorrectHeader: String { return self._s[1181]! } - public var MediaPicker_CameraRoll: String { return self._s[1183]! } - public var Month_GenAugust: String { return self._s[1184]! } - public var Wallet_Configuration_SourceHeader: String { return self._s[1185]! } - public var AccessDenied_VideoMessageMicrophone: String { return self._s[1186]! } - public var SharedMedia_EmptyText: String { return self._s[1187]! } - public var Map_ShareLiveLocation: String { return self._s[1188]! } - public var Calls_All: String { return self._s[1189]! } - public var Map_SendThisPlace: String { return self._s[1191]! } - public var Appearance_ThemeNight: String { return self._s[1193]! } - public var Conversation_HoldForAudio: String { return self._s[1194]! } - public var SettingsSearch_Synonyms_Support: String { return self._s[1197]! } - public var GroupInfo_GroupHistoryHidden: String { return self._s[1198]! } - public var SocksProxySetup_Secret: String { return self._s[1199]! } + public var DialogList_NoMessagesTitle: String { return self._s[1167]! } + public var EditProfile_NameAndPhotoHelp: String { return self._s[1168]! } + public var BlockedUsers_BlockUser: String { return self._s[1169]! } + public var Notifications_PermissionsOpenSettings: String { return self._s[1170]! } + public var MediaPicker_UngroupDescription: String { return self._s[1172]! } + public var Watch_NoConnection: String { return self._s[1173]! } + public var Month_GenSeptember: String { return self._s[1174]! } + public var Conversation_ViewGroup: String { return self._s[1176]! } + public var Channel_AdminLogFilter_EventsLeavingSubscribers: String { return self._s[1179]! } + public var Privacy_Forwards_AlwaysLink: String { return self._s[1180]! } + public var Channel_OwnershipTransfer_ErrorAdminsTooMuch: String { return self._s[1181]! } + public var Passport_FieldOneOf_FinalDelimeter: String { return self._s[1182]! } + public var Wallet_WordCheck_IncorrectHeader: String { return self._s[1183]! } + public var MediaPicker_CameraRoll: String { return self._s[1185]! } + public var Month_GenAugust: String { return self._s[1186]! } + public var Wallet_Configuration_SourceHeader: String { return self._s[1187]! } + public var AccessDenied_VideoMessageMicrophone: String { return self._s[1188]! } + public var SharedMedia_EmptyText: String { return self._s[1189]! } + public var Map_ShareLiveLocation: String { return self._s[1190]! } + public var Calls_All: String { return self._s[1191]! } + public var Map_SendThisPlace: String { return self._s[1193]! } + public var Appearance_ThemeNight: String { return self._s[1195]! } + public var Conversation_HoldForAudio: String { return self._s[1196]! } + public var SettingsSearch_Synonyms_Support: String { return self._s[1199]! } + public var GroupInfo_GroupHistoryHidden: String { return self._s[1200]! } + public var SocksProxySetup_Secret: String { return self._s[1201]! } public func Activity_RemindAboutChannel(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1200]!, self._r[1200]!, [_0]) + return formatWithArgumentRanges(self._s[1202]!, self._r[1202]!, [_0]) } - public var Channel_BanList_RestrictedTitle: String { return self._s[1202]! } - public var Conversation_Location: String { return self._s[1203]! } + public var Channel_BanList_RestrictedTitle: String { return self._s[1204]! } + public var Conversation_Location: String { return self._s[1205]! } public func AutoDownloadSettings_UpToFor(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1204]!, self._r[1204]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1206]!, self._r[1206]!, [_1, _2]) } - public var ChatSettings_AutoDownloadPhotos: String { return self._s[1206]! } - public var SettingsSearch_Synonyms_Privacy_Title: String { return self._s[1207]! } - public var Notifications_PermissionsText: String { return self._s[1208]! } - public var SettingsSearch_Synonyms_Data_SaveIncomingPhotos: String { return self._s[1209]! } - public var Call_Flip: String { return self._s[1210]! } - public var Channel_AdminLog_CanDeleteMessagesOfOthers: String { return self._s[1212]! } - public var SocksProxySetup_ProxyStatusConnecting: String { return self._s[1213]! } - public var Wallet_TransactionInfo_StorageFeeInfoUrl: String { return self._s[1214]! } - public var PrivacyPhoneNumberSettings_DiscoveryHeader: String { return self._s[1215]! } - public var Channel_EditAdmin_PermissionPinMessages: String { return self._s[1217]! } - public var TwoStepAuth_ReEnterPasswordDescription: String { return self._s[1219]! } - public var Channel_TooMuchBots: String { return self._s[1221]! } - public var Passport_DeletePassportConfirmation: String { return self._s[1222]! } - public var Login_InvalidCodeError: String { return self._s[1223]! } - public var StickerPacksSettings_FeaturedPacks: String { return self._s[1224]! } + public var ChatSettings_AutoDownloadPhotos: String { return self._s[1208]! } + public var SettingsSearch_Synonyms_Privacy_Title: String { return self._s[1209]! } + public var Notifications_PermissionsText: String { return self._s[1210]! } + public var SettingsSearch_Synonyms_Data_SaveIncomingPhotos: String { return self._s[1211]! } + public var Call_Flip: String { return self._s[1212]! } + public var Channel_AdminLog_CanDeleteMessagesOfOthers: String { return self._s[1214]! } + public var SocksProxySetup_ProxyStatusConnecting: String { return self._s[1215]! } + public var Wallet_TransactionInfo_StorageFeeInfoUrl: String { return self._s[1216]! } + public var PrivacyPhoneNumberSettings_DiscoveryHeader: String { return self._s[1217]! } + public var Channel_EditAdmin_PermissionPinMessages: String { return self._s[1219]! } + public var TwoStepAuth_ReEnterPasswordDescription: String { return self._s[1221]! } + public var Channel_TooMuchBots: String { return self._s[1223]! } + public var Passport_DeletePassportConfirmation: String { return self._s[1224]! } + public var Login_InvalidCodeError: String { return self._s[1225]! } + public var StickerPacksSettings_FeaturedPacks: String { return self._s[1226]! } public func ChatList_DeleteSecretChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1225]!, self._r[1225]!, [_0]) + return formatWithArgumentRanges(self._s[1227]!, self._r[1227]!, [_0]) } public func GroupInfo_InvitationLinkAcceptChannel(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1226]!, self._r[1226]!, [_0]) + return formatWithArgumentRanges(self._s[1228]!, self._r[1228]!, [_0]) } - public var VoiceOver_Navigation_ProxySettings: String { return self._s[1227]! } - public var Call_CallInProgressTitle: String { return self._s[1228]! } - public var Month_ShortSeptember: String { return self._s[1229]! } - public var Watch_ChannelInfo_Title: String { return self._s[1230]! } - public var ChatList_DeleteSavedMessagesConfirmation: String { return self._s[1233]! } - public var DialogList_PasscodeLockHelp: String { return self._s[1234]! } - public var Chat_MultipleTextMessagesDisabled: String { return self._s[1235]! } - public var Wallet_Receive_Title: String { return self._s[1236]! } - public var Notifications_Badge_IncludePublicGroups: String { return self._s[1237]! } - public var Channel_AdminLogFilter_EventsTitle: String { return self._s[1238]! } - public var PhotoEditor_CropReset: String { return self._s[1239]! } - public var Group_Username_CreatePrivateLinkHelp: String { return self._s[1241]! } - public var Channel_Management_LabelEditor: String { return self._s[1242]! } - public var Passport_Identity_LatinNameHelp: String { return self._s[1244]! } - public var PhotoEditor_HighlightsTool: String { return self._s[1245]! } - public var Wallet_Info_WalletCreated: String { return self._s[1246]! } - public var UserInfo_Title: String { return self._s[1247]! } - public var ChatList_HideAction: String { return self._s[1248]! } - public var AccessDenied_Title: String { return self._s[1249]! } - public var DialogList_SearchLabel: String { return self._s[1250]! } - public var Group_Setup_HistoryHidden: String { return self._s[1251]! } - public var TwoStepAuth_PasswordChangeSuccess: String { return self._s[1252]! } - public var State_Updating: String { return self._s[1254]! } - public var Contacts_TabTitle: String { return self._s[1255]! } - public var Notifications_Badge_CountUnreadMessages: String { return self._s[1257]! } - public var GroupInfo_GroupHistory: String { return self._s[1258]! } - public var Conversation_UnsupportedMediaPlaceholder: String { return self._s[1259]! } - public var Wallpaper_SetColor: String { return self._s[1260]! } - public var CheckoutInfo_ShippingInfoCountry: String { return self._s[1261]! } - public var SettingsSearch_Synonyms_SavedMessages: String { return self._s[1262]! } - public var Chat_AttachmentLimitReached: String { return self._s[1263]! } - public var Passport_Identity_OneOfTypeDriversLicense: String { return self._s[1264]! } - public var Contacts_NotRegisteredSection: String { return self._s[1265]! } + public var VoiceOver_Navigation_ProxySettings: String { return self._s[1229]! } + public var Call_CallInProgressTitle: String { return self._s[1230]! } + public var Month_ShortSeptember: String { return self._s[1231]! } + public var Watch_ChannelInfo_Title: String { return self._s[1232]! } + public var ChatList_DeleteSavedMessagesConfirmation: String { return self._s[1235]! } + public var DialogList_PasscodeLockHelp: String { return self._s[1236]! } + public var Chat_MultipleTextMessagesDisabled: String { return self._s[1237]! } + public var Wallet_Receive_Title: String { return self._s[1238]! } + public var Notifications_Badge_IncludePublicGroups: String { return self._s[1239]! } + public var Channel_AdminLogFilter_EventsTitle: String { return self._s[1240]! } + public var PhotoEditor_CropReset: String { return self._s[1241]! } + public var Group_Username_CreatePrivateLinkHelp: String { return self._s[1243]! } + public var Channel_Management_LabelEditor: String { return self._s[1244]! } + public var Passport_Identity_LatinNameHelp: String { return self._s[1246]! } + public var PhotoEditor_HighlightsTool: String { return self._s[1247]! } + public var Wallet_Info_WalletCreated: String { return self._s[1248]! } + public var UserInfo_Title: String { return self._s[1249]! } + public var ChatList_HideAction: String { return self._s[1250]! } + public var AccessDenied_Title: String { return self._s[1251]! } + public var DialogList_SearchLabel: String { return self._s[1252]! } + public var Group_Setup_HistoryHidden: String { return self._s[1253]! } + public var TwoStepAuth_PasswordChangeSuccess: String { return self._s[1254]! } + public var State_Updating: String { return self._s[1256]! } + public var Contacts_TabTitle: String { return self._s[1257]! } + public var Notifications_Badge_CountUnreadMessages: String { return self._s[1259]! } + public var GroupInfo_GroupHistory: String { return self._s[1260]! } + public var Conversation_UnsupportedMediaPlaceholder: String { return self._s[1261]! } + public var Wallpaper_SetColor: String { return self._s[1262]! } + public var CheckoutInfo_ShippingInfoCountry: String { return self._s[1263]! } + public var SettingsSearch_Synonyms_SavedMessages: String { return self._s[1264]! } + public var Chat_AttachmentLimitReached: String { return self._s[1265]! } + public var Passport_Identity_OneOfTypeDriversLicense: String { return self._s[1266]! } + public var Contacts_NotRegisteredSection: String { return self._s[1267]! } public func Time_PreciseDate_m4(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1266]!, self._r[1266]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1268]!, self._r[1268]!, [_1, _2, _3]) } - public var Paint_Clear: String { return self._s[1267]! } - public var StickerPacksSettings_ArchivedMasks: String { return self._s[1268]! } - public var SocksProxySetup_Connecting: String { return self._s[1269]! } - public var ExplicitContent_AlertChannel: String { return self._s[1270]! } - public var CreatePoll_AllOptionsAdded: String { return self._s[1271]! } - public var Conversation_Contact: String { return self._s[1272]! } - public var Login_CodeExpired: String { return self._s[1273]! } - public var Passport_DiscardMessageAction: String { return self._s[1274]! } - public var ChatList_Context_Unpin: String { return self._s[1275]! } - public var Channel_AdminLog_MessagePreviousDescription: String { return self._s[1276]! } + public var Paint_Clear: String { return self._s[1269]! } + public var StickerPacksSettings_ArchivedMasks: String { return self._s[1270]! } + public var SocksProxySetup_Connecting: String { return self._s[1271]! } + public var ExplicitContent_AlertChannel: String { return self._s[1272]! } + public var CreatePoll_AllOptionsAdded: String { return self._s[1273]! } + public var Conversation_Contact: String { return self._s[1274]! } + public var Login_CodeExpired: String { return self._s[1275]! } + public var Passport_DiscardMessageAction: String { return self._s[1276]! } + public var ChatList_Context_Unpin: String { return self._s[1277]! } + public var Channel_AdminLog_MessagePreviousDescription: String { return self._s[1278]! } public func VoiceOver_Chat_MusicFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1277]!, self._r[1277]!, [_0]) + return formatWithArgumentRanges(self._s[1279]!, self._r[1279]!, [_0]) } - public var Channel_AdminLog_EmptyMessageText: String { return self._s[1278]! } - public var SettingsSearch_Synonyms_Data_NetworkUsage: String { return self._s[1279]! } + public var Channel_AdminLog_EmptyMessageText: String { return self._s[1280]! } + public var SettingsSearch_Synonyms_Data_NetworkUsage: String { return self._s[1281]! } public func Group_EditAdmin_RankInfo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1280]!, self._r[1280]!, [_0]) + return formatWithArgumentRanges(self._s[1282]!, self._r[1282]!, [_0]) } - public var Month_ShortApril: String { return self._s[1281]! } - public var AuthSessions_CurrentSession: String { return self._s[1282]! } - public var Chat_AttachmentMultipleFilesDisabled: String { return self._s[1285]! } - public var Wallet_Navigation_Cancel: String { return self._s[1287]! } - public var WallpaperPreview_CropTopText: String { return self._s[1288]! } - public var PrivacySettings_DeleteAccountIfAwayFor: String { return self._s[1289]! } - public var CheckoutInfo_ShippingInfoTitle: String { return self._s[1290]! } + public var Month_ShortApril: String { return self._s[1283]! } + public var AuthSessions_CurrentSession: String { return self._s[1284]! } + public var Chat_AttachmentMultipleFilesDisabled: String { return self._s[1287]! } + public var Wallet_Navigation_Cancel: String { return self._s[1289]! } + public var WallpaperPreview_CropTopText: String { return self._s[1290]! } + public var PrivacySettings_DeleteAccountIfAwayFor: String { return self._s[1291]! } + public var CheckoutInfo_ShippingInfoTitle: String { return self._s[1292]! } public func Conversation_ScheduleMessage_SendOn(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1291]!, self._r[1291]!, [_0, _1]) + return formatWithArgumentRanges(self._s[1293]!, self._r[1293]!, [_0, _1]) } - public var Appearance_ThemePreview_Chat_2_Text: String { return self._s[1292]! } - public var Channel_Setup_TypePrivate: String { return self._s[1294]! } - public var Forward_ChannelReadOnly: String { return self._s[1297]! } - public var PhotoEditor_CurvesBlue: String { return self._s[1298]! } - public var AddContact_SharedContactException: String { return self._s[1299]! } - public var UserInfo_BotPrivacy: String { return self._s[1301]! } - public var Wallet_CreateInvoice_Title: String { return self._s[1302]! } - public var Notification_PassportValueEmail: String { return self._s[1303]! } - public var EmptyGroupInfo_Subtitle: String { return self._s[1304]! } - public var GroupPermission_NewTitle: String { return self._s[1305]! } - public var CallFeedback_ReasonDropped: String { return self._s[1306]! } - public var GroupInfo_Permissions_AddException: String { return self._s[1307]! } - public var Channel_SignMessages_Help: String { return self._s[1309]! } - public var Undo_ChatDeleted: String { return self._s[1311]! } - public var Conversation_ChatBackground: String { return self._s[1312]! } + public var Appearance_ThemePreview_Chat_2_Text: String { return self._s[1294]! } + public var Channel_Setup_TypePrivate: String { return self._s[1296]! } + public var Forward_ChannelReadOnly: String { return self._s[1299]! } + public var PhotoEditor_CurvesBlue: String { return self._s[1300]! } + public var AddContact_SharedContactException: String { return self._s[1301]! } + public var UserInfo_BotPrivacy: String { return self._s[1303]! } + public var Wallet_CreateInvoice_Title: String { return self._s[1304]! } + public var Notification_PassportValueEmail: String { return self._s[1305]! } + public var EmptyGroupInfo_Subtitle: String { return self._s[1306]! } + public var GroupPermission_NewTitle: String { return self._s[1307]! } + public var CallFeedback_ReasonDropped: String { return self._s[1308]! } + public var GroupInfo_Permissions_AddException: String { return self._s[1309]! } + public var Channel_SignMessages_Help: String { return self._s[1311]! } + public var Undo_ChatDeleted: String { return self._s[1313]! } + public var Conversation_ChatBackground: String { return self._s[1314]! } public func Wallet_WordCheck_Text(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1313]!, self._r[1313]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1315]!, self._r[1315]!, [_1, _2, _3]) } - public var ChannelMembers_WhoCanAddMembers_Admins: String { return self._s[1314]! } - public var FastTwoStepSetup_EmailPlaceholder: String { return self._s[1315]! } - public var Passport_Language_pt: String { return self._s[1316]! } - public var VoiceOver_Chat_YourVoiceMessage: String { return self._s[1317]! } - public var NotificationsSound_Popcorn: String { return self._s[1320]! } - public var AutoNightTheme_Disabled: String { return self._s[1321]! } - public var BlockedUsers_LeavePrefix: String { return self._s[1322]! } - public var WallpaperPreview_CustomColorTopText: String { return self._s[1323]! } - public var Contacts_PermissionsSuppressWarningText: String { return self._s[1324]! } - public var WallpaperSearch_ColorBlue: String { return self._s[1325]! } + public func PUSH_CHAT_MESSAGE_QUIZ(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1316]!, self._r[1316]!, [_1, _2, _3]) + } + public var ChannelMembers_WhoCanAddMembers_Admins: String { return self._s[1317]! } + public var FastTwoStepSetup_EmailPlaceholder: String { return self._s[1318]! } + public var Passport_Language_pt: String { return self._s[1319]! } + public var VoiceOver_Chat_YourVoiceMessage: String { return self._s[1320]! } + public var NotificationsSound_Popcorn: String { return self._s[1323]! } + public var AutoNightTheme_Disabled: String { return self._s[1324]! } + public var BlockedUsers_LeavePrefix: String { return self._s[1325]! } + public var WallpaperPreview_CustomColorTopText: String { return self._s[1326]! } + public var Contacts_PermissionsSuppressWarningText: String { return self._s[1327]! } + public var WallpaperSearch_ColorBlue: String { return self._s[1328]! } public func CancelResetAccount_TextSMS(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1326]!, self._r[1326]!, [_0]) + return formatWithArgumentRanges(self._s[1329]!, self._r[1329]!, [_0]) } - public var CheckoutInfo_ErrorNameInvalid: String { return self._s[1327]! } - public var SocksProxySetup_UseForCalls: String { return self._s[1328]! } - public var Passport_DeleteDocumentConfirmation: String { return self._s[1330]! } + public var CheckoutInfo_ErrorNameInvalid: String { return self._s[1330]! } + public var SocksProxySetup_UseForCalls: String { return self._s[1331]! } + public var Passport_DeleteDocumentConfirmation: String { return self._s[1333]! } public func Conversation_Megabytes(_ _0: Float) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1331]!, self._r[1331]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[1334]!, self._r[1334]!, ["\(_0)"]) } - public var SocksProxySetup_Hostname: String { return self._s[1334]! } - public var ChatSettings_AutoDownloadSettings_OffForAll: String { return self._s[1335]! } - public var Compose_NewEncryptedChat: String { return self._s[1336]! } - public var Login_CodeFloodError: String { return self._s[1337]! } - public var Calls_TabTitle: String { return self._s[1338]! } - public var Privacy_ProfilePhoto: String { return self._s[1339]! } - public var Passport_Language_he: String { return self._s[1340]! } + public var SocksProxySetup_Hostname: String { return self._s[1337]! } + public var ChatSettings_AutoDownloadSettings_OffForAll: String { return self._s[1338]! } + public var Compose_NewEncryptedChat: String { return self._s[1339]! } + public var Login_CodeFloodError: String { return self._s[1340]! } + public var Calls_TabTitle: String { return self._s[1341]! } + public var Privacy_ProfilePhoto: String { return self._s[1342]! } + public var Passport_Language_he: String { return self._s[1343]! } public func Conversation_SetReminder_RemindToday(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1341]!, self._r[1341]!, [_0]) + return formatWithArgumentRanges(self._s[1344]!, self._r[1344]!, [_0]) } - public var GroupPermission_Title: String { return self._s[1342]! } + public var GroupPermission_Title: String { return self._s[1345]! } public func Channel_AdminLog_MessageGroupPreHistoryHidden(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1343]!, self._r[1343]!, [_0]) + return formatWithArgumentRanges(self._s[1346]!, self._r[1346]!, [_0]) } - public var Wallet_TransactionInfo_SenderHeader: String { return self._s[1344]! } - public var GroupPermission_NoChangeInfo: String { return self._s[1345]! } - public var ChatList_DeleteForCurrentUser: String { return self._s[1346]! } - public var Tour_Text1: String { return self._s[1347]! } - public var Channel_EditAdmin_TransferOwnership: String { return self._s[1348]! } - public var Month_ShortFebruary: String { return self._s[1349]! } - public var TwoStepAuth_EmailSkip: String { return self._s[1350]! } + public var Wallet_TransactionInfo_SenderHeader: String { return self._s[1347]! } + public var GroupPermission_NoChangeInfo: String { return self._s[1348]! } + public var ChatList_DeleteForCurrentUser: String { return self._s[1349]! } + public var Tour_Text1: String { return self._s[1350]! } + public var Channel_EditAdmin_TransferOwnership: String { return self._s[1351]! } + public var Month_ShortFebruary: String { return self._s[1352]! } + public var TwoStepAuth_EmailSkip: String { return self._s[1353]! } public func Wallet_Time_PreciseDate_m4(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1351]!, self._r[1351]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1354]!, self._r[1354]!, [_1, _2, _3]) } - public var NotificationsSound_Glass: String { return self._s[1352]! } - public var Appearance_ThemeNightBlue: String { return self._s[1353]! } - public var CheckoutInfo_Pay: String { return self._s[1354]! } - public var Invite_LargeRecipientsCountWarning: String { return self._s[1356]! } - public var Call_CallAgain: String { return self._s[1358]! } - public var AttachmentMenu_SendAsFile: String { return self._s[1359]! } - public var AccessDenied_MicrophoneRestricted: String { return self._s[1360]! } - public var Passport_InvalidPasswordError: String { return self._s[1361]! } - public var Watch_Message_Game: String { return self._s[1362]! } - public var Stickers_Install: String { return self._s[1363]! } - public var VoiceOver_Chat_Message: String { return self._s[1364]! } - public var PrivacyLastSeenSettings_NeverShareWith: String { return self._s[1365]! } - public var Passport_Identity_ResidenceCountry: String { return self._s[1367]! } - public var Notifications_GroupNotificationsHelp: String { return self._s[1368]! } - public var AuthSessions_OtherSessions: String { return self._s[1369]! } - public var Channel_Username_Help: String { return self._s[1370]! } - public var Camera_Title: String { return self._s[1371]! } - public var IntentsSettings_Title: String { return self._s[1372]! } - public var GroupInfo_SetGroupPhotoDelete: String { return self._s[1374]! } - public var Privacy_ProfilePhoto_NeverShareWith_Title: String { return self._s[1375]! } - public var Channel_AdminLog_SendPolls: String { return self._s[1376]! } - public var Channel_AdminLog_TitleAllEvents: String { return self._s[1377]! } - public var Channel_EditAdmin_PermissionInviteMembers: String { return self._s[1378]! } - public var Contacts_MemberSearchSectionTitleGroup: String { return self._s[1379]! } - public var ScheduledMessages_DeleteMany: String { return self._s[1380]! } - public var Conversation_RestrictedStickers: String { return self._s[1381]! } - public var Notifications_ExceptionsResetToDefaults: String { return self._s[1383]! } - public var UserInfo_TelegramCall: String { return self._s[1385]! } - public var TwoStepAuth_SetupResendEmailCode: String { return self._s[1386]! } - public var CreatePoll_OptionsHeader: String { return self._s[1387]! } - public var SettingsSearch_Synonyms_Data_CallsUseLessData: String { return self._s[1388]! } - public var ArchivedChats_IntroTitle1: String { return self._s[1389]! } - public var Privacy_GroupsAndChannels_AlwaysAllow_Title: String { return self._s[1390]! } - public var Theme_Colors_Proceed: String { return self._s[1391]! } - public var Passport_Identity_EditPersonalDetails: String { return self._s[1392]! } + public var NotificationsSound_Glass: String { return self._s[1355]! } + public var Appearance_ThemeNightBlue: String { return self._s[1356]! } + public var CheckoutInfo_Pay: String { return self._s[1357]! } + public var Invite_LargeRecipientsCountWarning: String { return self._s[1359]! } + public var Call_CallAgain: String { return self._s[1361]! } + public var AttachmentMenu_SendAsFile: String { return self._s[1362]! } + public var AccessDenied_MicrophoneRestricted: String { return self._s[1363]! } + public var Passport_InvalidPasswordError: String { return self._s[1364]! } + public var Watch_Message_Game: String { return self._s[1365]! } + public var Stickers_Install: String { return self._s[1366]! } + public var VoiceOver_Chat_Message: String { return self._s[1367]! } + public var PrivacyLastSeenSettings_NeverShareWith: String { return self._s[1368]! } + public var Passport_Identity_ResidenceCountry: String { return self._s[1370]! } + public var Notifications_GroupNotificationsHelp: String { return self._s[1371]! } + public var AuthSessions_OtherSessions: String { return self._s[1372]! } + public var Channel_Username_Help: String { return self._s[1373]! } + public var Camera_Title: String { return self._s[1374]! } + public var IntentsSettings_Title: String { return self._s[1375]! } + public var GroupInfo_SetGroupPhotoDelete: String { return self._s[1377]! } + public var Privacy_ProfilePhoto_NeverShareWith_Title: String { return self._s[1378]! } + public var Channel_AdminLog_SendPolls: String { return self._s[1379]! } + public var Channel_AdminLog_TitleAllEvents: String { return self._s[1380]! } + public var Channel_EditAdmin_PermissionInviteMembers: String { return self._s[1381]! } + public var Contacts_MemberSearchSectionTitleGroup: String { return self._s[1382]! } + public var ScheduledMessages_DeleteMany: String { return self._s[1383]! } + public var Conversation_RestrictedStickers: String { return self._s[1384]! } + public var Notifications_ExceptionsResetToDefaults: String { return self._s[1386]! } + public var UserInfo_TelegramCall: String { return self._s[1388]! } + public var TwoStepAuth_SetupResendEmailCode: String { return self._s[1389]! } + public var CreatePoll_OptionsHeader: String { return self._s[1390]! } + public var SettingsSearch_Synonyms_Data_CallsUseLessData: String { return self._s[1391]! } + public var ArchivedChats_IntroTitle1: String { return self._s[1392]! } + public var Privacy_GroupsAndChannels_AlwaysAllow_Title: String { return self._s[1393]! } + public var Theme_Colors_Proceed: String { return self._s[1394]! } + public var Passport_Identity_EditPersonalDetails: String { return self._s[1395]! } public func Time_PreciseDate_m1(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1393]!, self._r[1393]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1396]!, self._r[1396]!, [_1, _2, _3]) } - public var Wallet_Month_GenAugust: String { return self._s[1394]! } - public var Settings_SaveEditedPhotos: String { return self._s[1395]! } - public var TwoStepAuth_ConfirmationTitle: String { return self._s[1396]! } - public var Privacy_GroupsAndChannels_NeverAllow_Title: String { return self._s[1397]! } - public var Conversation_MessageDialogRetry: String { return self._s[1398]! } - public var ChatList_Context_MarkAsUnread: String { return self._s[1399]! } - public var MessagePoll_SubmitVote: String { return self._s[1400]! } - public var Conversation_DiscardVoiceMessageAction: String { return self._s[1401]! } - public var Permissions_PeopleNearbyTitle_v0: String { return self._s[1402]! } - public var Group_Setup_TypeHeader: String { return self._s[1403]! } - public var Paint_RecentStickers: String { return self._s[1404]! } - public var PhotoEditor_GrainTool: String { return self._s[1405]! } - public var CheckoutInfo_ShippingInfoState: String { return self._s[1406]! } - public var EmptyGroupInfo_Line4: String { return self._s[1407]! } - public var Watch_AuthRequired: String { return self._s[1409]! } + public var Wallet_Month_GenAugust: String { return self._s[1397]! } + public var Settings_SaveEditedPhotos: String { return self._s[1398]! } + public var TwoStepAuth_ConfirmationTitle: String { return self._s[1399]! } + public var Privacy_GroupsAndChannels_NeverAllow_Title: String { return self._s[1400]! } + public var Conversation_MessageDialogRetry: String { return self._s[1401]! } + public var ChatList_Context_MarkAsUnread: String { return self._s[1402]! } + public var MessagePoll_SubmitVote: String { return self._s[1403]! } + public var Conversation_DiscardVoiceMessageAction: String { return self._s[1404]! } + public var Permissions_PeopleNearbyTitle_v0: String { return self._s[1405]! } + public var Group_Setup_TypeHeader: String { return self._s[1406]! } + public var Paint_RecentStickers: String { return self._s[1407]! } + public var PhotoEditor_GrainTool: String { return self._s[1408]! } + public var CheckoutInfo_ShippingInfoState: String { return self._s[1409]! } + public var EmptyGroupInfo_Line4: String { return self._s[1410]! } + public var Watch_AuthRequired: String { return self._s[1412]! } public func Passport_Email_UseTelegramEmail(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1410]!, self._r[1410]!, [_0]) + return formatWithArgumentRanges(self._s[1413]!, self._r[1413]!, [_0]) } - public var Conversation_EncryptedDescriptionTitle: String { return self._s[1411]! } - public var ChannelIntro_Text: String { return self._s[1412]! } - public var DialogList_DeleteBotConfirmation: String { return self._s[1413]! } - public var GroupPermission_NoSendMedia: String { return self._s[1414]! } - public var Calls_AddTab: String { return self._s[1415]! } - public var Message_ReplyActionButtonShowReceipt: String { return self._s[1416]! } - public var Channel_AdminLog_EmptyFilterText: String { return self._s[1417]! } - public var Conversation_WalletRequiredSetup: String { return self._s[1418]! } - public var Notification_MessageLifetime1d: String { return self._s[1419]! } - public var Notifications_ChannelNotificationsExceptionsHelp: String { return self._s[1420]! } - public var Channel_BanUser_PermissionsHeader: String { return self._s[1421]! } - public var Passport_Identity_GenderFemale: String { return self._s[1422]! } - public var BlockedUsers_BlockTitle: String { return self._s[1423]! } + public var Conversation_EncryptedDescriptionTitle: String { return self._s[1414]! } + public var ChannelIntro_Text: String { return self._s[1415]! } + public var DialogList_DeleteBotConfirmation: String { return self._s[1416]! } + public var GroupPermission_NoSendMedia: String { return self._s[1417]! } + public var Calls_AddTab: String { return self._s[1418]! } + public var Message_ReplyActionButtonShowReceipt: String { return self._s[1419]! } + public var Channel_AdminLog_EmptyFilterText: String { return self._s[1420]! } + public var Conversation_WalletRequiredSetup: String { return self._s[1421]! } + public var Notification_MessageLifetime1d: String { return self._s[1422]! } + public var Notifications_ChannelNotificationsExceptionsHelp: String { return self._s[1423]! } + public var Channel_BanUser_PermissionsHeader: String { return self._s[1424]! } + public var Passport_Identity_GenderFemale: String { return self._s[1425]! } + public var BlockedUsers_BlockTitle: String { return self._s[1426]! } public func PUSH_CHANNEL_MESSAGE_GIF(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1424]!, self._r[1424]!, [_1]) + return formatWithArgumentRanges(self._s[1427]!, self._r[1427]!, [_1]) } - public var Weekday_Yesterday: String { return self._s[1425]! } - public var WallpaperSearch_ColorBlack: String { return self._s[1426]! } - public var Settings_Context_Logout: String { return self._s[1427]! } - public var Wallet_Info_UnknownTransaction: String { return self._s[1428]! } - public var ChatList_ArchiveAction: String { return self._s[1429]! } - public var AutoNightTheme_Scheduled: String { return self._s[1430]! } - public var TwoFactorSetup_Email_SkipAction: String { return self._s[1431]! } - public var Settings_Devices: String { return self._s[1432]! } - public var ContactInfo_Note: String { return self._s[1433]! } + public var Weekday_Yesterday: String { return self._s[1428]! } + public var WallpaperSearch_ColorBlack: String { return self._s[1429]! } + public var Settings_Context_Logout: String { return self._s[1430]! } + public var Wallet_Info_UnknownTransaction: String { return self._s[1431]! } + public var ChatList_ArchiveAction: String { return self._s[1432]! } + public var AutoNightTheme_Scheduled: String { return self._s[1433]! } + public var TwoFactorSetup_Email_SkipAction: String { return self._s[1434]! } + public var Settings_Devices: String { return self._s[1435]! } + public var ContactInfo_Note: String { return self._s[1436]! } public func Login_PhoneGenericEmailBody(_ _1: String, _ _2: String, _ _3: String, _ _4: String, _ _5: String, _ _6: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1434]!, self._r[1434]!, [_1, _2, _3, _4, _5, _6]) + return formatWithArgumentRanges(self._s[1437]!, self._r[1437]!, [_1, _2, _3, _4, _5, _6]) } - public var EditTheme_ThemeTemplateAlertTitle: String { return self._s[1435]! } - public var Wallet_Receive_CreateInvoice: String { return self._s[1436]! } - public var PrivacyPolicy_DeclineDeleteNow: String { return self._s[1437]! } - public var Theme_Colors_ColorWallpaperWarningProceed: String { return self._s[1438]! } + public var EditTheme_ThemeTemplateAlertTitle: String { return self._s[1438]! } + public var Wallet_Receive_CreateInvoice: String { return self._s[1439]! } + public var PrivacyPolicy_DeclineDeleteNow: String { return self._s[1440]! } + public var Theme_Colors_ColorWallpaperWarningProceed: String { return self._s[1441]! } public func PUSH_CHAT_JOINED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1439]!, self._r[1439]!, [_1, _2]) - } - public var CreatePoll_Create: String { return self._s[1440]! } - public var Channel_Members_AddBannedErrorAdmin: String { return self._s[1441]! } - public func Notification_CallFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[1442]!, self._r[1442]!, [_1, _2]) } - public var ScheduledMessages_ClearAllConfirmation: String { return self._s[1443]! } - public var Checkout_ErrorProviderAccountInvalid: String { return self._s[1444]! } - public var Notifications_InAppNotificationsSounds: String { return self._s[1446]! } - public func PUSH_PINNED_GAME_SCORE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1447]!, self._r[1447]!, [_1]) + public var CreatePoll_Create: String { return self._s[1443]! } + public var Channel_Members_AddBannedErrorAdmin: String { return self._s[1444]! } + public func Notification_CallFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1445]!, self._r[1445]!, [_1, _2]) } - public var Preview_OpenInInstagram: String { return self._s[1448]! } - public var Notification_MessageLifetimeRemovedOutgoing: String { return self._s[1449]! } + public var ScheduledMessages_ClearAllConfirmation: String { return self._s[1446]! } + public var Checkout_ErrorProviderAccountInvalid: String { return self._s[1447]! } + public var Notifications_InAppNotificationsSounds: String { return self._s[1449]! } + public func PUSH_PINNED_GAME_SCORE(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1450]!, self._r[1450]!, [_1]) + } + public var Preview_OpenInInstagram: String { return self._s[1451]! } + public var Notification_MessageLifetimeRemovedOutgoing: String { return self._s[1452]! } public func PUSH_CHAT_ADD_MEMBER(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1450]!, self._r[1450]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1453]!, self._r[1453]!, [_1, _2, _3]) } public func Passport_PrivacyPolicy(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1451]!, self._r[1451]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1454]!, self._r[1454]!, [_1, _2]) } - public var Channel_AdminLog_InfoPanelAlertTitle: String { return self._s[1452]! } - public var ArchivedChats_IntroText3: String { return self._s[1453]! } - public var ChatList_UndoArchiveHiddenText: String { return self._s[1454]! } - public var NetworkUsageSettings_TotalSection: String { return self._s[1455]! } - public var Wallet_Month_GenSeptember: String { return self._s[1456]! } - public var Channel_Setup_TypePrivateHelp: String { return self._s[1457]! } + public var Channel_AdminLog_InfoPanelAlertTitle: String { return self._s[1455]! } + public var ArchivedChats_IntroText3: String { return self._s[1456]! } + public var ChatList_UndoArchiveHiddenText: String { return self._s[1457]! } + public var NetworkUsageSettings_TotalSection: String { return self._s[1458]! } + public var Wallet_Month_GenSeptember: String { return self._s[1459]! } + public var Channel_Setup_TypePrivateHelp: String { return self._s[1460]! } public func PUSH_CHAT_MESSAGE_POLL(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1458]!, self._r[1458]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1461]!, self._r[1461]!, [_1, _2, _3]) } - public var Privacy_GroupsAndChannels_NeverAllow_Placeholder: String { return self._s[1460]! } - public var FastTwoStepSetup_HintSection: String { return self._s[1461]! } - public var Wallpaper_PhotoLibrary: String { return self._s[1462]! } - public var TwoStepAuth_SetupResendEmailCodeAlert: String { return self._s[1463]! } - public var Gif_NoGifsFound: String { return self._s[1464]! } - public var Watch_LastSeen_WithinAMonth: String { return self._s[1465]! } - public var VoiceOver_MessageContextDelete: String { return self._s[1466]! } - public var EditTheme_Preview: String { return self._s[1467]! } + public var Privacy_GroupsAndChannels_NeverAllow_Placeholder: String { return self._s[1463]! } + public var FastTwoStepSetup_HintSection: String { return self._s[1464]! } + public var Wallpaper_PhotoLibrary: String { return self._s[1465]! } + public var TwoStepAuth_SetupResendEmailCodeAlert: String { return self._s[1466]! } + public var Gif_NoGifsFound: String { return self._s[1467]! } + public var Watch_LastSeen_WithinAMonth: String { return self._s[1468]! } + public var VoiceOver_MessageContextDelete: String { return self._s[1469]! } + public var EditTheme_Preview: String { return self._s[1470]! } public func ClearCache_StorageTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1468]!, self._r[1468]!, [_0]) + return formatWithArgumentRanges(self._s[1471]!, self._r[1471]!, [_0]) } - public var GroupInfo_ActionPromote: String { return self._s[1469]! } - public var PasscodeSettings_SimplePasscode: String { return self._s[1470]! } - public var GroupInfo_Permissions_Title: String { return self._s[1471]! } - public var Permissions_ContactsText_v0: String { return self._s[1472]! } - public var PrivacyPhoneNumberSettings_CustomDisabledHelp: String { return self._s[1473]! } - public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedPublicGroups: String { return self._s[1474]! } - public var PrivacySettings_DataSettingsHelp: String { return self._s[1477]! } - public var Passport_FieldEmailHelp: String { return self._s[1478]! } + public var GroupInfo_ActionPromote: String { return self._s[1472]! } + public var PasscodeSettings_SimplePasscode: String { return self._s[1473]! } + public var GroupInfo_Permissions_Title: String { return self._s[1474]! } + public var Permissions_ContactsText_v0: String { return self._s[1475]! } + public var PrivacyPhoneNumberSettings_CustomDisabledHelp: String { return self._s[1476]! } + public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedPublicGroups: String { return self._s[1477]! } + public var PrivacySettings_DataSettingsHelp: String { return self._s[1480]! } + public var Passport_FieldEmailHelp: String { return self._s[1481]! } public func Activity_RemindAboutUser(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1479]!, self._r[1479]!, [_0]) + return formatWithArgumentRanges(self._s[1482]!, self._r[1482]!, [_0]) } - public var Passport_Identity_GenderPlaceholder: String { return self._s[1480]! } - public var Weekday_ShortSaturday: String { return self._s[1481]! } - public var ContactInfo_PhoneLabelMain: String { return self._s[1482]! } - public var Watch_Conversation_UserInfo: String { return self._s[1483]! } - public var CheckoutInfo_ShippingInfoCityPlaceholder: String { return self._s[1484]! } - public var GroupPermission_PermissionDisabledByDefault: String { return self._s[1485]! } - public var PrivacyLastSeenSettings_Title: String { return self._s[1486]! } - public var Conversation_ShareBotLocationConfirmation: String { return self._s[1487]! } - public var PhotoEditor_VignetteTool: String { return self._s[1488]! } - public var Passport_Address_Street1Placeholder: String { return self._s[1489]! } - public var Passport_Language_et: String { return self._s[1490]! } - public var AppUpgrade_Running: String { return self._s[1491]! } - public var Channel_DiscussionGroup_Info: String { return self._s[1493]! } - public var EditTheme_Create_Preview_IncomingReplyName: String { return self._s[1494]! } - public var Passport_Language_bg: String { return self._s[1495]! } - public var Stickers_NoStickersFound: String { return self._s[1497]! } + public var Passport_Identity_GenderPlaceholder: String { return self._s[1483]! } + public var Weekday_ShortSaturday: String { return self._s[1484]! } + public var ContactInfo_PhoneLabelMain: String { return self._s[1485]! } + public var Watch_Conversation_UserInfo: String { return self._s[1486]! } + public var CheckoutInfo_ShippingInfoCityPlaceholder: String { return self._s[1487]! } + public var GroupPermission_PermissionDisabledByDefault: String { return self._s[1488]! } + public var PrivacyLastSeenSettings_Title: String { return self._s[1489]! } + public var Conversation_ShareBotLocationConfirmation: String { return self._s[1490]! } + public var PhotoEditor_VignetteTool: String { return self._s[1491]! } + public var Passport_Address_Street1Placeholder: String { return self._s[1492]! } + public var Passport_Language_et: String { return self._s[1493]! } + public var AppUpgrade_Running: String { return self._s[1494]! } + public var Channel_DiscussionGroup_Info: String { return self._s[1496]! } + public var EditTheme_Create_Preview_IncomingReplyName: String { return self._s[1497]! } + public var Passport_Language_bg: String { return self._s[1498]! } + public var Stickers_NoStickersFound: String { return self._s[1500]! } public func PUSH_CHANNEL_MESSAGE_TEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1499]!, self._r[1499]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1502]!, self._r[1502]!, [_1, _2]) } public func VoiceOver_Chat_ContactFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1500]!, self._r[1500]!, [_0]) + return formatWithArgumentRanges(self._s[1503]!, self._r[1503]!, [_0]) } - public var Wallet_Month_GenJuly: String { return self._s[1501]! } - public var Wallet_Receive_AddressHeader: String { return self._s[1502]! } - public var Wallet_Send_AmountText: String { return self._s[1503]! } - public var Settings_About: String { return self._s[1504]! } + public var Wallet_Month_GenJuly: String { return self._s[1504]! } + public var Wallet_Receive_AddressHeader: String { return self._s[1505]! } + public var Wallet_Send_AmountText: String { return self._s[1506]! } + public var Settings_About: String { return self._s[1507]! } public func Channel_AdminLog_MessageRestricted(_ _0: String, _ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1505]!, self._r[1505]!, [_0, _1, _2]) + return formatWithArgumentRanges(self._s[1508]!, self._r[1508]!, [_0, _1, _2]) } - public var ChatList_Context_MarkAsRead: String { return self._s[1507]! } - public var KeyCommand_NewMessage: String { return self._s[1508]! } - public var Group_ErrorAddBlocked: String { return self._s[1509]! } + public var ChatList_Context_MarkAsRead: String { return self._s[1510]! } + public var KeyCommand_NewMessage: String { return self._s[1511]! } + public var Group_ErrorAddBlocked: String { return self._s[1512]! } public func Message_PaymentSent(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1510]!, self._r[1510]!, [_0]) + return formatWithArgumentRanges(self._s[1513]!, self._r[1513]!, [_0]) } - public var Map_LocationTitle: String { return self._s[1511]! } - public var ReportGroupLocation_Title: String { return self._s[1512]! } - public var CallSettings_UseLessDataLongDescription: String { return self._s[1513]! } - public var Cache_ClearProgress: String { return self._s[1514]! } + public var Map_LocationTitle: String { return self._s[1514]! } + public var ReportGroupLocation_Title: String { return self._s[1515]! } + public var CallSettings_UseLessDataLongDescription: String { return self._s[1516]! } + public var Cache_ClearProgress: String { return self._s[1517]! } public func Channel_Management_ErrorNotMember(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1515]!, self._r[1515]!, [_0]) + return formatWithArgumentRanges(self._s[1518]!, self._r[1518]!, [_0]) } - public var GroupRemoved_AddToGroup: String { return self._s[1516]! } - public var Passport_UpdateRequiredError: String { return self._s[1517]! } - public var Wallet_SecureStorageNotAvailable_Text: String { return self._s[1518]! } + public var GroupRemoved_AddToGroup: String { return self._s[1519]! } + public var Passport_UpdateRequiredError: String { return self._s[1520]! } + public var Wallet_SecureStorageNotAvailable_Text: String { return self._s[1521]! } public func PUSH_MESSAGE_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1519]!, self._r[1519]!, [_1]) + return formatWithArgumentRanges(self._s[1522]!, self._r[1522]!, [_1]) } - public var Notifications_PermissionsSuppressWarningText: String { return self._s[1521]! } - public var Passport_Identity_MainPageHelp: String { return self._s[1522]! } - public var Conversation_StatusKickedFromGroup: String { return self._s[1523]! } - public var Passport_Language_ka: String { return self._s[1524]! } + public var Notifications_PermissionsSuppressWarningText: String { return self._s[1524]! } + public var Passport_Identity_MainPageHelp: String { return self._s[1525]! } + public var Conversation_StatusKickedFromGroup: String { return self._s[1526]! } + public var Passport_Language_ka: String { return self._s[1527]! } public func Wallet_Time_PreciseDate_m12(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1525]!, self._r[1525]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1528]!, self._r[1528]!, [_1, _2, _3]) } - public var Call_Decline: String { return self._s[1526]! } - public var SocksProxySetup_ProxyEnabled: String { return self._s[1527]! } - public var TwoFactorSetup_Email_SkipConfirmationText: String { return self._s[1530]! } + public var Call_Decline: String { return self._s[1529]! } + public var SocksProxySetup_ProxyEnabled: String { return self._s[1530]! } + public var TwoFactorSetup_Email_SkipConfirmationText: String { return self._s[1533]! } public func AuthCode_Alert(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1531]!, self._r[1531]!, [_0]) + return formatWithArgumentRanges(self._s[1534]!, self._r[1534]!, [_0]) } - public var CallFeedback_Send: String { return self._s[1532]! } - public var EditTheme_EditTitle: String { return self._s[1533]! } + public var CallFeedback_Send: String { return self._s[1535]! } + public var EditTheme_EditTitle: String { return self._s[1536]! } public func Channel_AdminLog_MessagePromotedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1534]!, self._r[1534]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1537]!, self._r[1537]!, [_1, _2]) } - public var Passport_Phone_UseTelegramNumberHelp: String { return self._s[1535]! } + public var Passport_Phone_UseTelegramNumberHelp: String { return self._s[1538]! } public func Wallet_Updated_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1537]!, self._r[1537]!, [_0]) + return formatWithArgumentRanges(self._s[1540]!, self._r[1540]!, [_0]) } - public var SettingsSearch_Synonyms_Data_Title: String { return self._s[1538]! } - public var Passport_DeletePassport: String { return self._s[1539]! } - public var Appearance_AppIconFilled: String { return self._s[1540]! } - public var Privacy_Calls_P2PAlways: String { return self._s[1541]! } - public var Month_ShortDecember: String { return self._s[1542]! } - public var Channel_AdminLog_CanEditMessages: String { return self._s[1544]! } + public var SettingsSearch_Synonyms_Data_Title: String { return self._s[1541]! } + public var Passport_DeletePassport: String { return self._s[1542]! } + public var Appearance_AppIconFilled: String { return self._s[1543]! } + public var Privacy_Calls_P2PAlways: String { return self._s[1544]! } + public var Month_ShortDecember: String { return self._s[1545]! } + public var Channel_AdminLog_CanEditMessages: String { return self._s[1547]! } public func Contacts_AccessDeniedHelpLandscape(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1545]!, self._r[1545]!, [_0]) + return formatWithArgumentRanges(self._s[1548]!, self._r[1548]!, [_0]) } - public var Channel_Stickers_Searching: String { return self._s[1546]! } - public var Conversation_EncryptedDescription1: String { return self._s[1547]! } - public var Conversation_EncryptedDescription2: String { return self._s[1548]! } - public var PasscodeSettings_PasscodeOptions: String { return self._s[1549]! } - public var Conversation_EncryptedDescription3: String { return self._s[1551]! } - public var PhotoEditor_SharpenTool: String { return self._s[1552]! } - public var Wallet_Configuration_Title: String { return self._s[1553]! } + public var Channel_Stickers_Searching: String { return self._s[1549]! } + public var Conversation_EncryptedDescription1: String { return self._s[1550]! } + public var Conversation_EncryptedDescription2: String { return self._s[1551]! } + public var PasscodeSettings_PasscodeOptions: String { return self._s[1552]! } + public var Conversation_EncryptedDescription3: String { return self._s[1554]! } + public var PhotoEditor_SharpenTool: String { return self._s[1555]! } + public var Wallet_Configuration_Title: String { return self._s[1556]! } public func Conversation_AddNameToContacts(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1554]!, self._r[1554]!, [_0]) + return formatWithArgumentRanges(self._s[1557]!, self._r[1557]!, [_0]) } - public var Conversation_EncryptedDescription4: String { return self._s[1556]! } - public var Channel_Members_AddMembers: String { return self._s[1557]! } - public var Wallpaper_Search: String { return self._s[1558]! } - public var Weekday_Friday: String { return self._s[1560]! } - public var Privacy_ContactsSync: String { return self._s[1561]! } - public var SettingsSearch_Synonyms_Privacy_Data_ContactsReset: String { return self._s[1562]! } - public var ApplyLanguage_ChangeLanguageAction: String { return self._s[1563]! } + public var Conversation_EncryptedDescription4: String { return self._s[1559]! } + public var Channel_Members_AddMembers: String { return self._s[1560]! } + public var Wallpaper_Search: String { return self._s[1561]! } + public var Weekday_Friday: String { return self._s[1563]! } + public var Privacy_ContactsSync: String { return self._s[1564]! } + public var SettingsSearch_Synonyms_Privacy_Data_ContactsReset: String { return self._s[1565]! } + public var ApplyLanguage_ChangeLanguageAction: String { return self._s[1566]! } public func Channel_Management_RestrictedBy(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1564]!, self._r[1564]!, [_0]) + return formatWithArgumentRanges(self._s[1567]!, self._r[1567]!, [_0]) } - public var Wallet_Configuration_BlockchainIdHeader: String { return self._s[1565]! } - public var GroupInfo_Permissions_Removed: String { return self._s[1566]! } - public var ScheduledMessages_ScheduledOnline: String { return self._s[1567]! } - public var Passport_Identity_GenderMale: String { return self._s[1568]! } + public var Wallet_Configuration_BlockchainIdHeader: String { return self._s[1568]! } + public var GroupInfo_Permissions_Removed: String { return self._s[1569]! } + public var ScheduledMessages_ScheduledOnline: String { return self._s[1570]! } + public var Passport_Identity_GenderMale: String { return self._s[1571]! } public func Call_StatusBar(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1569]!, self._r[1569]!, [_0]) + return formatWithArgumentRanges(self._s[1572]!, self._r[1572]!, [_0]) } - public var Notifications_PermissionsKeepDisabled: String { return self._s[1570]! } - public var Conversation_JumpToDate: String { return self._s[1571]! } - public var Contacts_GlobalSearch: String { return self._s[1572]! } - public var AutoDownloadSettings_ResetHelp: String { return self._s[1573]! } - public var SettingsSearch_Synonyms_FAQ: String { return self._s[1574]! } - public var Profile_MessageLifetime1d: String { return self._s[1575]! } + public var Notifications_PermissionsKeepDisabled: String { return self._s[1573]! } + public var Conversation_JumpToDate: String { return self._s[1574]! } + public var Contacts_GlobalSearch: String { return self._s[1575]! } + public var AutoDownloadSettings_ResetHelp: String { return self._s[1576]! } + public var SettingsSearch_Synonyms_FAQ: String { return self._s[1577]! } + public var Profile_MessageLifetime1d: String { return self._s[1578]! } public func MESSAGE_INVOICE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1576]!, self._r[1576]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1579]!, self._r[1579]!, [_1, _2]) } - public var StickerPack_BuiltinPackName: String { return self._s[1579]! } + public var StickerPack_BuiltinPackName: String { return self._s[1582]! } public func PUSH_CHAT_MESSAGE_AUDIO(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1580]!, self._r[1580]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1583]!, self._r[1583]!, [_1, _2]) } - public var VoiceOver_Chat_RecordModeVoiceMessageInfo: String { return self._s[1581]! } - public var Passport_InfoTitle: String { return self._s[1583]! } - public var Notifications_PermissionsUnreachableText: String { return self._s[1584]! } + public var VoiceOver_Chat_RecordModeVoiceMessageInfo: String { return self._s[1584]! } + public var Passport_InfoTitle: String { return self._s[1586]! } + public var Notifications_PermissionsUnreachableText: String { return self._s[1587]! } public func NetworkUsageSettings_CellularUsageSince(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1588]!, self._r[1588]!, [_0]) + return formatWithArgumentRanges(self._s[1591]!, self._r[1591]!, [_0]) } public func PUSH_CHAT_MESSAGE_GEO(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1589]!, self._r[1589]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1592]!, self._r[1592]!, [_1, _2]) } - public var Passport_Address_TypePassportRegistrationUploadScan: String { return self._s[1590]! } - public var Profile_BotInfo: String { return self._s[1591]! } - public var Watch_Compose_CreateMessage: String { return self._s[1592]! } - public var AutoDownloadSettings_VoiceMessagesInfo: String { return self._s[1593]! } - public var Month_ShortNovember: String { return self._s[1594]! } - public var Conversation_ScamWarning: String { return self._s[1595]! } - public var Wallpaper_SetCustomBackground: String { return self._s[1596]! } - public var Appearance_TextSize_Title: String { return self._s[1597]! } - public var Passport_Identity_TranslationsHelp: String { return self._s[1598]! } - public var NotificationsSound_Chime: String { return self._s[1599]! } - public var Passport_Language_ko: String { return self._s[1601]! } - public var InviteText_URL: String { return self._s[1602]! } - public var TextFormat_Monospace: String { return self._s[1603]! } + public var Passport_Address_TypePassportRegistrationUploadScan: String { return self._s[1593]! } + public var Profile_BotInfo: String { return self._s[1594]! } + public var Watch_Compose_CreateMessage: String { return self._s[1595]! } + public var AutoDownloadSettings_VoiceMessagesInfo: String { return self._s[1596]! } + public var Month_ShortNovember: String { return self._s[1597]! } + public var Conversation_ScamWarning: String { return self._s[1598]! } + public var Wallpaper_SetCustomBackground: String { return self._s[1599]! } + public var Appearance_TextSize_Title: String { return self._s[1600]! } + public var Passport_Identity_TranslationsHelp: String { return self._s[1601]! } + public var NotificationsSound_Chime: String { return self._s[1602]! } + public var Passport_Language_ko: String { return self._s[1604]! } + public var InviteText_URL: String { return self._s[1605]! } + public var TextFormat_Monospace: String { return self._s[1606]! } public func Time_PreciseDate_m11(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1604]!, self._r[1604]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1607]!, self._r[1607]!, [_1, _2, _3]) } - public var EditTheme_Edit_BottomInfo: String { return self._s[1605]! } + public var EditTheme_Edit_BottomInfo: String { return self._s[1608]! } public func Login_WillSendSms(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1606]!, self._r[1606]!, [_0]) + return formatWithArgumentRanges(self._s[1609]!, self._r[1609]!, [_0]) } public func Watch_Time_ShortWeekdayAt(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1607]!, self._r[1607]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1610]!, self._r[1610]!, [_1, _2]) } - public var Wallet_Words_Title: String { return self._s[1608]! } - public var Wallet_Month_ShortMay: String { return self._s[1609]! } - public var EditTheme_CreateTitle: String { return self._s[1611]! } - public var Passport_InfoLearnMore: String { return self._s[1612]! } - public var TwoStepAuth_EmailPlaceholder: String { return self._s[1613]! } - public var Passport_Identity_AddIdentityCard: String { return self._s[1614]! } - public var Your_card_has_expired: String { return self._s[1615]! } - public var StickerPacksSettings_StickerPacksSection: String { return self._s[1616]! } - public var GroupInfo_InviteLink_Help: String { return self._s[1617]! } - public var TwoFactorSetup_EmailVerification_ResendAction: String { return self._s[1621]! } - public var Conversation_Report: String { return self._s[1623]! } - public var Notifications_MessageNotificationsSound: String { return self._s[1624]! } - public var Notification_MessageLifetime1m: String { return self._s[1625]! } - public var Privacy_ContactsTitle: String { return self._s[1626]! } - public var Conversation_ShareMyContactInfo: String { return self._s[1627]! } - public var Wallet_WordCheck_Title: String { return self._s[1628]! } - public var ChannelMembers_WhoCanAddMembersAdminsHelp: String { return self._s[1629]! } - public var Channel_Members_Title: String { return self._s[1630]! } - public var Map_OpenInWaze: String { return self._s[1631]! } - public var Appearance_RemoveThemeColorConfirmation: String { return self._s[1632]! } - public var Login_PhoneBannedError: String { return self._s[1633]! } + public var Wallet_Words_Title: String { return self._s[1611]! } + public var Wallet_Month_ShortMay: String { return self._s[1612]! } + public var EditTheme_CreateTitle: String { return self._s[1614]! } + public var Passport_InfoLearnMore: String { return self._s[1615]! } + public var TwoStepAuth_EmailPlaceholder: String { return self._s[1616]! } + public var Passport_Identity_AddIdentityCard: String { return self._s[1617]! } + public var Your_card_has_expired: String { return self._s[1618]! } + public var StickerPacksSettings_StickerPacksSection: String { return self._s[1619]! } + public var GroupInfo_InviteLink_Help: String { return self._s[1620]! } + public var TwoFactorSetup_EmailVerification_ResendAction: String { return self._s[1624]! } + public var Conversation_Report: String { return self._s[1626]! } + public var Notifications_MessageNotificationsSound: String { return self._s[1627]! } + public var Notification_MessageLifetime1m: String { return self._s[1628]! } + public var Privacy_ContactsTitle: String { return self._s[1629]! } + public var Conversation_ShareMyContactInfo: String { return self._s[1630]! } + public var Wallet_WordCheck_Title: String { return self._s[1631]! } + public var ChannelMembers_WhoCanAddMembersAdminsHelp: String { return self._s[1632]! } + public var Channel_Members_Title: String { return self._s[1633]! } + public var Map_OpenInWaze: String { return self._s[1634]! } + public var Appearance_RemoveThemeColorConfirmation: String { return self._s[1635]! } + public var Login_PhoneBannedError: String { return self._s[1636]! } public func LiveLocationUpdated_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1634]!, self._r[1634]!, [_0]) + return formatWithArgumentRanges(self._s[1637]!, self._r[1637]!, [_0]) } - public var IntentsSettings_MainAccount: String { return self._s[1635]! } - public var Group_Management_AddModeratorHelp: String { return self._s[1636]! } - public var AutoDownloadSettings_WifiTitle: String { return self._s[1637]! } - public var Common_OK: String { return self._s[1638]! } - public var Passport_Address_TypeBankStatementUploadScan: String { return self._s[1639]! } - public var Wallet_Words_NotDoneResponse: String { return self._s[1640]! } - public var Cache_Music: String { return self._s[1641]! } - public var Wallet_Configuration_SourceURL: String { return self._s[1642]! } - public var SettingsSearch_Synonyms_EditProfile_PhoneNumber: String { return self._s[1643]! } - public var PasscodeSettings_UnlockWithTouchId: String { return self._s[1645]! } - public var TwoStepAuth_HintPlaceholder: String { return self._s[1646]! } + public var IntentsSettings_MainAccount: String { return self._s[1638]! } + public var Group_Management_AddModeratorHelp: String { return self._s[1639]! } + public var AutoDownloadSettings_WifiTitle: String { return self._s[1640]! } + public var Common_OK: String { return self._s[1641]! } + public var Passport_Address_TypeBankStatementUploadScan: String { return self._s[1642]! } + public var Wallet_Words_NotDoneResponse: String { return self._s[1643]! } + public var Cache_Music: String { return self._s[1644]! } + public var Wallet_Configuration_SourceURL: String { return self._s[1645]! } + public var SettingsSearch_Synonyms_EditProfile_PhoneNumber: String { return self._s[1646]! } + public var PasscodeSettings_UnlockWithTouchId: String { return self._s[1648]! } + public var TwoStepAuth_HintPlaceholder: String { return self._s[1649]! } public func PUSH_PINNED_INVOICE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1647]!, self._r[1647]!, [_1]) + return formatWithArgumentRanges(self._s[1650]!, self._r[1650]!, [_1]) } public func Passport_RequestHeader(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1648]!, self._r[1648]!, [_0]) + return formatWithArgumentRanges(self._s[1651]!, self._r[1651]!, [_0]) } - public var TwoFactorSetup_Done_Action: String { return self._s[1649]! } + public var TwoFactorSetup_Done_Action: String { return self._s[1652]! } public func VoiceOver_Chat_ContactOrganization(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1650]!, self._r[1650]!, [_0]) + return formatWithArgumentRanges(self._s[1653]!, self._r[1653]!, [_0]) } - public var Wallet_Send_ErrorNotEnoughFundsText: String { return self._s[1651]! } - public var Watch_MessageView_ViewOnPhone: String { return self._s[1653]! } - public var Privacy_Calls_CustomShareHelp: String { return self._s[1654]! } - public var Wallet_Receive_CreateInvoiceInfo: String { return self._s[1656]! } - public var ChangePhoneNumberNumber_Title: String { return self._s[1657]! } - public var State_ConnectingToProxyInfo: String { return self._s[1658]! } - public var Conversation_SwipeToReplyHintTitle: String { return self._s[1659]! } - public var Message_VideoMessage: String { return self._s[1661]! } - public var ChannelInfo_DeleteChannel: String { return self._s[1662]! } - public var ContactInfo_PhoneLabelOther: String { return self._s[1663]! } - public var Channel_EditAdmin_CannotEdit: String { return self._s[1664]! } - public var Passport_DeleteAddressConfirmation: String { return self._s[1665]! } + public var Wallet_Send_ErrorNotEnoughFundsText: String { return self._s[1654]! } + public var Watch_MessageView_ViewOnPhone: String { return self._s[1656]! } + public var Privacy_Calls_CustomShareHelp: String { return self._s[1657]! } + public var Wallet_Receive_CreateInvoiceInfo: String { return self._s[1659]! } + public var ChangePhoneNumberNumber_Title: String { return self._s[1660]! } + public var State_ConnectingToProxyInfo: String { return self._s[1661]! } + public var Conversation_SwipeToReplyHintTitle: String { return self._s[1662]! } + public var Message_VideoMessage: String { return self._s[1664]! } + public var ChannelInfo_DeleteChannel: String { return self._s[1665]! } + public var ContactInfo_PhoneLabelOther: String { return self._s[1666]! } + public var Channel_EditAdmin_CannotEdit: String { return self._s[1667]! } + public var Passport_DeleteAddressConfirmation: String { return self._s[1668]! } public func Wallet_Time_PreciseDate_m9(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1666]!, self._r[1666]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1669]!, self._r[1669]!, [_1, _2, _3]) } - public var WallpaperPreview_SwipeBottomText: String { return self._s[1667]! } - public var Activity_RecordingAudio: String { return self._s[1668]! } - public var SettingsSearch_Synonyms_Watch: String { return self._s[1669]! } - public var PasscodeSettings_TryAgainIn1Minute: String { return self._s[1670]! } - public var Wallet_Info_Address: String { return self._s[1671]! } + public var WallpaperPreview_SwipeBottomText: String { return self._s[1670]! } + public var Activity_RecordingAudio: String { return self._s[1671]! } + public var SettingsSearch_Synonyms_Watch: String { return self._s[1672]! } + public var PasscodeSettings_TryAgainIn1Minute: String { return self._s[1673]! } + public var Wallet_Info_Address: String { return self._s[1674]! } public func Notification_ChangedGroupName(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1673]!, self._r[1673]!, [_0, _1]) + return formatWithArgumentRanges(self._s[1676]!, self._r[1676]!, [_0, _1]) } public func EmptyGroupInfo_Line1(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1677]!, self._r[1677]!, [_0]) + return formatWithArgumentRanges(self._s[1680]!, self._r[1680]!, [_0]) } - public var Conversation_ApplyLocalization: String { return self._s[1678]! } - public var TwoFactorSetup_Intro_Action: String { return self._s[1679]! } - public var UserInfo_AddPhone: String { return self._s[1680]! } - public var Map_ShareLiveLocationHelp: String { return self._s[1681]! } + public var Conversation_ApplyLocalization: String { return self._s[1681]! } + public var TwoFactorSetup_Intro_Action: String { return self._s[1682]! } + public var UserInfo_AddPhone: String { return self._s[1683]! } + public var Map_ShareLiveLocationHelp: String { return self._s[1684]! } public func Passport_Identity_NativeNameGenericHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1682]!, self._r[1682]!, [_0]) + return formatWithArgumentRanges(self._s[1685]!, self._r[1685]!, [_0]) } - public var Passport_Scans: String { return self._s[1684]! } - public var BlockedUsers_Unblock: String { return self._s[1685]! } + public var Passport_Scans: String { return self._s[1687]! } + public var BlockedUsers_Unblock: String { return self._s[1688]! } public func PUSH_ENCRYPTION_REQUEST(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1686]!, self._r[1686]!, [_1]) + return formatWithArgumentRanges(self._s[1689]!, self._r[1689]!, [_1]) } - public var Channel_Management_LabelCreator: String { return self._s[1687]! } - public var Conversation_ReportSpamAndLeave: String { return self._s[1688]! } - public var SettingsSearch_Synonyms_EditProfile_Bio: String { return self._s[1689]! } - public var ChatList_UndoArchiveMultipleTitle: String { return self._s[1690]! } - public var Passport_Identity_NativeNameGenericTitle: String { return self._s[1691]! } + public var Channel_Management_LabelCreator: String { return self._s[1690]! } + public var Conversation_ReportSpamAndLeave: String { return self._s[1691]! } + public var SettingsSearch_Synonyms_EditProfile_Bio: String { return self._s[1692]! } + public var ChatList_UndoArchiveMultipleTitle: String { return self._s[1693]! } + public var Passport_Identity_NativeNameGenericTitle: String { return self._s[1694]! } public func Login_EmailPhoneBody(_ _0: String, _ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1692]!, self._r[1692]!, [_0, _1, _2]) + return formatWithArgumentRanges(self._s[1695]!, self._r[1695]!, [_0, _1, _2]) } - public var Login_PhoneNumberHelp: String { return self._s[1693]! } - public var LastSeen_ALongTimeAgo: String { return self._s[1694]! } - public var Channel_AdminLog_CanPinMessages: String { return self._s[1695]! } - public var ChannelIntro_CreateChannel: String { return self._s[1696]! } - public var Conversation_UnreadMessages: String { return self._s[1697]! } - public var SettingsSearch_Synonyms_Stickers_ArchivedPacks: String { return self._s[1698]! } - public var Channel_AdminLog_EmptyText: String { return self._s[1699]! } - public var Theme_Context_Apply: String { return self._s[1700]! } - public var Notification_GroupActivated: String { return self._s[1701]! } - public var NotificationSettings_ContactJoinedInfo: String { return self._s[1702]! } - public var Wallet_Intro_CreateWallet: String { return self._s[1703]! } + public var Login_PhoneNumberHelp: String { return self._s[1696]! } + public var LastSeen_ALongTimeAgo: String { return self._s[1697]! } + public var Channel_AdminLog_CanPinMessages: String { return self._s[1698]! } + public var ChannelIntro_CreateChannel: String { return self._s[1699]! } + public var Conversation_UnreadMessages: String { return self._s[1700]! } + public var SettingsSearch_Synonyms_Stickers_ArchivedPacks: String { return self._s[1701]! } + public var Channel_AdminLog_EmptyText: String { return self._s[1702]! } + public var Theme_Context_Apply: String { return self._s[1703]! } + public var Notification_GroupActivated: String { return self._s[1704]! } + public var NotificationSettings_ContactJoinedInfo: String { return self._s[1705]! } + public var Wallet_Intro_CreateWallet: String { return self._s[1706]! } public func Notification_PinnedContactMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1704]!, self._r[1704]!, [_0]) + return formatWithArgumentRanges(self._s[1707]!, self._r[1707]!, [_0]) } public func DownloadingStatus(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1705]!, self._r[1705]!, [_0, _1]) + return formatWithArgumentRanges(self._s[1708]!, self._r[1708]!, [_0, _1]) } - public var GroupInfo_ConvertToSupergroup: String { return self._s[1707]! } + public var GroupInfo_ConvertToSupergroup: String { return self._s[1710]! } public func PrivacyPolicy_AgeVerificationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1708]!, self._r[1708]!, [_0]) - } - public var Undo_DeletedChannel: String { return self._s[1709]! } - public var CallFeedback_AddComment: String { return self._s[1710]! } - public func Conversation_OpenBotLinkAllowMessages(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[1711]!, self._r[1711]!, [_0]) } - public var Document_TargetConfirmationFormat: String { return self._s[1712]! } + public var Undo_DeletedChannel: String { return self._s[1712]! } + public var CallFeedback_AddComment: String { return self._s[1713]! } + public func Conversation_OpenBotLinkAllowMessages(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1714]!, self._r[1714]!, [_0]) + } + public var Document_TargetConfirmationFormat: String { return self._s[1715]! } public func Call_StatusOngoing(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1713]!, self._r[1713]!, [_0]) + return formatWithArgumentRanges(self._s[1716]!, self._r[1716]!, [_0]) } - public var LogoutOptions_SetPasscodeTitle: String { return self._s[1714]! } + public var LogoutOptions_SetPasscodeTitle: String { return self._s[1717]! } public func PUSH_CHAT_MESSAGE_GAME_SCORE(_ _1: String, _ _2: String, _ _3: String, _ _4: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1715]!, self._r[1715]!, [_1, _2, _3, _4]) + return formatWithArgumentRanges(self._s[1718]!, self._r[1718]!, [_1, _2, _3, _4]) } - public var Wallet_SecureStorageChanged_PasscodeText: String { return self._s[1716]! } - public var Theme_ErrorNotFound: String { return self._s[1717]! } - public var Contacts_SortByName: String { return self._s[1718]! } - public var SettingsSearch_Synonyms_Privacy_Forwards: String { return self._s[1719]! } + public var Wallet_SecureStorageChanged_PasscodeText: String { return self._s[1719]! } + public var Theme_ErrorNotFound: String { return self._s[1720]! } + public var Contacts_SortByName: String { return self._s[1721]! } + public var SettingsSearch_Synonyms_Privacy_Forwards: String { return self._s[1722]! } public func CHAT_MESSAGE_INVOICE(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1721]!, self._r[1721]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1724]!, self._r[1724]!, [_1, _2, _3]) } - public var Notification_Exceptions_RemoveFromExceptions: String { return self._s[1722]! } - public var ScheduledMessages_EditTime: String { return self._s[1723]! } - public var Conversation_ClearSelfHistory: String { return self._s[1724]! } - public var Checkout_NewCard_PostcodePlaceholder: String { return self._s[1725]! } - public var PasscodeSettings_DoNotMatch: String { return self._s[1726]! } - public var Stickers_SuggestNone: String { return self._s[1727]! } - public var ChatSettings_Cache: String { return self._s[1728]! } - public var Settings_SaveIncomingPhotos: String { return self._s[1729]! } - public var Media_ShareThisPhoto: String { return self._s[1730]! } - public var Chat_SlowmodeTooltipPending: String { return self._s[1731]! } - public var InfoPlist_NSContactsUsageDescription: String { return self._s[1732]! } - public var Conversation_ContextMenuCopyLink: String { return self._s[1733]! } - public var PrivacyPolicy_AgeVerificationTitle: String { return self._s[1734]! } - public var SettingsSearch_Synonyms_Stickers_Masks: String { return self._s[1735]! } - public var TwoStepAuth_SetupPasswordEnterPasswordNew: String { return self._s[1736]! } - public var Appearance_ThemePreview_Chat_6_Text: String { return self._s[1737]! } + public var Notification_Exceptions_RemoveFromExceptions: String { return self._s[1725]! } + public var ScheduledMessages_EditTime: String { return self._s[1726]! } + public var Conversation_ClearSelfHistory: String { return self._s[1727]! } + public var Checkout_NewCard_PostcodePlaceholder: String { return self._s[1728]! } + public var PasscodeSettings_DoNotMatch: String { return self._s[1729]! } + public var Stickers_SuggestNone: String { return self._s[1730]! } + public var ChatSettings_Cache: String { return self._s[1731]! } + public var Settings_SaveIncomingPhotos: String { return self._s[1732]! } + public var Media_ShareThisPhoto: String { return self._s[1733]! } + public var Chat_SlowmodeTooltipPending: String { return self._s[1734]! } + public var InfoPlist_NSContactsUsageDescription: String { return self._s[1735]! } + public var Conversation_ContextMenuCopyLink: String { return self._s[1736]! } + public var PrivacyPolicy_AgeVerificationTitle: String { return self._s[1737]! } + public var SettingsSearch_Synonyms_Stickers_Masks: String { return self._s[1738]! } + public var TwoStepAuth_SetupPasswordEnterPasswordNew: String { return self._s[1739]! } + public var Appearance_ThemePreview_Chat_6_Text: String { return self._s[1740]! } public func Wallet_SecureStorageReset_BiometryText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1738]!, self._r[1738]!, [_0]) + return formatWithArgumentRanges(self._s[1741]!, self._r[1741]!, [_0]) } - public var Permissions_CellularDataTitle_v0: String { return self._s[1739]! } - public var WallpaperSearch_ColorWhite: String { return self._s[1741]! } - public var Channel_AdminLog_DefaultRestrictionsUpdated: String { return self._s[1742]! } - public var Conversation_ErrorInaccessibleMessage: String { return self._s[1743]! } - public var Map_OpenIn: String { return self._s[1744]! } + public var Permissions_CellularDataTitle_v0: String { return self._s[1742]! } + public var WallpaperSearch_ColorWhite: String { return self._s[1744]! } + public var Channel_AdminLog_DefaultRestrictionsUpdated: String { return self._s[1745]! } + public var Conversation_ErrorInaccessibleMessage: String { return self._s[1746]! } + public var Map_OpenIn: String { return self._s[1747]! } public func PUSH_PHONE_CALL_MISSED(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1747]!, self._r[1747]!, [_1]) + return formatWithArgumentRanges(self._s[1750]!, self._r[1750]!, [_1]) } public func ChannelInfo_AddParticipantConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1748]!, self._r[1748]!, [_0]) + return formatWithArgumentRanges(self._s[1751]!, self._r[1751]!, [_0]) } - public var GroupInfo_Permissions_SlowmodeHeader: String { return self._s[1749]! } - public var MessagePoll_LabelClosed: String { return self._s[1750]! } - public var GroupPermission_PermissionGloballyDisabled: String { return self._s[1752]! } - public var Wallet_Send_SendAnyway: String { return self._s[1753]! } - public var Passport_Identity_MiddleNamePlaceholder: String { return self._s[1754]! } - public var UserInfo_FirstNamePlaceholder: String { return self._s[1755]! } - public var PrivacyLastSeenSettings_WhoCanSeeMyTimestamp: String { return self._s[1756]! } - public var Map_SetThisPlace: String { return self._s[1757]! } - public var Login_SelectCountry_Title: String { return self._s[1758]! } - public var Channel_EditAdmin_PermissionBanUsers: String { return self._s[1759]! } + public var GroupInfo_Permissions_SlowmodeHeader: String { return self._s[1752]! } + public var MessagePoll_LabelClosed: String { return self._s[1753]! } + public var GroupPermission_PermissionGloballyDisabled: String { return self._s[1755]! } + public var Wallet_Send_SendAnyway: String { return self._s[1756]! } + public var Passport_Identity_MiddleNamePlaceholder: String { return self._s[1757]! } + public var UserInfo_FirstNamePlaceholder: String { return self._s[1758]! } + public var PrivacyLastSeenSettings_WhoCanSeeMyTimestamp: String { return self._s[1759]! } + public var Map_SetThisPlace: String { return self._s[1760]! } + public var Login_SelectCountry_Title: String { return self._s[1761]! } + public var Channel_EditAdmin_PermissionBanUsers: String { return self._s[1762]! } public func Conversation_OpenBotLinkLogin(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1760]!, self._r[1760]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1763]!, self._r[1763]!, [_1, _2]) } - public var Channel_AdminLog_ChangeInfo: String { return self._s[1761]! } - public var Watch_Suggestion_BRB: String { return self._s[1762]! } - public var Passport_Identity_EditIdentityCard: String { return self._s[1763]! } - public var Contacts_PermissionsTitle: String { return self._s[1764]! } - public var Conversation_RestrictedInline: String { return self._s[1765]! } - public var Appearance_RemoveThemeColor: String { return self._s[1767]! } - public var StickerPack_ViewPack: String { return self._s[1768]! } - public var Wallet_UnknownError: String { return self._s[1769]! } + public var Channel_AdminLog_ChangeInfo: String { return self._s[1764]! } + public var Watch_Suggestion_BRB: String { return self._s[1765]! } + public var Passport_Identity_EditIdentityCard: String { return self._s[1766]! } + public var Contacts_PermissionsTitle: String { return self._s[1767]! } + public var Conversation_RestrictedInline: String { return self._s[1768]! } + public var Appearance_RemoveThemeColor: String { return self._s[1770]! } + public var StickerPack_ViewPack: String { return self._s[1771]! } + public var Wallet_UnknownError: String { return self._s[1772]! } public func Update_AppVersion(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1770]!, self._r[1770]!, [_0]) + return formatWithArgumentRanges(self._s[1773]!, self._r[1773]!, [_0]) } - public var Compose_NewChannel: String { return self._s[1772]! } - public var ChatSettings_AutoDownloadSettings_TypePhoto: String { return self._s[1775]! } - public var MessagePoll_LabelQuiz: String { return self._s[1777]! } - public var Conversation_ReportSpamGroupConfirmation: String { return self._s[1778]! } - public var Channel_Info_Stickers: String { return self._s[1779]! } - public var AutoNightTheme_PreferredTheme: String { return self._s[1780]! } - public var PrivacyPolicy_AgeVerificationAgree: String { return self._s[1781]! } - public var Passport_DeletePersonalDetails: String { return self._s[1782]! } - public var LogoutOptions_AddAccountTitle: String { return self._s[1783]! } - public var Channel_DiscussionGroupInfo: String { return self._s[1784]! } - public var Group_EditAdmin_RankOwnerPlaceholder: String { return self._s[1785]! } - public var Conversation_SearchNoResults: String { return self._s[1788]! } - public var Wallet_Configuration_ApplyErrorTextURLInvalid: String { return self._s[1789]! } - public var MessagePoll_LabelAnonymous: String { return self._s[1790]! } - public var Channel_Members_AddAdminErrorNotAMember: String { return self._s[1791]! } - public var Login_Code: String { return self._s[1792]! } - public var EditTheme_Create_BottomInfo: String { return self._s[1793]! } - public var Watch_Suggestion_WhatsUp: String { return self._s[1794]! } - public var Weekday_ShortThursday: String { return self._s[1795]! } - public var Resolve_ErrorNotFound: String { return self._s[1797]! } - public var LastSeen_Offline: String { return self._s[1798]! } - public var PeopleNearby_NoMembers: String { return self._s[1799]! } - public var GroupPermission_AddMembersNotAvailable: String { return self._s[1800]! } - public var Privacy_Calls_AlwaysAllow_Title: String { return self._s[1801]! } - public var GroupInfo_Title: String { return self._s[1803]! } - public var NotificationsSound_Note: String { return self._s[1804]! } - public var Conversation_EditingMessagePanelTitle: String { return self._s[1805]! } - public var Watch_Message_Poll: String { return self._s[1806]! } - public var Privacy_Calls: String { return self._s[1807]! } + public var Compose_NewChannel: String { return self._s[1775]! } + public var ChatSettings_AutoDownloadSettings_TypePhoto: String { return self._s[1778]! } + public var MessagePoll_LabelQuiz: String { return self._s[1780]! } + public var Conversation_ReportSpamGroupConfirmation: String { return self._s[1781]! } + public var Channel_Info_Stickers: String { return self._s[1782]! } + public var AutoNightTheme_PreferredTheme: String { return self._s[1783]! } + public var PrivacyPolicy_AgeVerificationAgree: String { return self._s[1784]! } + public var Passport_DeletePersonalDetails: String { return self._s[1785]! } + public var LogoutOptions_AddAccountTitle: String { return self._s[1786]! } + public var Channel_DiscussionGroupInfo: String { return self._s[1787]! } + public var Group_EditAdmin_RankOwnerPlaceholder: String { return self._s[1788]! } + public var Conversation_SearchNoResults: String { return self._s[1791]! } + public var Wallet_Configuration_ApplyErrorTextURLInvalid: String { return self._s[1792]! } + public var MessagePoll_LabelAnonymous: String { return self._s[1793]! } + public var Channel_Members_AddAdminErrorNotAMember: String { return self._s[1794]! } + public var Login_Code: String { return self._s[1795]! } + public var EditTheme_Create_BottomInfo: String { return self._s[1796]! } + public var Watch_Suggestion_WhatsUp: String { return self._s[1797]! } + public var Weekday_ShortThursday: String { return self._s[1798]! } + public var Resolve_ErrorNotFound: String { return self._s[1800]! } + public var LastSeen_Offline: String { return self._s[1801]! } + public var PeopleNearby_NoMembers: String { return self._s[1802]! } + public var GroupPermission_AddMembersNotAvailable: String { return self._s[1803]! } + public var Privacy_Calls_AlwaysAllow_Title: String { return self._s[1804]! } + public var GroupInfo_Title: String { return self._s[1806]! } + public var NotificationsSound_Note: String { return self._s[1807]! } + public var Conversation_EditingMessagePanelTitle: String { return self._s[1808]! } + public var Watch_Message_Poll: String { return self._s[1809]! } + public var Privacy_Calls: String { return self._s[1810]! } public func Channel_AdminLog_MessageRankUsername(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1808]!, self._r[1808]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1811]!, self._r[1811]!, [_1, _2, _3]) } - public var Month_ShortAugust: String { return self._s[1809]! } - public var TwoStepAuth_SetPasswordHelp: String { return self._s[1810]! } - public var Notifications_Reset: String { return self._s[1811]! } - public var Conversation_Pin: String { return self._s[1812]! } - public var Passport_Language_lv: String { return self._s[1813]! } - public var Permissions_PeopleNearbyAllowInSettings_v0: String { return self._s[1814]! } - public var BlockedUsers_Info: String { return self._s[1815]! } - public var SettingsSearch_Synonyms_Data_AutoplayVideos: String { return self._s[1817]! } - public var Watch_Conversation_Unblock: String { return self._s[1819]! } + public var Month_ShortAugust: String { return self._s[1812]! } + public var TwoStepAuth_SetPasswordHelp: String { return self._s[1813]! } + public var Notifications_Reset: String { return self._s[1814]! } + public var Conversation_Pin: String { return self._s[1815]! } + public var Passport_Language_lv: String { return self._s[1816]! } + public var Permissions_PeopleNearbyAllowInSettings_v0: String { return self._s[1817]! } + public var BlockedUsers_Info: String { return self._s[1818]! } + public var SettingsSearch_Synonyms_Data_AutoplayVideos: String { return self._s[1820]! } + public var Watch_Conversation_Unblock: String { return self._s[1822]! } public func Time_MonthOfYear_m9(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1820]!, self._r[1820]!, [_0]) - } - public var CloudStorage_Title: String { return self._s[1821]! } - public var GroupInfo_DeleteAndExitConfirmation: String { return self._s[1822]! } - public func NetworkUsageSettings_WifiUsageSince(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[1823]!, self._r[1823]!, [_0]) } - public var Channel_AdminLogFilter_AdminsTitle: String { return self._s[1824]! } - public var Watch_Suggestion_OnMyWay: String { return self._s[1825]! } - public var TwoStepAuth_RecoveryEmailTitle: String { return self._s[1826]! } - public var Passport_Address_EditBankStatement: String { return self._s[1827]! } - public func Channel_AdminLog_MessageChangedUnlinkedGroup(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1828]!, self._r[1828]!, [_1, _2]) + public var CloudStorage_Title: String { return self._s[1824]! } + public var GroupInfo_DeleteAndExitConfirmation: String { return self._s[1825]! } + public func NetworkUsageSettings_WifiUsageSince(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1826]!, self._r[1826]!, [_0]) } - public var ChatSettings_DownloadInBackgroundInfo: String { return self._s[1829]! } - public var ShareMenu_Comment: String { return self._s[1830]! } - public var Permissions_ContactsTitle_v0: String { return self._s[1831]! } - public var Notifications_PermissionsTitle: String { return self._s[1832]! } - public var GroupPermission_NoSendLinks: String { return self._s[1833]! } - public var Privacy_Forwards_NeverAllow_Title: String { return self._s[1834]! } - public var Wallet_SecureStorageChanged_ImportWallet: String { return self._s[1835]! } - public var Settings_Support: String { return self._s[1836]! } - public var Notifications_ChannelNotificationsSound: String { return self._s[1837]! } - public var SettingsSearch_Synonyms_Data_AutoDownloadReset: String { return self._s[1838]! } - public var Privacy_Forwards_Preview: String { return self._s[1839]! } - public var GroupPermission_ApplyAlertAction: String { return self._s[1840]! } - public var Watch_Stickers_StickerPacks: String { return self._s[1841]! } - public var Common_Select: String { return self._s[1843]! } - public var CheckoutInfo_ErrorEmailInvalid: String { return self._s[1844]! } - public var WallpaperSearch_ColorGray: String { return self._s[1847]! } - public var TwoFactorSetup_Password_PlaceholderPassword: String { return self._s[1848]! } - public var TwoFactorSetup_Hint_SkipAction: String { return self._s[1849]! } - public var ChatAdmins_AllMembersAreAdminsOffHelp: String { return self._s[1850]! } - public var PollResults_Title: String { return self._s[1851]! } - public var PasscodeSettings_AutoLock_IfAwayFor_5hours: String { return self._s[1852]! } - public var Appearance_PreviewReplyAuthor: String { return self._s[1853]! } - public var TwoStepAuth_RecoveryTitle: String { return self._s[1854]! } - public var Widget_AuthRequired: String { return self._s[1855]! } - public var Camera_FlashOn: String { return self._s[1856]! } - public var Conversation_ContextMenuLookUp: String { return self._s[1857]! } - public var Channel_Stickers_NotFoundHelp: String { return self._s[1858]! } - public var Watch_Suggestion_OK: String { return self._s[1859]! } + public var Channel_AdminLogFilter_AdminsTitle: String { return self._s[1827]! } + public var Watch_Suggestion_OnMyWay: String { return self._s[1828]! } + public var TwoStepAuth_RecoveryEmailTitle: String { return self._s[1829]! } + public var Passport_Address_EditBankStatement: String { return self._s[1830]! } + public func Channel_AdminLog_MessageChangedUnlinkedGroup(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1831]!, self._r[1831]!, [_1, _2]) + } + public var ChatSettings_DownloadInBackgroundInfo: String { return self._s[1832]! } + public var ShareMenu_Comment: String { return self._s[1833]! } + public var Permissions_ContactsTitle_v0: String { return self._s[1834]! } + public var Notifications_PermissionsTitle: String { return self._s[1835]! } + public var GroupPermission_NoSendLinks: String { return self._s[1836]! } + public var Privacy_Forwards_NeverAllow_Title: String { return self._s[1837]! } + public var Wallet_SecureStorageChanged_ImportWallet: String { return self._s[1838]! } + public var Settings_Support: String { return self._s[1839]! } + public var Notifications_ChannelNotificationsSound: String { return self._s[1840]! } + public var SettingsSearch_Synonyms_Data_AutoDownloadReset: String { return self._s[1841]! } + public var Privacy_Forwards_Preview: String { return self._s[1842]! } + public var GroupPermission_ApplyAlertAction: String { return self._s[1843]! } + public var Watch_Stickers_StickerPacks: String { return self._s[1844]! } + public var Common_Select: String { return self._s[1846]! } + public var CheckoutInfo_ErrorEmailInvalid: String { return self._s[1847]! } + public var WallpaperSearch_ColorGray: String { return self._s[1850]! } + public var TwoFactorSetup_Password_PlaceholderPassword: String { return self._s[1851]! } + public var TwoFactorSetup_Hint_SkipAction: String { return self._s[1852]! } + public var ChatAdmins_AllMembersAreAdminsOffHelp: String { return self._s[1853]! } + public var PollResults_Title: String { return self._s[1854]! } + public var PasscodeSettings_AutoLock_IfAwayFor_5hours: String { return self._s[1855]! } + public var Appearance_PreviewReplyAuthor: String { return self._s[1856]! } + public var TwoStepAuth_RecoveryTitle: String { return self._s[1857]! } + public var Widget_AuthRequired: String { return self._s[1858]! } + public var Camera_FlashOn: String { return self._s[1859]! } + public var Conversation_ContextMenuLookUp: String { return self._s[1860]! } + public var Channel_Stickers_NotFoundHelp: String { return self._s[1861]! } + public var Watch_Suggestion_OK: String { return self._s[1862]! } public func Username_LinkHint(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1861]!, self._r[1861]!, [_0]) + return formatWithArgumentRanges(self._s[1864]!, self._r[1864]!, [_0]) } public func Notification_PinnedLiveLocationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1863]!, self._r[1863]!, [_0]) + return formatWithArgumentRanges(self._s[1866]!, self._r[1866]!, [_0]) } - public var TextFormat_Strikethrough: String { return self._s[1864]! } - public var DialogList_AdLabel: String { return self._s[1865]! } - public var WatchRemote_NotificationText: String { return self._s[1866]! } - public var IntentsSettings_SuggestedChatsSavedMessages: String { return self._s[1867]! } - public var SettingsSearch_Synonyms_Notifications_MessageNotificationsAlert: String { return self._s[1868]! } - public var Conversation_ReportSpam: String { return self._s[1869]! } - public var SettingsSearch_Synonyms_Privacy_Data_TopPeers: String { return self._s[1870]! } - public var Settings_LogoutConfirmationTitle: String { return self._s[1872]! } - public var PhoneLabel_Title: String { return self._s[1873]! } - public var Passport_Address_EditRentalAgreement: String { return self._s[1874]! } - public var Settings_ChangePhoneNumber: String { return self._s[1875]! } - public var Notifications_ExceptionsTitle: String { return self._s[1876]! } - public var Notifications_AlertTones: String { return self._s[1877]! } - public var Call_ReportIncludeLogDescription: String { return self._s[1878]! } - public var SettingsSearch_Synonyms_Notifications_ResetAllNotifications: String { return self._s[1879]! } - public var AutoDownloadSettings_PrivateChats: String { return self._s[1880]! } - public var VoiceOver_Chat_Photo: String { return self._s[1882]! } - public var TwoStepAuth_AddHintTitle: String { return self._s[1883]! } - public var ReportPeer_ReasonOther: String { return self._s[1884]! } - public var ChatList_Context_JoinChannel: String { return self._s[1885]! } - public var KeyCommand_ScrollDown: String { return self._s[1887]! } - public var Conversation_ScheduleMessage_Title: String { return self._s[1888]! } + public var TextFormat_Strikethrough: String { return self._s[1867]! } + public var DialogList_AdLabel: String { return self._s[1868]! } + public var WatchRemote_NotificationText: String { return self._s[1869]! } + public var IntentsSettings_SuggestedChatsSavedMessages: String { return self._s[1870]! } + public var SettingsSearch_Synonyms_Notifications_MessageNotificationsAlert: String { return self._s[1871]! } + public var Conversation_ReportSpam: String { return self._s[1872]! } + public var SettingsSearch_Synonyms_Privacy_Data_TopPeers: String { return self._s[1873]! } + public var Settings_LogoutConfirmationTitle: String { return self._s[1875]! } + public var PhoneLabel_Title: String { return self._s[1876]! } + public var Passport_Address_EditRentalAgreement: String { return self._s[1877]! } + public var Settings_ChangePhoneNumber: String { return self._s[1878]! } + public var Notifications_ExceptionsTitle: String { return self._s[1879]! } + public var Notifications_AlertTones: String { return self._s[1880]! } + public var Call_ReportIncludeLogDescription: String { return self._s[1881]! } + public var SettingsSearch_Synonyms_Notifications_ResetAllNotifications: String { return self._s[1882]! } + public var AutoDownloadSettings_PrivateChats: String { return self._s[1883]! } + public var VoiceOver_Chat_Photo: String { return self._s[1885]! } + public var TwoStepAuth_AddHintTitle: String { return self._s[1886]! } + public var ReportPeer_ReasonOther: String { return self._s[1887]! } + public var ChatList_Context_JoinChannel: String { return self._s[1888]! } + public var KeyCommand_ScrollDown: String { return self._s[1890]! } + public var Conversation_ScheduleMessage_Title: String { return self._s[1891]! } public func Login_BannedPhoneSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1889]!, self._r[1889]!, [_0]) + return formatWithArgumentRanges(self._s[1892]!, self._r[1892]!, [_0]) } - public var NetworkUsageSettings_MediaVideoDataSection: String { return self._s[1890]! } - public var ChannelInfo_DeleteGroupConfirmation: String { return self._s[1891]! } - public var AuthSessions_LogOut: String { return self._s[1892]! } - public var Passport_Identity_TypeInternalPassport: String { return self._s[1893]! } - public var ChatSettings_AutoDownloadVoiceMessages: String { return self._s[1894]! } - public var Passport_Phone_Title: String { return self._s[1895]! } - public var ContactList_Context_StartSecretChat: String { return self._s[1896]! } - public var Settings_PhoneNumber: String { return self._s[1897]! } + public var NetworkUsageSettings_MediaVideoDataSection: String { return self._s[1893]! } + public var ChannelInfo_DeleteGroupConfirmation: String { return self._s[1894]! } + public var AuthSessions_LogOut: String { return self._s[1895]! } + public var Passport_Identity_TypeInternalPassport: String { return self._s[1896]! } + public var ChatSettings_AutoDownloadVoiceMessages: String { return self._s[1897]! } + public var Passport_Phone_Title: String { return self._s[1898]! } + public var ContactList_Context_StartSecretChat: String { return self._s[1899]! } + public var Settings_PhoneNumber: String { return self._s[1900]! } public func Conversation_ScheduleMessage_SendToday(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1898]!, self._r[1898]!, [_0]) + return formatWithArgumentRanges(self._s[1901]!, self._r[1901]!, [_0]) } - public var NotificationsSound_Alert: String { return self._s[1900]! } - public var Wallet_SecureStorageChanged_CreateWallet: String { return self._s[1901]! } - public var WebSearch_SearchNoResults: String { return self._s[1902]! } - public var Privacy_ProfilePhoto_AlwaysShareWith_Title: String { return self._s[1904]! } - public var Wallet_Configuration_SourceInfo: String { return self._s[1905]! } - public var LogoutOptions_AlternativeOptionsSection: String { return self._s[1906]! } - public var SettingsSearch_Synonyms_Passport: String { return self._s[1907]! } - public var PhotoEditor_CurvesTool: String { return self._s[1908]! } - public var Checkout_PaymentMethod: String { return self._s[1910]! } + public var NotificationsSound_Alert: String { return self._s[1903]! } + public var Wallet_SecureStorageChanged_CreateWallet: String { return self._s[1904]! } + public var WebSearch_SearchNoResults: String { return self._s[1905]! } + public var Privacy_ProfilePhoto_AlwaysShareWith_Title: String { return self._s[1907]! } + public var Wallet_Configuration_SourceInfo: String { return self._s[1908]! } + public var LogoutOptions_AlternativeOptionsSection: String { return self._s[1909]! } + public var SettingsSearch_Synonyms_Passport: String { return self._s[1910]! } + public var PhotoEditor_CurvesTool: String { return self._s[1911]! } + public var Checkout_PaymentMethod: String { return self._s[1913]! } public func PUSH_CHAT_ADD_YOU(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1911]!, self._r[1911]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1914]!, self._r[1914]!, [_1, _2]) } - public var Contacts_AccessDeniedError: String { return self._s[1912]! } - public var Camera_PhotoMode: String { return self._s[1915]! } - public var EditTheme_Expand_Preview_IncomingText: String { return self._s[1916]! } - public var Appearance_TextSize_Apply: String { return self._s[1917]! } - public var Passport_Address_AddUtilityBill: String { return self._s[1919]! } - public var CallSettings_OnMobile: String { return self._s[1920]! } - public var Tour_Text2: String { return self._s[1921]! } + public var Contacts_AccessDeniedError: String { return self._s[1915]! } + public var Camera_PhotoMode: String { return self._s[1918]! } + public var EditTheme_Expand_Preview_IncomingText: String { return self._s[1919]! } + public var Appearance_TextSize_Apply: String { return self._s[1920]! } + public var Passport_Address_AddUtilityBill: String { return self._s[1922]! } + public var CallSettings_OnMobile: String { return self._s[1923]! } + public var Tour_Text2: String { return self._s[1924]! } public func PUSH_CHAT_MESSAGE_ROUND(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1922]!, self._r[1922]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1925]!, self._r[1925]!, [_1, _2]) } - public var DialogList_EncryptionProcessing: String { return self._s[1924]! } - public var Permissions_Skip: String { return self._s[1925]! } - public var Wallet_Words_NotDoneOk: String { return self._s[1926]! } - public var SecretImage_Title: String { return self._s[1927]! } - public var Watch_MessageView_Title: String { return self._s[1928]! } - public var Channel_DiscussionGroupAdd: String { return self._s[1929]! } - public var AttachmentMenu_Poll: String { return self._s[1930]! } + public var DialogList_EncryptionProcessing: String { return self._s[1927]! } + public var Permissions_Skip: String { return self._s[1928]! } + public var Wallet_Words_NotDoneOk: String { return self._s[1929]! } + public var SecretImage_Title: String { return self._s[1930]! } + public var Watch_MessageView_Title: String { return self._s[1931]! } + public var Channel_DiscussionGroupAdd: String { return self._s[1932]! } + public var AttachmentMenu_Poll: String { return self._s[1933]! } public func Notification_GroupInviter(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1931]!, self._r[1931]!, [_0]) + return formatWithArgumentRanges(self._s[1934]!, self._r[1934]!, [_0]) } public func Channel_DiscussionGroup_PrivateChannelLink(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1932]!, self._r[1932]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1935]!, self._r[1935]!, [_1, _2]) } - public var Notification_CallCanceled: String { return self._s[1933]! } - public var WallpaperPreview_Title: String { return self._s[1934]! } - public var Privacy_PaymentsClear_PaymentInfo: String { return self._s[1935]! } - public var Settings_ProxyConnecting: String { return self._s[1936]! } - public var Settings_CheckPhoneNumberText: String { return self._s[1938]! } - public var VoiceOver_Chat_YourVideo: String { return self._s[1939]! } - public var Wallet_Intro_Title: String { return self._s[1940]! } - public var TwoFactorSetup_Password_Action: String { return self._s[1941]! } - public var Profile_MessageLifetime5s: String { return self._s[1942]! } - public var Username_InvalidCharacters: String { return self._s[1943]! } - public var VoiceOver_Media_PlaybackRateFast: String { return self._s[1944]! } - public var ScheduledMessages_ClearAll: String { return self._s[1945]! } - public var WallpaperPreview_CropBottomText: String { return self._s[1946]! } - public var AutoDownloadSettings_LimitBySize: String { return self._s[1947]! } - public var Settings_AddAccount: String { return self._s[1948]! } - public var Notification_CreatedChannel: String { return self._s[1951]! } + public var Notification_CallCanceled: String { return self._s[1936]! } + public var WallpaperPreview_Title: String { return self._s[1937]! } + public var Privacy_PaymentsClear_PaymentInfo: String { return self._s[1938]! } + public var Settings_ProxyConnecting: String { return self._s[1939]! } + public var Settings_CheckPhoneNumberText: String { return self._s[1941]! } + public var VoiceOver_Chat_YourVideo: String { return self._s[1942]! } + public var Wallet_Intro_Title: String { return self._s[1943]! } + public var TwoFactorSetup_Password_Action: String { return self._s[1944]! } + public var Profile_MessageLifetime5s: String { return self._s[1945]! } + public var Username_InvalidCharacters: String { return self._s[1946]! } + public var VoiceOver_Media_PlaybackRateFast: String { return self._s[1947]! } + public var ScheduledMessages_ClearAll: String { return self._s[1948]! } + public var WallpaperPreview_CropBottomText: String { return self._s[1949]! } + public var AutoDownloadSettings_LimitBySize: String { return self._s[1950]! } + public var Settings_AddAccount: String { return self._s[1951]! } + public var Notification_CreatedChannel: String { return self._s[1954]! } public func PUSH_CHAT_DELETE_MEMBER(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1952]!, self._r[1952]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1955]!, self._r[1955]!, [_1, _2, _3]) } - public var Passcode_AppLockedAlert: String { return self._s[1954]! } - public var StickerPacksSettings_AnimatedStickersInfo: String { return self._s[1955]! } - public var VoiceOver_Media_PlaybackStop: String { return self._s[1956]! } - public var Contacts_TopSection: String { return self._s[1957]! } - public var ChatList_DeleteForEveryoneConfirmationAction: String { return self._s[1958]! } + public var Passcode_AppLockedAlert: String { return self._s[1957]! } + public var StickerPacksSettings_AnimatedStickersInfo: String { return self._s[1958]! } + public var VoiceOver_Media_PlaybackStop: String { return self._s[1959]! } + public var Contacts_TopSection: String { return self._s[1960]! } + public var ChatList_DeleteForEveryoneConfirmationAction: String { return self._s[1961]! } public func Conversation_SetReminder_RemindOn(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1959]!, self._r[1959]!, [_0, _1]) + return formatWithArgumentRanges(self._s[1962]!, self._r[1962]!, [_0, _1]) } - public var Wallet_Info_Receive: String { return self._s[1960]! } - public var Wallet_Completed_ViewWallet: String { return self._s[1961]! } + public var Wallet_Info_Receive: String { return self._s[1963]! } + public var Wallet_Completed_ViewWallet: String { return self._s[1964]! } public func Time_MonthOfYear_m6(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1962]!, self._r[1962]!, [_0]) + return formatWithArgumentRanges(self._s[1965]!, self._r[1965]!, [_0]) } - public var ReportPeer_ReasonSpam: String { return self._s[1963]! } - public var UserInfo_TapToCall: String { return self._s[1964]! } - public var Conversation_ForwardAuthorHiddenTooltip: String { return self._s[1966]! } - public var AutoDownloadSettings_DataUsageCustom: String { return self._s[1967]! } - public var Common_Search: String { return self._s[1968]! } - public var ScheduledMessages_EmptyPlaceholder: String { return self._s[1969]! } + public var ReportPeer_ReasonSpam: String { return self._s[1966]! } + public var UserInfo_TapToCall: String { return self._s[1967]! } + public var Conversation_ForwardAuthorHiddenTooltip: String { return self._s[1969]! } + public var AutoDownloadSettings_DataUsageCustom: String { return self._s[1970]! } + public var Common_Search: String { return self._s[1971]! } + public var ScheduledMessages_EmptyPlaceholder: String { return self._s[1972]! } public func Channel_AdminLog_MessageChangedGroupGeoLocation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1970]!, self._r[1970]!, [_0]) + return formatWithArgumentRanges(self._s[1973]!, self._r[1973]!, [_0]) } - public var Wallet_Month_ShortJuly: String { return self._s[1971]! } - public var AuthSessions_IncompleteAttemptsInfo: String { return self._s[1973]! } - public var Message_InvoiceLabel: String { return self._s[1974]! } - public var Conversation_InputTextPlaceholder: String { return self._s[1975]! } - public var NetworkUsageSettings_MediaImageDataSection: String { return self._s[1976]! } + public var Wallet_Month_ShortJuly: String { return self._s[1974]! } + public var AuthSessions_IncompleteAttemptsInfo: String { return self._s[1976]! } + public var Message_InvoiceLabel: String { return self._s[1977]! } + public var Conversation_InputTextPlaceholder: String { return self._s[1978]! } + public var NetworkUsageSettings_MediaImageDataSection: String { return self._s[1979]! } public func Passport_Address_UploadOneOfScan(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1977]!, self._r[1977]!, [_0]) + return formatWithArgumentRanges(self._s[1980]!, self._r[1980]!, [_0]) } - public var IntentsSettings_Reset: String { return self._s[1978]! } - public var Conversation_Info: String { return self._s[1979]! } - public var Login_InfoDeletePhoto: String { return self._s[1980]! } - public var Passport_Language_vi: String { return self._s[1982]! } - public var UserInfo_ScamUserWarning: String { return self._s[1983]! } - public var Conversation_Search: String { return self._s[1984]! } - public var DialogList_DeleteBotConversationConfirmation: String { return self._s[1986]! } - public var ReportPeer_ReasonPornography: String { return self._s[1987]! } - public var AutoDownloadSettings_PhotosTitle: String { return self._s[1988]! } - public var Conversation_SendMessageErrorGroupRestricted: String { return self._s[1989]! } - public var Map_LiveLocationGroupDescription: String { return self._s[1990]! } - public var Channel_Setup_TypeHeader: String { return self._s[1991]! } - public var AuthSessions_LoggedIn: String { return self._s[1992]! } - public var Privacy_Forwards_AlwaysAllow_Title: String { return self._s[1993]! } - public var Login_SmsRequestState3: String { return self._s[1994]! } - public var Passport_Address_EditUtilityBill: String { return self._s[1995]! } - public var Appearance_ReduceMotionInfo: String { return self._s[1996]! } - public var Join_ChannelsTooMuch: String { return self._s[1997]! } - public var Channel_Edit_LinkItem: String { return self._s[1998]! } - public var Privacy_Calls_P2PNever: String { return self._s[1999]! } - public var Conversation_AddToReadingList: String { return self._s[2001]! } - public var Share_MultipleMessagesDisabled: String { return self._s[2002]! } - public var Message_Animation: String { return self._s[2003]! } - public var Conversation_DefaultRestrictedMedia: String { return self._s[2004]! } - public var Map_Unknown: String { return self._s[2005]! } - public var AutoDownloadSettings_LastDelimeter: String { return self._s[2006]! } + public var IntentsSettings_Reset: String { return self._s[1981]! } + public var Conversation_Info: String { return self._s[1982]! } + public var Login_InfoDeletePhoto: String { return self._s[1983]! } + public var Passport_Language_vi: String { return self._s[1985]! } + public var UserInfo_ScamUserWarning: String { return self._s[1986]! } + public var Conversation_Search: String { return self._s[1987]! } + public var DialogList_DeleteBotConversationConfirmation: String { return self._s[1989]! } + public var ReportPeer_ReasonPornography: String { return self._s[1990]! } + public var AutoDownloadSettings_PhotosTitle: String { return self._s[1991]! } + public var Conversation_SendMessageErrorGroupRestricted: String { return self._s[1992]! } + public var Map_LiveLocationGroupDescription: String { return self._s[1993]! } + public var Channel_Setup_TypeHeader: String { return self._s[1994]! } + public var AuthSessions_LoggedIn: String { return self._s[1995]! } + public var Privacy_Forwards_AlwaysAllow_Title: String { return self._s[1996]! } + public var Login_SmsRequestState3: String { return self._s[1997]! } + public var Passport_Address_EditUtilityBill: String { return self._s[1998]! } + public var Appearance_ReduceMotionInfo: String { return self._s[1999]! } + public var Join_ChannelsTooMuch: String { return self._s[2000]! } + public var Channel_Edit_LinkItem: String { return self._s[2001]! } + public var Privacy_Calls_P2PNever: String { return self._s[2002]! } + public var Conversation_AddToReadingList: String { return self._s[2004]! } + public var Share_MultipleMessagesDisabled: String { return self._s[2005]! } + public var Message_Animation: String { return self._s[2006]! } + public var Conversation_DefaultRestrictedMedia: String { return self._s[2007]! } + public var Map_Unknown: String { return self._s[2008]! } + public var AutoDownloadSettings_LastDelimeter: String { return self._s[2009]! } public func PUSH_PINNED_TEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2007]!, self._r[2007]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2010]!, self._r[2010]!, [_1, _2]) } public func Passport_FieldOneOf_Or(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2008]!, self._r[2008]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2011]!, self._r[2011]!, [_1, _2]) } - public var Call_StatusRequesting: String { return self._s[2009]! } - public var Conversation_SecretChatContextBotAlert: String { return self._s[2010]! } - public var SocksProxySetup_ProxyStatusChecking: String { return self._s[2011]! } + public var Call_StatusRequesting: String { return self._s[2012]! } + public var Conversation_SecretChatContextBotAlert: String { return self._s[2013]! } + public var SocksProxySetup_ProxyStatusChecking: String { return self._s[2014]! } public func PUSH_CHAT_MESSAGE_DOC(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2012]!, self._r[2012]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2015]!, self._r[2015]!, [_1, _2]) } public func Notification_PinnedLocationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2013]!, self._r[2013]!, [_0]) + return formatWithArgumentRanges(self._s[2016]!, self._r[2016]!, [_0]) } - public var Update_Skip: String { return self._s[2014]! } - public var Group_Username_RemoveExistingUsernamesInfo: String { return self._s[2015]! } - public var Message_PinnedPollMessage: String { return self._s[2016]! } - public var BlockedUsers_Title: String { return self._s[2017]! } + public var Update_Skip: String { return self._s[2017]! } + public var Group_Username_RemoveExistingUsernamesInfo: String { return self._s[2018]! } + public var BlockedUsers_Title: String { return self._s[2019]! } + public var Weekday_Monday: String { return self._s[2020]! } public func PUSH_CHANNEL_MESSAGE_AUDIO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2018]!, self._r[2018]!, [_1]) + return formatWithArgumentRanges(self._s[2021]!, self._r[2021]!, [_1]) } - public var Username_CheckingUsername: String { return self._s[2019]! } - public var NotificationsSound_Bell: String { return self._s[2020]! } - public var Conversation_SendMessageErrorFlood: String { return self._s[2021]! } - public var Weekday_Monday: String { return self._s[2022]! } - public var SettingsSearch_Synonyms_Notifications_DisplayNamesOnLockScreen: String { return self._s[2023]! } - public var ChannelMembers_ChannelAdminsTitle: String { return self._s[2024]! } - public var ChatSettings_Groups: String { return self._s[2025]! } - public var WallpaperPreview_PatternPaternDiscard: String { return self._s[2026]! } + public var Username_CheckingUsername: String { return self._s[2022]! } + public var NotificationsSound_Bell: String { return self._s[2023]! } + public var Conversation_SendMessageErrorFlood: String { return self._s[2024]! } + public var SettingsSearch_Synonyms_Notifications_DisplayNamesOnLockScreen: String { return self._s[2025]! } + public var ChannelMembers_ChannelAdminsTitle: String { return self._s[2026]! } + public var ChatSettings_Groups: String { return self._s[2027]! } + public var WallpaperPreview_PatternPaternDiscard: String { return self._s[2028]! } public func Conversation_SetReminder_RemindTomorrow(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2027]!, self._r[2027]!, [_0]) + return formatWithArgumentRanges(self._s[2029]!, self._r[2029]!, [_0]) } - public var Your_card_was_declined: String { return self._s[2028]! } - public var TwoStepAuth_EnterPasswordHelp: String { return self._s[2030]! } - public var Wallet_Month_ShortApril: String { return self._s[2031]! } - public var ChatList_Unmute: String { return self._s[2032]! } - public var AuthSessions_AddDevice_ScanTitle: String { return self._s[2033]! } - public var PhotoEditor_CurvesAll: String { return self._s[2034]! } - public var Weekday_ShortTuesday: String { return self._s[2035]! } - public var DialogList_Read: String { return self._s[2036]! } - public var Appearance_AppIconClassic: String { return self._s[2037]! } - public var ChannelMembers_WhoCanAddMembers_AllMembers: String { return self._s[2038]! } - public var Passport_Identity_Gender: String { return self._s[2039]! } + public var Your_card_was_declined: String { return self._s[2030]! } + public var TwoStepAuth_EnterPasswordHelp: String { return self._s[2032]! } + public var Wallet_Month_ShortApril: String { return self._s[2033]! } + public var ChatList_Unmute: String { return self._s[2034]! } + public var AuthSessions_AddDevice_ScanTitle: String { return self._s[2035]! } + public var PhotoEditor_CurvesAll: String { return self._s[2036]! } + public var Weekday_ShortTuesday: String { return self._s[2037]! } + public var DialogList_Read: String { return self._s[2038]! } + public var Appearance_AppIconClassic: String { return self._s[2039]! } + public var ChannelMembers_WhoCanAddMembers_AllMembers: String { return self._s[2040]! } + public var Passport_Identity_Gender: String { return self._s[2041]! } public func Target_ShareGameConfirmationPrivate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2040]!, self._r[2040]!, [_0]) + return formatWithArgumentRanges(self._s[2042]!, self._r[2042]!, [_0]) } - public var Target_SelectGroup: String { return self._s[2041]! } - public var Map_HomeAndWorkInfo: String { return self._s[2043]! } + public var Target_SelectGroup: String { return self._s[2043]! } + public var Map_HomeAndWorkInfo: String { return self._s[2045]! } public func DialogList_EncryptedChatStartedIncoming(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2044]!, self._r[2044]!, [_0]) + return formatWithArgumentRanges(self._s[2046]!, self._r[2046]!, [_0]) } - public var Passport_Language_en: String { return self._s[2045]! } - public var AutoDownloadSettings_AutodownloadPhotos: String { return self._s[2046]! } - public var Channel_Username_CreatePublicLinkHelp: String { return self._s[2047]! } - public var Login_CancelPhoneVerificationContinue: String { return self._s[2048]! } - public var ScheduledMessages_SendNow: String { return self._s[2049]! } - public var Checkout_NewCard_PaymentCard: String { return self._s[2051]! } - public var Login_InfoHelp: String { return self._s[2052]! } - public var Contacts_PermissionsSuppressWarningTitle: String { return self._s[2053]! } - public var SettingsSearch_Synonyms_Stickers_FeaturedPacks: String { return self._s[2054]! } + public var Passport_Language_en: String { return self._s[2047]! } + public var AutoDownloadSettings_AutodownloadPhotos: String { return self._s[2048]! } + public var Channel_Username_CreatePublicLinkHelp: String { return self._s[2049]! } + public var Login_CancelPhoneVerificationContinue: String { return self._s[2050]! } + public var ScheduledMessages_SendNow: String { return self._s[2051]! } + public var Checkout_NewCard_PaymentCard: String { return self._s[2053]! } + public var Login_InfoHelp: String { return self._s[2054]! } + public var Contacts_PermissionsSuppressWarningTitle: String { return self._s[2055]! } + public var SettingsSearch_Synonyms_Stickers_FeaturedPacks: String { return self._s[2056]! } public func Channel_AdminLog_MessageChangedLinkedChannel(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2055]!, self._r[2055]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2057]!, self._r[2057]!, [_1, _2]) } - public var SocksProxySetup_AddProxy: String { return self._s[2058]! } - public var CreatePoll_Title: String { return self._s[2059]! } - public var MessagePoll_QuizNoUsers: String { return self._s[2060]! } - public var Conversation_ViewTheme: String { return self._s[2061]! } - public var SettingsSearch_Synonyms_Privacy_Data_SecretChatLinkPreview: String { return self._s[2062]! } - public var PasscodeSettings_SimplePasscodeHelp: String { return self._s[2063]! } - public var TwoFactorSetup_Intro_Text: String { return self._s[2064]! } - public var UserInfo_GroupsInCommon: String { return self._s[2065]! } - public var TelegramWallet_Intro_TermsUrl: String { return self._s[2066]! } - public var Call_AudioRouteHide: String { return self._s[2067]! } + public var SocksProxySetup_AddProxy: String { return self._s[2060]! } + public var CreatePoll_Title: String { return self._s[2061]! } + public var MessagePoll_QuizNoUsers: String { return self._s[2062]! } + public var Conversation_ViewTheme: String { return self._s[2063]! } + public var SettingsSearch_Synonyms_Privacy_Data_SecretChatLinkPreview: String { return self._s[2064]! } + public var PasscodeSettings_SimplePasscodeHelp: String { return self._s[2065]! } + public var TwoFactorSetup_Intro_Text: String { return self._s[2066]! } + public var UserInfo_GroupsInCommon: String { return self._s[2067]! } + public var TelegramWallet_Intro_TermsUrl: String { return self._s[2068]! } + public var Call_AudioRouteHide: String { return self._s[2069]! } public func Wallet_Info_TransactionDateHeader(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2069]!, self._r[2069]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2071]!, self._r[2071]!, [_1, _2]) } - public var ContactInfo_PhoneLabelMobile: String { return self._s[2070]! } - public var IntentsSettings_SuggestedChatsInfo: String { return self._s[2071]! } - public var CreatePoll_QuizOptionsHeader: String { return self._s[2072]! } + public var ContactInfo_PhoneLabelMobile: String { return self._s[2072]! } + public var IntentsSettings_SuggestedChatsInfo: String { return self._s[2073]! } + public var CreatePoll_QuizOptionsHeader: String { return self._s[2074]! } public func ChatList_LeaveGroupConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2073]!, self._r[2073]!, [_0]) + return formatWithArgumentRanges(self._s[2075]!, self._r[2075]!, [_0]) } - public var TextFormat_Bold: String { return self._s[2074]! } - public var FastTwoStepSetup_EmailSection: String { return self._s[2075]! } - public var StickerPackActionInfo_AddedTitle: String { return self._s[2076]! } - public var Notifications_Title: String { return self._s[2077]! } - public var Group_Username_InvalidTooShort: String { return self._s[2078]! } - public var Channel_ErrorAddTooMuch: String { return self._s[2079]! } + public var TextFormat_Bold: String { return self._s[2076]! } + public var FastTwoStepSetup_EmailSection: String { return self._s[2077]! } + public var StickerPackActionInfo_AddedTitle: String { return self._s[2078]! } + public var Notifications_Title: String { return self._s[2079]! } + public var Group_Username_InvalidTooShort: String { return self._s[2080]! } + public var Channel_ErrorAddTooMuch: String { return self._s[2081]! } public func DialogList_MultipleTypingSuffix(_ _0: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2080]!, self._r[2080]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[2082]!, self._r[2082]!, ["\(_0)"]) } - public var VoiceOver_DiscardPreparedContent: String { return self._s[2082]! } - public var Stickers_SuggestAdded: String { return self._s[2083]! } - public var Login_CountryCode: String { return self._s[2084]! } - public var ChatSettings_AutoPlayVideos: String { return self._s[2085]! } - public var Map_GetDirections: String { return self._s[2086]! } - public var Wallet_Receive_ShareInvoiceUrl: String { return self._s[2087]! } - public var Login_PhoneFloodError: String { return self._s[2088]! } + public var VoiceOver_DiscardPreparedContent: String { return self._s[2084]! } + public var Stickers_SuggestAdded: String { return self._s[2085]! } + public var Login_CountryCode: String { return self._s[2086]! } + public var ChatSettings_AutoPlayVideos: String { return self._s[2087]! } + public var Map_GetDirections: String { return self._s[2088]! } + public var Wallet_Receive_ShareInvoiceUrl: String { return self._s[2089]! } + public var Login_PhoneFloodError: String { return self._s[2090]! } public func Time_MonthOfYear_m3(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2089]!, self._r[2089]!, [_0]) + return formatWithArgumentRanges(self._s[2091]!, self._r[2091]!, [_0]) } public func Wallet_Time_PreciseDate_m10(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2090]!, self._r[2090]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2092]!, self._r[2092]!, [_1, _2, _3]) } - public var IntentsSettings_SuggestedChatsPrivateChats: String { return self._s[2091]! } - public var Settings_SetUsername: String { return self._s[2093]! } - public var Group_Location_ChangeLocation: String { return self._s[2094]! } - public var Notification_GroupInviterSelf: String { return self._s[2095]! } - public var InstantPage_TapToOpenLink: String { return self._s[2096]! } + public var IntentsSettings_SuggestedChatsPrivateChats: String { return self._s[2093]! } + public var Settings_SetUsername: String { return self._s[2095]! } + public var Group_Location_ChangeLocation: String { return self._s[2096]! } + public var Notification_GroupInviterSelf: String { return self._s[2097]! } + public var InstantPage_TapToOpenLink: String { return self._s[2098]! } public func Notification_ChannelInviter(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2097]!, self._r[2097]!, [_0]) + return formatWithArgumentRanges(self._s[2099]!, self._r[2099]!, [_0]) } - public var Watch_Suggestion_TalkLater: String { return self._s[2098]! } - public var SecretChat_Title: String { return self._s[2099]! } - public var Group_UpgradeNoticeText1: String { return self._s[2100]! } - public var AuthSessions_Title: String { return self._s[2101]! } + public var Watch_Suggestion_TalkLater: String { return self._s[2100]! } + public var SecretChat_Title: String { return self._s[2101]! } + public var Group_UpgradeNoticeText1: String { return self._s[2102]! } + public var AuthSessions_Title: String { return self._s[2103]! } public func TextFormat_AddLinkText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2102]!, self._r[2102]!, [_0]) + return formatWithArgumentRanges(self._s[2104]!, self._r[2104]!, [_0]) } - public var PhotoEditor_CropAuto: String { return self._s[2103]! } - public var Channel_About_Title: String { return self._s[2104]! } - public var Theme_ThemeChanged: String { return self._s[2105]! } - public var FastTwoStepSetup_EmailHelp: String { return self._s[2106]! } + public var PhotoEditor_CropAuto: String { return self._s[2105]! } + public var Channel_About_Title: String { return self._s[2106]! } + public var Theme_ThemeChanged: String { return self._s[2107]! } + public var FastTwoStepSetup_EmailHelp: String { return self._s[2108]! } public func Conversation_Bytes(_ _0: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2108]!, self._r[2108]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[2110]!, self._r[2110]!, ["\(_0)"]) } - public var VoiceOver_MessageContextReport: String { return self._s[2109]! } - public var Conversation_PinMessageAlert_OnlyPin: String { return self._s[2111]! } - public var Group_Setup_HistoryVisibleHelp: String { return self._s[2112]! } + public var VoiceOver_MessageContextReport: String { return self._s[2111]! } + public var Conversation_PinMessageAlert_OnlyPin: String { return self._s[2113]! } + public var Group_Setup_HistoryVisibleHelp: String { return self._s[2114]! } public func PUSH_MESSAGE_GIF(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2113]!, self._r[2113]!, [_1]) + return formatWithArgumentRanges(self._s[2115]!, self._r[2115]!, [_1]) } public func SharedMedia_SearchNoResultsDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2115]!, self._r[2115]!, [_0]) + return formatWithArgumentRanges(self._s[2117]!, self._r[2117]!, [_0]) } public func TwoStepAuth_RecoveryEmailUnavailable(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2116]!, self._r[2116]!, [_0]) + return formatWithArgumentRanges(self._s[2118]!, self._r[2118]!, [_0]) } - public var Privacy_PaymentsClearInfoHelp: String { return self._s[2117]! } - public var Presence_online: String { return self._s[2120]! } - public var PasscodeSettings_Title: String { return self._s[2121]! } - public var Passport_Identity_ExpiryDatePlaceholder: String { return self._s[2122]! } - public var Web_OpenExternal: String { return self._s[2123]! } - public var AutoDownloadSettings_AutoDownload: String { return self._s[2125]! } - public var Channel_OwnershipTransfer_EnterPasswordText: String { return self._s[2126]! } - public var LocalGroup_Title: String { return self._s[2127]! } + public var Privacy_PaymentsClearInfoHelp: String { return self._s[2119]! } + public var Presence_online: String { return self._s[2122]! } + public var PasscodeSettings_Title: String { return self._s[2123]! } + public var Passport_Identity_ExpiryDatePlaceholder: String { return self._s[2124]! } + public var Web_OpenExternal: String { return self._s[2125]! } + public var AutoDownloadSettings_AutoDownload: String { return self._s[2127]! } + public var Channel_OwnershipTransfer_EnterPasswordText: String { return self._s[2128]! } + public var LocalGroup_Title: String { return self._s[2129]! } public func AutoNightTheme_AutomaticHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2128]!, self._r[2128]!, [_0]) + return formatWithArgumentRanges(self._s[2130]!, self._r[2130]!, [_0]) } - public var FastTwoStepSetup_PasswordConfirmationPlaceholder: String { return self._s[2129]! } - public var Conversation_StopQuizConfirmation: String { return self._s[2130]! } - public var Map_YouAreHere: String { return self._s[2131]! } + public var FastTwoStepSetup_PasswordConfirmationPlaceholder: String { return self._s[2131]! } + public var Conversation_StopQuizConfirmation: String { return self._s[2132]! } + public var Map_YouAreHere: String { return self._s[2133]! } public func AuthSessions_Message(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2132]!, self._r[2132]!, [_0]) + return formatWithArgumentRanges(self._s[2134]!, self._r[2134]!, [_0]) } public func ChatList_DeleteChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2133]!, self._r[2133]!, [_0]) + return formatWithArgumentRanges(self._s[2135]!, self._r[2135]!, [_0]) } - public var Theme_Context_ChangeColors: String { return self._s[2134]! } - public var PrivacyLastSeenSettings_AlwaysShareWith: String { return self._s[2135]! } - public var Target_InviteToGroupErrorAlreadyInvited: String { return self._s[2136]! } + public var Theme_Context_ChangeColors: String { return self._s[2136]! } + public var PrivacyLastSeenSettings_AlwaysShareWith: String { return self._s[2137]! } + public var Target_InviteToGroupErrorAlreadyInvited: String { return self._s[2138]! } public func AuthSessions_AppUnofficial(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2137]!, self._r[2137]!, [_0]) + return formatWithArgumentRanges(self._s[2139]!, self._r[2139]!, [_0]) } public func DialogList_LiveLocationSharingTo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2138]!, self._r[2138]!, [_0]) + return formatWithArgumentRanges(self._s[2140]!, self._r[2140]!, [_0]) } - public var SocksProxySetup_Username: String { return self._s[2139]! } - public var Bot_Start: String { return self._s[2140]! } + public var SocksProxySetup_Username: String { return self._s[2141]! } + public var Bot_Start: String { return self._s[2142]! } public func Channel_AdminLog_EmptyFilterQueryText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2141]!, self._r[2141]!, [_0]) + return formatWithArgumentRanges(self._s[2143]!, self._r[2143]!, [_0]) } public func Channel_AdminLog_MessagePinned(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2142]!, self._r[2142]!, [_0]) + return formatWithArgumentRanges(self._s[2144]!, self._r[2144]!, [_0]) } - public var Contacts_SortByPresence: String { return self._s[2143]! } - public var AccentColor_Title: String { return self._s[2145]! } - public var Conversation_DiscardVoiceMessageTitle: String { return self._s[2146]! } + public var Contacts_SortByPresence: String { return self._s[2145]! } + public var AccentColor_Title: String { return self._s[2147]! } + public var Conversation_DiscardVoiceMessageTitle: String { return self._s[2148]! } public func PUSH_CHAT_CREATED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2147]!, self._r[2147]!, [_1, _2]) - } - public func PrivacySettings_LastSeenContactsMinus(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2148]!, self._r[2148]!, [_0]) - } - public func Channel_AdminLog_MessageChangedLinkedGroup(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2149]!, self._r[2149]!, [_1, _2]) } - public var Passport_Email_EnterOtherEmail: String { return self._s[2150]! } - public var Login_InfoAvatarPhoto: String { return self._s[2151]! } - public var Privacy_PaymentsClear_ShippingInfo: String { return self._s[2152]! } - public var Tour_Title4: String { return self._s[2153]! } - public var Passport_Identity_Translation: String { return self._s[2154]! } - public var SettingsSearch_Synonyms_Notifications_ContactJoined: String { return self._s[2155]! } - public var Login_TermsOfServiceLabel: String { return self._s[2157]! } - public var Passport_Language_it: String { return self._s[2158]! } - public var KeyCommand_JumpToNextUnreadChat: String { return self._s[2159]! } - public var Passport_Identity_SelfieHelp: String { return self._s[2160]! } - public var Conversation_ClearAll: String { return self._s[2162]! } - public var Wallet_Send_UninitializedText: String { return self._s[2164]! } - public var Channel_OwnershipTransfer_Title: String { return self._s[2165]! } - public var TwoStepAuth_FloodError: String { return self._s[2166]! } + public func PrivacySettings_LastSeenContactsMinus(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2150]!, self._r[2150]!, [_0]) + } + public func Channel_AdminLog_MessageChangedLinkedGroup(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2151]!, self._r[2151]!, [_1, _2]) + } + public var Passport_Email_EnterOtherEmail: String { return self._s[2152]! } + public var Login_InfoAvatarPhoto: String { return self._s[2153]! } + public var Privacy_PaymentsClear_ShippingInfo: String { return self._s[2154]! } + public var Tour_Title4: String { return self._s[2155]! } + public var Passport_Identity_Translation: String { return self._s[2156]! } + public var SettingsSearch_Synonyms_Notifications_ContactJoined: String { return self._s[2157]! } + public var Login_TermsOfServiceLabel: String { return self._s[2159]! } + public var Passport_Language_it: String { return self._s[2160]! } + public var KeyCommand_JumpToNextUnreadChat: String { return self._s[2161]! } + public var Passport_Identity_SelfieHelp: String { return self._s[2162]! } + public var Conversation_ClearAll: String { return self._s[2164]! } + public var Wallet_Send_UninitializedText: String { return self._s[2166]! } + public var Channel_OwnershipTransfer_Title: String { return self._s[2167]! } + public var TwoStepAuth_FloodError: String { return self._s[2168]! } public func PUSH_CHANNEL_MESSAGE_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2167]!, self._r[2167]!, [_1]) + return formatWithArgumentRanges(self._s[2169]!, self._r[2169]!, [_1]) } - public var Paint_Delete: String { return self._s[2168]! } + public var Paint_Delete: String { return self._s[2170]! } public func Wallet_Sent_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2169]!, self._r[2169]!, [_0]) + return formatWithArgumentRanges(self._s[2171]!, self._r[2171]!, [_0]) } - public var Privacy_AddNewPeer: String { return self._s[2170]! } + public var Privacy_AddNewPeer: String { return self._s[2172]! } public func Channel_AdminLog_MessageRank(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2171]!, self._r[2171]!, [_1]) + return formatWithArgumentRanges(self._s[2173]!, self._r[2173]!, [_1]) } - public var LogoutOptions_SetPasscodeText: String { return self._s[2172]! } + public var LogoutOptions_SetPasscodeText: String { return self._s[2174]! } public func Passport_AcceptHelp(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2173]!, self._r[2173]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2175]!, self._r[2175]!, [_1, _2]) } - public var Message_PinnedAudioMessage: String { return self._s[2174]! } + public var Message_PinnedAudioMessage: String { return self._s[2176]! } public func Watch_Time_ShortTodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2175]!, self._r[2175]!, [_0]) + return formatWithArgumentRanges(self._s[2177]!, self._r[2177]!, [_0]) } - public var Notification_Mute1hMin: String { return self._s[2176]! } - public var Notifications_GroupNotificationsSound: String { return self._s[2177]! } - public var Wallet_Month_GenNovember: String { return self._s[2178]! } - public var SocksProxySetup_ShareProxyList: String { return self._s[2179]! } - public var Conversation_MessageEditedLabel: String { return self._s[2180]! } + public var Notification_Mute1hMin: String { return self._s[2178]! } + public var Notifications_GroupNotificationsSound: String { return self._s[2179]! } + public var Wallet_Month_GenNovember: String { return self._s[2180]! } + public var SocksProxySetup_ShareProxyList: String { return self._s[2181]! } + public var Conversation_MessageEditedLabel: String { return self._s[2182]! } public func ClearCache_Success(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2181]!, self._r[2181]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2183]!, self._r[2183]!, [_0, _1]) } - public var Notification_Exceptions_AlwaysOff: String { return self._s[2182]! } - public var Notification_Exceptions_NewException_MessagePreviewHeader: String { return self._s[2183]! } + public var Notification_Exceptions_AlwaysOff: String { return self._s[2184]! } + public var Notification_Exceptions_NewException_MessagePreviewHeader: String { return self._s[2185]! } public func Channel_AdminLog_MessageAdmin(_ _0: String, _ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2184]!, self._r[2184]!, [_0, _1, _2]) + return formatWithArgumentRanges(self._s[2186]!, self._r[2186]!, [_0, _1, _2]) } - public var NetworkUsageSettings_ResetStats: String { return self._s[2185]! } + public var NetworkUsageSettings_ResetStats: String { return self._s[2187]! } public func PUSH_MESSAGE_GEOLIVE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2186]!, self._r[2186]!, [_1]) + return formatWithArgumentRanges(self._s[2188]!, self._r[2188]!, [_1]) } - public var AccessDenied_LocationTracking: String { return self._s[2187]! } - public var Month_GenOctober: String { return self._s[2188]! } - public var GroupInfo_InviteLink_RevokeAlert_Revoke: String { return self._s[2189]! } - public var EnterPasscode_EnterPasscode: String { return self._s[2190]! } - public var MediaPicker_TimerTooltip: String { return self._s[2192]! } - public var SharedMedia_TitleAll: String { return self._s[2193]! } - public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsExceptions: String { return self._s[2196]! } - public var Conversation_RestrictedMedia: String { return self._s[2197]! } - public var AccessDenied_PhotosRestricted: String { return self._s[2198]! } - public var Privacy_Forwards_WhoCanForward: String { return self._s[2200]! } - public var ChangePhoneNumberCode_Called: String { return self._s[2201]! } + public var AccessDenied_LocationTracking: String { return self._s[2189]! } + public var Month_GenOctober: String { return self._s[2190]! } + public var GroupInfo_InviteLink_RevokeAlert_Revoke: String { return self._s[2191]! } + public var EnterPasscode_EnterPasscode: String { return self._s[2192]! } + public var MediaPicker_TimerTooltip: String { return self._s[2194]! } + public var SharedMedia_TitleAll: String { return self._s[2195]! } + public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsExceptions: String { return self._s[2198]! } + public var Conversation_RestrictedMedia: String { return self._s[2199]! } + public var AccessDenied_PhotosRestricted: String { return self._s[2200]! } + public var Privacy_Forwards_WhoCanForward: String { return self._s[2202]! } + public var ChangePhoneNumberCode_Called: String { return self._s[2203]! } public func Notification_PinnedDocumentMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2202]!, self._r[2202]!, [_0]) + return formatWithArgumentRanges(self._s[2204]!, self._r[2204]!, [_0]) } - public var Conversation_SavedMessages: String { return self._s[2205]! } - public var Your_cards_expiration_month_is_invalid: String { return self._s[2207]! } - public var FastTwoStepSetup_PasswordPlaceholder: String { return self._s[2208]! } + public var Conversation_SavedMessages: String { return self._s[2207]! } + public var Your_cards_expiration_month_is_invalid: String { return self._s[2209]! } + public var FastTwoStepSetup_PasswordPlaceholder: String { return self._s[2210]! } public func Target_ShareGameConfirmationGroup(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2210]!, self._r[2210]!, [_0]) - } - public var VoiceOver_Chat_YourMessage: String { return self._s[2211]! } - public func VoiceOver_Chat_Title(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2212]!, self._r[2212]!, [_0]) } - public var ReportPeer_AlertSuccess: String { return self._s[2213]! } - public var PhotoEditor_CropAspectRatioOriginal: String { return self._s[2214]! } + public var VoiceOver_Chat_YourMessage: String { return self._s[2213]! } + public func VoiceOver_Chat_Title(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2214]!, self._r[2214]!, [_0]) + } + public var ReportPeer_AlertSuccess: String { return self._s[2215]! } + public var PhotoEditor_CropAspectRatioOriginal: String { return self._s[2216]! } public func InstantPage_RelatedArticleAuthorAndDateTitle(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2215]!, self._r[2215]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2217]!, self._r[2217]!, [_1, _2]) } - public var Checkout_PasswordEntry_Title: String { return self._s[2216]! } - public var PhotoEditor_FadeTool: String { return self._s[2217]! } - public var Privacy_ContactsReset: String { return self._s[2218]! } + public var Checkout_PasswordEntry_Title: String { return self._s[2218]! } + public var PhotoEditor_FadeTool: String { return self._s[2219]! } + public var Privacy_ContactsReset: String { return self._s[2220]! } public func Channel_AdminLog_MessageRestrictedUntil(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2220]!, self._r[2220]!, [_0]) + return formatWithArgumentRanges(self._s[2222]!, self._r[2222]!, [_0]) } - public var Message_PinnedVideoMessage: String { return self._s[2221]! } - public var ChatList_Mute: String { return self._s[2222]! } + public var Message_PinnedVideoMessage: String { return self._s[2223]! } + public var ChatList_Mute: String { return self._s[2224]! } public func Wallet_Time_PreciseDate_m5(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2223]!, self._r[2223]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2225]!, self._r[2225]!, [_1, _2, _3]) } - public var Permissions_CellularDataText_v0: String { return self._s[2224]! } - public var Conversation_PinnedQuiz: String { return self._s[2226]! } - public var ShareMenu_SelectChats: String { return self._s[2228]! } - public var ChatList_Context_Unarchive: String { return self._s[2229]! } - public var MusicPlayer_VoiceNote: String { return self._s[2230]! } - public var Conversation_RestrictedText: String { return self._s[2231]! } - public var SettingsSearch_Synonyms_Privacy_Data_DeleteDrafts: String { return self._s[2232]! } - public var Wallet_Month_GenApril: String { return self._s[2233]! } - public var Wallet_Month_ShortMarch: String { return self._s[2234]! } - public var TwoStepAuth_DisableSuccess: String { return self._s[2235]! } - public var Cache_Videos: String { return self._s[2236]! } - public var PrivacySettings_PhoneNumber: String { return self._s[2237]! } - public var Wallet_Month_GenFebruary: String { return self._s[2238]! } - public var FeatureDisabled_Oops: String { return self._s[2240]! } - public var Passport_Address_PostcodePlaceholder: String { return self._s[2241]! } + public var Permissions_CellularDataText_v0: String { return self._s[2226]! } + public var Conversation_PinnedQuiz: String { return self._s[2228]! } + public var ShareMenu_SelectChats: String { return self._s[2230]! } + public var ChatList_Context_Unarchive: String { return self._s[2231]! } + public var MusicPlayer_VoiceNote: String { return self._s[2232]! } + public var Conversation_RestrictedText: String { return self._s[2233]! } + public var SettingsSearch_Synonyms_Privacy_Data_DeleteDrafts: String { return self._s[2234]! } + public var Wallet_Month_GenApril: String { return self._s[2235]! } + public var Wallet_Month_ShortMarch: String { return self._s[2236]! } + public var TwoStepAuth_DisableSuccess: String { return self._s[2237]! } + public var Cache_Videos: String { return self._s[2238]! } + public var PrivacySettings_PhoneNumber: String { return self._s[2239]! } + public var Wallet_Month_GenFebruary: String { return self._s[2240]! } + public var FeatureDisabled_Oops: String { return self._s[2242]! } + public var Passport_Address_PostcodePlaceholder: String { return self._s[2243]! } public func AddContact_StatusSuccess(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2242]!, self._r[2242]!, [_0]) + return formatWithArgumentRanges(self._s[2244]!, self._r[2244]!, [_0]) } - public var Stickers_GroupStickersHelp: String { return self._s[2243]! } - public var GroupPermission_NoSendPolls: String { return self._s[2244]! } - public var Wallet_Qr_ScanCode: String { return self._s[2245]! } - public var Message_VideoExpired: String { return self._s[2247]! } - public var GroupInfo_GroupHistoryVisible: String { return self._s[2248]! } - public var Notifications_Badge: String { return self._s[2249]! } - public var Wallet_Receive_AddressCopied: String { return self._s[2250]! } - public var CreatePoll_OptionPlaceholder: String { return self._s[2251]! } - public var Username_InvalidTooShort: String { return self._s[2252]! } - public var EnterPasscode_EnterNewPasscodeChange: String { return self._s[2253]! } - public var Channel_AdminLog_PinMessages: String { return self._s[2254]! } - public var ArchivedChats_IntroTitle3: String { return self._s[2255]! } + public var Stickers_GroupStickersHelp: String { return self._s[2245]! } + public var GroupPermission_NoSendPolls: String { return self._s[2246]! } + public var Wallet_Qr_ScanCode: String { return self._s[2247]! } + public var Message_VideoExpired: String { return self._s[2249]! } + public var GroupInfo_GroupHistoryVisible: String { return self._s[2250]! } + public var Notifications_Badge: String { return self._s[2251]! } + public var Wallet_Receive_AddressCopied: String { return self._s[2252]! } + public var CreatePoll_OptionPlaceholder: String { return self._s[2253]! } + public var Username_InvalidTooShort: String { return self._s[2254]! } + public var EnterPasscode_EnterNewPasscodeChange: String { return self._s[2255]! } + public var Channel_AdminLog_PinMessages: String { return self._s[2256]! } + public var ArchivedChats_IntroTitle3: String { return self._s[2257]! } public func Notification_MessageLifetimeRemoved(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2256]!, self._r[2256]!, [_1]) + return formatWithArgumentRanges(self._s[2258]!, self._r[2258]!, [_1]) } - public var Permissions_SiriAllowInSettings_v0: String { return self._s[2257]! } - public var Conversation_DefaultRestrictedText: String { return self._s[2258]! } - public var SharedMedia_CategoryDocs: String { return self._s[2261]! } + public var Permissions_SiriAllowInSettings_v0: String { return self._s[2259]! } + public var Conversation_DefaultRestrictedText: String { return self._s[2260]! } + public var SharedMedia_CategoryDocs: String { return self._s[2263]! } public func PUSH_MESSAGE_CONTACT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2262]!, self._r[2262]!, [_1]) + return formatWithArgumentRanges(self._s[2264]!, self._r[2264]!, [_1]) } - public var Wallet_Send_UninitializedTitle: String { return self._s[2263]! } - public var StickerPackActionInfo_ArchivedTitle: String { return self._s[2264]! } - public var Privacy_Forwards_NeverLink: String { return self._s[2266]! } + public var Wallet_Send_UninitializedTitle: String { return self._s[2265]! } + public var StickerPackActionInfo_ArchivedTitle: String { return self._s[2266]! } + public var Privacy_Forwards_NeverLink: String { return self._s[2268]! } public func Notification_MessageLifetimeChangedOutgoing(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2267]!, self._r[2267]!, [_1]) + return formatWithArgumentRanges(self._s[2269]!, self._r[2269]!, [_1]) } - public var CheckoutInfo_ErrorShippingNotAvailable: String { return self._s[2268]! } + public var CheckoutInfo_ErrorShippingNotAvailable: String { return self._s[2270]! } public func Time_MonthOfYear_m12(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2269]!, self._r[2269]!, [_0]) + return formatWithArgumentRanges(self._s[2271]!, self._r[2271]!, [_0]) } - public var ChatSettings_PrivateChats: String { return self._s[2270]! } - public var SettingsSearch_Synonyms_EditProfile_Logout: String { return self._s[2271]! } - public var Conversation_PrivateMessageLinkCopied: String { return self._s[2272]! } - public var Channel_UpdatePhotoItem: String { return self._s[2273]! } - public var GroupInfo_LeftStatus: String { return self._s[2274]! } - public var Watch_MessageView_Forward: String { return self._s[2276]! } - public var ReportPeer_ReasonChildAbuse: String { return self._s[2277]! } - public var Cache_ClearEmpty: String { return self._s[2279]! } - public var Localization_LanguageName: String { return self._s[2280]! } - public var Wallet_AccessDenied_Title: String { return self._s[2281]! } - public var WebSearch_GIFs: String { return self._s[2282]! } - public var Notifications_DisplayNamesOnLockScreenInfoWithLink: String { return self._s[2283]! } - public var Wallet_AccessDenied_Settings: String { return self._s[2284]! } - public var Username_InvalidStartsWithNumber: String { return self._s[2285]! } - public var Common_Back: String { return self._s[2286]! } - public var GroupInfo_Permissions_EditingDisabled: String { return self._s[2287]! } - public var Passport_Identity_DateOfBirthPlaceholder: String { return self._s[2288]! } - public var Wallet_Send_Send: String { return self._s[2289]! } + public var ChatSettings_PrivateChats: String { return self._s[2272]! } + public var SettingsSearch_Synonyms_EditProfile_Logout: String { return self._s[2273]! } + public var Conversation_PrivateMessageLinkCopied: String { return self._s[2274]! } + public var Channel_UpdatePhotoItem: String { return self._s[2275]! } + public var GroupInfo_LeftStatus: String { return self._s[2276]! } + public var Watch_MessageView_Forward: String { return self._s[2278]! } + public var ReportPeer_ReasonChildAbuse: String { return self._s[2279]! } + public var Cache_ClearEmpty: String { return self._s[2281]! } + public var Localization_LanguageName: String { return self._s[2282]! } + public var Wallet_AccessDenied_Title: String { return self._s[2283]! } + public var WebSearch_GIFs: String { return self._s[2284]! } + public var Notifications_DisplayNamesOnLockScreenInfoWithLink: String { return self._s[2285]! } + public var Wallet_AccessDenied_Settings: String { return self._s[2286]! } + public var Username_InvalidStartsWithNumber: String { return self._s[2287]! } + public var Common_Back: String { return self._s[2288]! } + public var GroupInfo_Permissions_EditingDisabled: String { return self._s[2289]! } + public var Passport_Identity_DateOfBirthPlaceholder: String { return self._s[2290]! } + public var Wallet_Send_Send: String { return self._s[2291]! } public func PUSH_CHANNEL_MESSAGE_STICKER(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2291]!, self._r[2291]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2293]!, self._r[2293]!, [_1, _2]) } - public var Wallet_Info_RefreshErrorTitle: String { return self._s[2292]! } - public var Wallet_Month_GenJune: String { return self._s[2293]! } - public var Passport_Email_Help: String { return self._s[2294]! } - public var Watch_Conversation_Reply: String { return self._s[2296]! } - public var Conversation_EditingMessageMediaChange: String { return self._s[2299]! } - public var Passport_Identity_IssueDatePlaceholder: String { return self._s[2300]! } - public var Channel_BanUser_Unban: String { return self._s[2302]! } - public var Channel_EditAdmin_PermissionPostMessages: String { return self._s[2303]! } - public var Group_Username_CreatePublicLinkHelp: String { return self._s[2304]! } - public var TwoStepAuth_ConfirmEmailCodePlaceholder: String { return self._s[2306]! } - public var Wallet_Send_AddressHeader: String { return self._s[2307]! } - public var Passport_Identity_Name: String { return self._s[2308]! } + public var Wallet_Info_RefreshErrorTitle: String { return self._s[2294]! } + public var Wallet_Month_GenJune: String { return self._s[2295]! } + public var Passport_Email_Help: String { return self._s[2296]! } + public var Watch_Conversation_Reply: String { return self._s[2298]! } + public var Conversation_EditingMessageMediaChange: String { return self._s[2301]! } + public var Passport_Identity_IssueDatePlaceholder: String { return self._s[2302]! } + public var Channel_BanUser_Unban: String { return self._s[2304]! } + public var Channel_EditAdmin_PermissionPostMessages: String { return self._s[2305]! } + public var Group_Username_CreatePublicLinkHelp: String { return self._s[2306]! } + public var TwoStepAuth_ConfirmEmailCodePlaceholder: String { return self._s[2308]! } + public var Wallet_Send_AddressHeader: String { return self._s[2309]! } + public var Passport_Identity_Name: String { return self._s[2310]! } public func Channel_DiscussionGroup_HeaderGroupSet(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2309]!, self._r[2309]!, [_0]) + return formatWithArgumentRanges(self._s[2311]!, self._r[2311]!, [_0]) } - public var GroupRemoved_ViewUserInfo: String { return self._s[2310]! } - public var Conversation_BlockUser: String { return self._s[2311]! } - public var Month_GenJanuary: String { return self._s[2312]! } - public var ChatSettings_TextSize: String { return self._s[2313]! } - public var Notification_PassportValuePhone: String { return self._s[2314]! } - public var MediaPlayer_UnknownArtist: String { return self._s[2315]! } - public var Passport_Language_ne: String { return self._s[2316]! } - public var Notification_CallBack: String { return self._s[2317]! } - public var Wallet_SecureStorageReset_BiometryTouchId: String { return self._s[2318]! } - public var TwoStepAuth_EmailHelp: String { return self._s[2319]! } + public var GroupRemoved_ViewUserInfo: String { return self._s[2312]! } + public var Conversation_BlockUser: String { return self._s[2313]! } + public var Month_GenJanuary: String { return self._s[2314]! } + public var ChatSettings_TextSize: String { return self._s[2315]! } + public var Notification_PassportValuePhone: String { return self._s[2316]! } + public var MediaPlayer_UnknownArtist: String { return self._s[2317]! } + public var Passport_Language_ne: String { return self._s[2318]! } + public var Notification_CallBack: String { return self._s[2319]! } + public var Wallet_SecureStorageReset_BiometryTouchId: String { return self._s[2320]! } + public var TwoStepAuth_EmailHelp: String { return self._s[2321]! } public func Time_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2320]!, self._r[2320]!, [_0]) + return formatWithArgumentRanges(self._s[2322]!, self._r[2322]!, [_0]) } - public var Channel_Info_Management: String { return self._s[2321]! } - public var Passport_FieldIdentityUploadHelp: String { return self._s[2322]! } - public var Stickers_FrequentlyUsed: String { return self._s[2323]! } - public var Channel_BanUser_PermissionSendMessages: String { return self._s[2324]! } - public var Passport_Address_OneOfTypeUtilityBill: String { return self._s[2326]! } + public var Channel_Info_Management: String { return self._s[2323]! } + public var Passport_FieldIdentityUploadHelp: String { return self._s[2324]! } + public var Stickers_FrequentlyUsed: String { return self._s[2325]! } + public var Channel_BanUser_PermissionSendMessages: String { return self._s[2326]! } + public var Passport_Address_OneOfTypeUtilityBill: String { return self._s[2328]! } public func LOCAL_CHANNEL_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2327]!, self._r[2327]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[2329]!, self._r[2329]!, [_1, "\(_2)"]) } - public var TwoFactorSetup_Password_Title: String { return self._s[2328]! } - public var Passport_Address_EditResidentialAddress: String { return self._s[2329]! } - public var PrivacyPolicy_DeclineTitle: String { return self._s[2330]! } - public var CreatePoll_TextHeader: String { return self._s[2331]! } + public var TwoFactorSetup_Password_Title: String { return self._s[2330]! } + public var Passport_Address_EditResidentialAddress: String { return self._s[2331]! } + public var PrivacyPolicy_DeclineTitle: String { return self._s[2332]! } + public var CreatePoll_TextHeader: String { return self._s[2333]! } public func Checkout_SavePasswordTimeoutAndTouchId(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2332]!, self._r[2332]!, [_0]) + return formatWithArgumentRanges(self._s[2334]!, self._r[2334]!, [_0]) } - public var PhotoEditor_QualityMedium: String { return self._s[2333]! } - public var InfoPlist_NSMicrophoneUsageDescription: String { return self._s[2334]! } - public var Conversation_StatusKickedFromChannel: String { return self._s[2336]! } - public var CheckoutInfo_ReceiverInfoName: String { return self._s[2337]! } - public var Group_ErrorSendRestrictedStickers: String { return self._s[2338]! } + public var PhotoEditor_QualityMedium: String { return self._s[2335]! } + public var InfoPlist_NSMicrophoneUsageDescription: String { return self._s[2336]! } + public var Conversation_StatusKickedFromChannel: String { return self._s[2338]! } + public var CheckoutInfo_ReceiverInfoName: String { return self._s[2339]! } + public var Group_ErrorSendRestrictedStickers: String { return self._s[2340]! } public func Conversation_RestrictedInlineTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2339]!, self._r[2339]!, [_0]) + return formatWithArgumentRanges(self._s[2341]!, self._r[2341]!, [_0]) } public func Channel_AdminLog_MessageTransferedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2340]!, self._r[2340]!, [_1]) + return formatWithArgumentRanges(self._s[2342]!, self._r[2342]!, [_1]) } - public var LogoutOptions_LogOutWalletInfo: String { return self._s[2341]! } - public var TwoFactorSetup_Email_SkipConfirmationTitle: String { return self._s[2342]! } - public var Conversation_LinkDialogOpen: String { return self._s[2344]! } - public var TwoFactorSetup_Hint_Title: String { return self._s[2345]! } - public var VoiceOver_Chat_PollNoVotes: String { return self._s[2346]! } - public var Settings_Username: String { return self._s[2348]! } - public var Conversation_Block: String { return self._s[2350]! } - public var Wallpaper_Wallpaper: String { return self._s[2351]! } - public var SocksProxySetup_UseProxy: String { return self._s[2353]! } - public var Wallet_Send_Confirmation: String { return self._s[2354]! } - public var EditTheme_UploadEditedTheme: String { return self._s[2355]! } - public var UserInfo_ShareMyContactInfo: String { return self._s[2356]! } - public var MessageTimer_Forever: String { return self._s[2357]! } - public var Privacy_Calls_WhoCanCallMe: String { return self._s[2358]! } - public var PhotoEditor_DiscardChanges: String { return self._s[2359]! } - public var AuthSessions_TerminateOtherSessionsHelp: String { return self._s[2360]! } - public var Passport_Language_da: String { return self._s[2361]! } - public var SocksProxySetup_PortPlaceholder: String { return self._s[2362]! } + public var LogoutOptions_LogOutWalletInfo: String { return self._s[2343]! } + public var TwoFactorSetup_Email_SkipConfirmationTitle: String { return self._s[2344]! } + public var Conversation_LinkDialogOpen: String { return self._s[2346]! } + public var TwoFactorSetup_Hint_Title: String { return self._s[2347]! } + public var VoiceOver_Chat_PollNoVotes: String { return self._s[2348]! } + public var Settings_Username: String { return self._s[2350]! } + public var Conversation_Block: String { return self._s[2352]! } + public var Wallpaper_Wallpaper: String { return self._s[2353]! } + public var SocksProxySetup_UseProxy: String { return self._s[2355]! } + public var Wallet_Send_Confirmation: String { return self._s[2356]! } + public var EditTheme_UploadEditedTheme: String { return self._s[2357]! } + public var UserInfo_ShareMyContactInfo: String { return self._s[2358]! } + public var MessageTimer_Forever: String { return self._s[2359]! } + public var Privacy_Calls_WhoCanCallMe: String { return self._s[2360]! } + public var PhotoEditor_DiscardChanges: String { return self._s[2361]! } + public var AuthSessions_TerminateOtherSessionsHelp: String { return self._s[2362]! } + public var Passport_Language_da: String { return self._s[2363]! } + public var SocksProxySetup_PortPlaceholder: String { return self._s[2364]! } public func SecretGIF_NotViewedYet(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2363]!, self._r[2363]!, [_0]) + return formatWithArgumentRanges(self._s[2365]!, self._r[2365]!, [_0]) } - public var Passport_Address_EditPassportRegistration: String { return self._s[2364]! } + public var Passport_Address_EditPassportRegistration: String { return self._s[2366]! } public func Channel_AdminLog_MessageChangedGroupAbout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2366]!, self._r[2366]!, [_0]) + return formatWithArgumentRanges(self._s[2368]!, self._r[2368]!, [_0]) } - public var Settings_AddDevice: String { return self._s[2367]! } - public var Passport_Identity_ResidenceCountryPlaceholder: String { return self._s[2369]! } - public var AuthSessions_AddDeviceIntro_Text1: String { return self._s[2370]! } - public var Conversation_SearchByName_Prefix: String { return self._s[2371]! } - public var Conversation_PinnedPoll: String { return self._s[2372]! } - public var AuthSessions_AddDeviceIntro_Text2: String { return self._s[2373]! } - public var Conversation_EmptyGifPanelPlaceholder: String { return self._s[2374]! } - public var AuthSessions_AddDeviceIntro_Text3: String { return self._s[2375]! } + public var Settings_AddDevice: String { return self._s[2369]! } + public var Passport_Identity_ResidenceCountryPlaceholder: String { return self._s[2371]! } + public var AuthSessions_AddDeviceIntro_Text1: String { return self._s[2372]! } + public var Conversation_SearchByName_Prefix: String { return self._s[2373]! } + public var Conversation_PinnedPoll: String { return self._s[2374]! } + public var AuthSessions_AddDeviceIntro_Text2: String { return self._s[2375]! } + public var Conversation_EmptyGifPanelPlaceholder: String { return self._s[2376]! } + public var AuthSessions_AddDeviceIntro_Text3: String { return self._s[2377]! } public func PUSH_ENCRYPTION_ACCEPT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2376]!, self._r[2376]!, [_1]) + return formatWithArgumentRanges(self._s[2378]!, self._r[2378]!, [_1]) } - public var WallpaperSearch_ColorPurple: String { return self._s[2377]! } - public var Cache_ByPeerHeader: String { return self._s[2378]! } + public var WallpaperSearch_ColorPurple: String { return self._s[2379]! } + public var Cache_ByPeerHeader: String { return self._s[2380]! } public func Conversation_EncryptedPlaceholderTitleIncoming(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2379]!, self._r[2379]!, [_0]) + return formatWithArgumentRanges(self._s[2381]!, self._r[2381]!, [_0]) } - public var ChatSettings_AutoDownloadDocuments: String { return self._s[2380]! } - public var Appearance_ThemePreview_Chat_3_Text: String { return self._s[2383]! } - public var Wallet_Completed_Title: String { return self._s[2384]! } - public var Notification_PinnedMessage: String { return self._s[2385]! } - public var TwoFactorSetup_EmailVerification_Placeholder: String { return self._s[2386]! } - public var VoiceOver_Chat_RecordModeVideoMessage: String { return self._s[2388]! } - public var Contacts_SortBy: String { return self._s[2389]! } + public var ChatSettings_AutoDownloadDocuments: String { return self._s[2382]! } + public var Appearance_ThemePreview_Chat_3_Text: String { return self._s[2385]! } + public var Wallet_Completed_Title: String { return self._s[2386]! } + public var Notification_PinnedMessage: String { return self._s[2387]! } + public var TwoFactorSetup_EmailVerification_Placeholder: String { return self._s[2388]! } + public var VoiceOver_Chat_RecordModeVideoMessage: String { return self._s[2390]! } + public var Contacts_SortBy: String { return self._s[2391]! } public func PUSH_CHANNEL_MESSAGE_NOTEXT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2390]!, self._r[2390]!, [_1]) + return formatWithArgumentRanges(self._s[2392]!, self._r[2392]!, [_1]) } - public var Appearance_ColorThemeNight: String { return self._s[2392]! } + public var Appearance_ColorThemeNight: String { return self._s[2394]! } public func PUSH_MESSAGE_GAME(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2393]!, self._r[2393]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2395]!, self._r[2395]!, [_1, _2]) } - public var Call_EncryptionKey_Title: String { return self._s[2394]! } - public var Watch_UserInfo_Service: String { return self._s[2395]! } - public var SettingsSearch_Synonyms_Data_SaveEditedPhotos: String { return self._s[2397]! } - public var Conversation_Unpin: String { return self._s[2399]! } - public var CancelResetAccount_Title: String { return self._s[2400]! } - public var Map_LiveLocationFor15Minutes: String { return self._s[2401]! } + public var Call_EncryptionKey_Title: String { return self._s[2396]! } + public var Watch_UserInfo_Service: String { return self._s[2397]! } + public var SettingsSearch_Synonyms_Data_SaveEditedPhotos: String { return self._s[2399]! } + public var Conversation_Unpin: String { return self._s[2401]! } + public var CancelResetAccount_Title: String { return self._s[2402]! } + public var Map_LiveLocationFor15Minutes: String { return self._s[2403]! } public func Time_PreciseDate_m8(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2403]!, self._r[2403]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2405]!, self._r[2405]!, [_1, _2, _3]) } - public var Group_Members_AddMemberBotErrorNotAllowed: String { return self._s[2404]! } - public var CallSettings_Title: String { return self._s[2405]! } - public var SettingsSearch_Synonyms_Appearance_ChatBackground: String { return self._s[2406]! } - public var PasscodeSettings_EncryptDataHelp: String { return self._s[2408]! } - public var AutoDownloadSettings_Contacts: String { return self._s[2409]! } + public var Group_Members_AddMemberBotErrorNotAllowed: String { return self._s[2406]! } + public var CallSettings_Title: String { return self._s[2407]! } + public var SettingsSearch_Synonyms_Appearance_ChatBackground: String { return self._s[2408]! } + public var PasscodeSettings_EncryptDataHelp: String { return self._s[2410]! } + public var AutoDownloadSettings_Contacts: String { return self._s[2411]! } public func Channel_AdminLog_MessageRankName(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2410]!, self._r[2410]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2412]!, self._r[2412]!, [_1, _2]) } - public var Passport_Identity_DocumentDetails: String { return self._s[2411]! } - public var LoginPassword_PasswordHelp: String { return self._s[2412]! } - public var SettingsSearch_Synonyms_Data_AutoDownloadUsingWifi: String { return self._s[2413]! } - public var PrivacyLastSeenSettings_CustomShareSettings_Delete: String { return self._s[2414]! } - public var ChatContextMenu_TextSelectionTip: String { return self._s[2415]! } - public var Checkout_TotalPaidAmount: String { return self._s[2416]! } + public var Passport_Identity_DocumentDetails: String { return self._s[2413]! } + public var LoginPassword_PasswordHelp: String { return self._s[2414]! } + public var SettingsSearch_Synonyms_Data_AutoDownloadUsingWifi: String { return self._s[2415]! } + public var PrivacyLastSeenSettings_CustomShareSettings_Delete: String { return self._s[2416]! } + public var ChatContextMenu_TextSelectionTip: String { return self._s[2417]! } + public var Checkout_TotalPaidAmount: String { return self._s[2418]! } public func FileSize_KB(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2417]!, self._r[2417]!, [_0]) + return formatWithArgumentRanges(self._s[2419]!, self._r[2419]!, [_0]) } - public var PasscodeSettings_ChangePasscode: String { return self._s[2418]! } - public var Conversation_SecretLinkPreviewAlert: String { return self._s[2420]! } - public var Privacy_SecretChatsLinkPreviews: String { return self._s[2421]! } + public var PasscodeSettings_ChangePasscode: String { return self._s[2420]! } + public var Conversation_SecretLinkPreviewAlert: String { return self._s[2422]! } + public var Privacy_SecretChatsLinkPreviews: String { return self._s[2423]! } public func PUSH_CHANNEL_MESSAGE_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2422]!, self._r[2422]!, [_1]) + return formatWithArgumentRanges(self._s[2424]!, self._r[2424]!, [_1]) } - public var VoiceOver_Chat_ReplyToYourMessage: String { return self._s[2423]! } - public var Contacts_InviteFriends: String { return self._s[2425]! } - public var Map_ChooseLocationTitle: String { return self._s[2426]! } - public var Conversation_StopPoll: String { return self._s[2428]! } + public var VoiceOver_Chat_ReplyToYourMessage: String { return self._s[2425]! } + public var Contacts_InviteFriends: String { return self._s[2427]! } + public var Map_ChooseLocationTitle: String { return self._s[2428]! } + public var Conversation_StopPoll: String { return self._s[2430]! } public func WebSearch_SearchNoResultsDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2429]!, self._r[2429]!, [_0]) + return formatWithArgumentRanges(self._s[2431]!, self._r[2431]!, [_0]) } - public var Call_Camera: String { return self._s[2430]! } - public var LogoutOptions_ChangePhoneNumberTitle: String { return self._s[2431]! } - public var AppWallet_Intro_Text: String { return self._s[2432]! } - public var Calls_RatingFeedback: String { return self._s[2433]! } - public var GroupInfo_BroadcastListNamePlaceholder: String { return self._s[2435]! } - public var Wallet_Alert_OK: String { return self._s[2436]! } - public var NotificationsSound_Pulse: String { return self._s[2437]! } - public var Watch_LastSeen_Lately: String { return self._s[2438]! } - public var ReportGroupLocation_Report: String { return self._s[2441]! } - public var Widget_NoUsers: String { return self._s[2442]! } - public var Conversation_UnvotePoll: String { return self._s[2443]! } - public var SettingsSearch_Synonyms_Privacy_ProfilePhoto: String { return self._s[2445]! } - public var Privacy_ProfilePhoto_WhoCanSeeMyPhoto: String { return self._s[2446]! } - public var NotificationsSound_Circles: String { return self._s[2447]! } - public var PrivacyLastSeenSettings_AlwaysShareWith_Title: String { return self._s[2450]! } - public var Wallet_Settings_DeleteWallet: String { return self._s[2451]! } - public var TwoStepAuth_RecoveryCodeExpired: String { return self._s[2452]! } - public var Proxy_TooltipUnavailable: String { return self._s[2453]! } - public var Passport_Identity_CountryPlaceholder: String { return self._s[2455]! } - public var GroupInfo_Permissions_SlowmodeInfo: String { return self._s[2457]! } - public var Conversation_FileDropbox: String { return self._s[2458]! } - public var Notifications_ExceptionsUnmuted: String { return self._s[2459]! } - public var Tour_Text3: String { return self._s[2461]! } - public var Login_ResetAccountProtected_Title: String { return self._s[2463]! } - public var GroupPermission_NoSendMessages: String { return self._s[2464]! } - public var WallpaperSearch_ColorTitle: String { return self._s[2465]! } - public var ChatAdmins_AllMembersAreAdminsOnHelp: String { return self._s[2466]! } + public var Call_Camera: String { return self._s[2432]! } + public var LogoutOptions_ChangePhoneNumberTitle: String { return self._s[2433]! } + public var AppWallet_Intro_Text: String { return self._s[2434]! } + public var Calls_RatingFeedback: String { return self._s[2435]! } + public var GroupInfo_BroadcastListNamePlaceholder: String { return self._s[2437]! } + public var Wallet_Alert_OK: String { return self._s[2438]! } + public var NotificationsSound_Pulse: String { return self._s[2439]! } + public var Watch_LastSeen_Lately: String { return self._s[2440]! } + public var ReportGroupLocation_Report: String { return self._s[2443]! } + public var Widget_NoUsers: String { return self._s[2444]! } + public var Conversation_UnvotePoll: String { return self._s[2445]! } + public var SettingsSearch_Synonyms_Privacy_ProfilePhoto: String { return self._s[2447]! } + public var Privacy_ProfilePhoto_WhoCanSeeMyPhoto: String { return self._s[2448]! } + public var NotificationsSound_Circles: String { return self._s[2449]! } + public var PrivacyLastSeenSettings_AlwaysShareWith_Title: String { return self._s[2452]! } + public var Wallet_Settings_DeleteWallet: String { return self._s[2453]! } + public var TwoStepAuth_RecoveryCodeExpired: String { return self._s[2454]! } + public var Proxy_TooltipUnavailable: String { return self._s[2455]! } + public var Passport_Identity_CountryPlaceholder: String { return self._s[2457]! } + public var GroupInfo_Permissions_SlowmodeInfo: String { return self._s[2459]! } + public var Conversation_FileDropbox: String { return self._s[2460]! } + public var Notifications_ExceptionsUnmuted: String { return self._s[2461]! } + public var Tour_Text3: String { return self._s[2463]! } + public var Login_ResetAccountProtected_Title: String { return self._s[2465]! } + public var GroupPermission_NoSendMessages: String { return self._s[2466]! } + public var WallpaperSearch_ColorTitle: String { return self._s[2467]! } + public var ChatAdmins_AllMembersAreAdminsOnHelp: String { return self._s[2468]! } public func Conversation_LiveLocationYouAnd(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2468]!, self._r[2468]!, [_0]) + return formatWithArgumentRanges(self._s[2470]!, self._r[2470]!, [_0]) } - public var GroupInfo_AddParticipantTitle: String { return self._s[2469]! } - public var Checkout_ShippingOption_Title: String { return self._s[2470]! } - public var ChatSettings_AutoDownloadTitle: String { return self._s[2471]! } + public var GroupInfo_AddParticipantTitle: String { return self._s[2471]! } + public var Checkout_ShippingOption_Title: String { return self._s[2472]! } + public var ChatSettings_AutoDownloadTitle: String { return self._s[2473]! } public func DialogList_SingleTypingSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2472]!, self._r[2472]!, [_0]) + return formatWithArgumentRanges(self._s[2474]!, self._r[2474]!, [_0]) } public func ChatSettings_AutoDownloadSettings_TypeVideo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2473]!, self._r[2473]!, [_0]) + return formatWithArgumentRanges(self._s[2475]!, self._r[2475]!, [_0]) } - public var Channel_Management_LabelAdministrator: String { return self._s[2474]! } - public var EditTheme_FileReadError: String { return self._s[2475]! } - public var OwnershipTransfer_ComeBackLater: String { return self._s[2476]! } - public var PrivacyLastSeenSettings_NeverShareWith_Placeholder: String { return self._s[2477]! } - public var AutoDownloadSettings_Photos: String { return self._s[2479]! } - public var Appearance_PreviewIncomingText: String { return self._s[2480]! } - public var ChatList_Context_MarkAllAsRead: String { return self._s[2481]! } - public var ChannelInfo_ConfirmLeave: String { return self._s[2482]! } - public var MediaPicker_MomentsDateRangeSameMonthYearFormat: String { return self._s[2483]! } - public var Passport_Identity_DocumentNumberPlaceholder: String { return self._s[2484]! } - public var Channel_AdminLogFilter_EventsNewMembers: String { return self._s[2485]! } - public var PasscodeSettings_AutoLock_IfAwayFor_5minutes: String { return self._s[2486]! } - public var GroupInfo_SetGroupPhotoStop: String { return self._s[2487]! } - public var Notification_SecretChatScreenshot: String { return self._s[2488]! } - public var AccessDenied_Wallpapers: String { return self._s[2489]! } - public var ChatList_Context_Mute: String { return self._s[2491]! } - public var Passport_Address_City: String { return self._s[2492]! } - public var InfoPlist_NSPhotoLibraryAddUsageDescription: String { return self._s[2493]! } - public var Appearance_ThemeCarouselClassic: String { return self._s[2494]! } - public var SocksProxySetup_SecretPlaceholder: String { return self._s[2495]! } - public var AccessDenied_LocationDisabled: String { return self._s[2496]! } - public var Group_Location_Title: String { return self._s[2497]! } - public var SocksProxySetup_HostnamePlaceholder: String { return self._s[2499]! } - public var GroupInfo_Sound: String { return self._s[2500]! } - public var SettingsSearch_Synonyms_ChatSettings_OpenLinksIn: String { return self._s[2501]! } - public var ChannelInfo_ScamChannelWarning: String { return self._s[2502]! } - public var Stickers_RemoveFromFavorites: String { return self._s[2503]! } - public var Contacts_Title: String { return self._s[2504]! } - public var EditTheme_ThemeTemplateAlertText: String { return self._s[2505]! } - public var Passport_Language_fr: String { return self._s[2506]! } - public var TwoFactorSetup_EmailVerification_Action: String { return self._s[2507]! } - public var Notifications_ResetAllNotifications: String { return self._s[2508]! } - public var IntentsSettings_SuggestedChats: String { return self._s[2510]! } - public var PrivacySettings_SecurityTitle: String { return self._s[2512]! } - public var Checkout_NewCard_Title: String { return self._s[2513]! } - public var Login_HaveNotReceivedCodeInternal: String { return self._s[2514]! } - public var Conversation_ForwardChats: String { return self._s[2515]! } - public var Wallet_SecureStorageReset_PasscodeText: String { return self._s[2517]! } - public var PasscodeSettings_4DigitCode: String { return self._s[2518]! } - public var Settings_FAQ: String { return self._s[2520]! } - public var AutoDownloadSettings_DocumentsTitle: String { return self._s[2521]! } - public var Conversation_ContextMenuForward: String { return self._s[2522]! } - public var VoiceOver_Chat_YourPhoto: String { return self._s[2525]! } - public var PrivacyPolicy_Title: String { return self._s[2528]! } - public var Notifications_TextTone: String { return self._s[2529]! } - public var Profile_CreateNewContact: String { return self._s[2530]! } - public var PrivacyPhoneNumberSettings_WhoCanSeeMyPhoneNumber: String { return self._s[2531]! } - public var TwoFactorSetup_EmailVerification_Title: String { return self._s[2533]! } - public var Call_Speaker: String { return self._s[2534]! } - public var AutoNightTheme_AutomaticSection: String { return self._s[2535]! } - public var Channel_OwnershipTransfer_EnterPassword: String { return self._s[2537]! } - public var Channel_Username_InvalidCharacters: String { return self._s[2538]! } + public var Channel_Management_LabelAdministrator: String { return self._s[2476]! } + public var EditTheme_FileReadError: String { return self._s[2477]! } + public var OwnershipTransfer_ComeBackLater: String { return self._s[2478]! } + public var PrivacyLastSeenSettings_NeverShareWith_Placeholder: String { return self._s[2479]! } + public var AutoDownloadSettings_Photos: String { return self._s[2481]! } + public var Appearance_PreviewIncomingText: String { return self._s[2482]! } + public var ChatList_Context_MarkAllAsRead: String { return self._s[2483]! } + public var ChannelInfo_ConfirmLeave: String { return self._s[2484]! } + public var MediaPicker_MomentsDateRangeSameMonthYearFormat: String { return self._s[2485]! } + public var Passport_Identity_DocumentNumberPlaceholder: String { return self._s[2486]! } + public var Channel_AdminLogFilter_EventsNewMembers: String { return self._s[2487]! } + public var PasscodeSettings_AutoLock_IfAwayFor_5minutes: String { return self._s[2488]! } + public var GroupInfo_SetGroupPhotoStop: String { return self._s[2489]! } + public var Notification_SecretChatScreenshot: String { return self._s[2490]! } + public var AccessDenied_Wallpapers: String { return self._s[2491]! } + public var ChatList_Context_Mute: String { return self._s[2493]! } + public var Passport_Address_City: String { return self._s[2494]! } + public var InfoPlist_NSPhotoLibraryAddUsageDescription: String { return self._s[2495]! } + public var Appearance_ThemeCarouselClassic: String { return self._s[2496]! } + public var SocksProxySetup_SecretPlaceholder: String { return self._s[2497]! } + public var AccessDenied_LocationDisabled: String { return self._s[2498]! } + public var Group_Location_Title: String { return self._s[2499]! } + public var SocksProxySetup_HostnamePlaceholder: String { return self._s[2501]! } + public var GroupInfo_Sound: String { return self._s[2502]! } + public var SettingsSearch_Synonyms_ChatSettings_OpenLinksIn: String { return self._s[2503]! } + public var ChannelInfo_ScamChannelWarning: String { return self._s[2504]! } + public var Stickers_RemoveFromFavorites: String { return self._s[2505]! } + public var Contacts_Title: String { return self._s[2506]! } + public var EditTheme_ThemeTemplateAlertText: String { return self._s[2507]! } + public var Passport_Language_fr: String { return self._s[2508]! } + public var TwoFactorSetup_EmailVerification_Action: String { return self._s[2509]! } + public var Notifications_ResetAllNotifications: String { return self._s[2510]! } + public var IntentsSettings_SuggestedChats: String { return self._s[2512]! } + public var PrivacySettings_SecurityTitle: String { return self._s[2514]! } + public var Checkout_NewCard_Title: String { return self._s[2515]! } + public var Login_HaveNotReceivedCodeInternal: String { return self._s[2516]! } + public var Conversation_ForwardChats: String { return self._s[2517]! } + public var Wallet_SecureStorageReset_PasscodeText: String { return self._s[2519]! } + public var PasscodeSettings_4DigitCode: String { return self._s[2520]! } + public var Settings_FAQ: String { return self._s[2522]! } + public var AutoDownloadSettings_DocumentsTitle: String { return self._s[2523]! } + public var Conversation_ContextMenuForward: String { return self._s[2524]! } + public var VoiceOver_Chat_YourPhoto: String { return self._s[2527]! } + public var PrivacyPolicy_Title: String { return self._s[2530]! } + public var Notifications_TextTone: String { return self._s[2531]! } + public var Profile_CreateNewContact: String { return self._s[2532]! } + public var PrivacyPhoneNumberSettings_WhoCanSeeMyPhoneNumber: String { return self._s[2533]! } + public var TwoFactorSetup_EmailVerification_Title: String { return self._s[2535]! } + public var Call_Speaker: String { return self._s[2536]! } + public var AutoNightTheme_AutomaticSection: String { return self._s[2537]! } + public var Channel_OwnershipTransfer_EnterPassword: String { return self._s[2539]! } + public var Channel_Username_InvalidCharacters: String { return self._s[2540]! } public func Channel_AdminLog_MessageChangedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2539]!, self._r[2539]!, [_0]) + return formatWithArgumentRanges(self._s[2541]!, self._r[2541]!, [_0]) } - public var AutoDownloadSettings_AutodownloadFiles: String { return self._s[2540]! } - public var PrivacySettings_LastSeenTitle: String { return self._s[2541]! } - public var Channel_AdminLog_CanInviteUsers: String { return self._s[2542]! } - public var SettingsSearch_Synonyms_Privacy_Data_ClearPaymentsInfo: String { return self._s[2543]! } - public var OwnershipTransfer_SecurityCheck: String { return self._s[2544]! } - public var Conversation_MessageDeliveryFailed: String { return self._s[2545]! } - public var Watch_ChatList_NoConversationsText: String { return self._s[2546]! } - public var Bot_Unblock: String { return self._s[2547]! } - public var TextFormat_Italic: String { return self._s[2548]! } - public var WallpaperSearch_ColorPink: String { return self._s[2549]! } - public var Settings_About_Help: String { return self._s[2551]! } - public var SearchImages_Title: String { return self._s[2552]! } - public var Weekday_Wednesday: String { return self._s[2553]! } - public var Conversation_ClousStorageInfo_Description1: String { return self._s[2554]! } - public var ExplicitContent_AlertTitle: String { return self._s[2555]! } + public var AutoDownloadSettings_AutodownloadFiles: String { return self._s[2542]! } + public var PrivacySettings_LastSeenTitle: String { return self._s[2543]! } + public var Channel_AdminLog_CanInviteUsers: String { return self._s[2544]! } + public var SettingsSearch_Synonyms_Privacy_Data_ClearPaymentsInfo: String { return self._s[2545]! } + public var OwnershipTransfer_SecurityCheck: String { return self._s[2546]! } + public var Conversation_MessageDeliveryFailed: String { return self._s[2547]! } + public var Watch_ChatList_NoConversationsText: String { return self._s[2548]! } + public var Bot_Unblock: String { return self._s[2549]! } + public var TextFormat_Italic: String { return self._s[2550]! } + public var WallpaperSearch_ColorPink: String { return self._s[2551]! } + public var Settings_About_Help: String { return self._s[2553]! } + public var SearchImages_Title: String { return self._s[2554]! } + public var Weekday_Wednesday: String { return self._s[2555]! } + public var Conversation_ClousStorageInfo_Description1: String { return self._s[2556]! } + public var ExplicitContent_AlertTitle: String { return self._s[2557]! } public func Time_PreciseDate_m5(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2556]!, self._r[2556]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2558]!, self._r[2558]!, [_1, _2, _3]) } - public var Channel_DiscussionGroup_Create: String { return self._s[2557]! } - public var Weekday_Thursday: String { return self._s[2558]! } - public var Channel_BanUser_PermissionChangeGroupInfo: String { return self._s[2559]! } - public var Channel_Members_AddMembersHelp: String { return self._s[2560]! } + public var Channel_DiscussionGroup_Create: String { return self._s[2559]! } + public var Weekday_Thursday: String { return self._s[2560]! } + public var Channel_BanUser_PermissionChangeGroupInfo: String { return self._s[2561]! } + public var Channel_Members_AddMembersHelp: String { return self._s[2562]! } public func Checkout_SavePasswordTimeout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2561]!, self._r[2561]!, [_0]) + return formatWithArgumentRanges(self._s[2563]!, self._r[2563]!, [_0]) } - public var Channel_DiscussionGroup_LinkGroup: String { return self._s[2562]! } - public var SettingsSearch_Synonyms_Notifications_InAppNotificationsVibrate: String { return self._s[2563]! } - public var Passport_RequestedInformation: String { return self._s[2564]! } - public var Login_PhoneAndCountryHelp: String { return self._s[2565]! } - public var Conversation_EncryptionProcessing: String { return self._s[2567]! } - public var Notifications_PermissionsSuppressWarningTitle: String { return self._s[2568]! } - public var PhotoEditor_EnhanceTool: String { return self._s[2570]! } - public var Channel_Setup_Title: String { return self._s[2571]! } - public var Conversation_SearchPlaceholder: String { return self._s[2572]! } - public var OldChannels_GroupEmptyFormat: String { return self._s[2573]! } - public var AccessDenied_LocationAlwaysDenied: String { return self._s[2574]! } - public var Checkout_ErrorGeneric: String { return self._s[2575]! } - public var Passport_Language_hu: String { return self._s[2576]! } - public var GroupPermission_EditingDisabled: String { return self._s[2577]! } - public var Wallet_Month_ShortSeptember: String { return self._s[2579]! } + public var Channel_DiscussionGroup_LinkGroup: String { return self._s[2564]! } + public var SettingsSearch_Synonyms_Notifications_InAppNotificationsVibrate: String { return self._s[2565]! } + public var Passport_RequestedInformation: String { return self._s[2566]! } + public var Login_PhoneAndCountryHelp: String { return self._s[2567]! } + public var Conversation_EncryptionProcessing: String { return self._s[2569]! } + public var Notifications_PermissionsSuppressWarningTitle: String { return self._s[2570]! } + public var PhotoEditor_EnhanceTool: String { return self._s[2572]! } + public var Channel_Setup_Title: String { return self._s[2573]! } + public var Conversation_SearchPlaceholder: String { return self._s[2574]! } + public var OldChannels_GroupEmptyFormat: String { return self._s[2575]! } + public var AccessDenied_LocationAlwaysDenied: String { return self._s[2576]! } + public var Checkout_ErrorGeneric: String { return self._s[2577]! } + public var Passport_Language_hu: String { return self._s[2578]! } + public var GroupPermission_EditingDisabled: String { return self._s[2579]! } + public var Wallet_Month_ShortSeptember: String { return self._s[2581]! } public func Passport_Identity_UploadOneOfScan(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2580]!, self._r[2580]!, [_0]) + return formatWithArgumentRanges(self._s[2582]!, self._r[2582]!, [_0]) } public func PUSH_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2583]!, self._r[2583]!, [_1]) + return formatWithArgumentRanges(self._s[2585]!, self._r[2585]!, [_1]) } - public var ChatList_DeleteSavedMessagesConfirmationTitle: String { return self._s[2584]! } + public var ChatList_DeleteSavedMessagesConfirmationTitle: String { return self._s[2586]! } public func UserInfo_BlockConfirmationTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2585]!, self._r[2585]!, [_0]) + return formatWithArgumentRanges(self._s[2587]!, self._r[2587]!, [_0]) } - public var Conversation_CloudStorageInfo_Title: String { return self._s[2586]! } - public var Group_Location_Info: String { return self._s[2587]! } - public var PhotoEditor_CropAspectRatioSquare: String { return self._s[2588]! } - public var Permissions_PeopleNearbyAllow_v0: String { return self._s[2589]! } + public var Conversation_CloudStorageInfo_Title: String { return self._s[2588]! } + public var Group_Location_Info: String { return self._s[2589]! } + public var PhotoEditor_CropAspectRatioSquare: String { return self._s[2590]! } + public var Permissions_PeopleNearbyAllow_v0: String { return self._s[2591]! } public func Notification_Exceptions_MutedUntil(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2590]!, self._r[2590]!, [_0]) + return formatWithArgumentRanges(self._s[2592]!, self._r[2592]!, [_0]) } - public var Conversation_ClearPrivateHistory: String { return self._s[2591]! } - public var ContactInfo_PhoneLabelHome: String { return self._s[2592]! } - public var Appearance_RemoveThemeConfirmation: String { return self._s[2593]! } - public var PrivacySettings_LastSeenContacts: String { return self._s[2594]! } + public var Conversation_ClearPrivateHistory: String { return self._s[2593]! } + public var ContactInfo_PhoneLabelHome: String { return self._s[2594]! } + public var Appearance_RemoveThemeConfirmation: String { return self._s[2595]! } + public var PrivacySettings_LastSeenContacts: String { return self._s[2596]! } public func ChangePhone_ErrorOccupied(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2595]!, self._r[2595]!, [_0]) + return formatWithArgumentRanges(self._s[2597]!, self._r[2597]!, [_0]) } - public var Passport_Language_cs: String { return self._s[2596]! } - public var Message_PinnedAnimationMessage: String { return self._s[2598]! } - public var Passport_Identity_ReverseSideHelp: String { return self._s[2600]! } - public var SettingsSearch_Synonyms_Data_Storage_Title: String { return self._s[2601]! } - public var Wallet_Info_TransactionTo: String { return self._s[2603]! } - public var ChatList_DeleteForEveryoneConfirmationText: String { return self._s[2604]! } - public var SettingsSearch_Synonyms_Privacy_PasscodeAndTouchId: String { return self._s[2605]! } - public var Embed_PlayingInPIP: String { return self._s[2606]! } - public var Appearance_ThemePreview_Chat_3_TextWithLink: String { return self._s[2607]! } - public var AutoNightTheme_ScheduleSection: String { return self._s[2608]! } + public func Notification_PinnedQuizMessage(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2598]!, self._r[2598]!, [_0]) + } + public var Passport_Language_cs: String { return self._s[2599]! } + public var Message_PinnedAnimationMessage: String { return self._s[2601]! } + public var Passport_Identity_ReverseSideHelp: String { return self._s[2603]! } + public var SettingsSearch_Synonyms_Data_Storage_Title: String { return self._s[2604]! } + public var Wallet_Info_TransactionTo: String { return self._s[2606]! } + public var ChatList_DeleteForEveryoneConfirmationText: String { return self._s[2607]! } + public var SettingsSearch_Synonyms_Privacy_PasscodeAndTouchId: String { return self._s[2608]! } + public var Embed_PlayingInPIP: String { return self._s[2609]! } + public var Appearance_ThemePreview_Chat_3_TextWithLink: String { return self._s[2610]! } + public var AutoNightTheme_ScheduleSection: String { return self._s[2611]! } public func Call_EmojiDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2609]!, self._r[2609]!, [_0]) + return formatWithArgumentRanges(self._s[2612]!, self._r[2612]!, [_0]) } - public var MediaPicker_LivePhotoDescription: String { return self._s[2610]! } + public var MediaPicker_LivePhotoDescription: String { return self._s[2613]! } public func Channel_AdminLog_MessageRestrictedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2611]!, self._r[2611]!, [_1]) + return formatWithArgumentRanges(self._s[2614]!, self._r[2614]!, [_1]) } - public var Notification_PaymentSent: String { return self._s[2612]! } - public var PhotoEditor_CurvesGreen: String { return self._s[2613]! } - public var Notification_Exceptions_PreviewAlwaysOff: String { return self._s[2614]! } - public var AutoNightTheme_System: String { return self._s[2615]! } - public var SaveIncomingPhotosSettings_Title: String { return self._s[2616]! } - public var CreatePoll_QuizTitle: String { return self._s[2617]! } - public var NotificationSettings_ShowNotificationsAllAccounts: String { return self._s[2618]! } - public var VoiceOver_Chat_PagePreview: String { return self._s[2619]! } + public var Notification_PaymentSent: String { return self._s[2615]! } + public var PhotoEditor_CurvesGreen: String { return self._s[2616]! } + public var Notification_Exceptions_PreviewAlwaysOff: String { return self._s[2617]! } + public var AutoNightTheme_System: String { return self._s[2618]! } + public var SaveIncomingPhotosSettings_Title: String { return self._s[2619]! } + public var CreatePoll_QuizTitle: String { return self._s[2620]! } + public var NotificationSettings_ShowNotificationsAllAccounts: String { return self._s[2621]! } + public var VoiceOver_Chat_PagePreview: String { return self._s[2622]! } public func PUSH_MESSAGE_SCREENSHOT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2622]!, self._r[2622]!, [_1]) + return formatWithArgumentRanges(self._s[2625]!, self._r[2625]!, [_1]) } public func PUSH_MESSAGE_PHOTO_SECRET(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2623]!, self._r[2623]!, [_1]) + return formatWithArgumentRanges(self._s[2626]!, self._r[2626]!, [_1]) } public func ApplyLanguage_UnsufficientDataText(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2624]!, self._r[2624]!, [_1]) + return formatWithArgumentRanges(self._s[2627]!, self._r[2627]!, [_1]) } - public var NetworkUsageSettings_CallDataSection: String { return self._s[2626]! } - public var PasscodeSettings_HelpTop: String { return self._s[2627]! } - public var Conversation_WalletRequiredTitle: String { return self._s[2628]! } - public var Group_OwnershipTransfer_ErrorAdminsTooMuch: String { return self._s[2629]! } - public var Passport_Address_TypeRentalAgreement: String { return self._s[2630]! } - public var EditTheme_ShortLink: String { return self._s[2631]! } - public var Theme_Colors_ColorWallpaperWarning: String { return self._s[2632]! } - public var ProxyServer_VoiceOver_Active: String { return self._s[2633]! } - public var ReportPeer_ReasonOther_Placeholder: String { return self._s[2634]! } - public var CheckoutInfo_ErrorPhoneInvalid: String { return self._s[2635]! } - public var Call_Accept: String { return self._s[2637]! } - public var GroupRemoved_RemoveInfo: String { return self._s[2638]! } - public var Month_GenMarch: String { return self._s[2640]! } - public var PhotoEditor_ShadowsTool: String { return self._s[2641]! } - public var LoginPassword_Title: String { return self._s[2642]! } - public var Call_End: String { return self._s[2643]! } - public var Watch_Conversation_GroupInfo: String { return self._s[2644]! } - public var VoiceOver_Chat_Contact: String { return self._s[2645]! } - public var EditTheme_Create_Preview_IncomingText: String { return self._s[2646]! } - public var CallSettings_Always: String { return self._s[2647]! } - public var CallFeedback_Success: String { return self._s[2648]! } - public var TwoStepAuth_SetupHint: String { return self._s[2649]! } + public var NetworkUsageSettings_CallDataSection: String { return self._s[2629]! } + public var PasscodeSettings_HelpTop: String { return self._s[2630]! } + public var Conversation_WalletRequiredTitle: String { return self._s[2631]! } + public var Group_OwnershipTransfer_ErrorAdminsTooMuch: String { return self._s[2632]! } + public var Passport_Address_TypeRentalAgreement: String { return self._s[2633]! } + public var EditTheme_ShortLink: String { return self._s[2634]! } + public var Theme_Colors_ColorWallpaperWarning: String { return self._s[2635]! } + public var ProxyServer_VoiceOver_Active: String { return self._s[2636]! } + public var ReportPeer_ReasonOther_Placeholder: String { return self._s[2637]! } + public var CheckoutInfo_ErrorPhoneInvalid: String { return self._s[2638]! } + public var Call_Accept: String { return self._s[2640]! } + public var GroupRemoved_RemoveInfo: String { return self._s[2641]! } + public var Month_GenMarch: String { return self._s[2643]! } + public var PhotoEditor_ShadowsTool: String { return self._s[2644]! } + public var LoginPassword_Title: String { return self._s[2645]! } + public var Call_End: String { return self._s[2646]! } + public var Watch_Conversation_GroupInfo: String { return self._s[2647]! } + public var VoiceOver_Chat_Contact: String { return self._s[2648]! } + public var EditTheme_Create_Preview_IncomingText: String { return self._s[2649]! } + public var CallSettings_Always: String { return self._s[2650]! } + public var CallFeedback_Success: String { return self._s[2651]! } + public var TwoStepAuth_SetupHint: String { return self._s[2652]! } public func AddContact_ContactWillBeSharedAfterMutual(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2650]!, self._r[2650]!, [_1]) + return formatWithArgumentRanges(self._s[2653]!, self._r[2653]!, [_1]) } - public var ConversationProfile_UsersTooMuchError: String { return self._s[2651]! } - public var Login_PhoneTitle: String { return self._s[2652]! } - public var Passport_FieldPhoneHelp: String { return self._s[2653]! } - public var Weekday_ShortSunday: String { return self._s[2654]! } - public var Passport_InfoFAQ_URL: String { return self._s[2655]! } - public var ContactInfo_Job: String { return self._s[2657]! } - public var UserInfo_InviteBotToGroup: String { return self._s[2658]! } - public var Appearance_ThemeCarouselNightBlue: String { return self._s[2659]! } - public var CreatePoll_QuizTip: String { return self._s[2660]! } - public var TwoFactorSetup_Email_Text: String { return self._s[2661]! } - public var TwoStepAuth_PasswordRemovePassportConfirmation: String { return self._s[2662]! } - public var Invite_ChannelsTooMuch: String { return self._s[2663]! } - public var Wallet_Send_ConfirmationConfirm: String { return self._s[2664]! } - public var Wallet_TransactionInfo_OtherFeeInfo: String { return self._s[2665]! } - public var SettingsSearch_Synonyms_Notifications_InAppNotificationsPreview: String { return self._s[2666]! } - public var Wallet_Receive_AmountText: String { return self._s[2667]! } - public var Passport_DeletePersonalDetailsConfirmation: String { return self._s[2668]! } - public var CallFeedback_ReasonNoise: String { return self._s[2669]! } - public var Appearance_AppIconDefault: String { return self._s[2671]! } - public var Passport_Identity_AddInternalPassport: String { return self._s[2672]! } - public var MediaPicker_AddCaption: String { return self._s[2673]! } - public var CallSettings_TabIconDescription: String { return self._s[2674]! } + public var ConversationProfile_UsersTooMuchError: String { return self._s[2654]! } + public var Login_PhoneTitle: String { return self._s[2655]! } + public var Passport_FieldPhoneHelp: String { return self._s[2656]! } + public var Weekday_ShortSunday: String { return self._s[2657]! } + public var Passport_InfoFAQ_URL: String { return self._s[2658]! } + public var ContactInfo_Job: String { return self._s[2660]! } + public var UserInfo_InviteBotToGroup: String { return self._s[2661]! } + public var Appearance_ThemeCarouselNightBlue: String { return self._s[2662]! } + public var CreatePoll_QuizTip: String { return self._s[2663]! } + public var TwoFactorSetup_Email_Text: String { return self._s[2664]! } + public var TwoStepAuth_PasswordRemovePassportConfirmation: String { return self._s[2665]! } + public var Invite_ChannelsTooMuch: String { return self._s[2666]! } + public var Wallet_Send_ConfirmationConfirm: String { return self._s[2667]! } + public var Wallet_TransactionInfo_OtherFeeInfo: String { return self._s[2668]! } + public var SettingsSearch_Synonyms_Notifications_InAppNotificationsPreview: String { return self._s[2669]! } + public var Wallet_Receive_AmountText: String { return self._s[2670]! } + public var Passport_DeletePersonalDetailsConfirmation: String { return self._s[2671]! } + public var CallFeedback_ReasonNoise: String { return self._s[2672]! } + public var Appearance_AppIconDefault: String { return self._s[2674]! } + public var Passport_Identity_AddInternalPassport: String { return self._s[2675]! } + public var MediaPicker_AddCaption: String { return self._s[2676]! } + public var CallSettings_TabIconDescription: String { return self._s[2677]! } public func VoiceOver_Chat_Caption(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2675]!, self._r[2675]!, [_0]) + return formatWithArgumentRanges(self._s[2678]!, self._r[2678]!, [_0]) } - public var IntentsSettings_SuggestedChatsGroups: String { return self._s[2676]! } + public var IntentsSettings_SuggestedChatsGroups: String { return self._s[2679]! } public func Map_SearchNoResultsDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2677]!, self._r[2677]!, [_0]) + return formatWithArgumentRanges(self._s[2680]!, self._r[2680]!, [_0]) } - public var ChatList_UndoArchiveHiddenTitle: String { return self._s[2678]! } - public var Privacy_GroupsAndChannels_AlwaysAllow: String { return self._s[2679]! } - public var Passport_Identity_TypePersonalDetails: String { return self._s[2680]! } - public var DialogList_SearchSectionRecent: String { return self._s[2681]! } - public var PrivacyPolicy_DeclineMessage: String { return self._s[2682]! } - public var CreatePoll_Anonymous: String { return self._s[2683]! } - public var LogoutOptions_ClearCacheText: String { return self._s[2686]! } - public var LastSeen_WithinAWeek: String { return self._s[2687]! } - public var ChannelMembers_GroupAdminsTitle: String { return self._s[2688]! } - public var Conversation_CloudStorage_ChatStatus: String { return self._s[2690]! } - public var VoiceOver_Media_PlaybackRateNormal: String { return self._s[2691]! } + public var ChatList_UndoArchiveHiddenTitle: String { return self._s[2681]! } + public var Privacy_GroupsAndChannels_AlwaysAllow: String { return self._s[2682]! } + public var Passport_Identity_TypePersonalDetails: String { return self._s[2683]! } + public var DialogList_SearchSectionRecent: String { return self._s[2684]! } + public var PrivacyPolicy_DeclineMessage: String { return self._s[2685]! } + public var CreatePoll_Anonymous: String { return self._s[2686]! } + public var LogoutOptions_ClearCacheText: String { return self._s[2689]! } + public var LastSeen_WithinAWeek: String { return self._s[2690]! } + public var ChannelMembers_GroupAdminsTitle: String { return self._s[2691]! } + public var Conversation_CloudStorage_ChatStatus: String { return self._s[2693]! } + public var VoiceOver_Media_PlaybackRateNormal: String { return self._s[2694]! } public func AddContact_SharedContactExceptionInfo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2692]!, self._r[2692]!, [_0]) + return formatWithArgumentRanges(self._s[2695]!, self._r[2695]!, [_0]) } - public var Passport_Address_TypeResidentialAddress: String { return self._s[2693]! } - public var Conversation_StatusLeftGroup: String { return self._s[2694]! } - public var SocksProxySetup_ProxyDetailsTitle: String { return self._s[2695]! } - public var SettingsSearch_Synonyms_Calls_Title: String { return self._s[2697]! } - public var GroupPermission_AddSuccess: String { return self._s[2698]! } - public var PhotoEditor_BlurToolRadial: String { return self._s[2700]! } - public var Conversation_ContextMenuCopy: String { return self._s[2701]! } - public var AccessDenied_CallMicrophone: String { return self._s[2702]! } + public var Passport_Address_TypeResidentialAddress: String { return self._s[2696]! } + public var Conversation_StatusLeftGroup: String { return self._s[2697]! } + public var SocksProxySetup_ProxyDetailsTitle: String { return self._s[2698]! } + public var SettingsSearch_Synonyms_Calls_Title: String { return self._s[2700]! } + public var GroupPermission_AddSuccess: String { return self._s[2701]! } + public var PhotoEditor_BlurToolRadial: String { return self._s[2703]! } + public var Conversation_ContextMenuCopy: String { return self._s[2704]! } + public var AccessDenied_CallMicrophone: String { return self._s[2705]! } public func Time_PreciseDate_m2(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2703]!, self._r[2703]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2706]!, self._r[2706]!, [_1, _2, _3]) } - public var Login_InvalidFirstNameError: String { return self._s[2704]! } - public var Notifications_Badge_CountUnreadMessages_InfoOn: String { return self._s[2705]! } - public var Checkout_PaymentMethod_New: String { return self._s[2706]! } - public var ShareMenu_CopyShareLinkGame: String { return self._s[2707]! } - public var PhotoEditor_QualityTool: String { return self._s[2708]! } - public var Login_SendCodeViaSms: String { return self._s[2709]! } - public var SettingsSearch_Synonyms_Privacy_DeleteAccountIfAwayFor: String { return self._s[2710]! } - public var Chat_SlowmodeAttachmentLimitReached: String { return self._s[2711]! } - public var Wallet_Receive_CopyAddress: String { return self._s[2712]! } - public var Login_EmailNotConfiguredError: String { return self._s[2713]! } - public var SocksProxySetup_Status: String { return self._s[2714]! } - public var Conversation_ScheduleMessage_SendWhenOnline: String { return self._s[2715]! } - public var PrivacyPolicy_Accept: String { return self._s[2716]! } - public var Notifications_ExceptionsMessagePlaceholder: String { return self._s[2717]! } - public var Appearance_AppIconClassicX: String { return self._s[2718]! } + public var Login_InvalidFirstNameError: String { return self._s[2707]! } + public var Notifications_Badge_CountUnreadMessages_InfoOn: String { return self._s[2708]! } + public var Checkout_PaymentMethod_New: String { return self._s[2709]! } + public var ShareMenu_CopyShareLinkGame: String { return self._s[2710]! } + public var PhotoEditor_QualityTool: String { return self._s[2711]! } + public var Login_SendCodeViaSms: String { return self._s[2712]! } + public var SettingsSearch_Synonyms_Privacy_DeleteAccountIfAwayFor: String { return self._s[2713]! } + public var Chat_SlowmodeAttachmentLimitReached: String { return self._s[2714]! } + public var Wallet_Receive_CopyAddress: String { return self._s[2715]! } + public var Login_EmailNotConfiguredError: String { return self._s[2716]! } + public var SocksProxySetup_Status: String { return self._s[2717]! } + public var Conversation_ScheduleMessage_SendWhenOnline: String { return self._s[2718]! } + public var PrivacyPolicy_Accept: String { return self._s[2719]! } + public var Notifications_ExceptionsMessagePlaceholder: String { return self._s[2720]! } + public var Appearance_AppIconClassicX: String { return self._s[2721]! } public func PUSH_CHAT_MESSAGE_TEXT(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2719]!, self._r[2719]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2722]!, self._r[2722]!, [_1, _2, _3]) } - public var OwnershipTransfer_SecurityRequirements: String { return self._s[2720]! } - public var InfoPlist_NSLocationAlwaysUsageDescription: String { return self._s[2722]! } - public var AutoNightTheme_Automatic: String { return self._s[2723]! } - public var Channel_Username_InvalidStartsWithNumber: String { return self._s[2724]! } - public var Privacy_ContactsSyncHelp: String { return self._s[2725]! } - public var Cache_Help: String { return self._s[2726]! } - public var Group_ErrorAccessDenied: String { return self._s[2727]! } - public var Passport_Language_fa: String { return self._s[2728]! } - public var Wallet_Intro_Text: String { return self._s[2729]! } - public var Login_ResetAccountProtected_TimerTitle: String { return self._s[2730]! } - public var VoiceOver_Chat_YourVideoMessage: String { return self._s[2731]! } - public var PrivacySettings_LastSeen: String { return self._s[2732]! } + public var OwnershipTransfer_SecurityRequirements: String { return self._s[2723]! } + public var InfoPlist_NSLocationAlwaysUsageDescription: String { return self._s[2725]! } + public var AutoNightTheme_Automatic: String { return self._s[2726]! } + public var Channel_Username_InvalidStartsWithNumber: String { return self._s[2727]! } + public var Privacy_ContactsSyncHelp: String { return self._s[2728]! } + public var Cache_Help: String { return self._s[2729]! } + public var Group_ErrorAccessDenied: String { return self._s[2730]! } + public var Passport_Language_fa: String { return self._s[2731]! } + public var Wallet_Intro_Text: String { return self._s[2732]! } + public var Login_ResetAccountProtected_TimerTitle: String { return self._s[2733]! } + public var VoiceOver_Chat_YourVideoMessage: String { return self._s[2734]! } + public var PrivacySettings_LastSeen: String { return self._s[2735]! } public func DialogList_MultipleTyping(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2733]!, self._r[2733]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2736]!, self._r[2736]!, [_0, _1]) } - public var Wallet_Configuration_Apply: String { return self._s[2737]! } - public var Preview_SaveGif: String { return self._s[2738]! } - public var SettingsSearch_Synonyms_Privacy_TwoStepAuth: String { return self._s[2739]! } - public var Profile_About: String { return self._s[2740]! } - public var Channel_About_Placeholder: String { return self._s[2741]! } - public var Login_InfoTitle: String { return self._s[2742]! } + public var Wallet_Configuration_Apply: String { return self._s[2740]! } + public var Preview_SaveGif: String { return self._s[2741]! } + public var SettingsSearch_Synonyms_Privacy_TwoStepAuth: String { return self._s[2742]! } + public var Profile_About: String { return self._s[2743]! } + public var Channel_About_Placeholder: String { return self._s[2744]! } + public var Login_InfoTitle: String { return self._s[2745]! } public func TwoStepAuth_SetupPendingEmail(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2743]!, self._r[2743]!, [_0]) + return formatWithArgumentRanges(self._s[2746]!, self._r[2746]!, [_0]) } - public var EditTheme_Expand_Preview_IncomingReplyText: String { return self._s[2744]! } - public var Watch_Suggestion_CantTalk: String { return self._s[2746]! } - public var ContactInfo_Title: String { return self._s[2747]! } - public var Media_ShareThisVideo: String { return self._s[2748]! } - public var Weekday_ShortFriday: String { return self._s[2749]! } - public var AccessDenied_Contacts: String { return self._s[2751]! } - public var Notification_CallIncomingShort: String { return self._s[2752]! } - public var Group_Setup_TypePublic: String { return self._s[2753]! } - public var Notifications_MessageNotificationsExceptions: String { return self._s[2754]! } - public var Notifications_Badge_IncludeChannels: String { return self._s[2755]! } - public var Notifications_MessageNotificationsPreview: String { return self._s[2758]! } - public var ConversationProfile_ErrorCreatingConversation: String { return self._s[2759]! } - public var Group_ErrorAddTooMuchBots: String { return self._s[2760]! } - public var Privacy_GroupsAndChannels_CustomShareHelp: String { return self._s[2761]! } - public var Permissions_CellularDataAllowInSettings_v0: String { return self._s[2762]! } + public var EditTheme_Expand_Preview_IncomingReplyText: String { return self._s[2747]! } + public var Watch_Suggestion_CantTalk: String { return self._s[2749]! } + public var ContactInfo_Title: String { return self._s[2750]! } + public var Media_ShareThisVideo: String { return self._s[2751]! } + public var Weekday_ShortFriday: String { return self._s[2752]! } + public var AccessDenied_Contacts: String { return self._s[2754]! } + public var Notification_CallIncomingShort: String { return self._s[2755]! } + public var Group_Setup_TypePublic: String { return self._s[2756]! } + public var Notifications_MessageNotificationsExceptions: String { return self._s[2757]! } + public var Notifications_Badge_IncludeChannels: String { return self._s[2758]! } + public var Notifications_MessageNotificationsPreview: String { return self._s[2761]! } + public var ConversationProfile_ErrorCreatingConversation: String { return self._s[2762]! } + public var Group_ErrorAddTooMuchBots: String { return self._s[2763]! } + public var Privacy_GroupsAndChannels_CustomShareHelp: String { return self._s[2764]! } + public var Permissions_CellularDataAllowInSettings_v0: String { return self._s[2765]! } public func Wallet_SecureStorageChanged_BiometryText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2763]!, self._r[2763]!, [_0]) + return formatWithArgumentRanges(self._s[2766]!, self._r[2766]!, [_0]) } - public var DialogList_Typing: String { return self._s[2764]! } - public var CallFeedback_IncludeLogs: String { return self._s[2766]! } - public var Checkout_Phone: String { return self._s[2768]! } - public var Login_InfoFirstNamePlaceholder: String { return self._s[2771]! } - public var Privacy_Calls_Integration: String { return self._s[2772]! } - public var Notifications_PermissionsAllow: String { return self._s[2773]! } - public var TwoStepAuth_AddHintDescription: String { return self._s[2777]! } - public var Settings_ChatSettings: String { return self._s[2778]! } - public var Conversation_SendingOptionsTooltip: String { return self._s[2779]! } + public var DialogList_Typing: String { return self._s[2767]! } + public var CallFeedback_IncludeLogs: String { return self._s[2769]! } + public var Checkout_Phone: String { return self._s[2771]! } + public var Login_InfoFirstNamePlaceholder: String { return self._s[2774]! } + public var Privacy_Calls_Integration: String { return self._s[2775]! } + public var Notifications_PermissionsAllow: String { return self._s[2776]! } + public var TwoStepAuth_AddHintDescription: String { return self._s[2780]! } + public var Settings_ChatSettings: String { return self._s[2781]! } + public var Conversation_SendingOptionsTooltip: String { return self._s[2782]! } public func UserInfo_StartSecretChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2781]!, self._r[2781]!, [_0]) + return formatWithArgumentRanges(self._s[2784]!, self._r[2784]!, [_0]) } public func Channel_AdminLog_MessageInvitedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2782]!, self._r[2782]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2785]!, self._r[2785]!, [_1, _2]) } - public var GroupRemoved_DeleteUser: String { return self._s[2784]! } + public var GroupRemoved_DeleteUser: String { return self._s[2787]! } public func Channel_AdminLog_PollStopped(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2785]!, self._r[2785]!, [_0]) + return formatWithArgumentRanges(self._s[2788]!, self._r[2788]!, [_0]) } public func PUSH_MESSAGE_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2786]!, self._r[2786]!, [_1]) + return formatWithArgumentRanges(self._s[2789]!, self._r[2789]!, [_1]) } - public var Login_ContinueWithLocalization: String { return self._s[2787]! } - public var Watch_Message_ForwardedFrom: String { return self._s[2788]! } - public var TwoStepAuth_EnterEmailCode: String { return self._s[2790]! } - public var Conversation_Unblock: String { return self._s[2791]! } - public var PrivacySettings_DataSettings: String { return self._s[2792]! } - public var WallpaperPreview_PatternPaternApply: String { return self._s[2793]! } - public var Group_PublicLink_Info: String { return self._s[2794]! } + public var Login_ContinueWithLocalization: String { return self._s[2790]! } + public var Watch_Message_ForwardedFrom: String { return self._s[2791]! } + public var TwoStepAuth_EnterEmailCode: String { return self._s[2793]! } + public var Conversation_Unblock: String { return self._s[2794]! } + public var PrivacySettings_DataSettings: String { return self._s[2795]! } + public var WallpaperPreview_PatternPaternApply: String { return self._s[2796]! } + public var Group_PublicLink_Info: String { return self._s[2797]! } public func Wallet_Time_PreciseDate_m1(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2795]!, self._r[2795]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2798]!, self._r[2798]!, [_1, _2, _3]) } - public var Notifications_InAppNotificationsVibrate: String { return self._s[2796]! } + public var Notifications_InAppNotificationsVibrate: String { return self._s[2799]! } public func Privacy_GroupsAndChannels_InviteToChannelError(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2797]!, self._r[2797]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2800]!, self._r[2800]!, [_0, _1]) } - public var OldChannels_ChannelsHeader: String { return self._s[2799]! } - public var Wallet_RestoreFailed_CreateWallet: String { return self._s[2800]! } - public var PrivacySettings_Passcode: String { return self._s[2802]! } - public var Call_Mute: String { return self._s[2803]! } - public var Wallet_Weekday_Yesterday: String { return self._s[2804]! } - public var Passport_Language_dz: String { return self._s[2805]! } - public var Wallet_Receive_AmountHeader: String { return self._s[2806]! } - public var Wallet_TransactionInfo_OtherFeeInfoUrl: String { return self._s[2807]! } - public var Passport_Language_tk: String { return self._s[2808]! } + public var OldChannels_ChannelsHeader: String { return self._s[2802]! } + public var Wallet_RestoreFailed_CreateWallet: String { return self._s[2803]! } + public var PrivacySettings_Passcode: String { return self._s[2805]! } + public var Call_Mute: String { return self._s[2806]! } + public var Wallet_Weekday_Yesterday: String { return self._s[2807]! } + public var Passport_Language_dz: String { return self._s[2808]! } + public var Wallet_Receive_AmountHeader: String { return self._s[2809]! } + public var Wallet_TransactionInfo_OtherFeeInfoUrl: String { return self._s[2810]! } + public var Passport_Language_tk: String { return self._s[2811]! } public func Login_EmailCodeSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2809]!, self._r[2809]!, [_0]) + return formatWithArgumentRanges(self._s[2812]!, self._r[2812]!, [_0]) } - public var Settings_Search: String { return self._s[2810]! } - public var Wallet_Month_ShortFebruary: String { return self._s[2811]! } - public var InfoPlist_NSPhotoLibraryUsageDescription: String { return self._s[2812]! } - public var Wallet_Configuration_SourceJSON: String { return self._s[2813]! } - public var Conversation_ContextMenuReply: String { return self._s[2814]! } - public var WallpaperSearch_ColorBrown: String { return self._s[2815]! } - public var Chat_AttachmentMultipleForwardDisabled: String { return self._s[2816]! } - public var Tour_Title1: String { return self._s[2817]! } - public var Wallet_Alert_Cancel: String { return self._s[2818]! } - public var Conversation_ClearGroupHistory: String { return self._s[2820]! } - public var Wallet_TransactionInfo_RecipientHeader: String { return self._s[2821]! } - public var WallpaperPreview_Motion: String { return self._s[2822]! } + public var Settings_Search: String { return self._s[2813]! } + public var Wallet_Month_ShortFebruary: String { return self._s[2814]! } + public var InfoPlist_NSPhotoLibraryUsageDescription: String { return self._s[2815]! } + public var Wallet_Configuration_SourceJSON: String { return self._s[2816]! } + public var Conversation_ContextMenuReply: String { return self._s[2817]! } + public var WallpaperSearch_ColorBrown: String { return self._s[2818]! } + public var Chat_AttachmentMultipleForwardDisabled: String { return self._s[2819]! } + public var Tour_Title1: String { return self._s[2820]! } + public var Wallet_Alert_Cancel: String { return self._s[2821]! } + public var Conversation_ClearGroupHistory: String { return self._s[2823]! } + public var Wallet_TransactionInfo_RecipientHeader: String { return self._s[2824]! } + public var WallpaperPreview_Motion: String { return self._s[2825]! } public func Checkout_PasswordEntry_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2823]!, self._r[2823]!, [_0]) + return formatWithArgumentRanges(self._s[2826]!, self._r[2826]!, [_0]) } - public var Wallet_Configuration_ApplyErrorTextJSONInvalidData: String { return self._s[2824]! } - public var Call_RateCall: String { return self._s[2825]! } - public var Channel_AdminLog_BanSendStickersAndGifs: String { return self._s[2826]! } - public var Passport_PasswordCompleteSetup: String { return self._s[2827]! } - public var Conversation_InputTextSilentBroadcastPlaceholder: String { return self._s[2828]! } - public var UserInfo_LastNamePlaceholder: String { return self._s[2830]! } + public var Wallet_Configuration_ApplyErrorTextJSONInvalidData: String { return self._s[2827]! } + public var Call_RateCall: String { return self._s[2828]! } + public var Channel_AdminLog_BanSendStickersAndGifs: String { return self._s[2829]! } + public var Passport_PasswordCompleteSetup: String { return self._s[2830]! } + public var Conversation_InputTextSilentBroadcastPlaceholder: String { return self._s[2831]! } + public var UserInfo_LastNamePlaceholder: String { return self._s[2833]! } public func Login_WillCallYou(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2832]!, self._r[2832]!, [_0]) + return formatWithArgumentRanges(self._s[2835]!, self._r[2835]!, [_0]) } - public var Compose_Create: String { return self._s[2833]! } - public var Contacts_InviteToTelegram: String { return self._s[2834]! } - public var GroupInfo_Notifications: String { return self._s[2835]! } - public var ChatList_DeleteSavedMessagesConfirmationAction: String { return self._s[2837]! } - public var Message_PinnedLiveLocationMessage: String { return self._s[2838]! } - public var Month_GenApril: String { return self._s[2839]! } - public var Appearance_AutoNightTheme: String { return self._s[2840]! } - public var ChatSettings_AutomaticAudioDownload: String { return self._s[2842]! } - public var Login_CodeSentSms: String { return self._s[2844]! } + public var Compose_Create: String { return self._s[2836]! } + public var Contacts_InviteToTelegram: String { return self._s[2837]! } + public var GroupInfo_Notifications: String { return self._s[2838]! } + public var ChatList_DeleteSavedMessagesConfirmationAction: String { return self._s[2840]! } + public var Message_PinnedLiveLocationMessage: String { return self._s[2841]! } + public var Month_GenApril: String { return self._s[2842]! } + public var Appearance_AutoNightTheme: String { return self._s[2843]! } + public var ChatSettings_AutomaticAudioDownload: String { return self._s[2845]! } + public var Login_CodeSentSms: String { return self._s[2847]! } public func UserInfo_UnblockConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2845]!, self._r[2845]!, [_0]) + return formatWithArgumentRanges(self._s[2848]!, self._r[2848]!, [_0]) } - public var EmptyGroupInfo_Line3: String { return self._s[2846]! } - public var LogoutOptions_ContactSupportText: String { return self._s[2847]! } - public var Passport_Language_hr: String { return self._s[2848]! } - public var Common_ActionNotAllowedError: String { return self._s[2849]! } + public var EmptyGroupInfo_Line3: String { return self._s[2849]! } + public var LogoutOptions_ContactSupportText: String { return self._s[2850]! } + public var Passport_Language_hr: String { return self._s[2851]! } + public var Common_ActionNotAllowedError: String { return self._s[2852]! } public func Channel_AdminLog_MessageRestrictedNewSetting(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2850]!, self._r[2850]!, [_0]) + return formatWithArgumentRanges(self._s[2853]!, self._r[2853]!, [_0]) } - public var GroupInfo_InviteLink_CopyLink: String { return self._s[2851]! } - public var Wallet_Info_TransactionFrom: String { return self._s[2852]! } - public var Wallet_Send_ErrorDecryptionFailed: String { return self._s[2853]! } - public var Conversation_InputTextBroadcastPlaceholder: String { return self._s[2854]! } - public var Privacy_SecretChatsTitle: String { return self._s[2855]! } - public var Notification_SecretChatMessageScreenshotSelf: String { return self._s[2857]! } - public var GroupInfo_AddUserLeftError: String { return self._s[2858]! } - public var AutoDownloadSettings_TypePrivateChats: String { return self._s[2859]! } - public var LogoutOptions_ContactSupportTitle: String { return self._s[2860]! } - public var Appearance_ThemePreview_Chat_7_Text: String { return self._s[2861]! } - public var Channel_AddBotErrorHaveRights: String { return self._s[2862]! } - public var Preview_DeleteGif: String { return self._s[2863]! } - public var GroupInfo_Permissions_Exceptions: String { return self._s[2864]! } - public var Group_ErrorNotMutualContact: String { return self._s[2865]! } - public var Notification_MessageLifetime5s: String { return self._s[2866]! } - public var Wallet_Send_OwnAddressAlertText: String { return self._s[2867]! } - public var OldChannels_ChannelFormat: String { return self._s[2868]! } + public var GroupInfo_InviteLink_CopyLink: String { return self._s[2854]! } + public var Wallet_Info_TransactionFrom: String { return self._s[2855]! } + public var Wallet_Send_ErrorDecryptionFailed: String { return self._s[2856]! } + public var Conversation_InputTextBroadcastPlaceholder: String { return self._s[2857]! } + public var Privacy_SecretChatsTitle: String { return self._s[2858]! } + public var Notification_SecretChatMessageScreenshotSelf: String { return self._s[2860]! } + public var GroupInfo_AddUserLeftError: String { return self._s[2861]! } + public var AutoDownloadSettings_TypePrivateChats: String { return self._s[2862]! } + public var LogoutOptions_ContactSupportTitle: String { return self._s[2863]! } + public var Appearance_ThemePreview_Chat_7_Text: String { return self._s[2864]! } + public var Channel_AddBotErrorHaveRights: String { return self._s[2865]! } + public var Preview_DeleteGif: String { return self._s[2866]! } + public var GroupInfo_Permissions_Exceptions: String { return self._s[2867]! } + public var Group_ErrorNotMutualContact: String { return self._s[2868]! } + public var Notification_MessageLifetime5s: String { return self._s[2869]! } + public var Wallet_Send_OwnAddressAlertText: String { return self._s[2870]! } + public var OldChannels_ChannelFormat: String { return self._s[2871]! } public func Watch_LastSeen_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2869]!, self._r[2869]!, [_0]) + return formatWithArgumentRanges(self._s[2872]!, self._r[2872]!, [_0]) } - public var VoiceOver_Chat_Video: String { return self._s[2870]! } - public var Channel_OwnershipTransfer_ErrorPublicChannelsTooMuch: String { return self._s[2872]! } - public var ReportSpam_DeleteThisChat: String { return self._s[2873]! } - public var Passport_Address_AddBankStatement: String { return self._s[2874]! } - public var Notification_CallIncoming: String { return self._s[2875]! } - public var Wallet_Words_NotDoneTitle: String { return self._s[2876]! } - public var Compose_NewGroupTitle: String { return self._s[2877]! } - public var TwoStepAuth_RecoveryCodeHelp: String { return self._s[2879]! } - public var Passport_Address_Postcode: String { return self._s[2881]! } + public var VoiceOver_Chat_Video: String { return self._s[2873]! } + public var Channel_OwnershipTransfer_ErrorPublicChannelsTooMuch: String { return self._s[2875]! } + public var ReportSpam_DeleteThisChat: String { return self._s[2876]! } + public var Passport_Address_AddBankStatement: String { return self._s[2877]! } + public var Notification_CallIncoming: String { return self._s[2878]! } + public var Wallet_Words_NotDoneTitle: String { return self._s[2879]! } + public var Compose_NewGroupTitle: String { return self._s[2880]! } + public var TwoStepAuth_RecoveryCodeHelp: String { return self._s[2882]! } + public var Passport_Address_Postcode: String { return self._s[2884]! } public func LastSeen_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2882]!, self._r[2882]!, [_0]) + return formatWithArgumentRanges(self._s[2885]!, self._r[2885]!, [_0]) } - public var Checkout_NewCard_SaveInfoHelp: String { return self._s[2883]! } - public var Wallet_Month_ShortOctober: String { return self._s[2884]! } - public var VoiceOver_Chat_YourMusic: String { return self._s[2885]! } - public var WallpaperColors_Title: String { return self._s[2886]! } - public var SocksProxySetup_ShareQRCodeInfo: String { return self._s[2887]! } - public var VoiceOver_MessageContextForward: String { return self._s[2888]! } - public var GroupPermission_Duration: String { return self._s[2889]! } + public var Checkout_NewCard_SaveInfoHelp: String { return self._s[2886]! } + public var Wallet_Month_ShortOctober: String { return self._s[2887]! } + public var VoiceOver_Chat_YourMusic: String { return self._s[2888]! } + public var WallpaperColors_Title: String { return self._s[2889]! } + public var SocksProxySetup_ShareQRCodeInfo: String { return self._s[2890]! } + public var VoiceOver_MessageContextForward: String { return self._s[2891]! } + public var GroupPermission_Duration: String { return self._s[2892]! } public func Cache_Clear(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2890]!, self._r[2890]!, [_0]) + return formatWithArgumentRanges(self._s[2893]!, self._r[2893]!, [_0]) } - public var Bot_GroupStatusDoesNotReadHistory: String { return self._s[2891]! } - public var Username_Placeholder: String { return self._s[2892]! } - public var CallFeedback_WhatWentWrong: String { return self._s[2893]! } - public var Passport_FieldAddressUploadHelp: String { return self._s[2894]! } - public var Permissions_NotificationsAllowInSettings_v0: String { return self._s[2895]! } + public var Bot_GroupStatusDoesNotReadHistory: String { return self._s[2894]! } + public var Username_Placeholder: String { return self._s[2895]! } + public var CallFeedback_WhatWentWrong: String { return self._s[2896]! } + public var Passport_FieldAddressUploadHelp: String { return self._s[2897]! } + public var Permissions_NotificationsAllowInSettings_v0: String { return self._s[2898]! } public func Channel_AdminLog_MessageChangedUnlinkedChannel(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2897]!, self._r[2897]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2900]!, self._r[2900]!, [_1, _2]) } - public var Passport_PasswordDescription: String { return self._s[2898]! } - public var Channel_MessagePhotoUpdated: String { return self._s[2899]! } - public var MediaPicker_TapToUngroupDescription: String { return self._s[2900]! } - public var SettingsSearch_Synonyms_Notifications_BadgeCountUnreadMessages: String { return self._s[2901]! } - public var AttachmentMenu_PhotoOrVideo: String { return self._s[2902]! } - public var Conversation_ContextMenuMore: String { return self._s[2903]! } - public var Privacy_PaymentsClearInfo: String { return self._s[2904]! } - public var CallSettings_TabIcon: String { return self._s[2905]! } - public var KeyCommand_Find: String { return self._s[2906]! } - public var ClearCache_FreeSpaceDescription: String { return self._s[2907]! } - public var Appearance_ThemePreview_ChatList_7_Text: String { return self._s[2908]! } - public var EditTheme_Edit_Preview_IncomingText: String { return self._s[2909]! } - public var Message_PinnedGame: String { return self._s[2910]! } - public var VoiceOver_Chat_ForwardedFromYou: String { return self._s[2911]! } - public var Notifications_Badge_CountUnreadMessages_InfoOff: String { return self._s[2913]! } - public var Login_CallRequestState2: String { return self._s[2915]! } - public var CheckoutInfo_ReceiverInfoNamePlaceholder: String { return self._s[2917]! } + public var Passport_PasswordDescription: String { return self._s[2901]! } + public var Channel_MessagePhotoUpdated: String { return self._s[2902]! } + public var MediaPicker_TapToUngroupDescription: String { return self._s[2903]! } + public var SettingsSearch_Synonyms_Notifications_BadgeCountUnreadMessages: String { return self._s[2904]! } + public var AttachmentMenu_PhotoOrVideo: String { return self._s[2905]! } + public var Conversation_ContextMenuMore: String { return self._s[2906]! } + public var Privacy_PaymentsClearInfo: String { return self._s[2907]! } + public var CallSettings_TabIcon: String { return self._s[2908]! } + public var KeyCommand_Find: String { return self._s[2909]! } + public var ClearCache_FreeSpaceDescription: String { return self._s[2910]! } + public var Appearance_ThemePreview_ChatList_7_Text: String { return self._s[2911]! } + public var EditTheme_Edit_Preview_IncomingText: String { return self._s[2912]! } + public var Message_PinnedGame: String { return self._s[2913]! } + public var VoiceOver_Chat_ForwardedFromYou: String { return self._s[2914]! } + public var Notifications_Badge_CountUnreadMessages_InfoOff: String { return self._s[2916]! } + public var Login_CallRequestState2: String { return self._s[2918]! } + public var CheckoutInfo_ReceiverInfoNamePlaceholder: String { return self._s[2920]! } public func VoiceOver_Chat_PhotoFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2918]!, self._r[2918]!, [_0]) + return formatWithArgumentRanges(self._s[2921]!, self._r[2921]!, [_0]) } public func Checkout_PayPrice(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2920]!, self._r[2920]!, [_0]) + return formatWithArgumentRanges(self._s[2923]!, self._r[2923]!, [_0]) } - public var AuthSessions_AddDevice: String { return self._s[2921]! } - public var WallpaperPreview_Blurred: String { return self._s[2922]! } - public var Conversation_InstantPagePreview: String { return self._s[2923]! } + public var AuthSessions_AddDevice: String { return self._s[2924]! } + public var WallpaperPreview_Blurred: String { return self._s[2925]! } + public var Conversation_InstantPagePreview: String { return self._s[2926]! } public func DialogList_SingleUploadingVideoSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2924]!, self._r[2924]!, [_0]) + return formatWithArgumentRanges(self._s[2927]!, self._r[2927]!, [_0]) } - public var SecretTimer_VideoDescription: String { return self._s[2927]! } - public var WallpaperSearch_ColorRed: String { return self._s[2928]! } - public var GroupPermission_NoPinMessages: String { return self._s[2929]! } - public var Passport_Language_es: String { return self._s[2930]! } - public var Permissions_ContactsAllow_v0: String { return self._s[2932]! } - public var Conversation_EditingMessageMediaEditCurrentVideo: String { return self._s[2933]! } + public var SecretTimer_VideoDescription: String { return self._s[2930]! } + public var WallpaperSearch_ColorRed: String { return self._s[2931]! } + public var GroupPermission_NoPinMessages: String { return self._s[2932]! } + public var Passport_Language_es: String { return self._s[2933]! } + public var Permissions_ContactsAllow_v0: String { return self._s[2935]! } + public var Conversation_EditingMessageMediaEditCurrentVideo: String { return self._s[2936]! } public func PUSH_CHAT_MESSAGE_CONTACT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2934]!, self._r[2934]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2937]!, self._r[2937]!, [_1, _2]) } - public var Privacy_Forwards_CustomHelp: String { return self._s[2935]! } - public var WebPreview_GettingLinkInfo: String { return self._s[2936]! } - public var Watch_UserInfo_Unmute: String { return self._s[2937]! } - public var GroupInfo_ChannelListNamePlaceholder: String { return self._s[2938]! } - public var AccessDenied_CameraRestricted: String { return self._s[2940]! } + public var Privacy_Forwards_CustomHelp: String { return self._s[2938]! } + public var WebPreview_GettingLinkInfo: String { return self._s[2939]! } + public var Watch_UserInfo_Unmute: String { return self._s[2940]! } + public var GroupInfo_ChannelListNamePlaceholder: String { return self._s[2941]! } + public var AccessDenied_CameraRestricted: String { return self._s[2943]! } public func Conversation_Kilobytes(_ _0: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2941]!, self._r[2941]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[2944]!, self._r[2944]!, ["\(_0)"]) } - public var ChatList_ReadAll: String { return self._s[2943]! } - public var Settings_CopyUsername: String { return self._s[2944]! } - public var Contacts_SearchLabel: String { return self._s[2945]! } - public var Map_OpenInYandexNavigator: String { return self._s[2947]! } - public var PasscodeSettings_EncryptData: String { return self._s[2948]! } - public var Settings_Wallet: String { return self._s[2949]! } - public var Group_ErrorSupergroupConversionNotPossible: String { return self._s[2950]! } - public var WallpaperSearch_ColorPrefix: String { return self._s[2951]! } - public var Notifications_GroupNotificationsPreview: String { return self._s[2952]! } - public var DialogList_AdNoticeAlert: String { return self._s[2953]! } - public var Wallet_Month_GenMay: String { return self._s[2955]! } - public var CheckoutInfo_ShippingInfoAddress1: String { return self._s[2956]! } - public var CheckoutInfo_ShippingInfoAddress2: String { return self._s[2957]! } - public var Localization_LanguageCustom: String { return self._s[2958]! } - public var Passport_Identity_TypeDriversLicenseUploadScan: String { return self._s[2959]! } - public var CallFeedback_Title: String { return self._s[2960]! } - public var VoiceOver_Chat_RecordPreviewVoiceMessage: String { return self._s[2963]! } - public var Passport_Address_OneOfTypePassportRegistration: String { return self._s[2964]! } - public var Wallet_Intro_CreateErrorTitle: String { return self._s[2965]! } - public var Conversation_InfoGroup: String { return self._s[2966]! } - public var Compose_NewMessage: String { return self._s[2967]! } - public var FastTwoStepSetup_HintPlaceholder: String { return self._s[2968]! } - public var ChatSettings_AutoDownloadVideoMessages: String { return self._s[2969]! } - public var Wallet_SecureStorageReset_BiometryFaceId: String { return self._s[2970]! } - public var Channel_DiscussionGroup_UnlinkChannel: String { return self._s[2971]! } + public var ChatList_ReadAll: String { return self._s[2946]! } + public var Settings_CopyUsername: String { return self._s[2947]! } + public var Contacts_SearchLabel: String { return self._s[2948]! } + public var Map_OpenInYandexNavigator: String { return self._s[2950]! } + public var PasscodeSettings_EncryptData: String { return self._s[2951]! } + public var Settings_Wallet: String { return self._s[2952]! } + public var Group_ErrorSupergroupConversionNotPossible: String { return self._s[2953]! } + public var WallpaperSearch_ColorPrefix: String { return self._s[2954]! } + public var Notifications_GroupNotificationsPreview: String { return self._s[2955]! } + public var DialogList_AdNoticeAlert: String { return self._s[2956]! } + public var Wallet_Month_GenMay: String { return self._s[2958]! } + public var CheckoutInfo_ShippingInfoAddress1: String { return self._s[2959]! } + public var CheckoutInfo_ShippingInfoAddress2: String { return self._s[2960]! } + public var Localization_LanguageCustom: String { return self._s[2961]! } + public var Passport_Identity_TypeDriversLicenseUploadScan: String { return self._s[2962]! } + public var CallFeedback_Title: String { return self._s[2963]! } + public var VoiceOver_Chat_RecordPreviewVoiceMessage: String { return self._s[2966]! } + public var Passport_Address_OneOfTypePassportRegistration: String { return self._s[2967]! } + public var Wallet_Intro_CreateErrorTitle: String { return self._s[2968]! } + public var Conversation_InfoGroup: String { return self._s[2969]! } + public var Compose_NewMessage: String { return self._s[2970]! } + public var FastTwoStepSetup_HintPlaceholder: String { return self._s[2971]! } + public var ChatSettings_AutoDownloadVideoMessages: String { return self._s[2972]! } + public var Wallet_SecureStorageReset_BiometryFaceId: String { return self._s[2973]! } + public var Channel_DiscussionGroup_UnlinkChannel: String { return self._s[2974]! } public func Passport_Scans_ScanIndex(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2972]!, self._r[2972]!, [_0]) + return formatWithArgumentRanges(self._s[2975]!, self._r[2975]!, [_0]) } - public var Channel_AdminLog_CanDeleteMessages: String { return self._s[2973]! } - public var Login_CancelSignUpConfirmation: String { return self._s[2974]! } - public var ChangePhoneNumberCode_Help: String { return self._s[2975]! } - public var PrivacySettings_DeleteAccountHelp: String { return self._s[2976]! } - public var Channel_BlackList_Title: String { return self._s[2977]! } - public var UserInfo_PhoneCall: String { return self._s[2978]! } - public var Passport_Address_OneOfTypeBankStatement: String { return self._s[2980]! } - public var Wallet_Month_ShortJanuary: String { return self._s[2981]! } - public var State_connecting: String { return self._s[2982]! } - public var Appearance_ThemePreview_ChatList_6_Text: String { return self._s[2983]! } - public var Wallet_Month_GenMarch: String { return self._s[2984]! } - public var EditTheme_Expand_BottomInfo: String { return self._s[2985]! } - public var AuthSessions_AddedDeviceTerminate: String { return self._s[2986]! } + public var Channel_AdminLog_CanDeleteMessages: String { return self._s[2976]! } + public var Login_CancelSignUpConfirmation: String { return self._s[2977]! } + public var ChangePhoneNumberCode_Help: String { return self._s[2978]! } + public var PrivacySettings_DeleteAccountHelp: String { return self._s[2979]! } + public var Channel_BlackList_Title: String { return self._s[2980]! } + public var UserInfo_PhoneCall: String { return self._s[2981]! } + public var Passport_Address_OneOfTypeBankStatement: String { return self._s[2983]! } + public var Wallet_Month_ShortJanuary: String { return self._s[2984]! } + public var State_connecting: String { return self._s[2985]! } + public var Appearance_ThemePreview_ChatList_6_Text: String { return self._s[2986]! } + public var Wallet_Month_GenMarch: String { return self._s[2987]! } + public var EditTheme_Expand_BottomInfo: String { return self._s[2988]! } + public var AuthSessions_AddedDeviceTerminate: String { return self._s[2989]! } public func LastSeen_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2987]!, self._r[2987]!, [_0]) + return formatWithArgumentRanges(self._s[2990]!, self._r[2990]!, [_0]) } public func DialogList_SingleRecordingAudioSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2988]!, self._r[2988]!, [_0]) + return formatWithArgumentRanges(self._s[2991]!, self._r[2991]!, [_0]) } - public var Notifications_GroupNotifications: String { return self._s[2989]! } - public var Conversation_SendMessageErrorTooMuchScheduled: String { return self._s[2990]! } - public var Passport_Identity_EditPassport: String { return self._s[2991]! } - public var EnterPasscode_RepeatNewPasscode: String { return self._s[2993]! } - public var Localization_EnglishLanguageName: String { return self._s[2994]! } - public var Share_AuthDescription: String { return self._s[2995]! } - public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsAlert: String { return self._s[2996]! } - public var Passport_Identity_Surname: String { return self._s[2997]! } - public var Compose_TokenListPlaceholder: String { return self._s[2998]! } - public var Wallet_AccessDenied_Camera: String { return self._s[2999]! } - public var Passport_Identity_OneOfTypePassport: String { return self._s[3000]! } - public var Settings_AboutEmpty: String { return self._s[3001]! } - public var Conversation_Unmute: String { return self._s[3002]! } - public var CreateGroup_ChannelsTooMuch: String { return self._s[3004]! } - public var Wallet_Sending_Text: String { return self._s[3005]! } + public var Notifications_GroupNotifications: String { return self._s[2992]! } + public var Conversation_SendMessageErrorTooMuchScheduled: String { return self._s[2993]! } + public var Passport_Identity_EditPassport: String { return self._s[2994]! } + public var EnterPasscode_RepeatNewPasscode: String { return self._s[2996]! } + public var Localization_EnglishLanguageName: String { return self._s[2997]! } + public var Share_AuthDescription: String { return self._s[2998]! } + public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsAlert: String { return self._s[2999]! } + public var Passport_Identity_Surname: String { return self._s[3000]! } + public var Compose_TokenListPlaceholder: String { return self._s[3001]! } + public var Wallet_AccessDenied_Camera: String { return self._s[3002]! } + public var Passport_Identity_OneOfTypePassport: String { return self._s[3003]! } + public var Settings_AboutEmpty: String { return self._s[3004]! } + public var Conversation_Unmute: String { return self._s[3005]! } + public var CreateGroup_ChannelsTooMuch: String { return self._s[3007]! } + public var Wallet_Sending_Text: String { return self._s[3008]! } public func PUSH_CONTACT_JOINED(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3006]!, self._r[3006]!, [_1]) + return formatWithArgumentRanges(self._s[3009]!, self._r[3009]!, [_1]) } - public var Login_CodeSentCall: String { return self._s[3007]! } - public var ContactInfo_PhoneLabelHomeFax: String { return self._s[3009]! } - public var ChatSettings_Appearance: String { return self._s[3010]! } - public var ClearCache_StorageUsage: String { return self._s[3011]! } - public var Appearance_PickAccentColor: String { return self._s[3012]! } + public var Login_CodeSentCall: String { return self._s[3010]! } + public var ContactInfo_PhoneLabelHomeFax: String { return self._s[3012]! } + public var ChatSettings_Appearance: String { return self._s[3013]! } + public var ClearCache_StorageUsage: String { return self._s[3014]! } + public var Appearance_PickAccentColor: String { return self._s[3015]! } public func PUSH_CHAT_MESSAGE_NOTEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3013]!, self._r[3013]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3016]!, self._r[3016]!, [_1, _2]) } public func PUSH_MESSAGE_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3014]!, self._r[3014]!, [_1]) + return formatWithArgumentRanges(self._s[3017]!, self._r[3017]!, [_1]) } - public var Notification_CallMissed: String { return self._s[3015]! } - public var SettingsSearch_Synonyms_Appearance_ChatBackground_Custom: String { return self._s[3016]! } - public var Channel_AdminLogFilter_EventsInfo: String { return self._s[3017]! } - public var Wallet_Month_GenOctober: String { return self._s[3019]! } - public var ChatAdmins_AdminLabel: String { return self._s[3020]! } - public var KeyCommand_JumpToNextChat: String { return self._s[3021]! } - public var Conversation_StopPollConfirmationTitle: String { return self._s[3023]! } - public var ChangePhoneNumberCode_CodePlaceholder: String { return self._s[3024]! } - public var Month_GenJune: String { return self._s[3025]! } - public var IntentsSettings_MainAccountInfo: String { return self._s[3026]! } - public var Watch_Location_Current: String { return self._s[3027]! } - public var Wallet_Receive_CopyInvoiceUrl: String { return self._s[3028]! } - public var Conversation_TitleMute: String { return self._s[3029]! } - public var Map_PlacesInThisArea: String { return self._s[3030]! } + public var Notification_CallMissed: String { return self._s[3018]! } + public var SettingsSearch_Synonyms_Appearance_ChatBackground_Custom: String { return self._s[3019]! } + public var Channel_AdminLogFilter_EventsInfo: String { return self._s[3020]! } + public var Wallet_Month_GenOctober: String { return self._s[3022]! } + public var ChatAdmins_AdminLabel: String { return self._s[3023]! } + public var KeyCommand_JumpToNextChat: String { return self._s[3024]! } + public var Conversation_StopPollConfirmationTitle: String { return self._s[3026]! } + public var ChangePhoneNumberCode_CodePlaceholder: String { return self._s[3027]! } + public var Month_GenJune: String { return self._s[3028]! } + public var IntentsSettings_MainAccountInfo: String { return self._s[3029]! } + public var Watch_Location_Current: String { return self._s[3030]! } + public var Wallet_Receive_CopyInvoiceUrl: String { return self._s[3031]! } + public var Conversation_TitleMute: String { return self._s[3032]! } + public var Map_PlacesInThisArea: String { return self._s[3033]! } public func PUSH_CHANNEL_MESSAGE_ROUND(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3031]!, self._r[3031]!, [_1]) + return formatWithArgumentRanges(self._s[3034]!, self._r[3034]!, [_1]) } - public var GroupInfo_DeleteAndExit: String { return self._s[3032]! } + public var GroupInfo_DeleteAndExit: String { return self._s[3035]! } public func Conversation_Moderate_DeleteAllMessages(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3033]!, self._r[3033]!, [_0]) + return formatWithArgumentRanges(self._s[3036]!, self._r[3036]!, [_0]) } - public var Call_ReportPlaceholder: String { return self._s[3034]! } - public var Chat_SlowmodeSendError: String { return self._s[3035]! } - public var MaskStickerSettings_Info: String { return self._s[3036]! } - public var EditTheme_Expand_TopInfo: String { return self._s[3037]! } + public var Call_ReportPlaceholder: String { return self._s[3037]! } + public var Chat_SlowmodeSendError: String { return self._s[3038]! } + public var MaskStickerSettings_Info: String { return self._s[3039]! } + public var EditTheme_Expand_TopInfo: String { return self._s[3040]! } public func GroupInfo_AddParticipantConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3038]!, self._r[3038]!, [_0]) + return formatWithArgumentRanges(self._s[3041]!, self._r[3041]!, [_0]) } - public var Checkout_NewCard_PostcodeTitle: String { return self._s[3039]! } - public var Passport_Address_RegionPlaceholder: String { return self._s[3041]! } - public var Contacts_ShareTelegram: String { return self._s[3042]! } - public var EnterPasscode_EnterNewPasscodeNew: String { return self._s[3043]! } - public var Map_AddressOnMap: String { return self._s[3044]! } - public var Channel_ErrorAccessDenied: String { return self._s[3045]! } - public var UserInfo_ScamBotWarning: String { return self._s[3047]! } - public var Stickers_GroupChooseStickerPack: String { return self._s[3048]! } - public var Call_ConnectionErrorTitle: String { return self._s[3049]! } - public var UserInfo_NotificationsEnable: String { return self._s[3050]! } - public var ArchivedChats_IntroText1: String { return self._s[3051]! } - public var Tour_Text4: String { return self._s[3054]! } - public var WallpaperSearch_Recent: String { return self._s[3055]! } - public var GroupInfo_ScamGroupWarning: String { return self._s[3056]! } - public var Profile_MessageLifetime2s: String { return self._s[3058]! } - public var Appearance_ThemePreview_ChatList_5_Text: String { return self._s[3059]! } - public var Notification_MessageLifetime2s: String { return self._s[3060]! } + public var Checkout_NewCard_PostcodeTitle: String { return self._s[3042]! } + public var Passport_Address_RegionPlaceholder: String { return self._s[3044]! } + public var Contacts_ShareTelegram: String { return self._s[3045]! } + public var EnterPasscode_EnterNewPasscodeNew: String { return self._s[3046]! } + public var Map_AddressOnMap: String { return self._s[3047]! } + public var Channel_ErrorAccessDenied: String { return self._s[3048]! } + public var UserInfo_ScamBotWarning: String { return self._s[3050]! } + public var Stickers_GroupChooseStickerPack: String { return self._s[3051]! } + public var Call_ConnectionErrorTitle: String { return self._s[3052]! } + public var UserInfo_NotificationsEnable: String { return self._s[3053]! } + public var ArchivedChats_IntroText1: String { return self._s[3054]! } + public var Tour_Text4: String { return self._s[3057]! } + public var WallpaperSearch_Recent: String { return self._s[3058]! } + public var GroupInfo_ScamGroupWarning: String { return self._s[3059]! } + public var Profile_MessageLifetime2s: String { return self._s[3061]! } + public var Appearance_ThemePreview_ChatList_5_Text: String { return self._s[3062]! } + public var Notification_MessageLifetime2s: String { return self._s[3063]! } public func Time_PreciseDate_m10(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3061]!, self._r[3061]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3064]!, self._r[3064]!, [_1, _2, _3]) } - public var Cache_ClearCache: String { return self._s[3062]! } - public var AutoNightTheme_UpdateLocation: String { return self._s[3063]! } - public var Permissions_NotificationsUnreachableText_v0: String { return self._s[3064]! } + public var Cache_ClearCache: String { return self._s[3065]! } + public var AutoNightTheme_UpdateLocation: String { return self._s[3066]! } + public var Permissions_NotificationsUnreachableText_v0: String { return self._s[3067]! } public func Channel_AdminLog_MessageChangedGroupUsername(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3068]!, self._r[3068]!, [_0]) + return formatWithArgumentRanges(self._s[3071]!, self._r[3071]!, [_0]) } public func Conversation_ShareMyPhoneNumber_StatusSuccess(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3070]!, self._r[3070]!, [_0]) + return formatWithArgumentRanges(self._s[3073]!, self._r[3073]!, [_0]) } - public var LocalGroup_Text: String { return self._s[3071]! } - public var Channel_AdminLog_EmptyFilterTitle: String { return self._s[3072]! } - public var SocksProxySetup_TypeSocks: String { return self._s[3073]! } - public var ChatList_UnarchiveAction: String { return self._s[3074]! } - public var AutoNightTheme_Title: String { return self._s[3075]! } - public var InstantPage_FeedbackButton: String { return self._s[3076]! } - public var Passport_FieldAddress: String { return self._s[3077]! } + public var LocalGroup_Text: String { return self._s[3074]! } + public var Channel_AdminLog_EmptyFilterTitle: String { return self._s[3075]! } + public var SocksProxySetup_TypeSocks: String { return self._s[3076]! } + public var ChatList_UnarchiveAction: String { return self._s[3077]! } + public var AutoNightTheme_Title: String { return self._s[3078]! } + public var InstantPage_FeedbackButton: String { return self._s[3079]! } + public var Passport_FieldAddress: String { return self._s[3080]! } public func Channel_AdminLog_SetSlowmode(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3078]!, self._r[3078]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3081]!, self._r[3081]!, [_1, _2]) } - public var Month_ShortMarch: String { return self._s[3079]! } + public var Month_ShortMarch: String { return self._s[3082]! } public func PUSH_MESSAGE_INVOICE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3080]!, self._r[3080]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3083]!, self._r[3083]!, [_1, _2]) } - public var SocksProxySetup_UsernamePlaceholder: String { return self._s[3081]! } - public var Conversation_ShareInlineBotLocationConfirmation: String { return self._s[3082]! } - public var Passport_FloodError: String { return self._s[3083]! } - public var SecretGif_Title: String { return self._s[3084]! } - public var NotificationSettings_ShowNotificationsAllAccountsInfoOn: String { return self._s[3085]! } - public var ChatList_Context_UnhideArchive: String { return self._s[3086]! } - public var Passport_Language_th: String { return self._s[3088]! } - public var Passport_Address_Address: String { return self._s[3089]! } - public var Login_InvalidLastNameError: String { return self._s[3090]! } - public var Notifications_InAppNotificationsPreview: String { return self._s[3091]! } - public var Notifications_PermissionsUnreachableTitle: String { return self._s[3092]! } - public var ChatList_Context_Archive: String { return self._s[3093]! } - public var SettingsSearch_FAQ: String { return self._s[3094]! } - public var ShareMenu_Send: String { return self._s[3095]! } - public var WallpaperSearch_ColorYellow: String { return self._s[3097]! } - public var Month_GenNovember: String { return self._s[3099]! } - public var SettingsSearch_Synonyms_Appearance_LargeEmoji: String { return self._s[3101]! } + public var SocksProxySetup_UsernamePlaceholder: String { return self._s[3084]! } + public var Conversation_ShareInlineBotLocationConfirmation: String { return self._s[3085]! } + public var Passport_FloodError: String { return self._s[3086]! } + public var SecretGif_Title: String { return self._s[3087]! } + public var NotificationSettings_ShowNotificationsAllAccountsInfoOn: String { return self._s[3088]! } + public var ChatList_Context_UnhideArchive: String { return self._s[3089]! } + public var Passport_Language_th: String { return self._s[3091]! } + public var Passport_Address_Address: String { return self._s[3092]! } + public var Login_InvalidLastNameError: String { return self._s[3093]! } + public var Notifications_InAppNotificationsPreview: String { return self._s[3094]! } + public var Notifications_PermissionsUnreachableTitle: String { return self._s[3095]! } + public var ChatList_Context_Archive: String { return self._s[3096]! } + public var SettingsSearch_FAQ: String { return self._s[3097]! } + public var ShareMenu_Send: String { return self._s[3098]! } + public var WallpaperSearch_ColorYellow: String { return self._s[3100]! } + public var Month_GenNovember: String { return self._s[3102]! } + public var SettingsSearch_Synonyms_Appearance_LargeEmoji: String { return self._s[3104]! } public func Conversation_ShareMyPhoneNumberConfirmation(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3102]!, self._r[3102]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3105]!, self._r[3105]!, [_1, _2]) } - public var Conversation_SwipeToReplyHintText: String { return self._s[3103]! } - public var Checkout_Email: String { return self._s[3104]! } - public var NotificationsSound_Tritone: String { return self._s[3105]! } - public var StickerPacksSettings_ManagingHelp: String { return self._s[3107]! } - public var Wallet_ContextMenuCopy: String { return self._s[3109]! } + public var Conversation_SwipeToReplyHintText: String { return self._s[3106]! } + public var Checkout_Email: String { return self._s[3107]! } + public var NotificationsSound_Tritone: String { return self._s[3108]! } + public var StickerPacksSettings_ManagingHelp: String { return self._s[3110]! } + public var Wallet_ContextMenuCopy: String { return self._s[3112]! } public func Wallet_Time_PreciseDate_m6(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3111]!, self._r[3111]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3114]!, self._r[3114]!, [_1, _2, _3]) } - public var Appearance_TextSize_Automatic: String { return self._s[3112]! } + public var Appearance_TextSize_Automatic: String { return self._s[3115]! } public func PUSH_PINNED_ROUND(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3113]!, self._r[3113]!, [_1]) + return formatWithArgumentRanges(self._s[3116]!, self._r[3116]!, [_1]) } public func StickerPackActionInfo_AddedText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3114]!, self._r[3114]!, [_0]) + return formatWithArgumentRanges(self._s[3117]!, self._r[3117]!, [_0]) } - public var ChangePhoneNumberNumber_Help: String { return self._s[3115]! } + public var ChangePhoneNumberNumber_Help: String { return self._s[3118]! } public func Checkout_LiabilityAlert(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3116]!, self._r[3116]!, [_1, _1, _1, _2]) + return formatWithArgumentRanges(self._s[3119]!, self._r[3119]!, [_1, _1, _1, _2]) } - public var ChatList_UndoArchiveTitle: String { return self._s[3117]! } - public var Notification_Exceptions_Add: String { return self._s[3118]! } - public var DialogList_You: String { return self._s[3119]! } - public var MediaPicker_Send: String { return self._s[3122]! } - public var SettingsSearch_Synonyms_Stickers_Title: String { return self._s[3123]! } - public var Appearance_ThemePreview_ChatList_4_Text: String { return self._s[3124]! } - public var Call_AudioRouteSpeaker: String { return self._s[3125]! } - public var Watch_UserInfo_Title: String { return self._s[3126]! } - public var VoiceOver_Chat_PollFinalResults: String { return self._s[3127]! } - public var Appearance_AccentColor: String { return self._s[3129]! } + public var ChatList_UndoArchiveTitle: String { return self._s[3120]! } + public var Notification_Exceptions_Add: String { return self._s[3121]! } + public var DialogList_You: String { return self._s[3122]! } + public var MediaPicker_Send: String { return self._s[3125]! } + public var SettingsSearch_Synonyms_Stickers_Title: String { return self._s[3126]! } + public var Appearance_ThemePreview_ChatList_4_Text: String { return self._s[3127]! } + public var Call_AudioRouteSpeaker: String { return self._s[3128]! } + public var Watch_UserInfo_Title: String { return self._s[3129]! } + public var VoiceOver_Chat_PollFinalResults: String { return self._s[3130]! } + public var Appearance_AccentColor: String { return self._s[3132]! } public func Login_EmailPhoneSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3130]!, self._r[3130]!, [_0]) + return formatWithArgumentRanges(self._s[3133]!, self._r[3133]!, [_0]) } - public var Permissions_ContactsAllowInSettings_v0: String { return self._s[3131]! } + public var Permissions_ContactsAllowInSettings_v0: String { return self._s[3134]! } public func PUSH_CHANNEL_MESSAGE_GAME(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3132]!, self._r[3132]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3135]!, self._r[3135]!, [_1, _2]) } - public var Conversation_ClousStorageInfo_Description2: String { return self._s[3133]! } - public var WebSearch_RecentClearConfirmation: String { return self._s[3134]! } - public var Notification_CallOutgoing: String { return self._s[3135]! } - public var PrivacySettings_PasscodeAndFaceId: String { return self._s[3136]! } - public var Channel_DiscussionGroup_MakeHistoryPublic: String { return self._s[3137]! } - public var Call_RecordingDisabledMessage: String { return self._s[3138]! } - public var Message_Game: String { return self._s[3139]! } - public var Conversation_PressVolumeButtonForSound: String { return self._s[3140]! } - public var PrivacyLastSeenSettings_CustomHelp: String { return self._s[3141]! } - public var Channel_DiscussionGroup_PrivateGroup: String { return self._s[3142]! } - public var Channel_EditAdmin_PermissionAddAdmins: String { return self._s[3143]! } - public var Date_DialogDateFormat: String { return self._s[3145]! } - public var WallpaperColors_SetCustomColor: String { return self._s[3146]! } - public var Notifications_InAppNotifications: String { return self._s[3147]! } + public var Conversation_ClousStorageInfo_Description2: String { return self._s[3136]! } + public var WebSearch_RecentClearConfirmation: String { return self._s[3137]! } + public var Notification_CallOutgoing: String { return self._s[3138]! } + public var PrivacySettings_PasscodeAndFaceId: String { return self._s[3139]! } + public var Channel_DiscussionGroup_MakeHistoryPublic: String { return self._s[3140]! } + public var Call_RecordingDisabledMessage: String { return self._s[3141]! } + public var Message_Game: String { return self._s[3142]! } + public var Conversation_PressVolumeButtonForSound: String { return self._s[3143]! } + public var PrivacyLastSeenSettings_CustomHelp: String { return self._s[3144]! } + public var Channel_DiscussionGroup_PrivateGroup: String { return self._s[3145]! } + public var Channel_EditAdmin_PermissionAddAdmins: String { return self._s[3146]! } + public var Date_DialogDateFormat: String { return self._s[3148]! } + public var WallpaperColors_SetCustomColor: String { return self._s[3149]! } + public var Notifications_InAppNotifications: String { return self._s[3150]! } public func Channel_Management_RemovedBy(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3148]!, self._r[3148]!, [_0]) - } - public func Settings_ApplyProxyAlert(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3149]!, self._r[3149]!, [_1, _2]) - } - public var NewContact_Title: String { return self._s[3150]! } - public func AutoDownloadSettings_UpToForAll(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3151]!, self._r[3151]!, [_0]) } - public var Conversation_ViewContactDetails: String { return self._s[3152]! } + public func Settings_ApplyProxyAlert(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3152]!, self._r[3152]!, [_1, _2]) + } + public var NewContact_Title: String { return self._s[3153]! } + public func AutoDownloadSettings_UpToForAll(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3154]!, self._r[3154]!, [_0]) + } + public var Conversation_ViewContactDetails: String { return self._s[3155]! } public func PUSH_CHANNEL_MESSAGE_CONTACT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3154]!, self._r[3154]!, [_1]) + return formatWithArgumentRanges(self._s[3157]!, self._r[3157]!, [_1]) } - public var Checkout_NewCard_CardholderNameTitle: String { return self._s[3155]! } - public var Passport_Identity_ExpiryDateNone: String { return self._s[3156]! } - public var PrivacySettings_Title: String { return self._s[3157]! } - public var Conversation_SilentBroadcastTooltipOff: String { return self._s[3160]! } - public var GroupRemoved_UsersSectionTitle: String { return self._s[3161]! } - public var VoiceOver_Chat_ContactEmail: String { return self._s[3162]! } - public var Contacts_PhoneNumber: String { return self._s[3163]! } - public var TwoFactorSetup_Password_PlaceholderConfirmPassword: String { return self._s[3165]! } - public var Map_ShowPlaces: String { return self._s[3166]! } - public var ChatAdmins_Title: String { return self._s[3167]! } - public var InstantPage_Reference: String { return self._s[3169]! } - public var Wallet_Info_Updating: String { return self._s[3170]! } - public var ReportGroupLocation_Text: String { return self._s[3171]! } + public var Checkout_NewCard_CardholderNameTitle: String { return self._s[3158]! } + public var Passport_Identity_ExpiryDateNone: String { return self._s[3159]! } + public var PrivacySettings_Title: String { return self._s[3160]! } + public var Conversation_SilentBroadcastTooltipOff: String { return self._s[3163]! } + public var GroupRemoved_UsersSectionTitle: String { return self._s[3164]! } + public var VoiceOver_Chat_ContactEmail: String { return self._s[3165]! } + public var Contacts_PhoneNumber: String { return self._s[3166]! } + public var TwoFactorSetup_Password_PlaceholderConfirmPassword: String { return self._s[3168]! } + public var Map_ShowPlaces: String { return self._s[3169]! } + public var ChatAdmins_Title: String { return self._s[3170]! } + public var InstantPage_Reference: String { return self._s[3172]! } + public var Wallet_Info_Updating: String { return self._s[3173]! } + public var ReportGroupLocation_Text: String { return self._s[3174]! } public func PUSH_CHAT_MESSAGE_FWD(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3172]!, self._r[3172]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3175]!, self._r[3175]!, [_1, _2]) } - public var Camera_FlashOff: String { return self._s[3173]! } - public var Watch_UserInfo_Block: String { return self._s[3174]! } - public var ChatSettings_Stickers: String { return self._s[3175]! } - public var ChatSettings_DownloadInBackground: String { return self._s[3176]! } - public var Appearance_ThemeCarouselTintedNight: String { return self._s[3177]! } + public var Camera_FlashOff: String { return self._s[3176]! } + public var Watch_UserInfo_Block: String { return self._s[3177]! } + public var ChatSettings_Stickers: String { return self._s[3178]! } + public var ChatSettings_DownloadInBackground: String { return self._s[3179]! } + public var Appearance_ThemeCarouselTintedNight: String { return self._s[3180]! } public func UserInfo_BlockConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3178]!, self._r[3178]!, [_0]) + return formatWithArgumentRanges(self._s[3181]!, self._r[3181]!, [_0]) } - public var Settings_ViewPhoto: String { return self._s[3179]! } - public var Login_CheckOtherSessionMessages: String { return self._s[3180]! } - public var AutoDownloadSettings_Cellular: String { return self._s[3181]! } - public var Wallet_Created_ExportErrorTitle: String { return self._s[3182]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsExceptions: String { return self._s[3183]! } - public var VoiceOver_MessageContextShare: String { return self._s[3184]! } + public var Settings_ViewPhoto: String { return self._s[3182]! } + public var Login_CheckOtherSessionMessages: String { return self._s[3183]! } + public var AutoDownloadSettings_Cellular: String { return self._s[3184]! } + public var Wallet_Created_ExportErrorTitle: String { return self._s[3185]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsExceptions: String { return self._s[3186]! } + public var VoiceOver_MessageContextShare: String { return self._s[3187]! } public func Target_InviteToGroupConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3186]!, self._r[3186]!, [_0]) - } - public var Privacy_DeleteDrafts: String { return self._s[3187]! } - public var Wallpaper_SetCustomBackgroundInfo: String { return self._s[3188]! } - public func LastSeen_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3189]!, self._r[3189]!, [_0]) } - public var DialogList_SavedMessagesHelp: String { return self._s[3190]! } - public var Wallet_SecureStorageNotAvailable_Title: String { return self._s[3191]! } - public var DialogList_SavedMessages: String { return self._s[3192]! } - public var GroupInfo_UpgradeButton: String { return self._s[3193]! } - public var Appearance_ThemePreview_ChatList_3_Text: String { return self._s[3195]! } - public var DialogList_Pin: String { return self._s[3196]! } + public var Privacy_DeleteDrafts: String { return self._s[3190]! } + public var Wallpaper_SetCustomBackgroundInfo: String { return self._s[3191]! } + public func LastSeen_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3192]!, self._r[3192]!, [_0]) + } + public var DialogList_SavedMessagesHelp: String { return self._s[3193]! } + public var Wallet_SecureStorageNotAvailable_Title: String { return self._s[3194]! } + public var DialogList_SavedMessages: String { return self._s[3195]! } + public var GroupInfo_UpgradeButton: String { return self._s[3196]! } + public var Appearance_ThemePreview_ChatList_3_Text: String { return self._s[3198]! } + public var DialogList_Pin: String { return self._s[3199]! } public func ForwardedAuthors2(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3197]!, self._r[3197]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3200]!, self._r[3200]!, [_0, _1]) } public func Login_PhoneGenericEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3198]!, self._r[3198]!, [_0]) + return formatWithArgumentRanges(self._s[3201]!, self._r[3201]!, [_0]) } - public var Notification_Exceptions_AlwaysOn: String { return self._s[3199]! } - public var UserInfo_NotificationsDisable: String { return self._s[3200]! } - public var Conversation_ContextMenuCancelEditing: String { return self._s[3201]! } - public var Paint_Outlined: String { return self._s[3202]! } - public var Activity_PlayingGame: String { return self._s[3203]! } - public var SearchImages_NoImagesFound: String { return self._s[3204]! } - public var SocksProxySetup_ProxyType: String { return self._s[3205]! } - public var AppleWatch_ReplyPresetsHelp: String { return self._s[3207]! } - public var Conversation_ContextMenuCancelSending: String { return self._s[3208]! } - public var Settings_AppLanguage: String { return self._s[3209]! } - public var TwoStepAuth_ResetAccountHelp: String { return self._s[3210]! } - public var Common_ChoosePhoto: String { return self._s[3211]! } - public var AuthSessions_AddDevice_InvalidQRCode: String { return self._s[3212]! } - public var CallFeedback_ReasonEcho: String { return self._s[3213]! } + public var Notification_Exceptions_AlwaysOn: String { return self._s[3202]! } + public var UserInfo_NotificationsDisable: String { return self._s[3203]! } + public var Conversation_ContextMenuCancelEditing: String { return self._s[3204]! } + public var Paint_Outlined: String { return self._s[3205]! } + public var Activity_PlayingGame: String { return self._s[3206]! } + public var SearchImages_NoImagesFound: String { return self._s[3207]! } + public var SocksProxySetup_ProxyType: String { return self._s[3208]! } + public var AppleWatch_ReplyPresetsHelp: String { return self._s[3210]! } + public var Conversation_ContextMenuCancelSending: String { return self._s[3211]! } + public var Settings_AppLanguage: String { return self._s[3212]! } + public var TwoStepAuth_ResetAccountHelp: String { return self._s[3213]! } + public var Common_ChoosePhoto: String { return self._s[3214]! } + public var AuthSessions_AddDevice_InvalidQRCode: String { return self._s[3215]! } + public var CallFeedback_ReasonEcho: String { return self._s[3216]! } public func PUSH_PINNED_AUDIO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3214]!, self._r[3214]!, [_1]) + return formatWithArgumentRanges(self._s[3217]!, self._r[3217]!, [_1]) } - public var Privacy_Calls_AlwaysAllow: String { return self._s[3215]! } - public var PollResults_Collapse: String { return self._s[3216]! } - public var Activity_UploadingVideo: String { return self._s[3217]! } - public var Conversation_WalletRequiredNotNow: String { return self._s[3218]! } - public var ChannelInfo_DeleteChannelConfirmation: String { return self._s[3219]! } - public var NetworkUsageSettings_Wifi: String { return self._s[3220]! } - public var VoiceOver_Editing_ClearText: String { return self._s[3221]! } - public var PUSH_SENDER_YOU: String { return self._s[3222]! } - public var Channel_BanUser_PermissionReadMessages: String { return self._s[3223]! } - public var Checkout_PayWithTouchId: String { return self._s[3224]! } - public var Wallpaper_ResetWallpapersConfirmation: String { return self._s[3225]! } + public var Privacy_Calls_AlwaysAllow: String { return self._s[3218]! } + public var PollResults_Collapse: String { return self._s[3219]! } + public var Activity_UploadingVideo: String { return self._s[3220]! } + public var Conversation_WalletRequiredNotNow: String { return self._s[3221]! } + public var ChannelInfo_DeleteChannelConfirmation: String { return self._s[3222]! } + public var NetworkUsageSettings_Wifi: String { return self._s[3223]! } + public var VoiceOver_Editing_ClearText: String { return self._s[3224]! } + public var PUSH_SENDER_YOU: String { return self._s[3225]! } + public var Channel_BanUser_PermissionReadMessages: String { return self._s[3226]! } + public var Checkout_PayWithTouchId: String { return self._s[3227]! } + public var Wallpaper_ResetWallpapersConfirmation: String { return self._s[3228]! } public func PUSH_LOCKED_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3227]!, self._r[3227]!, [_1]) - } - public var Notifications_ExceptionsNone: String { return self._s[3228]! } - public func Message_ForwardedMessageShort(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3229]!, self._r[3229]!, [_0]) - } - public func PUSH_PINNED_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3230]!, self._r[3230]!, [_1]) } - public var AuthSessions_IncompleteAttempts: String { return self._s[3232]! } - public var Passport_Address_Region: String { return self._s[3235]! } - public var ChatList_DeleteChat: String { return self._s[3236]! } - public var LogoutOptions_ClearCacheTitle: String { return self._s[3237]! } - public var PhotoEditor_TiltShift: String { return self._s[3238]! } - public var Settings_FAQ_URL: String { return self._s[3239]! } - public var TwoFactorSetup_EmailVerification_ChangeAction: String { return self._s[3240]! } - public var Passport_Language_sl: String { return self._s[3241]! } - public var Settings_PrivacySettings: String { return self._s[3243]! } - public var SharedMedia_TitleLink: String { return self._s[3244]! } - public var Passport_Identity_TypePassportUploadScan: String { return self._s[3245]! } - public var Settings_SetProfilePhoto: String { return self._s[3246]! } - public var Channel_About_Help: String { return self._s[3247]! } - public var Contacts_PermissionsEnable: String { return self._s[3248]! } - public var Wallet_Sending_Title: String { return self._s[3249]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsAlert: String { return self._s[3250]! } - public var AttachmentMenu_SendAsFiles: String { return self._s[3251]! } - public var CallFeedback_ReasonInterruption: String { return self._s[3253]! } - public var Passport_Address_AddTemporaryRegistration: String { return self._s[3254]! } - public var AutoDownloadSettings_AutodownloadVideos: String { return self._s[3255]! } - public var ChatSettings_AutoDownloadSettings_Delimeter: String { return self._s[3256]! } - public var OldChannels_Title: String { return self._s[3257]! } - public var PrivacySettings_DeleteAccountTitle: String { return self._s[3258]! } - public var AccessDenied_VideoMessageCamera: String { return self._s[3260]! } - public var Map_OpenInYandexMaps: String { return self._s[3262]! } - public var CreateGroup_ErrorLocatedGroupsTooMuch: String { return self._s[3263]! } - public var VoiceOver_MessageContextReply: String { return self._s[3264]! } - public var PhotoEditor_SaturationTool: String { return self._s[3266]! } + public var Notifications_ExceptionsNone: String { return self._s[3231]! } + public func Message_ForwardedMessageShort(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3232]!, self._r[3232]!, [_0]) + } + public func PUSH_PINNED_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3233]!, self._r[3233]!, [_1]) + } + public var AuthSessions_IncompleteAttempts: String { return self._s[3235]! } + public var Passport_Address_Region: String { return self._s[3238]! } + public var ChatList_DeleteChat: String { return self._s[3239]! } + public var LogoutOptions_ClearCacheTitle: String { return self._s[3240]! } + public var PhotoEditor_TiltShift: String { return self._s[3241]! } + public var Settings_FAQ_URL: String { return self._s[3242]! } + public var TwoFactorSetup_EmailVerification_ChangeAction: String { return self._s[3243]! } + public var Passport_Language_sl: String { return self._s[3244]! } + public var Settings_PrivacySettings: String { return self._s[3246]! } + public var SharedMedia_TitleLink: String { return self._s[3247]! } + public var Passport_Identity_TypePassportUploadScan: String { return self._s[3248]! } + public var Settings_SetProfilePhoto: String { return self._s[3249]! } + public var Channel_About_Help: String { return self._s[3250]! } + public var Contacts_PermissionsEnable: String { return self._s[3251]! } + public var Wallet_Sending_Title: String { return self._s[3252]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsAlert: String { return self._s[3253]! } + public var AttachmentMenu_SendAsFiles: String { return self._s[3254]! } + public var CallFeedback_ReasonInterruption: String { return self._s[3256]! } + public var Passport_Address_AddTemporaryRegistration: String { return self._s[3257]! } + public var AutoDownloadSettings_AutodownloadVideos: String { return self._s[3258]! } + public var ChatSettings_AutoDownloadSettings_Delimeter: String { return self._s[3259]! } + public var OldChannels_Title: String { return self._s[3260]! } + public var PrivacySettings_DeleteAccountTitle: String { return self._s[3261]! } + public var AccessDenied_VideoMessageCamera: String { return self._s[3263]! } + public var Map_OpenInYandexMaps: String { return self._s[3265]! } + public var CreateGroup_ErrorLocatedGroupsTooMuch: String { return self._s[3266]! } + public var VoiceOver_MessageContextReply: String { return self._s[3267]! } + public var PhotoEditor_SaturationTool: String { return self._s[3269]! } public func PUSH_MESSAGE_STICKER(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3267]!, self._r[3267]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3270]!, self._r[3270]!, [_1, _2]) } - public var PrivacyPhoneNumberSettings_CustomHelp: String { return self._s[3268]! } - public var Notification_Exceptions_NewException_NotificationHeader: String { return self._s[3269]! } - public var Group_OwnershipTransfer_ErrorLocatedGroupsTooMuch: String { return self._s[3270]! } + public var PrivacyPhoneNumberSettings_CustomHelp: String { return self._s[3271]! } + public var Notification_Exceptions_NewException_NotificationHeader: String { return self._s[3272]! } + public var Group_OwnershipTransfer_ErrorLocatedGroupsTooMuch: String { return self._s[3273]! } public func LOCAL_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3271]!, self._r[3271]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[3274]!, self._r[3274]!, [_1, "\(_2)"]) } - public var Appearance_ThemePreview_ChatList_2_Text: String { return self._s[3272]! } - public var Channel_Username_InvalidTooShort: String { return self._s[3274]! } - public var SettingsSearch_Synonyms_Wallet: String { return self._s[3275]! } + public var Appearance_ThemePreview_ChatList_2_Text: String { return self._s[3275]! } + public var Channel_Username_InvalidTooShort: String { return self._s[3277]! } + public var SettingsSearch_Synonyms_Wallet: String { return self._s[3278]! } public func Group_OwnershipTransfer_DescriptionInfo(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3276]!, self._r[3276]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3279]!, self._r[3279]!, [_1, _2]) } - public var Forward_ErrorPublicPollDisabledInChannels: String { return self._s[3277]! } + public var Forward_ErrorPublicPollDisabledInChannels: String { return self._s[3280]! } public func PUSH_CHAT_MESSAGE_GAME(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3278]!, self._r[3278]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3281]!, self._r[3281]!, [_1, _2, _3]) } - public var WallpaperPreview_PatternTitle: String { return self._s[3279]! } - public var GroupInfo_PublicLinkAdd: String { return self._s[3280]! } - public var Passport_PassportInformation: String { return self._s[3283]! } - public var Theme_Unsupported: String { return self._s[3284]! } - public var WatchRemote_AlertTitle: String { return self._s[3285]! } - public var Privacy_GroupsAndChannels_NeverAllow: String { return self._s[3286]! } - public var ConvertToSupergroup_HelpText: String { return self._s[3288]! } + public var WallpaperPreview_PatternTitle: String { return self._s[3282]! } + public var GroupInfo_PublicLinkAdd: String { return self._s[3283]! } + public var Passport_PassportInformation: String { return self._s[3286]! } + public var Theme_Unsupported: String { return self._s[3287]! } + public var WatchRemote_AlertTitle: String { return self._s[3288]! } + public var Privacy_GroupsAndChannels_NeverAllow: String { return self._s[3289]! } + public var ConvertToSupergroup_HelpText: String { return self._s[3291]! } public func Time_MonthOfYear_m7(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3289]!, self._r[3289]!, [_0]) + return formatWithArgumentRanges(self._s[3292]!, self._r[3292]!, [_0]) } public func PUSH_PHONE_CALL_REQUEST(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3290]!, self._r[3290]!, [_1]) + return formatWithArgumentRanges(self._s[3293]!, self._r[3293]!, [_1]) } - public var Privacy_GroupsAndChannels_CustomHelp: String { return self._s[3291]! } - public var Wallet_Navigation_Done: String { return self._s[3293]! } - public var TwoStepAuth_RecoveryCodeInvalid: String { return self._s[3294]! } - public var AccessDenied_CameraDisabled: String { return self._s[3295]! } + public var Privacy_GroupsAndChannels_CustomHelp: String { return self._s[3294]! } + public var Wallet_Navigation_Done: String { return self._s[3296]! } + public var TwoStepAuth_RecoveryCodeInvalid: String { return self._s[3297]! } + public var AccessDenied_CameraDisabled: String { return self._s[3298]! } public func Channel_Username_UsernameIsAvailable(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3296]!, self._r[3296]!, [_0]) + return formatWithArgumentRanges(self._s[3299]!, self._r[3299]!, [_0]) } - public var ClearCache_Forever: String { return self._s[3297]! } - public var AuthSessions_AddDeviceIntro_Title: String { return self._s[3298]! } - public var CreatePoll_Quiz: String { return self._s[3299]! } - public var PhotoEditor_ContrastTool: String { return self._s[3302]! } + public var ClearCache_Forever: String { return self._s[3300]! } + public var AuthSessions_AddDeviceIntro_Title: String { return self._s[3301]! } + public var CreatePoll_Quiz: String { return self._s[3302]! } + public var PhotoEditor_ContrastTool: String { return self._s[3305]! } public func PUSH_PINNED_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3303]!, self._r[3303]!, [_1]) + return formatWithArgumentRanges(self._s[3306]!, self._r[3306]!, [_1]) } - public var DialogList_Draft: String { return self._s[3304]! } - public var Wallet_Configuration_BlockchainIdInfo: String { return self._s[3305]! } - public var Privacy_TopPeersDelete: String { return self._s[3307]! } - public var LoginPassword_PasswordPlaceholder: String { return self._s[3308]! } - public var Passport_Identity_TypeIdentityCardUploadScan: String { return self._s[3309]! } - public var WebSearch_RecentSectionClear: String { return self._s[3310]! } - public var EditTheme_ErrorInvalidCharacters: String { return self._s[3311]! } - public var Watch_ChatList_NoConversationsTitle: String { return self._s[3313]! } - public var Common_Done: String { return self._s[3315]! } - public var Shortcut_SwitchAccount: String { return self._s[3316]! } - public var AuthSessions_EmptyText: String { return self._s[3317]! } - public var Wallet_Configuration_BlockchainNameChangedTitle: String { return self._s[3318]! } - public var Conversation_ShareBotContactConfirmation: String { return self._s[3319]! } - public var Tour_Title5: String { return self._s[3320]! } - public var Wallet_Settings_Title: String { return self._s[3321]! } + public var DialogList_Draft: String { return self._s[3307]! } + public var Wallet_Configuration_BlockchainIdInfo: String { return self._s[3308]! } + public var Privacy_TopPeersDelete: String { return self._s[3310]! } + public var LoginPassword_PasswordPlaceholder: String { return self._s[3311]! } + public var Passport_Identity_TypeIdentityCardUploadScan: String { return self._s[3312]! } + public var WebSearch_RecentSectionClear: String { return self._s[3313]! } + public var EditTheme_ErrorInvalidCharacters: String { return self._s[3314]! } + public var Watch_ChatList_NoConversationsTitle: String { return self._s[3316]! } + public var Common_Done: String { return self._s[3318]! } + public var Shortcut_SwitchAccount: String { return self._s[3319]! } + public var AuthSessions_EmptyText: String { return self._s[3320]! } + public var Wallet_Configuration_BlockchainNameChangedTitle: String { return self._s[3321]! } + public var Conversation_ShareBotContactConfirmation: String { return self._s[3322]! } + public var Tour_Title5: String { return self._s[3323]! } + public var Wallet_Settings_Title: String { return self._s[3324]! } public func Map_DirectionsDriveEta(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3322]!, self._r[3322]!, [_0]) + return formatWithArgumentRanges(self._s[3325]!, self._r[3325]!, [_0]) } - public var ApplyLanguage_UnsufficientDataTitle: String { return self._s[3323]! } - public var Conversation_LinkDialogSave: String { return self._s[3324]! } - public var GroupInfo_ActionRestrict: String { return self._s[3325]! } - public var Checkout_Title: String { return self._s[3326]! } - public var Channel_DiscussionGroup_HeaderLabel: String { return self._s[3328]! } - public var Channel_AdminLog_CanChangeInfo: String { return self._s[3330]! } - public var Notification_RenamedGroup: String { return self._s[3331]! } - public var PeopleNearby_Groups: String { return self._s[3332]! } - public var Checkout_PayWithFaceId: String { return self._s[3333]! } - public var Channel_BanList_BlockedTitle: String { return self._s[3334]! } - public var SettingsSearch_Synonyms_Notifications_InAppNotificationsSound: String { return self._s[3336]! } - public var Checkout_WebConfirmation_Title: String { return self._s[3337]! } - public var Notifications_MessageNotificationsAlert: String { return self._s[3338]! } + public var ApplyLanguage_UnsufficientDataTitle: String { return self._s[3326]! } + public var Conversation_LinkDialogSave: String { return self._s[3327]! } + public var GroupInfo_ActionRestrict: String { return self._s[3328]! } + public var Checkout_Title: String { return self._s[3329]! } + public var Channel_DiscussionGroup_HeaderLabel: String { return self._s[3331]! } + public var Channel_AdminLog_CanChangeInfo: String { return self._s[3333]! } + public var Notification_RenamedGroup: String { return self._s[3334]! } + public var PeopleNearby_Groups: String { return self._s[3335]! } + public var Checkout_PayWithFaceId: String { return self._s[3336]! } + public var Channel_BanList_BlockedTitle: String { return self._s[3337]! } + public var SettingsSearch_Synonyms_Notifications_InAppNotificationsSound: String { return self._s[3339]! } + public var Checkout_WebConfirmation_Title: String { return self._s[3340]! } + public var Notifications_MessageNotificationsAlert: String { return self._s[3341]! } public func Activity_RemindAboutGroup(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3339]!, self._r[3339]!, [_0]) + return formatWithArgumentRanges(self._s[3342]!, self._r[3342]!, [_0]) } - public var Profile_AddToExisting: String { return self._s[3341]! } + public var Profile_AddToExisting: String { return self._s[3344]! } public func Profile_CreateEncryptedChatOutdatedError(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3342]!, self._r[3342]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3345]!, self._r[3345]!, [_0, _1]) } - public var Cache_Files: String { return self._s[3344]! } - public var Permissions_PrivacyPolicy: String { return self._s[3345]! } - public var SocksProxySetup_ConnectAndSave: String { return self._s[3346]! } - public var UserInfo_NotificationsDefaultDisabled: String { return self._s[3347]! } - public var AutoDownloadSettings_TypeContacts: String { return self._s[3349]! } - public var Appearance_ThemePreview_ChatList_1_Text: String { return self._s[3351]! } - public var Calls_NoCallsPlaceholder: String { return self._s[3352]! } + public var Cache_Files: String { return self._s[3347]! } + public var Permissions_PrivacyPolicy: String { return self._s[3348]! } + public var SocksProxySetup_ConnectAndSave: String { return self._s[3349]! } + public var UserInfo_NotificationsDefaultDisabled: String { return self._s[3350]! } + public var AutoDownloadSettings_TypeContacts: String { return self._s[3352]! } + public var Appearance_ThemePreview_ChatList_1_Text: String { return self._s[3354]! } + public var Calls_NoCallsPlaceholder: String { return self._s[3355]! } public func Wallet_Receive_ShareInvoiceUrlInfo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3353]!, self._r[3353]!, [_0]) + return formatWithArgumentRanges(self._s[3356]!, self._r[3356]!, [_0]) } - public var Channel_Username_RevokeExistingUsernamesInfo: String { return self._s[3354]! } - public var VoiceOver_AttachMedia: String { return self._s[3357]! } - public var Notifications_ExceptionsGroupPlaceholder: String { return self._s[3358]! } + public var Channel_Username_RevokeExistingUsernamesInfo: String { return self._s[3357]! } + public var VoiceOver_AttachMedia: String { return self._s[3360]! } + public var Notifications_ExceptionsGroupPlaceholder: String { return self._s[3361]! } public func PUSH_CHAT_MESSAGE_INVOICE(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3359]!, self._r[3359]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3362]!, self._r[3362]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsSound: String { return self._s[3360]! } - public var Conversation_SetReminder_Title: String { return self._s[3361]! } - public var Passport_FieldAddressHelp: String { return self._s[3362]! } - public var Privacy_GroupsAndChannels_InviteToChannelMultipleError: String { return self._s[3363]! } - public var PUSH_REMINDER_TITLE: String { return self._s[3364]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsSound: String { return self._s[3363]! } + public var Conversation_SetReminder_Title: String { return self._s[3364]! } + public var Passport_FieldAddressHelp: String { return self._s[3365]! } + public var Privacy_GroupsAndChannels_InviteToChannelMultipleError: String { return self._s[3366]! } + public var PUSH_REMINDER_TITLE: String { return self._s[3367]! } public func Login_TermsOfService_ProceedBot(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3365]!, self._r[3365]!, [_0]) + return formatWithArgumentRanges(self._s[3368]!, self._r[3368]!, [_0]) } - public var Channel_AdminLog_EmptyTitle: String { return self._s[3366]! } - public var Privacy_Calls_NeverAllow_Title: String { return self._s[3367]! } - public var Login_UnknownError: String { return self._s[3368]! } - public var Group_UpgradeNoticeText2: String { return self._s[3371]! } - public var Watch_Compose_AddContact: String { return self._s[3372]! } - public var ClearCache_StorageServiceFiles: String { return self._s[3373]! } - public var Web_Error: String { return self._s[3374]! } - public var Gif_Search: String { return self._s[3375]! } - public var Profile_MessageLifetime1h: String { return self._s[3376]! } - public var CheckoutInfo_ReceiverInfoEmailPlaceholder: String { return self._s[3377]! } - public var Channel_Username_CheckingUsername: String { return self._s[3378]! } - public var CallFeedback_ReasonSilentRemote: String { return self._s[3379]! } - public var AutoDownloadSettings_TypeChannels: String { return self._s[3380]! } - public var Channel_AboutItem: String { return self._s[3381]! } - public var Privacy_GroupsAndChannels_AlwaysAllow_Placeholder: String { return self._s[3383]! } - public var VoiceOver_Chat_VoiceMessage: String { return self._s[3384]! } - public var GroupInfo_SharedMedia: String { return self._s[3385]! } + public var Channel_AdminLog_EmptyTitle: String { return self._s[3369]! } + public var Privacy_Calls_NeverAllow_Title: String { return self._s[3370]! } + public var Login_UnknownError: String { return self._s[3371]! } + public var Group_UpgradeNoticeText2: String { return self._s[3374]! } + public var Watch_Compose_AddContact: String { return self._s[3375]! } + public var ClearCache_StorageServiceFiles: String { return self._s[3376]! } + public var Web_Error: String { return self._s[3377]! } + public var Gif_Search: String { return self._s[3378]! } + public var Profile_MessageLifetime1h: String { return self._s[3379]! } + public var CheckoutInfo_ReceiverInfoEmailPlaceholder: String { return self._s[3380]! } + public var Channel_Username_CheckingUsername: String { return self._s[3381]! } + public var CallFeedback_ReasonSilentRemote: String { return self._s[3382]! } + public var AutoDownloadSettings_TypeChannels: String { return self._s[3383]! } + public var Channel_AboutItem: String { return self._s[3384]! } + public var Privacy_GroupsAndChannels_AlwaysAllow_Placeholder: String { return self._s[3386]! } + public var VoiceOver_Chat_VoiceMessage: String { return self._s[3387]! } + public var GroupInfo_SharedMedia: String { return self._s[3388]! } public func Channel_AdminLog_MessagePromotedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3386]!, self._r[3386]!, [_1]) + return formatWithArgumentRanges(self._s[3389]!, self._r[3389]!, [_1]) } - public var Call_PhoneCallInProgressMessage: String { return self._s[3387]! } + public var Call_PhoneCallInProgressMessage: String { return self._s[3390]! } public func PUSH_CHANNEL_ALBUM(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3388]!, self._r[3388]!, [_1]) + return formatWithArgumentRanges(self._s[3391]!, self._r[3391]!, [_1]) } - public var ChatList_UndoArchiveRevealedText: String { return self._s[3389]! } - public var GroupInfo_InviteLink_RevokeAlert_Text: String { return self._s[3390]! } - public var Conversation_SearchByName_Placeholder: String { return self._s[3391]! } - public var CreatePoll_AddOption: String { return self._s[3392]! } - public var GroupInfo_Permissions_SearchPlaceholder: String { return self._s[3393]! } - public var Group_UpgradeNoticeHeader: String { return self._s[3394]! } - public var Channel_Management_AddModerator: String { return self._s[3395]! } - public var AutoDownloadSettings_MaxFileSize: String { return self._s[3396]! } - public var StickerPacksSettings_ShowStickersButton: String { return self._s[3397]! } - public var Wallet_Info_RefreshErrorNetworkText: String { return self._s[3398]! } - public var Theme_Colors_Background: String { return self._s[3399]! } - public var NotificationsSound_Hello: String { return self._s[3401]! } - public var SocksProxySetup_SavedProxies: String { return self._s[3402]! } - public var Channel_Stickers_Placeholder: String { return self._s[3404]! } + public var ChatList_UndoArchiveRevealedText: String { return self._s[3392]! } + public var GroupInfo_InviteLink_RevokeAlert_Text: String { return self._s[3393]! } + public var Conversation_SearchByName_Placeholder: String { return self._s[3394]! } + public var CreatePoll_AddOption: String { return self._s[3395]! } + public var GroupInfo_Permissions_SearchPlaceholder: String { return self._s[3396]! } + public var Group_UpgradeNoticeHeader: String { return self._s[3397]! } + public var Channel_Management_AddModerator: String { return self._s[3398]! } + public var AutoDownloadSettings_MaxFileSize: String { return self._s[3399]! } + public var StickerPacksSettings_ShowStickersButton: String { return self._s[3400]! } + public var Wallet_Info_RefreshErrorNetworkText: String { return self._s[3401]! } + public var Theme_Colors_Background: String { return self._s[3402]! } + public var NotificationsSound_Hello: String { return self._s[3404]! } + public var SocksProxySetup_SavedProxies: String { return self._s[3405]! } + public var Channel_Stickers_Placeholder: String { return self._s[3407]! } public func Login_EmailCodeBody(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3405]!, self._r[3405]!, [_0]) + return formatWithArgumentRanges(self._s[3408]!, self._r[3408]!, [_0]) } - public var PrivacyPolicy_DeclineDeclineAndDelete: String { return self._s[3406]! } - public var Channel_Management_AddModeratorHelp: String { return self._s[3407]! } - public var ContactInfo_BirthdayLabel: String { return self._s[3408]! } - public var ChangePhoneNumberCode_RequestingACall: String { return self._s[3409]! } - public var AutoDownloadSettings_Channels: String { return self._s[3410]! } - public var Passport_Language_mn: String { return self._s[3411]! } - public var Notifications_ResetAllNotificationsHelp: String { return self._s[3414]! } - public var GroupInfo_Permissions_SlowmodeValue_Off: String { return self._s[3415]! } - public var Passport_Language_ja: String { return self._s[3417]! } - public var Settings_About_Title: String { return self._s[3418]! } - public var Settings_NotificationsAndSounds: String { return self._s[3419]! } - public var ChannelInfo_DeleteGroup: String { return self._s[3420]! } - public var Settings_BlockedUsers: String { return self._s[3421]! } + public var PrivacyPolicy_DeclineDeclineAndDelete: String { return self._s[3409]! } + public var Channel_Management_AddModeratorHelp: String { return self._s[3410]! } + public var ContactInfo_BirthdayLabel: String { return self._s[3411]! } + public var ChangePhoneNumberCode_RequestingACall: String { return self._s[3412]! } + public var AutoDownloadSettings_Channels: String { return self._s[3413]! } + public var Passport_Language_mn: String { return self._s[3414]! } + public var Notifications_ResetAllNotificationsHelp: String { return self._s[3417]! } + public var GroupInfo_Permissions_SlowmodeValue_Off: String { return self._s[3418]! } + public var Passport_Language_ja: String { return self._s[3420]! } + public var Settings_About_Title: String { return self._s[3421]! } + public var Settings_NotificationsAndSounds: String { return self._s[3422]! } + public var ChannelInfo_DeleteGroup: String { return self._s[3423]! } + public var Settings_BlockedUsers: String { return self._s[3424]! } public func Time_MonthOfYear_m4(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3422]!, self._r[3422]!, [_0]) + return formatWithArgumentRanges(self._s[3425]!, self._r[3425]!, [_0]) } - public var EditTheme_Create_Preview_OutgoingText: String { return self._s[3423]! } - public var Wallet_Weekday_Today: String { return self._s[3424]! } - public var AutoDownloadSettings_PreloadVideo: String { return self._s[3425]! } - public var Widget_ApplicationLocked: String { return self._s[3426]! } - public var Passport_Address_AddResidentialAddress: String { return self._s[3427]! } - public var Channel_Username_Title: String { return self._s[3428]! } + public var EditTheme_Create_Preview_OutgoingText: String { return self._s[3426]! } + public var Wallet_Weekday_Today: String { return self._s[3427]! } + public var AutoDownloadSettings_PreloadVideo: String { return self._s[3428]! } + public var Widget_ApplicationLocked: String { return self._s[3429]! } + public var Passport_Address_AddResidentialAddress: String { return self._s[3430]! } + public var Channel_Username_Title: String { return self._s[3431]! } public func Notification_RemovedGroupPhoto(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3429]!, self._r[3429]!, [_0]) + return formatWithArgumentRanges(self._s[3432]!, self._r[3432]!, [_0]) } - public var AttachmentMenu_File: String { return self._s[3431]! } - public var AppleWatch_Title: String { return self._s[3432]! } - public var Activity_RecordingVideoMessage: String { return self._s[3433]! } + public var AttachmentMenu_File: String { return self._s[3434]! } + public var AppleWatch_Title: String { return self._s[3435]! } + public var Activity_RecordingVideoMessage: String { return self._s[3436]! } public func Channel_DiscussionGroup_PublicChannelLink(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3434]!, self._r[3434]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3437]!, self._r[3437]!, [_1, _2]) } - public var Theme_Colors_Messages: String { return self._s[3435]! } - public var Weekday_Saturday: String { return self._s[3436]! } - public var WallpaperPreview_SwipeColorsTopText: String { return self._s[3437]! } - public var Profile_CreateEncryptedChatError: String { return self._s[3438]! } - public var Common_Next: String { return self._s[3440]! } - public var Channel_Stickers_YourStickers: String { return self._s[3442]! } - public var Message_Theme: String { return self._s[3443]! } - public var Call_AudioRouteHeadphones: String { return self._s[3444]! } - public var TwoStepAuth_EnterPasswordForgot: String { return self._s[3446]! } - public var Watch_Contacts_NoResults: String { return self._s[3448]! } - public var PhotoEditor_TintTool: String { return self._s[3451]! } - public var LoginPassword_ResetAccount: String { return self._s[3453]! } - public var Settings_SavedMessages: String { return self._s[3454]! } - public var SettingsSearch_Synonyms_Appearance_Animations: String { return self._s[3455]! } - public var Bot_GenericSupportStatus: String { return self._s[3456]! } - public var StickerPack_Add: String { return self._s[3457]! } - public var Checkout_TotalAmount: String { return self._s[3458]! } - public var Your_cards_number_is_invalid: String { return self._s[3459]! } - public var SettingsSearch_Synonyms_Appearance_AutoNightTheme: String { return self._s[3460]! } - public var VoiceOver_Chat_VideoMessage: String { return self._s[3461]! } + public var Theme_Colors_Messages: String { return self._s[3438]! } + public var Weekday_Saturday: String { return self._s[3439]! } + public var WallpaperPreview_SwipeColorsTopText: String { return self._s[3440]! } + public var Profile_CreateEncryptedChatError: String { return self._s[3441]! } + public var Common_Next: String { return self._s[3443]! } + public var Channel_Stickers_YourStickers: String { return self._s[3445]! } + public var Message_Theme: String { return self._s[3446]! } + public var Call_AudioRouteHeadphones: String { return self._s[3447]! } + public var TwoStepAuth_EnterPasswordForgot: String { return self._s[3449]! } + public var Watch_Contacts_NoResults: String { return self._s[3451]! } + public var PhotoEditor_TintTool: String { return self._s[3454]! } + public var LoginPassword_ResetAccount: String { return self._s[3456]! } + public var Settings_SavedMessages: String { return self._s[3457]! } + public var SettingsSearch_Synonyms_Appearance_Animations: String { return self._s[3458]! } + public var Bot_GenericSupportStatus: String { return self._s[3459]! } + public var StickerPack_Add: String { return self._s[3460]! } + public var Checkout_TotalAmount: String { return self._s[3461]! } + public var Your_cards_number_is_invalid: String { return self._s[3462]! } + public var SettingsSearch_Synonyms_Appearance_AutoNightTheme: String { return self._s[3463]! } + public var VoiceOver_Chat_VideoMessage: String { return self._s[3464]! } public func ChangePhoneNumberCode_CallTimer(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3462]!, self._r[3462]!, [_0]) + return formatWithArgumentRanges(self._s[3465]!, self._r[3465]!, [_0]) } public func GroupPermission_AddedInfo(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3463]!, self._r[3463]!, [_1, _2]) - } - public var ChatSettings_ConnectionType_UseSocks5: String { return self._s[3464]! } - public func PUSH_CHAT_PHOTO_EDITED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3466]!, self._r[3466]!, [_1, _2]) } + public var ChatSettings_ConnectionType_UseSocks5: String { return self._s[3467]! } + public func PUSH_CHAT_PHOTO_EDITED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3469]!, self._r[3469]!, [_1, _2]) + } public func Conversation_RestrictedTextTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3467]!, self._r[3467]!, [_0]) + return formatWithArgumentRanges(self._s[3470]!, self._r[3470]!, [_0]) } - public var GroupInfo_InviteLink_ShareLink: String { return self._s[3468]! } - public var StickerPack_Share: String { return self._s[3469]! } - public var Passport_DeleteAddress: String { return self._s[3470]! } - public var Settings_Passport: String { return self._s[3471]! } - public var SharedMedia_EmptyFilesText: String { return self._s[3472]! } - public var Conversation_DeleteMessagesForMe: String { return self._s[3473]! } - public var PasscodeSettings_AutoLock_IfAwayFor_1hour: String { return self._s[3474]! } - public var Contacts_PermissionsText: String { return self._s[3475]! } - public var Group_Setup_HistoryVisible: String { return self._s[3476]! } - public var Wallet_Month_ShortDecember: String { return self._s[3478]! } - public var Channel_EditAdmin_PermissionEnabledByDefault: String { return self._s[3479]! } - public var Passport_Address_AddRentalAgreement: String { return self._s[3480]! } - public var SocksProxySetup_Title: String { return self._s[3481]! } - public var Notification_Mute1h: String { return self._s[3482]! } + public var GroupInfo_InviteLink_ShareLink: String { return self._s[3471]! } + public var StickerPack_Share: String { return self._s[3472]! } + public var Passport_DeleteAddress: String { return self._s[3473]! } + public var Settings_Passport: String { return self._s[3474]! } + public var SharedMedia_EmptyFilesText: String { return self._s[3475]! } + public var Conversation_DeleteMessagesForMe: String { return self._s[3476]! } + public var PasscodeSettings_AutoLock_IfAwayFor_1hour: String { return self._s[3477]! } + public var Contacts_PermissionsText: String { return self._s[3478]! } + public var Group_Setup_HistoryVisible: String { return self._s[3479]! } + public var Wallet_Month_ShortDecember: String { return self._s[3481]! } + public var Channel_EditAdmin_PermissionEnabledByDefault: String { return self._s[3482]! } + public var Passport_Address_AddRentalAgreement: String { return self._s[3483]! } + public var SocksProxySetup_Title: String { return self._s[3484]! } + public var Notification_Mute1h: String { return self._s[3485]! } public func Passport_Email_CodeHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3483]!, self._r[3483]!, [_0]) + return formatWithArgumentRanges(self._s[3486]!, self._r[3486]!, [_0]) } - public var NotificationSettings_ShowNotificationsAllAccountsInfoOff: String { return self._s[3484]! } + public var NotificationSettings_ShowNotificationsAllAccountsInfoOff: String { return self._s[3487]! } public func PUSH_PINNED_GEOLIVE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3485]!, self._r[3485]!, [_1]) + return formatWithArgumentRanges(self._s[3488]!, self._r[3488]!, [_1]) } - public var FastTwoStepSetup_PasswordSection: String { return self._s[3486]! } - public var NetworkUsageSettings_ResetStatsConfirmation: String { return self._s[3489]! } - public var InfoPlist_NSFaceIDUsageDescription: String { return self._s[3491]! } - public var DialogList_NoMessagesText: String { return self._s[3492]! } - public var Privacy_ContactsResetConfirmation: String { return self._s[3493]! } - public var Privacy_Calls_P2PHelp: String { return self._s[3494]! } - public var Channel_DiscussionGroup_SearchPlaceholder: String { return self._s[3496]! } - public var Your_cards_expiration_year_is_invalid: String { return self._s[3497]! } - public var Common_TakePhotoOrVideo: String { return self._s[3498]! } - public var Wallet_Words_Text: String { return self._s[3499]! } - public var Call_StatusBusy: String { return self._s[3500]! } - public var Conversation_PinnedMessage: String { return self._s[3501]! } - public var AutoDownloadSettings_VoiceMessagesTitle: String { return self._s[3502]! } - public var Wallet_Configuration_BlockchainNameChangedProceed: String { return self._s[3503]! } - public var TwoStepAuth_SetupPasswordConfirmFailed: String { return self._s[3504]! } - public var Undo_ChatCleared: String { return self._s[3505]! } - public var AppleWatch_ReplyPresets: String { return self._s[3506]! } - public var Passport_DiscardMessageDescription: String { return self._s[3508]! } - public var Login_NetworkError: String { return self._s[3509]! } + public var FastTwoStepSetup_PasswordSection: String { return self._s[3489]! } + public var NetworkUsageSettings_ResetStatsConfirmation: String { return self._s[3492]! } + public var InfoPlist_NSFaceIDUsageDescription: String { return self._s[3494]! } + public var DialogList_NoMessagesText: String { return self._s[3495]! } + public var Privacy_ContactsResetConfirmation: String { return self._s[3496]! } + public var Privacy_Calls_P2PHelp: String { return self._s[3497]! } + public var Channel_DiscussionGroup_SearchPlaceholder: String { return self._s[3499]! } + public var Your_cards_expiration_year_is_invalid: String { return self._s[3500]! } + public var Common_TakePhotoOrVideo: String { return self._s[3501]! } + public var Wallet_Words_Text: String { return self._s[3502]! } + public var Call_StatusBusy: String { return self._s[3503]! } + public var Conversation_PinnedMessage: String { return self._s[3504]! } + public var AutoDownloadSettings_VoiceMessagesTitle: String { return self._s[3505]! } + public var Wallet_Configuration_BlockchainNameChangedProceed: String { return self._s[3506]! } + public var TwoStepAuth_SetupPasswordConfirmFailed: String { return self._s[3507]! } + public var Undo_ChatCleared: String { return self._s[3508]! } + public var AppleWatch_ReplyPresets: String { return self._s[3509]! } + public var Passport_DiscardMessageDescription: String { return self._s[3511]! } + public var Login_NetworkError: String { return self._s[3512]! } public func Notification_PinnedRoundMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3510]!, self._r[3510]!, [_0]) + return formatWithArgumentRanges(self._s[3513]!, self._r[3513]!, [_0]) } public func Channel_AdminLog_MessageRemovedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3511]!, self._r[3511]!, [_0]) + return formatWithArgumentRanges(self._s[3514]!, self._r[3514]!, [_0]) } - public var SocksProxySetup_PasswordPlaceholder: String { return self._s[3512]! } - public var Wallet_WordCheck_ViewWords: String { return self._s[3514]! } - public var Login_ResetAccountProtected_LimitExceeded: String { return self._s[3515]! } + public var SocksProxySetup_PasswordPlaceholder: String { return self._s[3515]! } + public var Wallet_WordCheck_ViewWords: String { return self._s[3517]! } + public var Login_ResetAccountProtected_LimitExceeded: String { return self._s[3518]! } public func Watch_LastSeen_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3517]!, self._r[3517]!, [_0]) + return formatWithArgumentRanges(self._s[3520]!, self._r[3520]!, [_0]) } - public var Call_ConnectionErrorMessage: String { return self._s[3518]! } - public var VoiceOver_Chat_Music: String { return self._s[3519]! } - public var SettingsSearch_Synonyms_Notifications_MessageNotificationsSound: String { return self._s[3520]! } - public var Compose_GroupTokenListPlaceholder: String { return self._s[3522]! } - public var ConversationMedia_Title: String { return self._s[3523]! } - public var EncryptionKey_Title: String { return self._s[3525]! } - public var TwoStepAuth_EnterPasswordTitle: String { return self._s[3526]! } - public var Notification_Exceptions_AddException: String { return self._s[3527]! } - public var PrivacySettings_BlockedPeersEmpty: String { return self._s[3528]! } - public var Profile_MessageLifetime1m: String { return self._s[3529]! } + public var Call_ConnectionErrorMessage: String { return self._s[3521]! } + public var VoiceOver_Chat_Music: String { return self._s[3522]! } + public var SettingsSearch_Synonyms_Notifications_MessageNotificationsSound: String { return self._s[3523]! } + public var Compose_GroupTokenListPlaceholder: String { return self._s[3525]! } + public var ConversationMedia_Title: String { return self._s[3526]! } + public var EncryptionKey_Title: String { return self._s[3528]! } + public var TwoStepAuth_EnterPasswordTitle: String { return self._s[3529]! } + public var Notification_Exceptions_AddException: String { return self._s[3530]! } + public var PrivacySettings_BlockedPeersEmpty: String { return self._s[3531]! } + public var Profile_MessageLifetime1m: String { return self._s[3532]! } public func Channel_AdminLog_MessageUnkickedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3530]!, self._r[3530]!, [_1]) + return formatWithArgumentRanges(self._s[3533]!, self._r[3533]!, [_1]) } - public var Month_GenMay: String { return self._s[3531]! } + public var Month_GenMay: String { return self._s[3534]! } public func LiveLocationUpdated_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3532]!, self._r[3532]!, [_0]) + return formatWithArgumentRanges(self._s[3535]!, self._r[3535]!, [_0]) } - public var PeopleNearby_Users: String { return self._s[3533]! } - public var Wallet_Send_AddressInfo: String { return self._s[3534]! } - public var ChannelMembers_WhoCanAddMembersAllHelp: String { return self._s[3535]! } - public var AutoDownloadSettings_ResetSettings: String { return self._s[3536]! } + public var PeopleNearby_Users: String { return self._s[3536]! } + public var Wallet_Send_AddressInfo: String { return self._s[3537]! } + public var ChannelMembers_WhoCanAddMembersAllHelp: String { return self._s[3538]! } + public var AutoDownloadSettings_ResetSettings: String { return self._s[3539]! } public func Wallet_Updated_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3538]!, self._r[3538]!, [_0]) + return formatWithArgumentRanges(self._s[3541]!, self._r[3541]!, [_0]) } - public var Conversation_EmptyPlaceholder: String { return self._s[3539]! } - public var Passport_Address_AddPassportRegistration: String { return self._s[3540]! } - public var Notifications_ChannelNotificationsAlert: String { return self._s[3541]! } - public var ChatSettings_AutoDownloadUsingCellular: String { return self._s[3542]! } - public var Camera_TapAndHoldForVideo: String { return self._s[3543]! } - public var Channel_JoinChannel: String { return self._s[3545]! } - public var Appearance_Animations: String { return self._s[3548]! } + public var Conversation_EmptyPlaceholder: String { return self._s[3542]! } + public var Passport_Address_AddPassportRegistration: String { return self._s[3543]! } + public var Notifications_ChannelNotificationsAlert: String { return self._s[3544]! } + public var ChatSettings_AutoDownloadUsingCellular: String { return self._s[3545]! } + public var Camera_TapAndHoldForVideo: String { return self._s[3546]! } + public var Channel_JoinChannel: String { return self._s[3548]! } + public var Appearance_Animations: String { return self._s[3551]! } public func Notification_MessageLifetimeChanged(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3549]!, self._r[3549]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3552]!, self._r[3552]!, [_1, _2]) } - public var Stickers_GroupStickers: String { return self._s[3551]! } - public var Appearance_ShareTheme: String { return self._s[3552]! } - public var TwoFactorSetup_Hint_Placeholder: String { return self._s[3553]! } - public var ConvertToSupergroup_HelpTitle: String { return self._s[3555]! } - public var StickerPackActionInfo_RemovedTitle: String { return self._s[3556]! } - public var Passport_Address_Street: String { return self._s[3557]! } - public var Conversation_AddContact: String { return self._s[3558]! } - public var Login_PhonePlaceholder: String { return self._s[3559]! } - public var Channel_Members_InviteLink: String { return self._s[3561]! } - public var Bot_Stop: String { return self._s[3562]! } - public var SettingsSearch_Synonyms_Proxy_UseForCalls: String { return self._s[3564]! } - public var Notification_PassportValueAddress: String { return self._s[3565]! } - public var Month_ShortJuly: String { return self._s[3566]! } - public var Passport_Address_TypeTemporaryRegistrationUploadScan: String { return self._s[3567]! } - public var Channel_AdminLog_BanSendMedia: String { return self._s[3568]! } - public var Passport_Identity_ReverseSide: String { return self._s[3569]! } - public var Watch_Stickers_Recents: String { return self._s[3572]! } - public var PrivacyLastSeenSettings_EmpryUsersPlaceholder: String { return self._s[3574]! } - public var Map_SendThisLocation: String { return self._s[3575]! } + public var Stickers_GroupStickers: String { return self._s[3554]! } + public var Appearance_ShareTheme: String { return self._s[3555]! } + public var TwoFactorSetup_Hint_Placeholder: String { return self._s[3556]! } + public var ConvertToSupergroup_HelpTitle: String { return self._s[3558]! } + public var StickerPackActionInfo_RemovedTitle: String { return self._s[3559]! } + public var Passport_Address_Street: String { return self._s[3560]! } + public var Conversation_AddContact: String { return self._s[3561]! } + public var Login_PhonePlaceholder: String { return self._s[3562]! } + public var Channel_Members_InviteLink: String { return self._s[3564]! } + public var Bot_Stop: String { return self._s[3565]! } + public var SettingsSearch_Synonyms_Proxy_UseForCalls: String { return self._s[3567]! } + public var Notification_PassportValueAddress: String { return self._s[3568]! } + public var Month_ShortJuly: String { return self._s[3569]! } + public var Passport_Address_TypeTemporaryRegistrationUploadScan: String { return self._s[3570]! } + public var Channel_AdminLog_BanSendMedia: String { return self._s[3571]! } + public var Passport_Identity_ReverseSide: String { return self._s[3572]! } + public var Watch_Stickers_Recents: String { return self._s[3575]! } + public var PrivacyLastSeenSettings_EmpryUsersPlaceholder: String { return self._s[3577]! } + public var Map_SendThisLocation: String { return self._s[3578]! } public func Time_MonthOfYear_m1(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3576]!, self._r[3576]!, [_0]) + return formatWithArgumentRanges(self._s[3579]!, self._r[3579]!, [_0]) } public func InviteText_SingleContact(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3577]!, self._r[3577]!, [_0]) - } - public var ConvertToSupergroup_Note: String { return self._s[3578]! } - public var Wallet_Intro_NotNow: String { return self._s[3579]! } - public func FileSize_MB(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3580]!, self._r[3580]!, [_0]) } - public var NetworkUsageSettings_GeneralDataSection: String { return self._s[3581]! } + public var ConvertToSupergroup_Note: String { return self._s[3581]! } + public var Wallet_Intro_NotNow: String { return self._s[3582]! } + public func FileSize_MB(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3583]!, self._r[3583]!, [_0]) + } + public var NetworkUsageSettings_GeneralDataSection: String { return self._s[3584]! } public func Compatibility_SecretMediaVersionTooLow(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3582]!, self._r[3582]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3585]!, self._r[3585]!, [_0, _1]) } - public var Login_CallRequestState3: String { return self._s[3584]! } - public var Wallpaper_SearchShort: String { return self._s[3585]! } - public var SettingsSearch_Synonyms_Appearance_ColorTheme: String { return self._s[3587]! } - public var PasscodeSettings_UnlockWithFaceId: String { return self._s[3588]! } - public var Channel_BotDoesntSupportGroups: String { return self._s[3589]! } + public var Login_CallRequestState3: String { return self._s[3587]! } + public var Wallpaper_SearchShort: String { return self._s[3588]! } + public var SettingsSearch_Synonyms_Appearance_ColorTheme: String { return self._s[3590]! } + public var PasscodeSettings_UnlockWithFaceId: String { return self._s[3591]! } + public var Channel_BotDoesntSupportGroups: String { return self._s[3592]! } public func PUSH_CHAT_MESSAGE_GEOLIVE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3590]!, self._r[3590]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3593]!, self._r[3593]!, [_1, _2]) } - public var Channel_AdminLogFilter_Title: String { return self._s[3591]! } - public var Appearance_ThemePreview_Chat_4_Text: String { return self._s[3593]! } - public var Notifications_GroupNotificationsExceptions: String { return self._s[3596]! } + public var Channel_AdminLogFilter_Title: String { return self._s[3594]! } + public var Appearance_ThemePreview_Chat_4_Text: String { return self._s[3596]! } + public var Notifications_GroupNotificationsExceptions: String { return self._s[3599]! } public func FileSize_B(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3597]!, self._r[3597]!, [_0]) - } - public var Passport_CorrectErrors: String { return self._s[3598]! } - public var VoiceOver_Chat_YourAnonymousPoll: String { return self._s[3599]! } - public func Channel_MessageTitleUpdated(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3600]!, self._r[3600]!, [_0]) } - public var Map_SendMyCurrentLocation: String { return self._s[3601]! } - public var Channel_DiscussionGroup: String { return self._s[3602]! } - public var TwoFactorSetup_Email_SkipConfirmationSkip: String { return self._s[3603]! } + public var Passport_CorrectErrors: String { return self._s[3601]! } + public var VoiceOver_Chat_YourAnonymousPoll: String { return self._s[3602]! } + public func Channel_MessageTitleUpdated(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3603]!, self._r[3603]!, [_0]) + } + public var Map_SendMyCurrentLocation: String { return self._s[3604]! } + public var Channel_DiscussionGroup: String { return self._s[3605]! } + public var TwoFactorSetup_Email_SkipConfirmationSkip: String { return self._s[3606]! } public func PUSH_PINNED_CONTACT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3604]!, self._r[3604]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3607]!, self._r[3607]!, [_1, _2]) } - public var SharedMedia_SearchNoResults: String { return self._s[3605]! } - public var Permissions_NotificationsText_v0: String { return self._s[3606]! } - public var Channel_EditAdmin_PermissionDeleteMessagesOfOthers: String { return self._s[3607]! } - public var Appearance_AppIcon: String { return self._s[3608]! } - public var Appearance_ThemePreview_ChatList_3_AuthorName: String { return self._s[3609]! } - public var LoginPassword_FloodError: String { return self._s[3610]! } - public var Wallet_Send_OwnAddressAlertProceed: String { return self._s[3612]! } - public var Group_Setup_HistoryHiddenHelp: String { return self._s[3613]! } + public var SharedMedia_SearchNoResults: String { return self._s[3608]! } + public var Permissions_NotificationsText_v0: String { return self._s[3609]! } + public var Channel_EditAdmin_PermissionDeleteMessagesOfOthers: String { return self._s[3610]! } + public var Appearance_AppIcon: String { return self._s[3611]! } + public var Appearance_ThemePreview_ChatList_3_AuthorName: String { return self._s[3612]! } + public var LoginPassword_FloodError: String { return self._s[3613]! } + public var Wallet_Send_OwnAddressAlertProceed: String { return self._s[3615]! } + public var Group_Setup_HistoryHiddenHelp: String { return self._s[3616]! } public func TwoStepAuth_PendingEmailHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3614]!, self._r[3614]!, [_0]) + return formatWithArgumentRanges(self._s[3617]!, self._r[3617]!, [_0]) } - public var Passport_Language_bn: String { return self._s[3615]! } + public var Passport_Language_bn: String { return self._s[3618]! } public func DialogList_SingleUploadingPhotoSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3616]!, self._r[3616]!, [_0]) - } - public var ChatList_Context_Pin: String { return self._s[3617]! } - public func Notification_PinnedAudioMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3618]!, self._r[3618]!, [_0]) - } - public func Channel_AdminLog_MessageChangedGroupStickerPack(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3619]!, self._r[3619]!, [_0]) } - public var Wallet_Navigation_Close: String { return self._s[3620]! } - public var GroupInfo_InvitationLinkGroupFull: String { return self._s[3624]! } - public var Group_EditAdmin_PermissionChangeInfo: String { return self._s[3626]! } - public var Wallet_Month_GenDecember: String { return self._s[3627]! } - public var Contacts_PermissionsAllow: String { return self._s[3628]! } - public var ReportPeer_ReasonCopyright: String { return self._s[3629]! } - public var Channel_EditAdmin_PermissinAddAdminOn: String { return self._s[3630]! } - public var WallpaperPreview_Pattern: String { return self._s[3631]! } - public var Paint_Duplicate: String { return self._s[3632]! } - public var Passport_Address_Country: String { return self._s[3633]! } - public var Notification_RenamedChannel: String { return self._s[3635]! } - public var ChatList_Context_Unmute: String { return self._s[3636]! } - public var CheckoutInfo_ErrorPostcodeInvalid: String { return self._s[3637]! } - public var Group_MessagePhotoUpdated: String { return self._s[3638]! } - public var Channel_BanUser_PermissionSendMedia: String { return self._s[3639]! } - public var Conversation_ContextMenuBan: String { return self._s[3640]! } - public var TwoStepAuth_EmailSent: String { return self._s[3641]! } - public var MessagePoll_NoVotes: String { return self._s[3642]! } - public var Wallet_Send_ErrorNotEnoughFundsTitle: String { return self._s[3643]! } - public var Passport_Language_is: String { return self._s[3645]! } - public var PeopleNearby_UsersEmpty: String { return self._s[3647]! } - public var Tour_Text5: String { return self._s[3648]! } + public var ChatList_Context_Pin: String { return self._s[3620]! } + public func Notification_PinnedAudioMessage(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3621]!, self._r[3621]!, [_0]) + } + public func Channel_AdminLog_MessageChangedGroupStickerPack(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3622]!, self._r[3622]!, [_0]) + } + public var Wallet_Navigation_Close: String { return self._s[3623]! } + public var GroupInfo_InvitationLinkGroupFull: String { return self._s[3627]! } + public var Group_EditAdmin_PermissionChangeInfo: String { return self._s[3629]! } + public var Wallet_Month_GenDecember: String { return self._s[3630]! } + public var Contacts_PermissionsAllow: String { return self._s[3631]! } + public var ReportPeer_ReasonCopyright: String { return self._s[3632]! } + public var Channel_EditAdmin_PermissinAddAdminOn: String { return self._s[3633]! } + public var WallpaperPreview_Pattern: String { return self._s[3634]! } + public var Paint_Duplicate: String { return self._s[3635]! } + public var Passport_Address_Country: String { return self._s[3636]! } + public var Notification_RenamedChannel: String { return self._s[3638]! } + public var ChatList_Context_Unmute: String { return self._s[3639]! } + public var CheckoutInfo_ErrorPostcodeInvalid: String { return self._s[3640]! } + public var Group_MessagePhotoUpdated: String { return self._s[3641]! } + public var Channel_BanUser_PermissionSendMedia: String { return self._s[3642]! } + public var Conversation_ContextMenuBan: String { return self._s[3643]! } + public var TwoStepAuth_EmailSent: String { return self._s[3644]! } + public var MessagePoll_NoVotes: String { return self._s[3645]! } + public var Wallet_Send_ErrorNotEnoughFundsTitle: String { return self._s[3646]! } + public var Passport_Language_is: String { return self._s[3648]! } + public var PeopleNearby_UsersEmpty: String { return self._s[3650]! } + public var Tour_Text5: String { return self._s[3651]! } public func Call_GroupFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3651]!, self._r[3651]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3654]!, self._r[3654]!, [_1, _2]) } - public var Undo_SecretChatDeleted: String { return self._s[3652]! } - public var SocksProxySetup_ShareQRCode: String { return self._s[3653]! } + public var Undo_SecretChatDeleted: String { return self._s[3655]! } + public var SocksProxySetup_ShareQRCode: String { return self._s[3656]! } public func VoiceOver_Chat_Size(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3654]!, self._r[3654]!, [_0]) + return formatWithArgumentRanges(self._s[3657]!, self._r[3657]!, [_0]) } - public var Forward_ErrorDisabledForChat: String { return self._s[3655]! } - public var LogoutOptions_ChangePhoneNumberText: String { return self._s[3656]! } - public var Paint_Edit: String { return self._s[3658]! } - public var ScheduledMessages_ReminderNotification: String { return self._s[3660]! } - public var Undo_DeletedGroup: String { return self._s[3662]! } - public var LoginPassword_ForgotPassword: String { return self._s[3663]! } - public var Wallet_WordImport_IncorrectTitle: String { return self._s[3664]! } - public var GroupInfo_GroupNamePlaceholder: String { return self._s[3665]! } + public var Forward_ErrorDisabledForChat: String { return self._s[3658]! } + public var LogoutOptions_ChangePhoneNumberText: String { return self._s[3659]! } + public var Paint_Edit: String { return self._s[3661]! } + public var ScheduledMessages_ReminderNotification: String { return self._s[3663]! } + public var Undo_DeletedGroup: String { return self._s[3665]! } + public var LoginPassword_ForgotPassword: String { return self._s[3666]! } + public var Wallet_WordImport_IncorrectTitle: String { return self._s[3667]! } + public var GroupInfo_GroupNamePlaceholder: String { return self._s[3668]! } public func Notification_Kicked(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3666]!, self._r[3666]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3669]!, self._r[3669]!, [_0, _1]) } - public var AppWallet_TransactionInfo_FeeInfoURL: String { return self._s[3667]! } - public var Conversation_InputTextCaptionPlaceholder: String { return self._s[3668]! } - public var AutoDownloadSettings_VideoMessagesTitle: String { return self._s[3669]! } - public var Passport_Language_uz: String { return self._s[3670]! } - public var Conversation_PinMessageAlertGroup: String { return self._s[3671]! } - public var SettingsSearch_Synonyms_Privacy_GroupsAndChannels: String { return self._s[3672]! } - public var Map_StopLiveLocation: String { return self._s[3674]! } - public var VoiceOver_MessageContextSend: String { return self._s[3676]! } - public var PasscodeSettings_Help: String { return self._s[3677]! } - public var NotificationsSound_Input: String { return self._s[3678]! } - public var Share_Title: String { return self._s[3681]! } - public var LogoutOptions_Title: String { return self._s[3682]! } - public var Wallet_Send_AddressText: String { return self._s[3683]! } - public var Login_TermsOfServiceAgree: String { return self._s[3684]! } - public var Compose_NewEncryptedChatTitle: String { return self._s[3685]! } - public var Channel_AdminLog_TitleSelectedEvents: String { return self._s[3686]! } - public var Channel_EditAdmin_PermissionEditMessages: String { return self._s[3687]! } - public var EnterPasscode_EnterTitle: String { return self._s[3688]! } + public var AppWallet_TransactionInfo_FeeInfoURL: String { return self._s[3670]! } + public var Conversation_InputTextCaptionPlaceholder: String { return self._s[3671]! } + public var AutoDownloadSettings_VideoMessagesTitle: String { return self._s[3672]! } + public var Passport_Language_uz: String { return self._s[3673]! } + public var Conversation_PinMessageAlertGroup: String { return self._s[3674]! } + public var SettingsSearch_Synonyms_Privacy_GroupsAndChannels: String { return self._s[3675]! } + public var Map_StopLiveLocation: String { return self._s[3677]! } + public var VoiceOver_MessageContextSend: String { return self._s[3679]! } + public var PasscodeSettings_Help: String { return self._s[3680]! } + public var NotificationsSound_Input: String { return self._s[3681]! } + public var Share_Title: String { return self._s[3684]! } + public var LogoutOptions_Title: String { return self._s[3685]! } + public var Wallet_Send_AddressText: String { return self._s[3686]! } + public var Login_TermsOfServiceAgree: String { return self._s[3687]! } + public var Compose_NewEncryptedChatTitle: String { return self._s[3688]! } + public var Channel_AdminLog_TitleSelectedEvents: String { return self._s[3689]! } + public var Channel_EditAdmin_PermissionEditMessages: String { return self._s[3690]! } + public var EnterPasscode_EnterTitle: String { return self._s[3691]! } public func Call_PrivacyErrorMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3689]!, self._r[3689]!, [_0]) - } - public var Settings_CopyPhoneNumber: String { return self._s[3690]! } - public var Conversation_AddToContacts: String { return self._s[3691]! } - public func VoiceOver_Chat_ReplyFrom(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3692]!, self._r[3692]!, [_0]) } - public var NotificationsSound_Keys: String { return self._s[3693]! } + public var Settings_CopyPhoneNumber: String { return self._s[3693]! } + public var Conversation_AddToContacts: String { return self._s[3694]! } + public func VoiceOver_Chat_ReplyFrom(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3695]!, self._r[3695]!, [_0]) + } + public var NotificationsSound_Keys: String { return self._s[3696]! } public func Call_ParticipantVersionOutdatedError(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3694]!, self._r[3694]!, [_0]) + return formatWithArgumentRanges(self._s[3697]!, self._r[3697]!, [_0]) } - public var Notification_MessageLifetime1w: String { return self._s[3695]! } - public var Message_Video: String { return self._s[3696]! } - public var AutoDownloadSettings_CellularTitle: String { return self._s[3697]! } + public var Notification_MessageLifetime1w: String { return self._s[3698]! } + public var Message_Video: String { return self._s[3699]! } + public var AutoDownloadSettings_CellularTitle: String { return self._s[3700]! } public func PUSH_CHANNEL_MESSAGE_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3698]!, self._r[3698]!, [_1]) + return formatWithArgumentRanges(self._s[3701]!, self._r[3701]!, [_1]) } - public var Wallet_Receive_AmountInfo: String { return self._s[3701]! } + public var Wallet_Receive_AmountInfo: String { return self._s[3704]! } public func Notification_JoinedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3702]!, self._r[3702]!, [_0]) + return formatWithArgumentRanges(self._s[3705]!, self._r[3705]!, [_0]) } public func PrivacySettings_LastSeenContactsPlus(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3703]!, self._r[3703]!, [_0]) + return formatWithArgumentRanges(self._s[3706]!, self._r[3706]!, [_0]) } - public var Passport_Language_mk: String { return self._s[3704]! } + public var Passport_Language_mk: String { return self._s[3707]! } public func Wallet_Time_PreciseDate_m2(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3705]!, self._r[3705]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3708]!, self._r[3708]!, [_1, _2, _3]) } - public var CreatePoll_CancelConfirmation: String { return self._s[3706]! } - public var MessagePoll_LabelAnonymousQuiz: String { return self._s[3707]! } - public var Conversation_SilentBroadcastTooltipOn: String { return self._s[3709]! } - public var PrivacyPolicy_Decline: String { return self._s[3710]! } - public var Passport_Identity_DoesNotExpire: String { return self._s[3711]! } - public var Channel_AdminLogFilter_EventsRestrictions: String { return self._s[3712]! } - public var AuthSessions_AddDeviceIntro_Action: String { return self._s[3713]! } - public var Permissions_SiriAllow_v0: String { return self._s[3715]! } - public var Wallet_Month_ShortAugust: String { return self._s[3716]! } - public var Appearance_ThemeCarouselNight: String { return self._s[3717]! } + public var CreatePoll_CancelConfirmation: String { return self._s[3709]! } + public var MessagePoll_LabelAnonymousQuiz: String { return self._s[3710]! } + public var Conversation_SilentBroadcastTooltipOn: String { return self._s[3712]! } + public var PrivacyPolicy_Decline: String { return self._s[3713]! } + public var Passport_Identity_DoesNotExpire: String { return self._s[3714]! } + public var Channel_AdminLogFilter_EventsRestrictions: String { return self._s[3715]! } + public var AuthSessions_AddDeviceIntro_Action: String { return self._s[3716]! } + public var Permissions_SiriAllow_v0: String { return self._s[3718]! } + public var Wallet_Month_ShortAugust: String { return self._s[3719]! } + public var Appearance_ThemeCarouselNight: String { return self._s[3720]! } public func LOCAL_CHAT_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3718]!, self._r[3718]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[3721]!, self._r[3721]!, [_1, "\(_2)"]) } public func Notification_RenamedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3719]!, self._r[3719]!, [_0]) + return formatWithArgumentRanges(self._s[3722]!, self._r[3722]!, [_0]) } - public var Paint_Regular: String { return self._s[3720]! } - public var ChatSettings_AutoDownloadReset: String { return self._s[3721]! } - public var SocksProxySetup_ShareLink: String { return self._s[3722]! } - public var Wallet_Qr_Title: String { return self._s[3723]! } - public var BlockedUsers_SelectUserTitle: String { return self._s[3724]! } - public var VoiceOver_Chat_RecordModeVoiceMessage: String { return self._s[3726]! } - public var Wallet_Settings_Configuration: String { return self._s[3727]! } - public var GroupInfo_InviteByLink: String { return self._s[3728]! } - public var MessageTimer_Custom: String { return self._s[3729]! } - public var UserInfo_NotificationsDefaultEnabled: String { return self._s[3730]! } - public var Conversation_StopQuizConfirmationTitle: String { return self._s[3731]! } - public var Passport_Address_TypeTemporaryRegistration: String { return self._s[3733]! } - public var Conversation_SendMessage_SetReminder: String { return self._s[3734]! } - public var VoiceOver_Chat_Selected: String { return self._s[3735]! } - public var ChatSettings_AutoDownloadUsingWiFi: String { return self._s[3736]! } - public var Channel_Username_InvalidTaken: String { return self._s[3737]! } - public var Conversation_ClousStorageInfo_Description3: String { return self._s[3738]! } - public var Wallet_WordCheck_TryAgain: String { return self._s[3739]! } - public var Wallet_Info_TransactionPendingHeader: String { return self._s[3740]! } - public var Settings_ChatBackground: String { return self._s[3741]! } - public var Channel_Subscribers_Title: String { return self._s[3742]! } - public var Wallet_Receive_InvoiceUrlHeader: String { return self._s[3743]! } - public var ApplyLanguage_ChangeLanguageTitle: String { return self._s[3744]! } - public var Watch_ConnectionDescription: String { return self._s[3745]! } - public var OldChannels_NoticeText: String { return self._s[3748]! } - public var Wallet_Configuration_ApplyErrorTitle: String { return self._s[3749]! } - public var IntentsSettings_SuggestBy: String { return self._s[3751]! } - public var Theme_ThemeChangedText: String { return self._s[3752]! } - public var ChatList_ArchivedChatsTitle: String { return self._s[3753]! } - public var Wallpaper_ResetWallpapers: String { return self._s[3754]! } - public var Wallet_Send_TransactionInProgress: String { return self._s[3755]! } - public var EditProfile_Title: String { return self._s[3756]! } - public var NotificationsSound_Bamboo: String { return self._s[3758]! } - public var Channel_AdminLog_MessagePreviousMessage: String { return self._s[3760]! } - public var Login_SmsRequestState2: String { return self._s[3761]! } - public var Passport_Language_ar: String { return self._s[3762]! } + public var Paint_Regular: String { return self._s[3723]! } + public var ChatSettings_AutoDownloadReset: String { return self._s[3724]! } + public var SocksProxySetup_ShareLink: String { return self._s[3725]! } + public var Wallet_Qr_Title: String { return self._s[3726]! } + public var BlockedUsers_SelectUserTitle: String { return self._s[3727]! } + public var VoiceOver_Chat_RecordModeVoiceMessage: String { return self._s[3729]! } + public var Wallet_Settings_Configuration: String { return self._s[3730]! } + public var GroupInfo_InviteByLink: String { return self._s[3731]! } + public var MessageTimer_Custom: String { return self._s[3732]! } + public var UserInfo_NotificationsDefaultEnabled: String { return self._s[3733]! } + public var Conversation_StopQuizConfirmationTitle: String { return self._s[3734]! } + public var Passport_Address_TypeTemporaryRegistration: String { return self._s[3736]! } + public var Conversation_SendMessage_SetReminder: String { return self._s[3737]! } + public var VoiceOver_Chat_Selected: String { return self._s[3738]! } + public var ChatSettings_AutoDownloadUsingWiFi: String { return self._s[3739]! } + public var Channel_Username_InvalidTaken: String { return self._s[3740]! } + public var Conversation_ClousStorageInfo_Description3: String { return self._s[3741]! } + public var Wallet_WordCheck_TryAgain: String { return self._s[3742]! } + public var Wallet_Info_TransactionPendingHeader: String { return self._s[3743]! } + public var Settings_ChatBackground: String { return self._s[3744]! } + public var Channel_Subscribers_Title: String { return self._s[3745]! } + public var Wallet_Receive_InvoiceUrlHeader: String { return self._s[3746]! } + public var ApplyLanguage_ChangeLanguageTitle: String { return self._s[3747]! } + public var Watch_ConnectionDescription: String { return self._s[3748]! } + public var OldChannels_NoticeText: String { return self._s[3751]! } + public var Wallet_Configuration_ApplyErrorTitle: String { return self._s[3752]! } + public var IntentsSettings_SuggestBy: String { return self._s[3754]! } + public var Theme_ThemeChangedText: String { return self._s[3755]! } + public var ChatList_ArchivedChatsTitle: String { return self._s[3756]! } + public var Wallpaper_ResetWallpapers: String { return self._s[3757]! } + public var Wallet_Send_TransactionInProgress: String { return self._s[3758]! } + public var EditProfile_Title: String { return self._s[3759]! } + public var NotificationsSound_Bamboo: String { return self._s[3761]! } + public var Channel_AdminLog_MessagePreviousMessage: String { return self._s[3763]! } + public var Login_SmsRequestState2: String { return self._s[3764]! } + public var Passport_Language_ar: String { return self._s[3765]! } public func Message_AuthorPinnedGame(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3763]!, self._r[3763]!, [_0]) + return formatWithArgumentRanges(self._s[3766]!, self._r[3766]!, [_0]) } - public var SettingsSearch_Synonyms_EditProfile_Title: String { return self._s[3764]! } - public var Wallet_Created_Text: String { return self._s[3765]! } - public var Conversation_MessageDialogEdit: String { return self._s[3767]! } - public var Wallet_Created_Proceed: String { return self._s[3768]! } - public var Wallet_Words_Done: String { return self._s[3769]! } - public var VoiceOver_Media_PlaybackPause: String { return self._s[3770]! } + public var SettingsSearch_Synonyms_EditProfile_Title: String { return self._s[3767]! } + public var Wallet_Created_Text: String { return self._s[3768]! } + public var Conversation_MessageDialogEdit: String { return self._s[3770]! } + public var Wallet_Created_Proceed: String { return self._s[3771]! } + public var Wallet_Words_Done: String { return self._s[3772]! } + public var VoiceOver_Media_PlaybackPause: String { return self._s[3773]! } public func PUSH_AUTH_UNKNOWN(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3771]!, self._r[3771]!, [_1]) + return formatWithArgumentRanges(self._s[3774]!, self._r[3774]!, [_1]) } - public var Common_Close: String { return self._s[3772]! } - public var GroupInfo_PublicLink: String { return self._s[3773]! } - public var Channel_OwnershipTransfer_ErrorPrivacyRestricted: String { return self._s[3774]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsPreview: String { return self._s[3775]! } + public var Common_Close: String { return self._s[3775]! } + public var GroupInfo_PublicLink: String { return self._s[3776]! } + public var Channel_OwnershipTransfer_ErrorPrivacyRestricted: String { return self._s[3777]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsPreview: String { return self._s[3778]! } public func Channel_AdminLog_MessageToggleInvitesOff(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3779]!, self._r[3779]!, [_0]) + return formatWithArgumentRanges(self._s[3782]!, self._r[3782]!, [_0]) } - public var UserInfo_About_Placeholder: String { return self._s[3780]! } + public var UserInfo_About_Placeholder: String { return self._s[3783]! } public func Conversation_FileHowToText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3781]!, self._r[3781]!, [_0]) + return formatWithArgumentRanges(self._s[3784]!, self._r[3784]!, [_0]) } - public var GroupInfo_Permissions_SectionTitle: String { return self._s[3782]! } - public var Channel_Info_Banned: String { return self._s[3784]! } + public var GroupInfo_Permissions_SectionTitle: String { return self._s[3785]! } + public var Channel_Info_Banned: String { return self._s[3787]! } public func Time_MonthOfYear_m11(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3785]!, self._r[3785]!, [_0]) + return formatWithArgumentRanges(self._s[3788]!, self._r[3788]!, [_0]) } - public var Appearance_Other: String { return self._s[3786]! } - public var Passport_Language_my: String { return self._s[3787]! } - public var Group_Setup_BasicHistoryHiddenHelp: String { return self._s[3788]! } + public var Appearance_Other: String { return self._s[3789]! } + public var Passport_Language_my: String { return self._s[3790]! } + public var Group_Setup_BasicHistoryHiddenHelp: String { return self._s[3791]! } public func Time_PreciseDate_m9(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3789]!, self._r[3789]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3792]!, self._r[3792]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_Privacy_PasscodeAndFaceId: String { return self._s[3790]! } - public var IntentsSettings_SuggestedAndSpotlightChatsInfo: String { return self._s[3791]! } - public var Preview_CopyAddress: String { return self._s[3792]! } + public var SettingsSearch_Synonyms_Privacy_PasscodeAndFaceId: String { return self._s[3793]! } + public var IntentsSettings_SuggestedAndSpotlightChatsInfo: String { return self._s[3794]! } + public var Preview_CopyAddress: String { return self._s[3795]! } public func DialogList_SinglePlayingGameSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3793]!, self._r[3793]!, [_0]) + return formatWithArgumentRanges(self._s[3796]!, self._r[3796]!, [_0]) } - public var KeyCommand_JumpToPreviousChat: String { return self._s[3794]! } - public var UserInfo_BotSettings: String { return self._s[3795]! } - public var LiveLocation_MenuStopAll: String { return self._s[3797]! } - public var Passport_PasswordCreate: String { return self._s[3798]! } - public var StickerSettings_MaskContextInfo: String { return self._s[3799]! } - public var Message_PinnedLocationMessage: String { return self._s[3800]! } - public var Map_Satellite: String { return self._s[3801]! } - public var Watch_Message_Unsupported: String { return self._s[3802]! } - public var Username_TooManyPublicUsernamesError: String { return self._s[3803]! } - public var TwoStepAuth_EnterPasswordInvalid: String { return self._s[3804]! } + public var KeyCommand_JumpToPreviousChat: String { return self._s[3797]! } + public var UserInfo_BotSettings: String { return self._s[3798]! } + public var LiveLocation_MenuStopAll: String { return self._s[3800]! } + public var Passport_PasswordCreate: String { return self._s[3801]! } + public var StickerSettings_MaskContextInfo: String { return self._s[3802]! } + public var Message_PinnedLocationMessage: String { return self._s[3803]! } + public var Map_Satellite: String { return self._s[3804]! } + public var Watch_Message_Unsupported: String { return self._s[3805]! } + public var Username_TooManyPublicUsernamesError: String { return self._s[3806]! } + public var TwoStepAuth_EnterPasswordInvalid: String { return self._s[3807]! } public func Notification_PinnedTextMessage(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3805]!, self._r[3805]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3808]!, self._r[3808]!, [_0, _1]) } public func Conversation_OpenBotLinkText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3806]!, self._r[3806]!, [_0]) + return formatWithArgumentRanges(self._s[3809]!, self._r[3809]!, [_0]) } - public var Wallet_WordImport_Continue: String { return self._s[3807]! } + public var Wallet_WordImport_Continue: String { return self._s[3810]! } public func TwoFactorSetup_EmailVerification_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3808]!, self._r[3808]!, [_0]) + return formatWithArgumentRanges(self._s[3811]!, self._r[3811]!, [_0]) } - public var Notifications_ChannelNotificationsHelp: String { return self._s[3809]! } - public var Privacy_Calls_P2PContacts: String { return self._s[3810]! } - public var NotificationsSound_None: String { return self._s[3811]! } - public var Wallet_TransactionInfo_StorageFeeHeader: String { return self._s[3812]! } - public var Channel_DiscussionGroup_UnlinkGroup: String { return self._s[3814]! } - public var AccessDenied_VoiceMicrophone: String { return self._s[3815]! } + public var Notifications_ChannelNotificationsHelp: String { return self._s[3812]! } + public var Privacy_Calls_P2PContacts: String { return self._s[3813]! } + public var NotificationsSound_None: String { return self._s[3814]! } + public var Wallet_TransactionInfo_StorageFeeHeader: String { return self._s[3815]! } + public var Channel_DiscussionGroup_UnlinkGroup: String { return self._s[3817]! } + public var AccessDenied_VoiceMicrophone: String { return self._s[3818]! } public func ApplyLanguage_ChangeLanguageAlreadyActive(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3816]!, self._r[3816]!, [_1]) + return formatWithArgumentRanges(self._s[3819]!, self._r[3819]!, [_1]) } - public var Cache_Indexing: String { return self._s[3817]! } - public var DialogList_RecentTitlePeople: String { return self._s[3819]! } - public var DialogList_EncryptionRejected: String { return self._s[3820]! } - public var GroupInfo_Administrators: String { return self._s[3821]! } - public var Passport_ScanPassportHelp: String { return self._s[3822]! } - public var Application_Name: String { return self._s[3823]! } - public var Channel_AdminLogFilter_ChannelEventsInfo: String { return self._s[3824]! } - public var Appearance_ThemeCarouselDay: String { return self._s[3826]! } - public var Passport_Identity_TranslationHelp: String { return self._s[3827]! } + public var Cache_Indexing: String { return self._s[3820]! } + public var DialogList_RecentTitlePeople: String { return self._s[3822]! } + public var DialogList_EncryptionRejected: String { return self._s[3823]! } + public var GroupInfo_Administrators: String { return self._s[3824]! } + public var Passport_ScanPassportHelp: String { return self._s[3825]! } + public var Application_Name: String { return self._s[3826]! } + public var Channel_AdminLogFilter_ChannelEventsInfo: String { return self._s[3827]! } + public var Appearance_ThemeCarouselDay: String { return self._s[3829]! } + public var Passport_Identity_TranslationHelp: String { return self._s[3830]! } public func VoiceOver_Chat_VideoMessageFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3828]!, self._r[3828]!, [_0]) + return formatWithArgumentRanges(self._s[3831]!, self._r[3831]!, [_0]) } public func Notification_JoinedGroupByLink(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3829]!, self._r[3829]!, [_0]) + return formatWithArgumentRanges(self._s[3832]!, self._r[3832]!, [_0]) } public func DialogList_EncryptedChatStartedOutgoing(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3830]!, self._r[3830]!, [_0]) + return formatWithArgumentRanges(self._s[3833]!, self._r[3833]!, [_0]) } - public var Channel_EditAdmin_PermissionDeleteMessages: String { return self._s[3831]! } - public var Privacy_ChatsTitle: String { return self._s[3832]! } - public var DialogList_ClearHistoryConfirmation: String { return self._s[3833]! } - public var SettingsSearch_Synonyms_Data_Storage_ClearCache: String { return self._s[3834]! } - public var Watch_Suggestion_HoldOn: String { return self._s[3835]! } - public var Group_EditAdmin_TransferOwnership: String { return self._s[3836]! } - public var WebBrowser_Title: String { return self._s[3837]! } - public var Group_LinkedChannel: String { return self._s[3838]! } - public var VoiceOver_Chat_SeenByRecipient: String { return self._s[3839]! } - public var SocksProxySetup_RequiredCredentials: String { return self._s[3840]! } - public var Passport_Address_TypeRentalAgreementUploadScan: String { return self._s[3841]! } - public var Appearance_TextSize_UseSystem: String { return self._s[3842]! } - public var TwoStepAuth_EmailSkipAlert: String { return self._s[3843]! } - public var ScheduledMessages_RemindersTitle: String { return self._s[3845]! } - public var Channel_Setup_TypePublic: String { return self._s[3847]! } + public var Channel_EditAdmin_PermissionDeleteMessages: String { return self._s[3834]! } + public var Privacy_ChatsTitle: String { return self._s[3835]! } + public var DialogList_ClearHistoryConfirmation: String { return self._s[3836]! } + public var SettingsSearch_Synonyms_Data_Storage_ClearCache: String { return self._s[3837]! } + public var Watch_Suggestion_HoldOn: String { return self._s[3838]! } + public var Group_EditAdmin_TransferOwnership: String { return self._s[3839]! } + public var WebBrowser_Title: String { return self._s[3840]! } + public var Group_LinkedChannel: String { return self._s[3841]! } + public var VoiceOver_Chat_SeenByRecipient: String { return self._s[3842]! } + public var SocksProxySetup_RequiredCredentials: String { return self._s[3843]! } + public var Passport_Address_TypeRentalAgreementUploadScan: String { return self._s[3844]! } + public var Appearance_TextSize_UseSystem: String { return self._s[3845]! } + public var TwoStepAuth_EmailSkipAlert: String { return self._s[3846]! } + public var ScheduledMessages_RemindersTitle: String { return self._s[3848]! } + public var Channel_Setup_TypePublic: String { return self._s[3850]! } public func Channel_AdminLog_MessageToggleInvitesOn(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3848]!, self._r[3848]!, [_0]) + return formatWithArgumentRanges(self._s[3851]!, self._r[3851]!, [_0]) } - public var Channel_TypeSetup_Title: String { return self._s[3850]! } - public var MessagePoll_ViewResults: String { return self._s[3851]! } - public var Map_OpenInMaps: String { return self._s[3853]! } + public var Channel_TypeSetup_Title: String { return self._s[3853]! } + public var MessagePoll_ViewResults: String { return self._s[3854]! } + public var Map_OpenInMaps: String { return self._s[3856]! } public func PUSH_PINNED_NOTEXT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3854]!, self._r[3854]!, [_1]) + return formatWithArgumentRanges(self._s[3857]!, self._r[3857]!, [_1]) } - public var NotificationsSound_Tremolo: String { return self._s[3856]! } + public var NotificationsSound_Tremolo: String { return self._s[3859]! } public func Date_ChatDateHeaderYear(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3857]!, self._r[3857]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3860]!, self._r[3860]!, [_1, _2, _3]) } - public var ConversationProfile_UnknownAddMemberError: String { return self._s[3858]! } - public var Channel_OwnershipTransfer_PasswordPlaceholder: String { return self._s[3859]! } - public var Passport_PasswordHelp: String { return self._s[3860]! } - public var Login_CodeExpiredError: String { return self._s[3861]! } - public var Channel_EditAdmin_PermissionChangeInfo: String { return self._s[3862]! } - public var Conversation_TitleUnmute: String { return self._s[3863]! } - public var Passport_Identity_ScansHelp: String { return self._s[3864]! } - public var Passport_Language_lo: String { return self._s[3865]! } - public var Camera_FlashAuto: String { return self._s[3866]! } - public var Conversation_OpenBotLinkOpen: String { return self._s[3867]! } - public var Common_Cancel: String { return self._s[3868]! } - public var DialogList_SavedMessagesTooltip: String { return self._s[3869]! } - public var TwoStepAuth_SetupPasswordTitle: String { return self._s[3870]! } - public var Appearance_TintAllColors: String { return self._s[3871]! } + public var ConversationProfile_UnknownAddMemberError: String { return self._s[3861]! } + public var Channel_OwnershipTransfer_PasswordPlaceholder: String { return self._s[3862]! } + public var Passport_PasswordHelp: String { return self._s[3863]! } + public var Login_CodeExpiredError: String { return self._s[3864]! } + public var Channel_EditAdmin_PermissionChangeInfo: String { return self._s[3865]! } + public var Conversation_TitleUnmute: String { return self._s[3866]! } + public var Passport_Identity_ScansHelp: String { return self._s[3867]! } + public var Passport_Language_lo: String { return self._s[3868]! } + public var Camera_FlashAuto: String { return self._s[3869]! } + public var Conversation_OpenBotLinkOpen: String { return self._s[3870]! } + public var Common_Cancel: String { return self._s[3871]! } + public var DialogList_SavedMessagesTooltip: String { return self._s[3872]! } + public var TwoStepAuth_SetupPasswordTitle: String { return self._s[3873]! } + public var Appearance_TintAllColors: String { return self._s[3874]! } public func PUSH_MESSAGE_FWD(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3872]!, self._r[3872]!, [_1]) + return formatWithArgumentRanges(self._s[3875]!, self._r[3875]!, [_1]) } - public var Conversation_ReportSpamConfirmation: String { return self._s[3873]! } - public var ChatSettings_Title: String { return self._s[3875]! } - public var Passport_PasswordReset: String { return self._s[3876]! } - public var SocksProxySetup_TypeNone: String { return self._s[3877]! } - public var EditTheme_Title: String { return self._s[3880]! } - public var PhoneNumberHelp_Help: String { return self._s[3881]! } - public var Checkout_EnterPassword: String { return self._s[3882]! } - public var Share_AuthTitle: String { return self._s[3884]! } - public var Activity_UploadingDocument: String { return self._s[3885]! } - public var State_Connecting: String { return self._s[3886]! } - public var Profile_MessageLifetime1w: String { return self._s[3887]! } - public var Conversation_ContextMenuReport: String { return self._s[3888]! } - public var CheckoutInfo_ReceiverInfoPhone: String { return self._s[3889]! } - public var AutoNightTheme_ScheduledTo: String { return self._s[3890]! } + public var Conversation_ReportSpamConfirmation: String { return self._s[3876]! } + public var ChatSettings_Title: String { return self._s[3878]! } + public var Passport_PasswordReset: String { return self._s[3879]! } + public var SocksProxySetup_TypeNone: String { return self._s[3880]! } + public var EditTheme_Title: String { return self._s[3883]! } + public var PhoneNumberHelp_Help: String { return self._s[3884]! } + public var Checkout_EnterPassword: String { return self._s[3885]! } + public var Activity_UploadingDocument: String { return self._s[3887]! } + public var Share_AuthTitle: String { return self._s[3888]! } + public var State_Connecting: String { return self._s[3889]! } + public var Profile_MessageLifetime1w: String { return self._s[3890]! } + public var Conversation_ContextMenuReport: String { return self._s[3891]! } + public var CheckoutInfo_ReceiverInfoPhone: String { return self._s[3892]! } + public var AutoNightTheme_ScheduledTo: String { return self._s[3893]! } public func VoiceOver_Chat_AnonymousPollFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3891]!, self._r[3891]!, [_0]) + return formatWithArgumentRanges(self._s[3894]!, self._r[3894]!, [_0]) } - public var AuthSessions_Terminate: String { return self._s[3892]! } - public var Wallet_WordImport_CanNotRemember: String { return self._s[3893]! } - public var Checkout_NewCard_CardholderNamePlaceholder: String { return self._s[3895]! } - public var KeyCommand_JumpToPreviousUnreadChat: String { return self._s[3896]! } - public var PhotoEditor_Set: String { return self._s[3897]! } - public var EmptyGroupInfo_Title: String { return self._s[3898]! } - public var Login_PadPhoneHelp: String { return self._s[3899]! } - public var AutoDownloadSettings_TypeGroupChats: String { return self._s[3901]! } - public var PrivacyPolicy_DeclineLastWarning: String { return self._s[3903]! } - public var NotificationsSound_Complete: String { return self._s[3904]! } - public var SettingsSearch_Synonyms_Privacy_Data_Title: String { return self._s[3905]! } - public var Group_Info_AdminLog: String { return self._s[3906]! } - public var GroupPermission_NotAvailableInPublicGroups: String { return self._s[3907]! } + public var AuthSessions_Terminate: String { return self._s[3895]! } + public var Wallet_WordImport_CanNotRemember: String { return self._s[3896]! } + public var Checkout_NewCard_CardholderNamePlaceholder: String { return self._s[3898]! } + public var KeyCommand_JumpToPreviousUnreadChat: String { return self._s[3899]! } + public var PhotoEditor_Set: String { return self._s[3900]! } + public var EmptyGroupInfo_Title: String { return self._s[3901]! } + public var Login_PadPhoneHelp: String { return self._s[3902]! } + public var AutoDownloadSettings_TypeGroupChats: String { return self._s[3904]! } + public var PrivacyPolicy_DeclineLastWarning: String { return self._s[3906]! } + public var NotificationsSound_Complete: String { return self._s[3907]! } + public var SettingsSearch_Synonyms_Privacy_Data_Title: String { return self._s[3908]! } + public var Group_Info_AdminLog: String { return self._s[3909]! } + public var GroupPermission_NotAvailableInPublicGroups: String { return self._s[3910]! } public func Wallet_Time_PreciseDate_m11(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3908]!, self._r[3908]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3911]!, self._r[3911]!, [_1, _2, _3]) } - public var Channel_AdminLog_InfoPanelAlertText: String { return self._s[3909]! } - public var Group_Location_CreateInThisPlace: String { return self._s[3911]! } - public var Conversation_Admin: String { return self._s[3912]! } - public var Conversation_GifTooltip: String { return self._s[3913]! } - public var Passport_NotLoggedInMessage: String { return self._s[3914]! } + public var Channel_AdminLog_InfoPanelAlertText: String { return self._s[3912]! } + public var Group_Location_CreateInThisPlace: String { return self._s[3914]! } + public var Conversation_Admin: String { return self._s[3915]! } + public var Conversation_GifTooltip: String { return self._s[3916]! } + public var Passport_NotLoggedInMessage: String { return self._s[3917]! } public func AutoDownloadSettings_OnFor(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3916]!, self._r[3916]!, [_0]) + return formatWithArgumentRanges(self._s[3919]!, self._r[3919]!, [_0]) } - public var Profile_MessageLifetimeForever: String { return self._s[3917]! } - public var SharedMedia_EmptyTitle: String { return self._s[3919]! } - public var Channel_Edit_PrivatePublicLinkAlert: String { return self._s[3921]! } - public var Username_Help: String { return self._s[3922]! } - public var DialogList_LanguageTooltip: String { return self._s[3924]! } - public var Map_LoadError: String { return self._s[3925]! } - public var Login_PhoneNumberAlreadyAuthorized: String { return self._s[3926]! } - public var Channel_AdminLog_AddMembers: String { return self._s[3927]! } - public var ArchivedChats_IntroTitle2: String { return self._s[3928]! } - public var Notification_Exceptions_NewException: String { return self._s[3929]! } - public var TwoStepAuth_EmailTitle: String { return self._s[3930]! } - public var WatchRemote_AlertText: String { return self._s[3931]! } + public var Profile_MessageLifetimeForever: String { return self._s[3920]! } + public var SharedMedia_EmptyTitle: String { return self._s[3922]! } + public var Channel_Edit_PrivatePublicLinkAlert: String { return self._s[3924]! } + public var Username_Help: String { return self._s[3925]! } + public var DialogList_LanguageTooltip: String { return self._s[3927]! } + public var Map_LoadError: String { return self._s[3928]! } + public var Login_PhoneNumberAlreadyAuthorized: String { return self._s[3929]! } + public var Channel_AdminLog_AddMembers: String { return self._s[3930]! } + public var ArchivedChats_IntroTitle2: String { return self._s[3931]! } + public var Notification_Exceptions_NewException: String { return self._s[3932]! } + public var TwoStepAuth_EmailTitle: String { return self._s[3933]! } + public var WatchRemote_AlertText: String { return self._s[3934]! } public func Wallet_Send_ConfirmationText(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3932]!, self._r[3932]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3935]!, self._r[3935]!, [_1, _2, _3]) + } + public var ChatSettings_ConnectionType_Title: String { return self._s[3939]! } + public func PUSH_PINNED_QUIZ(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3940]!, self._r[3940]!, [_1, _2]) } - public var ChatSettings_ConnectionType_Title: String { return self._s[3936]! } - public var WebBrowser_DefaultBrowser: String { return self._s[3937]! } public func Settings_CheckPhoneNumberTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3938]!, self._r[3938]!, [_0]) - } - public var SettingsSearch_Synonyms_Calls_CallTab: String { return self._s[3939]! } - public var Passport_Address_CountryPlaceholder: String { return self._s[3940]! } - public func DialogList_AwaitingEncryption(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3941]!, self._r[3941]!, [_0]) } + public var SettingsSearch_Synonyms_Calls_CallTab: String { return self._s[3942]! } + public var WebBrowser_DefaultBrowser: String { return self._s[3943]! } + public var Passport_Address_CountryPlaceholder: String { return self._s[3944]! } + public func DialogList_AwaitingEncryption(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3945]!, self._r[3945]!, [_0]) + } public func Time_PreciseDate_m6(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3942]!, self._r[3942]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3946]!, self._r[3946]!, [_1, _2, _3]) } - public var Group_AdminLog_EmptyText: String { return self._s[3943]! } - public var SettingsSearch_Synonyms_Appearance_Title: String { return self._s[3944]! } - public var Conversation_PrivateChannelTooltip: String { return self._s[3946]! } - public var Wallet_Created_ExportErrorText: String { return self._s[3947]! } - public var ChatList_UndoArchiveText1: String { return self._s[3948]! } - public var AccessDenied_VideoMicrophone: String { return self._s[3949]! } - public var Conversation_ContextMenuStickerPackAdd: String { return self._s[3950]! } - public var Cache_ClearNone: String { return self._s[3951]! } - public var SocksProxySetup_FailedToConnect: String { return self._s[3952]! } - public var Permissions_NotificationsTitle_v0: String { return self._s[3953]! } + public var Group_AdminLog_EmptyText: String { return self._s[3947]! } + public var SettingsSearch_Synonyms_Appearance_Title: String { return self._s[3948]! } + public var Conversation_PrivateChannelTooltip: String { return self._s[3950]! } + public var Wallet_Created_ExportErrorText: String { return self._s[3951]! } + public var ChatList_UndoArchiveText1: String { return self._s[3952]! } + public var AccessDenied_VideoMicrophone: String { return self._s[3953]! } + public var Conversation_ContextMenuStickerPackAdd: String { return self._s[3954]! } + public var Cache_ClearNone: String { return self._s[3955]! } + public var SocksProxySetup_FailedToConnect: String { return self._s[3956]! } + public var Permissions_NotificationsTitle_v0: String { return self._s[3957]! } public func Channel_AdminLog_MessageEdited(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3954]!, self._r[3954]!, [_0]) + return formatWithArgumentRanges(self._s[3958]!, self._r[3958]!, [_0]) } - public var Passport_Identity_Country: String { return self._s[3955]! } + public var Passport_Identity_Country: String { return self._s[3959]! } public func ChatSettings_AutoDownloadSettings_TypeFile(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3956]!, self._r[3956]!, [_0]) + return formatWithArgumentRanges(self._s[3960]!, self._r[3960]!, [_0]) } public func Notification_CreatedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3957]!, self._r[3957]!, [_0]) + return formatWithArgumentRanges(self._s[3961]!, self._r[3961]!, [_0]) } - public var Exceptions_AddToExceptions: String { return self._s[3958]! } - public var AccessDenied_Settings: String { return self._s[3959]! } - public var Passport_Address_TypeUtilityBillUploadScan: String { return self._s[3960]! } - public var Month_ShortMay: String { return self._s[3961]! } - public var Compose_NewGroup: String { return self._s[3963]! } - public var Group_Setup_TypePrivate: String { return self._s[3965]! } - public var Login_PadPhoneHelpTitle: String { return self._s[3967]! } - public var Appearance_ThemeDayClassic: String { return self._s[3968]! } - public var Channel_AdminLog_MessagePreviousCaption: String { return self._s[3969]! } - public var AutoDownloadSettings_OffForAll: String { return self._s[3970]! } - public var Privacy_GroupsAndChannels_WhoCanAddMe: String { return self._s[3971]! } - public var Conversation_typing: String { return self._s[3973]! } - public var Undo_ScheduledMessagesCleared: String { return self._s[3974]! } - public var Paint_Masks: String { return self._s[3975]! } - public var Contacts_DeselectAll: String { return self._s[3976]! } + public var Exceptions_AddToExceptions: String { return self._s[3962]! } + public var AccessDenied_Settings: String { return self._s[3963]! } + public var Passport_Address_TypeUtilityBillUploadScan: String { return self._s[3964]! } + public var Month_ShortMay: String { return self._s[3965]! } + public var Compose_NewGroup: String { return self._s[3967]! } + public var Group_Setup_TypePrivate: String { return self._s[3969]! } + public var Login_PadPhoneHelpTitle: String { return self._s[3971]! } + public var Appearance_ThemeDayClassic: String { return self._s[3972]! } + public var Channel_AdminLog_MessagePreviousCaption: String { return self._s[3973]! } + public var AutoDownloadSettings_OffForAll: String { return self._s[3974]! } + public var Privacy_GroupsAndChannels_WhoCanAddMe: String { return self._s[3975]! } + public var Conversation_typing: String { return self._s[3977]! } + public var Undo_ScheduledMessagesCleared: String { return self._s[3978]! } + public var Paint_Masks: String { return self._s[3979]! } + public var Contacts_DeselectAll: String { return self._s[3980]! } public func Wallet_Updated_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3977]!, self._r[3977]!, [_0]) + return formatWithArgumentRanges(self._s[3981]!, self._r[3981]!, [_0]) } - public var CreatePoll_MultipleChoiceQuizAlert: String { return self._s[3978]! } - public var Username_InvalidTaken: String { return self._s[3979]! } - public var Call_StatusNoAnswer: String { return self._s[3980]! } - public var TwoStepAuth_EmailAddSuccess: String { return self._s[3981]! } - public var SettingsSearch_Synonyms_Privacy_BlockedUsers: String { return self._s[3982]! } - public var Passport_Identity_Selfie: String { return self._s[3983]! } - public var Login_InfoLastNamePlaceholder: String { return self._s[3984]! } - public var Privacy_SecretChatsLinkPreviewsHelp: String { return self._s[3985]! } - public var Conversation_ClearSecretHistory: String { return self._s[3986]! } - public var PeopleNearby_Description: String { return self._s[3988]! } - public var NetworkUsageSettings_Title: String { return self._s[3989]! } - public var Your_cards_security_code_is_invalid: String { return self._s[3991]! } + public var CreatePoll_MultipleChoiceQuizAlert: String { return self._s[3982]! } + public var Username_InvalidTaken: String { return self._s[3983]! } + public var Call_StatusNoAnswer: String { return self._s[3984]! } + public var TwoStepAuth_EmailAddSuccess: String { return self._s[3985]! } + public var SettingsSearch_Synonyms_Privacy_BlockedUsers: String { return self._s[3986]! } + public var Passport_Identity_Selfie: String { return self._s[3987]! } + public var Login_InfoLastNamePlaceholder: String { return self._s[3988]! } + public var Privacy_SecretChatsLinkPreviewsHelp: String { return self._s[3989]! } + public var Conversation_ClearSecretHistory: String { return self._s[3990]! } + public var PeopleNearby_Description: String { return self._s[3992]! } + public var NetworkUsageSettings_Title: String { return self._s[3993]! } + public var Your_cards_security_code_is_invalid: String { return self._s[3995]! } public func Notification_LeftChannel(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3993]!, self._r[3993]!, [_0]) + return formatWithArgumentRanges(self._s[3997]!, self._r[3997]!, [_0]) } public func Call_CallInProgressMessage(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3994]!, self._r[3994]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3998]!, self._r[3998]!, [_1, _2]) } - public var SaveIncomingPhotosSettings_From: String { return self._s[3996]! } - public var VoiceOver_Navigation_Search: String { return self._s[3997]! } - public var Map_LiveLocationTitle: String { return self._s[3998]! } - public var Login_InfoAvatarAdd: String { return self._s[3999]! } - public var Passport_Identity_FilesView: String { return self._s[4000]! } - public var UserInfo_GenericPhoneLabel: String { return self._s[4001]! } - public var Privacy_Calls_NeverAllow: String { return self._s[4002]! } - public var VoiceOver_Chat_File: String { return self._s[4003]! } - public var Wallet_Settings_DeleteWalletInfo: String { return self._s[4004]! } + public var SaveIncomingPhotosSettings_From: String { return self._s[4000]! } + public var VoiceOver_Navigation_Search: String { return self._s[4001]! } + public var Map_LiveLocationTitle: String { return self._s[4002]! } + public var Login_InfoAvatarAdd: String { return self._s[4003]! } + public var Passport_Identity_FilesView: String { return self._s[4004]! } + public var UserInfo_GenericPhoneLabel: String { return self._s[4005]! } + public var Privacy_Calls_NeverAllow: String { return self._s[4006]! } + public var VoiceOver_Chat_File: String { return self._s[4007]! } + public var Wallet_Settings_DeleteWalletInfo: String { return self._s[4008]! } public func Contacts_AddPhoneNumber(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4005]!, self._r[4005]!, [_0]) + return formatWithArgumentRanges(self._s[4009]!, self._r[4009]!, [_0]) } - public var ContactInfo_PhoneNumberHidden: String { return self._s[4006]! } - public var TwoStepAuth_ConfirmationText: String { return self._s[4007]! } - public var ChatSettings_AutomaticVideoMessageDownload: String { return self._s[4008]! } + public var ContactInfo_PhoneNumberHidden: String { return self._s[4010]! } + public var TwoStepAuth_ConfirmationText: String { return self._s[4011]! } + public var ChatSettings_AutomaticVideoMessageDownload: String { return self._s[4012]! } public func PUSH_CHAT_MESSAGE_VIDEOS(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4009]!, self._r[4009]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[4013]!, self._r[4013]!, [_1, _2, _3]) } - public var Channel_AdminLogFilter_AdminsAll: String { return self._s[4010]! } - public var Wallet_Intro_CreateErrorText: String { return self._s[4011]! } - public var Tour_Title2: String { return self._s[4012]! } - public var Wallet_Sent_ViewWallet: String { return self._s[4013]! } - public var Conversation_FileOpenIn: String { return self._s[4014]! } - public var Checkout_ErrorPrecheckoutFailed: String { return self._s[4015]! } - public var Wallet_Send_ErrorInvalidAddress: String { return self._s[4016]! } - public var Wallpaper_Set: String { return self._s[4017]! } - public var Passport_Identity_Translations: String { return self._s[4019]! } + public var Channel_AdminLogFilter_AdminsAll: String { return self._s[4014]! } + public var Wallet_Intro_CreateErrorText: String { return self._s[4015]! } + public var Tour_Title2: String { return self._s[4016]! } + public var Wallet_Sent_ViewWallet: String { return self._s[4017]! } + public var Conversation_FileOpenIn: String { return self._s[4018]! } + public var Checkout_ErrorPrecheckoutFailed: String { return self._s[4019]! } + public var Wallet_Send_ErrorInvalidAddress: String { return self._s[4020]! } + public var Wallpaper_Set: String { return self._s[4021]! } + public var Passport_Identity_Translations: String { return self._s[4023]! } public func Channel_AdminLog_MessageChangedChannelAbout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4020]!, self._r[4020]!, [_0]) + return formatWithArgumentRanges(self._s[4024]!, self._r[4024]!, [_0]) } - public var Channel_LeaveChannel: String { return self._s[4021]! } + public var Channel_LeaveChannel: String { return self._s[4025]! } public func PINNED_INVOICE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4022]!, self._r[4022]!, [_1]) + return formatWithArgumentRanges(self._s[4026]!, self._r[4026]!, [_1]) } - public var SettingsSearch_Synonyms_Proxy_AddProxy: String { return self._s[4024]! } - public var PhotoEditor_HighlightsTint: String { return self._s[4025]! } - public var MessagePoll_LabelPoll: String { return self._s[4026]! } - public var Passport_Email_Delete: String { return self._s[4027]! } - public var Conversation_Mute: String { return self._s[4029]! } - public var Channel_AddBotAsAdmin: String { return self._s[4030]! } - public var Channel_AdminLog_CanSendMessages: String { return self._s[4032]! } - public var Wallet_Configuration_BlockchainNameChangedText: String { return self._s[4033]! } - public var ChatSettings_IntentsSettings: String { return self._s[4035]! } - public var Channel_Management_LabelOwner: String { return self._s[4036]! } + public var SettingsSearch_Synonyms_Proxy_AddProxy: String { return self._s[4028]! } + public var PhotoEditor_HighlightsTint: String { return self._s[4029]! } + public var MessagePoll_LabelPoll: String { return self._s[4030]! } + public var Passport_Email_Delete: String { return self._s[4031]! } + public var Conversation_Mute: String { return self._s[4033]! } + public var Channel_AddBotAsAdmin: String { return self._s[4034]! } + public var Channel_AdminLog_CanSendMessages: String { return self._s[4036]! } + public var Wallet_Configuration_BlockchainNameChangedText: String { return self._s[4037]! } + public var ChatSettings_IntentsSettings: String { return self._s[4039]! } + public var Channel_Management_LabelOwner: String { return self._s[4040]! } public func Notification_PassportValuesSentMessage(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4037]!, self._r[4037]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4041]!, self._r[4041]!, [_1, _2]) } - public var Calls_CallTabDescription: String { return self._s[4038]! } - public var Passport_Identity_NativeNameHelp: String { return self._s[4039]! } - public var Common_No: String { return self._s[4040]! } - public var Weekday_Sunday: String { return self._s[4041]! } - public var Notification_Reply: String { return self._s[4042]! } - public var Conversation_ViewMessage: String { return self._s[4043]! } + public var Calls_CallTabDescription: String { return self._s[4042]! } + public var Passport_Identity_NativeNameHelp: String { return self._s[4043]! } + public var Common_No: String { return self._s[4044]! } + public var Weekday_Sunday: String { return self._s[4045]! } + public var Notification_Reply: String { return self._s[4046]! } + public var Conversation_ViewMessage: String { return self._s[4047]! } public func Checkout_SavePasswordTimeoutAndFaceId(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4044]!, self._r[4044]!, [_0]) + return formatWithArgumentRanges(self._s[4048]!, self._r[4048]!, [_0]) } public func Map_LiveLocationPrivateDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4045]!, self._r[4045]!, [_0]) + return formatWithArgumentRanges(self._s[4049]!, self._r[4049]!, [_0]) } public func Wallet_Time_PreciseDate_m7(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4046]!, self._r[4046]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[4050]!, self._r[4050]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_EditProfile_AddAccount: String { return self._s[4047]! } - public var Wallet_Send_Title: String { return self._s[4048]! } - public var Message_PinnedDocumentMessage: String { return self._s[4049]! } - public var Wallet_Info_RefreshErrorText: String { return self._s[4050]! } - public var DialogList_TabTitle: String { return self._s[4052]! } - public var ChatSettings_AutoPlayTitle: String { return self._s[4053]! } - public var Passport_FieldEmail: String { return self._s[4054]! } - public var Conversation_UnpinMessageAlert: String { return self._s[4055]! } - public var Passport_Address_TypeBankStatement: String { return self._s[4056]! } - public var Wallet_SecureStorageReset_Title: String { return self._s[4057]! } - public var Passport_Identity_ExpiryDate: String { return self._s[4058]! } - public var Privacy_Calls_P2P: String { return self._s[4059]! } + public var SettingsSearch_Synonyms_EditProfile_AddAccount: String { return self._s[4051]! } + public var Wallet_Send_Title: String { return self._s[4052]! } + public var Message_PinnedDocumentMessage: String { return self._s[4053]! } + public var Wallet_Info_RefreshErrorText: String { return self._s[4054]! } + public var DialogList_TabTitle: String { return self._s[4056]! } + public var ChatSettings_AutoPlayTitle: String { return self._s[4057]! } + public var Passport_FieldEmail: String { return self._s[4058]! } + public var Conversation_UnpinMessageAlert: String { return self._s[4059]! } + public var Passport_Address_TypeBankStatement: String { return self._s[4060]! } + public var Wallet_SecureStorageReset_Title: String { return self._s[4061]! } + public var Passport_Identity_ExpiryDate: String { return self._s[4062]! } + public var Privacy_Calls_P2P: String { return self._s[4063]! } public func CancelResetAccount_Success(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4061]!, self._r[4061]!, [_0]) + return formatWithArgumentRanges(self._s[4065]!, self._r[4065]!, [_0]) } - public var SocksProxySetup_UseForCallsHelp: String { return self._s[4062]! } + public var SocksProxySetup_UseForCallsHelp: String { return self._s[4066]! } public func PUSH_CHAT_ALBUM(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4063]!, self._r[4063]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4067]!, self._r[4067]!, [_1, _2]) } - public var Stickers_ClearRecent: String { return self._s[4064]! } - public var EnterPasscode_ChangeTitle: String { return self._s[4065]! } - public var TwoFactorSetup_Email_Title: String { return self._s[4066]! } - public var Passport_InfoText: String { return self._s[4067]! } - public var Checkout_NewCard_SaveInfoEnableHelp: String { return self._s[4068]! } + public var Stickers_ClearRecent: String { return self._s[4068]! } + public var EnterPasscode_ChangeTitle: String { return self._s[4069]! } + public var TwoFactorSetup_Email_Title: String { return self._s[4070]! } + public var Passport_InfoText: String { return self._s[4071]! } + public var Checkout_NewCard_SaveInfoEnableHelp: String { return self._s[4072]! } public func Login_InvalidPhoneEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4069]!, self._r[4069]!, [_0]) + return formatWithArgumentRanges(self._s[4073]!, self._r[4073]!, [_0]) } public func Time_PreciseDate_m3(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4070]!, self._r[4070]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[4074]!, self._r[4074]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChannels: String { return self._s[4071]! } - public var ScheduledMessages_PollUnavailable: String { return self._s[4072]! } - public var VoiceOver_Navigation_Compose: String { return self._s[4073]! } - public var Passport_Identity_EditDriversLicense: String { return self._s[4074]! } - public var Conversation_TapAndHoldToRecord: String { return self._s[4076]! } - public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChats: String { return self._s[4077]! } + public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChannels: String { return self._s[4075]! } + public var ScheduledMessages_PollUnavailable: String { return self._s[4076]! } + public var VoiceOver_Navigation_Compose: String { return self._s[4077]! } + public var Passport_Identity_EditDriversLicense: String { return self._s[4078]! } + public var Conversation_TapAndHoldToRecord: String { return self._s[4080]! } + public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChats: String { return self._s[4081]! } public func Notification_CallTimeFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4078]!, self._r[4078]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4082]!, self._r[4082]!, [_1, _2]) } - public var Channel_EditAdmin_PermissionInviteViaLink: String { return self._s[4080]! } - public var ChatSettings_OpenLinksIn: String { return self._s[4081]! } - public var Map_HomeAndWorkTitle: String { return self._s[4082]! } + public var Channel_EditAdmin_PermissionInviteViaLink: String { return self._s[4084]! } + public var ChatSettings_OpenLinksIn: String { return self._s[4085]! } + public var Map_HomeAndWorkTitle: String { return self._s[4086]! } public func Generic_OpenHiddenLinkAlert(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4084]!, self._r[4084]!, [_0]) + return formatWithArgumentRanges(self._s[4088]!, self._r[4088]!, [_0]) } - public var DialogList_Unread: String { return self._s[4085]! } + public var DialogList_Unread: String { return self._s[4089]! } public func PUSH_CHAT_MESSAGE_GIF(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4086]!, self._r[4086]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4090]!, self._r[4090]!, [_1, _2]) } - public var User_DeletedAccount: String { return self._s[4087]! } - public var OwnershipTransfer_SetupTwoStepAuth: String { return self._s[4088]! } + public var User_DeletedAccount: String { return self._s[4091]! } + public var OwnershipTransfer_SetupTwoStepAuth: String { return self._s[4092]! } public func Watch_Time_ShortYesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4089]!, self._r[4089]!, [_0]) + return formatWithArgumentRanges(self._s[4093]!, self._r[4093]!, [_0]) } - public var UserInfo_NotificationsDefault: String { return self._s[4090]! } - public var SharedMedia_CategoryMedia: String { return self._s[4091]! } - public var SocksProxySetup_ProxyStatusUnavailable: String { return self._s[4092]! } - public var Channel_AdminLog_MessageRestrictedForever: String { return self._s[4093]! } - public var Watch_ChatList_Compose: String { return self._s[4094]! } - public var Notifications_MessageNotificationsExceptionsHelp: String { return self._s[4095]! } - public var AutoDownloadSettings_Delimeter: String { return self._s[4096]! } - public var Watch_Microphone_Access: String { return self._s[4097]! } - public var Group_Setup_HistoryHeader: String { return self._s[4098]! } - public var Map_SetThisLocation: String { return self._s[4099]! } - public var Appearance_ThemePreview_Chat_2_ReplyName: String { return self._s[4100]! } - public var Activity_UploadingPhoto: String { return self._s[4101]! } - public var Conversation_Edit: String { return self._s[4103]! } - public var Group_ErrorSendRestrictedMedia: String { return self._s[4104]! } - public var Login_TermsOfServiceDecline: String { return self._s[4105]! } - public var Message_PinnedContactMessage: String { return self._s[4106]! } + public var UserInfo_NotificationsDefault: String { return self._s[4094]! } + public var SharedMedia_CategoryMedia: String { return self._s[4095]! } + public var SocksProxySetup_ProxyStatusUnavailable: String { return self._s[4096]! } + public var Channel_AdminLog_MessageRestrictedForever: String { return self._s[4097]! } + public var Watch_ChatList_Compose: String { return self._s[4098]! } + public var Notifications_MessageNotificationsExceptionsHelp: String { return self._s[4099]! } + public var AutoDownloadSettings_Delimeter: String { return self._s[4100]! } + public var Watch_Microphone_Access: String { return self._s[4101]! } + public var Group_Setup_HistoryHeader: String { return self._s[4102]! } + public var Map_SetThisLocation: String { return self._s[4103]! } + public var Appearance_ThemePreview_Chat_2_ReplyName: String { return self._s[4104]! } + public var Activity_UploadingPhoto: String { return self._s[4105]! } + public var Conversation_Edit: String { return self._s[4107]! } + public var Group_ErrorSendRestrictedMedia: String { return self._s[4108]! } + public var Login_TermsOfServiceDecline: String { return self._s[4109]! } + public var Message_PinnedContactMessage: String { return self._s[4110]! } public func Channel_AdminLog_MessageRestrictedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4107]!, self._r[4107]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4111]!, self._r[4111]!, [_1, _2]) } public func Login_PhoneBannedEmailBody(_ _1: String, _ _2: String, _ _3: String, _ _4: String, _ _5: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4108]!, self._r[4108]!, [_1, _2, _3, _4, _5]) + return formatWithArgumentRanges(self._s[4112]!, self._r[4112]!, [_1, _2, _3, _4, _5]) } - public var Appearance_LargeEmoji: String { return self._s[4109]! } - public var TwoStepAuth_AdditionalPassword: String { return self._s[4111]! } - public var EditTheme_Edit_Preview_IncomingReplyText: String { return self._s[4112]! } + public var Appearance_LargeEmoji: String { return self._s[4113]! } + public var TwoStepAuth_AdditionalPassword: String { return self._s[4115]! } + public var EditTheme_Edit_Preview_IncomingReplyText: String { return self._s[4116]! } public func PUSH_CHAT_DELETE_YOU(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4113]!, self._r[4113]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4117]!, self._r[4117]!, [_1, _2]) } - public var Passport_Phone_EnterOtherNumber: String { return self._s[4114]! } - public var Message_PinnedPhotoMessage: String { return self._s[4115]! } - public var Passport_FieldPhone: String { return self._s[4116]! } - public var TwoStepAuth_RecoveryEmailAddDescription: String { return self._s[4117]! } - public var ChatSettings_AutoPlayGifs: String { return self._s[4118]! } - public var InfoPlist_NSCameraUsageDescription: String { return self._s[4120]! } - public var Conversation_Call: String { return self._s[4121]! } - public var Common_TakePhoto: String { return self._s[4123]! } - public var Group_EditAdmin_RankTitle: String { return self._s[4124]! } - public var Wallet_Receive_CommentHeader: String { return self._s[4125]! } - public var Channel_NotificationLoading: String { return self._s[4126]! } + public var Passport_Phone_EnterOtherNumber: String { return self._s[4118]! } + public var Message_PinnedPhotoMessage: String { return self._s[4119]! } + public var Passport_FieldPhone: String { return self._s[4120]! } + public var TwoStepAuth_RecoveryEmailAddDescription: String { return self._s[4121]! } + public var ChatSettings_AutoPlayGifs: String { return self._s[4122]! } + public var InfoPlist_NSCameraUsageDescription: String { return self._s[4124]! } + public var Conversation_Call: String { return self._s[4125]! } + public var Common_TakePhoto: String { return self._s[4127]! } + public var Group_EditAdmin_RankTitle: String { return self._s[4128]! } + public var Wallet_Receive_CommentHeader: String { return self._s[4129]! } + public var Channel_NotificationLoading: String { return self._s[4130]! } public func Notification_Exceptions_Sound(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4127]!, self._r[4127]!, [_0]) - } - public func ScheduledMessages_ScheduledDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4128]!, self._r[4128]!, [_0]) - } - public func PUSH_CHANNEL_MESSAGE_VIDEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4129]!, self._r[4129]!, [_1]) - } - public var Permissions_SiriTitle_v0: String { return self._s[4130]! } - public func VoiceOver_Chat_VoiceMessageFrom(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[4131]!, self._r[4131]!, [_0]) } - public func Login_ResetAccountProtected_Text(_ _0: String) -> (String, [(Int, NSRange)]) { + public func ScheduledMessages_ScheduledDate(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[4132]!, self._r[4132]!, [_0]) } - public var Channel_MessagePhotoRemoved: String { return self._s[4133]! } - public var Wallet_Info_ReceiveGrams: String { return self._s[4134]! } - public var ClearCache_FreeSpace: String { return self._s[4135]! } - public var Common_edit: String { return self._s[4136]! } - public var PrivacySettings_AuthSessions: String { return self._s[4137]! } - public var Month_ShortJune: String { return self._s[4138]! } - public var PrivacyLastSeenSettings_AlwaysShareWith_Placeholder: String { return self._s[4139]! } - public var Call_ReportSend: String { return self._s[4140]! } - public var Watch_LastSeen_JustNow: String { return self._s[4141]! } - public var Notifications_MessageNotifications: String { return self._s[4142]! } - public var WallpaperSearch_ColorGreen: String { return self._s[4143]! } - public var BroadcastListInfo_AddRecipient: String { return self._s[4145]! } - public var Group_Status: String { return self._s[4146]! } + public func PUSH_CHANNEL_MESSAGE_VIDEO(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[4133]!, self._r[4133]!, [_1]) + } + public var Permissions_SiriTitle_v0: String { return self._s[4134]! } + public func VoiceOver_Chat_VoiceMessageFrom(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[4135]!, self._r[4135]!, [_0]) + } + public func Login_ResetAccountProtected_Text(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[4136]!, self._r[4136]!, [_0]) + } + public var Channel_MessagePhotoRemoved: String { return self._s[4137]! } + public var Wallet_Info_ReceiveGrams: String { return self._s[4138]! } + public var ClearCache_FreeSpace: String { return self._s[4139]! } + public var Common_edit: String { return self._s[4140]! } + public var PrivacySettings_AuthSessions: String { return self._s[4141]! } + public var Month_ShortJune: String { return self._s[4142]! } + public var PrivacyLastSeenSettings_AlwaysShareWith_Placeholder: String { return self._s[4143]! } + public var Call_ReportSend: String { return self._s[4144]! } + public var Watch_LastSeen_JustNow: String { return self._s[4145]! } + public var Notifications_MessageNotifications: String { return self._s[4146]! } + public var WallpaperSearch_ColorGreen: String { return self._s[4147]! } + public var BroadcastListInfo_AddRecipient: String { return self._s[4149]! } + public var Group_Status: String { return self._s[4150]! } public func AutoNightTheme_LocationHelp(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4147]!, self._r[4147]!, [_0, _1]) + return formatWithArgumentRanges(self._s[4151]!, self._r[4151]!, [_0, _1]) } - public var TextFormat_AddLinkTitle: String { return self._s[4148]! } - public var ShareMenu_ShareTo: String { return self._s[4149]! } - public var Conversation_Moderate_Ban: String { return self._s[4150]! } + public var TextFormat_AddLinkTitle: String { return self._s[4152]! } + public var ShareMenu_ShareTo: String { return self._s[4153]! } + public var Conversation_Moderate_Ban: String { return self._s[4154]! } public func Conversation_DeleteMessagesFor(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4151]!, self._r[4151]!, [_0]) + return formatWithArgumentRanges(self._s[4155]!, self._r[4155]!, [_0]) } - public var SharedMedia_ViewInChat: String { return self._s[4152]! } - public var Map_LiveLocationFor8Hours: String { return self._s[4153]! } + public var SharedMedia_ViewInChat: String { return self._s[4156]! } + public var Map_LiveLocationFor8Hours: String { return self._s[4157]! } public func PUSH_PINNED_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4154]!, self._r[4154]!, [_1]) + return formatWithArgumentRanges(self._s[4158]!, self._r[4158]!, [_1]) } public func PUSH_PINNED_POLL(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4155]!, self._r[4155]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4159]!, self._r[4159]!, [_1, _2]) } public func Map_AccurateTo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4157]!, self._r[4157]!, [_0]) + return formatWithArgumentRanges(self._s[4161]!, self._r[4161]!, [_0]) } - public var Map_OpenInHereMaps: String { return self._s[4158]! } - public var Appearance_ReduceMotion: String { return self._s[4159]! } + public var Map_OpenInHereMaps: String { return self._s[4162]! } + public var Appearance_ReduceMotion: String { return self._s[4163]! } public func PUSH_MESSAGE_TEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4160]!, self._r[4160]!, [_1, _2]) - } - public var Channel_Setup_TypePublicHelp: String { return self._s[4161]! } - public var Passport_Identity_EditInternalPassport: String { return self._s[4162]! } - public var PhotoEditor_Skip: String { return self._s[4163]! } - public func PUSH_CHANNEL_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func ForwardedPolls(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Invitation_Members(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[2 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Call_ShortSeconds(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[3 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MuteFor_Days(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[4 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notification_GameScoreSimple(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[5 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedLocations(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[6 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MuteExpires_Days(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[7 * 6 + Int(form.rawValue)]!, stringValue) + return formatWithArgumentRanges(self._s[4164]!, self._r[4164]!, [_1, _2]) } + public var Channel_Setup_TypePublicHelp: String { return self._s[4165]! } + public var Passport_Identity_EditInternalPassport: String { return self._s[4166]! } + public var PhotoEditor_Skip: String { return self._s[4167]! } public func MessagePoll_QuizCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[8 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Map_ETAMinutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[9 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedAudios(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[10 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGE_FWDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[11 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func PrivacyLastSeenSettings_AddUsers(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[12 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedContacts(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[13 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGE_PHOTOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[14 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func SharedMedia_Generic(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[15 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedPhotos(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[16 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedGifs(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[17 * 6 + Int(form.rawValue)]!, stringValue) - } - public func AttachmentMenu_SendVideo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[18 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[19 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func VoiceOver_Chat_ContactEmailCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[20 * 6 + Int(form.rawValue)]!, stringValue) - } - public func StickerPack_AddStickerCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[21 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Media_SharePhoto(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[22 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Days(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[23 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[24 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Weeks(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[25 * 6 + Int(form.rawValue)]!, stringValue) - } - public func SharedMedia_File(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[26 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedStickers(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[27 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGE_VIDEOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[28 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func Map_ETAHours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[29 * 6 + Int(form.rawValue)]!, stringValue) - } - public func OldChannels_InactiveMonth(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[30 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ChatList_DeletedChats(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[31 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Years(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[32 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MuteFor_Hours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[33 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_ShortMinutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[34 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[35 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func SharedMedia_Photo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[36 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Wallpaper_DeleteConfirmation(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[37 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Theme_UsersCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[38 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGE_ROUNDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[39 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func PUSH_CHANNEL_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[40 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func MuteExpires_Minutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[41 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Media_ShareItem(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[42 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Contacts_ImportersCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[43 * 6 + Int(form.rawValue)]!, stringValue) - } - public func InviteText_ContactsCountText(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[44 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Passport_Scans(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[45 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ServiceMessage_GameScoreExtended(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[46 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Call_ShortMinutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[47 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[48 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func Watch_UserInfo_Mute(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[49 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ServiceMessage_GameScoreSelfSimple(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[50 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Media_ShareVideo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[51 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Minutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[52 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHANNEL_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[53 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func DialogList_LiveLocationChatsCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[54 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Call_Minutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[55 * 6 + Int(form.rawValue)]!, stringValue) - } - public func LiveLocationUpdated_MinutesAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[56 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Forward_ConfirmMultipleFiles(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[57 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ChatList_SelectedChats(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[58 * 6 + Int(form.rawValue)]!, stringValue) - } - public func OldChannels_InactiveYear(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[59 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedFiles(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[60 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, stringValue) } public func ForwardedVideoMessages(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[61 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, stringValue) } - public func PUSH_CHANNEL_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[62 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func GroupInfo_ShowMoreMembers(_ value: Int32) -> String { + public func ForwardedFiles(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[63 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[2 * 6 + Int(form.rawValue)]!, stringValue) } - public func AttachmentMenu_SendItem(_ value: Int32) -> String { + public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[64 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Watch_LastSeen_HoursAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[65 * 6 + Int(form.rawValue)]!, stringValue) - } - public func LastSeen_MinutesAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[66 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PollResults_ShowMore(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[67 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PasscodeSettings_FailedAttempts(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[68 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Hours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[69 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notifications_Exceptions(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[70 * 6 + Int(form.rawValue)]!, stringValue) - } - public func SharedMedia_Video(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[71 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notification_GameScoreExtended(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[72 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ChatList_DeleteConfirmation(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[73 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGES(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[74 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func Conversation_SelectedMessages(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[75 * 6 + Int(form.rawValue)]!, stringValue) - } - public func StickerPack_StickerCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[76 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notifications_ExceptionMuteExpires_Minutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[77 * 6 + Int(form.rawValue)]!, stringValue) - } - public func StickerPack_RemoveMaskCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[78 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Watch_LastSeen_MinutesAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[79 * 6 + Int(form.rawValue)]!, stringValue) - } - public func CreatePoll_AddMoreOptions(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[80 * 6 + Int(form.rawValue)]!, stringValue) - } - public func LiveLocation_MenuChatsCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[81 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[82 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func SharedMedia_Link(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[83 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notification_GameScoreSelfSimple(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[84 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notifications_ExceptionMuteExpires_Days(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[85 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedMessages(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[86 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Wallet_Updated_HoursAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[87 * 6 + Int(form.rawValue)]!, stringValue) - } - public func VoiceOver_Chat_PollOptionCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[88 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[3 * 6 + Int(form.rawValue)]!, stringValue) } public func Call_Seconds(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[89 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[4 * 6 + Int(form.rawValue)]!, stringValue) } - public func LastSeen_HoursAgo(_ value: Int32) -> String { + public func PUSH_CHANNEL_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[5 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func StickerPack_RemoveMaskCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[90 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[6 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedVideos(_ value: Int32) -> String { + public func ForwardedMessages(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[91 * 6 + Int(form.rawValue)]!, stringValue) - } - public func OldChannels_InactiveWeek(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[92 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Conversation_StatusOnline(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[93 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[7 * 6 + Int(form.rawValue)]!, stringValue) } public func MessageTimer_Seconds(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[94 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[8 * 6 + Int(form.rawValue)]!, stringValue) } - public func Notifications_ExceptionMuteExpires_Hours(_ value: Int32) -> String { + public func MessageTimer_Months(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[95 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[9 * 6 + Int(form.rawValue)]!, stringValue) } - public func UserCount(_ value: Int32) -> String { + public func ForwardedStickers(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[96 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[10 * 6 + Int(form.rawValue)]!, stringValue) } - public func Conversation_LiveLocationMembersCount(_ value: Int32) -> String { + public func Watch_LastSeen_HoursAgo(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[97 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[11 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_ShortDays(_ value: Int32) -> String { + public func InviteText_ContactsCountText(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[98 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[12 * 6 + Int(form.rawValue)]!, stringValue) + } + public func LastSeen_HoursAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[13 * 6 + Int(form.rawValue)]!, stringValue) + } + public func AttachmentMenu_SendPhoto(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[14 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[15 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func Notification_GameScoreSelfSimple(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[16 * 6 + Int(form.rawValue)]!, stringValue) + } + public func AttachmentMenu_SendItem(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[17 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PrivacyLastSeenSettings_AddUsers(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[18 * 6 + Int(form.rawValue)]!, stringValue) + } + public func DialogList_LiveLocationChatsCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[19 * 6 + Int(form.rawValue)]!, stringValue) + } + public func AttachmentMenu_SendVideo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[20 * 6 + Int(form.rawValue)]!, stringValue) + } + public func VoiceOver_Chat_ContactEmailCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[21 * 6 + Int(form.rawValue)]!, stringValue) + } + public func SharedMedia_DeleteItemsConfirmation(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[22 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Media_SharePhoto(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[23 * 6 + Int(form.rawValue)]!, stringValue) + } + public func OldChannels_InactiveYear(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[24 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedPhotos(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[25 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Theme_UsersCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[26 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[27 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func LastSeen_MinutesAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[28 * 6 + Int(form.rawValue)]!, stringValue) + } + public func QuickSend_Photos(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[29 * 6 + Int(form.rawValue)]!, stringValue) + } + public func VoiceOver_Chat_PollOptionCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[30 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Hours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[31 * 6 + Int(form.rawValue)]!, stringValue) } public func Conversation_StatusSubscribers(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[99 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[32 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_ShortHours(_ value: Int32) -> String { + public func OldChannels_GroupFormat(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[100 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[33 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Media_ShareItem(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[34 * 6 + Int(form.rawValue)]!, stringValue) + } + public func AttachmentMenu_SendGif(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[35 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notification_GameScoreExtended(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[36 * 6 + Int(form.rawValue)]!, stringValue) + } + public func GroupInfo_ShowMoreMembers(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[37 * 6 + Int(form.rawValue)]!, stringValue) + } + public func SharedMedia_Generic(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[38 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MuteExpires_Hours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[39 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Watch_UserInfo_Mute(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[40 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notifications_ExceptionMuteExpires_Days(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[41 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MuteExpires_Days(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[42 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Chat_DeleteMessagesConfirmation(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[43 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Call_Minutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[44 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Conversation_SelectedMessages(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[45 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortDays(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[46 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notifications_ExceptionMuteExpires_Minutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[47 * 6 + Int(form.rawValue)]!, stringValue) + } + public func LiveLocation_MenuChatsCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[48 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHAT_MESSAGE_ROUNDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[49 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func UserCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[50 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Contacts_ImportersCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[51 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedContacts(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[52 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedAudios(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[53 * 6 + Int(form.rawValue)]!, stringValue) + } + public func StickerPack_StickerCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[54 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notifications_ExceptionMuteExpires_Hours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[55 * 6 + Int(form.rawValue)]!, stringValue) + } + public func VoiceOver_Chat_ContactPhoneNumberCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[56 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortWeeks(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[57 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notifications_Exceptions(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[58 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ChatList_DeletedChats(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[59 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Call_ShortSeconds(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[60 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[61 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func Notification_GameScoreSimple(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[62 * 6 + Int(form.rawValue)]!, stringValue) + } + public func CreatePoll_AddMoreOptions(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[63 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MuteFor_Hours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[64 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notification_GameScoreSelfExtended(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[65 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Media_ShareVideo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[66 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[67 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func SharedMedia_File(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[68 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Conversation_LiveLocationMembersCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[69 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Minutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[70 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Conversation_StatusMembers(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[71 * 6 + Int(form.rawValue)]!, stringValue) + } + public func StickerPack_AddStickerCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[72 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Years(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[73 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Map_ETAMinutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[74 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedVideos(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[75 * 6 + Int(form.rawValue)]!, stringValue) + } + public func SharedMedia_Link(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[76 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessagePoll_VotedCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[77 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[78 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func Contacts_InviteContacts(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[79 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Days(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[80 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Watch_LastSeen_MinutesAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[81 * 6 + Int(form.rawValue)]!, stringValue) + } + public func SharedMedia_Photo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[82 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Wallet_Updated_HoursAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[83 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHAT_MESSAGES(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[84 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func ServiceMessage_GameScoreExtended(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[85 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Passport_Scans(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[86 * 6 + Int(form.rawValue)]!, stringValue) + } + public func GroupInfo_ParticipantCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[87 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ServiceMessage_GameScoreSelfExtended(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[88 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Call_ShortMinutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[89 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[90 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func PUSH_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[91 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func OldChannels_Leave(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[92 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[93 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func PUSH_CHAT_MESSAGE_PHOTOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[94 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func PUSH_CHANNEL_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[95 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func OldChannels_InactiveMonth(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[96 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortMinutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[97 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PasscodeSettings_FailedAttempts(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[98 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Invitation_Members(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[99 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedAuthorsOthers(_ selector: Int32, _ _0: String, _ _1: String) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[100 * 6 + Int(form.rawValue)]!, _0, _1) } public func StickerPack_RemoveStickerCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[101 * 6 + Int(form.rawValue)]!, stringValue) } - public func VoiceOver_Chat_PollVotes(_ value: Int32) -> String { + public func ServiceMessage_GameScoreSimple(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[102 * 6 + Int(form.rawValue)]!, stringValue) } - public func SharedMedia_DeleteItemsConfirmation(_ value: Int32) -> String { + public func OldChannels_InactiveWeek(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[103 * 6 + Int(form.rawValue)]!, stringValue) @@ -5198,104 +5211,105 @@ public final class PresentationStrings: Equatable { let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[104 * 6 + Int(form.rawValue)]!, stringValue) } - public func ServiceMessage_GameScoreSelfExtended(_ value: Int32) -> String { + public func ForwardedLocations(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[105 * 6 + Int(form.rawValue)]!, stringValue) } - public func Chat_DeleteMessagesConfirmation(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[106 * 6 + Int(form.rawValue)]!, stringValue) + public func PUSH_CHAT_MESSAGE_FWDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[106 * 6 + Int(form.rawValue)]!, _2, _1, _3) } - public func OldChannels_GroupFormat(_ value: Int32) -> String { + public func MessageTimer_ShortHours(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[107 * 6 + Int(form.rawValue)]!, stringValue) } - public func VoiceOver_Chat_ContactPhoneNumberCount(_ value: Int32) -> String { + public func MuteFor_Days(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[108 * 6 + Int(form.rawValue)]!, stringValue) } - public func PUSH_CHANNEL_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + public func ServiceMessage_GameScoreSelfSimple(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[109 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHAT_MESSAGE_VIDEOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[109 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func AttachmentMenu_SendGif(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[110 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_ShortWeeks(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[111 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessagePoll_VotedCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[112 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[110 * 6 + Int(form.rawValue)]!, _2, _1, _3) } public func MessageTimer_ShortSeconds(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[111 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Forward_ConfirmMultipleFiles(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[112 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ChatList_DeleteConfirmation(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[113 * 6 + Int(form.rawValue)]!, stringValue) } - public func AttachmentMenu_SendPhoto(_ value: Int32) -> String { + public func ForwardedGifs(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[114 * 6 + Int(form.rawValue)]!, stringValue) } - public func QuickSend_Photos(_ value: Int32) -> String { + public func MuteExpires_Minutes(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[115 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_Months(_ value: Int32) -> String { + public func Wallpaper_DeleteConfirmation(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[116 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedAuthorsOthers(_ selector: Int32, _ _0: String, _ _1: String) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[117 * 6 + Int(form.rawValue)]!, _0, _1) + public func LiveLocationUpdated_MinutesAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[117 * 6 + Int(form.rawValue)]!, stringValue) } - public func OldChannels_Leave(_ value: Int32) -> String { + public func VoiceOver_Chat_PollVotes(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[118 * 6 + Int(form.rawValue)]!, stringValue) } - public func Notification_GameScoreSelfExtended(_ value: Int32) -> String { + public func ChatList_SelectedChats(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[119 * 6 + Int(form.rawValue)]!, stringValue) } - public func GroupInfo_ParticipantCount(_ value: Int32) -> String { + public func MessageTimer_Weeks(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[120 * 6 + Int(form.rawValue)]!, stringValue) } - public func Contacts_InviteContacts(_ value: Int32) -> String { + public func PollResults_ShowMore(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[121 * 6 + Int(form.rawValue)]!, stringValue) } - public func PUSH_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[122 * 6 + Int(form.rawValue)]!, _1, _2) + public func ForwardedPolls(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[122 * 6 + Int(form.rawValue)]!, stringValue) } - public func ServiceMessage_GameScoreSimple(_ value: Int32) -> String { + public func SharedMedia_Video(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[123 * 6 + Int(form.rawValue)]!, stringValue) } - public func MuteExpires_Hours(_ value: Int32) -> String { + public func Map_ETAHours(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[124 * 6 + Int(form.rawValue)]!, stringValue) } - public func Conversation_StatusMembers(_ value: Int32) -> String { + public func Conversation_StatusOnline(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[125 * 6 + Int(form.rawValue)]!, stringValue) diff --git a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift index 4483315d8d..d634e990e1 100644 --- a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift +++ b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift @@ -132,7 +132,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, case sticker case location case contact - case poll + case poll(TelegramMediaPollKind) case deleted } @@ -188,8 +188,8 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, type = .location } else if let _ = media as? TelegramMediaContact { type = .contact - } else if let _ = media as? TelegramMediaPoll { - type = .poll + } else if let poll = media as? TelegramMediaPoll { + type = .poll(poll.kind) } } } else { @@ -229,8 +229,13 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, attributedString = addAttributesToStringWithRanges(strings.Notification_PinnedLocationMessage(authorName), body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, message.author?.id)])) case .contact: attributedString = addAttributesToStringWithRanges(strings.Notification_PinnedContactMessage(authorName), body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, message.author?.id)])) - case .poll: - attributedString = addAttributesToStringWithRanges(strings.Notification_PinnedPollMessage(authorName), body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, message.author?.id)])) + case let .poll(kind): + switch kind { + case .poll: + attributedString = addAttributesToStringWithRanges(strings.Notification_PinnedPollMessage(authorName), body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, message.author?.id)])) + case .quiz: + attributedString = addAttributesToStringWithRanges(strings.Notification_PinnedQuizMessage(authorName), body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, message.author?.id)])) + } case .deleted: attributedString = addAttributesToStringWithRanges(strings.PUSH_PINNED_NOTEXT(authorName), body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, message.author?.id)])) } diff --git a/submodules/TelegramUI/TelegramUI/ChatMessagePollBubbleContentNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessagePollBubbleContentNode.swift index fdd12e66a8..bdca4308d6 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessagePollBubbleContentNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessagePollBubbleContentNode.swift @@ -1018,7 +1018,7 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode { } } - if let poll = poll, poll.isClosed, case .poll = poll.kind { + if let poll = poll, poll.isClosed { typeText = item.presentationData.strings.MessagePoll_LabelClosed } else if let poll = poll { switch poll.kind { diff --git a/submodules/TelegramUI/TelegramUI/Resources/PresentationStrings.mapping b/submodules/TelegramUI/TelegramUI/Resources/PresentationStrings.mapping index 0aedd8b408bd15f8fcb7fbf646f700074a5647a2..aab4fb144de75691c1805eb292a35ee88189e6ef 100644 GIT binary patch delta 38162 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 @Kg%>4MHZ?*;1^s-$564#(hSi81f&eZtyk) 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 D3?zEm delta 37784 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 From 305f2802c83e8773876c592bab6bb3488700a6f1 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Mon, 20 Jan 2020 22:03:58 +0400 Subject: [PATCH 09/50] Fix poll update processing --- .../Sources/AccountStateManagementUtils.swift | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/submodules/TelegramCore/Sources/AccountStateManagementUtils.swift b/submodules/TelegramCore/Sources/AccountStateManagementUtils.swift index ad168e7d01..5cc2c88aa7 100644 --- a/submodules/TelegramCore/Sources/AccountStateManagementUtils.swift +++ b/submodules/TelegramCore/Sources/AccountStateManagementUtils.swift @@ -2344,29 +2344,28 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP case let .UpdateMessagePoll(pollId, apiPoll, results): if let poll = transaction.getMedia(pollId) as? TelegramMediaPoll { var updatedPoll = poll - if let apiPoll = apiPoll { - switch apiPoll { - case let .poll(id, flags, question, answers): - let publicity: TelegramMediaPollPublicity - if (flags & (1 << 1)) != 0 { - publicity = .public - } else { - publicity = .anonymous - } - let kind: TelegramMediaPollKind - if (flags & (1 << 3)) != 0 { - kind = .quiz - } else { - kind = .poll(multipleAnswers: (flags & (1 << 2)) != 0) - } - updatedPoll = TelegramMediaPoll(pollId: MediaId(namespace: Namespaces.Media.CloudPoll, id: id), publicity: publicity, kind: kind, text: question, options: answers.map(TelegramMediaPollOption.init(apiOption:)), correctAnswers: nil, results: TelegramMediaPollResults(apiResults: results), isClosed: (flags & (1 << 0)) != 0) - } - } - let resultsMin: Bool switch results { - case let .pollResults(pollResults): - resultsMin = (pollResults.flags & (1 << 0)) != 0 + case let .pollResults(pollResults): + resultsMin = (pollResults.flags & (1 << 0)) != 0 + } + if let apiPoll = apiPoll { + switch apiPoll { + case let .poll(id, flags, question, answers): + let publicity: TelegramMediaPollPublicity + if (flags & (1 << 1)) != 0 { + publicity = .public + } else { + publicity = .anonymous + } + let kind: TelegramMediaPollKind + if (flags & (1 << 3)) != 0 { + kind = .quiz + } else { + kind = .poll(multipleAnswers: (flags & (1 << 2)) != 0) + } + updatedPoll = TelegramMediaPoll(pollId: MediaId(namespace: Namespaces.Media.CloudPoll, id: id), publicity: publicity, kind: kind, text: question, options: answers.map(TelegramMediaPollOption.init(apiOption:)), correctAnswers: nil, results: poll.results, isClosed: (flags & (1 << 0)) != 0) + } } updatedPoll = updatedPoll.withUpdatedResults(TelegramMediaPollResults(apiResults: results), min: resultsMin) updateMessageMedia(transaction: transaction, id: pollId, media: updatedPoll) From 53bf42bffc03cfc0e95c5bcc2c6808b17d9df7ad Mon Sep 17 00:00:00 2001 From: Ali <> Date: Mon, 20 Jan 2020 22:04:48 +0400 Subject: [PATCH 10/50] Fix poll results cache consistency --- submodules/TelegramCore/Sources/Polls.swift | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/submodules/TelegramCore/Sources/Polls.swift b/submodules/TelegramCore/Sources/Polls.swift index 19aeb100ec..803323a618 100644 --- a/submodules/TelegramCore/Sources/Polls.swift +++ b/submodules/TelegramCore/Sources/Polls.swift @@ -196,7 +196,7 @@ private final class PollResultsOptionContext { self.count = count self.isLoadingMore = true - self.disposable.set((account.postbox.transaction { transaction -> [RenderedPeer]? in + self.disposable.set((account.postbox.transaction { transaction -> (peers: [RenderedPeer], canLoadMore: Bool)? in let cachedResult = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPollResults, key: CachedPollOptionResult.key(pollId: pollId, optionOpaqueIdentifier: opaqueIdentifier))) as? CachedPollOptionResult if let cachedResult = cachedResult, Int(cachedResult.count) == count { var result: [RenderedPeer] = [] @@ -207,19 +207,20 @@ private final class PollResultsOptionContext { return nil } } - return result + return (result, Int(cachedResult.count) > result.count) } else { return nil } } - |> deliverOn(self.queue)).start(next: { [weak self] cachedPeers in + |> deliverOn(self.queue)).start(next: { [weak self] cachedPeersAndCanLoadMore in guard let strongSelf = self else { return } strongSelf.isLoadingMore = false - if let cachedPeers = cachedPeers { + if let (cachedPeers, canLoadMore) = cachedPeersAndCanLoadMore { strongSelf.results = cachedPeers strongSelf.hasLoadedOnce = true + strongSelf.canLoadMore = canLoadMore } strongSelf.loadMore() })) From 1db4fbd241051cbe24d8ae413189f131670e0a19 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Tue, 21 Jan 2020 19:36:59 +0400 Subject: [PATCH 11/50] Upgrade message bubble graphics and introduce the ability to adjust corner radius via UI --- Telegram-iOS/en.lproj/Localizable.strings | 5 + .../Sources/AccountContext.swift | 4 +- submodules/Display/Display/ImageCorners.swift | 114 +- submodules/Display/Display/ImageNode.swift | 21 +- .../BubbleSettingsController.swift | 578 ++ .../ForwardPrivacyChatPreviewItem.swift | 6 +- .../SelectivePrivacySettingsController.swift | 12 +- .../TextSizeSelectionController.swift | 10 +- .../Sources/Themes/EditThemeController.swift | 16 +- .../Themes/ThemeAccentColorController.swift | 4 +- .../ThemeAccentColorControllerNode.swift | 7 +- .../Themes/ThemePreviewControllerNode.swift | 4 +- .../Themes/ThemeSettingsChatPreviewItem.swift | 6 +- .../Themes/ThemeSettingsController.swift | 57 +- .../Themes/ThemeSettingsFontSizeItem.swift | 14 +- .../Sources/Themes/WallpaperGalleryItem.swift | 4 +- .../Sources/ChatMessageBubbleImages.swift | 346 +- .../Sources/PresentationData.swift | 38 +- .../Sources/PresentationStrings.swift | 4724 +++++++++-------- .../Sources/PresentationTheme.swift | 4 + .../PresentationThemeEssentialGraphics.swift | 139 +- .../Sources/PresentationsResourceCache.swift | 19 + .../Resources/PresentationResourceKey.swift | 7 +- .../Resources/PresentationResourcesChat.swift | 13 +- .../TelegramUI/ChatHistoryGridNode.swift | 2 +- .../TelegramUI/ChatHistoryListNode.swift | 4 +- .../ChatMessageAnimatedStickerItemNode.swift | 2 +- .../TelegramUI/ChatMessageBackground.swift | 2 +- .../ChatMessageBubbleBackdrop.swift | 2 +- ...eBubbleContentCalclulateImageCorners.swift | 56 +- .../ChatMessageBubbleItemNode.swift | 6 +- .../ChatMessageDateAndStatusNode.swift | 2 +- .../TelegramUI/ChatMessageDateHeader.swift | 4 +- .../ChatMessageInstantVideoItemNode.swift | 2 +- .../ChatMessageInteractiveFileNode.swift | 2 +- .../TelegramUI/ChatMessageItemView.swift | 92 +- .../ChatMessageMapBubbleContentNode.swift | 4 +- .../ChatMessageMediaBubbleContentNode.swift | 6 +- .../ChatMessageStickerItemNode.swift | 2 +- .../TelegramUI/ChatPresentationData.swift | 4 +- .../ChatRecentActionsControllerNode.swift | 4 +- ...SendMessageActionSheetControllerNode.swift | 9 +- .../Resources/PresentationStrings.mapping | Bin 144339 -> 144517 bytes .../TelegramUI/SharedAccountContext.swift | 8 +- .../TelegramUI/ThemeUpdateManager.swift | 2 +- .../TelegramUI/WallpaperUploadManager.swift | 2 +- .../Sources/PresentationThemeSettings.swift | 56 +- 47 files changed, 3657 insertions(+), 2768 deletions(-) create mode 100644 submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift diff --git a/Telegram-iOS/en.lproj/Localizable.strings b/Telegram-iOS/en.lproj/Localizable.strings index 4af86fec1d..d7d634db54 100644 --- a/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram-iOS/en.lproj/Localizable.strings @@ -5291,3 +5291,8 @@ Any member of this group will be able to see messages in the channel."; "Forward.ErrorPublicQuizDisabledInChannels" = "Sorry, public polls can’t be forwarded to channels."; "Map.PlacesInThisArea" = "Places In This Area"; + +"Appearance.BubbleCornersSetting" = "Message Corners"; +"Appearance.BubbleCorners.Title" = "Message Corners"; +"Appearance.BubbleCorners.AdjustAdjacent" = "Adjust Adjacent Corners"; +"Appearance.BubbleCorners.Apply" = "Set"; diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index 063be71577..620bf03962 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -446,8 +446,8 @@ public protocol SharedAccountContext: class { func makeComposeController(context: AccountContext) -> ViewController func makeChatListController(context: AccountContext, groupId: PeerGroupId, controlsHistoryPreload: Bool, hideNetworkActivityStatus: Bool, previewing: Bool, enableDebugActions: Bool) -> ChatListController func makeChatController(context: AccountContext, chatLocation: ChatLocation, subject: ChatControllerSubject?, botStart: ChatControllerInitialBotStart?, mode: ChatControllerPresentationMode) -> ChatController - func makeChatMessagePreviewItem(context: AccountContext, message: Message, theme: PresentationTheme, strings: PresentationStrings, wallpaper: TelegramWallpaper, fontSize: PresentationFontSize, dateTimeFormat: PresentationDateTimeFormat, nameOrder: PresentationPersonNameOrder, forcedResourceStatus: FileMediaResourceStatus?, tapMessage: ((Message) -> Void)?, clickThroughMessage: (() -> Void)?) -> ListViewItem - func makeChatMessageDateHeaderItem(context: AccountContext, timestamp: Int32, theme: PresentationTheme, strings: PresentationStrings, wallpaper: TelegramWallpaper, fontSize: PresentationFontSize, dateTimeFormat: PresentationDateTimeFormat, nameOrder: PresentationPersonNameOrder) -> ListViewItemHeader + func makeChatMessagePreviewItem(context: AccountContext, message: Message, theme: PresentationTheme, strings: PresentationStrings, wallpaper: TelegramWallpaper, fontSize: PresentationFontSize, chatBubbleCorners: PresentationChatBubbleCorners, dateTimeFormat: PresentationDateTimeFormat, nameOrder: PresentationPersonNameOrder, forcedResourceStatus: FileMediaResourceStatus?, tapMessage: ((Message) -> Void)?, clickThroughMessage: (() -> Void)?) -> ListViewItem + func makeChatMessageDateHeaderItem(context: AccountContext, timestamp: Int32, theme: PresentationTheme, strings: PresentationStrings, wallpaper: TelegramWallpaper, fontSize: PresentationFontSize, chatBubbleCorners: PresentationChatBubbleCorners, dateTimeFormat: PresentationDateTimeFormat, nameOrder: PresentationPersonNameOrder) -> ListViewItemHeader func makePeerSharedMediaController(context: AccountContext, peerId: PeerId) -> ViewController? func makeContactSelectionController(_ params: ContactSelectionControllerParams) -> ContactSelectionController func makeContactMultiselectionController(_ params: ContactMultiselectionControllerParams) -> ContactMultiselectionController diff --git a/submodules/Display/Display/ImageCorners.swift b/submodules/Display/Display/ImageCorners.swift index ce45a9565a..6930a5bcf4 100644 --- a/submodules/Display/Display/ImageCorners.swift +++ b/submodules/Display/Display/ImageCorners.swift @@ -109,7 +109,6 @@ private func ==(lhs: Tail, rhs: Tail) -> Bool { } private var cachedCorners = Atomic<[Corner: DrawingContext]>(value: [:]) -private var cachedTails = Atomic<[Tail: DrawingContext]>(value: [:]) private func cornerContext(_ corner: Corner) -> DrawingContext { let cached: DrawingContext? = cachedCorners.with { @@ -148,62 +147,6 @@ private func cornerContext(_ corner: Corner) -> DrawingContext { } } -private func tailContext(_ tail: Tail) -> DrawingContext { - let cached: DrawingContext? = cachedTails.with { - return $0[tail] - } - - if let cached = cached { - return cached - } else { - let context = DrawingContext(size: CGSize(width: CGFloat(tail.radius) + 3.0, height: CGFloat(tail.radius)), clear: true) - - context.withContext { c in - c.setBlendMode(.copy) - c.setFillColor(UIColor.black.cgColor) - let rect: CGRect - switch tail { - case let .BottomLeft(radius): - rect = CGRect(origin: CGPoint(x: 3.0, y: -CGFloat(radius)), size: CGSize(width: CGFloat(radius << 1), height: CGFloat(radius << 1))) - - c.move(to: CGPoint(x: 3.0, y: 1.0)) - c.addLine(to: CGPoint(x: 3.0, y: 11.0)) - c.addLine(to: CGPoint(x: 2.3, y: 13.0)) - c.addLine(to: CGPoint(x: 0.0, y: 16.6)) - c.addLine(to: CGPoint(x: 4.5, y: 15.5)) - c.addLine(to: CGPoint(x: 6.5, y: 14.3)) - c.addLine(to: CGPoint(x: 9.0, y: 12.5)) - c.closePath() - c.fillPath() - case let .BottomRight(radius): - rect = CGRect(origin: CGPoint(x: 3.0, y: -CGFloat(radius)), size: CGSize(width: CGFloat(radius << 1), height: CGFloat(radius << 1))) - - c.translateBy(x: context.size.width / 2.0, y: context.size.height / 2.0) - c.scaleBy(x: -1.0, y: 1.0) - c.translateBy(x: -context.size.width / 2.0, y: -context.size.height / 2.0) - - c.move(to: CGPoint(x: 3.0, y: 1.0)) - c.addLine(to: CGPoint(x: 3.0, y: 11.0)) - c.addLine(to: CGPoint(x: 2.3, y: 13.0)) - c.addLine(to: CGPoint(x: 0.0, y: 16.6)) - c.addLine(to: CGPoint(x: 4.5, y: 15.5)) - c.addLine(to: CGPoint(x: 6.5, y: 14.3)) - c.addLine(to: CGPoint(x: 9.0, y: 12.5)) - c.closePath() - c.fillPath() - } - c.fillEllipse(in: rect) - } - - let _ = cachedTails.modify { current in - var current = current - current[tail] = context - return current - } - return context - } -} - public func addCorners(_ context: DrawingContext, arguments: TransformImageArguments) { let corners = arguments.corners let drawingRect = arguments.drawingRect @@ -223,23 +166,24 @@ public func addCorners(_ context: DrawingContext, arguments: TransformImageArgum let corner = cornerContext(.BottomLeft(Int(radius))) context.blt(corner, at: CGPoint(x: drawingRect.minX, y: drawingRect.maxY - radius)) } - case let .Tail(radius, enabled): + case let .Tail(radius, image): if radius > CGFloat.ulpOfOne { - if enabled { - let tail = tailContext(.BottomLeft(Int(radius))) - let color = context.colorAt(CGPoint(x: drawingRect.minX, y: drawingRect.maxY - 1.0)) - context.withContext { c in - c.clear(CGRect(x: drawingRect.minX - 3.0, y: 0.0, width: 3.0, height: drawingRect.maxY - 6.0)) - c.setFillColor(color.cgColor) - c.fill(CGRect(x: 0.0, y: drawingRect.maxY - 6.0, width: 3.0, height: 6.0)) - } - context.blt(tail, at: CGPoint(x: drawingRect.minX - 3.0, y: drawingRect.maxY - radius)) - } else { - let corner = cornerContext(.BottomLeft(Int(radius))) - context.blt(corner, at: CGPoint(x: drawingRect.minX, y: drawingRect.maxY - radius)) + let color = context.colorAt(CGPoint(x: drawingRect.minX, y: drawingRect.maxY - 1.0)) + context.withContext { c in + c.clear(CGRect(x: drawingRect.minX - 4.0, y: 0.0, width: 4.0, height: drawingRect.maxY - 6.0)) + c.setFillColor(color.cgColor) + c.fill(CGRect(x: 0.0, y: drawingRect.maxY - 6.0, width: 4.0, height: 6.0)) + c.setBlendMode(.destinationIn) + let cornerRect = CGRect(origin: CGPoint(x: drawingRect.minX - 6.0, y: drawingRect.maxY - image.size.height), size: image.size) + c.translateBy(x: cornerRect.midX, y: cornerRect.midY) + c.scaleBy(x: 1.0, y: -1.0) + c.translateBy(x: -cornerRect.midX, y: -cornerRect.midY) + c.draw(image.cgImage!, in: cornerRect) + c.translateBy(x: cornerRect.midX, y: cornerRect.midY) + c.scaleBy(x: 1.0, y: -1.0) + c.translateBy(x: -cornerRect.midX, y: -cornerRect.midY) } } - } switch corners.bottomRight { @@ -248,20 +192,22 @@ public func addCorners(_ context: DrawingContext, arguments: TransformImageArgum let corner = cornerContext(.BottomRight(Int(radius))) context.blt(corner, at: CGPoint(x: drawingRect.maxX - radius, y: drawingRect.maxY - radius)) } - case let .Tail(radius, enabled): + case let .Tail(radius, image): if radius > CGFloat.ulpOfOne { - if enabled { - let tail = tailContext(.BottomRight(Int(radius))) - let color = context.colorAt(CGPoint(x: drawingRect.maxX - 1.0, y: drawingRect.maxY - 1.0)) - context.withContext { c in - c.clear(CGRect(x: drawingRect.maxX, y: 0.0, width: 3.0, height: drawingRect.maxY - 6.0)) - c.setFillColor(color.cgColor) - c.fill(CGRect(x: drawingRect.maxX, y: drawingRect.maxY - 6.0, width: 3.0, height: 6.0)) - } - context.blt(tail, at: CGPoint(x: drawingRect.maxX - radius, y: drawingRect.maxY - radius)) - } else { - let corner = cornerContext(.BottomRight(Int(radius))) - context.blt(corner, at: CGPoint(x: drawingRect.maxX - radius, y: drawingRect.maxY - radius)) + let color = context.colorAt(CGPoint(x: drawingRect.maxX - 1.0, y: drawingRect.maxY - 1.0)) + context.withContext { c in + c.clear(CGRect(x: drawingRect.maxX, y: 0.0, width: 4.0, height: drawingRect.maxY - image.size.height)) + c.setFillColor(color.cgColor) + c.fill(CGRect(x: drawingRect.maxX, y: drawingRect.maxY - 6.0, width: 4.0, height: 6.0)) + c.setBlendMode(.destinationIn) + let cornerRect = CGRect(origin: CGPoint(x: drawingRect.maxX - image.size.width + 6.0, y: drawingRect.maxY - image.size.height), size: image.size) + c.translateBy(x: cornerRect.midX, y: cornerRect.midY) + c.scaleBy(x: 1.0, y: -1.0) + c.translateBy(x: -cornerRect.midX, y: -cornerRect.midY) + c.draw(image.cgImage!, in: cornerRect) + c.translateBy(x: cornerRect.midX, y: cornerRect.midY) + c.scaleBy(x: 1.0, y: -1.0) + c.translateBy(x: -cornerRect.midX, y: -cornerRect.midY) } } } diff --git a/submodules/Display/Display/ImageNode.swift b/submodules/Display/Display/ImageNode.swift index 99192e4895..87422abbc6 100644 --- a/submodules/Display/Display/ImageNode.swift +++ b/submodules/Display/Display/ImageNode.swift @@ -8,12 +8,12 @@ private let dispatcher = displayLinkDispatcher public enum ImageCorner: Equatable { case Corner(CGFloat) - case Tail(CGFloat, Bool) + case Tail(CGFloat, UIImage) public var extendedInsets: CGSize { switch self { case .Tail: - return CGSize(width: 3.0, height: 0.0) + return CGSize(width: 4.0, height: 0.0) default: return CGSize() } @@ -36,15 +36,6 @@ public enum ImageCorner: Equatable { return radius } } - - public func scaledBy(_ scale: CGFloat) -> ImageCorner { - switch self { - case let .Corner(radius): - return .Corner(radius * scale) - case let .Tail(radius, enabled): - return .Tail(radius * scale, enabled) - } - } } public func ==(lhs: ImageCorner, rhs: ImageCorner) -> Bool { @@ -56,8 +47,8 @@ public func ==(lhs: ImageCorner, rhs: ImageCorner) -> Bool { default: return false } - case let .Tail(lhsRadius, lhsEnabled): - if case let .Tail(rhsRadius, rhsEnabled) = rhs, lhsRadius.isEqual(to: rhsRadius), lhsEnabled == rhsEnabled { + case let .Tail(lhsRadius, lhsImage): + if case let .Tail(rhsRadius, rhsImage) = rhs, lhsRadius.isEqual(to: rhsRadius), lhsImage === rhsImage { return true } else { return false @@ -124,10 +115,6 @@ public struct ImageCorners: Equatable { public func withRemovedTails() -> ImageCorners { return ImageCorners(topLeft: self.topLeft.withoutTail, topRight: self.topRight.withoutTail, bottomLeft: self.bottomLeft.withoutTail, bottomRight: self.bottomRight.withoutTail) } - - public func scaledBy(_ scale: CGFloat) -> ImageCorners { - return ImageCorners(topLeft: self.topLeft.scaledBy(scale), topRight: self.topRight.scaledBy(scale), bottomLeft: self.bottomLeft.scaledBy(scale), bottomRight: self.bottomRight.scaledBy(scale)) - } } public func ==(lhs: ImageCorners, rhs: ImageCorners) -> Bool { diff --git a/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift b/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift new file mode 100644 index 0000000000..769aa9f3c5 --- /dev/null +++ b/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift @@ -0,0 +1,578 @@ +import Foundation +import UIKit +import Display +import Postbox +import SwiftSignalKit +import AsyncDisplayKit +import TelegramCore +import SyncCore +import TelegramPresentationData +import TelegramUIPreferences +import AccountContext +import ChatListUI +import WallpaperResources +import LegacyComponents +import ItemListUI + +private func generateMaskImage(color: UIColor) -> UIImage? { + return generateImage(CGSize(width: 1.0, height: 80.0), opaque: false, rotatedContext: { size, context in + let bounds = CGRect(origin: CGPoint(), size: size) + context.clear(bounds) + + let gradientColors = [color.withAlphaComponent(0.0).cgColor, color.cgColor, color.cgColor] as CFArray + + var locations: [CGFloat] = [0.0, 0.75, 1.0] + let colorSpace = CGColorSpaceCreateDeviceRGB() + let gradient = CGGradient(colorsSpace: colorSpace, colors: gradientColors, locations: &locations)! + + context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: 80.0), options: CGGradientDrawingOptions()) + }) +} + +private final class BubbleSettingsControllerNode: ASDisplayNode, UIScrollViewDelegate { + private let context: AccountContext + private var presentationThemeSettings: PresentationThemeSettings + private var presentationData: PresentationData + + private let referenceTimestamp: Int32 + + private let scrollNode: ASScrollNode + + private let maskNode: ASImageNode + private let chatBackgroundNode: WallpaperBackgroundNode + private let messagesContainerNode: ASDisplayNode + private var dateHeaderNode: ListViewItemHeaderNode? + private var messageNodes: [ListViewItemNode]? + private let toolbarNode: BubbleSettingsToolbarNode + + private var validLayout: (ContainerViewLayout, CGFloat)? + + init(context: AccountContext, presentationThemeSettings: PresentationThemeSettings, dismiss: @escaping () -> Void, apply: @escaping (PresentationChatBubbleSettings) -> Void) { + self.context = context + + self.presentationData = context.sharedContext.currentPresentationData.with { $0 } + self.presentationThemeSettings = presentationThemeSettings + + let calendar = Calendar(identifier: .gregorian) + var components = calendar.dateComponents(Set([.era, .year, .month, .day, .hour, .minute, .second]), from: Date()) + components.hour = 13 + components.minute = 0 + components.second = 0 + self.referenceTimestamp = Int32(calendar.date(from: components)?.timeIntervalSince1970 ?? 0.0) + + self.scrollNode = ASScrollNode() + + self.chatBackgroundNode = WallpaperBackgroundNode() + self.chatBackgroundNode.displaysAsynchronously = false + + self.messagesContainerNode = ASDisplayNode() + self.messagesContainerNode.clipsToBounds = true + self.messagesContainerNode.transform = CATransform3DMakeScale(1.0, -1.0, 1.0) + + self.chatBackgroundNode.image = chatControllerBackgroundImage(theme: self.presentationData.theme, wallpaper: self.presentationData.chatWallpaper, mediaBox: context.sharedContext.accountManager.mediaBox, knockoutMode: false) + self.chatBackgroundNode.motionEnabled = self.presentationData.chatWallpaper.settings?.motion ?? false + if case .gradient = self.presentationData.chatWallpaper { + self.chatBackgroundNode.imageContentMode = .scaleToFill + } + + self.toolbarNode = BubbleSettingsToolbarNode(presentationThemeSettings: self.presentationThemeSettings, presentationData: self.presentationData) + + self.maskNode = ASImageNode() + self.maskNode.displaysAsynchronously = false + self.maskNode.displayWithoutProcessing = true + self.maskNode.contentMode = .scaleToFill + + + super.init() + + self.setViewBlock({ + return UITracingLayerView() + }) + + self.backgroundColor = self.presentationData.theme.list.plainBackgroundColor + + self.maskNode.image = generateMaskImage(color: self.presentationData.theme.chatList.backgroundColor) + + self.addSubnode(self.scrollNode) + self.addSubnode(self.toolbarNode) + + self.scrollNode.addSubnode(self.chatBackgroundNode) + self.scrollNode.addSubnode(self.messagesContainerNode) + + self.toolbarNode.cancel = { + dismiss() + } + var dismissed = false + self.toolbarNode.done = { [weak self] in + guard let strongSelf = self else { + return + } + if !dismissed { + dismissed = true + apply(strongSelf.presentationThemeSettings.chatBubbleSettings) + } + } + self.toolbarNode.updateMergeBubbleCorners = { [weak self] value in + guard let strongSelf = self else { + return + } + strongSelf.presentationThemeSettings.chatBubbleSettings.mergeBubbleCorners = value + strongSelf.updatePresentationThemeSettings(strongSelf.presentationThemeSettings) + } + self.toolbarNode.updateCornerRadius = { [weak self] value in + guard let strongSelf = self else { + return + } + strongSelf.presentationThemeSettings.chatBubbleSettings.mainRadius = Int32(value) + strongSelf.presentationThemeSettings.chatBubbleSettings.auxiliaryRadius = Int32(value / 2) + strongSelf.updatePresentationThemeSettings(strongSelf.presentationThemeSettings) + } + } + + override func didLoad() { + super.didLoad() + + self.scrollNode.view.disablesInteractiveTransitionGestureRecognizer = true + self.scrollNode.view.showsHorizontalScrollIndicator = false + self.scrollNode.view.isPagingEnabled = true + self.scrollNode.view.delegate = self + self.scrollNode.view.alwaysBounceHorizontal = false + } + + func scrollViewDidScroll(_ scrollView: UIScrollView) { + } + + func animateIn(completion: (() -> Void)? = nil) { + if let (layout, _) = self.validLayout, case .compact = layout.metrics.widthClass { + 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 animateOut(completion: (() -> Void)? = nil) { + if let (layout, _) = self.validLayout, case .compact = layout.metrics.widthClass { + self.layer.animatePosition(from: self.layer.position, to: CGPoint(x: self.layer.position.x, y: self.layer.position.y + self.layer.bounds.size.height), duration: 0.2, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false, completion: { _ in + completion?() + }) + } else { + completion?() + } + } + + private func updateMessagesLayout(layout: ContainerViewLayout, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) { + let headerItem = self.context.sharedContext.makeChatMessageDateHeaderItem(context: self.context, timestamp: self.referenceTimestamp, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder) + + var items: [ListViewItem] = [] + let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: 1) + let otherPeerId = self.context.account.peerId + var peers = SimpleDictionary() + var messages = SimpleDictionary() + peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: []) + peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: []) + + let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3) + messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + + let message1 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66003, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message1, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil)) + + let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message2, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil)) + + let waveformBase64 = "DAAOAAkACQAGAAwADwAMABAADQAPABsAGAALAA0AGAAfABoAHgATABgAGQAYABQADAAVABEAHwANAA0ACQAWABkACQAOAAwACQAfAAAAGQAVAAAAEwATAAAACAAfAAAAHAAAABwAHwAAABcAGQAAABQADgAAABQAHwAAAB8AHwAAAAwADwAAAB8AEwAAABoAFwAAAB8AFAAAAAAAHwAAAAAAHgAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAAAA=" + let voiceAttributes: [TelegramMediaFileAttribute] = [.Audio(isVoice: true, duration: 23, title: nil, performer: nil, waveform: MemoryBuffer(data: Data(base64Encoded: waveformBase64)!))] + let voiceMedia = TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: 0, attributes: voiceAttributes) + + let message3 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: []) + items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message3, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: FileMediaResourceStatus(mediaStatus: .playbackStatus(.paused), fetchStatus: .Local), tapMessage: nil, clickThroughMessage: nil)) + + let message4 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message4, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil)) + + let width: CGFloat + if case .regular = layout.metrics.widthClass { + width = layout.size.width / 2.0 + } else { + width = layout.size.width + } + + let params = ListViewItemLayoutParams(width: width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, availableHeight: layout.size.height) + if let messageNodes = self.messageNodes { + for i in 0 ..< items.count { + let itemNode = messageNodes[i] + items[i].updateNode(async: { $0() }, node: { + return itemNode + }, params: params, previousItem: i == 0 ? nil : items[i - 1], nextItem: i == (items.count - 1) ? nil : items[i + 1], animation: .None, completion: { (layout, apply) in + let nodeFrame = CGRect(origin: itemNode.frame.origin, size: CGSize(width: width, height: layout.size.height)) + + itemNode.contentSize = layout.contentSize + itemNode.insets = layout.insets + itemNode.frame = nodeFrame + itemNode.isUserInteractionEnabled = false + + apply(ListViewItemApply(isOnScreen: true)) + }) + } + } else { + var messageNodes: [ListViewItemNode] = [] + for i in 0 ..< items.count { + var itemNode: ListViewItemNode? + items[i].nodeConfiguredForParams(async: { $0() }, params: params, synchronousLoads: false, previousItem: i == 0 ? nil : items[i - 1], nextItem: i == (items.count - 1) ? nil : items[i + 1], completion: { node, apply in + itemNode = node + apply().1(ListViewItemApply(isOnScreen: true)) + }) + itemNode!.subnodeTransform = CATransform3DMakeScale(-1.0, 1.0, 1.0) + itemNode!.isUserInteractionEnabled = false + messageNodes.append(itemNode!) + self.messagesContainerNode.addSubnode(itemNode!) + } + self.messageNodes = messageNodes + } + + var bottomOffset: CGFloat = 9.0 + bottomInset + if let messageNodes = self.messageNodes { + for itemNode in messageNodes { + transition.updateFrame(node: itemNode, frame: CGRect(origin: CGPoint(x: 0.0, y: bottomOffset), size: itemNode.frame.size)) + bottomOffset += itemNode.frame.height + itemNode.updateFrame(itemNode.frame, within: layout.size) + } + } + + let dateHeaderNode: ListViewItemHeaderNode + if let currentDateHeaderNode = self.dateHeaderNode { + dateHeaderNode = currentDateHeaderNode + headerItem.updateNode(dateHeaderNode, previous: nil, next: headerItem) + } else { + dateHeaderNode = headerItem.node() + dateHeaderNode.subnodeTransform = CATransform3DMakeScale(-1.0, 1.0, 1.0) + self.messagesContainerNode.addSubnode(dateHeaderNode) + self.dateHeaderNode = dateHeaderNode + } + + transition.updateFrame(node: dateHeaderNode, frame: CGRect(origin: CGPoint(x: 0.0, y: bottomOffset), size: CGSize(width: layout.size.width, height: headerItem.height))) + dateHeaderNode.updateLayout(size: self.messagesContainerNode.frame.size, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right) + } + + func updatePresentationThemeSettings(_ presentationThemeSettings: PresentationThemeSettings) { + let chatBubbleCorners = PresentationChatBubbleCorners(mainRadius: CGFloat(presentationThemeSettings.chatBubbleSettings.mainRadius), auxiliaryRadius: CGFloat(presentationThemeSettings.chatBubbleSettings.auxiliaryRadius), mergeBubbleCorners: presentationThemeSettings.chatBubbleSettings.mergeBubbleCorners) + + self.presentationData = self.presentationData.withChatBubbleCorners(chatBubbleCorners) + self.toolbarNode.updatePresentationData(presentationData: self.presentationData) + self.toolbarNode.updatePresentationThemeSettings(presentationThemeSettings: self.presentationThemeSettings) + if let (layout, navigationBarHeight) = self.validLayout { + self.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate) + self.recursivelyEnsureDisplaySynchronously(true) + } + } + + func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) { + self.validLayout = (layout, navigationBarHeight) + + let bounds = CGRect(origin: CGPoint(), size: layout.size) + self.scrollNode.frame = bounds + + let toolbarHeight = self.toolbarNode.updateLayout(width: layout.size.width, bottomInset: layout.intrinsicInsets.bottom, layout: layout, transition: transition) + + var chatFrame = CGRect(x: 0.0, y: 0.0, width: bounds.width, height: bounds.height) + + let bottomInset: CGFloat + chatFrame = CGRect(x: 0.0, y: 0.0, width: bounds.width, height: bounds.height) + self.scrollNode.view.contentSize = CGSize(width: bounds.width, height: bounds.height) + + bottomInset = 37.0 + + self.chatBackgroundNode.frame = chatFrame + self.chatBackgroundNode.updateLayout(size: chatFrame.size, transition: transition) + self.messagesContainerNode.frame = chatFrame + + transition.updateFrame(node: self.toolbarNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - toolbarHeight), size: CGSize(width: layout.size.width, height: toolbarHeight + layout.intrinsicInsets.bottom))) + + self.updateMessagesLayout(layout: layout, bottomInset: toolbarHeight + bottomInset, transition: transition) + + transition.updateFrame(node: self.maskNode, frame: CGRect(x: 0.0, y: layout.size.height - toolbarHeight - 80.0, width: bounds.width, height: 80.0)) + } +} + +final class BubbleSettingsController: ViewController { + private let context: AccountContext + + private var controllerNode: BubbleSettingsControllerNode { + return self.displayNode as! BubbleSettingsControllerNode + } + + private var didPlayPresentationAnimation = false + + private var presentationData: PresentationData + private var presentationDataDisposable: Disposable? + + private var presentationThemeSettings: PresentationThemeSettings + private var presentationThemeSettingsDisposable: Disposable? + + private var disposable: Disposable? + private var applyDisposable = MetaDisposable() + + public init(context: AccountContext, presentationThemeSettings: PresentationThemeSettings) { + self.context = context + + self.presentationData = context.sharedContext.currentPresentationData.with { $0 } + self.presentationThemeSettings = presentationThemeSettings + + super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationTheme: self.presentationData.theme, presentationStrings: self.presentationData.strings)) + + self.blocksBackgroundWhenInOverlay = true + self.navigationPresentation = .modal + + self.navigationItem.title = self.presentationData.strings.Appearance_BubbleCorners_Title + self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: UIView()) + + self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style + self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait) + + self.presentationDataDisposable = (context.sharedContext.presentationData + |> deliverOnMainQueue).start(next: { [weak self] presentationData in + if let strongSelf = self { + strongSelf.presentationData = presentationData + } + }) + } + + required public init(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + deinit { + self.presentationDataDisposable?.dispose() + self.presentationThemeSettingsDisposable?.dispose() + self.disposable?.dispose() + self.applyDisposable.dispose() + } + + override public func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + if let presentationArguments = self.presentationArguments as? ViewControllerPresentationArguments, !self.didPlayPresentationAnimation { + self.didPlayPresentationAnimation = true + if case .modalSheet = presentationArguments.presentationAnimation { + self.controllerNode.animateIn() + } + } + } + + override public func loadDisplayNode() { + super.loadDisplayNode() + + self.displayNode = BubbleSettingsControllerNode(context: self.context, presentationThemeSettings: self.presentationThemeSettings, dismiss: { [weak self] in + if let strongSelf = self { + strongSelf.dismiss() + } + }, apply: { [weak self] chatBubbleSettings in + if let strongSelf = self { + strongSelf.apply(chatBubbleSettings: chatBubbleSettings) + } + }) + self.displayNodeDidLoad() + } + + private func apply(chatBubbleSettings: PresentationChatBubbleSettings) { + let _ = (updatePresentationThemeSettingsInteractively(accountManager: self.context.sharedContext.accountManager, { current in + var current = current + current.chatBubbleSettings = chatBubbleSettings + return current + }) + |> deliverOnMainQueue).start(completed: { [weak self] in + self?.dismiss() + }) + } + + override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { + super.containerLayoutUpdated(layout, transition: transition) + + self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: self.navigationHeight, transition: transition) + } +} + +private enum TextSelectionCustomMode { + case list + case chat +} + +private final class BubbleSettingsToolbarNode: ASDisplayNode { + private var presentationThemeSettings: PresentationThemeSettings + private var presentationData: PresentationData + + private let cancelButton = HighlightableButtonNode() + private let doneButton = HighlightableButtonNode() + private let separatorNode = ASDisplayNode() + private let topSeparatorNode = ASDisplayNode() + + private var switchItemNode: ItemListSwitchItemNode + private var cornerRadiusItemNode: ThemeSettingsFontSizeItemNode + + private(set) var customMode: TextSelectionCustomMode = .chat + + var cancel: (() -> Void)? + var done: (() -> Void)? + + var updateMergeBubbleCorners: ((Bool) -> Void)? + var updateCornerRadius: ((Int32) -> Void)? + + init(presentationThemeSettings: PresentationThemeSettings, presentationData: PresentationData) { + self.presentationThemeSettings = presentationThemeSettings + self.presentationData = presentationData + + self.switchItemNode = ItemListSwitchItemNode(type: .regular) + self.cornerRadiusItemNode = ThemeSettingsFontSizeItemNode() + + super.init() + + self.addSubnode(self.switchItemNode) + self.addSubnode(self.cornerRadiusItemNode) + self.addSubnode(self.cancelButton) + self.addSubnode(self.doneButton) + self.addSubnode(self.separatorNode) + self.addSubnode(self.topSeparatorNode) + + self.updatePresentationData(presentationData: self.presentationData) + + self.cancelButton.highligthedChanged = { [weak self] highlighted in + if let strongSelf = self { + if highlighted { + strongSelf.cancelButton.backgroundColor = strongSelf.presentationData.theme.list.itemHighlightedBackgroundColor + } else { + UIView.animate(withDuration: 0.3, animations: { + strongSelf.cancelButton.backgroundColor = .clear + }) + } + } + } + + self.doneButton.highligthedChanged = { [weak self] highlighted in + if let strongSelf = self { + if highlighted { + strongSelf.doneButton.backgroundColor = strongSelf.presentationData.theme.list.itemHighlightedBackgroundColor + } else { + UIView.animate(withDuration: 0.3, animations: { + strongSelf.doneButton.backgroundColor = .clear + }) + } + } + } + + self.cancelButton.addTarget(self, action: #selector(self.cancelPressed), forControlEvents: .touchUpInside) + self.doneButton.addTarget(self, action: #selector(self.donePressed), forControlEvents: .touchUpInside) + } + + func setDoneEnabled(_ enabled: Bool) { + self.doneButton.alpha = enabled ? 1.0 : 0.4 + self.doneButton.isUserInteractionEnabled = enabled + } + + func setCustomMode(_ customMode: TextSelectionCustomMode) { + self.customMode = customMode + } + + func updatePresentationData(presentationData: PresentationData) { + self.backgroundColor = presentationData.theme.rootController.tabBar.backgroundColor + self.separatorNode.backgroundColor = presentationData.theme.rootController.tabBar.separatorColor + self.topSeparatorNode.backgroundColor = presentationData.theme.rootController.tabBar.separatorColor + + self.cancelButton.setTitle(presentationData.strings.Common_Cancel, with: Font.regular(17.0), with: presentationData.theme.list.itemPrimaryTextColor, for: []) + self.doneButton.setTitle(presentationData.strings.Wallpaper_Set, with: Font.regular(17.0), with: presentationData.theme.list.itemPrimaryTextColor, for: []) + } + + func updatePresentationThemeSettings(presentationThemeSettings: PresentationThemeSettings) { + self.presentationThemeSettings = presentationThemeSettings + } + + func updateLayout(width: CGFloat, bottomInset: CGFloat, layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) -> CGFloat { + var contentHeight: CGFloat = 0.0 + + let switchItem = ItemListSwitchItem(presentationData: ItemListPresentationData(self.presentationData), title: self.presentationData.strings.Appearance_BubbleCorners_AdjustAdjacent, value: self.presentationThemeSettings.chatBubbleSettings.mergeBubbleCorners, disableLeadingInset: true, sectionId: 0, style: .blocks, updated: { [weak self] value in + self?.updateMergeBubbleCorners?(value) + }) + let fontSize: PresentationFontSize + switch Int(self.presentationData.chatBubbleCorners.mainRadius) { + case 4: + fontSize = .extraSmall + case 6: + fontSize = .small + case 8: + fontSize = .medium + case 10: + fontSize = .regular + case 12: + fontSize = .large + case 14: + fontSize = .extraLarge + case 16: + fontSize = .extraLargeX2 + default: + fontSize = .extraLargeX2 + } + let cornerRadiusItem = ThemeSettingsFontSizeItem(theme: self.presentationData.theme, fontSize: fontSize, enabled: true, disableLeadingInset: false, displayIcons: false, force: false, sectionId: 0, updated: { [weak self] value in + let numericValue: Int32 + switch value { + case .extraSmall: + numericValue = 4 + case .small: + numericValue = 6 + case .medium: + numericValue = 8 + case .regular: + numericValue = 10 + case .large: + numericValue = 12 + case .extraLarge: + numericValue = 14 + case .extraLargeX2: + numericValue = 16 + } + self?.updateCornerRadius?(numericValue) + }) + + /*switchItem.updateNode(async: { f in + f() + }, node: { + return self.switchItemNode + }, params: ListViewItemLayoutParams(width: width, leftInset: layout.intrinsicInsets.left, rightInset: layout.intrinsicInsets.right, availableHeight: 1000.0), previousItem: nil, nextItem: cornerRadiusItem, animation: .None, completion: { layout, apply in + self.switchItemNode.contentSize = layout.contentSize + self.switchItemNode.insets = layout.insets + transition.updateFrame(node: self.switchItemNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: layout.contentSize)) + contentHeight += layout.contentSize.height + apply(ListViewItemApply(isOnScreen: true)) + })*/ + + cornerRadiusItem.updateNode(async: { f in + f() + }, node: { + return self.cornerRadiusItemNode + }, params: ListViewItemLayoutParams(width: width, leftInset: layout.intrinsicInsets.left, rightInset: layout.intrinsicInsets.right, availableHeight: 1000.0), previousItem: switchItem, nextItem: nil, animation: .None, completion: { layout, apply in + self.cornerRadiusItemNode.contentSize = layout.contentSize + self.cornerRadiusItemNode.insets = layout.insets + transition.updateFrame(node: self.cornerRadiusItemNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: layout.contentSize)) + contentHeight += layout.contentSize.height + apply(ListViewItemApply(isOnScreen: true)) + }) + + self.cancelButton.frame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: floor(width / 2.0), height: 49.0)) + self.doneButton.frame = CGRect(origin: CGPoint(x: floor(width / 2.0), y: contentHeight), size: CGSize(width: width - floor(width / 2.0), height: 49.0)) + + contentHeight += 49.0 + + self.topSeparatorNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: width, height: UIScreenPixel)) + + let resultHeight = contentHeight + bottomInset + + self.separatorNode.frame = CGRect(origin: CGPoint(x: floor(width / 2.0), y: self.cancelButton.frame.minY), size: CGSize(width: UIScreenPixel, height: resultHeight - self.cancelButton.frame.minY)) + + return resultHeight + } + + @objc func cancelPressed() { + self.cancel?() + } + + @objc func donePressed() { + self.doneButton.isUserInteractionEnabled = false + self.done?() + } +} diff --git a/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift b/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift index dfdba0d1ea..ccc324d7ef 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift @@ -18,6 +18,7 @@ class ForwardPrivacyChatPreviewItem: ListViewItem, ItemListItem { let strings: PresentationStrings let sectionId: ItemListSectionId let fontSize: PresentationFontSize + let chatBubbleCorners: PresentationChatBubbleCorners let wallpaper: TelegramWallpaper let dateTimeFormat: PresentationDateTimeFormat let nameDisplayOrder: PresentationPersonNameOrder @@ -25,12 +26,13 @@ class ForwardPrivacyChatPreviewItem: ListViewItem, ItemListItem { let linkEnabled: Bool let 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) { + init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, sectionId: ItemListSectionId, fontSize: PresentationFontSize, chatBubbleCorners: PresentationChatBubbleCorners, wallpaper: TelegramWallpaper, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, peerName: String, linkEnabled: Bool, tooltipText: String) { self.context = context self.theme = theme self.strings = strings self.sectionId = sectionId self.fontSize = fontSize + self.chatBubbleCorners = chatBubbleCorners self.wallpaper = wallpaper self.dateTimeFormat = dateTimeFormat self.nameDisplayOrder = nameDisplayOrder @@ -157,7 +159,7 @@ class ForwardPrivacyChatPreviewItemNode: ListViewItemNode { let forwardInfo = MessageForwardInfo(author: item.linkEnabled ? peers[peerId] : nil, source: nil, sourceMessageId: nil, date: 0, authorSignature: item.linkEnabled ? nil : item.peerName) - let messageItem = item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, message: Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: forwardInfo, author: nil, text: item.strings.Privacy_Forwards_PreviewMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), theme: item.theme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil) + let messageItem = item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, message: Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: forwardInfo, author: nil, text: item.strings.Privacy_Forwards_PreviewMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), theme: item.theme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil) var node: ListViewItemNode? if let current = currentNode { diff --git a/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsController.swift b/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsController.swift index 1a89bcca3c..3c7774bcc4 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsController.swift @@ -87,7 +87,7 @@ private func stringForUserCount(_ peers: [PeerId: SelectivePrivacyPeer], strings private enum SelectivePrivacySettingsEntry: ItemListNodeEntry { case forwardsPreviewHeader(PresentationTheme, String) - case forwardsPreview(PresentationTheme, TelegramWallpaper, PresentationFontSize, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, String, Bool, String) + case forwardsPreview(PresentationTheme, TelegramWallpaper, PresentationFontSize, PresentationChatBubbleCorners, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, String, Bool, String) case settingHeader(PresentationTheme, String) case everybody(PresentationTheme, String, Bool) case contacts(PresentationTheme, String, Bool) @@ -194,8 +194,8 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry { } else { return false } - 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 { + case let .forwardsPreview(lhsTheme, lhsWallpaper, lhsFontSize, lhsChatBubbleCorners, lhsStrings, lhsTimeFormat, lhsNameOrder, lhsPeerName, lhsLinkEnabled, lhsTooltipText): + if case let .forwardsPreview(rhsTheme, rhsWallpaper, rhsFontSize, rhsChatBubbleCorners, rhsStrings, rhsTimeFormat, rhsNameOrder, rhsPeerName, rhsLinkEnabled, rhsTooltipText) = rhs, lhsTheme === rhsTheme, lhsWallpaper == rhsWallpaper, lhsFontSize == rhsFontSize, lhsChatBubbleCorners == rhsChatBubbleCorners, lhsStrings === rhsStrings, lhsTimeFormat == rhsTimeFormat, lhsNameOrder == rhsNameOrder, lhsPeerName == rhsPeerName, lhsLinkEnabled == rhsLinkEnabled, lhsTooltipText == rhsTooltipText { return true } else { return false @@ -350,8 +350,8 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry { switch self { case let .forwardsPreviewHeader(theme, text): return ItemListSectionHeaderItem(presentationData: presentationData, text: text, multiline: true, sectionId: self.section) - 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 .forwardsPreview(theme, wallpaper, fontSize, chatBubbleCorners, strings, dateTimeFormat, nameDisplayOrder, peerName, linkEnabled, tooltipText): + return ForwardPrivacyChatPreviewItem(context: arguments.context, theme: theme, strings: strings, sectionId: self.section, fontSize: fontSize, chatBubbleCorners: chatBubbleCorners, wallpaper: wallpaper, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, peerName: peerName, linkEnabled: linkEnabled, tooltipText: tooltipText) case let .settingHeader(theme, text): return ItemListSectionHeaderItem(presentationData: presentationData, text: text, multiline: true, sectionId: self.section) case let .everybody(theme, text, value): @@ -591,7 +591,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.chatFontSize, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, peerName, linkEnabled, tootipText)) + entries.append(.forwardsPreview(presentationData.theme, presentationData.chatWallpaper, presentationData.chatFontSize, presentationData.chatBubbleCorners, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, peerName, linkEnabled, tootipText)) } entries.append(.settingHeader(presentationData.theme, settingTitle)) diff --git a/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift b/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift index 20a23a462b..675dc81df5 100644 --- a/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift +++ b/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift @@ -303,7 +303,7 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView } private func updateMessagesLayout(layout: ContainerViewLayout, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) { - let headerItem = self.context.sharedContext.makeChatMessageDateHeaderItem(context: self.context, timestamp: self.referenceTimestamp, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder) + let headerItem = self.context.sharedContext.makeChatMessageDateHeaderItem(context: self.context, timestamp: self.referenceTimestamp, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder) var items: [ListViewItem] = [] let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: 1) @@ -317,20 +317,20 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) let message1 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66003, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) - items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message1, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil)) + items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message1, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil)) let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) - items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message2, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil)) + items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message2, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil)) let waveformBase64 = "DAAOAAkACQAGAAwADwAMABAADQAPABsAGAALAA0AGAAfABoAHgATABgAGQAYABQADAAVABEAHwANAA0ACQAWABkACQAOAAwACQAfAAAAGQAVAAAAEwATAAAACAAfAAAAHAAAABwAHwAAABcAGQAAABQADgAAABQAHwAAAB8AHwAAAAwADwAAAB8AEwAAABoAFwAAAB8AFAAAAAAAHwAAAAAAHgAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAAAA=" let voiceAttributes: [TelegramMediaFileAttribute] = [.Audio(isVoice: true, duration: 23, title: nil, performer: nil, waveform: MemoryBuffer(data: Data(base64Encoded: waveformBase64)!))] let voiceMedia = TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: 0, attributes: voiceAttributes) let message3 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: []) - items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message3, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: FileMediaResourceStatus(mediaStatus: .playbackStatus(.paused), fetchStatus: .Local), tapMessage: nil, clickThroughMessage: nil)) + items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message3, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: FileMediaResourceStatus(mediaStatus: .playbackStatus(.paused), fetchStatus: .Local), tapMessage: nil, clickThroughMessage: nil)) let message4 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) - items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message4, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil)) + items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message4, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil)) let width: CGFloat if case .regular = layout.metrics.widthClass { diff --git a/submodules/SettingsUI/Sources/Themes/EditThemeController.swift b/submodules/SettingsUI/Sources/Themes/EditThemeController.swift index b918e65d1a..f85e96e5ce 100644 --- a/submodules/SettingsUI/Sources/Themes/EditThemeController.swift +++ b/submodules/SettingsUI/Sources/Themes/EditThemeController.swift @@ -53,7 +53,7 @@ private enum EditThemeControllerEntry: ItemListNodeEntry { case slug(PresentationTheme, PresentationStrings, String, String, Bool) case slugInfo(PresentationTheme, String) case chatPreviewHeader(PresentationTheme, String) - case chatPreview(PresentationTheme, PresentationTheme, TelegramWallpaper, PresentationFontSize, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, [ChatPreviewMessageItem]) + case chatPreview(PresentationTheme, PresentationTheme, TelegramWallpaper, PresentationFontSize, PresentationChatBubbleCorners, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, [ChatPreviewMessageItem]) case changeColors(PresentationTheme, String) case uploadTheme(PresentationTheme, String) case uploadInfo(PresentationTheme, String) @@ -114,8 +114,8 @@ private enum EditThemeControllerEntry: ItemListNodeEntry { } else { return false } - case let .chatPreview(lhsTheme, lhsComponentTheme, lhsWallpaper, lhsFontSize, lhsStrings, lhsTimeFormat, lhsNameOrder, lhsItems): - if case let .chatPreview(rhsTheme, rhsComponentTheme, rhsWallpaper, rhsFontSize, rhsStrings, rhsTimeFormat, rhsNameOrder, rhsItems) = rhs, lhsComponentTheme === rhsComponentTheme, lhsTheme === rhsTheme, lhsWallpaper == rhsWallpaper, lhsFontSize == rhsFontSize, lhsStrings === rhsStrings, lhsTimeFormat == rhsTimeFormat, lhsNameOrder == rhsNameOrder, lhsItems == rhsItems { + case let .chatPreview(lhsTheme, lhsComponentTheme, lhsWallpaper, lhsFontSize, lhsChatBubbleCorners, lhsStrings, lhsTimeFormat, lhsNameOrder, lhsItems): + if case let .chatPreview(rhsTheme, rhsComponentTheme, rhsWallpaper, rhsFontSize, rhsChatBubbleCorners, rhsStrings, rhsTimeFormat, rhsNameOrder, rhsItems) = rhs, lhsComponentTheme === rhsComponentTheme, lhsTheme === rhsTheme, lhsWallpaper == rhsWallpaper, lhsFontSize == rhsFontSize, lhsChatBubbleCorners == rhsChatBubbleCorners, lhsStrings === rhsStrings, lhsTimeFormat == rhsTimeFormat, lhsNameOrder == rhsNameOrder, lhsItems == rhsItems { return true } else { return false @@ -172,8 +172,8 @@ private enum EditThemeControllerEntry: ItemListNodeEntry { return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section) case let .chatPreviewHeader(theme, text): return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) - case let .chatPreview(theme, componentTheme, wallpaper, fontSize, strings, dateTimeFormat, nameDisplayOrder, items): - return ThemeSettingsChatPreviewItem(context: arguments.context, theme: theme, componentTheme: componentTheme, strings: strings, sectionId: self.section, fontSize: fontSize, wallpaper: wallpaper, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, messageItems: items) + case let .chatPreview(theme, componentTheme, wallpaper, fontSize, chatBubbleCorners, strings, dateTimeFormat, nameDisplayOrder, items): + return ThemeSettingsChatPreviewItem(context: arguments.context, theme: theme, componentTheme: componentTheme, strings: strings, sectionId: self.section, fontSize: fontSize, chatBubbleCorners: chatBubbleCorners, wallpaper: wallpaper, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, messageItems: items) case let .changeColors(theme, text): return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: { arguments.openColors() @@ -253,7 +253,7 @@ private func editThemeControllerEntries(presentationData: PresentationData, stat entries.append(.slugInfo(presentationData.theme, infoText)) entries.append(.chatPreviewHeader(presentationData.theme, presentationData.strings.EditTheme_Preview.uppercased())) - entries.append(.chatPreview(presentationData.theme, previewTheme, previewTheme.chat.defaultWallpaper, presentationData.chatFontSize, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, [ChatPreviewMessageItem(outgoing: false, reply: (previewIncomingReplyName, previewIncomingReplyText), text: previewIncomingText), ChatPreviewMessageItem(outgoing: true, reply: nil, text: previewOutgoingText)])) + entries.append(.chatPreview(presentationData.theme, previewTheme, previewTheme.chat.defaultWallpaper, presentationData.chatFontSize, presentationData.chatBubbleCorners, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, [ChatPreviewMessageItem(outgoing: false, reply: (previewIncomingReplyName, previewIncomingReplyText), text: previewIncomingText), ChatPreviewMessageItem(outgoing: true, reply: nil, text: previewOutgoingText)])) entries.append(.changeColors(presentationData.theme, presentationData.strings.EditTheme_ChangeColors)) if !hasSettings { @@ -556,7 +556,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers themeSpecificChatWallpapers[themeReference.index] = nil - return PresentationThemeSettings(theme: themeReference, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) + return PresentationThemeSettings(theme: themeReference, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) }) |> deliverOnMainQueue).start(completed: { if !hasCustomFile { saveThemeTemplateFile(state.title, themeResource, { @@ -590,7 +590,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers themeSpecificChatWallpapers[themeReference.index] = nil - return PresentationThemeSettings(theme: themeReference, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) + return PresentationThemeSettings(theme: themeReference, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) }) |> deliverOnMainQueue).start(completed: { if let themeResource = themeResource, !hasCustomFile { saveThemeTemplateFile(state.title, themeResource, { diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift index 503d9005d3..21c9950124 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift @@ -276,7 +276,7 @@ final class ThemeAccentColorController: ViewController { var themeSpecificAccentColors = current.themeSpecificAccentColors themeSpecificAccentColors[baseThemeReference.index] = PresentationThemeAccentColor(themeIndex: themeReference.index) - return PresentationThemeSettings(theme: updatedTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, automaticThemeSwitchSetting: updatedAutomaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) + return PresentationThemeSettings(theme: updatedTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: updatedAutomaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) }) |> castError(CreateThemeError.self) } else { @@ -305,7 +305,7 @@ final class ThemeAccentColorController: ViewController { var themeSpecificAccentColors = current.themeSpecificAccentColors themeSpecificAccentColors[baseThemeReference.index] = PresentationThemeAccentColor(themeIndex: themeReference.index) - return PresentationThemeSettings(theme: updatedTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, automaticThemeSwitchSetting: updatedAutomaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) + return PresentationThemeSettings(theme: updatedTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: updatedAutomaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) }) |> castError(CreateThemeError.self) } else { diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift index beef472dec..57916acc46 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift @@ -226,6 +226,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate self.presentationData = context.sharedContext.currentPresentationData.with { $0 } self.theme = theme self.wallpaper = self.presentationData.chatWallpaper + let bubbleCorners = self.presentationData.chatBubbleCorners self.ready = ready @@ -498,7 +499,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate updatedTheme = theme } - let _ = PresentationResourcesChat.principalGraphics(mediaBox: context.account.postbox.mediaBox, knockoutWallpaper: context.sharedContext.immediateExperimentalUISettings.knockoutWallpaper, theme: updatedTheme!, wallpaper: wallpaper) + let _ = PresentationResourcesChat.principalGraphics(mediaBox: context.account.postbox.mediaBox, knockoutWallpaper: context.sharedContext.immediateExperimentalUISettings.knockoutWallpaper, theme: updatedTheme!, wallpaper: wallpaper, bubbleCorners: bubbleCorners) } else { updatedTheme = nil } @@ -836,7 +837,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate } private func updateMessagesLayout(layout: ContainerViewLayout, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) { - let headerItem = self.context.sharedContext.makeChatMessageDateHeaderItem(context: self.context, timestamp: self.referenceTimestamp, theme: self.theme, strings: self.presentationData.strings, wallpaper: self.wallpaper, fontSize: self.presentationData.chatFontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder) + let headerItem = self.context.sharedContext.makeChatMessageDateHeaderItem(context: self.context, timestamp: self.referenceTimestamp, theme: self.theme, strings: self.presentationData.strings, wallpaper: self.wallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder) var items: [ListViewItem] = [] let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: 1) @@ -878,7 +879,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate sampleMessages.append(message8) items = sampleMessages.reversed().map { message in - let item = self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message, theme: self.theme, strings: self.presentationData.strings, wallpaper: self.wallpaper, fontSize: self.presentationData.chatFontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: !message.media.isEmpty ? FileMediaResourceStatus(mediaStatus: .playbackStatus(.paused), fetchStatus: .Local) : nil, tapMessage: { [weak self] message in + let item = self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message, theme: self.theme, strings: self.presentationData.strings, wallpaper: self.wallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: !message.media.isEmpty ? FileMediaResourceStatus(mediaStatus: .playbackStatus(.paused), fetchStatus: .Local) : nil, tapMessage: { [weak self] message in if message.flags.contains(.Incoming) { self?.updateSection(.accent) self?.requestSectionUpdate?(.accent) diff --git a/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift index b4b5cbaf2f..469477a0d6 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift @@ -442,7 +442,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate { } private func updateMessagesLayout(layout: ContainerViewLayout, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) { - let headerItem = self.context.sharedContext.makeChatMessageDateHeaderItem(context: self.context, timestamp: self.referenceTimestamp, theme: self.previewTheme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder) + let headerItem = self.context.sharedContext.makeChatMessageDateHeaderItem(context: self.context, timestamp: self.referenceTimestamp, theme: self.previewTheme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder) var items: [ListViewItem] = [] let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: 1) @@ -484,7 +484,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate { sampleMessages.append(message8) items = sampleMessages.reversed().map { message in - self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message, theme: self.previewTheme, strings: self.presentationData.strings, wallpaper: self.previewTheme.chat.defaultWallpaper, fontSize: self.presentationData.chatFontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: !message.media.isEmpty ? FileMediaResourceStatus(mediaStatus: .playbackStatus(.paused), fetchStatus: .Local) : nil, tapMessage: nil, clickThroughMessage: nil) + self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message, theme: self.previewTheme, strings: self.presentationData.strings, wallpaper: self.previewTheme.chat.defaultWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: !message.media.isEmpty ? FileMediaResourceStatus(mediaStatus: .playbackStatus(.paused), fetchStatus: .Local) : nil, tapMessage: nil, clickThroughMessage: nil) } let width: CGFloat diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift index 4a2a1361ad..47b4bbda37 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift @@ -40,18 +40,20 @@ class ThemeSettingsChatPreviewItem: ListViewItem, ItemListItem { let strings: PresentationStrings let sectionId: ItemListSectionId let fontSize: PresentationFontSize + let chatBubbleCorners: PresentationChatBubbleCorners let wallpaper: TelegramWallpaper let dateTimeFormat: PresentationDateTimeFormat let nameDisplayOrder: PresentationPersonNameOrder let messageItems: [ChatPreviewMessageItem] - init(context: AccountContext, theme: PresentationTheme, componentTheme: PresentationTheme, strings: PresentationStrings, sectionId: ItemListSectionId, fontSize: PresentationFontSize, wallpaper: TelegramWallpaper, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, messageItems: [ChatPreviewMessageItem]) { + init(context: AccountContext, theme: PresentationTheme, componentTheme: PresentationTheme, strings: PresentationStrings, sectionId: ItemListSectionId, fontSize: PresentationFontSize, chatBubbleCorners: PresentationChatBubbleCorners, wallpaper: TelegramWallpaper, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, messageItems: [ChatPreviewMessageItem]) { self.context = context self.theme = theme self.componentTheme = componentTheme self.strings = strings self.sectionId = sectionId self.fontSize = fontSize + self.chatBubbleCorners = chatBubbleCorners self.wallpaper = wallpaper self.dateTimeFormat = dateTimeFormat self.nameDisplayOrder = nameDisplayOrder @@ -163,7 +165,7 @@ class ThemeSettingsChatPreviewItemNode: ListViewItemNode { } let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: messageItem.outgoing ? otherPeerId : peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: messageItem.outgoing ? TelegramUser(id: otherPeerId, accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: []) : nil, text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId)] : [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) - items.append(item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, message: message, theme: item.componentTheme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil)) + items.append(item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, message: message, theme: item.componentTheme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil)) } var nodes: [ListViewItemNode] = [] diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift index d45c21762c..6f8357dfba 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift @@ -76,6 +76,7 @@ private final class ThemeSettingsControllerArguments { let openAccentColorPicker: (PresentationThemeReference, Bool) -> Void let openAutoNightTheme: () -> Void let openTextSize: () -> Void + let openBubbleSettings: () -> Void let toggleLargeEmoji: (Bool) -> Void let disableAnimations: (Bool) -> Void let selectAppIcon: (String) -> Void @@ -83,7 +84,7 @@ private final class ThemeSettingsControllerArguments { let themeContextAction: (Bool, PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void let colorContextAction: (Bool, PresentationThemeReference, ThemeSettingsColorOption?, ASDisplayNode, ContextGesture?) -> Void - init(context: AccountContext, selectTheme: @escaping (PresentationThemeReference) -> Void, selectFontSize: @escaping (PresentationFontSize) -> Void, openWallpaperSettings: @escaping () -> Void, selectAccentColor: @escaping (PresentationThemeAccentColor?) -> Void, openAccentColorPicker: @escaping (PresentationThemeReference, Bool) -> Void, openAutoNightTheme: @escaping () -> Void, openTextSize: @escaping () -> Void, toggleLargeEmoji: @escaping (Bool) -> Void, disableAnimations: @escaping (Bool) -> Void, selectAppIcon: @escaping (String) -> Void, editTheme: @escaping (PresentationCloudTheme) -> Void, themeContextAction: @escaping (Bool, PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void, colorContextAction: @escaping (Bool, PresentationThemeReference, ThemeSettingsColorOption?, ASDisplayNode, ContextGesture?) -> Void) { + init(context: AccountContext, selectTheme: @escaping (PresentationThemeReference) -> Void, selectFontSize: @escaping (PresentationFontSize) -> Void, openWallpaperSettings: @escaping () -> Void, selectAccentColor: @escaping (PresentationThemeAccentColor?) -> Void, openAccentColorPicker: @escaping (PresentationThemeReference, Bool) -> Void, openAutoNightTheme: @escaping () -> Void, openTextSize: @escaping () -> Void, openBubbleSettings: @escaping () -> Void, toggleLargeEmoji: @escaping (Bool) -> Void, disableAnimations: @escaping (Bool) -> Void, selectAppIcon: @escaping (String) -> Void, editTheme: @escaping (PresentationCloudTheme) -> Void, themeContextAction: @escaping (Bool, PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void, colorContextAction: @escaping (Bool, PresentationThemeReference, ThemeSettingsColorOption?, ASDisplayNode, ContextGesture?) -> Void) { self.context = context self.selectTheme = selectTheme self.selectFontSize = selectFontSize @@ -92,6 +93,7 @@ private final class ThemeSettingsControllerArguments { self.openAccentColorPicker = openAccentColorPicker self.openAutoNightTheme = openAutoNightTheme self.openTextSize = openTextSize + self.openBubbleSettings = openBubbleSettings self.toggleLargeEmoji = toggleLargeEmoji self.disableAnimations = disableAnimations self.selectAppIcon = selectAppIcon @@ -131,11 +133,12 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry { case themeListHeader(PresentationTheme, String) case fontSizeHeader(PresentationTheme, String) case fontSize(PresentationTheme, PresentationFontSize) - case chatPreview(PresentationTheme, TelegramWallpaper, PresentationFontSize, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, [ChatPreviewMessageItem]) + case chatPreview(PresentationTheme, TelegramWallpaper, PresentationFontSize, PresentationChatBubbleCorners, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, [ChatPreviewMessageItem]) case wallpaper(PresentationTheme, String) case accentColor(PresentationTheme, PresentationThemeReference, PresentationThemeReference, [PresentationThemeReference], ThemeSettingsColorOption?) case autoNightTheme(PresentationTheme, String, String) case textSize(PresentationTheme, String, String) + case bubbleSettings(PresentationTheme, String, String) case themeItem(PresentationTheme, PresentationStrings, [PresentationThemeReference], [PresentationThemeReference], PresentationThemeReference, [Int64: PresentationThemeAccentColor], [Int64: TelegramWallpaper], PresentationThemeAccentColor?) case iconHeader(PresentationTheme, String) case iconItem(PresentationTheme, PresentationStrings, [PresentationAppIcon], String?) @@ -150,7 +153,7 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry { return ThemeSettingsControllerSection.chatPreview.rawValue case .fontSizeHeader, .fontSize: return ThemeSettingsControllerSection.fontSize.rawValue - case .wallpaper, .autoNightTheme, .textSize: + case .wallpaper, .autoNightTheme, .textSize, .bubbleSettings: return ThemeSettingsControllerSection.background.rawValue case .iconHeader, .iconItem: return ThemeSettingsControllerSection.icon.rawValue @@ -175,29 +178,31 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry { return 6 case .textSize: return 7 - case .fontSizeHeader: + case .bubbleSettings: return 8 - case .fontSize: + case .fontSizeHeader: return 9 - case .iconHeader: + case .fontSize: return 10 - case .iconItem: + case .iconHeader: return 11 - case .otherHeader: + case .iconItem: return 12 - case .largeEmoji: + case .otherHeader: return 13 - case .animations: + case .largeEmoji: return 14 - case .animationsInfo: + case .animations: return 15 + case .animationsInfo: + return 16 } } static func ==(lhs: ThemeSettingsControllerEntry, rhs: ThemeSettingsControllerEntry) -> Bool { switch lhs { - case let .chatPreview(lhsTheme, lhsWallpaper, lhsFontSize, lhsStrings, lhsTimeFormat, lhsNameOrder, lhsItems): - if case let .chatPreview(rhsTheme, rhsWallpaper, rhsFontSize, rhsStrings, rhsTimeFormat, rhsNameOrder, rhsItems) = rhs, lhsTheme === rhsTheme, lhsWallpaper == rhsWallpaper, lhsFontSize == rhsFontSize, lhsStrings === rhsStrings, lhsTimeFormat == rhsTimeFormat, lhsNameOrder == rhsNameOrder, lhsItems == rhsItems { + case let .chatPreview(lhsTheme, lhsWallpaper, lhsFontSize, lhsChatBubbleCorners, lhsStrings, lhsTimeFormat, lhsNameOrder, lhsItems): + if case let .chatPreview(rhsTheme, rhsWallpaper, rhsFontSize, rhsChatBubbleCorners, rhsStrings, rhsTimeFormat, rhsNameOrder, rhsItems) = rhs, lhsTheme === rhsTheme, lhsWallpaper == rhsWallpaper, lhsFontSize == rhsFontSize, lhsChatBubbleCorners == rhsChatBubbleCorners, lhsStrings === rhsStrings, lhsTimeFormat == rhsTimeFormat, lhsNameOrder == rhsNameOrder, lhsItems == rhsItems { return true } else { return false @@ -226,6 +231,12 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry { } else { return false } + case let .bubbleSettings(lhsTheme, lhsText, lhsValue): + if case let .bubbleSettings(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { + return true + } else { + return false + } case let .themeListHeader(lhsTheme, lhsText): if case let .themeListHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { return true @@ -302,8 +313,8 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry { return ThemeSettingsFontSizeItem(theme: theme, fontSize: fontSize, sectionId: self.section, updated: { value in arguments.selectFontSize(value) }, tag: ThemeSettingsEntryTag.fontSize) - case let .chatPreview(theme, wallpaper, fontSize, strings, dateTimeFormat, nameDisplayOrder, items): - return ThemeSettingsChatPreviewItem(context: arguments.context, theme: theme, componentTheme: theme, strings: strings, sectionId: self.section, fontSize: fontSize, wallpaper: wallpaper, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, messageItems: items) + case let .chatPreview(theme, wallpaper, fontSize, chatBubbleCorners, strings, dateTimeFormat, nameDisplayOrder, items): + return ThemeSettingsChatPreviewItem(context: arguments.context, theme: theme, componentTheme: theme, strings: strings, sectionId: self.section, fontSize: fontSize, chatBubbleCorners: chatBubbleCorners, wallpaper: wallpaper, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, messageItems: items) case let .wallpaper(theme, text): return ItemListDisclosureItem(presentationData: presentationData, title: text, label: "", sectionId: self.section, style: .blocks, action: { arguments.openWallpaperSettings() @@ -387,6 +398,10 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry { return ItemListDisclosureItem(presentationData: presentationData, icon: nil, title: text, label: value, labelStyle: .text, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { arguments.openTextSize() }) + case let .bubbleSettings(theme, text, value): + return ItemListDisclosureItem(presentationData: presentationData, icon: nil, title: text, label: value, labelStyle: .text, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { + arguments.openBubbleSettings() + }) case let .themeListHeader(theme, text): return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) case let .themeItem(theme, strings, themes, allThemes, currentTheme, themeSpecificAccentColors, themeSpecificChatWallpapers, _): @@ -429,7 +444,7 @@ private func themeSettingsControllerEntries(presentationData: PresentationData, let strings = presentationData.strings let title = presentationData.autoNightModeTriggered ? strings.Appearance_ColorThemeNight.uppercased() : strings.Appearance_ColorTheme.uppercased() entries.append(.themeListHeader(presentationData.theme, title)) - entries.append(.chatPreview(presentationData.theme, presentationData.chatWallpaper, presentationData.chatFontSize, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, [ChatPreviewMessageItem(outgoing: false, reply: (presentationData.strings.Appearance_PreviewReplyAuthor, presentationData.strings.Appearance_PreviewReplyText), text: presentationData.strings.Appearance_PreviewIncomingText), ChatPreviewMessageItem(outgoing: true, reply: nil, text: presentationData.strings.Appearance_PreviewOutgoingText)])) + entries.append(.chatPreview(presentationData.theme, presentationData.chatWallpaper, presentationData.chatFontSize, presentationData.chatBubbleCorners, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, [ChatPreviewMessageItem(outgoing: false, reply: (presentationData.strings.Appearance_PreviewReplyAuthor, presentationData.strings.Appearance_PreviewReplyText), text: presentationData.strings.Appearance_PreviewIncomingText), ChatPreviewMessageItem(outgoing: true, reply: nil, text: presentationData.strings.Appearance_PreviewOutgoingText)])) let generalThemes: [PresentationThemeReference] = availableThemes.filter { reference in if case let .cloud(theme) = reference { @@ -497,6 +512,7 @@ private func themeSettingsControllerEntries(presentationData: PresentationData, } } entries.append(.textSize(presentationData.theme, strings.Appearance_TextSizeSetting, textSizeValue)) + entries.append(.bubbleSettings(presentationData.theme, strings.Appearance_BubbleCornersSetting, "")) if !availableAppIcons.isEmpty { entries.append(.iconHeader(presentationData.theme, strings.Appearance_AppIcon.uppercased())) @@ -570,6 +586,13 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The let settings = (view.entries[ApplicationSpecificSharedDataKeys.presentationThemeSettings] as? PresentationThemeSettings) ?? PresentationThemeSettings.defaultSettings pushControllerImpl?(TextSizeSelectionController(context: context, presentationThemeSettings: settings)) }) + }, openBubbleSettings: { + let _ = (context.sharedContext.accountManager.sharedData(keys: Set([ApplicationSpecificSharedDataKeys.presentationThemeSettings])) + |> take(1) + |> deliverOnMainQueue).start(next: { view in + let settings = (view.entries[ApplicationSpecificSharedDataKeys.presentationThemeSettings] as? PresentationThemeSettings) ?? PresentationThemeSettings.defaultSettings + pushControllerImpl?(BubbleSettingsController(context: context, presentationThemeSettings: settings)) + }) }, toggleLargeEmoji: { largeEmoji in let _ = updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in return current.withUpdatedLargeEmoji(largeEmoji) @@ -1272,7 +1295,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The } } - return PresentationThemeSettings(theme: updatedTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, automaticThemeSwitchSetting: updatedAutomaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) + return PresentationThemeSettings(theme: updatedTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: updatedAutomaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) }).start() presentCrossfadeControllerImpl?(true) diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsFontSizeItem.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsFontSizeItem.swift index b409c93e4b..61b07eabff 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsFontSizeItem.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsFontSizeItem.swift @@ -16,17 +16,19 @@ class ThemeSettingsFontSizeItem: ListViewItem, ItemListItem { let theme: PresentationTheme let fontSize: PresentationFontSize let disableLeadingInset: Bool + let displayIcons: Bool let force: Bool let enabled: Bool let sectionId: ItemListSectionId let updated: (PresentationFontSize) -> Void let tag: ItemListItemTag? - init(theme: PresentationTheme, fontSize: PresentationFontSize, enabled: Bool = true, disableLeadingInset: Bool = false, force: Bool = false, sectionId: ItemListSectionId, updated: @escaping (PresentationFontSize) -> Void, tag: ItemListItemTag? = nil) { + init(theme: PresentationTheme, fontSize: PresentationFontSize, enabled: Bool = true, disableLeadingInset: Bool = false, displayIcons: Bool = true, force: Bool = false, sectionId: ItemListSectionId, updated: @escaping (PresentationFontSize) -> Void, tag: ItemListItemTag? = nil) { self.theme = theme self.fontSize = fontSize self.enabled = enabled self.disableLeadingInset = disableLeadingInset + self.displayIcons = displayIcons self.force = force self.sectionId = sectionId self.updated = updated @@ -164,7 +166,9 @@ class ThemeSettingsFontSizeItemNode: ListViewItemNode, ItemListItemNode { sliderView.trackColor = item.enabled ? item.theme.list.itemAccentColor : item.theme.list.itemDisabledTextColor sliderView.knobImage = generateKnobImage() - sliderView.frame = CGRect(origin: CGPoint(x: params.leftInset + 38.0, y: 8.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - 38.0 * 2.0, height: 44.0)) + let sliderInset: CGFloat = item.displayIcons ? 38.0 : 16.0 + + sliderView.frame = CGRect(origin: CGPoint(x: params.leftInset + sliderInset, y: 8.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - sliderInset * 2.0, height: 44.0)) } self.view.insertSubview(sliderView, belowSubview: self.disabledOverlayNode.view) sliderView.addTarget(self, action: #selector(self.sliderValueChanged), for: .valueChanged) @@ -271,6 +275,9 @@ class ThemeSettingsFontSizeItemNode: ListViewItemNode, ItemListItemNode { strongSelf.rightIconNode.frame = CGRect(origin: CGPoint(x: params.width - params.rightInset - 14.0 - image.size.width, y: 21.0), size: CGSize(width: image.size.width, height: image.size.height)) } + strongSelf.leftIconNode.isHidden = !item.displayIcons + strongSelf.rightIconNode.isHidden = !item.displayIcons + if let sliderView = strongSelf.sliderView { sliderView.isUserInteractionEnabled = item.enabled sliderView.trackColor = item.enabled ? item.theme.list.itemAccentColor : item.theme.list.itemDisabledTextColor @@ -302,7 +309,8 @@ class ThemeSettingsFontSizeItemNode: ListViewItemNode, ItemListItemNode { sliderView.value = value } - sliderView.frame = CGRect(origin: CGPoint(x: params.leftInset + 38.0, y: 8.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - 38.0 * 2.0, height: 44.0)) + let sliderInset: CGFloat = item.displayIcons ? 38.0 : 16.0 + sliderView.frame = CGRect(origin: CGPoint(x: params.leftInset + sliderInset, y: 8.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - sliderInset * 2.0, height: 44.0)) } } }) diff --git a/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift b/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift index 9453bc392c..a159690102 100644 --- a/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift +++ b/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift @@ -832,10 +832,10 @@ final class WallpaperGalleryItemNode: GalleryItemNode { let theme = self.presentationData.theme.withUpdated(preview: true) let message1 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: bottomMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) - items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message1, theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.chatFontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil)) + items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message1, theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil)) let message2 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: topMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) - items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message2, theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.chatFontSize, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil)) + items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, message: message2, theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil)) let params = ListViewItemLayoutParams(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, availableHeight: layout.size.height) if let messageNodes = self.messageNodes { diff --git a/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift b/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift index 4ae705e92f..36850b476d 100644 --- a/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift +++ b/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift @@ -26,14 +26,253 @@ public func messageSingleBubbleLikeImage(fillColor: UIColor, strokeColor: UIColo })!.stretchableImage(withLeftCapWidth: Int(diameter / 2.0), topCapHeight: Int(diameter / 2.0)) } -public func messageBubbleImage(incoming: Bool, fillColor: UIColor, strokeColor: UIColor, neighbors: MessageBubbleImageNeighbors, theme: PresentationThemeChat, wallpaper: TelegramWallpaper, knockout knockoutValue: Bool, mask: Bool = false, extendedEdges: Bool = false, onlyOutline: Bool = false) -> UIImage { - let diameter: CGFloat = 36.0 - let corner: CGFloat = 7.0 +private let minRadiusForFullTailCorner: CGFloat = 14.0 + +func mediaBubbleCornerImage(incoming: Bool, radius: CGFloat, inset: CGFloat) -> UIImage { + let imageSize = CGSize(width: radius + 7.0, height: 8.0) + let fixedMainDiameter: CGFloat = 33.0 + + let formContext = DrawingContext(size: imageSize) + formContext.withFlippedContext { context in + context.clear(CGRect(origin: CGPoint(), size: imageSize)) + context.translateBy(x: imageSize.width / 2.0, y: imageSize.height / 2.0) + context.scaleBy(x: incoming ? -1.0 : 1.0, y: -1.0) + context.translateBy(x: -imageSize.width / 2.0, y: -imageSize.height / 2.0) + + context.setFillColor(UIColor.black.cgColor) + + let bottomEllipse = CGRect(origin: CGPoint(x: 24.0, y: 16.0), size: CGSize(width: 27.0, height: 17.0)).insetBy(dx: inset, dy: inset).offsetBy(dx: inset, dy: inset) + let topEllipse = CGRect(origin: CGPoint(x: 33.0, y: 14.0), size: CGSize(width: 23.0, height: 21.0)).insetBy(dx: -inset, dy: -inset).offsetBy(dx: inset, dy: inset) + + context.translateBy(x: -fixedMainDiameter + imageSize.width - 6.0, y: -fixedMainDiameter + imageSize.height) + + let topLeftRadius: CGFloat = 2.0 + let topRightRadius: CGFloat = 2.0 + let bottomLeftRadius: CGFloat = 2.0 + let bottomRightRadius: CGFloat = radius + + context.move(to: CGPoint(x: 0.0, y: topLeftRadius)) + context.addArc(tangent1End: CGPoint(x: 0.0, y: 0.0), tangent2End: CGPoint(x: topLeftRadius, y: 0.0), radius: topLeftRadius) + context.addLine(to: CGPoint(x: fixedMainDiameter - topRightRadius, y: 0.0)) + context.addArc(tangent1End: CGPoint(x: fixedMainDiameter, y: 0.0), tangent2End: CGPoint(x: fixedMainDiameter, y: topRightRadius), radius: topRightRadius) + context.addLine(to: CGPoint(x: fixedMainDiameter, y: fixedMainDiameter - bottomRightRadius)) + context.addArc(tangent1End: CGPoint(x: fixedMainDiameter, y: fixedMainDiameter), tangent2End: CGPoint(x: fixedMainDiameter - bottomRightRadius, y: fixedMainDiameter), radius: bottomRightRadius) + context.addLine(to: CGPoint(x: bottomLeftRadius, y: fixedMainDiameter)) + context.addArc(tangent1End: CGPoint(x: 0.0, y: fixedMainDiameter), tangent2End: CGPoint(x: 0.0, y: fixedMainDiameter - bottomLeftRadius), radius: bottomLeftRadius) + context.addLine(to: CGPoint(x: 0.0, y: topLeftRadius)) + context.fillPath() + + if radius >= minRadiusForFullTailCorner { + context.move(to: CGPoint(x: bottomEllipse.minX, y: bottomEllipse.midY)) + context.addQuadCurve(to: CGPoint(x: bottomEllipse.midX, y: bottomEllipse.maxY), control: CGPoint(x: bottomEllipse.minX, y: bottomEllipse.maxY)) + context.addQuadCurve(to: CGPoint(x: bottomEllipse.maxX, y: bottomEllipse.midY), control: CGPoint(x: bottomEllipse.maxX, y: bottomEllipse.maxY)) + context.fillPath() + } else { + context.fill(CGRect(origin: CGPoint(x: bottomEllipse.minX - 5.0, y: bottomEllipse.midY), size: CGSize(width: bottomEllipse.width + 5.0, height: bottomEllipse.height / 2.0))) + } + context.fill(CGRect(origin: CGPoint(x: fixedMainDiameter / 2.0, y: fixedMainDiameter / 2.0), size: CGSize(width: fixedMainDiameter / 2.0, height: bottomEllipse.midY - fixedMainDiameter / 2.0))) + context.setFillColor(UIColor.clear.cgColor) + context.setBlendMode(.copy) + context.fillEllipse(in: topEllipse) + } + + return formContext.generateImage()! +} + +public func messageBubbleImage(maxCornerRadius: CGFloat, minCornerRadius: CGFloat, incoming: Bool, fillColor: UIColor, strokeColor: UIColor, neighbors: MessageBubbleImageNeighbors, theme: PresentationThemeChat, wallpaper: TelegramWallpaper, knockout knockoutValue: Bool, mask: Bool = false, extendedEdges: Bool = false, onlyOutline: Bool = false) -> UIImage { + let topLeftRadius: CGFloat + let topRightRadius: CGFloat + let bottomLeftRadius: CGFloat + let bottomRightRadius: CGFloat + let drawTail: Bool + + switch neighbors { + case .none: + topLeftRadius = maxCornerRadius + topRightRadius = maxCornerRadius + bottomLeftRadius = maxCornerRadius + bottomRightRadius = maxCornerRadius + drawTail = true + case .both: + topLeftRadius = maxCornerRadius + topRightRadius = minCornerRadius + bottomLeftRadius = maxCornerRadius + bottomRightRadius = minCornerRadius + drawTail = false + case .bottom: + topLeftRadius = maxCornerRadius + topRightRadius = minCornerRadius + bottomLeftRadius = maxCornerRadius + bottomRightRadius = maxCornerRadius + drawTail = true + case .side: + topLeftRadius = maxCornerRadius + topRightRadius = maxCornerRadius + bottomLeftRadius = maxCornerRadius + bottomRightRadius = maxCornerRadius + drawTail = false + case let .top(side): + topLeftRadius = maxCornerRadius + topRightRadius = side ? minCornerRadius : maxCornerRadius + bottomLeftRadius = maxCornerRadius + bottomRightRadius = minCornerRadius + drawTail = false + } + + let fixedMainDiameter: CGFloat = 33.0 + let innerSize = CGSize(width: fixedMainDiameter + 6.0, height: fixedMainDiameter) + let strokeInset: CGFloat = 1.0 + let sourceRawSize = CGSize(width: innerSize.width + strokeInset * 2.0, height: innerSize.height + strokeInset * 2.0) + let additionalInset: CGFloat = 1.0 + let imageSize = CGSize(width: sourceRawSize.width + additionalInset * 2.0, height: sourceRawSize.height + additionalInset * 2.0) + let outgoingStretchPoint: (x: Int, y: Int) = (Int(additionalInset + strokeInset + round(fixedMainDiameter / 2.0)) - 1, Int(additionalInset + strokeInset + round(fixedMainDiameter / 2.0))) + let incomingStretchPoint: (x: Int, y: Int) = (Int(sourceRawSize.width) - outgoingStretchPoint.x + 1, outgoingStretchPoint.y) + let knockout = knockoutValue && !mask - let inset: CGFloat = 1.0 + let rawSize = imageSize - return generateImage(CGSize(width: 42.0 + inset * 2.0, height: diameter + inset * 2.0), contextGenerator: { rawSize, context in + let bottomEllipse = CGRect(origin: CGPoint(x: 24.0, y: 16.0), size: CGSize(width: 27.0, height: 17.0)) + let topEllipse = CGRect(origin: CGPoint(x: 33.0, y: 14.0), size: CGSize(width: 23.0, height: 21.0)) + + let formContext = DrawingContext(size: imageSize) + formContext.withFlippedContext { context in + context.clear(CGRect(origin: CGPoint(), size: rawSize)) + context.translateBy(x: additionalInset + strokeInset, y: additionalInset + strokeInset) + + context.setFillColor(UIColor.black.cgColor) + + context.move(to: CGPoint(x: 0.0, y: topLeftRadius)) + context.addArc(tangent1End: CGPoint(x: 0.0, y: 0.0), tangent2End: CGPoint(x: topLeftRadius, y: 0.0), radius: topLeftRadius) + context.addLine(to: CGPoint(x: fixedMainDiameter - topRightRadius, y: 0.0)) + context.addArc(tangent1End: CGPoint(x: fixedMainDiameter, y: 0.0), tangent2End: CGPoint(x: fixedMainDiameter, y: topRightRadius), radius: topRightRadius) + context.addLine(to: CGPoint(x: fixedMainDiameter, y: fixedMainDiameter - bottomRightRadius)) + context.addArc(tangent1End: CGPoint(x: fixedMainDiameter, y: fixedMainDiameter), tangent2End: CGPoint(x: fixedMainDiameter - bottomRightRadius, y: fixedMainDiameter), radius: bottomRightRadius) + context.addLine(to: CGPoint(x: bottomLeftRadius, y: fixedMainDiameter)) + context.addArc(tangent1End: CGPoint(x: 0.0, y: fixedMainDiameter), tangent2End: CGPoint(x: 0.0, y: fixedMainDiameter - bottomLeftRadius), radius: bottomLeftRadius) + context.addLine(to: CGPoint(x: 0.0, y: topLeftRadius)) + context.fillPath() + + if drawTail { + if maxCornerRadius >= minRadiusForFullTailCorner { + context.move(to: CGPoint(x: bottomEllipse.minX, y: bottomEllipse.midY)) + context.addQuadCurve(to: CGPoint(x: bottomEllipse.midX, y: bottomEllipse.maxY), control: CGPoint(x: bottomEllipse.minX, y: bottomEllipse.maxY)) + context.addQuadCurve(to: CGPoint(x: bottomEllipse.maxX, y: bottomEllipse.midY), control: CGPoint(x: bottomEllipse.maxX, y: bottomEllipse.maxY)) + context.fillPath() + } else { + context.fill(CGRect(origin: CGPoint(x: bottomEllipse.minX - 2.0, y: bottomEllipse.midY), size: CGSize(width: bottomEllipse.width + 2.0, height: bottomEllipse.height / 2.0))) + } + context.fill(CGRect(origin: CGPoint(x: fixedMainDiameter / 2.0, y: fixedMainDiameter / 2.0), size: CGSize(width: fixedMainDiameter / 2.0, height: bottomEllipse.midY - fixedMainDiameter / 2.0))) + context.setFillColor(UIColor.clear.cgColor) + context.setBlendMode(.copy) + context.fillEllipse(in: topEllipse) + } + } + let formImage = formContext.generateImage()! + + let outlineContext = DrawingContext(size: imageSize) + outlineContext.withFlippedContext { context in + context.clear(CGRect(origin: CGPoint(), size: rawSize)) + context.translateBy(x: additionalInset + strokeInset, y: additionalInset + strokeInset) + + context.setStrokeColor(UIColor.black.cgColor) + let borderWidth: CGFloat = UIScreenPixel * 2.0 + context.setLineWidth(borderWidth) + + let borderOffset: CGFloat = borderWidth / 2.0 + + context.move(to: CGPoint(x: -borderOffset, y: topLeftRadius + borderOffset)) + context.addArc(tangent1End: CGPoint(x: -borderOffset, y: -borderOffset), tangent2End: CGPoint(x: topLeftRadius + borderOffset, y: -borderOffset), radius: topLeftRadius + borderOffset * 2.0) + context.addLine(to: CGPoint(x: fixedMainDiameter - topRightRadius - borderOffset, y: -borderOffset)) + context.addArc(tangent1End: CGPoint(x: fixedMainDiameter + borderOffset, y: -borderOffset), tangent2End: CGPoint(x: fixedMainDiameter + borderOffset, y: topRightRadius + borderOffset), radius: topRightRadius + borderOffset * 2.0) + context.addLine(to: CGPoint(x: fixedMainDiameter + borderOffset, y: fixedMainDiameter - bottomRightRadius - borderOffset)) + context.addArc(tangent1End: CGPoint(x: fixedMainDiameter + borderOffset, y: fixedMainDiameter + borderOffset), tangent2End: CGPoint(x: fixedMainDiameter - bottomRightRadius - borderOffset, y: fixedMainDiameter + borderOffset), radius: bottomRightRadius + borderOffset * 2.0) + context.addLine(to: CGPoint(x: bottomLeftRadius + borderOffset, y: fixedMainDiameter + borderOffset)) + context.addArc(tangent1End: CGPoint(x: -borderOffset, y: fixedMainDiameter + borderOffset), tangent2End: CGPoint(x: -borderOffset, y: fixedMainDiameter - bottomLeftRadius - borderOffset), radius: bottomLeftRadius + borderOffset * 2.0) + context.closePath() + context.strokePath() + + if drawTail { + let outlineBottomEllipse = bottomEllipse.insetBy(dx: -borderOffset, dy: -borderOffset) + let outlineInnerTopEllipse = topEllipse.insetBy(dx: borderOffset, dy: borderOffset) + let outlineTopEllipse = topEllipse.insetBy(dx: -borderOffset, dy: -borderOffset) + + context.setBlendMode(.copy) + context.setFillColor(UIColor.clear.cgColor) + + if maxCornerRadius >= minRadiusForFullTailCorner { + context.move(to: CGPoint(x: bottomEllipse.minX, y: bottomEllipse.midY)) + context.addQuadCurve(to: CGPoint(x: bottomEllipse.midX, y: bottomEllipse.maxY), control: CGPoint(x: bottomEllipse.minX, y: bottomEllipse.maxY)) + context.addQuadCurve(to: CGPoint(x: bottomEllipse.maxX, y: bottomEllipse.midY), control: CGPoint(x: bottomEllipse.maxX, y: bottomEllipse.maxY)) + context.fillPath() + } else { + context.fill(CGRect(origin: CGPoint(x: bottomEllipse.minX - 2.0, y: bottomEllipse.midY), size: CGSize(width: bottomEllipse.width + 2.0, height: bottomEllipse.height / 2.0))) + } + context.fill(CGRect(origin: CGPoint(x: fixedMainDiameter / 2.0, y: fixedMainDiameter / 2.0), size: CGSize(width: fixedMainDiameter / 2.0 + borderWidth, height: bottomEllipse.midY - fixedMainDiameter / 2.0))) + + context.setBlendMode(.normal) + context.move(to: CGPoint(x: fixedMainDiameter + borderOffset, y: fixedMainDiameter / 2.0)) + context.addLine(to: CGPoint(x: fixedMainDiameter + borderOffset, y: outlineBottomEllipse.midY)) + context.strokePath() + + let bubbleTailContext = DrawingContext(size: imageSize) + bubbleTailContext.withFlippedContext { context in + context.clear(CGRect(origin: CGPoint(), size: rawSize)) + context.translateBy(x: additionalInset + strokeInset, y: additionalInset + strokeInset) + + context.setStrokeColor(UIColor.black.cgColor) + context.setLineWidth(borderWidth) + + if maxCornerRadius >= minRadiusForFullTailCorner { + context.move(to: CGPoint(x: outlineBottomEllipse.minX, y: outlineBottomEllipse.midY)) + context.addQuadCurve(to: CGPoint(x: outlineBottomEllipse.midX, y: outlineBottomEllipse.maxY), control: CGPoint(x: outlineBottomEllipse.minX, y: outlineBottomEllipse.maxY)) + context.addQuadCurve(to: CGPoint(x: outlineBottomEllipse.maxX, y: outlineBottomEllipse.midY), control: CGPoint(x: outlineBottomEllipse.maxX, y: outlineBottomEllipse.maxY)) + } else { + context.move(to: CGPoint(x: outlineBottomEllipse.minX - 2.0, y: outlineBottomEllipse.maxY)) + context.addLine(to: CGPoint(x: outlineBottomEllipse.minX, y: outlineBottomEllipse.maxY)) + context.addLine(to: CGPoint(x: outlineBottomEllipse.maxX, y: outlineBottomEllipse.maxY)) + } + context.strokePath() + context.setFillColor(UIColor.clear.cgColor) + context.setBlendMode(.copy) + context.fillEllipse(in: outlineInnerTopEllipse) + + context.move(to: CGPoint(x: 0.0, y: topLeftRadius)) + context.addArc(tangent1End: CGPoint(x: 0.0, y: 0.0), tangent2End: CGPoint(x: topLeftRadius, y: 0.0), radius: topLeftRadius) + context.addLine(to: CGPoint(x: fixedMainDiameter - topRightRadius, y: 0.0)) + context.addArc(tangent1End: CGPoint(x: fixedMainDiameter, y: 0.0), tangent2End: CGPoint(x: fixedMainDiameter, y: topRightRadius), radius: topRightRadius) + context.addLine(to: CGPoint(x: fixedMainDiameter, y: fixedMainDiameter - bottomRightRadius)) + context.addArc(tangent1End: CGPoint(x: fixedMainDiameter, y: fixedMainDiameter), tangent2End: CGPoint(x: fixedMainDiameter - bottomRightRadius, y: fixedMainDiameter), radius: bottomRightRadius) + context.addLine(to: CGPoint(x: bottomLeftRadius, y: fixedMainDiameter)) + context.addArc(tangent1End: CGPoint(x: 0.0, y: fixedMainDiameter), tangent2End: CGPoint(x: 0.0, y: fixedMainDiameter - bottomLeftRadius), radius: bottomLeftRadius) + context.addLine(to: CGPoint(x: 0.0, y: topLeftRadius)) + context.fillPath() + + let bottomEllipseMask = generateImage(bottomEllipse.insetBy(dx: -1.0, dy: -1.0).size, contextGenerator: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + context.setFillColor(UIColor.black.cgColor) + if maxCornerRadius >= minRadiusForFullTailCorner { + context.fillEllipse(in: CGRect(origin: CGPoint(x: 1.0 - borderOffset, y: 1.0 - borderOffset), size: CGSize(width: outlineBottomEllipse.width, height: outlineBottomEllipse.height))) + } else { + context.fill(CGRect(origin: CGPoint(x: 1.0 - borderOffset, y: 1.0 - borderOffset), size: CGSize(width: outlineBottomEllipse.width, height: outlineBottomEllipse.height))) + } + context.clear(CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: size.height / 2.0))) + })! + + context.clip(to: bottomEllipse.insetBy(dx: -1.0, dy: -1.0), mask: bottomEllipseMask.cgImage!) + context.strokeEllipse(in: outlineInnerTopEllipse) + context.resetClip() + } + + context.translateBy(x: -(additionalInset + strokeInset), y: -(additionalInset + strokeInset)) + context.draw(bubbleTailContext.generateImage()!.cgImage!, in: CGRect(origin: CGPoint(), size: rawSize)) + context.translateBy(x: additionalInset + strokeInset, y: additionalInset + strokeInset) + } + } + let outlineImage = outlineContext.generateImage()! + + let drawingContext = DrawingContext(size: imageSize) + drawingContext.withFlippedContext { context in var drawWithClearColor = false if knockout { @@ -48,94 +287,33 @@ public func messageBubbleImage(incoming: Bool, fillColor: UIColor, strokeColor: context.clear(CGRect(origin: CGPoint(), size: rawSize)) } - let additionalOffset: CGFloat - switch neighbors { - case .none, .bottom: - additionalOffset = 0.0 - case .both, .side, .top: - additionalOffset = 6.0 - } - - context.translateBy(x: rawSize.width / 2.0, y: rawSize.height / 2.0) - context.scaleBy(x: incoming ? 1.0 : -1.0, y: -1.0) - context.translateBy(x: -rawSize.width / 2.0, y: -rawSize.height / 2.0) - - context.translateBy(x: additionalOffset + 0.5, y: 0.5) - - let size = CGSize(width: rawSize.width - inset * 2.0, height: rawSize.height - inset * 2.0) - context.translateBy(x: inset, y: inset) - - var lineWidth: CGFloat = 1.0 - if drawWithClearColor { context.setBlendMode(.copy) context.setFillColor(UIColor.clear.cgColor) - context.setStrokeColor(UIColor.clear.cgColor) } else { + context.setBlendMode(.normal) context.setFillColor(fillColor.cgColor) - context.setLineWidth(lineWidth) - context.setStrokeColor(strokeColor.cgColor) } - if onlyOutline { - if knockout { - lineWidth = max(UIScreenPixel, 1.0 - 0.5) - } - context.setLineWidth(lineWidth) - context.setStrokeColor(strokeColor.cgColor) + context.saveGState() + + context.translateBy(x: rawSize.width / 2.0, y: rawSize.height / 2.0) + context.scaleBy(x: incoming ? -1.0 : 1.0, y: -1.0) + context.translateBy(x: -rawSize.width / 2.0, y: -rawSize.height / 2.0) + + if !onlyOutline { + context.clip(to: CGRect(origin: CGPoint(), size: rawSize), mask: formImage.cgImage!) + context.fill(CGRect(origin: CGPoint(), size: rawSize)) + } else { + context.setFillColor(strokeColor.cgColor) + context.clip(to: CGRect(origin: CGPoint(), size: rawSize), mask: outlineImage.cgImage!) + context.fill(CGRect(origin: CGPoint(), size: rawSize)) } - switch neighbors { - case .none: - if onlyOutline { - let _ = try? drawSvgPath(context, path: "M6,17.5 C6,7.83289181 13.8350169,0 23.5,0 C33.1671082,0 41,7.83501688 41,17.5 C41,27.1671082 33.1649831,35 23.5,35 C19.2941198,35 15.4354328,33.5169337 12.4179496,31.0453367 C9.05531719,34.9894816 -2.41102995e-08,35 0,35 C5.972003,31.5499861 6,26.8616169 6,26.8616169 L6,17.5 L6,17.5 ") - context.strokePath() - } else { - let _ = try? drawSvgPath(context, path: "M6,17.5 C6,7.83289181 13.8350169,0 23.5,0 C33.1671082,0 41,7.83501688 41,17.5 C41,27.1671082 33.1649831,35 23.5,35 C19.2941198,35 15.4354328,33.5169337 12.4179496,31.0453367 C9.05531719,34.9894816 -2.41102995e-08,35 0,35 C5.972003,31.5499861 6,26.8616169 6,26.8616169 L6,17.5 L6,17.5 ") - context.fillPath() - } - case .side: - if onlyOutline { - context.strokeEllipse(in: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: 35.0, height: 35.0))) - } else { - context.fillEllipse(in: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: 35.0, height: 35.0))) - } - case let .top(side): - if side { - if onlyOutline { - let _ = try? drawSvgPath(context, path: "M17.5,0 L17.5,0 C27.1649831,-1.7754286e-15 35,7.83501688 35,17.5 L35,29 C35,32.3137085 32.3137085,35 29,35 L6,35 C2.6862915,35 4.05812251e-16,32.3137085 0,29 L0,17.5 C-1.18361906e-15,7.83501688 7.83501688,1.7754286e-15 17.5,0 ") - context.strokePath() - } else { - let _ = try? drawSvgPath(context, path: "M17.5,0 L17.5,0 C27.1649831,-1.7754286e-15 35,7.83501688 35,17.5 L35,29 C35,32.3137085 32.3137085,35 29,35 L6,35 C2.6862915,35 4.05812251e-16,32.3137085 0,29 L0,17.5 C-1.18361906e-15,7.83501688 7.83501688,1.7754286e-15 17.5,0 ") - context.fillPath() - } - } else { - if onlyOutline { - let _ = try? drawSvgPath(context, path: "M35,17.5 C35,7.83501688 27.1671082,0 17.5,0 L17.5,0 C7.83501688,0 0,7.83289181 0,17.5 L0,29.0031815 C0,32.3151329 2.6882755,35 5.99681848,35 L17.5,35 C27.1649831,35 35,27.1671082 35,17.5 L35,17.5 L35,17.5 ") - context.strokePath() - } else { - let _ = try? drawSvgPath(context, path: "M35,17.5 C35,7.83501688 27.1671082,0 17.5,0 L17.5,0 C7.83501688,0 0,7.83289181 0,17.5 L0,29.0031815 C0,32.3151329 2.6882755,35 5.99681848,35 L17.5,35 C27.1649831,35 35,27.1671082 35,17.5 L35,17.5 L35,17.5 ") - context.fillPath() - } - } - case .bottom: - if onlyOutline { - let _ = try? drawSvgPath(context, path: "M6,17.5 L6,5.99681848 C6,2.6882755 8.68486709,0 11.9968185,0 L23.5,0 C33.1671082,0 41,7.83501688 41,17.5 C41,27.1671082 33.1649831,35 23.5,35 C19.2941198,35 15.4354328,33.5169337 12.4179496,31.0453367 C9.05531719,34.9894816 -2.41103066e-08,35 0,35 C5.972003,31.5499861 6,26.8616169 6,26.8616169 L6,17.5 L6,17.5 ") - context.strokePath() - } else { - let _ = try? drawSvgPath(context, path: "M6,17.5 L6,5.99681848 C6,2.6882755 8.68486709,0 11.9968185,0 L23.5,0 C33.1671082,0 41,7.83501688 41,17.5 C41,27.1671082 33.1649831,35 23.5,35 C19.2941198,35 15.4354328,33.5169337 12.4179496,31.0453367 C9.05531719,34.9894816 -2.41103066e-08,35 0,35 C5.972003,31.5499861 6,26.8616169 6,26.8616169 L6,17.5 L6,17.5 ") - context.fillPath() - } - case .both: - if onlyOutline { - let _ = try? drawSvgPath(context, path: "M35,17.5 C35,7.83501688 27.1671082,0 17.5,0 L5.99681848,0 C2.68486709,0 0,2.6882755 0,5.99681848 L0,29.0031815 C0,32.3151329 2.6882755,35 5.99681848,35 L17.5,35 C27.1649831,35 35,27.1671082 35,17.5 L35,17.5 L35,17.5 ") - context.strokePath() - } else { - let _ = try? drawSvgPath(context, path: "M35,17.5 C35,7.83501688 27.1671082,0 17.5,0 L5.99681848,0 C2.68486709,0 0,2.6882755 0,5.99681848 L0,29.0031815 C0,32.3151329 2.6882755,35 5.99681848,35 L17.5,35 C27.1649831,35 35,27.1671082 35,17.5 L35,17.5 L35,17.5 ") - context.fillPath() - } - } - })!.stretchableImage(withLeftCapWidth: incoming ? Int(inset + corner + diameter / 2.0 - 1.0) : Int(inset + diameter / 2.0), topCapHeight: Int(inset + diameter / 2.0)) + context.restoreGState() + } + + return drawingContext.generateImage()!.stretchableImage(withLeftCapWidth: incoming ? incomingStretchPoint.x : outgoingStretchPoint.x, topCapHeight: incoming ? incomingStretchPoint.y : outgoingStretchPoint.y) } public enum MessageBubbleActionButtonPosition { diff --git a/submodules/TelegramPresentationData/Sources/PresentationData.swift b/submodules/TelegramPresentationData/Sources/PresentationData.swift index c8e271e5cd..f33079da79 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationData.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationData.swift @@ -48,12 +48,25 @@ public enum PresentationDateFormat { case dayFirst } +public struct PresentationChatBubbleCorners: Equatable, Hashable { + public var mainRadius: CGFloat + public var auxiliaryRadius: CGFloat + public var mergeBubbleCorners: Bool + + public init(mainRadius: CGFloat, auxiliaryRadius: CGFloat, mergeBubbleCorners: Bool) { + self.mainRadius = mainRadius + self.auxiliaryRadius = auxiliaryRadius + self.mergeBubbleCorners = mergeBubbleCorners + } +} + public final class PresentationData: Equatable { public let strings: PresentationStrings public let theme: PresentationTheme public let autoNightModeTriggered: Bool public let chatWallpaper: TelegramWallpaper public let chatFontSize: PresentationFontSize + public let chatBubbleCorners: PresentationChatBubbleCorners public let listsFontSize: PresentationFontSize public let dateTimeFormat: PresentationDateTimeFormat public let nameDisplayOrder: PresentationPersonNameOrder @@ -61,12 +74,13 @@ public final class PresentationData: Equatable { public let disableAnimations: Bool public let largeEmoji: Bool - public init(strings: PresentationStrings, theme: PresentationTheme, autoNightModeTriggered: Bool, chatWallpaper: TelegramWallpaper, chatFontSize: PresentationFontSize, listsFontSize: PresentationFontSize, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, nameSortOrder: PresentationPersonNameOrder, disableAnimations: Bool, largeEmoji: Bool) { + public init(strings: PresentationStrings, theme: PresentationTheme, autoNightModeTriggered: Bool, chatWallpaper: TelegramWallpaper, chatFontSize: PresentationFontSize, chatBubbleCorners: PresentationChatBubbleCorners, listsFontSize: PresentationFontSize, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, nameSortOrder: PresentationPersonNameOrder, disableAnimations: Bool, largeEmoji: Bool) { self.strings = strings self.theme = theme self.autoNightModeTriggered = autoNightModeTriggered self.chatWallpaper = chatWallpaper self.chatFontSize = chatFontSize + self.chatBubbleCorners = chatBubbleCorners self.listsFontSize = listsFontSize self.dateTimeFormat = dateTimeFormat self.nameDisplayOrder = nameDisplayOrder @@ -76,7 +90,7 @@ public final class PresentationData: Equatable { } public static func ==(lhs: PresentationData, rhs: PresentationData) -> Bool { - return lhs.strings === rhs.strings && lhs.theme === rhs.theme && lhs.autoNightModeTriggered == rhs.autoNightModeTriggered && lhs.chatWallpaper == rhs.chatWallpaper && lhs.chatFontSize == rhs.chatFontSize && lhs.listsFontSize == rhs.listsFontSize && lhs.dateTimeFormat == rhs.dateTimeFormat && lhs.disableAnimations == rhs.disableAnimations && lhs.largeEmoji == rhs.largeEmoji + return lhs.strings === rhs.strings && lhs.theme === rhs.theme && lhs.autoNightModeTriggered == rhs.autoNightModeTriggered && lhs.chatWallpaper == rhs.chatWallpaper && lhs.chatFontSize == rhs.chatFontSize && lhs.chatBubbleCorners == rhs.chatBubbleCorners && lhs.listsFontSize == rhs.listsFontSize && lhs.dateTimeFormat == rhs.dateTimeFormat && lhs.disableAnimations == rhs.disableAnimations && lhs.largeEmoji == rhs.largeEmoji } } @@ -268,7 +282,9 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager, s let (chatFontSize, listsFontSize) = resolveFontSize(settings: themeSettings) - return InitialPresentationDataAndSettings(presentationData: PresentationData(strings: stringsValue, theme: theme, autoNightModeTriggered: autoNightModeTriggered, chatWallpaper: effectiveChatWallpaper, chatFontSize: chatFontSize, listsFontSize: listsFontSize, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, nameSortOrder: nameSortOrder, disableAnimations: themeSettings.disableAnimations, largeEmoji: themeSettings.largeEmoji), automaticMediaDownloadSettings: automaticMediaDownloadSettings, autodownloadSettings: autodownloadSettings, callListSettings: callListSettings, inAppNotificationSettings: inAppNotificationSettings, mediaInputSettings: mediaInputSettings, experimentalUISettings: experimentalUISettings) + let chatBubbleCorners = PresentationChatBubbleCorners(mainRadius: CGFloat(themeSettings.chatBubbleSettings.mainRadius), auxiliaryRadius: CGFloat(themeSettings.chatBubbleSettings.auxiliaryRadius), mergeBubbleCorners: themeSettings.chatBubbleSettings.mergeBubbleCorners) + + return InitialPresentationDataAndSettings(presentationData: PresentationData(strings: stringsValue, theme: theme, autoNightModeTriggered: autoNightModeTriggered, chatWallpaper: effectiveChatWallpaper, chatFontSize: chatFontSize, chatBubbleCorners: chatBubbleCorners, listsFontSize: listsFontSize, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, nameSortOrder: nameSortOrder, disableAnimations: themeSettings.disableAnimations, largeEmoji: themeSettings.largeEmoji), automaticMediaDownloadSettings: automaticMediaDownloadSettings, autodownloadSettings: autodownloadSettings, callListSettings: callListSettings, inAppNotificationSettings: inAppNotificationSettings, mediaInputSettings: mediaInputSettings, experimentalUISettings: experimentalUISettings) } } @@ -601,7 +617,9 @@ public func updatedPresentationData(accountManager: AccountManager, applicationI let (chatFontSize, listsFontSize) = resolveFontSize(settings: themeSettings) - return PresentationData(strings: stringsValue, theme: themeValue, autoNightModeTriggered: autoNightModeTriggered, chatWallpaper: effectiveChatWallpaper, chatFontSize: chatFontSize, listsFontSize: listsFontSize, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, nameSortOrder: nameSortOrder, disableAnimations: themeSettings.disableAnimations, largeEmoji: themeSettings.largeEmoji) + let chatBubbleCorners = PresentationChatBubbleCorners(mainRadius: CGFloat(themeSettings.chatBubbleSettings.mainRadius), auxiliaryRadius: CGFloat(themeSettings.chatBubbleSettings.auxiliaryRadius), mergeBubbleCorners: themeSettings.chatBubbleSettings.mergeBubbleCorners) + + return PresentationData(strings: stringsValue, theme: themeValue, autoNightModeTriggered: autoNightModeTriggered, chatWallpaper: effectiveChatWallpaper, chatFontSize: chatFontSize, chatBubbleCorners: chatBubbleCorners, listsFontSize: listsFontSize, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, nameSortOrder: nameSortOrder, disableAnimations: themeSettings.disableAnimations, largeEmoji: themeSettings.largeEmoji) } } else { return .complete() @@ -634,15 +652,21 @@ public func defaultPresentationData() -> PresentationData { let (chatFontSize, listsFontSize) = resolveFontSize(settings: themeSettings) - return PresentationData(strings: defaultPresentationStrings, theme: defaultPresentationTheme, autoNightModeTriggered: false, chatWallpaper: .builtin(WallpaperSettings()), chatFontSize: chatFontSize, listsFontSize: listsFontSize, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, nameSortOrder: nameSortOrder, disableAnimations: themeSettings.disableAnimations, largeEmoji: themeSettings.largeEmoji) + let chatBubbleCorners = PresentationChatBubbleCorners(mainRadius: CGFloat(themeSettings.chatBubbleSettings.mainRadius), auxiliaryRadius: CGFloat(themeSettings.chatBubbleSettings.auxiliaryRadius), mergeBubbleCorners: themeSettings.chatBubbleSettings.mergeBubbleCorners) + + return PresentationData(strings: defaultPresentationStrings, theme: defaultPresentationTheme, autoNightModeTriggered: false, chatWallpaper: .builtin(WallpaperSettings()), chatFontSize: chatFontSize, chatBubbleCorners: chatBubbleCorners, listsFontSize: listsFontSize, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, nameSortOrder: nameSortOrder, disableAnimations: themeSettings.disableAnimations, largeEmoji: themeSettings.largeEmoji) } public extension PresentationData { func withFontSizes(chatFontSize: PresentationFontSize, listsFontSize: PresentationFontSize) -> PresentationData { - return PresentationData(strings: self.strings, theme: self.theme, autoNightModeTriggered: self.autoNightModeTriggered, chatWallpaper: self.chatWallpaper, chatFontSize: chatFontSize, listsFontSize: listsFontSize, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, nameSortOrder: self.nameSortOrder, disableAnimations: self.disableAnimations, largeEmoji: self.largeEmoji) + return PresentationData(strings: self.strings, theme: self.theme, autoNightModeTriggered: self.autoNightModeTriggered, chatWallpaper: self.chatWallpaper, chatFontSize: chatFontSize, chatBubbleCorners: self.chatBubbleCorners, listsFontSize: listsFontSize, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, nameSortOrder: self.nameSortOrder, disableAnimations: self.disableAnimations, largeEmoji: self.largeEmoji) + } + + func withChatBubbleCorners(_ chatBubbleCorners: PresentationChatBubbleCorners) -> PresentationData { + return PresentationData(strings: self.strings, theme: self.theme, autoNightModeTriggered: self.autoNightModeTriggered, chatWallpaper: self.chatWallpaper, chatFontSize: self.chatFontSize, chatBubbleCorners: chatBubbleCorners, listsFontSize: self.listsFontSize, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, nameSortOrder: self.nameSortOrder, disableAnimations: self.disableAnimations, largeEmoji: self.largeEmoji) } func withStrings(_ strings: PresentationStrings) -> PresentationData { - return PresentationData(strings: strings, theme: self.theme, autoNightModeTriggered: self.autoNightModeTriggered, chatWallpaper: self.chatWallpaper, chatFontSize: self.chatFontSize, listsFontSize: self.listsFontSize, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, nameSortOrder: self.nameSortOrder, disableAnimations: self.disableAnimations, largeEmoji: self.largeEmoji) + return PresentationData(strings: strings, theme: self.theme, autoNightModeTriggered: self.autoNightModeTriggered, chatWallpaper: self.chatWallpaper, chatFontSize: self.chatFontSize, chatBubbleCorners: chatBubbleCorners, listsFontSize: self.listsFontSize, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, nameSortOrder: self.nameSortOrder, disableAnimations: self.disableAnimations, largeEmoji: self.largeEmoji) } } diff --git a/submodules/TelegramPresentationData/Sources/PresentationStrings.swift b/submodules/TelegramPresentationData/Sources/PresentationStrings.swift index d4e4d3501b..221c9c51a5 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationStrings.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationStrings.swift @@ -2403,2916 +2403,2920 @@ public final class PresentationStrings: Equatable { public var ScheduledMessages_SendNow: String { return self._s[2051]! } public var Checkout_NewCard_PaymentCard: String { return self._s[2053]! } public var Login_InfoHelp: String { return self._s[2054]! } - public var Contacts_PermissionsSuppressWarningTitle: String { return self._s[2055]! } - public var SettingsSearch_Synonyms_Stickers_FeaturedPacks: String { return self._s[2056]! } + public var Appearance_BubbleCorners_AdjustAdjacent: String { return self._s[2055]! } + public var Contacts_PermissionsSuppressWarningTitle: String { return self._s[2056]! } + public var SettingsSearch_Synonyms_Stickers_FeaturedPacks: String { return self._s[2057]! } public func Channel_AdminLog_MessageChangedLinkedChannel(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2057]!, self._r[2057]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2058]!, self._r[2058]!, [_1, _2]) } - public var SocksProxySetup_AddProxy: String { return self._s[2060]! } - public var CreatePoll_Title: String { return self._s[2061]! } - public var MessagePoll_QuizNoUsers: String { return self._s[2062]! } - public var Conversation_ViewTheme: String { return self._s[2063]! } - public var SettingsSearch_Synonyms_Privacy_Data_SecretChatLinkPreview: String { return self._s[2064]! } - public var PasscodeSettings_SimplePasscodeHelp: String { return self._s[2065]! } - public var TwoFactorSetup_Intro_Text: String { return self._s[2066]! } - public var UserInfo_GroupsInCommon: String { return self._s[2067]! } - public var TelegramWallet_Intro_TermsUrl: String { return self._s[2068]! } - public var Call_AudioRouteHide: String { return self._s[2069]! } + public var SocksProxySetup_AddProxy: String { return self._s[2061]! } + public var CreatePoll_Title: String { return self._s[2062]! } + public var MessagePoll_QuizNoUsers: String { return self._s[2063]! } + public var Conversation_ViewTheme: String { return self._s[2064]! } + public var SettingsSearch_Synonyms_Privacy_Data_SecretChatLinkPreview: String { return self._s[2065]! } + public var PasscodeSettings_SimplePasscodeHelp: String { return self._s[2066]! } + public var TwoFactorSetup_Intro_Text: String { return self._s[2067]! } + public var UserInfo_GroupsInCommon: String { return self._s[2068]! } + public var TelegramWallet_Intro_TermsUrl: String { return self._s[2069]! } + public var Call_AudioRouteHide: String { return self._s[2070]! } public func Wallet_Info_TransactionDateHeader(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2071]!, self._r[2071]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2072]!, self._r[2072]!, [_1, _2]) } - public var ContactInfo_PhoneLabelMobile: String { return self._s[2072]! } - public var IntentsSettings_SuggestedChatsInfo: String { return self._s[2073]! } - public var CreatePoll_QuizOptionsHeader: String { return self._s[2074]! } + public var ContactInfo_PhoneLabelMobile: String { return self._s[2073]! } + public var IntentsSettings_SuggestedChatsInfo: String { return self._s[2074]! } + public var CreatePoll_QuizOptionsHeader: String { return self._s[2075]! } public func ChatList_LeaveGroupConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2075]!, self._r[2075]!, [_0]) + return formatWithArgumentRanges(self._s[2076]!, self._r[2076]!, [_0]) } - public var TextFormat_Bold: String { return self._s[2076]! } - public var FastTwoStepSetup_EmailSection: String { return self._s[2077]! } - public var StickerPackActionInfo_AddedTitle: String { return self._s[2078]! } - public var Notifications_Title: String { return self._s[2079]! } - public var Group_Username_InvalidTooShort: String { return self._s[2080]! } - public var Channel_ErrorAddTooMuch: String { return self._s[2081]! } + public var TextFormat_Bold: String { return self._s[2077]! } + public var FastTwoStepSetup_EmailSection: String { return self._s[2078]! } + public var StickerPackActionInfo_AddedTitle: String { return self._s[2079]! } + public var Notifications_Title: String { return self._s[2080]! } + public var Group_Username_InvalidTooShort: String { return self._s[2081]! } + public var Channel_ErrorAddTooMuch: String { return self._s[2082]! } public func DialogList_MultipleTypingSuffix(_ _0: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2082]!, self._r[2082]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[2083]!, self._r[2083]!, ["\(_0)"]) } - public var VoiceOver_DiscardPreparedContent: String { return self._s[2084]! } - public var Stickers_SuggestAdded: String { return self._s[2085]! } - public var Login_CountryCode: String { return self._s[2086]! } - public var ChatSettings_AutoPlayVideos: String { return self._s[2087]! } - public var Map_GetDirections: String { return self._s[2088]! } - public var Wallet_Receive_ShareInvoiceUrl: String { return self._s[2089]! } - public var Login_PhoneFloodError: String { return self._s[2090]! } + public var VoiceOver_DiscardPreparedContent: String { return self._s[2085]! } + public var Stickers_SuggestAdded: String { return self._s[2086]! } + public var Login_CountryCode: String { return self._s[2087]! } + public var ChatSettings_AutoPlayVideos: String { return self._s[2088]! } + public var Map_GetDirections: String { return self._s[2089]! } + public var Wallet_Receive_ShareInvoiceUrl: String { return self._s[2090]! } + public var Login_PhoneFloodError: String { return self._s[2091]! } public func Time_MonthOfYear_m3(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2091]!, self._r[2091]!, [_0]) + return formatWithArgumentRanges(self._s[2092]!, self._r[2092]!, [_0]) } public func Wallet_Time_PreciseDate_m10(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2092]!, self._r[2092]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2093]!, self._r[2093]!, [_1, _2, _3]) } - public var IntentsSettings_SuggestedChatsPrivateChats: String { return self._s[2093]! } - public var Settings_SetUsername: String { return self._s[2095]! } - public var Group_Location_ChangeLocation: String { return self._s[2096]! } - public var Notification_GroupInviterSelf: String { return self._s[2097]! } - public var InstantPage_TapToOpenLink: String { return self._s[2098]! } + public var IntentsSettings_SuggestedChatsPrivateChats: String { return self._s[2094]! } + public var Settings_SetUsername: String { return self._s[2096]! } + public var Group_Location_ChangeLocation: String { return self._s[2097]! } + public var Notification_GroupInviterSelf: String { return self._s[2098]! } + public var InstantPage_TapToOpenLink: String { return self._s[2099]! } public func Notification_ChannelInviter(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2099]!, self._r[2099]!, [_0]) + return formatWithArgumentRanges(self._s[2100]!, self._r[2100]!, [_0]) } - public var Watch_Suggestion_TalkLater: String { return self._s[2100]! } - public var SecretChat_Title: String { return self._s[2101]! } - public var Group_UpgradeNoticeText1: String { return self._s[2102]! } - public var AuthSessions_Title: String { return self._s[2103]! } + public var Watch_Suggestion_TalkLater: String { return self._s[2101]! } + public var SecretChat_Title: String { return self._s[2102]! } + public var Group_UpgradeNoticeText1: String { return self._s[2103]! } + public var AuthSessions_Title: String { return self._s[2104]! } public func TextFormat_AddLinkText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2104]!, self._r[2104]!, [_0]) + return formatWithArgumentRanges(self._s[2105]!, self._r[2105]!, [_0]) } - public var PhotoEditor_CropAuto: String { return self._s[2105]! } - public var Channel_About_Title: String { return self._s[2106]! } - public var Theme_ThemeChanged: String { return self._s[2107]! } - public var FastTwoStepSetup_EmailHelp: String { return self._s[2108]! } + public var PhotoEditor_CropAuto: String { return self._s[2106]! } + public var Channel_About_Title: String { return self._s[2107]! } + public var Theme_ThemeChanged: String { return self._s[2108]! } + public var FastTwoStepSetup_EmailHelp: String { return self._s[2109]! } public func Conversation_Bytes(_ _0: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2110]!, self._r[2110]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[2111]!, self._r[2111]!, ["\(_0)"]) } - public var VoiceOver_MessageContextReport: String { return self._s[2111]! } - public var Conversation_PinMessageAlert_OnlyPin: String { return self._s[2113]! } - public var Group_Setup_HistoryVisibleHelp: String { return self._s[2114]! } + public var VoiceOver_MessageContextReport: String { return self._s[2112]! } + public var Conversation_PinMessageAlert_OnlyPin: String { return self._s[2114]! } + public var Group_Setup_HistoryVisibleHelp: String { return self._s[2115]! } public func PUSH_MESSAGE_GIF(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2115]!, self._r[2115]!, [_1]) + return formatWithArgumentRanges(self._s[2116]!, self._r[2116]!, [_1]) } public func SharedMedia_SearchNoResultsDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2117]!, self._r[2117]!, [_0]) - } - public func TwoStepAuth_RecoveryEmailUnavailable(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2118]!, self._r[2118]!, [_0]) } - public var Privacy_PaymentsClearInfoHelp: String { return self._s[2119]! } - public var Presence_online: String { return self._s[2122]! } - public var PasscodeSettings_Title: String { return self._s[2123]! } - public var Passport_Identity_ExpiryDatePlaceholder: String { return self._s[2124]! } - public var Web_OpenExternal: String { return self._s[2125]! } - public var AutoDownloadSettings_AutoDownload: String { return self._s[2127]! } - public var Channel_OwnershipTransfer_EnterPasswordText: String { return self._s[2128]! } - public var LocalGroup_Title: String { return self._s[2129]! } + public func TwoStepAuth_RecoveryEmailUnavailable(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2119]!, self._r[2119]!, [_0]) + } + public var Privacy_PaymentsClearInfoHelp: String { return self._s[2120]! } + public var Presence_online: String { return self._s[2123]! } + public var PasscodeSettings_Title: String { return self._s[2124]! } + public var Passport_Identity_ExpiryDatePlaceholder: String { return self._s[2125]! } + public var Web_OpenExternal: String { return self._s[2126]! } + public var AutoDownloadSettings_AutoDownload: String { return self._s[2128]! } + public var Channel_OwnershipTransfer_EnterPasswordText: String { return self._s[2129]! } + public var LocalGroup_Title: String { return self._s[2130]! } public func AutoNightTheme_AutomaticHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2130]!, self._r[2130]!, [_0]) + return formatWithArgumentRanges(self._s[2131]!, self._r[2131]!, [_0]) } - public var FastTwoStepSetup_PasswordConfirmationPlaceholder: String { return self._s[2131]! } - public var Conversation_StopQuizConfirmation: String { return self._s[2132]! } - public var Map_YouAreHere: String { return self._s[2133]! } + public var FastTwoStepSetup_PasswordConfirmationPlaceholder: String { return self._s[2132]! } + public var Conversation_StopQuizConfirmation: String { return self._s[2133]! } + public var Map_YouAreHere: String { return self._s[2134]! } public func AuthSessions_Message(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2134]!, self._r[2134]!, [_0]) - } - public func ChatList_DeleteChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2135]!, self._r[2135]!, [_0]) } - public var Theme_Context_ChangeColors: String { return self._s[2136]! } - public var PrivacyLastSeenSettings_AlwaysShareWith: String { return self._s[2137]! } - public var Target_InviteToGroupErrorAlreadyInvited: String { return self._s[2138]! } - public func AuthSessions_AppUnofficial(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2139]!, self._r[2139]!, [_0]) + public func ChatList_DeleteChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2136]!, self._r[2136]!, [_0]) } - public func DialogList_LiveLocationSharingTo(_ _0: String) -> (String, [(Int, NSRange)]) { + public var Theme_Context_ChangeColors: String { return self._s[2137]! } + public var PrivacyLastSeenSettings_AlwaysShareWith: String { return self._s[2138]! } + public var Target_InviteToGroupErrorAlreadyInvited: String { return self._s[2139]! } + public func AuthSessions_AppUnofficial(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2140]!, self._r[2140]!, [_0]) } - public var SocksProxySetup_Username: String { return self._s[2141]! } - public var Bot_Start: String { return self._s[2142]! } - public func Channel_AdminLog_EmptyFilterQueryText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2143]!, self._r[2143]!, [_0]) + public func DialogList_LiveLocationSharingTo(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2141]!, self._r[2141]!, [_0]) } - public func Channel_AdminLog_MessagePinned(_ _0: String) -> (String, [(Int, NSRange)]) { + public var SocksProxySetup_Username: String { return self._s[2142]! } + public var Bot_Start: String { return self._s[2143]! } + public func Channel_AdminLog_EmptyFilterQueryText(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2144]!, self._r[2144]!, [_0]) } - public var Contacts_SortByPresence: String { return self._s[2145]! } - public var AccentColor_Title: String { return self._s[2147]! } - public var Conversation_DiscardVoiceMessageTitle: String { return self._s[2148]! } + public func Channel_AdminLog_MessagePinned(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2145]!, self._r[2145]!, [_0]) + } + public var Contacts_SortByPresence: String { return self._s[2146]! } + public var AccentColor_Title: String { return self._s[2148]! } + public var Conversation_DiscardVoiceMessageTitle: String { return self._s[2149]! } public func PUSH_CHAT_CREATED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2149]!, self._r[2149]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2150]!, self._r[2150]!, [_1, _2]) } public func PrivacySettings_LastSeenContactsMinus(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2150]!, self._r[2150]!, [_0]) + return formatWithArgumentRanges(self._s[2151]!, self._r[2151]!, [_0]) } public func Channel_AdminLog_MessageChangedLinkedGroup(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2151]!, self._r[2151]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2152]!, self._r[2152]!, [_1, _2]) } - public var Passport_Email_EnterOtherEmail: String { return self._s[2152]! } - public var Login_InfoAvatarPhoto: String { return self._s[2153]! } - public var Privacy_PaymentsClear_ShippingInfo: String { return self._s[2154]! } - public var Tour_Title4: String { return self._s[2155]! } - public var Passport_Identity_Translation: String { return self._s[2156]! } - public var SettingsSearch_Synonyms_Notifications_ContactJoined: String { return self._s[2157]! } - public var Login_TermsOfServiceLabel: String { return self._s[2159]! } - public var Passport_Language_it: String { return self._s[2160]! } - public var KeyCommand_JumpToNextUnreadChat: String { return self._s[2161]! } - public var Passport_Identity_SelfieHelp: String { return self._s[2162]! } - public var Conversation_ClearAll: String { return self._s[2164]! } - public var Wallet_Send_UninitializedText: String { return self._s[2166]! } - public var Channel_OwnershipTransfer_Title: String { return self._s[2167]! } - public var TwoStepAuth_FloodError: String { return self._s[2168]! } + public var Passport_Email_EnterOtherEmail: String { return self._s[2153]! } + public var Login_InfoAvatarPhoto: String { return self._s[2154]! } + public var Privacy_PaymentsClear_ShippingInfo: String { return self._s[2155]! } + public var Tour_Title4: String { return self._s[2156]! } + public var Passport_Identity_Translation: String { return self._s[2157]! } + public var SettingsSearch_Synonyms_Notifications_ContactJoined: String { return self._s[2158]! } + public var Login_TermsOfServiceLabel: String { return self._s[2160]! } + public var Passport_Language_it: String { return self._s[2161]! } + public var KeyCommand_JumpToNextUnreadChat: String { return self._s[2162]! } + public var Passport_Identity_SelfieHelp: String { return self._s[2163]! } + public var Conversation_ClearAll: String { return self._s[2165]! } + public var Wallet_Send_UninitializedText: String { return self._s[2167]! } + public var Channel_OwnershipTransfer_Title: String { return self._s[2168]! } + public var TwoStepAuth_FloodError: String { return self._s[2169]! } public func PUSH_CHANNEL_MESSAGE_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2169]!, self._r[2169]!, [_1]) + return formatWithArgumentRanges(self._s[2170]!, self._r[2170]!, [_1]) } - public var Paint_Delete: String { return self._s[2170]! } + public var Paint_Delete: String { return self._s[2171]! } public func Wallet_Sent_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2171]!, self._r[2171]!, [_0]) + return formatWithArgumentRanges(self._s[2172]!, self._r[2172]!, [_0]) } - public var Privacy_AddNewPeer: String { return self._s[2172]! } + public var Privacy_AddNewPeer: String { return self._s[2173]! } public func Channel_AdminLog_MessageRank(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2173]!, self._r[2173]!, [_1]) + return formatWithArgumentRanges(self._s[2174]!, self._r[2174]!, [_1]) } - public var LogoutOptions_SetPasscodeText: String { return self._s[2174]! } + public var LogoutOptions_SetPasscodeText: String { return self._s[2175]! } public func Passport_AcceptHelp(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2175]!, self._r[2175]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2176]!, self._r[2176]!, [_1, _2]) } - public var Message_PinnedAudioMessage: String { return self._s[2176]! } + public var Message_PinnedAudioMessage: String { return self._s[2177]! } public func Watch_Time_ShortTodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2177]!, self._r[2177]!, [_0]) + return formatWithArgumentRanges(self._s[2178]!, self._r[2178]!, [_0]) } - public var Notification_Mute1hMin: String { return self._s[2178]! } - public var Notifications_GroupNotificationsSound: String { return self._s[2179]! } - public var Wallet_Month_GenNovember: String { return self._s[2180]! } - public var SocksProxySetup_ShareProxyList: String { return self._s[2181]! } - public var Conversation_MessageEditedLabel: String { return self._s[2182]! } + public var Notification_Mute1hMin: String { return self._s[2179]! } + public var Notifications_GroupNotificationsSound: String { return self._s[2180]! } + public var Wallet_Month_GenNovember: String { return self._s[2181]! } + public var SocksProxySetup_ShareProxyList: String { return self._s[2182]! } + public var Conversation_MessageEditedLabel: String { return self._s[2183]! } public func ClearCache_Success(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2183]!, self._r[2183]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2184]!, self._r[2184]!, [_0, _1]) } - public var Notification_Exceptions_AlwaysOff: String { return self._s[2184]! } - public var Notification_Exceptions_NewException_MessagePreviewHeader: String { return self._s[2185]! } + public var Notification_Exceptions_AlwaysOff: String { return self._s[2185]! } + public var Notification_Exceptions_NewException_MessagePreviewHeader: String { return self._s[2186]! } public func Channel_AdminLog_MessageAdmin(_ _0: String, _ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2186]!, self._r[2186]!, [_0, _1, _2]) + return formatWithArgumentRanges(self._s[2187]!, self._r[2187]!, [_0, _1, _2]) } - public var NetworkUsageSettings_ResetStats: String { return self._s[2187]! } + public var NetworkUsageSettings_ResetStats: String { return self._s[2188]! } public func PUSH_MESSAGE_GEOLIVE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2188]!, self._r[2188]!, [_1]) + return formatWithArgumentRanges(self._s[2189]!, self._r[2189]!, [_1]) } - public var AccessDenied_LocationTracking: String { return self._s[2189]! } - public var Month_GenOctober: String { return self._s[2190]! } - public var GroupInfo_InviteLink_RevokeAlert_Revoke: String { return self._s[2191]! } - public var EnterPasscode_EnterPasscode: String { return self._s[2192]! } - public var MediaPicker_TimerTooltip: String { return self._s[2194]! } - public var SharedMedia_TitleAll: String { return self._s[2195]! } - public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsExceptions: String { return self._s[2198]! } - public var Conversation_RestrictedMedia: String { return self._s[2199]! } - public var AccessDenied_PhotosRestricted: String { return self._s[2200]! } - public var Privacy_Forwards_WhoCanForward: String { return self._s[2202]! } - public var ChangePhoneNumberCode_Called: String { return self._s[2203]! } + public var AccessDenied_LocationTracking: String { return self._s[2190]! } + public var Month_GenOctober: String { return self._s[2191]! } + public var GroupInfo_InviteLink_RevokeAlert_Revoke: String { return self._s[2192]! } + public var EnterPasscode_EnterPasscode: String { return self._s[2193]! } + public var MediaPicker_TimerTooltip: String { return self._s[2195]! } + public var SharedMedia_TitleAll: String { return self._s[2196]! } + public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsExceptions: String { return self._s[2199]! } + public var Conversation_RestrictedMedia: String { return self._s[2200]! } + public var AccessDenied_PhotosRestricted: String { return self._s[2201]! } + public var Privacy_Forwards_WhoCanForward: String { return self._s[2203]! } + public var ChangePhoneNumberCode_Called: String { return self._s[2204]! } public func Notification_PinnedDocumentMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2204]!, self._r[2204]!, [_0]) + return formatWithArgumentRanges(self._s[2205]!, self._r[2205]!, [_0]) } - public var Conversation_SavedMessages: String { return self._s[2207]! } - public var Your_cards_expiration_month_is_invalid: String { return self._s[2209]! } - public var FastTwoStepSetup_PasswordPlaceholder: String { return self._s[2210]! } + public var Conversation_SavedMessages: String { return self._s[2208]! } + public var Your_cards_expiration_month_is_invalid: String { return self._s[2210]! } + public var FastTwoStepSetup_PasswordPlaceholder: String { return self._s[2211]! } public func Target_ShareGameConfirmationGroup(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2212]!, self._r[2212]!, [_0]) + return formatWithArgumentRanges(self._s[2213]!, self._r[2213]!, [_0]) } - public var VoiceOver_Chat_YourMessage: String { return self._s[2213]! } + public var VoiceOver_Chat_YourMessage: String { return self._s[2214]! } public func VoiceOver_Chat_Title(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2214]!, self._r[2214]!, [_0]) + return formatWithArgumentRanges(self._s[2215]!, self._r[2215]!, [_0]) } - public var ReportPeer_AlertSuccess: String { return self._s[2215]! } - public var PhotoEditor_CropAspectRatioOriginal: String { return self._s[2216]! } + public var ReportPeer_AlertSuccess: String { return self._s[2216]! } + public var PhotoEditor_CropAspectRatioOriginal: String { return self._s[2217]! } public func InstantPage_RelatedArticleAuthorAndDateTitle(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2217]!, self._r[2217]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2218]!, self._r[2218]!, [_1, _2]) } - public var Checkout_PasswordEntry_Title: String { return self._s[2218]! } - public var PhotoEditor_FadeTool: String { return self._s[2219]! } - public var Privacy_ContactsReset: String { return self._s[2220]! } + public var Checkout_PasswordEntry_Title: String { return self._s[2219]! } + public var PhotoEditor_FadeTool: String { return self._s[2220]! } + public var Privacy_ContactsReset: String { return self._s[2221]! } public func Channel_AdminLog_MessageRestrictedUntil(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2222]!, self._r[2222]!, [_0]) + return formatWithArgumentRanges(self._s[2223]!, self._r[2223]!, [_0]) } - public var Message_PinnedVideoMessage: String { return self._s[2223]! } - public var ChatList_Mute: String { return self._s[2224]! } + public var Message_PinnedVideoMessage: String { return self._s[2224]! } + public var ChatList_Mute: String { return self._s[2225]! } public func Wallet_Time_PreciseDate_m5(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2225]!, self._r[2225]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2226]!, self._r[2226]!, [_1, _2, _3]) } - public var Permissions_CellularDataText_v0: String { return self._s[2226]! } - public var Conversation_PinnedQuiz: String { return self._s[2228]! } - public var ShareMenu_SelectChats: String { return self._s[2230]! } - public var ChatList_Context_Unarchive: String { return self._s[2231]! } - public var MusicPlayer_VoiceNote: String { return self._s[2232]! } - public var Conversation_RestrictedText: String { return self._s[2233]! } - public var SettingsSearch_Synonyms_Privacy_Data_DeleteDrafts: String { return self._s[2234]! } - public var Wallet_Month_GenApril: String { return self._s[2235]! } - public var Wallet_Month_ShortMarch: String { return self._s[2236]! } - public var TwoStepAuth_DisableSuccess: String { return self._s[2237]! } - public var Cache_Videos: String { return self._s[2238]! } - public var PrivacySettings_PhoneNumber: String { return self._s[2239]! } - public var Wallet_Month_GenFebruary: String { return self._s[2240]! } - public var FeatureDisabled_Oops: String { return self._s[2242]! } - public var Passport_Address_PostcodePlaceholder: String { return self._s[2243]! } + public var Permissions_CellularDataText_v0: String { return self._s[2227]! } + public var Conversation_PinnedQuiz: String { return self._s[2229]! } + public var ShareMenu_SelectChats: String { return self._s[2231]! } + public var ChatList_Context_Unarchive: String { return self._s[2232]! } + public var MusicPlayer_VoiceNote: String { return self._s[2233]! } + public var Conversation_RestrictedText: String { return self._s[2234]! } + public var SettingsSearch_Synonyms_Privacy_Data_DeleteDrafts: String { return self._s[2235]! } + public var Wallet_Month_GenApril: String { return self._s[2236]! } + public var Wallet_Month_ShortMarch: String { return self._s[2237]! } + public var TwoStepAuth_DisableSuccess: String { return self._s[2238]! } + public var Cache_Videos: String { return self._s[2239]! } + public var PrivacySettings_PhoneNumber: String { return self._s[2240]! } + public var Wallet_Month_GenFebruary: String { return self._s[2241]! } + public var FeatureDisabled_Oops: String { return self._s[2243]! } + public var Passport_Address_PostcodePlaceholder: String { return self._s[2244]! } public func AddContact_StatusSuccess(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2244]!, self._r[2244]!, [_0]) + return formatWithArgumentRanges(self._s[2245]!, self._r[2245]!, [_0]) } - public var Stickers_GroupStickersHelp: String { return self._s[2245]! } - public var GroupPermission_NoSendPolls: String { return self._s[2246]! } - public var Wallet_Qr_ScanCode: String { return self._s[2247]! } - public var Message_VideoExpired: String { return self._s[2249]! } - public var GroupInfo_GroupHistoryVisible: String { return self._s[2250]! } - public var Notifications_Badge: String { return self._s[2251]! } - public var Wallet_Receive_AddressCopied: String { return self._s[2252]! } - public var CreatePoll_OptionPlaceholder: String { return self._s[2253]! } - public var Username_InvalidTooShort: String { return self._s[2254]! } - public var EnterPasscode_EnterNewPasscodeChange: String { return self._s[2255]! } - public var Channel_AdminLog_PinMessages: String { return self._s[2256]! } - public var ArchivedChats_IntroTitle3: String { return self._s[2257]! } + public var Stickers_GroupStickersHelp: String { return self._s[2246]! } + public var GroupPermission_NoSendPolls: String { return self._s[2247]! } + public var Wallet_Qr_ScanCode: String { return self._s[2248]! } + public var Message_VideoExpired: String { return self._s[2250]! } + public var GroupInfo_GroupHistoryVisible: String { return self._s[2251]! } + public var Notifications_Badge: String { return self._s[2252]! } + public var Wallet_Receive_AddressCopied: String { return self._s[2253]! } + public var CreatePoll_OptionPlaceholder: String { return self._s[2254]! } + public var Username_InvalidTooShort: String { return self._s[2255]! } + public var EnterPasscode_EnterNewPasscodeChange: String { return self._s[2256]! } + public var Channel_AdminLog_PinMessages: String { return self._s[2257]! } + public var ArchivedChats_IntroTitle3: String { return self._s[2258]! } public func Notification_MessageLifetimeRemoved(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2258]!, self._r[2258]!, [_1]) + return formatWithArgumentRanges(self._s[2259]!, self._r[2259]!, [_1]) } - public var Permissions_SiriAllowInSettings_v0: String { return self._s[2259]! } - public var Conversation_DefaultRestrictedText: String { return self._s[2260]! } - public var SharedMedia_CategoryDocs: String { return self._s[2263]! } + public var Permissions_SiriAllowInSettings_v0: String { return self._s[2260]! } + public var Conversation_DefaultRestrictedText: String { return self._s[2261]! } + public var SharedMedia_CategoryDocs: String { return self._s[2264]! } public func PUSH_MESSAGE_CONTACT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2264]!, self._r[2264]!, [_1]) + return formatWithArgumentRanges(self._s[2265]!, self._r[2265]!, [_1]) } - public var Wallet_Send_UninitializedTitle: String { return self._s[2265]! } - public var StickerPackActionInfo_ArchivedTitle: String { return self._s[2266]! } - public var Privacy_Forwards_NeverLink: String { return self._s[2268]! } + public var Wallet_Send_UninitializedTitle: String { return self._s[2266]! } + public var StickerPackActionInfo_ArchivedTitle: String { return self._s[2267]! } + public var Privacy_Forwards_NeverLink: String { return self._s[2269]! } public func Notification_MessageLifetimeChangedOutgoing(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2269]!, self._r[2269]!, [_1]) + return formatWithArgumentRanges(self._s[2270]!, self._r[2270]!, [_1]) } - public var CheckoutInfo_ErrorShippingNotAvailable: String { return self._s[2270]! } + public var CheckoutInfo_ErrorShippingNotAvailable: String { return self._s[2271]! } public func Time_MonthOfYear_m12(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2271]!, self._r[2271]!, [_0]) + return formatWithArgumentRanges(self._s[2272]!, self._r[2272]!, [_0]) } - public var ChatSettings_PrivateChats: String { return self._s[2272]! } - public var SettingsSearch_Synonyms_EditProfile_Logout: String { return self._s[2273]! } - public var Conversation_PrivateMessageLinkCopied: String { return self._s[2274]! } - public var Channel_UpdatePhotoItem: String { return self._s[2275]! } - public var GroupInfo_LeftStatus: String { return self._s[2276]! } - public var Watch_MessageView_Forward: String { return self._s[2278]! } - public var ReportPeer_ReasonChildAbuse: String { return self._s[2279]! } - public var Cache_ClearEmpty: String { return self._s[2281]! } - public var Localization_LanguageName: String { return self._s[2282]! } - public var Wallet_AccessDenied_Title: String { return self._s[2283]! } - public var WebSearch_GIFs: String { return self._s[2284]! } - public var Notifications_DisplayNamesOnLockScreenInfoWithLink: String { return self._s[2285]! } - public var Wallet_AccessDenied_Settings: String { return self._s[2286]! } - public var Username_InvalidStartsWithNumber: String { return self._s[2287]! } - public var Common_Back: String { return self._s[2288]! } - public var GroupInfo_Permissions_EditingDisabled: String { return self._s[2289]! } - public var Passport_Identity_DateOfBirthPlaceholder: String { return self._s[2290]! } - public var Wallet_Send_Send: String { return self._s[2291]! } + public var ChatSettings_PrivateChats: String { return self._s[2273]! } + public var SettingsSearch_Synonyms_EditProfile_Logout: String { return self._s[2274]! } + public var Conversation_PrivateMessageLinkCopied: String { return self._s[2275]! } + public var Channel_UpdatePhotoItem: String { return self._s[2276]! } + public var GroupInfo_LeftStatus: String { return self._s[2277]! } + public var Watch_MessageView_Forward: String { return self._s[2279]! } + public var ReportPeer_ReasonChildAbuse: String { return self._s[2280]! } + public var Cache_ClearEmpty: String { return self._s[2282]! } + public var Localization_LanguageName: String { return self._s[2283]! } + public var Wallet_AccessDenied_Title: String { return self._s[2284]! } + public var WebSearch_GIFs: String { return self._s[2285]! } + public var Notifications_DisplayNamesOnLockScreenInfoWithLink: String { return self._s[2286]! } + public var Wallet_AccessDenied_Settings: String { return self._s[2287]! } + public var Username_InvalidStartsWithNumber: String { return self._s[2288]! } + public var Common_Back: String { return self._s[2289]! } + public var GroupInfo_Permissions_EditingDisabled: String { return self._s[2290]! } + public var Passport_Identity_DateOfBirthPlaceholder: String { return self._s[2291]! } + public var Wallet_Send_Send: String { return self._s[2292]! } public func PUSH_CHANNEL_MESSAGE_STICKER(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2293]!, self._r[2293]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2294]!, self._r[2294]!, [_1, _2]) } - public var Wallet_Info_RefreshErrorTitle: String { return self._s[2294]! } - public var Wallet_Month_GenJune: String { return self._s[2295]! } - public var Passport_Email_Help: String { return self._s[2296]! } - public var Watch_Conversation_Reply: String { return self._s[2298]! } - public var Conversation_EditingMessageMediaChange: String { return self._s[2301]! } - public var Passport_Identity_IssueDatePlaceholder: String { return self._s[2302]! } - public var Channel_BanUser_Unban: String { return self._s[2304]! } - public var Channel_EditAdmin_PermissionPostMessages: String { return self._s[2305]! } - public var Group_Username_CreatePublicLinkHelp: String { return self._s[2306]! } - public var TwoStepAuth_ConfirmEmailCodePlaceholder: String { return self._s[2308]! } - public var Wallet_Send_AddressHeader: String { return self._s[2309]! } - public var Passport_Identity_Name: String { return self._s[2310]! } + public var Wallet_Info_RefreshErrorTitle: String { return self._s[2295]! } + public var Wallet_Month_GenJune: String { return self._s[2296]! } + public var Passport_Email_Help: String { return self._s[2297]! } + public var Watch_Conversation_Reply: String { return self._s[2299]! } + public var Conversation_EditingMessageMediaChange: String { return self._s[2302]! } + public var Passport_Identity_IssueDatePlaceholder: String { return self._s[2303]! } + public var Channel_BanUser_Unban: String { return self._s[2305]! } + public var Channel_EditAdmin_PermissionPostMessages: String { return self._s[2306]! } + public var Group_Username_CreatePublicLinkHelp: String { return self._s[2307]! } + public var TwoStepAuth_ConfirmEmailCodePlaceholder: String { return self._s[2309]! } + public var Wallet_Send_AddressHeader: String { return self._s[2310]! } + public var Passport_Identity_Name: String { return self._s[2311]! } public func Channel_DiscussionGroup_HeaderGroupSet(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2311]!, self._r[2311]!, [_0]) + return formatWithArgumentRanges(self._s[2312]!, self._r[2312]!, [_0]) } - public var GroupRemoved_ViewUserInfo: String { return self._s[2312]! } - public var Conversation_BlockUser: String { return self._s[2313]! } - public var Month_GenJanuary: String { return self._s[2314]! } - public var ChatSettings_TextSize: String { return self._s[2315]! } - public var Notification_PassportValuePhone: String { return self._s[2316]! } - public var MediaPlayer_UnknownArtist: String { return self._s[2317]! } - public var Passport_Language_ne: String { return self._s[2318]! } - public var Notification_CallBack: String { return self._s[2319]! } - public var Wallet_SecureStorageReset_BiometryTouchId: String { return self._s[2320]! } - public var TwoStepAuth_EmailHelp: String { return self._s[2321]! } + public var GroupRemoved_ViewUserInfo: String { return self._s[2313]! } + public var Conversation_BlockUser: String { return self._s[2314]! } + public var Month_GenJanuary: String { return self._s[2315]! } + public var ChatSettings_TextSize: String { return self._s[2316]! } + public var Notification_PassportValuePhone: String { return self._s[2317]! } + public var MediaPlayer_UnknownArtist: String { return self._s[2318]! } + public var Passport_Language_ne: String { return self._s[2319]! } + public var Notification_CallBack: String { return self._s[2320]! } + public var Wallet_SecureStorageReset_BiometryTouchId: String { return self._s[2321]! } + public var TwoStepAuth_EmailHelp: String { return self._s[2322]! } public func Time_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2322]!, self._r[2322]!, [_0]) + return formatWithArgumentRanges(self._s[2323]!, self._r[2323]!, [_0]) } - public var Channel_Info_Management: String { return self._s[2323]! } - public var Passport_FieldIdentityUploadHelp: String { return self._s[2324]! } - public var Stickers_FrequentlyUsed: String { return self._s[2325]! } - public var Channel_BanUser_PermissionSendMessages: String { return self._s[2326]! } - public var Passport_Address_OneOfTypeUtilityBill: String { return self._s[2328]! } + public var Channel_Info_Management: String { return self._s[2324]! } + public var Passport_FieldIdentityUploadHelp: String { return self._s[2325]! } + public var Stickers_FrequentlyUsed: String { return self._s[2326]! } + public var Channel_BanUser_PermissionSendMessages: String { return self._s[2327]! } + public var Passport_Address_OneOfTypeUtilityBill: String { return self._s[2329]! } public func LOCAL_CHANNEL_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2329]!, self._r[2329]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[2330]!, self._r[2330]!, [_1, "\(_2)"]) } - public var TwoFactorSetup_Password_Title: String { return self._s[2330]! } - public var Passport_Address_EditResidentialAddress: String { return self._s[2331]! } - public var PrivacyPolicy_DeclineTitle: String { return self._s[2332]! } - public var CreatePoll_TextHeader: String { return self._s[2333]! } + public var TwoFactorSetup_Password_Title: String { return self._s[2331]! } + public var Passport_Address_EditResidentialAddress: String { return self._s[2332]! } + public var PrivacyPolicy_DeclineTitle: String { return self._s[2333]! } + public var CreatePoll_TextHeader: String { return self._s[2334]! } public func Checkout_SavePasswordTimeoutAndTouchId(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2334]!, self._r[2334]!, [_0]) + return formatWithArgumentRanges(self._s[2335]!, self._r[2335]!, [_0]) } - public var PhotoEditor_QualityMedium: String { return self._s[2335]! } - public var InfoPlist_NSMicrophoneUsageDescription: String { return self._s[2336]! } - public var Conversation_StatusKickedFromChannel: String { return self._s[2338]! } - public var CheckoutInfo_ReceiverInfoName: String { return self._s[2339]! } - public var Group_ErrorSendRestrictedStickers: String { return self._s[2340]! } + public var PhotoEditor_QualityMedium: String { return self._s[2336]! } + public var InfoPlist_NSMicrophoneUsageDescription: String { return self._s[2337]! } + public var Conversation_StatusKickedFromChannel: String { return self._s[2339]! } + public var CheckoutInfo_ReceiverInfoName: String { return self._s[2340]! } + public var Group_ErrorSendRestrictedStickers: String { return self._s[2341]! } public func Conversation_RestrictedInlineTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2341]!, self._r[2341]!, [_0]) + return formatWithArgumentRanges(self._s[2342]!, self._r[2342]!, [_0]) } public func Channel_AdminLog_MessageTransferedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2342]!, self._r[2342]!, [_1]) + return formatWithArgumentRanges(self._s[2343]!, self._r[2343]!, [_1]) } - public var LogoutOptions_LogOutWalletInfo: String { return self._s[2343]! } - public var TwoFactorSetup_Email_SkipConfirmationTitle: String { return self._s[2344]! } - public var Conversation_LinkDialogOpen: String { return self._s[2346]! } - public var TwoFactorSetup_Hint_Title: String { return self._s[2347]! } - public var VoiceOver_Chat_PollNoVotes: String { return self._s[2348]! } - public var Settings_Username: String { return self._s[2350]! } - public var Conversation_Block: String { return self._s[2352]! } - public var Wallpaper_Wallpaper: String { return self._s[2353]! } - public var SocksProxySetup_UseProxy: String { return self._s[2355]! } - public var Wallet_Send_Confirmation: String { return self._s[2356]! } - public var EditTheme_UploadEditedTheme: String { return self._s[2357]! } - public var UserInfo_ShareMyContactInfo: String { return self._s[2358]! } - public var MessageTimer_Forever: String { return self._s[2359]! } - public var Privacy_Calls_WhoCanCallMe: String { return self._s[2360]! } - public var PhotoEditor_DiscardChanges: String { return self._s[2361]! } - public var AuthSessions_TerminateOtherSessionsHelp: String { return self._s[2362]! } - public var Passport_Language_da: String { return self._s[2363]! } - public var SocksProxySetup_PortPlaceholder: String { return self._s[2364]! } + public var LogoutOptions_LogOutWalletInfo: String { return self._s[2344]! } + public var TwoFactorSetup_Email_SkipConfirmationTitle: String { return self._s[2345]! } + public var Conversation_LinkDialogOpen: String { return self._s[2347]! } + public var TwoFactorSetup_Hint_Title: String { return self._s[2348]! } + public var VoiceOver_Chat_PollNoVotes: String { return self._s[2349]! } + public var Settings_Username: String { return self._s[2351]! } + public var Conversation_Block: String { return self._s[2353]! } + public var Wallpaper_Wallpaper: String { return self._s[2354]! } + public var SocksProxySetup_UseProxy: String { return self._s[2356]! } + public var Wallet_Send_Confirmation: String { return self._s[2357]! } + public var EditTheme_UploadEditedTheme: String { return self._s[2358]! } + public var UserInfo_ShareMyContactInfo: String { return self._s[2359]! } + public var MessageTimer_Forever: String { return self._s[2360]! } + public var Privacy_Calls_WhoCanCallMe: String { return self._s[2361]! } + public var PhotoEditor_DiscardChanges: String { return self._s[2362]! } + public var AuthSessions_TerminateOtherSessionsHelp: String { return self._s[2363]! } + public var Passport_Language_da: String { return self._s[2364]! } + public var SocksProxySetup_PortPlaceholder: String { return self._s[2365]! } public func SecretGIF_NotViewedYet(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2365]!, self._r[2365]!, [_0]) + return formatWithArgumentRanges(self._s[2366]!, self._r[2366]!, [_0]) } - public var Passport_Address_EditPassportRegistration: String { return self._s[2366]! } + public var Passport_Address_EditPassportRegistration: String { return self._s[2367]! } public func Channel_AdminLog_MessageChangedGroupAbout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2368]!, self._r[2368]!, [_0]) + return formatWithArgumentRanges(self._s[2369]!, self._r[2369]!, [_0]) } - public var Settings_AddDevice: String { return self._s[2369]! } - public var Passport_Identity_ResidenceCountryPlaceholder: String { return self._s[2371]! } - public var AuthSessions_AddDeviceIntro_Text1: String { return self._s[2372]! } - public var Conversation_SearchByName_Prefix: String { return self._s[2373]! } - public var Conversation_PinnedPoll: String { return self._s[2374]! } - public var AuthSessions_AddDeviceIntro_Text2: String { return self._s[2375]! } - public var Conversation_EmptyGifPanelPlaceholder: String { return self._s[2376]! } - public var AuthSessions_AddDeviceIntro_Text3: String { return self._s[2377]! } + public var Settings_AddDevice: String { return self._s[2370]! } + public var Passport_Identity_ResidenceCountryPlaceholder: String { return self._s[2372]! } + public var AuthSessions_AddDeviceIntro_Text1: String { return self._s[2373]! } + public var Conversation_SearchByName_Prefix: String { return self._s[2374]! } + public var Conversation_PinnedPoll: String { return self._s[2375]! } + public var AuthSessions_AddDeviceIntro_Text2: String { return self._s[2376]! } + public var Conversation_EmptyGifPanelPlaceholder: String { return self._s[2377]! } + public var AuthSessions_AddDeviceIntro_Text3: String { return self._s[2378]! } public func PUSH_ENCRYPTION_ACCEPT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2378]!, self._r[2378]!, [_1]) + return formatWithArgumentRanges(self._s[2379]!, self._r[2379]!, [_1]) } - public var WallpaperSearch_ColorPurple: String { return self._s[2379]! } - public var Cache_ByPeerHeader: String { return self._s[2380]! } + public var WallpaperSearch_ColorPurple: String { return self._s[2380]! } + public var Cache_ByPeerHeader: String { return self._s[2381]! } public func Conversation_EncryptedPlaceholderTitleIncoming(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2381]!, self._r[2381]!, [_0]) + return formatWithArgumentRanges(self._s[2382]!, self._r[2382]!, [_0]) } - public var ChatSettings_AutoDownloadDocuments: String { return self._s[2382]! } - public var Appearance_ThemePreview_Chat_3_Text: String { return self._s[2385]! } - public var Wallet_Completed_Title: String { return self._s[2386]! } - public var Notification_PinnedMessage: String { return self._s[2387]! } - public var TwoFactorSetup_EmailVerification_Placeholder: String { return self._s[2388]! } - public var VoiceOver_Chat_RecordModeVideoMessage: String { return self._s[2390]! } - public var Contacts_SortBy: String { return self._s[2391]! } + public var ChatSettings_AutoDownloadDocuments: String { return self._s[2383]! } + public var Appearance_ThemePreview_Chat_3_Text: String { return self._s[2386]! } + public var Wallet_Completed_Title: String { return self._s[2387]! } + public var Notification_PinnedMessage: String { return self._s[2388]! } + public var TwoFactorSetup_EmailVerification_Placeholder: String { return self._s[2389]! } + public var VoiceOver_Chat_RecordModeVideoMessage: String { return self._s[2391]! } + public var Contacts_SortBy: String { return self._s[2392]! } public func PUSH_CHANNEL_MESSAGE_NOTEXT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2392]!, self._r[2392]!, [_1]) + return formatWithArgumentRanges(self._s[2393]!, self._r[2393]!, [_1]) } - public var Appearance_ColorThemeNight: String { return self._s[2394]! } + public var Appearance_ColorThemeNight: String { return self._s[2395]! } public func PUSH_MESSAGE_GAME(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2395]!, self._r[2395]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2396]!, self._r[2396]!, [_1, _2]) } - public var Call_EncryptionKey_Title: String { return self._s[2396]! } - public var Watch_UserInfo_Service: String { return self._s[2397]! } - public var SettingsSearch_Synonyms_Data_SaveEditedPhotos: String { return self._s[2399]! } - public var Conversation_Unpin: String { return self._s[2401]! } - public var CancelResetAccount_Title: String { return self._s[2402]! } - public var Map_LiveLocationFor15Minutes: String { return self._s[2403]! } + public var Call_EncryptionKey_Title: String { return self._s[2397]! } + public var Watch_UserInfo_Service: String { return self._s[2398]! } + public var SettingsSearch_Synonyms_Data_SaveEditedPhotos: String { return self._s[2400]! } + public var Conversation_Unpin: String { return self._s[2402]! } + public var CancelResetAccount_Title: String { return self._s[2403]! } + public var Map_LiveLocationFor15Minutes: String { return self._s[2404]! } public func Time_PreciseDate_m8(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2405]!, self._r[2405]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2406]!, self._r[2406]!, [_1, _2, _3]) } - public var Group_Members_AddMemberBotErrorNotAllowed: String { return self._s[2406]! } - public var CallSettings_Title: String { return self._s[2407]! } - public var SettingsSearch_Synonyms_Appearance_ChatBackground: String { return self._s[2408]! } - public var PasscodeSettings_EncryptDataHelp: String { return self._s[2410]! } - public var AutoDownloadSettings_Contacts: String { return self._s[2411]! } + public var Group_Members_AddMemberBotErrorNotAllowed: String { return self._s[2407]! } + public var Appearance_BubbleCorners_Title: String { return self._s[2408]! } + public var CallSettings_Title: String { return self._s[2409]! } + public var SettingsSearch_Synonyms_Appearance_ChatBackground: String { return self._s[2410]! } + public var PasscodeSettings_EncryptDataHelp: String { return self._s[2412]! } + public var AutoDownloadSettings_Contacts: String { return self._s[2413]! } public func Channel_AdminLog_MessageRankName(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2412]!, self._r[2412]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2414]!, self._r[2414]!, [_1, _2]) } - public var Passport_Identity_DocumentDetails: String { return self._s[2413]! } - public var LoginPassword_PasswordHelp: String { return self._s[2414]! } - public var SettingsSearch_Synonyms_Data_AutoDownloadUsingWifi: String { return self._s[2415]! } - public var PrivacyLastSeenSettings_CustomShareSettings_Delete: String { return self._s[2416]! } - public var ChatContextMenu_TextSelectionTip: String { return self._s[2417]! } - public var Checkout_TotalPaidAmount: String { return self._s[2418]! } + public var Passport_Identity_DocumentDetails: String { return self._s[2415]! } + public var LoginPassword_PasswordHelp: String { return self._s[2416]! } + public var SettingsSearch_Synonyms_Data_AutoDownloadUsingWifi: String { return self._s[2417]! } + public var PrivacyLastSeenSettings_CustomShareSettings_Delete: String { return self._s[2418]! } + public var ChatContextMenu_TextSelectionTip: String { return self._s[2419]! } + public var Checkout_TotalPaidAmount: String { return self._s[2420]! } public func FileSize_KB(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2419]!, self._r[2419]!, [_0]) + return formatWithArgumentRanges(self._s[2421]!, self._r[2421]!, [_0]) } - public var PasscodeSettings_ChangePasscode: String { return self._s[2420]! } - public var Conversation_SecretLinkPreviewAlert: String { return self._s[2422]! } - public var Privacy_SecretChatsLinkPreviews: String { return self._s[2423]! } + public var PasscodeSettings_ChangePasscode: String { return self._s[2422]! } + public var Conversation_SecretLinkPreviewAlert: String { return self._s[2424]! } + public var Privacy_SecretChatsLinkPreviews: String { return self._s[2425]! } public func PUSH_CHANNEL_MESSAGE_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2424]!, self._r[2424]!, [_1]) + return formatWithArgumentRanges(self._s[2426]!, self._r[2426]!, [_1]) } - public var VoiceOver_Chat_ReplyToYourMessage: String { return self._s[2425]! } - public var Contacts_InviteFriends: String { return self._s[2427]! } - public var Map_ChooseLocationTitle: String { return self._s[2428]! } - public var Conversation_StopPoll: String { return self._s[2430]! } + public var VoiceOver_Chat_ReplyToYourMessage: String { return self._s[2427]! } + public var Contacts_InviteFriends: String { return self._s[2429]! } + public var Map_ChooseLocationTitle: String { return self._s[2430]! } + public var Conversation_StopPoll: String { return self._s[2432]! } public func WebSearch_SearchNoResultsDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2431]!, self._r[2431]!, [_0]) + return formatWithArgumentRanges(self._s[2433]!, self._r[2433]!, [_0]) } - public var Call_Camera: String { return self._s[2432]! } - public var LogoutOptions_ChangePhoneNumberTitle: String { return self._s[2433]! } - public var AppWallet_Intro_Text: String { return self._s[2434]! } - public var Calls_RatingFeedback: String { return self._s[2435]! } - public var GroupInfo_BroadcastListNamePlaceholder: String { return self._s[2437]! } - public var Wallet_Alert_OK: String { return self._s[2438]! } - public var NotificationsSound_Pulse: String { return self._s[2439]! } - public var Watch_LastSeen_Lately: String { return self._s[2440]! } - public var ReportGroupLocation_Report: String { return self._s[2443]! } - public var Widget_NoUsers: String { return self._s[2444]! } - public var Conversation_UnvotePoll: String { return self._s[2445]! } - public var SettingsSearch_Synonyms_Privacy_ProfilePhoto: String { return self._s[2447]! } - public var Privacy_ProfilePhoto_WhoCanSeeMyPhoto: String { return self._s[2448]! } - public var NotificationsSound_Circles: String { return self._s[2449]! } - public var PrivacyLastSeenSettings_AlwaysShareWith_Title: String { return self._s[2452]! } - public var Wallet_Settings_DeleteWallet: String { return self._s[2453]! } - public var TwoStepAuth_RecoveryCodeExpired: String { return self._s[2454]! } - public var Proxy_TooltipUnavailable: String { return self._s[2455]! } - public var Passport_Identity_CountryPlaceholder: String { return self._s[2457]! } - public var GroupInfo_Permissions_SlowmodeInfo: String { return self._s[2459]! } - public var Conversation_FileDropbox: String { return self._s[2460]! } - public var Notifications_ExceptionsUnmuted: String { return self._s[2461]! } - public var Tour_Text3: String { return self._s[2463]! } - public var Login_ResetAccountProtected_Title: String { return self._s[2465]! } - public var GroupPermission_NoSendMessages: String { return self._s[2466]! } - public var WallpaperSearch_ColorTitle: String { return self._s[2467]! } - public var ChatAdmins_AllMembersAreAdminsOnHelp: String { return self._s[2468]! } + public var Call_Camera: String { return self._s[2434]! } + public var LogoutOptions_ChangePhoneNumberTitle: String { return self._s[2435]! } + public var AppWallet_Intro_Text: String { return self._s[2436]! } + public var Appearance_BubbleCornersSetting: String { return self._s[2437]! } + public var Calls_RatingFeedback: String { return self._s[2438]! } + public var GroupInfo_BroadcastListNamePlaceholder: String { return self._s[2440]! } + public var Wallet_Alert_OK: String { return self._s[2441]! } + public var NotificationsSound_Pulse: String { return self._s[2442]! } + public var Watch_LastSeen_Lately: String { return self._s[2443]! } + public var ReportGroupLocation_Report: String { return self._s[2446]! } + public var Widget_NoUsers: String { return self._s[2447]! } + public var Conversation_UnvotePoll: String { return self._s[2448]! } + public var SettingsSearch_Synonyms_Privacy_ProfilePhoto: String { return self._s[2450]! } + public var Privacy_ProfilePhoto_WhoCanSeeMyPhoto: String { return self._s[2451]! } + public var NotificationsSound_Circles: String { return self._s[2452]! } + public var PrivacyLastSeenSettings_AlwaysShareWith_Title: String { return self._s[2455]! } + public var Wallet_Settings_DeleteWallet: String { return self._s[2456]! } + public var TwoStepAuth_RecoveryCodeExpired: String { return self._s[2457]! } + public var Proxy_TooltipUnavailable: String { return self._s[2458]! } + public var Passport_Identity_CountryPlaceholder: String { return self._s[2460]! } + public var GroupInfo_Permissions_SlowmodeInfo: String { return self._s[2462]! } + public var Conversation_FileDropbox: String { return self._s[2463]! } + public var Notifications_ExceptionsUnmuted: String { return self._s[2464]! } + public var Tour_Text3: String { return self._s[2466]! } + public var Login_ResetAccountProtected_Title: String { return self._s[2468]! } + public var GroupPermission_NoSendMessages: String { return self._s[2469]! } + public var WallpaperSearch_ColorTitle: String { return self._s[2470]! } + public var ChatAdmins_AllMembersAreAdminsOnHelp: String { return self._s[2471]! } public func Conversation_LiveLocationYouAnd(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2470]!, self._r[2470]!, [_0]) + return formatWithArgumentRanges(self._s[2473]!, self._r[2473]!, [_0]) } - public var GroupInfo_AddParticipantTitle: String { return self._s[2471]! } - public var Checkout_ShippingOption_Title: String { return self._s[2472]! } - public var ChatSettings_AutoDownloadTitle: String { return self._s[2473]! } + public var GroupInfo_AddParticipantTitle: String { return self._s[2474]! } + public var Checkout_ShippingOption_Title: String { return self._s[2475]! } + public var ChatSettings_AutoDownloadTitle: String { return self._s[2476]! } public func DialogList_SingleTypingSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2474]!, self._r[2474]!, [_0]) + return formatWithArgumentRanges(self._s[2477]!, self._r[2477]!, [_0]) } public func ChatSettings_AutoDownloadSettings_TypeVideo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2475]!, self._r[2475]!, [_0]) + return formatWithArgumentRanges(self._s[2478]!, self._r[2478]!, [_0]) } - public var Channel_Management_LabelAdministrator: String { return self._s[2476]! } - public var EditTheme_FileReadError: String { return self._s[2477]! } - public var OwnershipTransfer_ComeBackLater: String { return self._s[2478]! } - public var PrivacyLastSeenSettings_NeverShareWith_Placeholder: String { return self._s[2479]! } - public var AutoDownloadSettings_Photos: String { return self._s[2481]! } - public var Appearance_PreviewIncomingText: String { return self._s[2482]! } - public var ChatList_Context_MarkAllAsRead: String { return self._s[2483]! } - public var ChannelInfo_ConfirmLeave: String { return self._s[2484]! } - public var MediaPicker_MomentsDateRangeSameMonthYearFormat: String { return self._s[2485]! } - public var Passport_Identity_DocumentNumberPlaceholder: String { return self._s[2486]! } - public var Channel_AdminLogFilter_EventsNewMembers: String { return self._s[2487]! } - public var PasscodeSettings_AutoLock_IfAwayFor_5minutes: String { return self._s[2488]! } - public var GroupInfo_SetGroupPhotoStop: String { return self._s[2489]! } - public var Notification_SecretChatScreenshot: String { return self._s[2490]! } - public var AccessDenied_Wallpapers: String { return self._s[2491]! } - public var ChatList_Context_Mute: String { return self._s[2493]! } - public var Passport_Address_City: String { return self._s[2494]! } - public var InfoPlist_NSPhotoLibraryAddUsageDescription: String { return self._s[2495]! } - public var Appearance_ThemeCarouselClassic: String { return self._s[2496]! } - public var SocksProxySetup_SecretPlaceholder: String { return self._s[2497]! } - public var AccessDenied_LocationDisabled: String { return self._s[2498]! } - public var Group_Location_Title: String { return self._s[2499]! } - public var SocksProxySetup_HostnamePlaceholder: String { return self._s[2501]! } - public var GroupInfo_Sound: String { return self._s[2502]! } - public var SettingsSearch_Synonyms_ChatSettings_OpenLinksIn: String { return self._s[2503]! } - public var ChannelInfo_ScamChannelWarning: String { return self._s[2504]! } - public var Stickers_RemoveFromFavorites: String { return self._s[2505]! } - public var Contacts_Title: String { return self._s[2506]! } - public var EditTheme_ThemeTemplateAlertText: String { return self._s[2507]! } - public var Passport_Language_fr: String { return self._s[2508]! } - public var TwoFactorSetup_EmailVerification_Action: String { return self._s[2509]! } - public var Notifications_ResetAllNotifications: String { return self._s[2510]! } - public var IntentsSettings_SuggestedChats: String { return self._s[2512]! } - public var PrivacySettings_SecurityTitle: String { return self._s[2514]! } - public var Checkout_NewCard_Title: String { return self._s[2515]! } - public var Login_HaveNotReceivedCodeInternal: String { return self._s[2516]! } - public var Conversation_ForwardChats: String { return self._s[2517]! } - public var Wallet_SecureStorageReset_PasscodeText: String { return self._s[2519]! } - public var PasscodeSettings_4DigitCode: String { return self._s[2520]! } - public var Settings_FAQ: String { return self._s[2522]! } - public var AutoDownloadSettings_DocumentsTitle: String { return self._s[2523]! } - public var Conversation_ContextMenuForward: String { return self._s[2524]! } - public var VoiceOver_Chat_YourPhoto: String { return self._s[2527]! } - public var PrivacyPolicy_Title: String { return self._s[2530]! } - public var Notifications_TextTone: String { return self._s[2531]! } - public var Profile_CreateNewContact: String { return self._s[2532]! } - public var PrivacyPhoneNumberSettings_WhoCanSeeMyPhoneNumber: String { return self._s[2533]! } - public var TwoFactorSetup_EmailVerification_Title: String { return self._s[2535]! } - public var Call_Speaker: String { return self._s[2536]! } - public var AutoNightTheme_AutomaticSection: String { return self._s[2537]! } - public var Channel_OwnershipTransfer_EnterPassword: String { return self._s[2539]! } - public var Channel_Username_InvalidCharacters: String { return self._s[2540]! } + public var Channel_Management_LabelAdministrator: String { return self._s[2479]! } + public var EditTheme_FileReadError: String { return self._s[2480]! } + public var OwnershipTransfer_ComeBackLater: String { return self._s[2481]! } + public var PrivacyLastSeenSettings_NeverShareWith_Placeholder: String { return self._s[2482]! } + public var AutoDownloadSettings_Photos: String { return self._s[2484]! } + public var Appearance_PreviewIncomingText: String { return self._s[2485]! } + public var ChatList_Context_MarkAllAsRead: String { return self._s[2486]! } + public var ChannelInfo_ConfirmLeave: String { return self._s[2487]! } + public var MediaPicker_MomentsDateRangeSameMonthYearFormat: String { return self._s[2488]! } + public var Passport_Identity_DocumentNumberPlaceholder: String { return self._s[2489]! } + public var Channel_AdminLogFilter_EventsNewMembers: String { return self._s[2490]! } + public var PasscodeSettings_AutoLock_IfAwayFor_5minutes: String { return self._s[2491]! } + public var GroupInfo_SetGroupPhotoStop: String { return self._s[2492]! } + public var Notification_SecretChatScreenshot: String { return self._s[2493]! } + public var AccessDenied_Wallpapers: String { return self._s[2494]! } + public var ChatList_Context_Mute: String { return self._s[2496]! } + public var Passport_Address_City: String { return self._s[2497]! } + public var InfoPlist_NSPhotoLibraryAddUsageDescription: String { return self._s[2498]! } + public var Appearance_ThemeCarouselClassic: String { return self._s[2499]! } + public var SocksProxySetup_SecretPlaceholder: String { return self._s[2500]! } + public var AccessDenied_LocationDisabled: String { return self._s[2501]! } + public var Group_Location_Title: String { return self._s[2502]! } + public var SocksProxySetup_HostnamePlaceholder: String { return self._s[2504]! } + public var GroupInfo_Sound: String { return self._s[2505]! } + public var SettingsSearch_Synonyms_ChatSettings_OpenLinksIn: String { return self._s[2506]! } + public var ChannelInfo_ScamChannelWarning: String { return self._s[2507]! } + public var Stickers_RemoveFromFavorites: String { return self._s[2508]! } + public var Contacts_Title: String { return self._s[2509]! } + public var EditTheme_ThemeTemplateAlertText: String { return self._s[2510]! } + public var Passport_Language_fr: String { return self._s[2511]! } + public var TwoFactorSetup_EmailVerification_Action: String { return self._s[2512]! } + public var Notifications_ResetAllNotifications: String { return self._s[2513]! } + public var IntentsSettings_SuggestedChats: String { return self._s[2515]! } + public var PrivacySettings_SecurityTitle: String { return self._s[2517]! } + public var Checkout_NewCard_Title: String { return self._s[2518]! } + public var Login_HaveNotReceivedCodeInternal: String { return self._s[2519]! } + public var Conversation_ForwardChats: String { return self._s[2520]! } + public var Wallet_SecureStorageReset_PasscodeText: String { return self._s[2522]! } + public var PasscodeSettings_4DigitCode: String { return self._s[2523]! } + public var Settings_FAQ: String { return self._s[2525]! } + public var AutoDownloadSettings_DocumentsTitle: String { return self._s[2526]! } + public var Conversation_ContextMenuForward: String { return self._s[2527]! } + public var VoiceOver_Chat_YourPhoto: String { return self._s[2530]! } + public var PrivacyPolicy_Title: String { return self._s[2533]! } + public var Notifications_TextTone: String { return self._s[2534]! } + public var Profile_CreateNewContact: String { return self._s[2535]! } + public var PrivacyPhoneNumberSettings_WhoCanSeeMyPhoneNumber: String { return self._s[2536]! } + public var TwoFactorSetup_EmailVerification_Title: String { return self._s[2538]! } + public var Call_Speaker: String { return self._s[2539]! } + public var AutoNightTheme_AutomaticSection: String { return self._s[2540]! } + public var Channel_OwnershipTransfer_EnterPassword: String { return self._s[2542]! } + public var Channel_Username_InvalidCharacters: String { return self._s[2543]! } public func Channel_AdminLog_MessageChangedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2541]!, self._r[2541]!, [_0]) + return formatWithArgumentRanges(self._s[2544]!, self._r[2544]!, [_0]) } - public var AutoDownloadSettings_AutodownloadFiles: String { return self._s[2542]! } - public var PrivacySettings_LastSeenTitle: String { return self._s[2543]! } - public var Channel_AdminLog_CanInviteUsers: String { return self._s[2544]! } - public var SettingsSearch_Synonyms_Privacy_Data_ClearPaymentsInfo: String { return self._s[2545]! } - public var OwnershipTransfer_SecurityCheck: String { return self._s[2546]! } - public var Conversation_MessageDeliveryFailed: String { return self._s[2547]! } - public var Watch_ChatList_NoConversationsText: String { return self._s[2548]! } - public var Bot_Unblock: String { return self._s[2549]! } - public var TextFormat_Italic: String { return self._s[2550]! } - public var WallpaperSearch_ColorPink: String { return self._s[2551]! } - public var Settings_About_Help: String { return self._s[2553]! } - public var SearchImages_Title: String { return self._s[2554]! } - public var Weekday_Wednesday: String { return self._s[2555]! } - public var Conversation_ClousStorageInfo_Description1: String { return self._s[2556]! } - public var ExplicitContent_AlertTitle: String { return self._s[2557]! } + public var AutoDownloadSettings_AutodownloadFiles: String { return self._s[2545]! } + public var PrivacySettings_LastSeenTitle: String { return self._s[2546]! } + public var Channel_AdminLog_CanInviteUsers: String { return self._s[2547]! } + public var SettingsSearch_Synonyms_Privacy_Data_ClearPaymentsInfo: String { return self._s[2548]! } + public var OwnershipTransfer_SecurityCheck: String { return self._s[2549]! } + public var Conversation_MessageDeliveryFailed: String { return self._s[2550]! } + public var Watch_ChatList_NoConversationsText: String { return self._s[2551]! } + public var Bot_Unblock: String { return self._s[2552]! } + public var TextFormat_Italic: String { return self._s[2553]! } + public var WallpaperSearch_ColorPink: String { return self._s[2554]! } + public var Settings_About_Help: String { return self._s[2556]! } + public var SearchImages_Title: String { return self._s[2557]! } + public var Weekday_Wednesday: String { return self._s[2558]! } + public var Conversation_ClousStorageInfo_Description1: String { return self._s[2559]! } + public var ExplicitContent_AlertTitle: String { return self._s[2560]! } public func Time_PreciseDate_m5(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2558]!, self._r[2558]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2561]!, self._r[2561]!, [_1, _2, _3]) } - public var Channel_DiscussionGroup_Create: String { return self._s[2559]! } - public var Weekday_Thursday: String { return self._s[2560]! } - public var Channel_BanUser_PermissionChangeGroupInfo: String { return self._s[2561]! } - public var Channel_Members_AddMembersHelp: String { return self._s[2562]! } + public var Channel_DiscussionGroup_Create: String { return self._s[2562]! } + public var Weekday_Thursday: String { return self._s[2563]! } + public var Channel_BanUser_PermissionChangeGroupInfo: String { return self._s[2564]! } + public var Channel_Members_AddMembersHelp: String { return self._s[2565]! } public func Checkout_SavePasswordTimeout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2563]!, self._r[2563]!, [_0]) + return formatWithArgumentRanges(self._s[2566]!, self._r[2566]!, [_0]) } - public var Channel_DiscussionGroup_LinkGroup: String { return self._s[2564]! } - public var SettingsSearch_Synonyms_Notifications_InAppNotificationsVibrate: String { return self._s[2565]! } - public var Passport_RequestedInformation: String { return self._s[2566]! } - public var Login_PhoneAndCountryHelp: String { return self._s[2567]! } - public var Conversation_EncryptionProcessing: String { return self._s[2569]! } - public var Notifications_PermissionsSuppressWarningTitle: String { return self._s[2570]! } - public var PhotoEditor_EnhanceTool: String { return self._s[2572]! } - public var Channel_Setup_Title: String { return self._s[2573]! } - public var Conversation_SearchPlaceholder: String { return self._s[2574]! } - public var OldChannels_GroupEmptyFormat: String { return self._s[2575]! } - public var AccessDenied_LocationAlwaysDenied: String { return self._s[2576]! } - public var Checkout_ErrorGeneric: String { return self._s[2577]! } - public var Passport_Language_hu: String { return self._s[2578]! } - public var GroupPermission_EditingDisabled: String { return self._s[2579]! } - public var Wallet_Month_ShortSeptember: String { return self._s[2581]! } + public var Channel_DiscussionGroup_LinkGroup: String { return self._s[2567]! } + public var SettingsSearch_Synonyms_Notifications_InAppNotificationsVibrate: String { return self._s[2568]! } + public var Passport_RequestedInformation: String { return self._s[2569]! } + public var Login_PhoneAndCountryHelp: String { return self._s[2570]! } + public var Conversation_EncryptionProcessing: String { return self._s[2572]! } + public var Notifications_PermissionsSuppressWarningTitle: String { return self._s[2573]! } + public var PhotoEditor_EnhanceTool: String { return self._s[2575]! } + public var Channel_Setup_Title: String { return self._s[2576]! } + public var Conversation_SearchPlaceholder: String { return self._s[2577]! } + public var OldChannels_GroupEmptyFormat: String { return self._s[2578]! } + public var AccessDenied_LocationAlwaysDenied: String { return self._s[2579]! } + public var Checkout_ErrorGeneric: String { return self._s[2580]! } + public var Passport_Language_hu: String { return self._s[2581]! } + public var GroupPermission_EditingDisabled: String { return self._s[2582]! } + public var Wallet_Month_ShortSeptember: String { return self._s[2584]! } public func Passport_Identity_UploadOneOfScan(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2582]!, self._r[2582]!, [_0]) + return formatWithArgumentRanges(self._s[2585]!, self._r[2585]!, [_0]) } public func PUSH_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2585]!, self._r[2585]!, [_1]) + return formatWithArgumentRanges(self._s[2588]!, self._r[2588]!, [_1]) } - public var ChatList_DeleteSavedMessagesConfirmationTitle: String { return self._s[2586]! } + public var ChatList_DeleteSavedMessagesConfirmationTitle: String { return self._s[2589]! } public func UserInfo_BlockConfirmationTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2587]!, self._r[2587]!, [_0]) + return formatWithArgumentRanges(self._s[2590]!, self._r[2590]!, [_0]) } - public var Conversation_CloudStorageInfo_Title: String { return self._s[2588]! } - public var Group_Location_Info: String { return self._s[2589]! } - public var PhotoEditor_CropAspectRatioSquare: String { return self._s[2590]! } - public var Permissions_PeopleNearbyAllow_v0: String { return self._s[2591]! } + public var Conversation_CloudStorageInfo_Title: String { return self._s[2591]! } + public var Group_Location_Info: String { return self._s[2592]! } + public var PhotoEditor_CropAspectRatioSquare: String { return self._s[2593]! } + public var Permissions_PeopleNearbyAllow_v0: String { return self._s[2594]! } public func Notification_Exceptions_MutedUntil(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2592]!, self._r[2592]!, [_0]) + return formatWithArgumentRanges(self._s[2595]!, self._r[2595]!, [_0]) } - public var Conversation_ClearPrivateHistory: String { return self._s[2593]! } - public var ContactInfo_PhoneLabelHome: String { return self._s[2594]! } - public var Appearance_RemoveThemeConfirmation: String { return self._s[2595]! } - public var PrivacySettings_LastSeenContacts: String { return self._s[2596]! } + public var Conversation_ClearPrivateHistory: String { return self._s[2596]! } + public var ContactInfo_PhoneLabelHome: String { return self._s[2597]! } + public var Appearance_RemoveThemeConfirmation: String { return self._s[2598]! } + public var PrivacySettings_LastSeenContacts: String { return self._s[2599]! } public func ChangePhone_ErrorOccupied(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2597]!, self._r[2597]!, [_0]) + return formatWithArgumentRanges(self._s[2600]!, self._r[2600]!, [_0]) } public func Notification_PinnedQuizMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2598]!, self._r[2598]!, [_0]) + return formatWithArgumentRanges(self._s[2601]!, self._r[2601]!, [_0]) } - public var Passport_Language_cs: String { return self._s[2599]! } - public var Message_PinnedAnimationMessage: String { return self._s[2601]! } - public var Passport_Identity_ReverseSideHelp: String { return self._s[2603]! } - public var SettingsSearch_Synonyms_Data_Storage_Title: String { return self._s[2604]! } - public var Wallet_Info_TransactionTo: String { return self._s[2606]! } - public var ChatList_DeleteForEveryoneConfirmationText: String { return self._s[2607]! } - public var SettingsSearch_Synonyms_Privacy_PasscodeAndTouchId: String { return self._s[2608]! } - public var Embed_PlayingInPIP: String { return self._s[2609]! } - public var Appearance_ThemePreview_Chat_3_TextWithLink: String { return self._s[2610]! } - public var AutoNightTheme_ScheduleSection: String { return self._s[2611]! } + public var Passport_Language_cs: String { return self._s[2602]! } + public var Message_PinnedAnimationMessage: String { return self._s[2604]! } + public var Passport_Identity_ReverseSideHelp: String { return self._s[2606]! } + public var SettingsSearch_Synonyms_Data_Storage_Title: String { return self._s[2607]! } + public var Wallet_Info_TransactionTo: String { return self._s[2609]! } + public var ChatList_DeleteForEveryoneConfirmationText: String { return self._s[2610]! } + public var SettingsSearch_Synonyms_Privacy_PasscodeAndTouchId: String { return self._s[2611]! } + public var Embed_PlayingInPIP: String { return self._s[2612]! } + public var Appearance_ThemePreview_Chat_3_TextWithLink: String { return self._s[2613]! } + public var AutoNightTheme_ScheduleSection: String { return self._s[2614]! } public func Call_EmojiDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2612]!, self._r[2612]!, [_0]) + return formatWithArgumentRanges(self._s[2615]!, self._r[2615]!, [_0]) } - public var MediaPicker_LivePhotoDescription: String { return self._s[2613]! } + public var MediaPicker_LivePhotoDescription: String { return self._s[2616]! } public func Channel_AdminLog_MessageRestrictedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2614]!, self._r[2614]!, [_1]) + return formatWithArgumentRanges(self._s[2617]!, self._r[2617]!, [_1]) } - public var Notification_PaymentSent: String { return self._s[2615]! } - public var PhotoEditor_CurvesGreen: String { return self._s[2616]! } - public var Notification_Exceptions_PreviewAlwaysOff: String { return self._s[2617]! } - public var AutoNightTheme_System: String { return self._s[2618]! } - public var SaveIncomingPhotosSettings_Title: String { return self._s[2619]! } - public var CreatePoll_QuizTitle: String { return self._s[2620]! } - public var NotificationSettings_ShowNotificationsAllAccounts: String { return self._s[2621]! } - public var VoiceOver_Chat_PagePreview: String { return self._s[2622]! } + public var Notification_PaymentSent: String { return self._s[2618]! } + public var PhotoEditor_CurvesGreen: String { return self._s[2619]! } + public var Notification_Exceptions_PreviewAlwaysOff: String { return self._s[2620]! } + public var AutoNightTheme_System: String { return self._s[2621]! } + public var SaveIncomingPhotosSettings_Title: String { return self._s[2622]! } + public var CreatePoll_QuizTitle: String { return self._s[2623]! } + public var NotificationSettings_ShowNotificationsAllAccounts: String { return self._s[2624]! } + public var VoiceOver_Chat_PagePreview: String { return self._s[2625]! } public func PUSH_MESSAGE_SCREENSHOT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2625]!, self._r[2625]!, [_1]) + return formatWithArgumentRanges(self._s[2628]!, self._r[2628]!, [_1]) } public func PUSH_MESSAGE_PHOTO_SECRET(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2626]!, self._r[2626]!, [_1]) + return formatWithArgumentRanges(self._s[2629]!, self._r[2629]!, [_1]) } public func ApplyLanguage_UnsufficientDataText(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2627]!, self._r[2627]!, [_1]) + return formatWithArgumentRanges(self._s[2630]!, self._r[2630]!, [_1]) } - public var NetworkUsageSettings_CallDataSection: String { return self._s[2629]! } - public var PasscodeSettings_HelpTop: String { return self._s[2630]! } - public var Conversation_WalletRequiredTitle: String { return self._s[2631]! } - public var Group_OwnershipTransfer_ErrorAdminsTooMuch: String { return self._s[2632]! } - public var Passport_Address_TypeRentalAgreement: String { return self._s[2633]! } - public var EditTheme_ShortLink: String { return self._s[2634]! } - public var Theme_Colors_ColorWallpaperWarning: String { return self._s[2635]! } - public var ProxyServer_VoiceOver_Active: String { return self._s[2636]! } - public var ReportPeer_ReasonOther_Placeholder: String { return self._s[2637]! } - public var CheckoutInfo_ErrorPhoneInvalid: String { return self._s[2638]! } - public var Call_Accept: String { return self._s[2640]! } - public var GroupRemoved_RemoveInfo: String { return self._s[2641]! } - public var Month_GenMarch: String { return self._s[2643]! } - public var PhotoEditor_ShadowsTool: String { return self._s[2644]! } - public var LoginPassword_Title: String { return self._s[2645]! } - public var Call_End: String { return self._s[2646]! } - public var Watch_Conversation_GroupInfo: String { return self._s[2647]! } - public var VoiceOver_Chat_Contact: String { return self._s[2648]! } - public var EditTheme_Create_Preview_IncomingText: String { return self._s[2649]! } - public var CallSettings_Always: String { return self._s[2650]! } - public var CallFeedback_Success: String { return self._s[2651]! } - public var TwoStepAuth_SetupHint: String { return self._s[2652]! } + public var NetworkUsageSettings_CallDataSection: String { return self._s[2632]! } + public var PasscodeSettings_HelpTop: String { return self._s[2633]! } + public var Conversation_WalletRequiredTitle: String { return self._s[2634]! } + public var Group_OwnershipTransfer_ErrorAdminsTooMuch: String { return self._s[2635]! } + public var Passport_Address_TypeRentalAgreement: String { return self._s[2636]! } + public var EditTheme_ShortLink: String { return self._s[2637]! } + public var Theme_Colors_ColorWallpaperWarning: String { return self._s[2638]! } + public var ProxyServer_VoiceOver_Active: String { return self._s[2639]! } + public var ReportPeer_ReasonOther_Placeholder: String { return self._s[2640]! } + public var CheckoutInfo_ErrorPhoneInvalid: String { return self._s[2641]! } + public var Call_Accept: String { return self._s[2643]! } + public var GroupRemoved_RemoveInfo: String { return self._s[2644]! } + public var Month_GenMarch: String { return self._s[2646]! } + public var PhotoEditor_ShadowsTool: String { return self._s[2647]! } + public var LoginPassword_Title: String { return self._s[2648]! } + public var Call_End: String { return self._s[2649]! } + public var Watch_Conversation_GroupInfo: String { return self._s[2650]! } + public var VoiceOver_Chat_Contact: String { return self._s[2651]! } + public var EditTheme_Create_Preview_IncomingText: String { return self._s[2652]! } + public var CallSettings_Always: String { return self._s[2653]! } + public var CallFeedback_Success: String { return self._s[2654]! } + public var TwoStepAuth_SetupHint: String { return self._s[2655]! } public func AddContact_ContactWillBeSharedAfterMutual(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2653]!, self._r[2653]!, [_1]) + return formatWithArgumentRanges(self._s[2656]!, self._r[2656]!, [_1]) } - public var ConversationProfile_UsersTooMuchError: String { return self._s[2654]! } - public var Login_PhoneTitle: String { return self._s[2655]! } - public var Passport_FieldPhoneHelp: String { return self._s[2656]! } - public var Weekday_ShortSunday: String { return self._s[2657]! } - public var Passport_InfoFAQ_URL: String { return self._s[2658]! } - public var ContactInfo_Job: String { return self._s[2660]! } - public var UserInfo_InviteBotToGroup: String { return self._s[2661]! } - public var Appearance_ThemeCarouselNightBlue: String { return self._s[2662]! } - public var CreatePoll_QuizTip: String { return self._s[2663]! } - public var TwoFactorSetup_Email_Text: String { return self._s[2664]! } - public var TwoStepAuth_PasswordRemovePassportConfirmation: String { return self._s[2665]! } - public var Invite_ChannelsTooMuch: String { return self._s[2666]! } - public var Wallet_Send_ConfirmationConfirm: String { return self._s[2667]! } - public var Wallet_TransactionInfo_OtherFeeInfo: String { return self._s[2668]! } - public var SettingsSearch_Synonyms_Notifications_InAppNotificationsPreview: String { return self._s[2669]! } - public var Wallet_Receive_AmountText: String { return self._s[2670]! } - public var Passport_DeletePersonalDetailsConfirmation: String { return self._s[2671]! } - public var CallFeedback_ReasonNoise: String { return self._s[2672]! } - public var Appearance_AppIconDefault: String { return self._s[2674]! } - public var Passport_Identity_AddInternalPassport: String { return self._s[2675]! } - public var MediaPicker_AddCaption: String { return self._s[2676]! } - public var CallSettings_TabIconDescription: String { return self._s[2677]! } + public var ConversationProfile_UsersTooMuchError: String { return self._s[2657]! } + public var Login_PhoneTitle: String { return self._s[2658]! } + public var Passport_FieldPhoneHelp: String { return self._s[2659]! } + public var Weekday_ShortSunday: String { return self._s[2660]! } + public var Passport_InfoFAQ_URL: String { return self._s[2661]! } + public var ContactInfo_Job: String { return self._s[2663]! } + public var UserInfo_InviteBotToGroup: String { return self._s[2664]! } + public var Appearance_ThemeCarouselNightBlue: String { return self._s[2665]! } + public var CreatePoll_QuizTip: String { return self._s[2666]! } + public var TwoFactorSetup_Email_Text: String { return self._s[2667]! } + public var TwoStepAuth_PasswordRemovePassportConfirmation: String { return self._s[2668]! } + public var Invite_ChannelsTooMuch: String { return self._s[2669]! } + public var Wallet_Send_ConfirmationConfirm: String { return self._s[2670]! } + public var Wallet_TransactionInfo_OtherFeeInfo: String { return self._s[2671]! } + public var SettingsSearch_Synonyms_Notifications_InAppNotificationsPreview: String { return self._s[2672]! } + public var Wallet_Receive_AmountText: String { return self._s[2673]! } + public var Passport_DeletePersonalDetailsConfirmation: String { return self._s[2674]! } + public var CallFeedback_ReasonNoise: String { return self._s[2675]! } + public var Appearance_AppIconDefault: String { return self._s[2677]! } + public var Passport_Identity_AddInternalPassport: String { return self._s[2678]! } + public var MediaPicker_AddCaption: String { return self._s[2679]! } + public var CallSettings_TabIconDescription: String { return self._s[2680]! } public func VoiceOver_Chat_Caption(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2678]!, self._r[2678]!, [_0]) + return formatWithArgumentRanges(self._s[2681]!, self._r[2681]!, [_0]) } - public var IntentsSettings_SuggestedChatsGroups: String { return self._s[2679]! } + public var IntentsSettings_SuggestedChatsGroups: String { return self._s[2682]! } public func Map_SearchNoResultsDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2680]!, self._r[2680]!, [_0]) + return formatWithArgumentRanges(self._s[2683]!, self._r[2683]!, [_0]) } - public var ChatList_UndoArchiveHiddenTitle: String { return self._s[2681]! } - public var Privacy_GroupsAndChannels_AlwaysAllow: String { return self._s[2682]! } - public var Passport_Identity_TypePersonalDetails: String { return self._s[2683]! } - public var DialogList_SearchSectionRecent: String { return self._s[2684]! } - public var PrivacyPolicy_DeclineMessage: String { return self._s[2685]! } - public var CreatePoll_Anonymous: String { return self._s[2686]! } - public var LogoutOptions_ClearCacheText: String { return self._s[2689]! } - public var LastSeen_WithinAWeek: String { return self._s[2690]! } - public var ChannelMembers_GroupAdminsTitle: String { return self._s[2691]! } - public var Conversation_CloudStorage_ChatStatus: String { return self._s[2693]! } - public var VoiceOver_Media_PlaybackRateNormal: String { return self._s[2694]! } + public var ChatList_UndoArchiveHiddenTitle: String { return self._s[2684]! } + public var Privacy_GroupsAndChannels_AlwaysAllow: String { return self._s[2685]! } + public var Passport_Identity_TypePersonalDetails: String { return self._s[2686]! } + public var DialogList_SearchSectionRecent: String { return self._s[2687]! } + public var PrivacyPolicy_DeclineMessage: String { return self._s[2688]! } + public var CreatePoll_Anonymous: String { return self._s[2689]! } + public var LogoutOptions_ClearCacheText: String { return self._s[2692]! } + public var LastSeen_WithinAWeek: String { return self._s[2693]! } + public var ChannelMembers_GroupAdminsTitle: String { return self._s[2694]! } + public var Conversation_CloudStorage_ChatStatus: String { return self._s[2696]! } + public var VoiceOver_Media_PlaybackRateNormal: String { return self._s[2697]! } public func AddContact_SharedContactExceptionInfo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2695]!, self._r[2695]!, [_0]) + return formatWithArgumentRanges(self._s[2698]!, self._r[2698]!, [_0]) } - public var Passport_Address_TypeResidentialAddress: String { return self._s[2696]! } - public var Conversation_StatusLeftGroup: String { return self._s[2697]! } - public var SocksProxySetup_ProxyDetailsTitle: String { return self._s[2698]! } - public var SettingsSearch_Synonyms_Calls_Title: String { return self._s[2700]! } - public var GroupPermission_AddSuccess: String { return self._s[2701]! } - public var PhotoEditor_BlurToolRadial: String { return self._s[2703]! } - public var Conversation_ContextMenuCopy: String { return self._s[2704]! } - public var AccessDenied_CallMicrophone: String { return self._s[2705]! } + public var Passport_Address_TypeResidentialAddress: String { return self._s[2699]! } + public var Conversation_StatusLeftGroup: String { return self._s[2700]! } + public var SocksProxySetup_ProxyDetailsTitle: String { return self._s[2701]! } + public var SettingsSearch_Synonyms_Calls_Title: String { return self._s[2703]! } + public var GroupPermission_AddSuccess: String { return self._s[2704]! } + public var PhotoEditor_BlurToolRadial: String { return self._s[2706]! } + public var Conversation_ContextMenuCopy: String { return self._s[2707]! } + public var AccessDenied_CallMicrophone: String { return self._s[2708]! } public func Time_PreciseDate_m2(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2706]!, self._r[2706]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2709]!, self._r[2709]!, [_1, _2, _3]) } - public var Login_InvalidFirstNameError: String { return self._s[2707]! } - public var Notifications_Badge_CountUnreadMessages_InfoOn: String { return self._s[2708]! } - public var Checkout_PaymentMethod_New: String { return self._s[2709]! } - public var ShareMenu_CopyShareLinkGame: String { return self._s[2710]! } - public var PhotoEditor_QualityTool: String { return self._s[2711]! } - public var Login_SendCodeViaSms: String { return self._s[2712]! } - public var SettingsSearch_Synonyms_Privacy_DeleteAccountIfAwayFor: String { return self._s[2713]! } - public var Chat_SlowmodeAttachmentLimitReached: String { return self._s[2714]! } - public var Wallet_Receive_CopyAddress: String { return self._s[2715]! } - public var Login_EmailNotConfiguredError: String { return self._s[2716]! } - public var SocksProxySetup_Status: String { return self._s[2717]! } - public var Conversation_ScheduleMessage_SendWhenOnline: String { return self._s[2718]! } - public var PrivacyPolicy_Accept: String { return self._s[2719]! } - public var Notifications_ExceptionsMessagePlaceholder: String { return self._s[2720]! } - public var Appearance_AppIconClassicX: String { return self._s[2721]! } + public var Login_InvalidFirstNameError: String { return self._s[2710]! } + public var Notifications_Badge_CountUnreadMessages_InfoOn: String { return self._s[2711]! } + public var Checkout_PaymentMethod_New: String { return self._s[2712]! } + public var ShareMenu_CopyShareLinkGame: String { return self._s[2713]! } + public var PhotoEditor_QualityTool: String { return self._s[2714]! } + public var Login_SendCodeViaSms: String { return self._s[2715]! } + public var SettingsSearch_Synonyms_Privacy_DeleteAccountIfAwayFor: String { return self._s[2716]! } + public var Chat_SlowmodeAttachmentLimitReached: String { return self._s[2717]! } + public var Wallet_Receive_CopyAddress: String { return self._s[2718]! } + public var Login_EmailNotConfiguredError: String { return self._s[2719]! } + public var SocksProxySetup_Status: String { return self._s[2720]! } + public var Conversation_ScheduleMessage_SendWhenOnline: String { return self._s[2721]! } + public var PrivacyPolicy_Accept: String { return self._s[2722]! } + public var Notifications_ExceptionsMessagePlaceholder: String { return self._s[2723]! } + public var Appearance_AppIconClassicX: String { return self._s[2724]! } public func PUSH_CHAT_MESSAGE_TEXT(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2722]!, self._r[2722]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2725]!, self._r[2725]!, [_1, _2, _3]) } - public var OwnershipTransfer_SecurityRequirements: String { return self._s[2723]! } - public var InfoPlist_NSLocationAlwaysUsageDescription: String { return self._s[2725]! } - public var AutoNightTheme_Automatic: String { return self._s[2726]! } - public var Channel_Username_InvalidStartsWithNumber: String { return self._s[2727]! } - public var Privacy_ContactsSyncHelp: String { return self._s[2728]! } - public var Cache_Help: String { return self._s[2729]! } - public var Group_ErrorAccessDenied: String { return self._s[2730]! } - public var Passport_Language_fa: String { return self._s[2731]! } - public var Wallet_Intro_Text: String { return self._s[2732]! } - public var Login_ResetAccountProtected_TimerTitle: String { return self._s[2733]! } - public var VoiceOver_Chat_YourVideoMessage: String { return self._s[2734]! } - public var PrivacySettings_LastSeen: String { return self._s[2735]! } + public var OwnershipTransfer_SecurityRequirements: String { return self._s[2726]! } + public var InfoPlist_NSLocationAlwaysUsageDescription: String { return self._s[2728]! } + public var AutoNightTheme_Automatic: String { return self._s[2729]! } + public var Channel_Username_InvalidStartsWithNumber: String { return self._s[2730]! } + public var Privacy_ContactsSyncHelp: String { return self._s[2731]! } + public var Cache_Help: String { return self._s[2732]! } + public var Group_ErrorAccessDenied: String { return self._s[2733]! } + public var Passport_Language_fa: String { return self._s[2734]! } + public var Wallet_Intro_Text: String { return self._s[2735]! } + public var Login_ResetAccountProtected_TimerTitle: String { return self._s[2736]! } + public var VoiceOver_Chat_YourVideoMessage: String { return self._s[2737]! } + public var PrivacySettings_LastSeen: String { return self._s[2738]! } public func DialogList_MultipleTyping(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2736]!, self._r[2736]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2739]!, self._r[2739]!, [_0, _1]) } - public var Wallet_Configuration_Apply: String { return self._s[2740]! } - public var Preview_SaveGif: String { return self._s[2741]! } - public var SettingsSearch_Synonyms_Privacy_TwoStepAuth: String { return self._s[2742]! } - public var Profile_About: String { return self._s[2743]! } - public var Channel_About_Placeholder: String { return self._s[2744]! } - public var Login_InfoTitle: String { return self._s[2745]! } + public var Wallet_Configuration_Apply: String { return self._s[2743]! } + public var Preview_SaveGif: String { return self._s[2744]! } + public var SettingsSearch_Synonyms_Privacy_TwoStepAuth: String { return self._s[2745]! } + public var Profile_About: String { return self._s[2746]! } + public var Channel_About_Placeholder: String { return self._s[2747]! } + public var Login_InfoTitle: String { return self._s[2748]! } public func TwoStepAuth_SetupPendingEmail(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2746]!, self._r[2746]!, [_0]) + return formatWithArgumentRanges(self._s[2749]!, self._r[2749]!, [_0]) } - public var EditTheme_Expand_Preview_IncomingReplyText: String { return self._s[2747]! } - public var Watch_Suggestion_CantTalk: String { return self._s[2749]! } - public var ContactInfo_Title: String { return self._s[2750]! } - public var Media_ShareThisVideo: String { return self._s[2751]! } - public var Weekday_ShortFriday: String { return self._s[2752]! } - public var AccessDenied_Contacts: String { return self._s[2754]! } - public var Notification_CallIncomingShort: String { return self._s[2755]! } - public var Group_Setup_TypePublic: String { return self._s[2756]! } - public var Notifications_MessageNotificationsExceptions: String { return self._s[2757]! } - public var Notifications_Badge_IncludeChannels: String { return self._s[2758]! } - public var Notifications_MessageNotificationsPreview: String { return self._s[2761]! } - public var ConversationProfile_ErrorCreatingConversation: String { return self._s[2762]! } - public var Group_ErrorAddTooMuchBots: String { return self._s[2763]! } - public var Privacy_GroupsAndChannels_CustomShareHelp: String { return self._s[2764]! } - public var Permissions_CellularDataAllowInSettings_v0: String { return self._s[2765]! } + public var EditTheme_Expand_Preview_IncomingReplyText: String { return self._s[2750]! } + public var Watch_Suggestion_CantTalk: String { return self._s[2752]! } + public var ContactInfo_Title: String { return self._s[2753]! } + public var Media_ShareThisVideo: String { return self._s[2754]! } + public var Weekday_ShortFriday: String { return self._s[2755]! } + public var AccessDenied_Contacts: String { return self._s[2757]! } + public var Notification_CallIncomingShort: String { return self._s[2758]! } + public var Group_Setup_TypePublic: String { return self._s[2759]! } + public var Notifications_MessageNotificationsExceptions: String { return self._s[2760]! } + public var Notifications_Badge_IncludeChannels: String { return self._s[2761]! } + public var Notifications_MessageNotificationsPreview: String { return self._s[2764]! } + public var ConversationProfile_ErrorCreatingConversation: String { return self._s[2765]! } + public var Group_ErrorAddTooMuchBots: String { return self._s[2766]! } + public var Privacy_GroupsAndChannels_CustomShareHelp: String { return self._s[2767]! } + public var Permissions_CellularDataAllowInSettings_v0: String { return self._s[2768]! } public func Wallet_SecureStorageChanged_BiometryText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2766]!, self._r[2766]!, [_0]) + return formatWithArgumentRanges(self._s[2769]!, self._r[2769]!, [_0]) } - public var DialogList_Typing: String { return self._s[2767]! } - public var CallFeedback_IncludeLogs: String { return self._s[2769]! } - public var Checkout_Phone: String { return self._s[2771]! } - public var Login_InfoFirstNamePlaceholder: String { return self._s[2774]! } - public var Privacy_Calls_Integration: String { return self._s[2775]! } - public var Notifications_PermissionsAllow: String { return self._s[2776]! } - public var TwoStepAuth_AddHintDescription: String { return self._s[2780]! } - public var Settings_ChatSettings: String { return self._s[2781]! } - public var Conversation_SendingOptionsTooltip: String { return self._s[2782]! } + public var DialogList_Typing: String { return self._s[2770]! } + public var CallFeedback_IncludeLogs: String { return self._s[2772]! } + public var Checkout_Phone: String { return self._s[2774]! } + public var Login_InfoFirstNamePlaceholder: String { return self._s[2777]! } + public var Privacy_Calls_Integration: String { return self._s[2778]! } + public var Notifications_PermissionsAllow: String { return self._s[2779]! } + public var TwoStepAuth_AddHintDescription: String { return self._s[2783]! } + public var Settings_ChatSettings: String { return self._s[2784]! } + public var Conversation_SendingOptionsTooltip: String { return self._s[2785]! } public func UserInfo_StartSecretChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2784]!, self._r[2784]!, [_0]) + return formatWithArgumentRanges(self._s[2787]!, self._r[2787]!, [_0]) } public func Channel_AdminLog_MessageInvitedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2785]!, self._r[2785]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2788]!, self._r[2788]!, [_1, _2]) } - public var GroupRemoved_DeleteUser: String { return self._s[2787]! } + public var GroupRemoved_DeleteUser: String { return self._s[2790]! } public func Channel_AdminLog_PollStopped(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2788]!, self._r[2788]!, [_0]) + return formatWithArgumentRanges(self._s[2791]!, self._r[2791]!, [_0]) } public func PUSH_MESSAGE_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2789]!, self._r[2789]!, [_1]) + return formatWithArgumentRanges(self._s[2792]!, self._r[2792]!, [_1]) } - public var Login_ContinueWithLocalization: String { return self._s[2790]! } - public var Watch_Message_ForwardedFrom: String { return self._s[2791]! } - public var TwoStepAuth_EnterEmailCode: String { return self._s[2793]! } - public var Conversation_Unblock: String { return self._s[2794]! } - public var PrivacySettings_DataSettings: String { return self._s[2795]! } - public var WallpaperPreview_PatternPaternApply: String { return self._s[2796]! } - public var Group_PublicLink_Info: String { return self._s[2797]! } + public var Login_ContinueWithLocalization: String { return self._s[2793]! } + public var Watch_Message_ForwardedFrom: String { return self._s[2794]! } + public var TwoStepAuth_EnterEmailCode: String { return self._s[2796]! } + public var Conversation_Unblock: String { return self._s[2797]! } + public var PrivacySettings_DataSettings: String { return self._s[2798]! } + public var WallpaperPreview_PatternPaternApply: String { return self._s[2799]! } + public var Group_PublicLink_Info: String { return self._s[2800]! } public func Wallet_Time_PreciseDate_m1(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2798]!, self._r[2798]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2801]!, self._r[2801]!, [_1, _2, _3]) } - public var Notifications_InAppNotificationsVibrate: String { return self._s[2799]! } + public var Notifications_InAppNotificationsVibrate: String { return self._s[2802]! } public func Privacy_GroupsAndChannels_InviteToChannelError(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2800]!, self._r[2800]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2803]!, self._r[2803]!, [_0, _1]) } - public var OldChannels_ChannelsHeader: String { return self._s[2802]! } - public var Wallet_RestoreFailed_CreateWallet: String { return self._s[2803]! } - public var PrivacySettings_Passcode: String { return self._s[2805]! } - public var Call_Mute: String { return self._s[2806]! } - public var Wallet_Weekday_Yesterday: String { return self._s[2807]! } - public var Passport_Language_dz: String { return self._s[2808]! } - public var Wallet_Receive_AmountHeader: String { return self._s[2809]! } - public var Wallet_TransactionInfo_OtherFeeInfoUrl: String { return self._s[2810]! } - public var Passport_Language_tk: String { return self._s[2811]! } + public var OldChannels_ChannelsHeader: String { return self._s[2805]! } + public var Wallet_RestoreFailed_CreateWallet: String { return self._s[2806]! } + public var PrivacySettings_Passcode: String { return self._s[2808]! } + public var Call_Mute: String { return self._s[2809]! } + public var Wallet_Weekday_Yesterday: String { return self._s[2810]! } + public var Passport_Language_dz: String { return self._s[2811]! } + public var Wallet_Receive_AmountHeader: String { return self._s[2812]! } + public var Wallet_TransactionInfo_OtherFeeInfoUrl: String { return self._s[2813]! } + public var Passport_Language_tk: String { return self._s[2814]! } public func Login_EmailCodeSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2812]!, self._r[2812]!, [_0]) + return formatWithArgumentRanges(self._s[2815]!, self._r[2815]!, [_0]) } - public var Settings_Search: String { return self._s[2813]! } - public var Wallet_Month_ShortFebruary: String { return self._s[2814]! } - public var InfoPlist_NSPhotoLibraryUsageDescription: String { return self._s[2815]! } - public var Wallet_Configuration_SourceJSON: String { return self._s[2816]! } - public var Conversation_ContextMenuReply: String { return self._s[2817]! } - public var WallpaperSearch_ColorBrown: String { return self._s[2818]! } - public var Chat_AttachmentMultipleForwardDisabled: String { return self._s[2819]! } - public var Tour_Title1: String { return self._s[2820]! } - public var Wallet_Alert_Cancel: String { return self._s[2821]! } - public var Conversation_ClearGroupHistory: String { return self._s[2823]! } - public var Wallet_TransactionInfo_RecipientHeader: String { return self._s[2824]! } - public var WallpaperPreview_Motion: String { return self._s[2825]! } + public var Settings_Search: String { return self._s[2816]! } + public var Wallet_Month_ShortFebruary: String { return self._s[2817]! } + public var InfoPlist_NSPhotoLibraryUsageDescription: String { return self._s[2818]! } + public var Wallet_Configuration_SourceJSON: String { return self._s[2819]! } + public var Conversation_ContextMenuReply: String { return self._s[2820]! } + public var WallpaperSearch_ColorBrown: String { return self._s[2821]! } + public var Chat_AttachmentMultipleForwardDisabled: String { return self._s[2822]! } + public var Tour_Title1: String { return self._s[2823]! } + public var Wallet_Alert_Cancel: String { return self._s[2824]! } + public var Conversation_ClearGroupHistory: String { return self._s[2826]! } + public var Wallet_TransactionInfo_RecipientHeader: String { return self._s[2827]! } + public var WallpaperPreview_Motion: String { return self._s[2828]! } public func Checkout_PasswordEntry_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2826]!, self._r[2826]!, [_0]) + return formatWithArgumentRanges(self._s[2829]!, self._r[2829]!, [_0]) } - public var Wallet_Configuration_ApplyErrorTextJSONInvalidData: String { return self._s[2827]! } - public var Call_RateCall: String { return self._s[2828]! } - public var Channel_AdminLog_BanSendStickersAndGifs: String { return self._s[2829]! } - public var Passport_PasswordCompleteSetup: String { return self._s[2830]! } - public var Conversation_InputTextSilentBroadcastPlaceholder: String { return self._s[2831]! } - public var UserInfo_LastNamePlaceholder: String { return self._s[2833]! } + public var Wallet_Configuration_ApplyErrorTextJSONInvalidData: String { return self._s[2830]! } + public var Call_RateCall: String { return self._s[2831]! } + public var Channel_AdminLog_BanSendStickersAndGifs: String { return self._s[2832]! } + public var Passport_PasswordCompleteSetup: String { return self._s[2833]! } + public var Conversation_InputTextSilentBroadcastPlaceholder: String { return self._s[2834]! } + public var UserInfo_LastNamePlaceholder: String { return self._s[2836]! } public func Login_WillCallYou(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2835]!, self._r[2835]!, [_0]) + return formatWithArgumentRanges(self._s[2838]!, self._r[2838]!, [_0]) } - public var Compose_Create: String { return self._s[2836]! } - public var Contacts_InviteToTelegram: String { return self._s[2837]! } - public var GroupInfo_Notifications: String { return self._s[2838]! } - public var ChatList_DeleteSavedMessagesConfirmationAction: String { return self._s[2840]! } - public var Message_PinnedLiveLocationMessage: String { return self._s[2841]! } - public var Month_GenApril: String { return self._s[2842]! } - public var Appearance_AutoNightTheme: String { return self._s[2843]! } - public var ChatSettings_AutomaticAudioDownload: String { return self._s[2845]! } - public var Login_CodeSentSms: String { return self._s[2847]! } + public var Compose_Create: String { return self._s[2839]! } + public var Contacts_InviteToTelegram: String { return self._s[2840]! } + public var GroupInfo_Notifications: String { return self._s[2841]! } + public var ChatList_DeleteSavedMessagesConfirmationAction: String { return self._s[2843]! } + public var Message_PinnedLiveLocationMessage: String { return self._s[2844]! } + public var Month_GenApril: String { return self._s[2845]! } + public var Appearance_AutoNightTheme: String { return self._s[2846]! } + public var ChatSettings_AutomaticAudioDownload: String { return self._s[2848]! } + public var Login_CodeSentSms: String { return self._s[2850]! } public func UserInfo_UnblockConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2848]!, self._r[2848]!, [_0]) + return formatWithArgumentRanges(self._s[2851]!, self._r[2851]!, [_0]) } - public var EmptyGroupInfo_Line3: String { return self._s[2849]! } - public var LogoutOptions_ContactSupportText: String { return self._s[2850]! } - public var Passport_Language_hr: String { return self._s[2851]! } - public var Common_ActionNotAllowedError: String { return self._s[2852]! } + public var EmptyGroupInfo_Line3: String { return self._s[2852]! } + public var LogoutOptions_ContactSupportText: String { return self._s[2853]! } + public var Passport_Language_hr: String { return self._s[2854]! } + public var Common_ActionNotAllowedError: String { return self._s[2855]! } public func Channel_AdminLog_MessageRestrictedNewSetting(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2853]!, self._r[2853]!, [_0]) + return formatWithArgumentRanges(self._s[2856]!, self._r[2856]!, [_0]) } - public var GroupInfo_InviteLink_CopyLink: String { return self._s[2854]! } - public var Wallet_Info_TransactionFrom: String { return self._s[2855]! } - public var Wallet_Send_ErrorDecryptionFailed: String { return self._s[2856]! } - public var Conversation_InputTextBroadcastPlaceholder: String { return self._s[2857]! } - public var Privacy_SecretChatsTitle: String { return self._s[2858]! } - public var Notification_SecretChatMessageScreenshotSelf: String { return self._s[2860]! } - public var GroupInfo_AddUserLeftError: String { return self._s[2861]! } - public var AutoDownloadSettings_TypePrivateChats: String { return self._s[2862]! } - public var LogoutOptions_ContactSupportTitle: String { return self._s[2863]! } - public var Appearance_ThemePreview_Chat_7_Text: String { return self._s[2864]! } - public var Channel_AddBotErrorHaveRights: String { return self._s[2865]! } - public var Preview_DeleteGif: String { return self._s[2866]! } - public var GroupInfo_Permissions_Exceptions: String { return self._s[2867]! } - public var Group_ErrorNotMutualContact: String { return self._s[2868]! } - public var Notification_MessageLifetime5s: String { return self._s[2869]! } - public var Wallet_Send_OwnAddressAlertText: String { return self._s[2870]! } - public var OldChannels_ChannelFormat: String { return self._s[2871]! } + public var GroupInfo_InviteLink_CopyLink: String { return self._s[2857]! } + public var Wallet_Info_TransactionFrom: String { return self._s[2858]! } + public var Wallet_Send_ErrorDecryptionFailed: String { return self._s[2859]! } + public var Conversation_InputTextBroadcastPlaceholder: String { return self._s[2860]! } + public var Privacy_SecretChatsTitle: String { return self._s[2861]! } + public var Notification_SecretChatMessageScreenshotSelf: String { return self._s[2863]! } + public var GroupInfo_AddUserLeftError: String { return self._s[2864]! } + public var AutoDownloadSettings_TypePrivateChats: String { return self._s[2865]! } + public var LogoutOptions_ContactSupportTitle: String { return self._s[2866]! } + public var Appearance_ThemePreview_Chat_7_Text: String { return self._s[2867]! } + public var Channel_AddBotErrorHaveRights: String { return self._s[2868]! } + public var Preview_DeleteGif: String { return self._s[2869]! } + public var GroupInfo_Permissions_Exceptions: String { return self._s[2870]! } + public var Group_ErrorNotMutualContact: String { return self._s[2871]! } + public var Notification_MessageLifetime5s: String { return self._s[2872]! } + public var Wallet_Send_OwnAddressAlertText: String { return self._s[2873]! } + public var OldChannels_ChannelFormat: String { return self._s[2874]! } public func Watch_LastSeen_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2872]!, self._r[2872]!, [_0]) + return formatWithArgumentRanges(self._s[2875]!, self._r[2875]!, [_0]) } - public var VoiceOver_Chat_Video: String { return self._s[2873]! } - public var Channel_OwnershipTransfer_ErrorPublicChannelsTooMuch: String { return self._s[2875]! } - public var ReportSpam_DeleteThisChat: String { return self._s[2876]! } - public var Passport_Address_AddBankStatement: String { return self._s[2877]! } - public var Notification_CallIncoming: String { return self._s[2878]! } - public var Wallet_Words_NotDoneTitle: String { return self._s[2879]! } - public var Compose_NewGroupTitle: String { return self._s[2880]! } - public var TwoStepAuth_RecoveryCodeHelp: String { return self._s[2882]! } - public var Passport_Address_Postcode: String { return self._s[2884]! } + public var VoiceOver_Chat_Video: String { return self._s[2876]! } + public var Channel_OwnershipTransfer_ErrorPublicChannelsTooMuch: String { return self._s[2878]! } + public var ReportSpam_DeleteThisChat: String { return self._s[2879]! } + public var Passport_Address_AddBankStatement: String { return self._s[2880]! } + public var Notification_CallIncoming: String { return self._s[2881]! } + public var Wallet_Words_NotDoneTitle: String { return self._s[2882]! } + public var Compose_NewGroupTitle: String { return self._s[2883]! } + public var TwoStepAuth_RecoveryCodeHelp: String { return self._s[2885]! } + public var Passport_Address_Postcode: String { return self._s[2887]! } public func LastSeen_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2885]!, self._r[2885]!, [_0]) + return formatWithArgumentRanges(self._s[2888]!, self._r[2888]!, [_0]) } - public var Checkout_NewCard_SaveInfoHelp: String { return self._s[2886]! } - public var Wallet_Month_ShortOctober: String { return self._s[2887]! } - public var VoiceOver_Chat_YourMusic: String { return self._s[2888]! } - public var WallpaperColors_Title: String { return self._s[2889]! } - public var SocksProxySetup_ShareQRCodeInfo: String { return self._s[2890]! } - public var VoiceOver_MessageContextForward: String { return self._s[2891]! } - public var GroupPermission_Duration: String { return self._s[2892]! } + public var Checkout_NewCard_SaveInfoHelp: String { return self._s[2889]! } + public var Wallet_Month_ShortOctober: String { return self._s[2890]! } + public var VoiceOver_Chat_YourMusic: String { return self._s[2891]! } + public var WallpaperColors_Title: String { return self._s[2892]! } + public var SocksProxySetup_ShareQRCodeInfo: String { return self._s[2893]! } + public var VoiceOver_MessageContextForward: String { return self._s[2894]! } + public var GroupPermission_Duration: String { return self._s[2895]! } public func Cache_Clear(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2893]!, self._r[2893]!, [_0]) + return formatWithArgumentRanges(self._s[2896]!, self._r[2896]!, [_0]) } - public var Bot_GroupStatusDoesNotReadHistory: String { return self._s[2894]! } - public var Username_Placeholder: String { return self._s[2895]! } - public var CallFeedback_WhatWentWrong: String { return self._s[2896]! } - public var Passport_FieldAddressUploadHelp: String { return self._s[2897]! } - public var Permissions_NotificationsAllowInSettings_v0: String { return self._s[2898]! } + public var Bot_GroupStatusDoesNotReadHistory: String { return self._s[2897]! } + public var Username_Placeholder: String { return self._s[2898]! } + public var CallFeedback_WhatWentWrong: String { return self._s[2899]! } + public var Passport_FieldAddressUploadHelp: String { return self._s[2900]! } + public var Permissions_NotificationsAllowInSettings_v0: String { return self._s[2901]! } public func Channel_AdminLog_MessageChangedUnlinkedChannel(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2900]!, self._r[2900]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2903]!, self._r[2903]!, [_1, _2]) } - public var Passport_PasswordDescription: String { return self._s[2901]! } - public var Channel_MessagePhotoUpdated: String { return self._s[2902]! } - public var MediaPicker_TapToUngroupDescription: String { return self._s[2903]! } - public var SettingsSearch_Synonyms_Notifications_BadgeCountUnreadMessages: String { return self._s[2904]! } - public var AttachmentMenu_PhotoOrVideo: String { return self._s[2905]! } - public var Conversation_ContextMenuMore: String { return self._s[2906]! } - public var Privacy_PaymentsClearInfo: String { return self._s[2907]! } - public var CallSettings_TabIcon: String { return self._s[2908]! } - public var KeyCommand_Find: String { return self._s[2909]! } - public var ClearCache_FreeSpaceDescription: String { return self._s[2910]! } - public var Appearance_ThemePreview_ChatList_7_Text: String { return self._s[2911]! } - public var EditTheme_Edit_Preview_IncomingText: String { return self._s[2912]! } - public var Message_PinnedGame: String { return self._s[2913]! } - public var VoiceOver_Chat_ForwardedFromYou: String { return self._s[2914]! } - public var Notifications_Badge_CountUnreadMessages_InfoOff: String { return self._s[2916]! } - public var Login_CallRequestState2: String { return self._s[2918]! } - public var CheckoutInfo_ReceiverInfoNamePlaceholder: String { return self._s[2920]! } + public var Passport_PasswordDescription: String { return self._s[2904]! } + public var Channel_MessagePhotoUpdated: String { return self._s[2905]! } + public var MediaPicker_TapToUngroupDescription: String { return self._s[2906]! } + public var SettingsSearch_Synonyms_Notifications_BadgeCountUnreadMessages: String { return self._s[2907]! } + public var AttachmentMenu_PhotoOrVideo: String { return self._s[2908]! } + public var Conversation_ContextMenuMore: String { return self._s[2909]! } + public var Privacy_PaymentsClearInfo: String { return self._s[2910]! } + public var CallSettings_TabIcon: String { return self._s[2911]! } + public var KeyCommand_Find: String { return self._s[2912]! } + public var ClearCache_FreeSpaceDescription: String { return self._s[2913]! } + public var Appearance_ThemePreview_ChatList_7_Text: String { return self._s[2914]! } + public var EditTheme_Edit_Preview_IncomingText: String { return self._s[2915]! } + public var Message_PinnedGame: String { return self._s[2916]! } + public var VoiceOver_Chat_ForwardedFromYou: String { return self._s[2917]! } + public var Notifications_Badge_CountUnreadMessages_InfoOff: String { return self._s[2919]! } + public var Login_CallRequestState2: String { return self._s[2921]! } + public var CheckoutInfo_ReceiverInfoNamePlaceholder: String { return self._s[2923]! } public func VoiceOver_Chat_PhotoFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2921]!, self._r[2921]!, [_0]) + return formatWithArgumentRanges(self._s[2924]!, self._r[2924]!, [_0]) } public func Checkout_PayPrice(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2923]!, self._r[2923]!, [_0]) + return formatWithArgumentRanges(self._s[2926]!, self._r[2926]!, [_0]) } - public var AuthSessions_AddDevice: String { return self._s[2924]! } - public var WallpaperPreview_Blurred: String { return self._s[2925]! } - public var Conversation_InstantPagePreview: String { return self._s[2926]! } + public var AuthSessions_AddDevice: String { return self._s[2927]! } + public var WallpaperPreview_Blurred: String { return self._s[2928]! } + public var Conversation_InstantPagePreview: String { return self._s[2929]! } public func DialogList_SingleUploadingVideoSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2927]!, self._r[2927]!, [_0]) + return formatWithArgumentRanges(self._s[2930]!, self._r[2930]!, [_0]) } - public var SecretTimer_VideoDescription: String { return self._s[2930]! } - public var WallpaperSearch_ColorRed: String { return self._s[2931]! } - public var GroupPermission_NoPinMessages: String { return self._s[2932]! } - public var Passport_Language_es: String { return self._s[2933]! } - public var Permissions_ContactsAllow_v0: String { return self._s[2935]! } - public var Conversation_EditingMessageMediaEditCurrentVideo: String { return self._s[2936]! } + public var SecretTimer_VideoDescription: String { return self._s[2933]! } + public var WallpaperSearch_ColorRed: String { return self._s[2934]! } + public var GroupPermission_NoPinMessages: String { return self._s[2935]! } + public var Passport_Language_es: String { return self._s[2936]! } + public var Permissions_ContactsAllow_v0: String { return self._s[2938]! } + public var Conversation_EditingMessageMediaEditCurrentVideo: String { return self._s[2939]! } public func PUSH_CHAT_MESSAGE_CONTACT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2937]!, self._r[2937]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2940]!, self._r[2940]!, [_1, _2]) } - public var Privacy_Forwards_CustomHelp: String { return self._s[2938]! } - public var WebPreview_GettingLinkInfo: String { return self._s[2939]! } - public var Watch_UserInfo_Unmute: String { return self._s[2940]! } - public var GroupInfo_ChannelListNamePlaceholder: String { return self._s[2941]! } - public var AccessDenied_CameraRestricted: String { return self._s[2943]! } + public var Privacy_Forwards_CustomHelp: String { return self._s[2941]! } + public var WebPreview_GettingLinkInfo: String { return self._s[2942]! } + public var Watch_UserInfo_Unmute: String { return self._s[2943]! } + public var GroupInfo_ChannelListNamePlaceholder: String { return self._s[2944]! } + public var AccessDenied_CameraRestricted: String { return self._s[2946]! } public func Conversation_Kilobytes(_ _0: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2944]!, self._r[2944]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[2947]!, self._r[2947]!, ["\(_0)"]) } - public var ChatList_ReadAll: String { return self._s[2946]! } - public var Settings_CopyUsername: String { return self._s[2947]! } - public var Contacts_SearchLabel: String { return self._s[2948]! } - public var Map_OpenInYandexNavigator: String { return self._s[2950]! } - public var PasscodeSettings_EncryptData: String { return self._s[2951]! } - public var Settings_Wallet: String { return self._s[2952]! } - public var Group_ErrorSupergroupConversionNotPossible: String { return self._s[2953]! } - public var WallpaperSearch_ColorPrefix: String { return self._s[2954]! } - public var Notifications_GroupNotificationsPreview: String { return self._s[2955]! } - public var DialogList_AdNoticeAlert: String { return self._s[2956]! } - public var Wallet_Month_GenMay: String { return self._s[2958]! } - public var CheckoutInfo_ShippingInfoAddress1: String { return self._s[2959]! } - public var CheckoutInfo_ShippingInfoAddress2: String { return self._s[2960]! } - public var Localization_LanguageCustom: String { return self._s[2961]! } - public var Passport_Identity_TypeDriversLicenseUploadScan: String { return self._s[2962]! } - public var CallFeedback_Title: String { return self._s[2963]! } - public var VoiceOver_Chat_RecordPreviewVoiceMessage: String { return self._s[2966]! } - public var Passport_Address_OneOfTypePassportRegistration: String { return self._s[2967]! } - public var Wallet_Intro_CreateErrorTitle: String { return self._s[2968]! } - public var Conversation_InfoGroup: String { return self._s[2969]! } - public var Compose_NewMessage: String { return self._s[2970]! } - public var FastTwoStepSetup_HintPlaceholder: String { return self._s[2971]! } - public var ChatSettings_AutoDownloadVideoMessages: String { return self._s[2972]! } - public var Wallet_SecureStorageReset_BiometryFaceId: String { return self._s[2973]! } - public var Channel_DiscussionGroup_UnlinkChannel: String { return self._s[2974]! } + public var ChatList_ReadAll: String { return self._s[2949]! } + public var Settings_CopyUsername: String { return self._s[2950]! } + public var Contacts_SearchLabel: String { return self._s[2951]! } + public var Map_OpenInYandexNavigator: String { return self._s[2953]! } + public var PasscodeSettings_EncryptData: String { return self._s[2954]! } + public var Settings_Wallet: String { return self._s[2955]! } + public var Group_ErrorSupergroupConversionNotPossible: String { return self._s[2956]! } + public var WallpaperSearch_ColorPrefix: String { return self._s[2957]! } + public var Notifications_GroupNotificationsPreview: String { return self._s[2958]! } + public var DialogList_AdNoticeAlert: String { return self._s[2959]! } + public var Wallet_Month_GenMay: String { return self._s[2961]! } + public var CheckoutInfo_ShippingInfoAddress1: String { return self._s[2962]! } + public var CheckoutInfo_ShippingInfoAddress2: String { return self._s[2963]! } + public var Localization_LanguageCustom: String { return self._s[2964]! } + public var Passport_Identity_TypeDriversLicenseUploadScan: String { return self._s[2965]! } + public var CallFeedback_Title: String { return self._s[2966]! } + public var VoiceOver_Chat_RecordPreviewVoiceMessage: String { return self._s[2969]! } + public var Passport_Address_OneOfTypePassportRegistration: String { return self._s[2970]! } + public var Wallet_Intro_CreateErrorTitle: String { return self._s[2971]! } + public var Conversation_InfoGroup: String { return self._s[2972]! } + public var Compose_NewMessage: String { return self._s[2973]! } + public var FastTwoStepSetup_HintPlaceholder: String { return self._s[2974]! } + public var ChatSettings_AutoDownloadVideoMessages: String { return self._s[2975]! } + public var Wallet_SecureStorageReset_BiometryFaceId: String { return self._s[2976]! } + public var Channel_DiscussionGroup_UnlinkChannel: String { return self._s[2977]! } public func Passport_Scans_ScanIndex(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2975]!, self._r[2975]!, [_0]) + return formatWithArgumentRanges(self._s[2978]!, self._r[2978]!, [_0]) } - public var Channel_AdminLog_CanDeleteMessages: String { return self._s[2976]! } - public var Login_CancelSignUpConfirmation: String { return self._s[2977]! } - public var ChangePhoneNumberCode_Help: String { return self._s[2978]! } - public var PrivacySettings_DeleteAccountHelp: String { return self._s[2979]! } - public var Channel_BlackList_Title: String { return self._s[2980]! } - public var UserInfo_PhoneCall: String { return self._s[2981]! } - public var Passport_Address_OneOfTypeBankStatement: String { return self._s[2983]! } - public var Wallet_Month_ShortJanuary: String { return self._s[2984]! } - public var State_connecting: String { return self._s[2985]! } - public var Appearance_ThemePreview_ChatList_6_Text: String { return self._s[2986]! } - public var Wallet_Month_GenMarch: String { return self._s[2987]! } - public var EditTheme_Expand_BottomInfo: String { return self._s[2988]! } - public var AuthSessions_AddedDeviceTerminate: String { return self._s[2989]! } + public var Channel_AdminLog_CanDeleteMessages: String { return self._s[2979]! } + public var Login_CancelSignUpConfirmation: String { return self._s[2980]! } + public var ChangePhoneNumberCode_Help: String { return self._s[2981]! } + public var PrivacySettings_DeleteAccountHelp: String { return self._s[2982]! } + public var Channel_BlackList_Title: String { return self._s[2983]! } + public var UserInfo_PhoneCall: String { return self._s[2984]! } + public var Passport_Address_OneOfTypeBankStatement: String { return self._s[2986]! } + public var Wallet_Month_ShortJanuary: String { return self._s[2987]! } + public var State_connecting: String { return self._s[2988]! } + public var Appearance_ThemePreview_ChatList_6_Text: String { return self._s[2989]! } + public var Wallet_Month_GenMarch: String { return self._s[2990]! } + public var EditTheme_Expand_BottomInfo: String { return self._s[2991]! } + public var AuthSessions_AddedDeviceTerminate: String { return self._s[2992]! } public func LastSeen_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2990]!, self._r[2990]!, [_0]) + return formatWithArgumentRanges(self._s[2993]!, self._r[2993]!, [_0]) } public func DialogList_SingleRecordingAudioSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2991]!, self._r[2991]!, [_0]) + return formatWithArgumentRanges(self._s[2994]!, self._r[2994]!, [_0]) } - public var Notifications_GroupNotifications: String { return self._s[2992]! } - public var Conversation_SendMessageErrorTooMuchScheduled: String { return self._s[2993]! } - public var Passport_Identity_EditPassport: String { return self._s[2994]! } - public var EnterPasscode_RepeatNewPasscode: String { return self._s[2996]! } - public var Localization_EnglishLanguageName: String { return self._s[2997]! } - public var Share_AuthDescription: String { return self._s[2998]! } - public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsAlert: String { return self._s[2999]! } - public var Passport_Identity_Surname: String { return self._s[3000]! } - public var Compose_TokenListPlaceholder: String { return self._s[3001]! } - public var Wallet_AccessDenied_Camera: String { return self._s[3002]! } - public var Passport_Identity_OneOfTypePassport: String { return self._s[3003]! } - public var Settings_AboutEmpty: String { return self._s[3004]! } - public var Conversation_Unmute: String { return self._s[3005]! } - public var CreateGroup_ChannelsTooMuch: String { return self._s[3007]! } - public var Wallet_Sending_Text: String { return self._s[3008]! } + public var Notifications_GroupNotifications: String { return self._s[2995]! } + public var Conversation_SendMessageErrorTooMuchScheduled: String { return self._s[2996]! } + public var Passport_Identity_EditPassport: String { return self._s[2997]! } + public var EnterPasscode_RepeatNewPasscode: String { return self._s[2999]! } + public var Localization_EnglishLanguageName: String { return self._s[3000]! } + public var Share_AuthDescription: String { return self._s[3001]! } + public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsAlert: String { return self._s[3002]! } + public var Passport_Identity_Surname: String { return self._s[3003]! } + public var Compose_TokenListPlaceholder: String { return self._s[3004]! } + public var Wallet_AccessDenied_Camera: String { return self._s[3005]! } + public var Passport_Identity_OneOfTypePassport: String { return self._s[3006]! } + public var Settings_AboutEmpty: String { return self._s[3007]! } + public var Conversation_Unmute: String { return self._s[3008]! } + public var CreateGroup_ChannelsTooMuch: String { return self._s[3010]! } + public var Wallet_Sending_Text: String { return self._s[3011]! } public func PUSH_CONTACT_JOINED(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3009]!, self._r[3009]!, [_1]) + return formatWithArgumentRanges(self._s[3012]!, self._r[3012]!, [_1]) } - public var Login_CodeSentCall: String { return self._s[3010]! } - public var ContactInfo_PhoneLabelHomeFax: String { return self._s[3012]! } - public var ChatSettings_Appearance: String { return self._s[3013]! } - public var ClearCache_StorageUsage: String { return self._s[3014]! } - public var Appearance_PickAccentColor: String { return self._s[3015]! } + public var Login_CodeSentCall: String { return self._s[3013]! } + public var ContactInfo_PhoneLabelHomeFax: String { return self._s[3015]! } + public var ChatSettings_Appearance: String { return self._s[3016]! } + public var ClearCache_StorageUsage: String { return self._s[3017]! } + public var Appearance_PickAccentColor: String { return self._s[3018]! } public func PUSH_CHAT_MESSAGE_NOTEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3016]!, self._r[3016]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3019]!, self._r[3019]!, [_1, _2]) } public func PUSH_MESSAGE_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3017]!, self._r[3017]!, [_1]) + return formatWithArgumentRanges(self._s[3020]!, self._r[3020]!, [_1]) } - public var Notification_CallMissed: String { return self._s[3018]! } - public var SettingsSearch_Synonyms_Appearance_ChatBackground_Custom: String { return self._s[3019]! } - public var Channel_AdminLogFilter_EventsInfo: String { return self._s[3020]! } - public var Wallet_Month_GenOctober: String { return self._s[3022]! } - public var ChatAdmins_AdminLabel: String { return self._s[3023]! } - public var KeyCommand_JumpToNextChat: String { return self._s[3024]! } - public var Conversation_StopPollConfirmationTitle: String { return self._s[3026]! } - public var ChangePhoneNumberCode_CodePlaceholder: String { return self._s[3027]! } - public var Month_GenJune: String { return self._s[3028]! } - public var IntentsSettings_MainAccountInfo: String { return self._s[3029]! } - public var Watch_Location_Current: String { return self._s[3030]! } - public var Wallet_Receive_CopyInvoiceUrl: String { return self._s[3031]! } - public var Conversation_TitleMute: String { return self._s[3032]! } - public var Map_PlacesInThisArea: String { return self._s[3033]! } + public var Notification_CallMissed: String { return self._s[3021]! } + public var SettingsSearch_Synonyms_Appearance_ChatBackground_Custom: String { return self._s[3022]! } + public var Channel_AdminLogFilter_EventsInfo: String { return self._s[3023]! } + public var Wallet_Month_GenOctober: String { return self._s[3025]! } + public var ChatAdmins_AdminLabel: String { return self._s[3026]! } + public var KeyCommand_JumpToNextChat: String { return self._s[3027]! } + public var Conversation_StopPollConfirmationTitle: String { return self._s[3029]! } + public var ChangePhoneNumberCode_CodePlaceholder: String { return self._s[3030]! } + public var Month_GenJune: String { return self._s[3031]! } + public var IntentsSettings_MainAccountInfo: String { return self._s[3032]! } + public var Watch_Location_Current: String { return self._s[3033]! } + public var Wallet_Receive_CopyInvoiceUrl: String { return self._s[3034]! } + public var Conversation_TitleMute: String { return self._s[3035]! } + public var Map_PlacesInThisArea: String { return self._s[3036]! } public func PUSH_CHANNEL_MESSAGE_ROUND(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3034]!, self._r[3034]!, [_1]) + return formatWithArgumentRanges(self._s[3037]!, self._r[3037]!, [_1]) } - public var GroupInfo_DeleteAndExit: String { return self._s[3035]! } + public var GroupInfo_DeleteAndExit: String { return self._s[3038]! } public func Conversation_Moderate_DeleteAllMessages(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3036]!, self._r[3036]!, [_0]) + return formatWithArgumentRanges(self._s[3039]!, self._r[3039]!, [_0]) } - public var Call_ReportPlaceholder: String { return self._s[3037]! } - public var Chat_SlowmodeSendError: String { return self._s[3038]! } - public var MaskStickerSettings_Info: String { return self._s[3039]! } - public var EditTheme_Expand_TopInfo: String { return self._s[3040]! } + public var Call_ReportPlaceholder: String { return self._s[3040]! } + public var Chat_SlowmodeSendError: String { return self._s[3041]! } + public var MaskStickerSettings_Info: String { return self._s[3042]! } + public var EditTheme_Expand_TopInfo: String { return self._s[3043]! } public func GroupInfo_AddParticipantConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3041]!, self._r[3041]!, [_0]) + return formatWithArgumentRanges(self._s[3044]!, self._r[3044]!, [_0]) } - public var Checkout_NewCard_PostcodeTitle: String { return self._s[3042]! } - public var Passport_Address_RegionPlaceholder: String { return self._s[3044]! } - public var Contacts_ShareTelegram: String { return self._s[3045]! } - public var EnterPasscode_EnterNewPasscodeNew: String { return self._s[3046]! } - public var Map_AddressOnMap: String { return self._s[3047]! } - public var Channel_ErrorAccessDenied: String { return self._s[3048]! } - public var UserInfo_ScamBotWarning: String { return self._s[3050]! } - public var Stickers_GroupChooseStickerPack: String { return self._s[3051]! } - public var Call_ConnectionErrorTitle: String { return self._s[3052]! } - public var UserInfo_NotificationsEnable: String { return self._s[3053]! } - public var ArchivedChats_IntroText1: String { return self._s[3054]! } - public var Tour_Text4: String { return self._s[3057]! } - public var WallpaperSearch_Recent: String { return self._s[3058]! } - public var GroupInfo_ScamGroupWarning: String { return self._s[3059]! } - public var Profile_MessageLifetime2s: String { return self._s[3061]! } - public var Appearance_ThemePreview_ChatList_5_Text: String { return self._s[3062]! } - public var Notification_MessageLifetime2s: String { return self._s[3063]! } + public var Checkout_NewCard_PostcodeTitle: String { return self._s[3045]! } + public var Passport_Address_RegionPlaceholder: String { return self._s[3047]! } + public var Contacts_ShareTelegram: String { return self._s[3048]! } + public var EnterPasscode_EnterNewPasscodeNew: String { return self._s[3049]! } + public var Map_AddressOnMap: String { return self._s[3050]! } + public var Channel_ErrorAccessDenied: String { return self._s[3051]! } + public var UserInfo_ScamBotWarning: String { return self._s[3053]! } + public var Stickers_GroupChooseStickerPack: String { return self._s[3054]! } + public var Call_ConnectionErrorTitle: String { return self._s[3055]! } + public var UserInfo_NotificationsEnable: String { return self._s[3056]! } + public var ArchivedChats_IntroText1: String { return self._s[3057]! } + public var Tour_Text4: String { return self._s[3060]! } + public var WallpaperSearch_Recent: String { return self._s[3061]! } + public var GroupInfo_ScamGroupWarning: String { return self._s[3062]! } + public var Profile_MessageLifetime2s: String { return self._s[3064]! } + public var Appearance_ThemePreview_ChatList_5_Text: String { return self._s[3065]! } + public var Notification_MessageLifetime2s: String { return self._s[3066]! } public func Time_PreciseDate_m10(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3064]!, self._r[3064]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3067]!, self._r[3067]!, [_1, _2, _3]) } - public var Cache_ClearCache: String { return self._s[3065]! } - public var AutoNightTheme_UpdateLocation: String { return self._s[3066]! } - public var Permissions_NotificationsUnreachableText_v0: String { return self._s[3067]! } + public var Cache_ClearCache: String { return self._s[3068]! } + public var AutoNightTheme_UpdateLocation: String { return self._s[3069]! } + public var Permissions_NotificationsUnreachableText_v0: String { return self._s[3070]! } public func Channel_AdminLog_MessageChangedGroupUsername(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3071]!, self._r[3071]!, [_0]) + return formatWithArgumentRanges(self._s[3074]!, self._r[3074]!, [_0]) } public func Conversation_ShareMyPhoneNumber_StatusSuccess(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3073]!, self._r[3073]!, [_0]) + return formatWithArgumentRanges(self._s[3076]!, self._r[3076]!, [_0]) } - public var LocalGroup_Text: String { return self._s[3074]! } - public var Channel_AdminLog_EmptyFilterTitle: String { return self._s[3075]! } - public var SocksProxySetup_TypeSocks: String { return self._s[3076]! } - public var ChatList_UnarchiveAction: String { return self._s[3077]! } - public var AutoNightTheme_Title: String { return self._s[3078]! } - public var InstantPage_FeedbackButton: String { return self._s[3079]! } - public var Passport_FieldAddress: String { return self._s[3080]! } + public var LocalGroup_Text: String { return self._s[3077]! } + public var Channel_AdminLog_EmptyFilterTitle: String { return self._s[3078]! } + public var SocksProxySetup_TypeSocks: String { return self._s[3079]! } + public var ChatList_UnarchiveAction: String { return self._s[3080]! } + public var AutoNightTheme_Title: String { return self._s[3081]! } + public var InstantPage_FeedbackButton: String { return self._s[3082]! } + public var Passport_FieldAddress: String { return self._s[3083]! } public func Channel_AdminLog_SetSlowmode(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3081]!, self._r[3081]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3084]!, self._r[3084]!, [_1, _2]) } - public var Month_ShortMarch: String { return self._s[3082]! } + public var Month_ShortMarch: String { return self._s[3085]! } public func PUSH_MESSAGE_INVOICE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3083]!, self._r[3083]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3086]!, self._r[3086]!, [_1, _2]) } - public var SocksProxySetup_UsernamePlaceholder: String { return self._s[3084]! } - public var Conversation_ShareInlineBotLocationConfirmation: String { return self._s[3085]! } - public var Passport_FloodError: String { return self._s[3086]! } - public var SecretGif_Title: String { return self._s[3087]! } - public var NotificationSettings_ShowNotificationsAllAccountsInfoOn: String { return self._s[3088]! } - public var ChatList_Context_UnhideArchive: String { return self._s[3089]! } - public var Passport_Language_th: String { return self._s[3091]! } - public var Passport_Address_Address: String { return self._s[3092]! } - public var Login_InvalidLastNameError: String { return self._s[3093]! } - public var Notifications_InAppNotificationsPreview: String { return self._s[3094]! } - public var Notifications_PermissionsUnreachableTitle: String { return self._s[3095]! } - public var ChatList_Context_Archive: String { return self._s[3096]! } - public var SettingsSearch_FAQ: String { return self._s[3097]! } - public var ShareMenu_Send: String { return self._s[3098]! } - public var WallpaperSearch_ColorYellow: String { return self._s[3100]! } - public var Month_GenNovember: String { return self._s[3102]! } - public var SettingsSearch_Synonyms_Appearance_LargeEmoji: String { return self._s[3104]! } + public var SocksProxySetup_UsernamePlaceholder: String { return self._s[3087]! } + public var Conversation_ShareInlineBotLocationConfirmation: String { return self._s[3088]! } + public var Passport_FloodError: String { return self._s[3089]! } + public var SecretGif_Title: String { return self._s[3090]! } + public var NotificationSettings_ShowNotificationsAllAccountsInfoOn: String { return self._s[3091]! } + public var ChatList_Context_UnhideArchive: String { return self._s[3092]! } + public var Passport_Language_th: String { return self._s[3094]! } + public var Passport_Address_Address: String { return self._s[3095]! } + public var Login_InvalidLastNameError: String { return self._s[3096]! } + public var Notifications_InAppNotificationsPreview: String { return self._s[3097]! } + public var Notifications_PermissionsUnreachableTitle: String { return self._s[3098]! } + public var ChatList_Context_Archive: String { return self._s[3099]! } + public var SettingsSearch_FAQ: String { return self._s[3100]! } + public var ShareMenu_Send: String { return self._s[3101]! } + public var WallpaperSearch_ColorYellow: String { return self._s[3103]! } + public var Month_GenNovember: String { return self._s[3105]! } + public var SettingsSearch_Synonyms_Appearance_LargeEmoji: String { return self._s[3107]! } public func Conversation_ShareMyPhoneNumberConfirmation(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3105]!, self._r[3105]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3108]!, self._r[3108]!, [_1, _2]) } - public var Conversation_SwipeToReplyHintText: String { return self._s[3106]! } - public var Checkout_Email: String { return self._s[3107]! } - public var NotificationsSound_Tritone: String { return self._s[3108]! } - public var StickerPacksSettings_ManagingHelp: String { return self._s[3110]! } - public var Wallet_ContextMenuCopy: String { return self._s[3112]! } + public var Conversation_SwipeToReplyHintText: String { return self._s[3109]! } + public var Checkout_Email: String { return self._s[3110]! } + public var NotificationsSound_Tritone: String { return self._s[3111]! } + public var StickerPacksSettings_ManagingHelp: String { return self._s[3113]! } + public var Wallet_ContextMenuCopy: String { return self._s[3115]! } public func Wallet_Time_PreciseDate_m6(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3114]!, self._r[3114]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3117]!, self._r[3117]!, [_1, _2, _3]) } - public var Appearance_TextSize_Automatic: String { return self._s[3115]! } + public var Appearance_TextSize_Automatic: String { return self._s[3118]! } public func PUSH_PINNED_ROUND(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3116]!, self._r[3116]!, [_1]) + return formatWithArgumentRanges(self._s[3119]!, self._r[3119]!, [_1]) } public func StickerPackActionInfo_AddedText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3117]!, self._r[3117]!, [_0]) + return formatWithArgumentRanges(self._s[3120]!, self._r[3120]!, [_0]) } - public var ChangePhoneNumberNumber_Help: String { return self._s[3118]! } + public var ChangePhoneNumberNumber_Help: String { return self._s[3121]! } public func Checkout_LiabilityAlert(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3119]!, self._r[3119]!, [_1, _1, _1, _2]) + return formatWithArgumentRanges(self._s[3122]!, self._r[3122]!, [_1, _1, _1, _2]) } - public var ChatList_UndoArchiveTitle: String { return self._s[3120]! } - public var Notification_Exceptions_Add: String { return self._s[3121]! } - public var DialogList_You: String { return self._s[3122]! } - public var MediaPicker_Send: String { return self._s[3125]! } - public var SettingsSearch_Synonyms_Stickers_Title: String { return self._s[3126]! } - public var Appearance_ThemePreview_ChatList_4_Text: String { return self._s[3127]! } - public var Call_AudioRouteSpeaker: String { return self._s[3128]! } - public var Watch_UserInfo_Title: String { return self._s[3129]! } - public var VoiceOver_Chat_PollFinalResults: String { return self._s[3130]! } - public var Appearance_AccentColor: String { return self._s[3132]! } + public var ChatList_UndoArchiveTitle: String { return self._s[3123]! } + public var Notification_Exceptions_Add: String { return self._s[3124]! } + public var DialogList_You: String { return self._s[3125]! } + public var MediaPicker_Send: String { return self._s[3128]! } + public var SettingsSearch_Synonyms_Stickers_Title: String { return self._s[3129]! } + public var Appearance_ThemePreview_ChatList_4_Text: String { return self._s[3130]! } + public var Call_AudioRouteSpeaker: String { return self._s[3131]! } + public var Watch_UserInfo_Title: String { return self._s[3132]! } + public var VoiceOver_Chat_PollFinalResults: String { return self._s[3133]! } + public var Appearance_AccentColor: String { return self._s[3135]! } public func Login_EmailPhoneSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3133]!, self._r[3133]!, [_0]) + return formatWithArgumentRanges(self._s[3136]!, self._r[3136]!, [_0]) } - public var Permissions_ContactsAllowInSettings_v0: String { return self._s[3134]! } + public var Permissions_ContactsAllowInSettings_v0: String { return self._s[3137]! } public func PUSH_CHANNEL_MESSAGE_GAME(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3135]!, self._r[3135]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3138]!, self._r[3138]!, [_1, _2]) } - public var Conversation_ClousStorageInfo_Description2: String { return self._s[3136]! } - public var WebSearch_RecentClearConfirmation: String { return self._s[3137]! } - public var Notification_CallOutgoing: String { return self._s[3138]! } - public var PrivacySettings_PasscodeAndFaceId: String { return self._s[3139]! } - public var Channel_DiscussionGroup_MakeHistoryPublic: String { return self._s[3140]! } - public var Call_RecordingDisabledMessage: String { return self._s[3141]! } - public var Message_Game: String { return self._s[3142]! } - public var Conversation_PressVolumeButtonForSound: String { return self._s[3143]! } - public var PrivacyLastSeenSettings_CustomHelp: String { return self._s[3144]! } - public var Channel_DiscussionGroup_PrivateGroup: String { return self._s[3145]! } - public var Channel_EditAdmin_PermissionAddAdmins: String { return self._s[3146]! } - public var Date_DialogDateFormat: String { return self._s[3148]! } - public var WallpaperColors_SetCustomColor: String { return self._s[3149]! } - public var Notifications_InAppNotifications: String { return self._s[3150]! } + public var Conversation_ClousStorageInfo_Description2: String { return self._s[3139]! } + public var WebSearch_RecentClearConfirmation: String { return self._s[3140]! } + public var Notification_CallOutgoing: String { return self._s[3141]! } + public var PrivacySettings_PasscodeAndFaceId: String { return self._s[3142]! } + public var Channel_DiscussionGroup_MakeHistoryPublic: String { return self._s[3143]! } + public var Call_RecordingDisabledMessage: String { return self._s[3144]! } + public var Message_Game: String { return self._s[3145]! } + public var Conversation_PressVolumeButtonForSound: String { return self._s[3146]! } + public var PrivacyLastSeenSettings_CustomHelp: String { return self._s[3147]! } + public var Channel_DiscussionGroup_PrivateGroup: String { return self._s[3148]! } + public var Channel_EditAdmin_PermissionAddAdmins: String { return self._s[3149]! } + public var Date_DialogDateFormat: String { return self._s[3151]! } + public var WallpaperColors_SetCustomColor: String { return self._s[3152]! } + public var Notifications_InAppNotifications: String { return self._s[3153]! } public func Channel_Management_RemovedBy(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3151]!, self._r[3151]!, [_0]) - } - public func Settings_ApplyProxyAlert(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3152]!, self._r[3152]!, [_1, _2]) - } - public var NewContact_Title: String { return self._s[3153]! } - public func AutoDownloadSettings_UpToForAll(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3154]!, self._r[3154]!, [_0]) } - public var Conversation_ViewContactDetails: String { return self._s[3155]! } + public func Settings_ApplyProxyAlert(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3155]!, self._r[3155]!, [_1, _2]) + } + public var NewContact_Title: String { return self._s[3156]! } + public func AutoDownloadSettings_UpToForAll(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3157]!, self._r[3157]!, [_0]) + } + public var Conversation_ViewContactDetails: String { return self._s[3158]! } public func PUSH_CHANNEL_MESSAGE_CONTACT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3157]!, self._r[3157]!, [_1]) + return formatWithArgumentRanges(self._s[3160]!, self._r[3160]!, [_1]) } - public var Checkout_NewCard_CardholderNameTitle: String { return self._s[3158]! } - public var Passport_Identity_ExpiryDateNone: String { return self._s[3159]! } - public var PrivacySettings_Title: String { return self._s[3160]! } - public var Conversation_SilentBroadcastTooltipOff: String { return self._s[3163]! } - public var GroupRemoved_UsersSectionTitle: String { return self._s[3164]! } - public var VoiceOver_Chat_ContactEmail: String { return self._s[3165]! } - public var Contacts_PhoneNumber: String { return self._s[3166]! } - public var TwoFactorSetup_Password_PlaceholderConfirmPassword: String { return self._s[3168]! } - public var Map_ShowPlaces: String { return self._s[3169]! } - public var ChatAdmins_Title: String { return self._s[3170]! } - public var InstantPage_Reference: String { return self._s[3172]! } - public var Wallet_Info_Updating: String { return self._s[3173]! } - public var ReportGroupLocation_Text: String { return self._s[3174]! } + public var Checkout_NewCard_CardholderNameTitle: String { return self._s[3161]! } + public var Passport_Identity_ExpiryDateNone: String { return self._s[3162]! } + public var PrivacySettings_Title: String { return self._s[3163]! } + public var Conversation_SilentBroadcastTooltipOff: String { return self._s[3166]! } + public var GroupRemoved_UsersSectionTitle: String { return self._s[3167]! } + public var VoiceOver_Chat_ContactEmail: String { return self._s[3168]! } + public var Contacts_PhoneNumber: String { return self._s[3169]! } + public var TwoFactorSetup_Password_PlaceholderConfirmPassword: String { return self._s[3171]! } + public var Map_ShowPlaces: String { return self._s[3172]! } + public var ChatAdmins_Title: String { return self._s[3173]! } + public var InstantPage_Reference: String { return self._s[3175]! } + public var Wallet_Info_Updating: String { return self._s[3176]! } + public var ReportGroupLocation_Text: String { return self._s[3177]! } public func PUSH_CHAT_MESSAGE_FWD(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3175]!, self._r[3175]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3178]!, self._r[3178]!, [_1, _2]) } - public var Camera_FlashOff: String { return self._s[3176]! } - public var Watch_UserInfo_Block: String { return self._s[3177]! } - public var ChatSettings_Stickers: String { return self._s[3178]! } - public var ChatSettings_DownloadInBackground: String { return self._s[3179]! } - public var Appearance_ThemeCarouselTintedNight: String { return self._s[3180]! } + public var Camera_FlashOff: String { return self._s[3179]! } + public var Watch_UserInfo_Block: String { return self._s[3180]! } + public var ChatSettings_Stickers: String { return self._s[3181]! } + public var ChatSettings_DownloadInBackground: String { return self._s[3182]! } + public var Appearance_ThemeCarouselTintedNight: String { return self._s[3183]! } public func UserInfo_BlockConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3181]!, self._r[3181]!, [_0]) + return formatWithArgumentRanges(self._s[3184]!, self._r[3184]!, [_0]) } - public var Settings_ViewPhoto: String { return self._s[3182]! } - public var Login_CheckOtherSessionMessages: String { return self._s[3183]! } - public var AutoDownloadSettings_Cellular: String { return self._s[3184]! } - public var Wallet_Created_ExportErrorTitle: String { return self._s[3185]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsExceptions: String { return self._s[3186]! } - public var VoiceOver_MessageContextShare: String { return self._s[3187]! } + public var Settings_ViewPhoto: String { return self._s[3185]! } + public var Login_CheckOtherSessionMessages: String { return self._s[3186]! } + public var AutoDownloadSettings_Cellular: String { return self._s[3187]! } + public var Wallet_Created_ExportErrorTitle: String { return self._s[3188]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsExceptions: String { return self._s[3189]! } + public var VoiceOver_MessageContextShare: String { return self._s[3190]! } public func Target_InviteToGroupConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3189]!, self._r[3189]!, [_0]) - } - public var Privacy_DeleteDrafts: String { return self._s[3190]! } - public var Wallpaper_SetCustomBackgroundInfo: String { return self._s[3191]! } - public func LastSeen_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3192]!, self._r[3192]!, [_0]) } - public var DialogList_SavedMessagesHelp: String { return self._s[3193]! } - public var Wallet_SecureStorageNotAvailable_Title: String { return self._s[3194]! } - public var DialogList_SavedMessages: String { return self._s[3195]! } - public var GroupInfo_UpgradeButton: String { return self._s[3196]! } - public var Appearance_ThemePreview_ChatList_3_Text: String { return self._s[3198]! } - public var DialogList_Pin: String { return self._s[3199]! } + public var Privacy_DeleteDrafts: String { return self._s[3193]! } + public var Wallpaper_SetCustomBackgroundInfo: String { return self._s[3194]! } + public func LastSeen_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3195]!, self._r[3195]!, [_0]) + } + public var DialogList_SavedMessagesHelp: String { return self._s[3196]! } + public var Wallet_SecureStorageNotAvailable_Title: String { return self._s[3197]! } + public var DialogList_SavedMessages: String { return self._s[3198]! } + public var GroupInfo_UpgradeButton: String { return self._s[3199]! } + public var Appearance_ThemePreview_ChatList_3_Text: String { return self._s[3201]! } + public var DialogList_Pin: String { return self._s[3202]! } public func ForwardedAuthors2(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3200]!, self._r[3200]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3203]!, self._r[3203]!, [_0, _1]) } public func Login_PhoneGenericEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3201]!, self._r[3201]!, [_0]) + return formatWithArgumentRanges(self._s[3204]!, self._r[3204]!, [_0]) } - public var Notification_Exceptions_AlwaysOn: String { return self._s[3202]! } - public var UserInfo_NotificationsDisable: String { return self._s[3203]! } - public var Conversation_ContextMenuCancelEditing: String { return self._s[3204]! } - public var Paint_Outlined: String { return self._s[3205]! } - public var Activity_PlayingGame: String { return self._s[3206]! } - public var SearchImages_NoImagesFound: String { return self._s[3207]! } - public var SocksProxySetup_ProxyType: String { return self._s[3208]! } - public var AppleWatch_ReplyPresetsHelp: String { return self._s[3210]! } - public var Conversation_ContextMenuCancelSending: String { return self._s[3211]! } - public var Settings_AppLanguage: String { return self._s[3212]! } - public var TwoStepAuth_ResetAccountHelp: String { return self._s[3213]! } - public var Common_ChoosePhoto: String { return self._s[3214]! } - public var AuthSessions_AddDevice_InvalidQRCode: String { return self._s[3215]! } - public var CallFeedback_ReasonEcho: String { return self._s[3216]! } + public var Notification_Exceptions_AlwaysOn: String { return self._s[3205]! } + public var UserInfo_NotificationsDisable: String { return self._s[3206]! } + public var Conversation_ContextMenuCancelEditing: String { return self._s[3207]! } + public var Paint_Outlined: String { return self._s[3208]! } + public var Activity_PlayingGame: String { return self._s[3209]! } + public var SearchImages_NoImagesFound: String { return self._s[3210]! } + public var SocksProxySetup_ProxyType: String { return self._s[3211]! } + public var AppleWatch_ReplyPresetsHelp: String { return self._s[3213]! } + public var Conversation_ContextMenuCancelSending: String { return self._s[3214]! } + public var Settings_AppLanguage: String { return self._s[3215]! } + public var TwoStepAuth_ResetAccountHelp: String { return self._s[3216]! } + public var Common_ChoosePhoto: String { return self._s[3217]! } + public var AuthSessions_AddDevice_InvalidQRCode: String { return self._s[3218]! } + public var CallFeedback_ReasonEcho: String { return self._s[3219]! } public func PUSH_PINNED_AUDIO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3217]!, self._r[3217]!, [_1]) + return formatWithArgumentRanges(self._s[3220]!, self._r[3220]!, [_1]) } - public var Privacy_Calls_AlwaysAllow: String { return self._s[3218]! } - public var PollResults_Collapse: String { return self._s[3219]! } - public var Activity_UploadingVideo: String { return self._s[3220]! } - public var Conversation_WalletRequiredNotNow: String { return self._s[3221]! } - public var ChannelInfo_DeleteChannelConfirmation: String { return self._s[3222]! } - public var NetworkUsageSettings_Wifi: String { return self._s[3223]! } - public var VoiceOver_Editing_ClearText: String { return self._s[3224]! } - public var PUSH_SENDER_YOU: String { return self._s[3225]! } - public var Channel_BanUser_PermissionReadMessages: String { return self._s[3226]! } - public var Checkout_PayWithTouchId: String { return self._s[3227]! } - public var Wallpaper_ResetWallpapersConfirmation: String { return self._s[3228]! } + public var Privacy_Calls_AlwaysAllow: String { return self._s[3221]! } + public var PollResults_Collapse: String { return self._s[3222]! } + public var Activity_UploadingVideo: String { return self._s[3223]! } + public var Conversation_WalletRequiredNotNow: String { return self._s[3224]! } + public var ChannelInfo_DeleteChannelConfirmation: String { return self._s[3225]! } + public var NetworkUsageSettings_Wifi: String { return self._s[3226]! } + public var VoiceOver_Editing_ClearText: String { return self._s[3227]! } + public var PUSH_SENDER_YOU: String { return self._s[3228]! } + public var Channel_BanUser_PermissionReadMessages: String { return self._s[3229]! } + public var Checkout_PayWithTouchId: String { return self._s[3230]! } + public var Wallpaper_ResetWallpapersConfirmation: String { return self._s[3231]! } public func PUSH_LOCKED_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3230]!, self._r[3230]!, [_1]) - } - public var Notifications_ExceptionsNone: String { return self._s[3231]! } - public func Message_ForwardedMessageShort(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3232]!, self._r[3232]!, [_0]) - } - public func PUSH_PINNED_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3233]!, self._r[3233]!, [_1]) } - public var AuthSessions_IncompleteAttempts: String { return self._s[3235]! } - public var Passport_Address_Region: String { return self._s[3238]! } - public var ChatList_DeleteChat: String { return self._s[3239]! } - public var LogoutOptions_ClearCacheTitle: String { return self._s[3240]! } - public var PhotoEditor_TiltShift: String { return self._s[3241]! } - public var Settings_FAQ_URL: String { return self._s[3242]! } - public var TwoFactorSetup_EmailVerification_ChangeAction: String { return self._s[3243]! } - public var Passport_Language_sl: String { return self._s[3244]! } - public var Settings_PrivacySettings: String { return self._s[3246]! } - public var SharedMedia_TitleLink: String { return self._s[3247]! } - public var Passport_Identity_TypePassportUploadScan: String { return self._s[3248]! } - public var Settings_SetProfilePhoto: String { return self._s[3249]! } - public var Channel_About_Help: String { return self._s[3250]! } - public var Contacts_PermissionsEnable: String { return self._s[3251]! } - public var Wallet_Sending_Title: String { return self._s[3252]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsAlert: String { return self._s[3253]! } - public var AttachmentMenu_SendAsFiles: String { return self._s[3254]! } - public var CallFeedback_ReasonInterruption: String { return self._s[3256]! } - public var Passport_Address_AddTemporaryRegistration: String { return self._s[3257]! } - public var AutoDownloadSettings_AutodownloadVideos: String { return self._s[3258]! } - public var ChatSettings_AutoDownloadSettings_Delimeter: String { return self._s[3259]! } - public var OldChannels_Title: String { return self._s[3260]! } - public var PrivacySettings_DeleteAccountTitle: String { return self._s[3261]! } - public var AccessDenied_VideoMessageCamera: String { return self._s[3263]! } - public var Map_OpenInYandexMaps: String { return self._s[3265]! } - public var CreateGroup_ErrorLocatedGroupsTooMuch: String { return self._s[3266]! } - public var VoiceOver_MessageContextReply: String { return self._s[3267]! } - public var PhotoEditor_SaturationTool: String { return self._s[3269]! } + public var Notifications_ExceptionsNone: String { return self._s[3234]! } + public func Message_ForwardedMessageShort(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3235]!, self._r[3235]!, [_0]) + } + public func PUSH_PINNED_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3236]!, self._r[3236]!, [_1]) + } + public var AuthSessions_IncompleteAttempts: String { return self._s[3238]! } + public var Passport_Address_Region: String { return self._s[3241]! } + public var ChatList_DeleteChat: String { return self._s[3242]! } + public var LogoutOptions_ClearCacheTitle: String { return self._s[3243]! } + public var PhotoEditor_TiltShift: String { return self._s[3244]! } + public var Settings_FAQ_URL: String { return self._s[3245]! } + public var TwoFactorSetup_EmailVerification_ChangeAction: String { return self._s[3246]! } + public var Passport_Language_sl: String { return self._s[3247]! } + public var Settings_PrivacySettings: String { return self._s[3249]! } + public var SharedMedia_TitleLink: String { return self._s[3250]! } + public var Passport_Identity_TypePassportUploadScan: String { return self._s[3251]! } + public var Settings_SetProfilePhoto: String { return self._s[3252]! } + public var Channel_About_Help: String { return self._s[3253]! } + public var Contacts_PermissionsEnable: String { return self._s[3254]! } + public var Wallet_Sending_Title: String { return self._s[3255]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsAlert: String { return self._s[3256]! } + public var AttachmentMenu_SendAsFiles: String { return self._s[3257]! } + public var CallFeedback_ReasonInterruption: String { return self._s[3259]! } + public var Passport_Address_AddTemporaryRegistration: String { return self._s[3260]! } + public var AutoDownloadSettings_AutodownloadVideos: String { return self._s[3261]! } + public var ChatSettings_AutoDownloadSettings_Delimeter: String { return self._s[3262]! } + public var OldChannels_Title: String { return self._s[3263]! } + public var PrivacySettings_DeleteAccountTitle: String { return self._s[3264]! } + public var AccessDenied_VideoMessageCamera: String { return self._s[3266]! } + public var Map_OpenInYandexMaps: String { return self._s[3268]! } + public var CreateGroup_ErrorLocatedGroupsTooMuch: String { return self._s[3269]! } + public var VoiceOver_MessageContextReply: String { return self._s[3270]! } + public var PhotoEditor_SaturationTool: String { return self._s[3272]! } public func PUSH_MESSAGE_STICKER(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3270]!, self._r[3270]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3273]!, self._r[3273]!, [_1, _2]) } - public var PrivacyPhoneNumberSettings_CustomHelp: String { return self._s[3271]! } - public var Notification_Exceptions_NewException_NotificationHeader: String { return self._s[3272]! } - public var Group_OwnershipTransfer_ErrorLocatedGroupsTooMuch: String { return self._s[3273]! } + public var PrivacyPhoneNumberSettings_CustomHelp: String { return self._s[3274]! } + public var Notification_Exceptions_NewException_NotificationHeader: String { return self._s[3275]! } + public var Group_OwnershipTransfer_ErrorLocatedGroupsTooMuch: String { return self._s[3276]! } public func LOCAL_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3274]!, self._r[3274]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[3277]!, self._r[3277]!, [_1, "\(_2)"]) } - public var Appearance_ThemePreview_ChatList_2_Text: String { return self._s[3275]! } - public var Channel_Username_InvalidTooShort: String { return self._s[3277]! } - public var SettingsSearch_Synonyms_Wallet: String { return self._s[3278]! } + public var Appearance_ThemePreview_ChatList_2_Text: String { return self._s[3278]! } + public var Channel_Username_InvalidTooShort: String { return self._s[3280]! } + public var SettingsSearch_Synonyms_Wallet: String { return self._s[3281]! } public func Group_OwnershipTransfer_DescriptionInfo(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3279]!, self._r[3279]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3282]!, self._r[3282]!, [_1, _2]) } - public var Forward_ErrorPublicPollDisabledInChannels: String { return self._s[3280]! } + public var Forward_ErrorPublicPollDisabledInChannels: String { return self._s[3283]! } public func PUSH_CHAT_MESSAGE_GAME(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3281]!, self._r[3281]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3284]!, self._r[3284]!, [_1, _2, _3]) } - public var WallpaperPreview_PatternTitle: String { return self._s[3282]! } - public var GroupInfo_PublicLinkAdd: String { return self._s[3283]! } - public var Passport_PassportInformation: String { return self._s[3286]! } - public var Theme_Unsupported: String { return self._s[3287]! } - public var WatchRemote_AlertTitle: String { return self._s[3288]! } - public var Privacy_GroupsAndChannels_NeverAllow: String { return self._s[3289]! } - public var ConvertToSupergroup_HelpText: String { return self._s[3291]! } + public var WallpaperPreview_PatternTitle: String { return self._s[3285]! } + public var GroupInfo_PublicLinkAdd: String { return self._s[3286]! } + public var Passport_PassportInformation: String { return self._s[3289]! } + public var Theme_Unsupported: String { return self._s[3290]! } + public var WatchRemote_AlertTitle: String { return self._s[3291]! } + public var Privacy_GroupsAndChannels_NeverAllow: String { return self._s[3292]! } + public var ConvertToSupergroup_HelpText: String { return self._s[3294]! } public func Time_MonthOfYear_m7(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3292]!, self._r[3292]!, [_0]) + return formatWithArgumentRanges(self._s[3295]!, self._r[3295]!, [_0]) } public func PUSH_PHONE_CALL_REQUEST(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3293]!, self._r[3293]!, [_1]) + return formatWithArgumentRanges(self._s[3296]!, self._r[3296]!, [_1]) } - public var Privacy_GroupsAndChannels_CustomHelp: String { return self._s[3294]! } - public var Wallet_Navigation_Done: String { return self._s[3296]! } - public var TwoStepAuth_RecoveryCodeInvalid: String { return self._s[3297]! } - public var AccessDenied_CameraDisabled: String { return self._s[3298]! } + public var Privacy_GroupsAndChannels_CustomHelp: String { return self._s[3297]! } + public var Wallet_Navigation_Done: String { return self._s[3299]! } + public var TwoStepAuth_RecoveryCodeInvalid: String { return self._s[3300]! } + public var AccessDenied_CameraDisabled: String { return self._s[3301]! } public func Channel_Username_UsernameIsAvailable(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3299]!, self._r[3299]!, [_0]) + return formatWithArgumentRanges(self._s[3302]!, self._r[3302]!, [_0]) } - public var ClearCache_Forever: String { return self._s[3300]! } - public var AuthSessions_AddDeviceIntro_Title: String { return self._s[3301]! } - public var CreatePoll_Quiz: String { return self._s[3302]! } - public var PhotoEditor_ContrastTool: String { return self._s[3305]! } + public var ClearCache_Forever: String { return self._s[3303]! } + public var AuthSessions_AddDeviceIntro_Title: String { return self._s[3304]! } + public var CreatePoll_Quiz: String { return self._s[3305]! } + public var PhotoEditor_ContrastTool: String { return self._s[3308]! } public func PUSH_PINNED_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3306]!, self._r[3306]!, [_1]) + return formatWithArgumentRanges(self._s[3309]!, self._r[3309]!, [_1]) } - public var DialogList_Draft: String { return self._s[3307]! } - public var Wallet_Configuration_BlockchainIdInfo: String { return self._s[3308]! } - public var Privacy_TopPeersDelete: String { return self._s[3310]! } - public var LoginPassword_PasswordPlaceholder: String { return self._s[3311]! } - public var Passport_Identity_TypeIdentityCardUploadScan: String { return self._s[3312]! } - public var WebSearch_RecentSectionClear: String { return self._s[3313]! } - public var EditTheme_ErrorInvalidCharacters: String { return self._s[3314]! } - public var Watch_ChatList_NoConversationsTitle: String { return self._s[3316]! } - public var Common_Done: String { return self._s[3318]! } - public var Shortcut_SwitchAccount: String { return self._s[3319]! } - public var AuthSessions_EmptyText: String { return self._s[3320]! } - public var Wallet_Configuration_BlockchainNameChangedTitle: String { return self._s[3321]! } - public var Conversation_ShareBotContactConfirmation: String { return self._s[3322]! } - public var Tour_Title5: String { return self._s[3323]! } - public var Wallet_Settings_Title: String { return self._s[3324]! } + public var DialogList_Draft: String { return self._s[3310]! } + public var Wallet_Configuration_BlockchainIdInfo: String { return self._s[3311]! } + public var Privacy_TopPeersDelete: String { return self._s[3313]! } + public var LoginPassword_PasswordPlaceholder: String { return self._s[3314]! } + public var Passport_Identity_TypeIdentityCardUploadScan: String { return self._s[3315]! } + public var WebSearch_RecentSectionClear: String { return self._s[3316]! } + public var EditTheme_ErrorInvalidCharacters: String { return self._s[3317]! } + public var Watch_ChatList_NoConversationsTitle: String { return self._s[3319]! } + public var Common_Done: String { return self._s[3321]! } + public var Shortcut_SwitchAccount: String { return self._s[3322]! } + public var AuthSessions_EmptyText: String { return self._s[3323]! } + public var Wallet_Configuration_BlockchainNameChangedTitle: String { return self._s[3324]! } + public var Conversation_ShareBotContactConfirmation: String { return self._s[3325]! } + public var Tour_Title5: String { return self._s[3326]! } + public var Wallet_Settings_Title: String { return self._s[3327]! } public func Map_DirectionsDriveEta(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3325]!, self._r[3325]!, [_0]) + return formatWithArgumentRanges(self._s[3328]!, self._r[3328]!, [_0]) } - public var ApplyLanguage_UnsufficientDataTitle: String { return self._s[3326]! } - public var Conversation_LinkDialogSave: String { return self._s[3327]! } - public var GroupInfo_ActionRestrict: String { return self._s[3328]! } - public var Checkout_Title: String { return self._s[3329]! } - public var Channel_DiscussionGroup_HeaderLabel: String { return self._s[3331]! } - public var Channel_AdminLog_CanChangeInfo: String { return self._s[3333]! } - public var Notification_RenamedGroup: String { return self._s[3334]! } - public var PeopleNearby_Groups: String { return self._s[3335]! } - public var Checkout_PayWithFaceId: String { return self._s[3336]! } - public var Channel_BanList_BlockedTitle: String { return self._s[3337]! } - public var SettingsSearch_Synonyms_Notifications_InAppNotificationsSound: String { return self._s[3339]! } - public var Checkout_WebConfirmation_Title: String { return self._s[3340]! } - public var Notifications_MessageNotificationsAlert: String { return self._s[3341]! } + public var ApplyLanguage_UnsufficientDataTitle: String { return self._s[3329]! } + public var Conversation_LinkDialogSave: String { return self._s[3330]! } + public var GroupInfo_ActionRestrict: String { return self._s[3331]! } + public var Checkout_Title: String { return self._s[3332]! } + public var Channel_DiscussionGroup_HeaderLabel: String { return self._s[3334]! } + public var Channel_AdminLog_CanChangeInfo: String { return self._s[3336]! } + public var Notification_RenamedGroup: String { return self._s[3337]! } + public var PeopleNearby_Groups: String { return self._s[3338]! } + public var Checkout_PayWithFaceId: String { return self._s[3339]! } + public var Channel_BanList_BlockedTitle: String { return self._s[3340]! } + public var SettingsSearch_Synonyms_Notifications_InAppNotificationsSound: String { return self._s[3342]! } + public var Checkout_WebConfirmation_Title: String { return self._s[3343]! } + public var Notifications_MessageNotificationsAlert: String { return self._s[3344]! } public func Activity_RemindAboutGroup(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3342]!, self._r[3342]!, [_0]) + return formatWithArgumentRanges(self._s[3345]!, self._r[3345]!, [_0]) } - public var Profile_AddToExisting: String { return self._s[3344]! } + public var Profile_AddToExisting: String { return self._s[3347]! } public func Profile_CreateEncryptedChatOutdatedError(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3345]!, self._r[3345]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3348]!, self._r[3348]!, [_0, _1]) } - public var Cache_Files: String { return self._s[3347]! } - public var Permissions_PrivacyPolicy: String { return self._s[3348]! } - public var SocksProxySetup_ConnectAndSave: String { return self._s[3349]! } - public var UserInfo_NotificationsDefaultDisabled: String { return self._s[3350]! } - public var AutoDownloadSettings_TypeContacts: String { return self._s[3352]! } - public var Appearance_ThemePreview_ChatList_1_Text: String { return self._s[3354]! } - public var Calls_NoCallsPlaceholder: String { return self._s[3355]! } + public var Cache_Files: String { return self._s[3350]! } + public var Permissions_PrivacyPolicy: String { return self._s[3351]! } + public var SocksProxySetup_ConnectAndSave: String { return self._s[3352]! } + public var UserInfo_NotificationsDefaultDisabled: String { return self._s[3353]! } + public var AutoDownloadSettings_TypeContacts: String { return self._s[3355]! } + public var Appearance_ThemePreview_ChatList_1_Text: String { return self._s[3357]! } + public var Calls_NoCallsPlaceholder: String { return self._s[3358]! } public func Wallet_Receive_ShareInvoiceUrlInfo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3356]!, self._r[3356]!, [_0]) + return formatWithArgumentRanges(self._s[3359]!, self._r[3359]!, [_0]) } - public var Channel_Username_RevokeExistingUsernamesInfo: String { return self._s[3357]! } - public var VoiceOver_AttachMedia: String { return self._s[3360]! } - public var Notifications_ExceptionsGroupPlaceholder: String { return self._s[3361]! } + public var Channel_Username_RevokeExistingUsernamesInfo: String { return self._s[3360]! } + public var VoiceOver_AttachMedia: String { return self._s[3363]! } + public var Notifications_ExceptionsGroupPlaceholder: String { return self._s[3364]! } public func PUSH_CHAT_MESSAGE_INVOICE(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3362]!, self._r[3362]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3365]!, self._r[3365]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsSound: String { return self._s[3363]! } - public var Conversation_SetReminder_Title: String { return self._s[3364]! } - public var Passport_FieldAddressHelp: String { return self._s[3365]! } - public var Privacy_GroupsAndChannels_InviteToChannelMultipleError: String { return self._s[3366]! } - public var PUSH_REMINDER_TITLE: String { return self._s[3367]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsSound: String { return self._s[3366]! } + public var Conversation_SetReminder_Title: String { return self._s[3367]! } + public var Passport_FieldAddressHelp: String { return self._s[3368]! } + public var Privacy_GroupsAndChannels_InviteToChannelMultipleError: String { return self._s[3369]! } + public var PUSH_REMINDER_TITLE: String { return self._s[3370]! } public func Login_TermsOfService_ProceedBot(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3368]!, self._r[3368]!, [_0]) + return formatWithArgumentRanges(self._s[3371]!, self._r[3371]!, [_0]) } - public var Channel_AdminLog_EmptyTitle: String { return self._s[3369]! } - public var Privacy_Calls_NeverAllow_Title: String { return self._s[3370]! } - public var Login_UnknownError: String { return self._s[3371]! } - public var Group_UpgradeNoticeText2: String { return self._s[3374]! } - public var Watch_Compose_AddContact: String { return self._s[3375]! } - public var ClearCache_StorageServiceFiles: String { return self._s[3376]! } - public var Web_Error: String { return self._s[3377]! } - public var Gif_Search: String { return self._s[3378]! } - public var Profile_MessageLifetime1h: String { return self._s[3379]! } - public var CheckoutInfo_ReceiverInfoEmailPlaceholder: String { return self._s[3380]! } - public var Channel_Username_CheckingUsername: String { return self._s[3381]! } - public var CallFeedback_ReasonSilentRemote: String { return self._s[3382]! } - public var AutoDownloadSettings_TypeChannels: String { return self._s[3383]! } - public var Channel_AboutItem: String { return self._s[3384]! } - public var Privacy_GroupsAndChannels_AlwaysAllow_Placeholder: String { return self._s[3386]! } - public var VoiceOver_Chat_VoiceMessage: String { return self._s[3387]! } - public var GroupInfo_SharedMedia: String { return self._s[3388]! } + public var Channel_AdminLog_EmptyTitle: String { return self._s[3372]! } + public var Privacy_Calls_NeverAllow_Title: String { return self._s[3373]! } + public var Login_UnknownError: String { return self._s[3374]! } + public var Group_UpgradeNoticeText2: String { return self._s[3377]! } + public var Watch_Compose_AddContact: String { return self._s[3378]! } + public var ClearCache_StorageServiceFiles: String { return self._s[3379]! } + public var Web_Error: String { return self._s[3380]! } + public var Gif_Search: String { return self._s[3381]! } + public var Profile_MessageLifetime1h: String { return self._s[3382]! } + public var CheckoutInfo_ReceiverInfoEmailPlaceholder: String { return self._s[3383]! } + public var Channel_Username_CheckingUsername: String { return self._s[3384]! } + public var CallFeedback_ReasonSilentRemote: String { return self._s[3385]! } + public var AutoDownloadSettings_TypeChannels: String { return self._s[3386]! } + public var Channel_AboutItem: String { return self._s[3387]! } + public var Privacy_GroupsAndChannels_AlwaysAllow_Placeholder: String { return self._s[3389]! } + public var VoiceOver_Chat_VoiceMessage: String { return self._s[3390]! } + public var GroupInfo_SharedMedia: String { return self._s[3391]! } public func Channel_AdminLog_MessagePromotedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3389]!, self._r[3389]!, [_1]) + return formatWithArgumentRanges(self._s[3392]!, self._r[3392]!, [_1]) } - public var Call_PhoneCallInProgressMessage: String { return self._s[3390]! } + public var Call_PhoneCallInProgressMessage: String { return self._s[3393]! } public func PUSH_CHANNEL_ALBUM(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3391]!, self._r[3391]!, [_1]) + return formatWithArgumentRanges(self._s[3394]!, self._r[3394]!, [_1]) } - public var ChatList_UndoArchiveRevealedText: String { return self._s[3392]! } - public var GroupInfo_InviteLink_RevokeAlert_Text: String { return self._s[3393]! } - public var Conversation_SearchByName_Placeholder: String { return self._s[3394]! } - public var CreatePoll_AddOption: String { return self._s[3395]! } - public var GroupInfo_Permissions_SearchPlaceholder: String { return self._s[3396]! } - public var Group_UpgradeNoticeHeader: String { return self._s[3397]! } - public var Channel_Management_AddModerator: String { return self._s[3398]! } - public var AutoDownloadSettings_MaxFileSize: String { return self._s[3399]! } - public var StickerPacksSettings_ShowStickersButton: String { return self._s[3400]! } - public var Wallet_Info_RefreshErrorNetworkText: String { return self._s[3401]! } - public var Theme_Colors_Background: String { return self._s[3402]! } - public var NotificationsSound_Hello: String { return self._s[3404]! } - public var SocksProxySetup_SavedProxies: String { return self._s[3405]! } - public var Channel_Stickers_Placeholder: String { return self._s[3407]! } + public var ChatList_UndoArchiveRevealedText: String { return self._s[3395]! } + public var GroupInfo_InviteLink_RevokeAlert_Text: String { return self._s[3396]! } + public var Conversation_SearchByName_Placeholder: String { return self._s[3397]! } + public var CreatePoll_AddOption: String { return self._s[3398]! } + public var GroupInfo_Permissions_SearchPlaceholder: String { return self._s[3399]! } + public var Group_UpgradeNoticeHeader: String { return self._s[3400]! } + public var Channel_Management_AddModerator: String { return self._s[3401]! } + public var AutoDownloadSettings_MaxFileSize: String { return self._s[3402]! } + public var StickerPacksSettings_ShowStickersButton: String { return self._s[3403]! } + public var Wallet_Info_RefreshErrorNetworkText: String { return self._s[3404]! } + public var Theme_Colors_Background: String { return self._s[3405]! } + public var NotificationsSound_Hello: String { return self._s[3407]! } + public var SocksProxySetup_SavedProxies: String { return self._s[3408]! } + public var Channel_Stickers_Placeholder: String { return self._s[3410]! } public func Login_EmailCodeBody(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3408]!, self._r[3408]!, [_0]) + return formatWithArgumentRanges(self._s[3411]!, self._r[3411]!, [_0]) } - public var PrivacyPolicy_DeclineDeclineAndDelete: String { return self._s[3409]! } - public var Channel_Management_AddModeratorHelp: String { return self._s[3410]! } - public var ContactInfo_BirthdayLabel: String { return self._s[3411]! } - public var ChangePhoneNumberCode_RequestingACall: String { return self._s[3412]! } - public var AutoDownloadSettings_Channels: String { return self._s[3413]! } - public var Passport_Language_mn: String { return self._s[3414]! } - public var Notifications_ResetAllNotificationsHelp: String { return self._s[3417]! } - public var GroupInfo_Permissions_SlowmodeValue_Off: String { return self._s[3418]! } - public var Passport_Language_ja: String { return self._s[3420]! } - public var Settings_About_Title: String { return self._s[3421]! } - public var Settings_NotificationsAndSounds: String { return self._s[3422]! } - public var ChannelInfo_DeleteGroup: String { return self._s[3423]! } - public var Settings_BlockedUsers: String { return self._s[3424]! } + public var PrivacyPolicy_DeclineDeclineAndDelete: String { return self._s[3412]! } + public var Channel_Management_AddModeratorHelp: String { return self._s[3413]! } + public var ContactInfo_BirthdayLabel: String { return self._s[3414]! } + public var ChangePhoneNumberCode_RequestingACall: String { return self._s[3415]! } + public var AutoDownloadSettings_Channels: String { return self._s[3416]! } + public var Passport_Language_mn: String { return self._s[3417]! } + public var Notifications_ResetAllNotificationsHelp: String { return self._s[3420]! } + public var GroupInfo_Permissions_SlowmodeValue_Off: String { return self._s[3421]! } + public var Passport_Language_ja: String { return self._s[3423]! } + public var Settings_About_Title: String { return self._s[3424]! } + public var Settings_NotificationsAndSounds: String { return self._s[3425]! } + public var ChannelInfo_DeleteGroup: String { return self._s[3426]! } + public var Settings_BlockedUsers: String { return self._s[3427]! } public func Time_MonthOfYear_m4(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3425]!, self._r[3425]!, [_0]) + return formatWithArgumentRanges(self._s[3428]!, self._r[3428]!, [_0]) } - public var EditTheme_Create_Preview_OutgoingText: String { return self._s[3426]! } - public var Wallet_Weekday_Today: String { return self._s[3427]! } - public var AutoDownloadSettings_PreloadVideo: String { return self._s[3428]! } - public var Widget_ApplicationLocked: String { return self._s[3429]! } - public var Passport_Address_AddResidentialAddress: String { return self._s[3430]! } - public var Channel_Username_Title: String { return self._s[3431]! } + public var EditTheme_Create_Preview_OutgoingText: String { return self._s[3429]! } + public var Wallet_Weekday_Today: String { return self._s[3430]! } + public var AutoDownloadSettings_PreloadVideo: String { return self._s[3431]! } + public var Widget_ApplicationLocked: String { return self._s[3432]! } + public var Passport_Address_AddResidentialAddress: String { return self._s[3433]! } + public var Channel_Username_Title: String { return self._s[3434]! } public func Notification_RemovedGroupPhoto(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3432]!, self._r[3432]!, [_0]) + return formatWithArgumentRanges(self._s[3435]!, self._r[3435]!, [_0]) } - public var AttachmentMenu_File: String { return self._s[3434]! } - public var AppleWatch_Title: String { return self._s[3435]! } - public var Activity_RecordingVideoMessage: String { return self._s[3436]! } + public var AttachmentMenu_File: String { return self._s[3437]! } + public var AppleWatch_Title: String { return self._s[3438]! } + public var Activity_RecordingVideoMessage: String { return self._s[3439]! } public func Channel_DiscussionGroup_PublicChannelLink(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3437]!, self._r[3437]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3440]!, self._r[3440]!, [_1, _2]) } - public var Theme_Colors_Messages: String { return self._s[3438]! } - public var Weekday_Saturday: String { return self._s[3439]! } - public var WallpaperPreview_SwipeColorsTopText: String { return self._s[3440]! } - public var Profile_CreateEncryptedChatError: String { return self._s[3441]! } - public var Common_Next: String { return self._s[3443]! } - public var Channel_Stickers_YourStickers: String { return self._s[3445]! } - public var Message_Theme: String { return self._s[3446]! } - public var Call_AudioRouteHeadphones: String { return self._s[3447]! } - public var TwoStepAuth_EnterPasswordForgot: String { return self._s[3449]! } - public var Watch_Contacts_NoResults: String { return self._s[3451]! } - public var PhotoEditor_TintTool: String { return self._s[3454]! } - public var LoginPassword_ResetAccount: String { return self._s[3456]! } - public var Settings_SavedMessages: String { return self._s[3457]! } - public var SettingsSearch_Synonyms_Appearance_Animations: String { return self._s[3458]! } - public var Bot_GenericSupportStatus: String { return self._s[3459]! } - public var StickerPack_Add: String { return self._s[3460]! } - public var Checkout_TotalAmount: String { return self._s[3461]! } - public var Your_cards_number_is_invalid: String { return self._s[3462]! } - public var SettingsSearch_Synonyms_Appearance_AutoNightTheme: String { return self._s[3463]! } - public var VoiceOver_Chat_VideoMessage: String { return self._s[3464]! } + public var Theme_Colors_Messages: String { return self._s[3441]! } + public var Weekday_Saturday: String { return self._s[3442]! } + public var WallpaperPreview_SwipeColorsTopText: String { return self._s[3443]! } + public var Profile_CreateEncryptedChatError: String { return self._s[3444]! } + public var Common_Next: String { return self._s[3446]! } + public var Channel_Stickers_YourStickers: String { return self._s[3448]! } + public var Message_Theme: String { return self._s[3449]! } + public var Call_AudioRouteHeadphones: String { return self._s[3450]! } + public var TwoStepAuth_EnterPasswordForgot: String { return self._s[3452]! } + public var Watch_Contacts_NoResults: String { return self._s[3454]! } + public var PhotoEditor_TintTool: String { return self._s[3457]! } + public var LoginPassword_ResetAccount: String { return self._s[3459]! } + public var Settings_SavedMessages: String { return self._s[3460]! } + public var SettingsSearch_Synonyms_Appearance_Animations: String { return self._s[3461]! } + public var Bot_GenericSupportStatus: String { return self._s[3462]! } + public var StickerPack_Add: String { return self._s[3463]! } + public var Checkout_TotalAmount: String { return self._s[3464]! } + public var Your_cards_number_is_invalid: String { return self._s[3465]! } + public var SettingsSearch_Synonyms_Appearance_AutoNightTheme: String { return self._s[3466]! } + public var VoiceOver_Chat_VideoMessage: String { return self._s[3467]! } public func ChangePhoneNumberCode_CallTimer(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3465]!, self._r[3465]!, [_0]) + return formatWithArgumentRanges(self._s[3468]!, self._r[3468]!, [_0]) } public func GroupPermission_AddedInfo(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3466]!, self._r[3466]!, [_1, _2]) - } - public var ChatSettings_ConnectionType_UseSocks5: String { return self._s[3467]! } - public func PUSH_CHAT_PHOTO_EDITED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3469]!, self._r[3469]!, [_1, _2]) } + public var ChatSettings_ConnectionType_UseSocks5: String { return self._s[3470]! } + public func PUSH_CHAT_PHOTO_EDITED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3472]!, self._r[3472]!, [_1, _2]) + } public func Conversation_RestrictedTextTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3470]!, self._r[3470]!, [_0]) + return formatWithArgumentRanges(self._s[3473]!, self._r[3473]!, [_0]) } - public var GroupInfo_InviteLink_ShareLink: String { return self._s[3471]! } - public var StickerPack_Share: String { return self._s[3472]! } - public var Passport_DeleteAddress: String { return self._s[3473]! } - public var Settings_Passport: String { return self._s[3474]! } - public var SharedMedia_EmptyFilesText: String { return self._s[3475]! } - public var Conversation_DeleteMessagesForMe: String { return self._s[3476]! } - public var PasscodeSettings_AutoLock_IfAwayFor_1hour: String { return self._s[3477]! } - public var Contacts_PermissionsText: String { return self._s[3478]! } - public var Group_Setup_HistoryVisible: String { return self._s[3479]! } - public var Wallet_Month_ShortDecember: String { return self._s[3481]! } - public var Channel_EditAdmin_PermissionEnabledByDefault: String { return self._s[3482]! } - public var Passport_Address_AddRentalAgreement: String { return self._s[3483]! } - public var SocksProxySetup_Title: String { return self._s[3484]! } - public var Notification_Mute1h: String { return self._s[3485]! } + public var GroupInfo_InviteLink_ShareLink: String { return self._s[3474]! } + public var StickerPack_Share: String { return self._s[3475]! } + public var Passport_DeleteAddress: String { return self._s[3476]! } + public var Settings_Passport: String { return self._s[3477]! } + public var SharedMedia_EmptyFilesText: String { return self._s[3478]! } + public var Conversation_DeleteMessagesForMe: String { return self._s[3479]! } + public var PasscodeSettings_AutoLock_IfAwayFor_1hour: String { return self._s[3480]! } + public var Contacts_PermissionsText: String { return self._s[3481]! } + public var Group_Setup_HistoryVisible: String { return self._s[3482]! } + public var Wallet_Month_ShortDecember: String { return self._s[3484]! } + public var Channel_EditAdmin_PermissionEnabledByDefault: String { return self._s[3485]! } + public var Passport_Address_AddRentalAgreement: String { return self._s[3486]! } + public var SocksProxySetup_Title: String { return self._s[3487]! } + public var Notification_Mute1h: String { return self._s[3488]! } public func Passport_Email_CodeHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3486]!, self._r[3486]!, [_0]) + return formatWithArgumentRanges(self._s[3489]!, self._r[3489]!, [_0]) } - public var NotificationSettings_ShowNotificationsAllAccountsInfoOff: String { return self._s[3487]! } + public var NotificationSettings_ShowNotificationsAllAccountsInfoOff: String { return self._s[3490]! } public func PUSH_PINNED_GEOLIVE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3488]!, self._r[3488]!, [_1]) + return formatWithArgumentRanges(self._s[3491]!, self._r[3491]!, [_1]) } - public var FastTwoStepSetup_PasswordSection: String { return self._s[3489]! } - public var NetworkUsageSettings_ResetStatsConfirmation: String { return self._s[3492]! } - public var InfoPlist_NSFaceIDUsageDescription: String { return self._s[3494]! } - public var DialogList_NoMessagesText: String { return self._s[3495]! } - public var Privacy_ContactsResetConfirmation: String { return self._s[3496]! } - public var Privacy_Calls_P2PHelp: String { return self._s[3497]! } - public var Channel_DiscussionGroup_SearchPlaceholder: String { return self._s[3499]! } - public var Your_cards_expiration_year_is_invalid: String { return self._s[3500]! } - public var Common_TakePhotoOrVideo: String { return self._s[3501]! } - public var Wallet_Words_Text: String { return self._s[3502]! } - public var Call_StatusBusy: String { return self._s[3503]! } - public var Conversation_PinnedMessage: String { return self._s[3504]! } - public var AutoDownloadSettings_VoiceMessagesTitle: String { return self._s[3505]! } - public var Wallet_Configuration_BlockchainNameChangedProceed: String { return self._s[3506]! } - public var TwoStepAuth_SetupPasswordConfirmFailed: String { return self._s[3507]! } - public var Undo_ChatCleared: String { return self._s[3508]! } - public var AppleWatch_ReplyPresets: String { return self._s[3509]! } - public var Passport_DiscardMessageDescription: String { return self._s[3511]! } - public var Login_NetworkError: String { return self._s[3512]! } + public var FastTwoStepSetup_PasswordSection: String { return self._s[3492]! } + public var NetworkUsageSettings_ResetStatsConfirmation: String { return self._s[3495]! } + public var InfoPlist_NSFaceIDUsageDescription: String { return self._s[3497]! } + public var DialogList_NoMessagesText: String { return self._s[3498]! } + public var Privacy_ContactsResetConfirmation: String { return self._s[3499]! } + public var Privacy_Calls_P2PHelp: String { return self._s[3500]! } + public var Channel_DiscussionGroup_SearchPlaceholder: String { return self._s[3502]! } + public var Your_cards_expiration_year_is_invalid: String { return self._s[3503]! } + public var Common_TakePhotoOrVideo: String { return self._s[3504]! } + public var Wallet_Words_Text: String { return self._s[3505]! } + public var Call_StatusBusy: String { return self._s[3506]! } + public var Conversation_PinnedMessage: String { return self._s[3507]! } + public var AutoDownloadSettings_VoiceMessagesTitle: String { return self._s[3508]! } + public var Wallet_Configuration_BlockchainNameChangedProceed: String { return self._s[3509]! } + public var TwoStepAuth_SetupPasswordConfirmFailed: String { return self._s[3510]! } + public var Undo_ChatCleared: String { return self._s[3511]! } + public var AppleWatch_ReplyPresets: String { return self._s[3512]! } + public var Passport_DiscardMessageDescription: String { return self._s[3514]! } + public var Login_NetworkError: String { return self._s[3515]! } public func Notification_PinnedRoundMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3513]!, self._r[3513]!, [_0]) + return formatWithArgumentRanges(self._s[3516]!, self._r[3516]!, [_0]) } public func Channel_AdminLog_MessageRemovedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3514]!, self._r[3514]!, [_0]) + return formatWithArgumentRanges(self._s[3517]!, self._r[3517]!, [_0]) } - public var SocksProxySetup_PasswordPlaceholder: String { return self._s[3515]! } - public var Wallet_WordCheck_ViewWords: String { return self._s[3517]! } - public var Login_ResetAccountProtected_LimitExceeded: String { return self._s[3518]! } + public var SocksProxySetup_PasswordPlaceholder: String { return self._s[3518]! } + public var Wallet_WordCheck_ViewWords: String { return self._s[3520]! } + public var Login_ResetAccountProtected_LimitExceeded: String { return self._s[3521]! } public func Watch_LastSeen_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3520]!, self._r[3520]!, [_0]) + return formatWithArgumentRanges(self._s[3523]!, self._r[3523]!, [_0]) } - public var Call_ConnectionErrorMessage: String { return self._s[3521]! } - public var VoiceOver_Chat_Music: String { return self._s[3522]! } - public var SettingsSearch_Synonyms_Notifications_MessageNotificationsSound: String { return self._s[3523]! } - public var Compose_GroupTokenListPlaceholder: String { return self._s[3525]! } - public var ConversationMedia_Title: String { return self._s[3526]! } - public var EncryptionKey_Title: String { return self._s[3528]! } - public var TwoStepAuth_EnterPasswordTitle: String { return self._s[3529]! } - public var Notification_Exceptions_AddException: String { return self._s[3530]! } - public var PrivacySettings_BlockedPeersEmpty: String { return self._s[3531]! } - public var Profile_MessageLifetime1m: String { return self._s[3532]! } + public var Call_ConnectionErrorMessage: String { return self._s[3524]! } + public var VoiceOver_Chat_Music: String { return self._s[3525]! } + public var SettingsSearch_Synonyms_Notifications_MessageNotificationsSound: String { return self._s[3526]! } + public var Compose_GroupTokenListPlaceholder: String { return self._s[3528]! } + public var ConversationMedia_Title: String { return self._s[3529]! } + public var EncryptionKey_Title: String { return self._s[3531]! } + public var TwoStepAuth_EnterPasswordTitle: String { return self._s[3532]! } + public var Notification_Exceptions_AddException: String { return self._s[3533]! } + public var PrivacySettings_BlockedPeersEmpty: String { return self._s[3534]! } + public var Profile_MessageLifetime1m: String { return self._s[3535]! } public func Channel_AdminLog_MessageUnkickedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3533]!, self._r[3533]!, [_1]) + return formatWithArgumentRanges(self._s[3536]!, self._r[3536]!, [_1]) } - public var Month_GenMay: String { return self._s[3534]! } + public var Month_GenMay: String { return self._s[3537]! } public func LiveLocationUpdated_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3535]!, self._r[3535]!, [_0]) + return formatWithArgumentRanges(self._s[3538]!, self._r[3538]!, [_0]) } - public var PeopleNearby_Users: String { return self._s[3536]! } - public var Wallet_Send_AddressInfo: String { return self._s[3537]! } - public var ChannelMembers_WhoCanAddMembersAllHelp: String { return self._s[3538]! } - public var AutoDownloadSettings_ResetSettings: String { return self._s[3539]! } + public var PeopleNearby_Users: String { return self._s[3539]! } + public var Wallet_Send_AddressInfo: String { return self._s[3540]! } + public var ChannelMembers_WhoCanAddMembersAllHelp: String { return self._s[3541]! } + public var AutoDownloadSettings_ResetSettings: String { return self._s[3542]! } public func Wallet_Updated_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3541]!, self._r[3541]!, [_0]) + return formatWithArgumentRanges(self._s[3544]!, self._r[3544]!, [_0]) } - public var Conversation_EmptyPlaceholder: String { return self._s[3542]! } - public var Passport_Address_AddPassportRegistration: String { return self._s[3543]! } - public var Notifications_ChannelNotificationsAlert: String { return self._s[3544]! } - public var ChatSettings_AutoDownloadUsingCellular: String { return self._s[3545]! } - public var Camera_TapAndHoldForVideo: String { return self._s[3546]! } - public var Channel_JoinChannel: String { return self._s[3548]! } - public var Appearance_Animations: String { return self._s[3551]! } + public var Conversation_EmptyPlaceholder: String { return self._s[3545]! } + public var Passport_Address_AddPassportRegistration: String { return self._s[3546]! } + public var Notifications_ChannelNotificationsAlert: String { return self._s[3547]! } + public var ChatSettings_AutoDownloadUsingCellular: String { return self._s[3548]! } + public var Camera_TapAndHoldForVideo: String { return self._s[3549]! } + public var Channel_JoinChannel: String { return self._s[3551]! } + public var Appearance_Animations: String { return self._s[3554]! } public func Notification_MessageLifetimeChanged(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3552]!, self._r[3552]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3555]!, self._r[3555]!, [_1, _2]) } - public var Stickers_GroupStickers: String { return self._s[3554]! } - public var Appearance_ShareTheme: String { return self._s[3555]! } - public var TwoFactorSetup_Hint_Placeholder: String { return self._s[3556]! } - public var ConvertToSupergroup_HelpTitle: String { return self._s[3558]! } - public var StickerPackActionInfo_RemovedTitle: String { return self._s[3559]! } - public var Passport_Address_Street: String { return self._s[3560]! } - public var Conversation_AddContact: String { return self._s[3561]! } - public var Login_PhonePlaceholder: String { return self._s[3562]! } - public var Channel_Members_InviteLink: String { return self._s[3564]! } - public var Bot_Stop: String { return self._s[3565]! } - public var SettingsSearch_Synonyms_Proxy_UseForCalls: String { return self._s[3567]! } - public var Notification_PassportValueAddress: String { return self._s[3568]! } - public var Month_ShortJuly: String { return self._s[3569]! } - public var Passport_Address_TypeTemporaryRegistrationUploadScan: String { return self._s[3570]! } - public var Channel_AdminLog_BanSendMedia: String { return self._s[3571]! } - public var Passport_Identity_ReverseSide: String { return self._s[3572]! } - public var Watch_Stickers_Recents: String { return self._s[3575]! } - public var PrivacyLastSeenSettings_EmpryUsersPlaceholder: String { return self._s[3577]! } - public var Map_SendThisLocation: String { return self._s[3578]! } + public var Stickers_GroupStickers: String { return self._s[3557]! } + public var Appearance_ShareTheme: String { return self._s[3558]! } + public var TwoFactorSetup_Hint_Placeholder: String { return self._s[3559]! } + public var ConvertToSupergroup_HelpTitle: String { return self._s[3561]! } + public var StickerPackActionInfo_RemovedTitle: String { return self._s[3562]! } + public var Passport_Address_Street: String { return self._s[3563]! } + public var Conversation_AddContact: String { return self._s[3564]! } + public var Login_PhonePlaceholder: String { return self._s[3565]! } + public var Channel_Members_InviteLink: String { return self._s[3567]! } + public var Bot_Stop: String { return self._s[3568]! } + public var SettingsSearch_Synonyms_Proxy_UseForCalls: String { return self._s[3570]! } + public var Notification_PassportValueAddress: String { return self._s[3571]! } + public var Month_ShortJuly: String { return self._s[3572]! } + public var Passport_Address_TypeTemporaryRegistrationUploadScan: String { return self._s[3573]! } + public var Channel_AdminLog_BanSendMedia: String { return self._s[3574]! } + public var Passport_Identity_ReverseSide: String { return self._s[3575]! } + public var Watch_Stickers_Recents: String { return self._s[3578]! } + public var PrivacyLastSeenSettings_EmpryUsersPlaceholder: String { return self._s[3580]! } + public var Map_SendThisLocation: String { return self._s[3581]! } public func Time_MonthOfYear_m1(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3579]!, self._r[3579]!, [_0]) + return formatWithArgumentRanges(self._s[3582]!, self._r[3582]!, [_0]) } public func InviteText_SingleContact(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3580]!, self._r[3580]!, [_0]) - } - public var ConvertToSupergroup_Note: String { return self._s[3581]! } - public var Wallet_Intro_NotNow: String { return self._s[3582]! } - public func FileSize_MB(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3583]!, self._r[3583]!, [_0]) } - public var NetworkUsageSettings_GeneralDataSection: String { return self._s[3584]! } + public var ConvertToSupergroup_Note: String { return self._s[3584]! } + public var Wallet_Intro_NotNow: String { return self._s[3585]! } + public func FileSize_MB(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3586]!, self._r[3586]!, [_0]) + } + public var NetworkUsageSettings_GeneralDataSection: String { return self._s[3587]! } public func Compatibility_SecretMediaVersionTooLow(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3585]!, self._r[3585]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3588]!, self._r[3588]!, [_0, _1]) } - public var Login_CallRequestState3: String { return self._s[3587]! } - public var Wallpaper_SearchShort: String { return self._s[3588]! } - public var SettingsSearch_Synonyms_Appearance_ColorTheme: String { return self._s[3590]! } - public var PasscodeSettings_UnlockWithFaceId: String { return self._s[3591]! } - public var Channel_BotDoesntSupportGroups: String { return self._s[3592]! } + public var Login_CallRequestState3: String { return self._s[3590]! } + public var Wallpaper_SearchShort: String { return self._s[3591]! } + public var SettingsSearch_Synonyms_Appearance_ColorTheme: String { return self._s[3593]! } + public var PasscodeSettings_UnlockWithFaceId: String { return self._s[3594]! } + public var Channel_BotDoesntSupportGroups: String { return self._s[3595]! } public func PUSH_CHAT_MESSAGE_GEOLIVE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3593]!, self._r[3593]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3596]!, self._r[3596]!, [_1, _2]) } - public var Channel_AdminLogFilter_Title: String { return self._s[3594]! } - public var Appearance_ThemePreview_Chat_4_Text: String { return self._s[3596]! } - public var Notifications_GroupNotificationsExceptions: String { return self._s[3599]! } + public var Channel_AdminLogFilter_Title: String { return self._s[3597]! } + public var Appearance_ThemePreview_Chat_4_Text: String { return self._s[3599]! } + public var Notifications_GroupNotificationsExceptions: String { return self._s[3602]! } public func FileSize_B(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3600]!, self._r[3600]!, [_0]) - } - public var Passport_CorrectErrors: String { return self._s[3601]! } - public var VoiceOver_Chat_YourAnonymousPoll: String { return self._s[3602]! } - public func Channel_MessageTitleUpdated(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3603]!, self._r[3603]!, [_0]) } - public var Map_SendMyCurrentLocation: String { return self._s[3604]! } - public var Channel_DiscussionGroup: String { return self._s[3605]! } - public var TwoFactorSetup_Email_SkipConfirmationSkip: String { return self._s[3606]! } + public var Passport_CorrectErrors: String { return self._s[3604]! } + public var VoiceOver_Chat_YourAnonymousPoll: String { return self._s[3605]! } + public func Channel_MessageTitleUpdated(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3606]!, self._r[3606]!, [_0]) + } + public var Map_SendMyCurrentLocation: String { return self._s[3607]! } + public var Channel_DiscussionGroup: String { return self._s[3608]! } + public var TwoFactorSetup_Email_SkipConfirmationSkip: String { return self._s[3609]! } public func PUSH_PINNED_CONTACT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3607]!, self._r[3607]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3610]!, self._r[3610]!, [_1, _2]) } - public var SharedMedia_SearchNoResults: String { return self._s[3608]! } - public var Permissions_NotificationsText_v0: String { return self._s[3609]! } - public var Channel_EditAdmin_PermissionDeleteMessagesOfOthers: String { return self._s[3610]! } - public var Appearance_AppIcon: String { return self._s[3611]! } - public var Appearance_ThemePreview_ChatList_3_AuthorName: String { return self._s[3612]! } - public var LoginPassword_FloodError: String { return self._s[3613]! } - public var Wallet_Send_OwnAddressAlertProceed: String { return self._s[3615]! } - public var Group_Setup_HistoryHiddenHelp: String { return self._s[3616]! } + public var SharedMedia_SearchNoResults: String { return self._s[3611]! } + public var Permissions_NotificationsText_v0: String { return self._s[3612]! } + public var Channel_EditAdmin_PermissionDeleteMessagesOfOthers: String { return self._s[3613]! } + public var Appearance_AppIcon: String { return self._s[3614]! } + public var Appearance_ThemePreview_ChatList_3_AuthorName: String { return self._s[3615]! } + public var LoginPassword_FloodError: String { return self._s[3616]! } + public var Wallet_Send_OwnAddressAlertProceed: String { return self._s[3618]! } + public var Group_Setup_HistoryHiddenHelp: String { return self._s[3619]! } public func TwoStepAuth_PendingEmailHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3617]!, self._r[3617]!, [_0]) + return formatWithArgumentRanges(self._s[3620]!, self._r[3620]!, [_0]) } - public var Passport_Language_bn: String { return self._s[3618]! } + public var Passport_Language_bn: String { return self._s[3621]! } public func DialogList_SingleUploadingPhotoSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3619]!, self._r[3619]!, [_0]) - } - public var ChatList_Context_Pin: String { return self._s[3620]! } - public func Notification_PinnedAudioMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3621]!, self._r[3621]!, [_0]) - } - public func Channel_AdminLog_MessageChangedGroupStickerPack(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3622]!, self._r[3622]!, [_0]) } - public var Wallet_Navigation_Close: String { return self._s[3623]! } - public var GroupInfo_InvitationLinkGroupFull: String { return self._s[3627]! } - public var Group_EditAdmin_PermissionChangeInfo: String { return self._s[3629]! } - public var Wallet_Month_GenDecember: String { return self._s[3630]! } - public var Contacts_PermissionsAllow: String { return self._s[3631]! } - public var ReportPeer_ReasonCopyright: String { return self._s[3632]! } - public var Channel_EditAdmin_PermissinAddAdminOn: String { return self._s[3633]! } - public var WallpaperPreview_Pattern: String { return self._s[3634]! } - public var Paint_Duplicate: String { return self._s[3635]! } - public var Passport_Address_Country: String { return self._s[3636]! } - public var Notification_RenamedChannel: String { return self._s[3638]! } - public var ChatList_Context_Unmute: String { return self._s[3639]! } - public var CheckoutInfo_ErrorPostcodeInvalid: String { return self._s[3640]! } - public var Group_MessagePhotoUpdated: String { return self._s[3641]! } - public var Channel_BanUser_PermissionSendMedia: String { return self._s[3642]! } - public var Conversation_ContextMenuBan: String { return self._s[3643]! } - public var TwoStepAuth_EmailSent: String { return self._s[3644]! } - public var MessagePoll_NoVotes: String { return self._s[3645]! } - public var Wallet_Send_ErrorNotEnoughFundsTitle: String { return self._s[3646]! } - public var Passport_Language_is: String { return self._s[3648]! } - public var PeopleNearby_UsersEmpty: String { return self._s[3650]! } - public var Tour_Text5: String { return self._s[3651]! } + public var ChatList_Context_Pin: String { return self._s[3623]! } + public func Notification_PinnedAudioMessage(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3624]!, self._r[3624]!, [_0]) + } + public func Channel_AdminLog_MessageChangedGroupStickerPack(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3625]!, self._r[3625]!, [_0]) + } + public var Wallet_Navigation_Close: String { return self._s[3626]! } + public var GroupInfo_InvitationLinkGroupFull: String { return self._s[3630]! } + public var Group_EditAdmin_PermissionChangeInfo: String { return self._s[3632]! } + public var Wallet_Month_GenDecember: String { return self._s[3633]! } + public var Contacts_PermissionsAllow: String { return self._s[3634]! } + public var ReportPeer_ReasonCopyright: String { return self._s[3635]! } + public var Channel_EditAdmin_PermissinAddAdminOn: String { return self._s[3636]! } + public var WallpaperPreview_Pattern: String { return self._s[3637]! } + public var Paint_Duplicate: String { return self._s[3638]! } + public var Passport_Address_Country: String { return self._s[3639]! } + public var Notification_RenamedChannel: String { return self._s[3641]! } + public var ChatList_Context_Unmute: String { return self._s[3642]! } + public var CheckoutInfo_ErrorPostcodeInvalid: String { return self._s[3643]! } + public var Group_MessagePhotoUpdated: String { return self._s[3644]! } + public var Channel_BanUser_PermissionSendMedia: String { return self._s[3645]! } + public var Conversation_ContextMenuBan: String { return self._s[3646]! } + public var TwoStepAuth_EmailSent: String { return self._s[3647]! } + public var MessagePoll_NoVotes: String { return self._s[3648]! } + public var Wallet_Send_ErrorNotEnoughFundsTitle: String { return self._s[3649]! } + public var Passport_Language_is: String { return self._s[3651]! } + public var PeopleNearby_UsersEmpty: String { return self._s[3653]! } + public var Tour_Text5: String { return self._s[3654]! } public func Call_GroupFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3654]!, self._r[3654]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3657]!, self._r[3657]!, [_1, _2]) } - public var Undo_SecretChatDeleted: String { return self._s[3655]! } - public var SocksProxySetup_ShareQRCode: String { return self._s[3656]! } + public var Undo_SecretChatDeleted: String { return self._s[3658]! } + public var SocksProxySetup_ShareQRCode: String { return self._s[3659]! } public func VoiceOver_Chat_Size(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3657]!, self._r[3657]!, [_0]) + return formatWithArgumentRanges(self._s[3660]!, self._r[3660]!, [_0]) } - public var Forward_ErrorDisabledForChat: String { return self._s[3658]! } - public var LogoutOptions_ChangePhoneNumberText: String { return self._s[3659]! } - public var Paint_Edit: String { return self._s[3661]! } - public var ScheduledMessages_ReminderNotification: String { return self._s[3663]! } - public var Undo_DeletedGroup: String { return self._s[3665]! } - public var LoginPassword_ForgotPassword: String { return self._s[3666]! } - public var Wallet_WordImport_IncorrectTitle: String { return self._s[3667]! } - public var GroupInfo_GroupNamePlaceholder: String { return self._s[3668]! } + public var Forward_ErrorDisabledForChat: String { return self._s[3661]! } + public var LogoutOptions_ChangePhoneNumberText: String { return self._s[3662]! } + public var Paint_Edit: String { return self._s[3664]! } + public var ScheduledMessages_ReminderNotification: String { return self._s[3666]! } + public var Undo_DeletedGroup: String { return self._s[3668]! } + public var LoginPassword_ForgotPassword: String { return self._s[3669]! } + public var Wallet_WordImport_IncorrectTitle: String { return self._s[3670]! } + public var GroupInfo_GroupNamePlaceholder: String { return self._s[3671]! } public func Notification_Kicked(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3669]!, self._r[3669]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3672]!, self._r[3672]!, [_0, _1]) } - public var AppWallet_TransactionInfo_FeeInfoURL: String { return self._s[3670]! } - public var Conversation_InputTextCaptionPlaceholder: String { return self._s[3671]! } - public var AutoDownloadSettings_VideoMessagesTitle: String { return self._s[3672]! } - public var Passport_Language_uz: String { return self._s[3673]! } - public var Conversation_PinMessageAlertGroup: String { return self._s[3674]! } - public var SettingsSearch_Synonyms_Privacy_GroupsAndChannels: String { return self._s[3675]! } - public var Map_StopLiveLocation: String { return self._s[3677]! } - public var VoiceOver_MessageContextSend: String { return self._s[3679]! } - public var PasscodeSettings_Help: String { return self._s[3680]! } - public var NotificationsSound_Input: String { return self._s[3681]! } - public var Share_Title: String { return self._s[3684]! } - public var LogoutOptions_Title: String { return self._s[3685]! } - public var Wallet_Send_AddressText: String { return self._s[3686]! } - public var Login_TermsOfServiceAgree: String { return self._s[3687]! } - public var Compose_NewEncryptedChatTitle: String { return self._s[3688]! } - public var Channel_AdminLog_TitleSelectedEvents: String { return self._s[3689]! } - public var Channel_EditAdmin_PermissionEditMessages: String { return self._s[3690]! } - public var EnterPasscode_EnterTitle: String { return self._s[3691]! } + public var AppWallet_TransactionInfo_FeeInfoURL: String { return self._s[3673]! } + public var Conversation_InputTextCaptionPlaceholder: String { return self._s[3674]! } + public var AutoDownloadSettings_VideoMessagesTitle: String { return self._s[3675]! } + public var Passport_Language_uz: String { return self._s[3676]! } + public var Conversation_PinMessageAlertGroup: String { return self._s[3677]! } + public var SettingsSearch_Synonyms_Privacy_GroupsAndChannels: String { return self._s[3678]! } + public var Map_StopLiveLocation: String { return self._s[3680]! } + public var VoiceOver_MessageContextSend: String { return self._s[3682]! } + public var PasscodeSettings_Help: String { return self._s[3683]! } + public var NotificationsSound_Input: String { return self._s[3684]! } + public var Share_Title: String { return self._s[3687]! } + public var LogoutOptions_Title: String { return self._s[3688]! } + public var Wallet_Send_AddressText: String { return self._s[3689]! } + public var Login_TermsOfServiceAgree: String { return self._s[3690]! } + public var Compose_NewEncryptedChatTitle: String { return self._s[3691]! } + public var Channel_AdminLog_TitleSelectedEvents: String { return self._s[3692]! } + public var Channel_EditAdmin_PermissionEditMessages: String { return self._s[3693]! } + public var EnterPasscode_EnterTitle: String { return self._s[3694]! } public func Call_PrivacyErrorMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3692]!, self._r[3692]!, [_0]) - } - public var Settings_CopyPhoneNumber: String { return self._s[3693]! } - public var Conversation_AddToContacts: String { return self._s[3694]! } - public func VoiceOver_Chat_ReplyFrom(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3695]!, self._r[3695]!, [_0]) } - public var NotificationsSound_Keys: String { return self._s[3696]! } + public var Settings_CopyPhoneNumber: String { return self._s[3696]! } + public var Conversation_AddToContacts: String { return self._s[3697]! } + public func VoiceOver_Chat_ReplyFrom(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3698]!, self._r[3698]!, [_0]) + } + public var NotificationsSound_Keys: String { return self._s[3699]! } public func Call_ParticipantVersionOutdatedError(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3697]!, self._r[3697]!, [_0]) + return formatWithArgumentRanges(self._s[3700]!, self._r[3700]!, [_0]) } - public var Notification_MessageLifetime1w: String { return self._s[3698]! } - public var Message_Video: String { return self._s[3699]! } - public var AutoDownloadSettings_CellularTitle: String { return self._s[3700]! } + public var Notification_MessageLifetime1w: String { return self._s[3701]! } + public var Message_Video: String { return self._s[3702]! } + public var AutoDownloadSettings_CellularTitle: String { return self._s[3703]! } public func PUSH_CHANNEL_MESSAGE_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3701]!, self._r[3701]!, [_1]) + return formatWithArgumentRanges(self._s[3704]!, self._r[3704]!, [_1]) } - public var Wallet_Receive_AmountInfo: String { return self._s[3704]! } + public var Wallet_Receive_AmountInfo: String { return self._s[3707]! } public func Notification_JoinedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3705]!, self._r[3705]!, [_0]) + return formatWithArgumentRanges(self._s[3708]!, self._r[3708]!, [_0]) } public func PrivacySettings_LastSeenContactsPlus(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3706]!, self._r[3706]!, [_0]) + return formatWithArgumentRanges(self._s[3709]!, self._r[3709]!, [_0]) } - public var Passport_Language_mk: String { return self._s[3707]! } + public var Passport_Language_mk: String { return self._s[3710]! } public func Wallet_Time_PreciseDate_m2(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3708]!, self._r[3708]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3711]!, self._r[3711]!, [_1, _2, _3]) } - public var CreatePoll_CancelConfirmation: String { return self._s[3709]! } - public var MessagePoll_LabelAnonymousQuiz: String { return self._s[3710]! } - public var Conversation_SilentBroadcastTooltipOn: String { return self._s[3712]! } - public var PrivacyPolicy_Decline: String { return self._s[3713]! } - public var Passport_Identity_DoesNotExpire: String { return self._s[3714]! } - public var Channel_AdminLogFilter_EventsRestrictions: String { return self._s[3715]! } - public var AuthSessions_AddDeviceIntro_Action: String { return self._s[3716]! } - public var Permissions_SiriAllow_v0: String { return self._s[3718]! } - public var Wallet_Month_ShortAugust: String { return self._s[3719]! } - public var Appearance_ThemeCarouselNight: String { return self._s[3720]! } + public var CreatePoll_CancelConfirmation: String { return self._s[3712]! } + public var MessagePoll_LabelAnonymousQuiz: String { return self._s[3713]! } + public var Conversation_SilentBroadcastTooltipOn: String { return self._s[3715]! } + public var PrivacyPolicy_Decline: String { return self._s[3716]! } + public var Passport_Identity_DoesNotExpire: String { return self._s[3717]! } + public var Channel_AdminLogFilter_EventsRestrictions: String { return self._s[3718]! } + public var AuthSessions_AddDeviceIntro_Action: String { return self._s[3719]! } + public var Permissions_SiriAllow_v0: String { return self._s[3721]! } + public var Wallet_Month_ShortAugust: String { return self._s[3722]! } + public var Appearance_ThemeCarouselNight: String { return self._s[3723]! } public func LOCAL_CHAT_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3721]!, self._r[3721]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[3724]!, self._r[3724]!, [_1, "\(_2)"]) } public func Notification_RenamedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3722]!, self._r[3722]!, [_0]) + return formatWithArgumentRanges(self._s[3725]!, self._r[3725]!, [_0]) } - public var Paint_Regular: String { return self._s[3723]! } - public var ChatSettings_AutoDownloadReset: String { return self._s[3724]! } - public var SocksProxySetup_ShareLink: String { return self._s[3725]! } - public var Wallet_Qr_Title: String { return self._s[3726]! } - public var BlockedUsers_SelectUserTitle: String { return self._s[3727]! } - public var VoiceOver_Chat_RecordModeVoiceMessage: String { return self._s[3729]! } - public var Wallet_Settings_Configuration: String { return self._s[3730]! } - public var GroupInfo_InviteByLink: String { return self._s[3731]! } - public var MessageTimer_Custom: String { return self._s[3732]! } - public var UserInfo_NotificationsDefaultEnabled: String { return self._s[3733]! } - public var Conversation_StopQuizConfirmationTitle: String { return self._s[3734]! } - public var Passport_Address_TypeTemporaryRegistration: String { return self._s[3736]! } - public var Conversation_SendMessage_SetReminder: String { return self._s[3737]! } - public var VoiceOver_Chat_Selected: String { return self._s[3738]! } - public var ChatSettings_AutoDownloadUsingWiFi: String { return self._s[3739]! } - public var Channel_Username_InvalidTaken: String { return self._s[3740]! } - public var Conversation_ClousStorageInfo_Description3: String { return self._s[3741]! } - public var Wallet_WordCheck_TryAgain: String { return self._s[3742]! } - public var Wallet_Info_TransactionPendingHeader: String { return self._s[3743]! } - public var Settings_ChatBackground: String { return self._s[3744]! } - public var Channel_Subscribers_Title: String { return self._s[3745]! } - public var Wallet_Receive_InvoiceUrlHeader: String { return self._s[3746]! } - public var ApplyLanguage_ChangeLanguageTitle: String { return self._s[3747]! } - public var Watch_ConnectionDescription: String { return self._s[3748]! } - public var OldChannels_NoticeText: String { return self._s[3751]! } - public var Wallet_Configuration_ApplyErrorTitle: String { return self._s[3752]! } - public var IntentsSettings_SuggestBy: String { return self._s[3754]! } - public var Theme_ThemeChangedText: String { return self._s[3755]! } - public var ChatList_ArchivedChatsTitle: String { return self._s[3756]! } - public var Wallpaper_ResetWallpapers: String { return self._s[3757]! } - public var Wallet_Send_TransactionInProgress: String { return self._s[3758]! } - public var EditProfile_Title: String { return self._s[3759]! } - public var NotificationsSound_Bamboo: String { return self._s[3761]! } - public var Channel_AdminLog_MessagePreviousMessage: String { return self._s[3763]! } - public var Login_SmsRequestState2: String { return self._s[3764]! } - public var Passport_Language_ar: String { return self._s[3765]! } + public var Paint_Regular: String { return self._s[3726]! } + public var ChatSettings_AutoDownloadReset: String { return self._s[3727]! } + public var SocksProxySetup_ShareLink: String { return self._s[3728]! } + public var Wallet_Qr_Title: String { return self._s[3729]! } + public var BlockedUsers_SelectUserTitle: String { return self._s[3730]! } + public var VoiceOver_Chat_RecordModeVoiceMessage: String { return self._s[3732]! } + public var Wallet_Settings_Configuration: String { return self._s[3733]! } + public var GroupInfo_InviteByLink: String { return self._s[3734]! } + public var MessageTimer_Custom: String { return self._s[3735]! } + public var UserInfo_NotificationsDefaultEnabled: String { return self._s[3736]! } + public var Conversation_StopQuizConfirmationTitle: String { return self._s[3737]! } + public var Passport_Address_TypeTemporaryRegistration: String { return self._s[3739]! } + public var Conversation_SendMessage_SetReminder: String { return self._s[3740]! } + public var VoiceOver_Chat_Selected: String { return self._s[3741]! } + public var ChatSettings_AutoDownloadUsingWiFi: String { return self._s[3742]! } + public var Channel_Username_InvalidTaken: String { return self._s[3743]! } + public var Conversation_ClousStorageInfo_Description3: String { return self._s[3744]! } + public var Wallet_WordCheck_TryAgain: String { return self._s[3745]! } + public var Wallet_Info_TransactionPendingHeader: String { return self._s[3746]! } + public var Settings_ChatBackground: String { return self._s[3747]! } + public var Channel_Subscribers_Title: String { return self._s[3748]! } + public var Wallet_Receive_InvoiceUrlHeader: String { return self._s[3749]! } + public var ApplyLanguage_ChangeLanguageTitle: String { return self._s[3750]! } + public var Watch_ConnectionDescription: String { return self._s[3751]! } + public var OldChannels_NoticeText: String { return self._s[3754]! } + public var Wallet_Configuration_ApplyErrorTitle: String { return self._s[3755]! } + public var IntentsSettings_SuggestBy: String { return self._s[3757]! } + public var Theme_ThemeChangedText: String { return self._s[3758]! } + public var ChatList_ArchivedChatsTitle: String { return self._s[3759]! } + public var Wallpaper_ResetWallpapers: String { return self._s[3760]! } + public var Wallet_Send_TransactionInProgress: String { return self._s[3761]! } + public var EditProfile_Title: String { return self._s[3762]! } + public var NotificationsSound_Bamboo: String { return self._s[3764]! } + public var Channel_AdminLog_MessagePreviousMessage: String { return self._s[3766]! } + public var Login_SmsRequestState2: String { return self._s[3767]! } + public var Passport_Language_ar: String { return self._s[3768]! } public func Message_AuthorPinnedGame(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3766]!, self._r[3766]!, [_0]) + return formatWithArgumentRanges(self._s[3769]!, self._r[3769]!, [_0]) } - public var SettingsSearch_Synonyms_EditProfile_Title: String { return self._s[3767]! } - public var Wallet_Created_Text: String { return self._s[3768]! } - public var Conversation_MessageDialogEdit: String { return self._s[3770]! } - public var Wallet_Created_Proceed: String { return self._s[3771]! } - public var Wallet_Words_Done: String { return self._s[3772]! } - public var VoiceOver_Media_PlaybackPause: String { return self._s[3773]! } + public var SettingsSearch_Synonyms_EditProfile_Title: String { return self._s[3770]! } + public var Wallet_Created_Text: String { return self._s[3771]! } + public var Conversation_MessageDialogEdit: String { return self._s[3773]! } + public var Wallet_Created_Proceed: String { return self._s[3774]! } + public var Wallet_Words_Done: String { return self._s[3775]! } + public var VoiceOver_Media_PlaybackPause: String { return self._s[3776]! } public func PUSH_AUTH_UNKNOWN(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3774]!, self._r[3774]!, [_1]) + return formatWithArgumentRanges(self._s[3777]!, self._r[3777]!, [_1]) } - public var Common_Close: String { return self._s[3775]! } - public var GroupInfo_PublicLink: String { return self._s[3776]! } - public var Channel_OwnershipTransfer_ErrorPrivacyRestricted: String { return self._s[3777]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsPreview: String { return self._s[3778]! } + public var Common_Close: String { return self._s[3778]! } + public var GroupInfo_PublicLink: String { return self._s[3779]! } + public var Channel_OwnershipTransfer_ErrorPrivacyRestricted: String { return self._s[3780]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsPreview: String { return self._s[3781]! } public func Channel_AdminLog_MessageToggleInvitesOff(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3782]!, self._r[3782]!, [_0]) + return formatWithArgumentRanges(self._s[3785]!, self._r[3785]!, [_0]) } - public var UserInfo_About_Placeholder: String { return self._s[3783]! } + public var UserInfo_About_Placeholder: String { return self._s[3786]! } public func Conversation_FileHowToText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3784]!, self._r[3784]!, [_0]) + return formatWithArgumentRanges(self._s[3787]!, self._r[3787]!, [_0]) } - public var GroupInfo_Permissions_SectionTitle: String { return self._s[3785]! } - public var Channel_Info_Banned: String { return self._s[3787]! } + public var GroupInfo_Permissions_SectionTitle: String { return self._s[3788]! } + public var Channel_Info_Banned: String { return self._s[3790]! } public func Time_MonthOfYear_m11(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3788]!, self._r[3788]!, [_0]) + return formatWithArgumentRanges(self._s[3791]!, self._r[3791]!, [_0]) } - public var Appearance_Other: String { return self._s[3789]! } - public var Passport_Language_my: String { return self._s[3790]! } - public var Group_Setup_BasicHistoryHiddenHelp: String { return self._s[3791]! } + public var Appearance_Other: String { return self._s[3792]! } + public var Passport_Language_my: String { return self._s[3793]! } + public var Group_Setup_BasicHistoryHiddenHelp: String { return self._s[3794]! } public func Time_PreciseDate_m9(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3792]!, self._r[3792]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3795]!, self._r[3795]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_Privacy_PasscodeAndFaceId: String { return self._s[3793]! } - public var IntentsSettings_SuggestedAndSpotlightChatsInfo: String { return self._s[3794]! } - public var Preview_CopyAddress: String { return self._s[3795]! } + public var SettingsSearch_Synonyms_Privacy_PasscodeAndFaceId: String { return self._s[3796]! } + public var IntentsSettings_SuggestedAndSpotlightChatsInfo: String { return self._s[3797]! } + public var Preview_CopyAddress: String { return self._s[3798]! } public func DialogList_SinglePlayingGameSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3796]!, self._r[3796]!, [_0]) + return formatWithArgumentRanges(self._s[3799]!, self._r[3799]!, [_0]) } - public var KeyCommand_JumpToPreviousChat: String { return self._s[3797]! } - public var UserInfo_BotSettings: String { return self._s[3798]! } - public var LiveLocation_MenuStopAll: String { return self._s[3800]! } - public var Passport_PasswordCreate: String { return self._s[3801]! } - public var StickerSettings_MaskContextInfo: String { return self._s[3802]! } - public var Message_PinnedLocationMessage: String { return self._s[3803]! } - public var Map_Satellite: String { return self._s[3804]! } - public var Watch_Message_Unsupported: String { return self._s[3805]! } - public var Username_TooManyPublicUsernamesError: String { return self._s[3806]! } - public var TwoStepAuth_EnterPasswordInvalid: String { return self._s[3807]! } + public var KeyCommand_JumpToPreviousChat: String { return self._s[3800]! } + public var UserInfo_BotSettings: String { return self._s[3801]! } + public var LiveLocation_MenuStopAll: String { return self._s[3803]! } + public var Passport_PasswordCreate: String { return self._s[3804]! } + public var StickerSettings_MaskContextInfo: String { return self._s[3805]! } + public var Message_PinnedLocationMessage: String { return self._s[3806]! } + public var Map_Satellite: String { return self._s[3807]! } + public var Watch_Message_Unsupported: String { return self._s[3808]! } + public var Username_TooManyPublicUsernamesError: String { return self._s[3809]! } + public var TwoStepAuth_EnterPasswordInvalid: String { return self._s[3810]! } public func Notification_PinnedTextMessage(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3808]!, self._r[3808]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3811]!, self._r[3811]!, [_0, _1]) } public func Conversation_OpenBotLinkText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3809]!, self._r[3809]!, [_0]) + return formatWithArgumentRanges(self._s[3812]!, self._r[3812]!, [_0]) } - public var Wallet_WordImport_Continue: String { return self._s[3810]! } + public var Wallet_WordImport_Continue: String { return self._s[3813]! } public func TwoFactorSetup_EmailVerification_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3811]!, self._r[3811]!, [_0]) + return formatWithArgumentRanges(self._s[3814]!, self._r[3814]!, [_0]) } - public var Notifications_ChannelNotificationsHelp: String { return self._s[3812]! } - public var Privacy_Calls_P2PContacts: String { return self._s[3813]! } - public var NotificationsSound_None: String { return self._s[3814]! } - public var Wallet_TransactionInfo_StorageFeeHeader: String { return self._s[3815]! } - public var Channel_DiscussionGroup_UnlinkGroup: String { return self._s[3817]! } - public var AccessDenied_VoiceMicrophone: String { return self._s[3818]! } + public var Notifications_ChannelNotificationsHelp: String { return self._s[3815]! } + public var Privacy_Calls_P2PContacts: String { return self._s[3816]! } + public var NotificationsSound_None: String { return self._s[3817]! } + public var Wallet_TransactionInfo_StorageFeeHeader: String { return self._s[3818]! } + public var Channel_DiscussionGroup_UnlinkGroup: String { return self._s[3820]! } + public var AccessDenied_VoiceMicrophone: String { return self._s[3821]! } public func ApplyLanguage_ChangeLanguageAlreadyActive(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3819]!, self._r[3819]!, [_1]) + return formatWithArgumentRanges(self._s[3822]!, self._r[3822]!, [_1]) } - public var Cache_Indexing: String { return self._s[3820]! } - public var DialogList_RecentTitlePeople: String { return self._s[3822]! } - public var DialogList_EncryptionRejected: String { return self._s[3823]! } - public var GroupInfo_Administrators: String { return self._s[3824]! } - public var Passport_ScanPassportHelp: String { return self._s[3825]! } - public var Application_Name: String { return self._s[3826]! } - public var Channel_AdminLogFilter_ChannelEventsInfo: String { return self._s[3827]! } - public var Appearance_ThemeCarouselDay: String { return self._s[3829]! } - public var Passport_Identity_TranslationHelp: String { return self._s[3830]! } + public var Cache_Indexing: String { return self._s[3823]! } + public var DialogList_RecentTitlePeople: String { return self._s[3825]! } + public var DialogList_EncryptionRejected: String { return self._s[3826]! } + public var GroupInfo_Administrators: String { return self._s[3827]! } + public var Passport_ScanPassportHelp: String { return self._s[3828]! } + public var Application_Name: String { return self._s[3829]! } + public var Channel_AdminLogFilter_ChannelEventsInfo: String { return self._s[3830]! } + public var Appearance_ThemeCarouselDay: String { return self._s[3832]! } + public var Passport_Identity_TranslationHelp: String { return self._s[3833]! } public func VoiceOver_Chat_VideoMessageFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3831]!, self._r[3831]!, [_0]) + return formatWithArgumentRanges(self._s[3834]!, self._r[3834]!, [_0]) } public func Notification_JoinedGroupByLink(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3832]!, self._r[3832]!, [_0]) + return formatWithArgumentRanges(self._s[3835]!, self._r[3835]!, [_0]) } public func DialogList_EncryptedChatStartedOutgoing(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3833]!, self._r[3833]!, [_0]) + return formatWithArgumentRanges(self._s[3836]!, self._r[3836]!, [_0]) } - public var Channel_EditAdmin_PermissionDeleteMessages: String { return self._s[3834]! } - public var Privacy_ChatsTitle: String { return self._s[3835]! } - public var DialogList_ClearHistoryConfirmation: String { return self._s[3836]! } - public var SettingsSearch_Synonyms_Data_Storage_ClearCache: String { return self._s[3837]! } - public var Watch_Suggestion_HoldOn: String { return self._s[3838]! } - public var Group_EditAdmin_TransferOwnership: String { return self._s[3839]! } - public var WebBrowser_Title: String { return self._s[3840]! } - public var Group_LinkedChannel: String { return self._s[3841]! } - public var VoiceOver_Chat_SeenByRecipient: String { return self._s[3842]! } - public var SocksProxySetup_RequiredCredentials: String { return self._s[3843]! } - public var Passport_Address_TypeRentalAgreementUploadScan: String { return self._s[3844]! } - public var Appearance_TextSize_UseSystem: String { return self._s[3845]! } - public var TwoStepAuth_EmailSkipAlert: String { return self._s[3846]! } - public var ScheduledMessages_RemindersTitle: String { return self._s[3848]! } - public var Channel_Setup_TypePublic: String { return self._s[3850]! } + public var Channel_EditAdmin_PermissionDeleteMessages: String { return self._s[3837]! } + public var Privacy_ChatsTitle: String { return self._s[3838]! } + public var DialogList_ClearHistoryConfirmation: String { return self._s[3839]! } + public var SettingsSearch_Synonyms_Data_Storage_ClearCache: String { return self._s[3840]! } + public var Watch_Suggestion_HoldOn: String { return self._s[3841]! } + public var Group_EditAdmin_TransferOwnership: String { return self._s[3842]! } + public var WebBrowser_Title: String { return self._s[3843]! } + public var Group_LinkedChannel: String { return self._s[3844]! } + public var VoiceOver_Chat_SeenByRecipient: String { return self._s[3845]! } + public var SocksProxySetup_RequiredCredentials: String { return self._s[3846]! } + public var Passport_Address_TypeRentalAgreementUploadScan: String { return self._s[3847]! } + public var Appearance_TextSize_UseSystem: String { return self._s[3848]! } + public var TwoStepAuth_EmailSkipAlert: String { return self._s[3849]! } + public var ScheduledMessages_RemindersTitle: String { return self._s[3851]! } + public var Channel_Setup_TypePublic: String { return self._s[3853]! } public func Channel_AdminLog_MessageToggleInvitesOn(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3851]!, self._r[3851]!, [_0]) + return formatWithArgumentRanges(self._s[3854]!, self._r[3854]!, [_0]) } - public var Channel_TypeSetup_Title: String { return self._s[3853]! } - public var MessagePoll_ViewResults: String { return self._s[3854]! } - public var Map_OpenInMaps: String { return self._s[3856]! } + public var Channel_TypeSetup_Title: String { return self._s[3856]! } + public var MessagePoll_ViewResults: String { return self._s[3857]! } + public var Map_OpenInMaps: String { return self._s[3859]! } public func PUSH_PINNED_NOTEXT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3857]!, self._r[3857]!, [_1]) + return formatWithArgumentRanges(self._s[3860]!, self._r[3860]!, [_1]) } - public var NotificationsSound_Tremolo: String { return self._s[3859]! } + public var NotificationsSound_Tremolo: String { return self._s[3862]! } public func Date_ChatDateHeaderYear(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3860]!, self._r[3860]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3863]!, self._r[3863]!, [_1, _2, _3]) } - public var ConversationProfile_UnknownAddMemberError: String { return self._s[3861]! } - public var Channel_OwnershipTransfer_PasswordPlaceholder: String { return self._s[3862]! } - public var Passport_PasswordHelp: String { return self._s[3863]! } - public var Login_CodeExpiredError: String { return self._s[3864]! } - public var Channel_EditAdmin_PermissionChangeInfo: String { return self._s[3865]! } - public var Conversation_TitleUnmute: String { return self._s[3866]! } - public var Passport_Identity_ScansHelp: String { return self._s[3867]! } - public var Passport_Language_lo: String { return self._s[3868]! } - public var Camera_FlashAuto: String { return self._s[3869]! } - public var Conversation_OpenBotLinkOpen: String { return self._s[3870]! } - public var Common_Cancel: String { return self._s[3871]! } - public var DialogList_SavedMessagesTooltip: String { return self._s[3872]! } - public var TwoStepAuth_SetupPasswordTitle: String { return self._s[3873]! } - public var Appearance_TintAllColors: String { return self._s[3874]! } + public var ConversationProfile_UnknownAddMemberError: String { return self._s[3864]! } + public var Channel_OwnershipTransfer_PasswordPlaceholder: String { return self._s[3865]! } + public var Passport_PasswordHelp: String { return self._s[3866]! } + public var Login_CodeExpiredError: String { return self._s[3867]! } + public var Channel_EditAdmin_PermissionChangeInfo: String { return self._s[3868]! } + public var Conversation_TitleUnmute: String { return self._s[3869]! } + public var Passport_Identity_ScansHelp: String { return self._s[3870]! } + public var Passport_Language_lo: String { return self._s[3871]! } + public var Camera_FlashAuto: String { return self._s[3872]! } + public var Conversation_OpenBotLinkOpen: String { return self._s[3873]! } + public var Common_Cancel: String { return self._s[3874]! } + public var DialogList_SavedMessagesTooltip: String { return self._s[3875]! } + public var TwoStepAuth_SetupPasswordTitle: String { return self._s[3876]! } + public var Appearance_TintAllColors: String { return self._s[3877]! } public func PUSH_MESSAGE_FWD(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3875]!, self._r[3875]!, [_1]) + return formatWithArgumentRanges(self._s[3878]!, self._r[3878]!, [_1]) } - public var Conversation_ReportSpamConfirmation: String { return self._s[3876]! } - public var ChatSettings_Title: String { return self._s[3878]! } - public var Passport_PasswordReset: String { return self._s[3879]! } - public var SocksProxySetup_TypeNone: String { return self._s[3880]! } - public var EditTheme_Title: String { return self._s[3883]! } - public var PhoneNumberHelp_Help: String { return self._s[3884]! } - public var Checkout_EnterPassword: String { return self._s[3885]! } - public var Activity_UploadingDocument: String { return self._s[3887]! } - public var Share_AuthTitle: String { return self._s[3888]! } - public var State_Connecting: String { return self._s[3889]! } - public var Profile_MessageLifetime1w: String { return self._s[3890]! } - public var Conversation_ContextMenuReport: String { return self._s[3891]! } - public var CheckoutInfo_ReceiverInfoPhone: String { return self._s[3892]! } - public var AutoNightTheme_ScheduledTo: String { return self._s[3893]! } + public var Conversation_ReportSpamConfirmation: String { return self._s[3879]! } + public var ChatSettings_Title: String { return self._s[3881]! } + public var Passport_PasswordReset: String { return self._s[3882]! } + public var SocksProxySetup_TypeNone: String { return self._s[3883]! } + public var EditTheme_Title: String { return self._s[3886]! } + public var PhoneNumberHelp_Help: String { return self._s[3887]! } + public var Checkout_EnterPassword: String { return self._s[3888]! } + public var Activity_UploadingDocument: String { return self._s[3890]! } + public var Share_AuthTitle: String { return self._s[3891]! } + public var State_Connecting: String { return self._s[3892]! } + public var Profile_MessageLifetime1w: String { return self._s[3893]! } + public var Conversation_ContextMenuReport: String { return self._s[3894]! } + public var CheckoutInfo_ReceiverInfoPhone: String { return self._s[3895]! } + public var AutoNightTheme_ScheduledTo: String { return self._s[3896]! } public func VoiceOver_Chat_AnonymousPollFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3894]!, self._r[3894]!, [_0]) + return formatWithArgumentRanges(self._s[3897]!, self._r[3897]!, [_0]) } - public var AuthSessions_Terminate: String { return self._s[3895]! } - public var Wallet_WordImport_CanNotRemember: String { return self._s[3896]! } - public var Checkout_NewCard_CardholderNamePlaceholder: String { return self._s[3898]! } - public var KeyCommand_JumpToPreviousUnreadChat: String { return self._s[3899]! } - public var PhotoEditor_Set: String { return self._s[3900]! } - public var EmptyGroupInfo_Title: String { return self._s[3901]! } - public var Login_PadPhoneHelp: String { return self._s[3902]! } - public var AutoDownloadSettings_TypeGroupChats: String { return self._s[3904]! } - public var PrivacyPolicy_DeclineLastWarning: String { return self._s[3906]! } - public var NotificationsSound_Complete: String { return self._s[3907]! } - public var SettingsSearch_Synonyms_Privacy_Data_Title: String { return self._s[3908]! } - public var Group_Info_AdminLog: String { return self._s[3909]! } - public var GroupPermission_NotAvailableInPublicGroups: String { return self._s[3910]! } + public var AuthSessions_Terminate: String { return self._s[3898]! } + public var Wallet_WordImport_CanNotRemember: String { return self._s[3899]! } + public var Checkout_NewCard_CardholderNamePlaceholder: String { return self._s[3901]! } + public var KeyCommand_JumpToPreviousUnreadChat: String { return self._s[3902]! } + public var PhotoEditor_Set: String { return self._s[3903]! } + public var EmptyGroupInfo_Title: String { return self._s[3904]! } + public var Login_PadPhoneHelp: String { return self._s[3905]! } + public var AutoDownloadSettings_TypeGroupChats: String { return self._s[3907]! } + public var PrivacyPolicy_DeclineLastWarning: String { return self._s[3909]! } + public var NotificationsSound_Complete: String { return self._s[3910]! } + public var SettingsSearch_Synonyms_Privacy_Data_Title: String { return self._s[3911]! } + public var Group_Info_AdminLog: String { return self._s[3912]! } + public var GroupPermission_NotAvailableInPublicGroups: String { return self._s[3913]! } public func Wallet_Time_PreciseDate_m11(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3911]!, self._r[3911]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3914]!, self._r[3914]!, [_1, _2, _3]) } - public var Channel_AdminLog_InfoPanelAlertText: String { return self._s[3912]! } - public var Group_Location_CreateInThisPlace: String { return self._s[3914]! } - public var Conversation_Admin: String { return self._s[3915]! } - public var Conversation_GifTooltip: String { return self._s[3916]! } - public var Passport_NotLoggedInMessage: String { return self._s[3917]! } + public var Channel_AdminLog_InfoPanelAlertText: String { return self._s[3915]! } + public var Group_Location_CreateInThisPlace: String { return self._s[3917]! } + public var Conversation_Admin: String { return self._s[3918]! } + public var Conversation_GifTooltip: String { return self._s[3919]! } + public var Passport_NotLoggedInMessage: String { return self._s[3920]! } public func AutoDownloadSettings_OnFor(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3919]!, self._r[3919]!, [_0]) + return formatWithArgumentRanges(self._s[3922]!, self._r[3922]!, [_0]) } - public var Profile_MessageLifetimeForever: String { return self._s[3920]! } - public var SharedMedia_EmptyTitle: String { return self._s[3922]! } - public var Channel_Edit_PrivatePublicLinkAlert: String { return self._s[3924]! } - public var Username_Help: String { return self._s[3925]! } - public var DialogList_LanguageTooltip: String { return self._s[3927]! } - public var Map_LoadError: String { return self._s[3928]! } - public var Login_PhoneNumberAlreadyAuthorized: String { return self._s[3929]! } - public var Channel_AdminLog_AddMembers: String { return self._s[3930]! } - public var ArchivedChats_IntroTitle2: String { return self._s[3931]! } - public var Notification_Exceptions_NewException: String { return self._s[3932]! } - public var TwoStepAuth_EmailTitle: String { return self._s[3933]! } - public var WatchRemote_AlertText: String { return self._s[3934]! } + public var Profile_MessageLifetimeForever: String { return self._s[3923]! } + public var SharedMedia_EmptyTitle: String { return self._s[3925]! } + public var Channel_Edit_PrivatePublicLinkAlert: String { return self._s[3927]! } + public var Username_Help: String { return self._s[3928]! } + public var DialogList_LanguageTooltip: String { return self._s[3930]! } + public var Map_LoadError: String { return self._s[3931]! } + public var Login_PhoneNumberAlreadyAuthorized: String { return self._s[3932]! } + public var Channel_AdminLog_AddMembers: String { return self._s[3933]! } + public var ArchivedChats_IntroTitle2: String { return self._s[3934]! } + public var Notification_Exceptions_NewException: String { return self._s[3935]! } + public var TwoStepAuth_EmailTitle: String { return self._s[3936]! } + public var WatchRemote_AlertText: String { return self._s[3937]! } public func Wallet_Send_ConfirmationText(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3935]!, self._r[3935]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3938]!, self._r[3938]!, [_1, _2, _3]) } - public var ChatSettings_ConnectionType_Title: String { return self._s[3939]! } + public var ChatSettings_ConnectionType_Title: String { return self._s[3942]! } public func PUSH_PINNED_QUIZ(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3940]!, self._r[3940]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3943]!, self._r[3943]!, [_1, _2]) } public func Settings_CheckPhoneNumberTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3941]!, self._r[3941]!, [_0]) + return formatWithArgumentRanges(self._s[3944]!, self._r[3944]!, [_0]) } - public var SettingsSearch_Synonyms_Calls_CallTab: String { return self._s[3942]! } - public var WebBrowser_DefaultBrowser: String { return self._s[3943]! } - public var Passport_Address_CountryPlaceholder: String { return self._s[3944]! } + public var SettingsSearch_Synonyms_Calls_CallTab: String { return self._s[3945]! } + public var WebBrowser_DefaultBrowser: String { return self._s[3946]! } + public var Passport_Address_CountryPlaceholder: String { return self._s[3947]! } public func DialogList_AwaitingEncryption(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3945]!, self._r[3945]!, [_0]) + return formatWithArgumentRanges(self._s[3948]!, self._r[3948]!, [_0]) } public func Time_PreciseDate_m6(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3946]!, self._r[3946]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3949]!, self._r[3949]!, [_1, _2, _3]) } - public var Group_AdminLog_EmptyText: String { return self._s[3947]! } - public var SettingsSearch_Synonyms_Appearance_Title: String { return self._s[3948]! } - public var Conversation_PrivateChannelTooltip: String { return self._s[3950]! } - public var Wallet_Created_ExportErrorText: String { return self._s[3951]! } - public var ChatList_UndoArchiveText1: String { return self._s[3952]! } - public var AccessDenied_VideoMicrophone: String { return self._s[3953]! } - public var Conversation_ContextMenuStickerPackAdd: String { return self._s[3954]! } - public var Cache_ClearNone: String { return self._s[3955]! } - public var SocksProxySetup_FailedToConnect: String { return self._s[3956]! } - public var Permissions_NotificationsTitle_v0: String { return self._s[3957]! } + public var Group_AdminLog_EmptyText: String { return self._s[3950]! } + public var SettingsSearch_Synonyms_Appearance_Title: String { return self._s[3951]! } + public var Conversation_PrivateChannelTooltip: String { return self._s[3953]! } + public var Wallet_Created_ExportErrorText: String { return self._s[3954]! } + public var ChatList_UndoArchiveText1: String { return self._s[3955]! } + public var AccessDenied_VideoMicrophone: String { return self._s[3956]! } + public var Conversation_ContextMenuStickerPackAdd: String { return self._s[3957]! } + public var Cache_ClearNone: String { return self._s[3958]! } + public var SocksProxySetup_FailedToConnect: String { return self._s[3959]! } + public var Permissions_NotificationsTitle_v0: String { return self._s[3960]! } public func Channel_AdminLog_MessageEdited(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3958]!, self._r[3958]!, [_0]) - } - public var Passport_Identity_Country: String { return self._s[3959]! } - public func ChatSettings_AutoDownloadSettings_TypeFile(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3960]!, self._r[3960]!, [_0]) - } - public func Notification_CreatedChat(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3961]!, self._r[3961]!, [_0]) } - public var Exceptions_AddToExceptions: String { return self._s[3962]! } - public var AccessDenied_Settings: String { return self._s[3963]! } - public var Passport_Address_TypeUtilityBillUploadScan: String { return self._s[3964]! } - public var Month_ShortMay: String { return self._s[3965]! } - public var Compose_NewGroup: String { return self._s[3967]! } - public var Group_Setup_TypePrivate: String { return self._s[3969]! } - public var Login_PadPhoneHelpTitle: String { return self._s[3971]! } - public var Appearance_ThemeDayClassic: String { return self._s[3972]! } - public var Channel_AdminLog_MessagePreviousCaption: String { return self._s[3973]! } - public var AutoDownloadSettings_OffForAll: String { return self._s[3974]! } - public var Privacy_GroupsAndChannels_WhoCanAddMe: String { return self._s[3975]! } - public var Conversation_typing: String { return self._s[3977]! } - public var Undo_ScheduledMessagesCleared: String { return self._s[3978]! } - public var Paint_Masks: String { return self._s[3979]! } - public var Contacts_DeselectAll: String { return self._s[3980]! } - public func Wallet_Updated_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3981]!, self._r[3981]!, [_0]) + public var Passport_Identity_Country: String { return self._s[3962]! } + public func ChatSettings_AutoDownloadSettings_TypeFile(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3963]!, self._r[3963]!, [_0]) } - public var CreatePoll_MultipleChoiceQuizAlert: String { return self._s[3982]! } - public var Username_InvalidTaken: String { return self._s[3983]! } - public var Call_StatusNoAnswer: String { return self._s[3984]! } - public var TwoStepAuth_EmailAddSuccess: String { return self._s[3985]! } - public var SettingsSearch_Synonyms_Privacy_BlockedUsers: String { return self._s[3986]! } - public var Passport_Identity_Selfie: String { return self._s[3987]! } - public var Login_InfoLastNamePlaceholder: String { return self._s[3988]! } - public var Privacy_SecretChatsLinkPreviewsHelp: String { return self._s[3989]! } - public var Conversation_ClearSecretHistory: String { return self._s[3990]! } - public var PeopleNearby_Description: String { return self._s[3992]! } - public var NetworkUsageSettings_Title: String { return self._s[3993]! } - public var Your_cards_security_code_is_invalid: String { return self._s[3995]! } + public func Notification_CreatedChat(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3964]!, self._r[3964]!, [_0]) + } + public var Exceptions_AddToExceptions: String { return self._s[3965]! } + public var AccessDenied_Settings: String { return self._s[3966]! } + public var Passport_Address_TypeUtilityBillUploadScan: String { return self._s[3967]! } + public var Month_ShortMay: String { return self._s[3968]! } + public var Compose_NewGroup: String { return self._s[3970]! } + public var Group_Setup_TypePrivate: String { return self._s[3972]! } + public var Login_PadPhoneHelpTitle: String { return self._s[3974]! } + public var Appearance_ThemeDayClassic: String { return self._s[3975]! } + public var Channel_AdminLog_MessagePreviousCaption: String { return self._s[3976]! } + public var AutoDownloadSettings_OffForAll: String { return self._s[3977]! } + public var Privacy_GroupsAndChannels_WhoCanAddMe: String { return self._s[3978]! } + public var Conversation_typing: String { return self._s[3980]! } + public var Undo_ScheduledMessagesCleared: String { return self._s[3981]! } + public var Paint_Masks: String { return self._s[3982]! } + public var Contacts_DeselectAll: String { return self._s[3983]! } + public func Wallet_Updated_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3984]!, self._r[3984]!, [_0]) + } + public var CreatePoll_MultipleChoiceQuizAlert: String { return self._s[3985]! } + public var Username_InvalidTaken: String { return self._s[3986]! } + public var Call_StatusNoAnswer: String { return self._s[3987]! } + public var TwoStepAuth_EmailAddSuccess: String { return self._s[3988]! } + public var SettingsSearch_Synonyms_Privacy_BlockedUsers: String { return self._s[3989]! } + public var Passport_Identity_Selfie: String { return self._s[3990]! } + public var Login_InfoLastNamePlaceholder: String { return self._s[3991]! } + public var Privacy_SecretChatsLinkPreviewsHelp: String { return self._s[3992]! } + public var Conversation_ClearSecretHistory: String { return self._s[3993]! } + public var PeopleNearby_Description: String { return self._s[3995]! } + public var NetworkUsageSettings_Title: String { return self._s[3996]! } + public var Your_cards_security_code_is_invalid: String { return self._s[3998]! } public func Notification_LeftChannel(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3997]!, self._r[3997]!, [_0]) + return formatWithArgumentRanges(self._s[4000]!, self._r[4000]!, [_0]) } public func Call_CallInProgressMessage(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3998]!, self._r[3998]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4001]!, self._r[4001]!, [_1, _2]) } - public var SaveIncomingPhotosSettings_From: String { return self._s[4000]! } - public var VoiceOver_Navigation_Search: String { return self._s[4001]! } - public var Map_LiveLocationTitle: String { return self._s[4002]! } - public var Login_InfoAvatarAdd: String { return self._s[4003]! } - public var Passport_Identity_FilesView: String { return self._s[4004]! } - public var UserInfo_GenericPhoneLabel: String { return self._s[4005]! } - public var Privacy_Calls_NeverAllow: String { return self._s[4006]! } - public var VoiceOver_Chat_File: String { return self._s[4007]! } - public var Wallet_Settings_DeleteWalletInfo: String { return self._s[4008]! } + public var SaveIncomingPhotosSettings_From: String { return self._s[4003]! } + public var VoiceOver_Navigation_Search: String { return self._s[4004]! } + public var Map_LiveLocationTitle: String { return self._s[4005]! } + public var Login_InfoAvatarAdd: String { return self._s[4006]! } + public var Passport_Identity_FilesView: String { return self._s[4007]! } + public var UserInfo_GenericPhoneLabel: String { return self._s[4008]! } + public var Privacy_Calls_NeverAllow: String { return self._s[4009]! } + public var VoiceOver_Chat_File: String { return self._s[4010]! } + public var Wallet_Settings_DeleteWalletInfo: String { return self._s[4011]! } public func Contacts_AddPhoneNumber(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4009]!, self._r[4009]!, [_0]) + return formatWithArgumentRanges(self._s[4012]!, self._r[4012]!, [_0]) } - public var ContactInfo_PhoneNumberHidden: String { return self._s[4010]! } - public var TwoStepAuth_ConfirmationText: String { return self._s[4011]! } - public var ChatSettings_AutomaticVideoMessageDownload: String { return self._s[4012]! } + public var ContactInfo_PhoneNumberHidden: String { return self._s[4013]! } + public var TwoStepAuth_ConfirmationText: String { return self._s[4014]! } + public var ChatSettings_AutomaticVideoMessageDownload: String { return self._s[4015]! } public func PUSH_CHAT_MESSAGE_VIDEOS(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4013]!, self._r[4013]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[4016]!, self._r[4016]!, [_1, _2, _3]) } - public var Channel_AdminLogFilter_AdminsAll: String { return self._s[4014]! } - public var Wallet_Intro_CreateErrorText: String { return self._s[4015]! } - public var Tour_Title2: String { return self._s[4016]! } - public var Wallet_Sent_ViewWallet: String { return self._s[4017]! } - public var Conversation_FileOpenIn: String { return self._s[4018]! } - public var Checkout_ErrorPrecheckoutFailed: String { return self._s[4019]! } - public var Wallet_Send_ErrorInvalidAddress: String { return self._s[4020]! } - public var Wallpaper_Set: String { return self._s[4021]! } - public var Passport_Identity_Translations: String { return self._s[4023]! } + public var Channel_AdminLogFilter_AdminsAll: String { return self._s[4017]! } + public var Wallet_Intro_CreateErrorText: String { return self._s[4018]! } + public var Tour_Title2: String { return self._s[4019]! } + public var Wallet_Sent_ViewWallet: String { return self._s[4020]! } + public var Conversation_FileOpenIn: String { return self._s[4021]! } + public var Checkout_ErrorPrecheckoutFailed: String { return self._s[4022]! } + public var Wallet_Send_ErrorInvalidAddress: String { return self._s[4023]! } + public var Wallpaper_Set: String { return self._s[4024]! } + public var Passport_Identity_Translations: String { return self._s[4026]! } public func Channel_AdminLog_MessageChangedChannelAbout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4024]!, self._r[4024]!, [_0]) + return formatWithArgumentRanges(self._s[4027]!, self._r[4027]!, [_0]) } - public var Channel_LeaveChannel: String { return self._s[4025]! } + public var Channel_LeaveChannel: String { return self._s[4028]! } public func PINNED_INVOICE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4026]!, self._r[4026]!, [_1]) + return formatWithArgumentRanges(self._s[4029]!, self._r[4029]!, [_1]) } - public var SettingsSearch_Synonyms_Proxy_AddProxy: String { return self._s[4028]! } - public var PhotoEditor_HighlightsTint: String { return self._s[4029]! } - public var MessagePoll_LabelPoll: String { return self._s[4030]! } - public var Passport_Email_Delete: String { return self._s[4031]! } - public var Conversation_Mute: String { return self._s[4033]! } - public var Channel_AddBotAsAdmin: String { return self._s[4034]! } - public var Channel_AdminLog_CanSendMessages: String { return self._s[4036]! } - public var Wallet_Configuration_BlockchainNameChangedText: String { return self._s[4037]! } - public var ChatSettings_IntentsSettings: String { return self._s[4039]! } - public var Channel_Management_LabelOwner: String { return self._s[4040]! } + public var SettingsSearch_Synonyms_Proxy_AddProxy: String { return self._s[4031]! } + public var PhotoEditor_HighlightsTint: String { return self._s[4032]! } + public var MessagePoll_LabelPoll: String { return self._s[4033]! } + public var Passport_Email_Delete: String { return self._s[4034]! } + public var Conversation_Mute: String { return self._s[4036]! } + public var Channel_AddBotAsAdmin: String { return self._s[4037]! } + public var Channel_AdminLog_CanSendMessages: String { return self._s[4039]! } + public var Wallet_Configuration_BlockchainNameChangedText: String { return self._s[4040]! } + public var ChatSettings_IntentsSettings: String { return self._s[4042]! } + public var Channel_Management_LabelOwner: String { return self._s[4043]! } public func Notification_PassportValuesSentMessage(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4041]!, self._r[4041]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4044]!, self._r[4044]!, [_1, _2]) } - public var Calls_CallTabDescription: String { return self._s[4042]! } - public var Passport_Identity_NativeNameHelp: String { return self._s[4043]! } - public var Common_No: String { return self._s[4044]! } - public var Weekday_Sunday: String { return self._s[4045]! } - public var Notification_Reply: String { return self._s[4046]! } - public var Conversation_ViewMessage: String { return self._s[4047]! } + public var Calls_CallTabDescription: String { return self._s[4045]! } + public var Passport_Identity_NativeNameHelp: String { return self._s[4046]! } + public var Common_No: String { return self._s[4047]! } + public var Weekday_Sunday: String { return self._s[4048]! } + public var Notification_Reply: String { return self._s[4049]! } + public var Conversation_ViewMessage: String { return self._s[4050]! } public func Checkout_SavePasswordTimeoutAndFaceId(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4048]!, self._r[4048]!, [_0]) + return formatWithArgumentRanges(self._s[4051]!, self._r[4051]!, [_0]) } public func Map_LiveLocationPrivateDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4049]!, self._r[4049]!, [_0]) + return formatWithArgumentRanges(self._s[4052]!, self._r[4052]!, [_0]) } public func Wallet_Time_PreciseDate_m7(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4050]!, self._r[4050]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[4053]!, self._r[4053]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_EditProfile_AddAccount: String { return self._s[4051]! } - public var Wallet_Send_Title: String { return self._s[4052]! } - public var Message_PinnedDocumentMessage: String { return self._s[4053]! } - public var Wallet_Info_RefreshErrorText: String { return self._s[4054]! } - public var DialogList_TabTitle: String { return self._s[4056]! } - public var ChatSettings_AutoPlayTitle: String { return self._s[4057]! } - public var Passport_FieldEmail: String { return self._s[4058]! } - public var Conversation_UnpinMessageAlert: String { return self._s[4059]! } - public var Passport_Address_TypeBankStatement: String { return self._s[4060]! } - public var Wallet_SecureStorageReset_Title: String { return self._s[4061]! } - public var Passport_Identity_ExpiryDate: String { return self._s[4062]! } - public var Privacy_Calls_P2P: String { return self._s[4063]! } + public var SettingsSearch_Synonyms_EditProfile_AddAccount: String { return self._s[4054]! } + public var Wallet_Send_Title: String { return self._s[4055]! } + public var Message_PinnedDocumentMessage: String { return self._s[4056]! } + public var Wallet_Info_RefreshErrorText: String { return self._s[4057]! } + public var DialogList_TabTitle: String { return self._s[4059]! } + public var ChatSettings_AutoPlayTitle: String { return self._s[4060]! } + public var Passport_FieldEmail: String { return self._s[4061]! } + public var Conversation_UnpinMessageAlert: String { return self._s[4062]! } + public var Passport_Address_TypeBankStatement: String { return self._s[4063]! } + public var Wallet_SecureStorageReset_Title: String { return self._s[4064]! } + public var Passport_Identity_ExpiryDate: String { return self._s[4065]! } + public var Privacy_Calls_P2P: String { return self._s[4066]! } public func CancelResetAccount_Success(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4065]!, self._r[4065]!, [_0]) + return formatWithArgumentRanges(self._s[4068]!, self._r[4068]!, [_0]) } - public var SocksProxySetup_UseForCallsHelp: String { return self._s[4066]! } + public var SocksProxySetup_UseForCallsHelp: String { return self._s[4069]! } public func PUSH_CHAT_ALBUM(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4067]!, self._r[4067]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4070]!, self._r[4070]!, [_1, _2]) } - public var Stickers_ClearRecent: String { return self._s[4068]! } - public var EnterPasscode_ChangeTitle: String { return self._s[4069]! } - public var TwoFactorSetup_Email_Title: String { return self._s[4070]! } - public var Passport_InfoText: String { return self._s[4071]! } - public var Checkout_NewCard_SaveInfoEnableHelp: String { return self._s[4072]! } + public var Stickers_ClearRecent: String { return self._s[4071]! } + public var EnterPasscode_ChangeTitle: String { return self._s[4072]! } + public var TwoFactorSetup_Email_Title: String { return self._s[4073]! } + public var Passport_InfoText: String { return self._s[4074]! } + public var Checkout_NewCard_SaveInfoEnableHelp: String { return self._s[4075]! } public func Login_InvalidPhoneEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4073]!, self._r[4073]!, [_0]) + return formatWithArgumentRanges(self._s[4076]!, self._r[4076]!, [_0]) } public func Time_PreciseDate_m3(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4074]!, self._r[4074]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[4077]!, self._r[4077]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChannels: String { return self._s[4075]! } - public var ScheduledMessages_PollUnavailable: String { return self._s[4076]! } - public var VoiceOver_Navigation_Compose: String { return self._s[4077]! } - public var Passport_Identity_EditDriversLicense: String { return self._s[4078]! } - public var Conversation_TapAndHoldToRecord: String { return self._s[4080]! } - public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChats: String { return self._s[4081]! } + public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChannels: String { return self._s[4078]! } + public var ScheduledMessages_PollUnavailable: String { return self._s[4079]! } + public var VoiceOver_Navigation_Compose: String { return self._s[4080]! } + public var Passport_Identity_EditDriversLicense: String { return self._s[4081]! } + public var Conversation_TapAndHoldToRecord: String { return self._s[4083]! } + public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChats: String { return self._s[4084]! } public func Notification_CallTimeFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4082]!, self._r[4082]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4085]!, self._r[4085]!, [_1, _2]) } - public var Channel_EditAdmin_PermissionInviteViaLink: String { return self._s[4084]! } - public var ChatSettings_OpenLinksIn: String { return self._s[4085]! } - public var Map_HomeAndWorkTitle: String { return self._s[4086]! } + public var Channel_EditAdmin_PermissionInviteViaLink: String { return self._s[4087]! } + public var ChatSettings_OpenLinksIn: String { return self._s[4088]! } + public var Map_HomeAndWorkTitle: String { return self._s[4089]! } public func Generic_OpenHiddenLinkAlert(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4088]!, self._r[4088]!, [_0]) + return formatWithArgumentRanges(self._s[4091]!, self._r[4091]!, [_0]) } - public var DialogList_Unread: String { return self._s[4089]! } + public var DialogList_Unread: String { return self._s[4092]! } public func PUSH_CHAT_MESSAGE_GIF(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4090]!, self._r[4090]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4093]!, self._r[4093]!, [_1, _2]) } - public var User_DeletedAccount: String { return self._s[4091]! } - public var OwnershipTransfer_SetupTwoStepAuth: String { return self._s[4092]! } + public var User_DeletedAccount: String { return self._s[4094]! } + public var OwnershipTransfer_SetupTwoStepAuth: String { return self._s[4095]! } public func Watch_Time_ShortYesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4093]!, self._r[4093]!, [_0]) + return formatWithArgumentRanges(self._s[4096]!, self._r[4096]!, [_0]) } - public var UserInfo_NotificationsDefault: String { return self._s[4094]! } - public var SharedMedia_CategoryMedia: String { return self._s[4095]! } - public var SocksProxySetup_ProxyStatusUnavailable: String { return self._s[4096]! } - public var Channel_AdminLog_MessageRestrictedForever: String { return self._s[4097]! } - public var Watch_ChatList_Compose: String { return self._s[4098]! } - public var Notifications_MessageNotificationsExceptionsHelp: String { return self._s[4099]! } - public var AutoDownloadSettings_Delimeter: String { return self._s[4100]! } - public var Watch_Microphone_Access: String { return self._s[4101]! } - public var Group_Setup_HistoryHeader: String { return self._s[4102]! } - public var Map_SetThisLocation: String { return self._s[4103]! } - public var Appearance_ThemePreview_Chat_2_ReplyName: String { return self._s[4104]! } - public var Activity_UploadingPhoto: String { return self._s[4105]! } - public var Conversation_Edit: String { return self._s[4107]! } - public var Group_ErrorSendRestrictedMedia: String { return self._s[4108]! } - public var Login_TermsOfServiceDecline: String { return self._s[4109]! } - public var Message_PinnedContactMessage: String { return self._s[4110]! } + public var UserInfo_NotificationsDefault: String { return self._s[4097]! } + public var SharedMedia_CategoryMedia: String { return self._s[4098]! } + public var SocksProxySetup_ProxyStatusUnavailable: String { return self._s[4099]! } + public var Channel_AdminLog_MessageRestrictedForever: String { return self._s[4100]! } + public var Watch_ChatList_Compose: String { return self._s[4101]! } + public var Notifications_MessageNotificationsExceptionsHelp: String { return self._s[4102]! } + public var AutoDownloadSettings_Delimeter: String { return self._s[4103]! } + public var Watch_Microphone_Access: String { return self._s[4104]! } + public var Group_Setup_HistoryHeader: String { return self._s[4105]! } + public var Map_SetThisLocation: String { return self._s[4106]! } + public var Appearance_ThemePreview_Chat_2_ReplyName: String { return self._s[4107]! } + public var Activity_UploadingPhoto: String { return self._s[4108]! } + public var Conversation_Edit: String { return self._s[4110]! } + public var Group_ErrorSendRestrictedMedia: String { return self._s[4111]! } + public var Login_TermsOfServiceDecline: String { return self._s[4112]! } + public var Message_PinnedContactMessage: String { return self._s[4113]! } public func Channel_AdminLog_MessageRestrictedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4111]!, self._r[4111]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4114]!, self._r[4114]!, [_1, _2]) } public func Login_PhoneBannedEmailBody(_ _1: String, _ _2: String, _ _3: String, _ _4: String, _ _5: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4112]!, self._r[4112]!, [_1, _2, _3, _4, _5]) + return formatWithArgumentRanges(self._s[4115]!, self._r[4115]!, [_1, _2, _3, _4, _5]) } - public var Appearance_LargeEmoji: String { return self._s[4113]! } - public var TwoStepAuth_AdditionalPassword: String { return self._s[4115]! } - public var EditTheme_Edit_Preview_IncomingReplyText: String { return self._s[4116]! } + public var Appearance_LargeEmoji: String { return self._s[4116]! } + public var TwoStepAuth_AdditionalPassword: String { return self._s[4118]! } + public var EditTheme_Edit_Preview_IncomingReplyText: String { return self._s[4119]! } public func PUSH_CHAT_DELETE_YOU(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4117]!, self._r[4117]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4120]!, self._r[4120]!, [_1, _2]) } - public var Passport_Phone_EnterOtherNumber: String { return self._s[4118]! } - public var Message_PinnedPhotoMessage: String { return self._s[4119]! } - public var Passport_FieldPhone: String { return self._s[4120]! } - public var TwoStepAuth_RecoveryEmailAddDescription: String { return self._s[4121]! } - public var ChatSettings_AutoPlayGifs: String { return self._s[4122]! } - public var InfoPlist_NSCameraUsageDescription: String { return self._s[4124]! } - public var Conversation_Call: String { return self._s[4125]! } - public var Common_TakePhoto: String { return self._s[4127]! } - public var Group_EditAdmin_RankTitle: String { return self._s[4128]! } - public var Wallet_Receive_CommentHeader: String { return self._s[4129]! } - public var Channel_NotificationLoading: String { return self._s[4130]! } + public var Passport_Phone_EnterOtherNumber: String { return self._s[4121]! } + public var Message_PinnedPhotoMessage: String { return self._s[4122]! } + public var Passport_FieldPhone: String { return self._s[4123]! } + public var TwoStepAuth_RecoveryEmailAddDescription: String { return self._s[4124]! } + public var ChatSettings_AutoPlayGifs: String { return self._s[4125]! } + public var InfoPlist_NSCameraUsageDescription: String { return self._s[4127]! } + public var Conversation_Call: String { return self._s[4128]! } + public var Common_TakePhoto: String { return self._s[4130]! } + public var Group_EditAdmin_RankTitle: String { return self._s[4131]! } + public var Wallet_Receive_CommentHeader: String { return self._s[4132]! } + public var Channel_NotificationLoading: String { return self._s[4133]! } public func Notification_Exceptions_Sound(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4131]!, self._r[4131]!, [_0]) + return formatWithArgumentRanges(self._s[4134]!, self._r[4134]!, [_0]) } public func ScheduledMessages_ScheduledDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4132]!, self._r[4132]!, [_0]) - } - public func PUSH_CHANNEL_MESSAGE_VIDEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4133]!, self._r[4133]!, [_1]) - } - public var Permissions_SiriTitle_v0: String { return self._s[4134]! } - public func VoiceOver_Chat_VoiceMessageFrom(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[4135]!, self._r[4135]!, [_0]) } + public func PUSH_CHANNEL_MESSAGE_VIDEO(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[4136]!, self._r[4136]!, [_1]) + } + public var Permissions_SiriTitle_v0: String { return self._s[4137]! } + public func VoiceOver_Chat_VoiceMessageFrom(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[4138]!, self._r[4138]!, [_0]) + } public func Login_ResetAccountProtected_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4136]!, self._r[4136]!, [_0]) + return formatWithArgumentRanges(self._s[4139]!, self._r[4139]!, [_0]) } - public var Channel_MessagePhotoRemoved: String { return self._s[4137]! } - public var Wallet_Info_ReceiveGrams: String { return self._s[4138]! } - public var ClearCache_FreeSpace: String { return self._s[4139]! } - public var Common_edit: String { return self._s[4140]! } - public var PrivacySettings_AuthSessions: String { return self._s[4141]! } - public var Month_ShortJune: String { return self._s[4142]! } - public var PrivacyLastSeenSettings_AlwaysShareWith_Placeholder: String { return self._s[4143]! } - public var Call_ReportSend: String { return self._s[4144]! } - public var Watch_LastSeen_JustNow: String { return self._s[4145]! } - public var Notifications_MessageNotifications: String { return self._s[4146]! } - public var WallpaperSearch_ColorGreen: String { return self._s[4147]! } - public var BroadcastListInfo_AddRecipient: String { return self._s[4149]! } - public var Group_Status: String { return self._s[4150]! } + public var Channel_MessagePhotoRemoved: String { return self._s[4140]! } + public var Wallet_Info_ReceiveGrams: String { return self._s[4141]! } + public var ClearCache_FreeSpace: String { return self._s[4142]! } + public var Appearance_BubbleCorners_Apply: String { return self._s[4143]! } + public var Common_edit: String { return self._s[4144]! } + public var PrivacySettings_AuthSessions: String { return self._s[4145]! } + public var Month_ShortJune: String { return self._s[4146]! } + public var PrivacyLastSeenSettings_AlwaysShareWith_Placeholder: String { return self._s[4147]! } + public var Call_ReportSend: String { return self._s[4148]! } + public var Watch_LastSeen_JustNow: String { return self._s[4149]! } + public var Notifications_MessageNotifications: String { return self._s[4150]! } + public var WallpaperSearch_ColorGreen: String { return self._s[4151]! } + public var BroadcastListInfo_AddRecipient: String { return self._s[4153]! } + public var Group_Status: String { return self._s[4154]! } public func AutoNightTheme_LocationHelp(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4151]!, self._r[4151]!, [_0, _1]) + return formatWithArgumentRanges(self._s[4155]!, self._r[4155]!, [_0, _1]) } - public var TextFormat_AddLinkTitle: String { return self._s[4152]! } - public var ShareMenu_ShareTo: String { return self._s[4153]! } - public var Conversation_Moderate_Ban: String { return self._s[4154]! } + public var TextFormat_AddLinkTitle: String { return self._s[4156]! } + public var ShareMenu_ShareTo: String { return self._s[4157]! } + public var Conversation_Moderate_Ban: String { return self._s[4158]! } public func Conversation_DeleteMessagesFor(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4155]!, self._r[4155]!, [_0]) + return formatWithArgumentRanges(self._s[4159]!, self._r[4159]!, [_0]) } - public var SharedMedia_ViewInChat: String { return self._s[4156]! } - public var Map_LiveLocationFor8Hours: String { return self._s[4157]! } + public var SharedMedia_ViewInChat: String { return self._s[4160]! } + public var Map_LiveLocationFor8Hours: String { return self._s[4161]! } public func PUSH_PINNED_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4158]!, self._r[4158]!, [_1]) + return formatWithArgumentRanges(self._s[4162]!, self._r[4162]!, [_1]) } public func PUSH_PINNED_POLL(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4159]!, self._r[4159]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4163]!, self._r[4163]!, [_1, _2]) } public func Map_AccurateTo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4161]!, self._r[4161]!, [_0]) + return formatWithArgumentRanges(self._s[4165]!, self._r[4165]!, [_0]) } - public var Map_OpenInHereMaps: String { return self._s[4162]! } - public var Appearance_ReduceMotion: String { return self._s[4163]! } + public var Map_OpenInHereMaps: String { return self._s[4166]! } + public var Appearance_ReduceMotion: String { return self._s[4167]! } public func PUSH_MESSAGE_TEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4164]!, self._r[4164]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4168]!, self._r[4168]!, [_1, _2]) } - public var Channel_Setup_TypePublicHelp: String { return self._s[4165]! } - public var Passport_Identity_EditInternalPassport: String { return self._s[4166]! } - public var PhotoEditor_Skip: String { return self._s[4167]! } - public func MessagePoll_QuizCount(_ value: Int32) -> String { + public var Channel_Setup_TypePublicHelp: String { return self._s[4169]! } + public var Passport_Identity_EditInternalPassport: String { return self._s[4170]! } + public var PhotoEditor_Skip: String { return self._s[4171]! } + public func ForwardedGifs(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedVideoMessages(_ value: Int32) -> String { + public func ServiceMessage_GameScoreExtended(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedFiles(_ value: Int32) -> String { + public func Map_ETAMinutes(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[2 * 6 + Int(form.rawValue)]!, stringValue) } - public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[3 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Call_Seconds(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[4 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHANNEL_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[5 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func StickerPack_RemoveMaskCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[6 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedMessages(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[7 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Seconds(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[8 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Months(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[9 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedStickers(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[10 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Watch_LastSeen_HoursAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[11 * 6 + Int(form.rawValue)]!, stringValue) - } - public func InviteText_ContactsCountText(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[12 * 6 + Int(form.rawValue)]!, stringValue) - } - public func LastSeen_HoursAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[13 * 6 + Int(form.rawValue)]!, stringValue) - } - public func AttachmentMenu_SendPhoto(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[14 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[15 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func Notification_GameScoreSelfSimple(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[16 * 6 + Int(form.rawValue)]!, stringValue) - } - public func AttachmentMenu_SendItem(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[17 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PrivacyLastSeenSettings_AddUsers(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[18 * 6 + Int(form.rawValue)]!, stringValue) - } - public func DialogList_LiveLocationChatsCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[19 * 6 + Int(form.rawValue)]!, stringValue) - } - public func AttachmentMenu_SendVideo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[20 * 6 + Int(form.rawValue)]!, stringValue) - } - public func VoiceOver_Chat_ContactEmailCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[21 * 6 + Int(form.rawValue)]!, stringValue) - } - public func SharedMedia_DeleteItemsConfirmation(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[22 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Media_SharePhoto(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[23 * 6 + Int(form.rawValue)]!, stringValue) - } - public func OldChannels_InactiveYear(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[24 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedPhotos(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[25 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Theme_UsersCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[26 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHANNEL_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[27 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func LastSeen_MinutesAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[28 * 6 + Int(form.rawValue)]!, stringValue) - } - public func QuickSend_Photos(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[29 * 6 + Int(form.rawValue)]!, stringValue) - } - public func VoiceOver_Chat_PollOptionCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[30 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Hours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[31 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Conversation_StatusSubscribers(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[32 * 6 + Int(form.rawValue)]!, stringValue) - } - public func OldChannels_GroupFormat(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[33 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Media_ShareItem(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[34 * 6 + Int(form.rawValue)]!, stringValue) - } - public func AttachmentMenu_SendGif(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[35 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notification_GameScoreExtended(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[36 * 6 + Int(form.rawValue)]!, stringValue) - } - public func GroupInfo_ShowMoreMembers(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[37 * 6 + Int(form.rawValue)]!, stringValue) - } - public func SharedMedia_Generic(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[38 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MuteExpires_Hours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[39 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Watch_UserInfo_Mute(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[40 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notifications_ExceptionMuteExpires_Days(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[41 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MuteExpires_Days(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[42 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Chat_DeleteMessagesConfirmation(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[43 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Call_Minutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[44 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Conversation_SelectedMessages(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[45 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_ShortDays(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[46 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notifications_ExceptionMuteExpires_Minutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[47 * 6 + Int(form.rawValue)]!, stringValue) - } - public func LiveLocation_MenuChatsCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[48 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGE_ROUNDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[49 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func UserCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[50 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Contacts_ImportersCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[51 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedContacts(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[52 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedAudios(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[53 * 6 + Int(form.rawValue)]!, stringValue) - } - public func StickerPack_StickerCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[54 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notifications_ExceptionMuteExpires_Hours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[55 * 6 + Int(form.rawValue)]!, stringValue) - } - public func VoiceOver_Chat_ContactPhoneNumberCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[56 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_ShortWeeks(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[57 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notifications_Exceptions(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[58 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ChatList_DeletedChats(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[59 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Call_ShortSeconds(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[60 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[61 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func Notification_GameScoreSimple(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[62 * 6 + Int(form.rawValue)]!, stringValue) - } - public func CreatePoll_AddMoreOptions(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[63 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MuteFor_Hours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[64 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notification_GameScoreSelfExtended(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[65 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Media_ShareVideo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[66 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHANNEL_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[67 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func SharedMedia_File(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[68 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Conversation_LiveLocationMembersCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[69 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Minutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[70 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Conversation_StatusMembers(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[71 * 6 + Int(form.rawValue)]!, stringValue) - } - public func StickerPack_AddStickerCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[72 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Years(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[73 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Map_ETAMinutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[74 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedVideos(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[75 * 6 + Int(form.rawValue)]!, stringValue) - } - public func SharedMedia_Link(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[76 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessagePoll_VotedCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[77 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHANNEL_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[78 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func Contacts_InviteContacts(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[79 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Days(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[80 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Watch_LastSeen_MinutesAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[81 * 6 + Int(form.rawValue)]!, stringValue) - } - public func SharedMedia_Photo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[82 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Wallet_Updated_HoursAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[83 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGES(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[84 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func ServiceMessage_GameScoreExtended(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[85 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Passport_Scans(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[86 * 6 + Int(form.rawValue)]!, stringValue) - } - public func GroupInfo_ParticipantCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[87 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ServiceMessage_GameScoreSelfExtended(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[88 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Call_ShortMinutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[89 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[90 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func PUSH_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[91 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func OldChannels_Leave(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[92 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[93 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func PUSH_CHAT_MESSAGE_PHOTOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[94 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } public func PUSH_CHANNEL_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[95 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func OldChannels_InactiveMonth(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[96 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_ShortMinutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[97 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PasscodeSettings_FailedAttempts(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[98 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Invitation_Members(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[99 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedAuthorsOthers(_ selector: Int32, _ _0: String, _ _1: String) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[100 * 6 + Int(form.rawValue)]!, _0, _1) - } - public func StickerPack_RemoveStickerCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[101 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ServiceMessage_GameScoreSimple(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[102 * 6 + Int(form.rawValue)]!, stringValue) - } - public func OldChannels_InactiveWeek(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[103 * 6 + Int(form.rawValue)]!, stringValue) - } - public func StickerPack_AddMaskCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[104 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedLocations(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[105 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGE_FWDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[106 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func MessageTimer_ShortHours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[107 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MuteFor_Days(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[108 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ServiceMessage_GameScoreSelfSimple(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[109 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGE_VIDEOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[110 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func MessageTimer_ShortSeconds(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[111 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Forward_ConfirmMultipleFiles(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[112 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[3 * 6 + Int(form.rawValue)]!, _1, _2) } public func ChatList_DeleteConfirmation(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[113 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[4 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedGifs(_ value: Int32) -> String { + public func LastSeen_MinutesAgo(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[114 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[5 * 6 + Int(form.rawValue)]!, stringValue) } - public func MuteExpires_Minutes(_ value: Int32) -> String { + public func VoiceOver_Chat_ContactPhoneNumberCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[115 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[6 * 6 + Int(form.rawValue)]!, stringValue) } - public func Wallpaper_DeleteConfirmation(_ value: Int32) -> String { + public func Call_Minutes(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[116 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[7 * 6 + Int(form.rawValue)]!, stringValue) } - public func LiveLocationUpdated_MinutesAgo(_ value: Int32) -> String { + public func Notifications_ExceptionMuteExpires_Hours(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[117 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[8 * 6 + Int(form.rawValue)]!, stringValue) } - public func VoiceOver_Chat_PollVotes(_ value: Int32) -> String { + public func Contacts_InviteContacts(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[118 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[9 * 6 + Int(form.rawValue)]!, stringValue) } - public func ChatList_SelectedChats(_ value: Int32) -> String { + public func ServiceMessage_GameScoreSelfSimple(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[119 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[10 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_Weeks(_ value: Int32) -> String { + public func Conversation_StatusSubscribers(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[120 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[11 * 6 + Int(form.rawValue)]!, stringValue) + } + public func VoiceOver_Chat_PollOptionCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[12 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[13 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func MessageTimer_Seconds(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[14 * 6 + Int(form.rawValue)]!, stringValue) } public func PollResults_ShowMore(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[121 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[15 * 6 + Int(form.rawValue)]!, stringValue) + } + public func StickerPack_AddMaskCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[16 * 6 + Int(form.rawValue)]!, stringValue) + } + public func LastSeen_HoursAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[17 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Media_SharePhoto(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[18 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[19 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func Watch_UserInfo_Mute(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[20 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Media_ShareVideo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[21 * 6 + Int(form.rawValue)]!, stringValue) + } + public func OldChannels_InactiveWeek(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[22 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Conversation_LiveLocationMembersCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[23 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Invitation_Members(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[24 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessagePoll_QuizCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[25 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notification_GameScoreSimple(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[26 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PrivacyLastSeenSettings_AddUsers(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[27 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Watch_LastSeen_HoursAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[28 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ChatList_DeletedChats(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[29 * 6 + Int(form.rawValue)]!, stringValue) + } + public func VoiceOver_Chat_PollVotes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[30 * 6 + Int(form.rawValue)]!, stringValue) + } + public func StickerPack_StickerCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[31 * 6 + Int(form.rawValue)]!, stringValue) + } + public func StickerPack_RemoveStickerCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[32 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Conversation_StatusMembers(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[33 * 6 + Int(form.rawValue)]!, stringValue) + } + public func OldChannels_GroupFormat(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[34 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Media_ShareItem(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[35 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Wallet_Updated_HoursAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[36 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedVideoMessages(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[37 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedFiles(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[38 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notification_GameScoreSelfExtended(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[39 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortHours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[40 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notification_GameScoreExtended(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[41 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedPhotos(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[42 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Passport_Scans(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[43 * 6 + Int(form.rawValue)]!, stringValue) + } + public func StickerPack_AddStickerCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[44 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHAT_MESSAGE_PHOTOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[45 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func SharedMedia_Photo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[46 * 6 + Int(form.rawValue)]!, stringValue) + } + public func AttachmentMenu_SendGif(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[47 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessagePoll_VotedCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[48 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notifications_ExceptionMuteExpires_Days(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[49 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[50 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func Notification_GameScoreSelfSimple(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[51 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Call_ShortSeconds(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[52 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Chat_DeleteMessagesConfirmation(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[53 * 6 + Int(form.rawValue)]!, stringValue) + } + public func InviteText_ContactsCountText(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[54 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MuteExpires_Days(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[55 * 6 + Int(form.rawValue)]!, stringValue) } public func ForwardedPolls(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[122 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[56 * 6 + Int(form.rawValue)]!, stringValue) } - public func SharedMedia_Video(_ value: Int32) -> String { + public func ServiceMessage_GameScoreSelfExtended(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[123 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[57 * 6 + Int(form.rawValue)]!, stringValue) } - public func Map_ETAHours(_ value: Int32) -> String { + public func ChatList_SelectedChats(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[124 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[58 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Years(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[59 * 6 + Int(form.rawValue)]!, stringValue) + } + public func AttachmentMenu_SendVideo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[60 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[61 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MuteExpires_Minutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[62 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHAT_MESSAGE_FWDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[63 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func Notifications_Exceptions(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[64 * 6 + Int(form.rawValue)]!, stringValue) + } + public func UserCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[65 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[66 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func SharedMedia_Link(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[67 * 6 + Int(form.rawValue)]!, stringValue) } public func Conversation_StatusOnline(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[125 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[68 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Theme_UsersCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[69 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Forward_ConfirmMultipleFiles(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[70 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedStickers(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[71 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedVideos(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[72 * 6 + Int(form.rawValue)]!, stringValue) + } + public func VoiceOver_Chat_ContactEmailCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[73 * 6 + Int(form.rawValue)]!, stringValue) + } + public func SharedMedia_Video(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[74 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Wallpaper_DeleteConfirmation(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[75 * 6 + Int(form.rawValue)]!, stringValue) + } + public func OldChannels_InactiveMonth(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[76 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHAT_MESSAGE_ROUNDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[77 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func PUSH_CHAT_MESSAGES(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[78 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func ForwardedLocations(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[79 * 6 + Int(form.rawValue)]!, stringValue) + } + public func AttachmentMenu_SendItem(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[80 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHAT_MESSAGE_VIDEOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[81 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func ServiceMessage_GameScoreSimple(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[82 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[83 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func StickerPack_RemoveMaskCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[84 * 6 + Int(form.rawValue)]!, stringValue) + } + public func QuickSend_Photos(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[85 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Contacts_ImportersCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[86 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortWeeks(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[87 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Hours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[88 * 6 + Int(form.rawValue)]!, stringValue) + } + public func LiveLocationUpdated_MinutesAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[89 * 6 + Int(form.rawValue)]!, stringValue) + } + public func GroupInfo_ParticipantCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[90 * 6 + Int(form.rawValue)]!, stringValue) + } + public func SharedMedia_DeleteItemsConfirmation(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[91 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Map_ETAHours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[92 * 6 + Int(form.rawValue)]!, stringValue) + } + public func AttachmentMenu_SendPhoto(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[93 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedAudios(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[94 * 6 + Int(form.rawValue)]!, stringValue) + } + public func CreatePoll_AddMoreOptions(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[95 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[96 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func ForwardedContacts(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[97 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Weeks(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[98 * 6 + Int(form.rawValue)]!, stringValue) + } + public func LiveLocation_MenuChatsCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[99 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MuteExpires_Hours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[100 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[101 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func MuteFor_Days(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[102 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PasscodeSettings_FailedAttempts(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[103 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MuteFor_Hours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[104 * 6 + Int(form.rawValue)]!, stringValue) + } + public func SharedMedia_File(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[105 * 6 + Int(form.rawValue)]!, stringValue) + } + public func DialogList_LiveLocationChatsCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[106 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Call_ShortMinutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[107 * 6 + Int(form.rawValue)]!, stringValue) + } + public func SharedMedia_Generic(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[108 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Days(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[109 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortMinutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[110 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notifications_ExceptionMuteExpires_Minutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[111 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Call_Seconds(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[112 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedAuthorsOthers(_ selector: Int32, _ _0: String, _ _1: String) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[113 * 6 + Int(form.rawValue)]!, _0, _1) + } + public func MessageTimer_Minutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[114 * 6 + Int(form.rawValue)]!, stringValue) + } + public func GroupInfo_ShowMoreMembers(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[115 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Conversation_SelectedMessages(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[116 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortDays(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[117 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Watch_LastSeen_MinutesAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[118 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortSeconds(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[119 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Months(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[120 * 6 + Int(form.rawValue)]!, stringValue) + } + public func OldChannels_Leave(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[121 * 6 + Int(form.rawValue)]!, stringValue) + } + public func OldChannels_InactiveYear(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[122 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[123 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func ForwardedMessages(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[124 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[125 * 6 + Int(form.rawValue)]!, _1, _2) } public init(primaryComponent: PresentationStringsComponent, secondaryComponent: PresentationStringsComponent?, groupingSeparator: String) { diff --git a/submodules/TelegramPresentationData/Sources/PresentationTheme.swift b/submodules/TelegramPresentationData/Sources/PresentationTheme.swift index 3571d6d77f..e9ab5e256a 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationTheme.swift @@ -1182,6 +1182,10 @@ public final class PresentationTheme: Equatable { return self.resourceCache.object(key, self, generate) } + public func object(_ key: PresentationResourceParameterKey, _ generate: (PresentationTheme) -> AnyObject?) -> AnyObject? { + return self.resourceCache.parameterObject(key, self, generate) + } + public static func ==(lhs: PresentationTheme, rhs: PresentationTheme) -> Bool { return lhs === rhs } diff --git a/submodules/TelegramPresentationData/Sources/PresentationThemeEssentialGraphics.swift b/submodules/TelegramPresentationData/Sources/PresentationThemeEssentialGraphics.swift index dd1618f965..d5a0f0fc3a 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationThemeEssentialGraphics.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationThemeEssentialGraphics.swift @@ -160,7 +160,7 @@ public final class PrincipalThemeEssentialGraphics { public let incomingBubbleGradientImage: UIImage? public let outgoingBubbleGradientImage: UIImage? - init(mediaBox: MediaBox, presentationTheme: PresentationTheme, wallpaper initialWallpaper: TelegramWallpaper, preview: Bool = false, knockoutMode: Bool) { + init(mediaBox: MediaBox, presentationTheme: PresentationTheme, wallpaper initialWallpaper: TelegramWallpaper, preview: Bool = false, knockoutMode: Bool, bubbleCorners: PresentationChatBubbleCorners) { let theme = presentationTheme.chat var wallpaper = initialWallpaper @@ -215,28 +215,31 @@ public final class PrincipalThemeEssentialGraphics { let serviceColor = serviceMessageColorComponents(chatTheme: theme, wallpaper: wallpaper) + let maxCornerRadius = bubbleCorners.mainRadius + let minCornerRadius = bubbleCorners.mergeBubbleCorners ? bubbleCorners.auxiliaryRadius : bubbleCorners.mainRadius + let emptyImage = UIImage() if preview { - self.chatMessageBackgroundIncomingMaskImage = messageBubbleImage(incoming: true, fillColor: UIColor.black, strokeColor: UIColor.clear, neighbors: .none, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundIncomingImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingOutlineImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundOutgoingMaskImage = messageBubbleImage(incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .none, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundOutgoingImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingOutlineImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: UIColor.black, strokeColor: UIColor.clear, neighbors: .none, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) + self.chatMessageBackgroundIncomingImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .none, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) + self.chatMessageBackgroundOutgoingImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) self.checkBubbleFullImage = generateCheckImage(partial: false, color: theme.message.outgoingCheckColor, width: 11.0)! self.checkBubblePartialImage = generateCheckImage(partial: true, color: theme.message.outgoingCheckColor, width: 11.0)! self.chatMessageBackgroundIncomingHighlightedImage = emptyImage self.chatMessageBackgroundIncomingMergedTopMaskImage = emptyImage - self.chatMessageBackgroundIncomingMergedTopImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedTopOutlineImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMergedTopImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedTopOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) self.chatMessageBackgroundIncomingMergedTopHighlightedImage = emptyImage self.chatMessageBackgroundIncomingMergedTopSideMaskImage = emptyImage self.chatMessageBackgroundIncomingMergedTopSideImage = emptyImage self.chatMessageBackgroundIncomingMergedTopSideOutlineImage = emptyImage self.chatMessageBackgroundIncomingMergedTopSideHighlightedImage = emptyImage self.chatMessageBackgroundIncomingMergedBottomMaskImage = emptyImage - self.chatMessageBackgroundIncomingMergedBottomImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedBottomOutlineImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMergedBottomImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedBottomOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) self.chatMessageBackgroundIncomingMergedBottomHighlightedImage = emptyImage self.chatMessageBackgroundIncomingMergedBothMaskImage = emptyImage self.chatMessageBackgroundIncomingMergedBothImage = emptyImage @@ -247,21 +250,21 @@ public final class PrincipalThemeEssentialGraphics { self.chatMessageBackgroundIncomingMergedSideOutlineImage = emptyImage self.chatMessageBackgroundIncomingMergedSideHighlightedImage = emptyImage self.chatMessageBackgroundOutgoingHighlightedImage = emptyImage - self.chatMessageBackgroundOutgoingMergedTopMaskImage = messageBubbleImage(incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .top(side: false), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedTopImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedTopOutlineImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedTopMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .top(side: false), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedTopImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedTopOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) self.chatMessageBackgroundOutgoingMergedTopHighlightedImage = emptyImage self.chatMessageBackgroundOutgoingMergedTopSideMaskImage = emptyImage self.chatMessageBackgroundOutgoingMergedTopSideImage = emptyImage self.chatMessageBackgroundOutgoingMergedTopSideOutlineImage = emptyImage self.chatMessageBackgroundOutgoingMergedTopSideHighlightedImage = emptyImage - self.chatMessageBackgroundOutgoingMergedBottomMaskImage = messageBubbleImage(incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .bottom, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedBottomImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedBottomOutlineImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedBottomMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .bottom, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedBottomImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedBottomOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) self.chatMessageBackgroundOutgoingMergedBottomHighlightedImage = emptyImage - self.chatMessageBackgroundOutgoingMergedBothMaskImage = messageBubbleImage(incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .both, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedBothImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedBothOutlineImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedBothMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .both, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedBothImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedBothOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) self.chatMessageBackgroundOutgoingMergedBothHighlightedImage = emptyImage self.chatMessageBackgroundOutgoingMergedSideMaskImage = emptyImage self.chatMessageBackgroundOutgoingMergedSideImage = emptyImage @@ -288,56 +291,56 @@ public final class PrincipalThemeEssentialGraphics { self.radialIndicatorFileIconIncoming = emptyImage self.radialIndicatorFileIconOutgoing = emptyImage } else { - self.chatMessageBackgroundIncomingMaskImage = messageBubbleImage(incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .none, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundIncomingImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingOutlineImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundIncomingHighlightedImage = messageBubbleImage(incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedTopMaskImage = messageBubbleImage(incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .top(side: false), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedTopImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedTopOutlineImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundIncomingMergedTopHighlightedImage = messageBubbleImage(incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedTopSideMaskImage = messageBubbleImage(incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .top(side: true), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedTopSideImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedTopSideOutlineImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundIncomingMergedTopSideHighlightedImage = messageBubbleImage(incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedBottomMaskImage = messageBubbleImage(incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .bottom, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedBottomImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedBottomOutlineImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundIncomingMergedBottomHighlightedImage = messageBubbleImage(incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedBothMaskImage = messageBubbleImage(incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .both, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedBothImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedBothOutlineImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundIncomingMergedBothHighlightedImage = messageBubbleImage(incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .none, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) + self.chatMessageBackgroundIncomingImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedTopMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .top(side: false), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedTopImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedTopOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMergedTopHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedTopSideMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .top(side: true), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedTopSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedTopSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMergedTopSideHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedBottomMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .bottom, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedBottomImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedBottomOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMergedBottomHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedBothMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .both, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedBothImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedBothOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMergedBothHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingMaskImage = messageBubbleImage(incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .none, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundOutgoingImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingOutlineImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundOutgoingHighlightedImage = messageBubbleImage(incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedTopMaskImage = messageBubbleImage(incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .top(side: false), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedTopImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedTopOutlineImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundOutgoingMergedTopHighlightedImage = messageBubbleImage(incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedTopSideMaskImage = messageBubbleImage(incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .top(side: true), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedTopSideImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedTopSideOutlineImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundOutgoingMergedTopSideHighlightedImage = messageBubbleImage(incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedBottomMaskImage = messageBubbleImage(incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .bottom, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedBottomImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedBottomOutlineImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundOutgoingMergedBottomHighlightedImage = messageBubbleImage(incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedBothMaskImage = messageBubbleImage(incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .both, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedBothImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedBothOutlineImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundOutgoingMergedBothHighlightedImage = messageBubbleImage(incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .none, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) + self.chatMessageBackgroundOutgoingImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedTopMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .top(side: false), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedTopImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedTopOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedTopHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedTopSideMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .top(side: true), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedTopSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedTopSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedTopSideHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedBottomMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .bottom, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedBottomImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedBottomOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedBottomHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedBothMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .both, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedBothImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedBothOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedBothHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedSideMaskImage = messageBubbleImage(incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .side, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedSideImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedSideOutlineImage = messageBubbleImage(incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundOutgoingMergedSideMaskImage = messageBubbleImage(incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .side, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedSideImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedSideOutlineImage = messageBubbleImage(incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundIncomingMergedSideHighlightedImage = messageBubbleImage(incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedSideHighlightedImage = messageBubbleImage(incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedSideMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .side, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedSideMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .side, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMergedSideHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedSideHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) self.checkBubbleFullImage = generateCheckImage(partial: false, color: theme.message.outgoingCheckColor, width: 11.0)! self.checkBubblePartialImage = generateCheckImage(partial: true, color: theme.message.outgoingCheckColor, width: 11.0)! diff --git a/submodules/TelegramPresentationData/Sources/PresentationsResourceCache.swift b/submodules/TelegramPresentationData/Sources/PresentationsResourceCache.swift index a241cbfa43..2d59cc9eec 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationsResourceCache.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationsResourceCache.swift @@ -9,6 +9,7 @@ private final class PresentationsResourceCacheHolder { private final class PresentationsResourceAnyCacheHolder { var objects: [Int32: AnyObject] = [:] + var parameterObjects: [PresentationResourceParameterKey: AnyObject] = [:] } public final class PresentationsResourceCache { @@ -68,4 +69,22 @@ public final class PresentationsResourceCache { } } } + + public func parameterObject(_ key: PresentationResourceParameterKey, _ theme: PresentationTheme, _ generate: (PresentationTheme) -> AnyObject?) -> AnyObject? { + let result = self.objectCache.with { holder -> AnyObject? in + return holder.parameterObjects[key] + } + if let result = result { + return result + } else { + if let object = generate(theme) { + self.objectCache.with { holder -> Void in + holder.parameterObjects[key] = object + } + return object + } else { + return nil + } + } + } } diff --git a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift index a1b0744fad..82815c9990 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift @@ -78,9 +78,6 @@ public enum PresentationResourceKey: Int32 { case chatTitleLockIcon case chatTitleMuteIcon - case chatPrincipalThemeEssentialGraphicsWithWallpaper - case chatPrincipalThemeEssentialGraphicsWithoutWallpaper - case chatPrincipalThemeAdditionalGraphicsWithCustomWallpaper case chatPrincipalThemeAdditionalGraphicsWithDefaultWallpaper @@ -234,4 +231,8 @@ public enum PresentationResourceParameterKey: Hashable { case chatListBadgeBackgroundMention(CGFloat) case chatListBadgeBackgroundInactiveMention(CGFloat) case chatListBadgeBackgroundPinned(CGFloat) + + case chatBubbleMediaCorner(incoming: Bool, mainRadius: CGFloat, inset: CGFloat) + + case chatPrincipalThemeEssentialGraphics(hasWallpaper: Bool, bubbleCorners: PresentationChatBubbleCorners) } diff --git a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift index e3c4799b12..39e872972a 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift @@ -69,11 +69,10 @@ public struct PresentationResourcesChat { }) } - public static func principalGraphics(mediaBox: MediaBox, knockoutWallpaper: Bool, theme: PresentationTheme, wallpaper: TelegramWallpaper) -> PrincipalThemeEssentialGraphics { + public static func principalGraphics(mediaBox: MediaBox, knockoutWallpaper: Bool, theme: PresentationTheme, wallpaper: TelegramWallpaper, bubbleCorners: PresentationChatBubbleCorners) -> PrincipalThemeEssentialGraphics { let hasWallpaper = !wallpaper.isEmpty - let key: PresentationResourceKey = !hasWallpaper ? PresentationResourceKey.chatPrincipalThemeEssentialGraphicsWithoutWallpaper : PresentationResourceKey.chatPrincipalThemeEssentialGraphicsWithWallpaper - return theme.object(key.rawValue, { theme in - return PrincipalThemeEssentialGraphics(mediaBox: mediaBox, presentationTheme: theme, wallpaper: wallpaper, preview: theme.preview, knockoutMode: knockoutWallpaper) + return theme.object(PresentationResourceParameterKey.chatPrincipalThemeEssentialGraphics(hasWallpaper: hasWallpaper, bubbleCorners: bubbleCorners), { theme in + return PrincipalThemeEssentialGraphics(mediaBox: mediaBox, presentationTheme: theme, wallpaper: wallpaper, preview: theme.preview, knockoutMode: knockoutWallpaper, bubbleCorners: bubbleCorners) }) as! PrincipalThemeEssentialGraphics } @@ -950,4 +949,10 @@ public struct PresentationResourcesChat { return generateCheckImage(partial: true, color: color, width: size) }) } + + public static func chatBubbleMediaCorner(_ theme: PresentationTheme, incoming: Bool, mainRadius: CGFloat, inset: CGFloat) -> UIImage? { + return theme.image(PresentationResourceParameterKey.chatBubbleMediaCorner(incoming: incoming, mainRadius: mainRadius, inset: inset), { _ in + return mediaBubbleCornerImage(incoming: incoming, radius: mainRadius, inset: inset) + }) + } } diff --git a/submodules/TelegramUI/TelegramUI/ChatHistoryGridNode.swift b/submodules/TelegramUI/TelegramUI/ChatHistoryGridNode.swift index dfba0ca7ad..34f88f5cd1 100644 --- a/submodules/TelegramUI/TelegramUI/ChatHistoryGridNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatHistoryGridNode.swift @@ -251,7 +251,7 @@ public final class ChatHistoryGridNode: GridNode, ChatHistoryNode { self.chatPresentationDataPromise.set(context.sharedContext.presentationData |> map { presentationData in - return ChatPresentationData(theme: ChatPresentationThemeData(theme: presentationData.theme, wallpaper: presentationData.chatWallpaper), fontSize: presentationData.chatFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations, largeEmoji: presentationData.largeEmoji) + return ChatPresentationData(theme: ChatPresentationThemeData(theme: presentationData.theme, wallpaper: presentationData.chatWallpaper), fontSize: presentationData.chatFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations, largeEmoji: presentationData.largeEmoji, chatBubbleCorners: presentationData.chatBubbleCorners) }) self.floatingSections = true diff --git a/submodules/TelegramUI/TelegramUI/ChatHistoryListNode.swift b/submodules/TelegramUI/TelegramUI/ChatHistoryListNode.swift index ab032691e6..9e562d29e0 100644 --- a/submodules/TelegramUI/TelegramUI/ChatHistoryListNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatHistoryListNode.swift @@ -505,7 +505,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { self.mode = mode let presentationData = context.sharedContext.currentPresentationData.with { $0 } - self.currentPresentationData = ChatPresentationData(theme: ChatPresentationThemeData(theme: presentationData.theme, wallpaper: presentationData.chatWallpaper), fontSize: presentationData.chatFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations, largeEmoji: presentationData.largeEmoji, animatedEmojiScale: 1.0) + self.currentPresentationData = ChatPresentationData(theme: ChatPresentationThemeData(theme: presentationData.theme, wallpaper: presentationData.chatWallpaper), fontSize: presentationData.chatFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations, largeEmoji: presentationData.largeEmoji, chatBubbleCorners: presentationData.chatBubbleCorners, animatedEmojiScale: 1.0) self.chatPresentationDataPromise = Promise(self.currentPresentationData) @@ -880,7 +880,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { if previousTheme !== presentationData.theme || previousStrings !== presentationData.strings || previousWallpaper != presentationData.chatWallpaper || previousDisableAnimations != presentationData.disableAnimations || previousAnimatedEmojiScale != animatedEmojiConfig.scale { let themeData = ChatPresentationThemeData(theme: presentationData.theme, wallpaper: presentationData.chatWallpaper) - let chatPresentationData = ChatPresentationData(theme: themeData, fontSize: presentationData.chatFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations, largeEmoji: presentationData.largeEmoji, animatedEmojiScale: animatedEmojiConfig.scale) + let chatPresentationData = ChatPresentationData(theme: themeData, fontSize: presentationData.chatFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations, largeEmoji: presentationData.largeEmoji, chatBubbleCorners: presentationData.chatBubbleCorners, animatedEmojiScale: animatedEmojiConfig.scale) strongSelf.currentPresentationData = chatPresentationData strongSelf.dynamicBounceEnabled = !presentationData.disableAnimations diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift index 0cbef84d24..3fecaf1419 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift @@ -349,7 +349,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { let currentItem = self.item return { item, params, mergedTop, mergedBottom, dateHeaderAtBottom in - let layoutConstants = chatMessageItemLayoutConstants(layoutConstants, params: params) + let layoutConstants = chatMessageItemLayoutConstants(layoutConstants, params: params, presentationData: item.presentationData) let incoming = item.message.effectivelyIncoming(item.context.account.peerId) var imageSize: CGSize = CGSize(width: 200.0, height: 200.0) var isEmoji = false diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageBackground.swift b/submodules/TelegramUI/TelegramUI/ChatMessageBackground.swift index a24df24f77..09ab5933d4 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageBackground.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageBackground.swift @@ -82,8 +82,8 @@ class ChatMessageBackground: ASDisplayNode { super.init() self.isUserInteractionEnabled = false - self.addSubnode(self.outlineImageNode) self.addSubnode(self.imageNode) + self.addSubnode(self.outlineImageNode) } func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) { diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleBackdrop.swift b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleBackdrop.swift index 7da5d38987..1f0b4a71ad 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleBackdrop.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleBackdrop.swift @@ -91,7 +91,7 @@ final class ChatMessageBubbleBackdrop: ASDisplayNode { } func setType(type: ChatMessageBackgroundType, theme: ChatPresentationThemeData, mediaBox: MediaBox, essentialGraphics: PrincipalThemeEssentialGraphics, maskMode: Bool) { - if self.currentType != type || self.theme != theme || self.currentMaskMode != maskMode { + if self.currentType != type || self.theme != theme || self.currentMaskMode != maskMode || self.essentialGraphics !== essentialGraphics { self.currentType = type self.theme = theme self.essentialGraphics = essentialGraphics diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleContentCalclulateImageCorners.swift b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleContentCalclulateImageCorners.swift index f3c7671062..bb22c33754 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleContentCalclulateImageCorners.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleContentCalclulateImageCorners.swift @@ -1,8 +1,9 @@ import Foundation import UIKit import Display +import TelegramPresentationData -func chatMessageBubbleImageContentCorners(relativeContentPosition position: ChatMessageBubbleContentPosition, normalRadius: CGFloat, mergedRadius: CGFloat, mergedWithAnotherContentRadius: CGFloat) -> ImageCorners { +func chatMessageBubbleImageContentCorners(relativeContentPosition position: ChatMessageBubbleContentPosition, normalRadius: CGFloat, mergedRadius: CGFloat, mergedWithAnotherContentRadius: CGFloat, layoutConstants: ChatMessageItemLayoutConstants, chatPresentationData: ChatPresentationData) -> ImageCorners { let topLeftCorner: ImageCorner let topRightCorner: ImageCorner @@ -55,13 +56,33 @@ func chatMessageBubbleImageContentCorners(relativeContentPosition position: Chat bottomLeftCorner = .Corner(mergedRadius) bottomRightCorner = .Corner(normalRadius) case let .None(status): + let bubbleInsets: UIEdgeInsets + if case .color = chatPresentationData.theme.wallpaper { + let colors: PresentationThemeBubbleColorComponents + switch status { + case .Incoming: + colors = chatPresentationData.theme.theme.chat.message.incoming.bubble.withoutWallpaper + case .Outgoing: + colors = chatPresentationData.theme.theme.chat.message.outgoing.bubble.withoutWallpaper + case .None: + colors = chatPresentationData.theme.theme.chat.message.incoming.bubble.withoutWallpaper + } + if colors.fill == colors.stroke || colors.stroke.alpha.isZero { + bubbleInsets = UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0) + } else { + bubbleInsets = layoutConstants.bubble.strokeInsets + } + } else { + bubbleInsets = layoutConstants.image.bubbleInsets + } + switch status { case .Incoming: - bottomLeftCorner = .Tail(normalRadius, true) + bottomLeftCorner = .Tail(normalRadius, PresentationResourcesChat.chatBubbleMediaCorner(chatPresentationData.theme.theme, incoming: true, mainRadius: normalRadius, inset: max(0.0, bubbleInsets.left - 1.0))!) bottomRightCorner = .Corner(normalRadius) case .Outgoing: bottomLeftCorner = .Corner(normalRadius) - bottomRightCorner = .Tail(normalRadius, true) + bottomRightCorner = .Tail(normalRadius, PresentationResourcesChat.chatBubbleMediaCorner(chatPresentationData.theme.theme, incoming: false, mainRadius: normalRadius, inset: max(0.0, bubbleInsets.right - 1.0))!) case .None: bottomLeftCorner = .Corner(normalRadius) bottomRightCorner = .Corner(normalRadius) @@ -75,7 +96,20 @@ func chatMessageBubbleImageContentCorners(relativeContentPosition position: Chat switch position.bottomLeft { case let .none(tail): if tail { - bottomLeftCorner = .Tail(normalRadius, true) + let bubbleInsets: UIEdgeInsets + if case .color = chatPresentationData.theme.wallpaper { + let colors: PresentationThemeBubbleColorComponents + colors = chatPresentationData.theme.theme.chat.message.incoming.bubble.withoutWallpaper + if colors.fill == colors.stroke || colors.stroke.alpha.isZero { + bubbleInsets = UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0) + } else { + bubbleInsets = layoutConstants.bubble.strokeInsets + } + } else { + bubbleInsets = layoutConstants.image.bubbleInsets + } + + bottomLeftCorner = .Tail(normalRadius, PresentationResourcesChat.chatBubbleMediaCorner(chatPresentationData.theme.theme, incoming: true, mainRadius: normalRadius, inset: max(0.0, bubbleInsets.left - 1.0))!) } else { bottomLeftCorner = .Corner(normalRadius) } @@ -85,7 +119,19 @@ func chatMessageBubbleImageContentCorners(relativeContentPosition position: Chat switch position.bottomRight { case let .none(tail): if tail { - bottomRightCorner = .Tail(normalRadius, true) + let bubbleInsets: UIEdgeInsets + if case .color = chatPresentationData.theme.wallpaper { + let colors: PresentationThemeBubbleColorComponents + colors = chatPresentationData.theme.theme.chat.message.outgoing.bubble.withoutWallpaper + if colors.fill == colors.stroke || colors.stroke.alpha.isZero { + bubbleInsets = UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0) + } else { + bubbleInsets = layoutConstants.bubble.strokeInsets + } + } else { + bubbleInsets = layoutConstants.image.bubbleInsets + } + bottomRightCorner = .Tail(normalRadius, PresentationResourcesChat.chatBubbleMediaCorner(chatPresentationData.theme.theme, incoming: false, mainRadius: normalRadius, inset: max(0.0, bubbleInsets.right - 1.0))!) } else { bottomRightCorner = .Corner(normalRadius) } diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift index a507081fd5..406e3a59f5 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift @@ -615,7 +615,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode let weakSelf = Weak(self) return { item, params, mergedTop, mergedBottom, dateHeaderAtBottom in - let layoutConstants = chatMessageItemLayoutConstants(layoutConstants, params: params) + let layoutConstants = chatMessageItemLayoutConstants(layoutConstants, params: params, presentationData: item.presentationData) return ChatMessageBubbleItemNode.beginLayout(selfReference: weakSelf, item, params, mergedTop, mergedBottom, dateHeaderAtBottom, currentContentClassesPropertiesAndLayouts: currentContentClassesPropertiesAndLayouts, authorNameLayout: authorNameLayout, @@ -1546,7 +1546,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode let layout = ListViewItemNodeLayout(contentSize: layoutSize, insets: layoutInsets) - let graphics = PresentationResourcesChat.principalGraphics(mediaBox: item.context.account.postbox.mediaBox, knockoutWallpaper: item.context.sharedContext.immediateExperimentalUISettings.knockoutWallpaper, theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) + let graphics = PresentationResourcesChat.principalGraphics(mediaBox: item.context.account.postbox.mediaBox, knockoutWallpaper: item.context.sharedContext.immediateExperimentalUISettings.knockoutWallpaper, theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper, bubbleCorners: item.presentationData.chatBubbleCorners) var updatedMergedTop = mergedBottom var updatedMergedBottom = mergedTop @@ -2769,7 +2769,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode if self.highlightedState != highlighted { self.highlightedState = highlighted if let backgroundType = self.backgroundType { - let graphics = PresentationResourcesChat.principalGraphics(mediaBox: item.context.account.postbox.mediaBox, knockoutWallpaper: item.context.sharedContext.immediateExperimentalUISettings.knockoutWallpaper, theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) + let graphics = PresentationResourcesChat.principalGraphics(mediaBox: item.context.account.postbox.mediaBox, knockoutWallpaper: item.context.sharedContext.immediateExperimentalUISettings.knockoutWallpaper, theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper, bubbleCorners: item.presentationData.chatBubbleCorners) let hasWallpaper = item.presentationData.theme.wallpaper.hasWallpaper self.backgroundNode.setType(type: backgroundType, highlighted: highlighted, graphics: graphics, maskMode: self.contextSourceNode.isExtractedToContextPreview, hasWallpaper: hasWallpaper, transition: animated ? .animated(duration: 0.3, curve: .easeInOut) : .immediate) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageDateAndStatusNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageDateAndStatusNode.swift index 12b8e635f9..114cebebbd 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageDateAndStatusNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageDateAndStatusNode.swift @@ -187,7 +187,7 @@ class ChatMessageDateAndStatusNode: ASDisplayNode { let themeUpdated = presentationData.theme != currentTheme || type != currentType - let graphics = PresentationResourcesChat.principalGraphics(mediaBox: context.account.postbox.mediaBox, knockoutWallpaper: context.sharedContext.immediateExperimentalUISettings.knockoutWallpaper, theme: presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper) + let graphics = PresentationResourcesChat.principalGraphics(mediaBox: context.account.postbox.mediaBox, knockoutWallpaper: context.sharedContext.immediateExperimentalUISettings.knockoutWallpaper, theme: presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper, bubbleCorners: presentationData.chatBubbleCorners) let isDefaultWallpaper = serviceMessageColorHasDefaultWallpaper(presentationData.theme.wallpaper) let offset: CGFloat = -UIScreenPixel diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageDateHeader.swift b/submodules/TelegramUI/TelegramUI/ChatMessageDateHeader.swift index 45efafcf67..97640a4d64 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageDateHeader.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageDateHeader.swift @@ -161,7 +161,7 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode { self.transform = CATransform3DMakeRotation(CGFloat.pi, 0.0, 0.0, 1.0) - let graphics = PresentationResourcesChat.principalGraphics(mediaBox: context.account.postbox.mediaBox, knockoutWallpaper: context.sharedContext.immediateExperimentalUISettings.knockoutWallpaper, theme: presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper) + let graphics = PresentationResourcesChat.principalGraphics(mediaBox: context.account.postbox.mediaBox, knockoutWallpaper: context.sharedContext.immediateExperimentalUISettings.knockoutWallpaper, theme: presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper, bubbleCorners: presentationData.chatBubbleCorners) self.backgroundNode.image = graphics.dateStaticBackground self.stickBackgroundNode.image = graphics.dateFloatingBackground @@ -190,7 +190,7 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode { let previousPresentationData = self.presentationData self.presentationData = presentationData - let graphics = PresentationResourcesChat.principalGraphics(mediaBox: context.account.postbox.mediaBox, knockoutWallpaper: context.sharedContext.immediateExperimentalUISettings.knockoutWallpaper, theme: presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper) + let graphics = PresentationResourcesChat.principalGraphics(mediaBox: context.account.postbox.mediaBox, knockoutWallpaper: context.sharedContext.immediateExperimentalUISettings.knockoutWallpaper, theme: presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper, bubbleCorners: presentationData.chatBubbleCorners) self.backgroundNode.image = graphics.dateStaticBackground self.stickBackgroundNode.image = graphics.dateFloatingBackground diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageInstantVideoItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageInstantVideoItemNode.swift index 77dbaa3cbe..c1f5d88cec 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageInstantVideoItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageInstantVideoItemNode.swift @@ -115,7 +115,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView { let currentForwardInfo = self.appliedForwardInfo return { item, params, mergedTop, mergedBottom, dateHeaderAtBottom in - let layoutConstants = chatMessageItemLayoutConstants(layoutConstants, params: params) + let layoutConstants = chatMessageItemLayoutConstants(layoutConstants, params: params, presentationData: item.presentationData) let incoming = item.message.effectivelyIncoming(item.context.account.peerId) let avatarInset: CGFloat diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveFileNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveFileNode.swift index 1a3e3d599b..664a47f472 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveFileNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveFileNode.swift @@ -439,7 +439,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { if hasThumbnail { fileIconImage = nil } else { - let principalGraphics = PresentationResourcesChat.principalGraphics(mediaBox: context.account.postbox.mediaBox, knockoutWallpaper: context.sharedContext.immediateExperimentalUISettings.knockoutWallpaper, theme: presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper) + let principalGraphics = PresentationResourcesChat.principalGraphics(mediaBox: context.account.postbox.mediaBox, knockoutWallpaper: context.sharedContext.immediateExperimentalUISettings.knockoutWallpaper, theme: presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper, bubbleCorners: presentationData.chatBubbleCorners) fileIconImage = incoming ? principalGraphics.radialIndicatorFileIconIncoming : principalGraphics.radialIndicatorFileIconOutgoing } diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageItemView.swift b/submodules/TelegramUI/TelegramUI/ChatMessageItemView.swift index 11450a6aa4..5377241b60 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageItemView.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageItemView.swift @@ -11,9 +11,9 @@ import ContextUI import ChatListUI struct ChatMessageItemWidthFill { - let compactInset: CGFloat - let compactWidthBoundary: CGFloat - let freeMaximumFillFactor: CGFloat + var compactInset: CGFloat + var compactWidthBoundary: CGFloat + var freeMaximumFillFactor: CGFloat func widthFor(_ width: CGFloat) -> CGFloat { if width <= self.compactWidthBoundary { @@ -25,68 +25,68 @@ struct ChatMessageItemWidthFill { } struct ChatMessageItemBubbleLayoutConstants { - let edgeInset: CGFloat - let defaultSpacing: CGFloat - let mergedSpacing: CGFloat - let maximumWidthFill: ChatMessageItemWidthFill - let minimumSize: CGSize - let contentInsets: UIEdgeInsets - let borderInset: CGFloat - let strokeInsets: UIEdgeInsets + var edgeInset: CGFloat + var defaultSpacing: CGFloat + var mergedSpacing: CGFloat + var maximumWidthFill: ChatMessageItemWidthFill + var minimumSize: CGSize + var contentInsets: UIEdgeInsets + var borderInset: CGFloat + var strokeInsets: UIEdgeInsets } struct ChatMessageItemTextLayoutConstants { - let bubbleInsets: UIEdgeInsets + var bubbleInsets: UIEdgeInsets } struct ChatMessageItemImageLayoutConstants { - let bubbleInsets: UIEdgeInsets - let statusInsets: UIEdgeInsets - let defaultCornerRadius: CGFloat - let mergedCornerRadius: CGFloat - let contentMergedCornerRadius: CGFloat - let maxDimensions: CGSize - let minDimensions: CGSize + var bubbleInsets: UIEdgeInsets + var statusInsets: UIEdgeInsets + var defaultCornerRadius: CGFloat + var mergedCornerRadius: CGFloat + var contentMergedCornerRadius: CGFloat + var maxDimensions: CGSize + var minDimensions: CGSize } struct ChatMessageItemVideoLayoutConstants { - let maxHorizontalHeight: CGFloat - let maxVerticalHeight: CGFloat + var maxHorizontalHeight: CGFloat + var maxVerticalHeight: CGFloat } struct ChatMessageItemInstantVideoConstants { - let insets: UIEdgeInsets - let dimensions: CGSize + var insets: UIEdgeInsets + var dimensions: CGSize } struct ChatMessageItemFileLayoutConstants { - let bubbleInsets: UIEdgeInsets + var bubbleInsets: UIEdgeInsets } struct ChatMessageItemWallpaperLayoutConstants { - let maxTextWidth: CGFloat + var maxTextWidth: CGFloat } struct ChatMessageItemLayoutConstants { - let avatarDiameter: CGFloat - let timestampHeaderHeight: CGFloat + var avatarDiameter: CGFloat + var timestampHeaderHeight: CGFloat - let bubble: ChatMessageItemBubbleLayoutConstants - let image: ChatMessageItemImageLayoutConstants - let video: ChatMessageItemVideoLayoutConstants - let text: ChatMessageItemTextLayoutConstants - let file: ChatMessageItemFileLayoutConstants - let instantVideo: ChatMessageItemInstantVideoConstants - let wallpapers: ChatMessageItemWallpaperLayoutConstants + var bubble: ChatMessageItemBubbleLayoutConstants + var image: ChatMessageItemImageLayoutConstants + var video: ChatMessageItemVideoLayoutConstants + var text: ChatMessageItemTextLayoutConstants + var file: ChatMessageItemFileLayoutConstants + var instantVideo: ChatMessageItemInstantVideoConstants + var wallpapers: ChatMessageItemWallpaperLayoutConstants static var `default`: ChatMessageItemLayoutConstants { return self.compact } fileprivate static var compact: ChatMessageItemLayoutConstants { - let bubble = ChatMessageItemBubbleLayoutConstants(edgeInset: 4.0, defaultSpacing: 2.0 + UIScreenPixel, mergedSpacing: 1.0, maximumWidthFill: ChatMessageItemWidthFill(compactInset: 36.0, compactWidthBoundary: 500.0, freeMaximumFillFactor: 0.85), minimumSize: CGSize(width: 40.0, height: 35.0), contentInsets: UIEdgeInsets(top: 0.0, left: 6.0, bottom: 0.0, right: 0.0), borderInset: UIScreenPixel, strokeInsets: UIEdgeInsets(top: 1.0 - UIScreenPixel, left: 1.0 - UIScreenPixel, bottom: 1.0 - UIScreenPixel, right: 1.0 - UIScreenPixel)) + let bubble = ChatMessageItemBubbleLayoutConstants(edgeInset: 4.0, defaultSpacing: 2.0 + UIScreenPixel, mergedSpacing: 1.0, maximumWidthFill: ChatMessageItemWidthFill(compactInset: 36.0, compactWidthBoundary: 500.0, freeMaximumFillFactor: 0.85), minimumSize: CGSize(width: 40.0, height: 35.0), contentInsets: UIEdgeInsets(top: 0.0, left: 6.0, bottom: 0.0, right: 0.0), borderInset: UIScreenPixel, strokeInsets: UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0)) let text = ChatMessageItemTextLayoutConstants(bubbleInsets: UIEdgeInsets(top: 6.0 + UIScreenPixel, left: 12.0, bottom: 6.0 - UIScreenPixel, right: 12.0)) - let image = ChatMessageItemImageLayoutConstants(bubbleInsets: UIEdgeInsets(top: 1.0 + UIScreenPixel, left: 1.0 + UIScreenPixel, bottom: 1.0 + UIScreenPixel, right: 1.0 + UIScreenPixel), statusInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 6.0, right: 6.0), defaultCornerRadius: 17.0, mergedCornerRadius: 5.0, contentMergedCornerRadius: 0.0, maxDimensions: CGSize(width: 300.0, height: 300.0), minDimensions: CGSize(width: 170.0, height: 74.0)) + let image = ChatMessageItemImageLayoutConstants(bubbleInsets: UIEdgeInsets(top: 2.0, left: 2.0, bottom: 2.0, right: 2.0), statusInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 6.0, right: 6.0), defaultCornerRadius: 16.0, mergedCornerRadius: 8.0, contentMergedCornerRadius: 0.0, maxDimensions: CGSize(width: 300.0, height: 300.0), minDimensions: CGSize(width: 170.0, height: 74.0)) let video = ChatMessageItemVideoLayoutConstants(maxHorizontalHeight: 250.0, maxVerticalHeight: 360.0) let file = ChatMessageItemFileLayoutConstants(bubbleInsets: UIEdgeInsets(top: 15.0, left: 9.0, bottom: 15.0, right: 12.0)) let instantVideo = ChatMessageItemInstantVideoConstants(insets: UIEdgeInsets(top: 4.0, left: 0.0, bottom: 4.0, right: 0.0), dimensions: CGSize(width: 212.0, height: 212.0)) @@ -98,7 +98,7 @@ struct ChatMessageItemLayoutConstants { fileprivate static var regular: ChatMessageItemLayoutConstants { let bubble = ChatMessageItemBubbleLayoutConstants(edgeInset: 4.0, defaultSpacing: 2.0 + UIScreenPixel, mergedSpacing: 1.0, maximumWidthFill: ChatMessageItemWidthFill(compactInset: 36.0, compactWidthBoundary: 500.0, freeMaximumFillFactor: 0.65), minimumSize: CGSize(width: 40.0, height: 35.0), contentInsets: UIEdgeInsets(top: 0.0, left: 6.0, bottom: 0.0, right: 0.0), borderInset: UIScreenPixel, strokeInsets: UIEdgeInsets(top: 1.0 - UIScreenPixel, left: 1.0 - UIScreenPixel, bottom: 1.0 - UIScreenPixel, right: 1.0 - UIScreenPixel)) let text = ChatMessageItemTextLayoutConstants(bubbleInsets: UIEdgeInsets(top: 6.0 + UIScreenPixel, left: 12.0, bottom: 6.0 - UIScreenPixel, right: 12.0)) - let image = ChatMessageItemImageLayoutConstants(bubbleInsets: UIEdgeInsets(top: 1.0 + UIScreenPixel, left: 1.0 + UIScreenPixel, bottom: 1.0 + UIScreenPixel, right: 1.0 + UIScreenPixel), statusInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 6.0, right: 6.0), defaultCornerRadius: 17.0, mergedCornerRadius: 5.0, contentMergedCornerRadius: 5.0, maxDimensions: CGSize(width: 440.0, height: 440.0), minDimensions: CGSize(width: 170.0, height: 74.0)) + let image = ChatMessageItemImageLayoutConstants(bubbleInsets: UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0), statusInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 6.0, right: 6.0), defaultCornerRadius: 17.0, mergedCornerRadius: 5.0, contentMergedCornerRadius: 5.0, maxDimensions: CGSize(width: 440.0, height: 440.0), minDimensions: CGSize(width: 170.0, height: 74.0)) let video = ChatMessageItemVideoLayoutConstants(maxHorizontalHeight: 250.0, maxVerticalHeight: 360.0) let file = ChatMessageItemFileLayoutConstants(bubbleInsets: UIEdgeInsets(top: 15.0, left: 9.0, bottom: 15.0, right: 12.0)) let instantVideo = ChatMessageItemInstantVideoConstants(insets: UIEdgeInsets(top: 4.0, left: 0.0, bottom: 4.0, right: 0.0), dimensions: CGSize(width: 212.0, height: 212.0)) @@ -108,12 +108,24 @@ struct ChatMessageItemLayoutConstants { } } -func chatMessageItemLayoutConstants(_ constants: (ChatMessageItemLayoutConstants, ChatMessageItemLayoutConstants), params: ListViewItemLayoutParams) -> ChatMessageItemLayoutConstants { +func chatMessageItemLayoutConstants(_ constants: (ChatMessageItemLayoutConstants, ChatMessageItemLayoutConstants), params: ListViewItemLayoutParams, presentationData: ChatPresentationData) -> ChatMessageItemLayoutConstants { + var result: ChatMessageItemLayoutConstants if params.width > 680.0 { - return constants.1 + result = constants.1 } else { - return constants.0 + result = constants.0 } + result.image.defaultCornerRadius = presentationData.chatBubbleCorners.mainRadius + result.image.mergedCornerRadius = presentationData.chatBubbleCorners.mergeBubbleCorners ? presentationData.chatBubbleCorners.auxiliaryRadius : presentationData.chatBubbleCorners.mainRadius + let minRadius: CGFloat = 4.0 + let maxRadius: CGFloat = 16.0 + let radiusTransition = (presentationData.chatBubbleCorners.mainRadius - minRadius) / (maxRadius - minRadius) + let minInset: CGFloat = 9.0 + let maxInset: CGFloat = 12.0 + let textInset: CGFloat = min(maxInset, ceil(maxInset * radiusTransition + minInset * (1.0 - radiusTransition))) + result.text.bubbleInsets.left = textInset + result.text.bubbleInsets.right = textInset + return result } enum ChatMessageItemBottomNeighbor { diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageMapBubbleContentNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageMapBubbleContentNode.swift index f0602bea07..178685165d 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageMapBubbleContentNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageMapBubbleContentNode.swift @@ -159,13 +159,13 @@ class ChatMessageMapBubbleContentNode: ChatMessageBubbleContentNode { if case let .linear(top, _) = position { relativePosition = .linear(top: top, bottom: ChatMessageBubbleRelativePosition.Neighbour) } - imageCorners = chatMessageBubbleImageContentCorners(relativeContentPosition: relativePosition, normalRadius: layoutConstants.image.defaultCornerRadius, mergedRadius: layoutConstants.image.mergedCornerRadius, mergedWithAnotherContentRadius: layoutConstants.image.contentMergedCornerRadius) + imageCorners = chatMessageBubbleImageContentCorners(relativeContentPosition: relativePosition, normalRadius: layoutConstants.image.defaultCornerRadius, mergedRadius: layoutConstants.image.mergedCornerRadius, mergedWithAnotherContentRadius: layoutConstants.image.contentMergedCornerRadius, layoutConstants: layoutConstants, chatPresentationData: item.presentationData) maxTextWidth = constrainedSize.width - bubbleInsets.left + bubbleInsets.right - layoutConstants.text.bubbleInsets.left - layoutConstants.text.bubbleInsets.right - 40.0 } else { maxTextWidth = constrainedSize.width - imageSize.width - bubbleInsets.left + bubbleInsets.right - layoutConstants.text.bubbleInsets.right - imageCorners = chatMessageBubbleImageContentCorners(relativeContentPosition: position, normalRadius: layoutConstants.image.defaultCornerRadius, mergedRadius: layoutConstants.image.mergedCornerRadius, mergedWithAnotherContentRadius: layoutConstants.image.contentMergedCornerRadius) + imageCorners = chatMessageBubbleImageContentCorners(relativeContentPosition: position, normalRadius: layoutConstants.image.defaultCornerRadius, mergedRadius: layoutConstants.image.mergedCornerRadius, mergedWithAnotherContentRadius: layoutConstants.image.contentMergedCornerRadius, layoutConstants: layoutConstants, chatPresentationData: item.presentationData) } let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: max(1.0, maxTextWidth), height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageMediaBubbleContentNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageMediaBubbleContentNode.swift index c1f5213022..4566abadca 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageMediaBubbleContentNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageMediaBubbleContentNode.swift @@ -128,8 +128,8 @@ class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode { } else { colors = item.presentationData.theme.theme.chat.message.outgoing.bubble.withoutWallpaper } - if colors.fill == colors.stroke { - bubbleInsets = UIEdgeInsets() + if colors.fill == colors.stroke || colors.stroke.alpha.isZero { + bubbleInsets = UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0) } else { bubbleInsets = layoutConstants.bubble.strokeInsets } @@ -162,7 +162,7 @@ class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode { updatedPosition = .linear(top: top, bottom: .Neighbour) } - let imageCorners = chatMessageBubbleImageContentCorners(relativeContentPosition: updatedPosition, normalRadius: layoutConstants.image.defaultCornerRadius, mergedRadius: layoutConstants.image.mergedCornerRadius, mergedWithAnotherContentRadius: layoutConstants.image.contentMergedCornerRadius) + let imageCorners = chatMessageBubbleImageContentCorners(relativeContentPosition: updatedPosition, normalRadius: layoutConstants.image.defaultCornerRadius, mergedRadius: layoutConstants.image.mergedCornerRadius, mergedWithAnotherContentRadius: layoutConstants.image.contentMergedCornerRadius, layoutConstants: layoutConstants, chatPresentationData: item.presentationData) let (refinedWidth, finishLayout) = refineLayout(CGSize(width: constrainedSize.width - bubbleInsets.left - bubbleInsets.right, height: constrainedSize.height), automaticPlayback, wideLayout, imageCorners) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageStickerItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageStickerItemNode.swift index d9c2e3c55d..7a0f4ff8c8 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageStickerItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageStickerItemNode.swift @@ -143,7 +143,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { let currentItem = self.item return { item, params, mergedTop, mergedBottom, dateHeaderAtBottom in - let layoutConstants = chatMessageItemLayoutConstants(layoutConstants, params: params) + let layoutConstants = chatMessageItemLayoutConstants(layoutConstants, params: params, presentationData: item.presentationData) let incoming = item.message.effectivelyIncoming(item.context.account.peerId) var imageSize: CGSize = CGSize(width: 100.0, height: 100.0) if let telegramFile = telegramFile { diff --git a/submodules/TelegramUI/TelegramUI/ChatPresentationData.swift b/submodules/TelegramUI/TelegramUI/ChatPresentationData.swift index 0927b45710..253882e904 100644 --- a/submodules/TelegramUI/TelegramUI/ChatPresentationData.swift +++ b/submodules/TelegramUI/TelegramUI/ChatPresentationData.swift @@ -28,6 +28,7 @@ public final class ChatPresentationData { let nameDisplayOrder: PresentationPersonNameOrder let disableAnimations: Bool let largeEmoji: Bool + let chatBubbleCorners: PresentationChatBubbleCorners let animatedEmojiScale: CGFloat let isPreview: Bool @@ -39,13 +40,14 @@ public final class ChatPresentationData { let messageFixedFont: UIFont let messageBlockQuoteFont: UIFont - init(theme: ChatPresentationThemeData, fontSize: PresentationFontSize, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, disableAnimations: Bool, largeEmoji: Bool, animatedEmojiScale: CGFloat = 1.0, isPreview: Bool = false) { + init(theme: ChatPresentationThemeData, fontSize: PresentationFontSize, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, disableAnimations: Bool, largeEmoji: Bool, chatBubbleCorners: PresentationChatBubbleCorners, animatedEmojiScale: CGFloat = 1.0, isPreview: Bool = false) { self.theme = theme self.fontSize = fontSize self.strings = strings self.dateTimeFormat = dateTimeFormat self.nameDisplayOrder = nameDisplayOrder self.disableAnimations = disableAnimations + self.chatBubbleCorners = chatBubbleCorners self.largeEmoji = largeEmoji self.isPreview = isPreview diff --git a/submodules/TelegramUI/TelegramUI/ChatRecentActionsControllerNode.swift b/submodules/TelegramUI/TelegramUI/ChatRecentActionsControllerNode.swift index cf5344ad57..2a2b602ab9 100644 --- a/submodules/TelegramUI/TelegramUI/ChatRecentActionsControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatRecentActionsControllerNode.swift @@ -113,7 +113,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { self.state = ChatRecentActionsControllerState(chatWallpaper: self.presentationData.chatWallpaper, theme: self.presentationData.theme, strings: self.presentationData.strings, fontSize: self.presentationData.chatFontSize) - self.chatPresentationDataPromise = Promise(ChatPresentationData(theme: ChatPresentationThemeData(theme: self.presentationData.theme, wallpaper: self.presentationData.chatWallpaper), fontSize: self.presentationData.chatFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations, largeEmoji: self.presentationData.largeEmoji)) + self.chatPresentationDataPromise = Promise(ChatPresentationData(theme: ChatPresentationThemeData(theme: self.presentationData.theme, wallpaper: self.presentationData.chatWallpaper), fontSize: self.presentationData.chatFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations, largeEmoji: self.presentationData.largeEmoji, chatBubbleCorners: self.presentationData.chatBubbleCorners)) self.eventLogContext = ChannelAdminEventLogContext(postbox: self.context.account.postbox, network: self.context.account.network, peerId: self.peer.id) @@ -496,7 +496,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { |> deliverOnMainQueue).start(next: { [weak self] presentationData in if let strongSelf = self { strongSelf.presentationData = presentationData - strongSelf.chatPresentationDataPromise.set(.single(ChatPresentationData(theme: ChatPresentationThemeData(theme: presentationData.theme, wallpaper: presentationData.chatWallpaper), fontSize: presentationData.chatFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations, largeEmoji: presentationData.largeEmoji))) + strongSelf.chatPresentationDataPromise.set(.single(ChatPresentationData(theme: ChatPresentationThemeData(theme: presentationData.theme, wallpaper: presentationData.chatWallpaper), fontSize: presentationData.chatFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations, largeEmoji: presentationData.largeEmoji, chatBubbleCorners: presentationData.chatBubbleCorners))) strongSelf.updateThemeAndStrings(theme: presentationData.theme, strings: presentationData.strings) } diff --git a/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetControllerNode.swift b/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetControllerNode.swift index b30f9e2e02..9c845b4699 100644 --- a/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetControllerNode.swift @@ -272,7 +272,10 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, self.messageBackgroundNode.contentMode = .scaleToFill let outgoing: PresentationThemeBubbleColorComponents = self.presentationData.chatWallpaper.isEmpty ? self.presentationData.theme.chat.message.outgoing.bubble.withoutWallpaper : self.presentationData.theme.chat.message.outgoing.bubble.withWallpaper - self.messageBackgroundNode.image = messageBubbleImage(incoming: false, fillColor: outgoing.gradientFill, strokeColor: outgoing.fill == outgoing.gradientFill ? outgoing.stroke : .clear, neighbors: .none, theme: self.presentationData.theme.chat, wallpaper: self.presentationData.chatWallpaper, knockout: false) + + let maxCornerRadius = self.presentationData.chatBubbleCorners.mainRadius + let minCornerRadius = self.presentationData.chatBubbleCorners.auxiliaryRadius + self.messageBackgroundNode.image = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: maxCornerRadius, incoming: false, fillColor: outgoing.gradientFill, strokeColor: outgoing.fill == outgoing.gradientFill ? outgoing.stroke : .clear, neighbors: .none, theme: self.presentationData.theme.chat, wallpaper: self.presentationData.chatWallpaper, knockout: false) self.view.addSubview(self.effectView) self.addSubnode(self.dimNode) @@ -376,7 +379,9 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, } let outgoing: PresentationThemeBubbleColorComponents = self.presentationData.chatWallpaper.isEmpty ? self.presentationData.theme.chat.message.outgoing.bubble.withoutWallpaper : self.presentationData.theme.chat.message.outgoing.bubble.withWallpaper - self.messageBackgroundNode.image = messageBubbleImage(incoming: false, fillColor: outgoing.gradientFill, strokeColor: outgoing.fill == outgoing.gradientFill ? outgoing.stroke : .clear, neighbors: .none, theme: self.presentationData.theme.chat, wallpaper: self.presentationData.chatWallpaper, knockout: false) + let maxCornerRadius = self.presentationData.chatBubbleCorners.mainRadius + let minCornerRadius = self.presentationData.chatBubbleCorners.auxiliaryRadius + self.messageBackgroundNode.image = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: maxCornerRadius, incoming: false, fillColor: outgoing.gradientFill, strokeColor: outgoing.fill == outgoing.gradientFill ? outgoing.stroke : .clear, neighbors: .none, theme: self.presentationData.theme.chat, wallpaper: self.presentationData.chatWallpaper, knockout: false) for node in self.contentNodes { node.updateTheme(presentationData.theme) diff --git a/submodules/TelegramUI/TelegramUI/Resources/PresentationStrings.mapping b/submodules/TelegramUI/TelegramUI/Resources/PresentationStrings.mapping index aab4fb144de75691c1805eb292a35ee88189e6ef..8fcfb968b659141e77ba3896905c51a987a97092 100644 GIT binary patch delta 23767 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 XZWidpbJ%dxNn&vd&BeJq>ZJbzX8$Vv delta 23793 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 Void)? = nil, clickThroughMessage: (() -> Void)? = nil) -> ListViewItem { + public func makeChatMessagePreviewItem(context: AccountContext, message: Message, theme: PresentationTheme, strings: PresentationStrings, wallpaper: TelegramWallpaper, fontSize: PresentationFontSize, chatBubbleCorners: PresentationChatBubbleCorners, dateTimeFormat: PresentationDateTimeFormat, nameOrder: PresentationPersonNameOrder, forcedResourceStatus: FileMediaResourceStatus?, tapMessage: ((Message) -> Void)? = nil, clickThroughMessage: (() -> Void)? = nil) -> ListViewItem { let controllerInteraction: ChatControllerInteraction if tapMessage != nil || clickThroughMessage != nil { controllerInteraction = ChatControllerInteraction(openMessage: { _, _ in @@ -1139,11 +1139,11 @@ public final class SharedAccountContextImpl: SharedAccountContext { controllerInteraction = defaultChatControllerInteraction } - return ChatMessageItem(presentationData: ChatPresentationData(theme: ChatPresentationThemeData(theme: theme, wallpaper: wallpaper), fontSize: fontSize, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameOrder, disableAnimations: false, largeEmoji: false, animatedEmojiScale: 1.0, isPreview: true), context: context, chatLocation: .peer(message.id.peerId), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .contact, automaticDownloadNetworkType: .cellular, isRecentActions: false, isScheduledMessages: false, contactsPeerIds: Set(), animatedEmojiStickers: [:], forcedResourceStatus: forcedResourceStatus), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes()), disableDate: true, additionalContent: nil) + return ChatMessageItem(presentationData: ChatPresentationData(theme: ChatPresentationThemeData(theme: theme, wallpaper: wallpaper), fontSize: fontSize, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameOrder, disableAnimations: false, largeEmoji: false, chatBubbleCorners: chatBubbleCorners, animatedEmojiScale: 1.0, isPreview: true), context: context, chatLocation: .peer(message.id.peerId), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .contact, automaticDownloadNetworkType: .cellular, isRecentActions: false, isScheduledMessages: false, contactsPeerIds: Set(), animatedEmojiStickers: [:], forcedResourceStatus: forcedResourceStatus), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes()), disableDate: true, additionalContent: nil) } - public func makeChatMessageDateHeaderItem(context: AccountContext, timestamp: Int32, theme: PresentationTheme, strings: PresentationStrings, wallpaper: TelegramWallpaper, fontSize: PresentationFontSize, dateTimeFormat: PresentationDateTimeFormat, nameOrder: PresentationPersonNameOrder) -> ListViewItemHeader { - return ChatMessageDateHeader(timestamp: timestamp, scheduled: false, presentationData: ChatPresentationData(theme: ChatPresentationThemeData(theme: theme, wallpaper: wallpaper), fontSize: fontSize, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameOrder, disableAnimations: false, largeEmoji: false, animatedEmojiScale: 1.0, isPreview: true), context: context) + public func makeChatMessageDateHeaderItem(context: AccountContext, timestamp: Int32, theme: PresentationTheme, strings: PresentationStrings, wallpaper: TelegramWallpaper, fontSize: PresentationFontSize, chatBubbleCorners: PresentationChatBubbleCorners, dateTimeFormat: PresentationDateTimeFormat, nameOrder: PresentationPersonNameOrder) -> ListViewItemHeader { + return ChatMessageDateHeader(timestamp: timestamp, scheduled: false, presentationData: ChatPresentationData(theme: ChatPresentationThemeData(theme: theme, wallpaper: wallpaper), fontSize: fontSize, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameOrder, disableAnimations: false, largeEmoji: false, chatBubbleCorners: chatBubbleCorners, animatedEmojiScale: 1.0, isPreview: true), context: context) } public func openWallet(context: AccountContext, walletContext: OpenWalletContext, present: @escaping (ViewController) -> Void) { diff --git a/submodules/TelegramUI/TelegramUI/ThemeUpdateManager.swift b/submodules/TelegramUI/TelegramUI/ThemeUpdateManager.swift index 3051fa73ed..2371c501a3 100644 --- a/submodules/TelegramUI/TelegramUI/ThemeUpdateManager.swift +++ b/submodules/TelegramUI/TelegramUI/ThemeUpdateManager.swift @@ -139,7 +139,7 @@ final class ThemeUpdateManagerImpl: ThemeUpdateManager { theme = updatedTheme } - return PresentationThemeSettings(theme: theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: current.themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, automaticThemeSwitchSetting: automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) + return PresentationThemeSettings(theme: theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: current.themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) }) }).start() } diff --git a/submodules/TelegramUI/TelegramUI/WallpaperUploadManager.swift b/submodules/TelegramUI/TelegramUI/WallpaperUploadManager.swift index 9f20c48e3e..0527746dd8 100644 --- a/submodules/TelegramUI/TelegramUI/WallpaperUploadManager.swift +++ b/submodules/TelegramUI/TelegramUI/WallpaperUploadManager.swift @@ -133,7 +133,7 @@ final class WallpaperUploadManagerImpl: WallpaperUploadManager { var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers themeSpecificChatWallpapers[themeReference.index] = updatedWallpaper themeSpecificChatWallpapers[coloredThemeIndex(reference: themeReference, accentColor: current.themeSpecificAccentColors[themeReference.index])] = updatedWallpaper - return PresentationThemeSettings(theme: current.theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) + return PresentationThemeSettings(theme: current.theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) })).start() } diff --git a/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift b/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift index f78a460341..ab9d7e7291 100644 --- a/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift +++ b/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift @@ -531,6 +531,32 @@ public struct PresentationThemeAccentColor: PostboxCoding, Equatable { } } +public struct PresentationChatBubbleSettings: PostboxCoding, Equatable { + public var mainRadius: Int32 + public var auxiliaryRadius: Int32 + public var mergeBubbleCorners: Bool + + public static var `default`: PresentationChatBubbleSettings = PresentationChatBubbleSettings(mainRadius: 16, auxiliaryRadius: 8, mergeBubbleCorners: true) + + public init(mainRadius: Int32, auxiliaryRadius: Int32, mergeBubbleCorners: Bool) { + self.mainRadius = mainRadius + self.auxiliaryRadius = auxiliaryRadius + self.mergeBubbleCorners = mergeBubbleCorners + } + + public init(decoder: PostboxDecoder) { + self.mainRadius = decoder.decodeInt32ForKey("mainRadius", orElse: 16) + self.auxiliaryRadius = decoder.decodeInt32ForKey("auxiliaryRadius", orElse: 8) + self.mergeBubbleCorners = decoder.decodeInt32ForKey("mergeBubbleCorners", orElse: 1) != 0 + } + + public func encode(_ encoder: PostboxEncoder) { + encoder.encodeInt32(self.mainRadius, forKey: "mainRadius") + encoder.encodeInt32(self.auxiliaryRadius, forKey: "auxiliaryRadius") + encoder.encodeInt32(self.mergeBubbleCorners ? 1 : 0, forKey: "mergeBubbleCorners") + } +} + public struct PresentationThemeSettings: PreferencesEntry { public var theme: PresentationThemeReference public var themeSpecificAccentColors: [Int64: PresentationThemeAccentColor] @@ -538,6 +564,7 @@ public struct PresentationThemeSettings: PreferencesEntry { public var useSystemFont: Bool public var fontSize: PresentationFontSize public var listsFontSize: PresentationFontSize + public var chatBubbleSettings: PresentationChatBubbleSettings public var automaticThemeSwitchSetting: AutomaticThemeSwitchSetting public var largeEmoji: Bool public var disableAnimations: Bool @@ -578,16 +605,17 @@ public struct PresentationThemeSettings: PreferencesEntry { } public static var defaultSettings: PresentationThemeSettings { - return PresentationThemeSettings(theme: .builtin(.dayClassic), themeSpecificAccentColors: [:], themeSpecificChatWallpapers: [:], useSystemFont: true, fontSize: .regular, listsFontSize: .regular, automaticThemeSwitchSetting: AutomaticThemeSwitchSetting(trigger: .system, theme: .builtin(.night)), largeEmoji: true, disableAnimations: true) + return PresentationThemeSettings(theme: .builtin(.dayClassic), themeSpecificAccentColors: [:], themeSpecificChatWallpapers: [:], useSystemFont: true, fontSize: .regular, listsFontSize: .regular, chatBubbleSettings: .default, automaticThemeSwitchSetting: AutomaticThemeSwitchSetting(trigger: .system, theme: .builtin(.night)), largeEmoji: true, disableAnimations: true) } - public init(theme: PresentationThemeReference, themeSpecificAccentColors: [Int64: PresentationThemeAccentColor], themeSpecificChatWallpapers: [Int64: TelegramWallpaper], useSystemFont: Bool, fontSize: PresentationFontSize, listsFontSize: PresentationFontSize, automaticThemeSwitchSetting: AutomaticThemeSwitchSetting, largeEmoji: Bool, disableAnimations: Bool) { + public init(theme: PresentationThemeReference, themeSpecificAccentColors: [Int64: PresentationThemeAccentColor], themeSpecificChatWallpapers: [Int64: TelegramWallpaper], useSystemFont: Bool, fontSize: PresentationFontSize, listsFontSize: PresentationFontSize, chatBubbleSettings: PresentationChatBubbleSettings, automaticThemeSwitchSetting: AutomaticThemeSwitchSetting, largeEmoji: Bool, disableAnimations: Bool) { self.theme = theme self.themeSpecificAccentColors = themeSpecificAccentColors self.themeSpecificChatWallpapers = themeSpecificChatWallpapers self.useSystemFont = useSystemFont self.fontSize = fontSize self.listsFontSize = listsFontSize + self.chatBubbleSettings = chatBubbleSettings self.automaticThemeSwitchSetting = automaticThemeSwitchSetting self.largeEmoji = largeEmoji self.disableAnimations = disableAnimations @@ -612,6 +640,7 @@ public struct PresentationThemeSettings: PreferencesEntry { let fontSize = PresentationFontSize(rawValue: decoder.decodeInt32ForKey("f", orElse: PresentationFontSize.regular.rawValue)) ?? .regular self.fontSize = fontSize self.listsFontSize = PresentationFontSize(rawValue: decoder.decodeInt32ForKey("lf", orElse: PresentationFontSize.regular.rawValue)) ?? fontSize + self.chatBubbleSettings = decoder.decodeObjectForKey("chatBubbleSettings", decoder: { PresentationChatBubbleSettings(decoder: $0) }) as? PresentationChatBubbleSettings ?? PresentationChatBubbleSettings.default self.automaticThemeSwitchSetting = (decoder.decodeObjectForKey("automaticThemeSwitchSetting", decoder: { AutomaticThemeSwitchSetting(decoder: $0) }) as? AutomaticThemeSwitchSetting) ?? AutomaticThemeSwitchSetting(trigger: .system, theme: .builtin(.night)) self.largeEmoji = decoder.decodeBoolForKey("largeEmoji", orElse: true) self.disableAnimations = decoder.decodeBoolForKey("disableAnimations", orElse: true) @@ -628,6 +657,7 @@ public struct PresentationThemeSettings: PreferencesEntry { encoder.encodeInt32(self.useSystemFont ? 1 : 0, forKey: "useSystemFont") encoder.encodeInt32(self.fontSize.rawValue, forKey: "f") encoder.encodeInt32(self.listsFontSize.rawValue, forKey: "lf") + encoder.encodeObject(self.chatBubbleSettings, forKey: "chatBubbleSettings") encoder.encodeObject(self.automaticThemeSwitchSetting, forKey: "automaticThemeSwitchSetting") encoder.encodeBool(self.largeEmoji, forKey: "largeEmoji") encoder.encodeBool(self.disableAnimations, forKey: "disableAnimations") @@ -642,39 +672,43 @@ public struct PresentationThemeSettings: PreferencesEntry { } public static func ==(lhs: PresentationThemeSettings, rhs: PresentationThemeSettings) -> Bool { - return lhs.theme == rhs.theme && lhs.themeSpecificAccentColors == rhs.themeSpecificAccentColors && lhs.themeSpecificChatWallpapers == rhs.themeSpecificChatWallpapers && lhs.useSystemFont == rhs.useSystemFont && lhs.fontSize == rhs.fontSize && lhs.listsFontSize == rhs.listsFontSize && lhs.automaticThemeSwitchSetting == rhs.automaticThemeSwitchSetting && lhs.largeEmoji == rhs.largeEmoji && lhs.disableAnimations == rhs.disableAnimations + return lhs.theme == rhs.theme && lhs.themeSpecificAccentColors == rhs.themeSpecificAccentColors && lhs.themeSpecificChatWallpapers == rhs.themeSpecificChatWallpapers && lhs.useSystemFont == rhs.useSystemFont && lhs.fontSize == rhs.fontSize && lhs.listsFontSize == rhs.listsFontSize && lhs.chatBubbleSettings == rhs.chatBubbleSettings && lhs.automaticThemeSwitchSetting == rhs.automaticThemeSwitchSetting && lhs.largeEmoji == rhs.largeEmoji && lhs.disableAnimations == rhs.disableAnimations } public func withUpdatedTheme(_ theme: PresentationThemeReference) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) + return PresentationThemeSettings(theme: theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) } public func withUpdatedThemeSpecificAccentColors(_ themeSpecificAccentColors: [Int64: PresentationThemeAccentColor]) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) + return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) } public func withUpdatedThemeSpecificChatWallpapers(_ themeSpecificChatWallpapers: [Int64: TelegramWallpaper]) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) + return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) } public func withUpdatedUseSystemFont(_ useSystemFont: Bool) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) + return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) } public func withUpdatedFontSizes(fontSize: PresentationFontSize, listsFontSize: PresentationFontSize) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: fontSize, listsFontSize: listsFontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) + return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: fontSize, listsFontSize: listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) + } + + public func withUpdatedChatBubbleSettings(_ chatBubbleSettings: PresentationChatBubbleSettings) -> PresentationThemeSettings { + return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) } public func withUpdatedAutomaticThemeSwitchSetting(_ automaticThemeSwitchSetting: AutomaticThemeSwitchSetting) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, automaticThemeSwitchSetting: automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) + return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) } public func withUpdatedLargeEmoji(_ largeEmoji: Bool) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: largeEmoji, disableAnimations: self.disableAnimations) + return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: largeEmoji, disableAnimations: self.disableAnimations) } public func withUpdatedDisableAnimations(_ disableAnimations: Bool) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: disableAnimations) + return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: disableAnimations) } } From 5d684792b24ffbb610e06a26036426ff14a3d61e Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 21 Jan 2020 20:35:37 +0300 Subject: [PATCH 12/50] Escape asterisks in peer names in live location panel subtitle [skip ci] --- Telegram-iOS/en.lproj/Localizable.strings | 2 + ...ionBroadcastNavigationAccessoryPanel.swift | 4 +- .../Sources/PresentationStrings.swift | 6577 +++++++++-------- .../Resources/PresentationStrings.mapping | Bin 144339 -> 144387 bytes 4 files changed, 3294 insertions(+), 3289 deletions(-) diff --git a/Telegram-iOS/en.lproj/Localizable.strings b/Telegram-iOS/en.lproj/Localizable.strings index 4af86fec1d..88bbb9260e 100644 --- a/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram-iOS/en.lproj/Localizable.strings @@ -5291,3 +5291,5 @@ Any member of this group will be able to see messages in the channel."; "Forward.ErrorPublicQuizDisabledInChannels" = "Sorry, public polls can’t be forwarded to channels."; "Map.PlacesInThisArea" = "Places In This Area"; + +"Conversation.LiveLocationYouAndOther" = "**You** and %@"; diff --git a/submodules/TelegramBaseController/Sources/LocationBroadcastNavigationAccessoryPanel.swift b/submodules/TelegramBaseController/Sources/LocationBroadcastNavigationAccessoryPanel.swift index d75b0ee04f..59430f3883 100644 --- a/submodules/TelegramBaseController/Sources/LocationBroadcastNavigationAccessoryPanel.swift +++ b/submodules/TelegramBaseController/Sources/LocationBroadcastNavigationAccessoryPanel.swift @@ -135,13 +135,13 @@ final class LocationBroadcastNavigationAccessoryPanel: ASDisplayNode { } else { let otherString: String if filteredPeers.count == 1 { - otherString = peers[0].compactDisplayTitle + otherString = peers[0].compactDisplayTitle.replacingOccurrences(of: "*", with: "") } else { otherString = self.strings.Conversation_LiveLocationMembersCount(Int32(peers.count)) } let rawText: String if filteredPeers.count != peers.count { - rawText = self.strings.Conversation_LiveLocationYouAnd(otherString).0.replacingOccurrences(of: "*", with: "**") + rawText = self.strings.Conversation_LiveLocationYouAndOther(otherString).0 } else { rawText = otherString } diff --git a/submodules/TelegramPresentationData/Sources/PresentationStrings.swift b/submodules/TelegramPresentationData/Sources/PresentationStrings.swift index d4e4d3501b..615e220b50 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationStrings.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationStrings.swift @@ -1137,3639 +1137,3641 @@ public final class PresentationStrings: Equatable { public var TwoStepAuth_EnterPasswordPassword: String { return self._s[871]! } public var NotificationsSound_Calypso: String { return self._s[872]! } public var Map_Map: String { return self._s[873]! } - public var CheckoutInfo_ReceiverInfoTitle: String { return self._s[875]! } - public var ChatSettings_TextSizeUnits: String { return self._s[876]! } + public func Conversation_LiveLocationYouAndOther(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[874]!, self._r[874]!, [_0]) + } + public var CheckoutInfo_ReceiverInfoTitle: String { return self._s[876]! } + public var ChatSettings_TextSizeUnits: String { return self._s[877]! } public func VoiceOver_Chat_FileFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[877]!, self._r[877]!, [_0]) + return formatWithArgumentRanges(self._s[878]!, self._r[878]!, [_0]) } - public var Common_of: String { return self._s[878]! } - public var Conversation_ForwardContacts: String { return self._s[881]! } - public var IntentsSettings_SuggestByAll: String { return self._s[883]! } + public var Common_of: String { return self._s[879]! } + public var Conversation_ForwardContacts: String { return self._s[882]! } + public var IntentsSettings_SuggestByAll: String { return self._s[884]! } public func Call_AnsweringWithAccount(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[884]!, self._r[884]!, [_0]) + return formatWithArgumentRanges(self._s[885]!, self._r[885]!, [_0]) } - public var Passport_Language_hy: String { return self._s[885]! } - public var Notifications_MessageNotificationsHelp: String { return self._s[886]! } - public var AutoDownloadSettings_Reset: String { return self._s[887]! } - public var Wallet_TransactionInfo_AddressCopied: String { return self._s[888]! } - public var Paint_ClearConfirm: String { return self._s[889]! } - public var Camera_VideoMode: String { return self._s[890]! } + public var Passport_Language_hy: String { return self._s[886]! } + public var Notifications_MessageNotificationsHelp: String { return self._s[887]! } + public var AutoDownloadSettings_Reset: String { return self._s[888]! } + public var Wallet_TransactionInfo_AddressCopied: String { return self._s[889]! } + public var Paint_ClearConfirm: String { return self._s[890]! } + public var Camera_VideoMode: String { return self._s[891]! } public func Conversation_RestrictedStickersTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[891]!, self._r[891]!, [_0]) + return formatWithArgumentRanges(self._s[892]!, self._r[892]!, [_0]) } - public var Privacy_Calls_AlwaysAllow_Placeholder: String { return self._s[892]! } - public var Conversation_ViewBackground: String { return self._s[893]! } + public var Privacy_Calls_AlwaysAllow_Placeholder: String { return self._s[893]! } + public var Conversation_ViewBackground: String { return self._s[894]! } public func Wallet_Info_TransactionDateHeaderYear(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[894]!, self._r[894]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[895]!, self._r[895]!, [_1, _2, _3]) } - public var Passport_Language_el: String { return self._s[895]! } - public var PhotoEditor_Original: String { return self._s[896]! } - public var Settings_FAQ_Button: String { return self._s[898]! } - public var Channel_Setup_PublicNoLink: String { return self._s[900]! } - public var Conversation_UnsupportedMedia: String { return self._s[901]! } - public var Conversation_SlideToCancel: String { return self._s[902]! } - public var Appearance_ThemePreview_ChatList_4_Name: String { return self._s[903]! } - public var Passport_Identity_OneOfTypeInternalPassport: String { return self._s[904]! } - public var CheckoutInfo_ShippingInfoPostcode: String { return self._s[905]! } - public var Conversation_ReportSpamChannelConfirmation: String { return self._s[906]! } - public var AutoNightTheme_NotAvailable: String { return self._s[907]! } - public var Conversation_Owner: String { return self._s[908]! } - public var Common_Create: String { return self._s[909]! } - public var Settings_ApplyProxyAlertEnable: String { return self._s[910]! } - public var ContactList_Context_Call: String { return self._s[911]! } - public var Localization_ChooseLanguage: String { return self._s[913]! } - public var ChatList_Context_AddToContacts: String { return self._s[915]! } - public var OldChannels_NoticeTitle: String { return self._s[916]! } - public var Settings_Proxy: String { return self._s[918]! } - public var Privacy_TopPeersHelp: String { return self._s[919]! } - public var CheckoutInfo_ShippingInfoCountryPlaceholder: String { return self._s[920]! } - public var Chat_UnsendMyMessages: String { return self._s[921]! } + public var Passport_Language_el: String { return self._s[896]! } + public var PhotoEditor_Original: String { return self._s[897]! } + public var Settings_FAQ_Button: String { return self._s[899]! } + public var Channel_Setup_PublicNoLink: String { return self._s[901]! } + public var Conversation_UnsupportedMedia: String { return self._s[902]! } + public var Conversation_SlideToCancel: String { return self._s[903]! } + public var Appearance_ThemePreview_ChatList_4_Name: String { return self._s[904]! } + public var Passport_Identity_OneOfTypeInternalPassport: String { return self._s[905]! } + public var CheckoutInfo_ShippingInfoPostcode: String { return self._s[906]! } + public var Conversation_ReportSpamChannelConfirmation: String { return self._s[907]! } + public var AutoNightTheme_NotAvailable: String { return self._s[908]! } + public var Conversation_Owner: String { return self._s[909]! } + public var Common_Create: String { return self._s[910]! } + public var Settings_ApplyProxyAlertEnable: String { return self._s[911]! } + public var ContactList_Context_Call: String { return self._s[912]! } + public var Localization_ChooseLanguage: String { return self._s[914]! } + public var ChatList_Context_AddToContacts: String { return self._s[916]! } + public var OldChannels_NoticeTitle: String { return self._s[917]! } + public var Settings_Proxy: String { return self._s[919]! } + public var Privacy_TopPeersHelp: String { return self._s[920]! } + public var CheckoutInfo_ShippingInfoCountryPlaceholder: String { return self._s[921]! } + public var Chat_UnsendMyMessages: String { return self._s[922]! } public func VoiceOver_Chat_Duration(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[922]!, self._r[922]!, [_0]) + return formatWithArgumentRanges(self._s[923]!, self._r[923]!, [_0]) } - public var TwoStepAuth_ConfirmationAbort: String { return self._s[923]! } + public var TwoStepAuth_ConfirmationAbort: String { return self._s[924]! } public func Contacts_AccessDeniedHelpPortrait(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[925]!, self._r[925]!, [_0]) + return formatWithArgumentRanges(self._s[926]!, self._r[926]!, [_0]) } - public var Contacts_SortedByPresence: String { return self._s[926]! } - public var Passport_Identity_SurnamePlaceholder: String { return self._s[927]! } - public var Cache_Title: String { return self._s[928]! } + public var Contacts_SortedByPresence: String { return self._s[927]! } + public var Passport_Identity_SurnamePlaceholder: String { return self._s[928]! } + public var Cache_Title: String { return self._s[929]! } public func Login_PhoneBannedEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[929]!, self._r[929]!, [_0]) + return formatWithArgumentRanges(self._s[930]!, self._r[930]!, [_0]) } - public var TwoStepAuth_EmailCodeExpired: String { return self._s[930]! } - public var Channel_Moderator_Title: String { return self._s[931]! } - public var InstantPage_AutoNightTheme: String { return self._s[933]! } + public var TwoStepAuth_EmailCodeExpired: String { return self._s[931]! } + public var Channel_Moderator_Title: String { return self._s[932]! } + public var InstantPage_AutoNightTheme: String { return self._s[934]! } public func PUSH_MESSAGE_POLL(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[936]!, self._r[936]!, [_1]) + return formatWithArgumentRanges(self._s[937]!, self._r[937]!, [_1]) } - public var Passport_Scans_Upload: String { return self._s[937]! } - public var Undo_Undo: String { return self._s[939]! } - public var Contacts_AccessDeniedHelpON: String { return self._s[940]! } - public var TwoStepAuth_RemovePassword: String { return self._s[941]! } - public var Common_Delete: String { return self._s[942]! } - public var Contacts_AddPeopleNearby: String { return self._s[944]! } - public var Conversation_ContextMenuDelete: String { return self._s[945]! } - public var SocksProxySetup_Credentials: String { return self._s[946]! } - public var Appearance_EditTheme: String { return self._s[948]! } - public var ClearCache_StorageOtherApps: String { return self._s[949]! } - public var PasscodeSettings_AutoLock_Disabled: String { return self._s[950]! } - public var Wallet_Send_NetworkErrorText: String { return self._s[951]! } - public var AuthSessions_DevicesTitle: String { return self._s[953]! } - public var Passport_Address_OneOfTypeRentalAgreement: String { return self._s[955]! } - public var Conversation_ShareBotContactConfirmationTitle: String { return self._s[956]! } - public var Passport_Language_id: String { return self._s[958]! } - public var WallpaperSearch_ColorTeal: String { return self._s[959]! } - public var ChannelIntro_Title: String { return self._s[960]! } + public var Passport_Scans_Upload: String { return self._s[938]! } + public var Undo_Undo: String { return self._s[940]! } + public var Contacts_AccessDeniedHelpON: String { return self._s[941]! } + public var TwoStepAuth_RemovePassword: String { return self._s[942]! } + public var Common_Delete: String { return self._s[943]! } + public var Contacts_AddPeopleNearby: String { return self._s[945]! } + public var Conversation_ContextMenuDelete: String { return self._s[946]! } + public var SocksProxySetup_Credentials: String { return self._s[947]! } + public var Appearance_EditTheme: String { return self._s[949]! } + public var ClearCache_StorageOtherApps: String { return self._s[950]! } + public var PasscodeSettings_AutoLock_Disabled: String { return self._s[951]! } + public var Wallet_Send_NetworkErrorText: String { return self._s[952]! } + public var AuthSessions_DevicesTitle: String { return self._s[954]! } + public var Passport_Address_OneOfTypeRentalAgreement: String { return self._s[956]! } + public var Conversation_ShareBotContactConfirmationTitle: String { return self._s[957]! } + public var Passport_Language_id: String { return self._s[959]! } + public var WallpaperSearch_ColorTeal: String { return self._s[960]! } + public var ChannelIntro_Title: String { return self._s[961]! } public func Channel_AdminLog_MessageToggleSignaturesOff(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[961]!, self._r[961]!, [_0]) + return formatWithArgumentRanges(self._s[962]!, self._r[962]!, [_0]) } - public var VoiceOver_Chat_OpenLinkHint: String { return self._s[963]! } - public var VoiceOver_Chat_Reply: String { return self._s[964]! } - public var ScheduledMessages_BotActionUnavailable: String { return self._s[965]! } - public var Channel_Info_Description: String { return self._s[966]! } - public var Stickers_FavoriteStickers: String { return self._s[967]! } - public var Channel_BanUser_PermissionAddMembers: String { return self._s[968]! } - public var Notifications_DisplayNamesOnLockScreen: String { return self._s[969]! } - public var ChatSearch_ResultsTooltip: String { return self._s[970]! } - public var Wallet_VoiceOver_Editing_ClearText: String { return self._s[971]! } - public var Calls_NoMissedCallsPlacehoder: String { return self._s[972]! } - public var Group_PublicLink_Placeholder: String { return self._s[973]! } - public var Notifications_ExceptionsDefaultSound: String { return self._s[974]! } + public var VoiceOver_Chat_OpenLinkHint: String { return self._s[964]! } + public var VoiceOver_Chat_Reply: String { return self._s[965]! } + public var ScheduledMessages_BotActionUnavailable: String { return self._s[966]! } + public var Channel_Info_Description: String { return self._s[967]! } + public var Stickers_FavoriteStickers: String { return self._s[968]! } + public var Channel_BanUser_PermissionAddMembers: String { return self._s[969]! } + public var Notifications_DisplayNamesOnLockScreen: String { return self._s[970]! } + public var ChatSearch_ResultsTooltip: String { return self._s[971]! } + public var Wallet_VoiceOver_Editing_ClearText: String { return self._s[972]! } + public var Calls_NoMissedCallsPlacehoder: String { return self._s[973]! } + public var Group_PublicLink_Placeholder: String { return self._s[974]! } + public var Notifications_ExceptionsDefaultSound: String { return self._s[975]! } public func PUSH_CHANNEL_MESSAGE_POLL(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[975]!, self._r[975]!, [_1]) + return formatWithArgumentRanges(self._s[976]!, self._r[976]!, [_1]) } - public var TextFormat_Underline: String { return self._s[976]! } + public var TextFormat_Underline: String { return self._s[977]! } public func DialogList_SearchSubtitleFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[978]!, self._r[978]!, [_1, _2]) + return formatWithArgumentRanges(self._s[979]!, self._r[979]!, [_1, _2]) } public func Channel_AdminLog_MessageRemovedGroupStickerPack(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[979]!, self._r[979]!, [_0]) + return formatWithArgumentRanges(self._s[980]!, self._r[980]!, [_0]) } - public var Appearance_ThemePreview_ChatList_3_Name: String { return self._s[980]! } + public var Appearance_ThemePreview_ChatList_3_Name: String { return self._s[981]! } public func Channel_OwnershipTransfer_TransferCompleted(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[981]!, self._r[981]!, [_1, _2]) + return formatWithArgumentRanges(self._s[982]!, self._r[982]!, [_1, _2]) } - public var Wallet_Intro_ImportExisting: String { return self._s[982]! } - public var GroupPermission_Delete: String { return self._s[983]! } - public var Passport_Language_uk: String { return self._s[984]! } - public var StickerPack_HideStickers: String { return self._s[986]! } - public var ChangePhoneNumberNumber_NumberPlaceholder: String { return self._s[987]! } + public var Wallet_Intro_ImportExisting: String { return self._s[983]! } + public var GroupPermission_Delete: String { return self._s[984]! } + public var Passport_Language_uk: String { return self._s[985]! } + public var StickerPack_HideStickers: String { return self._s[987]! } + public var ChangePhoneNumberNumber_NumberPlaceholder: String { return self._s[988]! } public func PUSH_CHAT_MESSAGE_PHOTO(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[988]!, self._r[988]!, [_1, _2]) + return formatWithArgumentRanges(self._s[989]!, self._r[989]!, [_1, _2]) } - public var Activity_UploadingVideoMessage: String { return self._s[989]! } + public var Activity_UploadingVideoMessage: String { return self._s[990]! } public func GroupPermission_ApplyAlertText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[990]!, self._r[990]!, [_0]) + return formatWithArgumentRanges(self._s[991]!, self._r[991]!, [_0]) } - public var Channel_TitleInfo: String { return self._s[991]! } - public var StickerPacksSettings_ArchivedPacks_Info: String { return self._s[992]! } - public var Settings_CallSettings: String { return self._s[993]! } - public var Camera_SquareMode: String { return self._s[994]! } - public var Conversation_SendMessage_ScheduleMessage: String { return self._s[995]! } - public var GroupInfo_SharedMediaNone: String { return self._s[996]! } + public var Channel_TitleInfo: String { return self._s[992]! } + public var StickerPacksSettings_ArchivedPacks_Info: String { return self._s[993]! } + public var Settings_CallSettings: String { return self._s[994]! } + public var Camera_SquareMode: String { return self._s[995]! } + public var Conversation_SendMessage_ScheduleMessage: String { return self._s[996]! } + public var GroupInfo_SharedMediaNone: String { return self._s[997]! } public func PUSH_MESSAGE_VIDEO_SECRET(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[997]!, self._r[997]!, [_1]) + return formatWithArgumentRanges(self._s[998]!, self._r[998]!, [_1]) } - public var Bot_GenericBotStatus: String { return self._s[998]! } - public var Application_Update: String { return self._s[1000]! } - public var Month_ShortJanuary: String { return self._s[1001]! } - public var Contacts_PermissionsKeepDisabled: String { return self._s[1002]! } - public var Channel_AdminLog_BanReadMessages: String { return self._s[1003]! } - public var Settings_AppLanguage_Unofficial: String { return self._s[1004]! } - public var Passport_Address_Street2Placeholder: String { return self._s[1005]! } + public var Bot_GenericBotStatus: String { return self._s[999]! } + public var Application_Update: String { return self._s[1001]! } + public var Month_ShortJanuary: String { return self._s[1002]! } + public var Contacts_PermissionsKeepDisabled: String { return self._s[1003]! } + public var Channel_AdminLog_BanReadMessages: String { return self._s[1004]! } + public var Settings_AppLanguage_Unofficial: String { return self._s[1005]! } + public var Passport_Address_Street2Placeholder: String { return self._s[1006]! } public func Map_LiveLocationShortHour(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1006]!, self._r[1006]!, [_0]) + return formatWithArgumentRanges(self._s[1007]!, self._r[1007]!, [_0]) } - public var NetworkUsageSettings_Cellular: String { return self._s[1007]! } - public var Appearance_PreviewOutgoingText: String { return self._s[1008]! } + public var NetworkUsageSettings_Cellular: String { return self._s[1008]! } + public var Appearance_PreviewOutgoingText: String { return self._s[1009]! } public func StickerPackActionInfo_RemovedText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1009]!, self._r[1009]!, [_0]) + return formatWithArgumentRanges(self._s[1010]!, self._r[1010]!, [_0]) } - public var Notifications_PermissionsAllowInSettings: String { return self._s[1010]! } - public var AutoDownloadSettings_OnForAll: String { return self._s[1012]! } - public var Map_Directions: String { return self._s[1013]! } - public var Passport_FieldIdentityTranslationHelp: String { return self._s[1015]! } - public var Appearance_ThemeDay: String { return self._s[1016]! } - public var LogoutOptions_LogOut: String { return self._s[1017]! } - public var Group_PublicLink_Title: String { return self._s[1019]! } - public var Channel_AddBotErrorNoRights: String { return self._s[1020]! } - public var ChatList_Search_ShowLess: String { return self._s[1021]! } - public var Passport_Identity_AddPassport: String { return self._s[1022]! } - public var LocalGroup_ButtonTitle: String { return self._s[1023]! } - public var Call_Message: String { return self._s[1024]! } - public var PhotoEditor_ExposureTool: String { return self._s[1025]! } - public var Wallet_Receive_CommentInfo: String { return self._s[1027]! } - public var Passport_FieldOneOf_Delimeter: String { return self._s[1028]! } - public var Channel_AdminLog_CanBanUsers: String { return self._s[1030]! } - public var Appearance_ThemePreview_ChatList_2_Name: String { return self._s[1031]! } - public var Appearance_Preview: String { return self._s[1032]! } - public var Compose_ChannelMembers: String { return self._s[1033]! } - public var Conversation_DeleteManyMessages: String { return self._s[1034]! } - public var ReportPeer_ReasonOther_Title: String { return self._s[1035]! } - public var Checkout_ErrorProviderAccountTimeout: String { return self._s[1036]! } - public var TwoStepAuth_ResetAccountConfirmation: String { return self._s[1037]! } - public var Channel_Stickers_CreateYourOwn: String { return self._s[1040]! } - public var Conversation_UpdateTelegram: String { return self._s[1041]! } - public var EditTheme_Create_TopInfo: String { return self._s[1042]! } + public var Notifications_PermissionsAllowInSettings: String { return self._s[1011]! } + public var AutoDownloadSettings_OnForAll: String { return self._s[1013]! } + public var Map_Directions: String { return self._s[1014]! } + public var Passport_FieldIdentityTranslationHelp: String { return self._s[1016]! } + public var Appearance_ThemeDay: String { return self._s[1017]! } + public var LogoutOptions_LogOut: String { return self._s[1018]! } + public var Group_PublicLink_Title: String { return self._s[1020]! } + public var Channel_AddBotErrorNoRights: String { return self._s[1021]! } + public var ChatList_Search_ShowLess: String { return self._s[1022]! } + public var Passport_Identity_AddPassport: String { return self._s[1023]! } + public var LocalGroup_ButtonTitle: String { return self._s[1024]! } + public var Call_Message: String { return self._s[1025]! } + public var PhotoEditor_ExposureTool: String { return self._s[1026]! } + public var Wallet_Receive_CommentInfo: String { return self._s[1028]! } + public var Passport_FieldOneOf_Delimeter: String { return self._s[1029]! } + public var Channel_AdminLog_CanBanUsers: String { return self._s[1031]! } + public var Appearance_ThemePreview_ChatList_2_Name: String { return self._s[1032]! } + public var Appearance_Preview: String { return self._s[1033]! } + public var Compose_ChannelMembers: String { return self._s[1034]! } + public var Conversation_DeleteManyMessages: String { return self._s[1035]! } + public var ReportPeer_ReasonOther_Title: String { return self._s[1036]! } + public var Checkout_ErrorProviderAccountTimeout: String { return self._s[1037]! } + public var TwoStepAuth_ResetAccountConfirmation: String { return self._s[1038]! } + public var Channel_Stickers_CreateYourOwn: String { return self._s[1041]! } + public var Conversation_UpdateTelegram: String { return self._s[1042]! } + public var EditTheme_Create_TopInfo: String { return self._s[1043]! } public func Notification_PinnedPhotoMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1043]!, self._r[1043]!, [_0]) + return formatWithArgumentRanges(self._s[1044]!, self._r[1044]!, [_0]) } - public var Wallet_WordCheck_Continue: String { return self._s[1044]! } - public var TwoFactorSetup_Hint_Action: String { return self._s[1045]! } - public var IntentsSettings_ResetAll: String { return self._s[1046]! } + public var Wallet_WordCheck_Continue: String { return self._s[1045]! } + public var TwoFactorSetup_Hint_Action: String { return self._s[1046]! } + public var IntentsSettings_ResetAll: String { return self._s[1047]! } public func PUSH_PINNED_GIF(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1047]!, self._r[1047]!, [_1]) + return formatWithArgumentRanges(self._s[1048]!, self._r[1048]!, [_1]) } - public var GroupInfo_Administrators_Title: String { return self._s[1048]! } - public var Privacy_Forwards_PreviewMessageText: String { return self._s[1049]! } + public var GroupInfo_Administrators_Title: String { return self._s[1049]! } + public var Privacy_Forwards_PreviewMessageText: String { return self._s[1050]! } public func PrivacySettings_LastSeenNobodyPlus(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1050]!, self._r[1050]!, [_0]) + return formatWithArgumentRanges(self._s[1051]!, self._r[1051]!, [_0]) } - public var Tour_Title3: String { return self._s[1051]! } - public var Channel_EditAdmin_PermissionInviteSubscribers: String { return self._s[1052]! } - public var Clipboard_SendPhoto: String { return self._s[1056]! } - public var MediaPicker_Videos: String { return self._s[1057]! } - public var Passport_Email_Title: String { return self._s[1058]! } + public var Tour_Title3: String { return self._s[1052]! } + public var Channel_EditAdmin_PermissionInviteSubscribers: String { return self._s[1053]! } + public var Clipboard_SendPhoto: String { return self._s[1057]! } + public var MediaPicker_Videos: String { return self._s[1058]! } + public var Passport_Email_Title: String { return self._s[1059]! } public func PrivacySettings_LastSeenEverybodyMinus(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1059]!, self._r[1059]!, [_0]) + return formatWithArgumentRanges(self._s[1060]!, self._r[1060]!, [_0]) } - public var StickerPacksSettings_Title: String { return self._s[1060]! } - public var Conversation_MessageDialogDelete: String { return self._s[1061]! } - public var Privacy_Calls_CustomHelp: String { return self._s[1063]! } - public var Message_Wallpaper: String { return self._s[1064]! } - public var MemberSearch_BotSection: String { return self._s[1065]! } - public var GroupInfo_SetSound: String { return self._s[1066]! } - public var Core_ServiceUserStatus: String { return self._s[1067]! } - public var LiveLocationUpdated_JustNow: String { return self._s[1068]! } - public var Call_StatusFailed: String { return self._s[1069]! } - public var TwoFactorSetup_Email_Placeholder: String { return self._s[1070]! } - public var TwoStepAuth_SetupPasswordDescription: String { return self._s[1071]! } - public var TwoStepAuth_SetPassword: String { return self._s[1072]! } - public var Permissions_PeopleNearbyText_v0: String { return self._s[1073]! } + public var StickerPacksSettings_Title: String { return self._s[1061]! } + public var Conversation_MessageDialogDelete: String { return self._s[1062]! } + public var Privacy_Calls_CustomHelp: String { return self._s[1064]! } + public var Message_Wallpaper: String { return self._s[1065]! } + public var MemberSearch_BotSection: String { return self._s[1066]! } + public var GroupInfo_SetSound: String { return self._s[1067]! } + public var Core_ServiceUserStatus: String { return self._s[1068]! } + public var LiveLocationUpdated_JustNow: String { return self._s[1069]! } + public var Call_StatusFailed: String { return self._s[1070]! } + public var TwoFactorSetup_Email_Placeholder: String { return self._s[1071]! } + public var TwoStepAuth_SetupPasswordDescription: String { return self._s[1072]! } + public var TwoStepAuth_SetPassword: String { return self._s[1073]! } + public var Permissions_PeopleNearbyText_v0: String { return self._s[1074]! } public func SocksProxySetup_ProxyStatusPing(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1075]!, self._r[1075]!, [_0]) + return formatWithArgumentRanges(self._s[1076]!, self._r[1076]!, [_0]) } - public var Calls_SubmitRating: String { return self._s[1076]! } - public var Map_NoPlacesNearby: String { return self._s[1077]! } - public var Profile_Username: String { return self._s[1078]! } - public var Bot_DescriptionTitle: String { return self._s[1079]! } - public var MaskStickerSettings_Title: String { return self._s[1080]! } - public var SharedMedia_CategoryOther: String { return self._s[1081]! } - public var GroupInfo_SetGroupPhoto: String { return self._s[1082]! } - public var Common_NotNow: String { return self._s[1083]! } - public var CallFeedback_IncludeLogsInfo: String { return self._s[1084]! } - public var Conversation_ShareMyPhoneNumber: String { return self._s[1085]! } - public var Map_Location: String { return self._s[1086]! } - public var Invitation_JoinGroup: String { return self._s[1087]! } - public var AutoDownloadSettings_Title: String { return self._s[1089]! } - public var Conversation_DiscardVoiceMessageDescription: String { return self._s[1090]! } - public var Channel_ErrorAddBlocked: String { return self._s[1091]! } - public var Conversation_UnblockUser: String { return self._s[1092]! } - public var EditTheme_Edit_TopInfo: String { return self._s[1093]! } - public var Watch_Bot_Restart: String { return self._s[1094]! } - public var TwoStepAuth_Title: String { return self._s[1095]! } - public var Channel_AdminLog_BanSendMessages: String { return self._s[1096]! } - public var Checkout_ShippingMethod: String { return self._s[1097]! } - public var Passport_Identity_OneOfTypeIdentityCard: String { return self._s[1098]! } + public var Calls_SubmitRating: String { return self._s[1077]! } + public var Map_NoPlacesNearby: String { return self._s[1078]! } + public var Profile_Username: String { return self._s[1079]! } + public var Bot_DescriptionTitle: String { return self._s[1080]! } + public var MaskStickerSettings_Title: String { return self._s[1081]! } + public var SharedMedia_CategoryOther: String { return self._s[1082]! } + public var GroupInfo_SetGroupPhoto: String { return self._s[1083]! } + public var Common_NotNow: String { return self._s[1084]! } + public var CallFeedback_IncludeLogsInfo: String { return self._s[1085]! } + public var Conversation_ShareMyPhoneNumber: String { return self._s[1086]! } + public var Map_Location: String { return self._s[1087]! } + public var Invitation_JoinGroup: String { return self._s[1088]! } + public var AutoDownloadSettings_Title: String { return self._s[1090]! } + public var Conversation_DiscardVoiceMessageDescription: String { return self._s[1091]! } + public var Channel_ErrorAddBlocked: String { return self._s[1092]! } + public var Conversation_UnblockUser: String { return self._s[1093]! } + public var EditTheme_Edit_TopInfo: String { return self._s[1094]! } + public var Watch_Bot_Restart: String { return self._s[1095]! } + public var TwoStepAuth_Title: String { return self._s[1096]! } + public var Channel_AdminLog_BanSendMessages: String { return self._s[1097]! } + public var Checkout_ShippingMethod: String { return self._s[1098]! } + public var Passport_Identity_OneOfTypeIdentityCard: String { return self._s[1099]! } public func PUSH_CHAT_MESSAGE_STICKER(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1099]!, self._r[1099]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1100]!, self._r[1100]!, [_1, _2, _3]) } - public var EditTheme_ChangeColors: String { return self._s[1101]! } + public var EditTheme_ChangeColors: String { return self._s[1102]! } public func Chat_UnsendMyMessagesAlertTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1102]!, self._r[1102]!, [_0]) - } - public func Channel_Username_LinkHint(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[1103]!, self._r[1103]!, [_0]) } - public var Appearance_ThemePreview_ChatList_1_Name: String { return self._s[1104]! } - public var SettingsSearch_Synonyms_Data_AutoplayGifs: String { return self._s[1105]! } - public var AuthSessions_TerminateOtherSessions: String { return self._s[1106]! } - public var Contacts_FailedToSendInvitesMessage: String { return self._s[1107]! } - public var PrivacySettings_TwoStepAuth: String { return self._s[1108]! } - public var Notification_Exceptions_PreviewAlwaysOn: String { return self._s[1109]! } - public var SettingsSearch_Synonyms_Privacy_Passcode: String { return self._s[1110]! } - public var Conversation_EditingMessagePanelMedia: String { return self._s[1111]! } - public var Checkout_PaymentMethod_Title: String { return self._s[1112]! } - public var SocksProxySetup_Connection: String { return self._s[1113]! } - public var Group_MessagePhotoRemoved: String { return self._s[1114]! } - public var Channel_Stickers_NotFound: String { return self._s[1117]! } - public var Group_About_Help: String { return self._s[1118]! } - public var Notification_PassportValueProofOfIdentity: String { return self._s[1119]! } - public var PeopleNearby_Title: String { return self._s[1121]! } - public func ApplyLanguage_ChangeLanguageOfficialText(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1122]!, self._r[1122]!, [_1]) + public func Channel_Username_LinkHint(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1104]!, self._r[1104]!, [_0]) } - public var Map_Home: String { return self._s[1123]! } - public var CheckoutInfo_ShippingInfoStatePlaceholder: String { return self._s[1125]! } - public var Notifications_GroupNotificationsExceptionsHelp: String { return self._s[1126]! } - public var SocksProxySetup_Password: String { return self._s[1127]! } - public var Notifications_PermissionsEnable: String { return self._s[1128]! } - public var TwoStepAuth_ChangeEmail: String { return self._s[1130]! } + public var Appearance_ThemePreview_ChatList_1_Name: String { return self._s[1105]! } + public var SettingsSearch_Synonyms_Data_AutoplayGifs: String { return self._s[1106]! } + public var AuthSessions_TerminateOtherSessions: String { return self._s[1107]! } + public var Contacts_FailedToSendInvitesMessage: String { return self._s[1108]! } + public var PrivacySettings_TwoStepAuth: String { return self._s[1109]! } + public var Notification_Exceptions_PreviewAlwaysOn: String { return self._s[1110]! } + public var SettingsSearch_Synonyms_Privacy_Passcode: String { return self._s[1111]! } + public var Conversation_EditingMessagePanelMedia: String { return self._s[1112]! } + public var Checkout_PaymentMethod_Title: String { return self._s[1113]! } + public var SocksProxySetup_Connection: String { return self._s[1114]! } + public var Group_MessagePhotoRemoved: String { return self._s[1115]! } + public var Channel_Stickers_NotFound: String { return self._s[1118]! } + public var Group_About_Help: String { return self._s[1119]! } + public var Notification_PassportValueProofOfIdentity: String { return self._s[1120]! } + public var PeopleNearby_Title: String { return self._s[1122]! } + public func ApplyLanguage_ChangeLanguageOfficialText(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1123]!, self._r[1123]!, [_1]) + } + public var Map_Home: String { return self._s[1124]! } + public var CheckoutInfo_ShippingInfoStatePlaceholder: String { return self._s[1126]! } + public var Notifications_GroupNotificationsExceptionsHelp: String { return self._s[1127]! } + public var SocksProxySetup_Password: String { return self._s[1128]! } + public var Notifications_PermissionsEnable: String { return self._s[1129]! } + public var TwoStepAuth_ChangeEmail: String { return self._s[1131]! } public func Channel_AdminLog_MessageInvitedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1131]!, self._r[1131]!, [_1]) + return formatWithArgumentRanges(self._s[1132]!, self._r[1132]!, [_1]) } public func Time_MonthOfYear_m10(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1133]!, self._r[1133]!, [_0]) + return formatWithArgumentRanges(self._s[1134]!, self._r[1134]!, [_0]) } - public var Passport_Identity_TypeDriversLicense: String { return self._s[1134]! } - public var ArchivedPacksAlert_Title: String { return self._s[1135]! } - public var Wallet_Receive_InvoiceUrlCopied: String { return self._s[1136]! } - public var Map_PlacesNearby: String { return self._s[1137]! } + public var Passport_Identity_TypeDriversLicense: String { return self._s[1135]! } + public var ArchivedPacksAlert_Title: String { return self._s[1136]! } + public var Wallet_Receive_InvoiceUrlCopied: String { return self._s[1137]! } + public var Map_PlacesNearby: String { return self._s[1138]! } public func Time_PreciseDate_m7(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1138]!, self._r[1138]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1139]!, self._r[1139]!, [_1, _2, _3]) } - public var PrivacyLastSeenSettings_GroupsAndChannelsHelp: String { return self._s[1139]! } - public var Privacy_Calls_NeverAllow_Placeholder: String { return self._s[1141]! } - public var Conversation_StatusTyping: String { return self._s[1142]! } - public var Broadcast_AdminLog_EmptyText: String { return self._s[1143]! } - public var Notification_PassportValueProofOfAddress: String { return self._s[1144]! } - public var UserInfo_CreateNewContact: String { return self._s[1145]! } - public var Passport_Identity_FrontSide: String { return self._s[1146]! } - public var Login_PhoneNumberAlreadyAuthorizedSwitch: String { return self._s[1147]! } - public var Calls_CallTabTitle: String { return self._s[1148]! } - public var Channel_AdminLog_ChannelEmptyText: String { return self._s[1149]! } + public var PrivacyLastSeenSettings_GroupsAndChannelsHelp: String { return self._s[1140]! } + public var Privacy_Calls_NeverAllow_Placeholder: String { return self._s[1142]! } + public var Conversation_StatusTyping: String { return self._s[1143]! } + public var Broadcast_AdminLog_EmptyText: String { return self._s[1144]! } + public var Notification_PassportValueProofOfAddress: String { return self._s[1145]! } + public var UserInfo_CreateNewContact: String { return self._s[1146]! } + public var Passport_Identity_FrontSide: String { return self._s[1147]! } + public var Login_PhoneNumberAlreadyAuthorizedSwitch: String { return self._s[1148]! } + public var Calls_CallTabTitle: String { return self._s[1149]! } + public var Channel_AdminLog_ChannelEmptyText: String { return self._s[1150]! } public func Login_BannedPhoneBody(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1151]!, self._r[1151]!, [_0]) + return formatWithArgumentRanges(self._s[1152]!, self._r[1152]!, [_0]) } - public var Watch_UserInfo_MuteTitle: String { return self._s[1152]! } - public var Group_EditAdmin_RankAdminPlaceholder: String { return self._s[1153]! } - public var SharedMedia_EmptyMusicText: String { return self._s[1154]! } - public var Wallet_Completed_Text: String { return self._s[1155]! } - public var PasscodeSettings_AutoLock_IfAwayFor_1minute: String { return self._s[1156]! } - public var Paint_Stickers: String { return self._s[1157]! } - public var Privacy_GroupsAndChannels: String { return self._s[1158]! } - public var ChatList_Context_Delete: String { return self._s[1160]! } - public var UserInfo_AddContact: String { return self._s[1161]! } + public var Watch_UserInfo_MuteTitle: String { return self._s[1153]! } + public var Group_EditAdmin_RankAdminPlaceholder: String { return self._s[1154]! } + public var SharedMedia_EmptyMusicText: String { return self._s[1155]! } + public var Wallet_Completed_Text: String { return self._s[1156]! } + public var PasscodeSettings_AutoLock_IfAwayFor_1minute: String { return self._s[1157]! } + public var Paint_Stickers: String { return self._s[1158]! } + public var Privacy_GroupsAndChannels: String { return self._s[1159]! } + public var ChatList_Context_Delete: String { return self._s[1161]! } + public var UserInfo_AddContact: String { return self._s[1162]! } public func Conversation_MessageViaUser(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1162]!, self._r[1162]!, [_0]) + return formatWithArgumentRanges(self._s[1163]!, self._r[1163]!, [_0]) } - public var PhoneNumberHelp_ChangeNumber: String { return self._s[1164]! } + public var PhoneNumberHelp_ChangeNumber: String { return self._s[1165]! } public func ChatList_ClearChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1166]!, self._r[1166]!, [_0]) + return formatWithArgumentRanges(self._s[1167]!, self._r[1167]!, [_0]) } - public var DialogList_NoMessagesTitle: String { return self._s[1167]! } - public var EditProfile_NameAndPhotoHelp: String { return self._s[1168]! } - public var BlockedUsers_BlockUser: String { return self._s[1169]! } - public var Notifications_PermissionsOpenSettings: String { return self._s[1170]! } - public var MediaPicker_UngroupDescription: String { return self._s[1172]! } - public var Watch_NoConnection: String { return self._s[1173]! } - public var Month_GenSeptember: String { return self._s[1174]! } - public var Conversation_ViewGroup: String { return self._s[1176]! } - public var Channel_AdminLogFilter_EventsLeavingSubscribers: String { return self._s[1179]! } - public var Privacy_Forwards_AlwaysLink: String { return self._s[1180]! } - public var Channel_OwnershipTransfer_ErrorAdminsTooMuch: String { return self._s[1181]! } - public var Passport_FieldOneOf_FinalDelimeter: String { return self._s[1182]! } - public var Wallet_WordCheck_IncorrectHeader: String { return self._s[1183]! } - public var MediaPicker_CameraRoll: String { return self._s[1185]! } - public var Month_GenAugust: String { return self._s[1186]! } - public var Wallet_Configuration_SourceHeader: String { return self._s[1187]! } - public var AccessDenied_VideoMessageMicrophone: String { return self._s[1188]! } - public var SharedMedia_EmptyText: String { return self._s[1189]! } - public var Map_ShareLiveLocation: String { return self._s[1190]! } - public var Calls_All: String { return self._s[1191]! } - public var Map_SendThisPlace: String { return self._s[1193]! } - public var Appearance_ThemeNight: String { return self._s[1195]! } - public var Conversation_HoldForAudio: String { return self._s[1196]! } - public var SettingsSearch_Synonyms_Support: String { return self._s[1199]! } - public var GroupInfo_GroupHistoryHidden: String { return self._s[1200]! } - public var SocksProxySetup_Secret: String { return self._s[1201]! } + public var DialogList_NoMessagesTitle: String { return self._s[1168]! } + public var EditProfile_NameAndPhotoHelp: String { return self._s[1169]! } + public var BlockedUsers_BlockUser: String { return self._s[1170]! } + public var Notifications_PermissionsOpenSettings: String { return self._s[1171]! } + public var MediaPicker_UngroupDescription: String { return self._s[1173]! } + public var Watch_NoConnection: String { return self._s[1174]! } + public var Month_GenSeptember: String { return self._s[1175]! } + public var Conversation_ViewGroup: String { return self._s[1177]! } + public var Channel_AdminLogFilter_EventsLeavingSubscribers: String { return self._s[1180]! } + public var Privacy_Forwards_AlwaysLink: String { return self._s[1181]! } + public var Channel_OwnershipTransfer_ErrorAdminsTooMuch: String { return self._s[1182]! } + public var Passport_FieldOneOf_FinalDelimeter: String { return self._s[1183]! } + public var Wallet_WordCheck_IncorrectHeader: String { return self._s[1184]! } + public var MediaPicker_CameraRoll: String { return self._s[1186]! } + public var Month_GenAugust: String { return self._s[1187]! } + public var Wallet_Configuration_SourceHeader: String { return self._s[1188]! } + public var AccessDenied_VideoMessageMicrophone: String { return self._s[1189]! } + public var SharedMedia_EmptyText: String { return self._s[1190]! } + public var Map_ShareLiveLocation: String { return self._s[1191]! } + public var Calls_All: String { return self._s[1192]! } + public var Map_SendThisPlace: String { return self._s[1194]! } + public var Appearance_ThemeNight: String { return self._s[1196]! } + public var Conversation_HoldForAudio: String { return self._s[1197]! } + public var SettingsSearch_Synonyms_Support: String { return self._s[1200]! } + public var GroupInfo_GroupHistoryHidden: String { return self._s[1201]! } + public var SocksProxySetup_Secret: String { return self._s[1202]! } public func Activity_RemindAboutChannel(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1202]!, self._r[1202]!, [_0]) + return formatWithArgumentRanges(self._s[1203]!, self._r[1203]!, [_0]) } - public var Channel_BanList_RestrictedTitle: String { return self._s[1204]! } - public var Conversation_Location: String { return self._s[1205]! } + public var Channel_BanList_RestrictedTitle: String { return self._s[1205]! } + public var Conversation_Location: String { return self._s[1206]! } public func AutoDownloadSettings_UpToFor(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1206]!, self._r[1206]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1207]!, self._r[1207]!, [_1, _2]) } - public var ChatSettings_AutoDownloadPhotos: String { return self._s[1208]! } - public var SettingsSearch_Synonyms_Privacy_Title: String { return self._s[1209]! } - public var Notifications_PermissionsText: String { return self._s[1210]! } - public var SettingsSearch_Synonyms_Data_SaveIncomingPhotos: String { return self._s[1211]! } - public var Call_Flip: String { return self._s[1212]! } - public var Channel_AdminLog_CanDeleteMessagesOfOthers: String { return self._s[1214]! } - public var SocksProxySetup_ProxyStatusConnecting: String { return self._s[1215]! } - public var Wallet_TransactionInfo_StorageFeeInfoUrl: String { return self._s[1216]! } - public var PrivacyPhoneNumberSettings_DiscoveryHeader: String { return self._s[1217]! } - public var Channel_EditAdmin_PermissionPinMessages: String { return self._s[1219]! } - public var TwoStepAuth_ReEnterPasswordDescription: String { return self._s[1221]! } - public var Channel_TooMuchBots: String { return self._s[1223]! } - public var Passport_DeletePassportConfirmation: String { return self._s[1224]! } - public var Login_InvalidCodeError: String { return self._s[1225]! } - public var StickerPacksSettings_FeaturedPacks: String { return self._s[1226]! } + public var ChatSettings_AutoDownloadPhotos: String { return self._s[1209]! } + public var SettingsSearch_Synonyms_Privacy_Title: String { return self._s[1210]! } + public var Notifications_PermissionsText: String { return self._s[1211]! } + public var SettingsSearch_Synonyms_Data_SaveIncomingPhotos: String { return self._s[1212]! } + public var Call_Flip: String { return self._s[1213]! } + public var Channel_AdminLog_CanDeleteMessagesOfOthers: String { return self._s[1215]! } + public var SocksProxySetup_ProxyStatusConnecting: String { return self._s[1216]! } + public var Wallet_TransactionInfo_StorageFeeInfoUrl: String { return self._s[1217]! } + public var PrivacyPhoneNumberSettings_DiscoveryHeader: String { return self._s[1218]! } + public var Channel_EditAdmin_PermissionPinMessages: String { return self._s[1220]! } + public var TwoStepAuth_ReEnterPasswordDescription: String { return self._s[1222]! } + public var Channel_TooMuchBots: String { return self._s[1224]! } + public var Passport_DeletePassportConfirmation: String { return self._s[1225]! } + public var Login_InvalidCodeError: String { return self._s[1226]! } + public var StickerPacksSettings_FeaturedPacks: String { return self._s[1227]! } public func ChatList_DeleteSecretChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1227]!, self._r[1227]!, [_0]) - } - public func GroupInfo_InvitationLinkAcceptChannel(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[1228]!, self._r[1228]!, [_0]) } - public var VoiceOver_Navigation_ProxySettings: String { return self._s[1229]! } - public var Call_CallInProgressTitle: String { return self._s[1230]! } - public var Month_ShortSeptember: String { return self._s[1231]! } - public var Watch_ChannelInfo_Title: String { return self._s[1232]! } - public var ChatList_DeleteSavedMessagesConfirmation: String { return self._s[1235]! } - public var DialogList_PasscodeLockHelp: String { return self._s[1236]! } - public var Chat_MultipleTextMessagesDisabled: String { return self._s[1237]! } - public var Wallet_Receive_Title: String { return self._s[1238]! } - public var Notifications_Badge_IncludePublicGroups: String { return self._s[1239]! } - public var Channel_AdminLogFilter_EventsTitle: String { return self._s[1240]! } - public var PhotoEditor_CropReset: String { return self._s[1241]! } - public var Group_Username_CreatePrivateLinkHelp: String { return self._s[1243]! } - public var Channel_Management_LabelEditor: String { return self._s[1244]! } - public var Passport_Identity_LatinNameHelp: String { return self._s[1246]! } - public var PhotoEditor_HighlightsTool: String { return self._s[1247]! } - public var Wallet_Info_WalletCreated: String { return self._s[1248]! } - public var UserInfo_Title: String { return self._s[1249]! } - public var ChatList_HideAction: String { return self._s[1250]! } - public var AccessDenied_Title: String { return self._s[1251]! } - public var DialogList_SearchLabel: String { return self._s[1252]! } - public var Group_Setup_HistoryHidden: String { return self._s[1253]! } - public var TwoStepAuth_PasswordChangeSuccess: String { return self._s[1254]! } - public var State_Updating: String { return self._s[1256]! } - public var Contacts_TabTitle: String { return self._s[1257]! } - public var Notifications_Badge_CountUnreadMessages: String { return self._s[1259]! } - public var GroupInfo_GroupHistory: String { return self._s[1260]! } - public var Conversation_UnsupportedMediaPlaceholder: String { return self._s[1261]! } - public var Wallpaper_SetColor: String { return self._s[1262]! } - public var CheckoutInfo_ShippingInfoCountry: String { return self._s[1263]! } - public var SettingsSearch_Synonyms_SavedMessages: String { return self._s[1264]! } - public var Chat_AttachmentLimitReached: String { return self._s[1265]! } - public var Passport_Identity_OneOfTypeDriversLicense: String { return self._s[1266]! } - public var Contacts_NotRegisteredSection: String { return self._s[1267]! } + public func GroupInfo_InvitationLinkAcceptChannel(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1229]!, self._r[1229]!, [_0]) + } + public var VoiceOver_Navigation_ProxySettings: String { return self._s[1230]! } + public var Call_CallInProgressTitle: String { return self._s[1231]! } + public var Month_ShortSeptember: String { return self._s[1232]! } + public var Watch_ChannelInfo_Title: String { return self._s[1233]! } + public var ChatList_DeleteSavedMessagesConfirmation: String { return self._s[1236]! } + public var DialogList_PasscodeLockHelp: String { return self._s[1237]! } + public var Chat_MultipleTextMessagesDisabled: String { return self._s[1238]! } + public var Wallet_Receive_Title: String { return self._s[1239]! } + public var Notifications_Badge_IncludePublicGroups: String { return self._s[1240]! } + public var Channel_AdminLogFilter_EventsTitle: String { return self._s[1241]! } + public var PhotoEditor_CropReset: String { return self._s[1242]! } + public var Group_Username_CreatePrivateLinkHelp: String { return self._s[1244]! } + public var Channel_Management_LabelEditor: String { return self._s[1245]! } + public var Passport_Identity_LatinNameHelp: String { return self._s[1247]! } + public var PhotoEditor_HighlightsTool: String { return self._s[1248]! } + public var Wallet_Info_WalletCreated: String { return self._s[1249]! } + public var UserInfo_Title: String { return self._s[1250]! } + public var ChatList_HideAction: String { return self._s[1251]! } + public var AccessDenied_Title: String { return self._s[1252]! } + public var DialogList_SearchLabel: String { return self._s[1253]! } + public var Group_Setup_HistoryHidden: String { return self._s[1254]! } + public var TwoStepAuth_PasswordChangeSuccess: String { return self._s[1255]! } + public var State_Updating: String { return self._s[1257]! } + public var Contacts_TabTitle: String { return self._s[1258]! } + public var Notifications_Badge_CountUnreadMessages: String { return self._s[1260]! } + public var GroupInfo_GroupHistory: String { return self._s[1261]! } + public var Conversation_UnsupportedMediaPlaceholder: String { return self._s[1262]! } + public var Wallpaper_SetColor: String { return self._s[1263]! } + public var CheckoutInfo_ShippingInfoCountry: String { return self._s[1264]! } + public var SettingsSearch_Synonyms_SavedMessages: String { return self._s[1265]! } + public var Chat_AttachmentLimitReached: String { return self._s[1266]! } + public var Passport_Identity_OneOfTypeDriversLicense: String { return self._s[1267]! } + public var Contacts_NotRegisteredSection: String { return self._s[1268]! } public func Time_PreciseDate_m4(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1268]!, self._r[1268]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1269]!, self._r[1269]!, [_1, _2, _3]) } - public var Paint_Clear: String { return self._s[1269]! } - public var StickerPacksSettings_ArchivedMasks: String { return self._s[1270]! } - public var SocksProxySetup_Connecting: String { return self._s[1271]! } - public var ExplicitContent_AlertChannel: String { return self._s[1272]! } - public var CreatePoll_AllOptionsAdded: String { return self._s[1273]! } - public var Conversation_Contact: String { return self._s[1274]! } - public var Login_CodeExpired: String { return self._s[1275]! } - public var Passport_DiscardMessageAction: String { return self._s[1276]! } - public var ChatList_Context_Unpin: String { return self._s[1277]! } - public var Channel_AdminLog_MessagePreviousDescription: String { return self._s[1278]! } + public var Paint_Clear: String { return self._s[1270]! } + public var StickerPacksSettings_ArchivedMasks: String { return self._s[1271]! } + public var SocksProxySetup_Connecting: String { return self._s[1272]! } + public var ExplicitContent_AlertChannel: String { return self._s[1273]! } + public var CreatePoll_AllOptionsAdded: String { return self._s[1274]! } + public var Conversation_Contact: String { return self._s[1275]! } + public var Login_CodeExpired: String { return self._s[1276]! } + public var Passport_DiscardMessageAction: String { return self._s[1277]! } + public var ChatList_Context_Unpin: String { return self._s[1278]! } + public var Channel_AdminLog_MessagePreviousDescription: String { return self._s[1279]! } public func VoiceOver_Chat_MusicFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1279]!, self._r[1279]!, [_0]) + return formatWithArgumentRanges(self._s[1280]!, self._r[1280]!, [_0]) } - public var Channel_AdminLog_EmptyMessageText: String { return self._s[1280]! } - public var SettingsSearch_Synonyms_Data_NetworkUsage: String { return self._s[1281]! } + public var Channel_AdminLog_EmptyMessageText: String { return self._s[1281]! } + public var SettingsSearch_Synonyms_Data_NetworkUsage: String { return self._s[1282]! } public func Group_EditAdmin_RankInfo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1282]!, self._r[1282]!, [_0]) + return formatWithArgumentRanges(self._s[1283]!, self._r[1283]!, [_0]) } - public var Month_ShortApril: String { return self._s[1283]! } - public var AuthSessions_CurrentSession: String { return self._s[1284]! } - public var Chat_AttachmentMultipleFilesDisabled: String { return self._s[1287]! } - public var Wallet_Navigation_Cancel: String { return self._s[1289]! } - public var WallpaperPreview_CropTopText: String { return self._s[1290]! } - public var PrivacySettings_DeleteAccountIfAwayFor: String { return self._s[1291]! } - public var CheckoutInfo_ShippingInfoTitle: String { return self._s[1292]! } + public var Month_ShortApril: String { return self._s[1284]! } + public var AuthSessions_CurrentSession: String { return self._s[1285]! } + public var Chat_AttachmentMultipleFilesDisabled: String { return self._s[1288]! } + public var Wallet_Navigation_Cancel: String { return self._s[1290]! } + public var WallpaperPreview_CropTopText: String { return self._s[1291]! } + public var PrivacySettings_DeleteAccountIfAwayFor: String { return self._s[1292]! } + public var CheckoutInfo_ShippingInfoTitle: String { return self._s[1293]! } public func Conversation_ScheduleMessage_SendOn(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1293]!, self._r[1293]!, [_0, _1]) + return formatWithArgumentRanges(self._s[1294]!, self._r[1294]!, [_0, _1]) } - public var Appearance_ThemePreview_Chat_2_Text: String { return self._s[1294]! } - public var Channel_Setup_TypePrivate: String { return self._s[1296]! } - public var Forward_ChannelReadOnly: String { return self._s[1299]! } - public var PhotoEditor_CurvesBlue: String { return self._s[1300]! } - public var AddContact_SharedContactException: String { return self._s[1301]! } - public var UserInfo_BotPrivacy: String { return self._s[1303]! } - public var Wallet_CreateInvoice_Title: String { return self._s[1304]! } - public var Notification_PassportValueEmail: String { return self._s[1305]! } - public var EmptyGroupInfo_Subtitle: String { return self._s[1306]! } - public var GroupPermission_NewTitle: String { return self._s[1307]! } - public var CallFeedback_ReasonDropped: String { return self._s[1308]! } - public var GroupInfo_Permissions_AddException: String { return self._s[1309]! } - public var Channel_SignMessages_Help: String { return self._s[1311]! } - public var Undo_ChatDeleted: String { return self._s[1313]! } - public var Conversation_ChatBackground: String { return self._s[1314]! } + public var Appearance_ThemePreview_Chat_2_Text: String { return self._s[1295]! } + public var Channel_Setup_TypePrivate: String { return self._s[1297]! } + public var Forward_ChannelReadOnly: String { return self._s[1300]! } + public var PhotoEditor_CurvesBlue: String { return self._s[1301]! } + public var AddContact_SharedContactException: String { return self._s[1302]! } + public var UserInfo_BotPrivacy: String { return self._s[1304]! } + public var Wallet_CreateInvoice_Title: String { return self._s[1305]! } + public var Notification_PassportValueEmail: String { return self._s[1306]! } + public var EmptyGroupInfo_Subtitle: String { return self._s[1307]! } + public var GroupPermission_NewTitle: String { return self._s[1308]! } + public var CallFeedback_ReasonDropped: String { return self._s[1309]! } + public var GroupInfo_Permissions_AddException: String { return self._s[1310]! } + public var Channel_SignMessages_Help: String { return self._s[1312]! } + public var Undo_ChatDeleted: String { return self._s[1314]! } + public var Conversation_ChatBackground: String { return self._s[1315]! } public func Wallet_WordCheck_Text(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1315]!, self._r[1315]!, [_1, _2, _3]) - } - public func PUSH_CHAT_MESSAGE_QUIZ(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[1316]!, self._r[1316]!, [_1, _2, _3]) } - public var ChannelMembers_WhoCanAddMembers_Admins: String { return self._s[1317]! } - public var FastTwoStepSetup_EmailPlaceholder: String { return self._s[1318]! } - public var Passport_Language_pt: String { return self._s[1319]! } - public var VoiceOver_Chat_YourVoiceMessage: String { return self._s[1320]! } - public var NotificationsSound_Popcorn: String { return self._s[1323]! } - public var AutoNightTheme_Disabled: String { return self._s[1324]! } - public var BlockedUsers_LeavePrefix: String { return self._s[1325]! } - public var WallpaperPreview_CustomColorTopText: String { return self._s[1326]! } - public var Contacts_PermissionsSuppressWarningText: String { return self._s[1327]! } - public var WallpaperSearch_ColorBlue: String { return self._s[1328]! } + public func PUSH_CHAT_MESSAGE_QUIZ(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1317]!, self._r[1317]!, [_1, _2, _3]) + } + public var ChannelMembers_WhoCanAddMembers_Admins: String { return self._s[1318]! } + public var FastTwoStepSetup_EmailPlaceholder: String { return self._s[1319]! } + public var Passport_Language_pt: String { return self._s[1320]! } + public var VoiceOver_Chat_YourVoiceMessage: String { return self._s[1321]! } + public var NotificationsSound_Popcorn: String { return self._s[1324]! } + public var AutoNightTheme_Disabled: String { return self._s[1325]! } + public var BlockedUsers_LeavePrefix: String { return self._s[1326]! } + public var WallpaperPreview_CustomColorTopText: String { return self._s[1327]! } + public var Contacts_PermissionsSuppressWarningText: String { return self._s[1328]! } + public var WallpaperSearch_ColorBlue: String { return self._s[1329]! } public func CancelResetAccount_TextSMS(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1329]!, self._r[1329]!, [_0]) + return formatWithArgumentRanges(self._s[1330]!, self._r[1330]!, [_0]) } - public var CheckoutInfo_ErrorNameInvalid: String { return self._s[1330]! } - public var SocksProxySetup_UseForCalls: String { return self._s[1331]! } - public var Passport_DeleteDocumentConfirmation: String { return self._s[1333]! } + public var CheckoutInfo_ErrorNameInvalid: String { return self._s[1331]! } + public var SocksProxySetup_UseForCalls: String { return self._s[1332]! } + public var Passport_DeleteDocumentConfirmation: String { return self._s[1334]! } public func Conversation_Megabytes(_ _0: Float) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1334]!, self._r[1334]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[1335]!, self._r[1335]!, ["\(_0)"]) } - public var SocksProxySetup_Hostname: String { return self._s[1337]! } - public var ChatSettings_AutoDownloadSettings_OffForAll: String { return self._s[1338]! } - public var Compose_NewEncryptedChat: String { return self._s[1339]! } - public var Login_CodeFloodError: String { return self._s[1340]! } - public var Calls_TabTitle: String { return self._s[1341]! } - public var Privacy_ProfilePhoto: String { return self._s[1342]! } - public var Passport_Language_he: String { return self._s[1343]! } + public var SocksProxySetup_Hostname: String { return self._s[1338]! } + public var ChatSettings_AutoDownloadSettings_OffForAll: String { return self._s[1339]! } + public var Compose_NewEncryptedChat: String { return self._s[1340]! } + public var Login_CodeFloodError: String { return self._s[1341]! } + public var Calls_TabTitle: String { return self._s[1342]! } + public var Privacy_ProfilePhoto: String { return self._s[1343]! } + public var Passport_Language_he: String { return self._s[1344]! } public func Conversation_SetReminder_RemindToday(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1344]!, self._r[1344]!, [_0]) + return formatWithArgumentRanges(self._s[1345]!, self._r[1345]!, [_0]) } - public var GroupPermission_Title: String { return self._s[1345]! } + public var GroupPermission_Title: String { return self._s[1346]! } public func Channel_AdminLog_MessageGroupPreHistoryHidden(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1346]!, self._r[1346]!, [_0]) + return formatWithArgumentRanges(self._s[1347]!, self._r[1347]!, [_0]) } - public var Wallet_TransactionInfo_SenderHeader: String { return self._s[1347]! } - public var GroupPermission_NoChangeInfo: String { return self._s[1348]! } - public var ChatList_DeleteForCurrentUser: String { return self._s[1349]! } - public var Tour_Text1: String { return self._s[1350]! } - public var Channel_EditAdmin_TransferOwnership: String { return self._s[1351]! } - public var Month_ShortFebruary: String { return self._s[1352]! } - public var TwoStepAuth_EmailSkip: String { return self._s[1353]! } + public var Wallet_TransactionInfo_SenderHeader: String { return self._s[1348]! } + public var GroupPermission_NoChangeInfo: String { return self._s[1349]! } + public var ChatList_DeleteForCurrentUser: String { return self._s[1350]! } + public var Tour_Text1: String { return self._s[1351]! } + public var Channel_EditAdmin_TransferOwnership: String { return self._s[1352]! } + public var Month_ShortFebruary: String { return self._s[1353]! } + public var TwoStepAuth_EmailSkip: String { return self._s[1354]! } public func Wallet_Time_PreciseDate_m4(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1354]!, self._r[1354]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1355]!, self._r[1355]!, [_1, _2, _3]) } - public var NotificationsSound_Glass: String { return self._s[1355]! } - public var Appearance_ThemeNightBlue: String { return self._s[1356]! } - public var CheckoutInfo_Pay: String { return self._s[1357]! } - public var Invite_LargeRecipientsCountWarning: String { return self._s[1359]! } - public var Call_CallAgain: String { return self._s[1361]! } - public var AttachmentMenu_SendAsFile: String { return self._s[1362]! } - public var AccessDenied_MicrophoneRestricted: String { return self._s[1363]! } - public var Passport_InvalidPasswordError: String { return self._s[1364]! } - public var Watch_Message_Game: String { return self._s[1365]! } - public var Stickers_Install: String { return self._s[1366]! } - public var VoiceOver_Chat_Message: String { return self._s[1367]! } - public var PrivacyLastSeenSettings_NeverShareWith: String { return self._s[1368]! } - public var Passport_Identity_ResidenceCountry: String { return self._s[1370]! } - public var Notifications_GroupNotificationsHelp: String { return self._s[1371]! } - public var AuthSessions_OtherSessions: String { return self._s[1372]! } - public var Channel_Username_Help: String { return self._s[1373]! } - public var Camera_Title: String { return self._s[1374]! } - public var IntentsSettings_Title: String { return self._s[1375]! } - public var GroupInfo_SetGroupPhotoDelete: String { return self._s[1377]! } - public var Privacy_ProfilePhoto_NeverShareWith_Title: String { return self._s[1378]! } - public var Channel_AdminLog_SendPolls: String { return self._s[1379]! } - public var Channel_AdminLog_TitleAllEvents: String { return self._s[1380]! } - public var Channel_EditAdmin_PermissionInviteMembers: String { return self._s[1381]! } - public var Contacts_MemberSearchSectionTitleGroup: String { return self._s[1382]! } - public var ScheduledMessages_DeleteMany: String { return self._s[1383]! } - public var Conversation_RestrictedStickers: String { return self._s[1384]! } - public var Notifications_ExceptionsResetToDefaults: String { return self._s[1386]! } - public var UserInfo_TelegramCall: String { return self._s[1388]! } - public var TwoStepAuth_SetupResendEmailCode: String { return self._s[1389]! } - public var CreatePoll_OptionsHeader: String { return self._s[1390]! } - public var SettingsSearch_Synonyms_Data_CallsUseLessData: String { return self._s[1391]! } - public var ArchivedChats_IntroTitle1: String { return self._s[1392]! } - public var Privacy_GroupsAndChannels_AlwaysAllow_Title: String { return self._s[1393]! } - public var Theme_Colors_Proceed: String { return self._s[1394]! } - public var Passport_Identity_EditPersonalDetails: String { return self._s[1395]! } + public var NotificationsSound_Glass: String { return self._s[1356]! } + public var Appearance_ThemeNightBlue: String { return self._s[1357]! } + public var CheckoutInfo_Pay: String { return self._s[1358]! } + public var Invite_LargeRecipientsCountWarning: String { return self._s[1360]! } + public var Call_CallAgain: String { return self._s[1362]! } + public var AttachmentMenu_SendAsFile: String { return self._s[1363]! } + public var AccessDenied_MicrophoneRestricted: String { return self._s[1364]! } + public var Passport_InvalidPasswordError: String { return self._s[1365]! } + public var Watch_Message_Game: String { return self._s[1366]! } + public var Stickers_Install: String { return self._s[1367]! } + public var VoiceOver_Chat_Message: String { return self._s[1368]! } + public var PrivacyLastSeenSettings_NeverShareWith: String { return self._s[1369]! } + public var Passport_Identity_ResidenceCountry: String { return self._s[1371]! } + public var Notifications_GroupNotificationsHelp: String { return self._s[1372]! } + public var AuthSessions_OtherSessions: String { return self._s[1373]! } + public var Channel_Username_Help: String { return self._s[1374]! } + public var Camera_Title: String { return self._s[1375]! } + public var IntentsSettings_Title: String { return self._s[1376]! } + public var GroupInfo_SetGroupPhotoDelete: String { return self._s[1378]! } + public var Privacy_ProfilePhoto_NeverShareWith_Title: String { return self._s[1379]! } + public var Channel_AdminLog_SendPolls: String { return self._s[1380]! } + public var Channel_AdminLog_TitleAllEvents: String { return self._s[1381]! } + public var Channel_EditAdmin_PermissionInviteMembers: String { return self._s[1382]! } + public var Contacts_MemberSearchSectionTitleGroup: String { return self._s[1383]! } + public var ScheduledMessages_DeleteMany: String { return self._s[1384]! } + public var Conversation_RestrictedStickers: String { return self._s[1385]! } + public var Notifications_ExceptionsResetToDefaults: String { return self._s[1387]! } + public var UserInfo_TelegramCall: String { return self._s[1389]! } + public var TwoStepAuth_SetupResendEmailCode: String { return self._s[1390]! } + public var CreatePoll_OptionsHeader: String { return self._s[1391]! } + public var SettingsSearch_Synonyms_Data_CallsUseLessData: String { return self._s[1392]! } + public var ArchivedChats_IntroTitle1: String { return self._s[1393]! } + public var Privacy_GroupsAndChannels_AlwaysAllow_Title: String { return self._s[1394]! } + public var Theme_Colors_Proceed: String { return self._s[1395]! } + public var Passport_Identity_EditPersonalDetails: String { return self._s[1396]! } public func Time_PreciseDate_m1(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1396]!, self._r[1396]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1397]!, self._r[1397]!, [_1, _2, _3]) } - public var Wallet_Month_GenAugust: String { return self._s[1397]! } - public var Settings_SaveEditedPhotos: String { return self._s[1398]! } - public var TwoStepAuth_ConfirmationTitle: String { return self._s[1399]! } - public var Privacy_GroupsAndChannels_NeverAllow_Title: String { return self._s[1400]! } - public var Conversation_MessageDialogRetry: String { return self._s[1401]! } - public var ChatList_Context_MarkAsUnread: String { return self._s[1402]! } - public var MessagePoll_SubmitVote: String { return self._s[1403]! } - public var Conversation_DiscardVoiceMessageAction: String { return self._s[1404]! } - public var Permissions_PeopleNearbyTitle_v0: String { return self._s[1405]! } - public var Group_Setup_TypeHeader: String { return self._s[1406]! } - public var Paint_RecentStickers: String { return self._s[1407]! } - public var PhotoEditor_GrainTool: String { return self._s[1408]! } - public var CheckoutInfo_ShippingInfoState: String { return self._s[1409]! } - public var EmptyGroupInfo_Line4: String { return self._s[1410]! } - public var Watch_AuthRequired: String { return self._s[1412]! } + public var Wallet_Month_GenAugust: String { return self._s[1398]! } + public var Settings_SaveEditedPhotos: String { return self._s[1399]! } + public var TwoStepAuth_ConfirmationTitle: String { return self._s[1400]! } + public var Privacy_GroupsAndChannels_NeverAllow_Title: String { return self._s[1401]! } + public var Conversation_MessageDialogRetry: String { return self._s[1402]! } + public var ChatList_Context_MarkAsUnread: String { return self._s[1403]! } + public var MessagePoll_SubmitVote: String { return self._s[1404]! } + public var Conversation_DiscardVoiceMessageAction: String { return self._s[1405]! } + public var Permissions_PeopleNearbyTitle_v0: String { return self._s[1406]! } + public var Group_Setup_TypeHeader: String { return self._s[1407]! } + public var Paint_RecentStickers: String { return self._s[1408]! } + public var PhotoEditor_GrainTool: String { return self._s[1409]! } + public var CheckoutInfo_ShippingInfoState: String { return self._s[1410]! } + public var EmptyGroupInfo_Line4: String { return self._s[1411]! } + public var Watch_AuthRequired: String { return self._s[1413]! } public func Passport_Email_UseTelegramEmail(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1413]!, self._r[1413]!, [_0]) + return formatWithArgumentRanges(self._s[1414]!, self._r[1414]!, [_0]) } - public var Conversation_EncryptedDescriptionTitle: String { return self._s[1414]! } - public var ChannelIntro_Text: String { return self._s[1415]! } - public var DialogList_DeleteBotConfirmation: String { return self._s[1416]! } - public var GroupPermission_NoSendMedia: String { return self._s[1417]! } - public var Calls_AddTab: String { return self._s[1418]! } - public var Message_ReplyActionButtonShowReceipt: String { return self._s[1419]! } - public var Channel_AdminLog_EmptyFilterText: String { return self._s[1420]! } - public var Conversation_WalletRequiredSetup: String { return self._s[1421]! } - public var Notification_MessageLifetime1d: String { return self._s[1422]! } - public var Notifications_ChannelNotificationsExceptionsHelp: String { return self._s[1423]! } - public var Channel_BanUser_PermissionsHeader: String { return self._s[1424]! } - public var Passport_Identity_GenderFemale: String { return self._s[1425]! } - public var BlockedUsers_BlockTitle: String { return self._s[1426]! } + public var Conversation_EncryptedDescriptionTitle: String { return self._s[1415]! } + public var ChannelIntro_Text: String { return self._s[1416]! } + public var DialogList_DeleteBotConfirmation: String { return self._s[1417]! } + public var GroupPermission_NoSendMedia: String { return self._s[1418]! } + public var Calls_AddTab: String { return self._s[1419]! } + public var Message_ReplyActionButtonShowReceipt: String { return self._s[1420]! } + public var Channel_AdminLog_EmptyFilterText: String { return self._s[1421]! } + public var Conversation_WalletRequiredSetup: String { return self._s[1422]! } + public var Notification_MessageLifetime1d: String { return self._s[1423]! } + public var Notifications_ChannelNotificationsExceptionsHelp: String { return self._s[1424]! } + public var Channel_BanUser_PermissionsHeader: String { return self._s[1425]! } + public var Passport_Identity_GenderFemale: String { return self._s[1426]! } + public var BlockedUsers_BlockTitle: String { return self._s[1427]! } public func PUSH_CHANNEL_MESSAGE_GIF(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1427]!, self._r[1427]!, [_1]) + return formatWithArgumentRanges(self._s[1428]!, self._r[1428]!, [_1]) } - public var Weekday_Yesterday: String { return self._s[1428]! } - public var WallpaperSearch_ColorBlack: String { return self._s[1429]! } - public var Settings_Context_Logout: String { return self._s[1430]! } - public var Wallet_Info_UnknownTransaction: String { return self._s[1431]! } - public var ChatList_ArchiveAction: String { return self._s[1432]! } - public var AutoNightTheme_Scheduled: String { return self._s[1433]! } - public var TwoFactorSetup_Email_SkipAction: String { return self._s[1434]! } - public var Settings_Devices: String { return self._s[1435]! } - public var ContactInfo_Note: String { return self._s[1436]! } + public var Weekday_Yesterday: String { return self._s[1429]! } + public var WallpaperSearch_ColorBlack: String { return self._s[1430]! } + public var Settings_Context_Logout: String { return self._s[1431]! } + public var Wallet_Info_UnknownTransaction: String { return self._s[1432]! } + public var ChatList_ArchiveAction: String { return self._s[1433]! } + public var AutoNightTheme_Scheduled: String { return self._s[1434]! } + public var TwoFactorSetup_Email_SkipAction: String { return self._s[1435]! } + public var Settings_Devices: String { return self._s[1436]! } + public var ContactInfo_Note: String { return self._s[1437]! } public func Login_PhoneGenericEmailBody(_ _1: String, _ _2: String, _ _3: String, _ _4: String, _ _5: String, _ _6: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1437]!, self._r[1437]!, [_1, _2, _3, _4, _5, _6]) + return formatWithArgumentRanges(self._s[1438]!, self._r[1438]!, [_1, _2, _3, _4, _5, _6]) } - public var EditTheme_ThemeTemplateAlertTitle: String { return self._s[1438]! } - public var Wallet_Receive_CreateInvoice: String { return self._s[1439]! } - public var PrivacyPolicy_DeclineDeleteNow: String { return self._s[1440]! } - public var Theme_Colors_ColorWallpaperWarningProceed: String { return self._s[1441]! } + public var EditTheme_ThemeTemplateAlertTitle: String { return self._s[1439]! } + public var Wallet_Receive_CreateInvoice: String { return self._s[1440]! } + public var PrivacyPolicy_DeclineDeleteNow: String { return self._s[1441]! } + public var Theme_Colors_ColorWallpaperWarningProceed: String { return self._s[1442]! } public func PUSH_CHAT_JOINED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1442]!, self._r[1442]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1443]!, self._r[1443]!, [_1, _2]) } - public var CreatePoll_Create: String { return self._s[1443]! } - public var Channel_Members_AddBannedErrorAdmin: String { return self._s[1444]! } + public var CreatePoll_Create: String { return self._s[1444]! } + public var Channel_Members_AddBannedErrorAdmin: String { return self._s[1445]! } public func Notification_CallFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1445]!, self._r[1445]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1446]!, self._r[1446]!, [_1, _2]) } - public var ScheduledMessages_ClearAllConfirmation: String { return self._s[1446]! } - public var Checkout_ErrorProviderAccountInvalid: String { return self._s[1447]! } - public var Notifications_InAppNotificationsSounds: String { return self._s[1449]! } + public var ScheduledMessages_ClearAllConfirmation: String { return self._s[1447]! } + public var Checkout_ErrorProviderAccountInvalid: String { return self._s[1448]! } + public var Notifications_InAppNotificationsSounds: String { return self._s[1450]! } public func PUSH_PINNED_GAME_SCORE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1450]!, self._r[1450]!, [_1]) + return formatWithArgumentRanges(self._s[1451]!, self._r[1451]!, [_1]) } - public var Preview_OpenInInstagram: String { return self._s[1451]! } - public var Notification_MessageLifetimeRemovedOutgoing: String { return self._s[1452]! } + public var Preview_OpenInInstagram: String { return self._s[1452]! } + public var Notification_MessageLifetimeRemovedOutgoing: String { return self._s[1453]! } public func PUSH_CHAT_ADD_MEMBER(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1453]!, self._r[1453]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1454]!, self._r[1454]!, [_1, _2, _3]) } public func Passport_PrivacyPolicy(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1454]!, self._r[1454]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1455]!, self._r[1455]!, [_1, _2]) } - public var Channel_AdminLog_InfoPanelAlertTitle: String { return self._s[1455]! } - public var ArchivedChats_IntroText3: String { return self._s[1456]! } - public var ChatList_UndoArchiveHiddenText: String { return self._s[1457]! } - public var NetworkUsageSettings_TotalSection: String { return self._s[1458]! } - public var Wallet_Month_GenSeptember: String { return self._s[1459]! } - public var Channel_Setup_TypePrivateHelp: String { return self._s[1460]! } + public var Channel_AdminLog_InfoPanelAlertTitle: String { return self._s[1456]! } + public var ArchivedChats_IntroText3: String { return self._s[1457]! } + public var ChatList_UndoArchiveHiddenText: String { return self._s[1458]! } + public var NetworkUsageSettings_TotalSection: String { return self._s[1459]! } + public var Wallet_Month_GenSeptember: String { return self._s[1460]! } + public var Channel_Setup_TypePrivateHelp: String { return self._s[1461]! } public func PUSH_CHAT_MESSAGE_POLL(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1461]!, self._r[1461]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1462]!, self._r[1462]!, [_1, _2, _3]) } - public var Privacy_GroupsAndChannels_NeverAllow_Placeholder: String { return self._s[1463]! } - public var FastTwoStepSetup_HintSection: String { return self._s[1464]! } - public var Wallpaper_PhotoLibrary: String { return self._s[1465]! } - public var TwoStepAuth_SetupResendEmailCodeAlert: String { return self._s[1466]! } - public var Gif_NoGifsFound: String { return self._s[1467]! } - public var Watch_LastSeen_WithinAMonth: String { return self._s[1468]! } - public var VoiceOver_MessageContextDelete: String { return self._s[1469]! } - public var EditTheme_Preview: String { return self._s[1470]! } + public var Privacy_GroupsAndChannels_NeverAllow_Placeholder: String { return self._s[1464]! } + public var FastTwoStepSetup_HintSection: String { return self._s[1465]! } + public var Wallpaper_PhotoLibrary: String { return self._s[1466]! } + public var TwoStepAuth_SetupResendEmailCodeAlert: String { return self._s[1467]! } + public var Gif_NoGifsFound: String { return self._s[1468]! } + public var Watch_LastSeen_WithinAMonth: String { return self._s[1469]! } + public var VoiceOver_MessageContextDelete: String { return self._s[1470]! } + public var EditTheme_Preview: String { return self._s[1471]! } public func ClearCache_StorageTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1471]!, self._r[1471]!, [_0]) + return formatWithArgumentRanges(self._s[1472]!, self._r[1472]!, [_0]) } - public var GroupInfo_ActionPromote: String { return self._s[1472]! } - public var PasscodeSettings_SimplePasscode: String { return self._s[1473]! } - public var GroupInfo_Permissions_Title: String { return self._s[1474]! } - public var Permissions_ContactsText_v0: String { return self._s[1475]! } - public var PrivacyPhoneNumberSettings_CustomDisabledHelp: String { return self._s[1476]! } - public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedPublicGroups: String { return self._s[1477]! } - public var PrivacySettings_DataSettingsHelp: String { return self._s[1480]! } - public var Passport_FieldEmailHelp: String { return self._s[1481]! } + public var GroupInfo_ActionPromote: String { return self._s[1473]! } + public var PasscodeSettings_SimplePasscode: String { return self._s[1474]! } + public var GroupInfo_Permissions_Title: String { return self._s[1475]! } + public var Permissions_ContactsText_v0: String { return self._s[1476]! } + public var PrivacyPhoneNumberSettings_CustomDisabledHelp: String { return self._s[1477]! } + public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedPublicGroups: String { return self._s[1478]! } + public var PrivacySettings_DataSettingsHelp: String { return self._s[1481]! } + public var Passport_FieldEmailHelp: String { return self._s[1482]! } public func Activity_RemindAboutUser(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1482]!, self._r[1482]!, [_0]) + return formatWithArgumentRanges(self._s[1483]!, self._r[1483]!, [_0]) } - public var Passport_Identity_GenderPlaceholder: String { return self._s[1483]! } - public var Weekday_ShortSaturday: String { return self._s[1484]! } - public var ContactInfo_PhoneLabelMain: String { return self._s[1485]! } - public var Watch_Conversation_UserInfo: String { return self._s[1486]! } - public var CheckoutInfo_ShippingInfoCityPlaceholder: String { return self._s[1487]! } - public var GroupPermission_PermissionDisabledByDefault: String { return self._s[1488]! } - public var PrivacyLastSeenSettings_Title: String { return self._s[1489]! } - public var Conversation_ShareBotLocationConfirmation: String { return self._s[1490]! } - public var PhotoEditor_VignetteTool: String { return self._s[1491]! } - public var Passport_Address_Street1Placeholder: String { return self._s[1492]! } - public var Passport_Language_et: String { return self._s[1493]! } - public var AppUpgrade_Running: String { return self._s[1494]! } - public var Channel_DiscussionGroup_Info: String { return self._s[1496]! } - public var EditTheme_Create_Preview_IncomingReplyName: String { return self._s[1497]! } - public var Passport_Language_bg: String { return self._s[1498]! } - public var Stickers_NoStickersFound: String { return self._s[1500]! } + public var Passport_Identity_GenderPlaceholder: String { return self._s[1484]! } + public var Weekday_ShortSaturday: String { return self._s[1485]! } + public var ContactInfo_PhoneLabelMain: String { return self._s[1486]! } + public var Watch_Conversation_UserInfo: String { return self._s[1487]! } + public var CheckoutInfo_ShippingInfoCityPlaceholder: String { return self._s[1488]! } + public var GroupPermission_PermissionDisabledByDefault: String { return self._s[1489]! } + public var PrivacyLastSeenSettings_Title: String { return self._s[1490]! } + public var Conversation_ShareBotLocationConfirmation: String { return self._s[1491]! } + public var PhotoEditor_VignetteTool: String { return self._s[1492]! } + public var Passport_Address_Street1Placeholder: String { return self._s[1493]! } + public var Passport_Language_et: String { return self._s[1494]! } + public var AppUpgrade_Running: String { return self._s[1495]! } + public var Channel_DiscussionGroup_Info: String { return self._s[1497]! } + public var EditTheme_Create_Preview_IncomingReplyName: String { return self._s[1498]! } + public var Passport_Language_bg: String { return self._s[1499]! } + public var Stickers_NoStickersFound: String { return self._s[1501]! } public func PUSH_CHANNEL_MESSAGE_TEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1502]!, self._r[1502]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1503]!, self._r[1503]!, [_1, _2]) } public func VoiceOver_Chat_ContactFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1503]!, self._r[1503]!, [_0]) + return formatWithArgumentRanges(self._s[1504]!, self._r[1504]!, [_0]) } - public var Wallet_Month_GenJuly: String { return self._s[1504]! } - public var Wallet_Receive_AddressHeader: String { return self._s[1505]! } - public var Wallet_Send_AmountText: String { return self._s[1506]! } - public var Settings_About: String { return self._s[1507]! } + public var Wallet_Month_GenJuly: String { return self._s[1505]! } + public var Wallet_Receive_AddressHeader: String { return self._s[1506]! } + public var Wallet_Send_AmountText: String { return self._s[1507]! } + public var Settings_About: String { return self._s[1508]! } public func Channel_AdminLog_MessageRestricted(_ _0: String, _ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1508]!, self._r[1508]!, [_0, _1, _2]) + return formatWithArgumentRanges(self._s[1509]!, self._r[1509]!, [_0, _1, _2]) } - public var ChatList_Context_MarkAsRead: String { return self._s[1510]! } - public var KeyCommand_NewMessage: String { return self._s[1511]! } - public var Group_ErrorAddBlocked: String { return self._s[1512]! } + public var ChatList_Context_MarkAsRead: String { return self._s[1511]! } + public var KeyCommand_NewMessage: String { return self._s[1512]! } + public var Group_ErrorAddBlocked: String { return self._s[1513]! } public func Message_PaymentSent(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1513]!, self._r[1513]!, [_0]) + return formatWithArgumentRanges(self._s[1514]!, self._r[1514]!, [_0]) } - public var Map_LocationTitle: String { return self._s[1514]! } - public var ReportGroupLocation_Title: String { return self._s[1515]! } - public var CallSettings_UseLessDataLongDescription: String { return self._s[1516]! } - public var Cache_ClearProgress: String { return self._s[1517]! } + public var Map_LocationTitle: String { return self._s[1515]! } + public var ReportGroupLocation_Title: String { return self._s[1516]! } + public var CallSettings_UseLessDataLongDescription: String { return self._s[1517]! } + public var Cache_ClearProgress: String { return self._s[1518]! } public func Channel_Management_ErrorNotMember(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1518]!, self._r[1518]!, [_0]) + return formatWithArgumentRanges(self._s[1519]!, self._r[1519]!, [_0]) } - public var GroupRemoved_AddToGroup: String { return self._s[1519]! } - public var Passport_UpdateRequiredError: String { return self._s[1520]! } - public var Wallet_SecureStorageNotAvailable_Text: String { return self._s[1521]! } + public var GroupRemoved_AddToGroup: String { return self._s[1520]! } + public var Passport_UpdateRequiredError: String { return self._s[1521]! } + public var Wallet_SecureStorageNotAvailable_Text: String { return self._s[1522]! } public func PUSH_MESSAGE_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1522]!, self._r[1522]!, [_1]) + return formatWithArgumentRanges(self._s[1523]!, self._r[1523]!, [_1]) } - public var Notifications_PermissionsSuppressWarningText: String { return self._s[1524]! } - public var Passport_Identity_MainPageHelp: String { return self._s[1525]! } - public var Conversation_StatusKickedFromGroup: String { return self._s[1526]! } - public var Passport_Language_ka: String { return self._s[1527]! } + public var Notifications_PermissionsSuppressWarningText: String { return self._s[1525]! } + public var Passport_Identity_MainPageHelp: String { return self._s[1526]! } + public var Conversation_StatusKickedFromGroup: String { return self._s[1527]! } + public var Passport_Language_ka: String { return self._s[1528]! } public func Wallet_Time_PreciseDate_m12(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1528]!, self._r[1528]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1529]!, self._r[1529]!, [_1, _2, _3]) } - public var Call_Decline: String { return self._s[1529]! } - public var SocksProxySetup_ProxyEnabled: String { return self._s[1530]! } - public var TwoFactorSetup_Email_SkipConfirmationText: String { return self._s[1533]! } + public var Call_Decline: String { return self._s[1530]! } + public var SocksProxySetup_ProxyEnabled: String { return self._s[1531]! } + public var TwoFactorSetup_Email_SkipConfirmationText: String { return self._s[1534]! } public func AuthCode_Alert(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1534]!, self._r[1534]!, [_0]) + return formatWithArgumentRanges(self._s[1535]!, self._r[1535]!, [_0]) } - public var CallFeedback_Send: String { return self._s[1535]! } - public var EditTheme_EditTitle: String { return self._s[1536]! } + public var CallFeedback_Send: String { return self._s[1536]! } + public var EditTheme_EditTitle: String { return self._s[1537]! } public func Channel_AdminLog_MessagePromotedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1537]!, self._r[1537]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1538]!, self._r[1538]!, [_1, _2]) } - public var Passport_Phone_UseTelegramNumberHelp: String { return self._s[1538]! } + public var Passport_Phone_UseTelegramNumberHelp: String { return self._s[1539]! } public func Wallet_Updated_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1540]!, self._r[1540]!, [_0]) + return formatWithArgumentRanges(self._s[1541]!, self._r[1541]!, [_0]) } - public var SettingsSearch_Synonyms_Data_Title: String { return self._s[1541]! } - public var Passport_DeletePassport: String { return self._s[1542]! } - public var Appearance_AppIconFilled: String { return self._s[1543]! } - public var Privacy_Calls_P2PAlways: String { return self._s[1544]! } - public var Month_ShortDecember: String { return self._s[1545]! } - public var Channel_AdminLog_CanEditMessages: String { return self._s[1547]! } + public var SettingsSearch_Synonyms_Data_Title: String { return self._s[1542]! } + public var Passport_DeletePassport: String { return self._s[1543]! } + public var Appearance_AppIconFilled: String { return self._s[1544]! } + public var Privacy_Calls_P2PAlways: String { return self._s[1545]! } + public var Month_ShortDecember: String { return self._s[1546]! } + public var Channel_AdminLog_CanEditMessages: String { return self._s[1548]! } public func Contacts_AccessDeniedHelpLandscape(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1548]!, self._r[1548]!, [_0]) + return formatWithArgumentRanges(self._s[1549]!, self._r[1549]!, [_0]) } - public var Channel_Stickers_Searching: String { return self._s[1549]! } - public var Conversation_EncryptedDescription1: String { return self._s[1550]! } - public var Conversation_EncryptedDescription2: String { return self._s[1551]! } - public var PasscodeSettings_PasscodeOptions: String { return self._s[1552]! } - public var Conversation_EncryptedDescription3: String { return self._s[1554]! } - public var PhotoEditor_SharpenTool: String { return self._s[1555]! } - public var Wallet_Configuration_Title: String { return self._s[1556]! } + public var Channel_Stickers_Searching: String { return self._s[1550]! } + public var Conversation_EncryptedDescription1: String { return self._s[1551]! } + public var Conversation_EncryptedDescription2: String { return self._s[1552]! } + public var PasscodeSettings_PasscodeOptions: String { return self._s[1553]! } + public var Conversation_EncryptedDescription3: String { return self._s[1555]! } + public var PhotoEditor_SharpenTool: String { return self._s[1556]! } + public var Wallet_Configuration_Title: String { return self._s[1557]! } public func Conversation_AddNameToContacts(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1557]!, self._r[1557]!, [_0]) + return formatWithArgumentRanges(self._s[1558]!, self._r[1558]!, [_0]) } - public var Conversation_EncryptedDescription4: String { return self._s[1559]! } - public var Channel_Members_AddMembers: String { return self._s[1560]! } - public var Wallpaper_Search: String { return self._s[1561]! } - public var Weekday_Friday: String { return self._s[1563]! } - public var Privacy_ContactsSync: String { return self._s[1564]! } - public var SettingsSearch_Synonyms_Privacy_Data_ContactsReset: String { return self._s[1565]! } - public var ApplyLanguage_ChangeLanguageAction: String { return self._s[1566]! } + public var Conversation_EncryptedDescription4: String { return self._s[1560]! } + public var Channel_Members_AddMembers: String { return self._s[1561]! } + public var Wallpaper_Search: String { return self._s[1562]! } + public var Weekday_Friday: String { return self._s[1564]! } + public var Privacy_ContactsSync: String { return self._s[1565]! } + public var SettingsSearch_Synonyms_Privacy_Data_ContactsReset: String { return self._s[1566]! } + public var ApplyLanguage_ChangeLanguageAction: String { return self._s[1567]! } public func Channel_Management_RestrictedBy(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1567]!, self._r[1567]!, [_0]) + return formatWithArgumentRanges(self._s[1568]!, self._r[1568]!, [_0]) } - public var Wallet_Configuration_BlockchainIdHeader: String { return self._s[1568]! } - public var GroupInfo_Permissions_Removed: String { return self._s[1569]! } - public var ScheduledMessages_ScheduledOnline: String { return self._s[1570]! } - public var Passport_Identity_GenderMale: String { return self._s[1571]! } + public var Wallet_Configuration_BlockchainIdHeader: String { return self._s[1569]! } + public var GroupInfo_Permissions_Removed: String { return self._s[1570]! } + public var ScheduledMessages_ScheduledOnline: String { return self._s[1571]! } + public var Passport_Identity_GenderMale: String { return self._s[1572]! } public func Call_StatusBar(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1572]!, self._r[1572]!, [_0]) + return formatWithArgumentRanges(self._s[1573]!, self._r[1573]!, [_0]) } - public var Notifications_PermissionsKeepDisabled: String { return self._s[1573]! } - public var Conversation_JumpToDate: String { return self._s[1574]! } - public var Contacts_GlobalSearch: String { return self._s[1575]! } - public var AutoDownloadSettings_ResetHelp: String { return self._s[1576]! } - public var SettingsSearch_Synonyms_FAQ: String { return self._s[1577]! } - public var Profile_MessageLifetime1d: String { return self._s[1578]! } + public var Notifications_PermissionsKeepDisabled: String { return self._s[1574]! } + public var Conversation_JumpToDate: String { return self._s[1575]! } + public var Contacts_GlobalSearch: String { return self._s[1576]! } + public var AutoDownloadSettings_ResetHelp: String { return self._s[1577]! } + public var SettingsSearch_Synonyms_FAQ: String { return self._s[1578]! } + public var Profile_MessageLifetime1d: String { return self._s[1579]! } public func MESSAGE_INVOICE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1579]!, self._r[1579]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1580]!, self._r[1580]!, [_1, _2]) } - public var StickerPack_BuiltinPackName: String { return self._s[1582]! } + public var StickerPack_BuiltinPackName: String { return self._s[1583]! } public func PUSH_CHAT_MESSAGE_AUDIO(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1583]!, self._r[1583]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1584]!, self._r[1584]!, [_1, _2]) } - public var VoiceOver_Chat_RecordModeVoiceMessageInfo: String { return self._s[1584]! } - public var Passport_InfoTitle: String { return self._s[1586]! } - public var Notifications_PermissionsUnreachableText: String { return self._s[1587]! } + public var VoiceOver_Chat_RecordModeVoiceMessageInfo: String { return self._s[1585]! } + public var Passport_InfoTitle: String { return self._s[1587]! } + public var Notifications_PermissionsUnreachableText: String { return self._s[1588]! } public func NetworkUsageSettings_CellularUsageSince(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1591]!, self._r[1591]!, [_0]) + return formatWithArgumentRanges(self._s[1592]!, self._r[1592]!, [_0]) } public func PUSH_CHAT_MESSAGE_GEO(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1592]!, self._r[1592]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1593]!, self._r[1593]!, [_1, _2]) } - public var Passport_Address_TypePassportRegistrationUploadScan: String { return self._s[1593]! } - public var Profile_BotInfo: String { return self._s[1594]! } - public var Watch_Compose_CreateMessage: String { return self._s[1595]! } - public var AutoDownloadSettings_VoiceMessagesInfo: String { return self._s[1596]! } - public var Month_ShortNovember: String { return self._s[1597]! } - public var Conversation_ScamWarning: String { return self._s[1598]! } - public var Wallpaper_SetCustomBackground: String { return self._s[1599]! } - public var Appearance_TextSize_Title: String { return self._s[1600]! } - public var Passport_Identity_TranslationsHelp: String { return self._s[1601]! } - public var NotificationsSound_Chime: String { return self._s[1602]! } - public var Passport_Language_ko: String { return self._s[1604]! } - public var InviteText_URL: String { return self._s[1605]! } - public var TextFormat_Monospace: String { return self._s[1606]! } + public var Passport_Address_TypePassportRegistrationUploadScan: String { return self._s[1594]! } + public var Profile_BotInfo: String { return self._s[1595]! } + public var Watch_Compose_CreateMessage: String { return self._s[1596]! } + public var AutoDownloadSettings_VoiceMessagesInfo: String { return self._s[1597]! } + public var Month_ShortNovember: String { return self._s[1598]! } + public var Conversation_ScamWarning: String { return self._s[1599]! } + public var Wallpaper_SetCustomBackground: String { return self._s[1600]! } + public var Appearance_TextSize_Title: String { return self._s[1601]! } + public var Passport_Identity_TranslationsHelp: String { return self._s[1602]! } + public var NotificationsSound_Chime: String { return self._s[1603]! } + public var Passport_Language_ko: String { return self._s[1605]! } + public var InviteText_URL: String { return self._s[1606]! } + public var TextFormat_Monospace: String { return self._s[1607]! } public func Time_PreciseDate_m11(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1607]!, self._r[1607]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1608]!, self._r[1608]!, [_1, _2, _3]) } - public var EditTheme_Edit_BottomInfo: String { return self._s[1608]! } + public var EditTheme_Edit_BottomInfo: String { return self._s[1609]! } public func Login_WillSendSms(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1609]!, self._r[1609]!, [_0]) + return formatWithArgumentRanges(self._s[1610]!, self._r[1610]!, [_0]) } public func Watch_Time_ShortWeekdayAt(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1610]!, self._r[1610]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1611]!, self._r[1611]!, [_1, _2]) } - public var Wallet_Words_Title: String { return self._s[1611]! } - public var Wallet_Month_ShortMay: String { return self._s[1612]! } - public var EditTheme_CreateTitle: String { return self._s[1614]! } - public var Passport_InfoLearnMore: String { return self._s[1615]! } - public var TwoStepAuth_EmailPlaceholder: String { return self._s[1616]! } - public var Passport_Identity_AddIdentityCard: String { return self._s[1617]! } - public var Your_card_has_expired: String { return self._s[1618]! } - public var StickerPacksSettings_StickerPacksSection: String { return self._s[1619]! } - public var GroupInfo_InviteLink_Help: String { return self._s[1620]! } - public var TwoFactorSetup_EmailVerification_ResendAction: String { return self._s[1624]! } - public var Conversation_Report: String { return self._s[1626]! } - public var Notifications_MessageNotificationsSound: String { return self._s[1627]! } - public var Notification_MessageLifetime1m: String { return self._s[1628]! } - public var Privacy_ContactsTitle: String { return self._s[1629]! } - public var Conversation_ShareMyContactInfo: String { return self._s[1630]! } - public var Wallet_WordCheck_Title: String { return self._s[1631]! } - public var ChannelMembers_WhoCanAddMembersAdminsHelp: String { return self._s[1632]! } - public var Channel_Members_Title: String { return self._s[1633]! } - public var Map_OpenInWaze: String { return self._s[1634]! } - public var Appearance_RemoveThemeColorConfirmation: String { return self._s[1635]! } - public var Login_PhoneBannedError: String { return self._s[1636]! } + public var Wallet_Words_Title: String { return self._s[1612]! } + public var Wallet_Month_ShortMay: String { return self._s[1613]! } + public var EditTheme_CreateTitle: String { return self._s[1615]! } + public var Passport_InfoLearnMore: String { return self._s[1616]! } + public var TwoStepAuth_EmailPlaceholder: String { return self._s[1617]! } + public var Passport_Identity_AddIdentityCard: String { return self._s[1618]! } + public var Your_card_has_expired: String { return self._s[1619]! } + public var StickerPacksSettings_StickerPacksSection: String { return self._s[1620]! } + public var GroupInfo_InviteLink_Help: String { return self._s[1621]! } + public var TwoFactorSetup_EmailVerification_ResendAction: String { return self._s[1625]! } + public var Conversation_Report: String { return self._s[1627]! } + public var Notifications_MessageNotificationsSound: String { return self._s[1628]! } + public var Notification_MessageLifetime1m: String { return self._s[1629]! } + public var Privacy_ContactsTitle: String { return self._s[1630]! } + public var Conversation_ShareMyContactInfo: String { return self._s[1631]! } + public var Wallet_WordCheck_Title: String { return self._s[1632]! } + public var ChannelMembers_WhoCanAddMembersAdminsHelp: String { return self._s[1633]! } + public var Channel_Members_Title: String { return self._s[1634]! } + public var Map_OpenInWaze: String { return self._s[1635]! } + public var Appearance_RemoveThemeColorConfirmation: String { return self._s[1636]! } + public var Login_PhoneBannedError: String { return self._s[1637]! } public func LiveLocationUpdated_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1637]!, self._r[1637]!, [_0]) + return formatWithArgumentRanges(self._s[1638]!, self._r[1638]!, [_0]) } - public var IntentsSettings_MainAccount: String { return self._s[1638]! } - public var Group_Management_AddModeratorHelp: String { return self._s[1639]! } - public var AutoDownloadSettings_WifiTitle: String { return self._s[1640]! } - public var Common_OK: String { return self._s[1641]! } - public var Passport_Address_TypeBankStatementUploadScan: String { return self._s[1642]! } - public var Wallet_Words_NotDoneResponse: String { return self._s[1643]! } - public var Cache_Music: String { return self._s[1644]! } - public var Wallet_Configuration_SourceURL: String { return self._s[1645]! } - public var SettingsSearch_Synonyms_EditProfile_PhoneNumber: String { return self._s[1646]! } - public var PasscodeSettings_UnlockWithTouchId: String { return self._s[1648]! } - public var TwoStepAuth_HintPlaceholder: String { return self._s[1649]! } + public var IntentsSettings_MainAccount: String { return self._s[1639]! } + public var Group_Management_AddModeratorHelp: String { return self._s[1640]! } + public var AutoDownloadSettings_WifiTitle: String { return self._s[1641]! } + public var Common_OK: String { return self._s[1642]! } + public var Passport_Address_TypeBankStatementUploadScan: String { return self._s[1643]! } + public var Wallet_Words_NotDoneResponse: String { return self._s[1644]! } + public var Cache_Music: String { return self._s[1645]! } + public var Wallet_Configuration_SourceURL: String { return self._s[1646]! } + public var SettingsSearch_Synonyms_EditProfile_PhoneNumber: String { return self._s[1647]! } + public var PasscodeSettings_UnlockWithTouchId: String { return self._s[1649]! } + public var TwoStepAuth_HintPlaceholder: String { return self._s[1650]! } public func PUSH_PINNED_INVOICE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1650]!, self._r[1650]!, [_1]) + return formatWithArgumentRanges(self._s[1651]!, self._r[1651]!, [_1]) } public func Passport_RequestHeader(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1651]!, self._r[1651]!, [_0]) + return formatWithArgumentRanges(self._s[1652]!, self._r[1652]!, [_0]) } - public var TwoFactorSetup_Done_Action: String { return self._s[1652]! } + public var TwoFactorSetup_Done_Action: String { return self._s[1653]! } public func VoiceOver_Chat_ContactOrganization(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1653]!, self._r[1653]!, [_0]) + return formatWithArgumentRanges(self._s[1654]!, self._r[1654]!, [_0]) } - public var Wallet_Send_ErrorNotEnoughFundsText: String { return self._s[1654]! } - public var Watch_MessageView_ViewOnPhone: String { return self._s[1656]! } - public var Privacy_Calls_CustomShareHelp: String { return self._s[1657]! } - public var Wallet_Receive_CreateInvoiceInfo: String { return self._s[1659]! } - public var ChangePhoneNumberNumber_Title: String { return self._s[1660]! } - public var State_ConnectingToProxyInfo: String { return self._s[1661]! } - public var Conversation_SwipeToReplyHintTitle: String { return self._s[1662]! } - public var Message_VideoMessage: String { return self._s[1664]! } - public var ChannelInfo_DeleteChannel: String { return self._s[1665]! } - public var ContactInfo_PhoneLabelOther: String { return self._s[1666]! } - public var Channel_EditAdmin_CannotEdit: String { return self._s[1667]! } - public var Passport_DeleteAddressConfirmation: String { return self._s[1668]! } + public var Wallet_Send_ErrorNotEnoughFundsText: String { return self._s[1655]! } + public var Watch_MessageView_ViewOnPhone: String { return self._s[1657]! } + public var Privacy_Calls_CustomShareHelp: String { return self._s[1658]! } + public var Wallet_Receive_CreateInvoiceInfo: String { return self._s[1660]! } + public var ChangePhoneNumberNumber_Title: String { return self._s[1661]! } + public var State_ConnectingToProxyInfo: String { return self._s[1662]! } + public var Conversation_SwipeToReplyHintTitle: String { return self._s[1663]! } + public var Message_VideoMessage: String { return self._s[1665]! } + public var ChannelInfo_DeleteChannel: String { return self._s[1666]! } + public var ContactInfo_PhoneLabelOther: String { return self._s[1667]! } + public var Channel_EditAdmin_CannotEdit: String { return self._s[1668]! } + public var Passport_DeleteAddressConfirmation: String { return self._s[1669]! } public func Wallet_Time_PreciseDate_m9(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1669]!, self._r[1669]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1670]!, self._r[1670]!, [_1, _2, _3]) } - public var WallpaperPreview_SwipeBottomText: String { return self._s[1670]! } - public var Activity_RecordingAudio: String { return self._s[1671]! } - public var SettingsSearch_Synonyms_Watch: String { return self._s[1672]! } - public var PasscodeSettings_TryAgainIn1Minute: String { return self._s[1673]! } - public var Wallet_Info_Address: String { return self._s[1674]! } + public var WallpaperPreview_SwipeBottomText: String { return self._s[1671]! } + public var Activity_RecordingAudio: String { return self._s[1672]! } + public var SettingsSearch_Synonyms_Watch: String { return self._s[1673]! } + public var PasscodeSettings_TryAgainIn1Minute: String { return self._s[1674]! } + public var Wallet_Info_Address: String { return self._s[1675]! } public func Notification_ChangedGroupName(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1676]!, self._r[1676]!, [_0, _1]) + return formatWithArgumentRanges(self._s[1677]!, self._r[1677]!, [_0, _1]) } public func EmptyGroupInfo_Line1(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1680]!, self._r[1680]!, [_0]) + return formatWithArgumentRanges(self._s[1681]!, self._r[1681]!, [_0]) } - public var Conversation_ApplyLocalization: String { return self._s[1681]! } - public var TwoFactorSetup_Intro_Action: String { return self._s[1682]! } - public var UserInfo_AddPhone: String { return self._s[1683]! } - public var Map_ShareLiveLocationHelp: String { return self._s[1684]! } + public var Conversation_ApplyLocalization: String { return self._s[1682]! } + public var TwoFactorSetup_Intro_Action: String { return self._s[1683]! } + public var UserInfo_AddPhone: String { return self._s[1684]! } + public var Map_ShareLiveLocationHelp: String { return self._s[1685]! } public func Passport_Identity_NativeNameGenericHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1685]!, self._r[1685]!, [_0]) + return formatWithArgumentRanges(self._s[1686]!, self._r[1686]!, [_0]) } - public var Passport_Scans: String { return self._s[1687]! } - public var BlockedUsers_Unblock: String { return self._s[1688]! } + public var Passport_Scans: String { return self._s[1688]! } + public var BlockedUsers_Unblock: String { return self._s[1689]! } public func PUSH_ENCRYPTION_REQUEST(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1689]!, self._r[1689]!, [_1]) + return formatWithArgumentRanges(self._s[1690]!, self._r[1690]!, [_1]) } - public var Channel_Management_LabelCreator: String { return self._s[1690]! } - public var Conversation_ReportSpamAndLeave: String { return self._s[1691]! } - public var SettingsSearch_Synonyms_EditProfile_Bio: String { return self._s[1692]! } - public var ChatList_UndoArchiveMultipleTitle: String { return self._s[1693]! } - public var Passport_Identity_NativeNameGenericTitle: String { return self._s[1694]! } + public var Channel_Management_LabelCreator: String { return self._s[1691]! } + public var Conversation_ReportSpamAndLeave: String { return self._s[1692]! } + public var SettingsSearch_Synonyms_EditProfile_Bio: String { return self._s[1693]! } + public var ChatList_UndoArchiveMultipleTitle: String { return self._s[1694]! } + public var Passport_Identity_NativeNameGenericTitle: String { return self._s[1695]! } public func Login_EmailPhoneBody(_ _0: String, _ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1695]!, self._r[1695]!, [_0, _1, _2]) + return formatWithArgumentRanges(self._s[1696]!, self._r[1696]!, [_0, _1, _2]) } - public var Login_PhoneNumberHelp: String { return self._s[1696]! } - public var LastSeen_ALongTimeAgo: String { return self._s[1697]! } - public var Channel_AdminLog_CanPinMessages: String { return self._s[1698]! } - public var ChannelIntro_CreateChannel: String { return self._s[1699]! } - public var Conversation_UnreadMessages: String { return self._s[1700]! } - public var SettingsSearch_Synonyms_Stickers_ArchivedPacks: String { return self._s[1701]! } - public var Channel_AdminLog_EmptyText: String { return self._s[1702]! } - public var Theme_Context_Apply: String { return self._s[1703]! } - public var Notification_GroupActivated: String { return self._s[1704]! } - public var NotificationSettings_ContactJoinedInfo: String { return self._s[1705]! } - public var Wallet_Intro_CreateWallet: String { return self._s[1706]! } + public var Login_PhoneNumberHelp: String { return self._s[1697]! } + public var LastSeen_ALongTimeAgo: String { return self._s[1698]! } + public var Channel_AdminLog_CanPinMessages: String { return self._s[1699]! } + public var ChannelIntro_CreateChannel: String { return self._s[1700]! } + public var Conversation_UnreadMessages: String { return self._s[1701]! } + public var SettingsSearch_Synonyms_Stickers_ArchivedPacks: String { return self._s[1702]! } + public var Channel_AdminLog_EmptyText: String { return self._s[1703]! } + public var Theme_Context_Apply: String { return self._s[1704]! } + public var Notification_GroupActivated: String { return self._s[1705]! } + public var NotificationSettings_ContactJoinedInfo: String { return self._s[1706]! } + public var Wallet_Intro_CreateWallet: String { return self._s[1707]! } public func Notification_PinnedContactMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1707]!, self._r[1707]!, [_0]) + return formatWithArgumentRanges(self._s[1708]!, self._r[1708]!, [_0]) } public func DownloadingStatus(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1708]!, self._r[1708]!, [_0, _1]) + return formatWithArgumentRanges(self._s[1709]!, self._r[1709]!, [_0, _1]) } - public var GroupInfo_ConvertToSupergroup: String { return self._s[1710]! } + public var GroupInfo_ConvertToSupergroup: String { return self._s[1711]! } public func PrivacyPolicy_AgeVerificationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1711]!, self._r[1711]!, [_0]) + return formatWithArgumentRanges(self._s[1712]!, self._r[1712]!, [_0]) } - public var Undo_DeletedChannel: String { return self._s[1712]! } - public var CallFeedback_AddComment: String { return self._s[1713]! } + public var Undo_DeletedChannel: String { return self._s[1713]! } + public var CallFeedback_AddComment: String { return self._s[1714]! } public func Conversation_OpenBotLinkAllowMessages(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1714]!, self._r[1714]!, [_0]) + return formatWithArgumentRanges(self._s[1715]!, self._r[1715]!, [_0]) } - public var Document_TargetConfirmationFormat: String { return self._s[1715]! } + public var Document_TargetConfirmationFormat: String { return self._s[1716]! } public func Call_StatusOngoing(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1716]!, self._r[1716]!, [_0]) + return formatWithArgumentRanges(self._s[1717]!, self._r[1717]!, [_0]) } - public var LogoutOptions_SetPasscodeTitle: String { return self._s[1717]! } + public var LogoutOptions_SetPasscodeTitle: String { return self._s[1718]! } public func PUSH_CHAT_MESSAGE_GAME_SCORE(_ _1: String, _ _2: String, _ _3: String, _ _4: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1718]!, self._r[1718]!, [_1, _2, _3, _4]) + return formatWithArgumentRanges(self._s[1719]!, self._r[1719]!, [_1, _2, _3, _4]) } - public var Wallet_SecureStorageChanged_PasscodeText: String { return self._s[1719]! } - public var Theme_ErrorNotFound: String { return self._s[1720]! } - public var Contacts_SortByName: String { return self._s[1721]! } - public var SettingsSearch_Synonyms_Privacy_Forwards: String { return self._s[1722]! } + public var Wallet_SecureStorageChanged_PasscodeText: String { return self._s[1720]! } + public var Theme_ErrorNotFound: String { return self._s[1721]! } + public var Contacts_SortByName: String { return self._s[1722]! } + public var SettingsSearch_Synonyms_Privacy_Forwards: String { return self._s[1723]! } public func CHAT_MESSAGE_INVOICE(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1724]!, self._r[1724]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1725]!, self._r[1725]!, [_1, _2, _3]) } - public var Notification_Exceptions_RemoveFromExceptions: String { return self._s[1725]! } - public var ScheduledMessages_EditTime: String { return self._s[1726]! } - public var Conversation_ClearSelfHistory: String { return self._s[1727]! } - public var Checkout_NewCard_PostcodePlaceholder: String { return self._s[1728]! } - public var PasscodeSettings_DoNotMatch: String { return self._s[1729]! } - public var Stickers_SuggestNone: String { return self._s[1730]! } - public var ChatSettings_Cache: String { return self._s[1731]! } - public var Settings_SaveIncomingPhotos: String { return self._s[1732]! } - public var Media_ShareThisPhoto: String { return self._s[1733]! } - public var Chat_SlowmodeTooltipPending: String { return self._s[1734]! } - public var InfoPlist_NSContactsUsageDescription: String { return self._s[1735]! } - public var Conversation_ContextMenuCopyLink: String { return self._s[1736]! } - public var PrivacyPolicy_AgeVerificationTitle: String { return self._s[1737]! } - public var SettingsSearch_Synonyms_Stickers_Masks: String { return self._s[1738]! } - public var TwoStepAuth_SetupPasswordEnterPasswordNew: String { return self._s[1739]! } - public var Appearance_ThemePreview_Chat_6_Text: String { return self._s[1740]! } + public var Notification_Exceptions_RemoveFromExceptions: String { return self._s[1726]! } + public var ScheduledMessages_EditTime: String { return self._s[1727]! } + public var Conversation_ClearSelfHistory: String { return self._s[1728]! } + public var Checkout_NewCard_PostcodePlaceholder: String { return self._s[1729]! } + public var PasscodeSettings_DoNotMatch: String { return self._s[1730]! } + public var Stickers_SuggestNone: String { return self._s[1731]! } + public var ChatSettings_Cache: String { return self._s[1732]! } + public var Settings_SaveIncomingPhotos: String { return self._s[1733]! } + public var Media_ShareThisPhoto: String { return self._s[1734]! } + public var Chat_SlowmodeTooltipPending: String { return self._s[1735]! } + public var InfoPlist_NSContactsUsageDescription: String { return self._s[1736]! } + public var Conversation_ContextMenuCopyLink: String { return self._s[1737]! } + public var PrivacyPolicy_AgeVerificationTitle: String { return self._s[1738]! } + public var SettingsSearch_Synonyms_Stickers_Masks: String { return self._s[1739]! } + public var TwoStepAuth_SetupPasswordEnterPasswordNew: String { return self._s[1740]! } + public var Appearance_ThemePreview_Chat_6_Text: String { return self._s[1741]! } public func Wallet_SecureStorageReset_BiometryText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1741]!, self._r[1741]!, [_0]) + return formatWithArgumentRanges(self._s[1742]!, self._r[1742]!, [_0]) } - public var Permissions_CellularDataTitle_v0: String { return self._s[1742]! } - public var WallpaperSearch_ColorWhite: String { return self._s[1744]! } - public var Channel_AdminLog_DefaultRestrictionsUpdated: String { return self._s[1745]! } - public var Conversation_ErrorInaccessibleMessage: String { return self._s[1746]! } - public var Map_OpenIn: String { return self._s[1747]! } + public var Permissions_CellularDataTitle_v0: String { return self._s[1743]! } + public var WallpaperSearch_ColorWhite: String { return self._s[1745]! } + public var Channel_AdminLog_DefaultRestrictionsUpdated: String { return self._s[1746]! } + public var Conversation_ErrorInaccessibleMessage: String { return self._s[1747]! } + public var Map_OpenIn: String { return self._s[1748]! } public func PUSH_PHONE_CALL_MISSED(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1750]!, self._r[1750]!, [_1]) + return formatWithArgumentRanges(self._s[1751]!, self._r[1751]!, [_1]) } public func ChannelInfo_AddParticipantConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1751]!, self._r[1751]!, [_0]) + return formatWithArgumentRanges(self._s[1752]!, self._r[1752]!, [_0]) } - public var GroupInfo_Permissions_SlowmodeHeader: String { return self._s[1752]! } - public var MessagePoll_LabelClosed: String { return self._s[1753]! } - public var GroupPermission_PermissionGloballyDisabled: String { return self._s[1755]! } - public var Wallet_Send_SendAnyway: String { return self._s[1756]! } - public var Passport_Identity_MiddleNamePlaceholder: String { return self._s[1757]! } - public var UserInfo_FirstNamePlaceholder: String { return self._s[1758]! } - public var PrivacyLastSeenSettings_WhoCanSeeMyTimestamp: String { return self._s[1759]! } - public var Map_SetThisPlace: String { return self._s[1760]! } - public var Login_SelectCountry_Title: String { return self._s[1761]! } - public var Channel_EditAdmin_PermissionBanUsers: String { return self._s[1762]! } + public var GroupInfo_Permissions_SlowmodeHeader: String { return self._s[1753]! } + public var MessagePoll_LabelClosed: String { return self._s[1754]! } + public var GroupPermission_PermissionGloballyDisabled: String { return self._s[1756]! } + public var Wallet_Send_SendAnyway: String { return self._s[1757]! } + public var Passport_Identity_MiddleNamePlaceholder: String { return self._s[1758]! } + public var UserInfo_FirstNamePlaceholder: String { return self._s[1759]! } + public var PrivacyLastSeenSettings_WhoCanSeeMyTimestamp: String { return self._s[1760]! } + public var Map_SetThisPlace: String { return self._s[1761]! } + public var Login_SelectCountry_Title: String { return self._s[1762]! } + public var Channel_EditAdmin_PermissionBanUsers: String { return self._s[1763]! } public func Conversation_OpenBotLinkLogin(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1763]!, self._r[1763]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1764]!, self._r[1764]!, [_1, _2]) } - public var Channel_AdminLog_ChangeInfo: String { return self._s[1764]! } - public var Watch_Suggestion_BRB: String { return self._s[1765]! } - public var Passport_Identity_EditIdentityCard: String { return self._s[1766]! } - public var Contacts_PermissionsTitle: String { return self._s[1767]! } - public var Conversation_RestrictedInline: String { return self._s[1768]! } - public var Appearance_RemoveThemeColor: String { return self._s[1770]! } - public var StickerPack_ViewPack: String { return self._s[1771]! } - public var Wallet_UnknownError: String { return self._s[1772]! } + public var Channel_AdminLog_ChangeInfo: String { return self._s[1765]! } + public var Watch_Suggestion_BRB: String { return self._s[1766]! } + public var Passport_Identity_EditIdentityCard: String { return self._s[1767]! } + public var Contacts_PermissionsTitle: String { return self._s[1768]! } + public var Conversation_RestrictedInline: String { return self._s[1769]! } + public var Appearance_RemoveThemeColor: String { return self._s[1771]! } + public var StickerPack_ViewPack: String { return self._s[1772]! } + public var Wallet_UnknownError: String { return self._s[1773]! } public func Update_AppVersion(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1773]!, self._r[1773]!, [_0]) + return formatWithArgumentRanges(self._s[1774]!, self._r[1774]!, [_0]) } - public var Compose_NewChannel: String { return self._s[1775]! } - public var ChatSettings_AutoDownloadSettings_TypePhoto: String { return self._s[1778]! } - public var MessagePoll_LabelQuiz: String { return self._s[1780]! } - public var Conversation_ReportSpamGroupConfirmation: String { return self._s[1781]! } - public var Channel_Info_Stickers: String { return self._s[1782]! } - public var AutoNightTheme_PreferredTheme: String { return self._s[1783]! } - public var PrivacyPolicy_AgeVerificationAgree: String { return self._s[1784]! } - public var Passport_DeletePersonalDetails: String { return self._s[1785]! } - public var LogoutOptions_AddAccountTitle: String { return self._s[1786]! } - public var Channel_DiscussionGroupInfo: String { return self._s[1787]! } - public var Group_EditAdmin_RankOwnerPlaceholder: String { return self._s[1788]! } - public var Conversation_SearchNoResults: String { return self._s[1791]! } - public var Wallet_Configuration_ApplyErrorTextURLInvalid: String { return self._s[1792]! } - public var MessagePoll_LabelAnonymous: String { return self._s[1793]! } - public var Channel_Members_AddAdminErrorNotAMember: String { return self._s[1794]! } - public var Login_Code: String { return self._s[1795]! } - public var EditTheme_Create_BottomInfo: String { return self._s[1796]! } - public var Watch_Suggestion_WhatsUp: String { return self._s[1797]! } - public var Weekday_ShortThursday: String { return self._s[1798]! } - public var Resolve_ErrorNotFound: String { return self._s[1800]! } - public var LastSeen_Offline: String { return self._s[1801]! } - public var PeopleNearby_NoMembers: String { return self._s[1802]! } - public var GroupPermission_AddMembersNotAvailable: String { return self._s[1803]! } - public var Privacy_Calls_AlwaysAllow_Title: String { return self._s[1804]! } - public var GroupInfo_Title: String { return self._s[1806]! } - public var NotificationsSound_Note: String { return self._s[1807]! } - public var Conversation_EditingMessagePanelTitle: String { return self._s[1808]! } - public var Watch_Message_Poll: String { return self._s[1809]! } - public var Privacy_Calls: String { return self._s[1810]! } + public var Compose_NewChannel: String { return self._s[1776]! } + public var ChatSettings_AutoDownloadSettings_TypePhoto: String { return self._s[1779]! } + public var MessagePoll_LabelQuiz: String { return self._s[1781]! } + public var Conversation_ReportSpamGroupConfirmation: String { return self._s[1782]! } + public var Channel_Info_Stickers: String { return self._s[1783]! } + public var AutoNightTheme_PreferredTheme: String { return self._s[1784]! } + public var PrivacyPolicy_AgeVerificationAgree: String { return self._s[1785]! } + public var Passport_DeletePersonalDetails: String { return self._s[1786]! } + public var LogoutOptions_AddAccountTitle: String { return self._s[1787]! } + public var Channel_DiscussionGroupInfo: String { return self._s[1788]! } + public var Group_EditAdmin_RankOwnerPlaceholder: String { return self._s[1789]! } + public var Conversation_SearchNoResults: String { return self._s[1792]! } + public var Wallet_Configuration_ApplyErrorTextURLInvalid: String { return self._s[1793]! } + public var MessagePoll_LabelAnonymous: String { return self._s[1794]! } + public var Channel_Members_AddAdminErrorNotAMember: String { return self._s[1795]! } + public var Login_Code: String { return self._s[1796]! } + public var EditTheme_Create_BottomInfo: String { return self._s[1797]! } + public var Watch_Suggestion_WhatsUp: String { return self._s[1798]! } + public var Weekday_ShortThursday: String { return self._s[1799]! } + public var Resolve_ErrorNotFound: String { return self._s[1801]! } + public var LastSeen_Offline: String { return self._s[1802]! } + public var PeopleNearby_NoMembers: String { return self._s[1803]! } + public var GroupPermission_AddMembersNotAvailable: String { return self._s[1804]! } + public var Privacy_Calls_AlwaysAllow_Title: String { return self._s[1805]! } + public var GroupInfo_Title: String { return self._s[1807]! } + public var NotificationsSound_Note: String { return self._s[1808]! } + public var Conversation_EditingMessagePanelTitle: String { return self._s[1809]! } + public var Watch_Message_Poll: String { return self._s[1810]! } + public var Privacy_Calls: String { return self._s[1811]! } public func Channel_AdminLog_MessageRankUsername(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1811]!, self._r[1811]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1812]!, self._r[1812]!, [_1, _2, _3]) } - public var Month_ShortAugust: String { return self._s[1812]! } - public var TwoStepAuth_SetPasswordHelp: String { return self._s[1813]! } - public var Notifications_Reset: String { return self._s[1814]! } - public var Conversation_Pin: String { return self._s[1815]! } - public var Passport_Language_lv: String { return self._s[1816]! } - public var Permissions_PeopleNearbyAllowInSettings_v0: String { return self._s[1817]! } - public var BlockedUsers_Info: String { return self._s[1818]! } - public var SettingsSearch_Synonyms_Data_AutoplayVideos: String { return self._s[1820]! } - public var Watch_Conversation_Unblock: String { return self._s[1822]! } + public var Month_ShortAugust: String { return self._s[1813]! } + public var TwoStepAuth_SetPasswordHelp: String { return self._s[1814]! } + public var Notifications_Reset: String { return self._s[1815]! } + public var Conversation_Pin: String { return self._s[1816]! } + public var Passport_Language_lv: String { return self._s[1817]! } + public var Permissions_PeopleNearbyAllowInSettings_v0: String { return self._s[1818]! } + public var BlockedUsers_Info: String { return self._s[1819]! } + public var SettingsSearch_Synonyms_Data_AutoplayVideos: String { return self._s[1821]! } + public var Watch_Conversation_Unblock: String { return self._s[1823]! } public func Time_MonthOfYear_m9(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1823]!, self._r[1823]!, [_0]) + return formatWithArgumentRanges(self._s[1824]!, self._r[1824]!, [_0]) } - public var CloudStorage_Title: String { return self._s[1824]! } - public var GroupInfo_DeleteAndExitConfirmation: String { return self._s[1825]! } + public var CloudStorage_Title: String { return self._s[1825]! } + public var GroupInfo_DeleteAndExitConfirmation: String { return self._s[1826]! } public func NetworkUsageSettings_WifiUsageSince(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1826]!, self._r[1826]!, [_0]) + return formatWithArgumentRanges(self._s[1827]!, self._r[1827]!, [_0]) } - public var Channel_AdminLogFilter_AdminsTitle: String { return self._s[1827]! } - public var Watch_Suggestion_OnMyWay: String { return self._s[1828]! } - public var TwoStepAuth_RecoveryEmailTitle: String { return self._s[1829]! } - public var Passport_Address_EditBankStatement: String { return self._s[1830]! } + public var Channel_AdminLogFilter_AdminsTitle: String { return self._s[1828]! } + public var Watch_Suggestion_OnMyWay: String { return self._s[1829]! } + public var TwoStepAuth_RecoveryEmailTitle: String { return self._s[1830]! } + public var Passport_Address_EditBankStatement: String { return self._s[1831]! } public func Channel_AdminLog_MessageChangedUnlinkedGroup(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1831]!, self._r[1831]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1832]!, self._r[1832]!, [_1, _2]) } - public var ChatSettings_DownloadInBackgroundInfo: String { return self._s[1832]! } - public var ShareMenu_Comment: String { return self._s[1833]! } - public var Permissions_ContactsTitle_v0: String { return self._s[1834]! } - public var Notifications_PermissionsTitle: String { return self._s[1835]! } - public var GroupPermission_NoSendLinks: String { return self._s[1836]! } - public var Privacy_Forwards_NeverAllow_Title: String { return self._s[1837]! } - public var Wallet_SecureStorageChanged_ImportWallet: String { return self._s[1838]! } - public var Settings_Support: String { return self._s[1839]! } - public var Notifications_ChannelNotificationsSound: String { return self._s[1840]! } - public var SettingsSearch_Synonyms_Data_AutoDownloadReset: String { return self._s[1841]! } - public var Privacy_Forwards_Preview: String { return self._s[1842]! } - public var GroupPermission_ApplyAlertAction: String { return self._s[1843]! } - public var Watch_Stickers_StickerPacks: String { return self._s[1844]! } - public var Common_Select: String { return self._s[1846]! } - public var CheckoutInfo_ErrorEmailInvalid: String { return self._s[1847]! } - public var WallpaperSearch_ColorGray: String { return self._s[1850]! } - public var TwoFactorSetup_Password_PlaceholderPassword: String { return self._s[1851]! } - public var TwoFactorSetup_Hint_SkipAction: String { return self._s[1852]! } - public var ChatAdmins_AllMembersAreAdminsOffHelp: String { return self._s[1853]! } - public var PollResults_Title: String { return self._s[1854]! } - public var PasscodeSettings_AutoLock_IfAwayFor_5hours: String { return self._s[1855]! } - public var Appearance_PreviewReplyAuthor: String { return self._s[1856]! } - public var TwoStepAuth_RecoveryTitle: String { return self._s[1857]! } - public var Widget_AuthRequired: String { return self._s[1858]! } - public var Camera_FlashOn: String { return self._s[1859]! } - public var Conversation_ContextMenuLookUp: String { return self._s[1860]! } - public var Channel_Stickers_NotFoundHelp: String { return self._s[1861]! } - public var Watch_Suggestion_OK: String { return self._s[1862]! } + public var ChatSettings_DownloadInBackgroundInfo: String { return self._s[1833]! } + public var ShareMenu_Comment: String { return self._s[1834]! } + public var Permissions_ContactsTitle_v0: String { return self._s[1835]! } + public var Notifications_PermissionsTitle: String { return self._s[1836]! } + public var GroupPermission_NoSendLinks: String { return self._s[1837]! } + public var Privacy_Forwards_NeverAllow_Title: String { return self._s[1838]! } + public var Wallet_SecureStorageChanged_ImportWallet: String { return self._s[1839]! } + public var Settings_Support: String { return self._s[1840]! } + public var Notifications_ChannelNotificationsSound: String { return self._s[1841]! } + public var SettingsSearch_Synonyms_Data_AutoDownloadReset: String { return self._s[1842]! } + public var Privacy_Forwards_Preview: String { return self._s[1843]! } + public var GroupPermission_ApplyAlertAction: String { return self._s[1844]! } + public var Watch_Stickers_StickerPacks: String { return self._s[1845]! } + public var Common_Select: String { return self._s[1847]! } + public var CheckoutInfo_ErrorEmailInvalid: String { return self._s[1848]! } + public var WallpaperSearch_ColorGray: String { return self._s[1851]! } + public var TwoFactorSetup_Password_PlaceholderPassword: String { return self._s[1852]! } + public var TwoFactorSetup_Hint_SkipAction: String { return self._s[1853]! } + public var ChatAdmins_AllMembersAreAdminsOffHelp: String { return self._s[1854]! } + public var PollResults_Title: String { return self._s[1855]! } + public var PasscodeSettings_AutoLock_IfAwayFor_5hours: String { return self._s[1856]! } + public var Appearance_PreviewReplyAuthor: String { return self._s[1857]! } + public var TwoStepAuth_RecoveryTitle: String { return self._s[1858]! } + public var Widget_AuthRequired: String { return self._s[1859]! } + public var Camera_FlashOn: String { return self._s[1860]! } + public var Conversation_ContextMenuLookUp: String { return self._s[1861]! } + public var Channel_Stickers_NotFoundHelp: String { return self._s[1862]! } + public var Watch_Suggestion_OK: String { return self._s[1863]! } public func Username_LinkHint(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1864]!, self._r[1864]!, [_0]) + return formatWithArgumentRanges(self._s[1865]!, self._r[1865]!, [_0]) } public func Notification_PinnedLiveLocationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1866]!, self._r[1866]!, [_0]) + return formatWithArgumentRanges(self._s[1867]!, self._r[1867]!, [_0]) } - public var TextFormat_Strikethrough: String { return self._s[1867]! } - public var DialogList_AdLabel: String { return self._s[1868]! } - public var WatchRemote_NotificationText: String { return self._s[1869]! } - public var IntentsSettings_SuggestedChatsSavedMessages: String { return self._s[1870]! } - public var SettingsSearch_Synonyms_Notifications_MessageNotificationsAlert: String { return self._s[1871]! } - public var Conversation_ReportSpam: String { return self._s[1872]! } - public var SettingsSearch_Synonyms_Privacy_Data_TopPeers: String { return self._s[1873]! } - public var Settings_LogoutConfirmationTitle: String { return self._s[1875]! } - public var PhoneLabel_Title: String { return self._s[1876]! } - public var Passport_Address_EditRentalAgreement: String { return self._s[1877]! } - public var Settings_ChangePhoneNumber: String { return self._s[1878]! } - public var Notifications_ExceptionsTitle: String { return self._s[1879]! } - public var Notifications_AlertTones: String { return self._s[1880]! } - public var Call_ReportIncludeLogDescription: String { return self._s[1881]! } - public var SettingsSearch_Synonyms_Notifications_ResetAllNotifications: String { return self._s[1882]! } - public var AutoDownloadSettings_PrivateChats: String { return self._s[1883]! } - public var VoiceOver_Chat_Photo: String { return self._s[1885]! } - public var TwoStepAuth_AddHintTitle: String { return self._s[1886]! } - public var ReportPeer_ReasonOther: String { return self._s[1887]! } - public var ChatList_Context_JoinChannel: String { return self._s[1888]! } - public var KeyCommand_ScrollDown: String { return self._s[1890]! } - public var Conversation_ScheduleMessage_Title: String { return self._s[1891]! } + public var TextFormat_Strikethrough: String { return self._s[1868]! } + public var DialogList_AdLabel: String { return self._s[1869]! } + public var WatchRemote_NotificationText: String { return self._s[1870]! } + public var IntentsSettings_SuggestedChatsSavedMessages: String { return self._s[1871]! } + public var SettingsSearch_Synonyms_Notifications_MessageNotificationsAlert: String { return self._s[1872]! } + public var Conversation_ReportSpam: String { return self._s[1873]! } + public var SettingsSearch_Synonyms_Privacy_Data_TopPeers: String { return self._s[1874]! } + public var Settings_LogoutConfirmationTitle: String { return self._s[1876]! } + public var PhoneLabel_Title: String { return self._s[1877]! } + public var Passport_Address_EditRentalAgreement: String { return self._s[1878]! } + public var Settings_ChangePhoneNumber: String { return self._s[1879]! } + public var Notifications_ExceptionsTitle: String { return self._s[1880]! } + public var Notifications_AlertTones: String { return self._s[1881]! } + public var Call_ReportIncludeLogDescription: String { return self._s[1882]! } + public var SettingsSearch_Synonyms_Notifications_ResetAllNotifications: String { return self._s[1883]! } + public var AutoDownloadSettings_PrivateChats: String { return self._s[1884]! } + public var VoiceOver_Chat_Photo: String { return self._s[1886]! } + public var TwoStepAuth_AddHintTitle: String { return self._s[1887]! } + public var ReportPeer_ReasonOther: String { return self._s[1888]! } + public var ChatList_Context_JoinChannel: String { return self._s[1889]! } + public var KeyCommand_ScrollDown: String { return self._s[1891]! } + public var Conversation_ScheduleMessage_Title: String { return self._s[1892]! } public func Login_BannedPhoneSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1892]!, self._r[1892]!, [_0]) + return formatWithArgumentRanges(self._s[1893]!, self._r[1893]!, [_0]) } - public var NetworkUsageSettings_MediaVideoDataSection: String { return self._s[1893]! } - public var ChannelInfo_DeleteGroupConfirmation: String { return self._s[1894]! } - public var AuthSessions_LogOut: String { return self._s[1895]! } - public var Passport_Identity_TypeInternalPassport: String { return self._s[1896]! } - public var ChatSettings_AutoDownloadVoiceMessages: String { return self._s[1897]! } - public var Passport_Phone_Title: String { return self._s[1898]! } - public var ContactList_Context_StartSecretChat: String { return self._s[1899]! } - public var Settings_PhoneNumber: String { return self._s[1900]! } + public var NetworkUsageSettings_MediaVideoDataSection: String { return self._s[1894]! } + public var ChannelInfo_DeleteGroupConfirmation: String { return self._s[1895]! } + public var AuthSessions_LogOut: String { return self._s[1896]! } + public var Passport_Identity_TypeInternalPassport: String { return self._s[1897]! } + public var ChatSettings_AutoDownloadVoiceMessages: String { return self._s[1898]! } + public var Passport_Phone_Title: String { return self._s[1899]! } + public var ContactList_Context_StartSecretChat: String { return self._s[1900]! } + public var Settings_PhoneNumber: String { return self._s[1901]! } public func Conversation_ScheduleMessage_SendToday(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1901]!, self._r[1901]!, [_0]) + return formatWithArgumentRanges(self._s[1902]!, self._r[1902]!, [_0]) } - public var NotificationsSound_Alert: String { return self._s[1903]! } - public var Wallet_SecureStorageChanged_CreateWallet: String { return self._s[1904]! } - public var WebSearch_SearchNoResults: String { return self._s[1905]! } - public var Privacy_ProfilePhoto_AlwaysShareWith_Title: String { return self._s[1907]! } - public var Wallet_Configuration_SourceInfo: String { return self._s[1908]! } - public var LogoutOptions_AlternativeOptionsSection: String { return self._s[1909]! } - public var SettingsSearch_Synonyms_Passport: String { return self._s[1910]! } - public var PhotoEditor_CurvesTool: String { return self._s[1911]! } - public var Checkout_PaymentMethod: String { return self._s[1913]! } + public var NotificationsSound_Alert: String { return self._s[1904]! } + public var Wallet_SecureStorageChanged_CreateWallet: String { return self._s[1905]! } + public var WebSearch_SearchNoResults: String { return self._s[1906]! } + public var Privacy_ProfilePhoto_AlwaysShareWith_Title: String { return self._s[1908]! } + public var Wallet_Configuration_SourceInfo: String { return self._s[1909]! } + public var LogoutOptions_AlternativeOptionsSection: String { return self._s[1910]! } + public var SettingsSearch_Synonyms_Passport: String { return self._s[1911]! } + public var PhotoEditor_CurvesTool: String { return self._s[1912]! } + public var Checkout_PaymentMethod: String { return self._s[1914]! } public func PUSH_CHAT_ADD_YOU(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1914]!, self._r[1914]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1915]!, self._r[1915]!, [_1, _2]) } - public var Contacts_AccessDeniedError: String { return self._s[1915]! } - public var Camera_PhotoMode: String { return self._s[1918]! } - public var EditTheme_Expand_Preview_IncomingText: String { return self._s[1919]! } - public var Appearance_TextSize_Apply: String { return self._s[1920]! } - public var Passport_Address_AddUtilityBill: String { return self._s[1922]! } - public var CallSettings_OnMobile: String { return self._s[1923]! } - public var Tour_Text2: String { return self._s[1924]! } + public var Contacts_AccessDeniedError: String { return self._s[1916]! } + public var Camera_PhotoMode: String { return self._s[1919]! } + public var EditTheme_Expand_Preview_IncomingText: String { return self._s[1920]! } + public var Appearance_TextSize_Apply: String { return self._s[1921]! } + public var Passport_Address_AddUtilityBill: String { return self._s[1923]! } + public var CallSettings_OnMobile: String { return self._s[1924]! } + public var Tour_Text2: String { return self._s[1925]! } public func PUSH_CHAT_MESSAGE_ROUND(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1925]!, self._r[1925]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1926]!, self._r[1926]!, [_1, _2]) } - public var DialogList_EncryptionProcessing: String { return self._s[1927]! } - public var Permissions_Skip: String { return self._s[1928]! } - public var Wallet_Words_NotDoneOk: String { return self._s[1929]! } - public var SecretImage_Title: String { return self._s[1930]! } - public var Watch_MessageView_Title: String { return self._s[1931]! } - public var Channel_DiscussionGroupAdd: String { return self._s[1932]! } - public var AttachmentMenu_Poll: String { return self._s[1933]! } + public var DialogList_EncryptionProcessing: String { return self._s[1928]! } + public var Permissions_Skip: String { return self._s[1929]! } + public var Wallet_Words_NotDoneOk: String { return self._s[1930]! } + public var SecretImage_Title: String { return self._s[1931]! } + public var Watch_MessageView_Title: String { return self._s[1932]! } + public var Channel_DiscussionGroupAdd: String { return self._s[1933]! } + public var AttachmentMenu_Poll: String { return self._s[1934]! } public func Notification_GroupInviter(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1934]!, self._r[1934]!, [_0]) + return formatWithArgumentRanges(self._s[1935]!, self._r[1935]!, [_0]) } public func Channel_DiscussionGroup_PrivateChannelLink(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1935]!, self._r[1935]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1936]!, self._r[1936]!, [_1, _2]) } - public var Notification_CallCanceled: String { return self._s[1936]! } - public var WallpaperPreview_Title: String { return self._s[1937]! } - public var Privacy_PaymentsClear_PaymentInfo: String { return self._s[1938]! } - public var Settings_ProxyConnecting: String { return self._s[1939]! } - public var Settings_CheckPhoneNumberText: String { return self._s[1941]! } - public var VoiceOver_Chat_YourVideo: String { return self._s[1942]! } - public var Wallet_Intro_Title: String { return self._s[1943]! } - public var TwoFactorSetup_Password_Action: String { return self._s[1944]! } - public var Profile_MessageLifetime5s: String { return self._s[1945]! } - public var Username_InvalidCharacters: String { return self._s[1946]! } - public var VoiceOver_Media_PlaybackRateFast: String { return self._s[1947]! } - public var ScheduledMessages_ClearAll: String { return self._s[1948]! } - public var WallpaperPreview_CropBottomText: String { return self._s[1949]! } - public var AutoDownloadSettings_LimitBySize: String { return self._s[1950]! } - public var Settings_AddAccount: String { return self._s[1951]! } - public var Notification_CreatedChannel: String { return self._s[1954]! } + public var Notification_CallCanceled: String { return self._s[1937]! } + public var WallpaperPreview_Title: String { return self._s[1938]! } + public var Privacy_PaymentsClear_PaymentInfo: String { return self._s[1939]! } + public var Settings_ProxyConnecting: String { return self._s[1940]! } + public var Settings_CheckPhoneNumberText: String { return self._s[1942]! } + public var VoiceOver_Chat_YourVideo: String { return self._s[1943]! } + public var Wallet_Intro_Title: String { return self._s[1944]! } + public var TwoFactorSetup_Password_Action: String { return self._s[1945]! } + public var Profile_MessageLifetime5s: String { return self._s[1946]! } + public var Username_InvalidCharacters: String { return self._s[1947]! } + public var VoiceOver_Media_PlaybackRateFast: String { return self._s[1948]! } + public var ScheduledMessages_ClearAll: String { return self._s[1949]! } + public var WallpaperPreview_CropBottomText: String { return self._s[1950]! } + public var AutoDownloadSettings_LimitBySize: String { return self._s[1951]! } + public var Settings_AddAccount: String { return self._s[1952]! } + public var Notification_CreatedChannel: String { return self._s[1955]! } public func PUSH_CHAT_DELETE_MEMBER(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1955]!, self._r[1955]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1956]!, self._r[1956]!, [_1, _2, _3]) } - public var Passcode_AppLockedAlert: String { return self._s[1957]! } - public var StickerPacksSettings_AnimatedStickersInfo: String { return self._s[1958]! } - public var VoiceOver_Media_PlaybackStop: String { return self._s[1959]! } - public var Contacts_TopSection: String { return self._s[1960]! } - public var ChatList_DeleteForEveryoneConfirmationAction: String { return self._s[1961]! } + public var Passcode_AppLockedAlert: String { return self._s[1958]! } + public var StickerPacksSettings_AnimatedStickersInfo: String { return self._s[1959]! } + public var VoiceOver_Media_PlaybackStop: String { return self._s[1960]! } + public var Contacts_TopSection: String { return self._s[1961]! } + public var ChatList_DeleteForEveryoneConfirmationAction: String { return self._s[1962]! } public func Conversation_SetReminder_RemindOn(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1962]!, self._r[1962]!, [_0, _1]) + return formatWithArgumentRanges(self._s[1963]!, self._r[1963]!, [_0, _1]) } - public var Wallet_Info_Receive: String { return self._s[1963]! } - public var Wallet_Completed_ViewWallet: String { return self._s[1964]! } + public var Wallet_Info_Receive: String { return self._s[1964]! } + public var Wallet_Completed_ViewWallet: String { return self._s[1965]! } public func Time_MonthOfYear_m6(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1965]!, self._r[1965]!, [_0]) + return formatWithArgumentRanges(self._s[1966]!, self._r[1966]!, [_0]) } - public var ReportPeer_ReasonSpam: String { return self._s[1966]! } - public var UserInfo_TapToCall: String { return self._s[1967]! } - public var Conversation_ForwardAuthorHiddenTooltip: String { return self._s[1969]! } - public var AutoDownloadSettings_DataUsageCustom: String { return self._s[1970]! } - public var Common_Search: String { return self._s[1971]! } - public var ScheduledMessages_EmptyPlaceholder: String { return self._s[1972]! } + public var ReportPeer_ReasonSpam: String { return self._s[1967]! } + public var UserInfo_TapToCall: String { return self._s[1968]! } + public var Conversation_ForwardAuthorHiddenTooltip: String { return self._s[1970]! } + public var AutoDownloadSettings_DataUsageCustom: String { return self._s[1971]! } + public var Common_Search: String { return self._s[1972]! } + public var ScheduledMessages_EmptyPlaceholder: String { return self._s[1973]! } public func Channel_AdminLog_MessageChangedGroupGeoLocation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1973]!, self._r[1973]!, [_0]) + return formatWithArgumentRanges(self._s[1974]!, self._r[1974]!, [_0]) } - public var Wallet_Month_ShortJuly: String { return self._s[1974]! } - public var AuthSessions_IncompleteAttemptsInfo: String { return self._s[1976]! } - public var Message_InvoiceLabel: String { return self._s[1977]! } - public var Conversation_InputTextPlaceholder: String { return self._s[1978]! } - public var NetworkUsageSettings_MediaImageDataSection: String { return self._s[1979]! } + public var Wallet_Month_ShortJuly: String { return self._s[1975]! } + public var AuthSessions_IncompleteAttemptsInfo: String { return self._s[1977]! } + public var Message_InvoiceLabel: String { return self._s[1978]! } + public var Conversation_InputTextPlaceholder: String { return self._s[1979]! } + public var NetworkUsageSettings_MediaImageDataSection: String { return self._s[1980]! } public func Passport_Address_UploadOneOfScan(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1980]!, self._r[1980]!, [_0]) + return formatWithArgumentRanges(self._s[1981]!, self._r[1981]!, [_0]) } - public var IntentsSettings_Reset: String { return self._s[1981]! } - public var Conversation_Info: String { return self._s[1982]! } - public var Login_InfoDeletePhoto: String { return self._s[1983]! } - public var Passport_Language_vi: String { return self._s[1985]! } - public var UserInfo_ScamUserWarning: String { return self._s[1986]! } - public var Conversation_Search: String { return self._s[1987]! } - public var DialogList_DeleteBotConversationConfirmation: String { return self._s[1989]! } - public var ReportPeer_ReasonPornography: String { return self._s[1990]! } - public var AutoDownloadSettings_PhotosTitle: String { return self._s[1991]! } - public var Conversation_SendMessageErrorGroupRestricted: String { return self._s[1992]! } - public var Map_LiveLocationGroupDescription: String { return self._s[1993]! } - public var Channel_Setup_TypeHeader: String { return self._s[1994]! } - public var AuthSessions_LoggedIn: String { return self._s[1995]! } - public var Privacy_Forwards_AlwaysAllow_Title: String { return self._s[1996]! } - public var Login_SmsRequestState3: String { return self._s[1997]! } - public var Passport_Address_EditUtilityBill: String { return self._s[1998]! } - public var Appearance_ReduceMotionInfo: String { return self._s[1999]! } - public var Join_ChannelsTooMuch: String { return self._s[2000]! } - public var Channel_Edit_LinkItem: String { return self._s[2001]! } - public var Privacy_Calls_P2PNever: String { return self._s[2002]! } - public var Conversation_AddToReadingList: String { return self._s[2004]! } - public var Share_MultipleMessagesDisabled: String { return self._s[2005]! } - public var Message_Animation: String { return self._s[2006]! } - public var Conversation_DefaultRestrictedMedia: String { return self._s[2007]! } - public var Map_Unknown: String { return self._s[2008]! } - public var AutoDownloadSettings_LastDelimeter: String { return self._s[2009]! } + public var IntentsSettings_Reset: String { return self._s[1982]! } + public var Conversation_Info: String { return self._s[1983]! } + public var Login_InfoDeletePhoto: String { return self._s[1984]! } + public var Passport_Language_vi: String { return self._s[1986]! } + public var UserInfo_ScamUserWarning: String { return self._s[1987]! } + public var Conversation_Search: String { return self._s[1988]! } + public var DialogList_DeleteBotConversationConfirmation: String { return self._s[1990]! } + public var ReportPeer_ReasonPornography: String { return self._s[1991]! } + public var AutoDownloadSettings_PhotosTitle: String { return self._s[1992]! } + public var Conversation_SendMessageErrorGroupRestricted: String { return self._s[1993]! } + public var Map_LiveLocationGroupDescription: String { return self._s[1994]! } + public var Channel_Setup_TypeHeader: String { return self._s[1995]! } + public var AuthSessions_LoggedIn: String { return self._s[1996]! } + public var Privacy_Forwards_AlwaysAllow_Title: String { return self._s[1997]! } + public var Login_SmsRequestState3: String { return self._s[1998]! } + public var Passport_Address_EditUtilityBill: String { return self._s[1999]! } + public var Appearance_ReduceMotionInfo: String { return self._s[2000]! } + public var Join_ChannelsTooMuch: String { return self._s[2001]! } + public var Channel_Edit_LinkItem: String { return self._s[2002]! } + public var Privacy_Calls_P2PNever: String { return self._s[2003]! } + public var Conversation_AddToReadingList: String { return self._s[2005]! } + public var Share_MultipleMessagesDisabled: String { return self._s[2006]! } + public var Message_Animation: String { return self._s[2007]! } + public var Conversation_DefaultRestrictedMedia: String { return self._s[2008]! } + public var Map_Unknown: String { return self._s[2009]! } + public var AutoDownloadSettings_LastDelimeter: String { return self._s[2010]! } public func PUSH_PINNED_TEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2010]!, self._r[2010]!, [_1, _2]) - } - public func Passport_FieldOneOf_Or(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2011]!, self._r[2011]!, [_1, _2]) } - public var Call_StatusRequesting: String { return self._s[2012]! } - public var Conversation_SecretChatContextBotAlert: String { return self._s[2013]! } - public var SocksProxySetup_ProxyStatusChecking: String { return self._s[2014]! } + public func Passport_FieldOneOf_Or(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2012]!, self._r[2012]!, [_1, _2]) + } + public var Call_StatusRequesting: String { return self._s[2013]! } + public var Conversation_SecretChatContextBotAlert: String { return self._s[2014]! } + public var SocksProxySetup_ProxyStatusChecking: String { return self._s[2015]! } public func PUSH_CHAT_MESSAGE_DOC(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2015]!, self._r[2015]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2016]!, self._r[2016]!, [_1, _2]) } public func Notification_PinnedLocationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2016]!, self._r[2016]!, [_0]) + return formatWithArgumentRanges(self._s[2017]!, self._r[2017]!, [_0]) } - public var Update_Skip: String { return self._s[2017]! } - public var Group_Username_RemoveExistingUsernamesInfo: String { return self._s[2018]! } - public var BlockedUsers_Title: String { return self._s[2019]! } - public var Weekday_Monday: String { return self._s[2020]! } + public var Update_Skip: String { return self._s[2018]! } + public var Group_Username_RemoveExistingUsernamesInfo: String { return self._s[2019]! } + public var BlockedUsers_Title: String { return self._s[2020]! } + public var Weekday_Monday: String { return self._s[2021]! } public func PUSH_CHANNEL_MESSAGE_AUDIO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2021]!, self._r[2021]!, [_1]) + return formatWithArgumentRanges(self._s[2022]!, self._r[2022]!, [_1]) } - public var Username_CheckingUsername: String { return self._s[2022]! } - public var NotificationsSound_Bell: String { return self._s[2023]! } - public var Conversation_SendMessageErrorFlood: String { return self._s[2024]! } - public var SettingsSearch_Synonyms_Notifications_DisplayNamesOnLockScreen: String { return self._s[2025]! } - public var ChannelMembers_ChannelAdminsTitle: String { return self._s[2026]! } - public var ChatSettings_Groups: String { return self._s[2027]! } - public var WallpaperPreview_PatternPaternDiscard: String { return self._s[2028]! } + public var Username_CheckingUsername: String { return self._s[2023]! } + public var NotificationsSound_Bell: String { return self._s[2024]! } + public var Conversation_SendMessageErrorFlood: String { return self._s[2025]! } + public var SettingsSearch_Synonyms_Notifications_DisplayNamesOnLockScreen: String { return self._s[2026]! } + public var ChannelMembers_ChannelAdminsTitle: String { return self._s[2027]! } + public var ChatSettings_Groups: String { return self._s[2028]! } + public var WallpaperPreview_PatternPaternDiscard: String { return self._s[2029]! } public func Conversation_SetReminder_RemindTomorrow(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2029]!, self._r[2029]!, [_0]) + return formatWithArgumentRanges(self._s[2030]!, self._r[2030]!, [_0]) } - public var Your_card_was_declined: String { return self._s[2030]! } - public var TwoStepAuth_EnterPasswordHelp: String { return self._s[2032]! } - public var Wallet_Month_ShortApril: String { return self._s[2033]! } - public var ChatList_Unmute: String { return self._s[2034]! } - public var AuthSessions_AddDevice_ScanTitle: String { return self._s[2035]! } - public var PhotoEditor_CurvesAll: String { return self._s[2036]! } - public var Weekday_ShortTuesday: String { return self._s[2037]! } - public var DialogList_Read: String { return self._s[2038]! } - public var Appearance_AppIconClassic: String { return self._s[2039]! } - public var ChannelMembers_WhoCanAddMembers_AllMembers: String { return self._s[2040]! } - public var Passport_Identity_Gender: String { return self._s[2041]! } + public var Your_card_was_declined: String { return self._s[2031]! } + public var TwoStepAuth_EnterPasswordHelp: String { return self._s[2033]! } + public var Wallet_Month_ShortApril: String { return self._s[2034]! } + public var ChatList_Unmute: String { return self._s[2035]! } + public var AuthSessions_AddDevice_ScanTitle: String { return self._s[2036]! } + public var PhotoEditor_CurvesAll: String { return self._s[2037]! } + public var Weekday_ShortTuesday: String { return self._s[2038]! } + public var DialogList_Read: String { return self._s[2039]! } + public var Appearance_AppIconClassic: String { return self._s[2040]! } + public var ChannelMembers_WhoCanAddMembers_AllMembers: String { return self._s[2041]! } + public var Passport_Identity_Gender: String { return self._s[2042]! } public func Target_ShareGameConfirmationPrivate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2042]!, self._r[2042]!, [_0]) + return formatWithArgumentRanges(self._s[2043]!, self._r[2043]!, [_0]) } - public var Target_SelectGroup: String { return self._s[2043]! } - public var Map_HomeAndWorkInfo: String { return self._s[2045]! } + public var Target_SelectGroup: String { return self._s[2044]! } + public var Map_HomeAndWorkInfo: String { return self._s[2046]! } public func DialogList_EncryptedChatStartedIncoming(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2046]!, self._r[2046]!, [_0]) + return formatWithArgumentRanges(self._s[2047]!, self._r[2047]!, [_0]) } - public var Passport_Language_en: String { return self._s[2047]! } - public var AutoDownloadSettings_AutodownloadPhotos: String { return self._s[2048]! } - public var Channel_Username_CreatePublicLinkHelp: String { return self._s[2049]! } - public var Login_CancelPhoneVerificationContinue: String { return self._s[2050]! } - public var ScheduledMessages_SendNow: String { return self._s[2051]! } - public var Checkout_NewCard_PaymentCard: String { return self._s[2053]! } - public var Login_InfoHelp: String { return self._s[2054]! } - public var Contacts_PermissionsSuppressWarningTitle: String { return self._s[2055]! } - public var SettingsSearch_Synonyms_Stickers_FeaturedPacks: String { return self._s[2056]! } + public var Passport_Language_en: String { return self._s[2048]! } + public var AutoDownloadSettings_AutodownloadPhotos: String { return self._s[2049]! } + public var Channel_Username_CreatePublicLinkHelp: String { return self._s[2050]! } + public var Login_CancelPhoneVerificationContinue: String { return self._s[2051]! } + public var ScheduledMessages_SendNow: String { return self._s[2052]! } + public var Checkout_NewCard_PaymentCard: String { return self._s[2054]! } + public var Login_InfoHelp: String { return self._s[2055]! } + public var Contacts_PermissionsSuppressWarningTitle: String { return self._s[2056]! } + public var SettingsSearch_Synonyms_Stickers_FeaturedPacks: String { return self._s[2057]! } public func Channel_AdminLog_MessageChangedLinkedChannel(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2057]!, self._r[2057]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2058]!, self._r[2058]!, [_1, _2]) } - public var SocksProxySetup_AddProxy: String { return self._s[2060]! } - public var CreatePoll_Title: String { return self._s[2061]! } - public var MessagePoll_QuizNoUsers: String { return self._s[2062]! } - public var Conversation_ViewTheme: String { return self._s[2063]! } - public var SettingsSearch_Synonyms_Privacy_Data_SecretChatLinkPreview: String { return self._s[2064]! } - public var PasscodeSettings_SimplePasscodeHelp: String { return self._s[2065]! } - public var TwoFactorSetup_Intro_Text: String { return self._s[2066]! } - public var UserInfo_GroupsInCommon: String { return self._s[2067]! } - public var TelegramWallet_Intro_TermsUrl: String { return self._s[2068]! } - public var Call_AudioRouteHide: String { return self._s[2069]! } + public var SocksProxySetup_AddProxy: String { return self._s[2061]! } + public var CreatePoll_Title: String { return self._s[2062]! } + public var MessagePoll_QuizNoUsers: String { return self._s[2063]! } + public var Conversation_ViewTheme: String { return self._s[2064]! } + public var SettingsSearch_Synonyms_Privacy_Data_SecretChatLinkPreview: String { return self._s[2065]! } + public var PasscodeSettings_SimplePasscodeHelp: String { return self._s[2066]! } + public var TwoFactorSetup_Intro_Text: String { return self._s[2067]! } + public var UserInfo_GroupsInCommon: String { return self._s[2068]! } + public var TelegramWallet_Intro_TermsUrl: String { return self._s[2069]! } + public var Call_AudioRouteHide: String { return self._s[2070]! } public func Wallet_Info_TransactionDateHeader(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2071]!, self._r[2071]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2072]!, self._r[2072]!, [_1, _2]) } - public var ContactInfo_PhoneLabelMobile: String { return self._s[2072]! } - public var IntentsSettings_SuggestedChatsInfo: String { return self._s[2073]! } - public var CreatePoll_QuizOptionsHeader: String { return self._s[2074]! } + public var ContactInfo_PhoneLabelMobile: String { return self._s[2073]! } + public var IntentsSettings_SuggestedChatsInfo: String { return self._s[2074]! } + public var CreatePoll_QuizOptionsHeader: String { return self._s[2075]! } public func ChatList_LeaveGroupConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2075]!, self._r[2075]!, [_0]) + return formatWithArgumentRanges(self._s[2076]!, self._r[2076]!, [_0]) } - public var TextFormat_Bold: String { return self._s[2076]! } - public var FastTwoStepSetup_EmailSection: String { return self._s[2077]! } - public var StickerPackActionInfo_AddedTitle: String { return self._s[2078]! } - public var Notifications_Title: String { return self._s[2079]! } - public var Group_Username_InvalidTooShort: String { return self._s[2080]! } - public var Channel_ErrorAddTooMuch: String { return self._s[2081]! } + public var TextFormat_Bold: String { return self._s[2077]! } + public var FastTwoStepSetup_EmailSection: String { return self._s[2078]! } + public var StickerPackActionInfo_AddedTitle: String { return self._s[2079]! } + public var Notifications_Title: String { return self._s[2080]! } + public var Group_Username_InvalidTooShort: String { return self._s[2081]! } + public var Channel_ErrorAddTooMuch: String { return self._s[2082]! } public func DialogList_MultipleTypingSuffix(_ _0: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2082]!, self._r[2082]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[2083]!, self._r[2083]!, ["\(_0)"]) } - public var VoiceOver_DiscardPreparedContent: String { return self._s[2084]! } - public var Stickers_SuggestAdded: String { return self._s[2085]! } - public var Login_CountryCode: String { return self._s[2086]! } - public var ChatSettings_AutoPlayVideos: String { return self._s[2087]! } - public var Map_GetDirections: String { return self._s[2088]! } - public var Wallet_Receive_ShareInvoiceUrl: String { return self._s[2089]! } - public var Login_PhoneFloodError: String { return self._s[2090]! } + public var VoiceOver_DiscardPreparedContent: String { return self._s[2085]! } + public var Stickers_SuggestAdded: String { return self._s[2086]! } + public var Login_CountryCode: String { return self._s[2087]! } + public var ChatSettings_AutoPlayVideos: String { return self._s[2088]! } + public var Map_GetDirections: String { return self._s[2089]! } + public var Wallet_Receive_ShareInvoiceUrl: String { return self._s[2090]! } + public var Login_PhoneFloodError: String { return self._s[2091]! } public func Time_MonthOfYear_m3(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2091]!, self._r[2091]!, [_0]) + return formatWithArgumentRanges(self._s[2092]!, self._r[2092]!, [_0]) } public func Wallet_Time_PreciseDate_m10(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2092]!, self._r[2092]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2093]!, self._r[2093]!, [_1, _2, _3]) } - public var IntentsSettings_SuggestedChatsPrivateChats: String { return self._s[2093]! } - public var Settings_SetUsername: String { return self._s[2095]! } - public var Group_Location_ChangeLocation: String { return self._s[2096]! } - public var Notification_GroupInviterSelf: String { return self._s[2097]! } - public var InstantPage_TapToOpenLink: String { return self._s[2098]! } + public var IntentsSettings_SuggestedChatsPrivateChats: String { return self._s[2094]! } + public var Settings_SetUsername: String { return self._s[2096]! } + public var Group_Location_ChangeLocation: String { return self._s[2097]! } + public var Notification_GroupInviterSelf: String { return self._s[2098]! } + public var InstantPage_TapToOpenLink: String { return self._s[2099]! } public func Notification_ChannelInviter(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2099]!, self._r[2099]!, [_0]) + return formatWithArgumentRanges(self._s[2100]!, self._r[2100]!, [_0]) } - public var Watch_Suggestion_TalkLater: String { return self._s[2100]! } - public var SecretChat_Title: String { return self._s[2101]! } - public var Group_UpgradeNoticeText1: String { return self._s[2102]! } - public var AuthSessions_Title: String { return self._s[2103]! } + public var Watch_Suggestion_TalkLater: String { return self._s[2101]! } + public var SecretChat_Title: String { return self._s[2102]! } + public var Group_UpgradeNoticeText1: String { return self._s[2103]! } + public var AuthSessions_Title: String { return self._s[2104]! } public func TextFormat_AddLinkText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2104]!, self._r[2104]!, [_0]) + return formatWithArgumentRanges(self._s[2105]!, self._r[2105]!, [_0]) } - public var PhotoEditor_CropAuto: String { return self._s[2105]! } - public var Channel_About_Title: String { return self._s[2106]! } - public var Theme_ThemeChanged: String { return self._s[2107]! } - public var FastTwoStepSetup_EmailHelp: String { return self._s[2108]! } + public var PhotoEditor_CropAuto: String { return self._s[2106]! } + public var Channel_About_Title: String { return self._s[2107]! } + public var Theme_ThemeChanged: String { return self._s[2108]! } + public var FastTwoStepSetup_EmailHelp: String { return self._s[2109]! } public func Conversation_Bytes(_ _0: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2110]!, self._r[2110]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[2111]!, self._r[2111]!, ["\(_0)"]) } - public var VoiceOver_MessageContextReport: String { return self._s[2111]! } - public var Conversation_PinMessageAlert_OnlyPin: String { return self._s[2113]! } - public var Group_Setup_HistoryVisibleHelp: String { return self._s[2114]! } + public var VoiceOver_MessageContextReport: String { return self._s[2112]! } + public var Conversation_PinMessageAlert_OnlyPin: String { return self._s[2114]! } + public var Group_Setup_HistoryVisibleHelp: String { return self._s[2115]! } public func PUSH_MESSAGE_GIF(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2115]!, self._r[2115]!, [_1]) + return formatWithArgumentRanges(self._s[2116]!, self._r[2116]!, [_1]) } public func SharedMedia_SearchNoResultsDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2117]!, self._r[2117]!, [_0]) - } - public func TwoStepAuth_RecoveryEmailUnavailable(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2118]!, self._r[2118]!, [_0]) } - public var Privacy_PaymentsClearInfoHelp: String { return self._s[2119]! } - public var Presence_online: String { return self._s[2122]! } - public var PasscodeSettings_Title: String { return self._s[2123]! } - public var Passport_Identity_ExpiryDatePlaceholder: String { return self._s[2124]! } - public var Web_OpenExternal: String { return self._s[2125]! } - public var AutoDownloadSettings_AutoDownload: String { return self._s[2127]! } - public var Channel_OwnershipTransfer_EnterPasswordText: String { return self._s[2128]! } - public var LocalGroup_Title: String { return self._s[2129]! } + public func TwoStepAuth_RecoveryEmailUnavailable(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2119]!, self._r[2119]!, [_0]) + } + public var Privacy_PaymentsClearInfoHelp: String { return self._s[2120]! } + public var Presence_online: String { return self._s[2123]! } + public var PasscodeSettings_Title: String { return self._s[2124]! } + public var Passport_Identity_ExpiryDatePlaceholder: String { return self._s[2125]! } + public var Web_OpenExternal: String { return self._s[2126]! } + public var AutoDownloadSettings_AutoDownload: String { return self._s[2128]! } + public var Channel_OwnershipTransfer_EnterPasswordText: String { return self._s[2129]! } + public var LocalGroup_Title: String { return self._s[2130]! } public func AutoNightTheme_AutomaticHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2130]!, self._r[2130]!, [_0]) + return formatWithArgumentRanges(self._s[2131]!, self._r[2131]!, [_0]) } - public var FastTwoStepSetup_PasswordConfirmationPlaceholder: String { return self._s[2131]! } - public var Conversation_StopQuizConfirmation: String { return self._s[2132]! } - public var Map_YouAreHere: String { return self._s[2133]! } + public var FastTwoStepSetup_PasswordConfirmationPlaceholder: String { return self._s[2132]! } + public var Conversation_StopQuizConfirmation: String { return self._s[2133]! } + public var Map_YouAreHere: String { return self._s[2134]! } public func AuthSessions_Message(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2134]!, self._r[2134]!, [_0]) - } - public func ChatList_DeleteChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2135]!, self._r[2135]!, [_0]) } - public var Theme_Context_ChangeColors: String { return self._s[2136]! } - public var PrivacyLastSeenSettings_AlwaysShareWith: String { return self._s[2137]! } - public var Target_InviteToGroupErrorAlreadyInvited: String { return self._s[2138]! } - public func AuthSessions_AppUnofficial(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2139]!, self._r[2139]!, [_0]) + public func ChatList_DeleteChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2136]!, self._r[2136]!, [_0]) } - public func DialogList_LiveLocationSharingTo(_ _0: String) -> (String, [(Int, NSRange)]) { + public var Theme_Context_ChangeColors: String { return self._s[2137]! } + public var PrivacyLastSeenSettings_AlwaysShareWith: String { return self._s[2138]! } + public var Target_InviteToGroupErrorAlreadyInvited: String { return self._s[2139]! } + public func AuthSessions_AppUnofficial(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2140]!, self._r[2140]!, [_0]) } - public var SocksProxySetup_Username: String { return self._s[2141]! } - public var Bot_Start: String { return self._s[2142]! } - public func Channel_AdminLog_EmptyFilterQueryText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2143]!, self._r[2143]!, [_0]) + public func DialogList_LiveLocationSharingTo(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2141]!, self._r[2141]!, [_0]) } - public func Channel_AdminLog_MessagePinned(_ _0: String) -> (String, [(Int, NSRange)]) { + public var SocksProxySetup_Username: String { return self._s[2142]! } + public var Bot_Start: String { return self._s[2143]! } + public func Channel_AdminLog_EmptyFilterQueryText(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2144]!, self._r[2144]!, [_0]) } - public var Contacts_SortByPresence: String { return self._s[2145]! } - public var AccentColor_Title: String { return self._s[2147]! } - public var Conversation_DiscardVoiceMessageTitle: String { return self._s[2148]! } + public func Channel_AdminLog_MessagePinned(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2145]!, self._r[2145]!, [_0]) + } + public var Contacts_SortByPresence: String { return self._s[2146]! } + public var AccentColor_Title: String { return self._s[2148]! } + public var Conversation_DiscardVoiceMessageTitle: String { return self._s[2149]! } public func PUSH_CHAT_CREATED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2149]!, self._r[2149]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2150]!, self._r[2150]!, [_1, _2]) } public func PrivacySettings_LastSeenContactsMinus(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2150]!, self._r[2150]!, [_0]) + return formatWithArgumentRanges(self._s[2151]!, self._r[2151]!, [_0]) } public func Channel_AdminLog_MessageChangedLinkedGroup(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2151]!, self._r[2151]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2152]!, self._r[2152]!, [_1, _2]) } - public var Passport_Email_EnterOtherEmail: String { return self._s[2152]! } - public var Login_InfoAvatarPhoto: String { return self._s[2153]! } - public var Privacy_PaymentsClear_ShippingInfo: String { return self._s[2154]! } - public var Tour_Title4: String { return self._s[2155]! } - public var Passport_Identity_Translation: String { return self._s[2156]! } - public var SettingsSearch_Synonyms_Notifications_ContactJoined: String { return self._s[2157]! } - public var Login_TermsOfServiceLabel: String { return self._s[2159]! } - public var Passport_Language_it: String { return self._s[2160]! } - public var KeyCommand_JumpToNextUnreadChat: String { return self._s[2161]! } - public var Passport_Identity_SelfieHelp: String { return self._s[2162]! } - public var Conversation_ClearAll: String { return self._s[2164]! } - public var Wallet_Send_UninitializedText: String { return self._s[2166]! } - public var Channel_OwnershipTransfer_Title: String { return self._s[2167]! } - public var TwoStepAuth_FloodError: String { return self._s[2168]! } + public var Passport_Email_EnterOtherEmail: String { return self._s[2153]! } + public var Login_InfoAvatarPhoto: String { return self._s[2154]! } + public var Privacy_PaymentsClear_ShippingInfo: String { return self._s[2155]! } + public var Tour_Title4: String { return self._s[2156]! } + public var Passport_Identity_Translation: String { return self._s[2157]! } + public var SettingsSearch_Synonyms_Notifications_ContactJoined: String { return self._s[2158]! } + public var Login_TermsOfServiceLabel: String { return self._s[2160]! } + public var Passport_Language_it: String { return self._s[2161]! } + public var KeyCommand_JumpToNextUnreadChat: String { return self._s[2162]! } + public var Passport_Identity_SelfieHelp: String { return self._s[2163]! } + public var Conversation_ClearAll: String { return self._s[2165]! } + public var Wallet_Send_UninitializedText: String { return self._s[2167]! } + public var Channel_OwnershipTransfer_Title: String { return self._s[2168]! } + public var TwoStepAuth_FloodError: String { return self._s[2169]! } public func PUSH_CHANNEL_MESSAGE_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2169]!, self._r[2169]!, [_1]) + return formatWithArgumentRanges(self._s[2170]!, self._r[2170]!, [_1]) } - public var Paint_Delete: String { return self._s[2170]! } + public var Paint_Delete: String { return self._s[2171]! } public func Wallet_Sent_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2171]!, self._r[2171]!, [_0]) + return formatWithArgumentRanges(self._s[2172]!, self._r[2172]!, [_0]) } - public var Privacy_AddNewPeer: String { return self._s[2172]! } + public var Privacy_AddNewPeer: String { return self._s[2173]! } public func Channel_AdminLog_MessageRank(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2173]!, self._r[2173]!, [_1]) + return formatWithArgumentRanges(self._s[2174]!, self._r[2174]!, [_1]) } - public var LogoutOptions_SetPasscodeText: String { return self._s[2174]! } + public var LogoutOptions_SetPasscodeText: String { return self._s[2175]! } public func Passport_AcceptHelp(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2175]!, self._r[2175]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2176]!, self._r[2176]!, [_1, _2]) } - public var Message_PinnedAudioMessage: String { return self._s[2176]! } + public var Message_PinnedAudioMessage: String { return self._s[2177]! } public func Watch_Time_ShortTodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2177]!, self._r[2177]!, [_0]) + return formatWithArgumentRanges(self._s[2178]!, self._r[2178]!, [_0]) } - public var Notification_Mute1hMin: String { return self._s[2178]! } - public var Notifications_GroupNotificationsSound: String { return self._s[2179]! } - public var Wallet_Month_GenNovember: String { return self._s[2180]! } - public var SocksProxySetup_ShareProxyList: String { return self._s[2181]! } - public var Conversation_MessageEditedLabel: String { return self._s[2182]! } + public var Notification_Mute1hMin: String { return self._s[2179]! } + public var Notifications_GroupNotificationsSound: String { return self._s[2180]! } + public var Wallet_Month_GenNovember: String { return self._s[2181]! } + public var SocksProxySetup_ShareProxyList: String { return self._s[2182]! } + public var Conversation_MessageEditedLabel: String { return self._s[2183]! } public func ClearCache_Success(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2183]!, self._r[2183]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2184]!, self._r[2184]!, [_0, _1]) } - public var Notification_Exceptions_AlwaysOff: String { return self._s[2184]! } - public var Notification_Exceptions_NewException_MessagePreviewHeader: String { return self._s[2185]! } + public var Notification_Exceptions_AlwaysOff: String { return self._s[2185]! } + public var Notification_Exceptions_NewException_MessagePreviewHeader: String { return self._s[2186]! } public func Channel_AdminLog_MessageAdmin(_ _0: String, _ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2186]!, self._r[2186]!, [_0, _1, _2]) + return formatWithArgumentRanges(self._s[2187]!, self._r[2187]!, [_0, _1, _2]) } - public var NetworkUsageSettings_ResetStats: String { return self._s[2187]! } + public var NetworkUsageSettings_ResetStats: String { return self._s[2188]! } public func PUSH_MESSAGE_GEOLIVE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2188]!, self._r[2188]!, [_1]) + return formatWithArgumentRanges(self._s[2189]!, self._r[2189]!, [_1]) } - public var AccessDenied_LocationTracking: String { return self._s[2189]! } - public var Month_GenOctober: String { return self._s[2190]! } - public var GroupInfo_InviteLink_RevokeAlert_Revoke: String { return self._s[2191]! } - public var EnterPasscode_EnterPasscode: String { return self._s[2192]! } - public var MediaPicker_TimerTooltip: String { return self._s[2194]! } - public var SharedMedia_TitleAll: String { return self._s[2195]! } - public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsExceptions: String { return self._s[2198]! } - public var Conversation_RestrictedMedia: String { return self._s[2199]! } - public var AccessDenied_PhotosRestricted: String { return self._s[2200]! } - public var Privacy_Forwards_WhoCanForward: String { return self._s[2202]! } - public var ChangePhoneNumberCode_Called: String { return self._s[2203]! } + public var AccessDenied_LocationTracking: String { return self._s[2190]! } + public var Month_GenOctober: String { return self._s[2191]! } + public var GroupInfo_InviteLink_RevokeAlert_Revoke: String { return self._s[2192]! } + public var EnterPasscode_EnterPasscode: String { return self._s[2193]! } + public var MediaPicker_TimerTooltip: String { return self._s[2195]! } + public var SharedMedia_TitleAll: String { return self._s[2196]! } + public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsExceptions: String { return self._s[2199]! } + public var Conversation_RestrictedMedia: String { return self._s[2200]! } + public var AccessDenied_PhotosRestricted: String { return self._s[2201]! } + public var Privacy_Forwards_WhoCanForward: String { return self._s[2203]! } + public var ChangePhoneNumberCode_Called: String { return self._s[2204]! } public func Notification_PinnedDocumentMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2204]!, self._r[2204]!, [_0]) + return formatWithArgumentRanges(self._s[2205]!, self._r[2205]!, [_0]) } - public var Conversation_SavedMessages: String { return self._s[2207]! } - public var Your_cards_expiration_month_is_invalid: String { return self._s[2209]! } - public var FastTwoStepSetup_PasswordPlaceholder: String { return self._s[2210]! } + public var Conversation_SavedMessages: String { return self._s[2208]! } + public var Your_cards_expiration_month_is_invalid: String { return self._s[2210]! } + public var FastTwoStepSetup_PasswordPlaceholder: String { return self._s[2211]! } public func Target_ShareGameConfirmationGroup(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2212]!, self._r[2212]!, [_0]) + return formatWithArgumentRanges(self._s[2213]!, self._r[2213]!, [_0]) } - public var VoiceOver_Chat_YourMessage: String { return self._s[2213]! } + public var VoiceOver_Chat_YourMessage: String { return self._s[2214]! } public func VoiceOver_Chat_Title(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2214]!, self._r[2214]!, [_0]) + return formatWithArgumentRanges(self._s[2215]!, self._r[2215]!, [_0]) } - public var ReportPeer_AlertSuccess: String { return self._s[2215]! } - public var PhotoEditor_CropAspectRatioOriginal: String { return self._s[2216]! } + public var ReportPeer_AlertSuccess: String { return self._s[2216]! } + public var PhotoEditor_CropAspectRatioOriginal: String { return self._s[2217]! } public func InstantPage_RelatedArticleAuthorAndDateTitle(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2217]!, self._r[2217]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2218]!, self._r[2218]!, [_1, _2]) } - public var Checkout_PasswordEntry_Title: String { return self._s[2218]! } - public var PhotoEditor_FadeTool: String { return self._s[2219]! } - public var Privacy_ContactsReset: String { return self._s[2220]! } + public var Checkout_PasswordEntry_Title: String { return self._s[2219]! } + public var PhotoEditor_FadeTool: String { return self._s[2220]! } + public var Privacy_ContactsReset: String { return self._s[2221]! } public func Channel_AdminLog_MessageRestrictedUntil(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2222]!, self._r[2222]!, [_0]) + return formatWithArgumentRanges(self._s[2223]!, self._r[2223]!, [_0]) } - public var Message_PinnedVideoMessage: String { return self._s[2223]! } - public var ChatList_Mute: String { return self._s[2224]! } + public var Message_PinnedVideoMessage: String { return self._s[2224]! } + public var ChatList_Mute: String { return self._s[2225]! } public func Wallet_Time_PreciseDate_m5(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2225]!, self._r[2225]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2226]!, self._r[2226]!, [_1, _2, _3]) } - public var Permissions_CellularDataText_v0: String { return self._s[2226]! } - public var Conversation_PinnedQuiz: String { return self._s[2228]! } - public var ShareMenu_SelectChats: String { return self._s[2230]! } - public var ChatList_Context_Unarchive: String { return self._s[2231]! } - public var MusicPlayer_VoiceNote: String { return self._s[2232]! } - public var Conversation_RestrictedText: String { return self._s[2233]! } - public var SettingsSearch_Synonyms_Privacy_Data_DeleteDrafts: String { return self._s[2234]! } - public var Wallet_Month_GenApril: String { return self._s[2235]! } - public var Wallet_Month_ShortMarch: String { return self._s[2236]! } - public var TwoStepAuth_DisableSuccess: String { return self._s[2237]! } - public var Cache_Videos: String { return self._s[2238]! } - public var PrivacySettings_PhoneNumber: String { return self._s[2239]! } - public var Wallet_Month_GenFebruary: String { return self._s[2240]! } - public var FeatureDisabled_Oops: String { return self._s[2242]! } - public var Passport_Address_PostcodePlaceholder: String { return self._s[2243]! } + public var Permissions_CellularDataText_v0: String { return self._s[2227]! } + public var Conversation_PinnedQuiz: String { return self._s[2229]! } + public var ShareMenu_SelectChats: String { return self._s[2231]! } + public var ChatList_Context_Unarchive: String { return self._s[2232]! } + public var MusicPlayer_VoiceNote: String { return self._s[2233]! } + public var Conversation_RestrictedText: String { return self._s[2234]! } + public var SettingsSearch_Synonyms_Privacy_Data_DeleteDrafts: String { return self._s[2235]! } + public var Wallet_Month_GenApril: String { return self._s[2236]! } + public var Wallet_Month_ShortMarch: String { return self._s[2237]! } + public var TwoStepAuth_DisableSuccess: String { return self._s[2238]! } + public var Cache_Videos: String { return self._s[2239]! } + public var PrivacySettings_PhoneNumber: String { return self._s[2240]! } + public var Wallet_Month_GenFebruary: String { return self._s[2241]! } + public var FeatureDisabled_Oops: String { return self._s[2243]! } + public var Passport_Address_PostcodePlaceholder: String { return self._s[2244]! } public func AddContact_StatusSuccess(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2244]!, self._r[2244]!, [_0]) + return formatWithArgumentRanges(self._s[2245]!, self._r[2245]!, [_0]) } - public var Stickers_GroupStickersHelp: String { return self._s[2245]! } - public var GroupPermission_NoSendPolls: String { return self._s[2246]! } - public var Wallet_Qr_ScanCode: String { return self._s[2247]! } - public var Message_VideoExpired: String { return self._s[2249]! } - public var GroupInfo_GroupHistoryVisible: String { return self._s[2250]! } - public var Notifications_Badge: String { return self._s[2251]! } - public var Wallet_Receive_AddressCopied: String { return self._s[2252]! } - public var CreatePoll_OptionPlaceholder: String { return self._s[2253]! } - public var Username_InvalidTooShort: String { return self._s[2254]! } - public var EnterPasscode_EnterNewPasscodeChange: String { return self._s[2255]! } - public var Channel_AdminLog_PinMessages: String { return self._s[2256]! } - public var ArchivedChats_IntroTitle3: String { return self._s[2257]! } + public var Stickers_GroupStickersHelp: String { return self._s[2246]! } + public var GroupPermission_NoSendPolls: String { return self._s[2247]! } + public var Wallet_Qr_ScanCode: String { return self._s[2248]! } + public var Message_VideoExpired: String { return self._s[2250]! } + public var GroupInfo_GroupHistoryVisible: String { return self._s[2251]! } + public var Notifications_Badge: String { return self._s[2252]! } + public var Wallet_Receive_AddressCopied: String { return self._s[2253]! } + public var CreatePoll_OptionPlaceholder: String { return self._s[2254]! } + public var Username_InvalidTooShort: String { return self._s[2255]! } + public var EnterPasscode_EnterNewPasscodeChange: String { return self._s[2256]! } + public var Channel_AdminLog_PinMessages: String { return self._s[2257]! } + public var ArchivedChats_IntroTitle3: String { return self._s[2258]! } public func Notification_MessageLifetimeRemoved(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2258]!, self._r[2258]!, [_1]) + return formatWithArgumentRanges(self._s[2259]!, self._r[2259]!, [_1]) } - public var Permissions_SiriAllowInSettings_v0: String { return self._s[2259]! } - public var Conversation_DefaultRestrictedText: String { return self._s[2260]! } - public var SharedMedia_CategoryDocs: String { return self._s[2263]! } + public var Permissions_SiriAllowInSettings_v0: String { return self._s[2260]! } + public var Conversation_DefaultRestrictedText: String { return self._s[2261]! } + public var SharedMedia_CategoryDocs: String { return self._s[2264]! } public func PUSH_MESSAGE_CONTACT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2264]!, self._r[2264]!, [_1]) + return formatWithArgumentRanges(self._s[2265]!, self._r[2265]!, [_1]) } - public var Wallet_Send_UninitializedTitle: String { return self._s[2265]! } - public var StickerPackActionInfo_ArchivedTitle: String { return self._s[2266]! } - public var Privacy_Forwards_NeverLink: String { return self._s[2268]! } + public var Wallet_Send_UninitializedTitle: String { return self._s[2266]! } + public var StickerPackActionInfo_ArchivedTitle: String { return self._s[2267]! } + public var Privacy_Forwards_NeverLink: String { return self._s[2269]! } public func Notification_MessageLifetimeChangedOutgoing(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2269]!, self._r[2269]!, [_1]) + return formatWithArgumentRanges(self._s[2270]!, self._r[2270]!, [_1]) } - public var CheckoutInfo_ErrorShippingNotAvailable: String { return self._s[2270]! } + public var CheckoutInfo_ErrorShippingNotAvailable: String { return self._s[2271]! } public func Time_MonthOfYear_m12(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2271]!, self._r[2271]!, [_0]) + return formatWithArgumentRanges(self._s[2272]!, self._r[2272]!, [_0]) } - public var ChatSettings_PrivateChats: String { return self._s[2272]! } - public var SettingsSearch_Synonyms_EditProfile_Logout: String { return self._s[2273]! } - public var Conversation_PrivateMessageLinkCopied: String { return self._s[2274]! } - public var Channel_UpdatePhotoItem: String { return self._s[2275]! } - public var GroupInfo_LeftStatus: String { return self._s[2276]! } - public var Watch_MessageView_Forward: String { return self._s[2278]! } - public var ReportPeer_ReasonChildAbuse: String { return self._s[2279]! } - public var Cache_ClearEmpty: String { return self._s[2281]! } - public var Localization_LanguageName: String { return self._s[2282]! } - public var Wallet_AccessDenied_Title: String { return self._s[2283]! } - public var WebSearch_GIFs: String { return self._s[2284]! } - public var Notifications_DisplayNamesOnLockScreenInfoWithLink: String { return self._s[2285]! } - public var Wallet_AccessDenied_Settings: String { return self._s[2286]! } - public var Username_InvalidStartsWithNumber: String { return self._s[2287]! } - public var Common_Back: String { return self._s[2288]! } - public var GroupInfo_Permissions_EditingDisabled: String { return self._s[2289]! } - public var Passport_Identity_DateOfBirthPlaceholder: String { return self._s[2290]! } - public var Wallet_Send_Send: String { return self._s[2291]! } + public var ChatSettings_PrivateChats: String { return self._s[2273]! } + public var SettingsSearch_Synonyms_EditProfile_Logout: String { return self._s[2274]! } + public var Conversation_PrivateMessageLinkCopied: String { return self._s[2275]! } + public var Channel_UpdatePhotoItem: String { return self._s[2276]! } + public var GroupInfo_LeftStatus: String { return self._s[2277]! } + public var Watch_MessageView_Forward: String { return self._s[2279]! } + public var ReportPeer_ReasonChildAbuse: String { return self._s[2280]! } + public var Cache_ClearEmpty: String { return self._s[2282]! } + public var Localization_LanguageName: String { return self._s[2283]! } + public var Wallet_AccessDenied_Title: String { return self._s[2284]! } + public var WebSearch_GIFs: String { return self._s[2285]! } + public var Notifications_DisplayNamesOnLockScreenInfoWithLink: String { return self._s[2286]! } + public var Wallet_AccessDenied_Settings: String { return self._s[2287]! } + public var Username_InvalidStartsWithNumber: String { return self._s[2288]! } + public var Common_Back: String { return self._s[2289]! } + public var GroupInfo_Permissions_EditingDisabled: String { return self._s[2290]! } + public var Passport_Identity_DateOfBirthPlaceholder: String { return self._s[2291]! } + public var Wallet_Send_Send: String { return self._s[2292]! } public func PUSH_CHANNEL_MESSAGE_STICKER(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2293]!, self._r[2293]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2294]!, self._r[2294]!, [_1, _2]) } - public var Wallet_Info_RefreshErrorTitle: String { return self._s[2294]! } - public var Wallet_Month_GenJune: String { return self._s[2295]! } - public var Passport_Email_Help: String { return self._s[2296]! } - public var Watch_Conversation_Reply: String { return self._s[2298]! } - public var Conversation_EditingMessageMediaChange: String { return self._s[2301]! } - public var Passport_Identity_IssueDatePlaceholder: String { return self._s[2302]! } - public var Channel_BanUser_Unban: String { return self._s[2304]! } - public var Channel_EditAdmin_PermissionPostMessages: String { return self._s[2305]! } - public var Group_Username_CreatePublicLinkHelp: String { return self._s[2306]! } - public var TwoStepAuth_ConfirmEmailCodePlaceholder: String { return self._s[2308]! } - public var Wallet_Send_AddressHeader: String { return self._s[2309]! } - public var Passport_Identity_Name: String { return self._s[2310]! } + public var Wallet_Info_RefreshErrorTitle: String { return self._s[2295]! } + public var Wallet_Month_GenJune: String { return self._s[2296]! } + public var Passport_Email_Help: String { return self._s[2297]! } + public var Watch_Conversation_Reply: String { return self._s[2299]! } + public var Conversation_EditingMessageMediaChange: String { return self._s[2302]! } + public var Passport_Identity_IssueDatePlaceholder: String { return self._s[2303]! } + public var Channel_BanUser_Unban: String { return self._s[2305]! } + public var Channel_EditAdmin_PermissionPostMessages: String { return self._s[2306]! } + public var Group_Username_CreatePublicLinkHelp: String { return self._s[2307]! } + public var TwoStepAuth_ConfirmEmailCodePlaceholder: String { return self._s[2309]! } + public var Wallet_Send_AddressHeader: String { return self._s[2310]! } + public var Passport_Identity_Name: String { return self._s[2311]! } public func Channel_DiscussionGroup_HeaderGroupSet(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2311]!, self._r[2311]!, [_0]) + return formatWithArgumentRanges(self._s[2312]!, self._r[2312]!, [_0]) } - public var GroupRemoved_ViewUserInfo: String { return self._s[2312]! } - public var Conversation_BlockUser: String { return self._s[2313]! } - public var Month_GenJanuary: String { return self._s[2314]! } - public var ChatSettings_TextSize: String { return self._s[2315]! } - public var Notification_PassportValuePhone: String { return self._s[2316]! } - public var MediaPlayer_UnknownArtist: String { return self._s[2317]! } - public var Passport_Language_ne: String { return self._s[2318]! } - public var Notification_CallBack: String { return self._s[2319]! } - public var Wallet_SecureStorageReset_BiometryTouchId: String { return self._s[2320]! } - public var TwoStepAuth_EmailHelp: String { return self._s[2321]! } + public var GroupRemoved_ViewUserInfo: String { return self._s[2313]! } + public var Conversation_BlockUser: String { return self._s[2314]! } + public var Month_GenJanuary: String { return self._s[2315]! } + public var ChatSettings_TextSize: String { return self._s[2316]! } + public var Notification_PassportValuePhone: String { return self._s[2317]! } + public var MediaPlayer_UnknownArtist: String { return self._s[2318]! } + public var Passport_Language_ne: String { return self._s[2319]! } + public var Notification_CallBack: String { return self._s[2320]! } + public var Wallet_SecureStorageReset_BiometryTouchId: String { return self._s[2321]! } + public var TwoStepAuth_EmailHelp: String { return self._s[2322]! } public func Time_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2322]!, self._r[2322]!, [_0]) + return formatWithArgumentRanges(self._s[2323]!, self._r[2323]!, [_0]) } - public var Channel_Info_Management: String { return self._s[2323]! } - public var Passport_FieldIdentityUploadHelp: String { return self._s[2324]! } - public var Stickers_FrequentlyUsed: String { return self._s[2325]! } - public var Channel_BanUser_PermissionSendMessages: String { return self._s[2326]! } - public var Passport_Address_OneOfTypeUtilityBill: String { return self._s[2328]! } + public var Channel_Info_Management: String { return self._s[2324]! } + public var Passport_FieldIdentityUploadHelp: String { return self._s[2325]! } + public var Stickers_FrequentlyUsed: String { return self._s[2326]! } + public var Channel_BanUser_PermissionSendMessages: String { return self._s[2327]! } + public var Passport_Address_OneOfTypeUtilityBill: String { return self._s[2329]! } public func LOCAL_CHANNEL_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2329]!, self._r[2329]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[2330]!, self._r[2330]!, [_1, "\(_2)"]) } - public var TwoFactorSetup_Password_Title: String { return self._s[2330]! } - public var Passport_Address_EditResidentialAddress: String { return self._s[2331]! } - public var PrivacyPolicy_DeclineTitle: String { return self._s[2332]! } - public var CreatePoll_TextHeader: String { return self._s[2333]! } + public var TwoFactorSetup_Password_Title: String { return self._s[2331]! } + public var Passport_Address_EditResidentialAddress: String { return self._s[2332]! } + public var PrivacyPolicy_DeclineTitle: String { return self._s[2333]! } + public var CreatePoll_TextHeader: String { return self._s[2334]! } public func Checkout_SavePasswordTimeoutAndTouchId(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2334]!, self._r[2334]!, [_0]) + return formatWithArgumentRanges(self._s[2335]!, self._r[2335]!, [_0]) } - public var PhotoEditor_QualityMedium: String { return self._s[2335]! } - public var InfoPlist_NSMicrophoneUsageDescription: String { return self._s[2336]! } - public var Conversation_StatusKickedFromChannel: String { return self._s[2338]! } - public var CheckoutInfo_ReceiverInfoName: String { return self._s[2339]! } - public var Group_ErrorSendRestrictedStickers: String { return self._s[2340]! } + public var PhotoEditor_QualityMedium: String { return self._s[2336]! } + public var InfoPlist_NSMicrophoneUsageDescription: String { return self._s[2337]! } + public var Conversation_StatusKickedFromChannel: String { return self._s[2339]! } + public var CheckoutInfo_ReceiverInfoName: String { return self._s[2340]! } + public var Group_ErrorSendRestrictedStickers: String { return self._s[2341]! } public func Conversation_RestrictedInlineTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2341]!, self._r[2341]!, [_0]) + return formatWithArgumentRanges(self._s[2342]!, self._r[2342]!, [_0]) } public func Channel_AdminLog_MessageTransferedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2342]!, self._r[2342]!, [_1]) + return formatWithArgumentRanges(self._s[2343]!, self._r[2343]!, [_1]) } - public var LogoutOptions_LogOutWalletInfo: String { return self._s[2343]! } - public var TwoFactorSetup_Email_SkipConfirmationTitle: String { return self._s[2344]! } - public var Conversation_LinkDialogOpen: String { return self._s[2346]! } - public var TwoFactorSetup_Hint_Title: String { return self._s[2347]! } - public var VoiceOver_Chat_PollNoVotes: String { return self._s[2348]! } - public var Settings_Username: String { return self._s[2350]! } - public var Conversation_Block: String { return self._s[2352]! } - public var Wallpaper_Wallpaper: String { return self._s[2353]! } - public var SocksProxySetup_UseProxy: String { return self._s[2355]! } - public var Wallet_Send_Confirmation: String { return self._s[2356]! } - public var EditTheme_UploadEditedTheme: String { return self._s[2357]! } - public var UserInfo_ShareMyContactInfo: String { return self._s[2358]! } - public var MessageTimer_Forever: String { return self._s[2359]! } - public var Privacy_Calls_WhoCanCallMe: String { return self._s[2360]! } - public var PhotoEditor_DiscardChanges: String { return self._s[2361]! } - public var AuthSessions_TerminateOtherSessionsHelp: String { return self._s[2362]! } - public var Passport_Language_da: String { return self._s[2363]! } - public var SocksProxySetup_PortPlaceholder: String { return self._s[2364]! } + public var LogoutOptions_LogOutWalletInfo: String { return self._s[2344]! } + public var TwoFactorSetup_Email_SkipConfirmationTitle: String { return self._s[2345]! } + public var Conversation_LinkDialogOpen: String { return self._s[2347]! } + public var TwoFactorSetup_Hint_Title: String { return self._s[2348]! } + public var VoiceOver_Chat_PollNoVotes: String { return self._s[2349]! } + public var Settings_Username: String { return self._s[2351]! } + public var Conversation_Block: String { return self._s[2353]! } + public var Wallpaper_Wallpaper: String { return self._s[2354]! } + public var SocksProxySetup_UseProxy: String { return self._s[2356]! } + public var Wallet_Send_Confirmation: String { return self._s[2357]! } + public var EditTheme_UploadEditedTheme: String { return self._s[2358]! } + public var UserInfo_ShareMyContactInfo: String { return self._s[2359]! } + public var MessageTimer_Forever: String { return self._s[2360]! } + public var Privacy_Calls_WhoCanCallMe: String { return self._s[2361]! } + public var PhotoEditor_DiscardChanges: String { return self._s[2362]! } + public var AuthSessions_TerminateOtherSessionsHelp: String { return self._s[2363]! } + public var Passport_Language_da: String { return self._s[2364]! } + public var SocksProxySetup_PortPlaceholder: String { return self._s[2365]! } public func SecretGIF_NotViewedYet(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2365]!, self._r[2365]!, [_0]) + return formatWithArgumentRanges(self._s[2366]!, self._r[2366]!, [_0]) } - public var Passport_Address_EditPassportRegistration: String { return self._s[2366]! } + public var Passport_Address_EditPassportRegistration: String { return self._s[2367]! } public func Channel_AdminLog_MessageChangedGroupAbout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2368]!, self._r[2368]!, [_0]) + return formatWithArgumentRanges(self._s[2369]!, self._r[2369]!, [_0]) } - public var Settings_AddDevice: String { return self._s[2369]! } - public var Passport_Identity_ResidenceCountryPlaceholder: String { return self._s[2371]! } - public var AuthSessions_AddDeviceIntro_Text1: String { return self._s[2372]! } - public var Conversation_SearchByName_Prefix: String { return self._s[2373]! } - public var Conversation_PinnedPoll: String { return self._s[2374]! } - public var AuthSessions_AddDeviceIntro_Text2: String { return self._s[2375]! } - public var Conversation_EmptyGifPanelPlaceholder: String { return self._s[2376]! } - public var AuthSessions_AddDeviceIntro_Text3: String { return self._s[2377]! } + public var Settings_AddDevice: String { return self._s[2370]! } + public var Passport_Identity_ResidenceCountryPlaceholder: String { return self._s[2372]! } + public var AuthSessions_AddDeviceIntro_Text1: String { return self._s[2373]! } + public var Conversation_SearchByName_Prefix: String { return self._s[2374]! } + public var Conversation_PinnedPoll: String { return self._s[2375]! } + public var AuthSessions_AddDeviceIntro_Text2: String { return self._s[2376]! } + public var Conversation_EmptyGifPanelPlaceholder: String { return self._s[2377]! } + public var AuthSessions_AddDeviceIntro_Text3: String { return self._s[2378]! } public func PUSH_ENCRYPTION_ACCEPT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2378]!, self._r[2378]!, [_1]) + return formatWithArgumentRanges(self._s[2379]!, self._r[2379]!, [_1]) } - public var WallpaperSearch_ColorPurple: String { return self._s[2379]! } - public var Cache_ByPeerHeader: String { return self._s[2380]! } + public var WallpaperSearch_ColorPurple: String { return self._s[2380]! } + public var Cache_ByPeerHeader: String { return self._s[2381]! } public func Conversation_EncryptedPlaceholderTitleIncoming(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2381]!, self._r[2381]!, [_0]) + return formatWithArgumentRanges(self._s[2382]!, self._r[2382]!, [_0]) } - public var ChatSettings_AutoDownloadDocuments: String { return self._s[2382]! } - public var Appearance_ThemePreview_Chat_3_Text: String { return self._s[2385]! } - public var Wallet_Completed_Title: String { return self._s[2386]! } - public var Notification_PinnedMessage: String { return self._s[2387]! } - public var TwoFactorSetup_EmailVerification_Placeholder: String { return self._s[2388]! } - public var VoiceOver_Chat_RecordModeVideoMessage: String { return self._s[2390]! } - public var Contacts_SortBy: String { return self._s[2391]! } + public var ChatSettings_AutoDownloadDocuments: String { return self._s[2383]! } + public var Appearance_ThemePreview_Chat_3_Text: String { return self._s[2386]! } + public var Wallet_Completed_Title: String { return self._s[2387]! } + public var Notification_PinnedMessage: String { return self._s[2388]! } + public var TwoFactorSetup_EmailVerification_Placeholder: String { return self._s[2389]! } + public var VoiceOver_Chat_RecordModeVideoMessage: String { return self._s[2391]! } + public var Contacts_SortBy: String { return self._s[2392]! } public func PUSH_CHANNEL_MESSAGE_NOTEXT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2392]!, self._r[2392]!, [_1]) + return formatWithArgumentRanges(self._s[2393]!, self._r[2393]!, [_1]) } - public var Appearance_ColorThemeNight: String { return self._s[2394]! } + public var Appearance_ColorThemeNight: String { return self._s[2395]! } public func PUSH_MESSAGE_GAME(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2395]!, self._r[2395]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2396]!, self._r[2396]!, [_1, _2]) } - public var Call_EncryptionKey_Title: String { return self._s[2396]! } - public var Watch_UserInfo_Service: String { return self._s[2397]! } - public var SettingsSearch_Synonyms_Data_SaveEditedPhotos: String { return self._s[2399]! } - public var Conversation_Unpin: String { return self._s[2401]! } - public var CancelResetAccount_Title: String { return self._s[2402]! } - public var Map_LiveLocationFor15Minutes: String { return self._s[2403]! } + public var Call_EncryptionKey_Title: String { return self._s[2397]! } + public var Watch_UserInfo_Service: String { return self._s[2398]! } + public var SettingsSearch_Synonyms_Data_SaveEditedPhotos: String { return self._s[2400]! } + public var Conversation_Unpin: String { return self._s[2402]! } + public var CancelResetAccount_Title: String { return self._s[2403]! } + public var Map_LiveLocationFor15Minutes: String { return self._s[2404]! } public func Time_PreciseDate_m8(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2405]!, self._r[2405]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2406]!, self._r[2406]!, [_1, _2, _3]) } - public var Group_Members_AddMemberBotErrorNotAllowed: String { return self._s[2406]! } - public var CallSettings_Title: String { return self._s[2407]! } - public var SettingsSearch_Synonyms_Appearance_ChatBackground: String { return self._s[2408]! } - public var PasscodeSettings_EncryptDataHelp: String { return self._s[2410]! } - public var AutoDownloadSettings_Contacts: String { return self._s[2411]! } + public var Group_Members_AddMemberBotErrorNotAllowed: String { return self._s[2407]! } + public var CallSettings_Title: String { return self._s[2408]! } + public var SettingsSearch_Synonyms_Appearance_ChatBackground: String { return self._s[2409]! } + public var PasscodeSettings_EncryptDataHelp: String { return self._s[2411]! } + public var AutoDownloadSettings_Contacts: String { return self._s[2412]! } public func Channel_AdminLog_MessageRankName(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2412]!, self._r[2412]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2413]!, self._r[2413]!, [_1, _2]) } - public var Passport_Identity_DocumentDetails: String { return self._s[2413]! } - public var LoginPassword_PasswordHelp: String { return self._s[2414]! } - public var SettingsSearch_Synonyms_Data_AutoDownloadUsingWifi: String { return self._s[2415]! } - public var PrivacyLastSeenSettings_CustomShareSettings_Delete: String { return self._s[2416]! } - public var ChatContextMenu_TextSelectionTip: String { return self._s[2417]! } - public var Checkout_TotalPaidAmount: String { return self._s[2418]! } + public var Passport_Identity_DocumentDetails: String { return self._s[2414]! } + public var LoginPassword_PasswordHelp: String { return self._s[2415]! } + public var SettingsSearch_Synonyms_Data_AutoDownloadUsingWifi: String { return self._s[2416]! } + public var PrivacyLastSeenSettings_CustomShareSettings_Delete: String { return self._s[2417]! } + public var ChatContextMenu_TextSelectionTip: String { return self._s[2418]! } + public var Checkout_TotalPaidAmount: String { return self._s[2419]! } public func FileSize_KB(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2419]!, self._r[2419]!, [_0]) + return formatWithArgumentRanges(self._s[2420]!, self._r[2420]!, [_0]) } - public var PasscodeSettings_ChangePasscode: String { return self._s[2420]! } - public var Conversation_SecretLinkPreviewAlert: String { return self._s[2422]! } - public var Privacy_SecretChatsLinkPreviews: String { return self._s[2423]! } + public var PasscodeSettings_ChangePasscode: String { return self._s[2421]! } + public var Conversation_SecretLinkPreviewAlert: String { return self._s[2423]! } + public var Privacy_SecretChatsLinkPreviews: String { return self._s[2424]! } public func PUSH_CHANNEL_MESSAGE_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2424]!, self._r[2424]!, [_1]) + return formatWithArgumentRanges(self._s[2425]!, self._r[2425]!, [_1]) } - public var VoiceOver_Chat_ReplyToYourMessage: String { return self._s[2425]! } - public var Contacts_InviteFriends: String { return self._s[2427]! } - public var Map_ChooseLocationTitle: String { return self._s[2428]! } - public var Conversation_StopPoll: String { return self._s[2430]! } + public var VoiceOver_Chat_ReplyToYourMessage: String { return self._s[2426]! } + public var Contacts_InviteFriends: String { return self._s[2428]! } + public var Map_ChooseLocationTitle: String { return self._s[2429]! } + public var Conversation_StopPoll: String { return self._s[2431]! } public func WebSearch_SearchNoResultsDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2431]!, self._r[2431]!, [_0]) + return formatWithArgumentRanges(self._s[2432]!, self._r[2432]!, [_0]) } - public var Call_Camera: String { return self._s[2432]! } - public var LogoutOptions_ChangePhoneNumberTitle: String { return self._s[2433]! } - public var AppWallet_Intro_Text: String { return self._s[2434]! } - public var Calls_RatingFeedback: String { return self._s[2435]! } - public var GroupInfo_BroadcastListNamePlaceholder: String { return self._s[2437]! } - public var Wallet_Alert_OK: String { return self._s[2438]! } - public var NotificationsSound_Pulse: String { return self._s[2439]! } - public var Watch_LastSeen_Lately: String { return self._s[2440]! } - public var ReportGroupLocation_Report: String { return self._s[2443]! } - public var Widget_NoUsers: String { return self._s[2444]! } - public var Conversation_UnvotePoll: String { return self._s[2445]! } - public var SettingsSearch_Synonyms_Privacy_ProfilePhoto: String { return self._s[2447]! } - public var Privacy_ProfilePhoto_WhoCanSeeMyPhoto: String { return self._s[2448]! } - public var NotificationsSound_Circles: String { return self._s[2449]! } - public var PrivacyLastSeenSettings_AlwaysShareWith_Title: String { return self._s[2452]! } - public var Wallet_Settings_DeleteWallet: String { return self._s[2453]! } - public var TwoStepAuth_RecoveryCodeExpired: String { return self._s[2454]! } - public var Proxy_TooltipUnavailable: String { return self._s[2455]! } - public var Passport_Identity_CountryPlaceholder: String { return self._s[2457]! } - public var GroupInfo_Permissions_SlowmodeInfo: String { return self._s[2459]! } - public var Conversation_FileDropbox: String { return self._s[2460]! } - public var Notifications_ExceptionsUnmuted: String { return self._s[2461]! } - public var Tour_Text3: String { return self._s[2463]! } - public var Login_ResetAccountProtected_Title: String { return self._s[2465]! } - public var GroupPermission_NoSendMessages: String { return self._s[2466]! } - public var WallpaperSearch_ColorTitle: String { return self._s[2467]! } - public var ChatAdmins_AllMembersAreAdminsOnHelp: String { return self._s[2468]! } + public var Call_Camera: String { return self._s[2433]! } + public var LogoutOptions_ChangePhoneNumberTitle: String { return self._s[2434]! } + public var AppWallet_Intro_Text: String { return self._s[2435]! } + public var Calls_RatingFeedback: String { return self._s[2436]! } + public var GroupInfo_BroadcastListNamePlaceholder: String { return self._s[2438]! } + public var Wallet_Alert_OK: String { return self._s[2439]! } + public var NotificationsSound_Pulse: String { return self._s[2440]! } + public var Watch_LastSeen_Lately: String { return self._s[2441]! } + public var ReportGroupLocation_Report: String { return self._s[2444]! } + public var Widget_NoUsers: String { return self._s[2445]! } + public var Conversation_UnvotePoll: String { return self._s[2446]! } + public var SettingsSearch_Synonyms_Privacy_ProfilePhoto: String { return self._s[2448]! } + public var Privacy_ProfilePhoto_WhoCanSeeMyPhoto: String { return self._s[2449]! } + public var NotificationsSound_Circles: String { return self._s[2450]! } + public var PrivacyLastSeenSettings_AlwaysShareWith_Title: String { return self._s[2453]! } + public var Wallet_Settings_DeleteWallet: String { return self._s[2454]! } + public var TwoStepAuth_RecoveryCodeExpired: String { return self._s[2455]! } + public var Proxy_TooltipUnavailable: String { return self._s[2456]! } + public var Passport_Identity_CountryPlaceholder: String { return self._s[2458]! } + public var GroupInfo_Permissions_SlowmodeInfo: String { return self._s[2460]! } + public var Conversation_FileDropbox: String { return self._s[2461]! } + public var Notifications_ExceptionsUnmuted: String { return self._s[2462]! } + public var Tour_Text3: String { return self._s[2464]! } + public var Login_ResetAccountProtected_Title: String { return self._s[2466]! } + public var GroupPermission_NoSendMessages: String { return self._s[2467]! } + public var WallpaperSearch_ColorTitle: String { return self._s[2468]! } + public var ChatAdmins_AllMembersAreAdminsOnHelp: String { return self._s[2469]! } public func Conversation_LiveLocationYouAnd(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2470]!, self._r[2470]!, [_0]) + return formatWithArgumentRanges(self._s[2471]!, self._r[2471]!, [_0]) } - public var GroupInfo_AddParticipantTitle: String { return self._s[2471]! } - public var Checkout_ShippingOption_Title: String { return self._s[2472]! } - public var ChatSettings_AutoDownloadTitle: String { return self._s[2473]! } + public var GroupInfo_AddParticipantTitle: String { return self._s[2472]! } + public var Checkout_ShippingOption_Title: String { return self._s[2473]! } + public var ChatSettings_AutoDownloadTitle: String { return self._s[2474]! } public func DialogList_SingleTypingSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2474]!, self._r[2474]!, [_0]) - } - public func ChatSettings_AutoDownloadSettings_TypeVideo(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2475]!, self._r[2475]!, [_0]) } - public var Channel_Management_LabelAdministrator: String { return self._s[2476]! } - public var EditTheme_FileReadError: String { return self._s[2477]! } - public var OwnershipTransfer_ComeBackLater: String { return self._s[2478]! } - public var PrivacyLastSeenSettings_NeverShareWith_Placeholder: String { return self._s[2479]! } - public var AutoDownloadSettings_Photos: String { return self._s[2481]! } - public var Appearance_PreviewIncomingText: String { return self._s[2482]! } - public var ChatList_Context_MarkAllAsRead: String { return self._s[2483]! } - public var ChannelInfo_ConfirmLeave: String { return self._s[2484]! } - public var MediaPicker_MomentsDateRangeSameMonthYearFormat: String { return self._s[2485]! } - public var Passport_Identity_DocumentNumberPlaceholder: String { return self._s[2486]! } - public var Channel_AdminLogFilter_EventsNewMembers: String { return self._s[2487]! } - public var PasscodeSettings_AutoLock_IfAwayFor_5minutes: String { return self._s[2488]! } - public var GroupInfo_SetGroupPhotoStop: String { return self._s[2489]! } - public var Notification_SecretChatScreenshot: String { return self._s[2490]! } - public var AccessDenied_Wallpapers: String { return self._s[2491]! } - public var ChatList_Context_Mute: String { return self._s[2493]! } - public var Passport_Address_City: String { return self._s[2494]! } - public var InfoPlist_NSPhotoLibraryAddUsageDescription: String { return self._s[2495]! } - public var Appearance_ThemeCarouselClassic: String { return self._s[2496]! } - public var SocksProxySetup_SecretPlaceholder: String { return self._s[2497]! } - public var AccessDenied_LocationDisabled: String { return self._s[2498]! } - public var Group_Location_Title: String { return self._s[2499]! } - public var SocksProxySetup_HostnamePlaceholder: String { return self._s[2501]! } - public var GroupInfo_Sound: String { return self._s[2502]! } - public var SettingsSearch_Synonyms_ChatSettings_OpenLinksIn: String { return self._s[2503]! } - public var ChannelInfo_ScamChannelWarning: String { return self._s[2504]! } - public var Stickers_RemoveFromFavorites: String { return self._s[2505]! } - public var Contacts_Title: String { return self._s[2506]! } - public var EditTheme_ThemeTemplateAlertText: String { return self._s[2507]! } - public var Passport_Language_fr: String { return self._s[2508]! } - public var TwoFactorSetup_EmailVerification_Action: String { return self._s[2509]! } - public var Notifications_ResetAllNotifications: String { return self._s[2510]! } - public var IntentsSettings_SuggestedChats: String { return self._s[2512]! } - public var PrivacySettings_SecurityTitle: String { return self._s[2514]! } - public var Checkout_NewCard_Title: String { return self._s[2515]! } - public var Login_HaveNotReceivedCodeInternal: String { return self._s[2516]! } - public var Conversation_ForwardChats: String { return self._s[2517]! } - public var Wallet_SecureStorageReset_PasscodeText: String { return self._s[2519]! } - public var PasscodeSettings_4DigitCode: String { return self._s[2520]! } - public var Settings_FAQ: String { return self._s[2522]! } - public var AutoDownloadSettings_DocumentsTitle: String { return self._s[2523]! } - public var Conversation_ContextMenuForward: String { return self._s[2524]! } - public var VoiceOver_Chat_YourPhoto: String { return self._s[2527]! } - public var PrivacyPolicy_Title: String { return self._s[2530]! } - public var Notifications_TextTone: String { return self._s[2531]! } - public var Profile_CreateNewContact: String { return self._s[2532]! } - public var PrivacyPhoneNumberSettings_WhoCanSeeMyPhoneNumber: String { return self._s[2533]! } - public var TwoFactorSetup_EmailVerification_Title: String { return self._s[2535]! } - public var Call_Speaker: String { return self._s[2536]! } - public var AutoNightTheme_AutomaticSection: String { return self._s[2537]! } - public var Channel_OwnershipTransfer_EnterPassword: String { return self._s[2539]! } - public var Channel_Username_InvalidCharacters: String { return self._s[2540]! } + public func ChatSettings_AutoDownloadSettings_TypeVideo(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2476]!, self._r[2476]!, [_0]) + } + public var Channel_Management_LabelAdministrator: String { return self._s[2477]! } + public var EditTheme_FileReadError: String { return self._s[2478]! } + public var OwnershipTransfer_ComeBackLater: String { return self._s[2479]! } + public var PrivacyLastSeenSettings_NeverShareWith_Placeholder: String { return self._s[2480]! } + public var AutoDownloadSettings_Photos: String { return self._s[2482]! } + public var Appearance_PreviewIncomingText: String { return self._s[2483]! } + public var ChatList_Context_MarkAllAsRead: String { return self._s[2484]! } + public var ChannelInfo_ConfirmLeave: String { return self._s[2485]! } + public var MediaPicker_MomentsDateRangeSameMonthYearFormat: String { return self._s[2486]! } + public var Passport_Identity_DocumentNumberPlaceholder: String { return self._s[2487]! } + public var Channel_AdminLogFilter_EventsNewMembers: String { return self._s[2488]! } + public var PasscodeSettings_AutoLock_IfAwayFor_5minutes: String { return self._s[2489]! } + public var GroupInfo_SetGroupPhotoStop: String { return self._s[2490]! } + public var Notification_SecretChatScreenshot: String { return self._s[2491]! } + public var AccessDenied_Wallpapers: String { return self._s[2492]! } + public var ChatList_Context_Mute: String { return self._s[2494]! } + public var Passport_Address_City: String { return self._s[2495]! } + public var InfoPlist_NSPhotoLibraryAddUsageDescription: String { return self._s[2496]! } + public var Appearance_ThemeCarouselClassic: String { return self._s[2497]! } + public var SocksProxySetup_SecretPlaceholder: String { return self._s[2498]! } + public var AccessDenied_LocationDisabled: String { return self._s[2499]! } + public var Group_Location_Title: String { return self._s[2500]! } + public var SocksProxySetup_HostnamePlaceholder: String { return self._s[2502]! } + public var GroupInfo_Sound: String { return self._s[2503]! } + public var SettingsSearch_Synonyms_ChatSettings_OpenLinksIn: String { return self._s[2504]! } + public var ChannelInfo_ScamChannelWarning: String { return self._s[2505]! } + public var Stickers_RemoveFromFavorites: String { return self._s[2506]! } + public var Contacts_Title: String { return self._s[2507]! } + public var EditTheme_ThemeTemplateAlertText: String { return self._s[2508]! } + public var Passport_Language_fr: String { return self._s[2509]! } + public var TwoFactorSetup_EmailVerification_Action: String { return self._s[2510]! } + public var Notifications_ResetAllNotifications: String { return self._s[2511]! } + public var IntentsSettings_SuggestedChats: String { return self._s[2513]! } + public var PrivacySettings_SecurityTitle: String { return self._s[2515]! } + public var Checkout_NewCard_Title: String { return self._s[2516]! } + public var Login_HaveNotReceivedCodeInternal: String { return self._s[2517]! } + public var Conversation_ForwardChats: String { return self._s[2518]! } + public var Wallet_SecureStorageReset_PasscodeText: String { return self._s[2520]! } + public var PasscodeSettings_4DigitCode: String { return self._s[2521]! } + public var Settings_FAQ: String { return self._s[2523]! } + public var AutoDownloadSettings_DocumentsTitle: String { return self._s[2524]! } + public var Conversation_ContextMenuForward: String { return self._s[2525]! } + public var VoiceOver_Chat_YourPhoto: String { return self._s[2528]! } + public var PrivacyPolicy_Title: String { return self._s[2531]! } + public var Notifications_TextTone: String { return self._s[2532]! } + public var Profile_CreateNewContact: String { return self._s[2533]! } + public var PrivacyPhoneNumberSettings_WhoCanSeeMyPhoneNumber: String { return self._s[2534]! } + public var TwoFactorSetup_EmailVerification_Title: String { return self._s[2536]! } + public var Call_Speaker: String { return self._s[2537]! } + public var AutoNightTheme_AutomaticSection: String { return self._s[2538]! } + public var Channel_OwnershipTransfer_EnterPassword: String { return self._s[2540]! } + public var Channel_Username_InvalidCharacters: String { return self._s[2541]! } public func Channel_AdminLog_MessageChangedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2541]!, self._r[2541]!, [_0]) + return formatWithArgumentRanges(self._s[2542]!, self._r[2542]!, [_0]) } - public var AutoDownloadSettings_AutodownloadFiles: String { return self._s[2542]! } - public var PrivacySettings_LastSeenTitle: String { return self._s[2543]! } - public var Channel_AdminLog_CanInviteUsers: String { return self._s[2544]! } - public var SettingsSearch_Synonyms_Privacy_Data_ClearPaymentsInfo: String { return self._s[2545]! } - public var OwnershipTransfer_SecurityCheck: String { return self._s[2546]! } - public var Conversation_MessageDeliveryFailed: String { return self._s[2547]! } - public var Watch_ChatList_NoConversationsText: String { return self._s[2548]! } - public var Bot_Unblock: String { return self._s[2549]! } - public var TextFormat_Italic: String { return self._s[2550]! } - public var WallpaperSearch_ColorPink: String { return self._s[2551]! } - public var Settings_About_Help: String { return self._s[2553]! } - public var SearchImages_Title: String { return self._s[2554]! } - public var Weekday_Wednesday: String { return self._s[2555]! } - public var Conversation_ClousStorageInfo_Description1: String { return self._s[2556]! } - public var ExplicitContent_AlertTitle: String { return self._s[2557]! } + public var AutoDownloadSettings_AutodownloadFiles: String { return self._s[2543]! } + public var PrivacySettings_LastSeenTitle: String { return self._s[2544]! } + public var Channel_AdminLog_CanInviteUsers: String { return self._s[2545]! } + public var SettingsSearch_Synonyms_Privacy_Data_ClearPaymentsInfo: String { return self._s[2546]! } + public var OwnershipTransfer_SecurityCheck: String { return self._s[2547]! } + public var Conversation_MessageDeliveryFailed: String { return self._s[2548]! } + public var Watch_ChatList_NoConversationsText: String { return self._s[2549]! } + public var Bot_Unblock: String { return self._s[2550]! } + public var TextFormat_Italic: String { return self._s[2551]! } + public var WallpaperSearch_ColorPink: String { return self._s[2552]! } + public var Settings_About_Help: String { return self._s[2554]! } + public var SearchImages_Title: String { return self._s[2555]! } + public var Weekday_Wednesday: String { return self._s[2556]! } + public var Conversation_ClousStorageInfo_Description1: String { return self._s[2557]! } + public var ExplicitContent_AlertTitle: String { return self._s[2558]! } public func Time_PreciseDate_m5(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2558]!, self._r[2558]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2559]!, self._r[2559]!, [_1, _2, _3]) } - public var Channel_DiscussionGroup_Create: String { return self._s[2559]! } - public var Weekday_Thursday: String { return self._s[2560]! } - public var Channel_BanUser_PermissionChangeGroupInfo: String { return self._s[2561]! } - public var Channel_Members_AddMembersHelp: String { return self._s[2562]! } + public var Channel_DiscussionGroup_Create: String { return self._s[2560]! } + public var Weekday_Thursday: String { return self._s[2561]! } + public var Channel_BanUser_PermissionChangeGroupInfo: String { return self._s[2562]! } + public var Channel_Members_AddMembersHelp: String { return self._s[2563]! } public func Checkout_SavePasswordTimeout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2563]!, self._r[2563]!, [_0]) + return formatWithArgumentRanges(self._s[2564]!, self._r[2564]!, [_0]) } - public var Channel_DiscussionGroup_LinkGroup: String { return self._s[2564]! } - public var SettingsSearch_Synonyms_Notifications_InAppNotificationsVibrate: String { return self._s[2565]! } - public var Passport_RequestedInformation: String { return self._s[2566]! } - public var Login_PhoneAndCountryHelp: String { return self._s[2567]! } - public var Conversation_EncryptionProcessing: String { return self._s[2569]! } - public var Notifications_PermissionsSuppressWarningTitle: String { return self._s[2570]! } - public var PhotoEditor_EnhanceTool: String { return self._s[2572]! } - public var Channel_Setup_Title: String { return self._s[2573]! } - public var Conversation_SearchPlaceholder: String { return self._s[2574]! } - public var OldChannels_GroupEmptyFormat: String { return self._s[2575]! } - public var AccessDenied_LocationAlwaysDenied: String { return self._s[2576]! } - public var Checkout_ErrorGeneric: String { return self._s[2577]! } - public var Passport_Language_hu: String { return self._s[2578]! } - public var GroupPermission_EditingDisabled: String { return self._s[2579]! } - public var Wallet_Month_ShortSeptember: String { return self._s[2581]! } + public var Channel_DiscussionGroup_LinkGroup: String { return self._s[2565]! } + public var SettingsSearch_Synonyms_Notifications_InAppNotificationsVibrate: String { return self._s[2566]! } + public var Passport_RequestedInformation: String { return self._s[2567]! } + public var Login_PhoneAndCountryHelp: String { return self._s[2568]! } + public var Conversation_EncryptionProcessing: String { return self._s[2570]! } + public var Notifications_PermissionsSuppressWarningTitle: String { return self._s[2571]! } + public var PhotoEditor_EnhanceTool: String { return self._s[2573]! } + public var Channel_Setup_Title: String { return self._s[2574]! } + public var Conversation_SearchPlaceholder: String { return self._s[2575]! } + public var OldChannels_GroupEmptyFormat: String { return self._s[2576]! } + public var AccessDenied_LocationAlwaysDenied: String { return self._s[2577]! } + public var Checkout_ErrorGeneric: String { return self._s[2578]! } + public var Passport_Language_hu: String { return self._s[2579]! } + public var GroupPermission_EditingDisabled: String { return self._s[2580]! } + public var Wallet_Month_ShortSeptember: String { return self._s[2582]! } public func Passport_Identity_UploadOneOfScan(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2582]!, self._r[2582]!, [_0]) + return formatWithArgumentRanges(self._s[2583]!, self._r[2583]!, [_0]) } public func PUSH_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2585]!, self._r[2585]!, [_1]) + return formatWithArgumentRanges(self._s[2586]!, self._r[2586]!, [_1]) } - public var ChatList_DeleteSavedMessagesConfirmationTitle: String { return self._s[2586]! } + public var ChatList_DeleteSavedMessagesConfirmationTitle: String { return self._s[2587]! } public func UserInfo_BlockConfirmationTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2587]!, self._r[2587]!, [_0]) + return formatWithArgumentRanges(self._s[2588]!, self._r[2588]!, [_0]) } - public var Conversation_CloudStorageInfo_Title: String { return self._s[2588]! } - public var Group_Location_Info: String { return self._s[2589]! } - public var PhotoEditor_CropAspectRatioSquare: String { return self._s[2590]! } - public var Permissions_PeopleNearbyAllow_v0: String { return self._s[2591]! } + public var Conversation_CloudStorageInfo_Title: String { return self._s[2589]! } + public var Group_Location_Info: String { return self._s[2590]! } + public var PhotoEditor_CropAspectRatioSquare: String { return self._s[2591]! } + public var Permissions_PeopleNearbyAllow_v0: String { return self._s[2592]! } public func Notification_Exceptions_MutedUntil(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2592]!, self._r[2592]!, [_0]) + return formatWithArgumentRanges(self._s[2593]!, self._r[2593]!, [_0]) } - public var Conversation_ClearPrivateHistory: String { return self._s[2593]! } - public var ContactInfo_PhoneLabelHome: String { return self._s[2594]! } - public var Appearance_RemoveThemeConfirmation: String { return self._s[2595]! } - public var PrivacySettings_LastSeenContacts: String { return self._s[2596]! } + public var Conversation_ClearPrivateHistory: String { return self._s[2594]! } + public var ContactInfo_PhoneLabelHome: String { return self._s[2595]! } + public var Appearance_RemoveThemeConfirmation: String { return self._s[2596]! } + public var PrivacySettings_LastSeenContacts: String { return self._s[2597]! } public func ChangePhone_ErrorOccupied(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2597]!, self._r[2597]!, [_0]) - } - public func Notification_PinnedQuizMessage(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2598]!, self._r[2598]!, [_0]) } - public var Passport_Language_cs: String { return self._s[2599]! } - public var Message_PinnedAnimationMessage: String { return self._s[2601]! } - public var Passport_Identity_ReverseSideHelp: String { return self._s[2603]! } - public var SettingsSearch_Synonyms_Data_Storage_Title: String { return self._s[2604]! } - public var Wallet_Info_TransactionTo: String { return self._s[2606]! } - public var ChatList_DeleteForEveryoneConfirmationText: String { return self._s[2607]! } - public var SettingsSearch_Synonyms_Privacy_PasscodeAndTouchId: String { return self._s[2608]! } - public var Embed_PlayingInPIP: String { return self._s[2609]! } - public var Appearance_ThemePreview_Chat_3_TextWithLink: String { return self._s[2610]! } - public var AutoNightTheme_ScheduleSection: String { return self._s[2611]! } + public func Notification_PinnedQuizMessage(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2599]!, self._r[2599]!, [_0]) + } + public var Passport_Language_cs: String { return self._s[2600]! } + public var Message_PinnedAnimationMessage: String { return self._s[2602]! } + public var Passport_Identity_ReverseSideHelp: String { return self._s[2604]! } + public var SettingsSearch_Synonyms_Data_Storage_Title: String { return self._s[2605]! } + public var Wallet_Info_TransactionTo: String { return self._s[2607]! } + public var ChatList_DeleteForEveryoneConfirmationText: String { return self._s[2608]! } + public var SettingsSearch_Synonyms_Privacy_PasscodeAndTouchId: String { return self._s[2609]! } + public var Embed_PlayingInPIP: String { return self._s[2610]! } + public var Appearance_ThemePreview_Chat_3_TextWithLink: String { return self._s[2611]! } + public var AutoNightTheme_ScheduleSection: String { return self._s[2612]! } public func Call_EmojiDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2612]!, self._r[2612]!, [_0]) + return formatWithArgumentRanges(self._s[2613]!, self._r[2613]!, [_0]) } - public var MediaPicker_LivePhotoDescription: String { return self._s[2613]! } + public var MediaPicker_LivePhotoDescription: String { return self._s[2614]! } public func Channel_AdminLog_MessageRestrictedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2614]!, self._r[2614]!, [_1]) + return formatWithArgumentRanges(self._s[2615]!, self._r[2615]!, [_1]) } - public var Notification_PaymentSent: String { return self._s[2615]! } - public var PhotoEditor_CurvesGreen: String { return self._s[2616]! } - public var Notification_Exceptions_PreviewAlwaysOff: String { return self._s[2617]! } - public var AutoNightTheme_System: String { return self._s[2618]! } - public var SaveIncomingPhotosSettings_Title: String { return self._s[2619]! } - public var CreatePoll_QuizTitle: String { return self._s[2620]! } - public var NotificationSettings_ShowNotificationsAllAccounts: String { return self._s[2621]! } - public var VoiceOver_Chat_PagePreview: String { return self._s[2622]! } + public var Notification_PaymentSent: String { return self._s[2616]! } + public var PhotoEditor_CurvesGreen: String { return self._s[2617]! } + public var Notification_Exceptions_PreviewAlwaysOff: String { return self._s[2618]! } + public var AutoNightTheme_System: String { return self._s[2619]! } + public var SaveIncomingPhotosSettings_Title: String { return self._s[2620]! } + public var CreatePoll_QuizTitle: String { return self._s[2621]! } + public var NotificationSettings_ShowNotificationsAllAccounts: String { return self._s[2622]! } + public var VoiceOver_Chat_PagePreview: String { return self._s[2623]! } public func PUSH_MESSAGE_SCREENSHOT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2625]!, self._r[2625]!, [_1]) - } - public func PUSH_MESSAGE_PHOTO_SECRET(_ _1: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2626]!, self._r[2626]!, [_1]) } - public func ApplyLanguage_UnsufficientDataText(_ _1: String) -> (String, [(Int, NSRange)]) { + public func PUSH_MESSAGE_PHOTO_SECRET(_ _1: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2627]!, self._r[2627]!, [_1]) } - public var NetworkUsageSettings_CallDataSection: String { return self._s[2629]! } - public var PasscodeSettings_HelpTop: String { return self._s[2630]! } - public var Conversation_WalletRequiredTitle: String { return self._s[2631]! } - public var Group_OwnershipTransfer_ErrorAdminsTooMuch: String { return self._s[2632]! } - public var Passport_Address_TypeRentalAgreement: String { return self._s[2633]! } - public var EditTheme_ShortLink: String { return self._s[2634]! } - public var Theme_Colors_ColorWallpaperWarning: String { return self._s[2635]! } - public var ProxyServer_VoiceOver_Active: String { return self._s[2636]! } - public var ReportPeer_ReasonOther_Placeholder: String { return self._s[2637]! } - public var CheckoutInfo_ErrorPhoneInvalid: String { return self._s[2638]! } - public var Call_Accept: String { return self._s[2640]! } - public var GroupRemoved_RemoveInfo: String { return self._s[2641]! } - public var Month_GenMarch: String { return self._s[2643]! } - public var PhotoEditor_ShadowsTool: String { return self._s[2644]! } - public var LoginPassword_Title: String { return self._s[2645]! } - public var Call_End: String { return self._s[2646]! } - public var Watch_Conversation_GroupInfo: String { return self._s[2647]! } - public var VoiceOver_Chat_Contact: String { return self._s[2648]! } - public var EditTheme_Create_Preview_IncomingText: String { return self._s[2649]! } - public var CallSettings_Always: String { return self._s[2650]! } - public var CallFeedback_Success: String { return self._s[2651]! } - public var TwoStepAuth_SetupHint: String { return self._s[2652]! } + public func ApplyLanguage_UnsufficientDataText(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2628]!, self._r[2628]!, [_1]) + } + public var NetworkUsageSettings_CallDataSection: String { return self._s[2630]! } + public var PasscodeSettings_HelpTop: String { return self._s[2631]! } + public var Conversation_WalletRequiredTitle: String { return self._s[2632]! } + public var Group_OwnershipTransfer_ErrorAdminsTooMuch: String { return self._s[2633]! } + public var Passport_Address_TypeRentalAgreement: String { return self._s[2634]! } + public var EditTheme_ShortLink: String { return self._s[2635]! } + public var Theme_Colors_ColorWallpaperWarning: String { return self._s[2636]! } + public var ProxyServer_VoiceOver_Active: String { return self._s[2637]! } + public var ReportPeer_ReasonOther_Placeholder: String { return self._s[2638]! } + public var CheckoutInfo_ErrorPhoneInvalid: String { return self._s[2639]! } + public var Call_Accept: String { return self._s[2641]! } + public var GroupRemoved_RemoveInfo: String { return self._s[2642]! } + public var Month_GenMarch: String { return self._s[2644]! } + public var PhotoEditor_ShadowsTool: String { return self._s[2645]! } + public var LoginPassword_Title: String { return self._s[2646]! } + public var Call_End: String { return self._s[2647]! } + public var Watch_Conversation_GroupInfo: String { return self._s[2648]! } + public var VoiceOver_Chat_Contact: String { return self._s[2649]! } + public var EditTheme_Create_Preview_IncomingText: String { return self._s[2650]! } + public var CallSettings_Always: String { return self._s[2651]! } + public var CallFeedback_Success: String { return self._s[2652]! } + public var TwoStepAuth_SetupHint: String { return self._s[2653]! } public func AddContact_ContactWillBeSharedAfterMutual(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2653]!, self._r[2653]!, [_1]) + return formatWithArgumentRanges(self._s[2654]!, self._r[2654]!, [_1]) } - public var ConversationProfile_UsersTooMuchError: String { return self._s[2654]! } - public var Login_PhoneTitle: String { return self._s[2655]! } - public var Passport_FieldPhoneHelp: String { return self._s[2656]! } - public var Weekday_ShortSunday: String { return self._s[2657]! } - public var Passport_InfoFAQ_URL: String { return self._s[2658]! } - public var ContactInfo_Job: String { return self._s[2660]! } - public var UserInfo_InviteBotToGroup: String { return self._s[2661]! } - public var Appearance_ThemeCarouselNightBlue: String { return self._s[2662]! } - public var CreatePoll_QuizTip: String { return self._s[2663]! } - public var TwoFactorSetup_Email_Text: String { return self._s[2664]! } - public var TwoStepAuth_PasswordRemovePassportConfirmation: String { return self._s[2665]! } - public var Invite_ChannelsTooMuch: String { return self._s[2666]! } - public var Wallet_Send_ConfirmationConfirm: String { return self._s[2667]! } - public var Wallet_TransactionInfo_OtherFeeInfo: String { return self._s[2668]! } - public var SettingsSearch_Synonyms_Notifications_InAppNotificationsPreview: String { return self._s[2669]! } - public var Wallet_Receive_AmountText: String { return self._s[2670]! } - public var Passport_DeletePersonalDetailsConfirmation: String { return self._s[2671]! } - public var CallFeedback_ReasonNoise: String { return self._s[2672]! } - public var Appearance_AppIconDefault: String { return self._s[2674]! } - public var Passport_Identity_AddInternalPassport: String { return self._s[2675]! } - public var MediaPicker_AddCaption: String { return self._s[2676]! } - public var CallSettings_TabIconDescription: String { return self._s[2677]! } + public var ConversationProfile_UsersTooMuchError: String { return self._s[2655]! } + public var Login_PhoneTitle: String { return self._s[2656]! } + public var Passport_FieldPhoneHelp: String { return self._s[2657]! } + public var Weekday_ShortSunday: String { return self._s[2658]! } + public var Passport_InfoFAQ_URL: String { return self._s[2659]! } + public var ContactInfo_Job: String { return self._s[2661]! } + public var UserInfo_InviteBotToGroup: String { return self._s[2662]! } + public var Appearance_ThemeCarouselNightBlue: String { return self._s[2663]! } + public var CreatePoll_QuizTip: String { return self._s[2664]! } + public var TwoFactorSetup_Email_Text: String { return self._s[2665]! } + public var TwoStepAuth_PasswordRemovePassportConfirmation: String { return self._s[2666]! } + public var Invite_ChannelsTooMuch: String { return self._s[2667]! } + public var Wallet_Send_ConfirmationConfirm: String { return self._s[2668]! } + public var Wallet_TransactionInfo_OtherFeeInfo: String { return self._s[2669]! } + public var SettingsSearch_Synonyms_Notifications_InAppNotificationsPreview: String { return self._s[2670]! } + public var Wallet_Receive_AmountText: String { return self._s[2671]! } + public var Passport_DeletePersonalDetailsConfirmation: String { return self._s[2672]! } + public var CallFeedback_ReasonNoise: String { return self._s[2673]! } + public var Appearance_AppIconDefault: String { return self._s[2675]! } + public var Passport_Identity_AddInternalPassport: String { return self._s[2676]! } + public var MediaPicker_AddCaption: String { return self._s[2677]! } + public var CallSettings_TabIconDescription: String { return self._s[2678]! } public func VoiceOver_Chat_Caption(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2678]!, self._r[2678]!, [_0]) + return formatWithArgumentRanges(self._s[2679]!, self._r[2679]!, [_0]) } - public var IntentsSettings_SuggestedChatsGroups: String { return self._s[2679]! } + public var IntentsSettings_SuggestedChatsGroups: String { return self._s[2680]! } public func Map_SearchNoResultsDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2680]!, self._r[2680]!, [_0]) + return formatWithArgumentRanges(self._s[2681]!, self._r[2681]!, [_0]) } - public var ChatList_UndoArchiveHiddenTitle: String { return self._s[2681]! } - public var Privacy_GroupsAndChannels_AlwaysAllow: String { return self._s[2682]! } - public var Passport_Identity_TypePersonalDetails: String { return self._s[2683]! } - public var DialogList_SearchSectionRecent: String { return self._s[2684]! } - public var PrivacyPolicy_DeclineMessage: String { return self._s[2685]! } - public var CreatePoll_Anonymous: String { return self._s[2686]! } - public var LogoutOptions_ClearCacheText: String { return self._s[2689]! } - public var LastSeen_WithinAWeek: String { return self._s[2690]! } - public var ChannelMembers_GroupAdminsTitle: String { return self._s[2691]! } - public var Conversation_CloudStorage_ChatStatus: String { return self._s[2693]! } - public var VoiceOver_Media_PlaybackRateNormal: String { return self._s[2694]! } + public var ChatList_UndoArchiveHiddenTitle: String { return self._s[2682]! } + public var Privacy_GroupsAndChannels_AlwaysAllow: String { return self._s[2683]! } + public var Passport_Identity_TypePersonalDetails: String { return self._s[2684]! } + public var DialogList_SearchSectionRecent: String { return self._s[2685]! } + public var PrivacyPolicy_DeclineMessage: String { return self._s[2686]! } + public var CreatePoll_Anonymous: String { return self._s[2687]! } + public var LogoutOptions_ClearCacheText: String { return self._s[2690]! } + public var LastSeen_WithinAWeek: String { return self._s[2691]! } + public var ChannelMembers_GroupAdminsTitle: String { return self._s[2692]! } + public var Conversation_CloudStorage_ChatStatus: String { return self._s[2694]! } + public var VoiceOver_Media_PlaybackRateNormal: String { return self._s[2695]! } public func AddContact_SharedContactExceptionInfo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2695]!, self._r[2695]!, [_0]) + return formatWithArgumentRanges(self._s[2696]!, self._r[2696]!, [_0]) } - public var Passport_Address_TypeResidentialAddress: String { return self._s[2696]! } - public var Conversation_StatusLeftGroup: String { return self._s[2697]! } - public var SocksProxySetup_ProxyDetailsTitle: String { return self._s[2698]! } - public var SettingsSearch_Synonyms_Calls_Title: String { return self._s[2700]! } - public var GroupPermission_AddSuccess: String { return self._s[2701]! } - public var PhotoEditor_BlurToolRadial: String { return self._s[2703]! } - public var Conversation_ContextMenuCopy: String { return self._s[2704]! } - public var AccessDenied_CallMicrophone: String { return self._s[2705]! } + public var Passport_Address_TypeResidentialAddress: String { return self._s[2697]! } + public var Conversation_StatusLeftGroup: String { return self._s[2698]! } + public var SocksProxySetup_ProxyDetailsTitle: String { return self._s[2699]! } + public var SettingsSearch_Synonyms_Calls_Title: String { return self._s[2701]! } + public var GroupPermission_AddSuccess: String { return self._s[2702]! } + public var PhotoEditor_BlurToolRadial: String { return self._s[2704]! } + public var Conversation_ContextMenuCopy: String { return self._s[2705]! } + public var AccessDenied_CallMicrophone: String { return self._s[2706]! } public func Time_PreciseDate_m2(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2706]!, self._r[2706]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2707]!, self._r[2707]!, [_1, _2, _3]) } - public var Login_InvalidFirstNameError: String { return self._s[2707]! } - public var Notifications_Badge_CountUnreadMessages_InfoOn: String { return self._s[2708]! } - public var Checkout_PaymentMethod_New: String { return self._s[2709]! } - public var ShareMenu_CopyShareLinkGame: String { return self._s[2710]! } - public var PhotoEditor_QualityTool: String { return self._s[2711]! } - public var Login_SendCodeViaSms: String { return self._s[2712]! } - public var SettingsSearch_Synonyms_Privacy_DeleteAccountIfAwayFor: String { return self._s[2713]! } - public var Chat_SlowmodeAttachmentLimitReached: String { return self._s[2714]! } - public var Wallet_Receive_CopyAddress: String { return self._s[2715]! } - public var Login_EmailNotConfiguredError: String { return self._s[2716]! } - public var SocksProxySetup_Status: String { return self._s[2717]! } - public var Conversation_ScheduleMessage_SendWhenOnline: String { return self._s[2718]! } - public var PrivacyPolicy_Accept: String { return self._s[2719]! } - public var Notifications_ExceptionsMessagePlaceholder: String { return self._s[2720]! } - public var Appearance_AppIconClassicX: String { return self._s[2721]! } + public var Login_InvalidFirstNameError: String { return self._s[2708]! } + public var Notifications_Badge_CountUnreadMessages_InfoOn: String { return self._s[2709]! } + public var Checkout_PaymentMethod_New: String { return self._s[2710]! } + public var ShareMenu_CopyShareLinkGame: String { return self._s[2711]! } + public var PhotoEditor_QualityTool: String { return self._s[2712]! } + public var Login_SendCodeViaSms: String { return self._s[2713]! } + public var SettingsSearch_Synonyms_Privacy_DeleteAccountIfAwayFor: String { return self._s[2714]! } + public var Chat_SlowmodeAttachmentLimitReached: String { return self._s[2715]! } + public var Wallet_Receive_CopyAddress: String { return self._s[2716]! } + public var Login_EmailNotConfiguredError: String { return self._s[2717]! } + public var SocksProxySetup_Status: String { return self._s[2718]! } + public var Conversation_ScheduleMessage_SendWhenOnline: String { return self._s[2719]! } + public var PrivacyPolicy_Accept: String { return self._s[2720]! } + public var Notifications_ExceptionsMessagePlaceholder: String { return self._s[2721]! } + public var Appearance_AppIconClassicX: String { return self._s[2722]! } public func PUSH_CHAT_MESSAGE_TEXT(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2722]!, self._r[2722]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2723]!, self._r[2723]!, [_1, _2, _3]) } - public var OwnershipTransfer_SecurityRequirements: String { return self._s[2723]! } - public var InfoPlist_NSLocationAlwaysUsageDescription: String { return self._s[2725]! } - public var AutoNightTheme_Automatic: String { return self._s[2726]! } - public var Channel_Username_InvalidStartsWithNumber: String { return self._s[2727]! } - public var Privacy_ContactsSyncHelp: String { return self._s[2728]! } - public var Cache_Help: String { return self._s[2729]! } - public var Group_ErrorAccessDenied: String { return self._s[2730]! } - public var Passport_Language_fa: String { return self._s[2731]! } - public var Wallet_Intro_Text: String { return self._s[2732]! } - public var Login_ResetAccountProtected_TimerTitle: String { return self._s[2733]! } - public var VoiceOver_Chat_YourVideoMessage: String { return self._s[2734]! } - public var PrivacySettings_LastSeen: String { return self._s[2735]! } + public var OwnershipTransfer_SecurityRequirements: String { return self._s[2724]! } + public var InfoPlist_NSLocationAlwaysUsageDescription: String { return self._s[2726]! } + public var AutoNightTheme_Automatic: String { return self._s[2727]! } + public var Channel_Username_InvalidStartsWithNumber: String { return self._s[2728]! } + public var Privacy_ContactsSyncHelp: String { return self._s[2729]! } + public var Cache_Help: String { return self._s[2730]! } + public var Group_ErrorAccessDenied: String { return self._s[2731]! } + public var Passport_Language_fa: String { return self._s[2732]! } + public var Wallet_Intro_Text: String { return self._s[2733]! } + public var Login_ResetAccountProtected_TimerTitle: String { return self._s[2734]! } + public var VoiceOver_Chat_YourVideoMessage: String { return self._s[2735]! } + public var PrivacySettings_LastSeen: String { return self._s[2736]! } public func DialogList_MultipleTyping(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2736]!, self._r[2736]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2737]!, self._r[2737]!, [_0, _1]) } - public var Wallet_Configuration_Apply: String { return self._s[2740]! } - public var Preview_SaveGif: String { return self._s[2741]! } - public var SettingsSearch_Synonyms_Privacy_TwoStepAuth: String { return self._s[2742]! } - public var Profile_About: String { return self._s[2743]! } - public var Channel_About_Placeholder: String { return self._s[2744]! } - public var Login_InfoTitle: String { return self._s[2745]! } + public var Wallet_Configuration_Apply: String { return self._s[2741]! } + public var Preview_SaveGif: String { return self._s[2742]! } + public var SettingsSearch_Synonyms_Privacy_TwoStepAuth: String { return self._s[2743]! } + public var Profile_About: String { return self._s[2744]! } + public var Channel_About_Placeholder: String { return self._s[2745]! } + public var Login_InfoTitle: String { return self._s[2746]! } public func TwoStepAuth_SetupPendingEmail(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2746]!, self._r[2746]!, [_0]) + return formatWithArgumentRanges(self._s[2747]!, self._r[2747]!, [_0]) } - public var EditTheme_Expand_Preview_IncomingReplyText: String { return self._s[2747]! } - public var Watch_Suggestion_CantTalk: String { return self._s[2749]! } - public var ContactInfo_Title: String { return self._s[2750]! } - public var Media_ShareThisVideo: String { return self._s[2751]! } - public var Weekday_ShortFriday: String { return self._s[2752]! } - public var AccessDenied_Contacts: String { return self._s[2754]! } - public var Notification_CallIncomingShort: String { return self._s[2755]! } - public var Group_Setup_TypePublic: String { return self._s[2756]! } - public var Notifications_MessageNotificationsExceptions: String { return self._s[2757]! } - public var Notifications_Badge_IncludeChannels: String { return self._s[2758]! } - public var Notifications_MessageNotificationsPreview: String { return self._s[2761]! } - public var ConversationProfile_ErrorCreatingConversation: String { return self._s[2762]! } - public var Group_ErrorAddTooMuchBots: String { return self._s[2763]! } - public var Privacy_GroupsAndChannels_CustomShareHelp: String { return self._s[2764]! } - public var Permissions_CellularDataAllowInSettings_v0: String { return self._s[2765]! } + public var EditTheme_Expand_Preview_IncomingReplyText: String { return self._s[2748]! } + public var Watch_Suggestion_CantTalk: String { return self._s[2750]! } + public var ContactInfo_Title: String { return self._s[2751]! } + public var Media_ShareThisVideo: String { return self._s[2752]! } + public var Weekday_ShortFriday: String { return self._s[2753]! } + public var AccessDenied_Contacts: String { return self._s[2755]! } + public var Notification_CallIncomingShort: String { return self._s[2756]! } + public var Group_Setup_TypePublic: String { return self._s[2757]! } + public var Notifications_MessageNotificationsExceptions: String { return self._s[2758]! } + public var Notifications_Badge_IncludeChannels: String { return self._s[2759]! } + public var Notifications_MessageNotificationsPreview: String { return self._s[2762]! } + public var ConversationProfile_ErrorCreatingConversation: String { return self._s[2763]! } + public var Group_ErrorAddTooMuchBots: String { return self._s[2764]! } + public var Privacy_GroupsAndChannels_CustomShareHelp: String { return self._s[2765]! } + public var Permissions_CellularDataAllowInSettings_v0: String { return self._s[2766]! } public func Wallet_SecureStorageChanged_BiometryText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2766]!, self._r[2766]!, [_0]) + return formatWithArgumentRanges(self._s[2767]!, self._r[2767]!, [_0]) } - public var DialogList_Typing: String { return self._s[2767]! } - public var CallFeedback_IncludeLogs: String { return self._s[2769]! } - public var Checkout_Phone: String { return self._s[2771]! } - public var Login_InfoFirstNamePlaceholder: String { return self._s[2774]! } - public var Privacy_Calls_Integration: String { return self._s[2775]! } - public var Notifications_PermissionsAllow: String { return self._s[2776]! } - public var TwoStepAuth_AddHintDescription: String { return self._s[2780]! } - public var Settings_ChatSettings: String { return self._s[2781]! } - public var Conversation_SendingOptionsTooltip: String { return self._s[2782]! } + public var DialogList_Typing: String { return self._s[2768]! } + public var CallFeedback_IncludeLogs: String { return self._s[2770]! } + public var Checkout_Phone: String { return self._s[2772]! } + public var Login_InfoFirstNamePlaceholder: String { return self._s[2775]! } + public var Privacy_Calls_Integration: String { return self._s[2776]! } + public var Notifications_PermissionsAllow: String { return self._s[2777]! } + public var TwoStepAuth_AddHintDescription: String { return self._s[2781]! } + public var Settings_ChatSettings: String { return self._s[2782]! } + public var Conversation_SendingOptionsTooltip: String { return self._s[2783]! } public func UserInfo_StartSecretChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2784]!, self._r[2784]!, [_0]) + return formatWithArgumentRanges(self._s[2785]!, self._r[2785]!, [_0]) } public func Channel_AdminLog_MessageInvitedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2785]!, self._r[2785]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2786]!, self._r[2786]!, [_1, _2]) } - public var GroupRemoved_DeleteUser: String { return self._s[2787]! } + public var GroupRemoved_DeleteUser: String { return self._s[2788]! } public func Channel_AdminLog_PollStopped(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2788]!, self._r[2788]!, [_0]) + return formatWithArgumentRanges(self._s[2789]!, self._r[2789]!, [_0]) } public func PUSH_MESSAGE_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2789]!, self._r[2789]!, [_1]) + return formatWithArgumentRanges(self._s[2790]!, self._r[2790]!, [_1]) } - public var Login_ContinueWithLocalization: String { return self._s[2790]! } - public var Watch_Message_ForwardedFrom: String { return self._s[2791]! } - public var TwoStepAuth_EnterEmailCode: String { return self._s[2793]! } - public var Conversation_Unblock: String { return self._s[2794]! } - public var PrivacySettings_DataSettings: String { return self._s[2795]! } - public var WallpaperPreview_PatternPaternApply: String { return self._s[2796]! } - public var Group_PublicLink_Info: String { return self._s[2797]! } + public var Login_ContinueWithLocalization: String { return self._s[2791]! } + public var Watch_Message_ForwardedFrom: String { return self._s[2792]! } + public var TwoStepAuth_EnterEmailCode: String { return self._s[2794]! } + public var Conversation_Unblock: String { return self._s[2795]! } + public var PrivacySettings_DataSettings: String { return self._s[2796]! } + public var WallpaperPreview_PatternPaternApply: String { return self._s[2797]! } + public var Group_PublicLink_Info: String { return self._s[2798]! } public func Wallet_Time_PreciseDate_m1(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2798]!, self._r[2798]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2799]!, self._r[2799]!, [_1, _2, _3]) } - public var Notifications_InAppNotificationsVibrate: String { return self._s[2799]! } + public var Notifications_InAppNotificationsVibrate: String { return self._s[2800]! } public func Privacy_GroupsAndChannels_InviteToChannelError(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2800]!, self._r[2800]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2801]!, self._r[2801]!, [_0, _1]) } - public var OldChannels_ChannelsHeader: String { return self._s[2802]! } - public var Wallet_RestoreFailed_CreateWallet: String { return self._s[2803]! } - public var PrivacySettings_Passcode: String { return self._s[2805]! } - public var Call_Mute: String { return self._s[2806]! } - public var Wallet_Weekday_Yesterday: String { return self._s[2807]! } - public var Passport_Language_dz: String { return self._s[2808]! } - public var Wallet_Receive_AmountHeader: String { return self._s[2809]! } - public var Wallet_TransactionInfo_OtherFeeInfoUrl: String { return self._s[2810]! } - public var Passport_Language_tk: String { return self._s[2811]! } + public var OldChannels_ChannelsHeader: String { return self._s[2803]! } + public var Wallet_RestoreFailed_CreateWallet: String { return self._s[2804]! } + public var PrivacySettings_Passcode: String { return self._s[2806]! } + public var Call_Mute: String { return self._s[2807]! } + public var Wallet_Weekday_Yesterday: String { return self._s[2808]! } + public var Passport_Language_dz: String { return self._s[2809]! } + public var Wallet_Receive_AmountHeader: String { return self._s[2810]! } + public var Wallet_TransactionInfo_OtherFeeInfoUrl: String { return self._s[2811]! } + public var Passport_Language_tk: String { return self._s[2812]! } public func Login_EmailCodeSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2812]!, self._r[2812]!, [_0]) + return formatWithArgumentRanges(self._s[2813]!, self._r[2813]!, [_0]) } - public var Settings_Search: String { return self._s[2813]! } - public var Wallet_Month_ShortFebruary: String { return self._s[2814]! } - public var InfoPlist_NSPhotoLibraryUsageDescription: String { return self._s[2815]! } - public var Wallet_Configuration_SourceJSON: String { return self._s[2816]! } - public var Conversation_ContextMenuReply: String { return self._s[2817]! } - public var WallpaperSearch_ColorBrown: String { return self._s[2818]! } - public var Chat_AttachmentMultipleForwardDisabled: String { return self._s[2819]! } - public var Tour_Title1: String { return self._s[2820]! } - public var Wallet_Alert_Cancel: String { return self._s[2821]! } - public var Conversation_ClearGroupHistory: String { return self._s[2823]! } - public var Wallet_TransactionInfo_RecipientHeader: String { return self._s[2824]! } - public var WallpaperPreview_Motion: String { return self._s[2825]! } + public var Settings_Search: String { return self._s[2814]! } + public var Wallet_Month_ShortFebruary: String { return self._s[2815]! } + public var InfoPlist_NSPhotoLibraryUsageDescription: String { return self._s[2816]! } + public var Wallet_Configuration_SourceJSON: String { return self._s[2817]! } + public var Conversation_ContextMenuReply: String { return self._s[2818]! } + public var WallpaperSearch_ColorBrown: String { return self._s[2819]! } + public var Chat_AttachmentMultipleForwardDisabled: String { return self._s[2820]! } + public var Tour_Title1: String { return self._s[2821]! } + public var Wallet_Alert_Cancel: String { return self._s[2822]! } + public var Conversation_ClearGroupHistory: String { return self._s[2824]! } + public var Wallet_TransactionInfo_RecipientHeader: String { return self._s[2825]! } + public var WallpaperPreview_Motion: String { return self._s[2826]! } public func Checkout_PasswordEntry_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2826]!, self._r[2826]!, [_0]) + return formatWithArgumentRanges(self._s[2827]!, self._r[2827]!, [_0]) } - public var Wallet_Configuration_ApplyErrorTextJSONInvalidData: String { return self._s[2827]! } - public var Call_RateCall: String { return self._s[2828]! } - public var Channel_AdminLog_BanSendStickersAndGifs: String { return self._s[2829]! } - public var Passport_PasswordCompleteSetup: String { return self._s[2830]! } - public var Conversation_InputTextSilentBroadcastPlaceholder: String { return self._s[2831]! } - public var UserInfo_LastNamePlaceholder: String { return self._s[2833]! } + public var Wallet_Configuration_ApplyErrorTextJSONInvalidData: String { return self._s[2828]! } + public var Call_RateCall: String { return self._s[2829]! } + public var Channel_AdminLog_BanSendStickersAndGifs: String { return self._s[2830]! } + public var Passport_PasswordCompleteSetup: String { return self._s[2831]! } + public var Conversation_InputTextSilentBroadcastPlaceholder: String { return self._s[2832]! } + public var UserInfo_LastNamePlaceholder: String { return self._s[2834]! } public func Login_WillCallYou(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2835]!, self._r[2835]!, [_0]) + return formatWithArgumentRanges(self._s[2836]!, self._r[2836]!, [_0]) } - public var Compose_Create: String { return self._s[2836]! } - public var Contacts_InviteToTelegram: String { return self._s[2837]! } - public var GroupInfo_Notifications: String { return self._s[2838]! } - public var ChatList_DeleteSavedMessagesConfirmationAction: String { return self._s[2840]! } - public var Message_PinnedLiveLocationMessage: String { return self._s[2841]! } - public var Month_GenApril: String { return self._s[2842]! } - public var Appearance_AutoNightTheme: String { return self._s[2843]! } - public var ChatSettings_AutomaticAudioDownload: String { return self._s[2845]! } - public var Login_CodeSentSms: String { return self._s[2847]! } + public var Compose_Create: String { return self._s[2837]! } + public var Contacts_InviteToTelegram: String { return self._s[2838]! } + public var GroupInfo_Notifications: String { return self._s[2839]! } + public var ChatList_DeleteSavedMessagesConfirmationAction: String { return self._s[2841]! } + public var Message_PinnedLiveLocationMessage: String { return self._s[2842]! } + public var Month_GenApril: String { return self._s[2843]! } + public var Appearance_AutoNightTheme: String { return self._s[2844]! } + public var ChatSettings_AutomaticAudioDownload: String { return self._s[2846]! } + public var Login_CodeSentSms: String { return self._s[2848]! } public func UserInfo_UnblockConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2848]!, self._r[2848]!, [_0]) + return formatWithArgumentRanges(self._s[2849]!, self._r[2849]!, [_0]) } - public var EmptyGroupInfo_Line3: String { return self._s[2849]! } - public var LogoutOptions_ContactSupportText: String { return self._s[2850]! } - public var Passport_Language_hr: String { return self._s[2851]! } - public var Common_ActionNotAllowedError: String { return self._s[2852]! } + public var EmptyGroupInfo_Line3: String { return self._s[2850]! } + public var LogoutOptions_ContactSupportText: String { return self._s[2851]! } + public var Passport_Language_hr: String { return self._s[2852]! } + public var Common_ActionNotAllowedError: String { return self._s[2853]! } public func Channel_AdminLog_MessageRestrictedNewSetting(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2853]!, self._r[2853]!, [_0]) + return formatWithArgumentRanges(self._s[2854]!, self._r[2854]!, [_0]) } - public var GroupInfo_InviteLink_CopyLink: String { return self._s[2854]! } - public var Wallet_Info_TransactionFrom: String { return self._s[2855]! } - public var Wallet_Send_ErrorDecryptionFailed: String { return self._s[2856]! } - public var Conversation_InputTextBroadcastPlaceholder: String { return self._s[2857]! } - public var Privacy_SecretChatsTitle: String { return self._s[2858]! } - public var Notification_SecretChatMessageScreenshotSelf: String { return self._s[2860]! } - public var GroupInfo_AddUserLeftError: String { return self._s[2861]! } - public var AutoDownloadSettings_TypePrivateChats: String { return self._s[2862]! } - public var LogoutOptions_ContactSupportTitle: String { return self._s[2863]! } - public var Appearance_ThemePreview_Chat_7_Text: String { return self._s[2864]! } - public var Channel_AddBotErrorHaveRights: String { return self._s[2865]! } - public var Preview_DeleteGif: String { return self._s[2866]! } - public var GroupInfo_Permissions_Exceptions: String { return self._s[2867]! } - public var Group_ErrorNotMutualContact: String { return self._s[2868]! } - public var Notification_MessageLifetime5s: String { return self._s[2869]! } - public var Wallet_Send_OwnAddressAlertText: String { return self._s[2870]! } - public var OldChannels_ChannelFormat: String { return self._s[2871]! } + public var GroupInfo_InviteLink_CopyLink: String { return self._s[2855]! } + public var Wallet_Info_TransactionFrom: String { return self._s[2856]! } + public var Wallet_Send_ErrorDecryptionFailed: String { return self._s[2857]! } + public var Conversation_InputTextBroadcastPlaceholder: String { return self._s[2858]! } + public var Privacy_SecretChatsTitle: String { return self._s[2859]! } + public var Notification_SecretChatMessageScreenshotSelf: String { return self._s[2861]! } + public var GroupInfo_AddUserLeftError: String { return self._s[2862]! } + public var AutoDownloadSettings_TypePrivateChats: String { return self._s[2863]! } + public var LogoutOptions_ContactSupportTitle: String { return self._s[2864]! } + public var Appearance_ThemePreview_Chat_7_Text: String { return self._s[2865]! } + public var Channel_AddBotErrorHaveRights: String { return self._s[2866]! } + public var Preview_DeleteGif: String { return self._s[2867]! } + public var GroupInfo_Permissions_Exceptions: String { return self._s[2868]! } + public var Group_ErrorNotMutualContact: String { return self._s[2869]! } + public var Notification_MessageLifetime5s: String { return self._s[2870]! } + public var Wallet_Send_OwnAddressAlertText: String { return self._s[2871]! } + public var OldChannels_ChannelFormat: String { return self._s[2872]! } public func Watch_LastSeen_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2872]!, self._r[2872]!, [_0]) + return formatWithArgumentRanges(self._s[2873]!, self._r[2873]!, [_0]) } - public var VoiceOver_Chat_Video: String { return self._s[2873]! } - public var Channel_OwnershipTransfer_ErrorPublicChannelsTooMuch: String { return self._s[2875]! } - public var ReportSpam_DeleteThisChat: String { return self._s[2876]! } - public var Passport_Address_AddBankStatement: String { return self._s[2877]! } - public var Notification_CallIncoming: String { return self._s[2878]! } - public var Wallet_Words_NotDoneTitle: String { return self._s[2879]! } - public var Compose_NewGroupTitle: String { return self._s[2880]! } - public var TwoStepAuth_RecoveryCodeHelp: String { return self._s[2882]! } - public var Passport_Address_Postcode: String { return self._s[2884]! } + public var VoiceOver_Chat_Video: String { return self._s[2874]! } + public var Channel_OwnershipTransfer_ErrorPublicChannelsTooMuch: String { return self._s[2876]! } + public var ReportSpam_DeleteThisChat: String { return self._s[2877]! } + public var Passport_Address_AddBankStatement: String { return self._s[2878]! } + public var Notification_CallIncoming: String { return self._s[2879]! } + public var Wallet_Words_NotDoneTitle: String { return self._s[2880]! } + public var Compose_NewGroupTitle: String { return self._s[2881]! } + public var TwoStepAuth_RecoveryCodeHelp: String { return self._s[2883]! } + public var Passport_Address_Postcode: String { return self._s[2885]! } public func LastSeen_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2885]!, self._r[2885]!, [_0]) + return formatWithArgumentRanges(self._s[2886]!, self._r[2886]!, [_0]) } - public var Checkout_NewCard_SaveInfoHelp: String { return self._s[2886]! } - public var Wallet_Month_ShortOctober: String { return self._s[2887]! } - public var VoiceOver_Chat_YourMusic: String { return self._s[2888]! } - public var WallpaperColors_Title: String { return self._s[2889]! } - public var SocksProxySetup_ShareQRCodeInfo: String { return self._s[2890]! } - public var VoiceOver_MessageContextForward: String { return self._s[2891]! } - public var GroupPermission_Duration: String { return self._s[2892]! } + public var Checkout_NewCard_SaveInfoHelp: String { return self._s[2887]! } + public var Wallet_Month_ShortOctober: String { return self._s[2888]! } + public var VoiceOver_Chat_YourMusic: String { return self._s[2889]! } + public var WallpaperColors_Title: String { return self._s[2890]! } + public var SocksProxySetup_ShareQRCodeInfo: String { return self._s[2891]! } + public var VoiceOver_MessageContextForward: String { return self._s[2892]! } + public var GroupPermission_Duration: String { return self._s[2893]! } public func Cache_Clear(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2893]!, self._r[2893]!, [_0]) + return formatWithArgumentRanges(self._s[2894]!, self._r[2894]!, [_0]) } - public var Bot_GroupStatusDoesNotReadHistory: String { return self._s[2894]! } - public var Username_Placeholder: String { return self._s[2895]! } - public var CallFeedback_WhatWentWrong: String { return self._s[2896]! } - public var Passport_FieldAddressUploadHelp: String { return self._s[2897]! } - public var Permissions_NotificationsAllowInSettings_v0: String { return self._s[2898]! } + public var Bot_GroupStatusDoesNotReadHistory: String { return self._s[2895]! } + public var Username_Placeholder: String { return self._s[2896]! } + public var CallFeedback_WhatWentWrong: String { return self._s[2897]! } + public var Passport_FieldAddressUploadHelp: String { return self._s[2898]! } + public var Permissions_NotificationsAllowInSettings_v0: String { return self._s[2899]! } public func Channel_AdminLog_MessageChangedUnlinkedChannel(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2900]!, self._r[2900]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2901]!, self._r[2901]!, [_1, _2]) } - public var Passport_PasswordDescription: String { return self._s[2901]! } - public var Channel_MessagePhotoUpdated: String { return self._s[2902]! } - public var MediaPicker_TapToUngroupDescription: String { return self._s[2903]! } - public var SettingsSearch_Synonyms_Notifications_BadgeCountUnreadMessages: String { return self._s[2904]! } - public var AttachmentMenu_PhotoOrVideo: String { return self._s[2905]! } - public var Conversation_ContextMenuMore: String { return self._s[2906]! } - public var Privacy_PaymentsClearInfo: String { return self._s[2907]! } - public var CallSettings_TabIcon: String { return self._s[2908]! } - public var KeyCommand_Find: String { return self._s[2909]! } - public var ClearCache_FreeSpaceDescription: String { return self._s[2910]! } - public var Appearance_ThemePreview_ChatList_7_Text: String { return self._s[2911]! } - public var EditTheme_Edit_Preview_IncomingText: String { return self._s[2912]! } - public var Message_PinnedGame: String { return self._s[2913]! } - public var VoiceOver_Chat_ForwardedFromYou: String { return self._s[2914]! } - public var Notifications_Badge_CountUnreadMessages_InfoOff: String { return self._s[2916]! } - public var Login_CallRequestState2: String { return self._s[2918]! } - public var CheckoutInfo_ReceiverInfoNamePlaceholder: String { return self._s[2920]! } + public var Passport_PasswordDescription: String { return self._s[2902]! } + public var Channel_MessagePhotoUpdated: String { return self._s[2903]! } + public var MediaPicker_TapToUngroupDescription: String { return self._s[2904]! } + public var SettingsSearch_Synonyms_Notifications_BadgeCountUnreadMessages: String { return self._s[2905]! } + public var AttachmentMenu_PhotoOrVideo: String { return self._s[2906]! } + public var Conversation_ContextMenuMore: String { return self._s[2907]! } + public var Privacy_PaymentsClearInfo: String { return self._s[2908]! } + public var CallSettings_TabIcon: String { return self._s[2909]! } + public var KeyCommand_Find: String { return self._s[2910]! } + public var ClearCache_FreeSpaceDescription: String { return self._s[2911]! } + public var Appearance_ThemePreview_ChatList_7_Text: String { return self._s[2912]! } + public var EditTheme_Edit_Preview_IncomingText: String { return self._s[2913]! } + public var Message_PinnedGame: String { return self._s[2914]! } + public var VoiceOver_Chat_ForwardedFromYou: String { return self._s[2915]! } + public var Notifications_Badge_CountUnreadMessages_InfoOff: String { return self._s[2917]! } + public var Login_CallRequestState2: String { return self._s[2919]! } + public var CheckoutInfo_ReceiverInfoNamePlaceholder: String { return self._s[2921]! } public func VoiceOver_Chat_PhotoFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2921]!, self._r[2921]!, [_0]) + return formatWithArgumentRanges(self._s[2922]!, self._r[2922]!, [_0]) } public func Checkout_PayPrice(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2923]!, self._r[2923]!, [_0]) + return formatWithArgumentRanges(self._s[2924]!, self._r[2924]!, [_0]) } - public var AuthSessions_AddDevice: String { return self._s[2924]! } - public var WallpaperPreview_Blurred: String { return self._s[2925]! } - public var Conversation_InstantPagePreview: String { return self._s[2926]! } + public var AuthSessions_AddDevice: String { return self._s[2925]! } + public var WallpaperPreview_Blurred: String { return self._s[2926]! } + public var Conversation_InstantPagePreview: String { return self._s[2927]! } public func DialogList_SingleUploadingVideoSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2927]!, self._r[2927]!, [_0]) + return formatWithArgumentRanges(self._s[2928]!, self._r[2928]!, [_0]) } - public var SecretTimer_VideoDescription: String { return self._s[2930]! } - public var WallpaperSearch_ColorRed: String { return self._s[2931]! } - public var GroupPermission_NoPinMessages: String { return self._s[2932]! } - public var Passport_Language_es: String { return self._s[2933]! } - public var Permissions_ContactsAllow_v0: String { return self._s[2935]! } - public var Conversation_EditingMessageMediaEditCurrentVideo: String { return self._s[2936]! } + public var SecretTimer_VideoDescription: String { return self._s[2931]! } + public var WallpaperSearch_ColorRed: String { return self._s[2932]! } + public var GroupPermission_NoPinMessages: String { return self._s[2933]! } + public var Passport_Language_es: String { return self._s[2934]! } + public var Permissions_ContactsAllow_v0: String { return self._s[2936]! } + public var Conversation_EditingMessageMediaEditCurrentVideo: String { return self._s[2937]! } public func PUSH_CHAT_MESSAGE_CONTACT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2937]!, self._r[2937]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2938]!, self._r[2938]!, [_1, _2]) } - public var Privacy_Forwards_CustomHelp: String { return self._s[2938]! } - public var WebPreview_GettingLinkInfo: String { return self._s[2939]! } - public var Watch_UserInfo_Unmute: String { return self._s[2940]! } - public var GroupInfo_ChannelListNamePlaceholder: String { return self._s[2941]! } - public var AccessDenied_CameraRestricted: String { return self._s[2943]! } + public var Privacy_Forwards_CustomHelp: String { return self._s[2939]! } + public var WebPreview_GettingLinkInfo: String { return self._s[2940]! } + public var Watch_UserInfo_Unmute: String { return self._s[2941]! } + public var GroupInfo_ChannelListNamePlaceholder: String { return self._s[2942]! } + public var AccessDenied_CameraRestricted: String { return self._s[2944]! } public func Conversation_Kilobytes(_ _0: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2944]!, self._r[2944]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[2945]!, self._r[2945]!, ["\(_0)"]) } - public var ChatList_ReadAll: String { return self._s[2946]! } - public var Settings_CopyUsername: String { return self._s[2947]! } - public var Contacts_SearchLabel: String { return self._s[2948]! } - public var Map_OpenInYandexNavigator: String { return self._s[2950]! } - public var PasscodeSettings_EncryptData: String { return self._s[2951]! } - public var Settings_Wallet: String { return self._s[2952]! } - public var Group_ErrorSupergroupConversionNotPossible: String { return self._s[2953]! } - public var WallpaperSearch_ColorPrefix: String { return self._s[2954]! } - public var Notifications_GroupNotificationsPreview: String { return self._s[2955]! } - public var DialogList_AdNoticeAlert: String { return self._s[2956]! } - public var Wallet_Month_GenMay: String { return self._s[2958]! } - public var CheckoutInfo_ShippingInfoAddress1: String { return self._s[2959]! } - public var CheckoutInfo_ShippingInfoAddress2: String { return self._s[2960]! } - public var Localization_LanguageCustom: String { return self._s[2961]! } - public var Passport_Identity_TypeDriversLicenseUploadScan: String { return self._s[2962]! } - public var CallFeedback_Title: String { return self._s[2963]! } - public var VoiceOver_Chat_RecordPreviewVoiceMessage: String { return self._s[2966]! } - public var Passport_Address_OneOfTypePassportRegistration: String { return self._s[2967]! } - public var Wallet_Intro_CreateErrorTitle: String { return self._s[2968]! } - public var Conversation_InfoGroup: String { return self._s[2969]! } - public var Compose_NewMessage: String { return self._s[2970]! } - public var FastTwoStepSetup_HintPlaceholder: String { return self._s[2971]! } - public var ChatSettings_AutoDownloadVideoMessages: String { return self._s[2972]! } - public var Wallet_SecureStorageReset_BiometryFaceId: String { return self._s[2973]! } - public var Channel_DiscussionGroup_UnlinkChannel: String { return self._s[2974]! } + public var ChatList_ReadAll: String { return self._s[2947]! } + public var Settings_CopyUsername: String { return self._s[2948]! } + public var Contacts_SearchLabel: String { return self._s[2949]! } + public var Map_OpenInYandexNavigator: String { return self._s[2951]! } + public var PasscodeSettings_EncryptData: String { return self._s[2952]! } + public var Settings_Wallet: String { return self._s[2953]! } + public var Group_ErrorSupergroupConversionNotPossible: String { return self._s[2954]! } + public var WallpaperSearch_ColorPrefix: String { return self._s[2955]! } + public var Notifications_GroupNotificationsPreview: String { return self._s[2956]! } + public var DialogList_AdNoticeAlert: String { return self._s[2957]! } + public var Wallet_Month_GenMay: String { return self._s[2959]! } + public var CheckoutInfo_ShippingInfoAddress1: String { return self._s[2960]! } + public var CheckoutInfo_ShippingInfoAddress2: String { return self._s[2961]! } + public var Localization_LanguageCustom: String { return self._s[2962]! } + public var Passport_Identity_TypeDriversLicenseUploadScan: String { return self._s[2963]! } + public var CallFeedback_Title: String { return self._s[2964]! } + public var VoiceOver_Chat_RecordPreviewVoiceMessage: String { return self._s[2967]! } + public var Passport_Address_OneOfTypePassportRegistration: String { return self._s[2968]! } + public var Wallet_Intro_CreateErrorTitle: String { return self._s[2969]! } + public var Conversation_InfoGroup: String { return self._s[2970]! } + public var Compose_NewMessage: String { return self._s[2971]! } + public var FastTwoStepSetup_HintPlaceholder: String { return self._s[2972]! } + public var ChatSettings_AutoDownloadVideoMessages: String { return self._s[2973]! } + public var Wallet_SecureStorageReset_BiometryFaceId: String { return self._s[2974]! } + public var Channel_DiscussionGroup_UnlinkChannel: String { return self._s[2975]! } public func Passport_Scans_ScanIndex(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2975]!, self._r[2975]!, [_0]) + return formatWithArgumentRanges(self._s[2976]!, self._r[2976]!, [_0]) } - public var Channel_AdminLog_CanDeleteMessages: String { return self._s[2976]! } - public var Login_CancelSignUpConfirmation: String { return self._s[2977]! } - public var ChangePhoneNumberCode_Help: String { return self._s[2978]! } - public var PrivacySettings_DeleteAccountHelp: String { return self._s[2979]! } - public var Channel_BlackList_Title: String { return self._s[2980]! } - public var UserInfo_PhoneCall: String { return self._s[2981]! } - public var Passport_Address_OneOfTypeBankStatement: String { return self._s[2983]! } - public var Wallet_Month_ShortJanuary: String { return self._s[2984]! } - public var State_connecting: String { return self._s[2985]! } - public var Appearance_ThemePreview_ChatList_6_Text: String { return self._s[2986]! } - public var Wallet_Month_GenMarch: String { return self._s[2987]! } - public var EditTheme_Expand_BottomInfo: String { return self._s[2988]! } - public var AuthSessions_AddedDeviceTerminate: String { return self._s[2989]! } + public var Channel_AdminLog_CanDeleteMessages: String { return self._s[2977]! } + public var Login_CancelSignUpConfirmation: String { return self._s[2978]! } + public var ChangePhoneNumberCode_Help: String { return self._s[2979]! } + public var PrivacySettings_DeleteAccountHelp: String { return self._s[2980]! } + public var Channel_BlackList_Title: String { return self._s[2981]! } + public var UserInfo_PhoneCall: String { return self._s[2982]! } + public var Passport_Address_OneOfTypeBankStatement: String { return self._s[2984]! } + public var Wallet_Month_ShortJanuary: String { return self._s[2985]! } + public var State_connecting: String { return self._s[2986]! } + public var Appearance_ThemePreview_ChatList_6_Text: String { return self._s[2987]! } + public var Wallet_Month_GenMarch: String { return self._s[2988]! } + public var EditTheme_Expand_BottomInfo: String { return self._s[2989]! } + public var AuthSessions_AddedDeviceTerminate: String { return self._s[2990]! } public func LastSeen_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2990]!, self._r[2990]!, [_0]) - } - public func DialogList_SingleRecordingAudioSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2991]!, self._r[2991]!, [_0]) } - public var Notifications_GroupNotifications: String { return self._s[2992]! } - public var Conversation_SendMessageErrorTooMuchScheduled: String { return self._s[2993]! } - public var Passport_Identity_EditPassport: String { return self._s[2994]! } - public var EnterPasscode_RepeatNewPasscode: String { return self._s[2996]! } - public var Localization_EnglishLanguageName: String { return self._s[2997]! } - public var Share_AuthDescription: String { return self._s[2998]! } - public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsAlert: String { return self._s[2999]! } - public var Passport_Identity_Surname: String { return self._s[3000]! } - public var Compose_TokenListPlaceholder: String { return self._s[3001]! } - public var Wallet_AccessDenied_Camera: String { return self._s[3002]! } - public var Passport_Identity_OneOfTypePassport: String { return self._s[3003]! } - public var Settings_AboutEmpty: String { return self._s[3004]! } - public var Conversation_Unmute: String { return self._s[3005]! } - public var CreateGroup_ChannelsTooMuch: String { return self._s[3007]! } - public var Wallet_Sending_Text: String { return self._s[3008]! } - public func PUSH_CONTACT_JOINED(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3009]!, self._r[3009]!, [_1]) + public func DialogList_SingleRecordingAudioSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2992]!, self._r[2992]!, [_0]) } - public var Login_CodeSentCall: String { return self._s[3010]! } - public var ContactInfo_PhoneLabelHomeFax: String { return self._s[3012]! } - public var ChatSettings_Appearance: String { return self._s[3013]! } - public var ClearCache_StorageUsage: String { return self._s[3014]! } - public var Appearance_PickAccentColor: String { return self._s[3015]! } + public var Notifications_GroupNotifications: String { return self._s[2993]! } + public var Conversation_SendMessageErrorTooMuchScheduled: String { return self._s[2994]! } + public var Passport_Identity_EditPassport: String { return self._s[2995]! } + public var EnterPasscode_RepeatNewPasscode: String { return self._s[2997]! } + public var Localization_EnglishLanguageName: String { return self._s[2998]! } + public var Share_AuthDescription: String { return self._s[2999]! } + public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsAlert: String { return self._s[3000]! } + public var Passport_Identity_Surname: String { return self._s[3001]! } + public var Compose_TokenListPlaceholder: String { return self._s[3002]! } + public var Wallet_AccessDenied_Camera: String { return self._s[3003]! } + public var Passport_Identity_OneOfTypePassport: String { return self._s[3004]! } + public var Settings_AboutEmpty: String { return self._s[3005]! } + public var Conversation_Unmute: String { return self._s[3006]! } + public var CreateGroup_ChannelsTooMuch: String { return self._s[3008]! } + public var Wallet_Sending_Text: String { return self._s[3009]! } + public func PUSH_CONTACT_JOINED(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3010]!, self._r[3010]!, [_1]) + } + public var Login_CodeSentCall: String { return self._s[3011]! } + public var ContactInfo_PhoneLabelHomeFax: String { return self._s[3013]! } + public var ChatSettings_Appearance: String { return self._s[3014]! } + public var ClearCache_StorageUsage: String { return self._s[3015]! } + public var Appearance_PickAccentColor: String { return self._s[3016]! } public func PUSH_CHAT_MESSAGE_NOTEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3016]!, self._r[3016]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3017]!, self._r[3017]!, [_1, _2]) } public func PUSH_MESSAGE_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3017]!, self._r[3017]!, [_1]) + return formatWithArgumentRanges(self._s[3018]!, self._r[3018]!, [_1]) } - public var Notification_CallMissed: String { return self._s[3018]! } - public var SettingsSearch_Synonyms_Appearance_ChatBackground_Custom: String { return self._s[3019]! } - public var Channel_AdminLogFilter_EventsInfo: String { return self._s[3020]! } - public var Wallet_Month_GenOctober: String { return self._s[3022]! } - public var ChatAdmins_AdminLabel: String { return self._s[3023]! } - public var KeyCommand_JumpToNextChat: String { return self._s[3024]! } - public var Conversation_StopPollConfirmationTitle: String { return self._s[3026]! } - public var ChangePhoneNumberCode_CodePlaceholder: String { return self._s[3027]! } - public var Month_GenJune: String { return self._s[3028]! } - public var IntentsSettings_MainAccountInfo: String { return self._s[3029]! } - public var Watch_Location_Current: String { return self._s[3030]! } - public var Wallet_Receive_CopyInvoiceUrl: String { return self._s[3031]! } - public var Conversation_TitleMute: String { return self._s[3032]! } - public var Map_PlacesInThisArea: String { return self._s[3033]! } + public var Notification_CallMissed: String { return self._s[3019]! } + public var SettingsSearch_Synonyms_Appearance_ChatBackground_Custom: String { return self._s[3020]! } + public var Channel_AdminLogFilter_EventsInfo: String { return self._s[3021]! } + public var Wallet_Month_GenOctober: String { return self._s[3023]! } + public var ChatAdmins_AdminLabel: String { return self._s[3024]! } + public var KeyCommand_JumpToNextChat: String { return self._s[3025]! } + public var Conversation_StopPollConfirmationTitle: String { return self._s[3027]! } + public var ChangePhoneNumberCode_CodePlaceholder: String { return self._s[3028]! } + public var Month_GenJune: String { return self._s[3029]! } + public var IntentsSettings_MainAccountInfo: String { return self._s[3030]! } + public var Watch_Location_Current: String { return self._s[3031]! } + public var Wallet_Receive_CopyInvoiceUrl: String { return self._s[3032]! } + public var Conversation_TitleMute: String { return self._s[3033]! } + public var Map_PlacesInThisArea: String { return self._s[3034]! } public func PUSH_CHANNEL_MESSAGE_ROUND(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3034]!, self._r[3034]!, [_1]) + return formatWithArgumentRanges(self._s[3035]!, self._r[3035]!, [_1]) } - public var GroupInfo_DeleteAndExit: String { return self._s[3035]! } + public var GroupInfo_DeleteAndExit: String { return self._s[3036]! } public func Conversation_Moderate_DeleteAllMessages(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3036]!, self._r[3036]!, [_0]) + return formatWithArgumentRanges(self._s[3037]!, self._r[3037]!, [_0]) } - public var Call_ReportPlaceholder: String { return self._s[3037]! } - public var Chat_SlowmodeSendError: String { return self._s[3038]! } - public var MaskStickerSettings_Info: String { return self._s[3039]! } - public var EditTheme_Expand_TopInfo: String { return self._s[3040]! } + public var Call_ReportPlaceholder: String { return self._s[3038]! } + public var Chat_SlowmodeSendError: String { return self._s[3039]! } + public var MaskStickerSettings_Info: String { return self._s[3040]! } + public var EditTheme_Expand_TopInfo: String { return self._s[3041]! } public func GroupInfo_AddParticipantConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3041]!, self._r[3041]!, [_0]) + return formatWithArgumentRanges(self._s[3042]!, self._r[3042]!, [_0]) } - public var Checkout_NewCard_PostcodeTitle: String { return self._s[3042]! } - public var Passport_Address_RegionPlaceholder: String { return self._s[3044]! } - public var Contacts_ShareTelegram: String { return self._s[3045]! } - public var EnterPasscode_EnterNewPasscodeNew: String { return self._s[3046]! } - public var Map_AddressOnMap: String { return self._s[3047]! } - public var Channel_ErrorAccessDenied: String { return self._s[3048]! } - public var UserInfo_ScamBotWarning: String { return self._s[3050]! } - public var Stickers_GroupChooseStickerPack: String { return self._s[3051]! } - public var Call_ConnectionErrorTitle: String { return self._s[3052]! } - public var UserInfo_NotificationsEnable: String { return self._s[3053]! } - public var ArchivedChats_IntroText1: String { return self._s[3054]! } - public var Tour_Text4: String { return self._s[3057]! } - public var WallpaperSearch_Recent: String { return self._s[3058]! } - public var GroupInfo_ScamGroupWarning: String { return self._s[3059]! } - public var Profile_MessageLifetime2s: String { return self._s[3061]! } - public var Appearance_ThemePreview_ChatList_5_Text: String { return self._s[3062]! } - public var Notification_MessageLifetime2s: String { return self._s[3063]! } + public var Checkout_NewCard_PostcodeTitle: String { return self._s[3043]! } + public var Passport_Address_RegionPlaceholder: String { return self._s[3045]! } + public var Contacts_ShareTelegram: String { return self._s[3046]! } + public var EnterPasscode_EnterNewPasscodeNew: String { return self._s[3047]! } + public var Map_AddressOnMap: String { return self._s[3048]! } + public var Channel_ErrorAccessDenied: String { return self._s[3049]! } + public var UserInfo_ScamBotWarning: String { return self._s[3051]! } + public var Stickers_GroupChooseStickerPack: String { return self._s[3052]! } + public var Call_ConnectionErrorTitle: String { return self._s[3053]! } + public var UserInfo_NotificationsEnable: String { return self._s[3054]! } + public var ArchivedChats_IntroText1: String { return self._s[3055]! } + public var Tour_Text4: String { return self._s[3058]! } + public var WallpaperSearch_Recent: String { return self._s[3059]! } + public var GroupInfo_ScamGroupWarning: String { return self._s[3060]! } + public var Profile_MessageLifetime2s: String { return self._s[3062]! } + public var Appearance_ThemePreview_ChatList_5_Text: String { return self._s[3063]! } + public var Notification_MessageLifetime2s: String { return self._s[3064]! } public func Time_PreciseDate_m10(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3064]!, self._r[3064]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3065]!, self._r[3065]!, [_1, _2, _3]) } - public var Cache_ClearCache: String { return self._s[3065]! } - public var AutoNightTheme_UpdateLocation: String { return self._s[3066]! } - public var Permissions_NotificationsUnreachableText_v0: String { return self._s[3067]! } + public var Cache_ClearCache: String { return self._s[3066]! } + public var AutoNightTheme_UpdateLocation: String { return self._s[3067]! } + public var Permissions_NotificationsUnreachableText_v0: String { return self._s[3068]! } public func Channel_AdminLog_MessageChangedGroupUsername(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3071]!, self._r[3071]!, [_0]) + return formatWithArgumentRanges(self._s[3072]!, self._r[3072]!, [_0]) } public func Conversation_ShareMyPhoneNumber_StatusSuccess(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3073]!, self._r[3073]!, [_0]) + return formatWithArgumentRanges(self._s[3074]!, self._r[3074]!, [_0]) } - public var LocalGroup_Text: String { return self._s[3074]! } - public var Channel_AdminLog_EmptyFilterTitle: String { return self._s[3075]! } - public var SocksProxySetup_TypeSocks: String { return self._s[3076]! } - public var ChatList_UnarchiveAction: String { return self._s[3077]! } - public var AutoNightTheme_Title: String { return self._s[3078]! } - public var InstantPage_FeedbackButton: String { return self._s[3079]! } - public var Passport_FieldAddress: String { return self._s[3080]! } + public var LocalGroup_Text: String { return self._s[3075]! } + public var Channel_AdminLog_EmptyFilterTitle: String { return self._s[3076]! } + public var SocksProxySetup_TypeSocks: String { return self._s[3077]! } + public var ChatList_UnarchiveAction: String { return self._s[3078]! } + public var AutoNightTheme_Title: String { return self._s[3079]! } + public var InstantPage_FeedbackButton: String { return self._s[3080]! } + public var Passport_FieldAddress: String { return self._s[3081]! } public func Channel_AdminLog_SetSlowmode(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3081]!, self._r[3081]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3082]!, self._r[3082]!, [_1, _2]) } - public var Month_ShortMarch: String { return self._s[3082]! } + public var Month_ShortMarch: String { return self._s[3083]! } public func PUSH_MESSAGE_INVOICE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3083]!, self._r[3083]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3084]!, self._r[3084]!, [_1, _2]) } - public var SocksProxySetup_UsernamePlaceholder: String { return self._s[3084]! } - public var Conversation_ShareInlineBotLocationConfirmation: String { return self._s[3085]! } - public var Passport_FloodError: String { return self._s[3086]! } - public var SecretGif_Title: String { return self._s[3087]! } - public var NotificationSettings_ShowNotificationsAllAccountsInfoOn: String { return self._s[3088]! } - public var ChatList_Context_UnhideArchive: String { return self._s[3089]! } - public var Passport_Language_th: String { return self._s[3091]! } - public var Passport_Address_Address: String { return self._s[3092]! } - public var Login_InvalidLastNameError: String { return self._s[3093]! } - public var Notifications_InAppNotificationsPreview: String { return self._s[3094]! } - public var Notifications_PermissionsUnreachableTitle: String { return self._s[3095]! } - public var ChatList_Context_Archive: String { return self._s[3096]! } - public var SettingsSearch_FAQ: String { return self._s[3097]! } - public var ShareMenu_Send: String { return self._s[3098]! } - public var WallpaperSearch_ColorYellow: String { return self._s[3100]! } - public var Month_GenNovember: String { return self._s[3102]! } - public var SettingsSearch_Synonyms_Appearance_LargeEmoji: String { return self._s[3104]! } + public var SocksProxySetup_UsernamePlaceholder: String { return self._s[3085]! } + public var Conversation_ShareInlineBotLocationConfirmation: String { return self._s[3086]! } + public var Passport_FloodError: String { return self._s[3087]! } + public var SecretGif_Title: String { return self._s[3088]! } + public var NotificationSettings_ShowNotificationsAllAccountsInfoOn: String { return self._s[3089]! } + public var ChatList_Context_UnhideArchive: String { return self._s[3090]! } + public var Passport_Language_th: String { return self._s[3092]! } + public var Passport_Address_Address: String { return self._s[3093]! } + public var Login_InvalidLastNameError: String { return self._s[3094]! } + public var Notifications_InAppNotificationsPreview: String { return self._s[3095]! } + public var Notifications_PermissionsUnreachableTitle: String { return self._s[3096]! } + public var ChatList_Context_Archive: String { return self._s[3097]! } + public var SettingsSearch_FAQ: String { return self._s[3098]! } + public var ShareMenu_Send: String { return self._s[3099]! } + public var WallpaperSearch_ColorYellow: String { return self._s[3101]! } + public var Month_GenNovember: String { return self._s[3103]! } + public var SettingsSearch_Synonyms_Appearance_LargeEmoji: String { return self._s[3105]! } public func Conversation_ShareMyPhoneNumberConfirmation(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3105]!, self._r[3105]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3106]!, self._r[3106]!, [_1, _2]) } - public var Conversation_SwipeToReplyHintText: String { return self._s[3106]! } - public var Checkout_Email: String { return self._s[3107]! } - public var NotificationsSound_Tritone: String { return self._s[3108]! } - public var StickerPacksSettings_ManagingHelp: String { return self._s[3110]! } - public var Wallet_ContextMenuCopy: String { return self._s[3112]! } + public var Conversation_SwipeToReplyHintText: String { return self._s[3107]! } + public var Checkout_Email: String { return self._s[3108]! } + public var NotificationsSound_Tritone: String { return self._s[3109]! } + public var StickerPacksSettings_ManagingHelp: String { return self._s[3111]! } + public var Wallet_ContextMenuCopy: String { return self._s[3113]! } public func Wallet_Time_PreciseDate_m6(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3114]!, self._r[3114]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3115]!, self._r[3115]!, [_1, _2, _3]) } - public var Appearance_TextSize_Automatic: String { return self._s[3115]! } + public var Appearance_TextSize_Automatic: String { return self._s[3116]! } public func PUSH_PINNED_ROUND(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3116]!, self._r[3116]!, [_1]) + return formatWithArgumentRanges(self._s[3117]!, self._r[3117]!, [_1]) } public func StickerPackActionInfo_AddedText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3117]!, self._r[3117]!, [_0]) + return formatWithArgumentRanges(self._s[3118]!, self._r[3118]!, [_0]) } - public var ChangePhoneNumberNumber_Help: String { return self._s[3118]! } + public var ChangePhoneNumberNumber_Help: String { return self._s[3119]! } public func Checkout_LiabilityAlert(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3119]!, self._r[3119]!, [_1, _1, _1, _2]) + return formatWithArgumentRanges(self._s[3120]!, self._r[3120]!, [_1, _1, _1, _2]) } - public var ChatList_UndoArchiveTitle: String { return self._s[3120]! } - public var Notification_Exceptions_Add: String { return self._s[3121]! } - public var DialogList_You: String { return self._s[3122]! } - public var MediaPicker_Send: String { return self._s[3125]! } - public var SettingsSearch_Synonyms_Stickers_Title: String { return self._s[3126]! } - public var Appearance_ThemePreview_ChatList_4_Text: String { return self._s[3127]! } - public var Call_AudioRouteSpeaker: String { return self._s[3128]! } - public var Watch_UserInfo_Title: String { return self._s[3129]! } - public var VoiceOver_Chat_PollFinalResults: String { return self._s[3130]! } - public var Appearance_AccentColor: String { return self._s[3132]! } + public var ChatList_UndoArchiveTitle: String { return self._s[3121]! } + public var Notification_Exceptions_Add: String { return self._s[3122]! } + public var DialogList_You: String { return self._s[3123]! } + public var MediaPicker_Send: String { return self._s[3126]! } + public var SettingsSearch_Synonyms_Stickers_Title: String { return self._s[3127]! } + public var Appearance_ThemePreview_ChatList_4_Text: String { return self._s[3128]! } + public var Call_AudioRouteSpeaker: String { return self._s[3129]! } + public var Watch_UserInfo_Title: String { return self._s[3130]! } + public var VoiceOver_Chat_PollFinalResults: String { return self._s[3131]! } + public var Appearance_AccentColor: String { return self._s[3133]! } public func Login_EmailPhoneSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3133]!, self._r[3133]!, [_0]) + return formatWithArgumentRanges(self._s[3134]!, self._r[3134]!, [_0]) } - public var Permissions_ContactsAllowInSettings_v0: String { return self._s[3134]! } + public var Permissions_ContactsAllowInSettings_v0: String { return self._s[3135]! } public func PUSH_CHANNEL_MESSAGE_GAME(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3135]!, self._r[3135]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3136]!, self._r[3136]!, [_1, _2]) } - public var Conversation_ClousStorageInfo_Description2: String { return self._s[3136]! } - public var WebSearch_RecentClearConfirmation: String { return self._s[3137]! } - public var Notification_CallOutgoing: String { return self._s[3138]! } - public var PrivacySettings_PasscodeAndFaceId: String { return self._s[3139]! } - public var Channel_DiscussionGroup_MakeHistoryPublic: String { return self._s[3140]! } - public var Call_RecordingDisabledMessage: String { return self._s[3141]! } - public var Message_Game: String { return self._s[3142]! } - public var Conversation_PressVolumeButtonForSound: String { return self._s[3143]! } - public var PrivacyLastSeenSettings_CustomHelp: String { return self._s[3144]! } - public var Channel_DiscussionGroup_PrivateGroup: String { return self._s[3145]! } - public var Channel_EditAdmin_PermissionAddAdmins: String { return self._s[3146]! } - public var Date_DialogDateFormat: String { return self._s[3148]! } - public var WallpaperColors_SetCustomColor: String { return self._s[3149]! } - public var Notifications_InAppNotifications: String { return self._s[3150]! } + public var Conversation_ClousStorageInfo_Description2: String { return self._s[3137]! } + public var WebSearch_RecentClearConfirmation: String { return self._s[3138]! } + public var Notification_CallOutgoing: String { return self._s[3139]! } + public var PrivacySettings_PasscodeAndFaceId: String { return self._s[3140]! } + public var Channel_DiscussionGroup_MakeHistoryPublic: String { return self._s[3141]! } + public var Call_RecordingDisabledMessage: String { return self._s[3142]! } + public var Message_Game: String { return self._s[3143]! } + public var Conversation_PressVolumeButtonForSound: String { return self._s[3144]! } + public var PrivacyLastSeenSettings_CustomHelp: String { return self._s[3145]! } + public var Channel_DiscussionGroup_PrivateGroup: String { return self._s[3146]! } + public var Channel_EditAdmin_PermissionAddAdmins: String { return self._s[3147]! } + public var Date_DialogDateFormat: String { return self._s[3149]! } + public var WallpaperColors_SetCustomColor: String { return self._s[3150]! } + public var Notifications_InAppNotifications: String { return self._s[3151]! } public func Channel_Management_RemovedBy(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3151]!, self._r[3151]!, [_0]) + return formatWithArgumentRanges(self._s[3152]!, self._r[3152]!, [_0]) } public func Settings_ApplyProxyAlert(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3152]!, self._r[3152]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3153]!, self._r[3153]!, [_1, _2]) } - public var NewContact_Title: String { return self._s[3153]! } + public var NewContact_Title: String { return self._s[3154]! } public func AutoDownloadSettings_UpToForAll(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3154]!, self._r[3154]!, [_0]) + return formatWithArgumentRanges(self._s[3155]!, self._r[3155]!, [_0]) } - public var Conversation_ViewContactDetails: String { return self._s[3155]! } + public var Conversation_ViewContactDetails: String { return self._s[3156]! } public func PUSH_CHANNEL_MESSAGE_CONTACT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3157]!, self._r[3157]!, [_1]) + return formatWithArgumentRanges(self._s[3158]!, self._r[3158]!, [_1]) } - public var Checkout_NewCard_CardholderNameTitle: String { return self._s[3158]! } - public var Passport_Identity_ExpiryDateNone: String { return self._s[3159]! } - public var PrivacySettings_Title: String { return self._s[3160]! } - public var Conversation_SilentBroadcastTooltipOff: String { return self._s[3163]! } - public var GroupRemoved_UsersSectionTitle: String { return self._s[3164]! } - public var VoiceOver_Chat_ContactEmail: String { return self._s[3165]! } - public var Contacts_PhoneNumber: String { return self._s[3166]! } - public var TwoFactorSetup_Password_PlaceholderConfirmPassword: String { return self._s[3168]! } - public var Map_ShowPlaces: String { return self._s[3169]! } - public var ChatAdmins_Title: String { return self._s[3170]! } - public var InstantPage_Reference: String { return self._s[3172]! } - public var Wallet_Info_Updating: String { return self._s[3173]! } - public var ReportGroupLocation_Text: String { return self._s[3174]! } + public var Checkout_NewCard_CardholderNameTitle: String { return self._s[3159]! } + public var Passport_Identity_ExpiryDateNone: String { return self._s[3160]! } + public var PrivacySettings_Title: String { return self._s[3161]! } + public var Conversation_SilentBroadcastTooltipOff: String { return self._s[3164]! } + public var GroupRemoved_UsersSectionTitle: String { return self._s[3165]! } + public var VoiceOver_Chat_ContactEmail: String { return self._s[3166]! } + public var Contacts_PhoneNumber: String { return self._s[3167]! } + public var TwoFactorSetup_Password_PlaceholderConfirmPassword: String { return self._s[3169]! } + public var Map_ShowPlaces: String { return self._s[3170]! } + public var ChatAdmins_Title: String { return self._s[3171]! } + public var InstantPage_Reference: String { return self._s[3173]! } + public var Wallet_Info_Updating: String { return self._s[3174]! } + public var ReportGroupLocation_Text: String { return self._s[3175]! } public func PUSH_CHAT_MESSAGE_FWD(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3175]!, self._r[3175]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3176]!, self._r[3176]!, [_1, _2]) } - public var Camera_FlashOff: String { return self._s[3176]! } - public var Watch_UserInfo_Block: String { return self._s[3177]! } - public var ChatSettings_Stickers: String { return self._s[3178]! } - public var ChatSettings_DownloadInBackground: String { return self._s[3179]! } - public var Appearance_ThemeCarouselTintedNight: String { return self._s[3180]! } + public var Camera_FlashOff: String { return self._s[3177]! } + public var Watch_UserInfo_Block: String { return self._s[3178]! } + public var ChatSettings_Stickers: String { return self._s[3179]! } + public var ChatSettings_DownloadInBackground: String { return self._s[3180]! } + public var Appearance_ThemeCarouselTintedNight: String { return self._s[3181]! } public func UserInfo_BlockConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3181]!, self._r[3181]!, [_0]) + return formatWithArgumentRanges(self._s[3182]!, self._r[3182]!, [_0]) } - public var Settings_ViewPhoto: String { return self._s[3182]! } - public var Login_CheckOtherSessionMessages: String { return self._s[3183]! } - public var AutoDownloadSettings_Cellular: String { return self._s[3184]! } - public var Wallet_Created_ExportErrorTitle: String { return self._s[3185]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsExceptions: String { return self._s[3186]! } - public var VoiceOver_MessageContextShare: String { return self._s[3187]! } + public var Settings_ViewPhoto: String { return self._s[3183]! } + public var Login_CheckOtherSessionMessages: String { return self._s[3184]! } + public var AutoDownloadSettings_Cellular: String { return self._s[3185]! } + public var Wallet_Created_ExportErrorTitle: String { return self._s[3186]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsExceptions: String { return self._s[3187]! } + public var VoiceOver_MessageContextShare: String { return self._s[3188]! } public func Target_InviteToGroupConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3189]!, self._r[3189]!, [_0]) + return formatWithArgumentRanges(self._s[3190]!, self._r[3190]!, [_0]) } - public var Privacy_DeleteDrafts: String { return self._s[3190]! } - public var Wallpaper_SetCustomBackgroundInfo: String { return self._s[3191]! } + public var Privacy_DeleteDrafts: String { return self._s[3191]! } + public var Wallpaper_SetCustomBackgroundInfo: String { return self._s[3192]! } public func LastSeen_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3192]!, self._r[3192]!, [_0]) + return formatWithArgumentRanges(self._s[3193]!, self._r[3193]!, [_0]) } - public var DialogList_SavedMessagesHelp: String { return self._s[3193]! } - public var Wallet_SecureStorageNotAvailable_Title: String { return self._s[3194]! } - public var DialogList_SavedMessages: String { return self._s[3195]! } - public var GroupInfo_UpgradeButton: String { return self._s[3196]! } - public var Appearance_ThemePreview_ChatList_3_Text: String { return self._s[3198]! } - public var DialogList_Pin: String { return self._s[3199]! } + public var DialogList_SavedMessagesHelp: String { return self._s[3194]! } + public var Wallet_SecureStorageNotAvailable_Title: String { return self._s[3195]! } + public var DialogList_SavedMessages: String { return self._s[3196]! } + public var GroupInfo_UpgradeButton: String { return self._s[3197]! } + public var Appearance_ThemePreview_ChatList_3_Text: String { return self._s[3199]! } + public var DialogList_Pin: String { return self._s[3200]! } public func ForwardedAuthors2(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3200]!, self._r[3200]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3201]!, self._r[3201]!, [_0, _1]) } public func Login_PhoneGenericEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3201]!, self._r[3201]!, [_0]) + return formatWithArgumentRanges(self._s[3202]!, self._r[3202]!, [_0]) } - public var Notification_Exceptions_AlwaysOn: String { return self._s[3202]! } - public var UserInfo_NotificationsDisable: String { return self._s[3203]! } - public var Conversation_ContextMenuCancelEditing: String { return self._s[3204]! } - public var Paint_Outlined: String { return self._s[3205]! } - public var Activity_PlayingGame: String { return self._s[3206]! } - public var SearchImages_NoImagesFound: String { return self._s[3207]! } - public var SocksProxySetup_ProxyType: String { return self._s[3208]! } - public var AppleWatch_ReplyPresetsHelp: String { return self._s[3210]! } - public var Conversation_ContextMenuCancelSending: String { return self._s[3211]! } - public var Settings_AppLanguage: String { return self._s[3212]! } - public var TwoStepAuth_ResetAccountHelp: String { return self._s[3213]! } - public var Common_ChoosePhoto: String { return self._s[3214]! } - public var AuthSessions_AddDevice_InvalidQRCode: String { return self._s[3215]! } - public var CallFeedback_ReasonEcho: String { return self._s[3216]! } + public var Notification_Exceptions_AlwaysOn: String { return self._s[3203]! } + public var UserInfo_NotificationsDisable: String { return self._s[3204]! } + public var Conversation_ContextMenuCancelEditing: String { return self._s[3205]! } + public var Paint_Outlined: String { return self._s[3206]! } + public var Activity_PlayingGame: String { return self._s[3207]! } + public var SearchImages_NoImagesFound: String { return self._s[3208]! } + public var SocksProxySetup_ProxyType: String { return self._s[3209]! } + public var AppleWatch_ReplyPresetsHelp: String { return self._s[3211]! } + public var Conversation_ContextMenuCancelSending: String { return self._s[3212]! } + public var Settings_AppLanguage: String { return self._s[3213]! } + public var TwoStepAuth_ResetAccountHelp: String { return self._s[3214]! } + public var Common_ChoosePhoto: String { return self._s[3215]! } + public var AuthSessions_AddDevice_InvalidQRCode: String { return self._s[3216]! } + public var CallFeedback_ReasonEcho: String { return self._s[3217]! } public func PUSH_PINNED_AUDIO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3217]!, self._r[3217]!, [_1]) + return formatWithArgumentRanges(self._s[3218]!, self._r[3218]!, [_1]) } - public var Privacy_Calls_AlwaysAllow: String { return self._s[3218]! } - public var PollResults_Collapse: String { return self._s[3219]! } - public var Activity_UploadingVideo: String { return self._s[3220]! } - public var Conversation_WalletRequiredNotNow: String { return self._s[3221]! } - public var ChannelInfo_DeleteChannelConfirmation: String { return self._s[3222]! } - public var NetworkUsageSettings_Wifi: String { return self._s[3223]! } - public var VoiceOver_Editing_ClearText: String { return self._s[3224]! } - public var PUSH_SENDER_YOU: String { return self._s[3225]! } - public var Channel_BanUser_PermissionReadMessages: String { return self._s[3226]! } - public var Checkout_PayWithTouchId: String { return self._s[3227]! } - public var Wallpaper_ResetWallpapersConfirmation: String { return self._s[3228]! } + public var Privacy_Calls_AlwaysAllow: String { return self._s[3219]! } + public var PollResults_Collapse: String { return self._s[3220]! } + public var Activity_UploadingVideo: String { return self._s[3221]! } + public var Conversation_WalletRequiredNotNow: String { return self._s[3222]! } + public var ChannelInfo_DeleteChannelConfirmation: String { return self._s[3223]! } + public var NetworkUsageSettings_Wifi: String { return self._s[3224]! } + public var VoiceOver_Editing_ClearText: String { return self._s[3225]! } + public var PUSH_SENDER_YOU: String { return self._s[3226]! } + public var Channel_BanUser_PermissionReadMessages: String { return self._s[3227]! } + public var Checkout_PayWithTouchId: String { return self._s[3228]! } + public var Wallpaper_ResetWallpapersConfirmation: String { return self._s[3229]! } public func PUSH_LOCKED_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3230]!, self._r[3230]!, [_1]) + return formatWithArgumentRanges(self._s[3231]!, self._r[3231]!, [_1]) } - public var Notifications_ExceptionsNone: String { return self._s[3231]! } + public var Notifications_ExceptionsNone: String { return self._s[3232]! } public func Message_ForwardedMessageShort(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3232]!, self._r[3232]!, [_0]) + return formatWithArgumentRanges(self._s[3233]!, self._r[3233]!, [_0]) } public func PUSH_PINNED_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3233]!, self._r[3233]!, [_1]) + return formatWithArgumentRanges(self._s[3234]!, self._r[3234]!, [_1]) } - public var AuthSessions_IncompleteAttempts: String { return self._s[3235]! } - public var Passport_Address_Region: String { return self._s[3238]! } - public var ChatList_DeleteChat: String { return self._s[3239]! } - public var LogoutOptions_ClearCacheTitle: String { return self._s[3240]! } - public var PhotoEditor_TiltShift: String { return self._s[3241]! } - public var Settings_FAQ_URL: String { return self._s[3242]! } - public var TwoFactorSetup_EmailVerification_ChangeAction: String { return self._s[3243]! } - public var Passport_Language_sl: String { return self._s[3244]! } - public var Settings_PrivacySettings: String { return self._s[3246]! } - public var SharedMedia_TitleLink: String { return self._s[3247]! } - public var Passport_Identity_TypePassportUploadScan: String { return self._s[3248]! } - public var Settings_SetProfilePhoto: String { return self._s[3249]! } - public var Channel_About_Help: String { return self._s[3250]! } - public var Contacts_PermissionsEnable: String { return self._s[3251]! } - public var Wallet_Sending_Title: String { return self._s[3252]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsAlert: String { return self._s[3253]! } - public var AttachmentMenu_SendAsFiles: String { return self._s[3254]! } - public var CallFeedback_ReasonInterruption: String { return self._s[3256]! } - public var Passport_Address_AddTemporaryRegistration: String { return self._s[3257]! } - public var AutoDownloadSettings_AutodownloadVideos: String { return self._s[3258]! } - public var ChatSettings_AutoDownloadSettings_Delimeter: String { return self._s[3259]! } - public var OldChannels_Title: String { return self._s[3260]! } - public var PrivacySettings_DeleteAccountTitle: String { return self._s[3261]! } - public var AccessDenied_VideoMessageCamera: String { return self._s[3263]! } - public var Map_OpenInYandexMaps: String { return self._s[3265]! } - public var CreateGroup_ErrorLocatedGroupsTooMuch: String { return self._s[3266]! } - public var VoiceOver_MessageContextReply: String { return self._s[3267]! } - public var PhotoEditor_SaturationTool: String { return self._s[3269]! } + public var AuthSessions_IncompleteAttempts: String { return self._s[3236]! } + public var Passport_Address_Region: String { return self._s[3239]! } + public var ChatList_DeleteChat: String { return self._s[3240]! } + public var LogoutOptions_ClearCacheTitle: String { return self._s[3241]! } + public var PhotoEditor_TiltShift: String { return self._s[3242]! } + public var Settings_FAQ_URL: String { return self._s[3243]! } + public var TwoFactorSetup_EmailVerification_ChangeAction: String { return self._s[3244]! } + public var Passport_Language_sl: String { return self._s[3245]! } + public var Settings_PrivacySettings: String { return self._s[3247]! } + public var SharedMedia_TitleLink: String { return self._s[3248]! } + public var Passport_Identity_TypePassportUploadScan: String { return self._s[3249]! } + public var Settings_SetProfilePhoto: String { return self._s[3250]! } + public var Channel_About_Help: String { return self._s[3251]! } + public var Contacts_PermissionsEnable: String { return self._s[3252]! } + public var Wallet_Sending_Title: String { return self._s[3253]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsAlert: String { return self._s[3254]! } + public var AttachmentMenu_SendAsFiles: String { return self._s[3255]! } + public var CallFeedback_ReasonInterruption: String { return self._s[3257]! } + public var Passport_Address_AddTemporaryRegistration: String { return self._s[3258]! } + public var AutoDownloadSettings_AutodownloadVideos: String { return self._s[3259]! } + public var ChatSettings_AutoDownloadSettings_Delimeter: String { return self._s[3260]! } + public var OldChannels_Title: String { return self._s[3261]! } + public var PrivacySettings_DeleteAccountTitle: String { return self._s[3262]! } + public var AccessDenied_VideoMessageCamera: String { return self._s[3264]! } + public var Map_OpenInYandexMaps: String { return self._s[3266]! } + public var CreateGroup_ErrorLocatedGroupsTooMuch: String { return self._s[3267]! } + public var VoiceOver_MessageContextReply: String { return self._s[3268]! } + public var PhotoEditor_SaturationTool: String { return self._s[3270]! } public func PUSH_MESSAGE_STICKER(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3270]!, self._r[3270]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3271]!, self._r[3271]!, [_1, _2]) } - public var PrivacyPhoneNumberSettings_CustomHelp: String { return self._s[3271]! } - public var Notification_Exceptions_NewException_NotificationHeader: String { return self._s[3272]! } - public var Group_OwnershipTransfer_ErrorLocatedGroupsTooMuch: String { return self._s[3273]! } + public var PrivacyPhoneNumberSettings_CustomHelp: String { return self._s[3272]! } + public var Notification_Exceptions_NewException_NotificationHeader: String { return self._s[3273]! } + public var Group_OwnershipTransfer_ErrorLocatedGroupsTooMuch: String { return self._s[3274]! } public func LOCAL_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3274]!, self._r[3274]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[3275]!, self._r[3275]!, [_1, "\(_2)"]) } - public var Appearance_ThemePreview_ChatList_2_Text: String { return self._s[3275]! } - public var Channel_Username_InvalidTooShort: String { return self._s[3277]! } - public var SettingsSearch_Synonyms_Wallet: String { return self._s[3278]! } + public var Appearance_ThemePreview_ChatList_2_Text: String { return self._s[3276]! } + public var Channel_Username_InvalidTooShort: String { return self._s[3278]! } + public var SettingsSearch_Synonyms_Wallet: String { return self._s[3279]! } public func Group_OwnershipTransfer_DescriptionInfo(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3279]!, self._r[3279]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3280]!, self._r[3280]!, [_1, _2]) } - public var Forward_ErrorPublicPollDisabledInChannels: String { return self._s[3280]! } + public var Forward_ErrorPublicPollDisabledInChannels: String { return self._s[3281]! } public func PUSH_CHAT_MESSAGE_GAME(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3281]!, self._r[3281]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3282]!, self._r[3282]!, [_1, _2, _3]) } - public var WallpaperPreview_PatternTitle: String { return self._s[3282]! } - public var GroupInfo_PublicLinkAdd: String { return self._s[3283]! } - public var Passport_PassportInformation: String { return self._s[3286]! } - public var Theme_Unsupported: String { return self._s[3287]! } - public var WatchRemote_AlertTitle: String { return self._s[3288]! } - public var Privacy_GroupsAndChannels_NeverAllow: String { return self._s[3289]! } - public var ConvertToSupergroup_HelpText: String { return self._s[3291]! } + public var WallpaperPreview_PatternTitle: String { return self._s[3283]! } + public var GroupInfo_PublicLinkAdd: String { return self._s[3284]! } + public var Passport_PassportInformation: String { return self._s[3287]! } + public var Theme_Unsupported: String { return self._s[3288]! } + public var WatchRemote_AlertTitle: String { return self._s[3289]! } + public var Privacy_GroupsAndChannels_NeverAllow: String { return self._s[3290]! } + public var ConvertToSupergroup_HelpText: String { return self._s[3292]! } public func Time_MonthOfYear_m7(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3292]!, self._r[3292]!, [_0]) + return formatWithArgumentRanges(self._s[3293]!, self._r[3293]!, [_0]) } public func PUSH_PHONE_CALL_REQUEST(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3293]!, self._r[3293]!, [_1]) + return formatWithArgumentRanges(self._s[3294]!, self._r[3294]!, [_1]) } - public var Privacy_GroupsAndChannels_CustomHelp: String { return self._s[3294]! } - public var Wallet_Navigation_Done: String { return self._s[3296]! } - public var TwoStepAuth_RecoveryCodeInvalid: String { return self._s[3297]! } - public var AccessDenied_CameraDisabled: String { return self._s[3298]! } + public var Privacy_GroupsAndChannels_CustomHelp: String { return self._s[3295]! } + public var Wallet_Navigation_Done: String { return self._s[3297]! } + public var TwoStepAuth_RecoveryCodeInvalid: String { return self._s[3298]! } + public var AccessDenied_CameraDisabled: String { return self._s[3299]! } public func Channel_Username_UsernameIsAvailable(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3299]!, self._r[3299]!, [_0]) + return formatWithArgumentRanges(self._s[3300]!, self._r[3300]!, [_0]) } - public var ClearCache_Forever: String { return self._s[3300]! } - public var AuthSessions_AddDeviceIntro_Title: String { return self._s[3301]! } - public var CreatePoll_Quiz: String { return self._s[3302]! } - public var PhotoEditor_ContrastTool: String { return self._s[3305]! } + public var ClearCache_Forever: String { return self._s[3301]! } + public var AuthSessions_AddDeviceIntro_Title: String { return self._s[3302]! } + public var CreatePoll_Quiz: String { return self._s[3303]! } + public var PhotoEditor_ContrastTool: String { return self._s[3306]! } public func PUSH_PINNED_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3306]!, self._r[3306]!, [_1]) + return formatWithArgumentRanges(self._s[3307]!, self._r[3307]!, [_1]) } - public var DialogList_Draft: String { return self._s[3307]! } - public var Wallet_Configuration_BlockchainIdInfo: String { return self._s[3308]! } - public var Privacy_TopPeersDelete: String { return self._s[3310]! } - public var LoginPassword_PasswordPlaceholder: String { return self._s[3311]! } - public var Passport_Identity_TypeIdentityCardUploadScan: String { return self._s[3312]! } - public var WebSearch_RecentSectionClear: String { return self._s[3313]! } - public var EditTheme_ErrorInvalidCharacters: String { return self._s[3314]! } - public var Watch_ChatList_NoConversationsTitle: String { return self._s[3316]! } - public var Common_Done: String { return self._s[3318]! } - public var Shortcut_SwitchAccount: String { return self._s[3319]! } - public var AuthSessions_EmptyText: String { return self._s[3320]! } - public var Wallet_Configuration_BlockchainNameChangedTitle: String { return self._s[3321]! } - public var Conversation_ShareBotContactConfirmation: String { return self._s[3322]! } - public var Tour_Title5: String { return self._s[3323]! } - public var Wallet_Settings_Title: String { return self._s[3324]! } + public var DialogList_Draft: String { return self._s[3308]! } + public var Wallet_Configuration_BlockchainIdInfo: String { return self._s[3309]! } + public var Privacy_TopPeersDelete: String { return self._s[3311]! } + public var LoginPassword_PasswordPlaceholder: String { return self._s[3312]! } + public var Passport_Identity_TypeIdentityCardUploadScan: String { return self._s[3313]! } + public var WebSearch_RecentSectionClear: String { return self._s[3314]! } + public var EditTheme_ErrorInvalidCharacters: String { return self._s[3315]! } + public var Watch_ChatList_NoConversationsTitle: String { return self._s[3317]! } + public var Common_Done: String { return self._s[3319]! } + public var Shortcut_SwitchAccount: String { return self._s[3320]! } + public var AuthSessions_EmptyText: String { return self._s[3321]! } + public var Wallet_Configuration_BlockchainNameChangedTitle: String { return self._s[3322]! } + public var Conversation_ShareBotContactConfirmation: String { return self._s[3323]! } + public var Tour_Title5: String { return self._s[3324]! } + public var Wallet_Settings_Title: String { return self._s[3325]! } public func Map_DirectionsDriveEta(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3325]!, self._r[3325]!, [_0]) + return formatWithArgumentRanges(self._s[3326]!, self._r[3326]!, [_0]) } - public var ApplyLanguage_UnsufficientDataTitle: String { return self._s[3326]! } - public var Conversation_LinkDialogSave: String { return self._s[3327]! } - public var GroupInfo_ActionRestrict: String { return self._s[3328]! } - public var Checkout_Title: String { return self._s[3329]! } - public var Channel_DiscussionGroup_HeaderLabel: String { return self._s[3331]! } - public var Channel_AdminLog_CanChangeInfo: String { return self._s[3333]! } - public var Notification_RenamedGroup: String { return self._s[3334]! } - public var PeopleNearby_Groups: String { return self._s[3335]! } - public var Checkout_PayWithFaceId: String { return self._s[3336]! } - public var Channel_BanList_BlockedTitle: String { return self._s[3337]! } - public var SettingsSearch_Synonyms_Notifications_InAppNotificationsSound: String { return self._s[3339]! } - public var Checkout_WebConfirmation_Title: String { return self._s[3340]! } - public var Notifications_MessageNotificationsAlert: String { return self._s[3341]! } + public var ApplyLanguage_UnsufficientDataTitle: String { return self._s[3327]! } + public var Conversation_LinkDialogSave: String { return self._s[3328]! } + public var GroupInfo_ActionRestrict: String { return self._s[3329]! } + public var Checkout_Title: String { return self._s[3330]! } + public var Channel_DiscussionGroup_HeaderLabel: String { return self._s[3332]! } + public var Channel_AdminLog_CanChangeInfo: String { return self._s[3334]! } + public var Notification_RenamedGroup: String { return self._s[3335]! } + public var PeopleNearby_Groups: String { return self._s[3336]! } + public var Checkout_PayWithFaceId: String { return self._s[3337]! } + public var Channel_BanList_BlockedTitle: String { return self._s[3338]! } + public var SettingsSearch_Synonyms_Notifications_InAppNotificationsSound: String { return self._s[3340]! } + public var Checkout_WebConfirmation_Title: String { return self._s[3341]! } + public var Notifications_MessageNotificationsAlert: String { return self._s[3342]! } public func Activity_RemindAboutGroup(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3342]!, self._r[3342]!, [_0]) + return formatWithArgumentRanges(self._s[3343]!, self._r[3343]!, [_0]) } - public var Profile_AddToExisting: String { return self._s[3344]! } + public var Profile_AddToExisting: String { return self._s[3345]! } public func Profile_CreateEncryptedChatOutdatedError(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3345]!, self._r[3345]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3346]!, self._r[3346]!, [_0, _1]) } - public var Cache_Files: String { return self._s[3347]! } - public var Permissions_PrivacyPolicy: String { return self._s[3348]! } - public var SocksProxySetup_ConnectAndSave: String { return self._s[3349]! } - public var UserInfo_NotificationsDefaultDisabled: String { return self._s[3350]! } - public var AutoDownloadSettings_TypeContacts: String { return self._s[3352]! } - public var Appearance_ThemePreview_ChatList_1_Text: String { return self._s[3354]! } - public var Calls_NoCallsPlaceholder: String { return self._s[3355]! } + public var Cache_Files: String { return self._s[3348]! } + public var Permissions_PrivacyPolicy: String { return self._s[3349]! } + public var SocksProxySetup_ConnectAndSave: String { return self._s[3350]! } + public var UserInfo_NotificationsDefaultDisabled: String { return self._s[3351]! } + public var AutoDownloadSettings_TypeContacts: String { return self._s[3353]! } + public var Appearance_ThemePreview_ChatList_1_Text: String { return self._s[3355]! } + public var Calls_NoCallsPlaceholder: String { return self._s[3356]! } public func Wallet_Receive_ShareInvoiceUrlInfo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3356]!, self._r[3356]!, [_0]) + return formatWithArgumentRanges(self._s[3357]!, self._r[3357]!, [_0]) } - public var Channel_Username_RevokeExistingUsernamesInfo: String { return self._s[3357]! } - public var VoiceOver_AttachMedia: String { return self._s[3360]! } - public var Notifications_ExceptionsGroupPlaceholder: String { return self._s[3361]! } + public var Channel_Username_RevokeExistingUsernamesInfo: String { return self._s[3358]! } + public var VoiceOver_AttachMedia: String { return self._s[3361]! } + public var Notifications_ExceptionsGroupPlaceholder: String { return self._s[3362]! } public func PUSH_CHAT_MESSAGE_INVOICE(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3362]!, self._r[3362]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3363]!, self._r[3363]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsSound: String { return self._s[3363]! } - public var Conversation_SetReminder_Title: String { return self._s[3364]! } - public var Passport_FieldAddressHelp: String { return self._s[3365]! } - public var Privacy_GroupsAndChannels_InviteToChannelMultipleError: String { return self._s[3366]! } - public var PUSH_REMINDER_TITLE: String { return self._s[3367]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsSound: String { return self._s[3364]! } + public var Conversation_SetReminder_Title: String { return self._s[3365]! } + public var Passport_FieldAddressHelp: String { return self._s[3366]! } + public var Privacy_GroupsAndChannels_InviteToChannelMultipleError: String { return self._s[3367]! } + public var PUSH_REMINDER_TITLE: String { return self._s[3368]! } public func Login_TermsOfService_ProceedBot(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3368]!, self._r[3368]!, [_0]) + return formatWithArgumentRanges(self._s[3369]!, self._r[3369]!, [_0]) } - public var Channel_AdminLog_EmptyTitle: String { return self._s[3369]! } - public var Privacy_Calls_NeverAllow_Title: String { return self._s[3370]! } - public var Login_UnknownError: String { return self._s[3371]! } - public var Group_UpgradeNoticeText2: String { return self._s[3374]! } - public var Watch_Compose_AddContact: String { return self._s[3375]! } - public var ClearCache_StorageServiceFiles: String { return self._s[3376]! } - public var Web_Error: String { return self._s[3377]! } - public var Gif_Search: String { return self._s[3378]! } - public var Profile_MessageLifetime1h: String { return self._s[3379]! } - public var CheckoutInfo_ReceiverInfoEmailPlaceholder: String { return self._s[3380]! } - public var Channel_Username_CheckingUsername: String { return self._s[3381]! } - public var CallFeedback_ReasonSilentRemote: String { return self._s[3382]! } - public var AutoDownloadSettings_TypeChannels: String { return self._s[3383]! } - public var Channel_AboutItem: String { return self._s[3384]! } - public var Privacy_GroupsAndChannels_AlwaysAllow_Placeholder: String { return self._s[3386]! } - public var VoiceOver_Chat_VoiceMessage: String { return self._s[3387]! } - public var GroupInfo_SharedMedia: String { return self._s[3388]! } + public var Channel_AdminLog_EmptyTitle: String { return self._s[3370]! } + public var Privacy_Calls_NeverAllow_Title: String { return self._s[3371]! } + public var Login_UnknownError: String { return self._s[3372]! } + public var Group_UpgradeNoticeText2: String { return self._s[3375]! } + public var Watch_Compose_AddContact: String { return self._s[3376]! } + public var ClearCache_StorageServiceFiles: String { return self._s[3377]! } + public var Web_Error: String { return self._s[3378]! } + public var Gif_Search: String { return self._s[3379]! } + public var Profile_MessageLifetime1h: String { return self._s[3380]! } + public var CheckoutInfo_ReceiverInfoEmailPlaceholder: String { return self._s[3381]! } + public var Channel_Username_CheckingUsername: String { return self._s[3382]! } + public var CallFeedback_ReasonSilentRemote: String { return self._s[3383]! } + public var AutoDownloadSettings_TypeChannels: String { return self._s[3384]! } + public var Channel_AboutItem: String { return self._s[3385]! } + public var Privacy_GroupsAndChannels_AlwaysAllow_Placeholder: String { return self._s[3387]! } + public var VoiceOver_Chat_VoiceMessage: String { return self._s[3388]! } + public var GroupInfo_SharedMedia: String { return self._s[3389]! } public func Channel_AdminLog_MessagePromotedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3389]!, self._r[3389]!, [_1]) + return formatWithArgumentRanges(self._s[3390]!, self._r[3390]!, [_1]) } - public var Call_PhoneCallInProgressMessage: String { return self._s[3390]! } + public var Call_PhoneCallInProgressMessage: String { return self._s[3391]! } public func PUSH_CHANNEL_ALBUM(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3391]!, self._r[3391]!, [_1]) + return formatWithArgumentRanges(self._s[3392]!, self._r[3392]!, [_1]) } - public var ChatList_UndoArchiveRevealedText: String { return self._s[3392]! } - public var GroupInfo_InviteLink_RevokeAlert_Text: String { return self._s[3393]! } - public var Conversation_SearchByName_Placeholder: String { return self._s[3394]! } - public var CreatePoll_AddOption: String { return self._s[3395]! } - public var GroupInfo_Permissions_SearchPlaceholder: String { return self._s[3396]! } - public var Group_UpgradeNoticeHeader: String { return self._s[3397]! } - public var Channel_Management_AddModerator: String { return self._s[3398]! } - public var AutoDownloadSettings_MaxFileSize: String { return self._s[3399]! } - public var StickerPacksSettings_ShowStickersButton: String { return self._s[3400]! } - public var Wallet_Info_RefreshErrorNetworkText: String { return self._s[3401]! } - public var Theme_Colors_Background: String { return self._s[3402]! } - public var NotificationsSound_Hello: String { return self._s[3404]! } - public var SocksProxySetup_SavedProxies: String { return self._s[3405]! } - public var Channel_Stickers_Placeholder: String { return self._s[3407]! } + public var ChatList_UndoArchiveRevealedText: String { return self._s[3393]! } + public var GroupInfo_InviteLink_RevokeAlert_Text: String { return self._s[3394]! } + public var Conversation_SearchByName_Placeholder: String { return self._s[3395]! } + public var CreatePoll_AddOption: String { return self._s[3396]! } + public var GroupInfo_Permissions_SearchPlaceholder: String { return self._s[3397]! } + public var Group_UpgradeNoticeHeader: String { return self._s[3398]! } + public var Channel_Management_AddModerator: String { return self._s[3399]! } + public var AutoDownloadSettings_MaxFileSize: String { return self._s[3400]! } + public var StickerPacksSettings_ShowStickersButton: String { return self._s[3401]! } + public var Wallet_Info_RefreshErrorNetworkText: String { return self._s[3402]! } + public var Theme_Colors_Background: String { return self._s[3403]! } + public var NotificationsSound_Hello: String { return self._s[3405]! } + public var SocksProxySetup_SavedProxies: String { return self._s[3406]! } + public var Channel_Stickers_Placeholder: String { return self._s[3408]! } public func Login_EmailCodeBody(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3408]!, self._r[3408]!, [_0]) + return formatWithArgumentRanges(self._s[3409]!, self._r[3409]!, [_0]) } - public var PrivacyPolicy_DeclineDeclineAndDelete: String { return self._s[3409]! } - public var Channel_Management_AddModeratorHelp: String { return self._s[3410]! } - public var ContactInfo_BirthdayLabel: String { return self._s[3411]! } - public var ChangePhoneNumberCode_RequestingACall: String { return self._s[3412]! } - public var AutoDownloadSettings_Channels: String { return self._s[3413]! } - public var Passport_Language_mn: String { return self._s[3414]! } - public var Notifications_ResetAllNotificationsHelp: String { return self._s[3417]! } - public var GroupInfo_Permissions_SlowmodeValue_Off: String { return self._s[3418]! } - public var Passport_Language_ja: String { return self._s[3420]! } - public var Settings_About_Title: String { return self._s[3421]! } - public var Settings_NotificationsAndSounds: String { return self._s[3422]! } - public var ChannelInfo_DeleteGroup: String { return self._s[3423]! } - public var Settings_BlockedUsers: String { return self._s[3424]! } + public var PrivacyPolicy_DeclineDeclineAndDelete: String { return self._s[3410]! } + public var Channel_Management_AddModeratorHelp: String { return self._s[3411]! } + public var ContactInfo_BirthdayLabel: String { return self._s[3412]! } + public var ChangePhoneNumberCode_RequestingACall: String { return self._s[3413]! } + public var AutoDownloadSettings_Channels: String { return self._s[3414]! } + public var Passport_Language_mn: String { return self._s[3415]! } + public var Notifications_ResetAllNotificationsHelp: String { return self._s[3418]! } + public var GroupInfo_Permissions_SlowmodeValue_Off: String { return self._s[3419]! } + public var Passport_Language_ja: String { return self._s[3421]! } + public var Settings_About_Title: String { return self._s[3422]! } + public var Settings_NotificationsAndSounds: String { return self._s[3423]! } + public var ChannelInfo_DeleteGroup: String { return self._s[3424]! } + public var Settings_BlockedUsers: String { return self._s[3425]! } public func Time_MonthOfYear_m4(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3425]!, self._r[3425]!, [_0]) + return formatWithArgumentRanges(self._s[3426]!, self._r[3426]!, [_0]) } - public var EditTheme_Create_Preview_OutgoingText: String { return self._s[3426]! } - public var Wallet_Weekday_Today: String { return self._s[3427]! } - public var AutoDownloadSettings_PreloadVideo: String { return self._s[3428]! } - public var Widget_ApplicationLocked: String { return self._s[3429]! } - public var Passport_Address_AddResidentialAddress: String { return self._s[3430]! } - public var Channel_Username_Title: String { return self._s[3431]! } + public var EditTheme_Create_Preview_OutgoingText: String { return self._s[3427]! } + public var Wallet_Weekday_Today: String { return self._s[3428]! } + public var AutoDownloadSettings_PreloadVideo: String { return self._s[3429]! } + public var Widget_ApplicationLocked: String { return self._s[3430]! } + public var Passport_Address_AddResidentialAddress: String { return self._s[3431]! } + public var Channel_Username_Title: String { return self._s[3432]! } public func Notification_RemovedGroupPhoto(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3432]!, self._r[3432]!, [_0]) + return formatWithArgumentRanges(self._s[3433]!, self._r[3433]!, [_0]) } - public var AttachmentMenu_File: String { return self._s[3434]! } - public var AppleWatch_Title: String { return self._s[3435]! } - public var Activity_RecordingVideoMessage: String { return self._s[3436]! } + public var AttachmentMenu_File: String { return self._s[3435]! } + public var AppleWatch_Title: String { return self._s[3436]! } + public var Activity_RecordingVideoMessage: String { return self._s[3437]! } public func Channel_DiscussionGroup_PublicChannelLink(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3437]!, self._r[3437]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3438]!, self._r[3438]!, [_1, _2]) } - public var Theme_Colors_Messages: String { return self._s[3438]! } - public var Weekday_Saturday: String { return self._s[3439]! } - public var WallpaperPreview_SwipeColorsTopText: String { return self._s[3440]! } - public var Profile_CreateEncryptedChatError: String { return self._s[3441]! } - public var Common_Next: String { return self._s[3443]! } - public var Channel_Stickers_YourStickers: String { return self._s[3445]! } - public var Message_Theme: String { return self._s[3446]! } - public var Call_AudioRouteHeadphones: String { return self._s[3447]! } - public var TwoStepAuth_EnterPasswordForgot: String { return self._s[3449]! } - public var Watch_Contacts_NoResults: String { return self._s[3451]! } - public var PhotoEditor_TintTool: String { return self._s[3454]! } - public var LoginPassword_ResetAccount: String { return self._s[3456]! } - public var Settings_SavedMessages: String { return self._s[3457]! } - public var SettingsSearch_Synonyms_Appearance_Animations: String { return self._s[3458]! } - public var Bot_GenericSupportStatus: String { return self._s[3459]! } - public var StickerPack_Add: String { return self._s[3460]! } - public var Checkout_TotalAmount: String { return self._s[3461]! } - public var Your_cards_number_is_invalid: String { return self._s[3462]! } - public var SettingsSearch_Synonyms_Appearance_AutoNightTheme: String { return self._s[3463]! } - public var VoiceOver_Chat_VideoMessage: String { return self._s[3464]! } + public var Theme_Colors_Messages: String { return self._s[3439]! } + public var Weekday_Saturday: String { return self._s[3440]! } + public var WallpaperPreview_SwipeColorsTopText: String { return self._s[3441]! } + public var Profile_CreateEncryptedChatError: String { return self._s[3442]! } + public var Common_Next: String { return self._s[3444]! } + public var Channel_Stickers_YourStickers: String { return self._s[3446]! } + public var Message_Theme: String { return self._s[3447]! } + public var Call_AudioRouteHeadphones: String { return self._s[3448]! } + public var TwoStepAuth_EnterPasswordForgot: String { return self._s[3450]! } + public var Watch_Contacts_NoResults: String { return self._s[3452]! } + public var PhotoEditor_TintTool: String { return self._s[3455]! } + public var LoginPassword_ResetAccount: String { return self._s[3457]! } + public var Settings_SavedMessages: String { return self._s[3458]! } + public var SettingsSearch_Synonyms_Appearance_Animations: String { return self._s[3459]! } + public var Bot_GenericSupportStatus: String { return self._s[3460]! } + public var StickerPack_Add: String { return self._s[3461]! } + public var Checkout_TotalAmount: String { return self._s[3462]! } + public var Your_cards_number_is_invalid: String { return self._s[3463]! } + public var SettingsSearch_Synonyms_Appearance_AutoNightTheme: String { return self._s[3464]! } + public var VoiceOver_Chat_VideoMessage: String { return self._s[3465]! } public func ChangePhoneNumberCode_CallTimer(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3465]!, self._r[3465]!, [_0]) + return formatWithArgumentRanges(self._s[3466]!, self._r[3466]!, [_0]) } public func GroupPermission_AddedInfo(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3466]!, self._r[3466]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3467]!, self._r[3467]!, [_1, _2]) } - public var ChatSettings_ConnectionType_UseSocks5: String { return self._s[3467]! } + public var ChatSettings_ConnectionType_UseSocks5: String { return self._s[3468]! } public func PUSH_CHAT_PHOTO_EDITED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3469]!, self._r[3469]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3470]!, self._r[3470]!, [_1, _2]) } public func Conversation_RestrictedTextTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3470]!, self._r[3470]!, [_0]) + return formatWithArgumentRanges(self._s[3471]!, self._r[3471]!, [_0]) } - public var GroupInfo_InviteLink_ShareLink: String { return self._s[3471]! } - public var StickerPack_Share: String { return self._s[3472]! } - public var Passport_DeleteAddress: String { return self._s[3473]! } - public var Settings_Passport: String { return self._s[3474]! } - public var SharedMedia_EmptyFilesText: String { return self._s[3475]! } - public var Conversation_DeleteMessagesForMe: String { return self._s[3476]! } - public var PasscodeSettings_AutoLock_IfAwayFor_1hour: String { return self._s[3477]! } - public var Contacts_PermissionsText: String { return self._s[3478]! } - public var Group_Setup_HistoryVisible: String { return self._s[3479]! } - public var Wallet_Month_ShortDecember: String { return self._s[3481]! } - public var Channel_EditAdmin_PermissionEnabledByDefault: String { return self._s[3482]! } - public var Passport_Address_AddRentalAgreement: String { return self._s[3483]! } - public var SocksProxySetup_Title: String { return self._s[3484]! } - public var Notification_Mute1h: String { return self._s[3485]! } + public var GroupInfo_InviteLink_ShareLink: String { return self._s[3472]! } + public var StickerPack_Share: String { return self._s[3473]! } + public var Passport_DeleteAddress: String { return self._s[3474]! } + public var Settings_Passport: String { return self._s[3475]! } + public var SharedMedia_EmptyFilesText: String { return self._s[3476]! } + public var Conversation_DeleteMessagesForMe: String { return self._s[3477]! } + public var PasscodeSettings_AutoLock_IfAwayFor_1hour: String { return self._s[3478]! } + public var Contacts_PermissionsText: String { return self._s[3479]! } + public var Group_Setup_HistoryVisible: String { return self._s[3480]! } + public var Wallet_Month_ShortDecember: String { return self._s[3482]! } + public var Channel_EditAdmin_PermissionEnabledByDefault: String { return self._s[3483]! } + public var Passport_Address_AddRentalAgreement: String { return self._s[3484]! } + public var SocksProxySetup_Title: String { return self._s[3485]! } + public var Notification_Mute1h: String { return self._s[3486]! } public func Passport_Email_CodeHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3486]!, self._r[3486]!, [_0]) + return formatWithArgumentRanges(self._s[3487]!, self._r[3487]!, [_0]) } - public var NotificationSettings_ShowNotificationsAllAccountsInfoOff: String { return self._s[3487]! } + public var NotificationSettings_ShowNotificationsAllAccountsInfoOff: String { return self._s[3488]! } public func PUSH_PINNED_GEOLIVE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3488]!, self._r[3488]!, [_1]) + return formatWithArgumentRanges(self._s[3489]!, self._r[3489]!, [_1]) } - public var FastTwoStepSetup_PasswordSection: String { return self._s[3489]! } - public var NetworkUsageSettings_ResetStatsConfirmation: String { return self._s[3492]! } - public var InfoPlist_NSFaceIDUsageDescription: String { return self._s[3494]! } - public var DialogList_NoMessagesText: String { return self._s[3495]! } - public var Privacy_ContactsResetConfirmation: String { return self._s[3496]! } - public var Privacy_Calls_P2PHelp: String { return self._s[3497]! } - public var Channel_DiscussionGroup_SearchPlaceholder: String { return self._s[3499]! } - public var Your_cards_expiration_year_is_invalid: String { return self._s[3500]! } - public var Common_TakePhotoOrVideo: String { return self._s[3501]! } - public var Wallet_Words_Text: String { return self._s[3502]! } - public var Call_StatusBusy: String { return self._s[3503]! } - public var Conversation_PinnedMessage: String { return self._s[3504]! } - public var AutoDownloadSettings_VoiceMessagesTitle: String { return self._s[3505]! } - public var Wallet_Configuration_BlockchainNameChangedProceed: String { return self._s[3506]! } - public var TwoStepAuth_SetupPasswordConfirmFailed: String { return self._s[3507]! } - public var Undo_ChatCleared: String { return self._s[3508]! } - public var AppleWatch_ReplyPresets: String { return self._s[3509]! } - public var Passport_DiscardMessageDescription: String { return self._s[3511]! } - public var Login_NetworkError: String { return self._s[3512]! } + public var FastTwoStepSetup_PasswordSection: String { return self._s[3490]! } + public var NetworkUsageSettings_ResetStatsConfirmation: String { return self._s[3493]! } + public var InfoPlist_NSFaceIDUsageDescription: String { return self._s[3495]! } + public var DialogList_NoMessagesText: String { return self._s[3496]! } + public var Privacy_ContactsResetConfirmation: String { return self._s[3497]! } + public var Privacy_Calls_P2PHelp: String { return self._s[3498]! } + public var Channel_DiscussionGroup_SearchPlaceholder: String { return self._s[3500]! } + public var Your_cards_expiration_year_is_invalid: String { return self._s[3501]! } + public var Common_TakePhotoOrVideo: String { return self._s[3502]! } + public var Wallet_Words_Text: String { return self._s[3503]! } + public var Call_StatusBusy: String { return self._s[3504]! } + public var Conversation_PinnedMessage: String { return self._s[3505]! } + public var AutoDownloadSettings_VoiceMessagesTitle: String { return self._s[3506]! } + public var Wallet_Configuration_BlockchainNameChangedProceed: String { return self._s[3507]! } + public var TwoStepAuth_SetupPasswordConfirmFailed: String { return self._s[3508]! } + public var Undo_ChatCleared: String { return self._s[3509]! } + public var AppleWatch_ReplyPresets: String { return self._s[3510]! } + public var Passport_DiscardMessageDescription: String { return self._s[3512]! } + public var Login_NetworkError: String { return self._s[3513]! } public func Notification_PinnedRoundMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3513]!, self._r[3513]!, [_0]) - } - public func Channel_AdminLog_MessageRemovedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3514]!, self._r[3514]!, [_0]) } - public var SocksProxySetup_PasswordPlaceholder: String { return self._s[3515]! } - public var Wallet_WordCheck_ViewWords: String { return self._s[3517]! } - public var Login_ResetAccountProtected_LimitExceeded: String { return self._s[3518]! } + public func Channel_AdminLog_MessageRemovedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3515]!, self._r[3515]!, [_0]) + } + public var SocksProxySetup_PasswordPlaceholder: String { return self._s[3516]! } + public var Wallet_WordCheck_ViewWords: String { return self._s[3518]! } + public var Login_ResetAccountProtected_LimitExceeded: String { return self._s[3519]! } public func Watch_LastSeen_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3520]!, self._r[3520]!, [_0]) + return formatWithArgumentRanges(self._s[3521]!, self._r[3521]!, [_0]) } - public var Call_ConnectionErrorMessage: String { return self._s[3521]! } - public var VoiceOver_Chat_Music: String { return self._s[3522]! } - public var SettingsSearch_Synonyms_Notifications_MessageNotificationsSound: String { return self._s[3523]! } - public var Compose_GroupTokenListPlaceholder: String { return self._s[3525]! } - public var ConversationMedia_Title: String { return self._s[3526]! } - public var EncryptionKey_Title: String { return self._s[3528]! } - public var TwoStepAuth_EnterPasswordTitle: String { return self._s[3529]! } - public var Notification_Exceptions_AddException: String { return self._s[3530]! } - public var PrivacySettings_BlockedPeersEmpty: String { return self._s[3531]! } - public var Profile_MessageLifetime1m: String { return self._s[3532]! } + public var Call_ConnectionErrorMessage: String { return self._s[3522]! } + public var VoiceOver_Chat_Music: String { return self._s[3523]! } + public var SettingsSearch_Synonyms_Notifications_MessageNotificationsSound: String { return self._s[3524]! } + public var Compose_GroupTokenListPlaceholder: String { return self._s[3526]! } + public var ConversationMedia_Title: String { return self._s[3527]! } + public var EncryptionKey_Title: String { return self._s[3529]! } + public var TwoStepAuth_EnterPasswordTitle: String { return self._s[3530]! } + public var Notification_Exceptions_AddException: String { return self._s[3531]! } + public var PrivacySettings_BlockedPeersEmpty: String { return self._s[3532]! } + public var Profile_MessageLifetime1m: String { return self._s[3533]! } public func Channel_AdminLog_MessageUnkickedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3533]!, self._r[3533]!, [_1]) + return formatWithArgumentRanges(self._s[3534]!, self._r[3534]!, [_1]) } - public var Month_GenMay: String { return self._s[3534]! } + public var Month_GenMay: String { return self._s[3535]! } public func LiveLocationUpdated_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3535]!, self._r[3535]!, [_0]) + return formatWithArgumentRanges(self._s[3536]!, self._r[3536]!, [_0]) } - public var PeopleNearby_Users: String { return self._s[3536]! } - public var Wallet_Send_AddressInfo: String { return self._s[3537]! } - public var ChannelMembers_WhoCanAddMembersAllHelp: String { return self._s[3538]! } - public var AutoDownloadSettings_ResetSettings: String { return self._s[3539]! } + public var PeopleNearby_Users: String { return self._s[3537]! } + public var Wallet_Send_AddressInfo: String { return self._s[3538]! } + public var ChannelMembers_WhoCanAddMembersAllHelp: String { return self._s[3539]! } + public var AutoDownloadSettings_ResetSettings: String { return self._s[3540]! } public func Wallet_Updated_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3541]!, self._r[3541]!, [_0]) + return formatWithArgumentRanges(self._s[3542]!, self._r[3542]!, [_0]) } - public var Conversation_EmptyPlaceholder: String { return self._s[3542]! } - public var Passport_Address_AddPassportRegistration: String { return self._s[3543]! } - public var Notifications_ChannelNotificationsAlert: String { return self._s[3544]! } - public var ChatSettings_AutoDownloadUsingCellular: String { return self._s[3545]! } - public var Camera_TapAndHoldForVideo: String { return self._s[3546]! } - public var Channel_JoinChannel: String { return self._s[3548]! } - public var Appearance_Animations: String { return self._s[3551]! } + public var Conversation_EmptyPlaceholder: String { return self._s[3543]! } + public var Passport_Address_AddPassportRegistration: String { return self._s[3544]! } + public var Notifications_ChannelNotificationsAlert: String { return self._s[3545]! } + public var ChatSettings_AutoDownloadUsingCellular: String { return self._s[3546]! } + public var Camera_TapAndHoldForVideo: String { return self._s[3547]! } + public var Channel_JoinChannel: String { return self._s[3549]! } + public var Appearance_Animations: String { return self._s[3552]! } public func Notification_MessageLifetimeChanged(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3552]!, self._r[3552]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3553]!, self._r[3553]!, [_1, _2]) } - public var Stickers_GroupStickers: String { return self._s[3554]! } - public var Appearance_ShareTheme: String { return self._s[3555]! } - public var TwoFactorSetup_Hint_Placeholder: String { return self._s[3556]! } - public var ConvertToSupergroup_HelpTitle: String { return self._s[3558]! } - public var StickerPackActionInfo_RemovedTitle: String { return self._s[3559]! } - public var Passport_Address_Street: String { return self._s[3560]! } - public var Conversation_AddContact: String { return self._s[3561]! } - public var Login_PhonePlaceholder: String { return self._s[3562]! } - public var Channel_Members_InviteLink: String { return self._s[3564]! } - public var Bot_Stop: String { return self._s[3565]! } - public var SettingsSearch_Synonyms_Proxy_UseForCalls: String { return self._s[3567]! } - public var Notification_PassportValueAddress: String { return self._s[3568]! } - public var Month_ShortJuly: String { return self._s[3569]! } - public var Passport_Address_TypeTemporaryRegistrationUploadScan: String { return self._s[3570]! } - public var Channel_AdminLog_BanSendMedia: String { return self._s[3571]! } - public var Passport_Identity_ReverseSide: String { return self._s[3572]! } - public var Watch_Stickers_Recents: String { return self._s[3575]! } - public var PrivacyLastSeenSettings_EmpryUsersPlaceholder: String { return self._s[3577]! } - public var Map_SendThisLocation: String { return self._s[3578]! } + public var Stickers_GroupStickers: String { return self._s[3555]! } + public var Appearance_ShareTheme: String { return self._s[3556]! } + public var TwoFactorSetup_Hint_Placeholder: String { return self._s[3557]! } + public var ConvertToSupergroup_HelpTitle: String { return self._s[3559]! } + public var StickerPackActionInfo_RemovedTitle: String { return self._s[3560]! } + public var Passport_Address_Street: String { return self._s[3561]! } + public var Conversation_AddContact: String { return self._s[3562]! } + public var Login_PhonePlaceholder: String { return self._s[3563]! } + public var Channel_Members_InviteLink: String { return self._s[3565]! } + public var Bot_Stop: String { return self._s[3566]! } + public var SettingsSearch_Synonyms_Proxy_UseForCalls: String { return self._s[3568]! } + public var Notification_PassportValueAddress: String { return self._s[3569]! } + public var Month_ShortJuly: String { return self._s[3570]! } + public var Passport_Address_TypeTemporaryRegistrationUploadScan: String { return self._s[3571]! } + public var Channel_AdminLog_BanSendMedia: String { return self._s[3572]! } + public var Passport_Identity_ReverseSide: String { return self._s[3573]! } + public var Watch_Stickers_Recents: String { return self._s[3576]! } + public var PrivacyLastSeenSettings_EmpryUsersPlaceholder: String { return self._s[3578]! } + public var Map_SendThisLocation: String { return self._s[3579]! } public func Time_MonthOfYear_m1(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3579]!, self._r[3579]!, [_0]) - } - public func InviteText_SingleContact(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3580]!, self._r[3580]!, [_0]) } - public var ConvertToSupergroup_Note: String { return self._s[3581]! } - public var Wallet_Intro_NotNow: String { return self._s[3582]! } + public func InviteText_SingleContact(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3581]!, self._r[3581]!, [_0]) + } + public var ConvertToSupergroup_Note: String { return self._s[3582]! } + public var Wallet_Intro_NotNow: String { return self._s[3583]! } public func FileSize_MB(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3583]!, self._r[3583]!, [_0]) + return formatWithArgumentRanges(self._s[3584]!, self._r[3584]!, [_0]) } - public var NetworkUsageSettings_GeneralDataSection: String { return self._s[3584]! } + public var NetworkUsageSettings_GeneralDataSection: String { return self._s[3585]! } public func Compatibility_SecretMediaVersionTooLow(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3585]!, self._r[3585]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3586]!, self._r[3586]!, [_0, _1]) } - public var Login_CallRequestState3: String { return self._s[3587]! } - public var Wallpaper_SearchShort: String { return self._s[3588]! } - public var SettingsSearch_Synonyms_Appearance_ColorTheme: String { return self._s[3590]! } - public var PasscodeSettings_UnlockWithFaceId: String { return self._s[3591]! } - public var Channel_BotDoesntSupportGroups: String { return self._s[3592]! } + public var Login_CallRequestState3: String { return self._s[3588]! } + public var Wallpaper_SearchShort: String { return self._s[3589]! } + public var SettingsSearch_Synonyms_Appearance_ColorTheme: String { return self._s[3591]! } + public var PasscodeSettings_UnlockWithFaceId: String { return self._s[3592]! } + public var Channel_BotDoesntSupportGroups: String { return self._s[3593]! } public func PUSH_CHAT_MESSAGE_GEOLIVE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3593]!, self._r[3593]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3594]!, self._r[3594]!, [_1, _2]) } - public var Channel_AdminLogFilter_Title: String { return self._s[3594]! } - public var Appearance_ThemePreview_Chat_4_Text: String { return self._s[3596]! } - public var Notifications_GroupNotificationsExceptions: String { return self._s[3599]! } + public var Channel_AdminLogFilter_Title: String { return self._s[3595]! } + public var Appearance_ThemePreview_Chat_4_Text: String { return self._s[3597]! } + public var Notifications_GroupNotificationsExceptions: String { return self._s[3600]! } public func FileSize_B(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3600]!, self._r[3600]!, [_0]) + return formatWithArgumentRanges(self._s[3601]!, self._r[3601]!, [_0]) } - public var Passport_CorrectErrors: String { return self._s[3601]! } - public var VoiceOver_Chat_YourAnonymousPoll: String { return self._s[3602]! } + public var Passport_CorrectErrors: String { return self._s[3602]! } + public var VoiceOver_Chat_YourAnonymousPoll: String { return self._s[3603]! } public func Channel_MessageTitleUpdated(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3603]!, self._r[3603]!, [_0]) + return formatWithArgumentRanges(self._s[3604]!, self._r[3604]!, [_0]) } - public var Map_SendMyCurrentLocation: String { return self._s[3604]! } - public var Channel_DiscussionGroup: String { return self._s[3605]! } - public var TwoFactorSetup_Email_SkipConfirmationSkip: String { return self._s[3606]! } + public var Map_SendMyCurrentLocation: String { return self._s[3605]! } + public var Channel_DiscussionGroup: String { return self._s[3606]! } + public var TwoFactorSetup_Email_SkipConfirmationSkip: String { return self._s[3607]! } public func PUSH_PINNED_CONTACT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3607]!, self._r[3607]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3608]!, self._r[3608]!, [_1, _2]) } - public var SharedMedia_SearchNoResults: String { return self._s[3608]! } - public var Permissions_NotificationsText_v0: String { return self._s[3609]! } - public var Channel_EditAdmin_PermissionDeleteMessagesOfOthers: String { return self._s[3610]! } - public var Appearance_AppIcon: String { return self._s[3611]! } - public var Appearance_ThemePreview_ChatList_3_AuthorName: String { return self._s[3612]! } - public var LoginPassword_FloodError: String { return self._s[3613]! } - public var Wallet_Send_OwnAddressAlertProceed: String { return self._s[3615]! } - public var Group_Setup_HistoryHiddenHelp: String { return self._s[3616]! } + public var SharedMedia_SearchNoResults: String { return self._s[3609]! } + public var Permissions_NotificationsText_v0: String { return self._s[3610]! } + public var Channel_EditAdmin_PermissionDeleteMessagesOfOthers: String { return self._s[3611]! } + public var Appearance_AppIcon: String { return self._s[3612]! } + public var Appearance_ThemePreview_ChatList_3_AuthorName: String { return self._s[3613]! } + public var LoginPassword_FloodError: String { return self._s[3614]! } + public var Wallet_Send_OwnAddressAlertProceed: String { return self._s[3616]! } + public var Group_Setup_HistoryHiddenHelp: String { return self._s[3617]! } public func TwoStepAuth_PendingEmailHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3617]!, self._r[3617]!, [_0]) + return formatWithArgumentRanges(self._s[3618]!, self._r[3618]!, [_0]) } - public var Passport_Language_bn: String { return self._s[3618]! } + public var Passport_Language_bn: String { return self._s[3619]! } public func DialogList_SingleUploadingPhotoSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3619]!, self._r[3619]!, [_0]) + return formatWithArgumentRanges(self._s[3620]!, self._r[3620]!, [_0]) } - public var ChatList_Context_Pin: String { return self._s[3620]! } + public var ChatList_Context_Pin: String { return self._s[3621]! } public func Notification_PinnedAudioMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3621]!, self._r[3621]!, [_0]) - } - public func Channel_AdminLog_MessageChangedGroupStickerPack(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3622]!, self._r[3622]!, [_0]) } - public var Wallet_Navigation_Close: String { return self._s[3623]! } - public var GroupInfo_InvitationLinkGroupFull: String { return self._s[3627]! } - public var Group_EditAdmin_PermissionChangeInfo: String { return self._s[3629]! } - public var Wallet_Month_GenDecember: String { return self._s[3630]! } - public var Contacts_PermissionsAllow: String { return self._s[3631]! } - public var ReportPeer_ReasonCopyright: String { return self._s[3632]! } - public var Channel_EditAdmin_PermissinAddAdminOn: String { return self._s[3633]! } - public var WallpaperPreview_Pattern: String { return self._s[3634]! } - public var Paint_Duplicate: String { return self._s[3635]! } - public var Passport_Address_Country: String { return self._s[3636]! } - public var Notification_RenamedChannel: String { return self._s[3638]! } - public var ChatList_Context_Unmute: String { return self._s[3639]! } - public var CheckoutInfo_ErrorPostcodeInvalid: String { return self._s[3640]! } - public var Group_MessagePhotoUpdated: String { return self._s[3641]! } - public var Channel_BanUser_PermissionSendMedia: String { return self._s[3642]! } - public var Conversation_ContextMenuBan: String { return self._s[3643]! } - public var TwoStepAuth_EmailSent: String { return self._s[3644]! } - public var MessagePoll_NoVotes: String { return self._s[3645]! } - public var Wallet_Send_ErrorNotEnoughFundsTitle: String { return self._s[3646]! } - public var Passport_Language_is: String { return self._s[3648]! } - public var PeopleNearby_UsersEmpty: String { return self._s[3650]! } - public var Tour_Text5: String { return self._s[3651]! } + public func Channel_AdminLog_MessageChangedGroupStickerPack(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3623]!, self._r[3623]!, [_0]) + } + public var Wallet_Navigation_Close: String { return self._s[3624]! } + public var GroupInfo_InvitationLinkGroupFull: String { return self._s[3628]! } + public var Group_EditAdmin_PermissionChangeInfo: String { return self._s[3630]! } + public var Wallet_Month_GenDecember: String { return self._s[3631]! } + public var Contacts_PermissionsAllow: String { return self._s[3632]! } + public var ReportPeer_ReasonCopyright: String { return self._s[3633]! } + public var Channel_EditAdmin_PermissinAddAdminOn: String { return self._s[3634]! } + public var WallpaperPreview_Pattern: String { return self._s[3635]! } + public var Paint_Duplicate: String { return self._s[3636]! } + public var Passport_Address_Country: String { return self._s[3637]! } + public var Notification_RenamedChannel: String { return self._s[3639]! } + public var ChatList_Context_Unmute: String { return self._s[3640]! } + public var CheckoutInfo_ErrorPostcodeInvalid: String { return self._s[3641]! } + public var Group_MessagePhotoUpdated: String { return self._s[3642]! } + public var Channel_BanUser_PermissionSendMedia: String { return self._s[3643]! } + public var Conversation_ContextMenuBan: String { return self._s[3644]! } + public var TwoStepAuth_EmailSent: String { return self._s[3645]! } + public var MessagePoll_NoVotes: String { return self._s[3646]! } + public var Wallet_Send_ErrorNotEnoughFundsTitle: String { return self._s[3647]! } + public var Passport_Language_is: String { return self._s[3649]! } + public var PeopleNearby_UsersEmpty: String { return self._s[3651]! } + public var Tour_Text5: String { return self._s[3652]! } public func Call_GroupFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3654]!, self._r[3654]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3655]!, self._r[3655]!, [_1, _2]) } - public var Undo_SecretChatDeleted: String { return self._s[3655]! } - public var SocksProxySetup_ShareQRCode: String { return self._s[3656]! } + public var Undo_SecretChatDeleted: String { return self._s[3656]! } + public var SocksProxySetup_ShareQRCode: String { return self._s[3657]! } public func VoiceOver_Chat_Size(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3657]!, self._r[3657]!, [_0]) + return formatWithArgumentRanges(self._s[3658]!, self._r[3658]!, [_0]) } - public var Forward_ErrorDisabledForChat: String { return self._s[3658]! } - public var LogoutOptions_ChangePhoneNumberText: String { return self._s[3659]! } - public var Paint_Edit: String { return self._s[3661]! } - public var ScheduledMessages_ReminderNotification: String { return self._s[3663]! } - public var Undo_DeletedGroup: String { return self._s[3665]! } - public var LoginPassword_ForgotPassword: String { return self._s[3666]! } - public var Wallet_WordImport_IncorrectTitle: String { return self._s[3667]! } - public var GroupInfo_GroupNamePlaceholder: String { return self._s[3668]! } + public var Forward_ErrorDisabledForChat: String { return self._s[3659]! } + public var LogoutOptions_ChangePhoneNumberText: String { return self._s[3660]! } + public var Paint_Edit: String { return self._s[3662]! } + public var ScheduledMessages_ReminderNotification: String { return self._s[3664]! } + public var Undo_DeletedGroup: String { return self._s[3666]! } + public var LoginPassword_ForgotPassword: String { return self._s[3667]! } + public var Wallet_WordImport_IncorrectTitle: String { return self._s[3668]! } + public var GroupInfo_GroupNamePlaceholder: String { return self._s[3669]! } public func Notification_Kicked(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3669]!, self._r[3669]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3670]!, self._r[3670]!, [_0, _1]) } - public var AppWallet_TransactionInfo_FeeInfoURL: String { return self._s[3670]! } - public var Conversation_InputTextCaptionPlaceholder: String { return self._s[3671]! } - public var AutoDownloadSettings_VideoMessagesTitle: String { return self._s[3672]! } - public var Passport_Language_uz: String { return self._s[3673]! } - public var Conversation_PinMessageAlertGroup: String { return self._s[3674]! } - public var SettingsSearch_Synonyms_Privacy_GroupsAndChannels: String { return self._s[3675]! } - public var Map_StopLiveLocation: String { return self._s[3677]! } - public var VoiceOver_MessageContextSend: String { return self._s[3679]! } - public var PasscodeSettings_Help: String { return self._s[3680]! } - public var NotificationsSound_Input: String { return self._s[3681]! } - public var Share_Title: String { return self._s[3684]! } - public var LogoutOptions_Title: String { return self._s[3685]! } - public var Wallet_Send_AddressText: String { return self._s[3686]! } - public var Login_TermsOfServiceAgree: String { return self._s[3687]! } - public var Compose_NewEncryptedChatTitle: String { return self._s[3688]! } - public var Channel_AdminLog_TitleSelectedEvents: String { return self._s[3689]! } - public var Channel_EditAdmin_PermissionEditMessages: String { return self._s[3690]! } - public var EnterPasscode_EnterTitle: String { return self._s[3691]! } + public var AppWallet_TransactionInfo_FeeInfoURL: String { return self._s[3671]! } + public var Conversation_InputTextCaptionPlaceholder: String { return self._s[3672]! } + public var AutoDownloadSettings_VideoMessagesTitle: String { return self._s[3673]! } + public var Passport_Language_uz: String { return self._s[3674]! } + public var Conversation_PinMessageAlertGroup: String { return self._s[3675]! } + public var SettingsSearch_Synonyms_Privacy_GroupsAndChannels: String { return self._s[3676]! } + public var Map_StopLiveLocation: String { return self._s[3678]! } + public var VoiceOver_MessageContextSend: String { return self._s[3680]! } + public var PasscodeSettings_Help: String { return self._s[3681]! } + public var NotificationsSound_Input: String { return self._s[3682]! } + public var Share_Title: String { return self._s[3685]! } + public var LogoutOptions_Title: String { return self._s[3686]! } + public var Wallet_Send_AddressText: String { return self._s[3687]! } + public var Login_TermsOfServiceAgree: String { return self._s[3688]! } + public var Compose_NewEncryptedChatTitle: String { return self._s[3689]! } + public var Channel_AdminLog_TitleSelectedEvents: String { return self._s[3690]! } + public var Channel_EditAdmin_PermissionEditMessages: String { return self._s[3691]! } + public var EnterPasscode_EnterTitle: String { return self._s[3692]! } public func Call_PrivacyErrorMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3692]!, self._r[3692]!, [_0]) + return formatWithArgumentRanges(self._s[3693]!, self._r[3693]!, [_0]) } - public var Settings_CopyPhoneNumber: String { return self._s[3693]! } - public var Conversation_AddToContacts: String { return self._s[3694]! } + public var Settings_CopyPhoneNumber: String { return self._s[3694]! } + public var Conversation_AddToContacts: String { return self._s[3695]! } public func VoiceOver_Chat_ReplyFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3695]!, self._r[3695]!, [_0]) + return formatWithArgumentRanges(self._s[3696]!, self._r[3696]!, [_0]) } - public var NotificationsSound_Keys: String { return self._s[3696]! } + public var NotificationsSound_Keys: String { return self._s[3697]! } public func Call_ParticipantVersionOutdatedError(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3697]!, self._r[3697]!, [_0]) + return formatWithArgumentRanges(self._s[3698]!, self._r[3698]!, [_0]) } - public var Notification_MessageLifetime1w: String { return self._s[3698]! } - public var Message_Video: String { return self._s[3699]! } - public var AutoDownloadSettings_CellularTitle: String { return self._s[3700]! } + public var Notification_MessageLifetime1w: String { return self._s[3699]! } + public var Message_Video: String { return self._s[3700]! } + public var AutoDownloadSettings_CellularTitle: String { return self._s[3701]! } public func PUSH_CHANNEL_MESSAGE_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3701]!, self._r[3701]!, [_1]) + return formatWithArgumentRanges(self._s[3702]!, self._r[3702]!, [_1]) } - public var Wallet_Receive_AmountInfo: String { return self._s[3704]! } + public var Wallet_Receive_AmountInfo: String { return self._s[3705]! } public func Notification_JoinedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3705]!, self._r[3705]!, [_0]) - } - public func PrivacySettings_LastSeenContactsPlus(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3706]!, self._r[3706]!, [_0]) } - public var Passport_Language_mk: String { return self._s[3707]! } - public func Wallet_Time_PreciseDate_m2(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3708]!, self._r[3708]!, [_1, _2, _3]) + public func PrivacySettings_LastSeenContactsPlus(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3707]!, self._r[3707]!, [_0]) } - public var CreatePoll_CancelConfirmation: String { return self._s[3709]! } - public var MessagePoll_LabelAnonymousQuiz: String { return self._s[3710]! } - public var Conversation_SilentBroadcastTooltipOn: String { return self._s[3712]! } - public var PrivacyPolicy_Decline: String { return self._s[3713]! } - public var Passport_Identity_DoesNotExpire: String { return self._s[3714]! } - public var Channel_AdminLogFilter_EventsRestrictions: String { return self._s[3715]! } - public var AuthSessions_AddDeviceIntro_Action: String { return self._s[3716]! } - public var Permissions_SiriAllow_v0: String { return self._s[3718]! } - public var Wallet_Month_ShortAugust: String { return self._s[3719]! } - public var Appearance_ThemeCarouselNight: String { return self._s[3720]! } + public var Passport_Language_mk: String { return self._s[3708]! } + public func Wallet_Time_PreciseDate_m2(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3709]!, self._r[3709]!, [_1, _2, _3]) + } + public var CreatePoll_CancelConfirmation: String { return self._s[3710]! } + public var MessagePoll_LabelAnonymousQuiz: String { return self._s[3711]! } + public var Conversation_SilentBroadcastTooltipOn: String { return self._s[3713]! } + public var PrivacyPolicy_Decline: String { return self._s[3714]! } + public var Passport_Identity_DoesNotExpire: String { return self._s[3715]! } + public var Channel_AdminLogFilter_EventsRestrictions: String { return self._s[3716]! } + public var AuthSessions_AddDeviceIntro_Action: String { return self._s[3717]! } + public var Permissions_SiriAllow_v0: String { return self._s[3719]! } + public var Wallet_Month_ShortAugust: String { return self._s[3720]! } + public var Appearance_ThemeCarouselNight: String { return self._s[3721]! } public func LOCAL_CHAT_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3721]!, self._r[3721]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[3722]!, self._r[3722]!, [_1, "\(_2)"]) } public func Notification_RenamedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3722]!, self._r[3722]!, [_0]) + return formatWithArgumentRanges(self._s[3723]!, self._r[3723]!, [_0]) } - public var Paint_Regular: String { return self._s[3723]! } - public var ChatSettings_AutoDownloadReset: String { return self._s[3724]! } - public var SocksProxySetup_ShareLink: String { return self._s[3725]! } - public var Wallet_Qr_Title: String { return self._s[3726]! } - public var BlockedUsers_SelectUserTitle: String { return self._s[3727]! } - public var VoiceOver_Chat_RecordModeVoiceMessage: String { return self._s[3729]! } - public var Wallet_Settings_Configuration: String { return self._s[3730]! } - public var GroupInfo_InviteByLink: String { return self._s[3731]! } - public var MessageTimer_Custom: String { return self._s[3732]! } - public var UserInfo_NotificationsDefaultEnabled: String { return self._s[3733]! } - public var Conversation_StopQuizConfirmationTitle: String { return self._s[3734]! } - public var Passport_Address_TypeTemporaryRegistration: String { return self._s[3736]! } - public var Conversation_SendMessage_SetReminder: String { return self._s[3737]! } - public var VoiceOver_Chat_Selected: String { return self._s[3738]! } - public var ChatSettings_AutoDownloadUsingWiFi: String { return self._s[3739]! } - public var Channel_Username_InvalidTaken: String { return self._s[3740]! } - public var Conversation_ClousStorageInfo_Description3: String { return self._s[3741]! } - public var Wallet_WordCheck_TryAgain: String { return self._s[3742]! } - public var Wallet_Info_TransactionPendingHeader: String { return self._s[3743]! } - public var Settings_ChatBackground: String { return self._s[3744]! } - public var Channel_Subscribers_Title: String { return self._s[3745]! } - public var Wallet_Receive_InvoiceUrlHeader: String { return self._s[3746]! } - public var ApplyLanguage_ChangeLanguageTitle: String { return self._s[3747]! } - public var Watch_ConnectionDescription: String { return self._s[3748]! } - public var OldChannels_NoticeText: String { return self._s[3751]! } - public var Wallet_Configuration_ApplyErrorTitle: String { return self._s[3752]! } - public var IntentsSettings_SuggestBy: String { return self._s[3754]! } - public var Theme_ThemeChangedText: String { return self._s[3755]! } - public var ChatList_ArchivedChatsTitle: String { return self._s[3756]! } - public var Wallpaper_ResetWallpapers: String { return self._s[3757]! } - public var Wallet_Send_TransactionInProgress: String { return self._s[3758]! } - public var EditProfile_Title: String { return self._s[3759]! } - public var NotificationsSound_Bamboo: String { return self._s[3761]! } - public var Channel_AdminLog_MessagePreviousMessage: String { return self._s[3763]! } - public var Login_SmsRequestState2: String { return self._s[3764]! } - public var Passport_Language_ar: String { return self._s[3765]! } + public var Paint_Regular: String { return self._s[3724]! } + public var ChatSettings_AutoDownloadReset: String { return self._s[3725]! } + public var SocksProxySetup_ShareLink: String { return self._s[3726]! } + public var Wallet_Qr_Title: String { return self._s[3727]! } + public var BlockedUsers_SelectUserTitle: String { return self._s[3728]! } + public var VoiceOver_Chat_RecordModeVoiceMessage: String { return self._s[3730]! } + public var Wallet_Settings_Configuration: String { return self._s[3731]! } + public var GroupInfo_InviteByLink: String { return self._s[3732]! } + public var MessageTimer_Custom: String { return self._s[3733]! } + public var UserInfo_NotificationsDefaultEnabled: String { return self._s[3734]! } + public var Conversation_StopQuizConfirmationTitle: String { return self._s[3735]! } + public var Passport_Address_TypeTemporaryRegistration: String { return self._s[3737]! } + public var Conversation_SendMessage_SetReminder: String { return self._s[3738]! } + public var VoiceOver_Chat_Selected: String { return self._s[3739]! } + public var ChatSettings_AutoDownloadUsingWiFi: String { return self._s[3740]! } + public var Channel_Username_InvalidTaken: String { return self._s[3741]! } + public var Conversation_ClousStorageInfo_Description3: String { return self._s[3742]! } + public var Wallet_WordCheck_TryAgain: String { return self._s[3743]! } + public var Wallet_Info_TransactionPendingHeader: String { return self._s[3744]! } + public var Settings_ChatBackground: String { return self._s[3745]! } + public var Channel_Subscribers_Title: String { return self._s[3746]! } + public var Wallet_Receive_InvoiceUrlHeader: String { return self._s[3747]! } + public var ApplyLanguage_ChangeLanguageTitle: String { return self._s[3748]! } + public var Watch_ConnectionDescription: String { return self._s[3749]! } + public var OldChannels_NoticeText: String { return self._s[3752]! } + public var Wallet_Configuration_ApplyErrorTitle: String { return self._s[3753]! } + public var IntentsSettings_SuggestBy: String { return self._s[3755]! } + public var Theme_ThemeChangedText: String { return self._s[3756]! } + public var ChatList_ArchivedChatsTitle: String { return self._s[3757]! } + public var Wallpaper_ResetWallpapers: String { return self._s[3758]! } + public var Wallet_Send_TransactionInProgress: String { return self._s[3759]! } + public var EditProfile_Title: String { return self._s[3760]! } + public var NotificationsSound_Bamboo: String { return self._s[3762]! } + public var Channel_AdminLog_MessagePreviousMessage: String { return self._s[3764]! } + public var Login_SmsRequestState2: String { return self._s[3765]! } + public var Passport_Language_ar: String { return self._s[3766]! } public func Message_AuthorPinnedGame(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3766]!, self._r[3766]!, [_0]) + return formatWithArgumentRanges(self._s[3767]!, self._r[3767]!, [_0]) } - public var SettingsSearch_Synonyms_EditProfile_Title: String { return self._s[3767]! } - public var Wallet_Created_Text: String { return self._s[3768]! } - public var Conversation_MessageDialogEdit: String { return self._s[3770]! } - public var Wallet_Created_Proceed: String { return self._s[3771]! } - public var Wallet_Words_Done: String { return self._s[3772]! } - public var VoiceOver_Media_PlaybackPause: String { return self._s[3773]! } + public var SettingsSearch_Synonyms_EditProfile_Title: String { return self._s[3768]! } + public var Wallet_Created_Text: String { return self._s[3769]! } + public var Conversation_MessageDialogEdit: String { return self._s[3771]! } + public var Wallet_Created_Proceed: String { return self._s[3772]! } + public var Wallet_Words_Done: String { return self._s[3773]! } + public var VoiceOver_Media_PlaybackPause: String { return self._s[3774]! } public func PUSH_AUTH_UNKNOWN(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3774]!, self._r[3774]!, [_1]) + return formatWithArgumentRanges(self._s[3775]!, self._r[3775]!, [_1]) } - public var Common_Close: String { return self._s[3775]! } - public var GroupInfo_PublicLink: String { return self._s[3776]! } - public var Channel_OwnershipTransfer_ErrorPrivacyRestricted: String { return self._s[3777]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsPreview: String { return self._s[3778]! } + public var Common_Close: String { return self._s[3776]! } + public var GroupInfo_PublicLink: String { return self._s[3777]! } + public var Channel_OwnershipTransfer_ErrorPrivacyRestricted: String { return self._s[3778]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsPreview: String { return self._s[3779]! } public func Channel_AdminLog_MessageToggleInvitesOff(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3782]!, self._r[3782]!, [_0]) + return formatWithArgumentRanges(self._s[3783]!, self._r[3783]!, [_0]) } - public var UserInfo_About_Placeholder: String { return self._s[3783]! } + public var UserInfo_About_Placeholder: String { return self._s[3784]! } public func Conversation_FileHowToText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3784]!, self._r[3784]!, [_0]) + return formatWithArgumentRanges(self._s[3785]!, self._r[3785]!, [_0]) } - public var GroupInfo_Permissions_SectionTitle: String { return self._s[3785]! } - public var Channel_Info_Banned: String { return self._s[3787]! } + public var GroupInfo_Permissions_SectionTitle: String { return self._s[3786]! } + public var Channel_Info_Banned: String { return self._s[3788]! } public func Time_MonthOfYear_m11(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3788]!, self._r[3788]!, [_0]) + return formatWithArgumentRanges(self._s[3789]!, self._r[3789]!, [_0]) } - public var Appearance_Other: String { return self._s[3789]! } - public var Passport_Language_my: String { return self._s[3790]! } - public var Group_Setup_BasicHistoryHiddenHelp: String { return self._s[3791]! } + public var Appearance_Other: String { return self._s[3790]! } + public var Passport_Language_my: String { return self._s[3791]! } + public var Group_Setup_BasicHistoryHiddenHelp: String { return self._s[3792]! } public func Time_PreciseDate_m9(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3792]!, self._r[3792]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3793]!, self._r[3793]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_Privacy_PasscodeAndFaceId: String { return self._s[3793]! } - public var IntentsSettings_SuggestedAndSpotlightChatsInfo: String { return self._s[3794]! } - public var Preview_CopyAddress: String { return self._s[3795]! } + public var SettingsSearch_Synonyms_Privacy_PasscodeAndFaceId: String { return self._s[3794]! } + public var IntentsSettings_SuggestedAndSpotlightChatsInfo: String { return self._s[3795]! } + public var Preview_CopyAddress: String { return self._s[3796]! } public func DialogList_SinglePlayingGameSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3796]!, self._r[3796]!, [_0]) + return formatWithArgumentRanges(self._s[3797]!, self._r[3797]!, [_0]) } - public var KeyCommand_JumpToPreviousChat: String { return self._s[3797]! } - public var UserInfo_BotSettings: String { return self._s[3798]! } - public var LiveLocation_MenuStopAll: String { return self._s[3800]! } - public var Passport_PasswordCreate: String { return self._s[3801]! } - public var StickerSettings_MaskContextInfo: String { return self._s[3802]! } - public var Message_PinnedLocationMessage: String { return self._s[3803]! } - public var Map_Satellite: String { return self._s[3804]! } - public var Watch_Message_Unsupported: String { return self._s[3805]! } - public var Username_TooManyPublicUsernamesError: String { return self._s[3806]! } - public var TwoStepAuth_EnterPasswordInvalid: String { return self._s[3807]! } + public var KeyCommand_JumpToPreviousChat: String { return self._s[3798]! } + public var UserInfo_BotSettings: String { return self._s[3799]! } + public var LiveLocation_MenuStopAll: String { return self._s[3801]! } + public var Passport_PasswordCreate: String { return self._s[3802]! } + public var StickerSettings_MaskContextInfo: String { return self._s[3803]! } + public var Message_PinnedLocationMessage: String { return self._s[3804]! } + public var Map_Satellite: String { return self._s[3805]! } + public var Watch_Message_Unsupported: String { return self._s[3806]! } + public var Username_TooManyPublicUsernamesError: String { return self._s[3807]! } + public var TwoStepAuth_EnterPasswordInvalid: String { return self._s[3808]! } public func Notification_PinnedTextMessage(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3808]!, self._r[3808]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3809]!, self._r[3809]!, [_0, _1]) } public func Conversation_OpenBotLinkText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3809]!, self._r[3809]!, [_0]) + return formatWithArgumentRanges(self._s[3810]!, self._r[3810]!, [_0]) } - public var Wallet_WordImport_Continue: String { return self._s[3810]! } + public var Wallet_WordImport_Continue: String { return self._s[3811]! } public func TwoFactorSetup_EmailVerification_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3811]!, self._r[3811]!, [_0]) + return formatWithArgumentRanges(self._s[3812]!, self._r[3812]!, [_0]) } - public var Notifications_ChannelNotificationsHelp: String { return self._s[3812]! } - public var Privacy_Calls_P2PContacts: String { return self._s[3813]! } - public var NotificationsSound_None: String { return self._s[3814]! } - public var Wallet_TransactionInfo_StorageFeeHeader: String { return self._s[3815]! } - public var Channel_DiscussionGroup_UnlinkGroup: String { return self._s[3817]! } - public var AccessDenied_VoiceMicrophone: String { return self._s[3818]! } + public var Notifications_ChannelNotificationsHelp: String { return self._s[3813]! } + public var Privacy_Calls_P2PContacts: String { return self._s[3814]! } + public var NotificationsSound_None: String { return self._s[3815]! } + public var Wallet_TransactionInfo_StorageFeeHeader: String { return self._s[3816]! } + public var Channel_DiscussionGroup_UnlinkGroup: String { return self._s[3818]! } + public var AccessDenied_VoiceMicrophone: String { return self._s[3819]! } public func ApplyLanguage_ChangeLanguageAlreadyActive(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3819]!, self._r[3819]!, [_1]) + return formatWithArgumentRanges(self._s[3820]!, self._r[3820]!, [_1]) } - public var Cache_Indexing: String { return self._s[3820]! } - public var DialogList_RecentTitlePeople: String { return self._s[3822]! } - public var DialogList_EncryptionRejected: String { return self._s[3823]! } - public var GroupInfo_Administrators: String { return self._s[3824]! } - public var Passport_ScanPassportHelp: String { return self._s[3825]! } - public var Application_Name: String { return self._s[3826]! } - public var Channel_AdminLogFilter_ChannelEventsInfo: String { return self._s[3827]! } - public var Appearance_ThemeCarouselDay: String { return self._s[3829]! } - public var Passport_Identity_TranslationHelp: String { return self._s[3830]! } + public var Cache_Indexing: String { return self._s[3821]! } + public var DialogList_RecentTitlePeople: String { return self._s[3823]! } + public var DialogList_EncryptionRejected: String { return self._s[3824]! } + public var GroupInfo_Administrators: String { return self._s[3825]! } + public var Passport_ScanPassportHelp: String { return self._s[3826]! } + public var Application_Name: String { return self._s[3827]! } + public var Channel_AdminLogFilter_ChannelEventsInfo: String { return self._s[3828]! } + public var Appearance_ThemeCarouselDay: String { return self._s[3830]! } + public var Passport_Identity_TranslationHelp: String { return self._s[3831]! } public func VoiceOver_Chat_VideoMessageFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3831]!, self._r[3831]!, [_0]) - } - public func Notification_JoinedGroupByLink(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3832]!, self._r[3832]!, [_0]) } - public func DialogList_EncryptedChatStartedOutgoing(_ _0: String) -> (String, [(Int, NSRange)]) { + public func Notification_JoinedGroupByLink(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3833]!, self._r[3833]!, [_0]) } - public var Channel_EditAdmin_PermissionDeleteMessages: String { return self._s[3834]! } - public var Privacy_ChatsTitle: String { return self._s[3835]! } - public var DialogList_ClearHistoryConfirmation: String { return self._s[3836]! } - public var SettingsSearch_Synonyms_Data_Storage_ClearCache: String { return self._s[3837]! } - public var Watch_Suggestion_HoldOn: String { return self._s[3838]! } - public var Group_EditAdmin_TransferOwnership: String { return self._s[3839]! } - public var WebBrowser_Title: String { return self._s[3840]! } - public var Group_LinkedChannel: String { return self._s[3841]! } - public var VoiceOver_Chat_SeenByRecipient: String { return self._s[3842]! } - public var SocksProxySetup_RequiredCredentials: String { return self._s[3843]! } - public var Passport_Address_TypeRentalAgreementUploadScan: String { return self._s[3844]! } - public var Appearance_TextSize_UseSystem: String { return self._s[3845]! } - public var TwoStepAuth_EmailSkipAlert: String { return self._s[3846]! } - public var ScheduledMessages_RemindersTitle: String { return self._s[3848]! } - public var Channel_Setup_TypePublic: String { return self._s[3850]! } + public func DialogList_EncryptedChatStartedOutgoing(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3834]!, self._r[3834]!, [_0]) + } + public var Channel_EditAdmin_PermissionDeleteMessages: String { return self._s[3835]! } + public var Privacy_ChatsTitle: String { return self._s[3836]! } + public var DialogList_ClearHistoryConfirmation: String { return self._s[3837]! } + public var SettingsSearch_Synonyms_Data_Storage_ClearCache: String { return self._s[3838]! } + public var Watch_Suggestion_HoldOn: String { return self._s[3839]! } + public var Group_EditAdmin_TransferOwnership: String { return self._s[3840]! } + public var WebBrowser_Title: String { return self._s[3841]! } + public var Group_LinkedChannel: String { return self._s[3842]! } + public var VoiceOver_Chat_SeenByRecipient: String { return self._s[3843]! } + public var SocksProxySetup_RequiredCredentials: String { return self._s[3844]! } + public var Passport_Address_TypeRentalAgreementUploadScan: String { return self._s[3845]! } + public var Appearance_TextSize_UseSystem: String { return self._s[3846]! } + public var TwoStepAuth_EmailSkipAlert: String { return self._s[3847]! } + public var ScheduledMessages_RemindersTitle: String { return self._s[3849]! } + public var Channel_Setup_TypePublic: String { return self._s[3851]! } public func Channel_AdminLog_MessageToggleInvitesOn(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3851]!, self._r[3851]!, [_0]) + return formatWithArgumentRanges(self._s[3852]!, self._r[3852]!, [_0]) } - public var Channel_TypeSetup_Title: String { return self._s[3853]! } - public var MessagePoll_ViewResults: String { return self._s[3854]! } - public var Map_OpenInMaps: String { return self._s[3856]! } + public var Channel_TypeSetup_Title: String { return self._s[3854]! } + public var MessagePoll_ViewResults: String { return self._s[3855]! } + public var Map_OpenInMaps: String { return self._s[3857]! } public func PUSH_PINNED_NOTEXT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3857]!, self._r[3857]!, [_1]) + return formatWithArgumentRanges(self._s[3858]!, self._r[3858]!, [_1]) } - public var NotificationsSound_Tremolo: String { return self._s[3859]! } + public var NotificationsSound_Tremolo: String { return self._s[3860]! } public func Date_ChatDateHeaderYear(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3860]!, self._r[3860]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3861]!, self._r[3861]!, [_1, _2, _3]) } - public var ConversationProfile_UnknownAddMemberError: String { return self._s[3861]! } - public var Channel_OwnershipTransfer_PasswordPlaceholder: String { return self._s[3862]! } - public var Passport_PasswordHelp: String { return self._s[3863]! } - public var Login_CodeExpiredError: String { return self._s[3864]! } - public var Channel_EditAdmin_PermissionChangeInfo: String { return self._s[3865]! } - public var Conversation_TitleUnmute: String { return self._s[3866]! } - public var Passport_Identity_ScansHelp: String { return self._s[3867]! } - public var Passport_Language_lo: String { return self._s[3868]! } - public var Camera_FlashAuto: String { return self._s[3869]! } - public var Conversation_OpenBotLinkOpen: String { return self._s[3870]! } - public var Common_Cancel: String { return self._s[3871]! } - public var DialogList_SavedMessagesTooltip: String { return self._s[3872]! } - public var TwoStepAuth_SetupPasswordTitle: String { return self._s[3873]! } - public var Appearance_TintAllColors: String { return self._s[3874]! } + public var ConversationProfile_UnknownAddMemberError: String { return self._s[3862]! } + public var Channel_OwnershipTransfer_PasswordPlaceholder: String { return self._s[3863]! } + public var Passport_PasswordHelp: String { return self._s[3864]! } + public var Login_CodeExpiredError: String { return self._s[3865]! } + public var Channel_EditAdmin_PermissionChangeInfo: String { return self._s[3866]! } + public var Conversation_TitleUnmute: String { return self._s[3867]! } + public var Passport_Identity_ScansHelp: String { return self._s[3868]! } + public var Passport_Language_lo: String { return self._s[3869]! } + public var Camera_FlashAuto: String { return self._s[3870]! } + public var Conversation_OpenBotLinkOpen: String { return self._s[3871]! } + public var Common_Cancel: String { return self._s[3872]! } + public var DialogList_SavedMessagesTooltip: String { return self._s[3873]! } + public var TwoStepAuth_SetupPasswordTitle: String { return self._s[3874]! } + public var Appearance_TintAllColors: String { return self._s[3875]! } public func PUSH_MESSAGE_FWD(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3875]!, self._r[3875]!, [_1]) + return formatWithArgumentRanges(self._s[3876]!, self._r[3876]!, [_1]) } - public var Conversation_ReportSpamConfirmation: String { return self._s[3876]! } - public var ChatSettings_Title: String { return self._s[3878]! } - public var Passport_PasswordReset: String { return self._s[3879]! } - public var SocksProxySetup_TypeNone: String { return self._s[3880]! } - public var EditTheme_Title: String { return self._s[3883]! } - public var PhoneNumberHelp_Help: String { return self._s[3884]! } - public var Checkout_EnterPassword: String { return self._s[3885]! } - public var Activity_UploadingDocument: String { return self._s[3887]! } - public var Share_AuthTitle: String { return self._s[3888]! } - public var State_Connecting: String { return self._s[3889]! } - public var Profile_MessageLifetime1w: String { return self._s[3890]! } - public var Conversation_ContextMenuReport: String { return self._s[3891]! } - public var CheckoutInfo_ReceiverInfoPhone: String { return self._s[3892]! } - public var AutoNightTheme_ScheduledTo: String { return self._s[3893]! } + public var Conversation_ReportSpamConfirmation: String { return self._s[3877]! } + public var ChatSettings_Title: String { return self._s[3879]! } + public var Passport_PasswordReset: String { return self._s[3880]! } + public var SocksProxySetup_TypeNone: String { return self._s[3881]! } + public var EditTheme_Title: String { return self._s[3884]! } + public var PhoneNumberHelp_Help: String { return self._s[3885]! } + public var Checkout_EnterPassword: String { return self._s[3886]! } + public var Activity_UploadingDocument: String { return self._s[3888]! } + public var Share_AuthTitle: String { return self._s[3889]! } + public var State_Connecting: String { return self._s[3890]! } + public var Profile_MessageLifetime1w: String { return self._s[3891]! } + public var Conversation_ContextMenuReport: String { return self._s[3892]! } + public var CheckoutInfo_ReceiverInfoPhone: String { return self._s[3893]! } + public var AutoNightTheme_ScheduledTo: String { return self._s[3894]! } public func VoiceOver_Chat_AnonymousPollFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3894]!, self._r[3894]!, [_0]) + return formatWithArgumentRanges(self._s[3895]!, self._r[3895]!, [_0]) } - public var AuthSessions_Terminate: String { return self._s[3895]! } - public var Wallet_WordImport_CanNotRemember: String { return self._s[3896]! } - public var Checkout_NewCard_CardholderNamePlaceholder: String { return self._s[3898]! } - public var KeyCommand_JumpToPreviousUnreadChat: String { return self._s[3899]! } - public var PhotoEditor_Set: String { return self._s[3900]! } - public var EmptyGroupInfo_Title: String { return self._s[3901]! } - public var Login_PadPhoneHelp: String { return self._s[3902]! } - public var AutoDownloadSettings_TypeGroupChats: String { return self._s[3904]! } - public var PrivacyPolicy_DeclineLastWarning: String { return self._s[3906]! } - public var NotificationsSound_Complete: String { return self._s[3907]! } - public var SettingsSearch_Synonyms_Privacy_Data_Title: String { return self._s[3908]! } - public var Group_Info_AdminLog: String { return self._s[3909]! } - public var GroupPermission_NotAvailableInPublicGroups: String { return self._s[3910]! } + public var AuthSessions_Terminate: String { return self._s[3896]! } + public var Wallet_WordImport_CanNotRemember: String { return self._s[3897]! } + public var Checkout_NewCard_CardholderNamePlaceholder: String { return self._s[3899]! } + public var KeyCommand_JumpToPreviousUnreadChat: String { return self._s[3900]! } + public var PhotoEditor_Set: String { return self._s[3901]! } + public var EmptyGroupInfo_Title: String { return self._s[3902]! } + public var Login_PadPhoneHelp: String { return self._s[3903]! } + public var AutoDownloadSettings_TypeGroupChats: String { return self._s[3905]! } + public var PrivacyPolicy_DeclineLastWarning: String { return self._s[3907]! } + public var NotificationsSound_Complete: String { return self._s[3908]! } + public var SettingsSearch_Synonyms_Privacy_Data_Title: String { return self._s[3909]! } + public var Group_Info_AdminLog: String { return self._s[3910]! } + public var GroupPermission_NotAvailableInPublicGroups: String { return self._s[3911]! } public func Wallet_Time_PreciseDate_m11(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3911]!, self._r[3911]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3912]!, self._r[3912]!, [_1, _2, _3]) } - public var Channel_AdminLog_InfoPanelAlertText: String { return self._s[3912]! } - public var Group_Location_CreateInThisPlace: String { return self._s[3914]! } - public var Conversation_Admin: String { return self._s[3915]! } - public var Conversation_GifTooltip: String { return self._s[3916]! } - public var Passport_NotLoggedInMessage: String { return self._s[3917]! } + public var Channel_AdminLog_InfoPanelAlertText: String { return self._s[3913]! } + public var Group_Location_CreateInThisPlace: String { return self._s[3915]! } + public var Conversation_Admin: String { return self._s[3916]! } + public var Conversation_GifTooltip: String { return self._s[3917]! } + public var Passport_NotLoggedInMessage: String { return self._s[3918]! } public func AutoDownloadSettings_OnFor(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3919]!, self._r[3919]!, [_0]) + return formatWithArgumentRanges(self._s[3920]!, self._r[3920]!, [_0]) } - public var Profile_MessageLifetimeForever: String { return self._s[3920]! } - public var SharedMedia_EmptyTitle: String { return self._s[3922]! } - public var Channel_Edit_PrivatePublicLinkAlert: String { return self._s[3924]! } - public var Username_Help: String { return self._s[3925]! } - public var DialogList_LanguageTooltip: String { return self._s[3927]! } - public var Map_LoadError: String { return self._s[3928]! } - public var Login_PhoneNumberAlreadyAuthorized: String { return self._s[3929]! } - public var Channel_AdminLog_AddMembers: String { return self._s[3930]! } - public var ArchivedChats_IntroTitle2: String { return self._s[3931]! } - public var Notification_Exceptions_NewException: String { return self._s[3932]! } - public var TwoStepAuth_EmailTitle: String { return self._s[3933]! } - public var WatchRemote_AlertText: String { return self._s[3934]! } + public var Profile_MessageLifetimeForever: String { return self._s[3921]! } + public var SharedMedia_EmptyTitle: String { return self._s[3923]! } + public var Channel_Edit_PrivatePublicLinkAlert: String { return self._s[3925]! } + public var Username_Help: String { return self._s[3926]! } + public var DialogList_LanguageTooltip: String { return self._s[3928]! } + public var Map_LoadError: String { return self._s[3929]! } + public var Login_PhoneNumberAlreadyAuthorized: String { return self._s[3930]! } + public var Channel_AdminLog_AddMembers: String { return self._s[3931]! } + public var ArchivedChats_IntroTitle2: String { return self._s[3932]! } + public var Notification_Exceptions_NewException: String { return self._s[3933]! } + public var TwoStepAuth_EmailTitle: String { return self._s[3934]! } + public var WatchRemote_AlertText: String { return self._s[3935]! } public func Wallet_Send_ConfirmationText(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3935]!, self._r[3935]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3936]!, self._r[3936]!, [_1, _2, _3]) } - public var ChatSettings_ConnectionType_Title: String { return self._s[3939]! } + public var ChatSettings_ConnectionType_Title: String { return self._s[3940]! } public func PUSH_PINNED_QUIZ(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3940]!, self._r[3940]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3941]!, self._r[3941]!, [_1, _2]) } public func Settings_CheckPhoneNumberTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3941]!, self._r[3941]!, [_0]) + return formatWithArgumentRanges(self._s[3942]!, self._r[3942]!, [_0]) } - public var SettingsSearch_Synonyms_Calls_CallTab: String { return self._s[3942]! } - public var WebBrowser_DefaultBrowser: String { return self._s[3943]! } - public var Passport_Address_CountryPlaceholder: String { return self._s[3944]! } + public var SettingsSearch_Synonyms_Calls_CallTab: String { return self._s[3943]! } + public var WebBrowser_DefaultBrowser: String { return self._s[3944]! } + public var Passport_Address_CountryPlaceholder: String { return self._s[3945]! } public func DialogList_AwaitingEncryption(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3945]!, self._r[3945]!, [_0]) + return formatWithArgumentRanges(self._s[3946]!, self._r[3946]!, [_0]) } public func Time_PreciseDate_m6(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3946]!, self._r[3946]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3947]!, self._r[3947]!, [_1, _2, _3]) } - public var Group_AdminLog_EmptyText: String { return self._s[3947]! } - public var SettingsSearch_Synonyms_Appearance_Title: String { return self._s[3948]! } - public var Conversation_PrivateChannelTooltip: String { return self._s[3950]! } - public var Wallet_Created_ExportErrorText: String { return self._s[3951]! } - public var ChatList_UndoArchiveText1: String { return self._s[3952]! } - public var AccessDenied_VideoMicrophone: String { return self._s[3953]! } - public var Conversation_ContextMenuStickerPackAdd: String { return self._s[3954]! } - public var Cache_ClearNone: String { return self._s[3955]! } - public var SocksProxySetup_FailedToConnect: String { return self._s[3956]! } - public var Permissions_NotificationsTitle_v0: String { return self._s[3957]! } + public var Group_AdminLog_EmptyText: String { return self._s[3948]! } + public var SettingsSearch_Synonyms_Appearance_Title: String { return self._s[3949]! } + public var Conversation_PrivateChannelTooltip: String { return self._s[3951]! } + public var Wallet_Created_ExportErrorText: String { return self._s[3952]! } + public var ChatList_UndoArchiveText1: String { return self._s[3953]! } + public var AccessDenied_VideoMicrophone: String { return self._s[3954]! } + public var Conversation_ContextMenuStickerPackAdd: String { return self._s[3955]! } + public var Cache_ClearNone: String { return self._s[3956]! } + public var SocksProxySetup_FailedToConnect: String { return self._s[3957]! } + public var Permissions_NotificationsTitle_v0: String { return self._s[3958]! } public func Channel_AdminLog_MessageEdited(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3958]!, self._r[3958]!, [_0]) + return formatWithArgumentRanges(self._s[3959]!, self._r[3959]!, [_0]) } - public var Passport_Identity_Country: String { return self._s[3959]! } + public var Passport_Identity_Country: String { return self._s[3960]! } public func ChatSettings_AutoDownloadSettings_TypeFile(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3960]!, self._r[3960]!, [_0]) - } - public func Notification_CreatedChat(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3961]!, self._r[3961]!, [_0]) } - public var Exceptions_AddToExceptions: String { return self._s[3962]! } - public var AccessDenied_Settings: String { return self._s[3963]! } - public var Passport_Address_TypeUtilityBillUploadScan: String { return self._s[3964]! } - public var Month_ShortMay: String { return self._s[3965]! } - public var Compose_NewGroup: String { return self._s[3967]! } - public var Group_Setup_TypePrivate: String { return self._s[3969]! } - public var Login_PadPhoneHelpTitle: String { return self._s[3971]! } - public var Appearance_ThemeDayClassic: String { return self._s[3972]! } - public var Channel_AdminLog_MessagePreviousCaption: String { return self._s[3973]! } - public var AutoDownloadSettings_OffForAll: String { return self._s[3974]! } - public var Privacy_GroupsAndChannels_WhoCanAddMe: String { return self._s[3975]! } - public var Conversation_typing: String { return self._s[3977]! } - public var Undo_ScheduledMessagesCleared: String { return self._s[3978]! } - public var Paint_Masks: String { return self._s[3979]! } - public var Contacts_DeselectAll: String { return self._s[3980]! } - public func Wallet_Updated_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3981]!, self._r[3981]!, [_0]) + public func Notification_CreatedChat(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3962]!, self._r[3962]!, [_0]) } - public var CreatePoll_MultipleChoiceQuizAlert: String { return self._s[3982]! } - public var Username_InvalidTaken: String { return self._s[3983]! } - public var Call_StatusNoAnswer: String { return self._s[3984]! } - public var TwoStepAuth_EmailAddSuccess: String { return self._s[3985]! } - public var SettingsSearch_Synonyms_Privacy_BlockedUsers: String { return self._s[3986]! } - public var Passport_Identity_Selfie: String { return self._s[3987]! } - public var Login_InfoLastNamePlaceholder: String { return self._s[3988]! } - public var Privacy_SecretChatsLinkPreviewsHelp: String { return self._s[3989]! } - public var Conversation_ClearSecretHistory: String { return self._s[3990]! } - public var PeopleNearby_Description: String { return self._s[3992]! } - public var NetworkUsageSettings_Title: String { return self._s[3993]! } - public var Your_cards_security_code_is_invalid: String { return self._s[3995]! } + public var Exceptions_AddToExceptions: String { return self._s[3963]! } + public var AccessDenied_Settings: String { return self._s[3964]! } + public var Passport_Address_TypeUtilityBillUploadScan: String { return self._s[3965]! } + public var Month_ShortMay: String { return self._s[3966]! } + public var Compose_NewGroup: String { return self._s[3968]! } + public var Group_Setup_TypePrivate: String { return self._s[3970]! } + public var Login_PadPhoneHelpTitle: String { return self._s[3972]! } + public var Appearance_ThemeDayClassic: String { return self._s[3973]! } + public var Channel_AdminLog_MessagePreviousCaption: String { return self._s[3974]! } + public var AutoDownloadSettings_OffForAll: String { return self._s[3975]! } + public var Privacy_GroupsAndChannels_WhoCanAddMe: String { return self._s[3976]! } + public var Conversation_typing: String { return self._s[3978]! } + public var Undo_ScheduledMessagesCleared: String { return self._s[3979]! } + public var Paint_Masks: String { return self._s[3980]! } + public var Contacts_DeselectAll: String { return self._s[3981]! } + public func Wallet_Updated_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3982]!, self._r[3982]!, [_0]) + } + public var CreatePoll_MultipleChoiceQuizAlert: String { return self._s[3983]! } + public var Username_InvalidTaken: String { return self._s[3984]! } + public var Call_StatusNoAnswer: String { return self._s[3985]! } + public var TwoStepAuth_EmailAddSuccess: String { return self._s[3986]! } + public var SettingsSearch_Synonyms_Privacy_BlockedUsers: String { return self._s[3987]! } + public var Passport_Identity_Selfie: String { return self._s[3988]! } + public var Login_InfoLastNamePlaceholder: String { return self._s[3989]! } + public var Privacy_SecretChatsLinkPreviewsHelp: String { return self._s[3990]! } + public var Conversation_ClearSecretHistory: String { return self._s[3991]! } + public var PeopleNearby_Description: String { return self._s[3993]! } + public var NetworkUsageSettings_Title: String { return self._s[3994]! } + public var Your_cards_security_code_is_invalid: String { return self._s[3996]! } public func Notification_LeftChannel(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3997]!, self._r[3997]!, [_0]) + return formatWithArgumentRanges(self._s[3998]!, self._r[3998]!, [_0]) } public func Call_CallInProgressMessage(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3998]!, self._r[3998]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3999]!, self._r[3999]!, [_1, _2]) } - public var SaveIncomingPhotosSettings_From: String { return self._s[4000]! } - public var VoiceOver_Navigation_Search: String { return self._s[4001]! } - public var Map_LiveLocationTitle: String { return self._s[4002]! } - public var Login_InfoAvatarAdd: String { return self._s[4003]! } - public var Passport_Identity_FilesView: String { return self._s[4004]! } - public var UserInfo_GenericPhoneLabel: String { return self._s[4005]! } - public var Privacy_Calls_NeverAllow: String { return self._s[4006]! } - public var VoiceOver_Chat_File: String { return self._s[4007]! } - public var Wallet_Settings_DeleteWalletInfo: String { return self._s[4008]! } + public var SaveIncomingPhotosSettings_From: String { return self._s[4001]! } + public var VoiceOver_Navigation_Search: String { return self._s[4002]! } + public var Map_LiveLocationTitle: String { return self._s[4003]! } + public var Login_InfoAvatarAdd: String { return self._s[4004]! } + public var Passport_Identity_FilesView: String { return self._s[4005]! } + public var UserInfo_GenericPhoneLabel: String { return self._s[4006]! } + public var Privacy_Calls_NeverAllow: String { return self._s[4007]! } + public var VoiceOver_Chat_File: String { return self._s[4008]! } + public var Wallet_Settings_DeleteWalletInfo: String { return self._s[4009]! } public func Contacts_AddPhoneNumber(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4009]!, self._r[4009]!, [_0]) + return formatWithArgumentRanges(self._s[4010]!, self._r[4010]!, [_0]) } - public var ContactInfo_PhoneNumberHidden: String { return self._s[4010]! } - public var TwoStepAuth_ConfirmationText: String { return self._s[4011]! } - public var ChatSettings_AutomaticVideoMessageDownload: String { return self._s[4012]! } + public var ContactInfo_PhoneNumberHidden: String { return self._s[4011]! } + public var TwoStepAuth_ConfirmationText: String { return self._s[4012]! } + public var ChatSettings_AutomaticVideoMessageDownload: String { return self._s[4013]! } public func PUSH_CHAT_MESSAGE_VIDEOS(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4013]!, self._r[4013]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[4014]!, self._r[4014]!, [_1, _2, _3]) } - public var Channel_AdminLogFilter_AdminsAll: String { return self._s[4014]! } - public var Wallet_Intro_CreateErrorText: String { return self._s[4015]! } - public var Tour_Title2: String { return self._s[4016]! } - public var Wallet_Sent_ViewWallet: String { return self._s[4017]! } - public var Conversation_FileOpenIn: String { return self._s[4018]! } - public var Checkout_ErrorPrecheckoutFailed: String { return self._s[4019]! } - public var Wallet_Send_ErrorInvalidAddress: String { return self._s[4020]! } - public var Wallpaper_Set: String { return self._s[4021]! } - public var Passport_Identity_Translations: String { return self._s[4023]! } + public var Channel_AdminLogFilter_AdminsAll: String { return self._s[4015]! } + public var Wallet_Intro_CreateErrorText: String { return self._s[4016]! } + public var Tour_Title2: String { return self._s[4017]! } + public var Wallet_Sent_ViewWallet: String { return self._s[4018]! } + public var Conversation_FileOpenIn: String { return self._s[4019]! } + public var Checkout_ErrorPrecheckoutFailed: String { return self._s[4020]! } + public var Wallet_Send_ErrorInvalidAddress: String { return self._s[4021]! } + public var Wallpaper_Set: String { return self._s[4022]! } + public var Passport_Identity_Translations: String { return self._s[4024]! } public func Channel_AdminLog_MessageChangedChannelAbout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4024]!, self._r[4024]!, [_0]) + return formatWithArgumentRanges(self._s[4025]!, self._r[4025]!, [_0]) } - public var Channel_LeaveChannel: String { return self._s[4025]! } + public var Channel_LeaveChannel: String { return self._s[4026]! } public func PINNED_INVOICE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4026]!, self._r[4026]!, [_1]) + return formatWithArgumentRanges(self._s[4027]!, self._r[4027]!, [_1]) } - public var SettingsSearch_Synonyms_Proxy_AddProxy: String { return self._s[4028]! } - public var PhotoEditor_HighlightsTint: String { return self._s[4029]! } - public var MessagePoll_LabelPoll: String { return self._s[4030]! } - public var Passport_Email_Delete: String { return self._s[4031]! } - public var Conversation_Mute: String { return self._s[4033]! } - public var Channel_AddBotAsAdmin: String { return self._s[4034]! } - public var Channel_AdminLog_CanSendMessages: String { return self._s[4036]! } - public var Wallet_Configuration_BlockchainNameChangedText: String { return self._s[4037]! } - public var ChatSettings_IntentsSettings: String { return self._s[4039]! } - public var Channel_Management_LabelOwner: String { return self._s[4040]! } + public var SettingsSearch_Synonyms_Proxy_AddProxy: String { return self._s[4029]! } + public var PhotoEditor_HighlightsTint: String { return self._s[4030]! } + public var MessagePoll_LabelPoll: String { return self._s[4031]! } + public var Passport_Email_Delete: String { return self._s[4032]! } + public var Conversation_Mute: String { return self._s[4034]! } + public var Channel_AddBotAsAdmin: String { return self._s[4035]! } + public var Channel_AdminLog_CanSendMessages: String { return self._s[4037]! } + public var Wallet_Configuration_BlockchainNameChangedText: String { return self._s[4038]! } + public var ChatSettings_IntentsSettings: String { return self._s[4040]! } + public var Channel_Management_LabelOwner: String { return self._s[4041]! } public func Notification_PassportValuesSentMessage(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4041]!, self._r[4041]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4042]!, self._r[4042]!, [_1, _2]) } - public var Calls_CallTabDescription: String { return self._s[4042]! } - public var Passport_Identity_NativeNameHelp: String { return self._s[4043]! } - public var Common_No: String { return self._s[4044]! } - public var Weekday_Sunday: String { return self._s[4045]! } - public var Notification_Reply: String { return self._s[4046]! } - public var Conversation_ViewMessage: String { return self._s[4047]! } + public var Calls_CallTabDescription: String { return self._s[4043]! } + public var Passport_Identity_NativeNameHelp: String { return self._s[4044]! } + public var Common_No: String { return self._s[4045]! } + public var Weekday_Sunday: String { return self._s[4046]! } + public var Notification_Reply: String { return self._s[4047]! } + public var Conversation_ViewMessage: String { return self._s[4048]! } public func Checkout_SavePasswordTimeoutAndFaceId(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4048]!, self._r[4048]!, [_0]) - } - public func Map_LiveLocationPrivateDescription(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[4049]!, self._r[4049]!, [_0]) } + public func Map_LiveLocationPrivateDescription(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[4050]!, self._r[4050]!, [_0]) + } public func Wallet_Time_PreciseDate_m7(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4050]!, self._r[4050]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[4051]!, self._r[4051]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_EditProfile_AddAccount: String { return self._s[4051]! } - public var Wallet_Send_Title: String { return self._s[4052]! } - public var Message_PinnedDocumentMessage: String { return self._s[4053]! } - public var Wallet_Info_RefreshErrorText: String { return self._s[4054]! } - public var DialogList_TabTitle: String { return self._s[4056]! } - public var ChatSettings_AutoPlayTitle: String { return self._s[4057]! } - public var Passport_FieldEmail: String { return self._s[4058]! } - public var Conversation_UnpinMessageAlert: String { return self._s[4059]! } - public var Passport_Address_TypeBankStatement: String { return self._s[4060]! } - public var Wallet_SecureStorageReset_Title: String { return self._s[4061]! } - public var Passport_Identity_ExpiryDate: String { return self._s[4062]! } - public var Privacy_Calls_P2P: String { return self._s[4063]! } + public var SettingsSearch_Synonyms_EditProfile_AddAccount: String { return self._s[4052]! } + public var Wallet_Send_Title: String { return self._s[4053]! } + public var Message_PinnedDocumentMessage: String { return self._s[4054]! } + public var Wallet_Info_RefreshErrorText: String { return self._s[4055]! } + public var DialogList_TabTitle: String { return self._s[4057]! } + public var ChatSettings_AutoPlayTitle: String { return self._s[4058]! } + public var Passport_FieldEmail: String { return self._s[4059]! } + public var Conversation_UnpinMessageAlert: String { return self._s[4060]! } + public var Passport_Address_TypeBankStatement: String { return self._s[4061]! } + public var Wallet_SecureStorageReset_Title: String { return self._s[4062]! } + public var Passport_Identity_ExpiryDate: String { return self._s[4063]! } + public var Privacy_Calls_P2P: String { return self._s[4064]! } public func CancelResetAccount_Success(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4065]!, self._r[4065]!, [_0]) + return formatWithArgumentRanges(self._s[4066]!, self._r[4066]!, [_0]) } - public var SocksProxySetup_UseForCallsHelp: String { return self._s[4066]! } + public var SocksProxySetup_UseForCallsHelp: String { return self._s[4067]! } public func PUSH_CHAT_ALBUM(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4067]!, self._r[4067]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4068]!, self._r[4068]!, [_1, _2]) } - public var Stickers_ClearRecent: String { return self._s[4068]! } - public var EnterPasscode_ChangeTitle: String { return self._s[4069]! } - public var TwoFactorSetup_Email_Title: String { return self._s[4070]! } - public var Passport_InfoText: String { return self._s[4071]! } - public var Checkout_NewCard_SaveInfoEnableHelp: String { return self._s[4072]! } + public var Stickers_ClearRecent: String { return self._s[4069]! } + public var EnterPasscode_ChangeTitle: String { return self._s[4070]! } + public var TwoFactorSetup_Email_Title: String { return self._s[4071]! } + public var Passport_InfoText: String { return self._s[4072]! } + public var Checkout_NewCard_SaveInfoEnableHelp: String { return self._s[4073]! } public func Login_InvalidPhoneEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4073]!, self._r[4073]!, [_0]) + return formatWithArgumentRanges(self._s[4074]!, self._r[4074]!, [_0]) } public func Time_PreciseDate_m3(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4074]!, self._r[4074]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[4075]!, self._r[4075]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChannels: String { return self._s[4075]! } - public var ScheduledMessages_PollUnavailable: String { return self._s[4076]! } - public var VoiceOver_Navigation_Compose: String { return self._s[4077]! } - public var Passport_Identity_EditDriversLicense: String { return self._s[4078]! } - public var Conversation_TapAndHoldToRecord: String { return self._s[4080]! } - public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChats: String { return self._s[4081]! } + public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChannels: String { return self._s[4076]! } + public var ScheduledMessages_PollUnavailable: String { return self._s[4077]! } + public var VoiceOver_Navigation_Compose: String { return self._s[4078]! } + public var Passport_Identity_EditDriversLicense: String { return self._s[4079]! } + public var Conversation_TapAndHoldToRecord: String { return self._s[4081]! } + public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChats: String { return self._s[4082]! } public func Notification_CallTimeFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4082]!, self._r[4082]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4083]!, self._r[4083]!, [_1, _2]) } - public var Channel_EditAdmin_PermissionInviteViaLink: String { return self._s[4084]! } - public var ChatSettings_OpenLinksIn: String { return self._s[4085]! } - public var Map_HomeAndWorkTitle: String { return self._s[4086]! } + public var Channel_EditAdmin_PermissionInviteViaLink: String { return self._s[4085]! } + public var ChatSettings_OpenLinksIn: String { return self._s[4086]! } + public var Map_HomeAndWorkTitle: String { return self._s[4087]! } public func Generic_OpenHiddenLinkAlert(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4088]!, self._r[4088]!, [_0]) + return formatWithArgumentRanges(self._s[4089]!, self._r[4089]!, [_0]) } - public var DialogList_Unread: String { return self._s[4089]! } + public var DialogList_Unread: String { return self._s[4090]! } public func PUSH_CHAT_MESSAGE_GIF(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4090]!, self._r[4090]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4091]!, self._r[4091]!, [_1, _2]) } - public var User_DeletedAccount: String { return self._s[4091]! } - public var OwnershipTransfer_SetupTwoStepAuth: String { return self._s[4092]! } + public var User_DeletedAccount: String { return self._s[4092]! } + public var OwnershipTransfer_SetupTwoStepAuth: String { return self._s[4093]! } public func Watch_Time_ShortYesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4093]!, self._r[4093]!, [_0]) + return formatWithArgumentRanges(self._s[4094]!, self._r[4094]!, [_0]) } - public var UserInfo_NotificationsDefault: String { return self._s[4094]! } - public var SharedMedia_CategoryMedia: String { return self._s[4095]! } - public var SocksProxySetup_ProxyStatusUnavailable: String { return self._s[4096]! } - public var Channel_AdminLog_MessageRestrictedForever: String { return self._s[4097]! } - public var Watch_ChatList_Compose: String { return self._s[4098]! } - public var Notifications_MessageNotificationsExceptionsHelp: String { return self._s[4099]! } - public var AutoDownloadSettings_Delimeter: String { return self._s[4100]! } - public var Watch_Microphone_Access: String { return self._s[4101]! } - public var Group_Setup_HistoryHeader: String { return self._s[4102]! } - public var Map_SetThisLocation: String { return self._s[4103]! } - public var Appearance_ThemePreview_Chat_2_ReplyName: String { return self._s[4104]! } - public var Activity_UploadingPhoto: String { return self._s[4105]! } - public var Conversation_Edit: String { return self._s[4107]! } - public var Group_ErrorSendRestrictedMedia: String { return self._s[4108]! } - public var Login_TermsOfServiceDecline: String { return self._s[4109]! } - public var Message_PinnedContactMessage: String { return self._s[4110]! } + public var UserInfo_NotificationsDefault: String { return self._s[4095]! } + public var SharedMedia_CategoryMedia: String { return self._s[4096]! } + public var SocksProxySetup_ProxyStatusUnavailable: String { return self._s[4097]! } + public var Channel_AdminLog_MessageRestrictedForever: String { return self._s[4098]! } + public var Watch_ChatList_Compose: String { return self._s[4099]! } + public var Notifications_MessageNotificationsExceptionsHelp: String { return self._s[4100]! } + public var AutoDownloadSettings_Delimeter: String { return self._s[4101]! } + public var Watch_Microphone_Access: String { return self._s[4102]! } + public var Group_Setup_HistoryHeader: String { return self._s[4103]! } + public var Map_SetThisLocation: String { return self._s[4104]! } + public var Appearance_ThemePreview_Chat_2_ReplyName: String { return self._s[4105]! } + public var Activity_UploadingPhoto: String { return self._s[4106]! } + public var Conversation_Edit: String { return self._s[4108]! } + public var Group_ErrorSendRestrictedMedia: String { return self._s[4109]! } + public var Login_TermsOfServiceDecline: String { return self._s[4110]! } + public var Message_PinnedContactMessage: String { return self._s[4111]! } public func Channel_AdminLog_MessageRestrictedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4111]!, self._r[4111]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4112]!, self._r[4112]!, [_1, _2]) } public func Login_PhoneBannedEmailBody(_ _1: String, _ _2: String, _ _3: String, _ _4: String, _ _5: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4112]!, self._r[4112]!, [_1, _2, _3, _4, _5]) + return formatWithArgumentRanges(self._s[4113]!, self._r[4113]!, [_1, _2, _3, _4, _5]) } - public var Appearance_LargeEmoji: String { return self._s[4113]! } - public var TwoStepAuth_AdditionalPassword: String { return self._s[4115]! } - public var EditTheme_Edit_Preview_IncomingReplyText: String { return self._s[4116]! } + public var Appearance_LargeEmoji: String { return self._s[4114]! } + public var TwoStepAuth_AdditionalPassword: String { return self._s[4116]! } + public var EditTheme_Edit_Preview_IncomingReplyText: String { return self._s[4117]! } public func PUSH_CHAT_DELETE_YOU(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4117]!, self._r[4117]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4118]!, self._r[4118]!, [_1, _2]) } - public var Passport_Phone_EnterOtherNumber: String { return self._s[4118]! } - public var Message_PinnedPhotoMessage: String { return self._s[4119]! } - public var Passport_FieldPhone: String { return self._s[4120]! } - public var TwoStepAuth_RecoveryEmailAddDescription: String { return self._s[4121]! } - public var ChatSettings_AutoPlayGifs: String { return self._s[4122]! } - public var InfoPlist_NSCameraUsageDescription: String { return self._s[4124]! } - public var Conversation_Call: String { return self._s[4125]! } - public var Common_TakePhoto: String { return self._s[4127]! } - public var Group_EditAdmin_RankTitle: String { return self._s[4128]! } - public var Wallet_Receive_CommentHeader: String { return self._s[4129]! } - public var Channel_NotificationLoading: String { return self._s[4130]! } + public var Passport_Phone_EnterOtherNumber: String { return self._s[4119]! } + public var Message_PinnedPhotoMessage: String { return self._s[4120]! } + public var Passport_FieldPhone: String { return self._s[4121]! } + public var TwoStepAuth_RecoveryEmailAddDescription: String { return self._s[4122]! } + public var ChatSettings_AutoPlayGifs: String { return self._s[4123]! } + public var InfoPlist_NSCameraUsageDescription: String { return self._s[4125]! } + public var Conversation_Call: String { return self._s[4126]! } + public var Common_TakePhoto: String { return self._s[4128]! } + public var Group_EditAdmin_RankTitle: String { return self._s[4129]! } + public var Wallet_Receive_CommentHeader: String { return self._s[4130]! } + public var Channel_NotificationLoading: String { return self._s[4131]! } public func Notification_Exceptions_Sound(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4131]!, self._r[4131]!, [_0]) - } - public func ScheduledMessages_ScheduledDate(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[4132]!, self._r[4132]!, [_0]) } + public func ScheduledMessages_ScheduledDate(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[4133]!, self._r[4133]!, [_0]) + } public func PUSH_CHANNEL_MESSAGE_VIDEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4133]!, self._r[4133]!, [_1]) + return formatWithArgumentRanges(self._s[4134]!, self._r[4134]!, [_1]) } - public var Permissions_SiriTitle_v0: String { return self._s[4134]! } + public var Permissions_SiriTitle_v0: String { return self._s[4135]! } public func VoiceOver_Chat_VoiceMessageFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4135]!, self._r[4135]!, [_0]) - } - public func Login_ResetAccountProtected_Text(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[4136]!, self._r[4136]!, [_0]) } - public var Channel_MessagePhotoRemoved: String { return self._s[4137]! } - public var Wallet_Info_ReceiveGrams: String { return self._s[4138]! } - public var ClearCache_FreeSpace: String { return self._s[4139]! } - public var Common_edit: String { return self._s[4140]! } - public var PrivacySettings_AuthSessions: String { return self._s[4141]! } - public var Month_ShortJune: String { return self._s[4142]! } - public var PrivacyLastSeenSettings_AlwaysShareWith_Placeholder: String { return self._s[4143]! } - public var Call_ReportSend: String { return self._s[4144]! } - public var Watch_LastSeen_JustNow: String { return self._s[4145]! } - public var Notifications_MessageNotifications: String { return self._s[4146]! } - public var WallpaperSearch_ColorGreen: String { return self._s[4147]! } - public var BroadcastListInfo_AddRecipient: String { return self._s[4149]! } - public var Group_Status: String { return self._s[4150]! } + public func Login_ResetAccountProtected_Text(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[4137]!, self._r[4137]!, [_0]) + } + public var Channel_MessagePhotoRemoved: String { return self._s[4138]! } + public var Wallet_Info_ReceiveGrams: String { return self._s[4139]! } + public var ClearCache_FreeSpace: String { return self._s[4140]! } + public var Common_edit: String { return self._s[4141]! } + public var PrivacySettings_AuthSessions: String { return self._s[4142]! } + public var Month_ShortJune: String { return self._s[4143]! } + public var PrivacyLastSeenSettings_AlwaysShareWith_Placeholder: String { return self._s[4144]! } + public var Call_ReportSend: String { return self._s[4145]! } + public var Watch_LastSeen_JustNow: String { return self._s[4146]! } + public var Notifications_MessageNotifications: String { return self._s[4147]! } + public var WallpaperSearch_ColorGreen: String { return self._s[4148]! } + public var BroadcastListInfo_AddRecipient: String { return self._s[4150]! } + public var Group_Status: String { return self._s[4151]! } public func AutoNightTheme_LocationHelp(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4151]!, self._r[4151]!, [_0, _1]) + return formatWithArgumentRanges(self._s[4152]!, self._r[4152]!, [_0, _1]) } - public var TextFormat_AddLinkTitle: String { return self._s[4152]! } - public var ShareMenu_ShareTo: String { return self._s[4153]! } - public var Conversation_Moderate_Ban: String { return self._s[4154]! } + public var TextFormat_AddLinkTitle: String { return self._s[4153]! } + public var ShareMenu_ShareTo: String { return self._s[4154]! } + public var Conversation_Moderate_Ban: String { return self._s[4155]! } public func Conversation_DeleteMessagesFor(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4155]!, self._r[4155]!, [_0]) + return formatWithArgumentRanges(self._s[4156]!, self._r[4156]!, [_0]) } - public var SharedMedia_ViewInChat: String { return self._s[4156]! } - public var Map_LiveLocationFor8Hours: String { return self._s[4157]! } + public var SharedMedia_ViewInChat: String { return self._s[4157]! } + public var Map_LiveLocationFor8Hours: String { return self._s[4158]! } public func PUSH_PINNED_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4158]!, self._r[4158]!, [_1]) + return formatWithArgumentRanges(self._s[4159]!, self._r[4159]!, [_1]) } public func PUSH_PINNED_POLL(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4159]!, self._r[4159]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4160]!, self._r[4160]!, [_1, _2]) } public func Map_AccurateTo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4161]!, self._r[4161]!, [_0]) + return formatWithArgumentRanges(self._s[4162]!, self._r[4162]!, [_0]) } - public var Map_OpenInHereMaps: String { return self._s[4162]! } - public var Appearance_ReduceMotion: String { return self._s[4163]! } + public var Map_OpenInHereMaps: String { return self._s[4163]! } + public var Appearance_ReduceMotion: String { return self._s[4164]! } public func PUSH_MESSAGE_TEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4164]!, self._r[4164]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4165]!, self._r[4165]!, [_1, _2]) } - public var Channel_Setup_TypePublicHelp: String { return self._s[4165]! } - public var Passport_Identity_EditInternalPassport: String { return self._s[4166]! } - public var PhotoEditor_Skip: String { return self._s[4167]! } - public func MessagePoll_QuizCount(_ value: Int32) -> String { + public var Channel_Setup_TypePublicHelp: String { return self._s[4166]! } + public var Passport_Identity_EditInternalPassport: String { return self._s[4167]! } + public var PhotoEditor_Skip: String { return self._s[4168]! } + public func ChatList_DeletedChats(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedVideoMessages(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, stringValue) + public func PUSH_CHANNEL_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, _1, _2) } - public func ForwardedFiles(_ value: Int32) -> String { + public func DialogList_LiveLocationChatsCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[2 * 6 + Int(form.rawValue)]!, stringValue) } - public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String { + public func CreatePoll_AddMoreOptions(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[3 * 6 + Int(form.rawValue)]!, stringValue) } - public func Call_Seconds(_ value: Int32) -> String { + public func StickerPack_RemoveStickerCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[4 * 6 + Int(form.rawValue)]!, stringValue) } - public func PUSH_CHANNEL_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[5 * 6 + Int(form.rawValue)]!, _1, _2) + public func MessageTimer_ShortWeeks(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[5 * 6 + Int(form.rawValue)]!, stringValue) } - public func StickerPack_RemoveMaskCount(_ value: Int32) -> String { + public func Conversation_StatusMembers(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[6 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedMessages(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[7 * 6 + Int(form.rawValue)]!, stringValue) + public func PUSH_CHAT_MESSAGE_VIDEOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[7 * 6 + Int(form.rawValue)]!, _2, _1, _3) } - public func MessageTimer_Seconds(_ value: Int32) -> String { + public func MuteExpires_Hours(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[8 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_Months(_ value: Int32) -> String { + public func MessageTimer_Weeks(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[9 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedStickers(_ value: Int32) -> String { + public func MessageTimer_Days(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[10 * 6 + Int(form.rawValue)]!, stringValue) } - public func Watch_LastSeen_HoursAgo(_ value: Int32) -> String { + public func VoiceOver_Chat_PollVotes(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[11 * 6 + Int(form.rawValue)]!, stringValue) } - public func InviteText_ContactsCountText(_ value: Int32) -> String { + public func Notifications_Exceptions(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[12 * 6 + Int(form.rawValue)]!, stringValue) } - public func LastSeen_HoursAgo(_ value: Int32) -> String { + public func Passport_Scans(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[13 * 6 + Int(form.rawValue)]!, stringValue) } - public func AttachmentMenu_SendPhoto(_ value: Int32) -> String { + public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[14 * 6 + Int(form.rawValue)]!, stringValue) @@ -4778,538 +4780,539 @@ public final class PresentationStrings: Equatable { let form = getPluralizationForm(self.lc, selector) return String(format: self._ps[15 * 6 + Int(form.rawValue)]!, _1, _2) } - public func Notification_GameScoreSelfSimple(_ value: Int32) -> String { + public func SharedMedia_Video(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[16 * 6 + Int(form.rawValue)]!, stringValue) } - public func AttachmentMenu_SendItem(_ value: Int32) -> String { + public func LiveLocationUpdated_MinutesAgo(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[17 * 6 + Int(form.rawValue)]!, stringValue) } - public func PrivacyLastSeenSettings_AddUsers(_ value: Int32) -> String { + public func PasscodeSettings_FailedAttempts(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[18 * 6 + Int(form.rawValue)]!, stringValue) } - public func DialogList_LiveLocationChatsCount(_ value: Int32) -> String { + public func Contacts_ImportersCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[19 * 6 + Int(form.rawValue)]!, stringValue) } - public func AttachmentMenu_SendVideo(_ value: Int32) -> String { + public func Notification_GameScoreSelfExtended(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[20 * 6 + Int(form.rawValue)]!, stringValue) } - public func VoiceOver_Chat_ContactEmailCount(_ value: Int32) -> String { + public func LastSeen_MinutesAgo(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[21 * 6 + Int(form.rawValue)]!, stringValue) } - public func SharedMedia_DeleteItemsConfirmation(_ value: Int32) -> String { + public func MessageTimer_Minutes(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[22 * 6 + Int(form.rawValue)]!, stringValue) } - public func Media_SharePhoto(_ value: Int32) -> String { + public func Conversation_LiveLocationMembersCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[23 * 6 + Int(form.rawValue)]!, stringValue) } - public func OldChannels_InactiveYear(_ value: Int32) -> String { + public func ForwardedGifs(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[24 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedPhotos(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[25 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Theme_UsersCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[26 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHANNEL_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[27 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func LastSeen_MinutesAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[28 * 6 + Int(form.rawValue)]!, stringValue) - } - public func QuickSend_Photos(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[29 * 6 + Int(form.rawValue)]!, stringValue) - } - public func VoiceOver_Chat_PollOptionCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[30 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Hours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[31 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Conversation_StatusSubscribers(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[32 * 6 + Int(form.rawValue)]!, stringValue) - } - public func OldChannels_GroupFormat(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[33 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Media_ShareItem(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[34 * 6 + Int(form.rawValue)]!, stringValue) - } - public func AttachmentMenu_SendGif(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[35 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notification_GameScoreExtended(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[36 * 6 + Int(form.rawValue)]!, stringValue) - } - public func GroupInfo_ShowMoreMembers(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[37 * 6 + Int(form.rawValue)]!, stringValue) - } - public func SharedMedia_Generic(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[38 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MuteExpires_Hours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[39 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Watch_UserInfo_Mute(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[40 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notifications_ExceptionMuteExpires_Days(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[41 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MuteExpires_Days(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[42 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Chat_DeleteMessagesConfirmation(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[43 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Call_Minutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[44 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Conversation_SelectedMessages(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[45 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_ShortDays(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[46 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notifications_ExceptionMuteExpires_Minutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[47 * 6 + Int(form.rawValue)]!, stringValue) - } - public func LiveLocation_MenuChatsCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[48 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGE_ROUNDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[49 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func UserCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[50 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Contacts_ImportersCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[51 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedContacts(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[52 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedAudios(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[53 * 6 + Int(form.rawValue)]!, stringValue) - } - public func StickerPack_StickerCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[54 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notifications_ExceptionMuteExpires_Hours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[55 * 6 + Int(form.rawValue)]!, stringValue) - } - public func VoiceOver_Chat_ContactPhoneNumberCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[56 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_ShortWeeks(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[57 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notifications_Exceptions(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[58 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ChatList_DeletedChats(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[59 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Call_ShortSeconds(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[60 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[61 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func Notification_GameScoreSimple(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[62 * 6 + Int(form.rawValue)]!, stringValue) - } - public func CreatePoll_AddMoreOptions(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[63 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MuteFor_Hours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[64 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notification_GameScoreSelfExtended(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[65 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Media_ShareVideo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[66 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHANNEL_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[67 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func SharedMedia_File(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[68 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Conversation_LiveLocationMembersCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[69 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Minutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[70 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Conversation_StatusMembers(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[71 * 6 + Int(form.rawValue)]!, stringValue) - } - public func StickerPack_AddStickerCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[72 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Years(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[73 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Map_ETAMinutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[74 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedVideos(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[75 * 6 + Int(form.rawValue)]!, stringValue) - } - public func SharedMedia_Link(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[76 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessagePoll_VotedCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[77 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHANNEL_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[78 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func Contacts_InviteContacts(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[79 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Days(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[80 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Watch_LastSeen_MinutesAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[81 * 6 + Int(form.rawValue)]!, stringValue) - } - public func SharedMedia_Photo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[82 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Wallet_Updated_HoursAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[83 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGES(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[84 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func ServiceMessage_GameScoreExtended(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[85 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Passport_Scans(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[86 * 6 + Int(form.rawValue)]!, stringValue) - } - public func GroupInfo_ParticipantCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[87 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ServiceMessage_GameScoreSelfExtended(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[88 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Call_ShortMinutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[89 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[90 * 6 + Int(form.rawValue)]!, _1, _2) - } public func PUSH_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[91 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func OldChannels_Leave(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[92 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[93 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func PUSH_CHAT_MESSAGE_PHOTOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[94 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func PUSH_CHANNEL_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[95 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func OldChannels_InactiveMonth(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[96 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_ShortMinutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[97 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PasscodeSettings_FailedAttempts(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[98 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Invitation_Members(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[99 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedAuthorsOthers(_ selector: Int32, _ _0: String, _ _1: String) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[100 * 6 + Int(form.rawValue)]!, _0, _1) - } - public func StickerPack_RemoveStickerCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[101 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ServiceMessage_GameScoreSimple(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[102 * 6 + Int(form.rawValue)]!, stringValue) - } - public func OldChannels_InactiveWeek(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[103 * 6 + Int(form.rawValue)]!, stringValue) - } - public func StickerPack_AddMaskCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[104 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedLocations(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[105 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGE_FWDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[106 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func MessageTimer_ShortHours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[107 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MuteFor_Days(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[108 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ServiceMessage_GameScoreSelfSimple(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[109 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGE_VIDEOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[110 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func MessageTimer_ShortSeconds(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[111 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Forward_ConfirmMultipleFiles(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[112 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[25 * 6 + Int(form.rawValue)]!, _1, _2) } public func ChatList_DeleteConfirmation(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[113 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[26 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedGifs(_ value: Int32) -> String { + public func OldChannels_Leave(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[114 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[27 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHAT_MESSAGE_PHOTOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[28 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func SharedMedia_Generic(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[29 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notification_GameScoreSelfSimple(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[30 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ServiceMessage_GameScoreSelfSimple(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[31 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Call_Minutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[32 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Chat_DeleteMessagesConfirmation(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[33 * 6 + Int(form.rawValue)]!, stringValue) + } + public func LiveLocation_MenuChatsCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[34 * 6 + Int(form.rawValue)]!, stringValue) + } + public func GroupInfo_ShowMoreMembers(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[35 * 6 + Int(form.rawValue)]!, stringValue) } public func MuteExpires_Minutes(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[115 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[36 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[37 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func MessagePoll_VotedCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[38 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notification_GameScoreExtended(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[39 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ServiceMessage_GameScoreExtended(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[40 * 6 + Int(form.rawValue)]!, stringValue) } public func Wallpaper_DeleteConfirmation(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[116 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[41 * 6 + Int(form.rawValue)]!, stringValue) } - public func LiveLocationUpdated_MinutesAgo(_ value: Int32) -> String { + public func PUSH_CHAT_MESSAGE_ROUNDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[42 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func UserCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[117 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[43 * 6 + Int(form.rawValue)]!, stringValue) } - public func VoiceOver_Chat_PollVotes(_ value: Int32) -> String { + public func Notifications_ExceptionMuteExpires_Hours(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[118 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[44 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Watch_UserInfo_Mute(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[45 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Media_ShareItem(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[46 * 6 + Int(form.rawValue)]!, stringValue) } public func ChatList_SelectedChats(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[119 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[47 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_Weeks(_ value: Int32) -> String { + public func StickerPack_AddStickerCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[120 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[48 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Call_ShortSeconds(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[49 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MuteExpires_Days(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[50 * 6 + Int(form.rawValue)]!, stringValue) } public func PollResults_ShowMore(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[121 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[51 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedPolls(_ value: Int32) -> String { + public func OldChannels_InactiveYear(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[122 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[52 * 6 + Int(form.rawValue)]!, stringValue) } - public func SharedMedia_Video(_ value: Int32) -> String { + public func PUSH_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[53 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func MessageTimer_ShortHours(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[123 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[54 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Months(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[55 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedFiles(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[56 * 6 + Int(form.rawValue)]!, stringValue) } public func Map_ETAHours(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[124 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[57 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedPolls(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[58 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHAT_MESSAGE_FWDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[59 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func Notifications_ExceptionMuteExpires_Days(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[60 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[61 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func PUSH_CHAT_MESSAGES(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[62 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func StickerPack_AddMaskCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[63 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Seconds(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[64 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedAudios(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[65 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedVideoMessages(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[66 * 6 + Int(form.rawValue)]!, stringValue) + } + public func SharedMedia_Link(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[67 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Conversation_SelectedMessages(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[68 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedContacts(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[69 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedPhotos(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[70 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Forward_ConfirmMultipleFiles(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[71 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[72 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func OldChannels_InactiveWeek(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[73 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Watch_LastSeen_HoursAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[74 * 6 + Int(form.rawValue)]!, stringValue) + } + public func AttachmentMenu_SendGif(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[75 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[76 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func VoiceOver_Chat_PollOptionCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[77 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notifications_ExceptionMuteExpires_Minutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[78 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedVideos(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[79 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Map_ETAMinutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[80 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Call_ShortMinutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[81 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[82 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func MessageTimer_Years(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[83 * 6 + Int(form.rawValue)]!, stringValue) + } + public func SharedMedia_File(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[84 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedMessages(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[85 * 6 + Int(form.rawValue)]!, stringValue) + } + public func StickerPack_StickerCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[86 * 6 + Int(form.rawValue)]!, stringValue) + } + public func SharedMedia_DeleteItemsConfirmation(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[87 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[88 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func ServiceMessage_GameScoreSelfExtended(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[89 * 6 + Int(form.rawValue)]!, stringValue) + } + public func SharedMedia_Photo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[90 * 6 + Int(form.rawValue)]!, stringValue) + } + public func GroupInfo_ParticipantCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[91 * 6 + Int(form.rawValue)]!, stringValue) + } + public func QuickSend_Photos(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[92 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Media_SharePhoto(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[93 * 6 + Int(form.rawValue)]!, stringValue) } public func Conversation_StatusOnline(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[94 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortMinutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[95 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Wallet_Updated_HoursAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[96 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MuteFor_Hours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[97 * 6 + Int(form.rawValue)]!, stringValue) + } + public func AttachmentMenu_SendItem(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[98 * 6 + Int(form.rawValue)]!, stringValue) + } + public func InviteText_ContactsCountText(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[99 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Media_ShareVideo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[100 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Theme_UsersCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[101 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Call_Seconds(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[102 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Contacts_InviteContacts(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[103 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Invitation_Members(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[104 * 6 + Int(form.rawValue)]!, stringValue) + } + public func LastSeen_HoursAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[105 * 6 + Int(form.rawValue)]!, stringValue) + } + public func AttachmentMenu_SendPhoto(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[106 * 6 + Int(form.rawValue)]!, stringValue) + } + public func OldChannels_InactiveMonth(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[107 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notification_GameScoreSimple(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[108 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PrivacyLastSeenSettings_AddUsers(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[109 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedLocations(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[110 * 6 + Int(form.rawValue)]!, stringValue) + } + public func StickerPack_RemoveMaskCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[111 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ServiceMessage_GameScoreSimple(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[112 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Conversation_StatusSubscribers(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[113 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedStickers(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[114 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MuteFor_Days(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[115 * 6 + Int(form.rawValue)]!, stringValue) + } + public func OldChannels_GroupFormat(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[116 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedAuthorsOthers(_ selector: Int32, _ _0: String, _ _1: String) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[117 * 6 + Int(form.rawValue)]!, _0, _1) + } + public func Watch_LastSeen_MinutesAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[118 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortDays(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[119 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessagePoll_QuizCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[120 * 6 + Int(form.rawValue)]!, stringValue) + } + public func VoiceOver_Chat_ContactPhoneNumberCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[121 * 6 + Int(form.rawValue)]!, stringValue) + } + public func VoiceOver_Chat_ContactEmailCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[122 * 6 + Int(form.rawValue)]!, stringValue) + } + public func AttachmentMenu_SendVideo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[123 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortSeconds(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[124 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Hours(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[125 * 6 + Int(form.rawValue)]!, stringValue) diff --git a/submodules/TelegramUI/TelegramUI/Resources/PresentationStrings.mapping b/submodules/TelegramUI/TelegramUI/Resources/PresentationStrings.mapping index aab4fb144de75691c1805eb292a35ee88189e6ef..a3515d8ffabdb90d9476d7ca81f5cf17db70253d 100644 GIT binary patch delta 35138 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 delta 35342 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 From fd52c04fc2bbb4d062d6f8310b96aac8cbaf3e8a Mon Sep 17 00:00:00 2001 From: Ali <> Date: Tue, 21 Jan 2020 23:02:12 +0400 Subject: [PATCH 13/50] Bubble handling improvements --- .../BubbleSettingsController.swift | 44 +-- .../Text Size/TextSizeSelectionItem.swift | 302 ++++++++++++++++++ .../Sources/ChatMessageBubbleImages.swift | 32 +- .../PresentationThemeEssentialGraphics.swift | 20 +- .../Resources/PresentationResourceKey.swift | 4 +- .../Resources/PresentationResourcesChat.swift | 8 +- .../TelegramUI/ChatController.swift | 3 +- .../TelegramUI/ChatControllerNode.swift | 4 +- .../TelegramUI/TelegramUI/ChatEmptyNode.swift | 6 +- .../TelegramUI/TelegramUI/ChatHoleItem.swift | 2 +- .../TelegramUI/ChatLoadingNode.swift | 4 +- .../ChatMessageActionButtonsNode.swift | 14 +- .../ChatMessageAnimatedStickerItemNode.swift | 8 +- ...eBubbleContentCalclulateImageCorners.swift | 16 +- .../ChatMessageBubbleContentNode.swift | 2 + .../ChatMessageBubbleItemNode.swift | 22 +- .../ChatMessageInstantVideoItemNode.swift | 10 +- .../TelegramUI/ChatMessageItemView.swift | 2 +- .../ChatMessageMediaBubbleContentNode.swift | 2 +- .../TelegramUI/ChatMessageReplyInfoNode.swift | 2 +- .../ChatMessageStickerItemNode.swift | 8 +- .../ChatPresentationInterfaceState.swift | 84 ++--- .../ChatRecentActionsControllerNode.swift | 4 +- .../ChatRecentActionsEmptyNode.swift | 4 +- .../PeerMediaCollectionControllerNode.swift | 2 +- 25 files changed, 456 insertions(+), 153 deletions(-) create mode 100644 submodules/SettingsUI/Sources/Text Size/TextSizeSelectionItem.swift diff --git a/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift b/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift index 769aa9f3c5..780335a936 100644 --- a/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift +++ b/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift @@ -405,7 +405,7 @@ private final class BubbleSettingsToolbarNode: ASDisplayNode { private let topSeparatorNode = ASDisplayNode() private var switchItemNode: ItemListSwitchItemNode - private var cornerRadiusItemNode: ThemeSettingsFontSizeItemNode + private var cornerRadiusItemNode: BubbleSettingsRadiusItemNode private(set) var customMode: TextSelectionCustomMode = .chat @@ -420,7 +420,7 @@ private final class BubbleSettingsToolbarNode: ASDisplayNode { self.presentationData = presentationData self.switchItemNode = ItemListSwitchItemNode(type: .regular) - self.cornerRadiusItemNode = ThemeSettingsFontSizeItemNode() + self.cornerRadiusItemNode = BubbleSettingsRadiusItemNode() super.init() @@ -489,44 +489,8 @@ private final class BubbleSettingsToolbarNode: ASDisplayNode { let switchItem = ItemListSwitchItem(presentationData: ItemListPresentationData(self.presentationData), title: self.presentationData.strings.Appearance_BubbleCorners_AdjustAdjacent, value: self.presentationThemeSettings.chatBubbleSettings.mergeBubbleCorners, disableLeadingInset: true, sectionId: 0, style: .blocks, updated: { [weak self] value in self?.updateMergeBubbleCorners?(value) }) - let fontSize: PresentationFontSize - switch Int(self.presentationData.chatBubbleCorners.mainRadius) { - case 4: - fontSize = .extraSmall - case 6: - fontSize = .small - case 8: - fontSize = .medium - case 10: - fontSize = .regular - case 12: - fontSize = .large - case 14: - fontSize = .extraLarge - case 16: - fontSize = .extraLargeX2 - default: - fontSize = .extraLargeX2 - } - let cornerRadiusItem = ThemeSettingsFontSizeItem(theme: self.presentationData.theme, fontSize: fontSize, enabled: true, disableLeadingInset: false, displayIcons: false, force: false, sectionId: 0, updated: { [weak self] value in - let numericValue: Int32 - switch value { - case .extraSmall: - numericValue = 4 - case .small: - numericValue = 6 - case .medium: - numericValue = 8 - case .regular: - numericValue = 10 - case .large: - numericValue = 12 - case .extraLarge: - numericValue = 14 - case .extraLargeX2: - numericValue = 16 - } - self?.updateCornerRadius?(numericValue) + let cornerRadiusItem = BubbleSettingsRadiusItem(theme: self.presentationData.theme, value: Int(self.presentationData.chatBubbleCorners.mainRadius), enabled: true, disableLeadingInset: false, displayIcons: false, force: false, sectionId: 0, updated: { [weak self] value in + self?.updateCornerRadius?(Int32(max(8, min(16, value)))) }) /*switchItem.updateNode(async: { f in diff --git a/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionItem.swift b/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionItem.swift new file mode 100644 index 0000000000..d714a7a6bc --- /dev/null +++ b/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionItem.swift @@ -0,0 +1,302 @@ +import Foundation +import UIKit +import Display +import AsyncDisplayKit +import SwiftSignalKit +import TelegramCore +import SyncCore +import TelegramPresentationData +import TelegramUIPreferences +import LegacyComponents +import ItemListUI +import PresentationDataUtils +import AppBundle + +class BubbleSettingsRadiusItem: ListViewItem, ItemListItem { + let theme: PresentationTheme + let value: Int + let disableLeadingInset: Bool + let displayIcons: Bool + let force: Bool + let enabled: Bool + let sectionId: ItemListSectionId + let updated: (Int) -> Void + let tag: ItemListItemTag? + + init(theme: PresentationTheme, value: Int, enabled: Bool = true, disableLeadingInset: Bool = false, displayIcons: Bool = true, force: Bool = false, sectionId: ItemListSectionId, updated: @escaping (Int) -> Void, tag: ItemListItemTag? = nil) { + self.theme = theme + self.value = value + self.enabled = enabled + self.disableLeadingInset = disableLeadingInset + self.displayIcons = displayIcons + self.force = force + self.sectionId = sectionId + self.updated = updated + self.tag = tag + } + + func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal?, (ListViewItemApply) -> Void)) -> Void) { + async { + let node = BubbleSettingsRadiusItemNode() + let (layout, apply) = node.asyncLayout()(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem)) + + node.contentSize = layout.contentSize + node.insets = layout.insets + + Queue.mainQueue().async { + completion(node, { + return (nil, { _ in apply() }) + }) + } + } + } + + func updateNode(async: @escaping (@escaping () -> Void) -> Void, node: @escaping () -> ListViewItemNode, params: ListViewItemLayoutParams, previousItem: ListViewItem?, nextItem: ListViewItem?, animation: ListViewItemUpdateAnimation, completion: @escaping (ListViewItemNodeLayout, @escaping (ListViewItemApply) -> Void) -> Void) { + Queue.mainQueue().async { + if let nodeValue = node() as? BubbleSettingsRadiusItemNode { + let makeLayout = nodeValue.asyncLayout() + + async { + let (layout, apply) = makeLayout(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem)) + Queue.mainQueue().async { + completion(layout, { _ in + apply() + }) + } + } + } + } + } +} + +private func generateKnobImage() -> UIImage? { + return generateImage(CGSize(width: 40.0, height: 40.0), rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + context.setShadow(offset: CGSize(width: 0.0, height: -1.0), blur: 3.5, color: UIColor(white: 0.0, alpha: 0.25).cgColor) + context.setFillColor(UIColor.white.cgColor) + context.fillEllipse(in: CGRect(origin: CGPoint(x: 6.0, y: 6.0), size: CGSize(width: 28.0, height: 28.0))) + }) +} + +class BubbleSettingsRadiusItemNode: ListViewItemNode, ItemListItemNode { + private let backgroundNode: ASDisplayNode + private let topStripeNode: ASDisplayNode + private let bottomStripeNode: ASDisplayNode + private let maskNode: ASImageNode + + private var sliderView: TGPhotoEditorSliderView? + private let leftIconNode: ASImageNode + private let rightIconNode: ASImageNode + private let disabledOverlayNode: ASDisplayNode + + private var item: BubbleSettingsRadiusItem? + private var layoutParams: ListViewItemLayoutParams? + + var tag: ItemListItemTag? { + return self.item?.tag + } + + init() { + self.backgroundNode = ASDisplayNode() + self.backgroundNode.isLayerBacked = true + + self.topStripeNode = ASDisplayNode() + self.topStripeNode.isLayerBacked = true + + self.bottomStripeNode = ASDisplayNode() + self.bottomStripeNode.isLayerBacked = true + + self.maskNode = ASImageNode() + + self.leftIconNode = ASImageNode() + self.leftIconNode.displaysAsynchronously = false + self.leftIconNode.displayWithoutProcessing = true + + self.rightIconNode = ASImageNode() + self.rightIconNode.displaysAsynchronously = false + self.rightIconNode.displayWithoutProcessing = true + + self.disabledOverlayNode = ASDisplayNode() + + super.init(layerBacked: false, dynamicBounce: false) + + self.addSubnode(self.leftIconNode) + self.addSubnode(self.rightIconNode) + + self.addSubnode(self.disabledOverlayNode) + } + + override func didLoad() { + super.didLoad() + + let sliderView = TGPhotoEditorSliderView() + sliderView.enablePanHandling = true + sliderView.enablePanHandling = true + sliderView.trackCornerRadius = 1.0 + sliderView.lineSize = 2.0 + sliderView.dotSize = 5.0 + sliderView.minimumValue = 0.0 + sliderView.maximumValue = 4.0 + sliderView.startValue = 0.0 + sliderView.positionsCount = 5 + sliderView.disablesInteractiveTransitionGestureRecognizer = true + if let item = self.item, let params = self.layoutParams { + sliderView.isUserInteractionEnabled = item.enabled + + sliderView.value = CGFloat((item.value - 8) / 2) + sliderView.backgroundColor = item.theme.list.itemBlocksBackgroundColor + sliderView.backColor = item.theme.list.disclosureArrowColor + sliderView.trackColor = item.enabled ? item.theme.list.itemAccentColor : item.theme.list.itemDisabledTextColor + sliderView.knobImage = generateKnobImage() + + let sliderInset: CGFloat = item.displayIcons ? 38.0 : 16.0 + + sliderView.frame = CGRect(origin: CGPoint(x: params.leftInset + sliderInset, y: 8.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - sliderInset * 2.0, height: 44.0)) + } + self.view.insertSubview(sliderView, belowSubview: self.disabledOverlayNode.view) + sliderView.addTarget(self, action: #selector(self.sliderValueChanged), for: .valueChanged) + self.sliderView = sliderView + } + + func asyncLayout() -> (_ item: BubbleSettingsRadiusItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) { + let currentItem = self.item + + return { item, params, neighbors in + var updatedLeftIcon: UIImage? + var updatedRightIcon: UIImage? + + var themeUpdated = false + if currentItem?.theme !== item.theme { + themeUpdated = true + + updatedLeftIcon = generateTintedImage(image: UIImage(bundleImageName: "Instant View/SettingsFontMinIcon"), color: item.theme.list.itemPrimaryTextColor) + updatedRightIcon = generateTintedImage(image: UIImage(bundleImageName: "Instant View/SettingsFontMaxIcon"), color: item.theme.list.itemPrimaryTextColor) + } + + let contentSize: CGSize + var insets: UIEdgeInsets + let separatorHeight = UIScreenPixel + + contentSize = CGSize(width: params.width, height: 60.0) + insets = itemListNeighborsGroupedInsets(neighbors) + + if item.disableLeadingInset { + insets.top = 0.0 + insets.bottom = 0.0 + } + + let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets) + let layoutSize = layout.size + + return (layout, { [weak self] in + if let strongSelf = self { + let firstTime = strongSelf.item == nil || item.force + strongSelf.item = item + strongSelf.layoutParams = params + + strongSelf.backgroundNode.backgroundColor = item.theme.list.itemBlocksBackgroundColor + strongSelf.topStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor + strongSelf.bottomStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor + + strongSelf.disabledOverlayNode.backgroundColor = item.theme.list.itemBlocksBackgroundColor.withAlphaComponent(0.4) + strongSelf.disabledOverlayNode.isHidden = item.enabled + strongSelf.disabledOverlayNode.frame = CGRect(origin: CGPoint(x: params.leftInset, y: 8.0), size: CGSize(width: params.width - params.leftInset - params.rightInset, height: 44.0)) + + if strongSelf.backgroundNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0) + } + if strongSelf.topStripeNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.topStripeNode, at: 1) + } + if strongSelf.bottomStripeNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) + } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + let hasCorners = itemListHasRoundedBlockLayout(params) + var hasTopCorners = false + var hasBottomCorners = false + switch neighbors.top { + case .sameSection(false): + strongSelf.topStripeNode.isHidden = true + default: + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners + } + let bottomStripeInset: CGFloat + let bottomStripeOffset: CGFloat + switch neighbors.bottom { + case .sameSection(false): + bottomStripeInset = params.leftInset + 16.0 + bottomStripeOffset = -separatorHeight + default: + bottomStripeInset = 0.0 + bottomStripeOffset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners + } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) + strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight)) + strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight)) + + if let updatedLeftIcon = updatedLeftIcon { + strongSelf.leftIconNode.image = updatedLeftIcon + } + if let image = strongSelf.leftIconNode.image { + strongSelf.leftIconNode.frame = CGRect(origin: CGPoint(x: params.leftInset + 18.0, y: 25.0), size: CGSize(width: image.size.width, height: image.size.height)) + } + if let updatedRightIcon = updatedRightIcon { + strongSelf.rightIconNode.image = updatedRightIcon + } + if let image = strongSelf.rightIconNode.image { + strongSelf.rightIconNode.frame = CGRect(origin: CGPoint(x: params.width - params.rightInset - 14.0 - image.size.width, y: 21.0), size: CGSize(width: image.size.width, height: image.size.height)) + } + + strongSelf.leftIconNode.isHidden = !item.displayIcons + strongSelf.rightIconNode.isHidden = !item.displayIcons + + if let sliderView = strongSelf.sliderView { + sliderView.isUserInteractionEnabled = item.enabled + sliderView.trackColor = item.enabled ? item.theme.list.itemAccentColor : item.theme.list.itemDisabledTextColor + + if themeUpdated { + sliderView.backgroundColor = item.theme.list.itemBlocksBackgroundColor + sliderView.backColor = item.theme.list.disclosureArrowColor + sliderView.knobImage = generateKnobImage() + } + + let value: CGFloat = CGFloat((item.value - 8) / 2) + if firstTime { + sliderView.value = value + } + + let sliderInset: CGFloat = item.displayIcons ? 38.0 : 16.0 + sliderView.frame = CGRect(origin: CGPoint(x: params.leftInset + sliderInset, y: 8.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - sliderInset * 2.0, height: 44.0)) + } + } + }) + } + } + + override func animateInsertion(_ currentTimestamp: Double, duration: Double, short: Bool) { + self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.4) + } + + override func animateRemoved(_ currentTimestamp: Double, duration: Double) { + self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false) + } + + @objc func sliderValueChanged() { + guard let sliderView = self.sliderView else { + return + } + let value = Int(sliderView.value) * 2 + 8 + self.item?.updated(value) + } +} diff --git a/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift b/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift index 36850b476d..a33deb89cc 100644 --- a/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift +++ b/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift @@ -70,7 +70,7 @@ func mediaBubbleCornerImage(incoming: Bool, radius: CGFloat, inset: CGFloat) -> } else { context.fill(CGRect(origin: CGPoint(x: bottomEllipse.minX - 5.0, y: bottomEllipse.midY), size: CGSize(width: bottomEllipse.width + 5.0, height: bottomEllipse.height / 2.0))) } - context.fill(CGRect(origin: CGPoint(x: fixedMainDiameter / 2.0, y: fixedMainDiameter / 2.0), size: CGSize(width: fixedMainDiameter / 2.0, height: bottomEllipse.midY - fixedMainDiameter / 2.0))) + context.fill(CGRect(origin: CGPoint(x: fixedMainDiameter / 2.0, y: floor(fixedMainDiameter / 2.0)), size: CGSize(width: fixedMainDiameter / 2.0, height: ceil(bottomEllipse.midY) - floor(fixedMainDiameter / 2.0)))) context.setFillColor(UIColor.clear.cgColor) context.setBlendMode(.copy) context.fillEllipse(in: topEllipse) @@ -108,13 +108,13 @@ public func messageBubbleImage(maxCornerRadius: CGFloat, minCornerRadius: CGFloa case .side: topLeftRadius = maxCornerRadius topRightRadius = maxCornerRadius - bottomLeftRadius = maxCornerRadius - bottomRightRadius = maxCornerRadius + bottomLeftRadius = minCornerRadius + bottomRightRadius = minCornerRadius drawTail = false case let .top(side): topLeftRadius = maxCornerRadius - topRightRadius = side ? minCornerRadius : maxCornerRadius - bottomLeftRadius = maxCornerRadius + topRightRadius = maxCornerRadius + bottomLeftRadius = side ? minCornerRadius : maxCornerRadius bottomRightRadius = minCornerRadius drawTail = false } @@ -162,7 +162,7 @@ public func messageBubbleImage(maxCornerRadius: CGFloat, minCornerRadius: CGFloa } else { context.fill(CGRect(origin: CGPoint(x: bottomEllipse.minX - 2.0, y: bottomEllipse.midY), size: CGSize(width: bottomEllipse.width + 2.0, height: bottomEllipse.height / 2.0))) } - context.fill(CGRect(origin: CGPoint(x: fixedMainDiameter / 2.0, y: fixedMainDiameter / 2.0), size: CGSize(width: fixedMainDiameter / 2.0, height: bottomEllipse.midY - fixedMainDiameter / 2.0))) + context.fill(CGRect(origin: CGPoint(x: fixedMainDiameter / 2.0, y: floor(fixedMainDiameter / 2.0)), size: CGSize(width: fixedMainDiameter / 2.0, height: ceil(bottomEllipse.midY) - floor(fixedMainDiameter / 2.0)))) context.setFillColor(UIColor.clear.cgColor) context.setBlendMode(.copy) context.fillEllipse(in: topEllipse) @@ -206,9 +206,9 @@ public func messageBubbleImage(maxCornerRadius: CGFloat, minCornerRadius: CGFloa context.addQuadCurve(to: CGPoint(x: bottomEllipse.maxX, y: bottomEllipse.midY), control: CGPoint(x: bottomEllipse.maxX, y: bottomEllipse.maxY)) context.fillPath() } else { - context.fill(CGRect(origin: CGPoint(x: bottomEllipse.minX - 2.0, y: bottomEllipse.midY), size: CGSize(width: bottomEllipse.width + 2.0, height: bottomEllipse.height / 2.0))) + context.fill(CGRect(origin: CGPoint(x: bottomEllipse.minX - 2.0, y: floor(bottomEllipse.midY)), size: CGSize(width: bottomEllipse.width + 2.0, height: ceil(bottomEllipse.height / 2.0)))) } - context.fill(CGRect(origin: CGPoint(x: fixedMainDiameter / 2.0, y: fixedMainDiameter / 2.0), size: CGSize(width: fixedMainDiameter / 2.0 + borderWidth, height: bottomEllipse.midY - fixedMainDiameter / 2.0))) + context.fill(CGRect(origin: CGPoint(x: floor(fixedMainDiameter / 2.0), y: fixedMainDiameter / 2.0), size: CGSize(width: fixedMainDiameter / 2.0 + borderWidth, height: ceil(bottomEllipse.midY) - floor(fixedMainDiameter / 2.0)))) context.setBlendMode(.normal) context.move(to: CGPoint(x: fixedMainDiameter + borderOffset, y: fixedMainDiameter / 2.0)) @@ -269,7 +269,13 @@ public func messageBubbleImage(maxCornerRadius: CGFloat, minCornerRadius: CGFloa context.translateBy(x: additionalInset + strokeInset, y: additionalInset + strokeInset) } } - let outlineImage = outlineContext.generateImage()! + let outlineImage = generateImage(outlineContext.size, contextGenerator: { size, context in + context.setBlendMode(.copy) + let image = outlineContext.generateImage()! + context.draw(image.cgImage!, in: CGRect(origin: CGPoint(), size: size)) + context.setBlendMode(.normal) + context.draw(image.cgImage!, in: CGRect(origin: CGPoint(), size: size)) + })! let drawingContext = DrawingContext(size: imageSize) drawingContext.withFlippedContext { context in @@ -323,14 +329,14 @@ public enum MessageBubbleActionButtonPosition { case bottomSingle } -public func messageBubbleActionButtonImage(color: UIColor, strokeColor: UIColor, position: MessageBubbleActionButtonPosition) -> UIImage { - let largeRadius: CGFloat = 17.0 - let smallRadius: CGFloat = 6.0 +public func messageBubbleActionButtonImage(color: UIColor, strokeColor: UIColor, position: MessageBubbleActionButtonPosition, bubbleCorners: PresentationChatBubbleCorners) -> UIImage { + let largeRadius: CGFloat = bubbleCorners.mainRadius + let smallRadius: CGFloat = (bubbleCorners.mergeBubbleCorners && largeRadius >= 10.0) ? bubbleCorners.auxiliaryRadius : bubbleCorners.mainRadius let size: CGSize if case .middle = position { size = CGSize(width: smallRadius + smallRadius, height: smallRadius + smallRadius) } else { - size = CGSize(width: 35.0, height: 35.0) + size = CGSize(width: largeRadius + largeRadius, height: largeRadius + largeRadius) } return generateImage(size, contextGenerator: { size, context in context.clear(CGRect(origin: CGPoint(), size: size)) diff --git a/submodules/TelegramPresentationData/Sources/PresentationThemeEssentialGraphics.swift b/submodules/TelegramPresentationData/Sources/PresentationThemeEssentialGraphics.swift index d5a0f0fc3a..3374f03b51 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationThemeEssentialGraphics.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationThemeEssentialGraphics.swift @@ -216,7 +216,7 @@ public final class PrincipalThemeEssentialGraphics { let serviceColor = serviceMessageColorComponents(chatTheme: theme, wallpaper: wallpaper) let maxCornerRadius = bubbleCorners.mainRadius - let minCornerRadius = bubbleCorners.mergeBubbleCorners ? bubbleCorners.auxiliaryRadius : bubbleCorners.mainRadius + let minCornerRadius = (bubbleCorners.mergeBubbleCorners && maxCornerRadius >= 10.0) ? bubbleCorners.auxiliaryRadius : bubbleCorners.mainRadius let emptyImage = UIImage() if preview { @@ -423,7 +423,7 @@ public final class PrincipalThemeAdditionalGraphics { public let chatEmptyItemLockIcon: UIImage public let emptyChatListCheckIcon: UIImage - init(_ theme: PresentationThemeChat, wallpaper: TelegramWallpaper) { + init(_ theme: PresentationThemeChat, wallpaper: TelegramWallpaper, bubbleCorners: PresentationChatBubbleCorners) { let serviceColor = serviceMessageColorComponents(chatTheme: theme, wallpaper: wallpaper) self.chatServiceBubbleFillImage = generateImage(CGSize(width: 20.0, height: 20.0), contextGenerator: { size, context -> Void in context.clear(CGRect(origin: CGPoint(), size: size)) @@ -444,14 +444,14 @@ public final class PrincipalThemeAdditionalGraphics { self.chatBubbleShareButtonImage = chatBubbleActionButtonImage(fillColor: bubbleVariableColor(variableColor: theme.message.shareButtonFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.shareButtonStrokeColor, wallpaper: wallpaper), foregroundColor: bubbleVariableColor(variableColor: theme.message.shareButtonForegroundColor, wallpaper: wallpaper), image: UIImage(bundleImageName: "Chat/Message/ShareIcon"))! self.chatBubbleNavigateButtonImage = chatBubbleActionButtonImage(fillColor: bubbleVariableColor(variableColor: theme.message.shareButtonFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.shareButtonStrokeColor, wallpaper: wallpaper), foregroundColor: bubbleVariableColor(variableColor: theme.message.shareButtonForegroundColor, wallpaper: wallpaper), image: UIImage(bundleImageName: "Chat/Message/NavigateToMessageIcon"), iconOffset: CGPoint(x: 0.0, y: 1.0))! - self.chatBubbleActionButtonIncomingMiddleImage = messageBubbleActionButtonImage(color: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsStrokeColor, wallpaper: wallpaper), position: .middle) - self.chatBubbleActionButtonIncomingBottomLeftImage = messageBubbleActionButtonImage(color: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsStrokeColor, wallpaper: wallpaper), position: .bottomLeft) - self.chatBubbleActionButtonIncomingBottomRightImage = messageBubbleActionButtonImage(color: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsStrokeColor, wallpaper: wallpaper), position: .bottomRight) - self.chatBubbleActionButtonIncomingBottomSingleImage = messageBubbleActionButtonImage(color: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsStrokeColor, wallpaper: wallpaper), position: .bottomSingle) - self.chatBubbleActionButtonOutgoingMiddleImage = messageBubbleActionButtonImage(color: bubbleVariableColor(variableColor: theme.message.outgoing.actionButtonsFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.outgoing.actionButtonsStrokeColor, wallpaper: wallpaper), position: .middle) - self.chatBubbleActionButtonOutgoingBottomLeftImage = messageBubbleActionButtonImage(color: bubbleVariableColor(variableColor: theme.message.outgoing.actionButtonsFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.outgoing.actionButtonsStrokeColor, wallpaper: wallpaper), position: .bottomLeft) - self.chatBubbleActionButtonOutgoingBottomRightImage = messageBubbleActionButtonImage(color: bubbleVariableColor(variableColor: theme.message.outgoing.actionButtonsFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.outgoing.actionButtonsStrokeColor, wallpaper: wallpaper), position: .bottomRight) - self.chatBubbleActionButtonOutgoingBottomSingleImage = messageBubbleActionButtonImage(color: bubbleVariableColor(variableColor: theme.message.outgoing.actionButtonsFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.outgoing.actionButtonsStrokeColor, wallpaper: wallpaper), position: .bottomSingle) + self.chatBubbleActionButtonIncomingMiddleImage = messageBubbleActionButtonImage(color: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsStrokeColor, wallpaper: wallpaper), position: .middle, bubbleCorners: bubbleCorners) + self.chatBubbleActionButtonIncomingBottomLeftImage = messageBubbleActionButtonImage(color: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsStrokeColor, wallpaper: wallpaper), position: .bottomLeft, bubbleCorners: bubbleCorners) + self.chatBubbleActionButtonIncomingBottomRightImage = messageBubbleActionButtonImage(color: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsStrokeColor, wallpaper: wallpaper), position: .bottomRight, bubbleCorners: bubbleCorners) + self.chatBubbleActionButtonIncomingBottomSingleImage = messageBubbleActionButtonImage(color: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsStrokeColor, wallpaper: wallpaper), position: .bottomSingle, bubbleCorners: bubbleCorners) + self.chatBubbleActionButtonOutgoingMiddleImage = messageBubbleActionButtonImage(color: bubbleVariableColor(variableColor: theme.message.outgoing.actionButtonsFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.outgoing.actionButtonsStrokeColor, wallpaper: wallpaper), position: .middle, bubbleCorners: bubbleCorners) + self.chatBubbleActionButtonOutgoingBottomLeftImage = messageBubbleActionButtonImage(color: bubbleVariableColor(variableColor: theme.message.outgoing.actionButtonsFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.outgoing.actionButtonsStrokeColor, wallpaper: wallpaper), position: .bottomLeft, bubbleCorners: bubbleCorners) + self.chatBubbleActionButtonOutgoingBottomRightImage = messageBubbleActionButtonImage(color: bubbleVariableColor(variableColor: theme.message.outgoing.actionButtonsFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.outgoing.actionButtonsStrokeColor, wallpaper: wallpaper), position: .bottomRight, bubbleCorners: bubbleCorners) + self.chatBubbleActionButtonOutgoingBottomSingleImage = messageBubbleActionButtonImage(color: bubbleVariableColor(variableColor: theme.message.outgoing.actionButtonsFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.outgoing.actionButtonsStrokeColor, wallpaper: wallpaper), position: .bottomSingle, bubbleCorners: bubbleCorners) self.chatBubbleActionButtonIncomingMessageIconImage = generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/BotMessage"), color: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsTextColor, wallpaper: wallpaper))! self.chatBubbleActionButtonIncomingLinkIconImage = generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/BotLink"), color: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsTextColor, wallpaper: wallpaper))! self.chatBubbleActionButtonIncomingShareIconImage = generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/BotShare"), color: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsTextColor, wallpaper: wallpaper))! diff --git a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift index 82815c9990..0c11f4342c 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift @@ -78,9 +78,6 @@ public enum PresentationResourceKey: Int32 { case chatTitleLockIcon case chatTitleMuteIcon - case chatPrincipalThemeAdditionalGraphicsWithCustomWallpaper - case chatPrincipalThemeAdditionalGraphicsWithDefaultWallpaper - case chatBubbleVerticalLineIncomingImage case chatBubbleVerticalLineOutgoingImage @@ -235,4 +232,5 @@ public enum PresentationResourceParameterKey: Hashable { case chatBubbleMediaCorner(incoming: Bool, mainRadius: CGFloat, inset: CGFloat) case chatPrincipalThemeEssentialGraphics(hasWallpaper: Bool, bubbleCorners: PresentationChatBubbleCorners) + case chatPrincipalThemeAdditionalGraphics(isCustomWallpaper: Bool, bubbleCorners: PresentationChatBubbleCorners) } diff --git a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift index 39e872972a..c639d5bfa1 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift @@ -76,10 +76,10 @@ public struct PresentationResourcesChat { }) as! PrincipalThemeEssentialGraphics } - public static func additionalGraphics(_ theme: PresentationTheme, wallpaper: TelegramWallpaper) -> PrincipalThemeAdditionalGraphics { - let key: PresentationResourceKey = wallpaper.isBuiltin ? PresentationResourceKey.chatPrincipalThemeAdditionalGraphicsWithDefaultWallpaper : PresentationResourceKey.chatPrincipalThemeAdditionalGraphicsWithCustomWallpaper - return theme.object(key.rawValue, { theme in - return PrincipalThemeAdditionalGraphics(theme.chat, wallpaper: wallpaper) + public static func additionalGraphics(_ theme: PresentationTheme, wallpaper: TelegramWallpaper, bubbleCorners: PresentationChatBubbleCorners) -> PrincipalThemeAdditionalGraphics { + let key: PresentationResourceParameterKey = .chatPrincipalThemeAdditionalGraphics(isCustomWallpaper: !wallpaper.isBuiltin, bubbleCorners: bubbleCorners) + return theme.object(key, { theme in + return PrincipalThemeAdditionalGraphics(theme.chat, wallpaper: wallpaper, bubbleCorners: bubbleCorners) }) as! PrincipalThemeAdditionalGraphics } diff --git a/submodules/TelegramUI/TelegramUI/ChatController.swift b/submodules/TelegramUI/TelegramUI/ChatController.swift index b07dae10d7..80b1f3f7ad 100644 --- a/submodules/TelegramUI/TelegramUI/ChatController.swift +++ b/submodules/TelegramUI/TelegramUI/ChatController.swift @@ -346,7 +346,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G isScheduledMessages = true } - self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: self.presentationData.chatWallpaper, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: context.currentLimitsConfiguration.with { $0 }, fontSize: self.presentationData.chatFontSize, accountPeerId: context.account.peerId, mode: mode, chatLocation: chatLocation, isScheduledMessages: isScheduledMessages) + self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: self.presentationData.chatWallpaper, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: context.currentLimitsConfiguration.with { $0 }, fontSize: self.presentationData.chatFontSize, bubbleCorners: self.presentationData.chatBubbleCorners, accountPeerId: context.account.peerId, mode: mode, chatLocation: chatLocation, isScheduledMessages: isScheduledMessages) var mediaAccessoryPanelVisibility = MediaAccessoryPanelVisibility.none if case .standard = mode { @@ -2538,6 +2538,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G state = state.updatedStrings(self.presentationData.strings) state = state.updatedDateTimeFormat(self.presentationData.dateTimeFormat) state = state.updatedChatWallpaper(self.presentationData.chatWallpaper) + state = state.updatedBubbleCorners(self.presentationData.chatBubbleCorners) return state }) diff --git a/submodules/TelegramUI/TelegramUI/ChatControllerNode.swift b/submodules/TelegramUI/TelegramUI/ChatControllerNode.swift index 9ebd21cde6..b4d9552cd5 100644 --- a/submodules/TelegramUI/TelegramUI/ChatControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatControllerNode.swift @@ -225,7 +225,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.reactionContainerNode = ReactionSelectionParentNode(account: context.account, theme: chatPresentationInterfaceState.theme) - self.loadingNode = ChatLoadingNode(theme: self.chatPresentationInterfaceState.theme, chatWallpaper: self.chatPresentationInterfaceState.chatWallpaper) + self.loadingNode = ChatLoadingNode(theme: self.chatPresentationInterfaceState.theme, chatWallpaper: self.chatPresentationInterfaceState.chatWallpaper, bubbleCorners: self.chatPresentationInterfaceState.bubbleCorners) self.inputPanelBackgroundNode = ASDisplayNode() if case let .color(color) = self.chatPresentationInterfaceState.chatWallpaper, UIColor(rgb: color).isEqual(self.chatPresentationInterfaceState.theme.chat.inputPanel.panelBackgroundColorNoWallpaper) { @@ -1512,7 +1512,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { if let restrictionText = restrictionText { if self.restrictedNode == nil { - let restrictedNode = ChatRecentActionsEmptyNode(theme: chatPresentationInterfaceState.theme, chatWallpaper: chatPresentationInterfaceState.chatWallpaper) + let restrictedNode = ChatRecentActionsEmptyNode(theme: chatPresentationInterfaceState.theme, chatWallpaper: chatPresentationInterfaceState.chatWallpaper, chatBubbleCorners: chatPresentationInterfaceState.bubbleCorners) self.historyNodeContainer.supernode?.insertSubnode(restrictedNode, aboveSubnode: self.historyNodeContainer) self.restrictedNode = restrictedNode } diff --git a/submodules/TelegramUI/TelegramUI/ChatEmptyNode.swift b/submodules/TelegramUI/TelegramUI/ChatEmptyNode.swift index 57b0fef12d..c0f8623b98 100644 --- a/submodules/TelegramUI/TelegramUI/ChatEmptyNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatEmptyNode.swift @@ -121,7 +121,7 @@ private final class ChatEmptyNodeSecretChatContent: ASDisplayNode, ChatEmptyNode let lines: [NSAttributedString] = strings.map { NSAttributedString(string: $0, font: messageFont, textColor: serviceColor.primaryText) } - let graphics = PresentationResourcesChat.additionalGraphics(interfaceState.theme, wallpaper: interfaceState.chatWallpaper) + let graphics = PresentationResourcesChat.additionalGraphics(interfaceState.theme, wallpaper: interfaceState.chatWallpaper, bubbleCorners: interfaceState.bubbleCorners) let lockIcon = graphics.chatEmptyItemLockIcon for i in 0 ..< lines.count { @@ -237,7 +237,7 @@ private final class ChatEmptyNodeGroupChatContent: ASDisplayNode, ChatEmptyNodeC let lines: [NSAttributedString] = strings.map { NSAttributedString(string: $0, font: messageFont, textColor: serviceColor.primaryText) } - let graphics = PresentationResourcesChat.additionalGraphics(interfaceState.theme, wallpaper: interfaceState.chatWallpaper) + let graphics = PresentationResourcesChat.additionalGraphics(interfaceState.theme, wallpaper: interfaceState.chatWallpaper, bubbleCorners: interfaceState.bubbleCorners) let lockIcon = graphics.emptyChatListCheckIcon for i in 0 ..< lines.count { @@ -453,7 +453,7 @@ final class ChatEmptyNode: ASDisplayNode { self.currentTheme = interfaceState.theme self.currentStrings = interfaceState.strings - let graphics = PresentationResourcesChat.additionalGraphics(interfaceState.theme, wallpaper: interfaceState.chatWallpaper) + let graphics = PresentationResourcesChat.additionalGraphics(interfaceState.theme, wallpaper: interfaceState.chatWallpaper, bubbleCorners: interfaceState.bubbleCorners) self.backgroundNode.image = graphics.chatEmptyItemBackgroundImage } diff --git a/submodules/TelegramUI/TelegramUI/ChatHoleItem.swift b/submodules/TelegramUI/TelegramUI/ChatHoleItem.swift index 59c80a38c7..b88cf37698 100644 --- a/submodules/TelegramUI/TelegramUI/ChatHoleItem.swift +++ b/submodules/TelegramUI/TelegramUI/ChatHoleItem.swift @@ -81,7 +81,7 @@ class ChatHoleItemNode: ListViewItemNode { return { item, params, dateAtBottom in var updatedBackground: UIImage? if item.presentationData.theme !== currentItem?.presentationData.theme { - let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) + let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper, bubbleCorners: item.presentationData.chatBubbleCorners) updatedBackground = graphics.chatServiceBubbleFillImage } diff --git a/submodules/TelegramUI/TelegramUI/ChatLoadingNode.swift b/submodules/TelegramUI/TelegramUI/ChatLoadingNode.swift index e2280941f0..6cb7638a0b 100644 --- a/submodules/TelegramUI/TelegramUI/ChatLoadingNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatLoadingNode.swift @@ -12,13 +12,13 @@ final class ChatLoadingNode: ASDisplayNode { private let activityIndicator: ActivityIndicator private let offset: CGPoint - init(theme: PresentationTheme, chatWallpaper: TelegramWallpaper) { + init(theme: PresentationTheme, chatWallpaper: TelegramWallpaper, bubbleCorners: PresentationChatBubbleCorners) { self.backgroundNode = ASImageNode() self.backgroundNode.isLayerBacked = true self.backgroundNode.displayWithoutProcessing = true self.backgroundNode.displaysAsynchronously = false - let graphics = PresentationResourcesChat.additionalGraphics(theme, wallpaper: chatWallpaper) + let graphics = PresentationResourcesChat.additionalGraphics(theme, wallpaper: chatWallpaper, bubbleCorners: bubbleCorners) self.backgroundNode.image = graphics.chatLoadingIndicatorBackgroundImage let serviceColor = serviceMessageColorComponents(theme: theme, wallpaper: chatWallpaper) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageActionButtonsNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageActionButtonsNode.swift index af96c3b8f2..ab5189f89b 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageActionButtonsNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageActionButtonsNode.swift @@ -84,12 +84,12 @@ private final class ChatMessageActionButtonNode: ASDisplayNode { } } - class func asyncLayout(_ maybeNode: ChatMessageActionButtonNode?) -> (_ context: AccountContext, _ theme: ChatPresentationThemeData, _ strings: PresentationStrings, _ message: Message, _ button: ReplyMarkupButton, _ constrainedWidth: CGFloat, _ position: MessageBubbleActionButtonPosition) -> (minimumWidth: CGFloat, layout: ((CGFloat) -> (CGSize, () -> ChatMessageActionButtonNode))) { + class func asyncLayout(_ maybeNode: ChatMessageActionButtonNode?) -> (_ context: AccountContext, _ theme: ChatPresentationThemeData, _ bubbleCorners: PresentationChatBubbleCorners, _ strings: PresentationStrings, _ message: Message, _ button: ReplyMarkupButton, _ constrainedWidth: CGFloat, _ position: MessageBubbleActionButtonPosition) -> (minimumWidth: CGFloat, layout: ((CGFloat) -> (CGSize, () -> ChatMessageActionButtonNode))) { let titleLayout = TextNode.asyncLayout(maybeNode?.titleNode) - return { context, theme, strings, message, button, constrainedWidth, position in + return { context, theme, bubbleCorners, strings, message, button, constrainedWidth, position in let incoming = message.effectivelyIncoming(context.account.peerId) - let graphics = PresentationResourcesChat.additionalGraphics(theme.theme, wallpaper: theme.wallpaper) + let graphics = PresentationResourcesChat.additionalGraphics(theme.theme, wallpaper: theme.wallpaper, bubbleCorners: bubbleCorners) let iconImage: UIImage? switch button.action { @@ -216,10 +216,10 @@ final class ChatMessageActionButtonsNode: ASDisplayNode { } } - class func asyncLayout(_ maybeNode: ChatMessageActionButtonsNode?) -> (_ context: AccountContext, _ theme: ChatPresentationThemeData, _ strings: PresentationStrings, _ replyMarkup: ReplyMarkupMessageAttribute, _ message: Message, _ constrainedWidth: CGFloat) -> (minWidth: CGFloat, layout: (CGFloat) -> (CGSize, (_ animated: Bool) -> ChatMessageActionButtonsNode)) { + class func asyncLayout(_ maybeNode: ChatMessageActionButtonsNode?) -> (_ context: AccountContext, _ theme: ChatPresentationThemeData, _ chatBubbleCorners: PresentationChatBubbleCorners, _ strings: PresentationStrings, _ replyMarkup: ReplyMarkupMessageAttribute, _ message: Message, _ constrainedWidth: CGFloat) -> (minWidth: CGFloat, layout: (CGFloat) -> (CGSize, (_ animated: Bool) -> ChatMessageActionButtonsNode)) { let currentButtonLayouts = maybeNode?.buttonNodes.map { ChatMessageActionButtonNode.asyncLayout($0) } ?? [] - return { context, theme, strings, replyMarkup, message, constrainedWidth in + return { context, theme, chatBubbleCorners, strings, replyMarkup, message, constrainedWidth in let buttonHeight: CGFloat = 42.0 let buttonSpacing: CGFloat = 4.0 @@ -252,9 +252,9 @@ final class ChatMessageActionButtonsNode: ASDisplayNode { let prepareButtonLayout: (minimumWidth: CGFloat, layout: ((CGFloat) -> (CGSize, () -> ChatMessageActionButtonNode))) if buttonIndex < currentButtonLayouts.count { - prepareButtonLayout = currentButtonLayouts[buttonIndex](context, theme, strings, message, button, maximumButtonWidth, buttonPosition) + prepareButtonLayout = currentButtonLayouts[buttonIndex](context, theme, chatBubbleCorners, strings, message, button, maximumButtonWidth, buttonPosition) } else { - prepareButtonLayout = ChatMessageActionButtonNode.asyncLayout(nil)(context, theme, strings, message, button, maximumButtonWidth, buttonPosition) + prepareButtonLayout = ChatMessageActionButtonNode.asyncLayout(nil)(context, theme, chatBubbleCorners, strings, message, button, maximumButtonWidth, buttonPosition) } maximumRowButtonWidth = max(maximumRowButtonWidth, prepareButtonLayout.minimumWidth) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift index 3fecaf1419..da8d51b1c8 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift @@ -560,7 +560,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { updatedReplyBackgroundNode = ASImageNode() } - let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) + let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper, bubbleCorners: item.presentationData.chatBubbleCorners) replyBackgroundImage = graphics.chatFreeformContentAdditionalInfoBackgroundImage } @@ -571,7 +571,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { if currentShareButtonNode != nil { updatedShareButtonNode = currentShareButtonNode if item.presentationData.theme !== currentItem?.presentationData.theme { - let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) + let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper, bubbleCorners: item.presentationData.chatBubbleCorners) if item.message.id.peerId == item.context.account.peerId { updatedShareButtonBackground = graphics.chatBubbleNavigateButtonImage } else { @@ -581,7 +581,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { } else { let buttonNode = HighlightableButtonNode() let buttonIcon: UIImage? - let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) + let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper, bubbleCorners: item.presentationData.chatBubbleCorners) if item.message.id.peerId == item.context.account.peerId { buttonIcon = graphics.chatBubbleNavigateButtonImage } else { @@ -596,7 +596,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { var maxContentWidth = imageSize.width var actionButtonsFinalize: ((CGFloat) -> (CGSize, (_ animated: Bool) -> ChatMessageActionButtonsNode))? if let replyMarkup = replyMarkup { - let (minWidth, buttonsLayout) = actionButtonsLayout(item.context, item.presentationData.theme, item.presentationData.strings, replyMarkup, item.message, maxContentWidth) + let (minWidth, buttonsLayout) = actionButtonsLayout(item.context, item.presentationData.theme, item.presentationData.chatBubbleCorners, item.presentationData.strings, replyMarkup, item.message, maxContentWidth) maxContentWidth = max(maxContentWidth, minWidth) actionButtonsFinalize = buttonsLayout } diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleContentCalclulateImageCorners.swift b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleContentCalclulateImageCorners.swift index bb22c33754..7d3fbc07f6 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleContentCalclulateImageCorners.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleContentCalclulateImageCorners.swift @@ -13,6 +13,9 @@ func chatMessageBubbleImageContentCorners(relativeContentPosition position: Chat case .Neighbour: topLeftCorner = .Corner(mergedWithAnotherContentRadius) topRightCorner = .Corner(mergedWithAnotherContentRadius) + case .BubbleNeighbour: + topLeftCorner = .Corner(mergedRadius) + topRightCorner = .Corner(mergedRadius) case let .None(mergeStatus): switch mergeStatus { case .Left: @@ -32,12 +35,16 @@ func chatMessageBubbleImageContentCorners(relativeContentPosition position: Chat topLeftCorner = .Corner(normalRadius) case .merged: topLeftCorner = .Corner(mergedWithAnotherContentRadius) + case .mergedBubble: + topLeftCorner = .Corner(mergedRadius) } switch position.topRight { case .none: topRightCorner = .Corner(normalRadius) case .merged: topRightCorner = .Corner(mergedWithAnotherContentRadius) + case .mergedBubble: + topRightCorner = .Corner(mergedRadius) } } @@ -50,6 +57,9 @@ func chatMessageBubbleImageContentCorners(relativeContentPosition position: Chat case .Neighbour: bottomLeftCorner = .Corner(mergedWithAnotherContentRadius) bottomRightCorner = .Corner(mergedWithAnotherContentRadius) + case .BubbleNeighbour: + bottomLeftCorner = .Corner(mergedRadius) + bottomRightCorner = .Corner(mergedRadius) case let .None(mergeStatus): switch mergeStatus { case .Left: @@ -115,7 +125,9 @@ func chatMessageBubbleImageContentCorners(relativeContentPosition position: Chat } case .merged: bottomLeftCorner = .Corner(mergedWithAnotherContentRadius) - } + case .mergedBubble: + bottomLeftCorner = .Corner(mergedRadius) + } switch position.bottomRight { case let .none(tail): if tail { @@ -137,6 +149,8 @@ func chatMessageBubbleImageContentCorners(relativeContentPosition position: Chat } case .merged: bottomRightCorner = .Corner(mergedWithAnotherContentRadius) + case .mergedBubble: + bottomRightCorner = .Corner(mergedRadius) } } diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleContentNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleContentNode.swift index 4c10c8609a..621473f04c 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleContentNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleContentNode.swift @@ -41,11 +41,13 @@ enum ChatMessageBubbleMergeStatus { enum ChatMessageBubbleRelativePosition { case None(ChatMessageBubbleMergeStatus) + case BubbleNeighbour case Neighbour } enum ChatMessageBubbleContentMosaicNeighbor { case merged + case mergedBubble case none(tail: Bool) } diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift index 406e3a59f5..f6be80912a 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift @@ -639,7 +639,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode adminBadgeLayout: (TextNodeLayoutArguments) -> (TextNodeLayout, () -> TextNode), forwardInfoLayout: (ChatPresentationData, PresentationStrings, ChatMessageForwardInfoType, Peer?, String?, CGSize) -> (CGSize, () -> ChatMessageForwardInfoNode), replyInfoLayout: (ChatPresentationData, PresentationStrings, AccountContext, ChatMessageReplyInfoType, Message, CGSize) -> (CGSize, () -> ChatMessageReplyInfoNode), - actionButtonsLayout: (AccountContext, ChatPresentationThemeData, PresentationStrings, ReplyMarkupMessageAttribute, Message, CGFloat) -> (minWidth: CGFloat, layout: (CGFloat) -> (CGSize, (Bool) -> ChatMessageActionButtonsNode)), + actionButtonsLayout: (AccountContext, ChatPresentationThemeData, PresentationChatBubbleCorners, PresentationStrings, ReplyMarkupMessageAttribute, Message, CGFloat) -> (minWidth: CGFloat, layout: (CGFloat) -> (CGSize, (Bool) -> ChatMessageActionButtonsNode)), mosaicStatusLayout: (AccountContext, ChatPresentationData, Bool, Int?, String, ChatMessageDateAndStatusType, CGSize, [MessageReaction]) -> (CGSize, (Bool) -> ChatMessageDateAndStatusNode), currentShareButtonNode: HighlightableButtonNode?, layoutConstants: ChatMessageItemLayoutConstants, @@ -1291,7 +1291,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode var actionButtonsFinalize: ((CGFloat) -> (CGSize, (_ animated: Bool) -> ChatMessageActionButtonsNode))? if let replyMarkup = replyMarkup { - let (minWidth, buttonsLayout) = actionButtonsLayout(item.context, item.presentationData.theme, item.presentationData.strings, replyMarkup, item.message, maximumNodeWidth) + let (minWidth, buttonsLayout) = actionButtonsLayout(item.context, item.presentationData.theme, item.presentationData.chatBubbleCorners, item.presentationData.strings, replyMarkup, item.message, maximumNodeWidth) maxContentWidth = max(maxContentWidth, minWidth) actionButtonsFinalize = buttonsLayout } @@ -1313,11 +1313,14 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode case .Neighbour: topLeft = .merged topRight = .merged + case .BubbleNeighbour: + topLeft = .mergedBubble + topRight = .mergedBubble case let .None(status): if position.contains(.top) && position.contains(.left) { switch status { case .Left: - topLeft = .merged + topLeft = .mergedBubble case .Right: topLeft = .none(tail: false) case .None: @@ -1332,7 +1335,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode case .Left: topRight = .none(tail: false) case .Right: - topRight = .merged + topRight = .mergedBubble case .None: topRight = .none(tail: false) } @@ -1356,11 +1359,14 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode case .Neighbour: bottomLeft = .merged bottomRight = .merged + case .BubbleNeighbour: + bottomLeft = .mergedBubble + bottomRight = .mergedBubble case let .None(status): if position.contains(.bottom) && position.contains(.left) { switch status { case .Left: - bottomLeft = .merged + bottomLeft = .mergedBubble case .Right: bottomLeft = .none(tail: false) case let .None(tailStatus): @@ -1379,7 +1385,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode case .Left: bottomRight = .none(tail: false) case .Right: - bottomRight = .merged + bottomRight = .mergedBubble case let .None(tailStatus): if case .Outgoing = tailStatus { bottomRight = .none(tail: true) @@ -1523,7 +1529,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode if currentShareButtonNode != nil { updatedShareButtonNode = currentShareButtonNode if item.presentationData.theme !== currentItem?.presentationData.theme { - let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) + let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper, bubbleCorners: item.presentationData.chatBubbleCorners) if item.message.id.peerId == item.context.account.peerId { updatedShareButtonBackground = graphics.chatBubbleNavigateButtonImage } else { @@ -1533,7 +1539,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode } else { let buttonNode = HighlightableButtonNode() let buttonIcon: UIImage? - let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) + let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper, bubbleCorners: item.presentationData.chatBubbleCorners) if item.message.id.peerId == item.context.account.peerId { buttonIcon = graphics.chatBubbleNavigateButtonImage } else { diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageInstantVideoItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageInstantVideoItemNode.swift index c1f5d88cec..7ef8e6201b 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageInstantVideoItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageInstantVideoItemNode.swift @@ -295,7 +295,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView { updatedReplyBackgroundNode = ASImageNode() } - let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) + let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper, bubbleCorners: item.presentationData.chatBubbleCorners) replyBackgroundImage = graphics.chatFreeformContentAdditionalInfoBackgroundImage } @@ -306,7 +306,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView { if currentShareButtonNode != nil { updatedShareButtonNode = currentShareButtonNode if item.presentationData.theme !== currentItem?.presentationData.theme { - let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) + let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper, bubbleCorners: item.presentationData.chatBubbleCorners) if item.message.id.peerId == item.context.account.peerId { updatedShareButtonBackground = graphics.chatBubbleNavigateButtonImage } else { @@ -316,7 +316,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView { } else { let buttonNode = HighlightableButtonNode() let buttonIcon: UIImage? - let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) + let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper, bubbleCorners: item.presentationData.chatBubbleCorners) if item.message.id.peerId == item.context.account.peerId { buttonIcon = graphics.chatBubbleNavigateButtonImage } else { @@ -364,14 +364,14 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView { updatedForwardBackgroundNode = ASImageNode() } - let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) + let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper, bubbleCorners: item.presentationData.chatBubbleCorners) forwardBackgroundImage = graphics.chatServiceBubbleFillImage } var maxContentWidth = videoLayout.contentSize.width var actionButtonsFinalize: ((CGFloat) -> (CGSize, (_ animated: Bool) -> ChatMessageActionButtonsNode))? if let replyMarkup = replyMarkup { - let (minWidth, buttonsLayout) = actionButtonsLayout(item.context, item.presentationData.theme, item.presentationData.strings, replyMarkup, item.message, maxContentWidth) + let (minWidth, buttonsLayout) = actionButtonsLayout(item.context, item.presentationData.theme, item.presentationData.chatBubbleCorners, item.presentationData.strings, replyMarkup, item.message, maxContentWidth) maxContentWidth = max(maxContentWidth, minWidth) actionButtonsFinalize = buttonsLayout } diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageItemView.swift b/submodules/TelegramUI/TelegramUI/ChatMessageItemView.swift index 5377241b60..1d61b59968 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageItemView.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageItemView.swift @@ -116,7 +116,7 @@ func chatMessageItemLayoutConstants(_ constants: (ChatMessageItemLayoutConstants result = constants.0 } result.image.defaultCornerRadius = presentationData.chatBubbleCorners.mainRadius - result.image.mergedCornerRadius = presentationData.chatBubbleCorners.mergeBubbleCorners ? presentationData.chatBubbleCorners.auxiliaryRadius : presentationData.chatBubbleCorners.mainRadius + result.image.mergedCornerRadius = (presentationData.chatBubbleCorners.mergeBubbleCorners && result.image.defaultCornerRadius >= 10.0) ? presentationData.chatBubbleCorners.auxiliaryRadius : presentationData.chatBubbleCorners.mainRadius let minRadius: CGFloat = 4.0 let maxRadius: CGFloat = 16.0 let radiusTransition = (presentationData.chatBubbleCorners.mainRadius - minRadius) / (maxRadius - minRadius) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageMediaBubbleContentNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageMediaBubbleContentNode.swift index 4566abadca..fec48009c9 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageMediaBubbleContentNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageMediaBubbleContentNode.swift @@ -159,7 +159,7 @@ class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode { if forceFullCorners, case .linear = updatedPosition { updatedPosition = .linear(top: .None(.None(.None)), bottom: .None(.None(.None))) } else if hasReplyMarkup, case let .linear(top, _) = updatedPosition { - updatedPosition = .linear(top: top, bottom: .Neighbour) + updatedPosition = .linear(top: top, bottom: .BubbleNeighbour) } let imageCorners = chatMessageBubbleImageContentCorners(relativeContentPosition: updatedPosition, normalRadius: layoutConstants.image.defaultCornerRadius, mergedRadius: layoutConstants.image.mergedCornerRadius, mergedWithAnotherContentRadius: layoutConstants.image.contentMergedCornerRadius, layoutConstants: layoutConstants, chatPresentationData: item.presentationData) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageReplyInfoNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageReplyInfoNode.swift index 6b17612beb..b546deccc4 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageReplyInfoNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageReplyInfoNode.swift @@ -76,7 +76,7 @@ class ChatMessageReplyInfoNode: ASDisplayNode { let serviceColor = serviceMessageColorComponents(theme: presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper) titleColor = serviceColor.primaryText - let graphics = PresentationResourcesChat.additionalGraphics(presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper) + let graphics = PresentationResourcesChat.additionalGraphics(presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper, bubbleCorners: presentationData.chatBubbleCorners) lineImage = graphics.chatServiceVerticalLineImage textColor = titleColor } diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageStickerItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageStickerItemNode.swift index 7a0f4ff8c8..d4b5f3b248 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageStickerItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageStickerItemNode.swift @@ -353,7 +353,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { updatedReplyBackgroundNode = ASImageNode() } - let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) + let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper, bubbleCorners: item.presentationData.chatBubbleCorners) replyBackgroundImage = graphics.chatFreeformContentAdditionalInfoBackgroundImage } @@ -364,7 +364,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { if currentShareButtonNode != nil { updatedShareButtonNode = currentShareButtonNode if item.presentationData.theme !== currentItem?.presentationData.theme { - let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) + let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper, bubbleCorners: item.presentationData.chatBubbleCorners) if item.message.id.peerId == item.context.account.peerId { updatedShareButtonBackground = graphics.chatBubbleNavigateButtonImage } else { @@ -374,7 +374,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { } else { let buttonNode = HighlightableButtonNode() let buttonIcon: UIImage? - let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) + let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper, bubbleCorners: item.presentationData.chatBubbleCorners) if item.message.id.peerId == item.context.account.peerId { buttonIcon = graphics.chatBubbleNavigateButtonImage } else { @@ -389,7 +389,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { var maxContentWidth = imageSize.width var actionButtonsFinalize: ((CGFloat) -> (CGSize, (_ animated: Bool) -> ChatMessageActionButtonsNode))? if let replyMarkup = replyMarkup { - let (minWidth, buttonsLayout) = actionButtonsLayout(item.context, item.presentationData.theme, item.presentationData.strings, replyMarkup, item.message, maxContentWidth) + let (minWidth, buttonsLayout) = actionButtonsLayout(item.context, item.presentationData.theme, item.presentationData.chatBubbleCorners, item.presentationData.strings, replyMarkup, item.message, maxContentWidth) maxContentWidth = max(maxContentWidth, minWidth) actionButtonsFinalize = buttonsLayout } diff --git a/submodules/TelegramUI/TelegramUI/ChatPresentationInterfaceState.swift b/submodules/TelegramUI/TelegramUI/ChatPresentationInterfaceState.swift index 60e1c60d6a..3697ec4e39 100644 --- a/submodules/TelegramUI/TelegramUI/ChatPresentationInterfaceState.swift +++ b/submodules/TelegramUI/TelegramUI/ChatPresentationInterfaceState.swift @@ -306,12 +306,13 @@ final class ChatPresentationInterfaceState: Equatable { let nameDisplayOrder: PresentationPersonNameOrder let limitsConfiguration: LimitsConfiguration let fontSize: PresentationFontSize + let bubbleCorners: PresentationChatBubbleCorners let accountPeerId: PeerId let mode: ChatControllerPresentationMode let hasScheduledMessages: Bool let isScheduledMessages: Bool - init(chatWallpaper: TelegramWallpaper, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, limitsConfiguration: LimitsConfiguration, fontSize: PresentationFontSize, accountPeerId: PeerId, mode: ChatControllerPresentationMode, chatLocation: ChatLocation, isScheduledMessages: Bool) { + init(chatWallpaper: TelegramWallpaper, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, limitsConfiguration: LimitsConfiguration, fontSize: PresentationFontSize, bubbleCorners: PresentationChatBubbleCorners, accountPeerId: PeerId, mode: ChatControllerPresentationMode, chatLocation: ChatLocation, isScheduledMessages: Bool) { self.interfaceState = ChatInterfaceState() self.inputTextPanelState = ChatTextInputPanelState() self.editMessageState = nil @@ -349,13 +350,14 @@ final class ChatPresentationInterfaceState: Equatable { self.nameDisplayOrder = nameDisplayOrder self.limitsConfiguration = limitsConfiguration self.fontSize = fontSize + self.bubbleCorners = bubbleCorners self.accountPeerId = accountPeerId self.mode = mode self.hasScheduledMessages = false self.isScheduledMessages = isScheduledMessages } - init(interfaceState: ChatInterfaceState, chatLocation: ChatLocation, renderedPeer: RenderedPeer?, isNotAccessible: Bool, explicitelyCanPinMessages: Bool, contactStatus: ChatContactStatus?, hasBots: Bool, isArchived: Bool, inputTextPanelState: ChatTextInputPanelState, editMessageState: ChatEditInterfaceMessageState?, recordedMediaPreview: ChatRecordedMediaPreview?, inputQueryResults: [ChatPresentationInputQueryKind: ChatPresentationInputQueryResult], inputMode: ChatInputMode, titlePanelContexts: [ChatTitlePanelContext], keyboardButtonsMessage: Message?, pinnedMessageId: MessageId?, pinnedMessage: Message?, peerIsBlocked: Bool, peerIsMuted: Bool, peerDiscussionId: PeerId?, peerGeoLocation: PeerGeoLocation?, callsAvailable: Bool, callsPrivate: Bool, slowmodeState: ChatSlowmodeState?, chatHistoryState: ChatHistoryNodeHistoryState?, botStartPayload: String?, urlPreview: (String, TelegramMediaWebpage)?, editingUrlPreview: (String, TelegramMediaWebpage)?, search: ChatSearchData?, searchQuerySuggestionResult: ChatPresentationInputQueryResult?, chatWallpaper: TelegramWallpaper, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, limitsConfiguration: LimitsConfiguration, fontSize: PresentationFontSize, accountPeerId: PeerId, mode: ChatControllerPresentationMode, hasScheduledMessages: Bool, isScheduledMessages: Bool) { + init(interfaceState: ChatInterfaceState, chatLocation: ChatLocation, renderedPeer: RenderedPeer?, isNotAccessible: Bool, explicitelyCanPinMessages: Bool, contactStatus: ChatContactStatus?, hasBots: Bool, isArchived: Bool, inputTextPanelState: ChatTextInputPanelState, editMessageState: ChatEditInterfaceMessageState?, recordedMediaPreview: ChatRecordedMediaPreview?, inputQueryResults: [ChatPresentationInputQueryKind: ChatPresentationInputQueryResult], inputMode: ChatInputMode, titlePanelContexts: [ChatTitlePanelContext], keyboardButtonsMessage: Message?, pinnedMessageId: MessageId?, pinnedMessage: Message?, peerIsBlocked: Bool, peerIsMuted: Bool, peerDiscussionId: PeerId?, peerGeoLocation: PeerGeoLocation?, callsAvailable: Bool, callsPrivate: Bool, slowmodeState: ChatSlowmodeState?, chatHistoryState: ChatHistoryNodeHistoryState?, botStartPayload: String?, urlPreview: (String, TelegramMediaWebpage)?, editingUrlPreview: (String, TelegramMediaWebpage)?, search: ChatSearchData?, searchQuerySuggestionResult: ChatPresentationInputQueryResult?, chatWallpaper: TelegramWallpaper, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, limitsConfiguration: LimitsConfiguration, fontSize: PresentationFontSize, bubbleCorners: PresentationChatBubbleCorners, accountPeerId: PeerId, mode: ChatControllerPresentationMode, hasScheduledMessages: Bool, isScheduledMessages: Bool) { self.interfaceState = interfaceState self.chatLocation = chatLocation self.renderedPeer = renderedPeer @@ -393,6 +395,7 @@ final class ChatPresentationInterfaceState: Equatable { self.nameDisplayOrder = nameDisplayOrder self.limitsConfiguration = limitsConfiguration self.fontSize = fontSize + self.bubbleCorners = bubbleCorners self.accountPeerId = accountPeerId self.mode = mode self.hasScheduledMessages = hasScheduledMessages @@ -530,6 +533,9 @@ final class ChatPresentationInterfaceState: Equatable { if lhs.fontSize != rhs.fontSize { return false } + if lhs.bubbleCorners != rhs.bubbleCorners { + return false + } if lhs.accountPeerId != rhs.accountPeerId { return false } @@ -546,31 +552,31 @@ final class ChatPresentationInterfaceState: Equatable { } func updatedInterfaceState(_ f: (ChatInterfaceState) -> ChatInterfaceState) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: f(self.interfaceState), chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: f(self.interfaceState), chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedPeer(_ f: (RenderedPeer?) -> RenderedPeer?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: f(self.renderedPeer), isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: f(self.renderedPeer), isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedIsNotAccessible(_ isNotAccessible: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedExplicitelyCanPinMessages(_ explicitelyCanPinMessages: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedContactStatus(_ contactStatus: ChatContactStatus?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedHasBots(_ hasBots: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedIsArchived(_ isArchived: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedInputQueryResult(queryKind: ChatPresentationInputQueryKind, _ f: (ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?) -> ChatPresentationInterfaceState { @@ -581,115 +587,119 @@ final class ChatPresentationInterfaceState: Equatable { } else { inputQueryResults.removeValue(forKey: queryKind) } - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedInputTextPanelState(_ f: (ChatTextInputPanelState) -> ChatTextInputPanelState) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: f(self.inputTextPanelState), editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: f(self.inputTextPanelState), editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedEditMessageState(_ editMessageState: ChatEditInterfaceMessageState?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedRecordedMediaPreview(_ recordedMediaPreview: ChatRecordedMediaPreview?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedInputMode(_ f: (ChatInputMode) -> ChatInputMode) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: f(self.inputMode), titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: f(self.inputMode), titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedTitlePanelContext(_ f: ([ChatTitlePanelContext]) -> [ChatTitlePanelContext]) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: f(self.titlePanelContexts), keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: f(self.titlePanelContexts), keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedKeyboardButtonsMessage(_ message: Message?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: message, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: message, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedPinnedMessageId(_ pinnedMessageId: MessageId?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedPinnedMessage(_ pinnedMessage: Message?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedPeerIsBlocked(_ peerIsBlocked: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedPeerIsMuted(_ peerIsMuted: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedPeerDiscussionId(_ peerDiscussionId: PeerId?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedPeerGeoLocation(_ peerGeoLocation: PeerGeoLocation?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedCallsAvailable(_ callsAvailable: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedCallsPrivate(_ callsPrivate: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedSlowmodeState(_ slowmodeState: ChatSlowmodeState?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedBotStartPayload(_ botStartPayload: String?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedChatHistoryState(_ chatHistoryState: ChatHistoryNodeHistoryState?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedUrlPreview(_ urlPreview: (String, TelegramMediaWebpage)?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedEditingUrlPreview(_ editingUrlPreview: (String, TelegramMediaWebpage)?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedSearch(_ search: ChatSearchData?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedSearchQuerySuggestionResult(_ f: (ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: f(self.searchQuerySuggestionResult), chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: f(self.searchQuerySuggestionResult), chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedMode(_ mode: ChatControllerPresentationMode) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedTheme(_ theme: PresentationTheme) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedStrings(_ strings: PresentationStrings) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedDateTimeFormat(_ dateTimeFormat: PresentationDateTimeFormat) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedChatWallpaper(_ chatWallpaper: TelegramWallpaper) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + } + + func updatedBubbleCorners(_ bubbleCorners: PresentationChatBubbleCorners) -> ChatPresentationInterfaceState { + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } func updatedHasScheduledMessages(_ hasScheduledMessages: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: hasScheduledMessages, isScheduledMessages: self.isScheduledMessages) } } diff --git a/submodules/TelegramUI/TelegramUI/ChatRecentActionsControllerNode.swift b/submodules/TelegramUI/TelegramUI/ChatRecentActionsControllerNode.swift index 2a2b602ab9..271975abbe 100644 --- a/submodules/TelegramUI/TelegramUI/ChatRecentActionsControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatRecentActionsControllerNode.swift @@ -107,8 +107,8 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { self.listNode = ListView() self.listNode.dynamicBounceEnabled = !self.presentationData.disableAnimations self.listNode.transform = CATransform3DMakeRotation(CGFloat(Double.pi), 0.0, 0.0, 1.0) - self.loadingNode = ChatLoadingNode(theme: self.presentationData.theme, chatWallpaper: self.presentationData.chatWallpaper) - self.emptyNode = ChatRecentActionsEmptyNode(theme: self.presentationData.theme, chatWallpaper: self.presentationData.chatWallpaper) + self.loadingNode = ChatLoadingNode(theme: self.presentationData.theme, chatWallpaper: self.presentationData.chatWallpaper, bubbleCorners: self.presentationData.chatBubbleCorners) + self.emptyNode = ChatRecentActionsEmptyNode(theme: self.presentationData.theme, chatWallpaper: self.presentationData.chatWallpaper, chatBubbleCorners: self.presentationData.chatBubbleCorners) self.emptyNode.alpha = 0.0 self.state = ChatRecentActionsControllerState(chatWallpaper: self.presentationData.chatWallpaper, theme: self.presentationData.theme, strings: self.presentationData.strings, fontSize: self.presentationData.chatFontSize) diff --git a/submodules/TelegramUI/TelegramUI/ChatRecentActionsEmptyNode.swift b/submodules/TelegramUI/TelegramUI/ChatRecentActionsEmptyNode.swift index 3d45cd250d..8b4dfd82d5 100644 --- a/submodules/TelegramUI/TelegramUI/ChatRecentActionsEmptyNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatRecentActionsEmptyNode.swift @@ -22,7 +22,7 @@ final class ChatRecentActionsEmptyNode: ASDisplayNode { private var title: String = "" private var text: String = "" - init(theme: PresentationTheme, chatWallpaper: TelegramWallpaper) { + init(theme: PresentationTheme, chatWallpaper: TelegramWallpaper, chatBubbleCorners: PresentationChatBubbleCorners) { self.theme = theme self.chatWallpaper = chatWallpaper @@ -37,7 +37,7 @@ final class ChatRecentActionsEmptyNode: ASDisplayNode { super.init() - let graphics = PresentationResourcesChat.additionalGraphics(theme, wallpaper: chatWallpaper) + let graphics = PresentationResourcesChat.additionalGraphics(theme, wallpaper: chatWallpaper, bubbleCorners: chatBubbleCorners) self.backgroundNode.image = graphics.chatEmptyItemBackgroundImage self.addSubnode(self.backgroundNode) diff --git a/submodules/TelegramUI/TelegramUI/PeerMediaCollectionControllerNode.swift b/submodules/TelegramUI/TelegramUI/PeerMediaCollectionControllerNode.swift index 43b2d14d1d..cae95a602a 100644 --- a/submodules/TelegramUI/TelegramUI/PeerMediaCollectionControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/PeerMediaCollectionControllerNode.swift @@ -155,7 +155,7 @@ class PeerMediaCollectionControllerNode: ASDisplayNode { self.historyEmptyNode = PeerMediaCollectionEmptyNode(mode: self.mediaCollectionInterfaceState.mode, theme: self.presentationData.theme, strings: self.presentationData.strings) self.historyEmptyNode.isHidden = true - self.chatPresentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: self.presentationData.chatWallpaper, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: .defaultValue, fontSize: self.presentationData.listsFontSize, accountPeerId: context.account.peerId, mode: .standard(previewing: false), chatLocation: .peer(self.peerId), isScheduledMessages: false) + self.chatPresentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: self.presentationData.chatWallpaper, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: .defaultValue, fontSize: self.presentationData.listsFontSize, bubbleCorners: self.presentationData.chatBubbleCorners, accountPeerId: context.account.peerId, mode: .standard(previewing: false), chatLocation: .peer(self.peerId), isScheduledMessages: false) super.init() From 6a4224e67cf03b8549f519224ca2fa232ff08cc5 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Tue, 21 Jan 2020 23:12:19 +0400 Subject: [PATCH 14/50] Fix poll results update --- submodules/SyncCore/Sources/TelegramMediaPoll.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/submodules/SyncCore/Sources/TelegramMediaPoll.swift b/submodules/SyncCore/Sources/TelegramMediaPoll.swift index 942f1ba8fd..f01ba73c87 100644 --- a/submodules/SyncCore/Sources/TelegramMediaPoll.swift +++ b/submodules/SyncCore/Sources/TelegramMediaPoll.swift @@ -229,6 +229,8 @@ public final class TelegramMediaPoll: Media, Equatable { updatedResults = TelegramMediaPollResults(voters: updatedVoters.map({ voters in return TelegramMediaPollOptionVoters(selected: selectedOpaqueIdentifiers.contains(voters.opaqueIdentifier), opaqueIdentifier: voters.opaqueIdentifier, count: voters.count, isCorrect: correctOpaqueIdentifiers.contains(voters.opaqueIdentifier)) }), totalVoters: results.totalVoters, recentVoters: results.recentVoters) + } else if let updatedVoters = results.voters { + updatedResults = TelegramMediaPollResults(voters: updatedVoters, totalVoters: results.totalVoters, recentVoters: results.recentVoters) } else { updatedResults = TelegramMediaPollResults(voters: self.results.voters, totalVoters: results.totalVoters, recentVoters: results.recentVoters) } From 48ce3a34573ec54c8a9ddbb687f288724de4e959 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Tue, 21 Jan 2020 23:13:31 +0400 Subject: [PATCH 15/50] Disable View Results in Scheduled Messages --- .../ChatMessagePollBubbleContentNode.swift | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessagePollBubbleContentNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessagePollBubbleContentNode.swift index bdca4308d6..c1ba412885 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessagePollBubbleContentNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessagePollBubbleContentNode.swift @@ -891,7 +891,9 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode { } } if !hasSelection { - item.controllerInteraction.requestOpenMessagePollResults(item.message.id, pollId) + if !Namespaces.Message.allScheduled.contains(item.message.id.namespace) { + item.controllerInteraction.requestOpenMessagePollResults(item.message.id, pollId) + } } else if !selectedOpaqueIdentifiers.isEmpty { item.controllerInteraction.requestSelectMessagePollOptions(item.message.id, selectedOpaqueIdentifiers) } @@ -1391,15 +1393,23 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode { self.buttonSubmitInactiveTextNode.isHidden = hasSelectedOptions self.buttonSubmitActiveTextNode.isHidden = !hasSelectedOptions self.buttonNode.isHidden = !hasSelectedOptions + self.buttonNode.isUserInteractionEnabled = true } else { if case .public = poll.publicity, hasResults, !disableAllActions { self.votersNode.isHidden = true self.buttonViewResultsTextNode.isHidden = false self.buttonNode.isHidden = false + + if Namespaces.Message.allScheduled.contains(item.message.id.namespace) { + self.buttonNode.isUserInteractionEnabled = false + } else { + self.buttonNode.isUserInteractionEnabled = true + } } else { self.votersNode.isHidden = false self.buttonViewResultsTextNode.isHidden = true self.buttonNode.isHidden = true + self.buttonNode.isUserInteractionEnabled = true } self.buttonSubmitInactiveTextNode.isHidden = true self.buttonSubmitActiveTextNode.isHidden = true From 0a33b7f55a9e3dbf1e4401f2d09309c2f7436355 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Tue, 21 Jan 2020 23:28:36 +0400 Subject: [PATCH 16/50] Make rlottie use a relative url path --- .gitmodules | 2 +- submodules/rlottie/rlottie | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index f931b28d97..c319a7c828 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "submodules/rlottie/rlottie"] path = submodules/rlottie/rlottie - url = https://github.com/laktyushin/rlottie.git +url=../rlottie.git diff --git a/submodules/rlottie/rlottie b/submodules/rlottie/rlottie index a09896b3e7..0ee2e9c584 160000 --- a/submodules/rlottie/rlottie +++ b/submodules/rlottie/rlottie @@ -1 +1 @@ -Subproject commit a09896b3e72e76681c12e80572a7d570108cf885 +Subproject commit 0ee2e9c5843257ccd11672611829b9bb5d02aa98 From b30af2272dab2a6e4d0d62825ae62aedd21efe41 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Tue, 21 Jan 2020 23:28:56 +0400 Subject: [PATCH 17/50] Bubble layout improvements --- .../Sources/BubbleSettings/BubbleSettingsController.swift | 2 +- submodules/TelegramUI/TelegramUI/ChatMessageItemView.swift | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift b/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift index 780335a936..daa01db3bb 100644 --- a/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift +++ b/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift @@ -190,7 +190,7 @@ private final class BubbleSettingsControllerNode: ASDisplayNode, UIScrollViewDel let width: CGFloat if case .regular = layout.metrics.widthClass { - width = layout.size.width / 2.0 + width = layout.size.width } else { width = layout.size.width } diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageItemView.swift b/submodules/TelegramUI/TelegramUI/ChatMessageItemView.swift index 1d61b59968..96066bb31d 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageItemView.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageItemView.swift @@ -96,9 +96,9 @@ struct ChatMessageItemLayoutConstants { } fileprivate static var regular: ChatMessageItemLayoutConstants { - let bubble = ChatMessageItemBubbleLayoutConstants(edgeInset: 4.0, defaultSpacing: 2.0 + UIScreenPixel, mergedSpacing: 1.0, maximumWidthFill: ChatMessageItemWidthFill(compactInset: 36.0, compactWidthBoundary: 500.0, freeMaximumFillFactor: 0.65), minimumSize: CGSize(width: 40.0, height: 35.0), contentInsets: UIEdgeInsets(top: 0.0, left: 6.0, bottom: 0.0, right: 0.0), borderInset: UIScreenPixel, strokeInsets: UIEdgeInsets(top: 1.0 - UIScreenPixel, left: 1.0 - UIScreenPixel, bottom: 1.0 - UIScreenPixel, right: 1.0 - UIScreenPixel)) + let bubble = ChatMessageItemBubbleLayoutConstants(edgeInset: 4.0, defaultSpacing: 2.0 + UIScreenPixel, mergedSpacing: 1.0, maximumWidthFill: ChatMessageItemWidthFill(compactInset: 36.0, compactWidthBoundary: 500.0, freeMaximumFillFactor: 0.65), minimumSize: CGSize(width: 40.0, height: 35.0), contentInsets: UIEdgeInsets(top: 0.0, left: 6.0, bottom: 0.0, right: 0.0), borderInset: UIScreenPixel, strokeInsets: UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0)) let text = ChatMessageItemTextLayoutConstants(bubbleInsets: UIEdgeInsets(top: 6.0 + UIScreenPixel, left: 12.0, bottom: 6.0 - UIScreenPixel, right: 12.0)) - let image = ChatMessageItemImageLayoutConstants(bubbleInsets: UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0), statusInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 6.0, right: 6.0), defaultCornerRadius: 17.0, mergedCornerRadius: 5.0, contentMergedCornerRadius: 5.0, maxDimensions: CGSize(width: 440.0, height: 440.0), minDimensions: CGSize(width: 170.0, height: 74.0)) + let image = ChatMessageItemImageLayoutConstants(bubbleInsets: UIEdgeInsets(top: 2.0, left: 2.0, bottom: 2.0, right: 2.0), statusInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 6.0, right: 6.0), defaultCornerRadius: 16.0, mergedCornerRadius: 8.0, contentMergedCornerRadius: 5.0, maxDimensions: CGSize(width: 440.0, height: 440.0), minDimensions: CGSize(width: 170.0, height: 74.0)) let video = ChatMessageItemVideoLayoutConstants(maxHorizontalHeight: 250.0, maxVerticalHeight: 360.0) let file = ChatMessageItemFileLayoutConstants(bubbleInsets: UIEdgeInsets(top: 15.0, left: 9.0, bottom: 15.0, right: 12.0)) let instantVideo = ChatMessageItemInstantVideoConstants(insets: UIEdgeInsets(top: 4.0, left: 0.0, bottom: 4.0, right: 0.0), dimensions: CGSize(width: 212.0, height: 212.0)) From 5ad48ef7d428717a1b1be78834f4d215b588ef98 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Tue, 21 Jan 2020 23:58:49 +0400 Subject: [PATCH 18/50] Fix topPresentationContext overlay focus handling --- submodules/AppLock/Sources/AppLock.swift | 1 + submodules/Display/Display/WindowContent.swift | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/submodules/AppLock/Sources/AppLock.swift b/submodules/AppLock/Sources/AppLock.swift index fdb2016360..e339ed19ad 100644 --- a/submodules/AppLock/Sources/AppLock.swift +++ b/submodules/AppLock/Sources/AppLock.swift @@ -201,6 +201,7 @@ public final class AppLockContextImpl: AppLockContext { } } passcodeController.presentedOverCoveringView = true + passcodeController.isOpaqueWhenInOverlay = true strongSelf.passcodeController = passcodeController if let rootViewController = strongSelf.rootController { if let presentedViewController = rootViewController.presentedViewController as? UIActivityViewController { diff --git a/submodules/Display/Display/WindowContent.swift b/submodules/Display/Display/WindowContent.swift index 19514e85ee..cbf67d23e9 100644 --- a/submodules/Display/Display/WindowContent.swift +++ b/submodules/Display/Display/WindowContent.swift @@ -337,8 +337,17 @@ public class Window1 { self?.isInteractionBlocked = value } + let updateOpaqueOverlays: () -> Void = { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf._rootController?.displayNode.accessibilityElementsHidden = strongSelf.presentationContext.hasOpaqueOverlay || strongSelf.topPresentationContext.hasOpaqueOverlay + } self.presentationContext.updateHasOpaqueOverlay = { [weak self] value in - self?._rootController?.displayNode.accessibilityElementsHidden = value + updateOpaqueOverlays() + } + self.topPresentationContext.updateHasOpaqueOverlay = { [weak self] value in + updateOpaqueOverlays() } self.hostView.present = { [weak self] controller, level, blockInteraction, completion in From 9073516dbd74cd6e7b2c900cfcbe65a02a54fcd6 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Wed, 22 Jan 2020 00:16:42 +0400 Subject: [PATCH 19/50] Move screenshot detection activation to a later stage --- .../SecretMediaPreviewController.swift | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift b/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift index 4a2df1e638..3c36aeaa18 100644 --- a/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift +++ b/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift @@ -122,6 +122,7 @@ private final class SecretMediaPreviewControllerNode: GalleryControllerNode { public final class SecretMediaPreviewController: ViewController { private let context: AccountContext + private let messageId: MessageId private let _ready = Promise() override public var ready: Promise { @@ -150,6 +151,7 @@ public final class SecretMediaPreviewController: ViewController { public init(context: AccountContext, messageId: MessageId) { self.context = context + self.messageId = messageId self.presentationData = context.sharedContext.currentPresentationData.with { $0 } super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: GalleryController.darkNavigationTheme, strings: NavigationBarStrings(presentationStrings: self.presentationData.strings))) @@ -159,8 +161,6 @@ public final class SecretMediaPreviewController: ViewController { self.statusBar.statusBarStyle = .White - - self.disposable.set((context.account.postbox.messageView(messageId) |> deliverOnMainQueue).start(next: { [weak self] view in if let strongSelf = self { strongSelf.messageView = view @@ -178,17 +178,6 @@ public final class SecretMediaPreviewController: ViewController { return nil } }) - - self.screenCaptureEventsDisposable = (screenCaptureEvents() - |> deliverOnMainQueue).start(next: { [weak self] _ in - if let strongSelf = self, strongSelf.traceVisibility() { - if messageId.peerId.namespace == Namespaces.Peer.CloudUser { - let _ = enqueueMessages(account: context.account, peerId: messageId.peerId, messages: [.message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.historyScreenshot)), replyToMessageId: nil, localGroupingKey: nil)]).start() - } else if messageId.peerId.namespace == Namespaces.Peer.SecretChat { - let _ = addSecretChatMessageScreenshot(account: context.account, peerId: messageId.peerId).start() - } - } - }) } required public init(coder aDecoder: NSCoder) { @@ -348,6 +337,19 @@ public final class SecretMediaPreviewController: ViewController { override public func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) + if self.screenCaptureEventsDisposable == nil { + self.screenCaptureEventsDisposable = (screenCaptureEvents() + |> deliverOnMainQueue).start(next: { [weak self] _ in + if let strongSelf = self, strongSelf.traceVisibility() { + if strongSelf.messageId.peerId.namespace == Namespaces.Peer.CloudUser { + let _ = enqueueMessages(account: strongSelf.context.account, peerId: strongSelf.messageId.peerId, messages: [.message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.historyScreenshot)), replyToMessageId: nil, localGroupingKey: nil)]).start() + } else if strongSelf.messageId.peerId.namespace == Namespaces.Peer.SecretChat { + let _ = addSecretChatMessageScreenshot(account: strongSelf.context.account, peerId: strongSelf.messageId.peerId).start() + } + } + }) + } + var nodeAnimatesItself = false if let centralItemNode = self.controllerNode.pager.centralItemNode(), let message = self.messageView?.message { From d2fb7f07e535a3a3bd7aa5e8656b9e45faf97163 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Wed, 22 Jan 2020 00:26:44 +0400 Subject: [PATCH 20/50] Use 0.5pt borders on @2x displays --- .../Sources/ChatMessageBubbleImages.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift b/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift index a33deb89cc..d09c06ccc4 100644 --- a/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift +++ b/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift @@ -176,7 +176,12 @@ public func messageBubbleImage(maxCornerRadius: CGFloat, minCornerRadius: CGFloa context.translateBy(x: additionalInset + strokeInset, y: additionalInset + strokeInset) context.setStrokeColor(UIColor.black.cgColor) - let borderWidth: CGFloat = UIScreenPixel * 2.0 + let borderWidth: CGFloat + if abs(UIScreenPixel - 0.5) < CGFloat.ulpOfOne { + borderWidth = UIScreenPixel + } else { + borderWidth = UIScreenPixel * 2.0 + } context.setLineWidth(borderWidth) let borderOffset: CGFloat = borderWidth / 2.0 From 9db6a8551b905d11640956a4c786f9f16e97fee8 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Wed, 22 Jan 2020 01:44:29 +0400 Subject: [PATCH 21/50] Fix media corners --- submodules/Display/Display/ImageCorners.swift | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/submodules/Display/Display/ImageCorners.swift b/submodules/Display/Display/ImageCorners.swift index 6930a5bcf4..948a4d385d 100644 --- a/submodules/Display/Display/ImageCorners.swift +++ b/submodules/Display/Display/ImageCorners.swift @@ -121,20 +121,22 @@ private func cornerContext(_ corner: Corner) -> DrawingContext { let context = DrawingContext(size: CGSize(width: CGFloat(corner.radius), height: CGFloat(corner.radius)), clear: true) context.withContext { c in - c.setBlendMode(.copy) + c.clear(CGRect(origin: CGPoint(), size: CGSize(width: CGFloat(corner.radius), height: CGFloat(corner.radius)))) c.setFillColor(UIColor.black.cgColor) - let rect: CGRect switch corner { - case let .TopLeft(radius): - rect = CGRect(origin: CGPoint(), size: CGSize(width: CGFloat(radius << 1), height: CGFloat(radius << 1))) - case let .TopRight(radius): - rect = CGRect(origin: CGPoint(x: -CGFloat(radius), y: 0.0), size: CGSize(width: CGFloat(radius << 1), height: CGFloat(radius << 1))) - case let .BottomLeft(radius): - rect = CGRect(origin: CGPoint(x: 0.0, y: -CGFloat(radius)), size: CGSize(width: CGFloat(radius << 1), height: CGFloat(radius << 1))) - case let .BottomRight(radius): - rect = CGRect(origin: CGPoint(x: -CGFloat(radius), y: -CGFloat(radius)), size: CGSize(width: CGFloat(radius << 1), height: CGFloat(radius << 1))) + case let .TopLeft(radius): + let rect = CGRect(origin: CGPoint(), size: CGSize(width: CGFloat(radius * 2), height: CGFloat(radius * 2))) + c.fillEllipse(in: rect) + case let .TopRight(radius): + let rect = CGRect(origin: CGPoint(x: -CGFloat(radius), y: 0.0), size: CGSize(width: CGFloat(radius * 2), height: CGFloat(radius * 2))) + c.fillEllipse(in: rect) + case let .BottomLeft(radius): + let rect = CGRect(origin: CGPoint(x: 0.0, y: -CGFloat(radius)), size: CGSize(width: CGFloat(radius * 2), height: CGFloat(radius * 2))) + c.fillEllipse(in: rect) + case let .BottomRight(radius): + let rect = CGRect(origin: CGPoint(x: -CGFloat(radius), y: -CGFloat(radius)), size: CGSize(width: CGFloat(radius * 2), height: CGFloat(radius * 2))) + c.fillEllipse(in: rect) } - c.fillEllipse(in: rect) } let _ = cachedCorners.modify { current in @@ -172,7 +174,7 @@ public func addCorners(_ context: DrawingContext, arguments: TransformImageArgum context.withContext { c in c.clear(CGRect(x: drawingRect.minX - 4.0, y: 0.0, width: 4.0, height: drawingRect.maxY - 6.0)) c.setFillColor(color.cgColor) - c.fill(CGRect(x: 0.0, y: drawingRect.maxY - 6.0, width: 4.0, height: 6.0)) + c.fill(CGRect(x: 0.0, y: drawingRect.maxY - 7.0, width: 4.0, height: 7.0)) c.setBlendMode(.destinationIn) let cornerRect = CGRect(origin: CGPoint(x: drawingRect.minX - 6.0, y: drawingRect.maxY - image.size.height), size: image.size) c.translateBy(x: cornerRect.midX, y: cornerRect.midY) @@ -198,7 +200,7 @@ public func addCorners(_ context: DrawingContext, arguments: TransformImageArgum context.withContext { c in c.clear(CGRect(x: drawingRect.maxX, y: 0.0, width: 4.0, height: drawingRect.maxY - image.size.height)) c.setFillColor(color.cgColor) - c.fill(CGRect(x: drawingRect.maxX, y: drawingRect.maxY - 6.0, width: 4.0, height: 6.0)) + c.fill(CGRect(x: drawingRect.maxX, y: drawingRect.maxY - 7.0, width: 5.0, height: 7.0)) c.setBlendMode(.destinationIn) let cornerRect = CGRect(origin: CGPoint(x: drawingRect.maxX - image.size.width + 6.0, y: drawingRect.maxY - image.size.height), size: image.size) c.translateBy(x: cornerRect.midX, y: cornerRect.midY) From 4047d83584775bfa41802816421d2e321f61d24c Mon Sep 17 00:00:00 2001 From: Ali <> Date: Wed, 22 Jan 2020 01:44:56 +0400 Subject: [PATCH 22/50] Fix for message text component while editing caption --- .../TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift index f6be80912a..88a19d0bdb 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift @@ -76,7 +76,12 @@ private func contentNodeMessagesAndClassesForItem(_ item: ChatMessageItem) -> [( } } - if !message.text.isEmpty || isUnsupportedMedia { + var messageText = message.text + if let updatingMedia = itemAttributes.updatingMedia { + messageText = updatingMedia.text + } + + if !messageText.isEmpty || isUnsupportedMedia { if !skipText { if case .group = item.content { messageWithCaptionToAdd = (message, itemAttributes) From 1f5eaceb805abde2adc4218b11adc01a636eba3c Mon Sep 17 00:00:00 2001 From: Ali <> Date: Wed, 22 Jan 2020 02:23:57 +0400 Subject: [PATCH 23/50] improve screen capture detection --- .../Sources/ScreenCaptureDetection.swift | 47 +++++++++++++++++++ .../TelegramUI/ChatController.swift | 10 ++-- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/submodules/ScreenCaptureDetection/Sources/ScreenCaptureDetection.swift b/submodules/ScreenCaptureDetection/Sources/ScreenCaptureDetection.swift index 0c35661804..26f6bfba5b 100644 --- a/submodules/ScreenCaptureDetection/Sources/ScreenCaptureDetection.swift +++ b/submodules/ScreenCaptureDetection/Sources/ScreenCaptureDetection.swift @@ -75,3 +75,50 @@ public func screenCaptureEvents() -> Signal { } |> runOn(Queue.mainQueue()) } + +public final class ScreenCaptureDetectionManager { + private var observer: NSObjectProtocol? + private var screenRecordingDisposable: Disposable? + private var screenRecordingCheckTimer: SwiftSignalKit.Timer? + + public init(check: @escaping () -> Bool) { + self.observer = NotificationCenter.default.addObserver(forName: UIApplication.userDidTakeScreenshotNotification, object: nil, queue: .main, using: { [weak self] _ in + guard let strongSelf = self else { + return + } + check() + }) + + self.screenRecordingDisposable = screenRecordingActive().start(next: { [weak self] value in + Queue.mainQueue().async { + guard let strongSelf = self else { + return + } + if value { + if strongSelf.screenRecordingCheckTimer == nil { + strongSelf.screenRecordingCheckTimer = SwiftSignalKit.Timer(timeout: 0.5, repeat: true, completion: { + guard let strongSelf = self else { + return + } + if check() { + strongSelf.screenRecordingCheckTimer?.invalidate() + strongSelf.screenRecordingCheckTimer = nil + } + }, queue: Queue.mainQueue()) + strongSelf.screenRecordingCheckTimer?.start() + } + } else if strongSelf.screenRecordingCheckTimer != nil { + strongSelf.screenRecordingCheckTimer?.invalidate() + strongSelf.screenRecordingCheckTimer = nil + } + } + }) + } + + deinit { + NotificationCenter.default.removeObserver(self.observer) + self.screenRecordingDisposable?.dispose() + self.screenRecordingCheckTimer?.invalidate() + self.screenRecordingCheckTimer = nil + } +} diff --git a/submodules/TelegramUI/TelegramUI/ChatController.swift b/submodules/TelegramUI/TelegramUI/ChatController.swift index 80b1f3f7ad..8e92f38297 100644 --- a/submodules/TelegramUI/TelegramUI/ChatController.swift +++ b/submodules/TelegramUI/TelegramUI/ChatController.swift @@ -289,7 +289,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G private weak var sendMessageActionsController: ChatSendMessageActionSheetController? private var searchResultsController: ChatSearchResultsController? - private var screenCaptureEventsDisposable: Disposable? + private var screenCaptureManager: ScreenCaptureDetectionManager? private let chatAdditionalDataDisposable = MetaDisposable() private var reportIrrelvantGeoNoticePromise = Promise() @@ -2496,7 +2496,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.applicationInForegroundDisposable?.dispose() self.canReadHistoryDisposable?.dispose() self.networkStateDisposable?.dispose() - self.screenCaptureEventsDisposable?.dispose() self.chatAdditionalDataDisposable.dispose() self.shareStatusDisposable?.dispose() self.context.sharedContext.mediaManager.galleryHiddenMediaManager.removeTarget(self) @@ -4639,10 +4638,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if !self.checkedPeerChatServiceActions { self.checkedPeerChatServiceActions = true - if case let .peer(peerId) = self.chatLocation, peerId.namespace == Namespaces.Peer.SecretChat { - self.screenCaptureEventsDisposable = screenCaptureEvents().start(next: { [weak self] _ in + if case let .peer(peerId) = self.chatLocation, peerId.namespace == Namespaces.Peer.SecretChat, self.screenCaptureManager == nil { + self.screenCaptureManager = ScreenCaptureDetectionManager(check: { [weak self] in if let strongSelf = self, strongSelf.canReadHistoryValue, strongSelf.traceVisibility() { let _ = addSecretChatMessageScreenshot(account: strongSelf.context.account, peerId: peerId).start() + return true + } else { + return false } }) } From 66e10bf0d4dd6684e080d91ae8931a5f9621ff04 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Wed, 22 Jan 2020 23:16:46 +0400 Subject: [PATCH 24/50] extractedBackgroundNode --- submodules/Display/Display/ListViewItemNode.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/submodules/Display/Display/ListViewItemNode.swift b/submodules/Display/Display/ListViewItemNode.swift index 608580a667..3204d15744 100644 --- a/submodules/Display/Display/ListViewItemNode.swift +++ b/submodules/Display/Display/ListViewItemNode.swift @@ -110,6 +110,10 @@ open class ListViewItemNode: ASDisplayNode { } } + open var extractedBackgroundNode: ASDisplayNode? { + return nil + } + private final var spring: ListViewItemSpring? private final var animations: [(String, ListViewAnimation)] = [] From 1d7c0fbe409fdbbd12f57cf7eca6f489483b7070 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Thu, 23 Jan 2020 23:33:48 +0400 Subject: [PATCH 25/50] Fix create poll screen --- .../ComposePollUI/Sources/CreatePollController.swift | 7 ++++--- .../ComposePollUI/Sources/CreatePollOptionItem.swift | 6 ++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/submodules/ComposePollUI/Sources/CreatePollController.swift b/submodules/ComposePollUI/Sources/CreatePollController.swift index af294cccda..8fbcbab1ec 100644 --- a/submodules/ComposePollUI/Sources/CreatePollController.swift +++ b/submodules/ComposePollUI/Sources/CreatePollController.swift @@ -212,7 +212,7 @@ private enum CreatePollEntry: ItemListNodeEntry { case textHeader(String, ItemListSectionHeaderAccessoryText) case text(String, String, Int) case optionsHeader(String) - case option(id: Int, ordering: OrderedLinkedListItemOrdering, placeholder: String, text: String, revealed: Bool, hasNext: Bool, isLast: Bool, isSelected: Bool?) + case option(id: Int, ordering: OrderedLinkedListItemOrdering, placeholder: String, text: String, revealed: Bool, hasNext: Bool, isLast: Bool, canMove: Bool, isSelected: Bool?) case optionsInfo(String) case anonymousVotes(String, Bool) case multipleChoice(String, Bool, Bool) @@ -314,7 +314,7 @@ private enum CreatePollEntry: ItemListNodeEntry { }, tag: CreatePollEntryTag.text) case let .optionsHeader(text): return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) - case let .option(id, _, placeholder, text, revealed, hasNext, isLast, isSelected): + case let .option(id, _, placeholder, text, revealed, hasNext, isLast, canMove, isSelected): return CreatePollOptionItem(presentationData: presentationData, id: id, placeholder: placeholder, value: text, isSelected: isSelected, maxLength: maxOptionLength, editing: CreatePollOptionItemEditing(editable: true, hasActiveRevealControls: revealed), sectionId: self.section, setItemIdWithRevealedOptions: { id, fromId in arguments.setItemIdWithRevealedOptions(id, fromId) }, updated: { value, isFocused in @@ -328,6 +328,7 @@ private enum CreatePollEntry: ItemListNodeEntry { arguments.moveToPreviousOption(id) } }, canDelete: !isLast, + canMove: canMove, focused: { isFocused in arguments.optionFocused(id, isFocused) }, toggleSelected: { @@ -393,7 +394,7 @@ private func createPollControllerEntries(presentationData: PresentationData, pee let isSecondLast = state.options.count == 2 && i == 0 let isLast = i == state.options.count - 1 let option = state.options[i].item - entries.append(.option(id: option.id, ordering: state.options[i].ordering, placeholder: isLast ? presentationData.strings.CreatePoll_AddOption : presentationData.strings.CreatePoll_OptionPlaceholder, text: option.text, revealed: state.optionIdWithRevealControls == option.id, hasNext: i != 9, isLast: isLast || isSecondLast, isSelected: state.isQuiz ? option.isSelected : nil)) + entries.append(.option(id: option.id, ordering: state.options[i].ordering, placeholder: isLast ? presentationData.strings.CreatePoll_AddOption : presentationData.strings.CreatePoll_OptionPlaceholder, text: option.text, revealed: state.optionIdWithRevealControls == option.id, hasNext: i != 9, isLast: isLast || isSecondLast, canMove: !isLast || state.options.count == 10, isSelected: state.isQuiz ? option.isSelected : nil)) } if state.options.count < maxOptionCount { entries.append(.optionsInfo(presentationData.strings.CreatePoll_AddMoreOptions(Int32(maxOptionCount - state.options.count)))) diff --git a/submodules/ComposePollUI/Sources/CreatePollOptionItem.swift b/submodules/ComposePollUI/Sources/CreatePollOptionItem.swift index 6a658bac2a..026339a6b6 100644 --- a/submodules/ComposePollUI/Sources/CreatePollOptionItem.swift +++ b/submodules/ComposePollUI/Sources/CreatePollOptionItem.swift @@ -27,11 +27,12 @@ class CreatePollOptionItem: ListViewItem, ItemListItem { let next: (() -> Void)? let delete: (Bool) -> Void let canDelete: Bool + let canMove: Bool let focused: (Bool) -> Void let toggleSelected: () -> Void let tag: ItemListItemTag? - init(presentationData: ItemListPresentationData, id: Int, placeholder: String, value: String, isSelected: Bool?, maxLength: Int, editing: CreatePollOptionItemEditing, sectionId: ItemListSectionId, setItemIdWithRevealedOptions: @escaping (Int?, Int?) -> Void, updated: @escaping (String, Bool) -> Void, next: (() -> Void)?, delete: @escaping (Bool) -> Void, canDelete: Bool, focused: @escaping (Bool) -> Void, toggleSelected: @escaping () -> Void, tag: ItemListItemTag?) { + init(presentationData: ItemListPresentationData, id: Int, placeholder: String, value: String, isSelected: Bool?, maxLength: Int, editing: CreatePollOptionItemEditing, sectionId: ItemListSectionId, setItemIdWithRevealedOptions: @escaping (Int?, Int?) -> Void, updated: @escaping (String, Bool) -> Void, next: (() -> Void)?, delete: @escaping (Bool) -> Void, canDelete: Bool, canMove: Bool, focused: @escaping (Bool) -> Void, toggleSelected: @escaping () -> Void, tag: ItemListItemTag?) { self.presentationData = presentationData self.id = id self.placeholder = placeholder @@ -45,6 +46,7 @@ class CreatePollOptionItem: ListViewItem, ItemListItem { self.next = next self.delete = delete self.canDelete = canDelete + self.canMove = canMove self.focused = focused self.toggleSelected = toggleSelected self.tag = tag @@ -442,7 +444,7 @@ class CreatePollOptionItemNode: ItemListRevealOptionsItemNode, ItemListItemNode, let _ = reorderSizeAndApply.1(layout.contentSize.height, displayTextLimit, transition) let reorderControlFrame = CGRect(origin: CGPoint(x: params.width + revealOffset - params.rightInset - reorderSizeAndApply.0, y: 0.0), size: CGSize(width: reorderSizeAndApply.0, height: layout.contentSize.height)) strongSelf.reorderControlNode.frame = reorderControlFrame - strongSelf.reorderControlNode.isHidden = !item.canDelete + strongSelf.reorderControlNode.isHidden = !item.canMove let _ = textLimitApply() strongSelf.textLimitNode.frame = CGRect(origin: CGPoint(x: reorderControlFrame.minX + floor((reorderControlFrame.width - textLimitLayout.size.width) / 2.0) - 4.0 - UIScreenPixel, y: max(floor(reorderControlFrame.midY + 2.0), layout.contentSize.height - 15.0 - textLimitLayout.size.height)), size: textLimitLayout.size) From 13b0847b1e459871b7163b76b442fc41e06acf4b Mon Sep 17 00:00:00 2001 From: Ali <> Date: Thu, 23 Jan 2020 23:34:08 +0400 Subject: [PATCH 26/50] Don't use white-on-white colors --- .../Sources/DefaultDarkPresentationTheme.swift | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift index e1be4c62bf..6d330fa665 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift @@ -147,7 +147,14 @@ public func customizeDefaultDarkPresentationTheme(theme: PresentationTheme, edit polls: chat.message.incoming.polls.withUpdated( radioProgress: accentColor, highlight: accentColor?.withAlphaComponent(0.12), - bar: accentColor + bar: accentColor, + barIconForeground: accentColor.flatMap { accentColor -> UIColor in + if accentColor.rgb == 0xffffff { + return .clear + } else { + return .white + } + } ), textSelectionColor: accentColor?.withAlphaComponent(0.2), textSelectionKnobColor: accentColor @@ -387,7 +394,7 @@ public func makeDefaultDarkPresentationTheme(extendingThemeReference: Presentati ) let message = PresentationThemeChatMessage( - incoming: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x262628), highlightedFill: UIColor(rgb: 0x353539), stroke: UIColor(rgb: 0x262628)), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x262628), highlightedFill: UIColor(rgb: 0x353539), stroke: UIColor(rgb: 0x262628))), primaryTextColor: UIColor(rgb: 0xffffff), secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.5), linkTextColor: UIColor(rgb: 0xffffff), linkHighlightColor: UIColor(rgb: 0xffffff, alpha: 0.5), scamColor: UIColor(rgb: 0xeb5545), textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: UIColor(rgb: 0xffffff), accentControlColor: UIColor(rgb: 0xffffff), accentControlDisabledColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaActiveControlColor: UIColor(rgb: 0xffffff), mediaInactiveControlColor: UIColor(rgb: 0xffffff, alpha: 0.4), mediaControlInnerBackgroundColor: UIColor(rgb: 0x262628), pendingActivityColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileTitleColor: UIColor(rgb: 0xffffff), fileDescriptionColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileDurationColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaPlaceholderColor: UIColor(rgb: 0x1f1f1f).mixedWith(UIColor(rgb: 0xffffff), alpha: 0.05), polls: PresentationThemeChatBubblePolls(radioButton: UIColor(rgb: 0x737373), radioProgress: UIColor(rgb: 0xffffff), highlight: UIColor(rgb: 0xffffff, alpha: 0.12), separator: UIColor(rgb: 0x000000), bar: UIColor(rgb: 0xffffff), barIconForeground: .white, barPositive: UIColor(rgb: 0x00A700), barNegative: UIColor(rgb: 0xFE3824)), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: UIColor(rgb: 0x000000, alpha: 0.5), withoutWallpaper: UIColor(rgb: 0x000000, alpha: 0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xb2b2b2, alpha: 0.18)), actionButtonsTextColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xffffff)), textSelectionColor: UIColor(rgb: 0xffffff, alpha: 0.2), textSelectionKnobColor: UIColor(rgb: 0xffffff)), + incoming: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x262628), highlightedFill: UIColor(rgb: 0x353539), stroke: UIColor(rgb: 0x262628)), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x262628), highlightedFill: UIColor(rgb: 0x353539), stroke: UIColor(rgb: 0x262628))), primaryTextColor: UIColor(rgb: 0xffffff), secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.5), linkTextColor: UIColor(rgb: 0xffffff), linkHighlightColor: UIColor(rgb: 0xffffff, alpha: 0.5), scamColor: UIColor(rgb: 0xeb5545), textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: UIColor(rgb: 0xffffff), accentControlColor: UIColor(rgb: 0xffffff), accentControlDisabledColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaActiveControlColor: UIColor(rgb: 0xffffff), mediaInactiveControlColor: UIColor(rgb: 0xffffff, alpha: 0.4), mediaControlInnerBackgroundColor: UIColor(rgb: 0x262628), pendingActivityColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileTitleColor: UIColor(rgb: 0xffffff), fileDescriptionColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileDurationColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaPlaceholderColor: UIColor(rgb: 0x1f1f1f).mixedWith(UIColor(rgb: 0xffffff), alpha: 0.05), polls: PresentationThemeChatBubblePolls(radioButton: UIColor(rgb: 0x737373), radioProgress: UIColor(rgb: 0xffffff), highlight: UIColor(rgb: 0xffffff, alpha: 0.12), separator: UIColor(rgb: 0x000000), bar: UIColor(rgb: 0xffffff), barIconForeground: .clear, barPositive: UIColor(rgb: 0x00A700), barNegative: UIColor(rgb: 0xFE3824)), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: UIColor(rgb: 0x000000, alpha: 0.5), withoutWallpaper: UIColor(rgb: 0x000000, alpha: 0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xb2b2b2, alpha: 0.18)), actionButtonsTextColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xffffff)), textSelectionColor: UIColor(rgb: 0xffffff, alpha: 0.2), textSelectionKnobColor: UIColor(rgb: 0xffffff)), outgoing: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x313131), gradientFill: UIColor(rgb: 0x313131), highlightedFill: UIColor(rgb: 0x464646), stroke: UIColor(rgb: 0x313131)), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x313131), gradientFill: UIColor(rgb: 0x313131), highlightedFill: UIColor(rgb: 0x464646), stroke: UIColor(rgb: 0x313131))), primaryTextColor: UIColor(rgb: 0xffffff), secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.5), linkTextColor: UIColor(rgb: 0xffffff), linkHighlightColor: UIColor(rgb: 0xffffff, alpha: 0.5), scamColor: UIColor(rgb: 0xeb5545), textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: UIColor(rgb: 0xffffff), accentControlColor: UIColor(rgb: 0xffffff), accentControlDisabledColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaActiveControlColor: UIColor(rgb: 0xffffff), mediaInactiveControlColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaControlInnerBackgroundColor: UIColor(rgb: 0x313131), pendingActivityColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileTitleColor: UIColor(rgb: 0xffffff), fileDescriptionColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileDurationColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaPlaceholderColor: UIColor(rgb: 0x313131).mixedWith(UIColor(rgb: 0xffffff), alpha: 0.05), polls: PresentationThemeChatBubblePolls(radioButton: UIColor(rgb: 0xffffff), radioProgress: UIColor(rgb: 0xffffff), highlight: UIColor(rgb: 0xffffff).withAlphaComponent(0.12), separator: UIColor(rgb: 0xffffff, alpha: 0.5), bar: UIColor(rgb: 0xffffff), barIconForeground: .clear, barPositive: UIColor(rgb: 0xffffff), barNegative: UIColor(rgb: 0xffffff)), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: UIColor(rgb: 0x000000, alpha: 0.5), withoutWallpaper: UIColor(rgb: 0x000000, alpha: 0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xb2b2b2, alpha: 0.18)), actionButtonsTextColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xffffff)), textSelectionColor: UIColor(rgb: 0xffffff, alpha: 0.2), textSelectionKnobColor: UIColor(rgb: 0xffffff)), freeform: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x1f1f1f), highlightedFill: UIColor(rgb: 0x2a2a2a), stroke: UIColor(rgb: 0x1f1f1f)), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x1f1f1f), highlightedFill: UIColor(rgb: 0x2a2a2a), stroke: UIColor(rgb: 0x1f1f1f))), infoPrimaryTextColor: UIColor(rgb: 0xffffff), From d2e3c9d54a99e97f06fc75b16e44dfb64ddff505 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 24 Jan 2020 13:01:49 +0400 Subject: [PATCH 27/50] Experimental chat list filtering --- .../Sources/ChatListController.swift | 18 +- .../Sources/Node/ChatListItem.swift | 2 +- .../Sources/Node/ChatListNode.swift | 58 ++- .../Sources/Node/ChatListNodeLocation.swift | 80 ++- .../Sources/Node/ChatListViewTransition.swift | 1 + .../TabBarChatListFilterController.swift | 477 ++++++++++++++++++ .../Postbox/Sources/ChatListTable.swift | 103 +++- submodules/Postbox/Sources/ChatListView.swift | 74 ++- .../PeerNotificationSettingsTable.swift | 8 +- .../PeerNotificationSettingsView.swift | 2 +- submodules/Postbox/Sources/PeerView.swift | 4 +- submodules/Postbox/Sources/Postbox.swift | 66 ++- .../Postbox/Sources/PostboxTransaction.swift | 4 +- .../Postbox/Sources/SqliteValueBox.swift | 32 ++ submodules/Postbox/Sources/ValueBox.swift | 7 + .../Sources/AccountViewTracker.swift | 8 +- .../Sources/ChatMessageBubbleImages.swift | 21 +- .../TelegramUI/ChatMessageBackground.swift | 2 +- 18 files changed, 880 insertions(+), 87 deletions(-) create mode 100644 submodules/ChatListUI/Sources/TabBarChatListFilterController.swift diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index f2049711c5..44110de78e 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -99,7 +99,7 @@ private final class ContextControllerContentSourceImpl: ContextControllerContent } } -public class ChatListControllerImpl: TelegramBaseController, ChatListController, UIViewControllerPreviewingDelegate { +public class ChatListControllerImpl: TelegramBaseController, ChatListController, UIViewControllerPreviewingDelegate, TabBarContainedController { private var validLayout: ContainerViewLayout? public let context: AccountContext @@ -1790,4 +1790,20 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, return nil } } + + public func presentTabBarPreviewingController(sourceNodes: [ASDisplayNode]) { + if self.isNodeLoaded { + let controller = TabBarChatListFilterController(context: self.context, sourceNodes: sourceNodes, currentFilter: self.chatListDisplayNode.chatListNode.chatListFilter, updateFilter: { [weak self] value in + guard let strongSelf = self else { + return + } + strongSelf.chatListDisplayNode.chatListNode.chatListFilter = value + }) + self.context.sharedContext.mainWindow?.present(controller, on: .root) + } + } + + public func updateTabBarPreviewingControllerPresentation(_ update: TabBarContainedControllerPresentationUpdate) { + + } } diff --git a/submodules/ChatListUI/Sources/Node/ChatListItem.swift b/submodules/ChatListUI/Sources/Node/ChatListItem.swift index 8803effaeb..0996cf6aff 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItem.swift @@ -699,7 +699,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { isPeerGroup = false isAd = isAdValue displayAsMessage = displayAsMessageValue - hasFailedMessages = hasFailedMessagesValue + hasFailedMessages = messageValue?.flags.contains(.Failed) ?? false // hasFailedMessagesValue case let .groupReference(_, peers, messageValue, unreadState, hiddenByDefault): if let _ = messageValue, !peers.isEmpty { contentPeer = .chat(peers[0].peer) diff --git a/submodules/ChatListUI/Sources/Node/ChatListNode.swift b/submodules/ChatListUI/Sources/Node/ChatListNode.swift index 0276a2bd8b..a585454f05 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNode.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNode.swift @@ -366,6 +366,14 @@ public final class ChatListNode: ListView { } private var currentLocation: ChatListNodeLocation? + var chatListFilter: ChatListNodeFilter = .all { + didSet { + if self.chatListFilter != oldValue { + self.chatListFilterValue.set(self.chatListFilter) + } + } + } + private let chatListFilterValue = ValuePromise(.all) private let chatListLocation = ValuePromise() private let chatListDisposable = MetaDisposable() private var activityStatusesDisposable: Disposable? @@ -522,10 +530,21 @@ public final class ChatListNode: ListView { let viewProcessingQueue = self.viewProcessingQueue - let chatListViewUpdate = self.chatListLocation.get() - |> distinctUntilChanged - |> mapToSignal { location in - return chatListViewForLocation(groupId: groupId, location: location, account: context.account) + let chatListViewUpdate = combineLatest(self.chatListLocation.get(), self.chatListFilterValue.get()) + |> distinctUntilChanged(isEqual: { lhs, rhs in + if lhs.0 != rhs.0 { + return false + } + if lhs.1 != rhs.1 { + return false + } + return true + }) + |> mapToSignal { location, filter -> Signal<(ChatListNodeViewUpdate, ChatListNodeFilter), NoError> in + return chatListViewForLocation(groupId: groupId, filter: filter, location: location, account: context.account) + |> map { update in + return (update, filter) + } } let previousState = Atomic(value: self.currentState) @@ -575,7 +594,8 @@ public final class ChatListNode: ListView { let currentPeerId: PeerId = context.account.peerId let chatListNodeViewTransition = combineLatest(queue: viewProcessingQueue, hideArchivedFolderByDefault, displayArchiveIntro, savedMessagesPeer, chatListViewUpdate, self.statePromise.get()) - |> mapToQueue { (hideArchivedFolderByDefault, displayArchiveIntro, savedMessagesPeer, update, state) -> Signal in + |> mapToQueue { (hideArchivedFolderByDefault, displayArchiveIntro, savedMessagesPeer, updateAndFilter, state) -> Signal in + let (update, filter) = updateAndFilter let previousHideArchivedFolderByDefaultValue = previousHideArchivedFolderByDefault.swap(hideArchivedFolderByDefault) @@ -633,7 +653,7 @@ public final class ChatListNode: ListView { } } - let processedView = ChatListNodeView(originalView: update.view, filteredEntries: entries, isLoading: isLoading) + let processedView = ChatListNodeView(originalView: update.view, filteredEntries: entries, isLoading: isLoading, filter: filter) let previousView = previousView.swap(processedView) let previousState = previousState.swap(state) @@ -746,6 +766,10 @@ public final class ChatListNode: ListView { searchMode = true } + if filter != previousView?.filter { + disableAnimations = true + } + return preparedChatListNodeViewTransition(from: previousView, to: processedView, reason: reason, previewing: previewing, disableAnimations: disableAnimations, account: context.account, scrollPosition: updatedScrollPosition, searchMode: searchMode) |> map({ mappedChatListNodeViewListTransition(context: context, nodeInteraction: nodeInteraction, peerGroupId: groupId, mode: mode, transition: $0) }) |> runOn(prepareOnMainQueue ? Queue.mainQueue() : viewProcessingQueue) @@ -1439,17 +1463,23 @@ public final class ChatListNode: ListView { guard index < 10 else { return } - let _ = (chatListViewForLocation(groupId: self.groupId, location: .initial(count: 10), account: self.context.account) + let _ = (self.chatListFilterValue.get() |> take(1) - |> deliverOnMainQueue).start(next: { update in - let entries = update.view.entries - if entries.count > index, case let .MessageEntry(index, _, _, _, _, renderedPeer, _, _, _) = entries[10 - index - 1] { - let location: ChatListNodeLocation = .scroll(index: index, sourceIndex: .absoluteLowerBound, scrollPosition: .center(.top), animated: true) - self.setChatListLocation(location) - self.peerSelected?(renderedPeer.peerId, false, false) + |> deliverOnMainQueue).start(next: { [weak self] filter in + guard let self = self else { + return } + let _ = (chatListViewForLocation(groupId: self.groupId, filter: filter, location: .initial(count: 10), account: self.context.account) + |> take(1) + |> deliverOnMainQueue).start(next: { update in + let entries = update.view.entries + if entries.count > index, case let .MessageEntry(index, _, _, _, _, renderedPeer, _, _, _) = entries[10 - index - 1] { + let location: ChatListNodeLocation = .scroll(index: index, sourceIndex: .absoluteLowerBound, scrollPosition: .center(.top), animated: true) + self.setChatListLocation(location) + self.peerSelected?(renderedPeer.peerId, false, false) + } + }) }) - break } } diff --git a/submodules/ChatListUI/Sources/Node/ChatListNodeLocation.swift b/submodules/ChatListUI/Sources/Node/ChatListNodeLocation.swift index 45a78f684b..93e631b8f6 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNodeLocation.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNodeLocation.swift @@ -31,18 +31,90 @@ struct ChatListNodeViewUpdate { let scrollPosition: ChatListNodeViewScrollPosition? } -func chatListViewForLocation(groupId: PeerGroupId, location: ChatListNodeLocation, account: Account) -> Signal { +struct ChatListNodeFilter: OptionSet { + var rawValue: Int32 + + init(rawValue: Int32) { + self.rawValue = rawValue + } + + static let muted = ChatListNodeFilter(rawValue: 1 << 1) + static let privateChats = ChatListNodeFilter(rawValue: 1 << 2) + static let groups = ChatListNodeFilter(rawValue: 1 << 3) + static let bots = ChatListNodeFilter(rawValue: 1 << 4) + static let channels = ChatListNodeFilter(rawValue: 1 << 5) + + static let all: ChatListNodeFilter = [ + .muted, + .privateChats, + .groups, + .bots, + .channels + ] +} + +func chatListViewForLocation(groupId: PeerGroupId, filter: ChatListNodeFilter, location: ChatListNodeLocation, account: Account) -> Signal { + let filterPredicate: ((Peer, PeerNotificationSettings?) -> Bool)? + if filter == .all { + filterPredicate = nil + } else { + filterPredicate = { peer, notificationSettings in + if !filter.contains(.muted) { + if let notificationSettings = notificationSettings as? TelegramPeerNotificationSettings { + if case .muted = notificationSettings.muteState { + return false + } + } else { + return false + } + } + if !filter.contains(.privateChats) { + if let user = peer as? TelegramUser { + if user.botInfo == nil { + return false + } + } else if let _ = peer as? TelegramSecretChat { + return false + } + } + if !filter.contains(.bots) { + if let user = peer as? TelegramUser { + if user.botInfo != nil { + return false + } + } + } + if !filter.contains(.groups) { + if let _ = peer as? TelegramGroup { + return false + } else if let channel = peer as? TelegramChannel { + if case .group = channel.info { + return false + } + } + } + if !filter.contains(.channels) { + if let channel = peer as? TelegramChannel { + if case .broadcast = channel.info { + return false + } + } + } + return true + } + } + switch location { case let .initial(count): let signal: Signal<(ChatListView, ViewUpdateType), NoError> - signal = account.viewTracker.tailChatListView(groupId: groupId, count: count) + signal = account.viewTracker.tailChatListView(groupId: groupId, filterPredicate: filterPredicate, count: count) return signal |> map { view, updateType -> ChatListNodeViewUpdate in return ChatListNodeViewUpdate(view: view, type: updateType, scrollPosition: nil) } case let .navigation(index): var first = true - return account.viewTracker.aroundChatListView(groupId: groupId, index: index, count: 80) + return account.viewTracker.aroundChatListView(groupId: groupId, filterPredicate: filterPredicate, index: index, count: 80) |> map { view, updateType -> ChatListNodeViewUpdate in let genericType: ViewUpdateType if first { @@ -57,7 +129,7 @@ func chatListViewForLocation(groupId: PeerGroupId, location: ChatListNodeLocatio let directionHint: ListViewScrollToItemDirectionHint = sourceIndex > index ? .Down : .Up let chatScrollPosition: ChatListNodeViewScrollPosition = .index(index: index, position: scrollPosition, directionHint: directionHint, animated: animated) var first = true - return account.viewTracker.aroundChatListView(groupId: groupId, index: index, count: 80) + return account.viewTracker.aroundChatListView(groupId: groupId, filterPredicate: filterPredicate, index: index, count: 80) |> map { view, updateType -> ChatListNodeViewUpdate in let genericType: ViewUpdateType let scrollPosition: ChatListNodeViewScrollPosition? = first ? chatScrollPosition : nil diff --git a/submodules/ChatListUI/Sources/Node/ChatListViewTransition.swift b/submodules/ChatListUI/Sources/Node/ChatListViewTransition.swift index 6c10849cca..17350a0f77 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListViewTransition.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListViewTransition.swift @@ -11,6 +11,7 @@ struct ChatListNodeView { let originalView: ChatListView let filteredEntries: [ChatListNodeEntry] let isLoading: Bool + let filter: ChatListNodeFilter } enum ChatListNodeViewTransitionReason { diff --git a/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift b/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift new file mode 100644 index 0000000000..8048568cbd --- /dev/null +++ b/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift @@ -0,0 +1,477 @@ +import Foundation +import UIKit +import Display +import SwiftSignalKit +import AsyncDisplayKit +import TelegramPresentationData +import AccountContext + +final class TabBarChatListFilterController: ViewController { + private var controllerNode: TabBarChatListFilterControllerNode { + return self.displayNode as! TabBarChatListFilterControllerNode + } + + private let _ready = Promise(true) + override public var ready: Promise { + return self._ready + } + + private let context: AccountContext + private let sourceNodes: [ASDisplayNode] + private let currentFilter: ChatListNodeFilter + private let updateFilter: (ChatListNodeFilter) -> Void + + private var presentationData: PresentationData + private var didPlayPresentationAnimation = false + + private let hapticFeedback = HapticFeedback() + + public init(context: AccountContext, sourceNodes: [ASDisplayNode], currentFilter: ChatListNodeFilter, updateFilter: @escaping (ChatListNodeFilter) -> Void) { + self.context = context + self.sourceNodes = sourceNodes + self.currentFilter = currentFilter + self.updateFilter = updateFilter + + self.presentationData = context.sharedContext.currentPresentationData.with { $0 } + + super.init(navigationBarPresentationData: nil) + + self.statusBar.statusBarStyle = .Ignore + self.statusBar.ignoreInCall = true + + self.lockOrientation = true + } + + required public init(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + deinit { + } + + override public func loadDisplayNode() { + self.displayNode = TabBarChatListFilterControllerNode(context: self.context, presentationData: self.presentationData, cancel: { [weak self] in + self?.dismiss() + }, sourceNodes: self.sourceNodes, currentFilter: self.currentFilter, updateFilter: self.updateFilter) + self.displayNodeDidLoad() + } + + override public func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + if !self.didPlayPresentationAnimation { + self.didPlayPresentationAnimation = true + + self.hapticFeedback.impact() + self.controllerNode.animateIn() + } + } + + override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { + super.containerLayoutUpdated(layout, transition: transition) + + self.controllerNode.containerLayoutUpdated(layout, transition: transition) + } + + override public func dismiss(completion: (() -> Void)? = nil) { + self.dismiss(sourceNodes: []) + } + + public func dismiss(sourceNodes: [ASDisplayNode]) { + self.controllerNode.animateOut(sourceNodes: sourceNodes, completion: { [weak self] in + self?.didPlayPresentationAnimation = false + self?.presentingViewController?.dismiss(animated: false, completion: nil) + }) + } +} + +private let animationDurationFactor: Double = 1.0 + +private protocol AbstractTabBarChatListFilterItemNode { + func updateLayout(maxWidth: CGFloat) -> (CGFloat, CGFloat, (CGFloat) -> Void) +} + +private final class FilterItemNode: ASDisplayNode, AbstractTabBarChatListFilterItemNode { + private let context: AccountContext + private let title: String + private let isCurrent: Bool + private let presentationData: PresentationData + private let action: () -> Bool + + private let separatorNode: ASDisplayNode + private let highlightedBackgroundNode: ASDisplayNode + private let buttonNode: HighlightTrackingButtonNode + private let titleNode: ImmediateTextNode + private let checkNode: ASImageNode + + private let badgeBackgroundNode: ASImageNode + private let badgeTitleNode: ImmediateTextNode + + init(context: AccountContext, title: String, isCurrent: Bool, displaySeparator: Bool, presentationData: PresentationData, action: @escaping () -> Bool) { + self.context = context + self.title = title + self.isCurrent = isCurrent + self.presentationData = presentationData + self.action = action + + self.separatorNode = ASDisplayNode() + self.separatorNode.backgroundColor = presentationData.theme.actionSheet.opaqueItemSeparatorColor + self.separatorNode.isHidden = !displaySeparator + + self.highlightedBackgroundNode = ASDisplayNode() + self.highlightedBackgroundNode.backgroundColor = presentationData.theme.actionSheet.opaqueItemHighlightedBackgroundColor + self.highlightedBackgroundNode.alpha = 0.0 + + self.buttonNode = HighlightTrackingButtonNode() + + self.titleNode = ImmediateTextNode() + self.titleNode.maximumNumberOfLines = 1 + self.titleNode.attributedText = NSAttributedString(string: title, font: Font.regular(17.0), textColor: presentationData.theme.actionSheet.primaryTextColor) + + self.checkNode = ASImageNode() + self.checkNode.image = generateItemListCheckIcon(color: presentationData.theme.actionSheet.primaryTextColor) + self.checkNode.isHidden = !isCurrent + + self.badgeBackgroundNode = ASImageNode() + self.badgeBackgroundNode.image = generateStretchableFilledCircleImage(diameter: 20.0, color: presentationData.theme.list.itemCheckColors.fillColor) + self.badgeTitleNode = ImmediateTextNode() + self.badgeBackgroundNode.isHidden = true + self.badgeTitleNode.isHidden = true + + super.init() + + self.addSubnode(self.separatorNode) + self.addSubnode(self.highlightedBackgroundNode) + self.addSubnode(self.titleNode) + self.addSubnode(self.checkNode) + self.addSubnode(self.badgeBackgroundNode) + self.addSubnode(self.badgeTitleNode) + self.addSubnode(self.buttonNode) + + self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside) + self.buttonNode.highligthedChanged = { [weak self] highlighted in + if let strongSelf = self { + if highlighted { + strongSelf.highlightedBackgroundNode.layer.removeAnimation(forKey: "opacity") + strongSelf.highlightedBackgroundNode.alpha = 1.0 + } else { + strongSelf.highlightedBackgroundNode.alpha = 0.0 + strongSelf.highlightedBackgroundNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3) + } + } + } + } + + func updateLayout(maxWidth: CGFloat) -> (CGFloat, CGFloat, (CGFloat) -> Void) { + let leftInset: CGFloat = 16.0 + + let badgeTitleSize = self.badgeTitleNode.updateLayout(CGSize(width: 100.0, height: .greatestFiniteMagnitude)) + let badgeMinSize = self.badgeBackgroundNode.image?.size.width ?? 20.0 + let badgeSize = CGSize(width: max(badgeMinSize, badgeTitleSize.width + 12.0), height: badgeMinSize) + + let rightInset: CGFloat = max(60.0, badgeSize.width + 40.0) + + let titleSize = self.titleNode.updateLayout(CGSize(width: maxWidth - leftInset - rightInset, height: .greatestFiniteMagnitude)) + + let height: CGFloat = 61.0 + + return (titleSize.width + leftInset + rightInset, height, { width in + self.titleNode.frame = CGRect(origin: CGPoint(x: leftInset, y: floor((height - titleSize.height) / 2.0)), size: titleSize) + + if let image = self.checkNode.image { + self.checkNode.frame = CGRect(origin: CGPoint(x: width - rightInset + floor((rightInset - image.size.width) / 2.0), y: floor((height - image.size.height) / 2.0)), size: image.size) + } + + let badgeBackgroundFrame = CGRect(origin: CGPoint(x: width - rightInset + floor((rightInset - badgeSize.width) / 2.0), y: floor((height - badgeSize.height) / 2.0)), size: badgeSize) + self.badgeBackgroundNode.frame = badgeBackgroundFrame + self.badgeTitleNode.frame = CGRect(origin: CGPoint(x: badgeBackgroundFrame.minX + floor((badgeBackgroundFrame.width - badgeTitleSize.width) / 2.0), y: badgeBackgroundFrame.minY + floor((badgeBackgroundFrame.height - badgeTitleSize.height) / 2.0)), size: badgeTitleSize) + + self.separatorNode.frame = CGRect(origin: CGPoint(x: 0.0, y: height - UIScreenPixel), size: CGSize(width: width, height: UIScreenPixel)) + self.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: width, height: height)) + self.buttonNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: width, height: height)) + }) + } + + @objc private func buttonPressed() { + let isCurrent = self.action() + self.checkNode.isHidden = !isCurrent + } +} + +private final class TabBarChatListFilterControllerNode: ViewControllerTracingNode { + private let presentationData: PresentationData + private let cancel: () -> Void + + private let effectView: UIVisualEffectView + private var propertyAnimator: AnyObject? + private var displayLinkAnimator: DisplayLinkAnimator? + private let dimNode: ASDisplayNode + + private let contentContainerNode: ASDisplayNode + private let contentNodes: [ASDisplayNode & AbstractTabBarChatListFilterItemNode] + + private var sourceNodes: [ASDisplayNode] + private var snapshotViews: [UIView] = [] + + private var validLayout: ContainerViewLayout? + + init(context: AccountContext, presentationData: PresentationData, cancel: @escaping () -> Void, sourceNodes: [ASDisplayNode], currentFilter: ChatListNodeFilter, updateFilter: @escaping (ChatListNodeFilter) -> Void) { + self.presentationData = presentationData + self.cancel = cancel + self.sourceNodes = sourceNodes + + self.effectView = UIVisualEffectView() + if #available(iOS 9.0, *) { + } else { + if presentationData.theme.rootController.keyboardColor == .dark { + self.effectView.effect = UIBlurEffect(style: .dark) + } else { + self.effectView.effect = UIBlurEffect(style: .light) + } + self.effectView.alpha = 0.0 + } + + self.dimNode = ASDisplayNode() + self.dimNode.alpha = 1.0 + if presentationData.theme.rootController.keyboardColor == .light { + self.dimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.04) + } else { + self.dimNode.backgroundColor = presentationData.theme.chatList.backgroundColor.withAlphaComponent(0.2) + } + + self.contentContainerNode = ASDisplayNode() + self.contentContainerNode.backgroundColor = self.presentationData.theme.actionSheet.opaqueItemBackgroundColor + self.contentContainerNode.cornerRadius = 20.0 + self.contentContainerNode.clipsToBounds = true + + var contentNodes: [ASDisplayNode & AbstractTabBarChatListFilterItemNode] = [] + + let labels: [(String, ChatListNodeFilter)] = [ + ("Private Chats", .privateChats), + ("Groups", .groups), + ("Bots", .bots), + ("Channels", .channels), + ("Muted", .muted) + ] + + var updatedFilter = currentFilter + let toggleFilter: (ChatListNodeFilter) -> Void = { filter in + if updatedFilter.contains(filter) { + updatedFilter.remove(filter) + } else { + updatedFilter.insert(filter) + } + updateFilter(updatedFilter) + } + + for i in 0 ..< labels.count { + let filter = labels[i].1 + contentNodes.append(FilterItemNode(context: context, title: labels[i].0, isCurrent: updatedFilter.contains(filter), displaySeparator: i != labels.count - 1, presentationData: presentationData, action: { + toggleFilter(filter) + return updatedFilter.contains(filter) + })) + } + self.contentNodes = contentNodes + + super.init() + + self.view.addSubview(self.effectView) + self.addSubnode(self.dimNode) + self.addSubnode(self.contentContainerNode) + self.contentNodes.forEach(self.contentContainerNode.addSubnode) + + self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture(_:)))) + } + + deinit { + if let propertyAnimator = self.propertyAnimator { + if #available(iOSApplicationExtension 10.0, iOS 10.0, *) { + let propertyAnimator = propertyAnimator as? UIViewPropertyAnimator + propertyAnimator?.stopAnimation(true) + } + } + } + + func animateIn() { + self.dimNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) + + if #available(iOS 10.0, *) { + if let propertyAnimator = self.propertyAnimator { + let propertyAnimator = propertyAnimator as? UIViewPropertyAnimator + propertyAnimator?.stopAnimation(true) + } + self.propertyAnimator = UIViewPropertyAnimator(duration: 0.2 * animationDurationFactor, curve: .easeInOut, animations: { [weak self] in + self?.effectView.effect = makeCustomZoomBlurEffect() + }) + } + + if let _ = self.propertyAnimator { + if #available(iOSApplicationExtension 10.0, iOS 10.0, *) { + self.displayLinkAnimator = DisplayLinkAnimator(duration: 0.2 * animationDurationFactor, from: 0.0, to: 1.0, update: { [weak self] value in + (self?.propertyAnimator as? UIViewPropertyAnimator)?.fractionComplete = value + }, completion: { + }) + } + } else { + UIView.animate(withDuration: 0.2 * animationDurationFactor, animations: { + self.effectView.effect = makeCustomZoomBlurEffect() + }, completion: { _ in + }) + } + + self.contentContainerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) + + if let _ = self.validLayout, let sourceNode = self.sourceNodes.first { + let sourceFrame = sourceNode.view.convert(sourceNode.bounds, to: self.view) + self.contentContainerNode.layer.animateFrame(from: sourceFrame, to: self.contentContainerNode.frame, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring) + } + + for sourceNode in self.sourceNodes { + if let imageNode = sourceNode as? ASImageNode { + let snapshot = UIImageView() + snapshot.image = imageNode.image + snapshot.frame = sourceNode.view.convert(sourceNode.bounds, to: self.view) + snapshot.isUserInteractionEnabled = false + self.view.addSubview(snapshot) + self.snapshotViews.append(snapshot) + } else if let snapshot = sourceNode.view.snapshotContentTree() { + snapshot.frame = sourceNode.view.convert(sourceNode.bounds, to: self.view) + snapshot.isUserInteractionEnabled = false + self.view.addSubview(snapshot) + self.snapshotViews.append(snapshot) + } + sourceNode.alpha = 0.0 + } + } + + func animateOut(sourceNodes: [ASDisplayNode], completion: @escaping () -> Void) { + self.isUserInteractionEnabled = false + + var completedEffect = false + var completedSourceNodes = false + + let intermediateCompletion: () -> Void = { + if completedEffect && completedSourceNodes { + completion() + } + } + + if #available(iOS 10.0, *) { + if let propertyAnimator = self.propertyAnimator { + let propertyAnimator = propertyAnimator as? UIViewPropertyAnimator + propertyAnimator?.stopAnimation(true) + } + self.propertyAnimator = UIViewPropertyAnimator(duration: 0.2, curve: .easeInOut, animations: { [weak self] in + self?.effectView.effect = nil + }) + } + + if let _ = self.propertyAnimator { + if #available(iOSApplicationExtension 10.0, iOS 10.0, *) { + self.displayLinkAnimator = DisplayLinkAnimator(duration: 0.2 * animationDurationFactor, from: 0.0, to: 0.999, update: { [weak self] value in + (self?.propertyAnimator as? UIViewPropertyAnimator)?.fractionComplete = value + }, completion: { [weak self] in + if let strongSelf = self { + for sourceNode in strongSelf.sourceNodes { + sourceNode.alpha = 1.0 + } + } + + completedEffect = true + intermediateCompletion() + }) + } + self.effectView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.05 * animationDurationFactor, delay: 0.15, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false) + } else { + UIView.animate(withDuration: 0.21 * animationDurationFactor, animations: { + if #available(iOS 9.0, *) { + self.effectView.effect = nil + } else { + self.effectView.alpha = 0.0 + } + }, completion: { [weak self] _ in + if let strongSelf = self { + for sourceNode in strongSelf.sourceNodes { + sourceNode.alpha = 1.0 + } + } + + completedEffect = true + intermediateCompletion() + }) + } + + self.dimNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false) + self.contentContainerNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.12, removeOnCompletion: false, completion: { _ in + }) + if let _ = self.validLayout, let sourceNode = self.sourceNodes.first { + let sourceFrame = sourceNode.view.convert(sourceNode.bounds, to: self.view) + self.contentContainerNode.layer.animateFrame(from: self.contentContainerNode.frame, to: sourceFrame, duration: 0.15, timingFunction: CAMediaTimingFunctionName.easeIn.rawValue, removeOnCompletion: false) + } + completedSourceNodes = true + } + + func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { + self.validLayout = layout + + transition.updateFrame(view: self.effectView, frame: CGRect(origin: CGPoint(), size: layout.size)) + transition.updateFrame(node: self.dimNode, frame: CGRect(origin: CGPoint(), size: layout.size)) + + let sideInset: CGFloat = 18.0 + + var contentSize = CGSize() + contentSize.width = min(layout.size.width - 40.0, 250.0) + var applyNodes: [(ASDisplayNode, CGFloat, (CGFloat) -> Void)] = [] + for itemNode in self.contentNodes { + let (width, height, apply) = itemNode.updateLayout(maxWidth: layout.size.width - sideInset * 2.0) + applyNodes.append((itemNode, height, apply)) + contentSize.width = max(contentSize.width, width) + contentSize.height += height + } + + let insets = layout.insets(options: .input) + + let contentOrigin: CGPoint + if let sourceNode = self.sourceNodes.first, let screenFrame = sourceNode.supernode?.convert(sourceNode.frame, to: nil) { + contentOrigin = CGPoint(x: screenFrame.maxX - contentSize.width + 8.0, y: layout.size.height - 66.0 - insets.bottom - contentSize.height) + } else { + contentOrigin = CGPoint(x: layout.size.width - sideInset - contentSize.width, y: layout.size.height - 66.0 - layout.intrinsicInsets.bottom - contentSize.height) + } + + transition.updateFrame(node: self.contentContainerNode, frame: CGRect(origin: contentOrigin, size: contentSize)) + var nextY: CGFloat = 0.0 + for (itemNode, height, apply) in applyNodes { + transition.updateFrame(node: itemNode, frame: CGRect(origin: CGPoint(x: 0.0, y: nextY), size: CGSize(width: contentSize.width, height: height))) + apply(contentSize.width) + nextY += height + } + } + + @objc private func dimTapGesture(_ recognizer: UITapGestureRecognizer) { + if case .ended = recognizer.state { + self.cancel() + } + } +} + +private func setAnchorPoint(anchorPoint: CGPoint, forView view: UIView) { + var newPoint = CGPoint(x: view.bounds.size.width * anchorPoint.x, + y: view.bounds.size.height * anchorPoint.y) + + + var oldPoint = CGPoint(x: view.bounds.size.width * view.layer.anchorPoint.x, + y: view.bounds.size.height * view.layer.anchorPoint.y) + + newPoint = newPoint.applying(view.transform) + oldPoint = oldPoint.applying(view.transform) + + var position = view.layer.position + position.x -= oldPoint.x + position.x += newPoint.x + + position.y -= oldPoint.y + position.y += newPoint.y + + view.layer.position = position + view.layer.anchorPoint = anchorPoint +} diff --git a/submodules/Postbox/Sources/ChatListTable.swift b/submodules/Postbox/Sources/ChatListTable.swift index 6b9682e432..b0c84fb807 100644 --- a/submodules/Postbox/Sources/ChatListTable.swift +++ b/submodules/Postbox/Sources/ChatListTable.swift @@ -381,7 +381,7 @@ final class ChatListTable: Table { self.valueBox.remove(self.table, key: self.key(groupId: groupId, index: ChatListIndex(pinningIndex: nil, messageIndex: index), type: .hole), secure: false) } - func entriesAround(groupId: PeerGroupId, index: ChatListIndex, messageHistoryTable: MessageHistoryTable, peerChatInterfaceStateTable: PeerChatInterfaceStateTable, count: Int) -> (entries: [ChatListIntermediateEntry], lower: ChatListIntermediateEntry?, upper: ChatListIntermediateEntry?) { + func entriesAround(groupId: PeerGroupId, index: ChatListIndex, messageHistoryTable: MessageHistoryTable, peerChatInterfaceStateTable: PeerChatInterfaceStateTable, count: Int, predicate: ((ChatListIntermediateEntry) -> Bool)?) -> (entries: [ChatListIntermediateEntry], lower: ChatListIntermediateEntry?, upper: ChatListIntermediateEntry?) { self.ensureInitialized(groupId: groupId) var lowerEntries: [ChatListIntermediateEntry] = [] @@ -389,18 +389,38 @@ final class ChatListTable: Table { var lower: ChatListIntermediateEntry? var upper: ChatListIntermediateEntry? - self.valueBox.range(self.table, start: self.key(groupId: groupId, index: index, type: .message), end: self.lowerBound(groupId: groupId), values: { key, value in - lowerEntries.append(readEntry(groupId: groupId, messageHistoryTable: messageHistoryTable, peerChatInterfaceStateTable: peerChatInterfaceStateTable, key: key, value: value)) - return true + self.valueBox.filteredRange(self.table, start: self.key(groupId: groupId, index: index, type: .message), end: self.lowerBound(groupId: groupId), values: { key, value in + let entry = readEntry(groupId: groupId, messageHistoryTable: messageHistoryTable, peerChatInterfaceStateTable: peerChatInterfaceStateTable, key: key, value: value) + if let predicate = predicate { + if predicate(entry) { + lowerEntries.append(entry) + return .accept + } else { + return .skip + } + } else { + lowerEntries.append(entry) + return .accept + } }, limit: count / 2 + 1) if lowerEntries.count >= count / 2 + 1 { lower = lowerEntries.last lowerEntries.removeLast() } - self.valueBox.range(self.table, start: self.key(groupId: groupId, index: index, type: .message).predecessor, end: self.upperBound(groupId: groupId), values: { key, value in - upperEntries.append(readEntry(groupId: groupId, messageHistoryTable: messageHistoryTable, peerChatInterfaceStateTable: peerChatInterfaceStateTable, key: key, value: value)) - return true + self.valueBox.filteredRange(self.table, start: self.key(groupId: groupId, index: index, type: .message).predecessor, end: self.upperBound(groupId: groupId), values: { key, value in + let entry = readEntry(groupId: groupId, messageHistoryTable: messageHistoryTable, peerChatInterfaceStateTable: peerChatInterfaceStateTable, key: key, value: value) + if let predicate = predicate { + if predicate(entry) { + upperEntries.append(entry) + return .accept + } else { + return .skip + } + } else { + upperEntries.append(entry) + return .accept + } }, limit: count - lowerEntries.count + 1) if upperEntries.count >= count - lowerEntries.count + 1 { upper = upperEntries.last @@ -415,12 +435,20 @@ final class ChatListTable: Table { startEntryType = .message case .hole: startEntryType = .hole - /*case .groupReference: - startEntryType = .groupReference*/ } - self.valueBox.range(self.table, start: self.key(groupId: groupId, index: lowerEntries.last!.index, type: startEntryType), end: self.lowerBound(groupId: groupId), values: { key, value in - additionalLowerEntries.append(readEntry(groupId: groupId, messageHistoryTable: messageHistoryTable, peerChatInterfaceStateTable: peerChatInterfaceStateTable, key: key, value: value)) - return true + self.valueBox.filteredRange(self.table, start: self.key(groupId: groupId, index: lowerEntries.last!.index, type: startEntryType), end: self.lowerBound(groupId: groupId), values: { key, value in + let entry = readEntry(groupId: groupId, messageHistoryTable: messageHistoryTable, peerChatInterfaceStateTable: peerChatInterfaceStateTable, key: key, value: value) + if let predicate = predicate { + if predicate(entry) { + additionalLowerEntries.append(entry) + return .accept + } else { + return .skip + } + } else { + additionalLowerEntries.append(entry) + return .accept + } }, limit: count - lowerEntries.count - upperEntries.count + 1) if additionalLowerEntries.count >= count - lowerEntries.count + upperEntries.count + 1 { lower = additionalLowerEntries.last @@ -502,7 +530,7 @@ final class ChatListTable: Table { return result } - func earlierEntries(groupId: PeerGroupId, index: (ChatListIndex, Bool)?, messageHistoryTable: MessageHistoryTable, peerChatInterfaceStateTable: PeerChatInterfaceStateTable, count: Int) -> [ChatListIntermediateEntry] { + func earlierEntries(groupId: PeerGroupId, index: (ChatListIndex, Bool)?, messageHistoryTable: MessageHistoryTable, peerChatInterfaceStateTable: PeerChatInterfaceStateTable, count: Int, predicate: ((ChatListIntermediateEntry) -> Bool)?) -> [ChatListIntermediateEntry] { self.ensureInitialized(groupId: groupId) var entries: [ChatListIntermediateEntry] = [] @@ -513,9 +541,19 @@ final class ChatListTable: Table { key = self.upperBound(groupId: groupId) } - self.valueBox.range(self.table, start: key, end: self.lowerBound(groupId: groupId), values: { key, value in - entries.append(readEntry(groupId: groupId, messageHistoryTable: messageHistoryTable, peerChatInterfaceStateTable: peerChatInterfaceStateTable, key: key, value: value)) - return true + self.valueBox.filteredRange(self.table, start: key, end: self.lowerBound(groupId: groupId), values: { key, value in + let entry = readEntry(groupId: groupId, messageHistoryTable: messageHistoryTable, peerChatInterfaceStateTable: peerChatInterfaceStateTable, key: key, value: value) + if let predicate = predicate { + if predicate(entry) { + entries.append(entry) + return .accept + } else { + return .skip + } + } else { + entries.append(entry) + return .accept + } }, limit: count) return entries } @@ -556,7 +594,7 @@ final class ChatListTable: Table { return entries } - func laterEntries(groupId: PeerGroupId, index: (ChatListIndex, Bool)?, messageHistoryTable: MessageHistoryTable, peerChatInterfaceStateTable: PeerChatInterfaceStateTable, count: Int) -> [ChatListIntermediateEntry] { + func laterEntries(groupId: PeerGroupId, index: (ChatListIndex, Bool)?, messageHistoryTable: MessageHistoryTable, peerChatInterfaceStateTable: PeerChatInterfaceStateTable, count: Int, predicate: ((ChatListIntermediateEntry) -> Bool)?) -> [ChatListIntermediateEntry] { self.ensureInitialized(groupId: groupId) var entries: [ChatListIntermediateEntry] = [] @@ -567,9 +605,19 @@ final class ChatListTable: Table { key = self.lowerBound(groupId: groupId) } - self.valueBox.range(self.table, start: key, end: self.upperBound(groupId: groupId), values: { key, value in - entries.append(readEntry(groupId: groupId, messageHistoryTable: messageHistoryTable, peerChatInterfaceStateTable: peerChatInterfaceStateTable, key: key, value: value)) - return true + self.valueBox.filteredRange(self.table, start: key, end: self.upperBound(groupId: groupId), values: { key, value in + let entry = readEntry(groupId: groupId, messageHistoryTable: messageHistoryTable, peerChatInterfaceStateTable: peerChatInterfaceStateTable, key: key, value: value) + if let predicate = predicate { + if predicate(entry) { + entries.append(entry) + return .accept + } else { + return .skip + } + } else { + entries.append(entry) + return .accept + } }, limit: count) return entries } @@ -590,6 +638,19 @@ final class ChatListTable: Table { return nil } + func getEntry(groupId: PeerGroupId, peerId: PeerId, messageHistoryTable: MessageHistoryTable, peerChatInterfaceStateTable: PeerChatInterfaceStateTable) -> ChatListIntermediateEntry? { + if let (peerGroupId, index) = self.getPeerChatListIndex(peerId: peerId), peerGroupId == groupId { + let key = self.key(groupId: groupId, index: index, type: .message) + if let value = self.valueBox.get(self.table, key: key) { + return readEntry(groupId: groupId, messageHistoryTable: messageHistoryTable, peerChatInterfaceStateTable: peerChatInterfaceStateTable, key: key, value: value) + } else { + return nil + } + } else { + return nil + } + } + func allEntries(groupId: PeerGroupId) -> [ChatListEntryInfo] { var entries: [ChatListEntryInfo] = [] self.valueBox.range(self.table, start: self.upperBound(groupId: groupId), end: self.lowerBound(groupId: groupId), values: { key, value in @@ -710,7 +771,7 @@ final class ChatListTable: Table { } func debugList(groupId: PeerGroupId, messageHistoryTable: MessageHistoryTable, peerChatInterfaceStateTable: PeerChatInterfaceStateTable) -> [ChatListIntermediateEntry] { - return self.laterEntries(groupId: groupId, index: (ChatListIndex.absoluteLowerBound, true), messageHistoryTable: messageHistoryTable, peerChatInterfaceStateTable: peerChatInterfaceStateTable, count: 1000) + return self.laterEntries(groupId: groupId, index: (ChatListIndex.absoluteLowerBound, true), messageHistoryTable: messageHistoryTable, peerChatInterfaceStateTable: peerChatInterfaceStateTable, count: 1000, predicate: nil) } func getNamespaceEntries(groupId: PeerGroupId, namespace: MessageId.Namespace, summaryTag: MessageTags?, messageIndexTable: MessageHistoryIndexTable, messageHistoryTable: MessageHistoryTable, peerChatInterfaceStateTable: PeerChatInterfaceStateTable, readStateTable: MessageHistoryReadStateTable, summaryTable: MessageHistoryTagsSummaryTable) -> [ChatListNamespaceEntry] { diff --git a/submodules/Postbox/Sources/ChatListView.swift b/submodules/Postbox/Sources/ChatListView.swift index e8b09b758e..5c2ee9f22f 100644 --- a/submodules/Postbox/Sources/ChatListView.swift +++ b/submodules/Postbox/Sources/ChatListView.swift @@ -297,6 +297,7 @@ private func updatedRenderedPeer(_ renderedPeer: RenderedPeer, updatedPeers: [Pe final class MutableChatListView { let groupId: PeerGroupId + let filterPredicate: ((Peer, PeerNotificationSettings?) -> Bool)? private let summaryComponents: ChatListEntrySummaryComponents fileprivate var additionalItemIds: Set fileprivate var additionalItemEntries: [MutableChatListEntry] @@ -306,8 +307,11 @@ final class MutableChatListView { fileprivate var groupEntries: [ChatListGroupReferenceEntry] private var count: Int - init(postbox: Postbox, groupId: PeerGroupId, earlier: MutableChatListEntry?, entries: [MutableChatListEntry], later: MutableChatListEntry?, count: Int, summaryComponents: ChatListEntrySummaryComponents) { + init(postbox: Postbox, groupId: PeerGroupId, filterPredicate: ((Peer, PeerNotificationSettings?) -> Bool)?, aroundIndex: ChatListIndex, count: Int, summaryComponents: ChatListEntrySummaryComponents) { + let (entries, earlier, later) = postbox.fetchAroundChatEntries(groupId: groupId, index: aroundIndex, count: count, filterPredicate: filterPredicate) + self.groupId = groupId + self.filterPredicate = filterPredicate self.earlier = earlier self.entries = entries self.later = later @@ -405,7 +409,7 @@ final class MutableChatListView { index = self.entries[self.entries.count / 2].index } - let (entries, earlier, later) = postbox.fetchAroundChatEntries(groupId: self.groupId, index: index, count: self.count) + let (entries, earlier, later) = postbox.fetchAroundChatEntries(groupId: self.groupId, index: index, count: self.count, filterPredicate: self.filterPredicate) let currentGroupEntries = self.groupEntries self.reloadGroups(postbox: postbox) @@ -426,7 +430,7 @@ final class MutableChatListView { return updated } - func replay(postbox: Postbox, operations: [PeerGroupId: [ChatListOperation]], updatedPeerNotificationSettings: [PeerId: PeerNotificationSettings], updatedPeers: [PeerId: Peer], updatedPeerPresences: [PeerId: PeerPresence], transaction: PostboxTransaction, context: MutableChatListViewReplayContext) -> Bool { + func replay(postbox: Postbox, operations: [PeerGroupId: [ChatListOperation]], updatedPeerNotificationSettings: [PeerId: (PeerNotificationSettings?, PeerNotificationSettings)], updatedPeers: [PeerId: Peer], updatedPeerPresences: [PeerId: PeerPresence], transaction: PostboxTransaction, context: MutableChatListViewReplayContext) -> Bool { var hasChanges = false if let groupOperations = operations[self.groupId] { @@ -489,6 +493,43 @@ final class MutableChatListView { } if !updatedPeerNotificationSettings.isEmpty { + if let filterPredicate = self.filterPredicate { + for (peerId, settingsChange) in updatedPeerNotificationSettings { + if let peer = postbox.peerTable.get(peerId) { + let wasIncluded = filterPredicate(peer, settingsChange.0) + let isIncluded = filterPredicate(peer, settingsChange.1) + if wasIncluded != isIncluded { + if isIncluded { + if let entry = postbox.chatListTable.getEntry(groupId: self.groupId, peerId: peerId, messageHistoryTable: postbox.messageHistoryTable, peerChatInterfaceStateTable: postbox.peerChatInterfaceStateTable) { + switch entry { + case let .message(index, message, embeddedState): + let combinedReadState = postbox.readStateTable.getCombinedState(index.messageIndex.id.peerId) + if self.add(.IntermediateMessageEntry(entry.index, message, combinedReadState, embeddedState), postbox: postbox) { + hasChanges = true + } + default: + break + } + } + } else { + loop: for i in 0 ..< self.entries.count { + switch self.entries[i] { + case .MessageEntry(let index, _, _, _, _, _, _, _, _), .IntermediateMessageEntry(let index, _, _, _): + if index.messageIndex.id.peerId == peerId { + self.entries.remove(at: i) + hasChanges = true + break loop + } + default: + break + } + } + } + } + } + } + } + for i in 0 ..< self.entries.count { switch self.entries[i] { case let .MessageEntry(index, message, readState, _, embeddedState, peer, peerPresence, summaryInfo, hasFailed): @@ -496,7 +537,7 @@ final class MutableChatListView { if let peer = peer.peers[peer.peerId], let associatedPeerId = peer.associatedPeerId { notificationSettingsPeerId = associatedPeerId } - if let settings = updatedPeerNotificationSettings[notificationSettingsPeerId] { + if let (_, settings) = updatedPeerNotificationSettings[notificationSettingsPeerId] { self.entries[i] = .MessageEntry(index, message, readState, settings, embeddedState, peer, peerPresence, summaryInfo, hasFailed) hasChanges = true } @@ -619,7 +660,24 @@ final class MutableChatListView { } func add(_ initialEntry: MutableChatListEntry, postbox: Postbox) -> Bool { + if let filterPredicate = self.filterPredicate { + switch initialEntry { + case .IntermediateMessageEntry(let index, _, _, _), .MessageEntry(let index, _, _, _, _, _, _, _, _): + if let peer = postbox.peerTable.get(index.messageIndex.id.peerId) { + if !filterPredicate(peer, postbox.peerNotificationSettingsTable.getEffective(index.messageIndex.id.peerId)) { + return false + } + } else { + return false + } + break + default: + break + } + } + let entry = processedChatListEntry(initialEntry, cachedDataTable: postbox.cachedPeerDataTable, readStateTable: postbox.readStateTable, messageHistoryTable: postbox.messageHistoryTable) + if self.entries.count == 0 { self.entries.append(entry) return true @@ -756,10 +814,10 @@ final class MutableChatListView { } if let later = self.later { - addedEntries += postbox.fetchLaterChatEntries(groupId: self.groupId, index: later.index.predecessor, count: self.count) + addedEntries += postbox.fetchLaterChatEntries(groupId: self.groupId, index: later.index.predecessor, count: self.count, filterPredicate: filterPredicate) } if let earlier = self.earlier { - addedEntries += postbox.fetchEarlierChatEntries(groupId: self.groupId, index: earlier.index.successor, count: self.count) + addedEntries += postbox.fetchEarlierChatEntries(groupId: self.groupId, index: earlier.index.successor, count: self.count, filterPredicate: filterPredicate) } addedEntries += self.entries @@ -808,7 +866,7 @@ final class MutableChatListView { earlyId = self.entries[i].index } - let earlierEntries = postbox.fetchEarlierChatEntries(groupId: self.groupId, index: earlyId, count: 1) + let earlierEntries = postbox.fetchEarlierChatEntries(groupId: self.groupId, index: earlyId, count: 1, filterPredicate: self.filterPredicate) self.earlier = earlierEntries.first } @@ -819,7 +877,7 @@ final class MutableChatListView { laterId = self.entries[i].index } - let laterEntries = postbox.fetchLaterChatEntries(groupId: self.groupId, index: laterId, count: 1) + let laterEntries = postbox.fetchLaterChatEntries(groupId: self.groupId, index: laterId, count: 1, filterPredicate: self.filterPredicate) self.later = laterEntries.first } } diff --git a/submodules/Postbox/Sources/PeerNotificationSettingsTable.swift b/submodules/Postbox/Sources/PeerNotificationSettingsTable.swift index 2d45e0e054..7fea4ea0d4 100644 --- a/submodules/Postbox/Sources/PeerNotificationSettingsTable.swift +++ b/submodules/Postbox/Sources/PeerNotificationSettingsTable.swift @@ -225,7 +225,7 @@ final class PeerNotificationSettingsTable: Table { return (added, removed) } - func resetAll(to settings: PeerNotificationSettings, updatedSettings: inout Set, updatedTimestamps: inout [PeerId: PeerNotificationSettingsBehaviorTimestamp]) -> [PeerId] { + func resetAll(to settings: PeerNotificationSettings, updatedSettings: inout Set, updatedTimestamps: inout [PeerId: PeerNotificationSettingsBehaviorTimestamp]) -> [PeerId: PeerNotificationSettings?] { let lowerBound = ValueBoxKey(length: 8) lowerBound.setInt64(0, value: 0) let upperBound = ValueBoxKey(length: 8) @@ -236,17 +236,17 @@ final class PeerNotificationSettingsTable: Table { return true }, limit: 0) - var updatedPeerIds: [PeerId] = [] + var updatedPeers: [PeerId: PeerNotificationSettings?] = [:] for peerId in peerIds { let entry = self.getEntry(peerId) if let current = entry.current, !current.isEqual(to: settings) || entry.pending != nil { let _ = self.setCurrent(id: peerId, settings: settings, updatedTimestamps: &updatedTimestamps) let _ = self.setPending(id: peerId, settings: nil, updatedSettings: &updatedSettings) - updatedPeerIds.append(peerId) + updatedPeers[peerId] = entry.effective } } - return updatedPeerIds + return updatedPeers } override func beforeCommit() { diff --git a/submodules/Postbox/Sources/PeerNotificationSettingsView.swift b/submodules/Postbox/Sources/PeerNotificationSettingsView.swift index c22d0b4a93..22a0825d02 100644 --- a/submodules/Postbox/Sources/PeerNotificationSettingsView.swift +++ b/submodules/Postbox/Sources/PeerNotificationSettingsView.swift @@ -26,7 +26,7 @@ final class MutablePeerNotificationSettingsView: MutablePostboxView { if let peer = postbox.peerTable.get(peerId), let associatedPeerId = peer.associatedPeerId { notificationPeerId = associatedPeerId } - if let settings = transaction.currentUpdatedPeerNotificationSettings[notificationPeerId] { + if let (_, settings) = transaction.currentUpdatedPeerNotificationSettings[notificationPeerId] { self.notificationSettings[peerId] = settings updated = true } diff --git a/submodules/Postbox/Sources/PeerView.swift b/submodules/Postbox/Sources/PeerView.swift index fd389a7fa5..0c5d610e2f 100644 --- a/submodules/Postbox/Sources/PeerView.swift +++ b/submodules/Postbox/Sources/PeerView.swift @@ -214,12 +214,12 @@ final class MutablePeerView: MutablePostboxView { if let peer = self.peers[self.peerId] { if let associatedPeerId = peer.associatedPeerId { - if let notificationSettings = updatedNotificationSettings[associatedPeerId] { + if let (_, notificationSettings) = updatedNotificationSettings[associatedPeerId] { self.notificationSettings = notificationSettings updated = true } } else { - if let notificationSettings = updatedNotificationSettings[peer.id] { + if let (_, notificationSettings) = updatedNotificationSettings[peer.id] { self.notificationSettings = notificationSettings updated = true } diff --git a/submodules/Postbox/Sources/Postbox.swift b/submodules/Postbox/Sources/Postbox.swift index 187939b9ab..8ce0ed2c6e 100644 --- a/submodules/Postbox/Sources/Postbox.swift +++ b/submodules/Postbox/Sources/Postbox.swift @@ -1077,7 +1077,7 @@ public final class Postbox { private var currentPeerHoleOperations: [MessageHistoryIndexHoleOperationKey: [MessageHistoryIndexHoleOperation]] = [:] private var currentUpdatedPeers: [PeerId: Peer] = [:] - private var currentUpdatedPeerNotificationSettings: [PeerId: PeerNotificationSettings] = [:] + private var currentUpdatedPeerNotificationSettings: [PeerId: (PeerNotificationSettings?, PeerNotificationSettings)] = [:] private var currentUpdatedPeerNotificationBehaviorTimestamps: [PeerId: PeerNotificationSettingsBehaviorTimestamp] = [:] private var currentUpdatedCachedPeerData: [PeerId: CachedPeerData] = [:] private var currentUpdatedPeerPresences: [PeerId: PeerPresence] = [:] @@ -1650,8 +1650,28 @@ public final class Postbox { self.synchronizeGroupMessageStatsTable.set(groupId: groupId, namespace: namespace, needsValidation: false, operations: &self.currentUpdatedGroupSummarySynchronizeOperations) } - func fetchAroundChatEntries(groupId: PeerGroupId, index: ChatListIndex, count: Int) -> (entries: [MutableChatListEntry], earlier: MutableChatListEntry?, later: MutableChatListEntry?) { - let (intermediateEntries, intermediateLower, intermediateUpper) = self.chatListTable.entriesAround(groupId: groupId, index: index, messageHistoryTable: self.messageHistoryTable, peerChatInterfaceStateTable: self.peerChatInterfaceStateTable, count: count) + private func mappedChatListFilterPredicate(_ predicate: @escaping (Peer, PeerNotificationSettings?) -> Bool) -> (ChatListIntermediateEntry) -> Bool { + return { entry in + switch entry { + case let .message(index, _, _): + if let peer = self.peerTable.get(index.messageIndex.id.peerId) { + if predicate(peer, self.peerNotificationSettingsTable.getEffective(index.messageIndex.id.peerId)) { + return true + } else { + return false + } + } else { + return false + } + case .hole: + return true + } + } + } + + func fetchAroundChatEntries(groupId: PeerGroupId, index: ChatListIndex, count: Int, filterPredicate: ((Peer, PeerNotificationSettings?) -> Bool)?) -> (entries: [MutableChatListEntry], earlier: MutableChatListEntry?, later: MutableChatListEntry?) { + let mappedPredicate = filterPredicate.flatMap(self.mappedChatListFilterPredicate) + let (intermediateEntries, intermediateLower, intermediateUpper) = self.chatListTable.entriesAround(groupId: groupId, index: index, messageHistoryTable: self.messageHistoryTable, peerChatInterfaceStateTable: self.peerChatInterfaceStateTable, count: count, predicate: mappedPredicate) let entries: [MutableChatListEntry] = intermediateEntries.map { entry in return MutableChatListEntry(entry, cachedDataTable: self.cachedPeerDataTable, readStateTable: self.readStateTable, messageHistoryTable: self.messageHistoryTable) } @@ -1665,16 +1685,18 @@ public final class Postbox { return (entries, lower, upper) } - func fetchEarlierChatEntries(groupId: PeerGroupId, index: ChatListIndex?, count: Int) -> [MutableChatListEntry] { - let intermediateEntries = self.chatListTable.earlierEntries(groupId: groupId, index: index.flatMap({ ($0, true) }), messageHistoryTable: self.messageHistoryTable, peerChatInterfaceStateTable: self.peerChatInterfaceStateTable, count: count) + func fetchEarlierChatEntries(groupId: PeerGroupId, index: ChatListIndex?, count: Int, filterPredicate: ((Peer, PeerNotificationSettings?) -> Bool)?) -> [MutableChatListEntry] { + let mappedPredicate = filterPredicate.flatMap(self.mappedChatListFilterPredicate) + let intermediateEntries = self.chatListTable.earlierEntries(groupId: groupId, index: index.flatMap({ ($0, true) }), messageHistoryTable: self.messageHistoryTable, peerChatInterfaceStateTable: self.peerChatInterfaceStateTable, count: count, predicate: mappedPredicate) let entries: [MutableChatListEntry] = intermediateEntries.map { entry in return MutableChatListEntry(entry, cachedDataTable: self.cachedPeerDataTable, readStateTable: self.readStateTable, messageHistoryTable: self.messageHistoryTable) } return entries } - func fetchLaterChatEntries(groupId: PeerGroupId, index: ChatListIndex?, count: Int) -> [MutableChatListEntry] { - let intermediateEntries = self.chatListTable.laterEntries(groupId: groupId, index: index.flatMap({ ($0, true) }), messageHistoryTable: self.messageHistoryTable, peerChatInterfaceStateTable: self.peerChatInterfaceStateTable, count: count) + func fetchLaterChatEntries(groupId: PeerGroupId, index: ChatListIndex?, count: Int, filterPredicate: ((Peer, PeerNotificationSettings?) -> Bool)?) -> [MutableChatListEntry] { + let mappedPredicate = filterPredicate.flatMap(self.mappedChatListFilterPredicate) + let intermediateEntries = self.chatListTable.laterEntries(groupId: groupId, index: index.flatMap({ ($0, true) }), messageHistoryTable: self.messageHistoryTable, peerChatInterfaceStateTable: self.peerChatInterfaceStateTable, count: count, predicate: mappedPredicate) let entries: [MutableChatListEntry] = intermediateEntries.map { entry in return MutableChatListEntry(entry, cachedDataTable: self.cachedPeerDataTable, readStateTable: self.readStateTable, messageHistoryTable: self.messageHistoryTable) } @@ -1891,21 +1913,33 @@ public final class Postbox { fileprivate func updateCurrentPeerNotificationSettings(_ notificationSettings: [PeerId: PeerNotificationSettings]) { for (peerId, settings) in notificationSettings { + let previous: PeerNotificationSettings? + if let (value, _) = self.currentUpdatedPeerNotificationSettings[peerId] { + previous = value + } else { + previous = self.peerNotificationSettingsTable.getEffective(peerId) + } if let updated = self.peerNotificationSettingsTable.setCurrent(id: peerId, settings: settings, updatedTimestamps: &self.currentUpdatedPeerNotificationBehaviorTimestamps) { - self.currentUpdatedPeerNotificationSettings[peerId] = updated + self.currentUpdatedPeerNotificationSettings[peerId] = (previous, updated) } } } fileprivate func updatePendingPeerNotificationSettings(peerId: PeerId, settings: PeerNotificationSettings?) { + let previous: PeerNotificationSettings? + if let (value, _) = self.currentUpdatedPeerNotificationSettings[peerId] { + previous = value + } else { + previous = self.peerNotificationSettingsTable.getEffective(peerId) + } if let updated = self.peerNotificationSettingsTable.setPending(id: peerId, settings: settings, updatedSettings: &self.currentUpdatedPendingPeerNotificationSettings) { - self.currentUpdatedPeerNotificationSettings[peerId] = updated + self.currentUpdatedPeerNotificationSettings[peerId] = (previous, updated) } } fileprivate func resetAllPeerNotificationSettings(_ notificationSettings: PeerNotificationSettings) { - for peerId in self.peerNotificationSettingsTable.resetAll(to: notificationSettings, updatedSettings: &self.currentUpdatedPendingPeerNotificationSettings, updatedTimestamps: &self.currentUpdatedPeerNotificationBehaviorTimestamps) { - self.currentUpdatedPeerNotificationSettings[peerId] = notificationSettings + for (peerId, previous) in self.peerNotificationSettingsTable.resetAll(to: notificationSettings, updatedSettings: &self.currentUpdatedPendingPeerNotificationSettings, updatedTimestamps: &self.currentUpdatedPeerNotificationBehaviorTimestamps) { + self.currentUpdatedPeerNotificationSettings[peerId] = (previous, notificationSettings) } } @@ -2508,15 +2542,13 @@ public final class Postbox { |> switchToLatest } - public func tailChatListView(groupId: PeerGroupId, count: Int, summaryComponents: ChatListEntrySummaryComponents) -> Signal<(ChatListView, ViewUpdateType), NoError> { - return self.aroundChatListView(groupId: groupId, index: ChatListIndex.absoluteUpperBound, count: count, summaryComponents: summaryComponents, userInteractive: true) + public func tailChatListView(groupId: PeerGroupId, filterPredicate: ((Peer, PeerNotificationSettings?) -> Bool)? = nil, count: Int, summaryComponents: ChatListEntrySummaryComponents) -> Signal<(ChatListView, ViewUpdateType), NoError> { + return self.aroundChatListView(groupId: groupId, filterPredicate: filterPredicate, index: ChatListIndex.absoluteUpperBound, count: count, summaryComponents: summaryComponents, userInteractive: true) } - public func aroundChatListView(groupId: PeerGroupId, index: ChatListIndex, count: Int, summaryComponents: ChatListEntrySummaryComponents, userInteractive: Bool = false) -> Signal<(ChatListView, ViewUpdateType), NoError> { + public func aroundChatListView(groupId: PeerGroupId, filterPredicate: ((Peer, PeerNotificationSettings?) -> Bool)? = nil, index: ChatListIndex, count: Int, summaryComponents: ChatListEntrySummaryComponents, userInteractive: Bool = false) -> Signal<(ChatListView, ViewUpdateType), NoError> { return self.transactionSignal(userInteractive: userInteractive, { subscriber, transaction in - let (entries, earlier, later) = self.fetchAroundChatEntries(groupId: groupId, index: index, count: count) - - let mutableView = MutableChatListView(postbox: self, groupId: groupId, earlier: earlier, entries: entries, later: later, count: count, summaryComponents: summaryComponents) + let mutableView = MutableChatListView(postbox: self, groupId: groupId, filterPredicate: filterPredicate, aroundIndex: index, count: count, summaryComponents: summaryComponents) mutableView.render(postbox: self, renderMessage: self.renderIntermediateMessage, getPeer: { id in return self.peerTable.get(id) }, getPeerNotificationSettings: { self.peerNotificationSettingsTable.getEffective($0) }, getPeerPresence: { self.peerPresenceTable.get($0) }) diff --git a/submodules/Postbox/Sources/PostboxTransaction.swift b/submodules/Postbox/Sources/PostboxTransaction.swift index ab12fb1cb1..207ed2a45a 100644 --- a/submodules/Postbox/Sources/PostboxTransaction.swift +++ b/submodules/Postbox/Sources/PostboxTransaction.swift @@ -7,7 +7,7 @@ final class PostboxTransaction { let chatListOperations: [PeerGroupId: [ChatListOperation]] let currentUpdatedChatListInclusions: [PeerId: PeerChatListInclusion] let currentUpdatedPeers: [PeerId: Peer] - let currentUpdatedPeerNotificationSettings: [PeerId: PeerNotificationSettings] + let currentUpdatedPeerNotificationSettings: [PeerId: (PeerNotificationSettings?, PeerNotificationSettings)] let currentUpdatedPeerNotificationBehaviorTimestamps: [PeerId: PeerNotificationSettingsBehaviorTimestamp] let currentUpdatedCachedPeerData: [PeerId: CachedPeerData] let currentUpdatedPeerPresences: [PeerId: PeerPresence] @@ -172,7 +172,7 @@ final class PostboxTransaction { return true } - init(currentUpdatedState: PostboxCoding?, currentPeerHoleOperations: [MessageHistoryIndexHoleOperationKey: [MessageHistoryIndexHoleOperation]] = [:], currentOperationsByPeerId: [PeerId: [MessageHistoryOperation]], chatListOperations: [PeerGroupId: [ChatListOperation]], currentUpdatedChatListInclusions: [PeerId: PeerChatListInclusion], currentUpdatedPeers: [PeerId: Peer], currentUpdatedPeerNotificationSettings: [PeerId: PeerNotificationSettings], currentUpdatedPeerNotificationBehaviorTimestamps: [PeerId: PeerNotificationSettingsBehaviorTimestamp], currentUpdatedCachedPeerData: [PeerId: CachedPeerData], currentUpdatedPeerPresences: [PeerId: PeerPresence], currentUpdatedPeerChatListEmbeddedStates: [PeerId: PeerChatListEmbeddedInterfaceState?], currentUpdatedTotalUnreadState: ChatListTotalUnreadState?, currentUpdatedTotalUnreadSummaries: [PeerGroupId: PeerGroupUnreadCountersCombinedSummary], alteredInitialPeerCombinedReadStates: [PeerId: CombinedPeerReadState], currentPeerMergedOperationLogOperations: [PeerMergedOperationLogOperation], currentTimestampBasedMessageAttributesOperations: [TimestampBasedMessageAttributesOperation], unsentMessageOperations: [IntermediateMessageHistoryUnsentOperation], updatedSynchronizePeerReadStateOperations: [PeerId: PeerReadStateSynchronizationOperation?], currentUpdatedGroupSummarySynchronizeOperations: [PeerGroupAndNamespace: Bool], currentPreferencesOperations: [PreferencesOperation], currentOrderedItemListOperations: [Int32: [OrderedItemListOperation]], currentItemCollectionItemsOperations: [ItemCollectionId: [ItemCollectionItemsOperation]], currentItemCollectionInfosOperations: [ItemCollectionInfosOperation], currentUpdatedPeerChatStates: Set, currentGlobalTagsOperations: [GlobalMessageHistoryTagsOperation], currentLocalTagsOperations: [IntermediateMessageHistoryLocalTagsOperation], updatedMedia: [MediaId: Media?], replaceRemoteContactCount: Int32?, replaceContactPeerIds: Set?, currentPendingMessageActionsOperations: [PendingMessageActionsOperation], currentUpdatedMessageActionsSummaries: [PendingMessageActionsSummaryKey: Int32], currentUpdatedMessageTagSummaries: [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], currentInvalidateMessageTagSummaries: [InvalidatedMessageHistoryTagsSummaryEntryOperation], currentUpdatedPendingPeerNotificationSettings: Set, replacedAdditionalChatListItems: [PeerId]?, updatedNoticeEntryKeys: Set, updatedCacheEntryKeys: Set, currentUpdatedMasterClientId: Int64?, updatedFailedMessagePeerIds: Set, updatedFailedMessageIds: Set) { + init(currentUpdatedState: PostboxCoding?, currentPeerHoleOperations: [MessageHistoryIndexHoleOperationKey: [MessageHistoryIndexHoleOperation]] = [:], currentOperationsByPeerId: [PeerId: [MessageHistoryOperation]], chatListOperations: [PeerGroupId: [ChatListOperation]], currentUpdatedChatListInclusions: [PeerId: PeerChatListInclusion], currentUpdatedPeers: [PeerId: Peer], currentUpdatedPeerNotificationSettings: [PeerId: (PeerNotificationSettings?, PeerNotificationSettings)], currentUpdatedPeerNotificationBehaviorTimestamps: [PeerId: PeerNotificationSettingsBehaviorTimestamp], currentUpdatedCachedPeerData: [PeerId: CachedPeerData], currentUpdatedPeerPresences: [PeerId: PeerPresence], currentUpdatedPeerChatListEmbeddedStates: [PeerId: PeerChatListEmbeddedInterfaceState?], currentUpdatedTotalUnreadState: ChatListTotalUnreadState?, currentUpdatedTotalUnreadSummaries: [PeerGroupId: PeerGroupUnreadCountersCombinedSummary], alteredInitialPeerCombinedReadStates: [PeerId: CombinedPeerReadState], currentPeerMergedOperationLogOperations: [PeerMergedOperationLogOperation], currentTimestampBasedMessageAttributesOperations: [TimestampBasedMessageAttributesOperation], unsentMessageOperations: [IntermediateMessageHistoryUnsentOperation], updatedSynchronizePeerReadStateOperations: [PeerId: PeerReadStateSynchronizationOperation?], currentUpdatedGroupSummarySynchronizeOperations: [PeerGroupAndNamespace: Bool], currentPreferencesOperations: [PreferencesOperation], currentOrderedItemListOperations: [Int32: [OrderedItemListOperation]], currentItemCollectionItemsOperations: [ItemCollectionId: [ItemCollectionItemsOperation]], currentItemCollectionInfosOperations: [ItemCollectionInfosOperation], currentUpdatedPeerChatStates: Set, currentGlobalTagsOperations: [GlobalMessageHistoryTagsOperation], currentLocalTagsOperations: [IntermediateMessageHistoryLocalTagsOperation], updatedMedia: [MediaId: Media?], replaceRemoteContactCount: Int32?, replaceContactPeerIds: Set?, currentPendingMessageActionsOperations: [PendingMessageActionsOperation], currentUpdatedMessageActionsSummaries: [PendingMessageActionsSummaryKey: Int32], currentUpdatedMessageTagSummaries: [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], currentInvalidateMessageTagSummaries: [InvalidatedMessageHistoryTagsSummaryEntryOperation], currentUpdatedPendingPeerNotificationSettings: Set, replacedAdditionalChatListItems: [PeerId]?, updatedNoticeEntryKeys: Set, updatedCacheEntryKeys: Set, currentUpdatedMasterClientId: Int64?, updatedFailedMessagePeerIds: Set, updatedFailedMessageIds: Set) { self.currentUpdatedState = currentUpdatedState self.currentPeerHoleOperations = currentPeerHoleOperations self.currentOperationsByPeerId = currentOperationsByPeerId diff --git a/submodules/Postbox/Sources/SqliteValueBox.swift b/submodules/Postbox/Sources/SqliteValueBox.swift index dcaa340bb2..70b3e5661d 100644 --- a/submodules/Postbox/Sources/SqliteValueBox.swift +++ b/submodules/Postbox/Sources/SqliteValueBox.swift @@ -1498,6 +1498,38 @@ public final class SqliteValueBox: ValueBox { withExtendedLifetime(end, {}) } + public func filteredRange(_ table: ValueBoxTable, start: ValueBoxKey, end: ValueBoxKey, values: (ValueBoxKey, ReadBuffer) -> ValueBoxFilterResult, limit: Int) { + var currentStart = start + var acceptedCount = 0 + while acceptedCount < limit { + var hadStop = false + var lastKey: ValueBoxKey? + self.range(table, start: currentStart, end: end, values: { key, value in + lastKey = key + let result = values(key, value) + switch result { + case .accept: + acceptedCount += 1 + return true + case .skip: + return true + case .stop: + hadStop = true + return false + } + return true + }, limit: limit) + if let lastKey = lastKey { + currentStart = lastKey + } else { + break + } + if hadStop { + break + } + } + } + public func range(_ table: ValueBoxTable, start: ValueBoxKey, end: ValueBoxKey, keys: (ValueBoxKey) -> Bool, limit: Int) { precondition(self.queue.isCurrent()) if let _ = self.tables[table.id] { diff --git a/submodules/Postbox/Sources/ValueBox.swift b/submodules/Postbox/Sources/ValueBox.swift index 00297c3708..08396740e6 100644 --- a/submodules/Postbox/Sources/ValueBox.swift +++ b/submodules/Postbox/Sources/ValueBox.swift @@ -57,6 +57,12 @@ public struct ValueBoxEncryptionParameters { } } +public enum ValueBoxFilterResult { + case accept + case skip + case stop +} + public protocol ValueBox { func begin() func commit() @@ -66,6 +72,7 @@ public protocol ValueBox { func endStats() func range(_ table: ValueBoxTable, start: ValueBoxKey, end: ValueBoxKey, values: (ValueBoxKey, ReadBuffer) -> Bool, limit: Int) + func filteredRange(_ table: ValueBoxTable, start: ValueBoxKey, end: ValueBoxKey, values: (ValueBoxKey, ReadBuffer) -> ValueBoxFilterResult, limit: Int) func range(_ table: ValueBoxTable, start: ValueBoxKey, end: ValueBoxKey, keys: (ValueBoxKey) -> Bool, limit: Int) func scan(_ table: ValueBoxTable, values: (ValueBoxKey, ReadBuffer) -> Bool) func scan(_ table: ValueBoxTable, keys: (ValueBoxKey) -> Bool) diff --git a/submodules/TelegramCore/Sources/AccountViewTracker.swift b/submodules/TelegramCore/Sources/AccountViewTracker.swift index 94913597d1..0d5ebe5678 100644 --- a/submodules/TelegramCore/Sources/AccountViewTracker.swift +++ b/submodules/TelegramCore/Sources/AccountViewTracker.swift @@ -1330,17 +1330,17 @@ public final class AccountViewTracker { }) } - public func tailChatListView(groupId: PeerGroupId, count: Int) -> Signal<(ChatListView, ViewUpdateType), NoError> { + public func tailChatListView(groupId: PeerGroupId, filterPredicate: ((Peer, PeerNotificationSettings?) -> Bool)? = nil, count: Int) -> Signal<(ChatListView, ViewUpdateType), NoError> { if let account = self.account { - return self.wrappedChatListView(signal: account.postbox.tailChatListView(groupId: groupId, count: count, summaryComponents: ChatListEntrySummaryComponents(tagSummary: ChatListEntryMessageTagSummaryComponent(tag: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud), actionsSummary: ChatListEntryPendingMessageActionsSummaryComponent(type: PendingMessageActionType.consumeUnseenPersonalMessage, namespace: Namespaces.Message.Cloud)))) + return self.wrappedChatListView(signal: account.postbox.tailChatListView(groupId: groupId, filterPredicate: filterPredicate, count: count, summaryComponents: ChatListEntrySummaryComponents(tagSummary: ChatListEntryMessageTagSummaryComponent(tag: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud), actionsSummary: ChatListEntryPendingMessageActionsSummaryComponent(type: PendingMessageActionType.consumeUnseenPersonalMessage, namespace: Namespaces.Message.Cloud)))) } else { return .never() } } - public func aroundChatListView(groupId: PeerGroupId, index: ChatListIndex, count: Int) -> Signal<(ChatListView, ViewUpdateType), NoError> { + public func aroundChatListView(groupId: PeerGroupId, filterPredicate: ((Peer, PeerNotificationSettings?) -> Bool)? = nil, index: ChatListIndex, count: Int) -> Signal<(ChatListView, ViewUpdateType), NoError> { if let account = self.account { - return self.wrappedChatListView(signal: account.postbox.aroundChatListView(groupId: groupId, index: index, count: count, summaryComponents: ChatListEntrySummaryComponents(tagSummary: ChatListEntryMessageTagSummaryComponent(tag: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud), actionsSummary: ChatListEntryPendingMessageActionsSummaryComponent(type: PendingMessageActionType.consumeUnseenPersonalMessage, namespace: Namespaces.Message.Cloud)))) + return self.wrappedChatListView(signal: account.postbox.aroundChatListView(groupId: groupId, filterPredicate: filterPredicate, index: index, count: count, summaryComponents: ChatListEntrySummaryComponents(tagSummary: ChatListEntryMessageTagSummaryComponent(tag: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud), actionsSummary: ChatListEntryPendingMessageActionsSummaryComponent(type: PendingMessageActionType.consumeUnseenPersonalMessage, namespace: Namespaces.Message.Cloud)))) } else { return .never() } diff --git a/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift b/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift index d09c06ccc4..5e5ad3fb8e 100644 --- a/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift +++ b/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift @@ -177,15 +177,24 @@ public func messageBubbleImage(maxCornerRadius: CGFloat, minCornerRadius: CGFloa context.setStrokeColor(UIColor.black.cgColor) let borderWidth: CGFloat - if abs(UIScreenPixel - 0.5) < CGFloat.ulpOfOne { - borderWidth = UIScreenPixel + let borderOffset: CGFloat + + let innerExtension: CGFloat + if knockout && !mask { + innerExtension = 0.25 } else { - borderWidth = UIScreenPixel * 2.0 + innerExtension = 0.25 + } + + if abs(UIScreenPixel - 0.5) < CGFloat.ulpOfOne { + borderWidth = UIScreenPixel + innerExtension + borderOffset = -innerExtension / 2.0 + UIScreenPixel / 2.0 + } else { + borderWidth = UIScreenPixel * 2.0 + innerExtension + borderOffset = -innerExtension / 2.0 + UIScreenPixel * 2.0 / 2.0 } context.setLineWidth(borderWidth) - let borderOffset: CGFloat = borderWidth / 2.0 - context.move(to: CGPoint(x: -borderOffset, y: topLeftRadius + borderOffset)) context.addArc(tangent1End: CGPoint(x: -borderOffset, y: -borderOffset), tangent2End: CGPoint(x: topLeftRadius + borderOffset, y: -borderOffset), radius: topLeftRadius + borderOffset * 2.0) context.addLine(to: CGPoint(x: fixedMainDiameter - topRightRadius - borderOffset, y: -borderOffset)) @@ -278,8 +287,6 @@ public func messageBubbleImage(maxCornerRadius: CGFloat, minCornerRadius: CGFloa context.setBlendMode(.copy) let image = outlineContext.generateImage()! context.draw(image.cgImage!, in: CGRect(origin: CGPoint(), size: size)) - context.setBlendMode(.normal) - context.draw(image.cgImage!, in: CGRect(origin: CGPoint(), size: size)) })! let drawingContext = DrawingContext(size: imageSize) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageBackground.swift b/submodules/TelegramUI/TelegramUI/ChatMessageBackground.swift index 09ab5933d4..a24df24f77 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageBackground.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageBackground.swift @@ -82,8 +82,8 @@ class ChatMessageBackground: ASDisplayNode { super.init() self.isUserInteractionEnabled = false - self.addSubnode(self.imageNode) self.addSubnode(self.outlineImageNode) + self.addSubnode(self.imageNode) } func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) { From f7c306c4881f24154a9d3b31937eec9014183266 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 24 Jan 2020 14:18:56 +0400 Subject: [PATCH 28/50] Fix archive avatar animation --- submodules/ChatListUI/Sources/Node/ChatListItem.swift | 2 +- submodules/ChatListUI/Sources/Node/ChatListNode.swift | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/submodules/ChatListUI/Sources/Node/ChatListItem.swift b/submodules/ChatListUI/Sources/Node/ChatListItem.swift index 0996cf6aff..1b4ef38ca5 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItem.swift @@ -1360,7 +1360,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { transition.updateAlpha(node: strongSelf.statusNode, alpha: 1.0) } - let avatarFrame = CGRect(origin: CGPoint(x: leftInset - avatarLeftInset + editingOffset + 10.0 + revealOffset, y: floor((layout.contentSize.height - avatarDiameter) / 2.0)), size: CGSize(width: avatarDiameter, height: avatarDiameter)) + let avatarFrame = CGRect(origin: CGPoint(x: leftInset - avatarLeftInset + editingOffset + 10.0 + revealOffset, y: floor((itemHeight - avatarDiameter) / 2.0)), size: CGSize(width: avatarDiameter, height: avatarDiameter)) transition.updateFrame(node: strongSelf.avatarNode, frame: avatarFrame) let onlineFrame = CGRect(origin: CGPoint(x: avatarFrame.maxX - onlineLayout.width - 2.0, y: avatarFrame.maxY - onlineLayout.height - 2.0), size: onlineLayout) diff --git a/submodules/ChatListUI/Sources/Node/ChatListNode.swift b/submodules/ChatListUI/Sources/Node/ChatListNode.swift index a585454f05..0d6f40954d 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNode.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNode.swift @@ -768,6 +768,7 @@ public final class ChatListNode: ListView { if filter != previousView?.filter { disableAnimations = true + updatedScrollPosition = nil } return preparedChatListNodeViewTransition(from: previousView, to: processedView, reason: reason, previewing: previewing, disableAnimations: disableAnimations, account: context.account, scrollPosition: updatedScrollPosition, searchMode: searchMode) From e315586d653abd83468dcbd0d474ad448e2e2bb3 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 24 Jan 2020 16:16:20 +0400 Subject: [PATCH 29/50] Bubble shadows --- submodules/Display/Display/ListView.swift | 48 +++++++++- .../Display/Display/ListViewItemNode.swift | 7 ++ .../BubbleSettingsController.swift | 7 ++ .../Sources/ChatMessageBubbleImages.swift | 89 ++++++++++++------- .../PresentationThemeEssentialGraphics.swift | 36 ++++++++ .../TelegramUI/ChatControllerNode.swift | 1 + .../TelegramUI/ChatMessageBackground.swift | 73 +++++++++++++++ .../ChatMessageBubbleItemNode.swift | 13 +++ 8 files changed, 237 insertions(+), 37 deletions(-) diff --git a/submodules/Display/Display/ListView.swift b/submodules/Display/Display/ListView.swift index 964435ecb7..59fc67d902 100644 --- a/submodules/Display/Display/ListView.swift +++ b/submodules/Display/Display/ListView.swift @@ -230,6 +230,22 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture public final var synchronousNodes = false public final var debugInfo = false + public var enableExtractedBackgrounds: Bool = false { + didSet { + if self.enableExtractedBackgrounds != oldValue { + if self.enableExtractedBackgrounds { + let extractedBackgroundsContainerNode = ASDisplayNode() + self.extractedBackgroundsContainerNode = extractedBackgroundsContainerNode + self.insertSubnode(extractedBackgroundsContainerNode, at: 0) + } else if let extractedBackgroundsContainerNode = self.extractedBackgroundsContainerNode { + self.extractedBackgroundsContainerNode = nil + extractedBackgroundsContainerNode.removeFromSupernode() + } + } + } + } + private final var extractedBackgroundsContainerNode: ASDisplayNode? + private final var items: [ListViewItem] = [] private final var itemNodes: [ListViewItemNode] = [] private final var itemHeaderNodes: [Int64: ListViewItemHeaderNode] = [:] @@ -1095,7 +1111,11 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture topItemOverscrollBackground = ListViewOverscrollBackgroundNode(color: value.color) topItemOverscrollBackground.isLayerBacked = true self.topItemOverscrollBackground = topItemOverscrollBackground - self.insertSubnode(topItemOverscrollBackground, at: 0) + if let extractedBackgroundsContainerNode = self.extractedBackgroundsContainerNode { + self.insertSubnode(topItemOverscrollBackground, aboveSubnode: extractedBackgroundsContainerNode) + } else { + self.insertSubnode(topItemOverscrollBackground, at: 0) + } } var topItemFound = false var topItemNodeIndex: Int? @@ -1203,7 +1223,11 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture bottomItemOverscrollBackground = ASDisplayNode() bottomItemOverscrollBackground.backgroundColor = color bottomItemOverscrollBackground.isLayerBacked = true - self.insertSubnode(bottomItemOverscrollBackground, at: 0) + if let extractedBackgroundsContainerNode = self.extractedBackgroundsContainerNode { + self.insertSubnode(bottomItemOverscrollBackground, aboveSubnode: extractedBackgroundsContainerNode) + } else { + self.insertSubnode(bottomItemOverscrollBackground, at: 0) + } self.bottomItemOverscrollBackground = bottomItemOverscrollBackground } @@ -2295,13 +2319,21 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture } else { self.addSubnode(node) } + if let extractedBackgroundsNode = node.extractedBackgroundNode { + self.extractedBackgroundsContainerNode?.addSubnode(extractedBackgroundsNode) + } } else { if animated { if let topItemOverscrollBackground = self.topItemOverscrollBackground { self.insertSubnode(node, aboveSubnode: topItemOverscrollBackground) + } else if let extractedBackgroundsContainerNode = self.extractedBackgroundsContainerNode { + self.insertSubnode(node, aboveSubnode: extractedBackgroundsContainerNode) } else { self.insertSubnode(node, at: 0) } + if let extractedBackgroundsNode = node.extractedBackgroundNode { + self.extractedBackgroundsContainerNode?.addSubnode(extractedBackgroundsNode) + } } else { if let itemNode = self.reorderNode?.itemNode, itemNode.supernode == self { self.insertSubnode(node, belowSubnode: itemNode) @@ -2312,6 +2344,9 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture } else { self.addSubnode(node) } + if let extractedBackgroundsNode = node.extractedBackgroundNode { + self.extractedBackgroundsContainerNode?.addSubnode(extractedBackgroundsNode) + } } } case let .InsertDisappearingPlaceholder(index, referenceNodeObject, offsetDirection): @@ -2340,6 +2375,9 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture } else { self.addSubnode(referenceNode) } + if let extractedBackgroundsNode = referenceNode.extractedBackgroundNode { + self.extractedBackgroundsContainerNode?.addSubnode(extractedBackgroundsNode) + } } } else { assertionFailure() @@ -2846,6 +2884,9 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture } else { self.addSubnode(itemNode) } + if let extractedBackgroundsNode = itemNode.extractedBackgroundNode { + self.extractedBackgroundsContainerNode?.addSubnode(extractedBackgroundsNode) + } } var temporaryHeaderNodes: [ListViewItemHeaderNode] = [] @@ -2945,6 +2986,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture animation.completion = { _ in for itemNode in temporaryPreviousNodes { itemNode.removeFromSupernode() + itemNode.extractedBackgroundNode?.removeFromSupernode() } for headerNode in temporaryHeaderNodes { headerNode.removeFromSupernode() @@ -3023,7 +3065,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture let node = self.itemNodes[index] self.itemNodes.remove(at: index) node.removeFromSupernode() - + node.extractedBackgroundNode?.removeFromSupernode() node.accessoryItemNode?.removeFromSupernode() node.setAccessoryItemNode(nil, leftInset: self.insets.left, rightInset: self.insets.right) node.headerAccessoryItemNode?.removeFromSupernode() diff --git a/submodules/Display/Display/ListViewItemNode.swift b/submodules/Display/Display/ListViewItemNode.swift index 3204d15744..9ef0d00b25 100644 --- a/submodules/Display/Display/ListViewItemNode.swift +++ b/submodules/Display/Display/ListViewItemNode.swift @@ -559,12 +559,19 @@ open class ListViewItemNode: ASDisplayNode { public func updateFrame(_ frame: CGRect, within containerSize: CGSize) { self.frame = frame self.updateAbsoluteRect(frame, within: containerSize) + if let extractedBackgroundNode = self.extractedBackgroundNode { + extractedBackgroundNode.frame = frame.offsetBy(dx: 0.0, dy: -self.insets.top) + } } open func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) { } open func applyAbsoluteOffset(value: CGFloat, animationCurve: ContainedViewLayoutTransitionCurve, duration: Double) { + if let extractedBackgroundNode = self.extractedBackgroundNode { + let transition: ContainedViewLayoutTransition = .animated(duration: duration, curve: animationCurve) + transition.animatePositionAdditive(node: extractedBackgroundNode, offset: CGPoint(x: 0.0, y: -value)) + } } open func snapshotForReordering() -> UIView? { diff --git a/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift b/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift index daa01db3bb..dc1129ff5b 100644 --- a/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift +++ b/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift @@ -224,6 +224,10 @@ private final class BubbleSettingsControllerNode: ASDisplayNode, UIScrollViewDel itemNode!.isUserInteractionEnabled = false messageNodes.append(itemNode!) self.messagesContainerNode.addSubnode(itemNode!) + if let extractedBackgroundNode = itemNode!.extractedBackgroundNode { + extractedBackgroundNode.subnodeTransform = CATransform3DMakeScale(-1.0, 1.0, 1.0) + self.messagesContainerNode.insertSubnode(extractedBackgroundNode, at: 0) + } } self.messageNodes = messageNodes } @@ -232,6 +236,9 @@ private final class BubbleSettingsControllerNode: ASDisplayNode, UIScrollViewDel if let messageNodes = self.messageNodes { for itemNode in messageNodes { transition.updateFrame(node: itemNode, frame: CGRect(origin: CGPoint(x: 0.0, y: bottomOffset), size: itemNode.frame.size)) + if let extractedBackgroundNode = itemNode.extractedBackgroundNode { + transition.updateFrame(node: extractedBackgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: bottomOffset), size: itemNode.frame.size)) + } bottomOffset += itemNode.frame.height itemNode.updateFrame(itemNode.frame, within: layout.size) } diff --git a/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift b/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift index d09c06ccc4..bea03c23c8 100644 --- a/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift +++ b/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift @@ -79,7 +79,7 @@ func mediaBubbleCornerImage(incoming: Bool, radius: CGFloat, inset: CGFloat) -> return formContext.generateImage()! } -public func messageBubbleImage(maxCornerRadius: CGFloat, minCornerRadius: CGFloat, incoming: Bool, fillColor: UIColor, strokeColor: UIColor, neighbors: MessageBubbleImageNeighbors, theme: PresentationThemeChat, wallpaper: TelegramWallpaper, knockout knockoutValue: Bool, mask: Bool = false, extendedEdges: Bool = false, onlyOutline: Bool = false) -> UIImage { +public func messageBubbleImage(maxCornerRadius: CGFloat, minCornerRadius: CGFloat, incoming: Bool, fillColor: UIColor, strokeColor: UIColor, neighbors: MessageBubbleImageNeighbors, theme: PresentationThemeChat, wallpaper: TelegramWallpaper, knockout knockoutValue: Bool, mask: Bool = false, extendedEdges: Bool = false, onlyOutline: Bool = false, onlyShadow: Bool = false) -> UIImage { let topLeftRadius: CGFloat let topRightRadius: CGFloat let bottomLeftRadius: CGFloat @@ -123,10 +123,10 @@ public func messageBubbleImage(maxCornerRadius: CGFloat, minCornerRadius: CGFloa let innerSize = CGSize(width: fixedMainDiameter + 6.0, height: fixedMainDiameter) let strokeInset: CGFloat = 1.0 let sourceRawSize = CGSize(width: innerSize.width + strokeInset * 2.0, height: innerSize.height + strokeInset * 2.0) - let additionalInset: CGFloat = 1.0 + let additionalInset: CGFloat = onlyShadow ? 10.0 : 1.0 let imageSize = CGSize(width: sourceRawSize.width + additionalInset * 2.0, height: sourceRawSize.height + additionalInset * 2.0) let outgoingStretchPoint: (x: Int, y: Int) = (Int(additionalInset + strokeInset + round(fixedMainDiameter / 2.0)) - 1, Int(additionalInset + strokeInset + round(fixedMainDiameter / 2.0))) - let incomingStretchPoint: (x: Int, y: Int) = (Int(sourceRawSize.width) - outgoingStretchPoint.x + 1, outgoingStretchPoint.y) + let incomingStretchPoint: (x: Int, y: Int) = (Int(sourceRawSize.width) - outgoingStretchPoint.x + Int(additionalInset), outgoingStretchPoint.y) let knockout = knockoutValue && !mask @@ -284,44 +284,65 @@ public func messageBubbleImage(maxCornerRadius: CGFloat, minCornerRadius: CGFloa let drawingContext = DrawingContext(size: imageSize) drawingContext.withFlippedContext { context in - var drawWithClearColor = false - - if knockout { - drawWithClearColor = !mask - if case let .color(color) = wallpaper { - context.setFillColor(UIColor(rgb: UInt32(color)).cgColor) - context.fill(CGRect(origin: CGPoint(), size: rawSize)) - } else { - context.clear(CGRect(origin: CGPoint(), size: rawSize)) - } - } else { + if onlyShadow { context.clear(CGRect(origin: CGPoint(), size: rawSize)) - } - - if drawWithClearColor { + + //print("theme.message.outgoing.bubble.withWallpaper.fill.rgb \(theme.message.outgoing.bubble.withWallpaper.fill.rgb)") + if theme.message.outgoing.bubble.withWallpaper.fill.rgb == 14023347 { + return + } + + context.translateBy(x: rawSize.width / 2.0, y: rawSize.height / 2.0) + context.scaleBy(x: incoming ? -1.0 : 1.0, y: -1.0) + context.translateBy(x: -rawSize.width / 2.0, y: -rawSize.height / 2.0) + + context.setShadow(offset: CGSize(width: 0.0, height: -5.0), blur: 16.0, color: UIColor(white: 0.0, alpha: 0.15).cgColor) + context.draw(formImage.cgImage!, in: CGRect(origin: CGPoint(), size: rawSize)) + context.setBlendMode(.copy) context.setFillColor(UIColor.clear.cgColor) - } else { - context.setBlendMode(.normal) - context.setFillColor(fillColor.cgColor) - } - - context.saveGState() - - context.translateBy(x: rawSize.width / 2.0, y: rawSize.height / 2.0) - context.scaleBy(x: incoming ? -1.0 : 1.0, y: -1.0) - context.translateBy(x: -rawSize.width / 2.0, y: -rawSize.height / 2.0) - - if !onlyOutline { context.clip(to: CGRect(origin: CGPoint(), size: rawSize), mask: formImage.cgImage!) context.fill(CGRect(origin: CGPoint(), size: rawSize)) } else { - context.setFillColor(strokeColor.cgColor) - context.clip(to: CGRect(origin: CGPoint(), size: rawSize), mask: outlineImage.cgImage!) - context.fill(CGRect(origin: CGPoint(), size: rawSize)) + var drawWithClearColor = false + + if knockout { + drawWithClearColor = !mask + if case let .color(color) = wallpaper { + context.setFillColor(UIColor(rgb: UInt32(color)).cgColor) + context.fill(CGRect(origin: CGPoint(), size: rawSize)) + } else { + context.clear(CGRect(origin: CGPoint(), size: rawSize)) + } + } else { + context.clear(CGRect(origin: CGPoint(), size: rawSize)) + } + + if drawWithClearColor { + context.setBlendMode(.copy) + context.setFillColor(UIColor.clear.cgColor) + } else { + context.setBlendMode(.normal) + context.setFillColor(fillColor.cgColor) + } + + context.saveGState() + + context.translateBy(x: rawSize.width / 2.0, y: rawSize.height / 2.0) + context.scaleBy(x: incoming ? -1.0 : 1.0, y: -1.0) + context.translateBy(x: -rawSize.width / 2.0, y: -rawSize.height / 2.0) + + if !onlyOutline { + context.clip(to: CGRect(origin: CGPoint(), size: rawSize), mask: formImage.cgImage!) + context.fill(CGRect(origin: CGPoint(), size: rawSize)) + } else { + context.setFillColor(strokeColor.cgColor) + context.clip(to: CGRect(origin: CGPoint(), size: rawSize), mask: outlineImage.cgImage!) + context.fill(CGRect(origin: CGPoint(), size: rawSize)) + } + + context.restoreGState() } - - context.restoreGState() } return drawingContext.generateImage()!.stretchableImage(withLeftCapWidth: incoming ? incomingStretchPoint.x : outgoingStretchPoint.x, topCapHeight: incoming ? incomingStretchPoint.y : outgoingStretchPoint.y) diff --git a/submodules/TelegramPresentationData/Sources/PresentationThemeEssentialGraphics.swift b/submodules/TelegramPresentationData/Sources/PresentationThemeEssentialGraphics.swift index 3374f03b51..2aa29887cd 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationThemeEssentialGraphics.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationThemeEssentialGraphics.swift @@ -79,51 +79,63 @@ public final class PrincipalThemeEssentialGraphics { public let chatMessageBackgroundIncomingMaskImage: UIImage public let chatMessageBackgroundIncomingImage: UIImage public let chatMessageBackgroundIncomingOutlineImage: UIImage + public let chatMessageBackgroundIncomingShadowImage: UIImage public let chatMessageBackgroundIncomingHighlightedImage: UIImage public let chatMessageBackgroundIncomingMergedTopMaskImage: UIImage public let chatMessageBackgroundIncomingMergedTopImage: UIImage public let chatMessageBackgroundIncomingMergedTopOutlineImage: UIImage + public let chatMessageBackgroundIncomingMergedTopShadowImage: UIImage public let chatMessageBackgroundIncomingMergedTopHighlightedImage: UIImage public let chatMessageBackgroundIncomingMergedTopSideMaskImage: UIImage public let chatMessageBackgroundIncomingMergedTopSideImage: UIImage public let chatMessageBackgroundIncomingMergedTopSideOutlineImage: UIImage + public let chatMessageBackgroundIncomingMergedTopSideShadowImage: UIImage public let chatMessageBackgroundIncomingMergedTopSideHighlightedImage: UIImage public let chatMessageBackgroundIncomingMergedBottomMaskImage: UIImage public let chatMessageBackgroundIncomingMergedBottomImage: UIImage public let chatMessageBackgroundIncomingMergedBottomOutlineImage: UIImage + public let chatMessageBackgroundIncomingMergedBottomShadowImage: UIImage public let chatMessageBackgroundIncomingMergedBottomHighlightedImage: UIImage public let chatMessageBackgroundIncomingMergedBothMaskImage: UIImage public let chatMessageBackgroundIncomingMergedBothImage: UIImage public let chatMessageBackgroundIncomingMergedBothOutlineImage: UIImage + public let chatMessageBackgroundIncomingMergedBothShadowImage: UIImage public let chatMessageBackgroundIncomingMergedBothHighlightedImage: UIImage public let chatMessageBackgroundIncomingMergedSideMaskImage: UIImage public let chatMessageBackgroundIncomingMergedSideImage: UIImage public let chatMessageBackgroundIncomingMergedSideOutlineImage: UIImage + public let chatMessageBackgroundIncomingMergedSideShadowImage: UIImage public let chatMessageBackgroundIncomingMergedSideHighlightedImage: UIImage public let chatMessageBackgroundOutgoingMaskImage: UIImage public let chatMessageBackgroundOutgoingImage: UIImage public let chatMessageBackgroundOutgoingOutlineImage: UIImage + public let chatMessageBackgroundOutgoingShadowImage: UIImage public let chatMessageBackgroundOutgoingHighlightedImage: UIImage public let chatMessageBackgroundOutgoingMergedTopMaskImage: UIImage public let chatMessageBackgroundOutgoingMergedTopImage: UIImage public let chatMessageBackgroundOutgoingMergedTopOutlineImage: UIImage + public let chatMessageBackgroundOutgoingMergedTopShadowImage: UIImage public let chatMessageBackgroundOutgoingMergedTopHighlightedImage: UIImage public let chatMessageBackgroundOutgoingMergedTopSideMaskImage: UIImage public let chatMessageBackgroundOutgoingMergedTopSideImage: UIImage public let chatMessageBackgroundOutgoingMergedTopSideOutlineImage: UIImage + public let chatMessageBackgroundOutgoingMergedTopSideShadowImage: UIImage public let chatMessageBackgroundOutgoingMergedTopSideHighlightedImage: UIImage public let chatMessageBackgroundOutgoingMergedBottomMaskImage: UIImage public let chatMessageBackgroundOutgoingMergedBottomImage: UIImage public let chatMessageBackgroundOutgoingMergedBottomOutlineImage: UIImage + public let chatMessageBackgroundOutgoingMergedBottomShadowImage: UIImage public let chatMessageBackgroundOutgoingMergedBottomHighlightedImage: UIImage public let chatMessageBackgroundOutgoingMergedBothMaskImage: UIImage public let chatMessageBackgroundOutgoingMergedBothImage: UIImage public let chatMessageBackgroundOutgoingMergedBothOutlineImage: UIImage + public let chatMessageBackgroundOutgoingMergedBothShadowImage: UIImage public let chatMessageBackgroundOutgoingMergedBothHighlightedImage: UIImage public let chatMessageBackgroundOutgoingMergedSideMaskImage: UIImage public let chatMessageBackgroundOutgoingMergedSideImage: UIImage public let chatMessageBackgroundOutgoingMergedSideOutlineImage: UIImage + public let chatMessageBackgroundOutgoingMergedSideShadowImage: UIImage public let chatMessageBackgroundOutgoingMergedSideHighlightedImage: UIImage public let checkBubbleFullImage: UIImage @@ -223,52 +235,64 @@ public final class PrincipalThemeEssentialGraphics { self.chatMessageBackgroundIncomingMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: UIColor.black, strokeColor: UIColor.clear, neighbors: .none, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) self.chatMessageBackgroundIncomingImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) self.chatMessageBackgroundIncomingOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundOutgoingMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .none, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) self.chatMessageBackgroundOutgoingImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) self.chatMessageBackgroundOutgoingOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.checkBubbleFullImage = generateCheckImage(partial: false, color: theme.message.outgoingCheckColor, width: 11.0)! self.checkBubblePartialImage = generateCheckImage(partial: true, color: theme.message.outgoingCheckColor, width: 11.0)! self.chatMessageBackgroundIncomingHighlightedImage = emptyImage self.chatMessageBackgroundIncomingMergedTopMaskImage = emptyImage self.chatMessageBackgroundIncomingMergedTopImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) self.chatMessageBackgroundIncomingMergedTopOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMergedTopShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundIncomingMergedTopHighlightedImage = emptyImage self.chatMessageBackgroundIncomingMergedTopSideMaskImage = emptyImage self.chatMessageBackgroundIncomingMergedTopSideImage = emptyImage self.chatMessageBackgroundIncomingMergedTopSideOutlineImage = emptyImage + self.chatMessageBackgroundIncomingMergedTopSideShadowImage = emptyImage self.chatMessageBackgroundIncomingMergedTopSideHighlightedImage = emptyImage self.chatMessageBackgroundIncomingMergedBottomMaskImage = emptyImage self.chatMessageBackgroundIncomingMergedBottomImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) self.chatMessageBackgroundIncomingMergedBottomOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMergedBottomShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundIncomingMergedBottomHighlightedImage = emptyImage self.chatMessageBackgroundIncomingMergedBothMaskImage = emptyImage self.chatMessageBackgroundIncomingMergedBothImage = emptyImage self.chatMessageBackgroundIncomingMergedBothOutlineImage = emptyImage + self.chatMessageBackgroundIncomingMergedBothShadowImage = emptyImage self.chatMessageBackgroundIncomingMergedBothHighlightedImage = emptyImage self.chatMessageBackgroundIncomingMergedSideMaskImage = emptyImage self.chatMessageBackgroundIncomingMergedSideImage = emptyImage self.chatMessageBackgroundIncomingMergedSideOutlineImage = emptyImage + self.chatMessageBackgroundIncomingMergedSideShadowImage = emptyImage self.chatMessageBackgroundIncomingMergedSideHighlightedImage = emptyImage self.chatMessageBackgroundOutgoingHighlightedImage = emptyImage self.chatMessageBackgroundOutgoingMergedTopMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .top(side: false), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedTopImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedTopOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedTopShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundOutgoingMergedTopHighlightedImage = emptyImage self.chatMessageBackgroundOutgoingMergedTopSideMaskImage = emptyImage self.chatMessageBackgroundOutgoingMergedTopSideImage = emptyImage self.chatMessageBackgroundOutgoingMergedTopSideOutlineImage = emptyImage + self.chatMessageBackgroundOutgoingMergedTopSideShadowImage = emptyImage self.chatMessageBackgroundOutgoingMergedTopSideHighlightedImage = emptyImage self.chatMessageBackgroundOutgoingMergedBottomMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .bottom, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedBottomImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedBottomOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedBottomShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundOutgoingMergedBottomHighlightedImage = emptyImage self.chatMessageBackgroundOutgoingMergedBothMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .both, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedBothImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedBothOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedBothShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundOutgoingMergedBothHighlightedImage = emptyImage self.chatMessageBackgroundOutgoingMergedSideMaskImage = emptyImage self.chatMessageBackgroundOutgoingMergedSideImage = emptyImage self.chatMessageBackgroundOutgoingMergedSideOutlineImage = emptyImage + self.chatMessageBackgroundOutgoingMergedSideShadowImage = emptyImage self.chatMessageBackgroundOutgoingMergedSideHighlightedImage = emptyImage self.checkMediaFullImage = emptyImage self.checkMediaPartialImage = emptyImage @@ -294,51 +318,63 @@ public final class PrincipalThemeEssentialGraphics { self.chatMessageBackgroundIncomingMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .none, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) self.chatMessageBackgroundIncomingImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) self.chatMessageBackgroundIncomingOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundIncomingHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) self.chatMessageBackgroundIncomingMergedTopMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .top(side: false), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) self.chatMessageBackgroundIncomingMergedTopImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) self.chatMessageBackgroundIncomingMergedTopOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMergedTopShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundIncomingMergedTopHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) self.chatMessageBackgroundIncomingMergedTopSideMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .top(side: true), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) self.chatMessageBackgroundIncomingMergedTopSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) self.chatMessageBackgroundIncomingMergedTopSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMergedTopSideShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundIncomingMergedTopSideHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) self.chatMessageBackgroundIncomingMergedBottomMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .bottom, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) self.chatMessageBackgroundIncomingMergedBottomImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) self.chatMessageBackgroundIncomingMergedBottomOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMergedBottomShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundIncomingMergedBottomHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) self.chatMessageBackgroundIncomingMergedBothMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .both, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) self.chatMessageBackgroundIncomingMergedBothImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) self.chatMessageBackgroundIncomingMergedBothOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMergedBothShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundIncomingMergedBothHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) self.chatMessageBackgroundOutgoingMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .none, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) self.chatMessageBackgroundOutgoingImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) self.chatMessageBackgroundOutgoingOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundOutgoingHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedTopMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .top(side: false), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedTopImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedTopOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedTopShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundOutgoingMergedTopHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedTopSideMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .top(side: true), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedTopSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedTopSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedTopSideShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundOutgoingMergedTopSideHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedBottomMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .bottom, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedBottomImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedBottomOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedBottomShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundOutgoingMergedBottomHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedBothMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .both, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedBothImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedBothOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedBothShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundOutgoingMergedBothHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) self.chatMessageBackgroundIncomingMergedSideMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .side, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) self.chatMessageBackgroundIncomingMergedSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) self.chatMessageBackgroundIncomingMergedSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMergedSideShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundOutgoingMergedSideMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .side, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedSideShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundIncomingMergedSideHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedSideHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) diff --git a/submodules/TelegramUI/TelegramUI/ChatControllerNode.swift b/submodules/TelegramUI/TelegramUI/ChatControllerNode.swift index b4d9552cd5..53a7b86c40 100644 --- a/submodules/TelegramUI/TelegramUI/ChatControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatControllerNode.swift @@ -294,6 +294,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.backgroundNode.motionEnabled = chatPresentationInterfaceState.chatWallpaper.settings?.motion ?? false self.historyNode.verticalScrollIndicatorColor = UIColor(white: 0.5, alpha: 0.8) + self.historyNode.enableExtractedBackgrounds = true self.addSubnode(self.backgroundNode) self.addSubnode(self.historyNodeContainer) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageBackground.swift b/submodules/TelegramUI/TelegramUI/ChatMessageBackground.swift index 09ab5933d4..b88c4e6625 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageBackground.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageBackground.swift @@ -226,3 +226,76 @@ class ChatMessageBackground: ASDisplayNode { self.outlineImageNode.image = outlineImage } } + +final class ChatMessageShadowNode: ASDisplayNode { + private let contentNode: ASImageNode + private var graphics: PrincipalThemeEssentialGraphics? + + override init() { + self.contentNode = ASImageNode() + self.contentNode.isLayerBacked = true + self.contentNode.displaysAsynchronously = false + self.contentNode.displayWithoutProcessing = true + + super.init() + + self.transform = CATransform3DMakeRotation(CGFloat.pi, 0.0, 0.0, 1.0) + + self.isLayerBacked = true + + self.addSubnode(self.contentNode) + } + + func setType(type: ChatMessageBackgroundType, hasWallpaper: Bool, graphics: PrincipalThemeEssentialGraphics) { + let shadowImage: UIImage? + + if hasWallpaper { + switch type { + case .none: + shadowImage = nil + case let .incoming(mergeType): + switch mergeType { + case .None: + shadowImage = graphics.chatMessageBackgroundIncomingShadowImage + case let .Top(side): + if side { + shadowImage = graphics.chatMessageBackgroundIncomingMergedTopSideShadowImage + } else { + shadowImage = graphics.chatMessageBackgroundIncomingMergedTopShadowImage + } + case .Bottom: + shadowImage = graphics.chatMessageBackgroundIncomingMergedBottomShadowImage + case .Both: + shadowImage = graphics.chatMessageBackgroundIncomingMergedBothShadowImage + case .Side: + shadowImage = graphics.chatMessageBackgroundIncomingMergedSideShadowImage + } + case let .outgoing(mergeType): + switch mergeType { + case .None: + shadowImage = graphics.chatMessageBackgroundOutgoingShadowImage + case let .Top(side): + if side { + shadowImage = graphics.chatMessageBackgroundOutgoingMergedTopSideShadowImage + } else { + shadowImage = graphics.chatMessageBackgroundOutgoingMergedTopShadowImage + } + case .Bottom: + shadowImage = graphics.chatMessageBackgroundOutgoingMergedBottomShadowImage + case .Both: + shadowImage = graphics.chatMessageBackgroundOutgoingMergedBothShadowImage + case .Side: + shadowImage = graphics.chatMessageBackgroundOutgoingMergedSideShadowImage + } + } + } else { + shadowImage = nil + } + + self.contentNode.image = shadowImage + } + + func updateLayout(backgroundFrame: CGRect, transition: ContainedViewLayoutTransition) { + transition.updateFrame(node: self.contentNode, frame: CGRect(origin: CGPoint(x: backgroundFrame.minX - 10.0, y: backgroundFrame.minY - 10.0), size: CGSize(width: backgroundFrame.width + 20.0, height: backgroundFrame.height + 20.0))) + } +} diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift index 88a19d0bdb..5901a14934 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift @@ -147,8 +147,13 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode private let contextSourceNode: ContextExtractedContentContainingNode private let backgroundWallpaperNode: ChatMessageBubbleBackdrop private let backgroundNode: ChatMessageBackground + private let shadowNode: ChatMessageShadowNode private var transitionClippingNode: ASDisplayNode? + override var extractedBackgroundNode: ASDisplayNode? { + return self.shadowNode + } + private var selectionNode: ChatMessageSelectionNode? private var deliveryFailedNode: ChatMessageDeliveryFailedNode? private var swipeToReplyNode: ChatMessageSwipeToReplyNode? @@ -199,6 +204,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode self.backgroundWallpaperNode = ChatMessageBubbleBackdrop() self.backgroundNode = ChatMessageBackground() + self.shadowNode = ChatMessageShadowNode() self.messageAccessibilityArea = AccessibilityAreaNode() super.init(layerBacked: false) @@ -272,6 +278,8 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode override func animateInsertion(_ currentTimestamp: Double, duration: Double, short: Bool) { super.animateInsertion(currentTimestamp, duration: duration, short: short) + self.shadowNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) + if let subnodes = self.subnodes { for node in subnodes { if let contextNode = node as? ContextExtractedContentContainingNode { @@ -308,6 +316,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false, completion: { [weak self] _ in self?.allowsGroupOpacity = false }) + self.shadowNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false) self.layer.animateScale(from: 1.0, to: 0.1, duration: 0.15, removeOnCompletion: false) self.layer.animatePosition(from: CGPoint(), to: CGPoint(x: self.bounds.width / 2.0 - self.backgroundNode.frame.midX, y: self.backgroundNode.frame.midY), duration: 0.15, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false, additive: true) } @@ -1681,6 +1690,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode let hasWallpaper = item.presentationData.theme.wallpaper.hasWallpaper strongSelf.backgroundNode.setType(type: backgroundType, highlighted: strongSelf.highlightedState, graphics: graphics, maskMode: strongSelf.backgroundMaskMode, hasWallpaper: hasWallpaper, transition: transition) strongSelf.backgroundWallpaperNode.setType(type: backgroundType, theme: item.presentationData.theme, mediaBox: item.context.account.postbox.mediaBox, essentialGraphics: graphics, maskMode: strongSelf.backgroundMaskMode) + strongSelf.shadowNode.setType(type: backgroundType, hasWallpaper: hasWallpaper, graphics: graphics) strongSelf.backgroundType = backgroundType @@ -1953,10 +1963,12 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode transition.updateFrame(node: strongSelf.backgroundNode, frame: backgroundFrame) strongSelf.backgroundNode.updateLayout(size: backgroundFrame.size, transition: transition) strongSelf.backgroundWallpaperNode.updateFrame(backgroundFrame, transition: transition) + strongSelf.shadowNode.updateLayout(backgroundFrame: backgroundFrame, transition: transition) } else { strongSelf.backgroundNode.frame = backgroundFrame strongSelf.backgroundNode.updateLayout(size: backgroundFrame.size, transition: .immediate) strongSelf.backgroundWallpaperNode.frame = backgroundFrame + strongSelf.shadowNode.updateLayout(backgroundFrame: backgroundFrame, transition: .immediate) } if let (rect, size) = strongSelf.absoluteRect { strongSelf.updateAbsoluteRect(rect, within: size) @@ -2153,6 +2165,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode self.backgroundNode.frame = backgroundFrame self.backgroundNode.updateLayout(size: backgroundFrame.size, transition: .immediate) self.backgroundWallpaperNode.frame = backgroundFrame + self.shadowNode.updateLayout(backgroundFrame: backgroundFrame, transition: .immediate) if let type = self.backgroundNode.type { var incomingOffset: CGFloat = 0.0 From 648553970e604d0a0dcdb43fd4db7de6f62a60fe Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 24 Jan 2020 19:15:31 +0400 Subject: [PATCH 30/50] Temp --- .../Sources/ChatMessageBubbleImages.swift | 6 +--- .../Sources/PresentationTheme.swift | 18 ++++++++-- .../Sources/PresentationThemeCodable.swift | 36 ++++++++++++++++--- 3 files changed, 49 insertions(+), 11 deletions(-) diff --git a/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift b/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift index c5b70db909..dfe03cedeb 100644 --- a/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift +++ b/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift @@ -293,11 +293,7 @@ public func messageBubbleImage(maxCornerRadius: CGFloat, minCornerRadius: CGFloa drawingContext.withFlippedContext { context in if onlyShadow { context.clear(CGRect(origin: CGPoint(), size: rawSize)) - - //print("theme.message.outgoing.bubble.withWallpaper.fill.rgb \(theme.message.outgoing.bubble.withWallpaper.fill.rgb)") - if theme.message.outgoing.bubble.withWallpaper.fill.rgb == 14023347 { - return - } + return; context.translateBy(x: rawSize.width / 2.0, y: rawSize.height / 2.0) context.scaleBy(x: incoming ? -1.0 : 1.0, y: -1.0) diff --git a/submodules/TelegramPresentationData/Sources/PresentationTheme.swift b/submodules/TelegramPresentationData/Sources/PresentationTheme.swift index e9ab5e256a..c20bc02c28 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationTheme.swift @@ -549,21 +549,35 @@ public final class PresentationThemeChatList { } } +public struct PresentationThemeBubbleShadow { + public var color: UIColor + public var radius: CGFloat + public var verticalOffset: CGFloat + + public init(color: UIColor, radius: CGFloat, verticalOffset: CGFloat) { + self.color = color + self.radius = radius + self.verticalOffset = verticalOffset + } +} + public final class PresentationThemeBubbleColorComponents { public let fill: UIColor public let gradientFill: UIColor public let highlightedFill: UIColor public let stroke: UIColor + //public let shadow: PresentationThemeBubbleShadow? - public init(fill: UIColor, gradientFill: UIColor? = nil, highlightedFill: UIColor, stroke: UIColor) { + public init(fill: UIColor, gradientFill: UIColor? = nil, highlightedFill: UIColor, stroke: UIColor/*, shadow: PresentationThemeBubbleShadow?*/) { self.fill = fill self.gradientFill = gradientFill ?? fill self.highlightedFill = highlightedFill self.stroke = stroke + //self.shadow = shadow } public func withUpdated(fill: UIColor? = nil, gradientFill: UIColor? = nil, highlightedFill: UIColor? = nil, stroke: UIColor? = nil) -> PresentationThemeBubbleColorComponents { - return PresentationThemeBubbleColorComponents(fill: fill ?? self.fill, gradientFill: gradientFill ?? self.gradientFill, highlightedFill: highlightedFill ?? self.highlightedFill, stroke: stroke ?? self.stroke) + return PresentationThemeBubbleColorComponents(fill: fill ?? self.fill, gradientFill: gradientFill ?? self.gradientFill, highlightedFill: highlightedFill ?? self.highlightedFill, stroke: stroke ?? self.stroke/*, shadow: self.shadow*/) } } diff --git a/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift b/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift index 876a2f188c..9ed40a2f67 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift @@ -979,21 +979,49 @@ extension PresentationThemeChatList: Codable { } } +extension PresentationThemeBubbleShadow: Codable { + enum CodingKeys: String, CodingKey { + case color + case radius + case verticalOffset + } + + public init(from decoder: Decoder) throws { + let values = try decoder.container(keyedBy: CodingKeys.self) + self.init( + color: try decodeColor(values, .color), + radius: try CGFloat(values.decode(Float.self, forKey: .radius)), + verticalOffset: try CGFloat(values.decode(Float.self, forKey: .verticalOffset)) + ) + } + + public func encode(to encoder: Encoder) throws { + var values = encoder.container(keyedBy: CodingKeys.self) + try encodeColor(&values, self.color, .color) + try values.encode(Float(self.radius), forKey: .radius) + try values.encode(Float(self.verticalOffset), forKey: .verticalOffset) + } +} + extension PresentationThemeBubbleColorComponents: Codable { enum CodingKeys: String, CodingKey { case bg case gradientBg case highlightedBg case stroke + case shadow } public convenience init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) let codingPath = decoder.codingPath.map { $0.stringValue }.joined(separator: ".") - self.init(fill: try decodeColor(values, .bg), - gradientFill: try decodeColor(values, .gradientBg, decoder: decoder, fallbackKey: codingPath + ".bg"), - highlightedFill: try decodeColor(values, .highlightedBg), - stroke: try decodeColor(values, .stroke)) + self.init( + fill: try decodeColor(values, .bg), + gradientFill: try decodeColor(values, .gradientBg, decoder: decoder, fallbackKey: codingPath + ".bg"), + highlightedFill: try decodeColor(values, .highlightedBg), + stroke: try decodeColor(values, .stroke)//, + //shadow: try? values.decode(PresentationThemeBubbleShadow.self, forKey: .shadow) + ) } public func encode(to encoder: Encoder) throws { From 53eee9eccdce04664dc39dc64a9d0c6deb46a00b Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sat, 25 Jan 2020 01:03:47 +0400 Subject: [PATCH 31/50] Fix chat list filter layout --- .../Sources/TabBarChatListFilterController.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift b/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift index 8048568cbd..204ee79dea 100644 --- a/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift +++ b/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift @@ -420,10 +420,10 @@ private final class TabBarChatListFilterControllerNode: ViewControllerTracingNod let sideInset: CGFloat = 18.0 var contentSize = CGSize() - contentSize.width = min(layout.size.width - 40.0, 250.0) + contentSize.width = min(layout.size.width - 60.0, 220.0) var applyNodes: [(ASDisplayNode, CGFloat, (CGFloat) -> Void)] = [] for itemNode in self.contentNodes { - let (width, height, apply) = itemNode.updateLayout(maxWidth: layout.size.width - sideInset * 2.0) + let (width, height, apply) = itemNode.updateLayout(maxWidth: contentSize.width - sideInset * 2.0) applyNodes.append((itemNode, height, apply)) contentSize.width = max(contentSize.width, width) contentSize.height += height @@ -433,9 +433,9 @@ private final class TabBarChatListFilterControllerNode: ViewControllerTracingNod let contentOrigin: CGPoint if let sourceNode = self.sourceNodes.first, let screenFrame = sourceNode.supernode?.convert(sourceNode.frame, to: nil) { - contentOrigin = CGPoint(x: screenFrame.maxX - contentSize.width + 8.0, y: layout.size.height - 66.0 - insets.bottom - contentSize.height) + contentOrigin = CGPoint(x: max(16.0, screenFrame.maxX - contentSize.width + 8.0), y: layout.size.height - 66.0 - insets.bottom - contentSize.height) } else { - contentOrigin = CGPoint(x: layout.size.width - sideInset - contentSize.width, y: layout.size.height - 66.0 - layout.intrinsicInsets.bottom - contentSize.height) + contentOrigin = CGPoint(x: max(16.0, layout.size.width - sideInset - contentSize.width), y: layout.size.height - 66.0 - layout.intrinsicInsets.bottom - contentSize.height) } transition.updateFrame(node: self.contentContainerNode, frame: CGRect(origin: contentOrigin, size: contentSize)) From 0fe641ec1cd083b11a4d41dd85386d4ba48cdeea Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sat, 25 Jan 2020 02:01:09 +0400 Subject: [PATCH 32/50] Load shadow settings from theme files --- .../Sources/ChatMessageBubbleImages.swift | 25 ++++++----- .../DefaultDarkPresentationTheme.swift | 6 +-- .../DefaultDarkTintedPresentationTheme.swift | 6 +-- .../Sources/DefaultDayPresentationTheme.swift | 12 ++--- .../Sources/PresentationTheme.swift | 8 ++-- .../Sources/PresentationThemeCodable.swift | 12 ++--- .../Sources/PresentationThemeCoder.swift | 6 ++- .../ChatMessageBubbleItemNode.swift | 44 +++++++++++++++++++ 8 files changed, 85 insertions(+), 34 deletions(-) diff --git a/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift b/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift index dfe03cedeb..ef0d6dc6b7 100644 --- a/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift +++ b/submodules/TelegramPresentationData/Sources/ChatMessageBubbleImages.swift @@ -293,19 +293,22 @@ public func messageBubbleImage(maxCornerRadius: CGFloat, minCornerRadius: CGFloa drawingContext.withFlippedContext { context in if onlyShadow { context.clear(CGRect(origin: CGPoint(), size: rawSize)) - return; - context.translateBy(x: rawSize.width / 2.0, y: rawSize.height / 2.0) - context.scaleBy(x: incoming ? -1.0 : 1.0, y: -1.0) - context.translateBy(x: -rawSize.width / 2.0, y: -rawSize.height / 2.0) + let bubbleColors = incoming ? theme.message.incoming : theme.message.outgoing - context.setShadow(offset: CGSize(width: 0.0, height: -5.0), blur: 16.0, color: UIColor(white: 0.0, alpha: 0.15).cgColor) - context.draw(formImage.cgImage!, in: CGRect(origin: CGPoint(), size: rawSize)) - - context.setBlendMode(.copy) - context.setFillColor(UIColor.clear.cgColor) - context.clip(to: CGRect(origin: CGPoint(), size: rawSize), mask: formImage.cgImage!) - context.fill(CGRect(origin: CGPoint(), size: rawSize)) + if let shadow = bubbleColors.bubble.withWallpaper.shadow { + context.translateBy(x: rawSize.width / 2.0, y: rawSize.height / 2.0) + context.scaleBy(x: incoming ? -1.0 : 1.0, y: -1.0) + context.translateBy(x: -rawSize.width / 2.0, y: -rawSize.height / 2.0) + + context.setShadow(offset: CGSize(width: 0.0, height: -shadow.verticalOffset), blur: shadow.radius, color: shadow.color.cgColor) + context.draw(formImage.cgImage!, in: CGRect(origin: CGPoint(), size: rawSize)) + + context.setBlendMode(.copy) + context.setFillColor(UIColor.clear.cgColor) + context.clip(to: CGRect(origin: CGPoint(), size: rawSize), mask: formImage.cgImage!) + context.fill(CGRect(origin: CGPoint(), size: rawSize)) + } } else { var drawWithClearColor = false diff --git a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift index 6d330fa665..0814168886 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift @@ -394,9 +394,9 @@ public func makeDefaultDarkPresentationTheme(extendingThemeReference: Presentati ) let message = PresentationThemeChatMessage( - incoming: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x262628), highlightedFill: UIColor(rgb: 0x353539), stroke: UIColor(rgb: 0x262628)), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x262628), highlightedFill: UIColor(rgb: 0x353539), stroke: UIColor(rgb: 0x262628))), primaryTextColor: UIColor(rgb: 0xffffff), secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.5), linkTextColor: UIColor(rgb: 0xffffff), linkHighlightColor: UIColor(rgb: 0xffffff, alpha: 0.5), scamColor: UIColor(rgb: 0xeb5545), textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: UIColor(rgb: 0xffffff), accentControlColor: UIColor(rgb: 0xffffff), accentControlDisabledColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaActiveControlColor: UIColor(rgb: 0xffffff), mediaInactiveControlColor: UIColor(rgb: 0xffffff, alpha: 0.4), mediaControlInnerBackgroundColor: UIColor(rgb: 0x262628), pendingActivityColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileTitleColor: UIColor(rgb: 0xffffff), fileDescriptionColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileDurationColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaPlaceholderColor: UIColor(rgb: 0x1f1f1f).mixedWith(UIColor(rgb: 0xffffff), alpha: 0.05), polls: PresentationThemeChatBubblePolls(radioButton: UIColor(rgb: 0x737373), radioProgress: UIColor(rgb: 0xffffff), highlight: UIColor(rgb: 0xffffff, alpha: 0.12), separator: UIColor(rgb: 0x000000), bar: UIColor(rgb: 0xffffff), barIconForeground: .clear, barPositive: UIColor(rgb: 0x00A700), barNegative: UIColor(rgb: 0xFE3824)), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: UIColor(rgb: 0x000000, alpha: 0.5), withoutWallpaper: UIColor(rgb: 0x000000, alpha: 0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xb2b2b2, alpha: 0.18)), actionButtonsTextColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xffffff)), textSelectionColor: UIColor(rgb: 0xffffff, alpha: 0.2), textSelectionKnobColor: UIColor(rgb: 0xffffff)), - outgoing: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x313131), gradientFill: UIColor(rgb: 0x313131), highlightedFill: UIColor(rgb: 0x464646), stroke: UIColor(rgb: 0x313131)), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x313131), gradientFill: UIColor(rgb: 0x313131), highlightedFill: UIColor(rgb: 0x464646), stroke: UIColor(rgb: 0x313131))), primaryTextColor: UIColor(rgb: 0xffffff), secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.5), linkTextColor: UIColor(rgb: 0xffffff), linkHighlightColor: UIColor(rgb: 0xffffff, alpha: 0.5), scamColor: UIColor(rgb: 0xeb5545), textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: UIColor(rgb: 0xffffff), accentControlColor: UIColor(rgb: 0xffffff), accentControlDisabledColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaActiveControlColor: UIColor(rgb: 0xffffff), mediaInactiveControlColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaControlInnerBackgroundColor: UIColor(rgb: 0x313131), pendingActivityColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileTitleColor: UIColor(rgb: 0xffffff), fileDescriptionColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileDurationColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaPlaceholderColor: UIColor(rgb: 0x313131).mixedWith(UIColor(rgb: 0xffffff), alpha: 0.05), polls: PresentationThemeChatBubblePolls(radioButton: UIColor(rgb: 0xffffff), radioProgress: UIColor(rgb: 0xffffff), highlight: UIColor(rgb: 0xffffff).withAlphaComponent(0.12), separator: UIColor(rgb: 0xffffff, alpha: 0.5), bar: UIColor(rgb: 0xffffff), barIconForeground: .clear, barPositive: UIColor(rgb: 0xffffff), barNegative: UIColor(rgb: 0xffffff)), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: UIColor(rgb: 0x000000, alpha: 0.5), withoutWallpaper: UIColor(rgb: 0x000000, alpha: 0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xb2b2b2, alpha: 0.18)), actionButtonsTextColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xffffff)), textSelectionColor: UIColor(rgb: 0xffffff, alpha: 0.2), textSelectionKnobColor: UIColor(rgb: 0xffffff)), - freeform: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x1f1f1f), highlightedFill: UIColor(rgb: 0x2a2a2a), stroke: UIColor(rgb: 0x1f1f1f)), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x1f1f1f), highlightedFill: UIColor(rgb: 0x2a2a2a), stroke: UIColor(rgb: 0x1f1f1f))), + incoming: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x262628), highlightedFill: UIColor(rgb: 0x353539), stroke: UIColor(rgb: 0x262628), shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x262628), highlightedFill: UIColor(rgb: 0x353539), stroke: UIColor(rgb: 0x262628), shadow: nil)), primaryTextColor: UIColor(rgb: 0xffffff), secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.5), linkTextColor: UIColor(rgb: 0xffffff), linkHighlightColor: UIColor(rgb: 0xffffff, alpha: 0.5), scamColor: UIColor(rgb: 0xeb5545), textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: UIColor(rgb: 0xffffff), accentControlColor: UIColor(rgb: 0xffffff), accentControlDisabledColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaActiveControlColor: UIColor(rgb: 0xffffff), mediaInactiveControlColor: UIColor(rgb: 0xffffff, alpha: 0.4), mediaControlInnerBackgroundColor: UIColor(rgb: 0x262628), pendingActivityColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileTitleColor: UIColor(rgb: 0xffffff), fileDescriptionColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileDurationColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaPlaceholderColor: UIColor(rgb: 0x1f1f1f).mixedWith(UIColor(rgb: 0xffffff), alpha: 0.05), polls: PresentationThemeChatBubblePolls(radioButton: UIColor(rgb: 0x737373), radioProgress: UIColor(rgb: 0xffffff), highlight: UIColor(rgb: 0xffffff, alpha: 0.12), separator: UIColor(rgb: 0x000000), bar: UIColor(rgb: 0xffffff), barIconForeground: .clear, barPositive: UIColor(rgb: 0x00A700), barNegative: UIColor(rgb: 0xFE3824)), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: UIColor(rgb: 0x000000, alpha: 0.5), withoutWallpaper: UIColor(rgb: 0x000000, alpha: 0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xb2b2b2, alpha: 0.18)), actionButtonsTextColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xffffff)), textSelectionColor: UIColor(rgb: 0xffffff, alpha: 0.2), textSelectionKnobColor: UIColor(rgb: 0xffffff)), + outgoing: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x313131), gradientFill: UIColor(rgb: 0x313131), highlightedFill: UIColor(rgb: 0x464646), stroke: UIColor(rgb: 0x313131), shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x313131), gradientFill: UIColor(rgb: 0x313131), highlightedFill: UIColor(rgb: 0x464646), stroke: UIColor(rgb: 0x313131), shadow: nil)), primaryTextColor: UIColor(rgb: 0xffffff), secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.5), linkTextColor: UIColor(rgb: 0xffffff), linkHighlightColor: UIColor(rgb: 0xffffff, alpha: 0.5), scamColor: UIColor(rgb: 0xeb5545), textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: UIColor(rgb: 0xffffff), accentControlColor: UIColor(rgb: 0xffffff), accentControlDisabledColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaActiveControlColor: UIColor(rgb: 0xffffff), mediaInactiveControlColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaControlInnerBackgroundColor: UIColor(rgb: 0x313131), pendingActivityColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileTitleColor: UIColor(rgb: 0xffffff), fileDescriptionColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileDurationColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaPlaceholderColor: UIColor(rgb: 0x313131).mixedWith(UIColor(rgb: 0xffffff), alpha: 0.05), polls: PresentationThemeChatBubblePolls(radioButton: UIColor(rgb: 0xffffff), radioProgress: UIColor(rgb: 0xffffff), highlight: UIColor(rgb: 0xffffff).withAlphaComponent(0.12), separator: UIColor(rgb: 0xffffff, alpha: 0.5), bar: UIColor(rgb: 0xffffff), barIconForeground: .clear, barPositive: UIColor(rgb: 0xffffff), barNegative: UIColor(rgb: 0xffffff)), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: UIColor(rgb: 0x000000, alpha: 0.5), withoutWallpaper: UIColor(rgb: 0x000000, alpha: 0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xb2b2b2, alpha: 0.18)), actionButtonsTextColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xffffff)), textSelectionColor: UIColor(rgb: 0xffffff, alpha: 0.2), textSelectionKnobColor: UIColor(rgb: 0xffffff)), + freeform: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x1f1f1f), highlightedFill: UIColor(rgb: 0x2a2a2a), stroke: UIColor(rgb: 0x1f1f1f), shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x1f1f1f), highlightedFill: UIColor(rgb: 0x2a2a2a), stroke: UIColor(rgb: 0x1f1f1f), shadow: nil)), infoPrimaryTextColor: UIColor(rgb: 0xffffff), infoLinkTextColor: UIColor(rgb: 0xffffff), outgoingCheckColor: UIColor(rgb: 0xffffff), diff --git a/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift index 850da9400b..0781eba55a 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift @@ -643,9 +643,9 @@ public func makeDefaultDarkTintedPresentationTheme(extendingThemeReference: Pres let buttonStrokeColor = accentColor.withMultiplied(hue: 1.014, saturation: 0.56, brightness: 0.64).withAlphaComponent(0.15) let message = PresentationThemeChatMessage( - incoming: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: mainBackgroundColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: mainBackgroundColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor)), primaryTextColor: .white, secondaryTextColor: mainSecondaryTextColor.withAlphaComponent(0.5), linkTextColor: accentColor, linkHighlightColor: accentColor.withAlphaComponent(0.5), scamColor: UIColor(rgb: 0xff6767), textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: accentColor, accentControlColor: accentColor, accentControlDisabledColor: mainSecondaryTextColor.withAlphaComponent(0.5), mediaActiveControlColor: accentColor, mediaInactiveControlColor: accentColor.withAlphaComponent(0.5), mediaControlInnerBackgroundColor: mainBackgroundColor, pendingActivityColor: mainSecondaryTextColor.withAlphaComponent(0.5), fileTitleColor: accentColor, fileDescriptionColor: mainSecondaryTextColor.withAlphaComponent(0.5), fileDurationColor: mainSecondaryTextColor.withAlphaComponent(0.5), mediaPlaceholderColor: accentColor.withMultiplied(hue: 1.019, saturation: 0.585, brightness: 0.23), polls: PresentationThemeChatBubblePolls(radioButton: accentColor.withMultiplied(hue: 0.995, saturation: 0.317, brightness: 0.51), radioProgress: accentColor, highlight: accentColor.withAlphaComponent(0.12), separator: mainSeparatorColor, bar: accentColor, barIconForeground: .white, barPositive: UIColor(rgb: 0x00A700), barNegative: UIColor(rgb: 0xFE3824)), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: additionalBackgroundColor.withAlphaComponent(0.5), withoutWallpaper: additionalBackgroundColor.withAlphaComponent(0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: buttonStrokeColor), actionButtonsTextColor: PresentationThemeVariableColor(color: .white), textSelectionColor: accentColor.withAlphaComponent(0.2), textSelectionKnobColor: accentColor), - outgoing: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleFillColor, gradientFill: outgoingBubbleFillGradientColor, highlightedFill: highlightedOutgoingBubbleColor, stroke: outgoingBubbleFillColor), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleFillColor, gradientFill: outgoingBubbleFillGradientColor, highlightedFill: highlightedOutgoingBubbleColor, stroke: outgoingBubbleFillColor)), primaryTextColor: outgoingPrimaryTextColor, secondaryTextColor: outgoingSecondaryTextColor, linkTextColor: outgoingLinkTextColor, linkHighlightColor: UIColor.white.withAlphaComponent(0.5), scamColor: outgoingScamColor, textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: outgoingPrimaryTextColor, accentControlColor: outgoingPrimaryTextColor, accentControlDisabledColor: mainSecondaryTextColor.withAlphaComponent(0.5), mediaActiveControlColor: outgoingPrimaryTextColor, mediaInactiveControlColor: outgoingSecondaryTextColor, mediaControlInnerBackgroundColor: outgoingBubbleFillColor, pendingActivityColor: outgoingSecondaryTextColor, fileTitleColor: outgoingPrimaryTextColor, fileDescriptionColor: outgoingSecondaryTextColor, fileDurationColor: outgoingSecondaryTextColor, mediaPlaceholderColor: accentColor.withMultiplied(hue: 1.019, saturation: 0.804, brightness: 0.51), polls: PresentationThemeChatBubblePolls(radioButton: outgoingPrimaryTextColor, radioProgress: accentColor.withMultiplied(hue: 0.99, saturation: 0.56, brightness: 1.0), highlight: accentColor.withMultiplied(hue: 0.99, saturation: 0.56, brightness: 1.0).withAlphaComponent(0.12), separator: mainSeparatorColor, bar: outgoingPrimaryTextColor, barIconForeground: .clear, barPositive: outgoingPrimaryTextColor, barNegative: outgoingPrimaryTextColor), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: additionalBackgroundColor.withAlphaComponent(0.5), withoutWallpaper: additionalBackgroundColor.withAlphaComponent(0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: buttonStrokeColor), actionButtonsTextColor: PresentationThemeVariableColor(color: .white), textSelectionColor: UIColor.white.withAlphaComponent(0.2), textSelectionKnobColor: UIColor.white), - freeform: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: mainBackgroundColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: mainBackgroundColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor)), + incoming: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: mainBackgroundColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor, shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: mainBackgroundColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor, shadow: nil)), primaryTextColor: .white, secondaryTextColor: mainSecondaryTextColor.withAlphaComponent(0.5), linkTextColor: accentColor, linkHighlightColor: accentColor.withAlphaComponent(0.5), scamColor: UIColor(rgb: 0xff6767), textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: accentColor, accentControlColor: accentColor, accentControlDisabledColor: mainSecondaryTextColor.withAlphaComponent(0.5), mediaActiveControlColor: accentColor, mediaInactiveControlColor: accentColor.withAlphaComponent(0.5), mediaControlInnerBackgroundColor: mainBackgroundColor, pendingActivityColor: mainSecondaryTextColor.withAlphaComponent(0.5), fileTitleColor: accentColor, fileDescriptionColor: mainSecondaryTextColor.withAlphaComponent(0.5), fileDurationColor: mainSecondaryTextColor.withAlphaComponent(0.5), mediaPlaceholderColor: accentColor.withMultiplied(hue: 1.019, saturation: 0.585, brightness: 0.23), polls: PresentationThemeChatBubblePolls(radioButton: accentColor.withMultiplied(hue: 0.995, saturation: 0.317, brightness: 0.51), radioProgress: accentColor, highlight: accentColor.withAlphaComponent(0.12), separator: mainSeparatorColor, bar: accentColor, barIconForeground: .white, barPositive: UIColor(rgb: 0x00A700), barNegative: UIColor(rgb: 0xFE3824)), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: additionalBackgroundColor.withAlphaComponent(0.5), withoutWallpaper: additionalBackgroundColor.withAlphaComponent(0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: buttonStrokeColor), actionButtonsTextColor: PresentationThemeVariableColor(color: .white), textSelectionColor: accentColor.withAlphaComponent(0.2), textSelectionKnobColor: accentColor), + outgoing: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleFillColor, gradientFill: outgoingBubbleFillGradientColor, highlightedFill: highlightedOutgoingBubbleColor, stroke: outgoingBubbleFillColor, shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleFillColor, gradientFill: outgoingBubbleFillGradientColor, highlightedFill: highlightedOutgoingBubbleColor, stroke: outgoingBubbleFillColor, shadow: nil)), primaryTextColor: outgoingPrimaryTextColor, secondaryTextColor: outgoingSecondaryTextColor, linkTextColor: outgoingLinkTextColor, linkHighlightColor: UIColor.white.withAlphaComponent(0.5), scamColor: outgoingScamColor, textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: outgoingPrimaryTextColor, accentControlColor: outgoingPrimaryTextColor, accentControlDisabledColor: mainSecondaryTextColor.withAlphaComponent(0.5), mediaActiveControlColor: outgoingPrimaryTextColor, mediaInactiveControlColor: outgoingSecondaryTextColor, mediaControlInnerBackgroundColor: outgoingBubbleFillColor, pendingActivityColor: outgoingSecondaryTextColor, fileTitleColor: outgoingPrimaryTextColor, fileDescriptionColor: outgoingSecondaryTextColor, fileDurationColor: outgoingSecondaryTextColor, mediaPlaceholderColor: accentColor.withMultiplied(hue: 1.019, saturation: 0.804, brightness: 0.51), polls: PresentationThemeChatBubblePolls(radioButton: outgoingPrimaryTextColor, radioProgress: accentColor.withMultiplied(hue: 0.99, saturation: 0.56, brightness: 1.0), highlight: accentColor.withMultiplied(hue: 0.99, saturation: 0.56, brightness: 1.0).withAlphaComponent(0.12), separator: mainSeparatorColor, bar: outgoingPrimaryTextColor, barIconForeground: .clear, barPositive: outgoingPrimaryTextColor, barNegative: outgoingPrimaryTextColor), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: additionalBackgroundColor.withAlphaComponent(0.5), withoutWallpaper: additionalBackgroundColor.withAlphaComponent(0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: buttonStrokeColor), actionButtonsTextColor: PresentationThemeVariableColor(color: .white), textSelectionColor: UIColor.white.withAlphaComponent(0.2), textSelectionKnobColor: UIColor.white), + freeform: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: mainBackgroundColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor, shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: mainBackgroundColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor, shadow: nil)), infoPrimaryTextColor: UIColor(rgb: 0xffffff), infoLinkTextColor: accentColor, outgoingCheckColor: outgoingCheckColor, diff --git a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift index ce28633511..d18947cb4d 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift @@ -487,7 +487,7 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio let message = PresentationThemeChatMessage( incoming: PresentationThemePartedColors( - bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xffffff), highlightedFill: UIColor(rgb: 0xd9f4ff), stroke: bubbleStrokeColor), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xffffff), highlightedFill: UIColor(rgb: 0xd9f4ff), stroke: bubbleStrokeColor)), + bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xffffff), highlightedFill: UIColor(rgb: 0xd9f4ff), stroke: bubbleStrokeColor, shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xffffff), highlightedFill: UIColor(rgb: 0xd9f4ff), stroke: bubbleStrokeColor, shadow: nil)), primaryTextColor: UIColor(rgb: 0x000000), secondaryTextColor: UIColor(rgb: 0x525252, alpha: 0.6), linkTextColor: UIColor(rgb: 0x004bad), @@ -509,7 +509,7 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: serviceBackgroundColor, withoutWallpaper: UIColor(rgb: 0x596e89, alpha: 0.35)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: .clear), actionButtonsTextColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xffffff)), textSelectionColor: UIColor(rgb: 0x007ee5, alpha: 0.2), textSelectionKnobColor: UIColor(rgb: 0x007ee5)), outgoing: PresentationThemePartedColors( - bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xe1ffc7), highlightedFill: UIColor(rgb: 0xc8ffa6), stroke: bubbleStrokeColor), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xe1ffc7), highlightedFill: UIColor(rgb: 0xc8ffa6), stroke: bubbleStrokeColor)), + bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xe1ffc7), highlightedFill: UIColor(rgb: 0xc8ffa6), stroke: bubbleStrokeColor, shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xe1ffc7), highlightedFill: UIColor(rgb: 0xc8ffa6), stroke: bubbleStrokeColor, shadow: nil)), primaryTextColor: UIColor(rgb: 0x000000), secondaryTextColor: UIColor(rgb: 0x008c09, alpha: 0.8), linkTextColor: UIColor(rgb: 0x004bad), @@ -533,7 +533,7 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio actionButtonsTextColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xffffff)), textSelectionColor: UIColor(rgb: 0xbbde9f), textSelectionKnobColor: UIColor(rgb: 0x3fc33b)), - freeform: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xffffff), highlightedFill: UIColor(rgb: 0xd9f4ff), stroke: UIColor(rgb: 0x86a9c9, alpha: 0.5)), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xffffff), highlightedFill: UIColor(rgb: 0xd9f4ff), stroke: UIColor(rgb: 0x86a9c9, alpha: 0.5))), + freeform: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xffffff), highlightedFill: UIColor(rgb: 0xd9f4ff), stroke: UIColor(rgb: 0x86a9c9, alpha: 0.5), shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xffffff), highlightedFill: UIColor(rgb: 0xd9f4ff), stroke: UIColor(rgb: 0x86a9c9, alpha: 0.5), shadow: nil)), infoPrimaryTextColor: UIColor(rgb: 0x000000), infoLinkTextColor: UIColor(rgb: 0x004bad), outgoingCheckColor: UIColor(rgb: 0x19c700), @@ -550,7 +550,7 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio let messageDay = PresentationThemeChatMessage( incoming: PresentationThemePartedColors( - bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xffffff), highlightedFill: UIColor(rgb: 0xdadade), stroke: UIColor(rgb: 0xffffff)), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xf1f1f4), highlightedFill: UIColor(rgb: 0xdadade), stroke: UIColor(rgb: 0xf1f1f4))), + bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xffffff), highlightedFill: UIColor(rgb: 0xdadade), stroke: UIColor(rgb: 0xffffff), shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xf1f1f4), highlightedFill: UIColor(rgb: 0xdadade), stroke: UIColor(rgb: 0xf1f1f4), shadow: nil)), primaryTextColor: UIColor(rgb: 0x000000), secondaryTextColor: UIColor(rgb: 0x525252, alpha: 0.6), linkTextColor: UIColor(rgb: 0x004bad), @@ -575,7 +575,7 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio textSelectionColor: UIColor(rgb: 0x007ee5, alpha: 0.3), textSelectionKnobColor: UIColor(rgb: 0x007ee5)), outgoing: PresentationThemePartedColors( - bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x57b2e0), gradientFill: UIColor(rgb: 0x007ee5), highlightedFill: UIColor(rgb: 0x57b2e0).withMultipliedBrightnessBy(0.7), stroke: .clear), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x57b2e0), gradientFill: UIColor(rgb: 0x007ee5), highlightedFill: UIColor(rgb: 0x57b2e0).withMultipliedBrightnessBy(0.7), stroke: .clear)), + bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x57b2e0), gradientFill: UIColor(rgb: 0x007ee5), highlightedFill: UIColor(rgb: 0x57b2e0).withMultipliedBrightnessBy(0.7), stroke: .clear, shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x57b2e0), gradientFill: UIColor(rgb: 0x007ee5), highlightedFill: UIColor(rgb: 0x57b2e0).withMultipliedBrightnessBy(0.7), stroke: .clear, shadow: nil)), primaryTextColor: UIColor(rgb: 0xffffff), secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.65), linkTextColor: UIColor(rgb: 0xffffff), @@ -599,7 +599,7 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio actionButtonsTextColor: PresentationThemeVariableColor(withWallpaper: UIColor(rgb: 0xffffff), withoutWallpaper: UIColor(rgb: 0x007ee5)), textSelectionColor: UIColor(rgb: 0xffffff, alpha: 0.2), textSelectionKnobColor: UIColor(rgb: 0xffffff)), - freeform: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xe5e5ea), highlightedFill: UIColor(rgb: 0xdadade), stroke: UIColor(rgb: 0xe5e5ea)), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xe5e5ea), highlightedFill: UIColor(rgb: 0xdadade), stroke: UIColor(rgb: 0xe5e5ea))), + freeform: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xe5e5ea), highlightedFill: UIColor(rgb: 0xdadade), stroke: UIColor(rgb: 0xe5e5ea), shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xe5e5ea), highlightedFill: UIColor(rgb: 0xdadade), stroke: UIColor(rgb: 0xe5e5ea), shadow: nil)), infoPrimaryTextColor: UIColor(rgb: 0x000000), infoLinkTextColor: UIColor(rgb: 0x004bad), outgoingCheckColor: UIColor(rgb: 0xffffff), diff --git a/submodules/TelegramPresentationData/Sources/PresentationTheme.swift b/submodules/TelegramPresentationData/Sources/PresentationTheme.swift index c20bc02c28..b5696e11e6 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationTheme.swift @@ -566,18 +566,18 @@ public final class PresentationThemeBubbleColorComponents { public let gradientFill: UIColor public let highlightedFill: UIColor public let stroke: UIColor - //public let shadow: PresentationThemeBubbleShadow? + public let shadow: PresentationThemeBubbleShadow? - public init(fill: UIColor, gradientFill: UIColor? = nil, highlightedFill: UIColor, stroke: UIColor/*, shadow: PresentationThemeBubbleShadow?*/) { + public init(fill: UIColor, gradientFill: UIColor? = nil, highlightedFill: UIColor, stroke: UIColor, shadow: PresentationThemeBubbleShadow?) { self.fill = fill self.gradientFill = gradientFill ?? fill self.highlightedFill = highlightedFill self.stroke = stroke - //self.shadow = shadow + self.shadow = shadow } public func withUpdated(fill: UIColor? = nil, gradientFill: UIColor? = nil, highlightedFill: UIColor? = nil, stroke: UIColor? = nil) -> PresentationThemeBubbleColorComponents { - return PresentationThemeBubbleColorComponents(fill: fill ?? self.fill, gradientFill: gradientFill ?? self.gradientFill, highlightedFill: highlightedFill ?? self.highlightedFill, stroke: stroke ?? self.stroke/*, shadow: self.shadow*/) + return PresentationThemeBubbleColorComponents(fill: fill ?? self.fill, gradientFill: gradientFill ?? self.gradientFill, highlightedFill: highlightedFill ?? self.highlightedFill, stroke: stroke ?? self.stroke, shadow: self.shadow) } } diff --git a/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift b/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift index 9ed40a2f67..18b7119106 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift @@ -990,16 +990,16 @@ extension PresentationThemeBubbleShadow: Codable { let values = try decoder.container(keyedBy: CodingKeys.self) self.init( color: try decodeColor(values, .color), - radius: try CGFloat(values.decode(Float.self, forKey: .radius)), - verticalOffset: try CGFloat(values.decode(Float.self, forKey: .verticalOffset)) + radius: try CGFloat(Double(truncating: values.decode(Decimal.self, forKey: .radius) as NSNumber)), + verticalOffset: try CGFloat(Double(truncating: values.decode(Decimal.self, forKey: .verticalOffset) as NSNumber)) ) } public func encode(to encoder: Encoder) throws { var values = encoder.container(keyedBy: CodingKeys.self) try encodeColor(&values, self.color, .color) - try values.encode(Float(self.radius), forKey: .radius) - try values.encode(Float(self.verticalOffset), forKey: .verticalOffset) + try values.encode(Decimal(Double(self.radius)), forKey: .radius) + try values.encode(Decimal(Double(self.verticalOffset)), forKey: .verticalOffset) } } @@ -1019,8 +1019,8 @@ extension PresentationThemeBubbleColorComponents: Codable { fill: try decodeColor(values, .bg), gradientFill: try decodeColor(values, .gradientBg, decoder: decoder, fallbackKey: codingPath + ".bg"), highlightedFill: try decodeColor(values, .highlightedBg), - stroke: try decodeColor(values, .stroke)//, - //shadow: try? values.decode(PresentationThemeBubbleShadow.self, forKey: .shadow) + stroke: try decodeColor(values, .stroke), + shadow: try? values.decode(PresentationThemeBubbleShadow.self, forKey: .shadow) ) } diff --git a/submodules/TelegramPresentationData/Sources/PresentationThemeCoder.swift b/submodules/TelegramPresentationData/Sources/PresentationThemeCoder.swift index 4bc3e519cf..6811a56333 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationThemeCoder.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationThemeCoder.swift @@ -928,7 +928,11 @@ extension PresentationThemeDecoding { fileprivate func unbox_(_ value: Any, as type: Decodable.Type) throws -> Any? { if type == Decimal.self || type == NSDecimalNumber.self { - return try self.unbox(value, as: Decimal.self) + if let value = value as? String { + return Decimal(string: value) + } else { + return try self.unbox(value, as: Decimal.self) + } } else if let stringKeyedDictType = type as? _YAMLStringDictionaryDecodableMarker.Type { return try self.unbox(value, as: stringKeyedDictType) } else { diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift index 5901a14934..7768affa08 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift @@ -497,8 +497,14 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode var bounds = strongSelf.bounds bounds.origin.x = offset strongSelf.bounds = bounds + + var shadowBounds = strongSelf.shadowNode.bounds + shadowBounds.origin.x = offset + strongSelf.shadowNode.bounds = shadowBounds + if animated { strongSelf.layer.animateBoundsOriginXAdditive(from: -offset, to: 0.0, duration: 0.1, mediaTimingFunction: CAMediaTimingFunction(name: .easeOut)) + strongSelf.shadowNode.layer.animateBoundsOriginXAdditive(from: -offset, to: 0.0, duration: 0.1, mediaTimingFunction: CAMediaTimingFunction(name: .easeOut)) } if let swipeToReplyNode = strongSelf.swipeToReplyNode { swipeToReplyNode.alpha = max(0.0, min(1.0, abs(offset / 40.0))) @@ -512,9 +518,18 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode let offset = bounds.origin.x bounds.origin.x = 0.0 strongSelf.bounds = bounds + + var shadowBounds = strongSelf.shadowNode.bounds + let shadowOffset = shadowBounds.origin.x + shadowBounds.origin.x = 0.0 + strongSelf.shadowNode.bounds = shadowBounds + if !offset.isZero { strongSelf.layer.animateBoundsOriginXAdditive(from: offset, to: 0.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionSpring) } + if !shadowOffset.isZero { + strongSelf.shadowNode.layer.animateBoundsOriginXAdditive(from: shadowOffset, to: 0.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionSpring) + } if let swipeToReplyNode = strongSelf.swipeToReplyNode { strongSelf.swipeToReplyNode = nil swipeToReplyNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak swipeToReplyNode] _ in @@ -565,9 +580,16 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode let offset = bounds.origin.x bounds.origin.x = 0.0 strongSelf.bounds = bounds + var shadowBounds = strongSelf.shadowNode.bounds + let shadowOffset = shadowBounds.origin.x + shadowBounds.origin.x = 0.0 + strongSelf.shadowNode.bounds = shadowBounds if !offset.isZero { strongSelf.layer.animateBoundsOriginXAdditive(from: offset, to: 0.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionSpring) } + if !shadowOffset.isZero { + strongSelf.shadowNode.layer.animateBoundsOriginXAdditive(from: shadowOffset, to: 0.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionSpring) + } if let swipeToReplyNode = strongSelf.swipeToReplyNode { strongSelf.swipeToReplyNode = nil swipeToReplyNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak swipeToReplyNode] _ in @@ -583,9 +605,16 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode let offset = bounds.origin.x bounds.origin.x = 0.0 strongSelf.bounds = bounds + var shadowBounds = strongSelf.shadowNode.bounds + let shadowOffset = shadowBounds.origin.x + shadowBounds.origin.x = 0.0 + strongSelf.shadowNode.bounds = shadowBounds if !offset.isZero { strongSelf.layer.animateBoundsOriginXAdditive(from: offset, to: 0.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionSpring) } + if !shadowOffset.isZero { + strongSelf.shadowNode.layer.animateBoundsOriginXAdditive(from: shadowOffset, to: 0.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionSpring) + } if let swipeToReplyNode = strongSelf.swipeToReplyNode { strongSelf.swipeToReplyNode = nil swipeToReplyNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak swipeToReplyNode] _ in @@ -2035,9 +2064,16 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode let offset = bounds.origin.x bounds.origin.x = 0.0 strongSelf.bounds = bounds + var shadowBounds = strongSelf.shadowNode.bounds + let shadowOffset = shadowBounds.origin.x + shadowBounds.origin.x = 0.0 + strongSelf.shadowNode.bounds = shadowBounds if !offset.isZero { strongSelf.layer.animateBoundsOriginXAdditive(from: offset, to: 0.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionSpring) } + if !shadowOffset.isZero { + strongSelf.shadowNode.layer.animateBoundsOriginXAdditive(from: shadowOffset, to: 0.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionSpring) + } if let swipeToReplyNode = strongSelf.swipeToReplyNode { strongSelf.swipeToReplyNode = nil swipeToReplyNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak swipeToReplyNode] _ in @@ -2843,6 +2879,9 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode var bounds = self.bounds bounds.origin.x = -translation.x self.bounds = bounds + var shadowBounds = self.shadowNode.bounds + shadowBounds.origin.x = -translation.x + self.shadowNode.bounds = shadowBounds if let swipeToReplyNode = self.swipeToReplyNode { swipeToReplyNode.frame = CGRect(origin: CGPoint(x: bounds.size.width, y: floor((self.contentSize.height - 33.0) / 2.0)), size: CGSize(width: 33.0, height: 33.0)) @@ -2866,7 +2905,12 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode let previousBounds = bounds bounds.origin.x = 0.0 self.bounds = bounds + var shadowBounds = self.shadowNode.bounds + let previousShadowBounds = shadowBounds + shadowBounds.origin.x = 0.0 + self.shadowNode.bounds = shadowBounds self.layer.animateBounds(from: previousBounds, to: bounds, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring) + self.shadowNode.layer.animateBounds(from: previousShadowBounds, to: shadowBounds, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring) if let swipeToReplyNode = self.swipeToReplyNode { self.swipeToReplyNode = nil swipeToReplyNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak swipeToReplyNode] _ in From bdc0bb21e7f81dd599271ec021e12c205d94a3c2 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Tue, 28 Jan 2020 16:27:54 +0400 Subject: [PATCH 33/50] Don't link HockeyApp --- submodules/TelegramUI/BUCK | 1 - submodules/TelegramUI/TelegramUI/AppDelegate.swift | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/submodules/TelegramUI/BUCK b/submodules/TelegramUI/BUCK index f705915c30..9a62dca17e 100644 --- a/submodules/TelegramUI/BUCK +++ b/submodules/TelegramUI/BUCK @@ -47,7 +47,6 @@ framework( "//submodules/DeviceAccess:DeviceAccess", "//submodules/WatchCommon/Host:WatchCommon", "//submodules/LightweightAccountData:LightweightAccountData", - "//submodules/HockeySDK-iOS:HockeySDK", "//submodules/BuildConfig:BuildConfig", "//submodules/BuildConfigExtra:BuildConfigExtra", "//submodules/rlottie:RLottieBinding", diff --git a/submodules/TelegramUI/TelegramUI/AppDelegate.swift b/submodules/TelegramUI/TelegramUI/AppDelegate.swift index 5fd24a884e..02bcf8dd75 100644 --- a/submodules/TelegramUI/TelegramUI/AppDelegate.swift +++ b/submodules/TelegramUI/TelegramUI/AppDelegate.swift @@ -5,7 +5,7 @@ import TelegramCore import SyncCore import UserNotifications import Intents -import HockeySDK +//import HockeySDK import Postbox import PushKit import AsyncDisplayKit @@ -157,7 +157,7 @@ final class SharedApplicationContext { } } -@objc(AppDelegate) class AppDelegate: UIResponder, UIApplicationDelegate, PKPushRegistryDelegate, BITHockeyManagerDelegate, UNUserNotificationCenterDelegate, UIAlertViewDelegate { +@objc(AppDelegate) class AppDelegate: UIResponder, UIApplicationDelegate, PKPushRegistryDelegate/*, BITHockeyManagerDelegate*/, UNUserNotificationCenterDelegate, UIAlertViewDelegate { @objc var window: UIWindow? var nativeWindow: (UIWindow & WindowHost)? var mainWindow: Window1! @@ -1338,7 +1338,7 @@ final class SharedApplicationContext { self.isActivePromise.set(true) } - BITHockeyBaseManager.setPresentAlert({ [weak self] alert in + /*BITHockeyBaseManager.setPresentAlert({ [weak self] alert in if let strongSelf = self, let alert = alert { var actions: [TextAlertAction] = [] for action in alert.actions { @@ -1376,7 +1376,7 @@ final class SharedApplicationContext { #else BITHockeyManager.shared().authenticator.authenticateInstallation() #endif - } + }*/ if UIApplication.shared.isStatusBarHidden { UIApplication.shared.setStatusBarHidden(false, with: .none) From 5112310a32199b0160b45cb7ff8e76a39d8e4ef1 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Tue, 28 Jan 2020 16:28:41 +0400 Subject: [PATCH 34/50] Send forwarded messages in groups --- .../Sources/PendingMessageManager.swift | 61 ++++++++++++++++--- .../PendingMessageUploadedContent.swift | 28 ++++++--- 2 files changed, 74 insertions(+), 15 deletions(-) diff --git a/submodules/TelegramCore/Sources/PendingMessageManager.swift b/submodules/TelegramCore/Sources/PendingMessageManager.swift index 3a4a3054b7..cb35a4dccd 100644 --- a/submodules/TelegramCore/Sources/PendingMessageManager.swift +++ b/submodules/TelegramCore/Sources/PendingMessageManager.swift @@ -355,6 +355,8 @@ public final class PendingMessageManager { strongSelf.collectUploadingInfo(messageContext: messageContext, message: message) } + var messagesToUpload: [(PendingMessageContext, Message, PendingMessageUploadedContentType, Signal)] = [] + var messagesToForward: [PeerIdAndNamespace: [(PendingMessageContext, Message, ForwardSourceInfoAttribute)]] = [:] for (messageContext, _) in strongSelf.messageContexts.values.compactMap({ messageContext -> (PendingMessageContext, Message)? in if case let .collectingInfo(message) = messageContext.state { return (messageContext, message) @@ -365,16 +367,58 @@ public final class PendingMessageManager { return lhs.1.index < rhs.1.index }) { if case let .collectingInfo(message) = messageContext.state { - let (contentUploadSignal, contentType) = messageContentToUpload(network: strongSelf.network, postbox: strongSelf.postbox, auxiliaryMethods: strongSelf.auxiliaryMethods, transformOutgoingMessageMedia: strongSelf.transformOutgoingMessageMedia, messageMediaPreuploadManager: strongSelf.messageMediaPreuploadManager, revalidationContext: strongSelf.revalidationContext, forceReupload: messageContext.forcedReuploadOnce, isGrouped: message.groupingKey != nil, message: message) - messageContext.contentType = contentType - - if strongSelf.canBeginUploadingMessage(id: message.id, type: contentType) { - strongSelf.beginUploadingMessage(messageContext: messageContext, id: message.id, groupId: message.groupingKey, uploadSignal: contentUploadSignal) - } else { - messageContext.state = .waitingForUploadToStart(groupId: message.groupingKey, upload: contentUploadSignal) + let contentToUpload = messageContentToUpload(network: strongSelf.network, postbox: strongSelf.postbox, auxiliaryMethods: strongSelf.auxiliaryMethods, transformOutgoingMessageMedia: strongSelf.transformOutgoingMessageMedia, messageMediaPreuploadManager: strongSelf.messageMediaPreuploadManager, revalidationContext: strongSelf.revalidationContext, forceReupload: messageContext.forcedReuploadOnce, isGrouped: message.groupingKey != nil, message: message) + messageContext.contentType = contentToUpload.type + switch contentToUpload { + case let .immediate(result, type): + var isForward = false + switch result { + case let .content(content): + switch content.content { + case let .forward(forwardInfo): + isForward = true + let peerIdAndNamespace = PeerIdAndNamespace(peerId: message.id.peerId, namespace: message.id.namespace) + if messagesToForward[peerIdAndNamespace] == nil { + messagesToForward[peerIdAndNamespace] = [] + } + messagesToForward[peerIdAndNamespace]!.append((messageContext, message, forwardInfo)) + default: + break + } + default: + break + } + if !isForward { + messagesToUpload.append((messageContext, message, type, .single(result))) + } + case let .signal(signal, type): + messagesToUpload.append((messageContext, message, type, signal)) } } } + + for (messageContext, message, type, contentUploadSignal) in messagesToUpload { + if strongSelf.canBeginUploadingMessage(id: message.id, type: type) { + strongSelf.beginUploadingMessage(messageContext: messageContext, id: message.id, groupId: message.groupingKey, uploadSignal: contentUploadSignal) + } else { + messageContext.state = .waitingForUploadToStart(groupId: message.groupingKey, upload: contentUploadSignal) + } + } + + for (_, messages) in messagesToForward { + for (context, _, _) in messages { + context.state = .sending(groupId: nil) + } + let sendMessage: Signal = strongSelf.sendGroupMessagesContent(network: strongSelf.network, postbox: strongSelf.postbox, stateManager: strongSelf.stateManager, group: messages.map { data in + let (_, message, forwardInfo) = data + return (message.id, PendingMessageUploadedContentAndReuploadInfo(content: .forward(forwardInfo), reuploadInfo: nil)) + }) + |> map { next -> PendingMessageResult in + return .progress(1.0) + } + messages[0].0.sendDisposable.set((sendMessage + |> deliverOn(strongSelf.queue)).start()) + } } })) } @@ -502,7 +546,8 @@ public final class PendingMessageManager { } } return .complete() - }).start(next: { [weak self] next in + } + |> deliverOn(queue)).start(next: { [weak self] next in if let strongSelf = self { assert(strongSelf.queue.isCurrent()) diff --git a/submodules/TelegramCore/Sources/PendingMessageUploadedContent.swift b/submodules/TelegramCore/Sources/PendingMessageUploadedContent.swift index 6715783a15..e808ed503f 100644 --- a/submodules/TelegramCore/Sources/PendingMessageUploadedContent.swift +++ b/submodules/TelegramCore/Sources/PendingMessageUploadedContent.swift @@ -38,11 +38,25 @@ enum PendingMessageUploadError { case generic } -func messageContentToUpload(network: Network, postbox: Postbox, auxiliaryMethods: AccountAuxiliaryMethods, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, messageMediaPreuploadManager: MessageMediaPreuploadManager, revalidationContext: MediaReferenceRevalidationContext, forceReupload: Bool, isGrouped: Bool, message: Message) -> (Signal, PendingMessageUploadedContentType) { +enum MessageContentToUpload { + case signal(Signal, PendingMessageUploadedContentType) + case immediate(PendingMessageUploadedContentResult, PendingMessageUploadedContentType) + + var type: PendingMessageUploadedContentType { + switch self { + case let .signal(_, type): + return type + case let .immediate(_, type): + return type + } + } +} + +func messageContentToUpload(network: Network, postbox: Postbox, auxiliaryMethods: AccountAuxiliaryMethods, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, messageMediaPreuploadManager: MessageMediaPreuploadManager, revalidationContext: MediaReferenceRevalidationContext, forceReupload: Bool, isGrouped: Bool, message: Message) -> MessageContentToUpload { return messageContentToUpload(network: network, postbox: postbox, auxiliaryMethods: auxiliaryMethods, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, revalidationContext: revalidationContext, forceReupload: forceReupload, isGrouped: isGrouped, peerId: message.id.peerId, messageId: message.id, attributes: message.attributes, text: message.text, media: message.media) } -func messageContentToUpload(network: Network, postbox: Postbox, auxiliaryMethods: AccountAuxiliaryMethods, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, messageMediaPreuploadManager: MessageMediaPreuploadManager, revalidationContext: MediaReferenceRevalidationContext, forceReupload: Bool, isGrouped: Bool, peerId: PeerId, messageId: MessageId?, attributes: [MessageAttribute], text: String, media: [Media]) -> (Signal, PendingMessageUploadedContentType) { +func messageContentToUpload(network: Network, postbox: Postbox, auxiliaryMethods: AccountAuxiliaryMethods, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, messageMediaPreuploadManager: MessageMediaPreuploadManager, revalidationContext: MediaReferenceRevalidationContext, forceReupload: Bool, isGrouped: Bool, peerId: PeerId, messageId: MessageId?, attributes: [MessageAttribute], text: String, media: [Media]) -> MessageContentToUpload { var contextResult: OutgoingChatContextResultMessageAttribute? var autoremoveAttribute: AutoremoveTimeoutMessageAttribute? for attribute in attributes { @@ -65,15 +79,15 @@ func messageContentToUpload(network: Network, postbox: Postbox, auxiliaryMethods } if let media = media.first as? TelegramMediaAction, media.action == .historyScreenshot { - return (.single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .messageScreenshot, reuploadInfo: nil))), .none) + return .immediate(.content(PendingMessageUploadedContentAndReuploadInfo(content: .messageScreenshot, reuploadInfo: nil)), .none) } else if let forwardInfo = forwardInfo { - return (.single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .forward(forwardInfo), reuploadInfo: nil))), .text) + return .immediate(.content(PendingMessageUploadedContentAndReuploadInfo(content: .forward(forwardInfo), reuploadInfo: nil)), .text) } else if let contextResult = contextResult { - return (.single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .chatContextResult(contextResult), reuploadInfo: nil))), .text) + return .immediate(.content(PendingMessageUploadedContentAndReuploadInfo(content: .chatContextResult(contextResult), reuploadInfo: nil)), .text) } else if let media = media.first, let mediaResult = mediaContentToUpload(network: network, postbox: postbox, auxiliaryMethods: auxiliaryMethods, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, revalidationContext: revalidationContext, forceReupload: forceReupload, isGrouped: isGrouped, peerId: peerId, media: media, text: text, autoremoveAttribute: autoremoveAttribute, messageId: messageId, attributes: attributes) { - return (mediaResult, .media) + return .signal(mediaResult, .media) } else { - return (.single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .text(text), reuploadInfo: nil))), .text) + return .signal(.single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .text(text), reuploadInfo: nil))), .text) } } From 309a8b112b2ad69a153c2425df85522d4b0874bf Mon Sep 17 00:00:00 2001 From: Ali <> Date: Tue, 28 Jan 2020 16:29:00 +0400 Subject: [PATCH 35/50] Experimental chat list filtering --- .../InAppNotificationSettings.swift | 23 +- NotificationService/Namespaces.swift | 42 +- NotificationService/Sync.swift | 12 +- .../Sources/ChatListController.swift | 41 +- .../ChatListFilterPresetController.swift | 387 +++++++++++++++ .../ChatListFilterPresetListController.swift | 212 +++++++++ .../ChatListFilterPresetListItem.swift | 439 ++++++++++++++++++ .../Sources/Node/ChatListNode.swift | 9 +- .../Sources/Node/ChatListNodeLocation.swift | 72 +-- .../Sources/Node/ChatListViewTransition.swift | 3 +- .../TabBarChatListFilterController.swift | 316 +++++++++++-- submodules/Postbox/Sources/ChatListView.swift | 12 +- .../Sources/MessageHistoryViewState.swift | 11 +- submodules/Postbox/Sources/Postbox.swift | 20 +- .../NotificationsAndSounds.swift | 62 ++- submodules/SyncCore/Sources/Namespaces.swift | 40 +- .../StandaloneAccountTransaction.swift | 33 +- .../Sources/AccountViewTracker.swift | 4 +- .../TelegramUI/DeclareEncodables.swift | 1 + .../Sources/ChatListFilterSettings.swift | 127 +++++ .../Sources/InAppNotificationSettings.swift | 24 +- .../Sources/PostboxKeys.swift | 2 + 22 files changed, 1752 insertions(+), 140 deletions(-) create mode 100644 submodules/ChatListUI/Sources/ChatListFilterPresetController.swift create mode 100644 submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift create mode 100644 submodules/ChatListUI/Sources/ChatListFilterPresetListItem.swift create mode 100644 submodules/TelegramUIPreferences/Sources/ChatListFilterSettings.swift diff --git a/NotificationService/InAppNotificationSettings.swift b/NotificationService/InAppNotificationSettings.swift index a5f3ce36cc..ea6e849c8f 100644 --- a/NotificationService/InAppNotificationSettings.swift +++ b/NotificationService/InAppNotificationSettings.swift @@ -40,7 +40,7 @@ public struct InAppNotificationSettings: PreferencesEntry, Equatable { public var displayNotificationsFromAllAccounts: Bool public static var defaultSettings: InAppNotificationSettings { - return InAppNotificationSettings(playSounds: true, vibrate: false, displayPreviews: true, totalUnreadCountDisplayStyle: .filtered, totalUnreadCountDisplayCategory: .messages, totalUnreadCountIncludeTags: [.regularChatsAndPrivateGroups], displayNameOnLockscreen: true, displayNotificationsFromAllAccounts: true) + return InAppNotificationSettings(playSounds: true, vibrate: false, displayPreviews: true, totalUnreadCountDisplayStyle: .filtered, totalUnreadCountDisplayCategory: .messages, totalUnreadCountIncludeTags: [.privateChat, .secretChat, .bot, .privateGroup], displayNameOnLockscreen: true, displayNotificationsFromAllAccounts: true) } public init(playSounds: Bool, vibrate: Bool, displayPreviews: Bool, totalUnreadCountDisplayStyle: TotalUnreadCountDisplayStyle, totalUnreadCountDisplayCategory: TotalUnreadCountDisplayCategory, totalUnreadCountIncludeTags: PeerSummaryCounterTags, displayNameOnLockscreen: Bool, displayNotificationsFromAllAccounts: Bool) { @@ -60,10 +60,25 @@ public struct InAppNotificationSettings: PreferencesEntry, Equatable { self.displayPreviews = decoder.decodeInt32ForKey("p", orElse: 0) != 0 self.totalUnreadCountDisplayStyle = TotalUnreadCountDisplayStyle(rawValue: decoder.decodeInt32ForKey("cds", orElse: 0)) ?? .filtered self.totalUnreadCountDisplayCategory = TotalUnreadCountDisplayCategory(rawValue: decoder.decodeInt32ForKey("totalUnreadCountDisplayCategory", orElse: 1)) ?? .messages - if let value = decoder.decodeOptionalInt32ForKey("totalUnreadCountIncludeTags") { + if let value = decoder.decodeOptionalInt32ForKey("totalUnreadCountIncludeTags_2") { self.totalUnreadCountIncludeTags = PeerSummaryCounterTags(rawValue: value) + } else if let value = decoder.decodeOptionalInt32ForKey("totalUnreadCountIncludeTags") { + var resultTags: PeerSummaryCounterTags = [] + for legacyTag in LegacyPeerSummaryCounterTags(rawValue: value) { + if legacyTag == .regularChatsAndPrivateGroups { + resultTags.insert(.privateChat) + resultTags.insert(.secretChat) + resultTags.insert(.bot) + resultTags.insert(.privateGroup) + } else if legacyTag == .publicGroups { + resultTags.insert(.publicGroup) + } else if legacyTag == .channels { + resultTags.insert(.channel) + } + } + self.totalUnreadCountIncludeTags = resultTags } else { - self.totalUnreadCountIncludeTags = [.regularChatsAndPrivateGroups] + self.totalUnreadCountIncludeTags = [.privateChat, .secretChat, .bot, .privateGroup] } self.displayNameOnLockscreen = decoder.decodeInt32ForKey("displayNameOnLockscreen", orElse: 1) != 0 self.displayNotificationsFromAllAccounts = decoder.decodeInt32ForKey("displayNotificationsFromAllAccounts", orElse: 1) != 0 @@ -75,7 +90,7 @@ public struct InAppNotificationSettings: PreferencesEntry, Equatable { encoder.encodeInt32(self.displayPreviews ? 1 : 0, forKey: "p") encoder.encodeInt32(self.totalUnreadCountDisplayStyle.rawValue, forKey: "cds") encoder.encodeInt32(self.totalUnreadCountDisplayCategory.rawValue, forKey: "totalUnreadCountDisplayCategory") - encoder.encodeInt32(self.totalUnreadCountIncludeTags.rawValue, forKey: "totalUnreadCountIncludeTags") + encoder.encodeInt32(self.totalUnreadCountIncludeTags.rawValue, forKey: "totalUnreadCountIncludeTags_2") encoder.encodeInt32(self.displayNameOnLockscreen ? 1 : 0, forKey: "displayNameOnLockscreen") encoder.encodeInt32(self.displayNotificationsFromAllAccounts ? 1 : 0, forKey: "displayNotificationsFromAllAccounts") } diff --git a/NotificationService/Namespaces.swift b/NotificationService/Namespaces.swift index b60b7ff89a..d8aed1ec40 100644 --- a/NotificationService/Namespaces.swift +++ b/NotificationService/Namespaces.swift @@ -1,9 +1,43 @@ import PostboxDataTypes +struct LegacyPeerSummaryCounterTags: OptionSet, Sequence, Hashable { + var rawValue: Int32 + + init(rawValue: Int32) { + self.rawValue = rawValue + } + + static let regularChatsAndPrivateGroups = LegacyPeerSummaryCounterTags(rawValue: 1 << 0) + static let publicGroups = LegacyPeerSummaryCounterTags(rawValue: 1 << 1) + static let channels = LegacyPeerSummaryCounterTags(rawValue: 1 << 2) + + public func makeIterator() -> AnyIterator { + var index = 0 + return AnyIterator { () -> LegacyPeerSummaryCounterTags? in + while index < 31 { + let currentTags = self.rawValue >> UInt32(index) + let tag = LegacyPeerSummaryCounterTags(rawValue: 1 << UInt32(index)) + index += 1 + if currentTags == 0 { + break + } + + if (currentTags & 1) != 0 { + return tag + } + } + return nil + } + } +} + extension PeerSummaryCounterTags { - static let regularChatsAndPrivateGroups = PeerSummaryCounterTags(rawValue: 1 << 0) - static let publicGroups = PeerSummaryCounterTags(rawValue: 1 << 1) - static let channels = PeerSummaryCounterTags(rawValue: 1 << 2) + static let privateChat = PeerSummaryCounterTags(rawValue: 1 << 3) + static let secretChat = PeerSummaryCounterTags(rawValue: 1 << 4) + static let privateGroup = PeerSummaryCounterTags(rawValue: 1 << 5) + static let bot = PeerSummaryCounterTags(rawValue: 1 << 6) + static let channel = PeerSummaryCounterTags(rawValue: 1 << 7) + static let publicGroup = PeerSummaryCounterTags(rawValue: 1 << 8) } struct Namespaces { @@ -17,4 +51,4 @@ struct Namespaces { static let CloudChannel: Int32 = 2 static let SecretChat: Int32 = 3 } -} \ No newline at end of file +} diff --git a/NotificationService/Sync.swift b/NotificationService/Sync.swift index 21a93f439b..26fdd95d42 100644 --- a/NotificationService/Sync.swift +++ b/NotificationService/Sync.swift @@ -94,19 +94,21 @@ enum SyncProviderImpl { if let channel = peerTable.get(peerId) as? TelegramChannel { switch channel.info { case .broadcast: - tag = .channels + tag = .channel case .group: if channel.username != nil { - tag = .publicGroups + tag = .publicGroup } else { - tag = .regularChatsAndPrivateGroups + tag = .privateGroup } } } else { - tag = .channels + tag = .channel } + } else if peerId.namespace == Namespaces.Peer.CloudGroup { + tag = .privateGroup } else { - tag = .regularChatsAndPrivateGroups + tag = .privateChat } var totalCount: Int32 = -1 diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 44110de78e..e86ca39607 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -261,11 +261,28 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, } if !self.hideNetworkActivityStatus { - self.titleDisposable = combineLatest(queue: .mainQueue(), context.account.networkState, hasProxy, passcode, self.chatListDisplayNode.chatListNode.state).start(next: { [weak self] networkState, proxy, passcode, state in + self.titleDisposable = combineLatest(queue: .mainQueue(), + context.account.networkState, + hasProxy, + passcode, + self.chatListDisplayNode.chatListNode.state, + self.chatListDisplayNode.chatListNode.chatListFilterSignal + ).start(next: { [weak self] networkState, proxy, passcode, state, chatListFilter in if let strongSelf = self { let defaultTitle: String if case .root = strongSelf.groupId { - defaultTitle = strongSelf.presentationData.strings.DialogList_Title + if let chatListFilter = chatListFilter { + let title: String + switch chatListFilter.name { + case .unread: + title = "Unread" + case let .custom(value): + title = value + } + defaultTitle = title + } else { + defaultTitle = strongSelf.presentationData.strings.DialogList_Title + } } else { defaultTitle = strongSelf.presentationData.strings.ChatList_ArchivedChatsTitle } @@ -1793,13 +1810,27 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, public func presentTabBarPreviewingController(sourceNodes: [ASDisplayNode]) { if self.isNodeLoaded { - let controller = TabBarChatListFilterController(context: self.context, sourceNodes: sourceNodes, currentFilter: self.chatListDisplayNode.chatListNode.chatListFilter, updateFilter: { [weak self] value in + let _ = (self.context.account.postbox.transaction { transaction -> [ChatListFilterPreset] in + let settings = transaction.getPreferencesEntry(key: ApplicationSpecificPreferencesKeys.chatListFilterSettings) as? ChatListFilterSettings ?? ChatListFilterSettings.default + return settings.presets + } + |> deliverOnMainQueue).start(next: { [weak self] presetList in guard let strongSelf = self else { return } - strongSelf.chatListDisplayNode.chatListNode.chatListFilter = value + let controller = TabBarChatListFilterController(context: strongSelf.context, sourceNodes: sourceNodes, presetList: presetList, currentPreset: strongSelf.chatListDisplayNode.chatListNode.chatListFilter, setup: { + guard let strongSelf = self else { + return + } + strongSelf.push(chatListFilterPresetListController(context: strongSelf.context)) + }, updatePreset: { value in + guard let strongSelf = self else { + return + } + strongSelf.chatListDisplayNode.chatListNode.chatListFilter = value + }) + strongSelf.context.sharedContext.mainWindow?.present(controller, on: .root) }) - self.context.sharedContext.mainWindow?.present(controller, on: .root) } } diff --git a/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift b/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift new file mode 100644 index 0000000000..4599784653 --- /dev/null +++ b/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift @@ -0,0 +1,387 @@ +import Foundation +import UIKit +import Display +import SwiftSignalKit +import Postbox +import TelegramCore +import SyncCore +import TelegramPresentationData +import ItemListUI +import PresentationDataUtils +import AccountContext +import TelegramUIPreferences +import ItemListPeerItem +import ItemListPeerActionItem + +private final class ChatListFilterPresetControllerArguments { + let context: AccountContext + let updateState: ((ChatListFilterPresetControllerState) -> ChatListFilterPresetControllerState) -> Void + let openAddPeer: () -> Void + let deleteAdditionalPeer: (PeerId) -> Void + let setPeerIdWithRevealedOptions: (PeerId?, PeerId?) -> Void + + init(context: AccountContext, updateState: @escaping ((ChatListFilterPresetControllerState) -> ChatListFilterPresetControllerState) -> Void, openAddPeer: @escaping () -> Void, deleteAdditionalPeer: @escaping (PeerId) -> Void, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void) { + self.context = context + self.updateState = updateState + self.openAddPeer = openAddPeer + self.deleteAdditionalPeer = deleteAdditionalPeer + self.setPeerIdWithRevealedOptions = setPeerIdWithRevealedOptions + } +} + +private enum ChatListFilterPresetControllerSection: Int32 { + case name + case categories + case excludeCategories + case additionalPeers +} + +private func filterEntry(presentationData: ItemListPresentationData, arguments: ChatListFilterPresetControllerArguments, title: String, value: Bool, filter: ChatListIncludeCategoryFilter, section: Int32) -> ItemListCheckboxItem { + return ItemListCheckboxItem(presentationData: presentationData, title: title, style: .left, checked: value, zeroSeparatorInsets: false, sectionId: section, action: { + arguments.updateState { current in + var state = current + if state.includeCategories.contains(filter) { + state.includeCategories.remove(filter) + } else { + state.includeCategories.insert(filter) + } + return state + } + }) +} + +private enum ChatListFilterPresetEntryStableId: Hashable { + case index(Int) + case peer(PeerId) +} + +private enum ChatListFilterPresetEntry: ItemListNodeEntry { + case name(placeholder: String, value: String) + case filterPrivateChats(title: String, value: Bool) + case filterSecretChats(title: String, value: Bool) + case filterPrivateGroups(title: String, value: Bool) + case filterBots(title: String, value: Bool) + case filterPublicGroups(title: String, value: Bool) + case filterChannels(title: String, value: Bool) + case filterMuted(title: String, value: Bool) + case filterRead(title: String, value: Bool) + case additionalPeersHeader(String) + case addAdditionalPeer(title: String) + case additionalPeer(index: Int, peer: RenderedPeer, isRevealed: Bool) + + var section: ItemListSectionId { + switch self { + case .name: + return ChatListFilterPresetControllerSection.name.rawValue + case .filterPrivateChats, .filterSecretChats, .filterPrivateGroups, .filterBots, .filterPublicGroups, .filterChannels: + return ChatListFilterPresetControllerSection.categories.rawValue + case .filterMuted, .filterRead: + return ChatListFilterPresetControllerSection.excludeCategories.rawValue + case .additionalPeersHeader, .addAdditionalPeer, .additionalPeer: + return ChatListFilterPresetControllerSection.additionalPeers.rawValue + } + } + + var stableId: ChatListFilterPresetEntryStableId { + switch self { + case .name: + return .index(0) + case .filterPrivateChats: + return .index(1) + case .filterSecretChats: + return .index(2) + case .filterPrivateGroups: + return .index(3) + case .filterBots: + return .index(4) + case .filterPublicGroups: + return .index(5) + case .filterChannels: + return .index(6) + case .filterMuted: + return .index(7) + case .filterRead: + return .index(8) + case .additionalPeersHeader: + return .index(9) + case .addAdditionalPeer: + return .index(10) + case let .additionalPeer(additionalPeer): + return .peer(additionalPeer.peer.peerId) + } + } + + static func <(lhs: ChatListFilterPresetEntry, rhs: ChatListFilterPresetEntry) -> Bool { + switch lhs.stableId { + case let .index(lhsIndex): + switch rhs.stableId { + case let .index(rhsIndex): + return lhsIndex < rhsIndex + case .peer: + return true + } + case .peer: + switch lhs { + case let .additionalPeer(lhsIndex, _, _): + switch rhs.stableId { + case .index: + return false + case .peer: + switch rhs { + case let .additionalPeer(rhsIndex, _, _): + return lhsIndex < rhsIndex + default: + preconditionFailure() + } + } + default: + preconditionFailure() + } + } + } + + func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem { + let arguments = arguments as! ChatListFilterPresetControllerArguments + switch self { + case let .name(placeholder, value): + return ItemListSingleLineInputItem(presentationData: presentationData, title: NSAttributedString(), text: value, placeholder: placeholder, type: .regular(capitalization: true, autocorrection: false), sectionId: self.section, textUpdated: { value in + arguments.updateState { current in + var state = current + state.name = value + return state + } + }, action: {}) + case let .filterPrivateChats(title, value): + return filterEntry(presentationData: presentationData, arguments: arguments, title: title, value: value, filter: .privateChats, section: self.section) + case let .filterSecretChats(title, value): + return filterEntry(presentationData: presentationData, arguments: arguments, title: title, value: value, filter: .secretChats, section: self.section) + case let .filterPrivateGroups(title, value): + return filterEntry(presentationData: presentationData, arguments: arguments, title: title, value: value, filter: .privateGroups, section: self.section) + case let .filterBots(title, value): + return filterEntry(presentationData: presentationData, arguments: arguments, title: title, value: value, filter: .bots, section: self.section) + case let .filterPublicGroups(title, value): + return filterEntry(presentationData: presentationData, arguments: arguments, title: title, value: value, filter: .publicGroups, section: self.section) + case let .filterChannels(title, value): + return filterEntry(presentationData: presentationData, arguments: arguments, title: title, value: value, filter: .channels, section: self.section) + case let .filterMuted(title, value): + return ItemListSwitchItem(presentationData: presentationData, title: title, value: value, sectionId: self.section, style: .blocks, updated: { _ in + arguments.updateState { current in + var state = current + if state.includeCategories.contains(.muted) { + state.includeCategories.remove(.muted) + } else { + state.includeCategories.insert(.muted) + } + return state + } + }) + case let .filterRead(title, value): + return ItemListSwitchItem(presentationData: presentationData, title: title, value: value, sectionId: self.section, style: .blocks, updated: { _ in + arguments.updateState { current in + var state = current + if state.includeCategories.contains(.read) { + state.includeCategories.remove(.read) + } else { + state.includeCategories.insert(.read) + } + return state + } + }) + case let .additionalPeersHeader(title): + return ItemListSectionHeaderItem(presentationData: presentationData, text: title, sectionId: self.section) + case let .addAdditionalPeer(title): + return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.addPersonIcon(presentationData.theme), title: title, alwaysPlain: false, sectionId: self.section, height: .peerList, editing: false, action: { + arguments.openAddPeer() + }) + case let .additionalPeer(title, peer, isRevealed): + return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: PresentationDateTimeFormat(timeFormat: .regular, dateFormat: .monthFirst, dateSeparator: ".", decimalSeparator: ".", groupingSeparator: "."), nameDisplayOrder: .firstLast, context: arguments.context, peer: peer.chatMainPeer!, height: .peerList, presence: nil, text: .none, label: .none, editing: ItemListPeerItemEditing(editable: true, editing: false, revealed: isRevealed), revealOptions: ItemListPeerItemRevealOptions(options: [ItemListPeerItemRevealOption(type: .destructive, title: presentationData.strings.Common_Delete, action: { + arguments.deleteAdditionalPeer(peer.peerId) + })]), switchValue: nil, enabled: true, selectable: false, sectionId: self.section, action: nil, setPeerIdWithRevealedOptions: { lhs, rhs in + arguments.setPeerIdWithRevealedOptions(lhs, rhs) + }, removePeer: { id in + arguments.deleteAdditionalPeer(id) + }) + } + } +} + +private struct ChatListFilterPresetControllerState: Equatable { + var name: String + var includeCategories: ChatListIncludeCategoryFilter + var additionallyIncludePeers: [PeerId] + + var revealedPeerId: PeerId? + + var isComplete: Bool { + if self.name.isEmpty { + return false + } + if self.includeCategories.isEmpty && self.additionallyIncludePeers.isEmpty { + return false + } + return true + } +} + +private func chatListFilterPresetControllerEntries(presentationData: PresentationData, state: ChatListFilterPresetControllerState, peers: [RenderedPeer]) -> [ChatListFilterPresetEntry] { + var entries: [ChatListFilterPresetEntry] = [] + + entries.append(.name(placeholder: "Preset Name", value: state.name)) + + entries.append(.filterPrivateChats(title: "Private Chats", value: state.includeCategories.contains(.privateChats))) + entries.append(.filterSecretChats(title: "Secret Chats", value: state.includeCategories.contains(.secretChats))) + entries.append(.filterPrivateGroups(title: "Private Groups", value: state.includeCategories.contains(.privateGroups))) + entries.append(.filterBots(title: "Bots", value: state.includeCategories.contains(.bots))) + entries.append(.filterPublicGroups(title: "Public Groups", value: state.includeCategories.contains(.publicGroups))) + entries.append(.filterChannels(title: "Channels", value: state.includeCategories.contains(.channels))) + + entries.append(.filterMuted(title: "Exclude Muted", value: !state.includeCategories.contains(.muted))) + entries.append(.filterRead(title: "Exclude Read", value: !state.includeCategories.contains(.read))) + + entries.append(.additionalPeersHeader("ALWAYS INCLUDE")) + entries.append(.addAdditionalPeer(title: "Add")) + + for peer in peers { + entries.append(.additionalPeer(index: entries.count, peer: peer, isRevealed: state.revealedPeerId == peer.peerId)) + } + + return entries +} + +func chatListFilterPresetController(context: AccountContext, currentPreset: ChatListFilterPreset?) -> ViewController { + let initialName: String + if let currentPreset = currentPreset { + switch currentPreset.name { + case .unread: + initialName = "Unread" + case let .custom(value): + initialName = value + } + } else { + initialName = "New Preset" + } + let initialState = ChatListFilterPresetControllerState(name: initialName, includeCategories: currentPreset?.includeCategories ?? .all, additionallyIncludePeers: currentPreset?.additionallyIncludePeers ?? []) + let stateValue = Atomic(value: initialState) + let statePromise = ValuePromise(initialState, ignoreRepeated: true) + let updateState: ((ChatListFilterPresetControllerState) -> ChatListFilterPresetControllerState) -> Void = { f in + statePromise.set(stateValue.modify { f($0) }) + } + + let actionsDisposable = DisposableSet() + + let addPeerDisposable = MetaDisposable() + actionsDisposable.add(addPeerDisposable) + + var presentControllerImpl: ((ViewController, Any?) -> Void)? + var dismissImpl: (() -> Void)? + + let arguments = ChatListFilterPresetControllerArguments( + context: context, + updateState: { f in + updateState(f) + }, + openAddPeer: { + let controller = context.sharedContext.makeContactMultiselectionController(ContactMultiselectionControllerParams(context: context, mode: .peerSelection(searchChatList: true, searchGroups: true), options: [])) + addPeerDisposable.set((controller.result + |> take(1) + |> deliverOnMainQueue).start(next: { [weak controller] peerIds in + controller?.dismiss() + updateState { state in + var state = state + for peerId in peerIds { + switch peerId { + case let .peer(id): + if !state.additionallyIncludePeers.contains(id) { + state.additionallyIncludePeers.append(id) + } + default: + break + } + } + return state + } + })) + presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) + }, + deleteAdditionalPeer: { peerId in + updateState { state in + var state = state + if let index = state.additionallyIncludePeers.index(of: peerId) { + state.additionallyIncludePeers.remove(at: index) + } + return state + } + }, + setPeerIdWithRevealedOptions: { peerId, fromPeerId in + updateState { state in + var state = state + if (peerId == nil && fromPeerId == state.revealedPeerId) || (peerId != nil && fromPeerId == nil) { + state.revealedPeerId = peerId + } + return state + } + } + ) + + let statePeers = statePromise.get() + |> map { state -> [PeerId] in + return state.additionallyIncludePeers + } + |> distinctUntilChanged + |> mapToSignal { peerIds -> Signal<[RenderedPeer], NoError> in + return context.account.postbox.transaction { transaction -> [RenderedPeer] in + var result: [RenderedPeer] = [] + for peerId in peerIds { + if let peer = transaction.getPeer(peerId) { + result.append(RenderedPeer(peer: peer)) + } + } + return result + } + } + + let signal = combineLatest(queue: .mainQueue(), + context.sharedContext.presentationData, + statePromise.get(), + statePeers + ) + |> deliverOnMainQueue + |> map { presentationData, state, statePeers -> (ItemListControllerState, (ItemListNodeState, Any)) in + let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: { + dismissImpl?() + }) + let rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Done), style: .bold, enabled: state.isComplete, action: { + let state = stateValue.with { $0 } + let preset = ChatListFilterPreset(name: .custom(state.name), includeCategories: state.includeCategories, additionallyIncludePeers: state.additionallyIncludePeers) + let _ = (updateChatListFilterSettingsInteractively(postbox: context.account.postbox, { settings in + var settings = settings + settings.presets = settings.presets.filter { $0 != preset && $0 != currentPreset } + settings.presets.append(preset) + return settings + }) + |> deliverOnMainQueue).start(completed: { + dismissImpl?() + }) + }) + + let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.SocksProxySetup_Title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false) + let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: chatListFilterPresetControllerEntries(presentationData: presentationData, state: state, peers: statePeers), style: .blocks, emptyStateItem: nil, animateChanges: true) + + return (controllerState, (listState, arguments)) + } + |> afterDisposed { + actionsDisposable.dispose() + } + + let controller = ItemListController(context: context, state: signal) + controller.navigationPresentation = .modal + presentControllerImpl = { [weak controller] c, d in + controller?.present(c, in: .window(.root), with: d) + } + dismissImpl = { [weak controller] in + let _ = controller?.dismiss() + } + + return controller +} + diff --git a/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift b/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift new file mode 100644 index 0000000000..d1f55c8d6d --- /dev/null +++ b/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift @@ -0,0 +1,212 @@ +import Foundation +import UIKit +import Display +import SwiftSignalKit +import Postbox +import TelegramCore +import SyncCore +import TelegramPresentationData +import TelegramUIPreferences +import ItemListUI +import PresentationDataUtils +import AccountContext + +private final class ChatListFilterPresetListControllerArguments { + let context: AccountContext + + let openPreset: (ChatListFilterPreset) -> Void + let addNew: () -> Void + let setItemWithRevealedOptions: (ChatListFilterPreset?, ChatListFilterPreset?) -> Void + let removePreset: (ChatListFilterPreset) -> Void + + init(context: AccountContext, openPreset: @escaping (ChatListFilterPreset) -> Void, addNew: @escaping () -> Void, setItemWithRevealedOptions: @escaping (ChatListFilterPreset?, ChatListFilterPreset?) -> Void, removePreset: @escaping (ChatListFilterPreset) -> Void) { + self.context = context + self.openPreset = openPreset + self.addNew = addNew + self.setItemWithRevealedOptions = setItemWithRevealedOptions + self.removePreset = removePreset + } +} + +private enum ChatListFilterPresetListSection: Int32 { + case list +} + +private func stringForUserCount(_ peers: [PeerId: SelectivePrivacyPeer], strings: PresentationStrings) -> String { + if peers.isEmpty { + return strings.PrivacyLastSeenSettings_EmpryUsersPlaceholder + } else { + var result = 0 + for (_, peer) in peers { + result += peer.userCount + } + return strings.UserCount(Int32(result)) + } +} + +private enum ChatListFilterPresetListEntryStableId: Hashable { + case listHeader + case preset(ChatListFilterPresetName) + case addItem + case listFooter +} + +private enum ChatListFilterPresetListEntry: ItemListNodeEntry { + case listHeader(String) + case preset(index: Int, title: String, preset: ChatListFilterPreset, canBeReordered: Bool, canBeDeleted: Bool) + case addItem(String) + case listFooter(String) + + var section: ItemListSectionId { + switch self { + case .listHeader, .preset, .addItem, .listFooter: + return ChatListFilterPresetListSection.list.rawValue + } + } + + var sortId: Int { + switch self { + case .listHeader: + return 0 + case let .preset(preset): + return 1 + preset.index + case .addItem: + return 1000 + case .listFooter: + return 1001 + } + } + + var stableId: ChatListFilterPresetListEntryStableId { + switch self { + case .listHeader: + return .listHeader + case let .preset(preset): + return .preset(preset.preset.name) + case .addItem: + return .addItem + case .listFooter: + return .listFooter + } + } + + static func <(lhs: ChatListFilterPresetListEntry, rhs: ChatListFilterPresetListEntry) -> Bool { + return lhs.sortId < rhs.sortId + } + + func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem { + let arguments = arguments as! ChatListFilterPresetListControllerArguments + switch self { + case let .listHeader(text): + return ItemListSectionHeaderItem(presentationData: presentationData, text: text, multiline: true, sectionId: self.section) + case let .preset(index, title, preset, canBeReordered, canBeDeleted): + return ChatListFilterPresetListItem(presentationData: presentationData, preset: preset, title: title, editing: ChatListFilterPresetListItemEditing(editable: true, editing: false, revealed: false), canBeReordered: canBeReordered, canBeDeleted: canBeDeleted, sectionId: self.section, action: { + arguments.openPreset(preset) + }, setItemWithRevealedOptions: { lhs, rhs in + arguments.setItemWithRevealedOptions(lhs, rhs) + }, remove: { + arguments.removePreset(preset) + }) + case let .addItem(text): + return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: { + arguments.addNew() + }) + case let .listFooter(text): + return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section) + } + } +} + +private struct ChatListFilterPresetListControllerState: Equatable { + var revealedPreset: ChatListFilterPreset? = nil +} + +private func chatListFilterPresetListControllerEntries(presentationData: PresentationData, state: ChatListFilterPresetListControllerState, settings: ChatListFilterSettings) -> [ChatListFilterPresetListEntry] { + var entries: [ChatListFilterPresetListEntry] = [] + + entries.append(.listHeader("PRESETS")) + for preset in settings.presets { + let title: String + switch preset.name { + case .unread: + title = "Unread" + case let .custom(value): + title = value + } + entries.append(.preset(index: entries.count, title: title, preset: preset, canBeReordered: settings.presets.count > 1, canBeDeleted: true)) + } + entries.append(.addItem("Add New")) + entries.append(.listFooter("Add custom presets")) + + return entries +} + +func chatListFilterPresetListController(context: AccountContext) -> ViewController { + let initialState = ChatListFilterPresetListControllerState() + let statePromise = ValuePromise(initialState, ignoreRepeated: true) + let stateValue = Atomic(value: initialState) + let updateState: ((ChatListFilterPresetListControllerState) -> ChatListFilterPresetListControllerState) -> Void = { f in + statePromise.set(stateValue.modify { f($0) }) + } + + var dismissImpl: (() -> Void)? + var pushControllerImpl: ((ViewController) -> Void)? + var presentControllerImpl: ((ViewController, Any?) -> Void)? + + let arguments = ChatListFilterPresetListControllerArguments(context: context, openPreset: { preset in + pushControllerImpl?(chatListFilterPresetController(context: context, currentPreset: preset)) + }, addNew: { + pushControllerImpl?(chatListFilterPresetController(context: context, currentPreset: nil)) + }, setItemWithRevealedOptions: { preset, fromPreset in + updateState { state in + var state = state + if (preset == nil && fromPreset == state.revealedPreset) || (preset != nil && fromPreset == nil) { + state.revealedPreset = preset + } + return state + } + }, removePreset: { preset in + let _ = updateChatListFilterSettingsInteractively(postbox: context.account.postbox, { settings in + var settings = settings + if let index = settings.presets.index(of: preset) { + settings.presets.remove(at: index) + } + return settings + }).start() + }) + + let preferences = context.account.postbox.preferencesView(keys: [ApplicationSpecificPreferencesKeys.chatListFilterSettings]) + + let signal = combineLatest(queue: .mainQueue(), + context.sharedContext.presentationData, + statePromise.get(), + preferences + ) + |> map { presentationData, state, preferences -> (ItemListControllerState, (ItemListNodeState, Any)) in + let settings = preferences.values[ApplicationSpecificPreferencesKeys.chatListFilterSettings] as? ChatListFilterSettings ?? ChatListFilterSettings.default + let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Close), style: .regular, enabled: true, action: { + dismissImpl?() + }) + + let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text("Filter Presets"), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false) + let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: chatListFilterPresetListControllerEntries(presentationData: presentationData, state: state, settings: settings), style: .blocks, animateChanges: true) + + return (controllerState, (listState, arguments)) + } + |> afterDisposed { + } + + let controller = ItemListController(context: context, state: signal) + controller.navigationPresentation = .modal + pushControllerImpl = { [weak controller] c in + controller?.push(c) + } + presentControllerImpl = { [weak controller] c, a in + controller?.present(c, in: .window(.root), with: a) + } + dismissImpl = { [weak controller] in + controller?.dismiss() + } + + return controller +} diff --git a/submodules/ChatListUI/Sources/ChatListFilterPresetListItem.swift b/submodules/ChatListUI/Sources/ChatListFilterPresetListItem.swift new file mode 100644 index 0000000000..661dc45468 --- /dev/null +++ b/submodules/ChatListUI/Sources/ChatListFilterPresetListItem.swift @@ -0,0 +1,439 @@ +import Foundation +import UIKit +import Display +import AsyncDisplayKit +import SwiftSignalKit +import Postbox +import TelegramCore +import SyncCore +import TelegramPresentationData +import ItemListUI +import PresentationDataUtils +import ActivityIndicator +import TelegramUIPreferences + +struct ChatListFilterPresetListItemEditing: Equatable { + let editable: Bool + let editing: Bool + let revealed: Bool +} + +final class ChatListFilterPresetListItem: ListViewItem, ItemListItem { + let presentationData: ItemListPresentationData + let preset: ChatListFilterPreset + let title: String + let editing: ChatListFilterPresetListItemEditing + let canBeReordered: Bool + let canBeDeleted: Bool + let sectionId: ItemListSectionId + let action: () -> Void + let setItemWithRevealedOptions: (ChatListFilterPreset?, ChatListFilterPreset?) -> Void + let remove: () -> Void + + init( + presentationData: ItemListPresentationData, + preset: ChatListFilterPreset, + title: String, + editing: ChatListFilterPresetListItemEditing, + canBeReordered: Bool, + canBeDeleted: Bool, + sectionId: ItemListSectionId, + action: @escaping () -> Void, + setItemWithRevealedOptions: @escaping (ChatListFilterPreset?, ChatListFilterPreset?) -> Void, + remove: @escaping () -> Void + ) { + self.presentationData = presentationData + self.preset = preset + self.title = title + self.editing = editing + self.canBeReordered = canBeReordered + self.canBeDeleted = canBeDeleted + self.sectionId = sectionId + self.action = action + self.setItemWithRevealedOptions = setItemWithRevealedOptions + self.remove = remove + } + + func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal?, (ListViewItemApply) -> Void)) -> Void) { + async { + let node = ChatListFilterPresetListItemNode() + let (layout, apply) = node.asyncLayout()(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem)) + + node.contentSize = layout.contentSize + node.insets = layout.insets + + Queue.mainQueue().async { + completion(node, { + return (nil, { _ in apply(false) }) + }) + } + } + } + + func updateNode(async: @escaping (@escaping () -> Void) -> Void, node: @escaping () -> ListViewItemNode, params: ListViewItemLayoutParams, previousItem: ListViewItem?, nextItem: ListViewItem?, animation: ListViewItemUpdateAnimation, completion: @escaping (ListViewItemNodeLayout, @escaping (ListViewItemApply) -> Void) -> Void) { + Queue.mainQueue().async { + if let nodeValue = node() as? ChatListFilterPresetListItemNode { + let makeLayout = nodeValue.asyncLayout() + + var animated = true + if case .None = animation { + animated = false + } + + async { + let (layout, apply) = makeLayout(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem)) + Queue.mainQueue().async { + completion(layout, { _ in + apply(animated) + }) + } + } + } + } + } + + var selectable: Bool = true + + func selected(listView: ListView){ + listView.clearHighlightAnimated(true) + self.action() + } +} + +private let titleFont = Font.regular(17.0) + +private final class ChatListFilterPresetListItemNode: ItemListRevealOptionsItemNode { + private let backgroundNode: ASDisplayNode + private let topStripeNode: ASDisplayNode + private let bottomStripeNode: ASDisplayNode + private let highlightedBackgroundNode: ASDisplayNode + private let maskNode: ASImageNode + + private let titleNode: TextNode + + private let activateArea: AccessibilityAreaNode + + private var editableControlNode: ItemListEditableControlNode? + private var reorderControlNode: ItemListEditableReorderControlNode? + + private var item: ChatListFilterPresetListItem? + private var layoutParams: ListViewItemLayoutParams? + + override var canBeSelected: Bool { + if self.editableControlNode != nil { + return false + } + return true + } + + init() { + self.backgroundNode = ASDisplayNode() + self.backgroundNode.isLayerBacked = true + + self.topStripeNode = ASDisplayNode() + self.topStripeNode.isLayerBacked = true + + self.bottomStripeNode = ASDisplayNode() + self.bottomStripeNode.isLayerBacked = true + + self.maskNode = ASImageNode() + + self.titleNode = TextNode() + self.titleNode.isUserInteractionEnabled = false + self.titleNode.contentMode = .left + self.titleNode.contentsScale = UIScreen.main.scale + + self.activateArea = AccessibilityAreaNode() + + self.highlightedBackgroundNode = ASDisplayNode() + self.highlightedBackgroundNode.isLayerBacked = true + + super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false) + + self.addSubnode(self.titleNode) + self.addSubnode(self.activateArea) + + self.activateArea.activate = { [weak self] in + self?.item?.action() + return true + } + } + + func asyncLayout() -> (_ item: ChatListFilterPresetListItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, (Bool) -> Void) { + let makeTitleLayout = TextNode.asyncLayout(self.titleNode) + let editableControlLayout = ItemListEditableControlNode.asyncLayout(self.editableControlNode) + let reorderControlLayout = ItemListEditableReorderControlNode.asyncLayout(self.reorderControlNode) + + let currentItem = self.item + + return { item, params, neighbors in + var updatedTheme: PresentationTheme? + + if currentItem?.presentationData.theme !== item.presentationData.theme { + updatedTheme = item.presentationData.theme + } + + let peerRevealOptions: [ItemListRevealOption] + if item.editing.editable && item.canBeDeleted { + peerRevealOptions = [ItemListRevealOption(key: 0, title: item.presentationData.strings.Common_Delete, icon: .none, color: item.presentationData.theme.list.itemDisclosureActions.destructive.fillColor, textColor: item.presentationData.theme.list.itemDisclosureActions.destructive.foregroundColor)] + } else { + peerRevealOptions = [] + } + + let titleAttributedString = NSMutableAttributedString() + titleAttributedString.append(NSAttributedString(string: item.title, font: titleFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor)) + + var editableControlSizeAndApply: (CGFloat, (CGFloat) -> ItemListEditableControlNode)? + var reorderControlSizeAndApply: (CGFloat, (CGFloat, Bool, ContainedViewLayoutTransition) -> ItemListEditableReorderControlNode)? + + let editingOffset: CGFloat = 0.0 + var reorderInset: CGFloat = 0.0 + + if item.editing.editing && item.canBeReordered { + /*let sizeAndApply = editableControlLayout(item.presentationData.theme, false) + editableControlSizeAndApply = sizeAndApply + editingOffset = sizeAndApply.0*/ + + let reorderSizeAndApply = reorderControlLayout(item.presentationData.theme) + reorderControlSizeAndApply = reorderSizeAndApply + reorderInset = reorderSizeAndApply.0 + } + + let leftInset: CGFloat = 16.0 + params.leftInset + let rightInset: CGFloat = params.rightInset + max(reorderInset, 55.0) + + let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .middle, constrainedSize: CGSize(width: params.width - leftInset - 12.0 - editingOffset - rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) + + let insets = itemListNeighborsGroupedInsets(neighbors) + let contentSize = CGSize(width: params.width, height: titleLayout.size.height + 11.0 * 2.0) + let separatorHeight = UIScreenPixel + + let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets) + let layoutSize = layout.size + + return (layout, { [weak self] animated in + if let strongSelf = self { + strongSelf.item = item + strongSelf.layoutParams = params + + strongSelf.activateArea.accessibilityLabel = "\(titleAttributedString.string))" + + if let _ = updatedTheme { + strongSelf.topStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor + strongSelf.bottomStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor + strongSelf.backgroundNode.backgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor + strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor + } + + let revealOffset = strongSelf.revealOffset + + let transition: ContainedViewLayoutTransition + if animated { + transition = ContainedViewLayoutTransition.animated(duration: 0.4, curve: .spring) + } else { + transition = .immediate + } + + if let editableControlSizeAndApply = editableControlSizeAndApply { + let editableControlFrame = CGRect(origin: CGPoint(x: params.leftInset + revealOffset, y: 0.0), size: CGSize(width: editableControlSizeAndApply.0, height: layout.contentSize.height)) + if strongSelf.editableControlNode == nil { + let editableControlNode = editableControlSizeAndApply.1(layout.contentSize.height) + editableControlNode.tapped = { + if let strongSelf = self { + strongSelf.setRevealOptionsOpened(true, animated: true) + strongSelf.revealOptionsInteractivelyOpened() + } + } + strongSelf.editableControlNode = editableControlNode + strongSelf.insertSubnode(editableControlNode, aboveSubnode: strongSelf.titleNode) + editableControlNode.frame = editableControlFrame + transition.animatePosition(node: editableControlNode, from: CGPoint(x: -editableControlFrame.size.width / 2.0, y: editableControlFrame.midY)) + editableControlNode.alpha = 0.0 + transition.updateAlpha(node: editableControlNode, alpha: 1.0) + } else { + strongSelf.editableControlNode?.frame = editableControlFrame + } + strongSelf.editableControlNode?.isHidden = !item.editing.editable + } else if let editableControlNode = strongSelf.editableControlNode { + var editableControlFrame = editableControlNode.frame + editableControlFrame.origin.x = -editableControlFrame.size.width + strongSelf.editableControlNode = nil + transition.updateAlpha(node: editableControlNode, alpha: 0.0) + transition.updateFrame(node: editableControlNode, frame: editableControlFrame, completion: { [weak editableControlNode] _ in + editableControlNode?.removeFromSupernode() + }) + } + + if let reorderControlSizeAndApply = reorderControlSizeAndApply { + if strongSelf.reorderControlNode == nil { + let reorderControlNode = reorderControlSizeAndApply.1(layout.contentSize.height, false, .immediate) + strongSelf.reorderControlNode = reorderControlNode + strongSelf.addSubnode(reorderControlNode) + reorderControlNode.alpha = 0.0 + transition.updateAlpha(node: reorderControlNode, alpha: 1.0) + } + let reorderControlFrame = CGRect(origin: CGPoint(x: params.width + revealOffset - params.rightInset - reorderControlSizeAndApply.0, y: 0.0), size: CGSize(width: reorderControlSizeAndApply.0, height: layout.contentSize.height)) + strongSelf.reorderControlNode?.frame = reorderControlFrame + } else if let reorderControlNode = strongSelf.reorderControlNode { + strongSelf.reorderControlNode = nil + transition.updateAlpha(node: reorderControlNode, alpha: 0.0, completion: { [weak reorderControlNode] _ in + reorderControlNode?.removeFromSupernode() + }) + } + + let _ = titleApply() + + if strongSelf.backgroundNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0) + } + if strongSelf.topStripeNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.topStripeNode, at: 1) + } + if strongSelf.bottomStripeNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) + } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + let hasCorners = itemListHasRoundedBlockLayout(params) + var hasTopCorners = false + var hasBottomCorners = false + switch neighbors.top { + case .sameSection(false): + strongSelf.topStripeNode.isHidden = true + default: + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners + } + let bottomStripeInset: CGFloat + let bottomStripeOffset: CGFloat + switch neighbors.bottom { + case .sameSection(false): + bottomStripeInset = leftInset + editingOffset + bottomStripeOffset = -separatorHeight + default: + bottomStripeInset = 0.0 + bottomStripeOffset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners + } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) + transition.updateFrame(node: strongSelf.topStripeNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight))) + transition.updateFrame(node: strongSelf.bottomStripeNode, frame: CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight))) + + transition.updateFrame(node: strongSelf.titleNode, frame: CGRect(origin: CGPoint(x: leftInset + revealOffset + editingOffset, y: 11.0), size: titleLayout.size)) + + strongSelf.activateArea.frame = CGRect(origin: CGPoint(x: leftInset + revealOffset + editingOffset, y: 0.0), size: CGSize(width: params.width - params.rightInset - 56.0 - (leftInset + revealOffset + editingOffset), height: layout.contentSize.height)) + + strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: layout.contentSize.height + UIScreenPixel + UIScreenPixel)) + + strongSelf.updateLayout(size: layout.contentSize, leftInset: params.leftInset, rightInset: params.rightInset) + + strongSelf.setRevealOptions((left: [], right: peerRevealOptions)) + strongSelf.setRevealOptionsOpened(item.editing.revealed, animated: animated) + } + }) + } + } + + override func setHighlighted(_ highlighted: Bool, at point: CGPoint, animated: Bool) { + super.setHighlighted(highlighted, at: point, animated: animated) + + if highlighted { + self.highlightedBackgroundNode.alpha = 1.0 + if self.highlightedBackgroundNode.supernode == nil { + var anchorNode: ASDisplayNode? + if self.bottomStripeNode.supernode != nil { + anchorNode = self.bottomStripeNode + } else if self.topStripeNode.supernode != nil { + anchorNode = self.topStripeNode + } else if self.backgroundNode.supernode != nil { + anchorNode = self.backgroundNode + } + if let anchorNode = anchorNode { + self.insertSubnode(self.highlightedBackgroundNode, aboveSubnode: anchorNode) + } else { + self.addSubnode(self.highlightedBackgroundNode) + } + } + } else { + if self.highlightedBackgroundNode.supernode != nil { + if animated { + self.highlightedBackgroundNode.layer.animateAlpha(from: self.highlightedBackgroundNode.alpha, to: 0.0, duration: 0.4, completion: { [weak self] completed in + if let strongSelf = self { + if completed { + strongSelf.highlightedBackgroundNode.removeFromSupernode() + } + } + }) + self.highlightedBackgroundNode.alpha = 0.0 + } else { + self.highlightedBackgroundNode.removeFromSupernode() + } + } + } + } + + override func animateInsertion(_ currentTimestamp: Double, duration: Double, short: Bool) { + self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.4) + } + + override func animateRemoved(_ currentTimestamp: Double, duration: Double) { + self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false) + } + + override func updateRevealOffset(offset: CGFloat, transition: ContainedViewLayoutTransition) { + super.updateRevealOffset(offset: offset, transition: transition) + + guard let params = self.layoutParams else { + return + } + + let leftInset: CGFloat = 16.0 + params.leftInset + + let editingOffset: CGFloat + if let editableControlNode = self.editableControlNode { + editingOffset = editableControlNode.bounds.size.width + var editableControlFrame = editableControlNode.frame + editableControlFrame.origin.x = params.leftInset + offset + transition.updateFrame(node: editableControlNode, frame: editableControlFrame) + } else { + editingOffset = 0.0 + } + + transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: leftInset + offset + editingOffset, y: self.titleNode.frame.minY), size: self.titleNode.bounds.size)) + } + + override func revealOptionsInteractivelyOpened() { + if let item = self.item { + item.setItemWithRevealedOptions(item.preset, nil) + } + } + + override func revealOptionsInteractivelyClosed() { + if let item = self.item { + item.setItemWithRevealedOptions(nil, item.preset) + } + } + + override func revealOptionSelected(_ option: ItemListRevealOption, animated: Bool) { + self.setRevealOptionsOpened(false, animated: true) + self.revealOptionsInteractivelyClosed() + + if let item = self.item { + item.remove() + } + } + + override func isReorderable(at point: CGPoint) -> Bool { + if let reorderControlNode = self.reorderControlNode, reorderControlNode.frame.contains(point), !self.isDisplayingRevealedOptions { + return true + } + return false + } +} diff --git a/submodules/ChatListUI/Sources/Node/ChatListNode.swift b/submodules/ChatListUI/Sources/Node/ChatListNode.swift index 0d6f40954d..ab9abd8fe3 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNode.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNode.swift @@ -366,14 +366,17 @@ public final class ChatListNode: ListView { } private var currentLocation: ChatListNodeLocation? - var chatListFilter: ChatListNodeFilter = .all { + var chatListFilter: ChatListFilterPreset? { didSet { if self.chatListFilter != oldValue { self.chatListFilterValue.set(self.chatListFilter) } } } - private let chatListFilterValue = ValuePromise(.all) + private let chatListFilterValue = ValuePromise(nil) + var chatListFilterSignal: Signal { + return self.chatListFilterValue.get() + } private let chatListLocation = ValuePromise() private let chatListDisposable = MetaDisposable() private var activityStatusesDisposable: Disposable? @@ -540,7 +543,7 @@ public final class ChatListNode: ListView { } return true }) - |> mapToSignal { location, filter -> Signal<(ChatListNodeViewUpdate, ChatListNodeFilter), NoError> in + |> mapToSignal { location, filter -> Signal<(ChatListNodeViewUpdate, ChatListFilterPreset?), NoError> in return chatListViewForLocation(groupId: groupId, filter: filter, location: location, account: context.account) |> map { update in return (update, filter) diff --git a/submodules/ChatListUI/Sources/Node/ChatListNodeLocation.swift b/submodules/ChatListUI/Sources/Node/ChatListNodeLocation.swift index 93e631b8f6..231509cbe6 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNodeLocation.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNodeLocation.swift @@ -4,6 +4,7 @@ import TelegramCore import SyncCore import SwiftSignalKit import Display +import TelegramUIPreferences enum ChatListNodeLocation: Equatable { case initial(count: Int) @@ -31,35 +32,20 @@ struct ChatListNodeViewUpdate { let scrollPosition: ChatListNodeViewScrollPosition? } -struct ChatListNodeFilter: OptionSet { - var rawValue: Int32 - - init(rawValue: Int32) { - self.rawValue = rawValue - } - - static let muted = ChatListNodeFilter(rawValue: 1 << 1) - static let privateChats = ChatListNodeFilter(rawValue: 1 << 2) - static let groups = ChatListNodeFilter(rawValue: 1 << 3) - static let bots = ChatListNodeFilter(rawValue: 1 << 4) - static let channels = ChatListNodeFilter(rawValue: 1 << 5) - - static let all: ChatListNodeFilter = [ - .muted, - .privateChats, - .groups, - .bots, - .channels - ] -} - -func chatListViewForLocation(groupId: PeerGroupId, filter: ChatListNodeFilter, location: ChatListNodeLocation, account: Account) -> Signal { - let filterPredicate: ((Peer, PeerNotificationSettings?) -> Bool)? - if filter == .all { - filterPredicate = nil - } else { - filterPredicate = { peer, notificationSettings in - if !filter.contains(.muted) { +func chatListViewForLocation(groupId: PeerGroupId, filter: ChatListFilterPreset?, location: ChatListNodeLocation, account: Account) -> Signal { + let filterPredicate: ((Peer, PeerNotificationSettings?, Bool) -> Bool)? + if let filter = filter { + let includePeers = Set(filter.additionallyIncludePeers) + filterPredicate = { peer, notificationSettings, isUnread in + if includePeers.contains(peer.id) { + return true + } + if !filter.includeCategories.contains(.read) { + if !isUnread { + return false + } + } + if !filter.includeCategories.contains(.muted) { if let notificationSettings = notificationSettings as? TelegramPeerNotificationSettings { if case .muted = notificationSettings.muteState { return false @@ -68,32 +54,46 @@ func chatListViewForLocation(groupId: PeerGroupId, filter: ChatListNodeFilter, l return false } } - if !filter.contains(.privateChats) { + if !filter.includeCategories.contains(.privateChats) { if let user = peer as? TelegramUser { if user.botInfo == nil { return false } - } else if let _ = peer as? TelegramSecretChat { + } + } + if !filter.includeCategories.contains(.secretChats) { + if let _ = peer as? TelegramSecretChat { return false } } - if !filter.contains(.bots) { + if !filter.includeCategories.contains(.bots) { if let user = peer as? TelegramUser { if user.botInfo != nil { return false } } } - if !filter.contains(.groups) { + if !filter.includeCategories.contains(.privateGroups) { if let _ = peer as? TelegramGroup { return false } else if let channel = peer as? TelegramChannel { if case .group = channel.info { - return false + if channel.username == nil { + return false + } } } } - if !filter.contains(.channels) { + if !filter.includeCategories.contains(.publicGroups) { + if let channel = peer as? TelegramChannel { + if case .group = channel.info { + if channel.username != nil { + return false + } + } + } + } + if !filter.includeCategories.contains(.channels) { if let channel = peer as? TelegramChannel { if case .broadcast = channel.info { return false @@ -102,6 +102,8 @@ func chatListViewForLocation(groupId: PeerGroupId, filter: ChatListNodeFilter, l } return true } + } else { + filterPredicate = nil } switch location { diff --git a/submodules/ChatListUI/Sources/Node/ChatListViewTransition.swift b/submodules/ChatListUI/Sources/Node/ChatListViewTransition.swift index 17350a0f77..f0a07f75cc 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListViewTransition.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListViewTransition.swift @@ -6,12 +6,13 @@ import SwiftSignalKit import Display import MergeLists import SearchUI +import TelegramUIPreferences struct ChatListNodeView { let originalView: ChatListView let filteredEntries: [ChatListNodeEntry] let isLoading: Bool - let filter: ChatListNodeFilter + let filter: ChatListFilterPreset? } enum ChatListNodeViewTransitionReason { diff --git a/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift b/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift index 204ee79dea..12bb93be3a 100644 --- a/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift +++ b/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift @@ -5,32 +5,39 @@ import SwiftSignalKit import AsyncDisplayKit import TelegramPresentationData import AccountContext +import SyncCore +import Postbox +import TelegramUIPreferences final class TabBarChatListFilterController: ViewController { private var controllerNode: TabBarChatListFilterControllerNode { return self.displayNode as! TabBarChatListFilterControllerNode } - private let _ready = Promise(true) + private let _ready = Promise() override public var ready: Promise { return self._ready } private let context: AccountContext private let sourceNodes: [ASDisplayNode] - private let currentFilter: ChatListNodeFilter - private let updateFilter: (ChatListNodeFilter) -> Void + private let presetList: [ChatListFilterPreset] + private let currentPreset: ChatListFilterPreset? + private let setup: () -> Void + private let updatePreset: (ChatListFilterPreset?) -> Void private var presentationData: PresentationData private var didPlayPresentationAnimation = false private let hapticFeedback = HapticFeedback() - public init(context: AccountContext, sourceNodes: [ASDisplayNode], currentFilter: ChatListNodeFilter, updateFilter: @escaping (ChatListNodeFilter) -> Void) { + public init(context: AccountContext, sourceNodes: [ASDisplayNode], presetList: [ChatListFilterPreset], currentPreset: ChatListFilterPreset?, setup: @escaping () -> Void, updatePreset: @escaping (ChatListFilterPreset?) -> Void) { self.context = context self.sourceNodes = sourceNodes - self.currentFilter = currentFilter - self.updateFilter = updateFilter + self.presetList = presetList + self.currentPreset = currentPreset + self.setup = setup + self.updatePreset = updatePreset self.presentationData = context.sharedContext.currentPresentationData.with { $0 } @@ -52,7 +59,14 @@ final class TabBarChatListFilterController: ViewController { override public func loadDisplayNode() { self.displayNode = TabBarChatListFilterControllerNode(context: self.context, presentationData: self.presentationData, cancel: { [weak self] in self?.dismiss() - }, sourceNodes: self.sourceNodes, currentFilter: self.currentFilter, updateFilter: self.updateFilter) + }, sourceNodes: self.sourceNodes, presetList: self.presetList, currentPreset: self.currentPreset, setup: { [weak self] in + self?.setup() + self?.dismiss(sourceNodes: [], fadeOutIcon: true) + }, updatePreset: { [weak self] filter in + self?.updatePreset(filter) + self?.dismiss() + }) + self._ready.set(self.controllerNode.isReady.get()) self.displayNodeDidLoad() } @@ -74,11 +88,11 @@ final class TabBarChatListFilterController: ViewController { } override public func dismiss(completion: (() -> Void)? = nil) { - self.dismiss(sourceNodes: []) + self.dismiss(sourceNodes: [], fadeOutIcon: false) } - public func dismiss(sourceNodes: [ASDisplayNode]) { - self.controllerNode.animateOut(sourceNodes: sourceNodes, completion: { [weak self] in + func dismiss(sourceNodes: [ASDisplayNode], fadeOutIcon: Bool) { + self.controllerNode.animateOut(sourceNodes: sourceNodes, fadeOutIcon: fadeOutIcon, completion: { [weak self] in self?.didPlayPresentationAnimation = false self?.presentingViewController?.dismiss(animated: false, completion: nil) }) @@ -91,9 +105,86 @@ private protocol AbstractTabBarChatListFilterItemNode { func updateLayout(maxWidth: CGFloat) -> (CGFloat, CGFloat, (CGFloat) -> Void) } +private final class AddFilterItemNode: ASDisplayNode, AbstractTabBarChatListFilterItemNode { + private let action: () -> Void + + private let separatorNode: ASDisplayNode + private let highlightedBackgroundNode: ASDisplayNode + private let buttonNode: HighlightTrackingButtonNode + private let plusNode: ASImageNode + private let titleNode: ImmediateTextNode + + init(displaySeparator: Bool, presentationData: PresentationData, action: @escaping () -> Void) { + self.action = action + + self.separatorNode = ASDisplayNode() + self.separatorNode.backgroundColor = presentationData.theme.actionSheet.opaqueItemSeparatorColor + self.separatorNode.isHidden = !displaySeparator + + self.highlightedBackgroundNode = ASDisplayNode() + self.highlightedBackgroundNode.backgroundColor = presentationData.theme.actionSheet.opaqueItemHighlightedBackgroundColor + self.highlightedBackgroundNode.alpha = 0.0 + + self.buttonNode = HighlightTrackingButtonNode() + + self.titleNode = ImmediateTextNode() + self.titleNode.maximumNumberOfLines = 1 + self.titleNode.attributedText = NSAttributedString(string: "Setup", font: Font.regular(17.0), textColor: presentationData.theme.actionSheet.primaryTextColor) + + self.plusNode = ASImageNode() + self.plusNode.image = generateItemListPlusIcon(presentationData.theme.actionSheet.primaryTextColor) + + super.init() + + self.addSubnode(self.separatorNode) + self.addSubnode(self.highlightedBackgroundNode) + self.addSubnode(self.titleNode) + self.addSubnode(self.plusNode) + self.addSubnode(self.buttonNode) + + self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside) + self.buttonNode.highligthedChanged = { [weak self] highlighted in + if let strongSelf = self { + if highlighted { + strongSelf.highlightedBackgroundNode.layer.removeAnimation(forKey: "opacity") + strongSelf.highlightedBackgroundNode.alpha = 1.0 + } else { + strongSelf.highlightedBackgroundNode.alpha = 0.0 + strongSelf.highlightedBackgroundNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3) + } + } + } + } + + func updateLayout(maxWidth: CGFloat) -> (CGFloat, CGFloat, (CGFloat) -> Void) { + let leftInset: CGFloat = 16.0 + let rightInset: CGFloat = 10.0 + let iconInset: CGFloat = 60.0 + let titleSize = self.titleNode.updateLayout(CGSize(width: maxWidth - leftInset - rightInset, height: .greatestFiniteMagnitude)) + let height: CGFloat = 61.0 + + return (titleSize.width + leftInset + rightInset, height, { width in + self.titleNode.frame = CGRect(origin: CGPoint(x: leftInset, y: floor((height - titleSize.height) / 2.0)), size: titleSize) + + if let image = self.plusNode.image { + self.plusNode.frame = CGRect(origin: CGPoint(x: floor(width - iconInset + (iconInset - image.size.width) / 2.0), y: floor((height - image.size.height) / 2.0)), size: image.size) + } + + self.separatorNode.frame = CGRect(origin: CGPoint(x: 0.0, y: height - UIScreenPixel), size: CGSize(width: width, height: UIScreenPixel)) + self.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: width, height: height)) + self.buttonNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: width, height: height)) + }) + } + + @objc private func buttonPressed() { + self.action() + } +} + private final class FilterItemNode: ASDisplayNode, AbstractTabBarChatListFilterItemNode { private let context: AccountContext private let title: String + let preset: ChatListFilterPreset? private let isCurrent: Bool private let presentationData: PresentationData private let action: () -> Bool @@ -106,10 +197,12 @@ private final class FilterItemNode: ASDisplayNode, AbstractTabBarChatListFilterI private let badgeBackgroundNode: ASImageNode private let badgeTitleNode: ImmediateTextNode + private var badgeText: String = "" - init(context: AccountContext, title: String, isCurrent: Bool, displaySeparator: Bool, presentationData: PresentationData, action: @escaping () -> Bool) { + init(context: AccountContext, title: String, preset: ChatListFilterPreset?, isCurrent: Bool, displaySeparator: Bool, presentationData: PresentationData, action: @escaping () -> Bool) { self.context = context self.title = title + self.preset = preset self.isCurrent = isCurrent self.presentationData = presentationData self.action = action @@ -130,7 +223,7 @@ private final class FilterItemNode: ASDisplayNode, AbstractTabBarChatListFilterI self.checkNode = ASImageNode() self.checkNode.image = generateItemListCheckIcon(color: presentationData.theme.actionSheet.primaryTextColor) - self.checkNode.isHidden = !isCurrent + self.checkNode.isHidden = true//!isCurrent self.badgeBackgroundNode = ASImageNode() self.badgeBackgroundNode.image = generateStretchableFilledCircleImage(diameter: 20.0, color: presentationData.theme.list.itemCheckColors.fillColor) @@ -169,7 +262,7 @@ private final class FilterItemNode: ASDisplayNode, AbstractTabBarChatListFilterI let badgeMinSize = self.badgeBackgroundNode.image?.size.width ?? 20.0 let badgeSize = CGSize(width: max(badgeMinSize, badgeTitleSize.width + 12.0), height: badgeMinSize) - let rightInset: CGFloat = max(60.0, badgeSize.width + 40.0) + let rightInset: CGFloat = max(20.0, badgeSize.width + 20.0) let titleSize = self.titleNode.updateLayout(CGSize(width: maxWidth - leftInset - rightInset, height: .greatestFiniteMagnitude)) @@ -193,8 +286,20 @@ private final class FilterItemNode: ASDisplayNode, AbstractTabBarChatListFilterI } @objc private func buttonPressed() { - let isCurrent = self.action() - self.checkNode.isHidden = !isCurrent + let _ = self.action() + //self.checkNode.isHidden = !isCurrent + } + + func updateBadge(text: String) -> Bool { + if text != self.badgeText { + self.badgeText = text + self.badgeTitleNode.attributedText = NSAttributedString(string: text, font: Font.regular(14.0), textColor: self.presentationData.theme.list.itemCheckColors.foregroundColor) + self.badgeBackgroundNode.isHidden = text.isEmpty + self.badgeTitleNode.isHidden = text.isEmpty + return true + } else { + return false + } } } @@ -215,7 +320,11 @@ private final class TabBarChatListFilterControllerNode: ViewControllerTracingNod private var validLayout: ContainerViewLayout? - init(context: AccountContext, presentationData: PresentationData, cancel: @escaping () -> Void, sourceNodes: [ASDisplayNode], currentFilter: ChatListNodeFilter, updateFilter: @escaping (ChatListNodeFilter) -> Void) { + private var countsDisposable: Disposable? + let isReady = Promise() + private var didSetIsReady = false + + init(context: AccountContext, presentationData: PresentationData, cancel: @escaping () -> Void, sourceNodes: [ASDisplayNode], presetList: [ChatListFilterPreset], currentPreset: ChatListFilterPreset?, setup: @escaping () -> Void, updatePreset: @escaping (ChatListFilterPreset?) -> Void) { self.presentationData = presentationData self.cancel = cancel self.sourceNodes = sourceNodes @@ -245,30 +354,28 @@ private final class TabBarChatListFilterControllerNode: ViewControllerTracingNod self.contentContainerNode.clipsToBounds = true var contentNodes: [ASDisplayNode & AbstractTabBarChatListFilterItemNode] = [] + contentNodes.append(AddFilterItemNode(displaySeparator: true, presentationData: presentationData, action: { + setup() + })) - let labels: [(String, ChatListNodeFilter)] = [ - ("Private Chats", .privateChats), - ("Groups", .groups), - ("Bots", .bots), - ("Channels", .channels), - ("Muted", .muted) - ] + contentNodes.append(FilterItemNode(context: context, title: "All", preset: nil, isCurrent: currentPreset == nil, displaySeparator: !presetList.isEmpty, presentationData: presentationData, action: { + updatePreset(nil) + return false + })) - var updatedFilter = currentFilter - let toggleFilter: (ChatListNodeFilter) -> Void = { filter in - if updatedFilter.contains(filter) { - updatedFilter.remove(filter) - } else { - updatedFilter.insert(filter) + for i in 0 ..< presetList.count { + let preset = presetList[i] + + let title: String + switch preset.name { + case .unread: + title = "Unread" + case let .custom(value): + title = value } - updateFilter(updatedFilter) - } - - for i in 0 ..< labels.count { - let filter = labels[i].1 - contentNodes.append(FilterItemNode(context: context, title: labels[i].0, isCurrent: updatedFilter.contains(filter), displaySeparator: i != labels.count - 1, presentationData: presentationData, action: { - toggleFilter(filter) - return updatedFilter.contains(filter) + contentNodes.append(FilterItemNode(context: context, title: title, preset: preset, isCurrent: currentPreset == preset, displaySeparator: i != presetList.count - 1, presentationData: presentationData, action: { + updatePreset(preset) + return false })) } self.contentNodes = contentNodes @@ -281,6 +388,126 @@ private final class TabBarChatListFilterControllerNode: ViewControllerTracingNod self.contentNodes.forEach(self.contentContainerNode.addSubnode) self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture(_:)))) + + var unreadCountItems: [UnreadMessageCountsItem] = [] + unreadCountItems.append(.total(nil)) + var additionalPeerIds = Set() + for preset in presetList { + additionalPeerIds.formUnion(preset.additionallyIncludePeers) + } + if !additionalPeerIds.isEmpty { + for peerId in additionalPeerIds { + unreadCountItems.append(.peer(peerId)) + } + } + let unreadKey: PostboxViewKey = .unreadCounts(items: unreadCountItems) + var keys: [PostboxViewKey] = [] + keys.append(unreadKey) + for peerId in additionalPeerIds { + keys.append(.basicPeer(peerId)) + } + + self.countsDisposable = (context.account.postbox.combinedView(keys: keys) + |> deliverOnMainQueue).start(next: { [weak self] view in + guard let strongSelf = self else { + return + } + + if let unreadCounts = view.views[unreadKey] as? UnreadMessageCountsView { + var peerTagAndCount: [PeerId: (PeerSummaryCounterTags, Int)] = [:] + + var totalState: ChatListTotalUnreadState? + for entry in unreadCounts.entries { + switch entry { + case let .total(_, totalStateValue): + totalState = totalStateValue + case let .peer(peerId, state): + if let state = state, state.isUnread { + if let peerView = view.views[.basicPeer(peerId)] as? BasicPeerView, let peer = peerView.peer { + let tag = context.account.postbox.seedConfiguration.peerSummaryCounterTags(peer) + var peerCount = Int(state.count) + if state.isUnread { + peerCount = max(1, peerCount) + } + peerTagAndCount[peerId] = (tag, peerCount) + } + } + } + } + + var totalUnreadChatCount = 0 + if let totalState = totalState { + for (_, counters) in totalState.filteredCounters { + totalUnreadChatCount += Int(counters.chatCount) + } + } + + var shouldUpdateLayout = false + for case let contentNode as FilterItemNode in strongSelf.contentNodes { + let badgeString: String + if let preset = contentNode.preset { + var tags: [PeerSummaryCounterTags] = [] + if preset.includeCategories.contains(.privateChats) { + tags.append(.privateChat) + } + if preset.includeCategories.contains(.secretChats) { + tags.append(.secretChat) + } + if preset.includeCategories.contains(.privateGroups) { + tags.append(.privateGroup) + } + if preset.includeCategories.contains(.bots) { + tags.append(.bot) + } + if preset.includeCategories.contains(.publicGroups) { + tags.append(.publicGroup) + } + if preset.includeCategories.contains(.privateChats) { + tags.append(.channel) + } + + var count = 0 + if let totalState = totalState { + for tag in tags { + if preset.includeCategories.contains(.muted) { + } + if let value = totalState.filteredCounters[tag] { + count += Int(value.chatCount) + } + } + } + for peerId in preset.additionallyIncludePeers { + if let (tag, peerCount) = peerTagAndCount[peerId] { + if !tags.contains(tag) { + count += peerCount + } + } + } + if count != 0 { + badgeString = "\(count)" + } else { + badgeString = "" + } + } else { + badgeString = "" + } + if contentNode.updateBadge(text: badgeString) { + shouldUpdateLayout = true + } + } + + if shouldUpdateLayout { + if let layout = strongSelf.validLayout { + strongSelf.containerLayoutUpdated(layout, transition: .immediate) + } + } + } + + if !strongSelf.didSetIsReady { + strongSelf.didSetIsReady = true + strongSelf.isReady.set(.single(true)) + } + }) } deinit { @@ -290,6 +517,8 @@ private final class TabBarChatListFilterControllerNode: ViewControllerTracingNod propertyAnimator?.stopAnimation(true) } } + + self.countsDisposable?.dispose() } func animateIn() { @@ -344,7 +573,7 @@ private final class TabBarChatListFilterControllerNode: ViewControllerTracingNod } } - func animateOut(sourceNodes: [ASDisplayNode], completion: @escaping () -> Void) { + func animateOut(sourceNodes: [ASDisplayNode], fadeOutIcon: Bool, completion: @escaping () -> Void) { self.isUserInteractionEnabled = false var completedEffect = false @@ -408,7 +637,14 @@ private final class TabBarChatListFilterControllerNode: ViewControllerTracingNod let sourceFrame = sourceNode.view.convert(sourceNode.bounds, to: self.view) self.contentContainerNode.layer.animateFrame(from: self.contentContainerNode.frame, to: sourceFrame, duration: 0.15, timingFunction: CAMediaTimingFunctionName.easeIn.rawValue, removeOnCompletion: false) } - completedSourceNodes = true + if fadeOutIcon { + for snapshotView in self.snapshotViews { + snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false) + } + completedSourceNodes = true + } else { + completedSourceNodes = true + } } func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { @@ -420,7 +656,7 @@ private final class TabBarChatListFilterControllerNode: ViewControllerTracingNod let sideInset: CGFloat = 18.0 var contentSize = CGSize() - contentSize.width = min(layout.size.width - 60.0, 220.0) + contentSize.width = min(layout.size.width - 40.0, 260.0) var applyNodes: [(ASDisplayNode, CGFloat, (CGFloat) -> Void)] = [] for itemNode in self.contentNodes { let (width, height, apply) = itemNode.updateLayout(maxWidth: contentSize.width - sideInset * 2.0) diff --git a/submodules/Postbox/Sources/ChatListView.swift b/submodules/Postbox/Sources/ChatListView.swift index 5c2ee9f22f..920d88b95b 100644 --- a/submodules/Postbox/Sources/ChatListView.swift +++ b/submodules/Postbox/Sources/ChatListView.swift @@ -297,7 +297,7 @@ private func updatedRenderedPeer(_ renderedPeer: RenderedPeer, updatedPeers: [Pe final class MutableChatListView { let groupId: PeerGroupId - let filterPredicate: ((Peer, PeerNotificationSettings?) -> Bool)? + let filterPredicate: ((Peer, PeerNotificationSettings?, Bool) -> Bool)? private let summaryComponents: ChatListEntrySummaryComponents fileprivate var additionalItemIds: Set fileprivate var additionalItemEntries: [MutableChatListEntry] @@ -307,7 +307,7 @@ final class MutableChatListView { fileprivate var groupEntries: [ChatListGroupReferenceEntry] private var count: Int - init(postbox: Postbox, groupId: PeerGroupId, filterPredicate: ((Peer, PeerNotificationSettings?) -> Bool)?, aroundIndex: ChatListIndex, count: Int, summaryComponents: ChatListEntrySummaryComponents) { + init(postbox: Postbox, groupId: PeerGroupId, filterPredicate: ((Peer, PeerNotificationSettings?, Bool) -> Bool)?, aroundIndex: ChatListIndex, count: Int, summaryComponents: ChatListEntrySummaryComponents) { let (entries, earlier, later) = postbox.fetchAroundChatEntries(groupId: groupId, index: aroundIndex, count: count, filterPredicate: filterPredicate) self.groupId = groupId @@ -496,8 +496,9 @@ final class MutableChatListView { if let filterPredicate = self.filterPredicate { for (peerId, settingsChange) in updatedPeerNotificationSettings { if let peer = postbox.peerTable.get(peerId) { - let wasIncluded = filterPredicate(peer, settingsChange.0) - let isIncluded = filterPredicate(peer, settingsChange.1) + let isUnread = postbox.readStateTable.getCombinedState(peerId)?.isUnread ?? false + let wasIncluded = filterPredicate(peer, settingsChange.0, isUnread) + let isIncluded = filterPredicate(peer, settingsChange.1, isUnread) if wasIncluded != isIncluded { if isIncluded { if let entry = postbox.chatListTable.getEntry(groupId: self.groupId, peerId: peerId, messageHistoryTable: postbox.messageHistoryTable, peerChatInterfaceStateTable: postbox.peerChatInterfaceStateTable) { @@ -664,7 +665,8 @@ final class MutableChatListView { switch initialEntry { case .IntermediateMessageEntry(let index, _, _, _), .MessageEntry(let index, _, _, _, _, _, _, _, _): if let peer = postbox.peerTable.get(index.messageIndex.id.peerId) { - if !filterPredicate(peer, postbox.peerNotificationSettingsTable.getEffective(index.messageIndex.id.peerId)) { + let isUnread = postbox.readStateTable.getCombinedState(index.messageIndex.id.peerId)?.isUnread ?? false + if !filterPredicate(peer, postbox.peerNotificationSettingsTable.getEffective(index.messageIndex.id.peerId), isUnread) { return false } } else { diff --git a/submodules/Postbox/Sources/MessageHistoryViewState.swift b/submodules/Postbox/Sources/MessageHistoryViewState.swift index 10dd22b484..731a0d4263 100644 --- a/submodules/Postbox/Sources/MessageHistoryViewState.swift +++ b/submodules/Postbox/Sources/MessageHistoryViewState.swift @@ -1,8 +1,13 @@ import Foundation -struct PeerIdAndNamespace: Hashable { - let peerId: PeerId - let namespace: MessageId.Namespace +public struct PeerIdAndNamespace: Hashable { + public let peerId: PeerId + public let namespace: MessageId.Namespace + + public init(peerId: PeerId, namespace: MessageId.Namespace) { + self.peerId = peerId + self.namespace = namespace + } } private func canContainHoles(_ peerIdAndNamespace: PeerIdAndNamespace, seedConfiguration: SeedConfiguration) -> Bool { diff --git a/submodules/Postbox/Sources/Postbox.swift b/submodules/Postbox/Sources/Postbox.swift index 8ce0ed2c6e..31548f7f4f 100644 --- a/submodules/Postbox/Sources/Postbox.swift +++ b/submodules/Postbox/Sources/Postbox.swift @@ -1362,11 +1362,14 @@ public final class Postbox { print("(Postbox initialization took \((CFAbsoluteTimeGetCurrent() - startTime) * 1000.0) ms") let _ = self.transaction({ transaction -> Void in - let reindexUnreadVersion: Int32 = 1 + let reindexUnreadVersion: Int32 = 2 if self.messageHistoryMetadataTable.getShouldReindexUnreadCountsState() != reindexUnreadVersion { self.messageHistoryMetadataTable.setShouldReindexUnreadCounts(value: true) self.messageHistoryMetadataTable.setShouldReindexUnreadCountsState(value: reindexUnreadVersion) } + #if DEBUG + self.messageHistoryMetadataTable.setShouldReindexUnreadCounts(value: true) + #endif if self.messageHistoryMetadataTable.shouldReindexUnreadCounts() { self.groupMessageStatsTable.removeAll() @@ -1650,12 +1653,13 @@ public final class Postbox { self.synchronizeGroupMessageStatsTable.set(groupId: groupId, namespace: namespace, needsValidation: false, operations: &self.currentUpdatedGroupSummarySynchronizeOperations) } - private func mappedChatListFilterPredicate(_ predicate: @escaping (Peer, PeerNotificationSettings?) -> Bool) -> (ChatListIntermediateEntry) -> Bool { + private func mappedChatListFilterPredicate(_ predicate: @escaping (Peer, PeerNotificationSettings?, Bool) -> Bool) -> (ChatListIntermediateEntry) -> Bool { return { entry in switch entry { case let .message(index, _, _): if let peer = self.peerTable.get(index.messageIndex.id.peerId) { - if predicate(peer, self.peerNotificationSettingsTable.getEffective(index.messageIndex.id.peerId)) { + let isUnread = self.readStateTable.getCombinedState(index.messageIndex.id.peerId)?.isUnread ?? false + if predicate(peer, self.peerNotificationSettingsTable.getEffective(index.messageIndex.id.peerId), isUnread) { return true } else { return false @@ -1669,7 +1673,7 @@ public final class Postbox { } } - func fetchAroundChatEntries(groupId: PeerGroupId, index: ChatListIndex, count: Int, filterPredicate: ((Peer, PeerNotificationSettings?) -> Bool)?) -> (entries: [MutableChatListEntry], earlier: MutableChatListEntry?, later: MutableChatListEntry?) { + func fetchAroundChatEntries(groupId: PeerGroupId, index: ChatListIndex, count: Int, filterPredicate: ((Peer, PeerNotificationSettings?, Bool) -> Bool)?) -> (entries: [MutableChatListEntry], earlier: MutableChatListEntry?, later: MutableChatListEntry?) { let mappedPredicate = filterPredicate.flatMap(self.mappedChatListFilterPredicate) let (intermediateEntries, intermediateLower, intermediateUpper) = self.chatListTable.entriesAround(groupId: groupId, index: index, messageHistoryTable: self.messageHistoryTable, peerChatInterfaceStateTable: self.peerChatInterfaceStateTable, count: count, predicate: mappedPredicate) let entries: [MutableChatListEntry] = intermediateEntries.map { entry in @@ -1685,7 +1689,7 @@ public final class Postbox { return (entries, lower, upper) } - func fetchEarlierChatEntries(groupId: PeerGroupId, index: ChatListIndex?, count: Int, filterPredicate: ((Peer, PeerNotificationSettings?) -> Bool)?) -> [MutableChatListEntry] { + func fetchEarlierChatEntries(groupId: PeerGroupId, index: ChatListIndex?, count: Int, filterPredicate: ((Peer, PeerNotificationSettings?, Bool) -> Bool)?) -> [MutableChatListEntry] { let mappedPredicate = filterPredicate.flatMap(self.mappedChatListFilterPredicate) let intermediateEntries = self.chatListTable.earlierEntries(groupId: groupId, index: index.flatMap({ ($0, true) }), messageHistoryTable: self.messageHistoryTable, peerChatInterfaceStateTable: self.peerChatInterfaceStateTable, count: count, predicate: mappedPredicate) let entries: [MutableChatListEntry] = intermediateEntries.map { entry in @@ -1694,7 +1698,7 @@ public final class Postbox { return entries } - func fetchLaterChatEntries(groupId: PeerGroupId, index: ChatListIndex?, count: Int, filterPredicate: ((Peer, PeerNotificationSettings?) -> Bool)?) -> [MutableChatListEntry] { + func fetchLaterChatEntries(groupId: PeerGroupId, index: ChatListIndex?, count: Int, filterPredicate: ((Peer, PeerNotificationSettings?, Bool) -> Bool)?) -> [MutableChatListEntry] { let mappedPredicate = filterPredicate.flatMap(self.mappedChatListFilterPredicate) let intermediateEntries = self.chatListTable.laterEntries(groupId: groupId, index: index.flatMap({ ($0, true) }), messageHistoryTable: self.messageHistoryTable, peerChatInterfaceStateTable: self.peerChatInterfaceStateTable, count: count, predicate: mappedPredicate) let entries: [MutableChatListEntry] = intermediateEntries.map { entry in @@ -2542,11 +2546,11 @@ public final class Postbox { |> switchToLatest } - public func tailChatListView(groupId: PeerGroupId, filterPredicate: ((Peer, PeerNotificationSettings?) -> Bool)? = nil, count: Int, summaryComponents: ChatListEntrySummaryComponents) -> Signal<(ChatListView, ViewUpdateType), NoError> { + public func tailChatListView(groupId: PeerGroupId, filterPredicate: ((Peer, PeerNotificationSettings?, Bool) -> Bool)? = nil, count: Int, summaryComponents: ChatListEntrySummaryComponents) -> Signal<(ChatListView, ViewUpdateType), NoError> { return self.aroundChatListView(groupId: groupId, filterPredicate: filterPredicate, index: ChatListIndex.absoluteUpperBound, count: count, summaryComponents: summaryComponents, userInteractive: true) } - public func aroundChatListView(groupId: PeerGroupId, filterPredicate: ((Peer, PeerNotificationSettings?) -> Bool)? = nil, index: ChatListIndex, count: Int, summaryComponents: ChatListEntrySummaryComponents, userInteractive: Bool = false) -> Signal<(ChatListView, ViewUpdateType), NoError> { + public func aroundChatListView(groupId: PeerGroupId, filterPredicate: ((Peer, PeerNotificationSettings?, Bool) -> Bool)? = nil, index: ChatListIndex, count: Int, summaryComponents: ChatListEntrySummaryComponents, userInteractive: Bool = false) -> Signal<(ChatListView, ViewUpdateType), NoError> { return self.transactionSignal(userInteractive: userInteractive, { subscriber, transaction in let mutableView = MutableChatListView(postbox: self, groupId: groupId, filterPredicate: filterPredicate, aroundIndex: index, count: count, summaryComponents: summaryComponents) mutableView.render(postbox: self, renderMessage: self.renderIntermediateMessage, getPeer: { id in diff --git a/submodules/SettingsUI/Sources/Notifications/NotificationsAndSounds.swift b/submodules/SettingsUI/Sources/Notifications/NotificationsAndSounds.swift index 3db7091c49..f2ece41feb 100644 --- a/submodules/SettingsUI/Sources/Notifications/NotificationsAndSounds.swift +++ b/submodules/SettingsUI/Sources/Notifications/NotificationsAndSounds.swift @@ -17,6 +17,49 @@ import TelegramNotices import NotificationSoundSelectionUI import TelegramStringFormatting +private struct CounterTagSettings: OptionSet { + var rawValue: Int32 + + init(rawValue: Int32) { + self.rawValue = rawValue + } + + init(summaryTags: PeerSummaryCounterTags) { + var result = CounterTagSettings() + if summaryTags.contains(.privateChat) { + result.insert(.regularChatsAndPrivateGroups) + } + if summaryTags.contains(.channel) { + result.insert(.channels) + } + if summaryTags.contains(.publicGroup) { + result.insert(.publicGroups) + } + self = result + } + + func toSumaryTags() -> PeerSummaryCounterTags { + var result = PeerSummaryCounterTags() + if self.contains(.regularChatsAndPrivateGroups) { + result.insert(.privateChat) + result.insert(.secretChat) + result.insert(.bot) + result.insert(.privateGroup) + } + if self.contains(.publicGroups) { + result.insert(.publicGroup) + } + if self.contains(.channels) { + result.insert(.channel) + } + return result + } + + static let regularChatsAndPrivateGroups = CounterTagSettings(rawValue: 1 << 0) + static let publicGroups = CounterTagSettings(rawValue: 1 << 1) + static let channels = CounterTagSettings(rawValue: 1 << 2) +} + private final class NotificationsAndSoundsArguments { let context: AccountContext let presentController: (ViewController, ViewControllerPresentationArguments?) -> Void @@ -43,7 +86,7 @@ private final class NotificationsAndSoundsArguments { let updateInAppPreviews: (Bool) -> Void let updateDisplayNameOnLockscreen: (Bool) -> Void - let updateIncludeTag: (PeerSummaryCounterTags, Bool) -> Void + let updateIncludeTag: (CounterTagSettings, Bool) -> Void let updateTotalUnreadCountCategory: (Bool) -> Void let updateJoinedNotifications: (Bool) -> Void @@ -56,7 +99,7 @@ private final class NotificationsAndSoundsArguments { let updateNotificationsFromAllAccounts: (Bool) -> Void - init(context: AccountContext, presentController: @escaping (ViewController, ViewControllerPresentationArguments?) -> Void, pushController: @escaping(ViewController)->Void, soundSelectionDisposable: MetaDisposable, authorizeNotifications: @escaping () -> Void, suppressWarning: @escaping () -> Void, updateMessageAlerts: @escaping (Bool) -> Void, updateMessagePreviews: @escaping (Bool) -> Void, updateMessageSound: @escaping (PeerMessageSound) -> Void, updateGroupAlerts: @escaping (Bool) -> Void, updateGroupPreviews: @escaping (Bool) -> Void, updateGroupSound: @escaping (PeerMessageSound) -> Void, updateChannelAlerts: @escaping (Bool) -> Void, updateChannelPreviews: @escaping (Bool) -> Void, updateChannelSound: @escaping (PeerMessageSound) -> Void, updateInAppSounds: @escaping (Bool) -> Void, updateInAppVibration: @escaping (Bool) -> Void, updateInAppPreviews: @escaping (Bool) -> Void, updateDisplayNameOnLockscreen: @escaping (Bool) -> Void, updateIncludeTag: @escaping (PeerSummaryCounterTags, Bool) -> Void, updateTotalUnreadCountCategory: @escaping (Bool) -> Void, resetNotifications: @escaping () -> Void, updatedExceptionMode: @escaping(NotificationExceptionMode) -> Void, openAppSettings: @escaping () -> Void, updateJoinedNotifications: @escaping (Bool) -> Void, updateNotificationsFromAllAccounts: @escaping (Bool) -> Void) { + init(context: AccountContext, presentController: @escaping (ViewController, ViewControllerPresentationArguments?) -> Void, pushController: @escaping(ViewController)->Void, soundSelectionDisposable: MetaDisposable, authorizeNotifications: @escaping () -> Void, suppressWarning: @escaping () -> Void, updateMessageAlerts: @escaping (Bool) -> Void, updateMessagePreviews: @escaping (Bool) -> Void, updateMessageSound: @escaping (PeerMessageSound) -> Void, updateGroupAlerts: @escaping (Bool) -> Void, updateGroupPreviews: @escaping (Bool) -> Void, updateGroupSound: @escaping (PeerMessageSound) -> Void, updateChannelAlerts: @escaping (Bool) -> Void, updateChannelPreviews: @escaping (Bool) -> Void, updateChannelSound: @escaping (PeerMessageSound) -> Void, updateInAppSounds: @escaping (Bool) -> Void, updateInAppVibration: @escaping (Bool) -> Void, updateInAppPreviews: @escaping (Bool) -> Void, updateDisplayNameOnLockscreen: @escaping (Bool) -> Void, updateIncludeTag: @escaping (CounterTagSettings, Bool) -> Void, updateTotalUnreadCountCategory: @escaping (Bool) -> Void, resetNotifications: @escaping () -> Void, updatedExceptionMode: @escaping(NotificationExceptionMode) -> Void, openAppSettings: @escaping () -> Void, updateJoinedNotifications: @escaping (Bool) -> Void, updateNotificationsFromAllAccounts: @escaping (Bool) -> Void) { self.context = context self.presentController = presentController self.pushController = pushController @@ -779,8 +822,11 @@ private func notificationsAndSoundsEntries(authorizationStatus: AccessType, warn entries.append(.displayNamesOnLockscreenInfo(presentationData.theme, presentationData.strings.Notifications_DisplayNamesOnLockScreenInfoWithLink)) entries.append(.badgeHeader(presentationData.theme, presentationData.strings.Notifications_Badge.uppercased())) - entries.append(.includePublicGroups(presentationData.theme, presentationData.strings.Notifications_Badge_IncludePublicGroups, inAppSettings.totalUnreadCountIncludeTags.contains(.publicGroups))) - entries.append(.includeChannels(presentationData.theme, presentationData.strings.Notifications_Badge_IncludeChannels, inAppSettings.totalUnreadCountIncludeTags.contains(.channels))) + + let counterTagSettings = CounterTagSettings(summaryTags: inAppSettings.totalUnreadCountIncludeTags) + + entries.append(.includePublicGroups(presentationData.theme, presentationData.strings.Notifications_Badge_IncludePublicGroups, counterTagSettings.contains(.publicGroups))) + entries.append(.includeChannels(presentationData.theme, presentationData.strings.Notifications_Badge_IncludeChannels, counterTagSettings.contains(.channels))) entries.append(.unreadCountCategory(presentationData.theme, presentationData.strings.Notifications_Badge_CountUnreadMessages, inAppSettings.totalUnreadCountDisplayCategory == .messages)) entries.append(.unreadCountCategoryInfo(presentationData.theme, inAppSettings.totalUnreadCountDisplayCategory == .chats ? presentationData.strings.Notifications_Badge_CountUnreadMessages_InfoOff : presentationData.strings.Notifications_Badge_CountUnreadMessages_InfoOn)) entries.append(.joinedNotifications(presentationData.theme, presentationData.strings.NotificationSettings_ContactJoined, globalSettings.contactsJoined)) @@ -911,12 +957,14 @@ public func notificationsAndSoundsController(context: AccountContext, exceptions }).start() }, updateIncludeTag: { tag, value in let _ = updateInAppNotificationSettingsInteractively(accountManager: context.sharedContext.accountManager, { settings in - var settings = settings + var currentSettings = CounterTagSettings(summaryTags: settings.totalUnreadCountIncludeTags) if !value { - settings.totalUnreadCountIncludeTags.remove(tag) + currentSettings.remove(tag) } else { - settings.totalUnreadCountIncludeTags.insert(tag) + currentSettings.insert(tag) } + var settings = settings + settings.totalUnreadCountIncludeTags = currentSettings.toSumaryTags() return settings }).start() }, updateTotalUnreadCountCategory: { value in diff --git a/submodules/SyncCore/Sources/Namespaces.swift b/submodules/SyncCore/Sources/Namespaces.swift index 96db1f9af2..5317234ea5 100644 --- a/submodules/SyncCore/Sources/Namespaces.swift +++ b/submodules/SyncCore/Sources/Namespaces.swift @@ -139,10 +139,44 @@ public struct OperationLogTags { public static let SynchronizeEmojiKeywords = PeerOperationLogTag(value: 19) } +public struct LegacyPeerSummaryCounterTags: OptionSet, Sequence, Hashable { + public var rawValue: Int32 + + public init(rawValue: Int32) { + self.rawValue = rawValue + } + + public static let regularChatsAndPrivateGroups = LegacyPeerSummaryCounterTags(rawValue: 1 << 0) + public static let publicGroups = LegacyPeerSummaryCounterTags(rawValue: 1 << 1) + public static let channels = LegacyPeerSummaryCounterTags(rawValue: 1 << 2) + + public func makeIterator() -> AnyIterator { + var index = 0 + return AnyIterator { () -> LegacyPeerSummaryCounterTags? in + while index < 31 { + let currentTags = self.rawValue >> UInt32(index) + let tag = LegacyPeerSummaryCounterTags(rawValue: 1 << UInt32(index)) + index += 1 + if currentTags == 0 { + break + } + + if (currentTags & 1) != 0 { + return tag + } + } + return nil + } + } +} + public extension PeerSummaryCounterTags { - static let regularChatsAndPrivateGroups = PeerSummaryCounterTags(rawValue: 1 << 0) - static let publicGroups = PeerSummaryCounterTags(rawValue: 1 << 1) - static let channels = PeerSummaryCounterTags(rawValue: 1 << 2) + static let privateChat = PeerSummaryCounterTags(rawValue: 1 << 3) + static let secretChat = PeerSummaryCounterTags(rawValue: 1 << 4) + static let privateGroup = PeerSummaryCounterTags(rawValue: 1 << 5) + static let bot = PeerSummaryCounterTags(rawValue: 1 << 6) + static let channel = PeerSummaryCounterTags(rawValue: 1 << 7) + static let publicGroup = PeerSummaryCounterTags(rawValue: 1 << 8) } private enum PreferencesKeyValues: Int32 { diff --git a/submodules/SyncCore/Sources/StandaloneAccountTransaction.swift b/submodules/SyncCore/Sources/StandaloneAccountTransaction.swift index 93d625cb33..443881967e 100644 --- a/submodules/SyncCore/Sources/StandaloneAccountTransaction.swift +++ b/submodules/SyncCore/Sources/StandaloneAccountTransaction.swift @@ -19,19 +19,30 @@ public let telegramPostboxSeedConfiguration: SeedConfiguration = { } return SeedConfiguration(globalMessageIdsPeerIdNamespaces: globalMessageIdsPeerIdNamespaces, initializeChatListWithHole: (topLevel: ChatListHole(index: MessageIndex(id: MessageId(peerId: PeerId(namespace: Namespaces.Peer.Empty, id: 0), namespace: Namespaces.Message.Cloud, id: 1), timestamp: Int32.max - 1)), groups: ChatListHole(index: MessageIndex(id: MessageId(peerId: PeerId(namespace: Namespaces.Peer.Empty, id: 0), namespace: Namespaces.Message.Cloud, id: 1), timestamp: Int32.max - 1))), messageHoles: messageHoles, existingMessageTags: MessageTags.all, messageTagsWithSummary: MessageTags.unseenPersonalMessage, existingGlobalMessageTags: GlobalMessageTags.all, peerNamespacesRequiringMessageTextIndex: [Namespaces.Peer.SecretChat], peerSummaryCounterTags: { peer in - if let peer = peer as? TelegramChannel { - switch peer.info { - case .group: - if let addressName = peer.username, !addressName.isEmpty { - return [.publicGroups] - } else { - return [.regularChatsAndPrivateGroups] - } - case .broadcast: - return [.channels] + if let peer = peer as? TelegramUser { + if peer.botInfo != nil { + return .bot + } else { + return .privateChat + } + } else if let _ = peer as? TelegramGroup { + return .privateGroup + } else if let _ = peer as? TelegramSecretChat { + return .secretChat + } else if let channel = peer as? TelegramChannel { + switch channel.info { + case .broadcast: + return .channel + case .group: + if channel.username != nil { + return .publicGroup + } else { + return .privateGroup + } } } else { - return [.regularChatsAndPrivateGroups] + assertionFailure() + return .privateChat } }, additionalChatListIndexNamespace: Namespaces.Message.Cloud, messageNamespacesRequiringGroupStatsValidation: [Namespaces.Message.Cloud], defaultMessageNamespaceReadStates: [Namespaces.Message.Local: .idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 0, markedUnread: false)], chatMessagesNamespaces: Set([Namespaces.Message.Cloud, Namespaces.Message.Local, Namespaces.Message.SecretIncoming])) }() diff --git a/submodules/TelegramCore/Sources/AccountViewTracker.swift b/submodules/TelegramCore/Sources/AccountViewTracker.swift index 0d5ebe5678..23b6ecfb54 100644 --- a/submodules/TelegramCore/Sources/AccountViewTracker.swift +++ b/submodules/TelegramCore/Sources/AccountViewTracker.swift @@ -1330,7 +1330,7 @@ public final class AccountViewTracker { }) } - public func tailChatListView(groupId: PeerGroupId, filterPredicate: ((Peer, PeerNotificationSettings?) -> Bool)? = nil, count: Int) -> Signal<(ChatListView, ViewUpdateType), NoError> { + public func tailChatListView(groupId: PeerGroupId, filterPredicate: ((Peer, PeerNotificationSettings?, Bool) -> Bool)? = nil, count: Int) -> Signal<(ChatListView, ViewUpdateType), NoError> { if let account = self.account { return self.wrappedChatListView(signal: account.postbox.tailChatListView(groupId: groupId, filterPredicate: filterPredicate, count: count, summaryComponents: ChatListEntrySummaryComponents(tagSummary: ChatListEntryMessageTagSummaryComponent(tag: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud), actionsSummary: ChatListEntryPendingMessageActionsSummaryComponent(type: PendingMessageActionType.consumeUnseenPersonalMessage, namespace: Namespaces.Message.Cloud)))) } else { @@ -1338,7 +1338,7 @@ public final class AccountViewTracker { } } - public func aroundChatListView(groupId: PeerGroupId, filterPredicate: ((Peer, PeerNotificationSettings?) -> Bool)? = nil, index: ChatListIndex, count: Int) -> Signal<(ChatListView, ViewUpdateType), NoError> { + public func aroundChatListView(groupId: PeerGroupId, filterPredicate: ((Peer, PeerNotificationSettings?, Bool) -> Bool)? = nil, index: ChatListIndex, count: Int) -> Signal<(ChatListView, ViewUpdateType), NoError> { if let account = self.account { return self.wrappedChatListView(signal: account.postbox.aroundChatListView(groupId: groupId, filterPredicate: filterPredicate, index: index, count: count, summaryComponents: ChatListEntrySummaryComponents(tagSummary: ChatListEntryMessageTagSummaryComponent(tag: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud), actionsSummary: ChatListEntryPendingMessageActionsSummaryComponent(type: PendingMessageActionType.consumeUnseenPersonalMessage, namespace: Namespaces.Message.Cloud)))) } else { diff --git a/submodules/TelegramUI/TelegramUI/DeclareEncodables.swift b/submodules/TelegramUI/TelegramUI/DeclareEncodables.swift index 8de131f329..01c3ef9546 100644 --- a/submodules/TelegramUI/TelegramUI/DeclareEncodables.swift +++ b/submodules/TelegramUI/TelegramUI/DeclareEncodables.swift @@ -54,6 +54,7 @@ private var telegramUIDeclaredEncodables: Void = { declareEncodable(WebBrowserSettings.self, f: { WebBrowserSettings(decoder: $0) }) declareEncodable(IntentsSettings.self, f: { IntentsSettings(decoder: $0) }) declareEncodable(CachedGeocode.self, f: { CachedGeocode(decoder: $0) }) + declareEncodable(ChatListFilterSettings.self, f: { ChatListFilterSettings(decoder: $0) }) return }() diff --git a/submodules/TelegramUIPreferences/Sources/ChatListFilterSettings.swift b/submodules/TelegramUIPreferences/Sources/ChatListFilterSettings.swift new file mode 100644 index 0000000000..de6105939d --- /dev/null +++ b/submodules/TelegramUIPreferences/Sources/ChatListFilterSettings.swift @@ -0,0 +1,127 @@ +import Foundation +import Postbox +import SwiftSignalKit +import SyncCore + +public struct ChatListIncludeCategoryFilter: OptionSet { + public var rawValue: Int32 + + public init(rawValue: Int32) { + self.rawValue = rawValue + } + + public static let muted = ChatListIncludeCategoryFilter(rawValue: 1 << 1) + public static let privateChats = ChatListIncludeCategoryFilter(rawValue: 1 << 2) + public static let secretChats = ChatListIncludeCategoryFilter(rawValue: 1 << 3) + public static let privateGroups = ChatListIncludeCategoryFilter(rawValue: 1 << 4) + public static let bots = ChatListIncludeCategoryFilter(rawValue: 1 << 5) + public static let publicGroups = ChatListIncludeCategoryFilter(rawValue: 1 << 6) + public static let channels = ChatListIncludeCategoryFilter(rawValue: 1 << 7) + public static let read = ChatListIncludeCategoryFilter(rawValue: 1 << 8) + + public static let all: ChatListIncludeCategoryFilter = [ + .muted, + .privateChats, + .secretChats, + .privateGroups, + .bots, + .publicGroups, + .channels, + .read + ] +} + +public enum ChatListFilterPresetName: Equatable, Hashable, PostboxCoding { + case unread + case custom(String) + + public init(decoder: PostboxDecoder) { + switch decoder.decodeInt32ForKey("_t", orElse: 0) { + case 0: + self = .unread + case 1: + self = .custom(decoder.decodeStringForKey("title", orElse: "Preset")) + default: + assertionFailure() + self = .custom("Preset") + } + } + + public func encode(_ encoder: PostboxEncoder) { + switch self { + case .unread: + encoder.encodeInt32(0, forKey: "_t") + case let .custom(title): + encoder.encodeInt32(1, forKey: "_t") + encoder.encodeString(title, forKey: "title") + } + } +} + +public struct ChatListFilterPreset: Equatable, PostboxCoding { + public var name: ChatListFilterPresetName + public var includeCategories: ChatListIncludeCategoryFilter + public var additionallyIncludePeers: [PeerId] + + public init(name: ChatListFilterPresetName, includeCategories: ChatListIncludeCategoryFilter, additionallyIncludePeers: [PeerId]) { + self.name = name + self.includeCategories = includeCategories + self.additionallyIncludePeers = additionallyIncludePeers + } + + public init(decoder: PostboxDecoder) { + self.name = decoder.decodeObjectForKey("name", decoder: { ChatListFilterPresetName(decoder: $0) }) as? ChatListFilterPresetName ?? ChatListFilterPresetName.custom("Preset") + self.includeCategories = ChatListIncludeCategoryFilter(rawValue: decoder.decodeInt32ForKey("includeCategories", orElse: 0)) + self.additionallyIncludePeers = decoder.decodeInt64ArrayForKey("additionallyIncludePeers").map(PeerId.init) + } + + public func encode(_ encoder: PostboxEncoder) { + encoder.encodeObject(self.name, forKey: "name") + encoder.encodeInt32(self.includeCategories.rawValue, forKey: "includeCategories") + encoder.encodeInt64Array(self.additionallyIncludePeers.map { $0.toInt64() }, forKey: "additionallyIncludePeers") + } +} + +public struct ChatListFilterSettings: PreferencesEntry, Equatable { + public var presets: [ChatListFilterPreset] + + public static var `default`: ChatListFilterSettings { + return ChatListFilterSettings(presets: [ + ChatListFilterPreset( + name: .unread, + includeCategories: ChatListIncludeCategoryFilter.all.subtracting(.read), + additionallyIncludePeers: [] + ) + ]) + } + + public init(presets: [ChatListFilterPreset]) { + self.presets = presets + } + + public init(decoder: PostboxDecoder) { + self.presets = decoder.decodeObjectArrayWithDecoderForKey("presets") + } + + public func encode(_ encoder: PostboxEncoder) { + encoder.encodeObjectArray(self.presets, forKey: "presets") + } + + public func isEqual(to: PreferencesEntry) -> Bool { + if let to = to as? ChatListFilterSettings { + return self == to + } else { + return false + } + } +} + +public func updateChatListFilterSettingsInteractively(postbox: Postbox, _ f: @escaping (ChatListFilterSettings) -> ChatListFilterSettings) -> Signal { + return postbox.transaction { transaction -> Void in + transaction.updatePreferencesEntry(key: ApplicationSpecificPreferencesKeys.chatListFilterSettings, { entry in + var settings = entry as? ChatListFilterSettings ?? ChatListFilterSettings.default + return f(settings) + }) + } + |> ignoreValues +} diff --git a/submodules/TelegramUIPreferences/Sources/InAppNotificationSettings.swift b/submodules/TelegramUIPreferences/Sources/InAppNotificationSettings.swift index e1c47d10f7..3da4f51362 100644 --- a/submodules/TelegramUIPreferences/Sources/InAppNotificationSettings.swift +++ b/submodules/TelegramUIPreferences/Sources/InAppNotificationSettings.swift @@ -1,6 +1,7 @@ import Foundation import Postbox import SwiftSignalKit +import SyncCore public enum TotalUnreadCountDisplayStyle: Int32 { case filtered = 0 @@ -38,7 +39,7 @@ public struct InAppNotificationSettings: PreferencesEntry, Equatable { public var displayNotificationsFromAllAccounts: Bool public static var defaultSettings: InAppNotificationSettings { - return InAppNotificationSettings(playSounds: true, vibrate: false, displayPreviews: true, totalUnreadCountDisplayStyle: .filtered, totalUnreadCountDisplayCategory: .messages, totalUnreadCountIncludeTags: [.regularChatsAndPrivateGroups], displayNameOnLockscreen: true, displayNotificationsFromAllAccounts: true) + return InAppNotificationSettings(playSounds: true, vibrate: false, displayPreviews: true, totalUnreadCountDisplayStyle: .filtered, totalUnreadCountDisplayCategory: .messages, totalUnreadCountIncludeTags: [.privateChat, .secretChat, .bot, .privateGroup], displayNameOnLockscreen: true, displayNotificationsFromAllAccounts: true) } public init(playSounds: Bool, vibrate: Bool, displayPreviews: Bool, totalUnreadCountDisplayStyle: TotalUnreadCountDisplayStyle, totalUnreadCountDisplayCategory: TotalUnreadCountDisplayCategory, totalUnreadCountIncludeTags: PeerSummaryCounterTags, displayNameOnLockscreen: Bool, displayNotificationsFromAllAccounts: Bool) { @@ -58,10 +59,25 @@ public struct InAppNotificationSettings: PreferencesEntry, Equatable { self.displayPreviews = decoder.decodeInt32ForKey("p", orElse: 0) != 0 self.totalUnreadCountDisplayStyle = TotalUnreadCountDisplayStyle(rawValue: decoder.decodeInt32ForKey("cds", orElse: 0)) ?? .filtered self.totalUnreadCountDisplayCategory = TotalUnreadCountDisplayCategory(rawValue: decoder.decodeInt32ForKey("totalUnreadCountDisplayCategory", orElse: 1)) ?? .messages - if let value = decoder.decodeOptionalInt32ForKey("totalUnreadCountIncludeTags") { + if let value = decoder.decodeOptionalInt32ForKey("totalUnreadCountIncludeTags_2") { self.totalUnreadCountIncludeTags = PeerSummaryCounterTags(rawValue: value) + } else if let value = decoder.decodeOptionalInt32ForKey("totalUnreadCountIncludeTags") { + var resultTags: PeerSummaryCounterTags = [] + for legacyTag in LegacyPeerSummaryCounterTags(rawValue: value) { + if legacyTag == .regularChatsAndPrivateGroups { + resultTags.insert(.privateChat) + resultTags.insert(.secretChat) + resultTags.insert(.bot) + resultTags.insert(.privateGroup) + } else if legacyTag == .publicGroups { + resultTags.insert(.publicGroup) + } else if legacyTag == .channels { + resultTags.insert(.channel) + } + } + self.totalUnreadCountIncludeTags = resultTags } else { - self.totalUnreadCountIncludeTags = [.regularChatsAndPrivateGroups] + self.totalUnreadCountIncludeTags = [.privateChat, .secretChat, .bot, .privateGroup] } self.displayNameOnLockscreen = decoder.decodeInt32ForKey("displayNameOnLockscreen", orElse: 1) != 0 self.displayNotificationsFromAllAccounts = decoder.decodeInt32ForKey("displayNotificationsFromAllAccounts", orElse: 1) != 0 @@ -73,7 +89,7 @@ public struct InAppNotificationSettings: PreferencesEntry, Equatable { encoder.encodeInt32(self.displayPreviews ? 1 : 0, forKey: "p") encoder.encodeInt32(self.totalUnreadCountDisplayStyle.rawValue, forKey: "cds") encoder.encodeInt32(self.totalUnreadCountDisplayCategory.rawValue, forKey: "totalUnreadCountDisplayCategory") - encoder.encodeInt32(self.totalUnreadCountIncludeTags.rawValue, forKey: "totalUnreadCountIncludeTags") + encoder.encodeInt32(self.totalUnreadCountIncludeTags.rawValue, forKey: "totalUnreadCountIncludeTags_2") encoder.encodeInt32(self.displayNameOnLockscreen ? 1 : 0, forKey: "displayNameOnLockscreen") encoder.encodeInt32(self.displayNotificationsFromAllAccounts ? 1 : 0, forKey: "displayNotificationsFromAllAccounts") } diff --git a/submodules/TelegramUIPreferences/Sources/PostboxKeys.swift b/submodules/TelegramUIPreferences/Sources/PostboxKeys.swift index 52ac48e6e7..17f712a5e0 100644 --- a/submodules/TelegramUIPreferences/Sources/PostboxKeys.swift +++ b/submodules/TelegramUIPreferences/Sources/PostboxKeys.swift @@ -6,11 +6,13 @@ import Postbox private enum ApplicationSpecificPreferencesKeyValues: Int32 { case voipDerivedState = 16 case chatArchiveSettings = 17 + case chatListFilterSettings = 18 } public struct ApplicationSpecificPreferencesKeys { public static let voipDerivedState = applicationSpecificPreferencesKey(ApplicationSpecificPreferencesKeyValues.voipDerivedState.rawValue) public static let chatArchiveSettings = applicationSpecificPreferencesKey(ApplicationSpecificPreferencesKeyValues.chatArchiveSettings.rawValue) + public static let chatListFilterSettings = applicationSpecificPreferencesKey(ApplicationSpecificPreferencesKeyValues.chatListFilterSettings.rawValue) } private enum ApplicationSpecificSharedDataKeyValues: Int32 { From 77826e91d4b1f90e878b227c13d002c9af511b69 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Tue, 28 Jan 2020 19:46:28 +0400 Subject: [PATCH 36/50] Chat List Filter improvements --- .../Sources/ChatListController.swift | 18 +++++- .../ChatListFilterPresetController.swift | 60 +++++++++++++----- .../ChatListFilterPresetListController.swift | 17 ++--- .../Sources/Node/ChatListNode.swift | 52 ++++++++------- .../Sources/Node/ChatListNodeLocation.swift | 35 +++++------ .../Sources/Node/ChatListViewTransition.swift | 2 +- .../TabBarChatListFilterController.swift | 2 +- .../Sources/AllChatListHolesView.swift | 63 +++++++++++++++++++ .../Postbox/Sources/ChatListIndexTable.swift | 11 ++-- .../Postbox/Sources/ChatListTable.swift | 29 +++++++++ submodules/Postbox/Sources/Views.swift | 11 ++++ .../Sources/ManagedChatListHoles.swift | 37 +++++++++-- .../Sources/ChatListFilterSettings.swift | 18 ++++-- 13 files changed, 266 insertions(+), 89 deletions(-) create mode 100644 submodules/Postbox/Sources/AllChatListHolesView.swift diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index e86ca39607..57510f6e06 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -1822,7 +1822,23 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, guard let strongSelf = self else { return } - strongSelf.push(chatListFilterPresetListController(context: strongSelf.context)) + strongSelf.push(chatListFilterPresetListController(context: strongSelf.context, updated: { presets in + guard let strongSelf = self else { + return + } + if let currentPreset = strongSelf.chatListDisplayNode.chatListNode.chatListFilter { + var found = false + if let index = presets.index(where: { $0.id == currentPreset.id }) { + found = true + if currentPreset != presets[index] { + strongSelf.chatListDisplayNode.chatListNode.chatListFilter = presets[index] + } + } + if !found { + strongSelf.chatListDisplayNode.chatListNode.chatListFilter = nil + } + } + })) }, updatePreset: { value in guard let strongSelf = self else { return diff --git a/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift b/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift index 4599784653..517bc1a116 100644 --- a/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift +++ b/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift @@ -53,9 +53,11 @@ private func filterEntry(presentationData: ItemListPresentationData, arguments: private enum ChatListFilterPresetEntryStableId: Hashable { case index(Int) case peer(PeerId) + case additionalPeerInfo } private enum ChatListFilterPresetEntry: ItemListNodeEntry { + case nameHeader(String) case name(placeholder: String, value: String) case filterPrivateChats(title: String, value: Bool) case filterSecretChats(title: String, value: Bool) @@ -68,46 +70,51 @@ private enum ChatListFilterPresetEntry: ItemListNodeEntry { case additionalPeersHeader(String) case addAdditionalPeer(title: String) case additionalPeer(index: Int, peer: RenderedPeer, isRevealed: Bool) + case additionalPeerInfo(String) var section: ItemListSectionId { switch self { - case .name: + case .nameHeader, .name: return ChatListFilterPresetControllerSection.name.rawValue case .filterPrivateChats, .filterSecretChats, .filterPrivateGroups, .filterBots, .filterPublicGroups, .filterChannels: return ChatListFilterPresetControllerSection.categories.rawValue case .filterMuted, .filterRead: return ChatListFilterPresetControllerSection.excludeCategories.rawValue - case .additionalPeersHeader, .addAdditionalPeer, .additionalPeer: + case .additionalPeersHeader, .addAdditionalPeer, .additionalPeer, .additionalPeerInfo: return ChatListFilterPresetControllerSection.additionalPeers.rawValue } } var stableId: ChatListFilterPresetEntryStableId { switch self { - case .name: + case .nameHeader: return .index(0) - case .filterPrivateChats: + case .name: return .index(1) - case .filterSecretChats: + case .filterPrivateChats: return .index(2) - case .filterPrivateGroups: + case .filterSecretChats: return .index(3) - case .filterBots: + case .filterPrivateGroups: return .index(4) - case .filterPublicGroups: + case .filterBots: return .index(5) - case .filterChannels: + case .filterPublicGroups: return .index(6) - case .filterMuted: + case .filterChannels: return .index(7) - case .filterRead: + case .filterMuted: return .index(8) - case .additionalPeersHeader: + case .filterRead: return .index(9) - case .addAdditionalPeer: + case .additionalPeersHeader: return .index(10) + case .addAdditionalPeer: + return .index(11) case let .additionalPeer(additionalPeer): return .peer(additionalPeer.peer.peerId) + case .additionalPeerInfo: + return .additionalPeerInfo } } @@ -119,6 +126,8 @@ private enum ChatListFilterPresetEntry: ItemListNodeEntry { return lhsIndex < rhsIndex case .peer: return true + case .additionalPeerInfo: + return true } case .peer: switch lhs { @@ -126,6 +135,8 @@ private enum ChatListFilterPresetEntry: ItemListNodeEntry { switch rhs.stableId { case .index: return false + case .additionalPeerInfo: + return true case .peer: switch rhs { case let .additionalPeer(rhsIndex, _, _): @@ -137,12 +148,23 @@ private enum ChatListFilterPresetEntry: ItemListNodeEntry { default: preconditionFailure() } + case .additionalPeerInfo: + switch rhs.stableId { + case .index: + return false + case .peer: + return false + case .additionalPeerInfo: + return false + } } } func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem { let arguments = arguments as! ChatListFilterPresetControllerArguments switch self { + case let .nameHeader(title): + return ItemListSectionHeaderItem(presentationData: presentationData, text: title, sectionId: self.section) case let .name(placeholder, value): return ItemListSingleLineInputItem(presentationData: presentationData, title: NSAttributedString(), text: value, placeholder: placeholder, type: .regular(capitalization: true, autocorrection: false), sectionId: self.section, textUpdated: { value in arguments.updateState { current in @@ -201,6 +223,8 @@ private enum ChatListFilterPresetEntry: ItemListNodeEntry { }, removePeer: { id in arguments.deleteAdditionalPeer(id) }) + case let .additionalPeerInfo(text): + return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section) } } } @@ -226,6 +250,7 @@ private struct ChatListFilterPresetControllerState: Equatable { private func chatListFilterPresetControllerEntries(presentationData: PresentationData, state: ChatListFilterPresetControllerState, peers: [RenderedPeer]) -> [ChatListFilterPresetEntry] { var entries: [ChatListFilterPresetEntry] = [] + entries.append(.nameHeader("NAME")) entries.append(.name(placeholder: "Preset Name", value: state.name)) entries.append(.filterPrivateChats(title: "Private Chats", value: state.includeCategories.contains(.privateChats))) @@ -245,10 +270,12 @@ private func chatListFilterPresetControllerEntries(presentationData: Presentatio entries.append(.additionalPeer(index: entries.count, peer: peer, isRevealed: state.revealedPeerId == peer.peerId)) } + entries.append(.additionalPeerInfo("These chats will always be included in the list.")) + return entries } -func chatListFilterPresetController(context: AccountContext, currentPreset: ChatListFilterPreset?) -> ViewController { +func chatListFilterPresetController(context: AccountContext, currentPreset: ChatListFilterPreset?, updated: @escaping ([ChatListFilterPreset]) -> Void) -> ViewController { let initialName: String if let currentPreset = currentPreset { switch currentPreset.name { @@ -352,14 +379,15 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat }) let rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Done), style: .bold, enabled: state.isComplete, action: { let state = stateValue.with { $0 } - let preset = ChatListFilterPreset(name: .custom(state.name), includeCategories: state.includeCategories, additionallyIncludePeers: state.additionallyIncludePeers) + let preset = ChatListFilterPreset(id: currentPreset?.id ?? arc4random64(), name: .custom(state.name), includeCategories: state.includeCategories, additionallyIncludePeers: state.additionallyIncludePeers) let _ = (updateChatListFilterSettingsInteractively(postbox: context.account.postbox, { settings in var settings = settings settings.presets = settings.presets.filter { $0 != preset && $0 != currentPreset } settings.presets.append(preset) return settings }) - |> deliverOnMainQueue).start(completed: { + |> deliverOnMainQueue).start(next: { settings in + updated(settings.presets) dismissImpl?() }) }) diff --git a/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift b/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift index d1f55c8d6d..3d51524b2a 100644 --- a/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift +++ b/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift @@ -46,7 +46,7 @@ private func stringForUserCount(_ peers: [PeerId: SelectivePrivacyPeer], strings private enum ChatListFilterPresetListEntryStableId: Hashable { case listHeader - case preset(ChatListFilterPresetName) + case preset(Int64) case addItem case listFooter } @@ -82,7 +82,7 @@ private enum ChatListFilterPresetListEntry: ItemListNodeEntry { case .listHeader: return .listHeader case let .preset(preset): - return .preset(preset.preset.name) + return .preset(preset.preset.id) case .addItem: return .addItem case .listFooter: @@ -141,7 +141,7 @@ private func chatListFilterPresetListControllerEntries(presentationData: Present return entries } -func chatListFilterPresetListController(context: AccountContext) -> ViewController { +func chatListFilterPresetListController(context: AccountContext, updated: @escaping ([ChatListFilterPreset]) -> Void) -> ViewController { let initialState = ChatListFilterPresetListControllerState() let statePromise = ValuePromise(initialState, ignoreRepeated: true) let stateValue = Atomic(value: initialState) @@ -154,9 +154,9 @@ func chatListFilterPresetListController(context: AccountContext) -> ViewControll var presentControllerImpl: ((ViewController, Any?) -> Void)? let arguments = ChatListFilterPresetListControllerArguments(context: context, openPreset: { preset in - pushControllerImpl?(chatListFilterPresetController(context: context, currentPreset: preset)) + pushControllerImpl?(chatListFilterPresetController(context: context, currentPreset: preset, updated: updated)) }, addNew: { - pushControllerImpl?(chatListFilterPresetController(context: context, currentPreset: nil)) + pushControllerImpl?(chatListFilterPresetController(context: context, currentPreset: nil, updated: updated)) }, setItemWithRevealedOptions: { preset, fromPreset in updateState { state in var state = state @@ -166,13 +166,16 @@ func chatListFilterPresetListController(context: AccountContext) -> ViewControll return state } }, removePreset: { preset in - let _ = updateChatListFilterSettingsInteractively(postbox: context.account.postbox, { settings in + let _ = (updateChatListFilterSettingsInteractively(postbox: context.account.postbox, { settings in var settings = settings if let index = settings.presets.index(of: preset) { settings.presets.remove(at: index) } return settings - }).start() + }) + |> deliverOnMainQueue).start(next: { settings in + updated(settings.presets) + }) }) let preferences = context.account.postbox.preferencesView(keys: [ApplicationSpecificPreferencesKeys.chatListFilterSettings]) diff --git a/submodules/ChatListUI/Sources/Node/ChatListNode.swift b/submodules/ChatListUI/Sources/Node/ChatListNode.swift index ab9abd8fe3..3bd95959cd 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNode.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNode.swift @@ -370,6 +370,12 @@ public final class ChatListNode: ListView { didSet { if self.chatListFilter != oldValue { self.chatListFilterValue.set(self.chatListFilter) + + if self.chatListFilter?.includeCategories != oldValue?.includeCategories || self.chatListFilter?.additionallyIncludePeers != oldValue?.additionallyIncludePeers { + if let currentLocation = self.currentLocation { + self.setChatListLocation(.initial(count: 50, filter: self.chatListFilter)) + } + } } } } @@ -533,20 +539,12 @@ public final class ChatListNode: ListView { let viewProcessingQueue = self.viewProcessingQueue - let chatListViewUpdate = combineLatest(self.chatListLocation.get(), self.chatListFilterValue.get()) - |> distinctUntilChanged(isEqual: { lhs, rhs in - if lhs.0 != rhs.0 { - return false - } - if lhs.1 != rhs.1 { - return false - } - return true - }) - |> mapToSignal { location, filter -> Signal<(ChatListNodeViewUpdate, ChatListFilterPreset?), NoError> in - return chatListViewForLocation(groupId: groupId, filter: filter, location: location, account: context.account) + let chatListViewUpdate = self.chatListLocation.get() + |> distinctUntilChanged + |> mapToSignal { location -> Signal<(ChatListNodeViewUpdate, ChatListFilterPreset?), NoError> in + return chatListViewForLocation(groupId: groupId, location: location, account: context.account) |> map { update in - return (update, filter) + return (update, location.filter) } } @@ -792,9 +790,9 @@ public final class ChatListNode: ListView { if let range = range.loadedRange { var location: ChatListNodeLocation? if range.firstIndex < 5 && originalView.laterIndex != nil { - location = .navigation(index: originalView.entries[originalView.entries.count - 1].index) + location = .navigation(index: originalView.entries[originalView.entries.count - 1].index, filter: strongSelf.chatListFilter) } else if range.firstIndex >= 5 && range.lastIndex >= originalView.entries.count - 5 && originalView.earlierIndex != nil { - location = .navigation(index: originalView.entries[0].index) + location = .navigation(index: originalView.entries[0].index, filter: strongSelf.chatListFilter) } if let location = location, location != strongSelf.currentLocation { @@ -850,10 +848,10 @@ public final class ChatListNode: ListView { let initialLocation: ChatListNodeLocation switch mode { - case .chatList: - initialLocation = .initial(count: 50) - case .peers: - initialLocation = .initial(count: 200) + case .chatList: + initialLocation = .initial(count: 50, filter: self.chatListFilter) + case .peers: + initialLocation = .initial(count: 200, filter: self.chatListFilter) } self.setChatListLocation(initialLocation) @@ -1332,12 +1330,12 @@ public final class ChatListNode: ListView { if view.laterIndex == nil { self.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous], scrollToItem: ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: .Default(duration: nil), directionHint: .Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in }) } else { - let location: ChatListNodeLocation = .scroll(index: .absoluteUpperBound, sourceIndex: .absoluteLowerBound, scrollPosition: .top(0.0), animated: true) + let location: ChatListNodeLocation = .scroll(index: .absoluteUpperBound, sourceIndex: .absoluteLowerBound, scrollPosition: .top(0.0), animated: true, filter: self.chatListFilter) self.setChatListLocation(location) } } else { let location: ChatListNodeLocation = .scroll(index: .absoluteUpperBound, sourceIndex: .absoluteLowerBound - , scrollPosition: .top(0.0), animated: true) + , scrollPosition: .top(0.0), animated: true, filter: self.chatListFilter) self.setChatListLocation(location) } } @@ -1373,11 +1371,11 @@ public final class ChatListNode: ListView { if let index = index { let location: ChatListNodeLocation = .scroll(index: index, sourceIndex: self?.currentlyVisibleLatestChatListIndex() ?? .absoluteUpperBound - , scrollPosition: .center(.top), animated: true) + , scrollPosition: .center(.top), animated: true, filter: strongSelf.chatListFilter) strongSelf.setChatListLocation(location) } else { let location: ChatListNodeLocation = .scroll(index: .absoluteUpperBound, sourceIndex: .absoluteLowerBound - , scrollPosition: .top(0.0), animated: true) + , scrollPosition: .top(0.0), animated: true, filter: strongSelf.chatListFilter) strongSelf.setChatListLocation(location) } }) @@ -1433,7 +1431,7 @@ public final class ChatListNode: ListView { guard let strongSelf = self, let index = index else { return } - let location: ChatListNodeLocation = .scroll(index: index, sourceIndex: strongSelf.currentlyVisibleLatestChatListIndex() ?? .absoluteUpperBound, scrollPosition: .center(.top), animated: true) + let location: ChatListNodeLocation = .scroll(index: index, sourceIndex: strongSelf.currentlyVisibleLatestChatListIndex() ?? .absoluteUpperBound, scrollPosition: .center(.top), animated: true, filter: strongSelf.chatListFilter) strongSelf.setChatListLocation(location) strongSelf.peerSelected?(index.messageIndex.id.peerId, false, false) }) @@ -1457,7 +1455,7 @@ public final class ChatListNode: ListView { } } if let target = target { - let location: ChatListNodeLocation = .scroll(index: target.0, sourceIndex: .absoluteLowerBound, scrollPosition: .center(.top), animated: true) + let location: ChatListNodeLocation = .scroll(index: target.0, sourceIndex: .absoluteLowerBound, scrollPosition: .center(.top), animated: true, filter: self.chatListFilter) self.setChatListLocation(location) self.peerSelected?(target.1, false, false) } @@ -1473,12 +1471,12 @@ public final class ChatListNode: ListView { guard let self = self else { return } - let _ = (chatListViewForLocation(groupId: self.groupId, filter: filter, location: .initial(count: 10), account: self.context.account) + let _ = (chatListViewForLocation(groupId: self.groupId, location: .initial(count: 10, filter: filter), account: self.context.account) |> take(1) |> deliverOnMainQueue).start(next: { update in let entries = update.view.entries if entries.count > index, case let .MessageEntry(index, _, _, _, _, renderedPeer, _, _, _) = entries[10 - index - 1] { - let location: ChatListNodeLocation = .scroll(index: index, sourceIndex: .absoluteLowerBound, scrollPosition: .center(.top), animated: true) + let location: ChatListNodeLocation = .scroll(index: index, sourceIndex: .absoluteLowerBound, scrollPosition: .center(.top), animated: true, filter: filter) self.setChatListLocation(location) self.peerSelected?(renderedPeer.peerId, false, false) } diff --git a/submodules/ChatListUI/Sources/Node/ChatListNodeLocation.swift b/submodules/ChatListUI/Sources/Node/ChatListNodeLocation.swift index 231509cbe6..314f319a9d 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNodeLocation.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNodeLocation.swift @@ -7,21 +7,18 @@ import Display import TelegramUIPreferences enum ChatListNodeLocation: Equatable { - case initial(count: Int) - case navigation(index: ChatListIndex) - case scroll(index: ChatListIndex, sourceIndex: ChatListIndex, scrollPosition: ListViewScrollPosition, animated: Bool) + case initial(count: Int, filter: ChatListFilterPreset?) + case navigation(index: ChatListIndex, filter: ChatListFilterPreset?) + case scroll(index: ChatListIndex, sourceIndex: ChatListIndex, scrollPosition: ListViewScrollPosition, animated: Bool, filter: ChatListFilterPreset?) - static func ==(lhs: ChatListNodeLocation, rhs: ChatListNodeLocation) -> Bool { - switch lhs { - case let .navigation(index): - switch rhs { - case .navigation(index): - return true - default: - return false - } - default: - return false + var filter: ChatListFilterPreset? { + switch self { + case let .initial(initial): + return initial.filter + case let .navigation(navigation): + return navigation.filter + case let .scroll(scroll): + return scroll.filter } } } @@ -32,9 +29,9 @@ struct ChatListNodeViewUpdate { let scrollPosition: ChatListNodeViewScrollPosition? } -func chatListViewForLocation(groupId: PeerGroupId, filter: ChatListFilterPreset?, location: ChatListNodeLocation, account: Account) -> Signal { +func chatListViewForLocation(groupId: PeerGroupId, location: ChatListNodeLocation, account: Account) -> Signal { let filterPredicate: ((Peer, PeerNotificationSettings?, Bool) -> Bool)? - if let filter = filter { + if let filter = location.filter { let includePeers = Set(filter.additionallyIncludePeers) filterPredicate = { peer, notificationSettings, isUnread in if includePeers.contains(peer.id) { @@ -107,14 +104,14 @@ func chatListViewForLocation(groupId: PeerGroupId, filter: ChatListFilterPreset? } switch location { - case let .initial(count): + case let .initial(count, _): let signal: Signal<(ChatListView, ViewUpdateType), NoError> signal = account.viewTracker.tailChatListView(groupId: groupId, filterPredicate: filterPredicate, count: count) return signal |> map { view, updateType -> ChatListNodeViewUpdate in return ChatListNodeViewUpdate(view: view, type: updateType, scrollPosition: nil) } - case let .navigation(index): + case let .navigation(index, _): var first = true return account.viewTracker.aroundChatListView(groupId: groupId, filterPredicate: filterPredicate, index: index, count: 80) |> map { view, updateType -> ChatListNodeViewUpdate in @@ -127,7 +124,7 @@ func chatListViewForLocation(groupId: PeerGroupId, filter: ChatListFilterPreset? } return ChatListNodeViewUpdate(view: view, type: genericType, scrollPosition: nil) } - case let .scroll(index, sourceIndex, scrollPosition, animated): + case let .scroll(index, sourceIndex, scrollPosition, animated, _): let directionHint: ListViewScrollToItemDirectionHint = sourceIndex > index ? .Down : .Up let chatScrollPosition: ChatListNodeViewScrollPosition = .index(index: index, position: scrollPosition, directionHint: directionHint, animated: animated) var first = true diff --git a/submodules/ChatListUI/Sources/Node/ChatListViewTransition.swift b/submodules/ChatListUI/Sources/Node/ChatListViewTransition.swift index f0a07f75cc..4b0f09f8c2 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListViewTransition.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListViewTransition.swift @@ -167,7 +167,7 @@ func preparedChatListNodeViewTransition(from fromView: ChatListNodeView?, to toV var fromEmptyView = false if let fromView = fromView { - if fromView.filteredEntries.isEmpty { + if fromView.filteredEntries.isEmpty || fromView.filter != toView.filter { options.remove(.AnimateInsertion) options.remove(.AnimateAlpha) fromEmptyView = true diff --git a/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift b/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift index 12bb93be3a..79e09e3b11 100644 --- a/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift +++ b/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift @@ -462,7 +462,7 @@ private final class TabBarChatListFilterControllerNode: ViewControllerTracingNod if preset.includeCategories.contains(.publicGroups) { tags.append(.publicGroup) } - if preset.includeCategories.contains(.privateChats) { + if preset.includeCategories.contains(.channels) { tags.append(.channel) } diff --git a/submodules/Postbox/Sources/AllChatListHolesView.swift b/submodules/Postbox/Sources/AllChatListHolesView.swift new file mode 100644 index 0000000000..6f40b007c8 --- /dev/null +++ b/submodules/Postbox/Sources/AllChatListHolesView.swift @@ -0,0 +1,63 @@ +import Foundation + +final class MutableAllChatListHolesView: MutablePostboxView { + fileprivate let groupId: PeerGroupId + private var holes = Set() + fileprivate var latestHole: ChatListHole? + + init(postbox: Postbox, groupId: PeerGroupId) { + self.groupId = groupId + self.holes = Set(postbox.chatListTable.allHoles(groupId: groupId)) + self.latestHole = self.holes.max(by: { $0.index < $1.index }) + } + + func replay(postbox: Postbox, transaction: PostboxTransaction) -> Bool { + if let operations = transaction.chatListOperations[self.groupId] { + var updated = false + for operation in operations { + switch operation { + case let .InsertHole(hole): + if !self.holes.contains(hole) { + self.holes.insert(hole) + updated = true + } + case let .RemoveHoles(indices): + for index in indices { + if self.holes.contains(ChatListHole(index: index.messageIndex)) { + self.holes.remove(ChatListHole(index: index.messageIndex)) + updated = true + } + } + default: + break + } + } + + if updated { + let updatedLatestHole = self.holes.max(by: { $0.index < $1.index }) + if updatedLatestHole != self.latestHole { + self.latestHole = updatedLatestHole + return true + } else { + return false + } + } else { + return false + } + } else { + return false + } + } + + func immutableView() -> PostboxView { + return AllChatListHolesView(self) + } +} + +public final class AllChatListHolesView: PostboxView { + public let latestHole: ChatListHole? + + init(_ view: MutableAllChatListHolesView) { + self.latestHole = view.latestHole + } +} diff --git a/submodules/Postbox/Sources/ChatListIndexTable.swift b/submodules/Postbox/Sources/ChatListIndexTable.swift index 3d12b9b25a..1a66b80bd7 100644 --- a/submodules/Postbox/Sources/ChatListIndexTable.swift +++ b/submodules/Postbox/Sources/ChatListIndexTable.swift @@ -570,13 +570,10 @@ final class ChatListIndexTable: Table { func debugReindexUnreadCounts(postbox: Postbox) -> (ChatListTotalUnreadState, [PeerGroupId: PeerGroupUnreadCountersCombinedSummary]) { var peerIds: [PeerId] = [] - self.valueBox.scanInt64(self.table, values: { key, _ in - let peerId = PeerId(key) - if peerId.namespace != Int32.max { - peerIds.append(peerId) - } - return true - }) + for groupId in postbox.chatListTable.existingGroups() + [.root] { + let groupPeerIds = postbox.chatListTable.allPeerIds(groupId: groupId) + peerIds.append(contentsOf: groupPeerIds) + } var rootState = ChatListTotalUnreadState(absoluteCounters: [:], filteredCounters: [:]) var summaries: [PeerGroupId: PeerGroupUnreadCountersCombinedSummary] = [:] for peerId in peerIds { diff --git a/submodules/Postbox/Sources/ChatListTable.swift b/submodules/Postbox/Sources/ChatListTable.swift index b0c84fb807..b44e99fc82 100644 --- a/submodules/Postbox/Sources/ChatListTable.swift +++ b/submodules/Postbox/Sources/ChatListTable.swift @@ -680,6 +680,35 @@ final class ChatListTable: Table { return entries } + func allPeerIds(groupId: PeerGroupId) -> [PeerId] { + var peerIds: [PeerId] = [] + self.valueBox.range(self.table, start: self.upperBound(groupId: groupId), end: self.lowerBound(groupId: groupId), keys: { key in + let (keyGroupId, pinningIndex, messageIndex, type) = extractKey(key) + assert(groupId == keyGroupId) + + let index = ChatListIndex(pinningIndex: pinningIndex, messageIndex: messageIndex) + if type == ChatListEntryType.message.rawValue { + peerIds.append(messageIndex.id.peerId) + } + return true + }, limit: 0) + return peerIds + } + + func allHoles(groupId: PeerGroupId) -> [ChatListHole] { + var entries: [ChatListHole] = [] + self.valueBox.range(self.table, start: self.upperBound(groupId: groupId), end: self.lowerBound(groupId: groupId), keys: { key in + let (keyGroupId, pinningIndex, messageIndex, type) = extractKey(key) + assert(groupId == keyGroupId) + if type == ChatListEntryType.hole.rawValue { + let index = ChatListIndex(pinningIndex: pinningIndex, messageIndex: messageIndex) + entries.append(ChatListHole(index: index.messageIndex)) + } + return true + }, limit: 0) + return entries + } + func entriesInRange(groupId: PeerGroupId, upperBound: ChatListIndex, lowerBound: ChatListIndex) -> [ChatListEntryInfo] { var entries: [ChatListEntryInfo] = [] let upperBoundKey: ValueBoxKey diff --git a/submodules/Postbox/Sources/Views.swift b/submodules/Postbox/Sources/Views.swift index 86e870ac6b..962d0fe2ec 100644 --- a/submodules/Postbox/Sources/Views.swift +++ b/submodules/Postbox/Sources/Views.swift @@ -27,6 +27,7 @@ public enum PostboxViewKey: Hashable { case peerNotificationSettingsBehaviorTimestampView case peerChatInclusion(PeerId) case basicPeer(PeerId) + case allChatListHoles(PeerGroupId) public var hashValue: Int { switch self { @@ -82,6 +83,8 @@ public enum PostboxViewKey: Hashable { return peerId.hashValue case let .basicPeer(peerId): return peerId.hashValue + case let .allChatListHoles(groupId): + return groupId.hashValue } } @@ -243,6 +246,12 @@ public enum PostboxViewKey: Hashable { } else { return false } + case let .allChatListHoles(groupId): + if case .allChatListHoles(groupId) = rhs { + return true + } else { + return false + } } } } @@ -301,5 +310,7 @@ func postboxViewForKey(postbox: Postbox, key: PostboxViewKey) -> MutablePostboxV return MutablePeerChatInclusionView(postbox: postbox, peerId: peerId) case let .basicPeer(peerId): return MutableBasicPeerView(postbox: postbox, peerId: peerId) + case let .allChatListHoles(groupId): + return MutableAllChatListHolesView(postbox: postbox, groupId: groupId) } } diff --git a/submodules/TelegramCore/Sources/ManagedChatListHoles.swift b/submodules/TelegramCore/Sources/ManagedChatListHoles.swift index 8dbe238d06..4783619e83 100644 --- a/submodules/TelegramCore/Sources/ManagedChatListHoles.swift +++ b/submodules/TelegramCore/Sources/ManagedChatListHoles.swift @@ -4,6 +4,7 @@ import SwiftSignalKit private final class ManagedChatListHolesState { private var holeDisposables: [ChatListHolesEntry: Disposable] = [:] + private var additionalLatestHoleDisposable: (ChatListHole, Disposable)? func clearDisposables() -> [Disposable] { let disposables = Array(self.holeDisposables.values) @@ -11,7 +12,7 @@ private final class ManagedChatListHolesState { return disposables } - func update(entries: Set) -> (removed: [Disposable], added: [ChatListHolesEntry: MetaDisposable]) { + func update(entries: Set, additionalLatestHole: ChatListHole?) -> (removed: [Disposable], added: [ChatListHolesEntry: MetaDisposable], addedAdditionalLatestHole: (ChatListHole, MetaDisposable)?) { var removed: [Disposable] = [] var added: [ChatListHolesEntry: MetaDisposable] = [:] @@ -30,7 +31,21 @@ private final class ManagedChatListHolesState { } } - return (removed, added) + var addedAdditionalLatestHole: (ChatListHole, MetaDisposable)? + if self.holeDisposables.isEmpty { + if self.additionalLatestHoleDisposable?.0 != additionalLatestHole { + if let (_, disposable) = self.additionalLatestHoleDisposable { + removed.append(disposable) + } + if let additionalLatestHole = additionalLatestHole { + let disposable = MetaDisposable() + self.additionalLatestHoleDisposable = (additionalLatestHole, disposable) + addedAdditionalLatestHole = (additionalLatestHole, disposable) + } + } + } + + return (removed, added, addedAdditionalLatestHole) } } @@ -38,9 +53,17 @@ func managedChatListHoles(network: Network, postbox: Postbox, accountPeerId: Pee return Signal { _ in let state = Atomic(value: ManagedChatListHolesState()) - let disposable = postbox.chatListHolesView().start(next: { view in - let (removed, added) = state.with { state -> (removed: [Disposable], added: [ChatListHolesEntry: MetaDisposable]) in - return state.update(entries: view.entries) + let topRootHoleKey = PostboxViewKey.allChatListHoles(.root) + let topRootHole = postbox.combinedView(keys: [topRootHoleKey]) + + let disposable = combineLatest(postbox.chatListHolesView(), topRootHole).start(next: { view, topRootHoleView in + var additionalLatestHole: ChatListHole? + if let topRootHole = topRootHoleView.views[topRootHoleKey] as? AllChatListHolesView { + additionalLatestHole = topRootHole.latestHole + } + + let (removed, added, addedAdditionalLatestHole) = state.with { state in + return state.update(entries: view.entries, additionalLatestHole: additionalLatestHole) } for disposable in removed { @@ -50,6 +73,10 @@ func managedChatListHoles(network: Network, postbox: Postbox, accountPeerId: Pee for (entry, disposable) in added { disposable.set(fetchChatListHole(postbox: postbox, network: network, accountPeerId: accountPeerId, groupId: entry.groupId, hole: entry.hole).start()) } + + if let (hole, disposable) = addedAdditionalLatestHole { + disposable.set(fetchChatListHole(postbox: postbox, network: network, accountPeerId: accountPeerId, groupId: .root, hole: hole).start()) + } }) return ActionDisposable { diff --git a/submodules/TelegramUIPreferences/Sources/ChatListFilterSettings.swift b/submodules/TelegramUIPreferences/Sources/ChatListFilterSettings.swift index de6105939d..684bdbaa1a 100644 --- a/submodules/TelegramUIPreferences/Sources/ChatListFilterSettings.swift +++ b/submodules/TelegramUIPreferences/Sources/ChatListFilterSettings.swift @@ -59,23 +59,27 @@ public enum ChatListFilterPresetName: Equatable, Hashable, PostboxCoding { } public struct ChatListFilterPreset: Equatable, PostboxCoding { + public var id: Int64 public var name: ChatListFilterPresetName public var includeCategories: ChatListIncludeCategoryFilter public var additionallyIncludePeers: [PeerId] - public init(name: ChatListFilterPresetName, includeCategories: ChatListIncludeCategoryFilter, additionallyIncludePeers: [PeerId]) { + public init(id: Int64, name: ChatListFilterPresetName, includeCategories: ChatListIncludeCategoryFilter, additionallyIncludePeers: [PeerId]) { + self.id = id self.name = name self.includeCategories = includeCategories self.additionallyIncludePeers = additionallyIncludePeers } public init(decoder: PostboxDecoder) { + self.id = decoder.decodeInt64ForKey("id", orElse: 0) self.name = decoder.decodeObjectForKey("name", decoder: { ChatListFilterPresetName(decoder: $0) }) as? ChatListFilterPresetName ?? ChatListFilterPresetName.custom("Preset") self.includeCategories = ChatListIncludeCategoryFilter(rawValue: decoder.decodeInt32ForKey("includeCategories", orElse: 0)) self.additionallyIncludePeers = decoder.decodeInt64ArrayForKey("additionallyIncludePeers").map(PeerId.init) } public func encode(_ encoder: PostboxEncoder) { + encoder.encodeInt64(self.id, forKey: "id") encoder.encodeObject(self.name, forKey: "name") encoder.encodeInt32(self.includeCategories.rawValue, forKey: "includeCategories") encoder.encodeInt64Array(self.additionallyIncludePeers.map { $0.toInt64() }, forKey: "additionallyIncludePeers") @@ -88,6 +92,7 @@ public struct ChatListFilterSettings: PreferencesEntry, Equatable { public static var `default`: ChatListFilterSettings { return ChatListFilterSettings(presets: [ ChatListFilterPreset( + id: Int64(arc4random()), name: .unread, includeCategories: ChatListIncludeCategoryFilter.all.subtracting(.read), additionallyIncludePeers: [] @@ -116,12 +121,15 @@ public struct ChatListFilterSettings: PreferencesEntry, Equatable { } } -public func updateChatListFilterSettingsInteractively(postbox: Postbox, _ f: @escaping (ChatListFilterSettings) -> ChatListFilterSettings) -> Signal { - return postbox.transaction { transaction -> Void in +public func updateChatListFilterSettingsInteractively(postbox: Postbox, _ f: @escaping (ChatListFilterSettings) -> ChatListFilterSettings) -> Signal { + return postbox.transaction { transaction -> ChatListFilterSettings in + var result: ChatListFilterSettings? transaction.updatePreferencesEntry(key: ApplicationSpecificPreferencesKeys.chatListFilterSettings, { entry in var settings = entry as? ChatListFilterSettings ?? ChatListFilterSettings.default - return f(settings) + let updated = f(settings) + result = updated + return updated }) + return result ?? .default } - |> ignoreValues } From 535f1df20d55bdb4614db05de19e4af05b878796 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Tue, 28 Jan 2020 20:36:50 +0400 Subject: [PATCH 37/50] Fix build --- submodules/ChatListUI/BUCK | 1 + .../ChatListUI/Sources/ChatListFilterPresetController.swift | 1 - .../ChatListUI/Sources/ChatListFilterPresetListController.swift | 1 - .../ChatListUI/Sources/ChatListFilterPresetListItem.swift | 2 -- 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/submodules/ChatListUI/BUCK b/submodules/ChatListUI/BUCK index 3b391fe24e..77299792c5 100644 --- a/submodules/ChatListUI/BUCK +++ b/submodules/ChatListUI/BUCK @@ -42,6 +42,7 @@ static_library( "//submodules/ContextUI:ContextUI", "//submodules/PhoneNumberFormat:PhoneNumberFormat", "//submodules/TelegramIntents:TelegramIntents", + "//submodules/ItemListPeerActionItem:ItemListPeerActionItem", ], frameworks = [ "$SDKROOT/System/Library/Frameworks/Foundation.framework", diff --git a/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift b/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift index 517bc1a116..890a6414cc 100644 --- a/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift +++ b/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift @@ -7,7 +7,6 @@ import TelegramCore import SyncCore import TelegramPresentationData import ItemListUI -import PresentationDataUtils import AccountContext import TelegramUIPreferences import ItemListPeerItem diff --git a/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift b/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift index 3d51524b2a..a3900429f8 100644 --- a/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift +++ b/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift @@ -8,7 +8,6 @@ import SyncCore import TelegramPresentationData import TelegramUIPreferences import ItemListUI -import PresentationDataUtils import AccountContext private final class ChatListFilterPresetListControllerArguments { diff --git a/submodules/ChatListUI/Sources/ChatListFilterPresetListItem.swift b/submodules/ChatListUI/Sources/ChatListFilterPresetListItem.swift index 661dc45468..4e8454897f 100644 --- a/submodules/ChatListUI/Sources/ChatListFilterPresetListItem.swift +++ b/submodules/ChatListUI/Sources/ChatListFilterPresetListItem.swift @@ -8,8 +8,6 @@ import TelegramCore import SyncCore import TelegramPresentationData import ItemListUI -import PresentationDataUtils -import ActivityIndicator import TelegramUIPreferences struct ChatListFilterPresetListItemEditing: Equatable { From 0a061ebd69543398256da1c2c3c1c10a1fed5d3e Mon Sep 17 00:00:00 2001 From: Ali <> Date: Tue, 28 Jan 2020 21:01:29 +0400 Subject: [PATCH 38/50] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 169f5aa33f..ff68b48e5b 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ include Utils.makefile BUCK_OPTIONS=\ - --config custom.appVersion="5.14" \ + --config custom.appVersion="5.14.1" \ --config custom.developmentCodeSignIdentity="${DEVELOPMENT_CODE_SIGN_IDENTITY}" \ --config custom.distributionCodeSignIdentity="${DISTRIBUTION_CODE_SIGN_IDENTITY}" \ --config custom.developmentTeam="${DEVELOPMENT_TEAM}" \ From f436f10d4c29f554e70e8d0722c76600f954df01 Mon Sep 17 00:00:00 2001 From: overtake <> Date: Wed, 29 Jan 2020 12:01:30 +0400 Subject: [PATCH 39/50] fix forwarding messages --- submodules/TelegramCore/Sources/PendingMessageManager.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/submodules/TelegramCore/Sources/PendingMessageManager.swift b/submodules/TelegramCore/Sources/PendingMessageManager.swift index cb35a4dccd..9cb6459e60 100644 --- a/submodules/TelegramCore/Sources/PendingMessageManager.swift +++ b/submodules/TelegramCore/Sources/PendingMessageManager.swift @@ -675,7 +675,9 @@ public final class PendingMessageManager { let sendMessageRequest: Signal if isForward { - flags |= (1 << 9) + if !messages.contains(where: { $0.0.groupingKey == nil }) { + flags |= (1 << 9) + } var forwardIds: [(MessageId, Int64)] = [] for (message, content) in messages { From 8afd80c31d1103ca0fd42464fc1be0964f6e58b2 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sat, 1 Feb 2020 00:15:18 +0400 Subject: [PATCH 40/50] Basic implementation of the redesigned profiles --- .../AvatarNode/Sources/PeerAvatar.swift | 12 +- .../ContainedViewLayoutTransition.swift | 18 + submodules/Display/Display/ListView.swift | 2 +- .../Display/Display/ListViewScroller.swift | 16 +- .../Sources/PeerInfoController.swift | 14 - .../ButtonMessage.imageset/Contents.json | 20 + .../TelegramUI/PeerInfoFilesPane.swift | 174 ++ .../TelegramUI/PeerInfoScreen.swift | 1618 +++++++++++++++++ .../PeerInfoScreenLabeledValueItem.swift | 123 ++ ...erInfoScreenSelectableBackgroundNode.swift | 55 + .../TelegramUI/PeerInfoVisualMediaPane.swift | 458 +++++ .../TelegramUI/SharedAccountContext.swift | 17 + 12 files changed, 2500 insertions(+), 27 deletions(-) create mode 100644 submodules/TelegramUI/Images.xcassets/Peer Info/ButtonMessage.imageset/Contents.json create mode 100644 submodules/TelegramUI/TelegramUI/PeerInfoFilesPane.swift create mode 100644 submodules/TelegramUI/TelegramUI/PeerInfoScreen.swift create mode 100644 submodules/TelegramUI/TelegramUI/PeerInfoScreenLabeledValueItem.swift create mode 100644 submodules/TelegramUI/TelegramUI/PeerInfoScreenSelectableBackgroundNode.swift create mode 100644 submodules/TelegramUI/TelegramUI/PeerInfoVisualMediaPane.swift diff --git a/submodules/AvatarNode/Sources/PeerAvatar.swift b/submodules/AvatarNode/Sources/PeerAvatar.swift index 183a06137a..f9dee458bd 100644 --- a/submodules/AvatarNode/Sources/PeerAvatar.swift +++ b/submodules/AvatarNode/Sources/PeerAvatar.swift @@ -77,10 +77,18 @@ public func peerAvatarImage(account: Account, peerReference: PeerReference?, aut if let imageSource = CGImageSourceCreateWithData(data as CFData, nil), let dataImage = CGImageSourceCreateImageAtIndex(imageSource, 0, nil) { context.clear(CGRect(origin: CGPoint(), size: displayDimensions)) context.setBlendMode(.copy) + + if round && displayDimensions.width != 60.0 { + context.addEllipse(in: CGRect(origin: CGPoint(), size: displayDimensions).insetBy(dx: inset, dy: inset)) + context.clip() + } + context.draw(dataImage, in: CGRect(origin: CGPoint(), size: displayDimensions).insetBy(dx: inset, dy: inset)) if round { - context.setBlendMode(.destinationOut) - context.draw(roundCorners.cgImage!, in: CGRect(origin: CGPoint(), size: displayDimensions).insetBy(dx: inset, dy: inset)) + if displayDimensions.width == 60.0 { + context.setBlendMode(.destinationOut) + context.draw(roundCorners.cgImage!, in: CGRect(origin: CGPoint(), size: displayDimensions).insetBy(dx: inset, dy: inset)) + } } } else { if let emptyColor = emptyColor { diff --git a/submodules/Display/Display/ContainedViewLayoutTransition.swift b/submodules/Display/Display/ContainedViewLayoutTransition.swift index 45510880e9..3df59e854a 100644 --- a/submodules/Display/Display/ContainedViewLayoutTransition.swift +++ b/submodules/Display/Display/ContainedViewLayoutTransition.swift @@ -141,6 +141,24 @@ public extension ContainedViewLayoutTransition { } } + func updateFrameAdditiveToCenter(node: ASDisplayNode, frame: CGRect, force: Bool = false, completion: ((Bool) -> Void)? = nil) { + if node.frame.equalTo(frame) && !force { + completion?(true) + } else { + switch self { + case .immediate: + node.frame = frame + if let completion = completion { + completion(true) + } + case .animated: + let previousFrame = node.frame + node.frame = frame + self.animatePositionAdditive(node: node, offset: CGPoint(x: previousFrame.midX - frame.midX, y: previousFrame.midY - frame.midY)) + } + } + } + func updateBounds(node: ASDisplayNode, bounds: CGRect, force: Bool = false, completion: ((Bool) -> Void)? = nil) { if node.bounds.equalTo(bounds) && !force { completion?(true) diff --git a/submodules/Display/Display/ListView.swift b/submodules/Display/Display/ListView.swift index 59fc67d902..7a65d3b39e 100644 --- a/submodules/Display/Display/ListView.swift +++ b/submodules/Display/Display/ListView.swift @@ -125,7 +125,7 @@ public enum GeneralScrollDirection { } open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGestureRecognizerDelegate { - final let scroller: ListViewScroller + public final let scroller: ListViewScroller private final var visibleSize: CGSize = CGSize() public private(set) final var insets = UIEdgeInsets() public final var visualInsets: UIEdgeInsets? diff --git a/submodules/Display/Display/ListViewScroller.swift b/submodules/Display/Display/ListViewScroller.swift index 7e8921f718..c77b2207cb 100644 --- a/submodules/Display/Display/ListViewScroller.swift +++ b/submodules/Display/Display/ListViewScroller.swift @@ -1,29 +1,27 @@ import UIKit -class ListViewScroller: UIScrollView, UIGestureRecognizerDelegate { - override init(frame: CGRect) { +public final class ListViewScroller: UIScrollView, UIGestureRecognizerDelegate { + override public init(frame: CGRect) { super.init(frame: frame) - #if os(iOS) self.scrollsToTop = false if #available(iOSApplicationExtension 11.0, iOS 11.0, *) { self.contentInsetAdjustmentBehavior = .never } - #endif } - required init?(coder aDecoder: NSCoder) { + required public init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - @objc func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { + public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { if otherGestureRecognizer is ListViewTapGestureRecognizer { return true } return false } - override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { + override public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { if gestureRecognizer is UIPanGestureRecognizer, let gestureRecognizers = gestureRecognizer.view?.gestureRecognizers { for otherGestureRecognizer in gestureRecognizers { if otherGestureRecognizer !== gestureRecognizer, let panGestureRecognizer = otherGestureRecognizer as? UIPanGestureRecognizer, panGestureRecognizer.minimumNumberOfTouches == 2 { @@ -36,9 +34,7 @@ class ListViewScroller: UIScrollView, UIGestureRecognizerDelegate { } } - #if os(iOS) - override func touchesShouldCancel(in view: UIView) -> Bool { + override public func touchesShouldCancel(in view: UIView) -> Bool { return true } - #endif } diff --git a/submodules/PeerInfoUI/Sources/PeerInfoController.swift b/submodules/PeerInfoUI/Sources/PeerInfoController.swift index f34ef9a845..62e5703def 100644 --- a/submodules/PeerInfoUI/Sources/PeerInfoController.swift +++ b/submodules/PeerInfoUI/Sources/PeerInfoController.swift @@ -7,17 +7,3 @@ import TelegramCore import SyncCore import AccountContext -public func peerInfoControllerImpl(context: AccountContext, peer: Peer, mode: PeerInfoControllerMode) -> ViewController? { - if let _ = peer as? TelegramGroup { - return groupInfoController(context: context, peerId: peer.id) - } else if let channel = peer as? TelegramChannel { - if case .group = channel.info { - return groupInfoController(context: context, peerId: peer.id) - } else { - return channelInfoController(context: context, peerId: peer.id) - } - } else if peer is TelegramUser || peer is TelegramSecretChat { - return userInfoController(context: context, peerId: peer.id, mode: mode) - } - return nil -} diff --git a/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonMessage.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonMessage.imageset/Contents.json new file mode 100644 index 0000000000..f8f827e40b --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonMessage.imageset/Contents.json @@ -0,0 +1,20 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoFilesPane.swift b/submodules/TelegramUI/TelegramUI/PeerInfoFilesPane.swift new file mode 100644 index 0000000000..112682fe33 --- /dev/null +++ b/submodules/TelegramUI/TelegramUI/PeerInfoFilesPane.swift @@ -0,0 +1,174 @@ +import AsyncDisplayKit +import Display +import TelegramCore +import SyncCore +import SwiftSignalKit +import Postbox +import TelegramPresentationData +import AccountContext +import ContextUI +import PhotoResources +import TelegramUIPreferences + +final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode { + private let context: AccountContext + private let peerId: PeerId + + private let listNode: ChatHistoryListNode + + private var currentParams: (size: CGSize, isScrollingLockedAtTop: Bool, presentationData: PresentationData)? + + private let ready = Promise() + private var didSetReady: Bool = false + var isReady: Signal { + return self.ready.get() + } + + private var hiddenMediaDisposable: Disposable? + + init(context: AccountContext, openMessage: @escaping (MessageId) -> Bool, peerId: PeerId, tagMask: MessageTags) { + self.context = context + self.peerId = peerId + + var openMessageImpl: ((MessageId) -> Bool)? + let controllerInteraction = ChatControllerInteraction(openMessage: { message, _ in + return openMessageImpl?(message.id) ?? false + }, openPeer: { _, _, _ in + }, openPeerMention: { _ in + }, openMessageContextMenu: { _, _, _, _, _ in + }, openMessageContextActions: { _, _, _, _ in + }, navigateToMessage: { _, _ in + }, tapMessage: nil, clickThroughMessage: { + }, toggleMessagesSelection: { _, _ in + }, sendCurrentMessage: { _ in + }, sendMessage: { _ in + }, sendSticker: { _, _, _, _ in + return false + }, sendGif: { _, _, _ in + return false + }, requestMessageActionCallback: { _, _, _ in + }, requestMessageActionUrlAuth: { _, _, _ in + }, activateSwitchInline: { _, _ in + }, openUrl: { _, _, _, _ in + }, shareCurrentLocation: { + }, shareAccountContact: { + }, sendBotCommand: { _, _ in + }, openInstantPage: { _, _ in + }, openWallpaper: { _ in + }, openTheme: {_ in + }, openHashtag: { _, _ in + }, updateInputState: { _ in + }, updateInputMode: { _ in + }, openMessageShareMenu: { _ in + }, presentController: { _, _ in + }, navigationController: { + return nil + }, chatControllerNode: { + return nil + }, reactionContainerNode: { + return nil + }, presentGlobalOverlayController: { _, _ in + }, callPeer: { _ in + }, longTap: { _, _ in + }, openCheckoutOrReceipt: { _ in + }, openSearch: { + }, setupReply: { _ in + }, canSetupReply: { _ in + return false + }, navigateToFirstDateMessage: { _ in + }, requestRedeliveryOfFailedMessages: { _ in + }, addContact: { _ in + }, rateCall: { _, _ in + }, requestSelectMessagePollOptions: { _, _ in + }, requestOpenMessagePollResults: { _, _ in + }, openAppStorePage: { + }, displayMessageTooltip: { _, _, _, _ in + }, seekToTimecode: { _, _, _ in + }, scheduleCurrentMessage: { + }, sendScheduledMessagesNow: { _ in + }, editScheduledMessagesTime: { _ in + }, performTextSelectionAction: { _, _, _ in + }, updateMessageReaction: { _, _ in + }, openMessageReactions: { _ in + }, displaySwipeToReplyHint: { + }, dismissReplyMarkupMessage: { _ in + }, openMessagePollResults: { _, _ in + }, openPollCreation: { _ in + }, requestMessageUpdate: { _ in + }, cancelInteractiveKeyboardGestures: { + }, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: false)) + + self.listNode = ChatHistoryListNode(context: context, chatLocation: .peer(peerId), tagMask: tagMask, subject: nil, controllerInteraction: controllerInteraction, selectedMessages: .single(nil), mode: .list(search: false, reversed: false)) + + super.init() + + openMessageImpl = { id in + return openMessage(id) + } + + self.hiddenMediaDisposable = context.sharedContext.mediaManager.galleryHiddenMediaManager.hiddenIds().start(next: { [weak self] ids in + guard let strongSelf = self else { + return + } + var hiddenMedia: [MessageId: [Media]] = [:] + for id in ids { + if case let .chat(accountId, messageId, media) = id, accountId == strongSelf.context.account.id { + hiddenMedia[messageId] = [media] + } + } + controllerInteraction.hiddenMedia = hiddenMedia + strongSelf.listNode.forEachItemNode { itemNode in + if let itemNode = itemNode as? ListMessageNode { + itemNode.updateHiddenMedia() + } + } + }) + + self.listNode.preloadPages = true + self.addSubnode(self.listNode) + + self.ready.set(self.listNode.historyState.get() + |> take(1) + |> map { _ -> Bool in true }) + } + + deinit { + self.hiddenMediaDisposable?.dispose() + } + + func scrollToTop() -> Bool { + let offset = self.listNode.visibleContentOffset() + switch offset { + case let .known(value) where value <= CGFloat.ulpOfOne: + return false + default: + self.listNode.scrollToEndOfHistory() + return true + } + } + + func update(size: CGSize, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) { + self.currentParams = (size, isScrollingLockedAtTop, presentationData) + + transition.updateFrame(node: self.listNode, frame: CGRect(origin: CGPoint(), size: size)) + let (duration, curve) = listViewAnimationDurationAndCurve(transition: transition) + self.listNode.updateLayout(transition: transition, updateSizeAndInsets: ListViewUpdateSizeAndInsets(size: size, insets: UIEdgeInsets(), duration: duration, curve: curve)) + self.listNode.scrollEnabled = !isScrollingLockedAtTop + } + + func findLoadedMessage(id: MessageId) -> Message? { + self.listNode.messageInCurrentHistoryView(id) + } + + func transitionNodeForGallery(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + var transitionNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? + self.listNode.forEachItemNode { itemNode in + if let itemNode = itemNode as? ListMessageNode { + if let result = itemNode.transitionNode(id: messageId, media: media) { + transitionNode = result + } + } + } + return transitionNode + } +} diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoScreen.swift b/submodules/TelegramUI/TelegramUI/PeerInfoScreen.swift new file mode 100644 index 0000000000..e1f5116a47 --- /dev/null +++ b/submodules/TelegramUI/TelegramUI/PeerInfoScreen.swift @@ -0,0 +1,1618 @@ +import Foundation +import UIKit +import Display +import AsyncDisplayKit +import Postbox +import TelegramCore +import SyncCore +import SwiftSignalKit +import AccountContext +import TelegramPresentationData +import TelegramUIPreferences +import AvatarNode +import TelegramStringFormatting +import PhoneNumberFormat +import AppBundle +import PresentationDataUtils +import NotificationMuteSettingsUI +import NotificationSoundSelectionUI +import OverlayStatusController +import ShareController + +private let avatarFont = avatarPlaceholderFont(size: 28.0) + +private enum PeerInfoHeaderButtonKey: Hashable { + case message + case call + case mute + case more +} + +private enum PeerInfoHeaderButtonIcon { + case message + case call + case mute + case unmute + case more +} + +private final class PeerInfoHeaderButtonNode: HighlightableButtonNode { + let key: PeerInfoHeaderButtonKey + private let action: (PeerInfoHeaderButtonNode) -> Void + private let backgroundNode: ASImageNode + private let textNode: ImmediateTextNode + + private var theme: PresentationTheme? + private var icon: PeerInfoHeaderButtonIcon? + + init(key: PeerInfoHeaderButtonKey, action: @escaping (PeerInfoHeaderButtonNode) -> Void) { + self.key = key + self.action = action + + self.backgroundNode = ASImageNode() + self.backgroundNode.displaysAsynchronously = false + self.backgroundNode.displayWithoutProcessing = true + + self.textNode = ImmediateTextNode() + self.textNode.displaysAsynchronously = false + + super.init() + + self.addSubnode(self.backgroundNode) + self.addSubnode(self.textNode) + + self.highligthedChanged = { [weak self] highlighted in + if let strongSelf = self { + if highlighted { + strongSelf.layer.removeAnimation(forKey: "opacity") + strongSelf.alpha = 0.4 + } else { + strongSelf.alpha = 1.0 + strongSelf.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) + } + } + } + + self.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside) + } + + @objc private func buttonPressed() { + self.action(self) + } + + func update(size: CGSize, text: String, icon: PeerInfoHeaderButtonIcon, isExpanded: Bool, presentationData: PresentationData, transition: ContainedViewLayoutTransition) { + if self.theme != presentationData.theme || self.icon != icon { + self.theme = presentationData.theme + self.icon = icon + self.backgroundNode.image = generateImage(CGSize(width: 40.0, height: 40.0), contextGenerator: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + context.setFillColor(presentationData.theme.list.itemAccentColor.cgColor) + context.fillEllipse(in: CGRect(origin: CGPoint(), size: size)) + context.setBlendMode(.copy) + context.setFillColor(UIColor.clear.cgColor) + let imageName: String + switch icon { + case .message: + imageName = "Chat/Context Menu/Message" + case .call: + imageName = "Chat/Context Menu/Call" + case .mute: + imageName = "Chat/Context Menu/Muted" + case .unmute: + imageName = "Chat/Context Menu/Unmute" + case .more: + imageName = "Chat/Context Menu/More" + } + if let image = UIImage(bundleImageName: imageName) { + let imageRect = CGRect(origin: CGPoint(x: floor((size.width - image.size.width) / 2.0), y: floor((size.height - image.size.height) / 2.0)), size: image.size) + context.clip(to: imageRect, mask: image.cgImage!) + context.fill(imageRect) + } + }) + } + + self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(12.0), textColor: presentationData.theme.list.itemAccentColor) + let titleSize = self.textNode.updateLayout(CGSize(width: 120.0, height: .greatestFiniteMagnitude)) + + transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: size)) + transition.updateFrameAdditiveToCenter(node: self.textNode, frame: CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: size.height + 6.0), size: titleSize)) + } +} + +private final class PeerInfoHeaderNode: ASDisplayNode { + private var context: AccountContext + private var presentationData: PresentationData? + + private let avatarNode: AvatarNode + private let titleNode: ImmediateTextNode + private let subtitleNode: ImmediateTextNode + private var buttonNodes: [PeerInfoHeaderButtonKey: PeerInfoHeaderButtonNode] = [:] + private let backgroundNode: ASDisplayNode + private let separatorNode: ASDisplayNode + + var performButtonAction: ((PeerInfoHeaderButtonKey) -> Void)? + + init(context: AccountContext) { + self.context = context + + self.avatarNode = AvatarNode(font: avatarFont) + + self.titleNode = ImmediateTextNode() + self.titleNode.displaysAsynchronously = false + + self.subtitleNode = ImmediateTextNode() + self.subtitleNode.displaysAsynchronously = false + + self.backgroundNode = ASDisplayNode() + self.backgroundNode.isLayerBacked = true + + self.separatorNode = ASDisplayNode() + self.separatorNode.isLayerBacked = true + + super.init() + + self.addSubnode(self.backgroundNode) + self.addSubnode(self.separatorNode) + self.addSubnode(self.avatarNode) + self.addSubnode(self.titleNode) + self.addSubnode(self.subtitleNode) + } + + func update(width: CGFloat, statusBarHeight: CGFloat, navigationHeight: CGFloat, presentationData: PresentationData, peer: Peer?, cachedData: CachedPeerData?, notificationSettings: TelegramPeerNotificationSettings?, presence: TelegramUserPresence?, transition: ContainedViewLayoutTransition) -> CGFloat { + self.presentationData = presentationData + + self.backgroundNode.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor + self.separatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor + + let avatarSize: CGFloat = 100.0 + let defaultButtonSize: CGFloat = 40.0 + let defaultMaxButtonSpacing: CGFloat = 40.0 + + var buttonKeys: [PeerInfoHeaderButtonKey] = [] + + if let peer = peer { + buttonKeys.append(.message) + buttonKeys.append(.call) + buttonKeys.append(.mute) + buttonKeys.append(.more) + + self.avatarNode.setPeer(context: self.context, theme: presentationData.theme, peer: peer, displayDimensions: CGSize(width: avatarSize, height: avatarSize)) + + self.titleNode.attributedText = NSAttributedString(string: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), font: Font.medium(24.0), textColor: presentationData.theme.list.itemPrimaryTextColor) + + let presence = presence ?? TelegramUserPresence(status: .none, lastActivity: 0) + let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 + let (subtitleString, activity) = stringAndActivityForUserPresence(strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, presence: presence, relativeTo: Int32(timestamp), expanded: true) + let subtitleColor: UIColor + if activity { + subtitleColor = presentationData.theme.list.itemAccentColor + } else { + subtitleColor = presentationData.theme.list.itemSecondaryTextColor + } + self.subtitleNode.attributedText = NSAttributedString(string: subtitleString, font: Font.regular(15.0), textColor: subtitleColor) + } + + let textSideInset: CGFloat = 16.0 + + var height: CGFloat = navigationHeight + height += 212.0 + + let avatarFrame = CGRect(origin: CGPoint(x: floor((width - avatarSize) / 2.0), y: statusBarHeight + 10.0), size: CGSize(width: avatarSize, height: avatarSize)) + transition.updateFrame(node: self.avatarNode, frame: avatarFrame) + + let titleSize = self.titleNode.updateLayout(CGSize(width: width - textSideInset * 2.0, height: .greatestFiniteMagnitude)) + let subtitleSize = self.subtitleNode.updateLayout(CGSize(width: width - textSideInset * 2.0, height: .greatestFiniteMagnitude)) + + let titleFrame = CGRect(origin: CGPoint(x: floor((width - titleSize.width) / 2.0), y: avatarFrame.maxY + 10.0), size: titleSize) + let subtitleFrame = CGRect(origin: CGPoint(x: floor((width - subtitleSize.width) / 2.0), y: titleFrame.maxY + 1.0), size: subtitleSize) + transition.updateFrameAdditiveToCenter(node: self.titleNode, frame: titleFrame) + transition.updateFrameAdditiveToCenter(node: self.subtitleNode, frame: subtitleFrame) + + let buttonSpacing: CGFloat = min(defaultMaxButtonSpacing, width - floor(CGFloat(buttonKeys.count) * defaultButtonSize / CGFloat(buttonKeys.count + 1))) + let buttonsWidth = buttonSpacing * CGFloat(buttonKeys.count - 1) + CGFloat(buttonKeys.count) * defaultButtonSize + var buttonRightOrigin = CGPoint(x: floor((width - buttonsWidth) / 2.0) + buttonsWidth, y: height - 74.0) + for buttonKey in buttonKeys.reversed() { + let buttonNode: PeerInfoHeaderButtonNode + var wasAdded = false + if let current = self.buttonNodes[buttonKey] { + buttonNode = current + } else { + wasAdded = true + buttonNode = PeerInfoHeaderButtonNode(key: buttonKey, action: { [weak self] buttonNode in + self?.buttonPressed(buttonNode) + }) + self.buttonNodes[buttonKey] = buttonNode + self.addSubnode(buttonNode) + } + + let buttonFrame = CGRect(origin: CGPoint(x: buttonRightOrigin.x - defaultButtonSize, y: buttonRightOrigin.y), size: CGSize(width: defaultButtonSize, height: defaultButtonSize)) + buttonRightOrigin.x -= defaultButtonSize + buttonSpacing + let buttonTransition: ContainedViewLayoutTransition = wasAdded ? .immediate : transition + buttonTransition.updateFrame(node: buttonNode, frame: buttonFrame) + let buttonText: String + let buttonIcon: PeerInfoHeaderButtonIcon + switch buttonKey { + case .message: + buttonText = "Message" + buttonIcon = .message + case .call: + buttonText = "Call" + buttonIcon = .call + case .mute: + if let notificationSettings = notificationSettings, case .muted = notificationSettings.muteState { + buttonText = "Unmute" + buttonIcon = .unmute + } else { + buttonText = "Mute" + buttonIcon = .mute + } + case .more: + buttonText = "More" + buttonIcon = .more + } + buttonNode.update(size: buttonFrame.size, text: buttonText, icon: buttonIcon, isExpanded: false, presentationData: presentationData, transition: buttonTransition) + } + + for key in self.buttonNodes.keys { + if !buttonKeys.contains(key) { + if let buttonNode = self.buttonNodes[key] { + self.buttonNodes.removeValue(forKey: key) + buttonNode.removeFromSupernode() + } + } + } + + transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -1000.0), size: CGSize(width: width, height: 1000.0 + height))) + transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: height), size: CGSize(width: width, height: UIScreenPixel))) + + return height + } + + private func buttonPressed(_ buttonNode: PeerInfoHeaderButtonNode) { + self.performButtonAction?(buttonNode.key) + } +} + +protocol PeerInfoPaneNode: ASDisplayNode { + var isReady: Signal { get } + + func update(size: CGSize, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) + func scrollToTop() -> Bool + func findLoadedMessage(id: MessageId) -> Message? + func transitionNodeForGallery(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? +} + +private final class PeerInfoPaneWrapper { + let key: PeerInfoPaneKey + let node: PeerInfoPaneNode + private var appliedParams: (CGSize, Bool, PresentationData)? + + init(key: PeerInfoPaneKey, node: PeerInfoPaneNode) { + self.key = key + self.node = node + } + + func update(size: CGSize, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) { + if let (currentSize, currentIsScrollingLockedAtTop, currentPresentationData) = self.appliedParams { + if currentSize == size && currentIsScrollingLockedAtTop == isScrollingLockedAtTop && currentPresentationData === presentationData { + return + } + } + self.appliedParams = (size, isScrollingLockedAtTop, presentationData) + self.node.update(size: size, isScrollingLockedAtTop: isScrollingLockedAtTop, presentationData: presentationData, synchronous: synchronous, transition: transition) + } +} + +private enum PeerInfoPaneKey { + case media + case files + case links + case music +} + +private final class PeerInfoPaneTabsContainerPaneNode: ASDisplayNode { + private let pressed: () -> Void + + private let titleNode: ImmediateTextNode + private let buttonNode: HighlightTrackingButtonNode + + init(pressed: @escaping () -> Void) { + self.pressed = pressed + + self.titleNode = ImmediateTextNode() + self.titleNode.displaysAsynchronously = false + + self.buttonNode = HighlightTrackingButtonNode() + + super.init() + + self.addSubnode(self.titleNode) + self.addSubnode(self.buttonNode) + + self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside) + self.buttonNode.highligthedChanged = { [weak self] highlighted in + if let strongSelf = self { + if highlighted { + strongSelf.titleNode.layer.removeAnimation(forKey: "opacity") + strongSelf.titleNode.alpha = 0.4 + } else { + strongSelf.titleNode.alpha = 1.0 + strongSelf.titleNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) + } + } + } + } + + @objc private func buttonPressed() { + self.pressed() + } + + func updateText(_ title: String, isSelected: Bool, presentationData: PresentationData) { + self.titleNode.attributedText = NSAttributedString(string: title, font: Font.medium(14.0), textColor: isSelected ? presentationData.theme.list.itemAccentColor : presentationData.theme.list.itemSecondaryTextColor) + } + + func updateLayout(height: CGFloat) -> CGFloat { + let titleSize = self.titleNode.updateLayout(CGSize(width: 200.0, height: .greatestFiniteMagnitude)) + self.titleNode.frame = CGRect(origin: CGPoint(x: 0.0, y: floor((height - titleSize.height) / 2.0)), size: titleSize) + return titleSize.width + } + + func updateArea(size: CGSize, sideInset: CGFloat) { + self.buttonNode.frame = CGRect(origin: CGPoint(x: -sideInset, y: 0.0), size: CGSize(width: size.width + sideInset * 2.0, height: size.height)) + } +} + +private struct PeerInfoPaneSpecifier: Equatable { + var key: PeerInfoPaneKey + var title: String +} + +private final class PeerInfoPaneTabsContainerNode: ASDisplayNode { + private let scrollNode: ASScrollNode + private var paneNodes: [PeerInfoPaneKey: PeerInfoPaneTabsContainerPaneNode] = [:] + private let selectedLineNode: ASImageNode + + private var currentParams: ([PeerInfoPaneSpecifier], PeerInfoPaneKey?, PresentationData)? + + var requestSelectPane: ((PeerInfoPaneKey) -> Void)? + + override init() { + self.scrollNode = ASScrollNode() + + self.selectedLineNode = ASImageNode() + self.selectedLineNode.displaysAsynchronously = false + self.selectedLineNode.displayWithoutProcessing = true + + super.init() + + self.scrollNode.view.showsHorizontalScrollIndicator = false + self.scrollNode.view.scrollsToTop = false + if #available(iOS 11.0, *) { + self.scrollNode.view.contentInsetAdjustmentBehavior = .never + } + + self.addSubnode(self.scrollNode) + self.scrollNode.addSubnode(self.selectedLineNode) + } + + func update(size: CGSize, presentationData: PresentationData, paneList: [PeerInfoPaneSpecifier], selectedPane: PeerInfoPaneKey?, transition: ContainedViewLayoutTransition) { + transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: size)) + + if self.currentParams?.2.theme !== presentationData.theme { + self.selectedLineNode.image = generateImage(CGSize(width: 7.0, height: 4.0), rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + context.setFillColor(presentationData.theme.list.itemAccentColor.cgColor) + context.fillEllipse(in: CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: size.width))) + })?.stretchableImage(withLeftCapWidth: 4, topCapHeight: 1) + } + + if self.currentParams?.0 != paneList || self.currentParams?.1 != selectedPane || self.currentParams?.2 !== presentationData { + self.currentParams = (paneList, selectedPane, presentationData) + for specifier in paneList { + let paneNode: PeerInfoPaneTabsContainerPaneNode + var wasAdded = false + if let current = self.paneNodes[specifier.key] { + paneNode = current + } else { + wasAdded = true + paneNode = PeerInfoPaneTabsContainerPaneNode(pressed: { [weak self] in + self?.paneSelected(specifier.key) + }) + self.paneNodes[specifier.key] = paneNode + self.scrollNode.addSubnode(paneNode) + } + paneNode.updateText(specifier.title, isSelected: selectedPane == specifier.key, presentationData: presentationData) + } + var removeKeys: [PeerInfoPaneKey] = [] + for (key, _) in self.paneNodes { + if !paneList.contains(where: { $0.key == key }) { + removeKeys.append(key) + } + } + for key in removeKeys { + if let paneNode = self.paneNodes.removeValue(forKey: key) { + paneNode.removeFromSupernode() + } + } + } + + var tabSizes: [(CGSize, PeerInfoPaneTabsContainerPaneNode)] = [] + var totalRawTabSize: CGFloat = 0.0 + + var selectedFrame: CGRect? + for specifier in paneList { + guard let paneNode = self.paneNodes[specifier.key] else { + continue + } + let paneNodeWidth = paneNode.updateLayout(height: size.height) + let paneNodeSize = CGSize(width: paneNodeWidth, height: size.height) + tabSizes.append((paneNodeSize, paneNode)) + totalRawTabSize += paneNodeSize.width + } + + let spacing: CGFloat = 32.0 + if totalRawTabSize + CGFloat(tabSizes.count + 1) * spacing <= size.width { + let singleTabSpace = floor((size.width - spacing * 2.0) / CGFloat(tabSizes.count)) + + for i in 0 ..< tabSizes.count { + let (paneNodeSize, paneNode) = tabSizes[i] + let leftOffset = spacing + CGFloat(i) * singleTabSpace + floor((singleTabSpace - paneNodeSize.width) / 2.0) + + let paneFrame = CGRect(origin: CGPoint(x: leftOffset, y: floor((size.height - paneNodeSize.height) / 2.0)), size: paneNodeSize) + paneNode.frame = paneFrame + let areaSideInset = floor((singleTabSpace - paneFrame.size.width) / 2.0) + paneNode.updateArea(size: paneFrame.size, sideInset: areaSideInset) + paneNode.hitTestSlop = UIEdgeInsets(top: 0.0, left: -areaSideInset, bottom: 0.0, right: -areaSideInset) + + if paneList[i].key == selectedPane { + selectedFrame = paneFrame + } + } + self.scrollNode.view.contentSize = CGSize(width: size.width, height: size.height) + } else { + let sideInset: CGFloat = 16.0 + var leftOffset: CGFloat = sideInset + for i in 0 ..< tabSizes.count { + let (paneNodeSize, paneNode) = tabSizes[i] + let paneFrame = CGRect(origin: CGPoint(x: leftOffset, y: floor((size.height - paneNodeSize.height) / 2.0)), size: paneNodeSize) + paneNode.frame = paneFrame + paneNode.updateArea(size: paneFrame.size, sideInset: spacing) + paneNode.hitTestSlop = UIEdgeInsets(top: 0.0, left: -spacing, bottom: 0.0, right: -spacing) + if paneList[i].key == selectedPane { + selectedFrame = paneFrame + } + leftOffset += paneNodeSize.width + spacing + } + self.scrollNode.view.contentSize = CGSize(width: leftOffset + sideInset, height: size.height) + } + + if let selectedFrame = selectedFrame { + self.selectedLineNode.isHidden = false + transition.updateFrame(node: self.selectedLineNode, frame: CGRect(origin: CGPoint(x: selectedFrame.minX, y: size.height - 4.0), size: CGSize(width: selectedFrame.width, height: 4.0))) + } else { + self.selectedLineNode.isHidden = true + } + } + + private func paneSelected(_ key: PeerInfoPaneKey) { + self.requestSelectPane?(key) + } +} + +private final class PeerInfoPaneContainerNode: ASDisplayNode { + private let context: AccountContext + private let peerId: PeerId + + private let coveringBackgroundNode: ASDisplayNode + private let separatorNode: ASDisplayNode + private let tabsContainerNode: PeerInfoPaneTabsContainerNode + private let tapsSeparatorNode: ASDisplayNode + + let isReady = Promise() + var didSetIsReady = false + + private var currentParams: (size: CGSize, isScrollingLockedAtTop: Bool, presentationData: PresentationData)? + + private var availablePanes: [PeerInfoPaneKey] = [] + private var currentPaneKey: PeerInfoPaneKey? + private var currentPane: PeerInfoPaneWrapper? + + private var candidatePane: (PeerInfoPaneWrapper, Disposable)? + + var openMessage: ((MessageId) -> Bool)? + + init(context: AccountContext, peerId: PeerId) { + self.context = context + self.peerId = peerId + + self.separatorNode = ASDisplayNode() + self.separatorNode.isLayerBacked = true + + self.coveringBackgroundNode = ASDisplayNode() + self.coveringBackgroundNode.isLayerBacked = true + + self.tabsContainerNode = PeerInfoPaneTabsContainerNode() + + self.tapsSeparatorNode = ASDisplayNode() + self.tapsSeparatorNode.isLayerBacked = true + + super.init() + + self.addSubnode(self.separatorNode) + self.addSubnode(self.coveringBackgroundNode) + self.addSubnode(self.tabsContainerNode) + self.addSubnode(self.tapsSeparatorNode) + + self.availablePanes = [.media, .files, .links, .music] + self.currentPaneKey = .media + + self.tabsContainerNode.requestSelectPane = { [weak self] key in + guard let strongSelf = self else { + return + } + if strongSelf.currentPaneKey == key { + return + } + + let paneNode: PeerInfoPaneNode + switch key { + case .media: + paneNode = PeerInfoVisualMediaPaneNode(context: strongSelf.context, openMessage: { id in + return self?.openMessage?(id) ?? false + }, peerId: strongSelf.peerId) + case .files: + paneNode = PeerInfoListPaneNode(context: strongSelf.context, openMessage: { id in + return self?.openMessage?(id) ?? false + }, peerId: strongSelf.peerId, tagMask: .file) + case .links: + paneNode = PeerInfoListPaneNode(context: strongSelf.context, openMessage: { id in + return self?.openMessage?(id) ?? false + }, peerId: strongSelf.peerId, tagMask: .webPage) + case .music: + paneNode = PeerInfoListPaneNode(context: strongSelf.context, openMessage: { id in + return self?.openMessage?(id) ?? false + }, peerId: strongSelf.peerId, tagMask: .music) + } + + if let (_, disposable) = strongSelf.candidatePane { + disposable.dispose() + } + + let disposable = MetaDisposable() + strongSelf.candidatePane = (PeerInfoPaneWrapper(key: key, node: paneNode), disposable) + + if let (size, isScrollingLockedAtTop, presentationData) = strongSelf.currentParams { + strongSelf.update(size: size, isScrollingLockedAtTop: isScrollingLockedAtTop, presentationData: presentationData, transition: .immediate) + } + + disposable.set((paneNode.isReady + |> take(1) + |> deliverOnMainQueue).start(next: { _ in + guard let strongSelf = self else { + return + } + if let (candidatePane, _) = strongSelf.candidatePane { + let previousPane = strongSelf.currentPane + strongSelf.candidatePane = nil + strongSelf.currentPaneKey = candidatePane.key + strongSelf.currentPane = candidatePane + + if let (size, isScrollingLockedAtTop, presentationData) = strongSelf.currentParams { + strongSelf.update(size: size, isScrollingLockedAtTop: isScrollingLockedAtTop, presentationData: presentationData, transition: .animated(duration: 0.35, curve: .spring)) + + if let previousPane = previousPane { + let directionToRight: Bool + if let previousIndex = strongSelf.availablePanes.index(of: previousPane.key), let updatedIndex = strongSelf.availablePanes.index(of: candidatePane.key) { + directionToRight = previousIndex < updatedIndex + } else { + directionToRight = false + } + + let offset: CGFloat = directionToRight ? previousPane.node.bounds.width : -previousPane.node.bounds.width + candidatePane.node.layer.animatePosition(from: CGPoint(x: offset, y: 0.0), to: CGPoint(), duration: 0.35, timingFunction: kCAMediaTimingFunctionSpring, additive: true) + let previousNode = previousPane.node + previousNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: -offset, y: 0.0), duration: 0.35, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, additive: true, completion: { [weak previousNode] _ in + previousNode?.removeFromSupernode() + }) + } + } else { + if let previousPane = previousPane { + previousPane.node.removeFromSupernode() + } + } + } + })) + } + } + + func scrollToTop() -> Bool { + if let currentPane = self.currentPane { + return currentPane.node.scrollToTop() + } else { + return false + } + } + + func findLoadedMessage(id: MessageId) -> Message? { + return self.currentPane?.node.findLoadedMessage(id: id) + } + + func transitionNodeForGallery(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + return self.currentPane?.node.transitionNodeForGallery(messageId: messageId, media: media) + } + + func update(size: CGSize, isScrollingLockedAtTop: Bool, presentationData: PresentationData, transition: ContainedViewLayoutTransition) { + self.currentParams = (size, isScrollingLockedAtTop, presentationData) + + transition.updateAlpha(node: self.coveringBackgroundNode, alpha: isScrollingLockedAtTop ? 0.0 : 1.0) + + self.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor + self.coveringBackgroundNode.backgroundColor = presentationData.theme.rootController.navigationBar.backgroundColor + self.separatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor + self.tapsSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor + + let tabsHeight: CGFloat = 48.0 + + transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: size.width, height: UIScreenPixel))) + transition.updateFrame(node: self.coveringBackgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: tabsHeight))) + + transition.updateFrame(node: self.tapsSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: tabsHeight - UIScreenPixel), size: CGSize(width: size.width, height: UIScreenPixel))) + + transition.updateFrame(node: self.tabsContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: tabsHeight))) + self.tabsContainerNode.update(size: CGSize(width: size.width, height: tabsHeight), presentationData: presentationData, paneList: self.availablePanes.map { key in + let title: String + switch key { + case .media: + title = "Media" + case .files: + title = "Files" + case .links: + title = "Links" + case .music: + title = "Audio" + } + return PeerInfoPaneSpecifier(key: key, title: title) + }, selectedPane: self.currentPaneKey, transition: transition) + + let paneFrame = CGRect(origin: CGPoint(x: 0.0, y: tabsHeight), size: CGSize(width: size.width, height: size.height - tabsHeight)) + + if self.currentPane?.key != self.currentPaneKey { + if let currentPane = self.currentPane { + currentPane.node.removeFromSupernode() + self.currentPane = nil + } + + if let currentPaneKey = self.currentPaneKey { + let paneNode: PeerInfoPaneNode + switch currentPaneKey { + case .media: + paneNode = PeerInfoVisualMediaPaneNode(context: self.context, openMessage: { [weak self] id in + return self?.openMessage?(id) ?? false + }, peerId: self.peerId) + case .files: + paneNode = PeerInfoListPaneNode(context: self.context, openMessage: { [weak self] id in + return self?.openMessage?(id) ?? false + }, peerId: self.peerId, tagMask: .file) + case .links: + paneNode = PeerInfoListPaneNode(context: self.context, openMessage: { [weak self] id in + return self?.openMessage?(id) ?? false + }, peerId: self.peerId, tagMask: .webPage) + case .music: + paneNode = PeerInfoListPaneNode(context: self.context, openMessage: { [weak self] id in + return self?.openMessage?(id) ?? false + }, peerId: self.peerId, tagMask: .music) + } + self.currentPane = PeerInfoPaneWrapper(key: currentPaneKey, node: paneNode) + } + } + + if let currentPane = self.currentPane { + let paneWasAdded = currentPane.node.supernode == nil + if paneWasAdded { + self.addSubnode(currentPane.node) + } + + let paneTransition: ContainedViewLayoutTransition = paneWasAdded ? .immediate : transition + paneTransition.updateFrame(node: currentPane.node, frame: paneFrame) + currentPane.update(size: paneFrame.size, isScrollingLockedAtTop: isScrollingLockedAtTop, presentationData: presentationData, synchronous: paneWasAdded, transition: paneTransition) + } + if let (candidatePane, _) = self.candidatePane { + let paneTransition: ContainedViewLayoutTransition = .immediate + paneTransition.updateFrame(node: candidatePane.node, frame: paneFrame) + candidatePane.update(size: paneFrame.size, isScrollingLockedAtTop: isScrollingLockedAtTop, presentationData: presentationData, synchronous: true, transition: paneTransition) + } + if !self.didSetIsReady { + self.didSetIsReady = true + if let currentPane = self.currentPane { + self.isReady.set(currentPane.node.isReady) + } else { + self.isReady.set(.single(true)) + } + } + } +} + +protocol PeerInfoScreenItem: class { + var id: AnyHashable { get } + func node() -> PeerInfoScreenItemNode +} + +class PeerInfoScreenItemNode: ASDisplayNode { + var bringToFrontForHighlight: (() -> Void)? + + func update(width: CGFloat, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, transition: ContainedViewLayoutTransition) -> CGFloat { + preconditionFailure() + } +} + +private final class PeerInfoScreenItemSectionContainerNode: ASDisplayNode { + let id: AnyHashable + + private let backgroundNode: ASDisplayNode + private let topSeparatorNode: ASDisplayNode + private let bottomSeparatorNode: ASDisplayNode + + private var currentItems: [PeerInfoScreenItem] = [] + private var itemNodes: [AnyHashable: PeerInfoScreenItemNode] = [:] + + init(id: AnyHashable) { + self.id = id + + self.backgroundNode = ASDisplayNode() + self.backgroundNode.isLayerBacked = true + + self.topSeparatorNode = ASDisplayNode() + self.topSeparatorNode.isLayerBacked = true + + self.bottomSeparatorNode = ASDisplayNode() + self.bottomSeparatorNode.isLayerBacked = true + + super.init() + + self.addSubnode(self.backgroundNode) + self.addSubnode(self.topSeparatorNode) + self.addSubnode(self.bottomSeparatorNode) + } + + func update(width: CGFloat, presentationData: PresentationData, items: [PeerInfoScreenItem], transition: ContainedViewLayoutTransition) -> CGFloat { + self.backgroundNode.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor + self.topSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor + self.bottomSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor + + var contentHeight: CGFloat = 0.0 + + for i in 0 ..< items.count { + let item = items[i] + + let itemNode: PeerInfoScreenItemNode + var wasAdded = false + if let current = self.itemNodes[item.id] { + itemNode = current + } else { + wasAdded = true + itemNode = item.node() + self.itemNodes[item.id] = itemNode + self.addSubnode(itemNode) + itemNode.bringToFrontForHighlight = { [weak self, weak itemNode] in + guard let strongSelf = self, let itemNode = itemNode else { + return + } + strongSelf.view.bringSubviewToFront(itemNode.view) + } + } + + let itemTransition: ContainedViewLayoutTransition = wasAdded ? .immediate : transition + + let itemHeight = itemNode.update(width: width, presentationData: presentationData, item: item, topItem: i == 0 ? nil : items[i - 1], bottomItem: (i == items.count - 1) ? nil : items[i + 1], transition: itemTransition) + let itemFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: width, height: itemHeight)) + itemTransition.updateFrame(node: itemNode, frame: itemFrame) + if wasAdded { + itemNode.alpha = 0.0 + transition.updateAlpha(node: itemNode, alpha: 1.0) + } + contentHeight += itemHeight + } + + var removeIds: [AnyHashable] = [] + for (id, _) in self.itemNodes { + if !items.contains(where: { $0.id == id }) { + removeIds.append(id) + } + } + for id in removeIds { + if let itemNode = self.itemNodes[id] { + transition.updateAlpha(node: itemNode, alpha: 0.0, completion: { [weak itemNode] _ in + itemNode?.removeFromSupernode() + }) + } + } + + transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: contentHeight))) + transition.updateFrame(node: self.topSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: width, height: UIScreenPixel))) + transition.updateFrame(node: self.bottomSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: width, height: UIScreenPixel))) + + return contentHeight + } +} + +private final class PeerInfoScreenData { + let peer: Peer? + let cachedData: CachedPeerData? + let presence: TelegramUserPresence? + let notificationSettings: TelegramPeerNotificationSettings? + + init( + peer: Peer?, + cachedData: CachedPeerData?, + presence: TelegramUserPresence?, + notificationSettings: TelegramPeerNotificationSettings? + ) { + self.peer = peer + self.cachedData = cachedData + self.presence = presence + self.notificationSettings = notificationSettings + } +} + +private enum PeerInfoScreenInputData: Equatable { + case none + case user +} + +private func peerInfoScreenData(context: AccountContext, peerId: PeerId) -> Signal { + return context.account.postbox.combinedView(keys: [.basicPeer(peerId)]) + |> map { view -> PeerInfoScreenInputData in + guard let peer = (view.views[.basicPeer(peerId)] as? BasicPeerView)?.peer else { + return .none + } + if let _ = peer as? TelegramUser { + return .user + } else { + preconditionFailure() + } + } + |> distinctUntilChanged + |> mapToSignal { inputData -> Signal in + switch inputData { + case .none: + return .single(PeerInfoScreenData( + peer: nil, + cachedData: nil, + presence: nil, + notificationSettings: nil + )) + case .user: + return context.account.viewTracker.peerView(peerId, updateData: true) + |> map { view -> PeerInfoScreenData in + return PeerInfoScreenData( + peer: view.peers[peerId], + cachedData: view.cachedData, + presence: view.peerPresences[peerId] as? TelegramUserPresence, + notificationSettings: view.notificationSettings as? TelegramPeerNotificationSettings + ) + } + } + } +} + +private final class PeerInfoInteraction { + let openUsername: (String) -> Void + let openPhone: (String) -> Void + + init( + openUsername: @escaping (String) -> Void, + openPhone: @escaping (String) -> Void + ) { + self.openUsername = openUsername + self.openPhone = openPhone + } +} + +private func peerInfoSectionItems(data: PeerInfoScreenData?, presentationData: PresentationData, interaction: PeerInfoInteraction) -> [PeerInfoScreenItem] { + var items: [PeerInfoScreenItem] = [] + if let user = data?.peer as? TelegramUser { + if let cachedData = data?.cachedData as? CachedUserData { + if let about = cachedData.about { + items.append(PeerInfoScreenLabeledValueItem(id: 0, label: "bio", text: about, textColor: .primary, textBehavior: .multiLine(maxLines: 10), action: nil)) + } + } + if let username = user.username { + items.append(PeerInfoScreenLabeledValueItem(id: 1, label: "username", text: "@\(username)", textColor: .accent, action: { + interaction.openUsername(username) + })) + } + if let phone = user.phone { + items.append(PeerInfoScreenLabeledValueItem(id: 2, label: "mobile", text: "\(formatPhoneNumber(phone))", textColor: .accent, action: { + interaction.openPhone(phone) + })) + } + } + return items +} + +private final class PeerInfoNavigationNode: ASDisplayNode { + private let backgroundNode: ASDisplayNode + private let separatorContainerNode: ASDisplayNode + private let separatorCoveringNode: ASDisplayNode + private let separatorNode: ASDisplayNode + private let titleNode: ImmediateTextNode + + private var currentParams: (PresentationData, Peer?)? + + override init() { + self.backgroundNode = ASDisplayNode() + self.backgroundNode.isLayerBacked = true + + self.separatorContainerNode = ASDisplayNode() + self.separatorContainerNode.isLayerBacked = true + self.separatorContainerNode.clipsToBounds = true + + self.separatorCoveringNode = ASDisplayNode() + self.separatorCoveringNode.isLayerBacked = true + + self.separatorNode = ASDisplayNode() + self.separatorNode.isLayerBacked = true + + self.titleNode = ImmediateTextNode() + + super.init() + + self.addSubnode(self.backgroundNode) + + self.separatorContainerNode.addSubnode(self.separatorNode) + self.separatorContainerNode.addSubnode(self.separatorCoveringNode) + self.addSubnode(self.separatorContainerNode) + + self.addSubnode(self.titleNode) + } + + func update(size: CGSize, statusBarHeight: CGFloat, navigationHeight: CGFloat, offset: CGFloat, paneContainerOffset: CGFloat, presentationData: PresentationData, peer: Peer?, transition: ContainedViewLayoutTransition) { + if let (currentPresentationData, currentPeer) = self.currentParams { + if currentPresentationData !== presentationData || currentPeer !== peer { + if let peer = peer { + self.titleNode.attributedText = NSAttributedString(string: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), font: Font.semibold(17.0), textColor: presentationData.theme.rootController.navigationBar.primaryTextColor) + } + } + } + + if self.currentParams?.0.theme !== presentationData.theme { + self.backgroundNode.backgroundColor = presentationData.theme.rootController.navigationBar.backgroundColor + self.separatorNode.backgroundColor = presentationData.theme.rootController.navigationBar.separatorColor + self.separatorCoveringNode.backgroundColor = presentationData.theme.rootController.navigationBar.backgroundColor + } + + self.currentParams = (presentationData, peer) + + let titleSize = self.titleNode.updateLayout(CGSize(width: size.width - 100.0, height: .greatestFiniteMagnitude)) + let titleFrame = CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: statusBarHeight + floor((navigationHeight - statusBarHeight - titleSize.height) / 2.0)), size: titleSize) + transition.updateFrameAdditiveToCenter(node: self.titleNode, frame: titleFrame) + + transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: size)) + transition.updateFrame(node: self.separatorContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: size.height), size: CGSize(width: size.width, height: UIScreenPixel))) + transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: UIScreenPixel))) + transition.updateFrame(node: self.separatorCoveringNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -offset + paneContainerOffset - size.height), size: CGSize(width: size.width, height: 10.0 + UIScreenPixel))) + + let revealOffset: CGFloat = 100.0 + let progress: CGFloat = max(0.0, min(1.0, offset / revealOffset)) + + transition.updateAlpha(node: self.backgroundNode, alpha: progress) + transition.updateAlpha(node: self.separatorNode, alpha: progress) + transition.updateAlpha(node: self.titleNode, alpha: progress) + } +} + +private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate { + private weak var controller: PeerInfoScreen? + + private let context: AccountContext + private let peerId: PeerId + private var presentationData: PresentationData + private let scrollNode: ASScrollNode + + private let navigationNode: PeerInfoNavigationNode + private let headerNode: PeerInfoHeaderNode + private let infoSection: PeerInfoScreenItemSectionContainerNode + private let paneContainerNode: PeerInfoPaneContainerNode + private var isPaneAreaExpanded: Bool = false + private var ignoreScrolling: Bool = false + + private var _interaction: PeerInfoInteraction? + private var interaction: PeerInfoInteraction { + return self._interaction! + } + + private var validLayout: (ContainerViewLayout, CGFloat)? + private var data: PeerInfoScreenData? + private var dataDisposable: Disposable? + + private let _ready = Promise() + var ready: Promise { + return self._ready + } + private var didSetReady = false + + init(controller: PeerInfoScreen, context: AccountContext, peerId: PeerId) { + self.controller = controller + self.context = context + self.peerId = peerId + self.presentationData = context.sharedContext.currentPresentationData.with { $0 } + + self.scrollNode = ASScrollNode() + + self.navigationNode = PeerInfoNavigationNode() + self.headerNode = PeerInfoHeaderNode(context: context) + self.infoSection = PeerInfoScreenItemSectionContainerNode(id: 0) + self.paneContainerNode = PeerInfoPaneContainerNode(context: context, peerId: peerId) + + super.init() + + self._interaction = PeerInfoInteraction( + openUsername: { [weak self] value in + self?.openUsername(value: value) + }, + openPhone: { [weak self] value in + self?.openPhone(value: value) + } + ) + + self.backgroundColor = self.presentationData.theme.list.blocksBackgroundColor + + self.scrollNode.view.showsVerticalScrollIndicator = false + if #available(iOS 11.0, *) { + self.scrollNode.view.contentInsetAdjustmentBehavior = .never + } + self.scrollNode.view.scrollsToTop = false + self.scrollNode.view.delegate = self + self.addSubnode(self.scrollNode) + self.addSubnode(self.navigationNode) + + self.scrollNode.addSubnode(self.headerNode) + self.scrollNode.addSubnode(self.infoSection) + self.scrollNode.addSubnode(self.paneContainerNode) + + self.paneContainerNode.openMessage = { [weak self] id in + return self?.openMessage(id: id) ?? false + } + + self.headerNode.performButtonAction = { [weak self] key in + self?.performButtonAction(key: key) + } + + self.dataDisposable = (peerInfoScreenData(context: context, peerId: peerId) + |> deliverOnMainQueue).start(next: { [weak self] data in + guard let strongSelf = self else { + return + } + strongSelf.updateData(data) + }) + } + + deinit { + self.dataDisposable?.dispose() + } + + override func didLoad() { + super.didLoad() + } + + private func updateData(_ data: PeerInfoScreenData) { + self.data = data + if let (layout, navigationHeight) = self.validLayout { + self.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate) + } + } + + func scrollToTop() { + if self.isPaneAreaExpanded { + if !self.paneContainerNode.scrollToTop() { + + } + } else { + self.scrollNode.view.setContentOffset(CGPoint(), animated: true) + } + } + + private func openMessage(id: MessageId) -> Bool { + guard let galleryMessage = self.paneContainerNode.findLoadedMessage(id: id), let controller = self.controller, let navigationController = controller.navigationController as? NavigationController else { + return false + } + self.view.endEditing(true) + + return self.context.sharedContext.openChatMessage(OpenChatMessageParams(context: self.context, message: galleryMessage, standalone: false, reverseMessageGalleryOrder: true, navigationController: navigationController, dismissInput: { [weak self] in + self?.view.endEditing(true) + }, present: { [weak self] c, a in + self?.controller?.present(c, in: .window(.root), with: a, blockInteraction: true) + }, transitionNode: { [weak self] messageId, media in + guard let strongSelf = self else { + return nil + } + return strongSelf.paneContainerNode.transitionNodeForGallery(messageId: messageId, media: media) + }, addToTransitionSurface: { [weak self] view in + guard let strongSelf = self else { + return + } + strongSelf.view.addSubview(view) + }, openUrl: { url in + //self?.openUrl(url) + }, openPeer: { peer, navigation in + //self?.controllerInteraction?.openPeer(peer.id, navigation, nil) + }, callPeer: { peerId in + //self?.controllerInteraction?.callPeer(peerId) + }, enqueueMessage: { _ in + }, sendSticker: nil, setupTemporaryHiddenMedia: { _, _, _ in }, chatAvatarHiddenMedia: { _, _ in })) + } + + private func performButtonAction(key: PeerInfoHeaderButtonKey) { + guard let controller = self.controller else { + return + } + switch key { + case .message: + if let navigationController = controller.navigationController as? NavigationController { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(self.peerId))) + } + case .call: + self.requestCall() + case .mute: + let peerId = self.peerId + let _ = (self.context.account.postbox.transaction { transaction -> (TelegramPeerNotificationSettings, GlobalNotificationSettings) in + let peerSettings: TelegramPeerNotificationSettings = (transaction.getPeerNotificationSettings(peerId) as? TelegramPeerNotificationSettings) ?? TelegramPeerNotificationSettings.defaultSettings + let globalSettings: GlobalNotificationSettings = (transaction.getPreferencesEntry(key: PreferencesKeys.globalNotifications) as? GlobalNotificationSettings) ?? GlobalNotificationSettings.defaultSettings + return (peerSettings, globalSettings) + } + |> deliverOnMainQueue).start(next: { [weak self] peerSettings, globalSettings in + guard let strongSelf = self else { + return + } + let soundSettings: NotificationSoundSettings? + if case .default = peerSettings.messageSound { + soundSettings = NotificationSoundSettings(value: nil) + } else { + soundSettings = NotificationSoundSettings(value: peerSettings.messageSound) + } + let muteSettingsController = notificationMuteSettingsController(presentationData: strongSelf.presentationData, notificationSettings: globalSettings.effective.groupChats, soundSettings: soundSettings, openSoundSettings: { + guard let strongSelf = self else { + return + } + let soundController = notificationSoundSelectionController(context: strongSelf.context, isModal: true, currentSound: peerSettings.messageSound, defaultSound: globalSettings.effective.groupChats.sound, completion: { sound in + guard let strongSelf = self else { + return + } + let _ = updatePeerNotificationSoundInteractive(account: strongSelf.context.account, peerId: strongSelf.peerId, sound: sound).start() + }) + strongSelf.controller?.present(soundController, in: .window(.root)) + }, updateSettings: { value in + guard let strongSelf = self else { + return + } + let _ = updatePeerMuteSetting(account: strongSelf.context.account, peerId: strongSelf.peerId, muteInterval: value).start() + }) + strongSelf.controller?.present(muteSettingsController, in: .window(.root)) + }) + case .more: + let actionSheet = ActionSheetController(presentationData: self.presentationData) + let dismissAction: () -> Void = { [weak actionSheet] in + actionSheet?.dismissAnimated() + } + var reportSpam = false + var deleteChat = false + actionSheet.setItemGroups([ + ActionSheetItemGroup(items: [ + ActionSheetButtonItem(title: presentationData.strings.UserInfo_StartSecretChat, color: .accent, action: { [weak self] in + dismissAction() + self?.openStartSecretChat() + }) + ]), + ActionSheetItemGroup(items: [ActionSheetButtonItem(title: self.presentationData.strings.Common_Cancel, action: { dismissAction() })]) + ]) + controller.present(actionSheet, in: .window(.root)) + } + } + + private func openStartSecretChat() { + let peerId = self.peerId + let _ = (self.context.account.postbox.transaction { transaction -> (Peer?, PeerId?) in + let peer = transaction.getPeer(peerId) + let filteredPeerIds = Array(transaction.getAssociatedPeerIds(peerId)).filter { $0.namespace == Namespaces.Peer.SecretChat } + var activeIndices: [ChatListIndex] = [] + for associatedId in filteredPeerIds { + if let state = (transaction.getPeer(associatedId) as? TelegramSecretChat)?.embeddedState { + switch state { + case .active, .handshake: + if let (_, index) = transaction.getPeerChatListIndex(associatedId) { + activeIndices.append(index) + } + default: + break + } + } + } + activeIndices.sort() + if let index = activeIndices.last { + return (peer, index.messageIndex.id.peerId) + } else { + return (peer, nil) + } + } + |> deliverOnMainQueue).start(next: { [weak self] peer, currentPeerId in + guard let strongSelf = self else { + return + } + if let currentPeerId = currentPeerId { + if let navigationController = (strongSelf.controller?.navigationController as? NavigationController) { + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(currentPeerId))) + } + } else if let controller = strongSelf.controller { + let displayTitle = peer?.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder) ?? "" + controller.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.UserInfo_StartSecretChatConfirmation(displayTitle).0, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.UserInfo_StartSecretChatStart, action: { + guard let strongSelf = self else { + return + } + var createSignal = createSecretChat(account: strongSelf.context.account, peerId: peerId) + var cancelImpl: (() -> Void)? + let progressSignal = Signal { subscriber in + if let strongSelf = self { + let statusController = OverlayStatusController(theme: strongSelf.presentationData.theme, type: .loading(cancelled: { + cancelImpl?() + })) + strongSelf.controller?.present(statusController, in: .window(.root)) + return ActionDisposable { [weak controller] in + Queue.mainQueue().async() { + controller?.dismiss() + } + } + } else { + return EmptyDisposable + } + } + |> runOn(Queue.mainQueue()) + |> delay(0.15, queue: Queue.mainQueue()) + let progressDisposable = progressSignal.start() + + createSignal = createSignal + |> afterDisposed { + Queue.mainQueue().async { + progressDisposable.dispose() + } + } + let createSecretChatDisposable = MetaDisposable() + cancelImpl = { + createSecretChatDisposable.set(nil) + } + + createSecretChatDisposable.set((createSignal + |> deliverOnMainQueue).start(next: { peerId in + guard let strongSelf = self else { + return + } + if let navigationController = (strongSelf.controller?.navigationController as? NavigationController) { + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(strongSelf.peerId))) + } + }, error: { _ in + guard let strongSelf = self else { + return + } + strongSelf.controller?.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root)) + })) + })]), in: .window(.root)) + } + }) + } + + private func openUsername(value: String) { + let shareController = ShareController(context: context, subject: .url("\(value)")) + self.controller?.present(shareController, in: .window(.root)) + } + + private func requestCall() { + guard let peer = self.data?.peer as? TelegramUser, let cachedUserData = self.data?.cachedData as? CachedUserData else { + return + } + if cachedUserData.callsPrivate { + self.controller?.present(textAlertController(context: self.context, title: self.presentationData.strings.Call_ConnectionErrorTitle, text: self.presentationData.strings.Call_PrivacyErrorMessage(peer.compactDisplayTitle).0, actions: [TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_OK, action: {})]), in: .window(.root)) + return + } + + let callResult = self.context.sharedContext.callManager?.requestCall(account: self.context.account, peerId: peer.id, endCurrentIfAny: false) + if let callResult = callResult, case let .alreadyInProgress(currentPeerId) = callResult { + if currentPeerId == peer.id { + self.context.sharedContext.navigateToCurrentCall() + } else { + let _ = (self.context.account.postbox.transaction { transaction -> (Peer?, Peer?) in + return (transaction.getPeer(peer.id), transaction.getPeer(currentPeerId)) + } + |> deliverOnMainQueue).start(next: { [weak self] peer, current in + guard let strongSelf = self else { + return + } + if let peer = peer, let current = current { + strongSelf.controller?.present(textAlertController(context: strongSelf.context, title: strongSelf.presentationData.strings.Call_CallInProgressTitle, text: strongSelf.presentationData.strings.Call_CallInProgressMessage(current.compactDisplayTitle, peer.compactDisplayTitle).0, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_OK, action: { + guard let strongSelf = self else { + return + } + let _ = strongSelf.context.sharedContext.callManager?.requestCall(account: strongSelf.context.account, peerId: peer.id, endCurrentIfAny: true) + })]), in: .window(.root)) + } + }) + } + } + } + + private func openPhone(value: String) { + let _ = (getUserPeer(postbox: self.context.account.postbox, peerId: peerId) + |> deliverOnMainQueue).start(next: { [weak self] peer, _ in + guard let strongSelf = self else { + return + } + if let peer = peer as? TelegramUser, let peerPhoneNumber = peer.phone, formatPhoneNumber(value) == formatPhoneNumber(peerPhoneNumber) { + let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData) + let dismissAction: () -> Void = { [weak actionSheet] in + actionSheet?.dismissAnimated() + } + actionSheet.setItemGroups([ + ActionSheetItemGroup(items: [ + ActionSheetButtonItem(title: strongSelf.presentationData.strings.UserInfo_TelegramCall, action: { + dismissAction() + self?.requestCall() + }), + ActionSheetButtonItem(title: strongSelf.presentationData.strings.UserInfo_PhoneCall, action: { + dismissAction() + + guard let strongSelf = self else { + return + } + strongSelf.context.sharedContext.applicationBindings.openUrl("tel:\(formatPhoneNumber(value).replacingOccurrences(of: " ", with: ""))") + }), + ]), + ActionSheetItemGroup(items: [ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, action: { dismissAction() })]) + ]) + strongSelf.controller?.present(actionSheet, in: .window(.root)) + } else { + strongSelf.context.sharedContext.applicationBindings.openUrl("tel:\(formatPhoneNumber(value).replacingOccurrences(of: " ", with: ""))") + } + }) + } + + func containerLayoutUpdated(layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition) { + self.validLayout = (layout, navigationHeight) + + self.ignoreScrolling = true + + transition.updateFrame(node: self.navigationNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: navigationHeight))) + transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: layout.size)) + + let sectionSpacing: CGFloat = 24.0 + + var contentHeight: CGFloat = 0.0 + + let headerHeight = self.headerNode.update(width: layout.size.width, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, presentationData: self.presentationData, peer: self.data?.peer, cachedData: self.data?.cachedData, notificationSettings: self.data?.notificationSettings, presence: self.data?.presence, transition: transition) + transition.updateFrame(node: self.headerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: layout.size.width, height: headerHeight))) + contentHeight += headerHeight + contentHeight += sectionSpacing + + let infoSectionHeight = self.infoSection.update(width: layout.size.width, presentationData: self.presentationData, items: peerInfoSectionItems(data: self.data, presentationData: self.presentationData, interaction: self.interaction), transition: transition) + let infoSectionFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: layout.size.width, height: infoSectionHeight)) + transition.updateFrame(node: self.infoSection, frame: infoSectionFrame) + contentHeight += infoSectionHeight + contentHeight += sectionSpacing + + let paneContainerSize = CGSize(width: layout.size.width, height: layout.size.height - navigationHeight) + self.paneContainerNode.update(size: paneContainerSize, isScrollingLockedAtTop: !self.isPaneAreaExpanded, presentationData: self.presentationData, transition: transition) + transition.updateFrame(node: self.paneContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: paneContainerSize)) + contentHeight += layout.size.height - navigationHeight + + self.scrollNode.view.contentSize = CGSize(width: layout.size.width, height: contentHeight) + + if self.isPaneAreaExpanded { + transition.updateBounds(node: self.scrollNode, bounds: CGRect(origin: CGPoint(x: 0.0, y: contentHeight - self.scrollNode.bounds.height), size: self.scrollNode.bounds.size)) + } else { + let maxOffsetY = max(0.0, contentHeight - floor(self.scrollNode.bounds.height * 1.5)) + if self.scrollNode.view.contentOffset.y > maxOffsetY { + //transition.updateBounds(node: self.scrollNode, bounds: CGRect(origin: CGPoint(x: 0.0, y: maxOffsetY), size: self.scrollNode.bounds.size)) + } + } + + self.ignoreScrolling = false + self.updateNavigation(transition: transition) + + if !self.didSetReady && self.data != nil { + self.didSetReady = true + self._ready.set(self.paneContainerNode.isReady.get()) + } + } + + private func updateNavigation(transition: ContainedViewLayoutTransition) { + let offsetY = self.scrollNode.view.contentOffset.y + + if offsetY <= 1.0 { + self.scrollNode.view.bounces = true + } else { + self.scrollNode.view.bounces = false + } + + if let (layout, navigationHeight) = self.validLayout { + self.navigationNode.update(size: CGSize(width: layout.size.width, height: navigationHeight), statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, offset: offsetY, paneContainerOffset: self.paneContainerNode.frame.minY, presentationData: self.presentationData, peer: self.data?.peer, transition: transition) + } + } + + func scrollViewDidScroll(_ scrollView: UIScrollView) { + if self.ignoreScrolling { + return + } + self.updateNavigation(transition: .immediate) + } + + func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) { + guard let (_, navigationHeight) = self.validLayout else { + return + } + let snapDurationFactor = max(0.5, min(1.5, abs(velocity.y) * 0.8)) + + var snapToOffset: CGFloat? + let offset = targetContentOffset.pointee.y + + let headerMaxOffset = self.headerNode.bounds.height - navigationHeight + let collapsedPanesOffset = max(0.0, scrollView.contentSize.height - floor(scrollNode.bounds.height * 1.5)) + let expandedPanesOffset = scrollView.contentSize.height - self.scrollNode.bounds.height + + if offset > collapsedPanesOffset { + if velocity.y < 0.0 { + var targetOffset = collapsedPanesOffset + if targetOffset < headerMaxOffset { + targetOffset = 0.0 + } + snapToOffset = targetOffset + } else { + snapToOffset = expandedPanesOffset + } + } else if offset < headerMaxOffset && offset > 0.0 { + let directionIsDown: Bool + if abs(velocity.y) > 0.2 { + directionIsDown = velocity.y >= 0.0 + } else { + directionIsDown = offset >= headerMaxOffset / 2.0 + } + + if directionIsDown { + snapToOffset = headerMaxOffset + } else { + snapToOffset = 0.0 + } + } else if self.isPaneAreaExpanded && offset < expandedPanesOffset { + let directionIsDown: Bool + if abs(velocity.y) > 0.2 { + directionIsDown = velocity.y >= 0.0 + } else { + directionIsDown = offset >= headerMaxOffset / 2.0 + } + + if directionIsDown { + snapToOffset = headerMaxOffset + } else { + snapToOffset = 0.0 + } + } + + if let snapToOffset = snapToOffset { + targetContentOffset.pointee = scrollView.contentOffset + DispatchQueue.main.async { + let isPaneAreaExpanded = abs(snapToOffset - expandedPanesOffset) < CGFloat.ulpOfOne ? true : false + self.isPaneAreaExpanded = isPaneAreaExpanded + let currentOffset = scrollView.contentOffset + let transition: ContainedViewLayoutTransition = .animated(duration: 0.3 * Double(1.0 / snapDurationFactor), curve: .spring) + self.ignoreScrolling = true + transition.updateBounds(node: self.scrollNode, bounds: CGRect(origin: CGPoint(x: 0.0, y: snapToOffset), size: self.scrollNode.bounds.size)) + self.ignoreScrolling = false + if let (layout, navigationHeight) = self.validLayout { + self.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: transition) + } + } + } + } + + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + guard let result = super.hitTest(point, with: event) else { + return nil + } + var currentParent: UIView? = result + var enableScrolling = true + while true { + if currentParent == nil || currentParent === self.view { + break + } + if let scrollView = currentParent as? UIScrollView { + if scrollView === self.scrollNode.view { + break + } + if scrollView.isDecelerating && scrollView.contentOffset.y < -scrollView.contentInset.top { + return self.scrollNode.view + } + } else if let listView = currentParent as? ListViewBackingView, let listNode = listView.target { + if listNode.scroller.isDecelerating && listNode.scroller.contentOffset.y < listNode.scroller.contentInset.top { + return self.scrollNode.view + } + } + currentParent = currentParent?.superview + } + return result + } +} + +public final class PeerInfoScreen: ViewController { + private let context: AccountContext + private let peerId: PeerId + + private var presentationData: PresentationData + + private var controllerNode: PeerInfoScreenNode { + return self.displayNode as! PeerInfoScreenNode + } + + private let _ready = Promise() + override public var ready: Promise { + return self._ready + } + + public init(context: AccountContext, peerId: PeerId) { + self.context = context + self.peerId = peerId + + self.presentationData = context.sharedContext.currentPresentationData.with { $0 } + + let baseNavigationBarPresentationData = NavigationBarPresentationData(presentationData: self.presentationData) + super.init(navigationBarPresentationData: NavigationBarPresentationData( + theme: NavigationBarTheme( + buttonColor: baseNavigationBarPresentationData.theme.buttonColor, + disabledButtonColor: baseNavigationBarPresentationData.theme.disabledButtonColor, + primaryTextColor: baseNavigationBarPresentationData.theme.primaryTextColor, + backgroundColor: .clear, + separatorColor: .clear, + badgeBackgroundColor: baseNavigationBarPresentationData.theme.badgeBackgroundColor, + badgeStrokeColor: baseNavigationBarPresentationData.theme.badgeStrokeColor, + badgeTextColor: baseNavigationBarPresentationData.theme.badgeTextColor + ), strings: baseNavigationBarPresentationData.strings)) + + self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style + + self.scrollToTop = { [weak self] in + self?.controllerNode.scrollToTop() + } + } + + required init(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override public func loadDisplayNode() { + self.displayNode = PeerInfoScreenNode(controller: self, context: self.context, peerId: self.peerId) + + self._ready.set(self.controllerNode.ready.get()) + + super.displayNodeDidLoad() + } + + override public func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + } + + override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { + super.containerLayoutUpdated(layout, transition: transition) + + self.controllerNode.containerLayoutUpdated(layout: layout, navigationHeight: self.navigationHeight, transition: transition) + } +} + +private func getUserPeer(postbox: Postbox, peerId: PeerId) -> Signal<(Peer?, CachedPeerData?), NoError> { + return postbox.transaction { transaction -> (Peer?, CachedPeerData?) in + guard let peer = transaction.getPeer(peerId) else { + return (nil, nil) + } + var resultPeer: Peer? + if let peer = peer as? TelegramSecretChat { + resultPeer = transaction.getPeer(peer.regularPeerId) + } else { + resultPeer = peer + } + return (resultPeer, resultPeer.flatMap({ transaction.getPeerCachedData(peerId: $0.id) })) + } +} diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoScreenLabeledValueItem.swift b/submodules/TelegramUI/TelegramUI/PeerInfoScreenLabeledValueItem.swift new file mode 100644 index 0000000000..d7f382389f --- /dev/null +++ b/submodules/TelegramUI/TelegramUI/PeerInfoScreenLabeledValueItem.swift @@ -0,0 +1,123 @@ +import AsyncDisplayKit +import Display +import TelegramPresentationData + +enum PeerInfoScreenLabeledValueTextColor { + case primary + case accent +} + +enum PeerInfoScreenLabeledValueTextBehavior: Equatable { + case singleLine + case multiLine(maxLines: Int) +} + +final class PeerInfoScreenLabeledValueItem: PeerInfoScreenItem { + let id: AnyHashable + let label: String + let text: String + let textColor: PeerInfoScreenLabeledValueTextColor + let textBehavior: PeerInfoScreenLabeledValueTextBehavior + let action: (() -> Void)? + + init(id: AnyHashable, label: String, text: String, textColor: PeerInfoScreenLabeledValueTextColor = .primary, textBehavior: PeerInfoScreenLabeledValueTextBehavior = .singleLine, action: (() -> Void)?) { + self.id = id + self.label = label + self.text = text + self.textColor = textColor + self.textBehavior = textBehavior + self.action = action + } + + func node() -> PeerInfoScreenItemNode { + return PeerInfoScreenLabeledValueItemNode() + } +} + +private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode { + private let selectionNode: PeerInfoScreenSelectableBackgroundNode + private let labelNode: ImmediateTextNode + private let textNode: ImmediateTextNode + private let bottomSeparatorNode: ASDisplayNode + + private var item: PeerInfoScreenLabeledValueItem? + + override init() { + var bringToFrontForHighlightImpl: (() -> Void)? + self.selectionNode = PeerInfoScreenSelectableBackgroundNode(bringToFrontForHighlight: { bringToFrontForHighlightImpl?() }) + + self.labelNode = ImmediateTextNode() + self.labelNode.displaysAsynchronously = false + self.labelNode.isUserInteractionEnabled = false + + self.textNode = ImmediateTextNode() + self.textNode.displaysAsynchronously = false + self.textNode.isUserInteractionEnabled = false + + self.bottomSeparatorNode = ASDisplayNode() + self.bottomSeparatorNode.isLayerBacked = true + + super.init() + + bringToFrontForHighlightImpl = { [weak self] in + self?.bringToFrontForHighlight?() + } + + self.addSubnode(self.bottomSeparatorNode) + self.addSubnode(self.selectionNode) + self.addSubnode(self.labelNode) + self.addSubnode(self.textNode) + } + + override func update(width: CGFloat, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, transition: ContainedViewLayoutTransition) -> CGFloat { + guard let item = item as? PeerInfoScreenLabeledValueItem else { + return 10.0 + } + + self.item = item + + self.selectionNode.pressed = item.action + + let sideInset: CGFloat = 16.0 + + self.bottomSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor + + let textColorValue: UIColor + switch item.textColor { + case .primary: + textColorValue = presentationData.theme.list.itemPrimaryTextColor + case .accent: + textColorValue = presentationData.theme.list.itemAccentColor + } + + self.labelNode.attributedText = NSAttributedString(string: item.label, font: Font.regular(14.0), textColor: presentationData.theme.list.itemPrimaryTextColor) + + switch item.textBehavior { + case .singleLine: + self.textNode.maximumNumberOfLines = 1 + case let .multiLine(maxLines): + self.textNode.maximumNumberOfLines = maxLines + } + self.textNode.attributedText = NSAttributedString(string: item.text, font: Font.regular(17.0), textColor: textColorValue) + + let labelSize = self.labelNode.updateLayout(CGSize(width: width - sideInset * 2.0, height: .greatestFiniteMagnitude)) + let textSize = self.textNode.updateLayout(CGSize(width: width - sideInset * 2.0, height: .greatestFiniteMagnitude)) + + let labelFrame = CGRect(origin: CGPoint(x: sideInset, y: 11.0), size: labelSize) + let textFrame = CGRect(origin: CGPoint(x: sideInset, y: labelFrame.maxY + 3.0), size: textSize) + + transition.updateFrame(node: self.labelNode, frame: labelFrame) + transition.updateFrame(node: self.textNode, frame: textFrame) + + let height = labelSize.height + 3.0 + textSize.height + 22.0 + + let highlightNodeOffset: CGFloat = topItem == nil ? 0.0 : UIScreenPixel + self.selectionNode.update(size: CGSize(width: width, height: height + highlightNodeOffset), theme: presentationData.theme, transition: transition) + transition.updateFrame(node: self.selectionNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -highlightNodeOffset), size: CGSize(width: width, height: height + highlightNodeOffset))) + + transition.updateFrame(node: self.bottomSeparatorNode, frame: CGRect(origin: CGPoint(x: sideInset, y: height - UIScreenPixel), size: CGSize(width: width - sideInset, height: UIScreenPixel))) + transition.updateAlpha(node: self.bottomSeparatorNode, alpha: bottomItem == nil ? 0.0 : 1.0) + + return height + } +} diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoScreenSelectableBackgroundNode.swift b/submodules/TelegramUI/TelegramUI/PeerInfoScreenSelectableBackgroundNode.swift new file mode 100644 index 0000000000..08b0c6e17a --- /dev/null +++ b/submodules/TelegramUI/TelegramUI/PeerInfoScreenSelectableBackgroundNode.swift @@ -0,0 +1,55 @@ +import AsyncDisplayKit +import Display +import TelegramPresentationData + +final class PeerInfoScreenSelectableBackgroundNode: ASDisplayNode { + private let backgroundNode: ASDisplayNode + private let buttonNode: HighlightTrackingButtonNode + + let bringToFrontForHighlight: () -> Void + + var pressed: (() -> Void)? { + didSet { + self.buttonNode.isUserInteractionEnabled = self.pressed != nil + } + } + + init(bringToFrontForHighlight: @escaping () -> Void) { + self.bringToFrontForHighlight = bringToFrontForHighlight + + self.backgroundNode = ASDisplayNode() + self.backgroundNode.isLayerBacked = true + self.backgroundNode.alpha = 0.0 + + self.buttonNode = HighlightTrackingButtonNode() + + super.init() + + self.addSubnode(self.backgroundNode) + self.addSubnode(self.buttonNode) + + self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside) + self.buttonNode.highligthedChanged = { [weak self] highlighted in + if let strongSelf = self { + if highlighted { + strongSelf.bringToFrontForHighlight() + strongSelf.backgroundNode.layer.removeAnimation(forKey: "opacity") + strongSelf.backgroundNode.alpha = 1.0 + } else { + strongSelf.backgroundNode.alpha = 0.0 + strongSelf.backgroundNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25) + } + } + } + } + + @objc private func buttonPressed() { + self.pressed?() + } + + func update(size: CGSize, theme: PresentationTheme, transition: ContainedViewLayoutTransition) { + self.backgroundNode.backgroundColor = theme.list.itemHighlightedBackgroundColor + transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: size)) + transition.updateFrame(node: self.buttonNode, frame: CGRect(origin: CGPoint(), size: size)) + } +} diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoVisualMediaPane.swift b/submodules/TelegramUI/TelegramUI/PeerInfoVisualMediaPane.swift new file mode 100644 index 0000000000..f49d9978e6 --- /dev/null +++ b/submodules/TelegramUI/TelegramUI/PeerInfoVisualMediaPane.swift @@ -0,0 +1,458 @@ +import AsyncDisplayKit +import Display +import TelegramCore +import SyncCore +import SwiftSignalKit +import Postbox +import TelegramPresentationData +import AccountContext +import ContextUI +import PhotoResources + +private final class VisualMediaItemInteraction { + let openMessage: (MessageId) -> Void + var hiddenMedia: [MessageId: [Media]] = [:] + + init(openMessage: @escaping (MessageId) -> Void) { + self.openMessage = openMessage + } +} + +private final class VisualMediaItemNode: ASDisplayNode { + private let context: AccountContext + private let interaction: VisualMediaItemInteraction + + private let containerNode: ContextControllerSourceNode + private let imageNode: TransformImageNode + + private let fetchStatusDisposable = MetaDisposable() + private let fetchDisposable = MetaDisposable() + private var resourceStatus: MediaResourceStatus? + + private var item: (VisualMediaItem, Media?, CGSize, CGSize?)? + + init(context: AccountContext, interaction: VisualMediaItemInteraction) { + self.context = context + self.interaction = interaction + + self.containerNode = ContextControllerSourceNode() + self.imageNode = TransformImageNode() + + super.init() + + self.addSubnode(self.containerNode) + self.containerNode.addSubnode(self.imageNode) + + self.containerNode.isGestureEnabled = false + } + + deinit { + self.fetchStatusDisposable.dispose() + self.fetchDisposable.dispose() + } + + override func didLoad() { + super.didLoad() + + self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) + } + + @objc func tapGesture(_ recognizer: UITapGestureRecognizer) { + if case .ended = recognizer.state { + if let (item, _, _, _) = self.item { + self.interaction.openMessage(item.message.id) + } + } + } + + func update(size: CGSize, item: VisualMediaItem, theme: PresentationTheme, synchronousLoad: Bool) { + if item === self.item?.0 && size == self.item?.2 { + return + } + var media: Media? + for value in item.message.media { + if let image = value as? TelegramMediaImage { + media = image + break + } else if let file = value as? TelegramMediaFile { + media = file + break + } + } + + if let media = media, (self.item?.1 == nil || !media.isEqual(to: self.item!.1!)) { + var mediaDimensions: CGSize? + if let image = media as? TelegramMediaImage, let largestSize = largestImageRepresentation(image.representations)?.dimensions { + mediaDimensions = largestSize.cgSize + + self.imageNode.setSignal(mediaGridMessagePhoto(account: context.account, photoReference: .message(message: MessageReference(item.message), media: image), fullRepresentationSize: CGSize(width: 300.0, height: 300.0), synchronousLoad: synchronousLoad), attemptSynchronously: synchronousLoad, dispatchOnDisplayLink: true) + + self.fetchStatusDisposable.set(nil) + /*self.statusNode.transitionToState(.none, completion: { [weak self] in + self?.statusNode.isHidden = true + })*/ + //self.mediaBadgeNode.isHidden = true + self.resourceStatus = nil + } else if let file = media as? TelegramMediaFile, file.isVideo { + mediaDimensions = file.dimensions?.cgSize + self.imageNode.setSignal(mediaGridMessageVideo(postbox: context.account.postbox, videoReference: .message(message: MessageReference(item.message), media: file), synchronousLoad: synchronousLoad, autoFetchFullSizeThumbnail: true), attemptSynchronously: synchronousLoad) + + /*self.mediaBadgeNode.isHidden = false + + self.resourceStatus = nil + self.fetchStatusDisposable.set((messageMediaFileStatus(context: context, messageId: messageId, file: file) |> deliverOnMainQueue).start(next: { [weak self] status in + if let strongSelf = self, let item = strongSelf.item { + strongSelf.resourceStatus = status + + let isStreamable = isMediaStreamable(message: item.message, media: file) + + let statusState: RadialStatusNodeState + if isStreamable { + statusState = .none + } else { + switch status { + case let .Fetching(_, progress): + let adjustedProgress = max(progress, 0.027) + statusState = .progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true) + case .Local: + statusState = .none + case .Remote: + statusState = .download(.white) + } + } + + switch statusState { + case .none: + break + default: + strongSelf.statusNode.isHidden = false + } + + strongSelf.statusNode.transitionToState(statusState, animated: true, completion: { + if let strongSelf = self { + if case .none = statusState { + strongSelf.statusNode.isHidden = true + } + } + }) + + if let duration = file.duration { + let durationString = stringForDuration(duration) + + var badgeContent: ChatMessageInteractiveMediaBadgeContent? + var mediaDownloadState: ChatMessageInteractiveMediaDownloadState? + + if isStreamable { + switch status { + case let .Fetching(_, progress): + let progressString = String(format: "%d%%", Int(progress * 100.0)) + badgeContent = .text(inset: 12.0, backgroundColor: mediaBadgeBackgroundColor, foregroundColor: mediaBadgeTextColor, text: NSAttributedString(string: progressString)) + mediaDownloadState = .compactFetching(progress: 0.0) + case .Local: + badgeContent = .text(inset: 0.0, backgroundColor: mediaBadgeBackgroundColor, foregroundColor: mediaBadgeTextColor, text: NSAttributedString(string: durationString)) + case .Remote: + badgeContent = .text(inset: 12.0, backgroundColor: mediaBadgeBackgroundColor, foregroundColor: mediaBadgeTextColor, text: NSAttributedString(string: durationString)) + mediaDownloadState = .compactRemote + } + } else { + badgeContent = .text(inset: 0.0, backgroundColor: mediaBadgeBackgroundColor, foregroundColor: mediaBadgeTextColor, text: NSAttributedString(string: durationString)) + } + + strongSelf.mediaBadgeNode.update(theme: item.theme, content: badgeContent, mediaDownloadState: mediaDownloadState, alignment: .right, animated: false, badgeAnimated: false) + } + } + })) + if self.statusNode.supernode == nil { + self.imageNode.addSubnode(self.statusNode) + }*/ + } else { + //self.mediaBadgeNode.isHidden = true + } + self.item = (item, media, size, mediaDimensions) + + self.updateHiddenMedia() + } + + if let (item, media, _, mediaDimensions) = self.item { + self.item = (item, media, size, mediaDimensions) + + let imageFrame = CGRect(origin: CGPoint(), size: size) + + self.containerNode.frame = imageFrame + self.imageNode.frame = imageFrame + + if let mediaDimensions = mediaDimensions { + let imageSize = mediaDimensions.aspectFilled(imageFrame.size) + self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageFrame.size, intrinsicInsets: UIEdgeInsets(), emptyColor: theme.list.mediaPlaceholderColor))() + } + } + } + + func transitionNode() -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + let imageNode = self.imageNode + return (self.imageNode, self.imageNode.bounds, { [weak self, weak imageNode] in + var statusNodeHidden = false + var accessoryHidden = false + if let strongSelf = self { + //statusNodeHidden = strongSelf.statusNode.isHidden + //accessoryHidden = strongSelf.mediaBadgeNode.isHidden + //strongSelf.statusNode.isHidden = true + //strongSelf.mediaBadgeNode.isHidden = true + } + let view = imageNode?.view.snapshotContentTree(unhide: true) + if let strongSelf = self { + //strongSelf.statusNode.isHidden = statusNodeHidden + //strongSelf.mediaBadgeNode.isHidden = accessoryHidden + } + return (view, nil) + }) + } + + func updateHiddenMedia() { + if let (item, _, _, _) = self.item { + if let _ = self.interaction.hiddenMedia[item.message.id] { + self.isHidden = true + } else { + self.isHidden = false + } + } else { + self.isHidden = false + } + } +} + +private final class VisualMediaItem { + let message: Message + + init(message: Message) { + self.message = message + } +} + +final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScrollViewDelegate { + private let context: AccountContext + private let peerId: PeerId + private let scrollNode: ASScrollNode + + private var _itemInteraction: VisualMediaItemInteraction? + private var itemInteraction: VisualMediaItemInteraction { + return self._itemInteraction! + } + + private var currentParams: (size: CGSize, isScrollingLockedAtTop: Bool, presentationData: PresentationData)? + + private let ready = Promise() + private var didSetReady: Bool = false + var isReady: Signal { + return self.ready.get() + } + + private let listDisposable = MetaDisposable() + private var hiddenMediaDisposable: Disposable? + private var mediaItems: [VisualMediaItem] = [] + private var visibleMediaItems: [UInt32: VisualMediaItemNode] = [:] + + private var numberOfItemsToRequest: Int = 50 + private var currentView: MessageHistoryView? + private var isRequestingView: Bool = false + private var isFirstHistoryView: Bool = true + + init(context: AccountContext, openMessage: @escaping (MessageId) -> Bool, peerId: PeerId) { + self.context = context + self.peerId = peerId + + self.scrollNode = ASScrollNode() + + super.init() + + self._itemInteraction = VisualMediaItemInteraction(openMessage: { id in + openMessage(id) + }) + + self.scrollNode.view.showsVerticalScrollIndicator = false + if #available(iOS 11.0, *) { + self.scrollNode.view.contentInsetAdjustmentBehavior = .never + } + self.scrollNode.view.scrollsToTop = false + self.scrollNode.view.delegate = self + + self.addSubnode(self.scrollNode) + + self.requestHistoryAroundVisiblePosition() + + self.hiddenMediaDisposable = context.sharedContext.mediaManager.galleryHiddenMediaManager.hiddenIds().start(next: { [weak self] ids in + guard let strongSelf = self else { + return + } + var hiddenMedia: [MessageId: [Media]] = [:] + for id in ids { + if case let .chat(accountId, messageId, media) = id, accountId == strongSelf.context.account.id { + hiddenMedia[messageId] = [media] + } + } + strongSelf.itemInteraction.hiddenMedia = hiddenMedia + for (_, itemNode) in strongSelf.visibleMediaItems { + itemNode.updateHiddenMedia() + } + }) + } + + deinit { + self.listDisposable.dispose() + self.hiddenMediaDisposable?.dispose() + } + + private func requestHistoryAroundVisiblePosition() { + if self.isRequestingView { + return + } + self.isRequestingView = true + self.listDisposable.set((self.context.account.viewTracker.aroundMessageHistoryViewForLocation(.peer(self.peerId), index: .upperBound, anchorIndex: .upperBound, count: self.numberOfItemsToRequest, fixedCombinedReadStates: nil, tagMask: .photoOrVideo) + |> deliverOnMainQueue).start(next: { [weak self] (view, updateType, _) in + guard let strongSelf = self else { + return + } + strongSelf.updateHistory(view: view, updateType: updateType) + strongSelf.isRequestingView = false + })) + } + + private func updateHistory(view: MessageHistoryView, updateType: ViewUpdateType) { + self.currentView = view + + self.mediaItems.removeAll() + switch updateType { + case .FillHole: + self.requestHistoryAroundVisiblePosition() + default: + for entry in view.entries.reversed() { + self.mediaItems.append(VisualMediaItem(message: entry.message)) + } + + let wasFirstHistoryView = self.isFirstHistoryView + self.isFirstHistoryView = false + + if let (size, isScrollingLockedAtTop, presentationData) = self.currentParams { + self.update(size: size, isScrollingLockedAtTop: isScrollingLockedAtTop, presentationData: presentationData, synchronous: wasFirstHistoryView, transition: .immediate) + if !self.didSetReady { + self.didSetReady = true + self.ready.set(.single(true)) + } + } + } + } + + func scrollToTop() -> Bool { + if self.scrollNode.view.contentOffset.y > 0.0 { + self.scrollNode.view.setContentOffset(CGPoint(), animated: true) + return true + } else { + return false + } + } + + func findLoadedMessage(id: MessageId) -> Message? { + for item in self.mediaItems { + if item.message.id == id { + return item.message + } + } + return nil + } + + func transitionNodeForGallery(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + for item in self.mediaItems { + if item.message.id == messageId { + if let itemNode = self.visibleMediaItems[item.message.stableId] { + return itemNode.transitionNode() + } + break + } + } + return nil + } + + func update(size: CGSize, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) { + self.currentParams = (size, isScrollingLockedAtTop, presentationData) + + transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: size)) + + let itemSpacing: CGFloat = 1.0 + let itemsInRow: Int = max(3, min(6, Int(size.width / 100.0))) + let itemSize: CGFloat = floor(size.width / CGFloat(itemsInRow)) + + let rowCount: Int = self.mediaItems.count / itemsInRow + (self.mediaItems.count % itemsInRow == 0 ? 0 : 1) + let contentHeight = CGFloat(rowCount + 1) * itemSpacing + CGFloat(rowCount) * itemSize + + self.scrollNode.view.contentSize = CGSize(width: size.width, height: contentHeight) + self.updateVisibleItems(size: size, theme: presentationData.theme, synchronousLoad: synchronous) + + if isScrollingLockedAtTop { + transition.updateBounds(node: self.scrollNode, bounds: CGRect(origin: CGPoint(), size: self.scrollNode.bounds.size)) + } + self.scrollNode.view.isScrollEnabled = !isScrollingLockedAtTop + } + + func scrollViewDidScroll(_ scrollView: UIScrollView) { + if let (size, _, presentationData) = self.currentParams { + self.updateVisibleItems(size: size, theme: presentationData.theme, synchronousLoad: false) + + if scrollView.contentOffset.y >= scrollView.contentSize.height - scrollView.bounds.height * 2.0, let currentView = self.currentView, currentView.earlierId != nil { + if !self.isRequestingView { + self.numberOfItemsToRequest += 50 + self.requestHistoryAroundVisiblePosition() + } + } + } + } + + private func updateVisibleItems(size: CGSize, theme: PresentationTheme, synchronousLoad: Bool) { + let itemSpacing: CGFloat = 1.0 + let itemsInRow: Int = max(3, min(6, Int(size.width / 100.0))) + let itemSize: CGFloat = floor(size.width / CGFloat(itemsInRow)) + + let rowCount: Int = self.mediaItems.count / itemsInRow + (self.mediaItems.count % itemsInRow == 0 ? 0 : 1) + + let visibleRect = self.scrollNode.view.bounds + var minVisibleRow = Int(floor((visibleRect.minY - itemSpacing) / (itemSize + itemSpacing))) + minVisibleRow = max(0, minVisibleRow) + var maxVisibleRow = Int(ceil((visibleRect.maxY - itemSpacing) / (itemSize + itemSpacing))) + maxVisibleRow = min(rowCount - 1, maxVisibleRow) + + let minVisibleIndex = minVisibleRow * itemsInRow + let maxVisibleIndex = min(self.mediaItems.count - 1, maxVisibleRow * itemsInRow - 1) + + var validIds = Set() + if minVisibleIndex < maxVisibleIndex { + for i in minVisibleIndex ... maxVisibleIndex { + let stableId = self.mediaItems[i].message.stableId + validIds.insert(stableId) + let rowIndex = i / Int(itemsInRow) + let columnIndex = i % Int(itemsInRow) + let itemOrigin = CGPoint(x: CGFloat(columnIndex) * (itemSize + itemSpacing), y: itemSpacing + CGFloat(rowIndex) * (itemSize + itemSpacing)) + let itemFrame = CGRect(origin: itemOrigin, size: CGSize(width: columnIndex == itemsInRow ? (size.width - itemOrigin.x) : itemSize, height: itemSize)) + let itemNode: VisualMediaItemNode + if let current = self.visibleMediaItems[stableId] { + itemNode = current + } else { + itemNode = VisualMediaItemNode(context: self.context, interaction: self.itemInteraction) + self.visibleMediaItems[stableId] = itemNode + self.scrollNode.addSubnode(itemNode) + } + itemNode.frame = itemFrame + itemNode.update(size: itemFrame.size, item: self.mediaItems[i], theme: theme, synchronousLoad: synchronousLoad) + } + } + var removeKeys: [UInt32] = [] + for (id, _) in self.visibleMediaItems { + if !validIds.contains(id) { + removeKeys.append(id) + } + } + for id in removeKeys { + if let itemNode = self.visibleMediaItems.removeValue(forKey: id) { + itemNode.removeFromSupernode() + } + } + } +} diff --git a/submodules/TelegramUI/TelegramUI/SharedAccountContext.swift b/submodules/TelegramUI/TelegramUI/SharedAccountContext.swift index f6fa41cde3..160fa6cfcc 100644 --- a/submodules/TelegramUI/TelegramUI/SharedAccountContext.swift +++ b/submodules/TelegramUI/TelegramUI/SharedAccountContext.swift @@ -1244,3 +1244,20 @@ public final class SharedAccountContextImpl: SharedAccountContext { } private let defaultChatControllerInteraction = ChatControllerInteraction.default + +private func peerInfoControllerImpl(context: AccountContext, peer: Peer, mode: PeerInfoControllerMode) -> ViewController? { + if let _ = peer as? TelegramGroup { + return groupInfoController(context: context, peerId: peer.id) + } else if let channel = peer as? TelegramChannel { + if case .group = channel.info { + return groupInfoController(context: context, peerId: peer.id) + } else { + return channelInfoController(context: context, peerId: peer.id) + } + } else if peer is TelegramUser { + return PeerInfoScreen(context: context, peerId: peer.id) + } else if peer is TelegramSecretChat { + return userInfoController(context: context, peerId: peer.id, mode: mode) + } + return nil +} From 6758002adef00d3a93d41a21117ffbf8dcec0c2a Mon Sep 17 00:00:00 2001 From: Ali <> Date: Wed, 5 Feb 2020 01:38:55 +0000 Subject: [PATCH 41/50] User info screen design update --- .../Sources/AccountContext.swift | 2 +- .../Sources/CallListController.swift | 2 +- .../ChatTitleActivityContentNode.swift | 9 + .../Sources/ChatTitleActivityNode.swift | 9 + .../Sources/ContactsController.swift | 2 +- .../ContainedViewLayoutTransition.swift | 47 +- .../Display/Display/ImmediateTextNode.swift | 7 + .../Display/Display/NavigationBar.swift | 71 +- .../Display/Display/NavigationBarBadge.swift | 6 +- .../Display/NavigationButtonNode.swift | 64 +- .../NavigationTransitionCoordinator.swift | 77 +- submodules/Display/Display/TextNode.swift | 2 +- .../Sources/InstantPageControllerNode.swift | 2 +- .../Sources/SecureIdAuthController.swift | 2 +- .../Sources/AvatarGalleryController.swift | 40 +- .../Sources/ChannelBlacklistController.swift | 2 +- .../Sources/ChannelMembersController.swift | 4 +- .../ChannelPermissionsController.swift | 2 +- .../Sources/GroupInfoController.swift | 4 +- .../BlockedPeersController.swift | 2 +- .../Recent Sessions/ItemListWebsiteItem.swift | 2 +- ...ectivePrivacySettingsPeersController.swift | 2 +- .../Resources/PresentationResourceKey.swift | 1 + .../PresentationResourcesRootController.swift | 13 + .../ButtonAddMember.imageset/Contents.json | 12 + .../ic_pf_addmember.pdf | Bin 0 -> 4256 bytes .../ButtonCall.imageset/Contents.json | 12 + .../ButtonCall.imageset/ic_pf_call.pdf | Bin 0 -> 4226 bytes .../ButtonMessage.imageset/Contents.json | 10 +- .../ButtonMessage.imageset/ic_pf_message.pdf | Bin 0 -> 3918 bytes .../ButtonMore.imageset/Contents.json | 12 + .../ButtonMore.imageset/ic_pf_more.pdf | Bin 0 -> 3933 bytes .../ButtonMute.imageset/Contents.json | 12 + .../ButtonMute.imageset/ic_pf_mute.pdf | Bin 0 -> 4295 bytes .../ButtonUnmute.imageset/Contents.json | 12 + .../ButtonUnmute.imageset/ic_pf_unmute.pdf | Bin 0 -> 4154 bytes .../TelegramUI/ChatAvatarNavigationNode.swift | 17 +- .../TelegramUI/ChatController.swift | 150 +- .../ChatInterfaceStateNavigationButtons.swift | 5 +- .../ChatRecentActionsControllerNode.swift | 4 +- .../TelegramUI/TelegramUI/ChatTitleView.swift | 65 +- .../TelegramUI/OpenAddContact.swift | 2 +- .../TelegramUI/TelegramUI/OpenUrl.swift | 4 +- .../TelegramUI/PeerInfoScreen.swift | 1275 ++++++++++++++--- .../PeerMediaCollectionController.swift | 2 +- .../TelegramUI/PollResultsController.swift | 2 +- .../TelegramUI/SharedAccountContext.swift | 8 +- .../TelegramUI/SharedWakeupManager.swift | 2 +- .../TelegramUI/TextLinkHandling.swift | 2 +- 49 files changed, 1543 insertions(+), 439 deletions(-) create mode 100644 submodules/TelegramUI/Images.xcassets/Peer Info/ButtonAddMember.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Peer Info/ButtonAddMember.imageset/ic_pf_addmember.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Peer Info/ButtonCall.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Peer Info/ButtonCall.imageset/ic_pf_call.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Peer Info/ButtonMessage.imageset/ic_pf_message.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Peer Info/ButtonMore.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Peer Info/ButtonMore.imageset/ic_pf_more.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Peer Info/ButtonMute.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Peer Info/ButtonMute.imageset/ic_pf_mute.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Peer Info/ButtonUnmute.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Peer Info/ButtonUnmute.imageset/ic_pf_unmute.pdf diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index 620bf03962..966bb8418a 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -440,7 +440,7 @@ public protocol SharedAccountContext: class { func openChatMessage(_ params: OpenChatMessageParams) -> Bool func messageFromPreloadedChatHistoryViewForLocation(id: MessageId, location: ChatHistoryLocationInput, account: Account, chatLocation: ChatLocation, tagMask: MessageTags?) -> Signal<(MessageIndex?, Bool), NoError> func makeOverlayAudioPlayerController(context: AccountContext, peerId: PeerId, type: MediaManagerPlayerType, initialMessageId: MessageId, initialOrder: MusicPlaybackSettingsOrder, parentNavigationController: NavigationController?) -> ViewController & OverlayAudioPlayerController - func makePeerInfoController(context: AccountContext, peer: Peer, mode: PeerInfoControllerMode) -> ViewController? + func makePeerInfoController(context: AccountContext, peer: Peer, mode: PeerInfoControllerMode, avatarInitiallyExpanded: Bool) -> ViewController? func makeDeviceContactInfoController(context: AccountContext, subject: DeviceContactInfoSubject, completed: (() -> Void)?, cancelled: (() -> Void)?) -> ViewController func makePeersNearbyController(context: AccountContext) -> ViewController func makeComposeController(context: AccountContext) -> ViewController diff --git a/submodules/CallListUI/Sources/CallListController.swift b/submodules/CallListUI/Sources/CallListController.swift index 8de824eba8..1b87df0834 100644 --- a/submodules/CallListUI/Sources/CallListController.swift +++ b/submodules/CallListUI/Sources/CallListController.swift @@ -149,7 +149,7 @@ public final class CallListController: ViewController { let _ = (strongSelf.context.account.postbox.loadedPeerWithId(peerId) |> take(1) |> deliverOnMainQueue).start(next: { peer in - if let strongSelf = self, let controller = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .calls(messages: messages)) { + if let strongSelf = self, let controller = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .calls(messages: messages), avatarInitiallyExpanded: false) { (strongSelf.navigationController as? NavigationController)?.pushViewController(controller) } }) diff --git a/submodules/ChatTitleActivityNode/Sources/ChatTitleActivityContentNode.swift b/submodules/ChatTitleActivityNode/Sources/ChatTitleActivityContentNode.swift index 27c2014190..3578b12212 100644 --- a/submodules/ChatTitleActivityNode/Sources/ChatTitleActivityContentNode.swift +++ b/submodules/ChatTitleActivityNode/Sources/ChatTitleActivityContentNode.swift @@ -95,6 +95,15 @@ public class ChatTitleActivityContentNode: ASDisplayNode { self.textNode.attributedText = text } + func makeCopy() -> ASDisplayNode { + let node = ASDisplayNode() + let textNode = self.textNode.makeCopy() + textNode.frame = self.textNode.frame + node.addSubnode(textNode) + node.frame = self.frame + return node + } + public func animateOut(to: ChatTitleActivityNodeState, style: ChatTitleActivityAnimationStyle, completion: @escaping () -> Void) { self.layer.animateAlpha(from: 1.0, to: 0.0, duration: transitionDuration, removeOnCompletion: false, completion: { _ in completion() diff --git a/submodules/ChatTitleActivityNode/Sources/ChatTitleActivityNode.swift b/submodules/ChatTitleActivityNode/Sources/ChatTitleActivityNode.swift index c345f428bb..2ccf9a29f5 100644 --- a/submodules/ChatTitleActivityNode/Sources/ChatTitleActivityNode.swift +++ b/submodules/ChatTitleActivityNode/Sources/ChatTitleActivityNode.swift @@ -61,6 +61,15 @@ public class ChatTitleActivityNode: ASDisplayNode { super.init() } + public func makeCopy() -> ASDisplayNode { + let node = ASDisplayNode() + if let contentNode = self.contentNode { + node.addSubnode(contentNode.makeCopy()) + } + node.frame = self.frame + return node + } + public func transitionToState(_ state: ChatTitleActivityNodeState, animation: ChatTitleActivityAnimationStyle = .crossfade, completion: @escaping () -> Void = {}) -> Bool { if self.state != state { let currentState = self.state diff --git a/submodules/ContactListUI/Sources/ContactsController.swift b/submodules/ContactListUI/Sources/ContactsController.swift index 7dcfc4b716..087fdfa678 100644 --- a/submodules/ContactListUI/Sources/ContactsController.swift +++ b/submodules/ContactListUI/Sources/ContactsController.swift @@ -530,7 +530,7 @@ public class ContactsController: ViewController { return } if let peer = peer { - if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic) { + if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic, avatarInitiallyExpanded: false) { (strongSelf.navigationController as? NavigationController)?.pushViewController(infoController) } } else { diff --git a/submodules/Display/Display/ContainedViewLayoutTransition.swift b/submodules/Display/Display/ContainedViewLayoutTransition.swift index 3df59e854a..286e3070e1 100644 --- a/submodules/Display/Display/ContainedViewLayoutTransition.swift +++ b/submodules/Display/Display/ContainedViewLayoutTransition.swift @@ -147,14 +147,17 @@ public extension ContainedViewLayoutTransition { } else { switch self { case .immediate: - node.frame = frame + node.position = frame.center + node.bounds = CGRect(origin: node.bounds.origin, size: frame.size) if let completion = completion { completion(true) } - case .animated: - let previousFrame = node.frame - node.frame = frame - self.animatePositionAdditive(node: node, offset: CGPoint(x: previousFrame.midX - frame.midX, y: previousFrame.midY - frame.midY)) + case let .animated(duration, curve): + let previousBounds = node.bounds + let previousCenter = node.frame.center + node.position = frame.center + node.bounds = CGRect(origin: node.bounds.origin, size: frame.size) + self.animatePositionAdditive(node: node, offset: CGPoint(x: previousCenter.x - frame.midX, y: previousCenter.y - frame.midY)) } } } @@ -655,6 +658,40 @@ public extension ContainedViewLayoutTransition { } } + func updateSublayerTransformScaleAdditive(node: ASDisplayNode, scale: CGFloat, completion: ((Bool) -> Void)? = nil) { + if !node.isNodeLoaded { + node.subnodeTransform = CATransform3DMakeScale(scale, scale, 1.0) + completion?(true) + return + } + let t = node.layer.sublayerTransform + let currentScale = sqrt((t.m11 * t.m11) + (t.m12 * t.m12) + (t.m13 * t.m13)) + if currentScale.isEqual(to: scale) { + if let completion = completion { + completion(true) + } + return + } + + switch self { + case .immediate: + node.layer.sublayerTransform = CATransform3DMakeScale(scale, scale, 1.0) + if let completion = completion { + completion(true) + } + case let .animated(duration, curve): + let t = node.layer.sublayerTransform + let currentScale = sqrt((t.m11 * t.m11) + (t.m12 * t.m12) + (t.m13 * t.m13)) + node.layer.sublayerTransform = CATransform3DMakeScale(scale, scale, 1.0) + node.layer.animate(from: -(scale - currentScale) as NSNumber, to: 0.0 as NSNumber, keyPath: "sublayerTransform.scale", timingFunction: curve.timingFunction, duration: duration, delay: 0.0, mediaTimingFunction: curve.mediaTimingFunction, removeOnCompletion: true, additive: true, completion: { + result in + if let completion = completion { + completion(result) + } + }) + } + } + func updateSublayerTransformScaleAndOffset(node: ASDisplayNode, scale: CGFloat, offset: CGPoint, beginWithCurrentState: Bool = false, completion: ((Bool) -> Void)? = nil) { if !node.isNodeLoaded { node.subnodeTransform = CATransform3DMakeScale(scale, scale, 1.0) diff --git a/submodules/Display/Display/ImmediateTextNode.swift b/submodules/Display/Display/ImmediateTextNode.swift index c8c70cc94f..38488ecda3 100644 --- a/submodules/Display/Display/ImmediateTextNode.swift +++ b/submodules/Display/Display/ImmediateTextNode.swift @@ -34,6 +34,13 @@ public class ImmediateTextNode: TextNode { public var tapAttributeAction: (([NSAttributedString.Key: Any]) -> Void)? public var longTapAttributeAction: (([NSAttributedString.Key: Any]) -> Void)? + public func makeCopy() -> TextNode { + let node = TextNode() + node.cachedLayout = self.cachedLayout + node.frame = self.frame + return node + } + public func updateLayout(_ constrainedSize: CGSize) -> CGSize { let makeLayout = TextNode.asyncLayout(self) let (layout, apply) = makeLayout(TextNodeLayoutArguments(attributedString: self.attributedText, backgroundColor: nil, maximumNumberOfLines: self.maximumNumberOfLines, truncationType: self.truncationType, constrainedSize: constrainedSize, alignment: self.textAlignment, lineSpacing: self.lineSpacing, cutout: nil, insets: self.insets, textShadowColor: self.textShadowColor, textStroke: self.textStroke)) diff --git a/submodules/Display/Display/NavigationBar.swift b/submodules/Display/Display/NavigationBar.swift index e26a082850..6fc314f111 100644 --- a/submodules/Display/Display/NavigationBar.swift +++ b/submodules/Display/Display/NavigationBar.swift @@ -111,6 +111,9 @@ open class NavigationBar: ASDisplayNode { public var backPressed: () -> () = { } + public var userInfo: Any? + public var makeCustomTransitionNode: ((NavigationBar) -> CustomNavigationTransitionNode?)? + private var collapsed: Bool { get { return self.frame.size.height.isLess(than: 44.0) @@ -243,6 +246,8 @@ open class NavigationBar: ASDisplayNode { } } + public var customBackButtonText: String? + private var title: String? { didSet { if let title = self.title { @@ -261,7 +266,7 @@ open class NavigationBar: ASDisplayNode { } } - private var titleView: UIView? { + public private(set) var titleView: UIView? { didSet { if let oldValue = oldValue { oldValue.removeFromSuperview() @@ -377,7 +382,9 @@ open class NavigationBar: ASDisplayNode { case let .item(itemValue): self.previousItemListenerKey = itemValue.addSetTitleListener { [weak self] _, _ in if let strongSelf = self, let previousItem = strongSelf.previousItem, case let .item(itemValue) = previousItem { - if let backBarButtonItem = itemValue.backBarButtonItem { + if let customBackButtonText = strongSelf.customBackButtonText { + strongSelf.backButtonNode.updateManualText(customBackButtonText) + } else if let backBarButtonItem = itemValue.backBarButtonItem { strongSelf.backButtonNode.updateManualText(backBarButtonItem.title ?? "") } else { strongSelf.backButtonNode.updateManualText(itemValue.title ?? "") @@ -389,7 +396,9 @@ open class NavigationBar: ASDisplayNode { self.previousItemBackListenerKey = itemValue.addSetBackBarButtonItemListener { [weak self] _, _, _ in if let strongSelf = self, let previousItem = strongSelf.previousItem, case let .item(itemValue) = previousItem { - if let backBarButtonItem = itemValue.backBarButtonItem { + if let customBackButtonText = strongSelf.customBackButtonText { + strongSelf.backButtonNode.updateManualText(customBackButtonText) + } else if let backBarButtonItem = itemValue.backBarButtonItem { strongSelf.backButtonNode.updateManualText(backBarButtonItem.title ?? "") } else { strongSelf.backButtonNode.updateManualText(itemValue.title ?? "") @@ -505,7 +514,9 @@ open class NavigationBar: ASDisplayNode { self.leftButtonNode.removeFromSupernode() var backTitle: String? - if let leftBarButtonItem = item.leftBarButtonItem, leftBarButtonItem.backButtonAppearance { + if let customBackButtonText = self.customBackButtonText { + backTitle = customBackButtonText + } else if let leftBarButtonItem = item.leftBarButtonItem, leftBarButtonItem.backButtonAppearance { backTitle = leftBarButtonItem.title } else if let previousItem = self.previousItem { switch previousItem { @@ -589,12 +600,11 @@ open class NavigationBar: ASDisplayNode { self.updateAccessibilityElements() } - private let backButtonNode: NavigationButtonNode - private let badgeNode: NavigationBarBadgeNode - private let backButtonArrow: ASImageNode - private let leftButtonNode: NavigationButtonNode - private let rightButtonNode: NavigationButtonNode - + public let backButtonNode: NavigationButtonNode + public let badgeNode: NavigationBarBadgeNode + public let backButtonArrow: ASImageNode + public let leftButtonNode: NavigationButtonNode + public let rightButtonNode: NavigationButtonNode private var _transitionState: NavigationBarTransitionState? var transitionState: NavigationBarTransitionState? { @@ -694,6 +704,7 @@ open class NavigationBar: ASDisplayNode { self.leftButtonNode.disabledColor = self.presentationData.theme.disabledButtonColor self.rightButtonNode.color = self.presentationData.theme.buttonColor self.rightButtonNode.disabledColor = self.presentationData.theme.disabledButtonColor + self.rightButtonNode.rippleColor = self.presentationData.theme.primaryTextColor.withAlphaComponent(0.05) self.backButtonArrow.image = backArrowImage(color: self.presentationData.theme.buttonColor) if let title = self.title { self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(17.0), textColor: self.presentationData.theme.primaryTextColor) @@ -768,6 +779,7 @@ open class NavigationBar: ASDisplayNode { self.leftButtonNode.disabledColor = self.presentationData.theme.disabledButtonColor self.rightButtonNode.color = self.presentationData.theme.buttonColor self.rightButtonNode.disabledColor = self.presentationData.theme.disabledButtonColor + self.rightButtonNode.rippleColor = self.presentationData.theme.primaryTextColor.withAlphaComponent(0.05) self.backButtonArrow.image = backArrowImage(color: self.presentationData.theme.buttonColor) if let title = self.title { self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(17.0), textColor: self.presentationData.theme.primaryTextColor) @@ -821,7 +833,7 @@ open class NavigationBar: ASDisplayNode { transition.updateFrame(node: self.stripeNode, frame: CGRect(x: 0.0, y: size.height, width: size.width, height: UIScreenPixel)) - let nominalHeight: CGFloat = self.collapsed ? 32.0 : defaultHeight + let nominalHeight: CGFloat = defaultHeight let contentVerticalOrigin = size.height - nominalHeight - expansionHeight var leftTitleInset: CGFloat = leftInset + 1.0 @@ -958,7 +970,7 @@ open class NavigationBar: ASDisplayNode { if let titleView = self.titleView { let titleSize = CGSize(width: max(1.0, size.width - max(leftTitleInset, rightTitleInset) * 2.0), height: nominalHeight) - let titleFrame = CGRect(origin: CGPoint(x: leftTitleInset, y: contentVerticalOrigin), size: titleSize) + let titleFrame = CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: contentVerticalOrigin + floorToScreenPixels((nominalHeight - titleSize.height) / 2.0)), size: titleSize) titleView.frame = titleFrame if let titleView = titleView as? NavigationBarTitleView { @@ -996,7 +1008,7 @@ open class NavigationBar: ASDisplayNode { } } titleView.alpha = 1.0 - titleView.frame = CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: contentVerticalOrigin + floorToScreenPixels((nominalHeight - titleSize.height) / 2.0)), size: titleSize) + titleView.frame = titleFrame } } } @@ -1017,18 +1029,45 @@ open class NavigationBar: ASDisplayNode { } } - private func makeTransitionBackButtonNode(accentColor: UIColor) -> NavigationButtonNode? { + public func makeTransitionBackButtonNode(accentColor: UIColor) -> NavigationButtonNode? { if self.backButtonNode.supernode != nil { let node = NavigationButtonNode() node.updateManualText(self.backButtonNode.manualText) node.color = accentColor + if let (size, defaultHeight, _, _) = self.validLayout { + node.updateLayout(constrainedSize: CGSize(width: size.width, height: defaultHeight)) + node.frame = self.backButtonNode.frame + } return node } else { return nil } } - private func makeTransitionBackArrowNode(accentColor: UIColor) -> ASDisplayNode? { + public func makeTransitionRightButtonNode(accentColor: UIColor) -> NavigationButtonNode? { + if self.rightButtonNode.supernode != nil { + let node = NavigationButtonNode() + var items: [UIBarButtonItem] = [] + if let item = self.item { + if let rightBarButtonItems = item.rightBarButtonItems, !rightBarButtonItems.isEmpty { + items = rightBarButtonItems + } else if let rightBarButtonItem = item.rightBarButtonItem { + items = [rightBarButtonItem] + } + } + node.updateItems(items) + node.color = accentColor + if let (size, defaultHeight, _, _) = self.validLayout { + node.updateLayout(constrainedSize: CGSize(width: size.width, height: defaultHeight)) + node.frame = self.backButtonNode.frame + } + return node + } else { + return nil + } + } + + public func makeTransitionBackArrowNode(accentColor: UIColor) -> ASDisplayNode? { if self.backButtonArrow.supernode != nil { let node = ASImageNode() node.image = backArrowImage(color: accentColor) @@ -1041,7 +1080,7 @@ open class NavigationBar: ASDisplayNode { } } - private func makeTransitionBadgeNode() -> ASDisplayNode? { + public func makeTransitionBadgeNode() -> ASDisplayNode? { if self.badgeNode.supernode != nil && !self.badgeNode.isHidden { let node = NavigationBarBadgeNode(fillColor: self.presentationData.theme.badgeBackgroundColor, strokeColor: self.presentationData.theme.badgeStrokeColor, textColor: self.presentationData.theme.badgeTextColor) node.text = self.badgeNode.text diff --git a/submodules/Display/Display/NavigationBarBadge.swift b/submodules/Display/Display/NavigationBarBadge.swift index 089b88b0e3..348ff085c5 100644 --- a/submodules/Display/Display/NavigationBarBadge.swift +++ b/submodules/Display/Display/NavigationBarBadge.swift @@ -2,7 +2,7 @@ import Foundation import UIKit import AsyncDisplayKit -final class NavigationBarBadgeNode: ASDisplayNode { +public final class NavigationBarBadgeNode: ASDisplayNode { private var fillColor: UIColor private var strokeColor: UIColor private var textColor: UIColor @@ -19,7 +19,7 @@ final class NavigationBarBadgeNode: ASDisplayNode { } } - init(fillColor: UIColor, strokeColor: UIColor, textColor: UIColor) { + public init(fillColor: UIColor, strokeColor: UIColor, textColor: UIColor) { self.fillColor = fillColor self.strokeColor = strokeColor self.textColor = textColor @@ -48,7 +48,7 @@ final class NavigationBarBadgeNode: ASDisplayNode { self.textNode.attributedText = NSAttributedString(string: self.text, font: self.font, textColor: self.textColor) } - override func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize { + override public func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize { let badgeSize = self.textNode.measure(constrainedSize) let backgroundSize = CGSize(width: max(18.0, badgeSize.width + 10.0 + 1.0), height: 18.0) let backgroundFrame = CGRect(origin: CGPoint(), size: backgroundSize) diff --git a/submodules/Display/Display/NavigationButtonNode.swift b/submodules/Display/Display/NavigationButtonNode.swift index d246df1c1f..29a6d37f0e 100644 --- a/submodules/Display/Display/NavigationButtonNode.swift +++ b/submodules/Display/Display/NavigationButtonNode.swift @@ -53,6 +53,7 @@ private final class NavigationButtonItemNode: ASTextNode { } private var imageNode: ASImageNode? + private let imageRippleNode: ASImageNode private var _image: UIImage? public var image: UIImage? { @@ -61,18 +62,34 @@ private final class NavigationButtonItemNode: ASTextNode { } set(value) { _image = value - if let _ = value { + if let value = value { if self.imageNode == nil { let imageNode = ASImageNode() imageNode.displayWithoutProcessing = true imageNode.displaysAsynchronously = false self.imageNode = imageNode + if value.size == CGSize(width: 30.0, height: 30.0) { + if self.imageRippleNode.supernode == nil { + self.addSubnode(self.imageRippleNode) + self.imageRippleNode.image = generateFilledCircleImage(diameter: 30.0, color: self.rippleColor) + } + } else { + if self.imageRippleNode.supernode != nil { + self.imageRippleNode.image = nil + self.imageRippleNode.removeFromSupernode() + } + } + self.addSubnode(imageNode) } self.imageNode?.image = image } else if let imageNode = self.imageNode { imageNode.removeFromSupernode() self.imageNode = nil + if self.imageRippleNode.supernode != nil { + self.imageRippleNode.image = nil + self.imageRippleNode.removeFromSupernode() + } } self.invalidateCalculatedLayout() @@ -101,6 +118,14 @@ private final class NavigationButtonItemNode: ASTextNode { } } + public var rippleColor: UIColor = UIColor(rgb: 0x000000, alpha: 0.05) { + didSet { + if self.imageRippleNode.image != nil { + self.imageRippleNode.image = generateFilledCircleImage(diameter: 30.0, color: self.rippleColor) + } + } + } + public var disabledColor: UIColor = UIColor(rgb: 0xd0d0d0) { didSet { if let text = self._text { @@ -160,6 +185,11 @@ private final class NavigationButtonItemNode: ASTextNode { } override public init() { + self.imageRippleNode = ASImageNode() + self.imageRippleNode.displaysAsynchronously = false + self.imageRippleNode.displayWithoutProcessing = true + self.imageRippleNode.alpha = 0.0 + super.init() self.isAccessibilityElement = true @@ -183,7 +213,9 @@ private final class NavigationButtonItemNode: ASTextNode { } else if let imageNode = self.imageNode { let nodeSize = imageNode.image?.size ?? CGSize() let size = CGSize(width: max(nodeSize.width, superSize.width), height: max(nodeSize.height, superSize.height)) - imageNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - nodeSize.width) / 2.0) + 5.0, y: floorToScreenPixels((size.height - nodeSize.height) / 2.0)), size: nodeSize) + let imageFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - nodeSize.width) / 2.0) + 5.0, y: floorToScreenPixels((size.height - nodeSize.height) / 2.0)), size: nodeSize) + imageNode.frame = imageFrame + self.imageRippleNode.frame = imageFrame return size } return superSize @@ -242,7 +274,15 @@ private final class NavigationButtonItemNode: ASTextNode { } if shouldChangeHighlight { - self.alpha = !self.isEnabled ? 1.0 : (highlighted ? 0.4 : 1.0) + if let imageNode = self.imageNode { + let previousAlpha = self.imageRippleNode.alpha + self.imageRippleNode.alpha = highlighted ? 1.0 : 0.0 + if !highlighted { + self.imageRippleNode.layer.animateAlpha(from: previousAlpha, to: self.imageRippleNode.alpha, duration: 0.25) + } + } else { + self.alpha = !self.isEnabled ? 1.0 : (highlighted ? 0.4 : 1.0) + } self.highlightChanged(highlighted) } } @@ -263,7 +303,7 @@ private final class NavigationButtonItemNode: ASTextNode { } -final class NavigationButtonNode: ASDisplayNode { +public final class NavigationButtonNode: ASDisplayNode { private var nodes: [NavigationButtonItemNode] = [] public var pressed: (Int) -> () = { _ in } @@ -279,6 +319,16 @@ final class NavigationButtonNode: ASDisplayNode { } } + public var rippleColor: UIColor = UIColor(rgb: 0x000000, alpha: 0.05) { + didSet { + if !self.rippleColor.isEqual(oldValue) { + for node in self.nodes { + node.rippleColor = self.rippleColor + } + } + } + } + public var disabledColor: UIColor = UIColor(rgb: 0xd0d0d0) { didSet { if !self.disabledColor.isEqual(oldValue) { @@ -296,7 +346,7 @@ final class NavigationButtonNode: ASDisplayNode { } } - override init() { + override public init() { super.init() self.isAccessibilityElement = false @@ -313,6 +363,7 @@ final class NavigationButtonNode: ASDisplayNode { } else { node = NavigationButtonItemNode() node.color = self.color + node.rippleColor = self.rippleColor node.highlightChanged = { [weak node, weak self] value in if let strongSelf = self, let node = node { if let index = strongSelf.nodes.firstIndex(where: { $0 === node }) { @@ -353,6 +404,7 @@ final class NavigationButtonNode: ASDisplayNode { } else { node = NavigationButtonItemNode() node.color = self.color + node.rippleColor = self.rippleColor node.highlightChanged = { [weak node, weak self] value in if let strongSelf = self, let node = node { if let index = strongSelf.nodes.firstIndex(where: { $0 === node }) { @@ -385,7 +437,7 @@ final class NavigationButtonNode: ASDisplayNode { } } - func updateLayout(constrainedSize: CGSize) -> CGSize { + public func updateLayout(constrainedSize: CGSize) -> CGSize { var nodeOrigin = CGPoint() var totalSize = CGSize() for node in self.nodes { diff --git a/submodules/Display/Display/NavigationTransitionCoordinator.swift b/submodules/Display/Display/NavigationTransitionCoordinator.swift index a3ea0997c5..f439a5bc64 100644 --- a/submodules/Display/Display/NavigationTransitionCoordinator.swift +++ b/submodules/Display/Display/NavigationTransitionCoordinator.swift @@ -15,12 +15,17 @@ private func generateShadow() -> UIImage? { context.setShadow(offset: CGSize(), blur: 16.0, color: UIColor(white: 0.0, alpha: 0.5).cgColor) context.fill(CGRect(origin: CGPoint(x: size.width, y: 0.0), size: CGSize(width: 16.0, height: 1.0))) }) - //return UIImage(named: "NavigationShadow", in: getAppBundle(), compatibleWith: nil)?.precomposed().resizableImage(withCapInsets: UIEdgeInsets(), resizingMode: .tile) } private let shadowImage = generateShadow() -class NavigationTransitionCoordinator { +public protocol CustomNavigationTransitionNode: ASDisplayNode { + func setup(topNavigationBar: NavigationBar, bottomNavigationBar: NavigationBar) + func update(containerSize: CGSize, fraction: CGFloat, transition: ContainedViewLayoutTransition) + func restore() +} + +final class NavigationTransitionCoordinator { private var _progress: CGFloat = 0.0 var progress: CGFloat { get { @@ -36,6 +41,7 @@ class NavigationTransitionCoordinator { private let bottomNavigationBar: NavigationBar? private let dimNode: ASDisplayNode private let shadowNode: ASImageNode + private let customTransitionNode: CustomNavigationTransitionNode? private let inlineNavigationBarTransition: Bool @@ -58,25 +64,43 @@ class NavigationTransitionCoordinator { self.shadowNode.displayWithoutProcessing = true self.shadowNode.image = shadowImage - if let topNavigationBar = topNavigationBar, let bottomNavigationBar = bottomNavigationBar, !topNavigationBar.isHidden, !bottomNavigationBar.isHidden, topNavigationBar.canTransitionInline, bottomNavigationBar.canTransitionInline, topNavigationBar.item?.leftBarButtonItem == nil { - var topFrame = topNavigationBar.view.convert(topNavigationBar.bounds, to: container.view) - var bottomFrame = bottomNavigationBar.view.convert(bottomNavigationBar.bounds, to: container.view) - topFrame.origin.x = 0.0 - bottomFrame.origin.x = 0.0 - self.inlineNavigationBarTransition = true// topFrame.equalTo(bottomFrame) + if let topNavigationBar = topNavigationBar, let bottomNavigationBar = bottomNavigationBar { + if let customTransitionNode = topNavigationBar.makeCustomTransitionNode?(bottomNavigationBar) { + self.inlineNavigationBarTransition = false + customTransitionNode.setup(topNavigationBar: topNavigationBar, bottomNavigationBar: bottomNavigationBar) + self.customTransitionNode = customTransitionNode + } else if let customTransitionNode = bottomNavigationBar.makeCustomTransitionNode?(topNavigationBar) { + self.inlineNavigationBarTransition = false + customTransitionNode.setup(topNavigationBar: topNavigationBar, bottomNavigationBar: bottomNavigationBar) + self.customTransitionNode = customTransitionNode + } else if !topNavigationBar.isHidden, !bottomNavigationBar.isHidden, topNavigationBar.canTransitionInline, bottomNavigationBar.canTransitionInline, topNavigationBar.item?.leftBarButtonItem == nil { + var topFrame = topNavigationBar.view.convert(topNavigationBar.bounds, to: container.view) + var bottomFrame = bottomNavigationBar.view.convert(bottomNavigationBar.bounds, to: container.view) + topFrame.origin.x = 0.0 + bottomFrame.origin.x = 0.0 + self.inlineNavigationBarTransition = true + self.customTransitionNode = nil + } else { + self.inlineNavigationBarTransition = false + self.customTransitionNode = nil + } } else { self.inlineNavigationBarTransition = false + self.customTransitionNode = nil } switch transition { - case .Push: - self.container.addSubnode(topNode) - case .Pop: - self.container.insertSubnode(bottomNode, belowSubnode: topNode) + case .Push: + self.container.addSubnode(topNode) + case .Pop: + self.container.insertSubnode(bottomNode, belowSubnode: topNode) } self.container.insertSubnode(self.dimNode, belowSubnode: topNode) - self.container.insertSubnode(self.shadowNode, belowSubnode: dimNode) + self.container.insertSubnode(self.shadowNode, belowSubnode: self.dimNode) + if let customTransitionNode = self.customTransitionNode { + self.container.addSubnode(customTransitionNode) + } self.maybeCreateNavigationBarTransition() self.updateProgress(0.0, transition: .immediate, completion: {}) @@ -91,10 +115,10 @@ class NavigationTransitionCoordinator { let position: CGFloat switch self.transition { - case .Push: - position = 1.0 - progress - case .Pop: - position = progress + case .Push: + position = 1.0 - progress + case .Pop: + position = progress } var dimInset: CGFloat = 0.0 @@ -119,10 +143,15 @@ class NavigationTransitionCoordinator { self.updateNavigationBarTransition(transition: transition) + if let customTransitionNode = self.customTransitionNode { + customTransitionNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: containerSize.width, height: containerSize.height)) + customTransitionNode.update(containerSize: containerSize, fraction: position, transition: transition) + } + self.didUpdateProgress?(self.progress, transition, topFrame, bottomFrame) } - func updateNavigationBarTransition(transition: ContainedViewLayoutTransition) { + private func updateNavigationBarTransition(transition: ContainedViewLayoutTransition) { if let topNavigationBar = self.topNavigationBar, let bottomNavigationBar = self.bottomNavigationBar, self.inlineNavigationBarTransition { let position: CGFloat switch self.transition { @@ -178,6 +207,9 @@ class NavigationTransitionCoordinator { strongSelf.dimNode.removeFromSupernode() strongSelf.shadowNode.removeFromSupernode() + strongSelf.customTransitionNode?.restore() + strongSelf.customTransitionNode?.removeFromSupernode() + strongSelf.endNavigationBarTransition() if let currentCompletion = strongSelf.currentCompletion { @@ -195,6 +227,9 @@ class NavigationTransitionCoordinator { self.dimNode.removeFromSupernode() self.shadowNode.removeFromSupernode() + self.customTransitionNode?.restore() + self.customTransitionNode?.removeFromSupernode() + self.endNavigationBarTransition() if let currentCompletion = self.currentCompletion { @@ -209,6 +244,9 @@ class NavigationTransitionCoordinator { strongSelf.dimNode.removeFromSupernode() strongSelf.shadowNode.removeFromSupernode() + strongSelf.customTransitionNode?.restore() + strongSelf.customTransitionNode?.removeFromSupernode() + strongSelf.endNavigationBarTransition() if let currentCompletion = strongSelf.currentCompletion { @@ -228,6 +266,9 @@ class NavigationTransitionCoordinator { self.dimNode.removeFromSupernode() self.shadowNode.removeFromSupernode() + self.customTransitionNode?.restore() + self.customTransitionNode?.removeFromSupernode() + self.endNavigationBarTransition() if let currentCompletion = self.currentCompletion { diff --git a/submodules/Display/Display/TextNode.swift b/submodules/Display/Display/TextNode.swift index 4f8d2a301e..1e7268cdde 100644 --- a/submodules/Display/Display/TextNode.swift +++ b/submodules/Display/Display/TextNode.swift @@ -771,7 +771,7 @@ public final class TextAccessibilityOverlayNode: ASDisplayNode { } public class TextNode: ASDisplayNode { - public private(set) var cachedLayout: TextNodeLayout? + public internal(set) var cachedLayout: TextNodeLayout? override public init() { super.init() diff --git a/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift b/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift index c930ad926b..e15556a53a 100644 --- a/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift +++ b/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift @@ -1180,7 +1180,7 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate { let _ = (strongSelf.context.account.postbox.loadedPeerWithId(peerId) |> deliverOnMainQueue).start(next: { peer in if let strongSelf = self { - if let controller = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic) { + if let controller = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic, avatarInitiallyExpanded: false) { strongSelf.getNavigationController()?.pushViewController(controller) } } diff --git a/submodules/PassportUI/Sources/SecureIdAuthController.swift b/submodules/PassportUI/Sources/SecureIdAuthController.swift index a21449e859..66ca2894ea 100644 --- a/submodules/PassportUI/Sources/SecureIdAuthController.swift +++ b/submodules/PassportUI/Sources/SecureIdAuthController.swift @@ -330,7 +330,7 @@ public final class SecureIdAuthController: ViewController, StandalonePresentable guard let strongSelf = self else { return } - if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic) { + if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic, avatarInitiallyExpanded: false) { (strongSelf.navigationController as? NavigationController)?.pushViewController(infoController) } }) diff --git a/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift b/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift index 30c25a1b5b..0692fc4ad2 100644 --- a/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift +++ b/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift @@ -61,7 +61,7 @@ public final class AvatarGalleryControllerPresentationArguments { } } -private func initialAvatarGalleryEntries(peer: Peer) -> [AvatarGalleryEntry]{ +private func initialAvatarGalleryEntries(peer: Peer) -> [AvatarGalleryEntry] { var initialEntries: [AvatarGalleryEntry] = [] if !peer.profileImageRepresentations.isEmpty, let peerReference = PeerReference(peer) { initialEntries.append(.topImage(peer.profileImageRepresentations.map({ ImageRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatar(peer: peerReference, resource: $0.resource)) }), nil)) @@ -70,26 +70,30 @@ private func initialAvatarGalleryEntries(peer: Peer) -> [AvatarGalleryEntry]{ } public func fetchedAvatarGalleryEntries(account: Account, peer: Peer) -> Signal<[AvatarGalleryEntry], NoError> { - return requestPeerPhotos(account: account, peerId: peer.id) - |> map { photos -> [AvatarGalleryEntry] in - var result: [AvatarGalleryEntry] = [] - let initialEntries = initialAvatarGalleryEntries(peer: peer) - if photos.isEmpty { - result = initialEntries - } else { - var index: Int32 = 0 - for photo in photos { - let indexData = GalleryItemIndexData(position: index, totalCount: Int32(photos.count)) - if result.isEmpty, let first = initialEntries.first { - result.append(.image(photo.image.reference, first.representations, peer, photo.date, indexData, photo.messageId)) - } else { - result.append(.image(photo.image.reference, photo.image.representations.map({ ImageRepresentationWithReference(representation: $0, reference: MediaResourceReference.standalone(resource: $0.resource)) }), peer, photo.date, indexData, photo.messageId)) + let initialEntries = initialAvatarGalleryEntries(peer: peer) + return Signal<[AvatarGalleryEntry], NoError>.single(initialEntries) + |> then( + requestPeerPhotos(account: account, peerId: peer.id) + |> map { photos -> [AvatarGalleryEntry] in + var result: [AvatarGalleryEntry] = [] + let initialEntries = initialAvatarGalleryEntries(peer: peer) + if photos.isEmpty { + result = initialEntries + } else { + var index: Int32 = 0 + for photo in photos { + let indexData = GalleryItemIndexData(position: index, totalCount: Int32(photos.count)) + if result.isEmpty, let first = initialEntries.first { + result.append(.image(photo.image.reference, first.representations, peer, photo.date, indexData, photo.messageId)) + } else { + result.append(.image(photo.image.reference, photo.image.representations.map({ ImageRepresentationWithReference(representation: $0, reference: MediaResourceReference.standalone(resource: $0.resource)) }), peer, photo.date, indexData, photo.messageId)) + } + index += 1 } - index += 1 } + return result } - return result - } + ) } public class AvatarGalleryController: ViewController, StandalonePresentableController { diff --git a/submodules/PeerInfoUI/Sources/ChannelBlacklistController.swift b/submodules/PeerInfoUI/Sources/ChannelBlacklistController.swift index 59a2a57ad7..0750e10edc 100644 --- a/submodules/PeerInfoUI/Sources/ChannelBlacklistController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelBlacklistController.swift @@ -366,7 +366,7 @@ public func channelBlacklistController(context: AccountContext, peerId: PeerId) } items.append(ActionSheetButtonItem(title: presentationData.strings.GroupRemoved_ViewUserInfo, action: { [weak actionSheet] in actionSheet?.dismissAnimated() - if let infoController = context.sharedContext.makePeerInfoController(context: context, peer: participant.peer, mode: .generic) { + if let infoController = context.sharedContext.makePeerInfoController(context: context, peer: participant.peer, mode: .generic, avatarInitiallyExpanded: false) { pushControllerImpl?(infoController) } })) diff --git a/submodules/PeerInfoUI/Sources/ChannelMembersController.swift b/submodules/PeerInfoUI/Sources/ChannelMembersController.swift index 85c6dce8d6..dc6dc37ef0 100644 --- a/submodules/PeerInfoUI/Sources/ChannelMembersController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelMembersController.swift @@ -450,7 +450,7 @@ public func channelMembersController(context: AccountContext, peerId: PeerId) -> } })) }, openPeer: { peer in - if let controller = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic) { + if let controller = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false) { pushControllerImpl?(controller) } }, inviteViaLink: { @@ -502,7 +502,7 @@ public func channelMembersController(context: AccountContext, peerId: PeerId) -> return state.withUpdatedSearchingMembers(false) } }, openPeer: { peer, _ in - if let infoController = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic) { + if let infoController = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false) { pushControllerImpl?(infoController) } }, pushController: { c in diff --git a/submodules/PeerInfoUI/Sources/ChannelPermissionsController.swift b/submodules/PeerInfoUI/Sources/ChannelPermissionsController.swift index 7615d720b0..05e6b55824 100644 --- a/submodules/PeerInfoUI/Sources/ChannelPermissionsController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelPermissionsController.swift @@ -666,7 +666,7 @@ public func channelPermissionsController(context: AccountContext, peerId origina }), ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) }) }, openPeerInfo: { peer in - if let controller = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic) { + if let controller = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false) { pushControllerImpl?(controller) } }, openKicked: { diff --git a/submodules/PeerInfoUI/Sources/GroupInfoController.swift b/submodules/PeerInfoUI/Sources/GroupInfoController.swift index c5c90866b8..8e3288a0aa 100644 --- a/submodules/PeerInfoUI/Sources/GroupInfoController.swift +++ b/submodules/PeerInfoUI/Sources/GroupInfoController.swift @@ -599,7 +599,7 @@ private enum GroupInfoEntry: ItemListNodeEntry { })) } return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, context: arguments.context, peer: peer, presence: presence, text: .presence, label: label == nil ? .none : .text(label!, .standard), editing: editing, revealOptions: ItemListPeerItemRevealOptions(options: options), switchValue: nil, enabled: enabled, selectable: selectable, sectionId: self.section, action: { - if let infoController = arguments.context.sharedContext.makePeerInfoController(context: arguments.context, peer: peer, mode: .generic), selectable { + if let infoController = arguments.context.sharedContext.makePeerInfoController(context: arguments.context, peer: peer, mode: .generic, avatarInitiallyExpanded: false), selectable { arguments.pushController(infoController) } }, setPeerIdWithRevealedOptions: { peerId, fromPeerId in @@ -2342,7 +2342,7 @@ public func groupInfoController(context: AccountContext, peerId originalPeerId: return state.withUpdatedSearchingMembers(false) } }, openPeer: { peer, _ in - if let infoController = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic) { + if let infoController = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false) { arguments.pushController(infoController) } }, pushController: { c in diff --git a/submodules/SettingsUI/Sources/Privacy and Security/BlockedPeersController.swift b/submodules/SettingsUI/Sources/Privacy and Security/BlockedPeersController.swift index d81c161b2f..b59ad0429d 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/BlockedPeersController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/BlockedPeersController.swift @@ -259,7 +259,7 @@ public func blockedPeersController(context: AccountContext, blockedPeersContext: } })) }, openPeer: { peer in - if let controller = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic) { + if let controller = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false) { pushControllerImpl?(controller) } }) diff --git a/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/ItemListWebsiteItem.swift b/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/ItemListWebsiteItem.swift index d889d5aac4..802c7bac02 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/ItemListWebsiteItem.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/ItemListWebsiteItem.swift @@ -112,7 +112,7 @@ class ItemListWebsiteItemNode: ItemListRevealOptionsItemNode { private var disabledOverlayNode: ASDisplayNode? private let maskNode: ASImageNode - private let avatarNode: AvatarNode + let avatarNode: AvatarNode private let titleNode: TextNode private let appNode: TextNode private let locationNode: TextNode diff --git a/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsPeersController.swift b/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsPeersController.swift index 627b6c3af5..130a649729 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsPeersController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsPeersController.swift @@ -341,7 +341,7 @@ public func selectivePrivacyPeersController(context: AccountContext, title: Stri return transaction.getPeer(peerId) } |> deliverOnMainQueue).start(next: { peer in - guard let peer = peer, let controller = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic) else { + guard let peer = peer, let controller = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false) else { return } pushControllerImpl?(controller) diff --git a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift index 0c11f4342c..845a5b7daf 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift @@ -20,6 +20,7 @@ public enum PresentationResourceKey: Int32 { case navigationShareIcon case navigationSearchIcon case navigationCompactSearchIcon + case navigationMoreIcon case navigationAddIcon case navigationPlayerCloseButton diff --git a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesRootController.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesRootController.swift index b5982305bb..afc4cc9f0a 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesRootController.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesRootController.swift @@ -71,6 +71,19 @@ public struct PresentationResourcesRootController { }) } + public static func navigationMoreIcon(_ theme: PresentationTheme) -> UIImage? { + return theme.image(PresentationResourceKey.navigationMoreIcon.rawValue, { theme in + return generateImage(CGSize(width: 30.0, height: 30.0), rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + context.setFillColor(theme.rootController.navigationBar.accentTextColor.cgColor) + let dotSize: CGFloat = 4.0 + context.fillEllipse(in: CGRect(origin: CGPoint(x: 6.0, y: floor((size.height - dotSize) / 2.0)), size: CGSize(width: dotSize, height: dotSize))) + context.fillEllipse(in: CGRect(origin: CGPoint(x: 13.0, y: floor((size.height - dotSize) / 2.0)), size: CGSize(width: dotSize, height: dotSize))) + context.fillEllipse(in: CGRect(origin: CGPoint(x: 20.0, y: floor((size.height - dotSize) / 2.0)), size: CGSize(width: dotSize, height: dotSize))) + }) + }) + } + public static func navigationAddIcon(_ theme: PresentationTheme) -> UIImage? { return theme.image(PresentationResourceKey.navigationAddIcon.rawValue, { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat List/AddIcon"), color: theme.rootController.navigationBar.accentTextColor) diff --git a/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonAddMember.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonAddMember.imageset/Contents.json new file mode 100644 index 0000000000..196b36b491 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonAddMember.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "ic_pf_addmember.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonAddMember.imageset/ic_pf_addmember.pdf b/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonAddMember.imageset/ic_pf_addmember.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ad2274b415c52c63ed481651d2e2e4bfeaf11c03 GIT binary patch literal 4256 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 C>`R0I literal 0 HcmV?d00001 diff --git a/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonMessage.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonMessage.imageset/Contents.json index f8f827e40b..c1007d847a 100644 --- a/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonMessage.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonMessage.imageset/Contents.json @@ -2,15 +2,7 @@ "images" : [ { "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "filename" : "ic_pf_message.pdf" } ], "info" : { diff --git a/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonMessage.imageset/ic_pf_message.pdf b/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonMessage.imageset/ic_pf_message.pdf new file mode 100644 index 0000000000000000000000000000000000000000..64fe2bdbd1711e147dd0893688c4c74b5391ef0d GIT binary patch literal 3918 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 C$6J42aC!9M`gGiv*5&>mph?~1B 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 O(Q*)RaZNof$iD#q0JEY1 literal 0 HcmV?d00001 diff --git a/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonMute.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonMute.imageset/Contents.json new file mode 100644 index 0000000000..61322e832d --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonMute.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "ic_pf_mute.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonMute.imageset/ic_pf_mute.pdf b/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonMute.imageset/ic_pf_mute.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2cabbef68d7202673f0c93e4e5865267e3d7fad4 GIT binary patch literal 4295 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 b|F_Fe0r`>`x%{!wa3z=`SWHaESQq?nA8~9Z literal 0 HcmV?d00001 diff --git a/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonUnmute.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonUnmute.imageset/Contents.json new file mode 100644 index 0000000000..29259c8539 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonUnmute.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "ic_pf_unmute.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonUnmute.imageset/ic_pf_unmute.pdf b/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonUnmute.imageset/ic_pf_unmute.pdf new file mode 100644 index 0000000000000000000000000000000000000000..617622f59ab7767dea94e224b007cedf9eaee1bc GIT binary patch literal 4154 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 Void)? + override init() { self.containerNode = ContextControllerSourceNode() self.avatarNode = AvatarNode(font: normalFont) @@ -67,6 +69,9 @@ final class ChatAvatarNavigationNode: ASDisplayNode { } strongSelf.contextAction?(strongSelf.containerNode, gesture) } + + self.containerNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 37.0, height: 37.0)) + self.avatarNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 37.0, height: 37.0)) } override func didLoad() { @@ -74,6 +79,14 @@ final class ChatAvatarNavigationNode: ASDisplayNode { self.view.isOpaque = false (self.view as? ChatAvatarNavigationNodeView)?.targetNode = self (self.view as? ChatAvatarNavigationNodeView)?.chatController = self.chatController + + self.avatarNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.avatarTapGesture(_:)))) + } + + @objc private func avatarTapGesture(_ recognizer: UITapGestureRecognizer) { + if case .ended = recognizer.state { + self.tapped?() + } } override func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize { @@ -85,7 +98,7 @@ final class ChatAvatarNavigationNode: ASDisplayNode { } func onLayout() { - let bounds = self.bounds + /*let bounds = self.bounds if self.bounds.size.height.isLessThanOrEqualTo(26.0) { if !self.avatarNode.bounds.size.equalTo(bounds.size) { self.avatarNode.font = smallFont @@ -98,6 +111,6 @@ final class ChatAvatarNavigationNode: ASDisplayNode { } self.containerNode.frame = bounds.offsetBy(dx: 10.0, dy: 1.0) self.avatarNode.frame = bounds - } + }*/ } } diff --git a/submodules/TelegramUI/TelegramUI/ChatController.swift b/submodules/TelegramUI/TelegramUI/ChatController.swift index 8e92f38297..ee1d46ff01 100644 --- a/submodules/TelegramUI/TelegramUI/ChatController.swift +++ b/submodules/TelegramUI/TelegramUI/ChatController.swift @@ -363,12 +363,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } super.init(context: context, navigationBarPresentationData: navigationBarPresentationData, mediaAccessoryPanelVisibility: mediaAccessoryPanelVisibility, locationBroadcastPanelSource: locationBroadcastPanelSource) - /*switch mode { - case .overlay: - self.navigationPresentation = .standaloneModal - default: - break - }*/ + self.navigationBar?.customBackButtonText = "" self.blocksBackgroundWhenInOverlay = true @@ -1871,67 +1866,43 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.controllerInteraction = controllerInteraction - self.chatTitleView = ChatTitleView(account: self.context.account, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder) - self.navigationItem.titleView = self.chatTitleView - self.chatTitleView?.pressed = { [weak self] in - if let strongSelf = self { - if strongSelf.chatLocation == .peer(strongSelf.context.account.peerId) { - strongSelf.effectiveNavigationController?.pushViewController(PeerMediaCollectionController(context: strongSelf.context, peerId: strongSelf.context.account.peerId)) - } else { - strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { - return $0.updatedTitlePanelContext { - if let index = $0.firstIndex(where: { - switch $0 { - case .chatInfo: - return true - default: - return false - } - }) { - var updatedContexts = $0 - updatedContexts.remove(at: index) - return updatedContexts - } else { - var updatedContexts = $0 - updatedContexts.append(.chatInfo) - return updatedContexts.sorted() - } - } - }) + var displayNavigationAvatar = false + if case let .peer(peerId) = chatLocation, peerId != context.account.peerId { + displayNavigationAvatar = true + self.navigationBar?.userInfo = PeerInfoNavigationSourceTag(peerId: peerId) + } + self.chatTitleView = ChatTitleView(account: self.context.account, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, displayAvatar: displayNavigationAvatar) + if let avatarNode = self.chatTitleView?.avatarNode { + avatarNode.chatController = self + avatarNode.contextAction = { [weak self] node, gesture in + guard let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.chatMainPeer, peer.smallProfileImage != nil else { + return } + let galleryController = AvatarGalleryController(context: strongSelf.context, peer: peer, remoteEntries: nil, replaceRootController: { controller, ready in + }, synchronousLoad: true) + galleryController.setHintWillBePresentedInPreviewingContext(true) + + let items: [ContextMenuItem] = [ + .action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Conversation_LinkDialogOpen, icon: { _ in nil }, action: { _, f in + f(.dismissWithoutContent) + self?.navigationButtonAction(.openChatInfo(expandAvatar: false)) + })) + ] + let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: galleryController, sourceNode: node)), items: .single(items), reactionItems: [], gesture: gesture) + strongSelf.presentInGlobalOverlay(contextController) + } + avatarNode.tapped = { [weak self] in + self?.navigationButtonAction(.openChatInfo(expandAvatar: true)) } } - - let chatInfoButtonItem: UIBarButtonItem - switch chatLocation { - case .peer: - let avatarNode = ChatAvatarNavigationNode() - avatarNode.chatController = self - avatarNode.contextAction = { [weak self] node, gesture in - guard let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.chatMainPeer, peer.smallProfileImage != nil else { - return - } - let galleryController = AvatarGalleryController(context: strongSelf.context, peer: peer, remoteEntries: nil, replaceRootController: { controller, ready in - }, synchronousLoad: true) - galleryController.setHintWillBePresentedInPreviewingContext(true) - - let items: [ContextMenuItem] = [ - .action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Conversation_LinkDialogOpen, icon: { _ in nil }, action: { _, f in - f(.dismissWithoutContent) - self?.navigationButtonAction(.openChatInfo) - })) - ] - let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: galleryController, sourceNode: node)), items: .single(items), reactionItems: [], gesture: gesture) - strongSelf.presentInGlobalOverlay(contextController) - } - chatInfoButtonItem = UIBarButtonItem(customDisplayNode: avatarNode)! - /*case .group: - chatInfoButtonItem = UIBarButtonItem(customDisplayNode: ChatMultipleAvatarsNavigationNode())!*/ + self.navigationItem.titleView = self.chatTitleView + self.chatTitleView?.pressed = { [weak self] in + self?.navigationButtonAction(.openChatInfo(expandAvatar: false)) } - chatInfoButtonItem.target = self - chatInfoButtonItem.action = #selector(self.rightNavigationButtonAction) - chatInfoButtonItem.accessibilityLabel = self.presentationData.strings.Conversation_Info - self.chatInfoNavigationButton = ChatNavigationButton(action: .openChatInfo, buttonItem: chatInfoButtonItem) + + let buttonItem = UIBarButtonItem(image: PresentationResourcesRootController.navigationMoreIcon(presentationInterfaceState.theme), style: .plain, target: self, action: #selector(self.rightNavigationButtonAction)) + //buttonItem.accessibilityLabel = strings.Conversation_Search + chatInfoNavigationButton = ChatNavigationButton(action: .toggleInfoPanel, buttonItem: buttonItem) self.updateChatPresentationInterfaceState(animated: false, interactive: false, { state in if let botStart = botStart, case .interactive = botStart.behavior { @@ -2010,7 +1981,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let strongSelf = self { if let peer = peerViewMainPeer(peerView) { strongSelf.chatTitleView?.titleContent = .peer(peerView: peerView, onlineMemberCount: onlineMemberCount, isScheduledMessages: isScheduledMessages) - (strongSelf.chatInfoNavigationButton?.buttonItem.customDisplayNode as? ChatAvatarNavigationNode)?.avatarNode.setPeer(context: strongSelf.context, theme: strongSelf.presentationData.theme, peer: peer, overrideImage: peer.isDeleted ? .deletedIcon : .none) + strongSelf.chatTitleView?.avatarNode?.avatarNode.setPeer(context: strongSelf.context, theme: strongSelf.presentationData.theme, peer: peer, overrideImage: peer.isDeleted ? .deletedIcon : .none) (strongSelf.chatInfoNavigationButton?.buttonItem.customDisplayNode as? ChatAvatarNavigationNode)?.contextActionIsEnabled = peer.restrictionText(platform: "ios", contentSettings: strongSelf.context.currentContentSettings.with { $0 }) == nil } @@ -3545,7 +3516,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), subject: nil, keepStack: .always)) } }, openPeerInfo: { [weak self] in - self?.navigationButtonAction(.openChatInfo) + self?.navigationButtonAction(.openChatInfo(expandAvatar: false)) }, togglePeerNotifications: { [weak self] in if let strongSelf = self, case let .peer(peerId) = strongSelf.chatLocation { let _ = togglePeerMuted(account: strongSelf.context.account, peerId: peerId).start() @@ -5319,18 +5290,22 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.chatDisplayNode.dismissInput() self.present(actionSheet, in: .window(.root)) } - case .openChatInfo: + case let .openChatInfo(expandAvatar): switch self.chatLocationInfoData { - case let .peer(peerView): - self.navigationActionDisposable.set((peerView.get() - |> take(1) - |> deliverOnMainQueue).start(next: { [weak self] peerView in - if let strongSelf = self, let peer = peerView.peers[peerView.peerId], peer.restrictionText(platform: "ios", contentSettings: strongSelf.context.currentContentSettings.with { $0 }) == nil && !strongSelf.presentationInterfaceState.isNotAccessible { - if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic) { + case let .peer(peerView): + self.navigationActionDisposable.set((peerView.get() + |> take(1) + |> deliverOnMainQueue).start(next: { [weak self] peerView in + if let strongSelf = self, let peer = peerView.peers[peerView.peerId], peer.restrictionText(platform: "ios", contentSettings: strongSelf.context.currentContentSettings.with { $0 }) == nil && !strongSelf.presentationInterfaceState.isNotAccessible { + if peer.id == strongSelf.context.account.peerId { + strongSelf.effectiveNavigationController?.pushViewController(PeerMediaCollectionController(context: strongSelf.context, peerId: strongSelf.context.account.peerId)) + } else { + if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic, avatarInitiallyExpanded: expandAvatar) { strongSelf.effectiveNavigationController?.pushViewController(infoController) } } - })) + } + })) } case .search: self.interfaceInteraction?.beginMessageSearch(.everything, "") @@ -5538,6 +5513,27 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) })) } + case .toggleInfoPanel: + self.updateChatPresentationInterfaceState(animated: true, interactive: true, { + return $0.updatedTitlePanelContext { + if let index = $0.firstIndex(where: { + switch $0 { + case .chatInfo: + return true + default: + return false + } + }) { + var updatedContexts = $0 + updatedContexts.remove(at: index) + return updatedContexts + } else { + var updatedContexts = $0 + updatedContexts.append(.chatInfo) + return updatedContexts.sorted() + } + } + }) } } @@ -7025,11 +7021,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.effectiveNavigationController?.pushViewController(controller) } - private func openPeer(peerId: PeerId?, navigation: ChatControllerInteractionNavigateToPeer, fromMessage: Message?) { + private func openPeer(peerId: PeerId?, navigation: ChatControllerInteractionNavigateToPeer, fromMessage: Message?, expandAvatar: Bool = false) { if case let .peer(currentPeerId) = self.chatLocation, peerId == currentPeerId { switch navigation { case .info: - self.navigationButtonAction(.openChatInfo) + self.navigationButtonAction(.openChatInfo(expandAvatar: expandAvatar)) case let .chat(textInputState, _): if let textInputState = textInputState { self.updateChatPresentationInterfaceState(animated: true, interactive: true, { @@ -7061,7 +7057,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } self.navigationActionDisposable.set((peerSignal |> take(1) |> deliverOnMainQueue).start(next: { [weak self] peer in if let strongSelf = self, let peer = peer { - if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic) { + if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic, avatarInitiallyExpanded: expandAvatar) { strongSelf.effectiveNavigationController?.pushViewController(infoController) } } @@ -7478,7 +7474,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G |> take(1) |> deliverOnMainQueue).start(next: { [weak self] peer in if let strongSelf = self, peer.restrictionText(platform: "ios", contentSettings: strongSelf.context.currentContentSettings.with { $0 }) == nil { - if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic) { + if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic, avatarInitiallyExpanded: false) { strongSelf.effectiveNavigationController?.pushViewController(infoController) } } diff --git a/submodules/TelegramUI/TelegramUI/ChatInterfaceStateNavigationButtons.swift b/submodules/TelegramUI/TelegramUI/ChatInterfaceStateNavigationButtons.swift index bf3eafbf57..3e0f9c33a0 100644 --- a/submodules/TelegramUI/TelegramUI/ChatInterfaceStateNavigationButtons.swift +++ b/submodules/TelegramUI/TelegramUI/ChatInterfaceStateNavigationButtons.swift @@ -6,13 +6,14 @@ import SyncCore import TelegramPresentationData import AccountContext -enum ChatNavigationButtonAction { - case openChatInfo +enum ChatNavigationButtonAction: Equatable { + case openChatInfo(expandAvatar: Bool) case clearHistory case clearCache case cancelMessageSelection case search case dismiss + case toggleInfoPanel } struct ChatNavigationButton: Equatable { diff --git a/submodules/TelegramUI/TelegramUI/ChatRecentActionsControllerNode.swift b/submodules/TelegramUI/TelegramUI/ChatRecentActionsControllerNode.swift index 271975abbe..c3b087ae3b 100644 --- a/submodules/TelegramUI/TelegramUI/ChatRecentActionsControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatRecentActionsControllerNode.swift @@ -659,7 +659,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { if peer is TelegramChannel, let navigationController = strongSelf.getNavigationController() { strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), animated: true)) } else { - if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic) { + if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic, avatarInitiallyExpanded: false) { strongSelf.pushController(infoController) } } @@ -681,7 +681,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { |> deliverOnMainQueue).start(next: { [weak self] peer in if let strongSelf = self { if let peer = peer { - if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic) { + if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic, avatarInitiallyExpanded: false) { strongSelf.pushController(infoController) } } diff --git a/submodules/TelegramUI/TelegramUI/ChatTitleView.swift b/submodules/TelegramUI/TelegramUI/ChatTitleView.swift index 04ae85c66b..bc988e496b 100644 --- a/submodules/TelegramUI/TelegramUI/ChatTitleView.swift +++ b/submodules/TelegramUI/TelegramUI/ChatTitleView.swift @@ -15,6 +15,7 @@ import PeerPresenceStatusManager import ChatTitleActivityNode import LocalizedPeerData import PhoneNumberFormat +import ChatTitleActivityNode enum ChatTitleContent { case peer(peerView: PeerView, onlineMemberCount: Int32?, isScheduledMessages: Bool) @@ -92,14 +93,16 @@ final class ChatTitleView: UIView, NavigationBarTitleView { private var nameDisplayOrder: PresentationPersonNameOrder private let contentContainer: ASDisplayNode - private let titleNode: ImmediateTextNode - private let titleLeftIconNode: ASImageNode - private let titleRightIconNode: ASImageNode - private let titleCredibilityIconNode: ASImageNode - private let activityNode: ChatTitleActivityNode + let titleNode: ImmediateTextNode + let titleLeftIconNode: ASImageNode + let titleRightIconNode: ASImageNode + let titleCredibilityIconNode: ASImageNode + let activityNode: ChatTitleActivityNode private let button: HighlightTrackingButtonNode + let avatarNode: ChatAvatarNavigationNode? + private var validLayout: (CGSize, CGRect)? private var titleLeftIcon: ChatTitleIcon = .none @@ -136,7 +139,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView { } else { statusNode = ChatTitleNetworkStatusNode(theme: self.theme) self.networkStatusNode = statusNode - self.insertSubview(statusNode.view, belowSubview: self.button.view) + self.insertSubview(statusNode.view, aboveSubview: self.contentContainer.view) } switch self.networkState { case .waitingForNetwork: @@ -451,7 +454,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView { } } - init(account: Account, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder) { + init(account: Account, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, displayAvatar: Bool) { self.account = account self.theme = theme self.strings = strings @@ -482,6 +485,11 @@ final class ChatTitleView: UIView, NavigationBarTitleView { self.activityNode = ChatTitleActivityNode() self.button = HighlightTrackingButtonNode() + if displayAvatar { + self.avatarNode = ChatAvatarNavigationNode() + } else { + self.avatarNode = nil + } super.init(frame: CGRect()) @@ -492,12 +500,13 @@ final class ChatTitleView: UIView, NavigationBarTitleView { self.contentContainer.addSubnode(self.titleNode) self.contentContainer.addSubnode(self.activityNode) self.addSubnode(self.button) + self.avatarNode.flatMap(self.contentContainer.addSubnode) self.presenceManager = PeerPresenceStatusManager(update: { [weak self] in self?.updateStatus() }) - self.button.addTarget(self, action: #selector(buttonPressed), forControlEvents: [.touchUpInside]) + self.button.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: [.touchUpInside]) self.button.highligthedChanged = { [weak self] highlighted in if let strongSelf = self { if highlighted { @@ -558,7 +567,6 @@ final class ChatTitleView: UIView, NavigationBarTitleView { let transition: ContainedViewLayoutTransition = .immediate - self.button.frame = clearBounds self.contentContainer.frame = clearBounds var leftIconWidth: CGFloat = 0.0 @@ -592,35 +600,35 @@ final class ChatTitleView: UIView, NavigationBarTitleView { self.titleRightIconNode.removeFromSupernode() } + var leftInset: CGFloat = 12.0 + if let avatarNode = self.avatarNode { + let avatarSize = CGSize(width: 37.0, height: 37.0) + let avatarFrame = CGRect(origin: CGPoint(x: leftInset + 10.0, y: floor((size.height - avatarSize.height) / 2.0)), size: avatarSize) + avatarNode.frame = avatarFrame + leftInset += avatarSize.width + 10.0 + 8.0 + } + + self.button.frame = CGRect(origin: CGPoint(x: leftInset - 20.0, y: 0.0), size: CGSize(width: clearBounds.width - leftInset, height: size.height)) + let titleSideInset: CGFloat = 3.0 if size.height > 40.0 { var titleSize = self.titleNode.updateLayout(CGSize(width: clearBounds.width - leftIconWidth - credibilityIconWidth - rightIconWidth - titleSideInset * 2.0, height: size.height)) titleSize.width += credibilityIconWidth - let activitySize = self.activityNode.updateLayout(clearBounds.size, alignment: .center) + let activitySize = self.activityNode.updateLayout(clearBounds.size, alignment: .left) let titleInfoSpacing: CGFloat = 0.0 var titleFrame: CGRect if activitySize.height.isZero { - titleFrame = CGRect(origin: CGPoint(x: floor((clearBounds.width - titleSize.width) / 2.0), y: floor((size.height - titleSize.height) / 2.0)), size: titleSize) - if titleFrame.size.width < size.width { - titleFrame.origin.x = -clearBounds.minX + floor((size.width - titleFrame.width) / 2.0) - } + titleFrame = CGRect(origin: CGPoint(x: leftInset + leftIconWidth, y: floor((size.height - titleSize.height) / 2.0)), size: titleSize) self.titleNode.frame = titleFrame } else { let combinedHeight = titleSize.height + activitySize.height + titleInfoSpacing - titleFrame = CGRect(origin: CGPoint(x: floor((clearBounds.width - titleSize.width) / 2.0), y: floor((size.height - combinedHeight) / 2.0)), size: titleSize) - if titleFrame.size.width < size.width { - titleFrame.origin.x = -clearBounds.minX + floor((size.width - titleFrame.width) / 2.0) - } - titleFrame.origin.x = max(titleFrame.origin.x, clearBounds.minX + leftIconWidth) + titleFrame = CGRect(origin: CGPoint(x: leftInset + leftIconWidth, y: floor((size.height - combinedHeight) / 2.0)), size: titleSize) self.titleNode.frame = titleFrame - var activityFrame = CGRect(origin: CGPoint(x: floor((clearBounds.width - activitySize.width) / 2.0), y: floor((size.height - combinedHeight) / 2.0) + titleSize.height + titleInfoSpacing), size: activitySize) - if activitySize.width < size.width { - activityFrame.origin.x = -clearBounds.minX + floor((size.width - activityFrame.width) / 2.0) - } + var activityFrame = CGRect(origin: CGPoint(x: leftInset, y: floor((size.height - combinedHeight) / 2.0) + titleSize.height + titleInfoSpacing), size: activitySize) self.activityNode.frame = activityFrame } @@ -662,13 +670,18 @@ final class ChatTitleView: UIView, NavigationBarTitleView { } @objc func buttonPressed() { - if let pressed = self.pressed { - pressed() - } + self.pressed?() } func animateLayoutTransition() { UIView.transition(with: self, duration: 0.25, options: [.transitionCrossDissolve], animations: { }, completion: nil) } + + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + if self.button.frame.contains(point) { + return self.button.view + } + return super.hitTest(point, with: event) + } } diff --git a/submodules/TelegramUI/TelegramUI/OpenAddContact.swift b/submodules/TelegramUI/TelegramUI/OpenAddContact.swift index 964bd20156..98c49ce1ba 100644 --- a/submodules/TelegramUI/TelegramUI/OpenAddContact.swift +++ b/submodules/TelegramUI/TelegramUI/OpenAddContact.swift @@ -18,7 +18,7 @@ func openAddContactImpl(context: AccountContext, firstName: String = "", lastNam 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: [], note: "") present(deviceContactInfoController(context: context, subject: .create(peer: nil, contactData: contactData, isSharing: false, shareViaException: false, completion: { peer, stableId, contactData in if let peer = peer { - if let infoController = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic) { + if let infoController = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false) { pushController(infoController) } } else { diff --git a/submodules/TelegramUI/TelegramUI/OpenUrl.swift b/submodules/TelegramUI/TelegramUI/OpenUrl.swift index b7f18394e6..11f7c094e2 100644 --- a/submodules/TelegramUI/TelegramUI/OpenUrl.swift +++ b/submodules/TelegramUI/TelegramUI/OpenUrl.swift @@ -209,7 +209,7 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur case .info: let _ = (context.account.postbox.loadedPeerWithId(peerId) |> deliverOnMainQueue).start(next: { peer in - if let infoController = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic) { + if let infoController = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false) { context.sharedContext.applicationBindings.dismissNativeController() navigationController?.pushViewController(infoController) } @@ -491,7 +491,7 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur return transaction.getPeer(PeerId(namespace: Namespaces.Peer.CloudUser, id: idValue)) } |> deliverOnMainQueue).start(next: { peer in - if let peer = peer, let controller = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic) { + if let peer = peer, let controller = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false) { navigationController?.pushViewController(controller) } }) diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoScreen.swift b/submodules/TelegramUI/TelegramUI/PeerInfoScreen.swift index e1f5116a47..06811f13db 100644 --- a/submodules/TelegramUI/TelegramUI/PeerInfoScreen.swift +++ b/submodules/TelegramUI/TelegramUI/PeerInfoScreen.swift @@ -18,6 +18,8 @@ import NotificationMuteSettingsUI import NotificationSoundSelectionUI import OverlayStatusController import ShareController +import PhotoResources +import PeerAvatarGalleryUI private let avatarFont = avatarPlaceholderFont(size: 28.0) @@ -26,6 +28,7 @@ private enum PeerInfoHeaderButtonKey: Hashable { case call case mute case more + case addMember } private enum PeerInfoHeaderButtonIcon { @@ -34,11 +37,13 @@ private enum PeerInfoHeaderButtonIcon { case mute case unmute case more + case addMember } private final class PeerInfoHeaderButtonNode: HighlightableButtonNode { let key: PeerInfoHeaderButtonKey private let action: (PeerInfoHeaderButtonNode) -> Void + let containerNode: ASDisplayNode private let backgroundNode: ASImageNode private let textNode: ImmediateTextNode @@ -49,6 +54,8 @@ private final class PeerInfoHeaderButtonNode: HighlightableButtonNode { self.key = key self.action = action + self.containerNode = ASDisplayNode() + self.backgroundNode = ASImageNode() self.backgroundNode.displaysAsynchronously = false self.backgroundNode.displayWithoutProcessing = true @@ -58,8 +65,9 @@ private final class PeerInfoHeaderButtonNode: HighlightableButtonNode { super.init() - self.addSubnode(self.backgroundNode) - self.addSubnode(self.textNode) + self.addSubnode(self.containerNode) + self.containerNode.addSubnode(self.backgroundNode) + self.containerNode.addSubnode(self.textNode) self.highligthedChanged = { [weak self] highlighted in if let strongSelf = self { @@ -88,20 +96,22 @@ private final class PeerInfoHeaderButtonNode: HighlightableButtonNode { context.clear(CGRect(origin: CGPoint(), size: size)) context.setFillColor(presentationData.theme.list.itemAccentColor.cgColor) context.fillEllipse(in: CGRect(origin: CGPoint(), size: size)) - context.setBlendMode(.copy) - context.setFillColor(UIColor.clear.cgColor) + context.setBlendMode(.normal) + context.setFillColor(presentationData.theme.list.itemCheckColors.foregroundColor.cgColor) let imageName: String switch icon { case .message: - imageName = "Chat/Context Menu/Message" + imageName = "Peer Info/ButtonMessage" case .call: - imageName = "Chat/Context Menu/Call" + imageName = "Peer Info/ButtonCall" case .mute: - imageName = "Chat/Context Menu/Muted" + imageName = "Peer Info/ButtonMute" case .unmute: - imageName = "Chat/Context Menu/Unmute" + imageName = "Peer Info/ButtonUnmute" case .more: - imageName = "Chat/Context Menu/More" + imageName = "Peer Info/ButtonMore" + case .addMember: + imageName = "Peer Info/ButtonAddMember" } if let image = UIImage(bundleImageName: imageName) { let imageRect = CGRect(origin: CGPoint(x: floor((size.width - image.size.width) / 2.0), y: floor((size.height - image.size.height) / 2.0)), size: image.size) @@ -114,8 +124,351 @@ private final class PeerInfoHeaderButtonNode: HighlightableButtonNode { self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(12.0), textColor: presentationData.theme.list.itemAccentColor) let titleSize = self.textNode.updateLayout(CGSize(width: 120.0, height: .greatestFiniteMagnitude)) + transition.updateFrame(node: self.containerNode, frame: CGRect(origin: CGPoint(), size: size)) transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: size)) transition.updateFrameAdditiveToCenter(node: self.textNode, frame: CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: size.height + 6.0), size: titleSize)) + transition.updateAlpha(node: self.textNode, alpha: isExpanded ? 0.0 : 1.0) + } +} + +private final class PeerInfoHeaderNavigationTransition { + let sourceNavigationBar: NavigationBar + let sourceTitleView: ChatTitleView + let sourceTitleFrame: CGRect + let sourceSubtitleFrame: CGRect + let fraction: CGFloat + + init(sourceNavigationBar: NavigationBar, sourceTitleView: ChatTitleView, sourceTitleFrame: CGRect, sourceSubtitleFrame: CGRect, fraction: CGFloat) { + self.sourceNavigationBar = sourceNavigationBar + self.sourceTitleView = sourceTitleView + self.sourceTitleFrame = sourceTitleFrame + self.sourceSubtitleFrame = sourceSubtitleFrame + self.fraction = fraction + } +} + +private enum PeerInfoAvatarListItem: Equatable { + case topImage([ImageRepresentationWithReference]) + case image(TelegramMediaImageReference?, [ImageRepresentationWithReference]) + + var id: WrappedMediaResourceId { + switch self { + case let .topImage(representations): + let representation = largestImageRepresentation(representations.map { $0.representation }) ?? representations[representations.count - 1].representation + return WrappedMediaResourceId(representation.resource.id) + case let .image(_, representations): + let representation = largestImageRepresentation(representations.map { $0.representation }) ?? representations[representations.count - 1].representation + return WrappedMediaResourceId(representation.resource.id) + } + } +} + +private final class PeerInfoAvatarListItemNode: ASDisplayNode { + private let imageNode: TransformImageNode + + let isReady = Promise() + private var didSetReady: Bool = false + + init(context: AccountContext, item: PeerInfoAvatarListItem) { + self.imageNode = TransformImageNode() + + super.init() + + self.addSubnode(self.imageNode) + let representations: [ImageRepresentationWithReference] + switch item { + case let .topImage(topRepresentations): + representations = topRepresentations + case let .image(_, imageRepresentations): + representations = imageRepresentations + } + self.imageNode.setSignal(chatAvatarGalleryPhoto(account: context.account, representations: representations, autoFetchFullSize: true), dispatchOnDisplayLink: false) + + self.imageNode.imageUpdated = { [weak self] _ in + guard let strongSelf = self else { + return + } + if !strongSelf.didSetReady { + strongSelf.didSetReady = true + strongSelf.isReady.set(.single(true)) + } + } + } + + func update(size: CGSize, transition: ContainedViewLayoutTransition) { + let makeLayout = self.imageNode.asyncLayout() + let applyLayout = makeLayout(TransformImageArguments(corners: ImageCorners(), imageSize: size, boundingSize: size, intrinsicInsets: UIEdgeInsets())) + let _ = applyLayout() + transition.updateFrame(node: self.imageNode, frame: CGRect(origin: CGPoint(), size: size)) + } +} + +private final class PeerInfoAvatarListContainerNode: ASDisplayNode { + private let context: AccountContext + + let contentNode: ASDisplayNode + private var items: [PeerInfoAvatarListItem] = [] + private var itemNodes: [WrappedMediaResourceId: PeerInfoAvatarListItemNode] = [:] + private var currentIndex: Int = 0 + private var transitionFraction: CGFloat = 0.0 + + private var validLayout: CGSize? + + private let disposable = MetaDisposable() + private var initializedList = false + + let isReady = Promise() + private var didSetReady = false + + init(context: AccountContext) { + self.context = context + + self.contentNode = ASDisplayNode() + + super.init() + + self.backgroundColor = .black + + self.addSubnode(self.contentNode) + + self.view.disablesInteractiveTransitionGestureRecognizer = true + self.view.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:)))) + } + + deinit { + self.disposable.dispose() + } + + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + return super.hitTest(point, with: event) + } + + @objc private func panGesture(_ recognizer: UIPanGestureRecognizer) { + switch recognizer.state { + case .changed: + let translation = recognizer.translation(in: self.view) + var transitionFraction = translation.x / self.bounds.width + if self.currentIndex <= 0 { + transitionFraction = min(0.0, transitionFraction) + } + if self.currentIndex >= self.items.count - 1 { + transitionFraction = max(0.0, transitionFraction) + } + self.transitionFraction = transitionFraction + if let size = self.validLayout { + self.updateItems(size: size, transition: .animated(duration: 0.3, curve: .spring)) + } + case .cancelled, .ended: + let translation = recognizer.translation(in: self.view) + let velocity = recognizer.velocity(in: self.view) + var directionIsToRight = false + if abs(velocity.x) > 10.0 { + directionIsToRight = velocity.x < 0.0 + } else { + directionIsToRight = translation.x > self.bounds.width / 2.0 + } + var updatedIndex = self.currentIndex + if directionIsToRight { + updatedIndex = min(updatedIndex + 1, self.items.count - 1) + } else { + updatedIndex = max(updatedIndex - 1, 0) + } + self.currentIndex = updatedIndex + self.transitionFraction = 0.0 + if let size = self.validLayout { + self.updateItems(size: size, transition: .animated(duration: 0.3, curve: .spring)) + } + default: + break + } + } + + func update(size: CGSize, peer: Peer?, transition: ContainedViewLayoutTransition) { + self.validLayout = size + if let peer = peer, !self.initializedList { + self.initializedList = true + self.disposable.set((fetchedAvatarGalleryEntries(account: self.context.account, peer: peer) + |> deliverOnMainQueue).start(next: { [weak self] entries in + guard let strongSelf = self else { + return + } + var items: [PeerInfoAvatarListItem] = [] + for entry in entries { + switch entry { + case let .topImage(representations, _): + items.append(.topImage(representations)) + case let .image(reference, representations, _, _, _, _): + items.append(.image(reference, representations)) + } + } + strongSelf.items = items + if let size = strongSelf.validLayout { + strongSelf.updateItems(size: size, transition: .immediate) + } + if items.isEmpty { + if !strongSelf.didSetReady { + strongSelf.didSetReady = true + strongSelf.isReady.set(.single(true)) + } + } + })) + } + self.updateItems(size: size, transition: transition) + } + + private func updateItems(size: CGSize, transition: ContainedViewLayoutTransition) { + var validIds: [WrappedMediaResourceId] = [] + var addedItemNodesForAdditiveTransition: [PeerInfoAvatarListItemNode] = [] + var additiveTransitionOffset: CGFloat = 0.0 + if self.currentIndex >= 0 && self.currentIndex < self.items.count { + for i in max(0, self.currentIndex - 1) ... min(self.currentIndex + 1, self.items.count - 1) { + validIds.append(self.items[i].id) + let itemNode: PeerInfoAvatarListItemNode + var wasAdded = false + if let current = self.itemNodes[self.items[i].id] { + itemNode = current + } else { + wasAdded = true + itemNode = PeerInfoAvatarListItemNode(context: self.context, item: self.items[i]) + self.itemNodes[self.items[i].id] = itemNode + self.contentNode.addSubnode(itemNode) + } + let indexOffset = CGFloat(i - self.currentIndex) + let itemFrame = CGRect(origin: CGPoint(x: indexOffset * size.width + self.transitionFraction * size.width - size.width / 2.0, y: -size.height / 2.0), size: size) + + if wasAdded { + addedItemNodesForAdditiveTransition.append(itemNode) + itemNode.frame = itemFrame + itemNode.update(size: size, transition: .immediate) + } else { + additiveTransitionOffset = itemNode.frame.minX - itemFrame.minX + transition.updateFrame(node: itemNode, frame: itemFrame) + itemNode.update(size: size, transition: transition) + } + } + } + for itemNode in addedItemNodesForAdditiveTransition { + transition.animatePositionAdditive(node: itemNode, offset: CGPoint(x: additiveTransitionOffset, y: 0.0)) + } + var removeIds: [WrappedMediaResourceId] = [] + for (id, _) in self.itemNodes { + if !validIds.contains(id) { + removeIds.append(id) + } + } + for id in removeIds { + if let itemNode = self.itemNodes.removeValue(forKey: id) { + itemNode.removeFromSupernode() + } + } + + if let item = self.items.first, let itemNode = self.itemNodes[item.id] { + if !self.didSetReady { + self.didSetReady = true + self.isReady.set(itemNode.isReady.get()) + } + } + } +} + +private final class PeerInfoAvatarTransformContainerNode: ASDisplayNode { + let context: AccountContext + let avatarNode: AvatarNode + + var tapped: (() -> Void)? + + private var isFirstAvatarLoading = true + + init(context: AccountContext) { + self.context = context + self.avatarNode = AvatarNode(font: avatarFont) + + super.init() + + self.addSubnode(self.avatarNode) + self.avatarNode.frame = CGRect(origin: CGPoint(x: -50.0, y: -50.0), size: CGSize(width: 100.0, height: 100.0)) + + self.avatarNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) + } + + @objc private func tapGesture(_ recognizer: UITapGestureRecognizer) { + if case .ended = recognizer.state { + self.tapped?() + } + } + + func update(peer: Peer?, theme: PresentationTheme) { + if let peer = peer { + self.avatarNode.setPeer(context: self.context, theme: theme, peer: peer, synchronousLoad: self.isFirstAvatarLoading, displayDimensions: CGSize(width: 100.0, height: 100.0)) + self.isFirstAvatarLoading = false + } + } +} + +private final class PeerInfoAvatarListNode: ASDisplayNode { + let avatarContainerNode: PeerInfoAvatarTransformContainerNode + let listContainerTransformNode: ASDisplayNode + let listContainerNode: PeerInfoAvatarListContainerNode + + let isReady = Promise() + + init(context: AccountContext, readyWhenGalleryLoads: Bool) { + self.avatarContainerNode = PeerInfoAvatarTransformContainerNode(context: context) + self.listContainerTransformNode = ASDisplayNode() + self.listContainerNode = PeerInfoAvatarListContainerNode(context: context) + self.listContainerNode.clipsToBounds = true + self.listContainerNode.isHidden = true + + super.init() + + self.addSubnode(self.avatarContainerNode) + self.listContainerTransformNode.addSubnode(self.listContainerNode) + self.addSubnode(self.listContainerTransformNode) + + let avatarReady = self.avatarContainerNode.avatarNode.ready + |> mapToSignal { _ -> Signal in + return .complete() + } + |> then(.single(true)) + + let galleryReady = self.listContainerNode.isReady.get() + |> filter { $0 } + |> take(1) + + let combinedSignal: Signal + if readyWhenGalleryLoads { + combinedSignal = combineLatest(queue: .mainQueue(), + avatarReady, + galleryReady + ) + |> map { lhs, rhs in + return lhs && rhs + } + } else { + combinedSignal = avatarReady + } + + self.isReady.set(combinedSignal + |> filter { $0 } + |> take(1)) + } + + func update(size: CGSize, isExpanded: Bool, peer: Peer?, theme: PresentationTheme, transition: ContainedViewLayoutTransition) { + self.avatarContainerNode.update(peer: peer, theme: theme) + } + + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + if !self.listContainerNode.isHidden { + if let result = self.listContainerNode.view.hitTest(self.view.convert(point, to: self.listContainerNode.view), with: event) { + return result + } + } else { + if let result = self.avatarContainerNode.avatarNode.view.hitTest(self.view.convert(point, to: self.avatarContainerNode.avatarNode.view), with: event) { + return result + } + } + + return super.hitTest(point, with: event) } } @@ -123,23 +476,37 @@ private final class PeerInfoHeaderNode: ASDisplayNode { private var context: AccountContext private var presentationData: PresentationData? - private let avatarNode: AvatarNode - private let titleNode: ImmediateTextNode - private let subtitleNode: ImmediateTextNode + private(set) var isAvatarExpanded: Bool + + private let avatarListNode: PeerInfoAvatarListNode + let titleNodeContainer: ASDisplayNode + let titleNodeRawContainer: ASDisplayNode + let titleNode: ImmediateTextNode + let subtitleNodeContainer: ASDisplayNode + let subtitleNodeRawContainer: ASDisplayNode + let subtitleNode: ImmediateTextNode private var buttonNodes: [PeerInfoHeaderButtonKey: PeerInfoHeaderButtonNode] = [:] private let backgroundNode: ASDisplayNode - private let separatorNode: ASDisplayNode + let separatorNode: ASDisplayNode var performButtonAction: ((PeerInfoHeaderButtonKey) -> Void)? + var requestAvatarExpansion: (() -> Void)? - init(context: AccountContext) { + var navigationTransition: PeerInfoHeaderNavigationTransition? + + init(context: AccountContext, avatarInitiallyExpanded: Bool) { self.context = context + self.isAvatarExpanded = avatarInitiallyExpanded - self.avatarNode = AvatarNode(font: avatarFont) + self.avatarListNode = PeerInfoAvatarListNode(context: context, readyWhenGalleryLoads: avatarInitiallyExpanded) + self.titleNodeContainer = ASDisplayNode() + self.titleNodeRawContainer = ASDisplayNode() self.titleNode = ImmediateTextNode() self.titleNode.displaysAsynchronously = false + self.subtitleNodeContainer = ASDisplayNode() + self.subtitleNodeRawContainer = ASDisplayNode() self.subtitleNode = ImmediateTextNode() self.subtitleNode.displaysAsynchronously = false @@ -153,18 +520,47 @@ private final class PeerInfoHeaderNode: ASDisplayNode { self.addSubnode(self.backgroundNode) self.addSubnode(self.separatorNode) - self.addSubnode(self.avatarNode) - self.addSubnode(self.titleNode) - self.addSubnode(self.subtitleNode) + self.addSubnode(self.avatarListNode) + self.titleNodeContainer.addSubnode(self.titleNode) + self.addSubnode(self.titleNodeContainer) + self.subtitleNodeContainer.addSubnode(self.subtitleNode) + self.addSubnode(self.subtitleNodeContainer) + + self.avatarListNode.avatarContainerNode.tapped = { [weak self] in + guard let strongSelf = self else { + return + } + if !strongSelf.isAvatarExpanded { + strongSelf.requestAvatarExpansion?() + } + } } - func update(width: CGFloat, statusBarHeight: CGFloat, navigationHeight: CGFloat, presentationData: PresentationData, peer: Peer?, cachedData: CachedPeerData?, notificationSettings: TelegramPeerNotificationSettings?, presence: TelegramUserPresence?, transition: ContainedViewLayoutTransition) -> CGFloat { + func update(width: CGFloat, statusBarHeight: CGFloat, navigationHeight: CGFloat, contentOffset: CGFloat, presentationData: PresentationData, peer: Peer?, cachedData: CachedPeerData?, notificationSettings: TelegramPeerNotificationSettings?, presence: TelegramUserPresence?, transition: ContainedViewLayoutTransition, additive: Bool) -> CGFloat { self.presentationData = presentationData - self.backgroundNode.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor + var transitionSourceHeight: CGFloat = 0.0 + var transitionFraction: CGFloat = 0.0 + var transitionSourceAvatarFrame = CGRect() + var transitionSourceTitleFrame = CGRect() + var transitionSourceSubtitleFrame = CGRect() + if let navigationTransition = self.navigationTransition, let sourceAvatarNode = navigationTransition.sourceTitleView.avatarNode?.avatarNode { + transitionSourceHeight = navigationTransition.sourceNavigationBar.bounds.height + transitionFraction = navigationTransition.fraction + transitionSourceAvatarFrame = sourceAvatarNode.view.convert(sourceAvatarNode.view.bounds, to: navigationTransition.sourceNavigationBar.view) + transitionSourceTitleFrame = navigationTransition.sourceTitleFrame + transitionSourceSubtitleFrame = navigationTransition.sourceSubtitleFrame + + transition.updateBackgroundColor(node: self.backgroundNode, color: presentationData.theme.list.itemBlocksBackgroundColor.interpolateTo(presentationData.theme.rootController.navigationBar.backgroundColor, fraction: transitionFraction)!) + } else { + self.backgroundNode.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor + + let backgroundTransitionFraction: CGFloat = max(0.0, min(1.0, contentOffset / (212.0))) + transition.updateBackgroundColor(node: self.backgroundNode, color: presentationData.theme.list.itemBlocksBackgroundColor.interpolateTo(presentationData.theme.rootController.navigationBar.backgroundColor, fraction: backgroundTransitionFraction)!) + } + self.separatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor - let avatarSize: CGFloat = 100.0 let defaultButtonSize: CGFloat = 40.0 let defaultMaxButtonSpacing: CGFloat = 40.0 @@ -176,9 +572,7 @@ private final class PeerInfoHeaderNode: ASDisplayNode { buttonKeys.append(.mute) buttonKeys.append(.more) - self.avatarNode.setPeer(context: self.context, theme: presentationData.theme, peer: peer, displayDimensions: CGSize(width: avatarSize, height: avatarSize)) - - self.titleNode.attributedText = NSAttributedString(string: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), font: Font.medium(24.0), textColor: presentationData.theme.list.itemPrimaryTextColor) + self.titleNode.attributedText = NSAttributedString(string: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), font: Font.semibold(24.0), textColor: presentationData.theme.list.itemPrimaryTextColor) let presence = presence ?? TelegramUserPresence(status: .none, lastActivity: 0) let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 @@ -193,24 +587,245 @@ private final class PeerInfoHeaderNode: ASDisplayNode { } let textSideInset: CGFloat = 16.0 + let expandedAvatarControlsHeight: CGFloat = 64.0 + let expandedAvatarHeight: CGFloat = width + expandedAvatarControlsHeight - var height: CGFloat = navigationHeight - height += 212.0 - + let avatarSize: CGFloat = 100.0 let avatarFrame = CGRect(origin: CGPoint(x: floor((width - avatarSize) / 2.0), y: statusBarHeight + 10.0), size: CGSize(width: avatarSize, height: avatarSize)) - transition.updateFrame(node: self.avatarNode, frame: avatarFrame) + let avatarCenter = CGPoint(x: (1.0 - transitionFraction) * avatarFrame.midX + transitionFraction * transitionSourceAvatarFrame.midX, y: (1.0 - transitionFraction) * avatarFrame.midY + transitionFraction * transitionSourceAvatarFrame.midY) let titleSize = self.titleNode.updateLayout(CGSize(width: width - textSideInset * 2.0, height: .greatestFiniteMagnitude)) let subtitleSize = self.subtitleNode.updateLayout(CGSize(width: width - textSideInset * 2.0, height: .greatestFiniteMagnitude)) - let titleFrame = CGRect(origin: CGPoint(x: floor((width - titleSize.width) / 2.0), y: avatarFrame.maxY + 10.0), size: titleSize) - let subtitleFrame = CGRect(origin: CGPoint(x: floor((width - subtitleSize.width) / 2.0), y: titleFrame.maxY + 1.0), size: subtitleSize) - transition.updateFrameAdditiveToCenter(node: self.titleNode, frame: titleFrame) - transition.updateFrameAdditiveToCenter(node: self.subtitleNode, frame: subtitleFrame) + let titleFrame: CGRect + let subtitleFrame: CGRect + if self.isAvatarExpanded { + titleFrame = CGRect(origin: CGPoint(x: 16.0, y: expandedAvatarHeight - expandedAvatarControlsHeight + 12.0), size: titleSize) + subtitleFrame = CGRect(origin: CGPoint(x: 16.0, y: titleFrame.maxY - 5.0), size: subtitleSize) + } else { + titleFrame = CGRect(origin: CGPoint(x: floor((width - titleSize.width) / 2.0), y: avatarFrame.maxY + 10.0), size: titleSize) + subtitleFrame = CGRect(origin: CGPoint(x: floor((width - subtitleSize.width) / 2.0), y: titleFrame.maxY + 1.0), size: subtitleSize) + } - let buttonSpacing: CGFloat = min(defaultMaxButtonSpacing, width - floor(CGFloat(buttonKeys.count) * defaultButtonSize / CGFloat(buttonKeys.count + 1))) + let titleLockOffset: CGFloat = 7.0 + let titleMaxLockOffset: CGFloat = 7.0 + let titleCollapseOffset = titleFrame.midY - statusBarHeight - titleLockOffset + let titleOffset = -min(titleCollapseOffset, contentOffset) + let titleCollapseFraction = max(0.0, min(1.0, contentOffset / titleCollapseOffset)) + + let titleMinScale: CGFloat = 0.7 + let subtitleMinScale: CGFloat = 0.8 + let avatarMinScale: CGFloat = 0.7 + + let apparentTitleLockOffset = (1.0 - titleCollapseFraction) * 0.0 + titleCollapseFraction * titleMaxLockOffset + + let avatarScale: CGFloat + let avatarOffset: CGFloat + if self.navigationTransition != nil { + avatarScale = ((1.0 - transitionFraction) * avatarFrame.width + transitionFraction * transitionSourceAvatarFrame.width) / avatarFrame.width + avatarOffset = 0.0 + } else { + avatarScale = 1.0 * (1.0 - titleCollapseFraction) + avatarMinScale * titleCollapseFraction + avatarOffset = apparentTitleLockOffset + 0.0 * (1.0 - titleCollapseFraction) + 10.0 * titleCollapseFraction + } + let avatarListFrame = CGRect(origin: CGPoint(), size: CGSize(width: width, height: width)) + + if self.isAvatarExpanded { + self.avatarListNode.listContainerNode.isHidden = false + if !transitionSourceAvatarFrame.width.isZero { + transition.updateCornerRadius(node: self.avatarListNode.listContainerNode, cornerRadius: transitionFraction * transitionSourceAvatarFrame.width / 2.0) + } else { + transition.updateCornerRadius(node: self.avatarListNode.listContainerNode, cornerRadius: 0.0) + } + } else if self.avatarListNode.listContainerNode.cornerRadius != 50.0 { + transition.updateCornerRadius(node: self.avatarListNode.listContainerNode, cornerRadius: 50.0, completion: { [weak self] _ in + guard let strongSelf = self else { + return + } + strongSelf.avatarListNode.listContainerNode.isHidden = true + }) + } + + self.avatarListNode.update(size: CGSize(), isExpanded: self.isAvatarExpanded, peer: peer, theme: presentationData.theme, transition: transition) + if additive { + transition.updateSublayerTransformScaleAdditive(node: self.avatarListNode.avatarContainerNode, scale: avatarScale) + } else { + transition.updateSublayerTransformScale(node: self.avatarListNode.avatarContainerNode, scale: avatarScale) + } + let apparentAvatarFrame: CGRect + if self.isAvatarExpanded { + let expandedAvatarCenter = CGPoint(x: width / 2.0, y: width / 2.0 - contentOffset / 2.0) + apparentAvatarFrame = CGRect(origin: CGPoint(x: expandedAvatarCenter.x * (1.0 - transitionFraction) + transitionFraction * avatarCenter.x, y: expandedAvatarCenter.y * (1.0 - transitionFraction) + transitionFraction * avatarCenter.y), size: CGSize()) + } else { + apparentAvatarFrame = CGRect(origin: CGPoint(x: avatarCenter.x - avatarFrame.width / 2.0, y: -contentOffset + avatarOffset + avatarCenter.y - avatarFrame.height / 2.0), size: avatarFrame.size) + } + if case let .animated(duration, curve) = transition, !transitionSourceAvatarFrame.width.isZero { + let previousFrame = self.avatarListNode.frame + self.avatarListNode.frame = CGRect(origin: apparentAvatarFrame.center, size: CGSize()) + let horizontalTransition: ContainedViewLayoutTransition + let verticalTransition: ContainedViewLayoutTransition + if transitionFraction < .ulpOfOne { + horizontalTransition = .animated(duration: duration * 0.85, curve: curve) + verticalTransition = .animated(duration: duration * 1.15, curve: curve) + } else { + horizontalTransition = transition + verticalTransition = .animated(duration: duration * 0.6, curve: curve) + } + horizontalTransition.animatePositionAdditive(node: self.avatarListNode, offset: CGPoint(x: previousFrame.midX - apparentAvatarFrame.midX, y: 0.0)) + verticalTransition.animatePositionAdditive(node: self.avatarListNode, offset: CGPoint(x: 0.0, y: previousFrame.midY - apparentAvatarFrame.midY)) + } else { + transition.updateFrameAdditive(node: self.avatarListNode, frame: CGRect(origin: apparentAvatarFrame.center, size: CGSize())) + } + + let avatarListContainerFrame: CGRect + let avatarListContainerScale: CGFloat + if self.isAvatarExpanded { + if !transitionSourceAvatarFrame.width.isZero { + let neutralAvatarListContainerSize = CGSize(width: width, height: width) + let avatarListContainerSize = CGSize(width: neutralAvatarListContainerSize.width * (1.0 - transitionFraction) + transitionSourceAvatarFrame.width * transitionFraction, height: neutralAvatarListContainerSize.height * (1.0 - transitionFraction) + transitionSourceAvatarFrame.height * transitionFraction) + avatarListContainerFrame = CGRect(origin: CGPoint(x: -avatarListContainerSize.width / 2.0, y: -avatarListContainerSize.height / 2.0), size: avatarListContainerSize) + } else { + avatarListContainerFrame = CGRect(origin: CGPoint(x: -width / 2.0, y: -width / 2.0), size: CGSize(width: width, height: width)) + } + avatarListContainerScale = 1.0 + max(0.0, -contentOffset / avatarListContainerFrame.width) + } else { + avatarListContainerFrame = CGRect(origin: CGPoint(x: -apparentAvatarFrame.width / 2.0, y: -apparentAvatarFrame.height / 2.0), size: apparentAvatarFrame.size) + avatarListContainerScale = avatarScale + } + transition.updateFrame(node: self.avatarListNode.listContainerNode, frame: avatarListContainerFrame) + let innerScale = avatarListContainerFrame.width / width + let innerDelta = (avatarListContainerFrame.width - width) / 2.0 + transition.updateSublayerTransformScale(node: self.avatarListNode.listContainerNode, scale: innerScale) + transition.updateFrameAdditive(node: self.avatarListNode.listContainerNode.contentNode, frame: CGRect(origin: CGPoint(x: innerDelta + width / 2.0, y: innerDelta + width / 2.0), size: CGSize())) + + if additive { + transition.updateSublayerTransformScaleAdditive(node: self.avatarListNode.listContainerTransformNode, scale: avatarListContainerScale) + } else { + transition.updateSublayerTransformScale(node: self.avatarListNode.listContainerTransformNode, scale: avatarListContainerScale) + } + + self.avatarListNode.listContainerNode.update(size: CGSize(width: width, height: width), peer: peer, transition: transition) + + let buttonsCollapseStart = titleCollapseOffset + let buttonsCollapseEnd = 212.0 - (navigationHeight - statusBarHeight) + 10.0 + + let buttonsCollapseFraction = max(0.0, contentOffset - buttonsCollapseStart) / (buttonsCollapseEnd - buttonsCollapseStart) + + let rawHeight: CGFloat + let height: CGFloat + if self.isAvatarExpanded { + rawHeight = expandedAvatarHeight + height = max(navigationHeight, rawHeight - contentOffset) + } else { + rawHeight = navigationHeight + 212.0 + height = navigationHeight + max(0.0, 212.0 - contentOffset) + } + + let apparentHeight = (1.0 - transitionFraction) * height + transitionFraction * transitionSourceHeight + + if !titleSize.width.isZero && !titleSize.height.isZero { + if self.navigationTransition != nil { + var neutralTitleScale: CGFloat = 1.0 + var neutralSubtitleScale: CGFloat = 1.0 + if self.isAvatarExpanded { + neutralTitleScale = 0.7 + neutralSubtitleScale = 1.0 + } + + let titleScale = (transitionFraction * transitionSourceTitleFrame.height + (1.0 - transitionFraction) * titleFrame.height * neutralTitleScale) / (titleFrame.height) + let subtitleScale = (transitionFraction * transitionSourceSubtitleFrame.height + (1.0 - transitionFraction) * subtitleFrame.height * neutralSubtitleScale) / (subtitleFrame.height) + + let titleOrigin = CGPoint(x: transitionFraction * transitionSourceTitleFrame.minX + (1.0 - transitionFraction) * titleFrame.minX, y: transitionFraction * transitionSourceTitleFrame.minY + (1.0 - transitionFraction) * titleFrame.minY) + let subtitleOrigin = CGPoint(x: transitionFraction * transitionSourceSubtitleFrame.minX + (1.0 - transitionFraction) * subtitleFrame.minX, y: transitionFraction * transitionSourceSubtitleFrame.minY + (1.0 - transitionFraction) * subtitleFrame.minY) + + let rawTitleFrame = CGRect(origin: titleOrigin, size: titleFrame.size) + self.titleNodeRawContainer.frame = rawTitleFrame + transition.updateFrameAdditiveToCenter(node: self.titleNodeContainer, frame: rawTitleFrame.offsetBy(dx: rawTitleFrame.width * 0.5 * (titleScale - 1.0), dy: titleOffset + rawTitleFrame.height * 0.5 * (titleScale - 1.0))) + transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(), size: titleFrame.size)) + let rawSubtitleFrame = CGRect(origin: subtitleOrigin, size: subtitleFrame.size) + self.subtitleNodeRawContainer.frame = rawSubtitleFrame + transition.updateFrameAdditiveToCenter(node: self.subtitleNodeContainer, frame: rawSubtitleFrame.offsetBy(dx: rawSubtitleFrame.width * 0.5 * (subtitleScale - 1.0), dy: titleOffset + rawSubtitleFrame.height * 0.5 * (subtitleScale - 1.0))) + transition.updateFrame(node: self.subtitleNode, frame: CGRect(origin: CGPoint(), size: subtitleFrame.size)) + transition.updateSublayerTransformScale(node: self.titleNodeContainer, scale: titleScale) + transition.updateSublayerTransformScale(node: self.subtitleNodeContainer, scale: subtitleScale) + } else { + let titleScale: CGFloat + let subtitleScale: CGFloat + if self.isAvatarExpanded { + titleScale = 0.7 + subtitleScale = 1.0 + } else { + titleScale = (1.0 - titleCollapseFraction) * 1.0 + titleCollapseFraction * titleMinScale + subtitleScale = (1.0 - titleCollapseFraction) * 1.0 + titleCollapseFraction * subtitleMinScale + } + + let rawTitleFrame = titleFrame + self.titleNodeRawContainer.frame = rawTitleFrame + transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(), size: titleFrame.size)) + let rawSubtitleFrame = subtitleFrame + self.subtitleNodeRawContainer.frame = rawSubtitleFrame + if self.isAvatarExpanded { + transition.updateFrameAdditive(node: self.titleNodeContainer, frame: rawTitleFrame.offsetBy(dx: 0.0, dy: titleOffset + apparentTitleLockOffset).offsetBy(dx: rawTitleFrame.width * 0.5 * (titleScale - 1.0), dy: rawTitleFrame.height * 0.5 * (titleScale - 1.0))) + transition.updateFrameAdditive(node: self.subtitleNodeContainer, frame: rawSubtitleFrame.offsetBy(dx: 0.0, dy: titleOffset).offsetBy(dx: rawSubtitleFrame.width * 0.5 * (subtitleScale - 1.0), dy: rawSubtitleFrame.height * 0.5 * (subtitleScale - 1.0))) + } else { + transition.updateFrameAdditiveToCenter(node: self.titleNodeContainer, frame: rawTitleFrame.offsetBy(dx: 0.0, dy: titleOffset + apparentTitleLockOffset)) + transition.updateFrameAdditiveToCenter(node: self.subtitleNodeContainer, frame: rawSubtitleFrame.offsetBy(dx: 0.0, dy: titleOffset)) + } + transition.updateFrame(node: self.subtitleNode, frame: CGRect(origin: CGPoint(), size: subtitleFrame.size)) + transition.updateSublayerTransformScaleAdditive(node: self.titleNodeContainer, scale: titleScale) + transition.updateSublayerTransformScaleAdditive(node: self.subtitleNodeContainer, scale: subtitleScale) + } + } + + let buttonSpacing: CGFloat + if self.isAvatarExpanded { + buttonSpacing = 16.0 + } else { + buttonSpacing = min(defaultMaxButtonSpacing, width - floor(CGFloat(buttonKeys.count) * defaultButtonSize / CGFloat(buttonKeys.count + 1))) + } + + let expandedButtonSize: CGFloat = 32.0 let buttonsWidth = buttonSpacing * CGFloat(buttonKeys.count - 1) + CGFloat(buttonKeys.count) * defaultButtonSize - var buttonRightOrigin = CGPoint(x: floor((width - buttonsWidth) / 2.0) + buttonsWidth, y: height - 74.0) + var buttonRightOrigin: CGPoint + if self.isAvatarExpanded { + buttonRightOrigin = CGPoint(x: width - 16.0, y: apparentHeight - 74.0) + } else { + buttonRightOrigin = CGPoint(x: floor((width - buttonsWidth) / 2.0) + buttonsWidth, y: apparentHeight - 74.0) + } + let buttonsScale: CGFloat + let buttonsAlpha: CGFloat + let apparentButtonSize: CGFloat + let buttonsVerticalOffset: CGFloat + if self.navigationTransition != nil { + if self.isAvatarExpanded { + apparentButtonSize = expandedButtonSize + } else { + apparentButtonSize = defaultButtonSize + } + let neutralButtonsScale = apparentButtonSize / defaultButtonSize + buttonsScale = (1.0 - transitionFraction) * neutralButtonsScale + 0.2 * transitionFraction + buttonsAlpha = 1.0 - transitionFraction + + let neutralButtonsOffset: CGFloat + if self.isAvatarExpanded { + neutralButtonsOffset = 74.0 - 15.0 - defaultButtonSize + (defaultButtonSize - apparentButtonSize) / 2.0 + } else { + neutralButtonsOffset = (1.0 - buttonsScale) * apparentButtonSize + } + + buttonsVerticalOffset = (1.0 - transitionFraction) * neutralButtonsOffset + ((1.0 - buttonsScale) * apparentButtonSize) * transitionFraction + } else { + apparentButtonSize = self.isAvatarExpanded ? expandedButtonSize : defaultButtonSize + if self.isAvatarExpanded { + buttonsScale = apparentButtonSize / defaultButtonSize + buttonsVerticalOffset = 74.0 - 15.0 - defaultButtonSize + (defaultButtonSize - apparentButtonSize) / 2.0 + } else { + buttonsScale = (1.0 - buttonsCollapseFraction) * 1.0 + 0.2 * buttonsCollapseFraction + buttonsVerticalOffset = (1.0 - buttonsScale) * apparentButtonSize + } + buttonsAlpha = 1.0 - buttonsCollapseFraction + } + let buttonsScaledOffset = (defaultButtonSize - apparentButtonSize) / 2.0 for buttonKey in buttonKeys.reversed() { let buttonNode: PeerInfoHeaderButtonNode var wasAdded = false @@ -225,10 +840,15 @@ private final class PeerInfoHeaderNode: ASDisplayNode { self.addSubnode(buttonNode) } - let buttonFrame = CGRect(origin: CGPoint(x: buttonRightOrigin.x - defaultButtonSize, y: buttonRightOrigin.y), size: CGSize(width: defaultButtonSize, height: defaultButtonSize)) - buttonRightOrigin.x -= defaultButtonSize + buttonSpacing + let buttonFrame = CGRect(origin: CGPoint(x: buttonRightOrigin.x - defaultButtonSize + buttonsScaledOffset, y: buttonRightOrigin.y), size: CGSize(width: defaultButtonSize, height: defaultButtonSize)) let buttonTransition: ContainedViewLayoutTransition = wasAdded ? .immediate : transition - buttonTransition.updateFrame(node: buttonNode, frame: buttonFrame) + + let apparentButtonFrame = buttonFrame.offsetBy(dx: 0.0, dy: buttonsVerticalOffset) + if additive { + buttonTransition.updateFrameAdditiveToCenter(node: buttonNode, frame: apparentButtonFrame) + } else { + buttonTransition.updateFrame(node: buttonNode, frame: apparentButtonFrame) + } let buttonText: String let buttonIcon: PeerInfoHeaderButtonIcon switch buttonKey { @@ -249,8 +869,32 @@ private final class PeerInfoHeaderNode: ASDisplayNode { case .more: buttonText = "More" buttonIcon = .more + case .addMember: + buttonText = "Add Member" + buttonIcon = .addMember + } + buttonNode.update(size: buttonFrame.size, text: buttonText, icon: buttonIcon, isExpanded: self.isAvatarExpanded, presentationData: presentationData, transition: buttonTransition) + transition.updateSublayerTransformScaleAdditive(node: buttonNode, scale: buttonsScale) + + transition.updateAlpha(node: buttonNode, alpha: buttonsAlpha) + if self.isAvatarExpanded, case .mute = buttonKey { + if case let .animated(duration, curve) = transition { + ContainedViewLayoutTransition.animated(duration: duration * 0.3, curve: curve).updateAlpha(node: buttonNode.containerNode, alpha: 0.0) + } else { + transition.updateAlpha(node: buttonNode.containerNode, alpha: 0.0) + } + } else { + if case .mute = buttonKey, buttonNode.containerNode.alpha.isZero, additive { + if case let .animated(duration, curve) = transition { + ContainedViewLayoutTransition.animated(duration: duration * 0.3, curve: curve).updateAlpha(node: buttonNode.containerNode, alpha: 1.0) + } else { + transition.updateAlpha(node: buttonNode.containerNode, alpha: 1.0) + } + } else { + transition.updateAlpha(node: buttonNode.containerNode, alpha: 1.0) + } + buttonRightOrigin.x -= apparentButtonSize + buttonSpacing } - buttonNode.update(size: buttonFrame.size, text: buttonText, icon: buttonIcon, isExpanded: false, presentationData: presentationData, transition: buttonTransition) } for key in self.buttonNodes.keys { @@ -262,15 +906,43 @@ private final class PeerInfoHeaderNode: ASDisplayNode { } } - transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -1000.0), size: CGSize(width: width, height: 1000.0 + height))) - transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: height), size: CGSize(width: width, height: UIScreenPixel))) + let backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: -2000.0 + apparentHeight), size: CGSize(width: width, height: 2000.0)) + let separatorFrame = CGRect(origin: CGPoint(x: 0.0, y: apparentHeight), size: CGSize(width: width, height: UIScreenPixel)) + if additive { + transition.updateFrameAdditive(node: self.backgroundNode, frame: backgroundFrame) + transition.updateFrameAdditive(node: self.separatorNode, frame: separatorFrame) + } else { + transition.updateFrame(node: self.backgroundNode, frame: backgroundFrame) + transition.updateFrame(node: self.separatorNode, frame: separatorFrame) + } - return height + if self.isAvatarExpanded { + return width + expandedAvatarControlsHeight + } else { + return 212.0 + navigationHeight + } } private func buttonPressed(_ buttonNode: PeerInfoHeaderButtonNode) { self.performButtonAction?(buttonNode.key) } + + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + if !self.backgroundNode.frame.contains(point) { + return nil + } + guard let result = super.hitTest(point, with: event) else { + return nil + } + if result == self.view { + return nil + } + return result + } + + func updateIsAvatarExpanded(_ isAvatarExpanded: Bool) { + self.isAvatarExpanded = isAvatarExpanded + } } protocol PeerInfoPaneNode: ASDisplayNode { @@ -511,7 +1183,7 @@ private final class PeerInfoPaneContainerNode: ASDisplayNode { let isReady = Promise() var didSetIsReady = false - private var currentParams: (size: CGSize, isScrollingLockedAtTop: Bool, presentationData: PresentationData)? + private var currentParams: (size: CGSize, expansionFraction: CGFloat, presentationData: PresentationData)? private var availablePanes: [PeerInfoPaneKey] = [] private var currentPaneKey: PeerInfoPaneKey? @@ -581,8 +1253,8 @@ private final class PeerInfoPaneContainerNode: ASDisplayNode { let disposable = MetaDisposable() strongSelf.candidatePane = (PeerInfoPaneWrapper(key: key, node: paneNode), disposable) - if let (size, isScrollingLockedAtTop, presentationData) = strongSelf.currentParams { - strongSelf.update(size: size, isScrollingLockedAtTop: isScrollingLockedAtTop, presentationData: presentationData, transition: .immediate) + if let (size, expansionFraction, presentationData) = strongSelf.currentParams { + strongSelf.update(size: size, expansionFraction: expansionFraction, presentationData: presentationData, transition: .immediate) } disposable.set((paneNode.isReady @@ -597,8 +1269,8 @@ private final class PeerInfoPaneContainerNode: ASDisplayNode { strongSelf.currentPaneKey = candidatePane.key strongSelf.currentPane = candidatePane - if let (size, isScrollingLockedAtTop, presentationData) = strongSelf.currentParams { - strongSelf.update(size: size, isScrollingLockedAtTop: isScrollingLockedAtTop, presentationData: presentationData, transition: .animated(duration: 0.35, curve: .spring)) + if let (size, expansionFraction, presentationData) = strongSelf.currentParams { + strongSelf.update(size: size, expansionFraction: expansionFraction, presentationData: presentationData, transition: .animated(duration: 0.35, curve: .spring)) if let previousPane = previousPane { let directionToRight: Bool @@ -641,10 +1313,10 @@ private final class PeerInfoPaneContainerNode: ASDisplayNode { return self.currentPane?.node.transitionNodeForGallery(messageId: messageId, media: media) } - func update(size: CGSize, isScrollingLockedAtTop: Bool, presentationData: PresentationData, transition: ContainedViewLayoutTransition) { - self.currentParams = (size, isScrollingLockedAtTop, presentationData) + func update(size: CGSize, expansionFraction: CGFloat, presentationData: PresentationData, transition: ContainedViewLayoutTransition) { + self.currentParams = (size, expansionFraction, presentationData) - transition.updateAlpha(node: self.coveringBackgroundNode, alpha: isScrollingLockedAtTop ? 0.0 : 1.0) + transition.updateAlpha(node: self.coveringBackgroundNode, alpha: expansionFraction) self.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor self.coveringBackgroundNode.backgroundColor = presentationData.theme.rootController.navigationBar.backgroundColor @@ -654,7 +1326,7 @@ private final class PeerInfoPaneContainerNode: ASDisplayNode { let tabsHeight: CGFloat = 48.0 transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: size.width, height: UIScreenPixel))) - transition.updateFrame(node: self.coveringBackgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: tabsHeight))) + transition.updateFrame(node: self.coveringBackgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: size.width, height: tabsHeight + UIScreenPixel))) transition.updateFrame(node: self.tapsSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: tabsHeight - UIScreenPixel), size: CGSize(width: size.width, height: UIScreenPixel))) @@ -714,12 +1386,12 @@ private final class PeerInfoPaneContainerNode: ASDisplayNode { let paneTransition: ContainedViewLayoutTransition = paneWasAdded ? .immediate : transition paneTransition.updateFrame(node: currentPane.node, frame: paneFrame) - currentPane.update(size: paneFrame.size, isScrollingLockedAtTop: isScrollingLockedAtTop, presentationData: presentationData, synchronous: paneWasAdded, transition: paneTransition) + currentPane.update(size: paneFrame.size, isScrollingLockedAtTop: expansionFraction < 1.0 - CGFloat.ulpOfOne, presentationData: presentationData, synchronous: paneWasAdded, transition: paneTransition) } if let (candidatePane, _) = self.candidatePane { let paneTransition: ContainedViewLayoutTransition = .immediate paneTransition.updateFrame(node: candidatePane.node, frame: paneFrame) - candidatePane.update(size: paneFrame.size, isScrollingLockedAtTop: isScrollingLockedAtTop, presentationData: presentationData, synchronous: true, transition: paneTransition) + candidatePane.update(size: paneFrame.size, isScrollingLockedAtTop: expansionFraction < 1.0 - CGFloat.ulpOfOne, presentationData: presentationData, synchronous: true, transition: paneTransition) } if !self.didSetIsReady { self.didSetIsReady = true @@ -930,99 +1602,27 @@ private func peerInfoSectionItems(data: PeerInfoScreenData?, presentationData: P return items } -private final class PeerInfoNavigationNode: ASDisplayNode { - private let backgroundNode: ASDisplayNode - private let separatorContainerNode: ASDisplayNode - private let separatorCoveringNode: ASDisplayNode - private let separatorNode: ASDisplayNode - private let titleNode: ImmediateTextNode - - private var currentParams: (PresentationData, Peer?)? - - override init() { - self.backgroundNode = ASDisplayNode() - self.backgroundNode.isLayerBacked = true - - self.separatorContainerNode = ASDisplayNode() - self.separatorContainerNode.isLayerBacked = true - self.separatorContainerNode.clipsToBounds = true - - self.separatorCoveringNode = ASDisplayNode() - self.separatorCoveringNode.isLayerBacked = true - - self.separatorNode = ASDisplayNode() - self.separatorNode.isLayerBacked = true - - self.titleNode = ImmediateTextNode() - - super.init() - - self.addSubnode(self.backgroundNode) - - self.separatorContainerNode.addSubnode(self.separatorNode) - self.separatorContainerNode.addSubnode(self.separatorCoveringNode) - self.addSubnode(self.separatorContainerNode) - - self.addSubnode(self.titleNode) - } - - func update(size: CGSize, statusBarHeight: CGFloat, navigationHeight: CGFloat, offset: CGFloat, paneContainerOffset: CGFloat, presentationData: PresentationData, peer: Peer?, transition: ContainedViewLayoutTransition) { - if let (currentPresentationData, currentPeer) = self.currentParams { - if currentPresentationData !== presentationData || currentPeer !== peer { - if let peer = peer { - self.titleNode.attributedText = NSAttributedString(string: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), font: Font.semibold(17.0), textColor: presentationData.theme.rootController.navigationBar.primaryTextColor) - } - } - } - - if self.currentParams?.0.theme !== presentationData.theme { - self.backgroundNode.backgroundColor = presentationData.theme.rootController.navigationBar.backgroundColor - self.separatorNode.backgroundColor = presentationData.theme.rootController.navigationBar.separatorColor - self.separatorCoveringNode.backgroundColor = presentationData.theme.rootController.navigationBar.backgroundColor - } - - self.currentParams = (presentationData, peer) - - let titleSize = self.titleNode.updateLayout(CGSize(width: size.width - 100.0, height: .greatestFiniteMagnitude)) - let titleFrame = CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: statusBarHeight + floor((navigationHeight - statusBarHeight - titleSize.height) / 2.0)), size: titleSize) - transition.updateFrameAdditiveToCenter(node: self.titleNode, frame: titleFrame) - - transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: size)) - transition.updateFrame(node: self.separatorContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: size.height), size: CGSize(width: size.width, height: UIScreenPixel))) - transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: UIScreenPixel))) - transition.updateFrame(node: self.separatorCoveringNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -offset + paneContainerOffset - size.height), size: CGSize(width: size.width, height: 10.0 + UIScreenPixel))) - - let revealOffset: CGFloat = 100.0 - let progress: CGFloat = max(0.0, min(1.0, offset / revealOffset)) - - transition.updateAlpha(node: self.backgroundNode, alpha: progress) - transition.updateAlpha(node: self.separatorNode, alpha: progress) - transition.updateAlpha(node: self.titleNode, alpha: progress) - } -} - private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate { private weak var controller: PeerInfoScreen? private let context: AccountContext private let peerId: PeerId private var presentationData: PresentationData - private let scrollNode: ASScrollNode + let scrollNode: ASScrollNode - private let navigationNode: PeerInfoNavigationNode - private let headerNode: PeerInfoHeaderNode + let headerNode: PeerInfoHeaderNode private let infoSection: PeerInfoScreenItemSectionContainerNode private let paneContainerNode: PeerInfoPaneContainerNode - private var isPaneAreaExpanded: Bool = false private var ignoreScrolling: Bool = false + private var hapticFeedback: HapticFeedback? private var _interaction: PeerInfoInteraction? private var interaction: PeerInfoInteraction { return self._interaction! } - private var validLayout: (ContainerViewLayout, CGFloat)? - private var data: PeerInfoScreenData? + private(set) var validLayout: (ContainerViewLayout, CGFloat)? + private(set) var data: PeerInfoScreenData? private var dataDisposable: Disposable? private let _ready = Promise() @@ -1031,7 +1631,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } private var didSetReady = false - init(controller: PeerInfoScreen, context: AccountContext, peerId: PeerId) { + init(controller: PeerInfoScreen, context: AccountContext, peerId: PeerId, avatarInitiallyExpanded: Bool) { self.controller = controller self.context = context self.peerId = peerId @@ -1039,8 +1639,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD self.scrollNode = ASScrollNode() - self.navigationNode = PeerInfoNavigationNode() - self.headerNode = PeerInfoHeaderNode(context: context) + self.headerNode = PeerInfoHeaderNode(context: context, avatarInitiallyExpanded: avatarInitiallyExpanded) self.infoSection = PeerInfoScreenItemSectionContainerNode(id: 0) self.paneContainerNode = PeerInfoPaneContainerNode(context: context, peerId: peerId) @@ -1064,11 +1663,9 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD self.scrollNode.view.scrollsToTop = false self.scrollNode.view.delegate = self self.addSubnode(self.scrollNode) - self.addSubnode(self.navigationNode) - - self.scrollNode.addSubnode(self.headerNode) self.scrollNode.addSubnode(self.infoSection) self.scrollNode.addSubnode(self.paneContainerNode) + self.addSubnode(self.headerNode) self.paneContainerNode.openMessage = { [weak self] id in return self?.openMessage(id: id) ?? false @@ -1078,6 +1675,20 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD self?.performButtonAction(key: key) } + self.headerNode.requestAvatarExpansion = { [weak self] in + guard let strongSelf = self else { + return + } + let transition: ContainedViewLayoutTransition = .animated(duration: 0.35, curve: .spring) + + strongSelf.headerNode.updateIsAvatarExpanded(true) + strongSelf.updateNavigationExpansionPresentation(isExpanded: true, animated: true) + + if let (layout, navigationHeight) = strongSelf.validLayout { + strongSelf.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: transition, additive: true) + } + } + self.dataDisposable = (peerInfoScreenData(context: context, peerId: peerId) |> deliverOnMainQueue).start(next: { [weak self] data in guard let strongSelf = self else { @@ -1103,13 +1714,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } func scrollToTop() { - if self.isPaneAreaExpanded { - if !self.paneContainerNode.scrollToTop() { - - } - } else { - self.scrollNode.view.setContentOffset(CGPoint(), animated: true) - } + self.scrollNode.view.setContentOffset(CGPoint(), animated: true) } private func openMessage(id: MessageId) -> Bool { @@ -1149,7 +1754,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD switch key { case .message: if let navigationController = controller.navigationController as? NavigationController { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(self.peerId))) + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(self.peerId))) } case .call: self.requestCall() @@ -1206,6 +1811,8 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD ActionSheetItemGroup(items: [ActionSheetButtonItem(title: self.presentationData.strings.Common_Cancel, action: { dismissAction() })]) ]) controller.present(actionSheet, in: .window(.root)) + case .addMember: + break } } @@ -1373,47 +1980,62 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD }) } - func containerLayoutUpdated(layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition) { + func containerLayoutUpdated(layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition, additive: Bool = false) { self.validLayout = (layout, navigationHeight) self.ignoreScrolling = true - transition.updateFrame(node: self.navigationNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: navigationHeight))) transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: layout.size)) let sectionSpacing: CGFloat = 24.0 var contentHeight: CGFloat = 0.0 - let headerHeight = self.headerNode.update(width: layout.size.width, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, presentationData: self.presentationData, peer: self.data?.peer, cachedData: self.data?.cachedData, notificationSettings: self.data?.notificationSettings, presence: self.data?.presence, transition: transition) - transition.updateFrame(node: self.headerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: layout.size.width, height: headerHeight))) + let headerHeight = self.headerNode.update(width: layout.size.width, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, contentOffset: self.scrollNode.view.contentOffset.y, presentationData: self.presentationData, peer: self.data?.peer, cachedData: self.data?.cachedData, notificationSettings: self.data?.notificationSettings, presence: self.data?.presence, transition: transition, additive: additive) + let headerFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: layout.size.width, height: headerHeight)) + if additive { + transition.updateFrameAdditive(node: self.headerNode, frame: headerFrame) + } else { + transition.updateFrame(node: self.headerNode, frame: headerFrame) + } contentHeight += headerHeight contentHeight += sectionSpacing let infoSectionHeight = self.infoSection.update(width: layout.size.width, presentationData: self.presentationData, items: peerInfoSectionItems(data: self.data, presentationData: self.presentationData, interaction: self.interaction), transition: transition) let infoSectionFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: layout.size.width, height: infoSectionHeight)) - transition.updateFrame(node: self.infoSection, frame: infoSectionFrame) + if additive { + transition.updateFrameAdditive(node: self.infoSection, frame: infoSectionFrame) + } else { + transition.updateFrame(node: self.infoSection, frame: infoSectionFrame) + } contentHeight += infoSectionHeight contentHeight += sectionSpacing let paneContainerSize = CGSize(width: layout.size.width, height: layout.size.height - navigationHeight) - self.paneContainerNode.update(size: paneContainerSize, isScrollingLockedAtTop: !self.isPaneAreaExpanded, presentationData: self.presentationData, transition: transition) - transition.updateFrame(node: self.paneContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: paneContainerSize)) - contentHeight += layout.size.height - navigationHeight - - self.scrollNode.view.contentSize = CGSize(width: layout.size.width, height: contentHeight) - - if self.isPaneAreaExpanded { - transition.updateBounds(node: self.scrollNode, bounds: CGRect(origin: CGPoint(x: 0.0, y: contentHeight - self.scrollNode.bounds.height), size: self.scrollNode.bounds.size)) - } else { - let maxOffsetY = max(0.0, contentHeight - floor(self.scrollNode.bounds.height * 1.5)) - if self.scrollNode.view.contentOffset.y > maxOffsetY { - //transition.updateBounds(node: self.scrollNode, bounds: CGRect(origin: CGPoint(x: 0.0, y: maxOffsetY), size: self.scrollNode.bounds.size)) - } + var restoreContentOffset: CGPoint? + if additive { + restoreContentOffset = self.scrollNode.view.contentOffset + } + self.scrollNode.view.contentSize = CGSize(width: layout.size.width, height: contentHeight + paneContainerSize.height) + if let restoreContentOffset = restoreContentOffset { + self.scrollNode.view.contentOffset = restoreContentOffset } + let paneAreaExpansionDistance: CGFloat = 32.0 + var paneAreaExpansionDelta = (contentHeight - navigationHeight) - self.scrollNode.view.contentOffset.y + paneAreaExpansionDelta = max(0.0, min(paneAreaExpansionDelta, paneAreaExpansionDistance)) + let paneAreaExpansionFraction: CGFloat = 1.0 - paneAreaExpansionDelta / paneAreaExpansionDistance + + let paneContainerFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: paneContainerSize) + if additive { + transition.updateFrameAdditive(node: self.paneContainerNode, frame: paneContainerFrame) + } else { + transition.updateFrame(node: self.paneContainerNode, frame: paneContainerFrame) + } + contentHeight += layout.size.height - navigationHeight + self.ignoreScrolling = false - self.updateNavigation(transition: transition) + self.updateNavigation(transition: transition, additive: additive) if !self.didSetReady && self.data != nil { self.didSetReady = true @@ -1421,91 +2043,113 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } } - private func updateNavigation(transition: ContainedViewLayoutTransition) { + private func updateNavigation(transition: ContainedViewLayoutTransition, additive: Bool) { let offsetY = self.scrollNode.view.contentOffset.y - if offsetY <= 1.0 { + if offsetY <= 50.0 { self.scrollNode.view.bounces = true } else { self.scrollNode.view.bounces = false } if let (layout, navigationHeight) = self.validLayout { - self.navigationNode.update(size: CGSize(width: layout.size.width, height: navigationHeight), statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, offset: offsetY, paneContainerOffset: self.paneContainerNode.frame.minY, presentationData: self.presentationData, peer: self.data?.peer, transition: transition) + if !additive { + self.headerNode.update(width: layout.size.width, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, contentOffset: offsetY, presentationData: self.presentationData, peer: self.data?.peer, cachedData: self.data?.cachedData, notificationSettings: self.data?.notificationSettings, presence: self.data?.presence, transition: transition, additive: additive) + } + + let paneAreaExpansionDistance: CGFloat = 32.0 + var paneAreaExpansionDelta = (self.paneContainerNode.frame.minY - navigationHeight) - self.scrollNode.view.contentOffset.y + paneAreaExpansionDelta = max(0.0, min(paneAreaExpansionDelta, paneAreaExpansionDistance)) + let paneAreaExpansionFraction: CGFloat = 1.0 - paneAreaExpansionDelta / paneAreaExpansionDistance + + transition.updateAlpha(node: self.headerNode.separatorNode, alpha: 1.0 - paneAreaExpansionFraction) + + self.paneContainerNode.update(size: self.paneContainerNode.bounds.size, expansionFraction: paneAreaExpansionFraction, presentationData: self.presentationData, transition: transition) } } + private var canUpdateAvatarExpansion = false + + func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { + self.canUpdateAvatarExpansion = true + } + func scrollViewDidScroll(_ scrollView: UIScrollView) { if self.ignoreScrolling { return } - self.updateNavigation(transition: .immediate) + self.updateNavigation(transition: .immediate, additive: false) + + if scrollView.isDragging && scrollView.isTracking { + let offsetY = self.scrollNode.view.contentOffset.y + var shouldBeExpanded: Bool? + if offsetY <= -32.0 { + shouldBeExpanded = true + } else if offsetY >= 4.0 { + shouldBeExpanded = false + } + if let shouldBeExpanded = shouldBeExpanded, self.canUpdateAvatarExpansion, shouldBeExpanded != self.headerNode.isAvatarExpanded { + let transition: ContainedViewLayoutTransition = .animated(duration: 0.35, curve: .spring) + + if self.hapticFeedback == nil { + self.hapticFeedback = HapticFeedback() + } + if shouldBeExpanded { + self.hapticFeedback?.impact() + } else { + self.hapticFeedback?.tap() + } + + self.headerNode.updateIsAvatarExpanded(shouldBeExpanded) + self.updateNavigationExpansionPresentation(isExpanded: shouldBeExpanded, animated: true) + + if let (layout, navigationHeight) = self.validLayout { + self.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: transition, additive: true) + } + + if !shouldBeExpanded { + //scrollView.setContentOffset(CGPoint(), animated: true) + } + } + } + } + + private func updateNavigationExpansionPresentation(isExpanded: Bool, animated: Bool) { + if let controller = self.controller { + controller.statusBar.updateStatusBarStyle(isExpanded ? .White : self.presentationData.theme.rootController.statusBarStyle.style, animated: animated) + + let baseNavigationBarPresentationData = NavigationBarPresentationData(presentationData: self.presentationData) + let navigationBarPresentationData = NavigationBarPresentationData( + theme: NavigationBarTheme( + buttonColor: isExpanded ? .white : baseNavigationBarPresentationData.theme.buttonColor, + disabledButtonColor: baseNavigationBarPresentationData.theme.disabledButtonColor, + primaryTextColor: baseNavigationBarPresentationData.theme.primaryTextColor, + backgroundColor: .clear, + separatorColor: .clear, + badgeBackgroundColor: baseNavigationBarPresentationData.theme.badgeBackgroundColor, + badgeStrokeColor: baseNavigationBarPresentationData.theme.badgeStrokeColor, + badgeTextColor: baseNavigationBarPresentationData.theme.badgeTextColor + ), strings: baseNavigationBarPresentationData.strings) + + if let navigationBar = controller.navigationBar { + if animated { + UIView.transition(with: navigationBar.view, duration: 0.3, options: [.transitionCrossDissolve], animations: { + }, completion: nil) + } + navigationBar.updatePresentationData(navigationBarPresentationData) + } + } } func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) { guard let (_, navigationHeight) = self.validLayout else { return } - let snapDurationFactor = max(0.5, min(1.5, abs(velocity.y) * 0.8)) - - var snapToOffset: CGFloat? - let offset = targetContentOffset.pointee.y - - let headerMaxOffset = self.headerNode.bounds.height - navigationHeight - let collapsedPanesOffset = max(0.0, scrollView.contentSize.height - floor(scrollNode.bounds.height * 1.5)) - let expandedPanesOffset = scrollView.contentSize.height - self.scrollNode.bounds.height - - if offset > collapsedPanesOffset { - if velocity.y < 0.0 { - var targetOffset = collapsedPanesOffset - if targetOffset < headerMaxOffset { - targetOffset = 0.0 - } - snapToOffset = targetOffset + if targetContentOffset.pointee.y < 212.0 { + if targetContentOffset.pointee.y < 212.0 / 2.0 { + targetContentOffset.pointee.y = 0.0 } else { - snapToOffset = expandedPanesOffset - } - } else if offset < headerMaxOffset && offset > 0.0 { - let directionIsDown: Bool - if abs(velocity.y) > 0.2 { - directionIsDown = velocity.y >= 0.0 - } else { - directionIsDown = offset >= headerMaxOffset / 2.0 - } - - if directionIsDown { - snapToOffset = headerMaxOffset - } else { - snapToOffset = 0.0 - } - } else if self.isPaneAreaExpanded && offset < expandedPanesOffset { - let directionIsDown: Bool - if abs(velocity.y) > 0.2 { - directionIsDown = velocity.y >= 0.0 - } else { - directionIsDown = offset >= headerMaxOffset / 2.0 - } - - if directionIsDown { - snapToOffset = headerMaxOffset - } else { - snapToOffset = 0.0 - } - } - - if let snapToOffset = snapToOffset { - targetContentOffset.pointee = scrollView.contentOffset - DispatchQueue.main.async { - let isPaneAreaExpanded = abs(snapToOffset - expandedPanesOffset) < CGFloat.ulpOfOne ? true : false - self.isPaneAreaExpanded = isPaneAreaExpanded - let currentOffset = scrollView.contentOffset - let transition: ContainedViewLayoutTransition = .animated(duration: 0.3 * Double(1.0 / snapDurationFactor), curve: .spring) - self.ignoreScrolling = true - transition.updateBounds(node: self.scrollNode, bounds: CGRect(origin: CGPoint(x: 0.0, y: snapToOffset), size: self.scrollNode.bounds.size)) - self.ignoreScrolling = false - if let (layout, navigationHeight) = self.validLayout { - self.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: transition) - } + targetContentOffset.pointee.y = 212.0 } } } @@ -1541,6 +2185,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD public final class PeerInfoScreen: ViewController { private let context: AccountContext private let peerId: PeerId + private let avatarInitiallyExpanded: Bool private var presentationData: PresentationData @@ -1553,16 +2198,17 @@ public final class PeerInfoScreen: ViewController { return self._ready } - public init(context: AccountContext, peerId: PeerId) { + public init(context: AccountContext, peerId: PeerId, avatarInitiallyExpanded: Bool = false) { self.context = context self.peerId = peerId + self.avatarInitiallyExpanded = avatarInitiallyExpanded self.presentationData = context.sharedContext.currentPresentationData.with { $0 } let baseNavigationBarPresentationData = NavigationBarPresentationData(presentationData: self.presentationData) super.init(navigationBarPresentationData: NavigationBarPresentationData( theme: NavigationBarTheme( - buttonColor: baseNavigationBarPresentationData.theme.buttonColor, + buttonColor: avatarInitiallyExpanded ? .white : baseNavigationBarPresentationData.theme.buttonColor, disabledButtonColor: baseNavigationBarPresentationData.theme.disabledButtonColor, primaryTextColor: baseNavigationBarPresentationData.theme.primaryTextColor, backgroundColor: .clear, @@ -1571,8 +2217,20 @@ public final class PeerInfoScreen: ViewController { badgeStrokeColor: baseNavigationBarPresentationData.theme.badgeStrokeColor, badgeTextColor: baseNavigationBarPresentationData.theme.badgeTextColor ), strings: baseNavigationBarPresentationData.strings)) + self.navigationBar?.makeCustomTransitionNode = { [weak self] other in + guard let strongSelf = self else { + return nil + } + if strongSelf.controllerNode.scrollNode.view.contentOffset.y > .ulpOfOne { + return nil + } + if let tag = other.userInfo as? PeerInfoNavigationSourceTag, tag.peerId == peerId { + return PeerInfoNavigationTransitionNode(screenNode: strongSelf.controllerNode, presentationData: strongSelf.presentationData, headerNode: strongSelf.controllerNode.headerNode) + } + return nil + } - self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style + self.statusBar.statusBarStyle = avatarInitiallyExpanded ? .White : self.presentationData.theme.rootController.statusBarStyle.style self.scrollToTop = { [weak self] in self?.controllerNode.scrollToTop() @@ -1584,7 +2242,7 @@ public final class PeerInfoScreen: ViewController { } override public func loadDisplayNode() { - self.displayNode = PeerInfoScreenNode(controller: self, context: self.context, peerId: self.peerId) + self.displayNode = PeerInfoScreenNode(controller: self, context: self.context, peerId: self.peerId, avatarInitiallyExpanded: self.avatarInitiallyExpanded) self._ready.set(self.controllerNode.ready.get()) @@ -1616,3 +2274,162 @@ private func getUserPeer(postbox: Postbox, peerId: PeerId) -> Signal<(Peer?, Cac return (resultPeer, resultPeer.flatMap({ transaction.getPeerCachedData(peerId: $0.id) })) } } + +final class PeerInfoNavigationSourceTag { + let peerId: PeerId + + init(peerId: PeerId) { + self.peerId = peerId + } +} + +private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavigationTransitionNode { + private let screenNode: PeerInfoScreenNode + private let presentationData: PresentationData + + private var topNavigationBar: NavigationBar? + private var bottomNavigationBar: NavigationBar? + + private let headerNode: PeerInfoHeaderNode + + private var previousBackButtonArrow: ASDisplayNode? + private var currentBackButtonArrow: ASDisplayNode? + private var previousBackButtonBadge: ASDisplayNode? + private var previousRightButton: ASDisplayNode? + private var currentBackButton: ASDisplayNode? + + private var previousTitleNode: (ASDisplayNode, TextNode)? + private var previousStatusNode: (ASDisplayNode, ASDisplayNode)? + + private var didSetup: Bool = false + + init(screenNode: PeerInfoScreenNode, presentationData: PresentationData, headerNode: PeerInfoHeaderNode) { + self.screenNode = screenNode + self.presentationData = presentationData + self.headerNode = headerNode + + super.init() + + self.addSubnode(headerNode) + } + + func setup(topNavigationBar: NavigationBar, bottomNavigationBar: NavigationBar) { + self.topNavigationBar = topNavigationBar + self.bottomNavigationBar = bottomNavigationBar + + topNavigationBar.isHidden = true + bottomNavigationBar.isHidden = true + + if let previousBackButtonArrow = bottomNavigationBar.makeTransitionBackArrowNode(accentColor: self.presentationData.theme.rootController.navigationBar.accentTextColor) { + self.previousBackButtonArrow = previousBackButtonArrow + self.addSubnode(previousBackButtonArrow) + } + if self.screenNode.headerNode.isAvatarExpanded, let currentBackButtonArrow = topNavigationBar.makeTransitionBackArrowNode(accentColor: self.screenNode.headerNode.isAvatarExpanded ? .white : self.presentationData.theme.rootController.navigationBar.accentTextColor) { + self.currentBackButtonArrow = currentBackButtonArrow + self.addSubnode(currentBackButtonArrow) + } + if let previousBackButtonBadge = bottomNavigationBar.makeTransitionBadgeNode() { + self.previousBackButtonBadge = previousBackButtonBadge + self.addSubnode(previousBackButtonBadge) + } + if let previousRightButton = bottomNavigationBar.makeTransitionRightButtonNode(accentColor: self.presentationData.theme.rootController.navigationBar.accentTextColor) { + self.previousRightButton = previousRightButton + self.addSubnode(previousRightButton) + } + if let currentBackButton = topNavigationBar.makeTransitionBackButtonNode(accentColor: self.screenNode.headerNode.isAvatarExpanded ? .white : self.presentationData.theme.rootController.navigationBar.accentTextColor) { + self.currentBackButton = currentBackButton + self.addSubnode(currentBackButton) + } + if let previousTitleView = bottomNavigationBar.titleView as? ChatTitleView { + let previousTitleNode = previousTitleView.titleNode.makeCopy() + let previousTitleContainerNode = ASDisplayNode() + previousTitleContainerNode.addSubnode(previousTitleNode) + self.previousTitleNode = (previousTitleContainerNode, previousTitleNode) + self.addSubnode(previousTitleContainerNode) + + let previousStatusNode = previousTitleView.activityNode.makeCopy() + let previousStatusContainerNode = ASDisplayNode() + previousStatusContainerNode.addSubnode(previousStatusNode) + self.previousStatusNode = (previousStatusContainerNode, previousStatusNode) + self.addSubnode(previousStatusContainerNode) + } + } + + func update(containerSize: CGSize, fraction: CGFloat, transition: ContainedViewLayoutTransition) { + guard let topNavigationBar = self.topNavigationBar, let bottomNavigationBar = self.bottomNavigationBar else { + return + } + + if let previousBackButtonArrow = self.previousBackButtonArrow { + let previousBackButtonArrowFrame = bottomNavigationBar.backButtonArrow.view.convert(bottomNavigationBar.backButtonArrow.view.bounds, to: bottomNavigationBar.view) + previousBackButtonArrow.frame = previousBackButtonArrowFrame + } + + if let currentBackButtonArrow = self.currentBackButtonArrow { + let currentBackButtonArrowFrame = topNavigationBar.backButtonArrow.view.convert(topNavigationBar.backButtonArrow.view.bounds, to: topNavigationBar.view) + currentBackButtonArrow.frame = currentBackButtonArrowFrame + + transition.updateAlpha(node: currentBackButtonArrow, alpha: 1.0 - fraction) + if let previousBackButtonArrow = self.previousBackButtonArrow { + transition.updateAlpha(node: previousBackButtonArrow, alpha: fraction) + } + } + + if let previousBackButtonBadge = self.previousBackButtonBadge { + let previousBackButtonBadgeFrame = bottomNavigationBar.badgeNode.view.convert(bottomNavigationBar.badgeNode.view.bounds, to: bottomNavigationBar.view) + previousBackButtonBadge.frame = previousBackButtonBadgeFrame + + transition.updateAlpha(node: previousBackButtonBadge, alpha: fraction) + } + + if let previousRightButton = self.previousRightButton { + let previousRightButtonFrame = bottomNavigationBar.rightButtonNode.view.convert(bottomNavigationBar.rightButtonNode.view.bounds, to: bottomNavigationBar.view) + previousRightButton.frame = previousRightButtonFrame + transition.updateAlpha(node: previousRightButton, alpha: fraction) + } + + if let currentBackButton = self.currentBackButton { + let currentBackButtonFrame = topNavigationBar.backButtonNode.view.convert(topNavigationBar.backButtonNode.view.bounds, to: topNavigationBar.view) + transition.updateFrame(node: currentBackButton, frame: currentBackButtonFrame.offsetBy(dx: fraction * 12.0, dy: 0.0)) + + transition.updateAlpha(node: currentBackButton, alpha: (1.0 - fraction)) + } + + if let previousTitleView = bottomNavigationBar.titleView as? ChatTitleView, let avatarNode = previousTitleView.avatarNode, let (previousTitleContainerNode, previousTitleNode) = self.previousTitleNode, let (previousStatusContainerNode, previousStatusNode) = self.previousStatusNode { + let previousTitleFrame = previousTitleView.titleNode.view.convert(previousTitleView.titleNode.bounds, to: bottomNavigationBar.view) + let previousStatusFrame = previousTitleView.activityNode.view.convert(previousTitleView.activityNode.bounds, to: bottomNavigationBar.view) + + self.headerNode.navigationTransition = PeerInfoHeaderNavigationTransition(sourceNavigationBar: bottomNavigationBar, sourceTitleView: previousTitleView, sourceTitleFrame: previousTitleFrame, sourceSubtitleFrame: previousStatusFrame, fraction: fraction) + if let (layout, navigationHeight) = self.screenNode.validLayout { + self.headerNode.update(width: layout.size.width, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: topNavigationBar.bounds.height, contentOffset: 0.0, presentationData: self.presentationData, peer: self.screenNode.data?.peer, cachedData: self.screenNode.data?.cachedData, notificationSettings: self.screenNode.data?.notificationSettings, presence: self.screenNode.data?.presence, transition: transition, additive: false) + } + + let titleScale = (fraction * previousTitleNode.bounds.height + (1.0 - fraction) * self.headerNode.titleNode.bounds.height) / previousTitleNode.bounds.height + let subtitleScale = (fraction * previousStatusNode.bounds.height + (1.0 - fraction) * self.headerNode.subtitleNode.bounds.height) / previousStatusNode.bounds.height + + transition.updateFrame(node: previousTitleContainerNode, frame: CGRect(origin: self.headerNode.titleNodeRawContainer.frame.origin.offsetBy(dx: previousTitleFrame.size.width * 0.5 * (titleScale - 1.0), dy: previousTitleFrame.size.height * 0.5 * (titleScale - 1.0)), size: previousTitleFrame.size)) + transition.updateFrame(node: previousTitleNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: previousTitleFrame.size)) + transition.updateFrame(node: previousStatusContainerNode, frame: CGRect(origin: self.headerNode.subtitleNodeRawContainer.frame.origin.offsetBy(dx: previousStatusFrame.size.width * 0.5 * (subtitleScale - 1.0), dy: previousStatusFrame.size.height * 0.5 * (subtitleScale - 1.0)), size: previousStatusFrame.size)) + transition.updateFrame(node: previousStatusNode, frame: CGRect(origin: CGPoint(), size: previousStatusFrame.size)) + + transition.updateSublayerTransformScale(node: previousTitleContainerNode, scale: titleScale) + transition.updateSublayerTransformScale(node: previousStatusContainerNode, scale: subtitleScale) + + transition.updateAlpha(node: self.headerNode.titleNode, alpha: (1.0 - fraction)) + transition.updateAlpha(node: previousTitleNode, alpha: fraction) + transition.updateAlpha(node: self.headerNode.subtitleNode, alpha: (1.0 - fraction)) + transition.updateAlpha(node: previousStatusNode, alpha: fraction) + } + } + + func restore() { + guard let topNavigationBar = self.topNavigationBar, let bottomNavigationBar = self.bottomNavigationBar else { + return + } + + topNavigationBar.isHidden = false + bottomNavigationBar.isHidden = false + self.headerNode.navigationTransition = nil + self.screenNode.insertSubnode(self.headerNode, aboveSubnode: self.screenNode.scrollNode) + } +} diff --git a/submodules/TelegramUI/TelegramUI/PeerMediaCollectionController.swift b/submodules/TelegramUI/TelegramUI/PeerMediaCollectionController.swift index 6863ff66a1..7374fc9577 100644 --- a/submodules/TelegramUI/TelegramUI/PeerMediaCollectionController.swift +++ b/submodules/TelegramUI/TelegramUI/PeerMediaCollectionController.swift @@ -759,7 +759,7 @@ public class PeerMediaCollectionController: TelegramBaseController { |> take(1) |> deliverOnMainQueue).start(next: { [weak self] peer in if let strongSelf = self, peer.restrictionText(platform: "ios", contentSettings: strongSelf.context.currentContentSettings.with { $0 }) == nil { - if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic) { + if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic, avatarInitiallyExpanded: false) { (strongSelf.navigationController as? NavigationController)?.pushViewController(infoController) } } diff --git a/submodules/TelegramUI/TelegramUI/PollResultsController.swift b/submodules/TelegramUI/TelegramUI/PollResultsController.swift index 177ca29828..a1a24b756a 100644 --- a/submodules/TelegramUI/TelegramUI/PollResultsController.swift +++ b/submodules/TelegramUI/TelegramUI/PollResultsController.swift @@ -303,7 +303,7 @@ public func pollResultsController(context: AccountContext, messageId: MessageId, }) }, openPeer: { peer in if let peer = peer.peers[peer.peerId] { - if let controller = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic) { + if let controller = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false) { pushControllerImpl?(controller) } } diff --git a/submodules/TelegramUI/TelegramUI/SharedAccountContext.swift b/submodules/TelegramUI/TelegramUI/SharedAccountContext.swift index 160fa6cfcc..50cdd8a69d 100644 --- a/submodules/TelegramUI/TelegramUI/SharedAccountContext.swift +++ b/submodules/TelegramUI/TelegramUI/SharedAccountContext.swift @@ -1004,8 +1004,8 @@ public final class SharedAccountContextImpl: SharedAccountContext { handleTextLinkActionImpl(context: context, peerId: peerId, navigateDisposable: navigateDisposable, controller: controller, action: action, itemLink: itemLink) } - public func makePeerInfoController(context: AccountContext, peer: Peer, mode: PeerInfoControllerMode) -> ViewController? { - let controller = peerInfoControllerImpl(context: context, peer: peer, mode: mode) + public func makePeerInfoController(context: AccountContext, peer: Peer, mode: PeerInfoControllerMode, avatarInitiallyExpanded: Bool) -> ViewController? { + let controller = peerInfoControllerImpl(context: context, peer: peer, mode: mode, avatarInitiallyExpanded: avatarInitiallyExpanded) controller?.navigationPresentation = .modalInLargeLayout return controller } @@ -1245,7 +1245,7 @@ public final class SharedAccountContextImpl: SharedAccountContext { private let defaultChatControllerInteraction = ChatControllerInteraction.default -private func peerInfoControllerImpl(context: AccountContext, peer: Peer, mode: PeerInfoControllerMode) -> ViewController? { +private func peerInfoControllerImpl(context: AccountContext, peer: Peer, mode: PeerInfoControllerMode, avatarInitiallyExpanded: Bool) -> ViewController? { if let _ = peer as? TelegramGroup { return groupInfoController(context: context, peerId: peer.id) } else if let channel = peer as? TelegramChannel { @@ -1255,7 +1255,7 @@ private func peerInfoControllerImpl(context: AccountContext, peer: Peer, mode: P return channelInfoController(context: context, peerId: peer.id) } } else if peer is TelegramUser { - return PeerInfoScreen(context: context, peerId: peer.id) + return PeerInfoScreen(context: context, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded) } else if peer is TelegramSecretChat { return userInfoController(context: context, peerId: peer.id, mode: mode) } diff --git a/submodules/TelegramUI/TelegramUI/SharedWakeupManager.swift b/submodules/TelegramUI/TelegramUI/SharedWakeupManager.swift index 962ac8a234..638751b63f 100644 --- a/submodules/TelegramUI/TelegramUI/SharedWakeupManager.swift +++ b/submodules/TelegramUI/TelegramUI/SharedWakeupManager.swift @@ -315,7 +315,7 @@ public final class SharedWakeupManager { if let taskId = self.beginBackgroundTask("background-wakeup", { handleExpiration() }) { - let timer = SwiftSignalKit.Timer(timeout: min(30.0, self.backgroundTimeRemaining()), repeat: false, completion: { + let timer = SwiftSignalKit.Timer(timeout: min(30.0, max(0.0, self.backgroundTimeRemaining() - 5.0)), repeat: false, completion: { handleExpiration() }, queue: Queue.mainQueue()) self.currentTask = (taskId, currentTime, timer) diff --git a/submodules/TelegramUI/TelegramUI/TextLinkHandling.swift b/submodules/TelegramUI/TelegramUI/TextLinkHandling.swift index cc46c4172e..d8d1fd0fb2 100644 --- a/submodules/TelegramUI/TelegramUI/TextLinkHandling.swift +++ b/submodules/TelegramUI/TelegramUI/TextLinkHandling.swift @@ -32,7 +32,7 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: PeerId?, navigate peerSignal = context.account.postbox.loadedPeerWithId(peerId) |> map(Optional.init) navigateDisposable.set((peerSignal |> take(1) |> deliverOnMainQueue).start(next: { peer in if let controller = controller, let peer = peer { - if let infoController = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic) { + if let infoController = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false) { (controller.navigationController as? NavigationController)?.pushViewController(infoController) } } From f9ccae936a39e3b5f70a9e72e359c8d5aa9cd9aa Mon Sep 17 00:00:00 2001 From: Ali <> Date: Wed, 5 Feb 2020 11:23:20 +0000 Subject: [PATCH 42/50] Add merchant id --- .../BotPaymentsUI/Sources/BotCheckoutControllerNode.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift b/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift index 75896af9e9..51c459351e 100644 --- a/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift +++ b/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift @@ -335,7 +335,8 @@ private func formSupportApplePay(_ paymentForm: BotPaymentForm) -> Bool { "stripe", "sberbank", "yandex", - "privatbank" + "privatbank", + "tranzzo" ]) if !applePayProviders.contains(nativeProvider.name) { return false From e2071301c275230da1fb99657638a8e8a08c9d05 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 7 Feb 2020 14:23:25 +0000 Subject: [PATCH 43/50] User Info screen --- Telegram-iOS/en.lproj/Localizable.strings | 5 + .../ContainedViewLayoutTransition.swift | 8 +- .../Display/Display/NavigationBar.swift | 21 + .../Display/NavigationButtonNode.swift | 12 +- .../Sources/ItemListPeerItem.swift | 2 +- .../Sources/NotificationSoundSelection.swift | 3 + submodules/Postbox/Sources/Coding.swift | 2 +- .../Postbox/Sources/HistoryTagInfoView.swift | 76 + .../Sources/MessageHistoryTagsTable.swift | 9 + submodules/Postbox/Sources/Views.swift | 551 +- .../Sources/SearchDisplayController.swift | 31 +- .../Sources/AccountViewTracker.swift | 4 +- .../Sources/PresentationStrings.swift | 8072 +++++++++-------- .../TelegramUI/ChatController.swift | 9 +- .../ChatMessageInteractiveMediaBadge.swift | 4 +- .../TelegramUI/TelegramUI/ChatTitleView.swift | 329 +- .../TelegramUI/FileMediaResourceStatus.swift | 2 +- .../TelegramUI/ListMessageFileItemNode.swift | 146 +- .../TelegramUI/PeerInfoFilesPane.swift | 47 +- .../PeerInfoGroupsInCommonPaneNode.swift | 165 + .../TelegramUI/PeerInfoScreen.swift | 2480 ++++- .../TelegramUI/PeerInfoScreenActionItem.swift | 98 + .../PeerInfoScreenDisclosureItem.swift | 115 + .../TelegramUI/PeerInfoScreenSwitchItem.swift | 121 + .../TelegramUI/PeerInfoVisualMediaPane.swift | 135 +- .../Resources/PresentationStrings.mapping | Bin 144565 -> 144705 bytes .../WalletUI/Resources/WalletStrings.mapping | Bin 8384 -> 8384 bytes .../WalletUI/Sources/WalletStrings.swift | 4 +- 28 files changed, 7682 insertions(+), 4769 deletions(-) create mode 100644 submodules/Postbox/Sources/HistoryTagInfoView.swift create mode 100644 submodules/TelegramUI/TelegramUI/PeerInfoGroupsInCommonPaneNode.swift create mode 100644 submodules/TelegramUI/TelegramUI/PeerInfoScreenActionItem.swift create mode 100644 submodules/TelegramUI/TelegramUI/PeerInfoScreenDisclosureItem.swift create mode 100644 submodules/TelegramUI/TelegramUI/PeerInfoScreenSwitchItem.swift diff --git a/Telegram-iOS/en.lproj/Localizable.strings b/Telegram-iOS/en.lproj/Localizable.strings index 2a8e328ead..f3195ab473 100644 --- a/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram-iOS/en.lproj/Localizable.strings @@ -262,6 +262,11 @@ "State.Updating" = "Updating..."; "State.WaitingForNetwork" = "Waiting for network"; +"ChatState.Connecting" = "connecting..."; +"ChatState.ConnectingToProxy" = "connecting to proxy..."; +"ChatState.Updating" = "updating..."; +"ChatState.WaitingForNetwork" = "waiting for network..."; + // Presence "Presence.online" = "online"; diff --git a/submodules/Display/Display/ContainedViewLayoutTransition.swift b/submodules/Display/Display/ContainedViewLayoutTransition.swift index 286e3070e1..0200f6f212 100644 --- a/submodules/Display/Display/ContainedViewLayoutTransition.swift +++ b/submodules/Display/Display/ContainedViewLayoutTransition.swift @@ -351,7 +351,7 @@ public extension ContainedViewLayoutTransition { func animatePositionAdditive(node: ASDisplayNode, offset: CGFloat, removeOnCompletion: Bool = true, completion: @escaping (Bool) -> Void) { switch self { case .immediate: - break + completion(true) case let .animated(duration, curve): node.layer.animatePosition(from: CGPoint(x: 0.0, y: offset), to: CGPoint(), duration: duration, timingFunction: curve.timingFunction, mediaTimingFunction: curve.mediaTimingFunction, removeOnCompletion: removeOnCompletion, additive: true, completion: completion) } @@ -360,7 +360,7 @@ public extension ContainedViewLayoutTransition { func animatePositionAdditive(layer: CALayer, offset: CGFloat, removeOnCompletion: Bool = true, completion: @escaping (Bool) -> Void) { switch self { case .immediate: - break + completion(true) case let .animated(duration, curve): layer.animatePosition(from: CGPoint(x: 0.0, y: offset), to: CGPoint(), duration: duration, timingFunction: curve.timingFunction, mediaTimingFunction: curve.mediaTimingFunction, removeOnCompletion: removeOnCompletion, additive: true, completion: completion) } @@ -369,7 +369,7 @@ public extension ContainedViewLayoutTransition { func animatePositionAdditive(node: ASDisplayNode, offset: CGPoint, removeOnCompletion: Bool = true, completion: (() -> Void)? = nil) { switch self { case .immediate: - break + completion?() case let .animated(duration, curve): node.layer.animatePosition(from: offset, to: CGPoint(), duration: duration, timingFunction: curve.timingFunction, mediaTimingFunction: curve.mediaTimingFunction, removeOnCompletion: removeOnCompletion, additive: true, completion: { _ in completion?() @@ -380,7 +380,7 @@ public extension ContainedViewLayoutTransition { func animatePositionAdditive(layer: CALayer, offset: CGPoint, to toOffset: CGPoint = CGPoint(), removeOnCompletion: Bool = true, completion: (() -> Void)? = nil) { switch self { case .immediate: - break + completion?() case let .animated(duration, curve): layer.animatePosition(from: offset, to: toOffset, duration: duration, timingFunction: curve.timingFunction, mediaTimingFunction: curve.mediaTimingFunction, removeOnCompletion: removeOnCompletion, additive: true, completion: { _ in completion?() diff --git a/submodules/Display/Display/NavigationBar.swift b/submodules/Display/Display/NavigationBar.swift index 6fc314f111..2bd04661cd 100644 --- a/submodules/Display/Display/NavigationBar.swift +++ b/submodules/Display/Display/NavigationBar.swift @@ -1188,4 +1188,25 @@ open class NavigationBar: ASDisplayNode { } } } + + override open func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + if self.bounds.contains(point) { + if self.backButtonNode.supernode != nil && !self.backButtonNode.isHidden { + let effectiveBackButtonRect = CGRect(origin: CGPoint(), size: CGSize(width: self.backButtonNode.frame.maxX + 20.0, height: self.bounds.height)) + if effectiveBackButtonRect.contains(point) { + return self.backButtonNode.internalHitTest(self.view.convert(point, to: self.backButtonNode.view), with: event) + } + } + } + + guard let result = super.hitTest(point, with: event) else { + return nil + } + + if result == self.view || result == self.clippingNode.view { + return nil + } + + return result + } } diff --git a/submodules/Display/Display/NavigationButtonNode.swift b/submodules/Display/Display/NavigationButtonNode.swift index 29a6d37f0e..b237e14361 100644 --- a/submodules/Display/Display/NavigationButtonNode.swift +++ b/submodules/Display/Display/NavigationButtonNode.swift @@ -241,7 +241,7 @@ private final class NavigationButtonItemNode: ASTextNode { public override func touchesMoved(_ touches: Set, with event: UIEvent?) { super.touchesMoved(touches, with: event) - self.updateHighlightedState(self.touchInsideApparentBounds(touches.first!), animated: true) + //self.updateHighlightedState(self.touchInsideApparentBounds(touches.first!), animated: true) } public override func touchesEnded(_ touches: Set, with event: UIEvent?) { @@ -251,7 +251,7 @@ private final class NavigationButtonItemNode: ASTextNode { let previousTouchCount = self.touchCount self.touchCount = max(0, self.touchCount - touches.count) - if previousTouchCount != 0 && self.touchCount == 0 && self.isEnabled && self.touchInsideApparentBounds(touches.first!) { + if previousTouchCount != 0 && self.touchCount == 0 && self.isEnabled { self.pressed() } } @@ -455,4 +455,12 @@ public final class NavigationButtonNode: ASDisplayNode { } return totalSize } + + func internalHitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + if self.nodes.count == 1 { + return self.nodes[0].view + } else { + return super.hitTest(point, with: event) + } + } } diff --git a/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift b/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift index a40405c95f..59d93c72ca 100644 --- a/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift +++ b/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift @@ -424,7 +424,7 @@ public final class ItemListPeerItem: ListViewItem, ItemListItem { } } -private let avatarFont = avatarPlaceholderFont(size: 15.0) +private let avatarFont = avatarPlaceholderFont(size: floor(40.0 * 16.0 / 37.0)) private let badgeFont = Font.regular(15.0) public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNode { diff --git a/submodules/NotificationSoundSelectionUI/Sources/NotificationSoundSelection.swift b/submodules/NotificationSoundSelectionUI/Sources/NotificationSoundSelection.swift index 3e01be1a20..5a6806fcf7 100644 --- a/submodules/NotificationSoundSelectionUI/Sources/NotificationSoundSelection.swift +++ b/submodules/NotificationSoundSelectionUI/Sources/NotificationSoundSelection.swift @@ -304,6 +304,9 @@ public func notificationSoundSelectionController(context: AccountContext, isModa playSoundDisposable.dispose() }) controller.enableInteractiveDismiss = true + if isModal { + controller.navigationPresentation = .modal + } completeImpl = { [weak controller] in let sound = stateValue.with { state in diff --git a/submodules/Postbox/Sources/Coding.swift b/submodules/Postbox/Sources/Coding.swift index 0e73649666..e25c870781 100644 --- a/submodules/Postbox/Sources/Coding.swift +++ b/submodules/Postbox/Sources/Coding.swift @@ -77,7 +77,7 @@ public class MemoryBuffer: Equatable, CustomStringConvertible { data.copyBytes(to: self.memory.assumingMemoryBound(to: UInt8.self), count: data.count) self.capacity = data.count self.length = data.count - self.freeWhenDone = false + self.freeWhenDone = true } } diff --git a/submodules/Postbox/Sources/HistoryTagInfoView.swift b/submodules/Postbox/Sources/HistoryTagInfoView.swift new file mode 100644 index 0000000000..4b145600b2 --- /dev/null +++ b/submodules/Postbox/Sources/HistoryTagInfoView.swift @@ -0,0 +1,76 @@ +import Foundation + +final class MutableHistoryTagInfoView: MutablePostboxView { + fileprivate let peerId: PeerId + fileprivate let tag: MessageTags + + fileprivate var currentIndex: MessageIndex? + + init(postbox: Postbox, peerId: PeerId, tag: MessageTags) { + self.peerId = peerId + self.tag = tag + for namespace in postbox.messageHistoryIndexTable.existingNamespaces(peerId: self.peerId) { + if let index = postbox.messageHistoryTagsTable.latestIndex(tag: self.tag, peerId: self.peerId, namespace: namespace) { + self.currentIndex = index + break + } + } + } + + func replay(postbox: Postbox, transaction: PostboxTransaction) -> Bool { + if let operations = transaction.currentOperationsByPeerId[self.peerId] { + var updated = false + var refresh = false + for operation in operations { + switch operation { + case let .InsertMessage(message): + if self.currentIndex == nil { + if message.tags.contains(self.tag) { + self.currentIndex = message.index + updated = true + } + } + case let .Remove(indicesAndTags): + if self.currentIndex != nil { + for (index, tags) in indicesAndTags { + if tags.contains(self.tag) { + if index == self.currentIndex { + self.currentIndex = nil + updated = true + refresh = true + } + } + } + } + default: + break + } + } + + if refresh { + for namespace in postbox.messageHistoryIndexTable.existingNamespaces(peerId: self.peerId) { + if let index = postbox.messageHistoryTagsTable.latestIndex(tag: self.tag, peerId: self.peerId, namespace: namespace) { + self.currentIndex = index + break + } + } + } + + return updated + } else { + return false + } + } + + func immutableView() -> PostboxView { + return HistoryTagInfoView(self) + } +} + +public final class HistoryTagInfoView: PostboxView { + public let isEmpty: Bool + + init(_ view: MutableHistoryTagInfoView) { + self.isEmpty = view.currentIndex == nil + } +} diff --git a/submodules/Postbox/Sources/MessageHistoryTagsTable.swift b/submodules/Postbox/Sources/MessageHistoryTagsTable.swift index 0f4c7f6570..2af930855d 100644 --- a/submodules/Postbox/Sources/MessageHistoryTagsTable.swift +++ b/submodules/Postbox/Sources/MessageHistoryTagsTable.swift @@ -132,6 +132,15 @@ class MessageHistoryTagsTable: Table { return Int(self.valueBox.count(self.table, start: lowerBoundKey, end: upperBoundKey)) } + func latestIndex(tag: MessageTags, peerId: PeerId, namespace: MessageId.Namespace) -> MessageIndex? { + var result: MessageIndex? + self.valueBox.range(self.table, start: self.lowerBound(tag: tag, peerId: peerId, namespace: namespace), end: self.upperBound(tag: tag, peerId: peerId, namespace: namespace), keys: { key in + result = extractKey(key) + return true + }, limit: 1) + return result + } + func findRandomIndex(peerId: PeerId, namespace: MessageId.Namespace, tag: MessageTags, ignoreIds: ([MessageId], Set), isMessage: (MessageIndex) -> Bool) -> MessageIndex? { var indices: [MessageIndex] = [] self.valueBox.range(self.table, start: self.lowerBound(tag: tag, peerId: peerId, namespace: namespace), end: self.upperBound(tag: tag, peerId: peerId, namespace: namespace), keys: { key in diff --git a/submodules/Postbox/Sources/Views.swift b/submodules/Postbox/Sources/Views.swift index 962d0fe2ec..c593c746e7 100644 --- a/submodules/Postbox/Sources/Views.swift +++ b/submodules/Postbox/Sources/Views.swift @@ -28,289 +28,300 @@ public enum PostboxViewKey: Hashable { case peerChatInclusion(PeerId) case basicPeer(PeerId) case allChatListHoles(PeerGroupId) + case historyTagInfo(peerId: PeerId, tag: MessageTags) public var hashValue: Int { switch self { - case .itemCollectionInfos: - return 0 - case .itemCollectionIds: - return 1 - case let .peerChatState(peerId): - return peerId.hashValue - case let .itemCollectionInfo(id): - return id.hashValue - case let .orderedItemList(id): - return id.hashValue - case .preferences: - return 3 - case .globalMessageTags: - return 4 - case let .peer(peerId, _): - return peerId.hashValue - case let .pendingMessageActions(type): - return type.hashValue - case let .invalidatedMessageHistoryTagSummaries(tagMask, namespace): - return tagMask.rawValue.hashValue ^ namespace.hashValue - case let .pendingMessageActionsSummary(type, peerId, namespace): - return type.hashValue ^ peerId.hashValue ^ namespace.hashValue - case let .historyTagSummaryView(tag, peerId, namespace): - return tag.rawValue.hashValue ^ peerId.hashValue ^ namespace.hashValue - case let .cachedPeerData(peerId): - return peerId.hashValue - case .unreadCounts: - return 5 - case .peerNotificationSettings: - return 6 - case .pendingPeerNotificationSettings: - return 7 - case let .messageOfInterestHole(location, namespace, count): - return 8 &+ 31 &* location.hashValue &+ 31 &* namespace.hashValue &+ 31 &* count.hashValue - case let .localMessageTag(tag): - return tag.hashValue - case .messages: - return 10 - case .additionalChatListItems: - return 11 - case let .cachedItem(id): - return id.hashValue - case .peerPresences: - return 13 - case .synchronizeGroupMessageStats: - return 14 - case .peerNotificationSettingsBehaviorTimestampView: - return 15 - case let .peerChatInclusion(peerId): - return peerId.hashValue - case let .basicPeer(peerId): - return peerId.hashValue - case let .allChatListHoles(groupId): - return groupId.hashValue + case .itemCollectionInfos: + return 0 + case .itemCollectionIds: + return 1 + case let .peerChatState(peerId): + return peerId.hashValue + case let .itemCollectionInfo(id): + return id.hashValue + case let .orderedItemList(id): + return id.hashValue + case .preferences: + return 3 + case .globalMessageTags: + return 4 + case let .peer(peerId, _): + return peerId.hashValue + case let .pendingMessageActions(type): + return type.hashValue + case let .invalidatedMessageHistoryTagSummaries(tagMask, namespace): + return tagMask.rawValue.hashValue ^ namespace.hashValue + case let .pendingMessageActionsSummary(type, peerId, namespace): + return type.hashValue ^ peerId.hashValue ^ namespace.hashValue + case let .historyTagSummaryView(tag, peerId, namespace): + return tag.rawValue.hashValue ^ peerId.hashValue ^ namespace.hashValue + case let .cachedPeerData(peerId): + return peerId.hashValue + case .unreadCounts: + return 5 + case .peerNotificationSettings: + return 6 + case .pendingPeerNotificationSettings: + return 7 + case let .messageOfInterestHole(location, namespace, count): + return 8 &+ 31 &* location.hashValue &+ 31 &* namespace.hashValue &+ 31 &* count.hashValue + case let .localMessageTag(tag): + return tag.hashValue + case .messages: + return 10 + case .additionalChatListItems: + return 11 + case let .cachedItem(id): + return id.hashValue + case .peerPresences: + return 13 + case .synchronizeGroupMessageStats: + return 14 + case .peerNotificationSettingsBehaviorTimestampView: + return 15 + case let .peerChatInclusion(peerId): + return peerId.hashValue + case let .basicPeer(peerId): + return peerId.hashValue + case let .allChatListHoles(groupId): + return groupId.hashValue + case let .historyTagInfo(peerId, tag): + return peerId.hashValue ^ tag.hashValue } } public static func ==(lhs: PostboxViewKey, rhs: PostboxViewKey) -> Bool { switch lhs { - case let .itemCollectionInfos(lhsNamespaces): - if case let .itemCollectionInfos(rhsNamespaces) = rhs, lhsNamespaces == rhsNamespaces { - return true - } else { - return false - } - case let .itemCollectionIds(lhsNamespaces): - if case let .itemCollectionIds(rhsNamespaces) = rhs, lhsNamespaces == rhsNamespaces { - return true - } else { - return false - } - case let .itemCollectionInfo(id): - if case .itemCollectionInfo(id) = rhs { - return true - } else { - return false - } - case let .peerChatState(peerId): - if case .peerChatState(peerId) = rhs { - return true - } else { - return false - } - case let .orderedItemList(id): - if case .orderedItemList(id) = rhs { - return true - } else { - return false - } - case let .preferences(lhsKeys): - if case let .preferences(rhsKeys) = rhs, lhsKeys == rhsKeys { - return true - } else { - return false - } - case let .globalMessageTags(globalTag, position, count, _): - if case .globalMessageTags(globalTag, position, count, _) = rhs { - return true - } else { - return false - } - case let .peer(peerId, components): - if case .peer(peerId, components) = rhs { - return true - } else { - return false - } - case let .pendingMessageActions(type): - if case .pendingMessageActions(type) = rhs { - return true - } else { - return false - } - case .invalidatedMessageHistoryTagSummaries: - if case .invalidatedMessageHistoryTagSummaries = rhs { - return true - } else { - return false - } - case let .pendingMessageActionsSummary(type, peerId, namespace): - if case .pendingMessageActionsSummary(type, peerId, namespace) = rhs { - return true - } else { - return false - } - case let .historyTagSummaryView(tag, peerId, namespace): - if case .historyTagSummaryView(tag, peerId, namespace) = rhs { - return true - } else { - return false - } - case let .cachedPeerData(peerId): - if case .cachedPeerData(peerId) = rhs { - return true - } else { - return false - } - case let .unreadCounts(lhsItems): - if case let .unreadCounts(rhsItems) = rhs, lhsItems == rhsItems { - return true - } else { - return false - } - case let .peerNotificationSettings(peerIds): - if case .peerNotificationSettings(peerIds) = rhs { - return true - } else { - return false - } - case .pendingPeerNotificationSettings: - if case .pendingPeerNotificationSettings = rhs { - return true - } else { - return false - } - case let .messageOfInterestHole(peerId, namespace, count): - if case .messageOfInterestHole(peerId, namespace, count) = rhs { - return true - } else { - return false - } - case let .localMessageTag(tag): - if case .localMessageTag(tag) = rhs { - return true - } else { - return false - } - case let .messages(ids): - if case .messages(ids) = rhs { - return true - } else { - return false - } - case .additionalChatListItems: - if case .additionalChatListItems = rhs { - return true - } else { - return false - } - case let .cachedItem(id): - if case .cachedItem(id) = rhs { - return true - } else { - return false - } - case let .peerPresences(ids): - if case .peerPresences(ids) = rhs { - return true - } else { - return false - } - case .synchronizeGroupMessageStats: - if case .synchronizeGroupMessageStats = rhs { - return true - } else { - return false - } - case .peerNotificationSettingsBehaviorTimestampView: - if case .peerNotificationSettingsBehaviorTimestampView = rhs { - return true - } else { - return false - } - case let .peerChatInclusion(id): - if case .peerChatInclusion(id) = rhs { - return true - } else { - return false - } - case let .basicPeer(id): - if case .basicPeer(id) = rhs { - return true - } else { - return false - } - case let .allChatListHoles(groupId): - if case .allChatListHoles(groupId) = rhs { - return true - } else { - return false - } + case let .itemCollectionInfos(lhsNamespaces): + if case let .itemCollectionInfos(rhsNamespaces) = rhs, lhsNamespaces == rhsNamespaces { + return true + } else { + return false + } + case let .itemCollectionIds(lhsNamespaces): + if case let .itemCollectionIds(rhsNamespaces) = rhs, lhsNamespaces == rhsNamespaces { + return true + } else { + return false + } + case let .itemCollectionInfo(id): + if case .itemCollectionInfo(id) = rhs { + return true + } else { + return false + } + case let .peerChatState(peerId): + if case .peerChatState(peerId) = rhs { + return true + } else { + return false + } + case let .orderedItemList(id): + if case .orderedItemList(id) = rhs { + return true + } else { + return false + } + case let .preferences(lhsKeys): + if case let .preferences(rhsKeys) = rhs, lhsKeys == rhsKeys { + return true + } else { + return false + } + case let .globalMessageTags(globalTag, position, count, _): + if case .globalMessageTags(globalTag, position, count, _) = rhs { + return true + } else { + return false + } + case let .peer(peerId, components): + if case .peer(peerId, components) = rhs { + return true + } else { + return false + } + case let .pendingMessageActions(type): + if case .pendingMessageActions(type) = rhs { + return true + } else { + return false + } + case .invalidatedMessageHistoryTagSummaries: + if case .invalidatedMessageHistoryTagSummaries = rhs { + return true + } else { + return false + } + case let .pendingMessageActionsSummary(type, peerId, namespace): + if case .pendingMessageActionsSummary(type, peerId, namespace) = rhs { + return true + } else { + return false + } + case let .historyTagSummaryView(tag, peerId, namespace): + if case .historyTagSummaryView(tag, peerId, namespace) = rhs { + return true + } else { + return false + } + case let .cachedPeerData(peerId): + if case .cachedPeerData(peerId) = rhs { + return true + } else { + return false + } + case let .unreadCounts(lhsItems): + if case let .unreadCounts(rhsItems) = rhs, lhsItems == rhsItems { + return true + } else { + return false + } + case let .peerNotificationSettings(peerIds): + if case .peerNotificationSettings(peerIds) = rhs { + return true + } else { + return false + } + case .pendingPeerNotificationSettings: + if case .pendingPeerNotificationSettings = rhs { + return true + } else { + return false + } + case let .messageOfInterestHole(peerId, namespace, count): + if case .messageOfInterestHole(peerId, namespace, count) = rhs { + return true + } else { + return false + } + case let .localMessageTag(tag): + if case .localMessageTag(tag) = rhs { + return true + } else { + return false + } + case let .messages(ids): + if case .messages(ids) = rhs { + return true + } else { + return false + } + case .additionalChatListItems: + if case .additionalChatListItems = rhs { + return true + } else { + return false + } + case let .cachedItem(id): + if case .cachedItem(id) = rhs { + return true + } else { + return false + } + case let .peerPresences(ids): + if case .peerPresences(ids) = rhs { + return true + } else { + return false + } + case .synchronizeGroupMessageStats: + if case .synchronizeGroupMessageStats = rhs { + return true + } else { + return false + } + case .peerNotificationSettingsBehaviorTimestampView: + if case .peerNotificationSettingsBehaviorTimestampView = rhs { + return true + } else { + return false + } + case let .peerChatInclusion(id): + if case .peerChatInclusion(id) = rhs { + return true + } else { + return false + } + case let .basicPeer(id): + if case .basicPeer(id) = rhs { + return true + } else { + return false + } + case let .allChatListHoles(groupId): + if case .allChatListHoles(groupId) = rhs { + return true + } else { + return false + } + case let .historyTagInfo(peerId, tag): + if case .historyTagInfo(peerId, tag) = rhs { + return true + } else { + return false + } } } } func postboxViewForKey(postbox: Postbox, key: PostboxViewKey) -> MutablePostboxView { switch key { - case let .itemCollectionInfos(namespaces): - return MutableItemCollectionInfosView(postbox: postbox, namespaces: namespaces) - case let .itemCollectionIds(namespaces): - return MutableItemCollectionIdsView(postbox: postbox, namespaces: namespaces) - case let .itemCollectionInfo(id): - return MutableItemCollectionInfoView(postbox: postbox, id: id) - case let .peerChatState(peerId): - return MutablePeerChatStateView(postbox: postbox, peerId: peerId) - case let .orderedItemList(id): - return MutableOrderedItemListView(postbox: postbox, collectionId: id) - case let .preferences(keys): - return MutablePreferencesView(postbox: postbox, keys: keys) - case let .globalMessageTags(globalTag, position, count, groupingPredicate): - return MutableGlobalMessageTagsView(postbox: postbox, globalTag: globalTag, position: position, count: count, groupingPredicate: groupingPredicate) - case let .peer(peerId, components): - return MutablePeerView(postbox: postbox, peerId: peerId, components: components) - case let .pendingMessageActions(type): - return MutablePendingMessageActionsView(postbox: postbox, type: type) - case let .invalidatedMessageHistoryTagSummaries(tagMask, namespace): - return MutableInvalidatedMessageHistoryTagSummariesView(postbox: postbox, tagMask: tagMask, namespace: namespace) - case let .pendingMessageActionsSummary(type, peerId, namespace): - return MutablePendingMessageActionsSummaryView(postbox: postbox, type: type, peerId: peerId, namespace: namespace) - case let .historyTagSummaryView(tag, peerId, namespace): - return MutableMessageHistoryTagSummaryView(postbox: postbox, tag: tag, peerId: peerId, namespace: namespace) - case let .cachedPeerData(peerId): - return MutableCachedPeerDataView(postbox: postbox, peerId: peerId) - case let .unreadCounts(items): - return MutableUnreadMessageCountsView(postbox: postbox, items: items) - case let .peerNotificationSettings(peerIds): - return MutablePeerNotificationSettingsView(postbox: postbox, peerIds: peerIds) - case .pendingPeerNotificationSettings: - return MutablePendingPeerNotificationSettingsView(postbox: postbox) - case let .messageOfInterestHole(location, namespace, count): - return MutableMessageOfInterestHolesView(postbox: postbox, location: location, namespace: namespace, count: count) - case let .localMessageTag(tag): - return MutableLocalMessageTagsView(postbox: postbox, tag: tag) - case let .messages(ids): - return MutableMessagesView(postbox: postbox, ids: ids) - case .additionalChatListItems: - return MutableAdditionalChatListItemsView(postbox: postbox) - case let .cachedItem(id): - return MutableCachedItemView(postbox: postbox, id: id) - case let .peerPresences(ids): - return MutablePeerPresencesView(postbox: postbox, ids: ids) - case .synchronizeGroupMessageStats: - return MutableSynchronizeGroupMessageStatsView(postbox: postbox) - case .peerNotificationSettingsBehaviorTimestampView: - return MutablePeerNotificationSettingsBehaviorTimestampView(postbox: postbox) - case let .peerChatInclusion(peerId): - return MutablePeerChatInclusionView(postbox: postbox, peerId: peerId) - case let .basicPeer(peerId): - return MutableBasicPeerView(postbox: postbox, peerId: peerId) - case let .allChatListHoles(groupId): - return MutableAllChatListHolesView(postbox: postbox, groupId: groupId) + case let .itemCollectionInfos(namespaces): + return MutableItemCollectionInfosView(postbox: postbox, namespaces: namespaces) + case let .itemCollectionIds(namespaces): + return MutableItemCollectionIdsView(postbox: postbox, namespaces: namespaces) + case let .itemCollectionInfo(id): + return MutableItemCollectionInfoView(postbox: postbox, id: id) + case let .peerChatState(peerId): + return MutablePeerChatStateView(postbox: postbox, peerId: peerId) + case let .orderedItemList(id): + return MutableOrderedItemListView(postbox: postbox, collectionId: id) + case let .preferences(keys): + return MutablePreferencesView(postbox: postbox, keys: keys) + case let .globalMessageTags(globalTag, position, count, groupingPredicate): + return MutableGlobalMessageTagsView(postbox: postbox, globalTag: globalTag, position: position, count: count, groupingPredicate: groupingPredicate) + case let .peer(peerId, components): + return MutablePeerView(postbox: postbox, peerId: peerId, components: components) + case let .pendingMessageActions(type): + return MutablePendingMessageActionsView(postbox: postbox, type: type) + case let .invalidatedMessageHistoryTagSummaries(tagMask, namespace): + return MutableInvalidatedMessageHistoryTagSummariesView(postbox: postbox, tagMask: tagMask, namespace: namespace) + case let .pendingMessageActionsSummary(type, peerId, namespace): + return MutablePendingMessageActionsSummaryView(postbox: postbox, type: type, peerId: peerId, namespace: namespace) + case let .historyTagSummaryView(tag, peerId, namespace): + return MutableMessageHistoryTagSummaryView(postbox: postbox, tag: tag, peerId: peerId, namespace: namespace) + case let .cachedPeerData(peerId): + return MutableCachedPeerDataView(postbox: postbox, peerId: peerId) + case let .unreadCounts(items): + return MutableUnreadMessageCountsView(postbox: postbox, items: items) + case let .peerNotificationSettings(peerIds): + return MutablePeerNotificationSettingsView(postbox: postbox, peerIds: peerIds) + case .pendingPeerNotificationSettings: + return MutablePendingPeerNotificationSettingsView(postbox: postbox) + case let .messageOfInterestHole(location, namespace, count): + return MutableMessageOfInterestHolesView(postbox: postbox, location: location, namespace: namespace, count: count) + case let .localMessageTag(tag): + return MutableLocalMessageTagsView(postbox: postbox, tag: tag) + case let .messages(ids): + return MutableMessagesView(postbox: postbox, ids: ids) + case .additionalChatListItems: + return MutableAdditionalChatListItemsView(postbox: postbox) + case let .cachedItem(id): + return MutableCachedItemView(postbox: postbox, id: id) + case let .peerPresences(ids): + return MutablePeerPresencesView(postbox: postbox, ids: ids) + case .synchronizeGroupMessageStats: + return MutableSynchronizeGroupMessageStatsView(postbox: postbox) + case .peerNotificationSettingsBehaviorTimestampView: + return MutablePeerNotificationSettingsBehaviorTimestampView(postbox: postbox) + case let .peerChatInclusion(peerId): + return MutablePeerChatInclusionView(postbox: postbox, peerId: peerId) + case let .basicPeer(peerId): + return MutableBasicPeerView(postbox: postbox, peerId: peerId) + case let .allChatListHoles(groupId): + return MutableAllChatListHolesView(postbox: postbox, groupId: groupId) + case let .historyTagInfo(peerId, tag): + return MutableHistoryTagInfoView(postbox: postbox, peerId: peerId, tag: tag) } } diff --git a/submodules/SearchUI/Sources/SearchDisplayController.swift b/submodules/SearchUI/Sources/SearchDisplayController.swift index fa86bdf81f..66d5fd6e9b 100644 --- a/submodules/SearchUI/Sources/SearchDisplayController.swift +++ b/submodules/SearchUI/Sources/SearchDisplayController.swift @@ -99,7 +99,7 @@ public final class SearchDisplayController { self.contentNode.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: LayoutMetrics(), deviceMetrics: layout.deviceMetrics, intrinsicInsets: layout.intrinsicInsets, safeInsets: layout.safeInsets, statusBarHeight: nil, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), navigationBarHeight: navigationBarFrame.maxY, transition: transition) } - public func activate(insertSubnode: (ASDisplayNode, Bool) -> Void, placeholder: SearchBarPlaceholderNode) { + public func activate(insertSubnode: (ASDisplayNode, Bool) -> Void, placeholder: SearchBarPlaceholderNode?) { guard let (layout, navigationBarHeight) = self.containerLayout else { return } @@ -110,19 +110,20 @@ public final class SearchDisplayController { self.contentNode.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: LayoutMetrics(), deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(), safeInsets: layout.safeInsets, statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), navigationBarHeight: navigationBarHeight, transition: .immediate) - let initialTextBackgroundFrame = placeholder.convert(placeholder.backgroundNode.frame, to: nil) - - let contentNodePosition = self.contentNode.layer.position - var contentNavigationBarHeight = navigationBarHeight if layout.statusBarHeight == nil { contentNavigationBarHeight += 28.0 } - self.contentNode.layer.animatePosition(from: CGPoint(x: contentNodePosition.x, y: contentNodePosition.y + (initialTextBackgroundFrame.maxY + 8.0 - contentNavigationBarHeight)), to: contentNodePosition, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring) - self.contentNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue) - - self.searchBar.placeholderString = placeholder.placeholderString + if let placeholder = placeholder { + let initialTextBackgroundFrame = placeholder.convert(placeholder.backgroundNode.frame, to: nil) + + let contentNodePosition = self.contentNode.layer.position + + self.contentNode.layer.animatePosition(from: CGPoint(x: contentNodePosition.x, y: contentNodePosition.y + (initialTextBackgroundFrame.maxY + 8.0 - contentNavigationBarHeight)), to: contentNodePosition, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring) + self.contentNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue) + self.searchBar.placeholderString = placeholder.placeholderString + } let navigationBarFrame: CGRect switch self.mode { @@ -149,18 +150,26 @@ public final class SearchDisplayController { self.searchBar.layout() self.searchBar.activate() - self.searchBar.animateIn(from: placeholder, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring) + if let placeholder = placeholder { + self.searchBar.animateIn(from: placeholder, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring) + } else { + self.contentNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue) + } } public func deactivate(placeholder: SearchBarPlaceholderNode?, animated: Bool = true) { self.searchBar.deactivate() + let searchBar = self.searchBar if let placeholder = placeholder { - let searchBar = self.searchBar searchBar.transitionOut(to: placeholder, transition: animated ? .animated(duration: 0.5, curve: .spring) : .immediate, completion: { [weak searchBar] in searchBar?.removeFromSupernode() }) + } else { + searchBar.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak searchBar] _ in + searchBar?.removeFromSupernode() + }) } let contentNode = self.contentNode diff --git a/submodules/TelegramCore/Sources/AccountViewTracker.swift b/submodules/TelegramCore/Sources/AccountViewTracker.swift index 23b6ecfb54..77d5c28d65 100644 --- a/submodules/TelegramCore/Sources/AccountViewTracker.swift +++ b/submodules/TelegramCore/Sources/AccountViewTracker.swift @@ -1064,7 +1064,7 @@ public final class AccountViewTracker { } } - public func aroundMessageHistoryViewForLocation(_ chatLocation: ChatLocation, index: MessageHistoryAnchorIndex, anchorIndex: MessageHistoryAnchorIndex, count: Int, fixedCombinedReadStates: MessageHistoryViewReadState?, tagMask: MessageTags? = nil, orderStatistics: MessageHistoryViewOrderStatistics = [], additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { + public func aroundMessageHistoryViewForLocation(_ chatLocation: ChatLocation, index: MessageHistoryAnchorIndex, anchorIndex: MessageHistoryAnchorIndex, count: Int, clipHoles: Bool = true, fixedCombinedReadStates: MessageHistoryViewReadState?, tagMask: MessageTags? = nil, orderStatistics: MessageHistoryViewOrderStatistics = [], additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { if let account = self.account { let inputAnchor: HistoryViewInputAnchor switch index { @@ -1075,7 +1075,7 @@ public final class AccountViewTracker { case let .message(index): inputAnchor = .index(index) } - let signal = account.postbox.aroundMessageHistoryViewForLocation(chatLocation, anchor: inputAnchor, count: count, fixedCombinedReadStates: fixedCombinedReadStates, topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud], tagMask: tagMask, namespaces: .not(Namespaces.Message.allScheduled), orderStatistics: orderStatistics, additionalData: wrappedHistoryViewAdditionalData(chatLocation: chatLocation, additionalData: additionalData)) + let signal = account.postbox.aroundMessageHistoryViewForLocation(chatLocation, anchor: inputAnchor, count: count, clipHoles: clipHoles, fixedCombinedReadStates: fixedCombinedReadStates, topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud], tagMask: tagMask, namespaces: .not(Namespaces.Message.allScheduled), orderStatistics: orderStatistics, additionalData: wrappedHistoryViewAdditionalData(chatLocation: chatLocation, additionalData: additionalData)) return wrappedMessageHistorySignal(chatLocation: chatLocation, signal: signal, addHoleIfNeeded: false) } else { return .never() diff --git a/submodules/TelegramPresentationData/Sources/PresentationStrings.swift b/submodules/TelegramPresentationData/Sources/PresentationStrings.swift index 05eee7ac5d..81d95743ff 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationStrings.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationStrings.swift @@ -239,4739 +239,4746 @@ public final class PresentationStrings: Equatable { public func MediaPicker_Nof(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[49]!, self._r[49]!, [_0]) } - public var EditTheme_Expand_Preview_IncomingReplyName: String { return self._s[50]! } - public var AutoDownloadSettings_MediaTypes: String { return self._s[52]! } - public var Watch_GroupInfo_Title: String { return self._s[53]! } - public var Passport_Identity_AddPersonalDetails: String { return self._s[54]! } - public var Channel_Info_Members: String { return self._s[55]! } - public var LoginPassword_InvalidPasswordError: String { return self._s[57]! } - public var Conversation_LiveLocation: String { return self._s[58]! } - public var Wallet_Month_ShortNovember: String { return self._s[59]! } - public var PrivacyLastSeenSettings_CustomShareSettingsHelp: String { return self._s[60]! } - public var NetworkUsageSettings_BytesReceived: String { return self._s[62]! } - public var Stickers_Search: String { return self._s[64]! } - public var NotificationsSound_Synth: String { return self._s[65]! } - public var LogoutOptions_LogOutInfo: String { return self._s[66]! } + public var ChatState_ConnectingToProxy: String { return self._s[50]! } + public var EditTheme_Expand_Preview_IncomingReplyName: String { return self._s[51]! } + public var AutoDownloadSettings_MediaTypes: String { return self._s[53]! } + public var Watch_GroupInfo_Title: String { return self._s[54]! } + public var Passport_Identity_AddPersonalDetails: String { return self._s[55]! } + public var Channel_Info_Members: String { return self._s[56]! } + public var LoginPassword_InvalidPasswordError: String { return self._s[58]! } + public var Conversation_LiveLocation: String { return self._s[59]! } + public var Wallet_Month_ShortNovember: String { return self._s[60]! } + public var PrivacyLastSeenSettings_CustomShareSettingsHelp: String { return self._s[61]! } + public var NetworkUsageSettings_BytesReceived: String { return self._s[63]! } + public var Stickers_Search: String { return self._s[65]! } + public var NotificationsSound_Synth: String { return self._s[66]! } + public var LogoutOptions_LogOutInfo: String { return self._s[67]! } public func VoiceOver_Chat_ForwardedFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[68]!, self._r[68]!, [_0]) + return formatWithArgumentRanges(self._s[69]!, self._r[69]!, [_0]) } - public var NetworkUsageSettings_MediaAudioDataSection: String { return self._s[69]! } - public var ChatList_Context_HideArchive: String { return self._s[71]! } - public var AutoNightTheme_UseSunsetSunrise: String { return self._s[72]! } - public var FastTwoStepSetup_Title: String { return self._s[73]! } - public var EditTheme_Create_Preview_IncomingReplyText: String { return self._s[74]! } - public var Channel_Info_BlackList: String { return self._s[75]! } - public var Channel_AdminLog_InfoPanelTitle: String { return self._s[76]! } - public var Conversation_OpenFile: String { return self._s[78]! } - public var SecretTimer_ImageDescription: String { return self._s[79]! } - public var StickerSettings_ContextInfo: String { return self._s[80]! } - public var TwoStepAuth_GenericHelp: String { return self._s[82]! } - public var AutoDownloadSettings_Unlimited: String { return self._s[83]! } - public var PrivacyLastSeenSettings_NeverShareWith_Title: String { return self._s[84]! } - public var AutoDownloadSettings_DataUsageHigh: String { return self._s[85]! } + public var NetworkUsageSettings_MediaAudioDataSection: String { return self._s[70]! } + public var ChatList_Context_HideArchive: String { return self._s[72]! } + public var AutoNightTheme_UseSunsetSunrise: String { return self._s[73]! } + public var FastTwoStepSetup_Title: String { return self._s[74]! } + public var EditTheme_Create_Preview_IncomingReplyText: String { return self._s[75]! } + public var Channel_Info_BlackList: String { return self._s[76]! } + public var Channel_AdminLog_InfoPanelTitle: String { return self._s[77]! } + public var Conversation_OpenFile: String { return self._s[79]! } + public var SecretTimer_ImageDescription: String { return self._s[80]! } + public var StickerSettings_ContextInfo: String { return self._s[81]! } + public var TwoStepAuth_GenericHelp: String { return self._s[83]! } + public var AutoDownloadSettings_Unlimited: String { return self._s[84]! } + public var PrivacyLastSeenSettings_NeverShareWith_Title: String { return self._s[85]! } + public var AutoDownloadSettings_DataUsageHigh: String { return self._s[86]! } public func PUSH_CHAT_MESSAGE_VIDEO(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[86]!, self._r[86]!, [_1, _2]) + return formatWithArgumentRanges(self._s[87]!, self._r[87]!, [_1, _2]) } - public var AuthSessions_AddDevice_ScanInfo: String { return self._s[87]! } - public var Notifications_AddExceptionTitle: String { return self._s[88]! } - public var Watch_MessageView_Reply: String { return self._s[89]! } - public var Tour_Text6: String { return self._s[90]! } - public var TwoStepAuth_SetupPasswordEnterPasswordChange: String { return self._s[91]! } + public var AuthSessions_AddDevice_ScanInfo: String { return self._s[88]! } + public var Notifications_AddExceptionTitle: String { return self._s[89]! } + public var Watch_MessageView_Reply: String { return self._s[90]! } + public var Tour_Text6: String { return self._s[91]! } + public var TwoStepAuth_SetupPasswordEnterPasswordChange: String { return self._s[92]! } public func Notification_PinnedAnimationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[92]!, self._r[92]!, [_0]) - } - public func ShareFileTip_Text(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[93]!, self._r[93]!, [_0]) } - public var Wallet_Configuration_BlockchainIdPlaceholder: String { return self._s[94]! } - public var AccessDenied_LocationDenied: String { return self._s[95]! } - public var CallSettings_RecentCalls: String { return self._s[96]! } - public var ConversationProfile_LeaveDeleteAndExit: String { return self._s[97]! } - public var Channel_Members_AddAdminErrorBlacklisted: String { return self._s[99]! } - public var Passport_Authorize: String { return self._s[100]! } - public var StickerPacksSettings_ArchivedMasks_Info: String { return self._s[101]! } - public var AutoDownloadSettings_Videos: String { return self._s[102]! } - public var TwoStepAuth_ReEnterPasswordTitle: String { return self._s[103]! } - public var Wallet_Info_Send: String { return self._s[104]! } - public var AuthSessions_AddDevice_UrlLoginHint: String { return self._s[105]! } - public var Wallet_TransactionInfo_SendGrams: String { return self._s[106]! } - public var Tour_StartButton: String { return self._s[107]! } - public var Watch_AppName: String { return self._s[109]! } - public var StickerPack_ErrorNotFound: String { return self._s[110]! } - public var Channel_Info_Subscribers: String { return self._s[111]! } - public func Channel_AdminLog_MessageGroupPreHistoryVisible(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[112]!, self._r[112]!, [_0]) + public func ShareFileTip_Text(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[94]!, self._r[94]!, [_0]) } - public func DialogList_PinLimitError(_ _0: String) -> (String, [(Int, NSRange)]) { + public var Wallet_Configuration_BlockchainIdPlaceholder: String { return self._s[95]! } + public var AccessDenied_LocationDenied: String { return self._s[96]! } + public var CallSettings_RecentCalls: String { return self._s[97]! } + public var ConversationProfile_LeaveDeleteAndExit: String { return self._s[98]! } + public var Channel_Members_AddAdminErrorBlacklisted: String { return self._s[100]! } + public var Passport_Authorize: String { return self._s[101]! } + public var StickerPacksSettings_ArchivedMasks_Info: String { return self._s[102]! } + public var AutoDownloadSettings_Videos: String { return self._s[103]! } + public var TwoStepAuth_ReEnterPasswordTitle: String { return self._s[104]! } + public var Wallet_Info_Send: String { return self._s[105]! } + public var AuthSessions_AddDevice_UrlLoginHint: String { return self._s[106]! } + public var Wallet_TransactionInfo_SendGrams: String { return self._s[107]! } + public var Tour_StartButton: String { return self._s[108]! } + public var Watch_AppName: String { return self._s[110]! } + public var StickerPack_ErrorNotFound: String { return self._s[111]! } + public var Channel_Info_Subscribers: String { return self._s[112]! } + public func Channel_AdminLog_MessageGroupPreHistoryVisible(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[113]!, self._r[113]!, [_0]) } - public var Appearance_RemoveTheme: String { return self._s[114]! } + public func DialogList_PinLimitError(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[114]!, self._r[114]!, [_0]) + } + public var Appearance_RemoveTheme: String { return self._s[115]! } public func Wallet_Info_TransactionBlockchainFee(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[115]!, self._r[115]!, [_0]) + return formatWithArgumentRanges(self._s[116]!, self._r[116]!, [_0]) } - public var Conversation_StopLiveLocation: String { return self._s[118]! } - public var Channel_AdminLogFilter_EventsAll: String { return self._s[119]! } - public var GroupInfo_InviteLink_CopyAlert_Success: String { return self._s[121]! } - public var Username_LinkCopied: String { return self._s[123]! } - public var GroupRemoved_Title: String { return self._s[124]! } - public var SecretVideo_Title: String { return self._s[125]! } + public var Conversation_StopLiveLocation: String { return self._s[119]! } + public var Channel_AdminLogFilter_EventsAll: String { return self._s[120]! } + public var GroupInfo_InviteLink_CopyAlert_Success: String { return self._s[122]! } + public var Username_LinkCopied: String { return self._s[124]! } + public var GroupRemoved_Title: String { return self._s[125]! } + public var SecretVideo_Title: String { return self._s[126]! } public func PUSH_PINNED_VIDEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[126]!, self._r[126]!, [_1]) + return formatWithArgumentRanges(self._s[127]!, self._r[127]!, [_1]) } - public var AccessDenied_PhotosAndVideos: String { return self._s[127]! } - public var Appearance_ThemePreview_Chat_1_Text: String { return self._s[128]! } + public var AccessDenied_PhotosAndVideos: String { return self._s[128]! } + public var Appearance_ThemePreview_Chat_1_Text: String { return self._s[129]! } public func PUSH_CHANNEL_MESSAGE_GEOLIVE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[130]!, self._r[130]!, [_1]) + return formatWithArgumentRanges(self._s[131]!, self._r[131]!, [_1]) } - public var Map_OpenInGoogleMaps: String { return self._s[132]! } + public var Map_OpenInGoogleMaps: String { return self._s[133]! } public func Time_PreciseDate_m12(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[133]!, self._r[133]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[134]!, self._r[134]!, [_1, _2, _3]) } public func Channel_AdminLog_MessageKickedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[134]!, self._r[134]!, [_1, _2]) + return formatWithArgumentRanges(self._s[135]!, self._r[135]!, [_1, _2]) } - public var Call_StatusRinging: String { return self._s[135]! } - public var SettingsSearch_Synonyms_EditProfile_Username: String { return self._s[136]! } - public var Group_Username_InvalidStartsWithNumber: String { return self._s[137]! } - public var UserInfo_NotificationsEnabled: String { return self._s[138]! } - public var Map_Search: String { return self._s[139]! } - public var ClearCache_StorageFree: String { return self._s[141]! } - public var Login_TermsOfServiceHeader: String { return self._s[142]! } + public var Call_StatusRinging: String { return self._s[136]! } + public var SettingsSearch_Synonyms_EditProfile_Username: String { return self._s[137]! } + public var Group_Username_InvalidStartsWithNumber: String { return self._s[138]! } + public var UserInfo_NotificationsEnabled: String { return self._s[139]! } + public var Map_Search: String { return self._s[140]! } + public var ClearCache_StorageFree: String { return self._s[142]! } + public var Login_TermsOfServiceHeader: String { return self._s[143]! } public func Notification_PinnedVideoMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[143]!, self._r[143]!, [_0]) + return formatWithArgumentRanges(self._s[144]!, self._r[144]!, [_0]) } public func Channel_AdminLog_MessageToggleSignaturesOn(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[145]!, self._r[145]!, [_0]) + return formatWithArgumentRanges(self._s[146]!, self._r[146]!, [_0]) } - public var Wallet_Sent_Title: String { return self._s[146]! } - public var TwoStepAuth_SetupPasswordConfirmPassword: String { return self._s[147]! } - public var Weekday_Today: String { return self._s[148]! } + public var Wallet_Sent_Title: String { return self._s[147]! } + public var TwoStepAuth_SetupPasswordConfirmPassword: String { return self._s[148]! } + public var Weekday_Today: String { return self._s[149]! } public func InstantPage_AuthorAndDateTitle(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[150]!, self._r[150]!, [_1, _2]) + return formatWithArgumentRanges(self._s[151]!, self._r[151]!, [_1, _2]) } public func Conversation_MessageDialogRetryAll(_ _1: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[151]!, self._r[151]!, ["\(_1)"]) + return formatWithArgumentRanges(self._s[152]!, self._r[152]!, ["\(_1)"]) } - public var Notification_PassportValuePersonalDetails: String { return self._s[153]! } - public var Channel_AdminLog_MessagePreviousLink: String { return self._s[154]! } - public var ChangePhoneNumberNumber_NewNumber: String { return self._s[155]! } - public var ApplyLanguage_LanguageNotSupportedError: String { return self._s[156]! } - public var TwoStepAuth_ChangePasswordDescription: String { return self._s[157]! } - public var PhotoEditor_BlurToolLinear: String { return self._s[158]! } - public var Contacts_PermissionsAllowInSettings: String { return self._s[159]! } - public var Weekday_ShortMonday: String { return self._s[160]! } - public var Cache_KeepMedia: String { return self._s[161]! } - public var Passport_FieldIdentitySelfieHelp: String { return self._s[162]! } + public var Notification_PassportValuePersonalDetails: String { return self._s[154]! } + public var Channel_AdminLog_MessagePreviousLink: String { return self._s[155]! } + public var ChangePhoneNumberNumber_NewNumber: String { return self._s[156]! } + public var ApplyLanguage_LanguageNotSupportedError: String { return self._s[157]! } + public var TwoStepAuth_ChangePasswordDescription: String { return self._s[158]! } + public var PhotoEditor_BlurToolLinear: String { return self._s[159]! } + public var Contacts_PermissionsAllowInSettings: String { return self._s[160]! } + public var Weekday_ShortMonday: String { return self._s[161]! } + public var Cache_KeepMedia: String { return self._s[162]! } + public var Passport_FieldIdentitySelfieHelp: String { return self._s[163]! } public func PUSH_PINNED_STICKER(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[163]!, self._r[163]!, [_1, _2]) + return formatWithArgumentRanges(self._s[164]!, self._r[164]!, [_1, _2]) } public func Chat_SlowmodeTooltip(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[164]!, self._r[164]!, [_0]) + return formatWithArgumentRanges(self._s[165]!, self._r[165]!, [_0]) } - public var Wallet_Receive_ShareUrlInfo: String { return self._s[165]! } - public var Conversation_ClousStorageInfo_Description4: String { return self._s[166]! } - public var Wallet_RestoreFailed_Title: String { return self._s[167]! } - public var Passport_Language_ru: String { return self._s[168]! } + public var Wallet_Receive_ShareUrlInfo: String { return self._s[166]! } + public var Conversation_ClousStorageInfo_Description4: String { return self._s[167]! } + public var Wallet_RestoreFailed_Title: String { return self._s[168]! } + public var Passport_Language_ru: String { return self._s[169]! } public func Notification_CreatedChatWithTitle(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[169]!, self._r[169]!, [_0, _1]) + return formatWithArgumentRanges(self._s[170]!, self._r[170]!, [_0, _1]) } - public var WallpaperPreview_PatternIntensity: String { return self._s[170]! } - public var WebBrowser_InAppSafari: String { return self._s[173]! } - public var TwoStepAuth_RecoveryUnavailable: String { return self._s[174]! } - public var EnterPasscode_TouchId: String { return self._s[175]! } - public var PhotoEditor_QualityVeryHigh: String { return self._s[178]! } - public var Checkout_NewCard_SaveInfo: String { return self._s[180]! } - public var Gif_NoGifsPlaceholder: String { return self._s[182]! } + public var WallpaperPreview_PatternIntensity: String { return self._s[171]! } + public var WebBrowser_InAppSafari: String { return self._s[174]! } + public var TwoStepAuth_RecoveryUnavailable: String { return self._s[175]! } + public var EnterPasscode_TouchId: String { return self._s[176]! } + public var PhotoEditor_QualityVeryHigh: String { return self._s[179]! } + public var Checkout_NewCard_SaveInfo: String { return self._s[181]! } + public var Gif_NoGifsPlaceholder: String { return self._s[183]! } public func Notification_InvitedMultiple(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[184]!, self._r[184]!, [_0, _1]) + return formatWithArgumentRanges(self._s[185]!, self._r[185]!, [_0, _1]) } - public var ChatSettings_AutoDownloadEnabled: String { return self._s[185]! } - public var NetworkUsageSettings_BytesSent: String { return self._s[186]! } - public var Checkout_PasswordEntry_Pay: String { return self._s[187]! } - public var AuthSessions_TerminateSession: String { return self._s[188]! } - public var Message_File: String { return self._s[189]! } - public var MediaPicker_VideoMuteDescription: String { return self._s[190]! } - public var SocksProxySetup_ProxyStatusConnected: String { return self._s[191]! } - public var TwoStepAuth_RecoveryCode: String { return self._s[192]! } - public var EnterPasscode_EnterCurrentPasscode: String { return self._s[193]! } + public var ChatSettings_AutoDownloadEnabled: String { return self._s[186]! } + public var NetworkUsageSettings_BytesSent: String { return self._s[187]! } + public var Checkout_PasswordEntry_Pay: String { return self._s[188]! } + public var AuthSessions_TerminateSession: String { return self._s[189]! } + public var Message_File: String { return self._s[190]! } + public var MediaPicker_VideoMuteDescription: String { return self._s[191]! } + public var SocksProxySetup_ProxyStatusConnected: String { return self._s[192]! } + public var TwoStepAuth_RecoveryCode: String { return self._s[193]! } + public var EnterPasscode_EnterCurrentPasscode: String { return self._s[194]! } public func TwoStepAuth_EnterPasswordHint(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[194]!, self._r[194]!, [_0]) - } - public var Conversation_Moderate_Report: String { return self._s[196]! } - public var TwoStepAuth_EmailInvalid: String { return self._s[197]! } - public var Passport_Language_ms: String { return self._s[198]! } - public var Channel_Edit_AboutItem: String { return self._s[200]! } - public var DialogList_SearchSectionGlobal: String { return self._s[204]! } - public var AttachmentMenu_WebSearch: String { return self._s[205]! } - public var PasscodeSettings_TurnPasscodeOn: String { return self._s[206]! } - public var Channel_BanUser_Title: String { return self._s[207]! } - public var WallpaperPreview_SwipeTopText: String { return self._s[208]! } - public var ChatList_DeleteSavedMessagesConfirmationText: String { return self._s[209]! } - public var ArchivedChats_IntroText2: String { return self._s[210]! } - public var Conversation_OpenBotLinkTitle: String { return self._s[211]! } - public var ChatSearch_SearchPlaceholder: String { return self._s[213]! } - public var Notification_Exceptions_DeleteAll: String { return self._s[214]! } - public var Passport_FieldAddressTranslationHelp: String { return self._s[215]! } - public var NotificationsSound_Aurora: String { return self._s[216]! } - public func Channel_AdminLog_MessageTransferedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[217]!, self._r[217]!, [_1, _2]) + return formatWithArgumentRanges(self._s[195]!, self._r[195]!, [_0]) } + public var Conversation_Moderate_Report: String { return self._s[197]! } + public var TwoStepAuth_EmailInvalid: String { return self._s[198]! } + public var Passport_Language_ms: String { return self._s[199]! } + public var Channel_Edit_AboutItem: String { return self._s[201]! } + public var DialogList_SearchSectionGlobal: String { return self._s[205]! } + public var AttachmentMenu_WebSearch: String { return self._s[206]! } + public var ChatState_WaitingForNetwork: String { return self._s[207]! } + public var Channel_BanUser_Title: String { return self._s[208]! } + public var PasscodeSettings_TurnPasscodeOn: String { return self._s[209]! } + public var WallpaperPreview_SwipeTopText: String { return self._s[210]! } + public var ChatList_DeleteSavedMessagesConfirmationText: String { return self._s[211]! } + public var ArchivedChats_IntroText2: String { return self._s[212]! } + public var ChatSearch_SearchPlaceholder: String { return self._s[214]! } + public var Conversation_OpenBotLinkTitle: String { return self._s[215]! } + public var Passport_FieldAddressTranslationHelp: String { return self._s[216]! } + public var NotificationsSound_Aurora: String { return self._s[217]! } + public var Notification_Exceptions_DeleteAll: String { return self._s[218]! } public func FileSize_GB(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[218]!, self._r[218]!, [_0]) + return formatWithArgumentRanges(self._s[219]!, self._r[219]!, [_0]) } - public var AuthSessions_LoggedInWithTelegram: String { return self._s[221]! } + public var AuthSessions_LoggedInWithTelegram: String { return self._s[222]! } public func Privacy_GroupsAndChannels_InviteToGroupError(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[222]!, self._r[222]!, [_0, _1]) + return formatWithArgumentRanges(self._s[223]!, self._r[223]!, [_0, _1]) } - public var Passport_PasswordNext: String { return self._s[223]! } - public var Bot_GroupStatusReadsHistory: String { return self._s[224]! } - public var EmptyGroupInfo_Line2: String { return self._s[225]! } - public var VoiceOver_Chat_SeenByRecipients: String { return self._s[226]! } - public var Settings_FAQ_Intro: String { return self._s[229]! } - public var PrivacySettings_PasscodeAndTouchId: String { return self._s[231]! } - public var FeaturedStickerPacks_Title: String { return self._s[232]! } - public var TwoStepAuth_PasswordRemoveConfirmation: String { return self._s[234]! } - public var Username_Title: String { return self._s[235]! } + public var Passport_PasswordNext: String { return self._s[224]! } + public var Bot_GroupStatusReadsHistory: String { return self._s[225]! } + public var EmptyGroupInfo_Line2: String { return self._s[226]! } + public func Channel_AdminLog_MessageTransferedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[227]!, self._r[227]!, [_1, _2]) + } + public var VoiceOver_Chat_SeenByRecipients: String { return self._s[228]! } + public var Settings_FAQ_Intro: String { return self._s[231]! } + public var PrivacySettings_PasscodeAndTouchId: String { return self._s[233]! } + public var FeaturedStickerPacks_Title: String { return self._s[234]! } + public var TwoStepAuth_PasswordRemoveConfirmation: String { return self._s[236]! } + public var Username_Title: String { return self._s[237]! } public func Message_StickerText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[236]!, self._r[236]!, [_0]) + return formatWithArgumentRanges(self._s[238]!, self._r[238]!, [_0]) } - public var PasscodeSettings_AlphanumericCode: String { return self._s[237]! } - public var Localization_LanguageOther: String { return self._s[238]! } - public var Stickers_SuggestStickers: String { return self._s[239]! } + public var PasscodeSettings_AlphanumericCode: String { return self._s[239]! } + public var Localization_LanguageOther: String { return self._s[240]! } + public var Stickers_SuggestStickers: String { return self._s[241]! } public func Channel_AdminLog_MessageRemovedGroupUsername(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[240]!, self._r[240]!, [_0]) + return formatWithArgumentRanges(self._s[242]!, self._r[242]!, [_0]) } - public var NotificationSettings_ShowNotificationsFromAccountsSection: String { return self._s[241]! } - public var Channel_AdminLogFilter_EventsAdmins: String { return self._s[242]! } - public var Conversation_DefaultRestrictedStickers: String { return self._s[243]! } + public var NotificationSettings_ShowNotificationsFromAccountsSection: String { return self._s[243]! } + public var Channel_AdminLogFilter_EventsAdmins: String { return self._s[244]! } + public var Conversation_DefaultRestrictedStickers: String { return self._s[245]! } public func Notification_PinnedDeletedMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[244]!, self._r[244]!, [_0]) + return formatWithArgumentRanges(self._s[246]!, self._r[246]!, [_0]) } - public var Wallet_TransactionInfo_CopyAddress: String { return self._s[246]! } - public var Group_UpgradeConfirmation: String { return self._s[247]! } - public var DialogList_Unpin: String { return self._s[248]! } - public var Passport_Identity_DateOfBirth: String { return self._s[249]! } - public var Month_ShortOctober: String { return self._s[250]! } - public var SettingsSearch_Synonyms_Privacy_Data_ContactsSync: String { return self._s[251]! } - public var TwoFactorSetup_Done_Text: String { return self._s[252]! } - public var Notification_CallCanceledShort: String { return self._s[253]! } - public var Conversation_StopQuiz: String { return self._s[254]! } - public var Passport_Phone_Help: String { return self._s[255]! } - public var Passport_Language_az: String { return self._s[257]! } - public var CreatePoll_TextPlaceholder: String { return self._s[259]! } - public var VoiceOver_Chat_AnonymousPoll: String { return self._s[260]! } - public var Passport_Identity_DocumentNumber: String { return self._s[261]! } - public var PhotoEditor_CurvesRed: String { return self._s[262]! } - public var PhoneNumberHelp_Alert: String { return self._s[264]! } - public var SocksProxySetup_Port: String { return self._s[265]! } - public var Checkout_PayNone: String { return self._s[266]! } - public var AutoDownloadSettings_WiFi: String { return self._s[267]! } - public var GroupInfo_GroupType: String { return self._s[268]! } - public var StickerSettings_ContextHide: String { return self._s[269]! } - public var Passport_Address_OneOfTypeTemporaryRegistration: String { return self._s[270]! } - public var Group_Setup_HistoryTitle: String { return self._s[272]! } - public var Passport_Identity_FilesUploadNew: String { return self._s[273]! } - public var PasscodeSettings_AutoLock: String { return self._s[274]! } - public var Passport_Title: String { return self._s[275]! } - public var VoiceOver_Chat_ContactPhoneNumber: String { return self._s[276]! } - public var Channel_AdminLogFilter_EventsNewSubscribers: String { return self._s[277]! } - public var GroupPermission_NoSendGifs: String { return self._s[278]! } - public var PrivacySettings_PasscodeOn: String { return self._s[279]! } + public var Wallet_TransactionInfo_CopyAddress: String { return self._s[248]! } + public var Group_UpgradeConfirmation: String { return self._s[249]! } + public var DialogList_Unpin: String { return self._s[250]! } + public var Passport_Identity_DateOfBirth: String { return self._s[251]! } + public var Month_ShortOctober: String { return self._s[252]! } + public var SettingsSearch_Synonyms_Privacy_Data_ContactsSync: String { return self._s[253]! } + public var TwoFactorSetup_Done_Text: String { return self._s[254]! } + public var Notification_CallCanceledShort: String { return self._s[255]! } + public var Conversation_StopQuiz: String { return self._s[256]! } + public var Passport_Phone_Help: String { return self._s[257]! } + public var Passport_Language_az: String { return self._s[259]! } + public var CreatePoll_TextPlaceholder: String { return self._s[261]! } + public var VoiceOver_Chat_AnonymousPoll: String { return self._s[262]! } + public var Passport_Identity_DocumentNumber: String { return self._s[263]! } + public var PhotoEditor_CurvesRed: String { return self._s[264]! } + public var PhoneNumberHelp_Alert: String { return self._s[266]! } + public var SocksProxySetup_Port: String { return self._s[267]! } + public var Checkout_PayNone: String { return self._s[268]! } + public var AutoDownloadSettings_WiFi: String { return self._s[269]! } + public var GroupInfo_GroupType: String { return self._s[270]! } + public var StickerSettings_ContextHide: String { return self._s[271]! } + public var Passport_Address_OneOfTypeTemporaryRegistration: String { return self._s[272]! } + public var Group_Setup_HistoryTitle: String { return self._s[274]! } + public var Passport_Identity_FilesUploadNew: String { return self._s[275]! } + public var PasscodeSettings_AutoLock: String { return self._s[276]! } + public var Passport_Title: String { return self._s[277]! } + public var VoiceOver_Chat_ContactPhoneNumber: String { return self._s[278]! } + public var Channel_AdminLogFilter_EventsNewSubscribers: String { return self._s[279]! } + public var GroupPermission_NoSendGifs: String { return self._s[280]! } + public var PrivacySettings_PasscodeOn: String { return self._s[281]! } public func Conversation_ScheduleMessage_SendTomorrow(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[280]!, self._r[280]!, [_0]) + return formatWithArgumentRanges(self._s[282]!, self._r[282]!, [_0]) } - public var State_WaitingForNetwork: String { return self._s[283]! } + public var State_WaitingForNetwork: String { return self._s[285]! } public func Notification_Invited(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[284]!, self._r[284]!, [_0, _1]) + return formatWithArgumentRanges(self._s[286]!, self._r[286]!, [_0, _1]) } - public var Calls_NotNow: String { return self._s[286]! } + public var Calls_NotNow: String { return self._s[288]! } public func Channel_DiscussionGroup_HeaderSet(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[287]!, self._r[287]!, [_0]) + return formatWithArgumentRanges(self._s[289]!, self._r[289]!, [_0]) } - public var UserInfo_SendMessage: String { return self._s[288]! } - public var TwoStepAuth_PasswordSet: String { return self._s[289]! } - public var Passport_DeleteDocument: String { return self._s[290]! } - public var SocksProxySetup_AddProxyTitle: String { return self._s[291]! } + public var UserInfo_SendMessage: String { return self._s[290]! } + public var TwoStepAuth_PasswordSet: String { return self._s[291]! } + public var Passport_DeleteDocument: String { return self._s[292]! } + public var SocksProxySetup_AddProxyTitle: String { return self._s[293]! } public func PUSH_MESSAGE_VIDEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[292]!, self._r[292]!, [_1]) + return formatWithArgumentRanges(self._s[294]!, self._r[294]!, [_1]) } - public var AuthSessions_AddedDeviceTitle: String { return self._s[293]! } - public var GroupRemoved_Remove: String { return self._s[294]! } - public var Passport_FieldIdentity: String { return self._s[295]! } - public var Group_Setup_TypePrivateHelp: String { return self._s[296]! } - public var Conversation_Processing: String { return self._s[299]! } - public var Wallet_Settings_BackupWallet: String { return self._s[301]! } - public var ChatSettings_AutoPlayAnimations: String { return self._s[302]! } - public var AuthSessions_LogOutApplicationsHelp: String { return self._s[305]! } - public var Forward_ErrorPublicQuizDisabledInChannels: String { return self._s[306]! } - public var Month_GenFebruary: String { return self._s[307]! } - public var Wallet_Send_NetworkErrorTitle: String { return self._s[308]! } + public var AuthSessions_AddedDeviceTitle: String { return self._s[295]! } + public var GroupRemoved_Remove: String { return self._s[296]! } + public var Passport_FieldIdentity: String { return self._s[297]! } + public var Group_Setup_TypePrivateHelp: String { return self._s[298]! } + public var Conversation_Processing: String { return self._s[301]! } + public var Wallet_Settings_BackupWallet: String { return self._s[303]! } + public var ChatSettings_AutoPlayAnimations: String { return self._s[304]! } + public var AuthSessions_LogOutApplicationsHelp: String { return self._s[307]! } + public var Forward_ErrorPublicQuizDisabledInChannels: String { return self._s[308]! } + public var Month_GenFebruary: String { return self._s[309]! } + public var Wallet_Send_NetworkErrorTitle: String { return self._s[310]! } public func Login_InvalidPhoneEmailBody(_ _1: String, _ _2: String, _ _3: String, _ _4: String, _ _5: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[310]!, self._r[310]!, [_1, _2, _3, _4, _5]) + return formatWithArgumentRanges(self._s[312]!, self._r[312]!, [_1, _2, _3, _4, _5]) } - public var Passport_Identity_TypeIdentityCard: String { return self._s[311]! } - public var Wallet_Month_ShortJune: String { return self._s[313]! } - public var AutoDownloadSettings_DataUsageMedium: String { return self._s[314]! } - public var GroupInfo_AddParticipant: String { return self._s[315]! } - public var KeyCommand_SendMessage: String { return self._s[316]! } - public var VoiceOver_Chat_YourContact: String { return self._s[318]! } - public var Map_LiveLocationShowAll: String { return self._s[319]! } - public var WallpaperSearch_ColorOrange: String { return self._s[321]! } - public var Appearance_AppIconDefaultX: String { return self._s[322]! } - public var Checkout_Receipt_Title: String { return self._s[323]! } - public var Group_OwnershipTransfer_ErrorPrivacyRestricted: String { return self._s[324]! } - public var WallpaperPreview_PreviewTopText: String { return self._s[325]! } - public var Message_Contact: String { return self._s[326]! } - public var Call_StatusIncoming: String { return self._s[327]! } - public var Wallet_TransactionInfo_StorageFeeInfo: String { return self._s[328]! } + public var Passport_Identity_TypeIdentityCard: String { return self._s[313]! } + public var Wallet_Month_ShortJune: String { return self._s[315]! } + public var AutoDownloadSettings_DataUsageMedium: String { return self._s[316]! } + public var GroupInfo_AddParticipant: String { return self._s[317]! } + public var KeyCommand_SendMessage: String { return self._s[318]! } + public var VoiceOver_Chat_YourContact: String { return self._s[320]! } + public var Map_LiveLocationShowAll: String { return self._s[321]! } + public var WallpaperSearch_ColorOrange: String { return self._s[323]! } + public var Appearance_AppIconDefaultX: String { return self._s[324]! } + public var Checkout_Receipt_Title: String { return self._s[325]! } + public var Group_OwnershipTransfer_ErrorPrivacyRestricted: String { return self._s[326]! } + public var WallpaperPreview_PreviewTopText: String { return self._s[327]! } + public var Message_Contact: String { return self._s[328]! } + public var Call_StatusIncoming: String { return self._s[329]! } + public var Wallet_TransactionInfo_StorageFeeInfo: String { return self._s[330]! } public func Channel_AdminLog_MessageKickedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[329]!, self._r[329]!, [_1]) - } - public func PUSH_ENCRYPTED_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[331]!, self._r[331]!, [_1]) } - public var VoiceOver_Media_PlaybackRate: String { return self._s[332]! } - public var Passport_FieldIdentityDetailsHelp: String { return self._s[333]! } - public var Conversation_ViewChannel: String { return self._s[334]! } + public func PUSH_ENCRYPTED_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[333]!, self._r[333]!, [_1]) + } + public var VoiceOver_Media_PlaybackRate: String { return self._s[334]! } + public var Passport_FieldIdentityDetailsHelp: String { return self._s[335]! } + public var Conversation_ViewChannel: String { return self._s[336]! } public func Time_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[335]!, self._r[335]!, [_0]) + return formatWithArgumentRanges(self._s[337]!, self._r[337]!, [_0]) } - public var Theme_Colors_Accent: String { return self._s[336]! } - public var Passport_Language_nl: String { return self._s[338]! } - public var Camera_Retake: String { return self._s[339]! } + public var Theme_Colors_Accent: String { return self._s[338]! } + public var Passport_Language_nl: String { return self._s[340]! } + public var Camera_Retake: String { return self._s[341]! } public func UserInfo_BlockActionTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[340]!, self._r[340]!, [_0]) + return formatWithArgumentRanges(self._s[342]!, self._r[342]!, [_0]) } - public var AuthSessions_LogOutApplications: String { return self._s[341]! } - public var ApplyLanguage_ApplySuccess: String { return self._s[342]! } - public var Tour_Title6: String { return self._s[343]! } - public var Map_ChooseAPlace: String { return self._s[344]! } - public var CallSettings_Never: String { return self._s[346]! } + public var AuthSessions_LogOutApplications: String { return self._s[343]! } + public var ApplyLanguage_ApplySuccess: String { return self._s[344]! } + public var Tour_Title6: String { return self._s[345]! } + public var Map_ChooseAPlace: String { return self._s[346]! } + public var CallSettings_Never: String { return self._s[348]! } public func Notification_ChangedGroupPhoto(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[347]!, self._r[347]!, [_0]) - } - public var ChannelRemoved_RemoveInfo: String { return self._s[348]! } - public func AutoDownloadSettings_PreloadVideoInfo(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[349]!, self._r[349]!, [_0]) } - public var SettingsSearch_Synonyms_Notifications_MessageNotificationsExceptions: String { return self._s[350]! } - public func Conversation_ClearChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { + public var ChannelRemoved_RemoveInfo: String { return self._s[350]! } + public func AutoDownloadSettings_PreloadVideoInfo(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[351]!, self._r[351]!, [_0]) } - public var GroupInfo_InviteLink_Title: String { return self._s[352]! } + public var SettingsSearch_Synonyms_Notifications_MessageNotificationsExceptions: String { return self._s[352]! } + public func Conversation_ClearChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[353]!, self._r[353]!, [_0]) + } + public var GroupInfo_InviteLink_Title: String { return self._s[354]! } public func Channel_AdminLog_MessageUnkickedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[353]!, self._r[353]!, [_1, _2]) + return formatWithArgumentRanges(self._s[355]!, self._r[355]!, [_1, _2]) } - public var KeyCommand_ScrollUp: String { return self._s[354]! } - public var ContactInfo_URLLabelHomepage: String { return self._s[355]! } - public var Channel_OwnershipTransfer_ChangeOwner: String { return self._s[356]! } + public var KeyCommand_ScrollUp: String { return self._s[356]! } + public var ContactInfo_URLLabelHomepage: String { return self._s[357]! } + public var Channel_OwnershipTransfer_ChangeOwner: String { return self._s[358]! } public func Channel_AdminLog_DisabledSlowmode(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[357]!, self._r[357]!, [_0]) - } - public var TwoFactorSetup_Done_Title: String { return self._s[358]! } - public func Conversation_EncryptedPlaceholderTitleOutgoing(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[359]!, self._r[359]!, [_0]) } - public var CallFeedback_ReasonDistortedSpeech: String { return self._s[360]! } - public var Watch_LastSeen_WithinAWeek: String { return self._s[361]! } - public var ContactList_Context_SendMessage: String { return self._s[363]! } - public var Weekday_Tuesday: String { return self._s[364]! } - public var Wallet_Created_Title: String { return self._s[366]! } - public var ScheduledMessages_Delete: String { return self._s[367]! } - public var UserInfo_StartSecretChat: String { return self._s[368]! } - public var Passport_Identity_FilesTitle: String { return self._s[369]! } - public var Permissions_NotificationsAllow_v0: String { return self._s[370]! } - public var DialogList_DeleteConversationConfirmation: String { return self._s[372]! } - public var ChatList_UndoArchiveRevealedTitle: String { return self._s[373]! } + public var TwoFactorSetup_Done_Title: String { return self._s[360]! } + public func Conversation_EncryptedPlaceholderTitleOutgoing(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[361]!, self._r[361]!, [_0]) + } + public var CallFeedback_ReasonDistortedSpeech: String { return self._s[362]! } + public var Watch_LastSeen_WithinAWeek: String { return self._s[363]! } + public var ContactList_Context_SendMessage: String { return self._s[365]! } + public var Weekday_Tuesday: String { return self._s[366]! } + public var Wallet_Created_Title: String { return self._s[368]! } + public var ScheduledMessages_Delete: String { return self._s[369]! } + public var UserInfo_StartSecretChat: String { return self._s[370]! } + public var Passport_Identity_FilesTitle: String { return self._s[371]! } + public var Permissions_NotificationsAllow_v0: String { return self._s[372]! } + public var DialogList_DeleteConversationConfirmation: String { return self._s[374]! } + public var ChatList_UndoArchiveRevealedTitle: String { return self._s[375]! } public func Wallet_Configuration_ApplyErrorTextURLUnreachable(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[374]!, self._r[374]!, [_0]) + return formatWithArgumentRanges(self._s[376]!, self._r[376]!, [_0]) } - public var AuthSessions_Sessions: String { return self._s[375]! } + public var AuthSessions_Sessions: String { return self._s[377]! } public func Settings_KeepPhoneNumber(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[377]!, self._r[377]!, [_0]) + return formatWithArgumentRanges(self._s[379]!, self._r[379]!, [_0]) } - public var TwoStepAuth_RecoveryEmailChangeDescription: String { return self._s[378]! } - public var Call_StatusWaiting: String { return self._s[379]! } - public var CreateGroup_SoftUserLimitAlert: String { return self._s[380]! } - public var FastTwoStepSetup_HintHelp: String { return self._s[381]! } - public var WallpaperPreview_CustomColorBottomText: String { return self._s[382]! } - public var EditTheme_Expand_Preview_OutgoingText: String { return self._s[383]! } - public var LogoutOptions_AddAccountText: String { return self._s[384]! } - public var PasscodeSettings_6DigitCode: String { return self._s[385]! } - public var Settings_LogoutConfirmationText: String { return self._s[386]! } - public var Passport_Identity_TypePassport: String { return self._s[388]! } - public var Map_Work: String { return self._s[391]! } + public var TwoStepAuth_RecoveryEmailChangeDescription: String { return self._s[380]! } + public var Call_StatusWaiting: String { return self._s[381]! } + public var CreateGroup_SoftUserLimitAlert: String { return self._s[382]! } + public var FastTwoStepSetup_HintHelp: String { return self._s[383]! } + public var WallpaperPreview_CustomColorBottomText: String { return self._s[384]! } + public var EditTheme_Expand_Preview_OutgoingText: String { return self._s[385]! } + public var LogoutOptions_AddAccountText: String { return self._s[386]! } + public var PasscodeSettings_6DigitCode: String { return self._s[387]! } + public var Settings_LogoutConfirmationText: String { return self._s[388]! } + public var Passport_Identity_TypePassport: String { return self._s[390]! } + public var Map_Work: String { return self._s[393]! } public func PUSH_MESSAGE_VIDEOS(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[392]!, self._r[392]!, [_1, _2]) + return formatWithArgumentRanges(self._s[394]!, self._r[394]!, [_1, _2]) } - public var SocksProxySetup_SaveProxy: String { return self._s[393]! } - public var AccessDenied_SaveMedia: String { return self._s[394]! } - public var Checkout_ErrorInvoiceAlreadyPaid: String { return self._s[396]! } - public var CreatePoll_MultipleChoice: String { return self._s[397]! } - public var Settings_Title: String { return self._s[399]! } - public var VoiceOver_Chat_RecordModeVideoMessageInfo: String { return self._s[400]! } - public var Contacts_InviteSearchLabel: String { return self._s[402]! } - public var PrivacySettings_WebSessions: String { return self._s[403]! } - public var ConvertToSupergroup_Title: String { return self._s[404]! } + public var SocksProxySetup_SaveProxy: String { return self._s[395]! } + public var AccessDenied_SaveMedia: String { return self._s[396]! } + public var Checkout_ErrorInvoiceAlreadyPaid: String { return self._s[398]! } + public var CreatePoll_MultipleChoice: String { return self._s[399]! } + public var Settings_Title: String { return self._s[401]! } + public var VoiceOver_Chat_RecordModeVideoMessageInfo: String { return self._s[402]! } + public var Contacts_InviteSearchLabel: String { return self._s[404]! } + public var PrivacySettings_WebSessions: String { return self._s[405]! } + public var ConvertToSupergroup_Title: String { return self._s[406]! } public func Channel_AdminLog_CaptionEdited(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[405]!, self._r[405]!, [_0]) + return formatWithArgumentRanges(self._s[407]!, self._r[407]!, [_0]) } - public var TwoFactorSetup_Hint_Text: String { return self._s[406]! } - public var InfoPlist_NSSiriUsageDescription: String { return self._s[407]! } + public var TwoFactorSetup_Hint_Text: String { return self._s[408]! } + public var InfoPlist_NSSiriUsageDescription: String { return self._s[409]! } public func PUSH_MESSAGE_CHANNEL_MESSAGE_GAME_SCORE(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[408]!, self._r[408]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[410]!, self._r[410]!, [_1, _2, _3]) } - public var ChatSettings_AutomaticPhotoDownload: String { return self._s[409]! } - public var UserInfo_BotHelp: String { return self._s[410]! } - public var PrivacySettings_LastSeenEverybody: String { return self._s[411]! } - public var Checkout_Name: String { return self._s[412]! } - public var AutoDownloadSettings_DataUsage: String { return self._s[413]! } - public var Channel_BanUser_BlockFor: String { return self._s[414]! } - public var Checkout_ShippingAddress: String { return self._s[415]! } - public var AutoDownloadSettings_MaxVideoSize: String { return self._s[416]! } - public var Privacy_PaymentsClearInfoDoneHelp: String { return self._s[417]! } - public var Privacy_Forwards: String { return self._s[418]! } - public var Channel_BanUser_PermissionSendPolls: String { return self._s[419]! } - public var Appearance_ThemeCarouselNewNight: String { return self._s[420]! } + public var ChatSettings_AutomaticPhotoDownload: String { return self._s[411]! } + public var UserInfo_BotHelp: String { return self._s[412]! } + public var PrivacySettings_LastSeenEverybody: String { return self._s[413]! } + public var Checkout_Name: String { return self._s[414]! } + public var AutoDownloadSettings_DataUsage: String { return self._s[415]! } + public var Channel_BanUser_BlockFor: String { return self._s[416]! } + public var Checkout_ShippingAddress: String { return self._s[417]! } + public var AutoDownloadSettings_MaxVideoSize: String { return self._s[418]! } + public var Privacy_PaymentsClearInfoDoneHelp: String { return self._s[419]! } + public var Privacy_Forwards: String { return self._s[420]! } + public var Channel_BanUser_PermissionSendPolls: String { return self._s[421]! } + public var Appearance_ThemeCarouselNewNight: String { return self._s[422]! } public func SecretVideo_NotViewedYet(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[423]!, self._r[423]!, [_0]) + return formatWithArgumentRanges(self._s[425]!, self._r[425]!, [_0]) } - public var Contacts_SortedByName: String { return self._s[424]! } - public var Group_OwnershipTransfer_Title: String { return self._s[425]! } - public var VoiceOver_Chat_OpenHint: String { return self._s[427]! } - public var Group_LeaveGroup: String { return self._s[428]! } - public var Settings_UsernameEmpty: String { return self._s[429]! } + public var Contacts_SortedByName: String { return self._s[426]! } + public var Group_OwnershipTransfer_Title: String { return self._s[427]! } + public var VoiceOver_Chat_OpenHint: String { return self._s[429]! } + public var Group_LeaveGroup: String { return self._s[430]! } + public var Settings_UsernameEmpty: String { return self._s[431]! } public func Notification_PinnedPollMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[430]!, self._r[430]!, [_0]) + return formatWithArgumentRanges(self._s[432]!, self._r[432]!, [_0]) } public func TwoStepAuth_ConfirmEmailDescription(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[431]!, self._r[431]!, [_1]) + return formatWithArgumentRanges(self._s[433]!, self._r[433]!, [_1]) } public func Channel_OwnershipTransfer_DescriptionInfo(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[432]!, self._r[432]!, [_1, _2]) + return formatWithArgumentRanges(self._s[434]!, self._r[434]!, [_1, _2]) } - public var Message_ImageExpired: String { return self._s[433]! } - public var TwoStepAuth_RecoveryFailed: String { return self._s[435]! } - public var EditTheme_Edit_Preview_OutgoingText: String { return self._s[436]! } - public var UserInfo_AddToExisting: String { return self._s[437]! } - public var TwoStepAuth_EnabledSuccess: String { return self._s[438]! } - public var Wallet_Send_SyncInProgress: String { return self._s[439]! } - public var SettingsSearch_Synonyms_Appearance_ChatBackground_SetColor: String { return self._s[440]! } + public var Message_ImageExpired: String { return self._s[435]! } + public var TwoStepAuth_RecoveryFailed: String { return self._s[437]! } + public var EditTheme_Edit_Preview_OutgoingText: String { return self._s[438]! } + public var UserInfo_AddToExisting: String { return self._s[439]! } + public var TwoStepAuth_EnabledSuccess: String { return self._s[440]! } + public var Wallet_Send_SyncInProgress: String { return self._s[441]! } + public var SettingsSearch_Synonyms_Appearance_ChatBackground_SetColor: String { return self._s[442]! } public func PUSH_CHANNEL_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[441]!, self._r[441]!, [_1]) + return formatWithArgumentRanges(self._s[443]!, self._r[443]!, [_1]) } - public var Notifications_GroupNotificationsAlert: String { return self._s[442]! } - public var Passport_Language_km: String { return self._s[443]! } - public var SocksProxySetup_AdNoticeHelp: String { return self._s[445]! } - public var VoiceOver_Media_PlaybackPlay: String { return self._s[446]! } - public var Notification_CallMissedShort: String { return self._s[447]! } - public var Wallet_Info_YourBalance: String { return self._s[448]! } - public var ReportPeer_ReasonOther_Send: String { return self._s[449]! } - public var Watch_Compose_Send: String { return self._s[450]! } - public var Passport_Identity_TypeInternalPassportUploadScan: String { return self._s[453]! } - public var TwoFactorSetup_Email_Action: String { return self._s[454]! } - public var Conversation_HoldForVideo: String { return self._s[455]! } - public var Wallet_Configuration_ApplyErrorTextURLInvalidData: String { return self._s[456]! } - public var AuthSessions_OtherDevices: String { return self._s[457]! } - public var Wallet_TransactionInfo_CommentHeader: String { return self._s[458]! } - public var CheckoutInfo_ErrorCityInvalid: String { return self._s[460]! } - public var Appearance_AutoNightThemeDisabled: String { return self._s[462]! } - public var Channel_LinkItem: String { return self._s[463]! } + public var Notifications_GroupNotificationsAlert: String { return self._s[444]! } + public var Passport_Language_km: String { return self._s[445]! } + public var SocksProxySetup_AdNoticeHelp: String { return self._s[447]! } + public var VoiceOver_Media_PlaybackPlay: String { return self._s[448]! } + public var Notification_CallMissedShort: String { return self._s[449]! } + public var Wallet_Info_YourBalance: String { return self._s[450]! } + public var ReportPeer_ReasonOther_Send: String { return self._s[451]! } + public var Watch_Compose_Send: String { return self._s[452]! } + public var Passport_Identity_TypeInternalPassportUploadScan: String { return self._s[455]! } + public var TwoFactorSetup_Email_Action: String { return self._s[456]! } + public var Conversation_HoldForVideo: String { return self._s[457]! } + public var Wallet_Configuration_ApplyErrorTextURLInvalidData: String { return self._s[458]! } + public var AuthSessions_OtherDevices: String { return self._s[459]! } + public var Wallet_TransactionInfo_CommentHeader: String { return self._s[460]! } + public var CheckoutInfo_ErrorCityInvalid: String { return self._s[462]! } + public var Appearance_AutoNightThemeDisabled: String { return self._s[464]! } + public var Channel_LinkItem: String { return self._s[465]! } public func PrivacySettings_LastSeenContactsMinusPlus(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[464]!, self._r[464]!, [_0, _1]) + return formatWithArgumentRanges(self._s[466]!, self._r[466]!, [_0, _1]) } public func Passport_Identity_NativeNameTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[467]!, self._r[467]!, [_0]) + return formatWithArgumentRanges(self._s[469]!, self._r[469]!, [_0]) } - public var VoiceOver_Recording_StopAndPreview: String { return self._s[468]! } - public var Passport_Language_dv: String { return self._s[469]! } - public var Undo_LeftChannel: String { return self._s[470]! } - public var Notifications_ExceptionsMuted: String { return self._s[471]! } - public var ChatList_UnhideAction: String { return self._s[472]! } - public var Conversation_ContextMenuShare: String { return self._s[473]! } - public var Conversation_ContextMenuStickerPackInfo: String { return self._s[474]! } - public var ShareFileTip_Title: String { return self._s[475]! } - public var NotificationsSound_Chord: String { return self._s[476]! } - public var Wallet_TransactionInfo_OtherFeeHeader: String { return self._s[477]! } + public var VoiceOver_Recording_StopAndPreview: String { return self._s[470]! } + public var Passport_Language_dv: String { return self._s[471]! } + public var Undo_LeftChannel: String { return self._s[472]! } + public var Notifications_ExceptionsMuted: String { return self._s[473]! } + public var ChatList_UnhideAction: String { return self._s[474]! } + public var Conversation_ContextMenuShare: String { return self._s[475]! } + public var Conversation_ContextMenuStickerPackInfo: String { return self._s[476]! } + public var ShareFileTip_Title: String { return self._s[477]! } + public var NotificationsSound_Chord: String { return self._s[478]! } + public var Wallet_TransactionInfo_OtherFeeHeader: String { return self._s[479]! } public func PUSH_CHAT_RETURNED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[478]!, self._r[478]!, [_1, _2]) + return formatWithArgumentRanges(self._s[480]!, self._r[480]!, [_1, _2]) } - public var Passport_Address_EditTemporaryRegistration: String { return self._s[479]! } + public var Passport_Address_EditTemporaryRegistration: String { return self._s[481]! } public func Notification_Joined(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[480]!, self._r[480]!, [_0]) + return formatWithArgumentRanges(self._s[482]!, self._r[482]!, [_0]) } public func Wallet_Time_PreciseDate_m3(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[481]!, self._r[481]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[483]!, self._r[483]!, [_1, _2, _3]) } - public var Wallet_Settings_ConfigurationInfo: String { return self._s[482]! } - public var Wallpaper_ErrorNotFound: String { return self._s[483]! } - public var Notification_CallOutgoingShort: String { return self._s[485]! } - public var Wallet_WordImport_IncorrectText: String { return self._s[486]! } + public var Wallet_Settings_ConfigurationInfo: String { return self._s[484]! } + public var Wallpaper_ErrorNotFound: String { return self._s[485]! } + public var Notification_CallOutgoingShort: String { return self._s[487]! } + public var Wallet_WordImport_IncorrectText: String { return self._s[488]! } public func Watch_Time_ShortFullAt(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[487]!, self._r[487]!, [_1, _2]) + return formatWithArgumentRanges(self._s[489]!, self._r[489]!, [_1, _2]) } - public var Passport_Address_TypeUtilityBill: String { return self._s[488]! } - public var Privacy_Forwards_LinkIfAllowed: String { return self._s[489]! } - public var ReportPeer_Report: String { return self._s[490]! } - public var SettingsSearch_Synonyms_Proxy_Title: String { return self._s[491]! } - public var GroupInfo_DeactivatedStatus: String { return self._s[492]! } + public var Passport_Address_TypeUtilityBill: String { return self._s[490]! } + public var Privacy_Forwards_LinkIfAllowed: String { return self._s[491]! } + public var ReportPeer_Report: String { return self._s[492]! } + public var SettingsSearch_Synonyms_Proxy_Title: String { return self._s[493]! } + public var GroupInfo_DeactivatedStatus: String { return self._s[494]! } public func VoiceOver_Chat_MusicTitle(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[493]!, self._r[493]!, [_1, _2]) + return formatWithArgumentRanges(self._s[495]!, self._r[495]!, [_1, _2]) } - public var StickerPack_Send: String { return self._s[494]! } - public var Login_CodeSentInternal: String { return self._s[495]! } - public var Wallet_Month_GenJanuary: String { return self._s[496]! } - public var GroupInfo_InviteLink_LinkSection: String { return self._s[497]! } + public var StickerPack_Send: String { return self._s[496]! } + public var Login_CodeSentInternal: String { return self._s[497]! } + public var Wallet_Month_GenJanuary: String { return self._s[498]! } + public var GroupInfo_InviteLink_LinkSection: String { return self._s[499]! } public func Channel_AdminLog_MessageDeleted(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[498]!, self._r[498]!, [_0]) - } - public func Conversation_EncryptionWaiting(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[500]!, self._r[500]!, [_0]) } - public var Channel_BanUser_PermissionSendStickersAndGifs: String { return self._s[501]! } - public func PUSH_PINNED_GAME(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[502]!, self._r[502]!, [_1]) + public func Conversation_EncryptionWaiting(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[502]!, self._r[502]!, [_0]) } - public var ReportPeer_ReasonViolence: String { return self._s[504]! } - public var Appearance_ShareThemeColor: String { return self._s[505]! } - public var Map_Locating: String { return self._s[506]! } + public var Channel_BanUser_PermissionSendStickersAndGifs: String { return self._s[503]! } + public func PUSH_PINNED_GAME(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[504]!, self._r[504]!, [_1]) + } + public var ReportPeer_ReasonViolence: String { return self._s[506]! } + public var Appearance_ShareThemeColor: String { return self._s[507]! } + public var Map_Locating: String { return self._s[508]! } public func VoiceOver_Chat_VideoFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[507]!, self._r[507]!, [_0]) + return formatWithArgumentRanges(self._s[509]!, self._r[509]!, [_0]) } public func PUSH_ALBUM(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[508]!, self._r[508]!, [_1]) + return formatWithArgumentRanges(self._s[510]!, self._r[510]!, [_1]) } - public var AutoDownloadSettings_GroupChats: String { return self._s[510]! } - public var CheckoutInfo_SaveInfo: String { return self._s[511]! } - public var SharedMedia_EmptyLinksText: String { return self._s[513]! } - public var Passport_Address_CityPlaceholder: String { return self._s[514]! } - public var CheckoutInfo_ErrorStateInvalid: String { return self._s[515]! } - public var Privacy_ProfilePhoto_CustomHelp: String { return self._s[516]! } - public var Wallet_Send_OwnAddressAlertTitle: String { return self._s[518]! } - public var Channel_AdminLog_CanAddAdmins: String { return self._s[519]! } + public var AutoDownloadSettings_GroupChats: String { return self._s[512]! } + public var CheckoutInfo_SaveInfo: String { return self._s[513]! } + public var SharedMedia_EmptyLinksText: String { return self._s[515]! } + public var Passport_Address_CityPlaceholder: String { return self._s[516]! } + public var CheckoutInfo_ErrorStateInvalid: String { return self._s[517]! } + public var Privacy_ProfilePhoto_CustomHelp: String { return self._s[518]! } + public var Wallet_Send_OwnAddressAlertTitle: String { return self._s[520]! } + public var Channel_AdminLog_CanAddAdmins: String { return self._s[521]! } public func PUSH_CHANNEL_MESSAGE_FWD(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[520]!, self._r[520]!, [_1]) + return formatWithArgumentRanges(self._s[522]!, self._r[522]!, [_1]) } public func Time_MonthOfYear_m8(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[521]!, self._r[521]!, [_0]) + return formatWithArgumentRanges(self._s[523]!, self._r[523]!, [_0]) } - public var InfoPlist_NSLocationWhenInUseUsageDescription: String { return self._s[522]! } - public var GroupInfo_InviteLink_RevokeAlert_Success: String { return self._s[523]! } - public var ChangePhoneNumberCode_Code: String { return self._s[524]! } - public var Appearance_CreateTheme: String { return self._s[525]! } + public var InfoPlist_NSLocationWhenInUseUsageDescription: String { return self._s[524]! } + public var GroupInfo_InviteLink_RevokeAlert_Success: String { return self._s[525]! } + public var ChangePhoneNumberCode_Code: String { return self._s[526]! } + public var Appearance_CreateTheme: String { return self._s[527]! } public func UserInfo_NotificationsDefaultSound(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[526]!, self._r[526]!, [_0]) + return formatWithArgumentRanges(self._s[528]!, self._r[528]!, [_0]) } - public var TwoStepAuth_SetupEmail: String { return self._s[527]! } - public var HashtagSearch_AllChats: String { return self._s[528]! } - public var MediaPlayer_UnknownTrack: String { return self._s[529]! } - public var SettingsSearch_Synonyms_Data_AutoDownloadUsingCellular: String { return self._s[531]! } + public var TwoStepAuth_SetupEmail: String { return self._s[529]! } + public var HashtagSearch_AllChats: String { return self._s[530]! } + public var MediaPlayer_UnknownTrack: String { return self._s[531]! } + public var SettingsSearch_Synonyms_Data_AutoDownloadUsingCellular: String { return self._s[533]! } public func ChatList_DeleteForEveryone(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[532]!, self._r[532]!, [_0]) + return formatWithArgumentRanges(self._s[534]!, self._r[534]!, [_0]) } - public var PhotoEditor_QualityHigh: String { return self._s[534]! } + public var PhotoEditor_QualityHigh: String { return self._s[536]! } public func Passport_Phone_UseTelegramNumber(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[535]!, self._r[535]!, [_0]) + return formatWithArgumentRanges(self._s[537]!, self._r[537]!, [_0]) } - public var ApplyLanguage_ApplyLanguageAction: String { return self._s[536]! } - public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsPreview: String { return self._s[537]! } - public var Message_LiveLocation: String { return self._s[538]! } - public var Cache_LowDiskSpaceText: String { return self._s[539]! } - public var Wallet_Receive_ShareAddress: String { return self._s[540]! } - public var EditTheme_ErrorLinkTaken: String { return self._s[541]! } - public var Conversation_SendMessage: String { return self._s[542]! } - public var AuthSessions_EmptyTitle: String { return self._s[543]! } - public var Privacy_PhoneNumber: String { return self._s[544]! } - public var PeopleNearby_CreateGroup: String { return self._s[545]! } - public var CallSettings_UseLessData: String { return self._s[546]! } - public var NetworkUsageSettings_MediaDocumentDataSection: String { return self._s[547]! } - public var Stickers_AddToFavorites: String { return self._s[548]! } - public var Wallet_WordImport_Title: String { return self._s[549]! } - public var PhotoEditor_QualityLow: String { return self._s[550]! } - public var Watch_UserInfo_Unblock: String { return self._s[551]! } - public var Settings_Logout: String { return self._s[552]! } + public var ApplyLanguage_ApplyLanguageAction: String { return self._s[538]! } + public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsPreview: String { return self._s[539]! } + public var Message_LiveLocation: String { return self._s[540]! } + public var Cache_LowDiskSpaceText: String { return self._s[541]! } + public var Wallet_Receive_ShareAddress: String { return self._s[542]! } + public var EditTheme_ErrorLinkTaken: String { return self._s[543]! } + public var Conversation_SendMessage: String { return self._s[544]! } + public var AuthSessions_EmptyTitle: String { return self._s[545]! } + public var Privacy_PhoneNumber: String { return self._s[546]! } + public var PeopleNearby_CreateGroup: String { return self._s[547]! } + public var CallSettings_UseLessData: String { return self._s[548]! } + public var NetworkUsageSettings_MediaDocumentDataSection: String { return self._s[549]! } + public var Stickers_AddToFavorites: String { return self._s[550]! } + public var Wallet_WordImport_Title: String { return self._s[551]! } + public var PhotoEditor_QualityLow: String { return self._s[552]! } + public var Watch_UserInfo_Unblock: String { return self._s[553]! } + public var Settings_Logout: String { return self._s[554]! } public func PUSH_MESSAGE_ROUND(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[553]!, self._r[553]!, [_1]) + return formatWithArgumentRanges(self._s[555]!, self._r[555]!, [_1]) } - public var ContactInfo_PhoneLabelWork: String { return self._s[554]! } - public var ChannelInfo_Stats: String { return self._s[555]! } - public var TextFormat_Link: String { return self._s[556]! } + public var ContactInfo_PhoneLabelWork: String { return self._s[556]! } + public var ChannelInfo_Stats: String { return self._s[557]! } + public var TextFormat_Link: String { return self._s[558]! } public func Date_ChatDateHeader(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[557]!, self._r[557]!, [_1, _2]) + return formatWithArgumentRanges(self._s[559]!, self._r[559]!, [_1, _2]) } - public var Wallet_TransactionInfo_Title: String { return self._s[558]! } + public var Wallet_TransactionInfo_Title: String { return self._s[560]! } public func Message_ForwardedMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[559]!, self._r[559]!, [_0]) + return formatWithArgumentRanges(self._s[561]!, self._r[561]!, [_0]) } - public var Watch_Notification_Joined: String { return self._s[560]! } - public var Group_Setup_TypePublicHelp: String { return self._s[561]! } - public var Passport_Scans_UploadNew: String { return self._s[562]! } - public var Checkout_LiabilityAlertTitle: String { return self._s[563]! } - public var DialogList_Title: String { return self._s[566]! } - public var NotificationSettings_ContactJoined: String { return self._s[567]! } - public var GroupInfo_LabelAdmin: String { return self._s[568]! } - public var KeyCommand_ChatInfo: String { return self._s[569]! } - public var Conversation_EditingCaptionPanelTitle: String { return self._s[570]! } - public var Call_ReportIncludeLog: String { return self._s[571]! } + public var Watch_Notification_Joined: String { return self._s[562]! } + public var Group_Setup_TypePublicHelp: String { return self._s[563]! } + public var Passport_Scans_UploadNew: String { return self._s[564]! } + public var Checkout_LiabilityAlertTitle: String { return self._s[565]! } + public var DialogList_Title: String { return self._s[568]! } + public var NotificationSettings_ContactJoined: String { return self._s[569]! } + public var GroupInfo_LabelAdmin: String { return self._s[570]! } + public var KeyCommand_ChatInfo: String { return self._s[571]! } + public var Conversation_EditingCaptionPanelTitle: String { return self._s[572]! } + public var Call_ReportIncludeLog: String { return self._s[573]! } public func Notifications_ExceptionsChangeSound(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[574]!, self._r[574]!, [_0]) + return formatWithArgumentRanges(self._s[576]!, self._r[576]!, [_0]) } - public var Channel_AdminLog_InfoPanelChannelAlertText: String { return self._s[575]! } - public var ChatAdmins_AllMembersAreAdmins: String { return self._s[576]! } - public var LocalGroup_IrrelevantWarning: String { return self._s[577]! } - public var Conversation_DefaultRestrictedInline: String { return self._s[578]! } - public var Message_Sticker: String { return self._s[579]! } - public var LastSeen_JustNow: String { return self._s[581]! } - public var Passport_Email_EmailPlaceholder: String { return self._s[583]! } - public var SettingsSearch_Synonyms_AppLanguage: String { return self._s[584]! } - public var Channel_AdminLogFilter_EventsEditedMessages: String { return self._s[585]! } - public var Channel_EditAdmin_PermissionsHeader: String { return self._s[586]! } - public var TwoStepAuth_Email: String { return self._s[587]! } - public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsSound: String { return self._s[588]! } - public var PhotoEditor_BlurToolOff: String { return self._s[589]! } - public var Message_PinnedStickerMessage: String { return self._s[590]! } - public var ContactInfo_PhoneLabelPager: String { return self._s[591]! } - public var SettingsSearch_Synonyms_Appearance_TextSize: String { return self._s[592]! } - public var Passport_DiscardMessageTitle: String { return self._s[593]! } - public var Privacy_PaymentsTitle: String { return self._s[594]! } - public var EditTheme_Edit_Preview_IncomingReplyName: String { return self._s[595]! } - public var ClearCache_StorageCache: String { return self._s[596]! } - public var Appearance_TextSizeSetting: String { return self._s[597]! } - public var Channel_DiscussionGroup_Header: String { return self._s[599]! } - public var VoiceOver_Chat_OptionSelected: String { return self._s[600]! } - public var Appearance_ColorTheme: String { return self._s[601]! } - public var UserInfo_ShareContact: String { return self._s[602]! } - public var Passport_Address_TypePassportRegistration: String { return self._s[603]! } - public var Common_More: String { return self._s[604]! } - public var Watch_Message_Call: String { return self._s[605]! } - public var Profile_EncryptionKey: String { return self._s[608]! } - public var Privacy_TopPeers: String { return self._s[609]! } - public var Conversation_StopPollConfirmation: String { return self._s[610]! } - public var Wallet_Words_NotDoneText: String { return self._s[612]! } - public var Privacy_TopPeersWarning: String { return self._s[614]! } - public var SettingsSearch_Synonyms_Data_DownloadInBackground: String { return self._s[615]! } - public var SettingsSearch_Synonyms_Data_Storage_KeepMedia: String { return self._s[616]! } - public var Wallet_RestoreFailed_EnterWords: String { return self._s[619]! } - public var DialogList_SearchSectionMessages: String { return self._s[620]! } - public var Notifications_ChannelNotifications: String { return self._s[621]! } - public var CheckoutInfo_ShippingInfoAddress1Placeholder: String { return self._s[622]! } - public var Passport_Language_sk: String { return self._s[623]! } - public var Notification_MessageLifetime1h: String { return self._s[624]! } - public var Wallpaper_ResetWallpapersInfo: String { return self._s[625]! } - public var Appearance_ThemePreview_Chat_5_Text: String { return self._s[626]! } - public var Call_ReportSkip: String { return self._s[628]! } - public var Cache_ServiceFiles: String { return self._s[629]! } - public var Group_ErrorAddTooMuchAdmins: String { return self._s[630]! } - public var VoiceOver_Chat_YourFile: String { return self._s[631]! } - public var Map_Hybrid: String { return self._s[632]! } - public var Contacts_SearchUsersAndGroupsLabel: String { return self._s[634]! } + public var Channel_AdminLog_InfoPanelChannelAlertText: String { return self._s[577]! } + public var ChatAdmins_AllMembersAreAdmins: String { return self._s[578]! } + public var LocalGroup_IrrelevantWarning: String { return self._s[579]! } + public var Conversation_DefaultRestrictedInline: String { return self._s[580]! } + public var Message_Sticker: String { return self._s[581]! } + public var LastSeen_JustNow: String { return self._s[583]! } + public var Passport_Email_EmailPlaceholder: String { return self._s[585]! } + public var SettingsSearch_Synonyms_AppLanguage: String { return self._s[586]! } + public var Channel_AdminLogFilter_EventsEditedMessages: String { return self._s[587]! } + public var Channel_EditAdmin_PermissionsHeader: String { return self._s[588]! } + public var TwoStepAuth_Email: String { return self._s[589]! } + public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsSound: String { return self._s[590]! } + public var PhotoEditor_BlurToolOff: String { return self._s[591]! } + public var Message_PinnedStickerMessage: String { return self._s[592]! } + public var ContactInfo_PhoneLabelPager: String { return self._s[593]! } + public var SettingsSearch_Synonyms_Appearance_TextSize: String { return self._s[594]! } + public var Passport_DiscardMessageTitle: String { return self._s[595]! } + public var Privacy_PaymentsTitle: String { return self._s[596]! } + public var EditTheme_Edit_Preview_IncomingReplyName: String { return self._s[597]! } + public var ClearCache_StorageCache: String { return self._s[598]! } + public var Appearance_TextSizeSetting: String { return self._s[599]! } + public var Channel_DiscussionGroup_Header: String { return self._s[601]! } + public var VoiceOver_Chat_OptionSelected: String { return self._s[602]! } + public var Appearance_ColorTheme: String { return self._s[603]! } + public var UserInfo_ShareContact: String { return self._s[604]! } + public var Passport_Address_TypePassportRegistration: String { return self._s[605]! } + public var Common_More: String { return self._s[606]! } + public var Watch_Message_Call: String { return self._s[607]! } + public var Profile_EncryptionKey: String { return self._s[610]! } + public var Privacy_TopPeers: String { return self._s[611]! } + public var Conversation_StopPollConfirmation: String { return self._s[612]! } + public var Wallet_Words_NotDoneText: String { return self._s[614]! } + public var Privacy_TopPeersWarning: String { return self._s[616]! } + public var SettingsSearch_Synonyms_Data_DownloadInBackground: String { return self._s[617]! } + public var SettingsSearch_Synonyms_Data_Storage_KeepMedia: String { return self._s[618]! } + public var Wallet_RestoreFailed_EnterWords: String { return self._s[621]! } + public var DialogList_SearchSectionMessages: String { return self._s[622]! } + public var Notifications_ChannelNotifications: String { return self._s[623]! } + public var CheckoutInfo_ShippingInfoAddress1Placeholder: String { return self._s[624]! } + public var Passport_Language_sk: String { return self._s[625]! } + public var Notification_MessageLifetime1h: String { return self._s[626]! } + public var Wallpaper_ResetWallpapersInfo: String { return self._s[627]! } + public var Appearance_ThemePreview_Chat_5_Text: String { return self._s[628]! } + public var Call_ReportSkip: String { return self._s[630]! } + public var Cache_ServiceFiles: String { return self._s[631]! } + public var Group_ErrorAddTooMuchAdmins: String { return self._s[632]! } + public var VoiceOver_Chat_YourFile: String { return self._s[633]! } + public var Map_Hybrid: String { return self._s[634]! } + public var Contacts_SearchUsersAndGroupsLabel: String { return self._s[636]! } public func PUSH_MESSAGE_QUIZ(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[635]!, self._r[635]!, [_1]) + return formatWithArgumentRanges(self._s[637]!, self._r[637]!, [_1]) } - public var ChatSettings_AutoDownloadVideos: String { return self._s[637]! } - public var Channel_BanUser_PermissionEmbedLinks: String { return self._s[638]! } - public var InfoPlist_NSLocationAlwaysAndWhenInUseUsageDescription: String { return self._s[639]! } - public var SocksProxySetup_ProxyTelegram: String { return self._s[642]! } + public var ChatSettings_AutoDownloadVideos: String { return self._s[639]! } + public var Channel_BanUser_PermissionEmbedLinks: String { return self._s[640]! } + public var InfoPlist_NSLocationAlwaysAndWhenInUseUsageDescription: String { return self._s[641]! } + public var SocksProxySetup_ProxyTelegram: String { return self._s[644]! } public func PUSH_MESSAGE_AUDIO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[643]!, self._r[643]!, [_1]) + return formatWithArgumentRanges(self._s[645]!, self._r[645]!, [_1]) } - public var Channel_Username_CreatePrivateLinkHelp: String { return self._s[645]! } - public var ScheduledMessages_ScheduledToday: String { return self._s[646]! } + public var Channel_Username_CreatePrivateLinkHelp: String { return self._s[647]! } + public var ScheduledMessages_ScheduledToday: String { return self._s[648]! } public func PUSH_CHAT_TITLE_EDITED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[647]!, self._r[647]!, [_1, _2]) + return formatWithArgumentRanges(self._s[649]!, self._r[649]!, [_1, _2]) } - public var Conversation_LiveLocationYou: String { return self._s[648]! } - public var SettingsSearch_Synonyms_Privacy_Calls: String { return self._s[649]! } - public var SettingsSearch_Synonyms_Notifications_MessageNotificationsPreview: String { return self._s[650]! } - public var UserInfo_ShareBot: String { return self._s[653]! } + public var Conversation_LiveLocationYou: String { return self._s[650]! } + public var SettingsSearch_Synonyms_Privacy_Calls: String { return self._s[651]! } + public var SettingsSearch_Synonyms_Notifications_MessageNotificationsPreview: String { return self._s[652]! } + public var UserInfo_ShareBot: String { return self._s[655]! } public func PUSH_AUTH_REGION(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[654]!, self._r[654]!, [_1, _2]) + return formatWithArgumentRanges(self._s[656]!, self._r[656]!, [_1, _2]) } - public var Conversation_ClearCache: String { return self._s[655]! } - public var PhotoEditor_ShadowsTint: String { return self._s[656]! } - public var Message_Audio: String { return self._s[657]! } - public var Passport_Language_lt: String { return self._s[658]! } + public var Conversation_ClearCache: String { return self._s[657]! } + public var PhotoEditor_ShadowsTint: String { return self._s[658]! } + public var Message_Audio: String { return self._s[659]! } + public var Passport_Language_lt: String { return self._s[660]! } public func Message_PinnedTextMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[659]!, self._r[659]!, [_0]) + return formatWithArgumentRanges(self._s[661]!, self._r[661]!, [_0]) } - public var Permissions_SiriText_v0: String { return self._s[660]! } - public var Conversation_FileICloudDrive: String { return self._s[661]! } - public var ChatList_DeleteForEveryoneConfirmationTitle: String { return self._s[662]! } - public var Notifications_Badge_IncludeMutedChats: String { return self._s[663]! } + public var Permissions_SiriText_v0: String { return self._s[662]! } + public var Conversation_FileICloudDrive: String { return self._s[663]! } + public var ChatList_DeleteForEveryoneConfirmationTitle: String { return self._s[664]! } + public var Notifications_Badge_IncludeMutedChats: String { return self._s[665]! } public func Notification_NewAuthDetected(_ _1: String, _ _2: String, _ _3: String, _ _4: String, _ _5: String, _ _6: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[664]!, self._r[664]!, [_1, _2, _3, _4, _5, _6]) + return formatWithArgumentRanges(self._s[666]!, self._r[666]!, [_1, _2, _3, _4, _5, _6]) } - public var DialogList_ProxyConnectionIssuesTooltip: String { return self._s[665]! } + public var DialogList_ProxyConnectionIssuesTooltip: String { return self._s[667]! } public func Time_MonthOfYear_m5(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[666]!, self._r[666]!, [_0]) + return formatWithArgumentRanges(self._s[668]!, self._r[668]!, [_0]) } - public var Channel_SignMessages: String { return self._s[667]! } + public var Channel_SignMessages: String { return self._s[669]! } public func PUSH_MESSAGE_NOTEXT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[668]!, self._r[668]!, [_1]) + return formatWithArgumentRanges(self._s[670]!, self._r[670]!, [_1]) } - public var Compose_ChannelTokenListPlaceholder: String { return self._s[669]! } - public var Passport_ScanPassport: String { return self._s[670]! } - public var Watch_Suggestion_Thanks: String { return self._s[671]! } - public var BlockedUsers_AddNew: String { return self._s[672]! } + public var Compose_ChannelTokenListPlaceholder: String { return self._s[671]! } + public var Passport_ScanPassport: String { return self._s[672]! } + public var Watch_Suggestion_Thanks: String { return self._s[673]! } + public var BlockedUsers_AddNew: String { return self._s[674]! } public func PUSH_CHAT_MESSAGE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[673]!, self._r[673]!, [_1, _2]) + return formatWithArgumentRanges(self._s[675]!, self._r[675]!, [_1, _2]) } - public var Watch_Message_Invoice: String { return self._s[674]! } - public var SettingsSearch_Synonyms_Privacy_LastSeen: String { return self._s[675]! } - public var Month_GenJuly: String { return self._s[676]! } - public var CreatePoll_QuizInfo: String { return self._s[677]! } - public var UserInfo_StartSecretChatStart: String { return self._s[678]! } - public var SocksProxySetup_ProxySocks5: String { return self._s[679]! } - public var IntentsSettings_SuggestByShare: String { return self._s[681]! } - public var Notification_Exceptions_DeleteAllConfirmation: String { return self._s[682]! } - public var Notification_ChannelInviterSelf: String { return self._s[683]! } - public var CheckoutInfo_ReceiverInfoEmail: String { return self._s[684]! } + public var Watch_Message_Invoice: String { return self._s[676]! } + public var SettingsSearch_Synonyms_Privacy_LastSeen: String { return self._s[677]! } + public var Month_GenJuly: String { return self._s[678]! } + public var CreatePoll_QuizInfo: String { return self._s[679]! } + public var UserInfo_StartSecretChatStart: String { return self._s[680]! } + public var SocksProxySetup_ProxySocks5: String { return self._s[681]! } + public var IntentsSettings_SuggestByShare: String { return self._s[683]! } + public var Notification_Exceptions_DeleteAllConfirmation: String { return self._s[684]! } + public var Notification_ChannelInviterSelf: String { return self._s[685]! } + public var CheckoutInfo_ReceiverInfoEmail: String { return self._s[686]! } public func ApplyLanguage_ChangeLanguageUnofficialText(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[685]!, self._r[685]!, [_1, _2]) + return formatWithArgumentRanges(self._s[687]!, self._r[687]!, [_1, _2]) } - public var CheckoutInfo_Title: String { return self._s[686]! } - public var Watch_Stickers_RecentPlaceholder: String { return self._s[687]! } + public var CheckoutInfo_Title: String { return self._s[688]! } + public var Watch_Stickers_RecentPlaceholder: String { return self._s[689]! } public func Map_DistanceAway(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[688]!, self._r[688]!, [_0]) + return formatWithArgumentRanges(self._s[690]!, self._r[690]!, [_0]) } - public var Passport_Identity_MainPage: String { return self._s[689]! } - public var TwoStepAuth_ConfirmEmailResendCode: String { return self._s[690]! } - public var Passport_Language_de: String { return self._s[691]! } - public var Update_Title: String { return self._s[692]! } - public var ContactInfo_PhoneLabelWorkFax: String { return self._s[693]! } - public var Channel_AdminLog_BanEmbedLinks: String { return self._s[694]! } - public var Passport_Email_UseTelegramEmailHelp: String { return self._s[695]! } - public var Notifications_ChannelNotificationsPreview: String { return self._s[696]! } - public var NotificationsSound_Telegraph: String { return self._s[697]! } - public var Watch_LastSeen_ALongTimeAgo: String { return self._s[698]! } - public var ChannelMembers_WhoCanAddMembers: String { return self._s[699]! } + public var Passport_Identity_MainPage: String { return self._s[691]! } + public var TwoStepAuth_ConfirmEmailResendCode: String { return self._s[692]! } + public var Passport_Language_de: String { return self._s[693]! } + public var Update_Title: String { return self._s[694]! } + public var ContactInfo_PhoneLabelWorkFax: String { return self._s[695]! } + public var Channel_AdminLog_BanEmbedLinks: String { return self._s[696]! } + public var Passport_Email_UseTelegramEmailHelp: String { return self._s[697]! } + public var Notifications_ChannelNotificationsPreview: String { return self._s[698]! } + public var NotificationsSound_Telegraph: String { return self._s[699]! } + public var Watch_LastSeen_ALongTimeAgo: String { return self._s[700]! } + public var ChannelMembers_WhoCanAddMembers: String { return self._s[701]! } public func AutoDownloadSettings_UpTo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[700]!, self._r[700]!, [_0]) + return formatWithArgumentRanges(self._s[702]!, self._r[702]!, [_0]) } - public var ClearCache_Description: String { return self._s[701]! } - public var Stickers_SuggestAll: String { return self._s[702]! } - public var Conversation_ForwardTitle: String { return self._s[703]! } - public var Appearance_ThemePreview_ChatList_7_Name: String { return self._s[704]! } + public var ClearCache_Description: String { return self._s[703]! } + public var Stickers_SuggestAll: String { return self._s[704]! } + public var Conversation_ForwardTitle: String { return self._s[705]! } + public var Appearance_ThemePreview_ChatList_7_Name: String { return self._s[706]! } public func Notification_JoinedChannel(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[705]!, self._r[705]!, [_0]) + return formatWithArgumentRanges(self._s[707]!, self._r[707]!, [_0]) } - public var Calls_NewCall: String { return self._s[706]! } - public var Call_StatusEnded: String { return self._s[707]! } - public var AutoDownloadSettings_DataUsageLow: String { return self._s[708]! } - public var Settings_ProxyConnected: String { return self._s[709]! } - public var Channel_AdminLogFilter_EventsPinned: String { return self._s[710]! } - public var PhotoEditor_QualityVeryLow: String { return self._s[711]! } - public var Channel_AdminLogFilter_EventsDeletedMessages: String { return self._s[712]! } - public var Passport_PasswordPlaceholder: String { return self._s[713]! } - public var Message_PinnedInvoice: String { return self._s[714]! } - public var Passport_Identity_IssueDate: String { return self._s[715]! } - public var Passport_Language_pl: String { return self._s[716]! } + public var Calls_NewCall: String { return self._s[708]! } + public var Call_StatusEnded: String { return self._s[709]! } + public var AutoDownloadSettings_DataUsageLow: String { return self._s[710]! } + public var Settings_ProxyConnected: String { return self._s[711]! } + public var Channel_AdminLogFilter_EventsPinned: String { return self._s[712]! } + public var PhotoEditor_QualityVeryLow: String { return self._s[713]! } + public var Channel_AdminLogFilter_EventsDeletedMessages: String { return self._s[714]! } + public var Passport_PasswordPlaceholder: String { return self._s[715]! } + public var Message_PinnedInvoice: String { return self._s[716]! } + public var Passport_Identity_IssueDate: String { return self._s[717]! } + public var Passport_Language_pl: String { return self._s[718]! } public func ChannelInfo_ChannelForbidden(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[717]!, self._r[717]!, [_0]) + return formatWithArgumentRanges(self._s[719]!, self._r[719]!, [_0]) } - public var SocksProxySetup_PasteFromClipboard: String { return self._s[718]! } - public var Call_StatusConnecting: String { return self._s[719]! } + public var Call_StatusConnecting: String { return self._s[720]! } + public var SocksProxySetup_PasteFromClipboard: String { return self._s[721]! } public func Username_UsernameIsAvailable(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[720]!, self._r[720]!, [_0]) + return formatWithArgumentRanges(self._s[722]!, self._r[722]!, [_0]) } - public var ChatSettings_ConnectionType_UseProxy: String { return self._s[722]! } - public var Common_Edit: String { return self._s[723]! } - public var PrivacySettings_LastSeenNobody: String { return self._s[724]! } + public var ChatSettings_ConnectionType_UseProxy: String { return self._s[724]! } + public var Common_Edit: String { return self._s[725]! } + public var PrivacySettings_LastSeenNobody: String { return self._s[726]! } public func Notification_LeftChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[725]!, self._r[725]!, [_0]) + return formatWithArgumentRanges(self._s[727]!, self._r[727]!, [_0]) } - public var GroupInfo_ChatAdmins: String { return self._s[726]! } - public var PrivateDataSettings_Title: String { return self._s[727]! } - public var Login_CancelPhoneVerificationStop: String { return self._s[728]! } - public var ChatList_Read: String { return self._s[729]! } - public var Wallet_WordImport_Text: String { return self._s[730]! } - public var Undo_ChatClearedForBothSides: String { return self._s[731]! } - public var GroupPermission_SectionTitle: String { return self._s[732]! } - public var TwoFactorSetup_Intro_Title: String { return self._s[734]! } + public var GroupInfo_ChatAdmins: String { return self._s[728]! } + public var PrivateDataSettings_Title: String { return self._s[729]! } + public var Login_CancelPhoneVerificationStop: String { return self._s[730]! } + public var ChatList_Read: String { return self._s[731]! } + public var Wallet_WordImport_Text: String { return self._s[732]! } + public var Undo_ChatClearedForBothSides: String { return self._s[733]! } + public var GroupPermission_SectionTitle: String { return self._s[734]! } + public var TwoFactorSetup_Intro_Title: String { return self._s[736]! } public func PUSH_CHAT_LEFT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[735]!, self._r[735]!, [_1, _2]) + return formatWithArgumentRanges(self._s[737]!, self._r[737]!, [_1, _2]) } - public var Checkout_ErrorPaymentFailed: String { return self._s[736]! } - public var Update_UpdateApp: String { return self._s[737]! } - public var Group_Username_RevokeExistingUsernamesInfo: String { return self._s[738]! } - public var Settings_Appearance: String { return self._s[739]! } - public var SettingsSearch_Synonyms_Stickers_SuggestStickers: String { return self._s[743]! } - public var Watch_Location_Access: String { return self._s[744]! } - public var ShareMenu_CopyShareLink: String { return self._s[746]! } - public var TwoStepAuth_SetupHintTitle: String { return self._s[747]! } - public var Conversation_Theme: String { return self._s[749]! } + public var Checkout_ErrorPaymentFailed: String { return self._s[738]! } + public var Update_UpdateApp: String { return self._s[739]! } + public var Group_Username_RevokeExistingUsernamesInfo: String { return self._s[740]! } + public var Settings_Appearance: String { return self._s[741]! } + public var SettingsSearch_Synonyms_Stickers_SuggestStickers: String { return self._s[745]! } + public var Watch_Location_Access: String { return self._s[746]! } + public var ShareMenu_CopyShareLink: String { return self._s[748]! } + public var TwoStepAuth_SetupHintTitle: String { return self._s[749]! } + public var Conversation_Theme: String { return self._s[751]! } public func DialogList_SingleRecordingVideoMessageSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[750]!, self._r[750]!, [_0]) + return formatWithArgumentRanges(self._s[752]!, self._r[752]!, [_0]) } - public var Notifications_ClassicTones: String { return self._s[751]! } - public var Weekday_ShortWednesday: String { return self._s[752]! } - public var WallpaperPreview_SwipeColorsBottomText: String { return self._s[753]! } - public var Undo_LeftGroup: String { return self._s[756]! } - public var Wallet_RestoreFailed_Text: String { return self._s[757]! } - public var Conversation_LinkDialogCopy: String { return self._s[758]! } - public var Wallet_TransactionInfo_NoAddress: String { return self._s[760]! } - public var Wallet_Navigation_Back: String { return self._s[761]! } - public var KeyCommand_FocusOnInputField: String { return self._s[762]! } - public var Contacts_SelectAll: String { return self._s[763]! } - public var Preview_SaveToCameraRoll: String { return self._s[764]! } - public var PrivacySettings_PasscodeOff: String { return self._s[765]! } - public var Appearance_ThemePreview_ChatList_6_Name: String { return self._s[766]! } + public var Notifications_ClassicTones: String { return self._s[753]! } + public var Weekday_ShortWednesday: String { return self._s[754]! } + public var WallpaperPreview_SwipeColorsBottomText: String { return self._s[755]! } + public var Undo_LeftGroup: String { return self._s[758]! } + public var Wallet_RestoreFailed_Text: String { return self._s[759]! } + public var Conversation_LinkDialogCopy: String { return self._s[760]! } + public var Wallet_TransactionInfo_NoAddress: String { return self._s[762]! } + public var Wallet_Navigation_Back: String { return self._s[763]! } + public var KeyCommand_FocusOnInputField: String { return self._s[764]! } + public var Contacts_SelectAll: String { return self._s[765]! } + public var Preview_SaveToCameraRoll: String { return self._s[766]! } + public var PrivacySettings_PasscodeOff: String { return self._s[767]! } + public var Appearance_ThemePreview_ChatList_6_Name: String { return self._s[768]! } public func PUSH_CHANNEL_MESSAGE_QUIZ(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[767]!, self._r[767]!, [_1]) + return formatWithArgumentRanges(self._s[769]!, self._r[769]!, [_1]) } - public var Wallpaper_Title: String { return self._s[768]! } - public var Conversation_FilePhotoOrVideo: String { return self._s[769]! } - public var AccessDenied_Camera: String { return self._s[770]! } - public var Watch_Compose_CurrentLocation: String { return self._s[771]! } - public var Channel_DiscussionGroup_MakeHistoryPublicProceed: String { return self._s[773]! } + public var Wallpaper_Title: String { return self._s[770]! } + public var Conversation_FilePhotoOrVideo: String { return self._s[771]! } + public var AccessDenied_Camera: String { return self._s[772]! } + public var Watch_Compose_CurrentLocation: String { return self._s[773]! } + public var Channel_DiscussionGroup_MakeHistoryPublicProceed: String { return self._s[775]! } public func SecretImage_NotViewedYet(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[774]!, self._r[774]!, [_0]) + return formatWithArgumentRanges(self._s[776]!, self._r[776]!, [_0]) } - public var GroupInfo_InvitationLinkDoesNotExist: String { return self._s[775]! } - public var Passport_Language_ro: String { return self._s[776]! } - public var EditTheme_UploadNewTheme: String { return self._s[777]! } - public var CheckoutInfo_SaveInfoHelp: String { return self._s[778]! } - public var Wallet_Intro_Terms: String { return self._s[779]! } + public var GroupInfo_InvitationLinkDoesNotExist: String { return self._s[777]! } + public var Passport_Language_ro: String { return self._s[778]! } + public var EditTheme_UploadNewTheme: String { return self._s[779]! } + public var CheckoutInfo_SaveInfoHelp: String { return self._s[780]! } + public var Wallet_Intro_Terms: String { return self._s[781]! } public func Notification_SecretChatMessageScreenshot(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[780]!, self._r[780]!, [_0]) + return formatWithArgumentRanges(self._s[782]!, self._r[782]!, [_0]) } - public var Login_CancelPhoneVerification: String { return self._s[781]! } - public var State_ConnectingToProxy: String { return self._s[782]! } - public var Calls_RatingTitle: String { return self._s[783]! } - public var Generic_ErrorMoreInfo: String { return self._s[784]! } - public var ChatList_Search_ShowMore: String { return self._s[785]! } - public var Appearance_PreviewReplyText: String { return self._s[786]! } - public var CheckoutInfo_ShippingInfoPostcodePlaceholder: String { return self._s[787]! } + public var Login_CancelPhoneVerification: String { return self._s[783]! } + public var State_ConnectingToProxy: String { return self._s[784]! } + public var Calls_RatingTitle: String { return self._s[785]! } + public var Generic_ErrorMoreInfo: String { return self._s[786]! } + public var ChatList_Search_ShowMore: String { return self._s[787]! } + public var Appearance_PreviewReplyText: String { return self._s[788]! } + public var CheckoutInfo_ShippingInfoPostcodePlaceholder: String { return self._s[789]! } public func Wallet_Send_Balance(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[788]!, self._r[788]!, [_0]) + return formatWithArgumentRanges(self._s[790]!, self._r[790]!, [_0]) } - public var IntentsSettings_SuggestedChatsContacts: String { return self._s[789]! } - public var SharedMedia_CategoryLinks: String { return self._s[790]! } - public var Calls_Missed: String { return self._s[791]! } - public var Cache_Photos: String { return self._s[795]! } - public var GroupPermission_NoAddMembers: String { return self._s[796]! } - public var ScheduledMessages_Title: String { return self._s[797]! } + public var IntentsSettings_SuggestedChatsContacts: String { return self._s[791]! } + public var SharedMedia_CategoryLinks: String { return self._s[792]! } + public var Calls_Missed: String { return self._s[793]! } + public var Cache_Photos: String { return self._s[797]! } + public var GroupPermission_NoAddMembers: String { return self._s[798]! } + public var ScheduledMessages_Title: String { return self._s[799]! } public func Channel_AdminLog_MessageUnpinned(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[798]!, self._r[798]!, [_0]) + return formatWithArgumentRanges(self._s[800]!, self._r[800]!, [_0]) } - public var Conversation_ShareBotLocationConfirmationTitle: String { return self._s[799]! } - public var Settings_ProxyDisabled: String { return self._s[800]! } + public var Conversation_ShareBotLocationConfirmationTitle: String { return self._s[801]! } + public var Settings_ProxyDisabled: String { return self._s[802]! } public func Settings_ApplyProxyAlertCredentials(_ _1: String, _ _2: String, _ _3: String, _ _4: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[801]!, self._r[801]!, [_1, _2, _3, _4]) + return formatWithArgumentRanges(self._s[803]!, self._r[803]!, [_1, _2, _3, _4]) } public func Conversation_RestrictedMediaTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[802]!, self._r[802]!, [_0]) + return formatWithArgumentRanges(self._s[804]!, self._r[804]!, [_0]) } - public var ChatList_Context_RemoveFromRecents: String { return self._s[804]! } - public var Appearance_Title: String { return self._s[805]! } + public var ChatList_Context_RemoveFromRecents: String { return self._s[806]! } + public var Appearance_Title: String { return self._s[807]! } public func Time_MonthOfYear_m2(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[807]!, self._r[807]!, [_0]) + return formatWithArgumentRanges(self._s[809]!, self._r[809]!, [_0]) } - public var Conversation_WalletRequiredText: String { return self._s[808]! } - public var StickerPacksSettings_ShowStickersButtonHelp: String { return self._s[809]! } - public var OldChannels_NoticeCreateText: String { return self._s[810]! } - public var Channel_EditMessageErrorGeneric: String { return self._s[811]! } - public var Privacy_Calls_IntegrationHelp: String { return self._s[812]! } - public var Preview_DeletePhoto: String { return self._s[813]! } - public var Appearance_AppIconFilledX: String { return self._s[814]! } - public var PrivacySettings_PrivacyTitle: String { return self._s[815]! } + public var Conversation_WalletRequiredText: String { return self._s[810]! } + public var StickerPacksSettings_ShowStickersButtonHelp: String { return self._s[811]! } + public var OldChannels_NoticeCreateText: String { return self._s[812]! } + public var Channel_EditMessageErrorGeneric: String { return self._s[813]! } + public var Privacy_Calls_IntegrationHelp: String { return self._s[814]! } + public var Preview_DeletePhoto: String { return self._s[815]! } + public var Appearance_AppIconFilledX: String { return self._s[816]! } + public var PrivacySettings_PrivacyTitle: String { return self._s[817]! } public func Conversation_BotInteractiveUrlAlert(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[816]!, self._r[816]!, [_0]) + return formatWithArgumentRanges(self._s[818]!, self._r[818]!, [_0]) } - public var Coub_TapForSound: String { return self._s[819]! } - public var Map_LocatingError: String { return self._s[820]! } - public var TwoStepAuth_EmailChangeSuccess: String { return self._s[822]! } - public var Conversation_SendMessage_SendSilently: String { return self._s[823]! } - public var VoiceOver_MessageContextOpenMessageMenu: String { return self._s[824]! } + public var Coub_TapForSound: String { return self._s[821]! } + public var Map_LocatingError: String { return self._s[822]! } + public var TwoStepAuth_EmailChangeSuccess: String { return self._s[824]! } + public var Conversation_SendMessage_SendSilently: String { return self._s[825]! } + public var VoiceOver_MessageContextOpenMessageMenu: String { return self._s[826]! } public func Wallet_Time_PreciseDate_m8(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[825]!, self._r[825]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[827]!, self._r[827]!, [_1, _2, _3]) } - public var Passport_ForgottenPassword: String { return self._s[826]! } - public var GroupInfo_InviteLink_RevokeLink: String { return self._s[827]! } - public var StickerPacksSettings_ArchivedPacks: String { return self._s[828]! } - public var Login_TermsOfServiceSignupDecline: String { return self._s[830]! } - public var Channel_Moderator_AccessLevelRevoke: String { return self._s[831]! } - public var Message_Location: String { return self._s[832]! } - public var Passport_Identity_NamePlaceholder: String { return self._s[833]! } - public var Channel_Management_Title: String { return self._s[834]! } - public var DialogList_SearchSectionDialogs: String { return self._s[836]! } - public var Compose_NewChannel_Members: String { return self._s[837]! } + public var Passport_ForgottenPassword: String { return self._s[828]! } + public var GroupInfo_InviteLink_RevokeLink: String { return self._s[829]! } + public var StickerPacksSettings_ArchivedPacks: String { return self._s[830]! } + public var Login_TermsOfServiceSignupDecline: String { return self._s[832]! } + public var Channel_Moderator_AccessLevelRevoke: String { return self._s[833]! } + public var Message_Location: String { return self._s[834]! } + public var Passport_Identity_NamePlaceholder: String { return self._s[835]! } + public var Channel_Management_Title: String { return self._s[836]! } + public var DialogList_SearchSectionDialogs: String { return self._s[838]! } + public var Compose_NewChannel_Members: String { return self._s[839]! } public func DialogList_SingleUploadingFileSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[838]!, self._r[838]!, [_0]) + return formatWithArgumentRanges(self._s[840]!, self._r[840]!, [_0]) } - public var GroupInfo_Location: String { return self._s[839]! } - public var Appearance_ThemePreview_ChatList_5_Name: String { return self._s[840]! } - public var ClearCache_Clear: String { return self._s[841]! } - public var AutoNightTheme_ScheduledFrom: String { return self._s[842]! } - public var PhotoEditor_WarmthTool: String { return self._s[843]! } - public var Passport_Language_tr: String { return self._s[844]! } + public var GroupInfo_Location: String { return self._s[841]! } + public var Appearance_ThemePreview_ChatList_5_Name: String { return self._s[842]! } + public var ClearCache_Clear: String { return self._s[843]! } + public var AutoNightTheme_ScheduledFrom: String { return self._s[844]! } + public var PhotoEditor_WarmthTool: String { return self._s[845]! } + public var Passport_Language_tr: String { return self._s[846]! } public func PUSH_MESSAGE_GAME_SCORE(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[845]!, self._r[845]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[847]!, self._r[847]!, [_1, _2, _3]) } - public var OldChannels_NoticeUpgradeText: String { return self._s[846]! } - public var Login_ResetAccountProtected_Reset: String { return self._s[848]! } - public var Watch_PhotoView_Title: String { return self._s[849]! } - public var Passport_Phone_Delete: String { return self._s[850]! } - public var Undo_ChatDeletedForBothSides: String { return self._s[851]! } - public var Conversation_EditingMessageMediaEditCurrentPhoto: String { return self._s[852]! } - public var GroupInfo_Permissions: String { return self._s[853]! } - public var PasscodeSettings_TurnPasscodeOff: String { return self._s[854]! } - public var Profile_ShareContactButton: String { return self._s[855]! } - public var ChatSettings_Other: String { return self._s[856]! } - public var UserInfo_NotificationsDisabled: String { return self._s[857]! } - public var CheckoutInfo_ShippingInfoCity: String { return self._s[858]! } - public var LastSeen_WithinAMonth: String { return self._s[859]! } - public var VoiceOver_Chat_PlayHint: String { return self._s[860]! } - public var Conversation_ReportGroupLocation: String { return self._s[861]! } - public var Conversation_EncryptionCanceled: String { return self._s[862]! } - public var MediaPicker_GroupDescription: String { return self._s[863]! } - public var WebSearch_Images: String { return self._s[864]! } + public var OldChannels_NoticeUpgradeText: String { return self._s[848]! } + public var Login_ResetAccountProtected_Reset: String { return self._s[850]! } + public var Watch_PhotoView_Title: String { return self._s[851]! } + public var Passport_Phone_Delete: String { return self._s[852]! } + public var Undo_ChatDeletedForBothSides: String { return self._s[853]! } + public var Conversation_EditingMessageMediaEditCurrentPhoto: String { return self._s[854]! } + public var GroupInfo_Permissions: String { return self._s[855]! } + public var PasscodeSettings_TurnPasscodeOff: String { return self._s[856]! } + public var Profile_ShareContactButton: String { return self._s[857]! } + public var ChatSettings_Other: String { return self._s[858]! } + public var UserInfo_NotificationsDisabled: String { return self._s[859]! } + public var CheckoutInfo_ShippingInfoCity: String { return self._s[860]! } + public var LastSeen_WithinAMonth: String { return self._s[861]! } + public var VoiceOver_Chat_PlayHint: String { return self._s[862]! } + public var Conversation_ReportGroupLocation: String { return self._s[863]! } + public var Conversation_EncryptionCanceled: String { return self._s[864]! } + public var MediaPicker_GroupDescription: String { return self._s[865]! } + public var WebSearch_Images: String { return self._s[866]! } public func Channel_Management_PromotedBy(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[865]!, self._r[865]!, [_0]) + return formatWithArgumentRanges(self._s[867]!, self._r[867]!, [_0]) } - public var Message_Photo: String { return self._s[866]! } - public var PasscodeSettings_HelpBottom: String { return self._s[867]! } - public var AutoDownloadSettings_VideosTitle: String { return self._s[868]! } - public var VoiceOver_Media_PlaybackRateChange: String { return self._s[869]! } - public var Passport_Identity_AddDriversLicense: String { return self._s[870]! } - public var TwoStepAuth_EnterPasswordPassword: String { return self._s[871]! } - public var NotificationsSound_Calypso: String { return self._s[872]! } - public var Map_Map: String { return self._s[873]! } + public var Message_Photo: String { return self._s[868]! } + public var PasscodeSettings_HelpBottom: String { return self._s[869]! } + public var AutoDownloadSettings_VideosTitle: String { return self._s[870]! } + public var VoiceOver_Media_PlaybackRateChange: String { return self._s[871]! } + public var Passport_Identity_AddDriversLicense: String { return self._s[872]! } + public var TwoStepAuth_EnterPasswordPassword: String { return self._s[873]! } + public var NotificationsSound_Calypso: String { return self._s[874]! } + public var Map_Map: String { return self._s[875]! } public func Conversation_LiveLocationYouAndOther(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[874]!, self._r[874]!, [_0]) + return formatWithArgumentRanges(self._s[876]!, self._r[876]!, [_0]) } - public var CheckoutInfo_ReceiverInfoTitle: String { return self._s[876]! } - public var ChatSettings_TextSizeUnits: String { return self._s[877]! } + public var CheckoutInfo_ReceiverInfoTitle: String { return self._s[878]! } + public var ChatSettings_TextSizeUnits: String { return self._s[879]! } public func VoiceOver_Chat_FileFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[878]!, self._r[878]!, [_0]) + return formatWithArgumentRanges(self._s[880]!, self._r[880]!, [_0]) } - public var Common_of: String { return self._s[879]! } - public var Conversation_ForwardContacts: String { return self._s[882]! } - public var IntentsSettings_SuggestByAll: String { return self._s[884]! } + public var Common_of: String { return self._s[881]! } + public var Conversation_ForwardContacts: String { return self._s[884]! } + public var IntentsSettings_SuggestByAll: String { return self._s[886]! } public func Call_AnsweringWithAccount(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[885]!, self._r[885]!, [_0]) + return formatWithArgumentRanges(self._s[887]!, self._r[887]!, [_0]) } - public var Passport_Language_hy: String { return self._s[886]! } - public var Notifications_MessageNotificationsHelp: String { return self._s[887]! } - public var AutoDownloadSettings_Reset: String { return self._s[888]! } - public var Wallet_TransactionInfo_AddressCopied: String { return self._s[889]! } - public var Paint_ClearConfirm: String { return self._s[890]! } - public var Camera_VideoMode: String { return self._s[891]! } + public var Passport_Language_hy: String { return self._s[888]! } + public var Notifications_MessageNotificationsHelp: String { return self._s[889]! } + public var AutoDownloadSettings_Reset: String { return self._s[890]! } + public var Wallet_TransactionInfo_AddressCopied: String { return self._s[891]! } + public var Paint_ClearConfirm: String { return self._s[892]! } + public var Camera_VideoMode: String { return self._s[893]! } public func Conversation_RestrictedStickersTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[892]!, self._r[892]!, [_0]) + return formatWithArgumentRanges(self._s[894]!, self._r[894]!, [_0]) } - public var Privacy_Calls_AlwaysAllow_Placeholder: String { return self._s[893]! } - public var Conversation_ViewBackground: String { return self._s[894]! } + public var Privacy_Calls_AlwaysAllow_Placeholder: String { return self._s[895]! } + public var Conversation_ViewBackground: String { return self._s[896]! } public func Wallet_Info_TransactionDateHeaderYear(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[895]!, self._r[895]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[897]!, self._r[897]!, [_1, _2, _3]) } - public var Passport_Language_el: String { return self._s[896]! } - public var PhotoEditor_Original: String { return self._s[897]! } - public var Settings_FAQ_Button: String { return self._s[899]! } - public var Channel_Setup_PublicNoLink: String { return self._s[901]! } - public var Conversation_UnsupportedMedia: String { return self._s[902]! } - public var Conversation_SlideToCancel: String { return self._s[903]! } - public var Appearance_ThemePreview_ChatList_4_Name: String { return self._s[904]! } - public var Passport_Identity_OneOfTypeInternalPassport: String { return self._s[905]! } - public var CheckoutInfo_ShippingInfoPostcode: String { return self._s[906]! } - public var Conversation_ReportSpamChannelConfirmation: String { return self._s[907]! } - public var AutoNightTheme_NotAvailable: String { return self._s[908]! } - public var Conversation_Owner: String { return self._s[909]! } - public var Common_Create: String { return self._s[910]! } - public var Settings_ApplyProxyAlertEnable: String { return self._s[911]! } - public var ContactList_Context_Call: String { return self._s[912]! } - public var Localization_ChooseLanguage: String { return self._s[914]! } - public var ChatList_Context_AddToContacts: String { return self._s[916]! } - public var OldChannels_NoticeTitle: String { return self._s[917]! } - public var Settings_Proxy: String { return self._s[919]! } - public var Privacy_TopPeersHelp: String { return self._s[920]! } - public var CheckoutInfo_ShippingInfoCountryPlaceholder: String { return self._s[921]! } - public var Chat_UnsendMyMessages: String { return self._s[922]! } + public var Passport_Language_el: String { return self._s[898]! } + public var PhotoEditor_Original: String { return self._s[899]! } + public var Settings_FAQ_Button: String { return self._s[901]! } + public var Channel_Setup_PublicNoLink: String { return self._s[903]! } + public var Conversation_UnsupportedMedia: String { return self._s[904]! } + public var Conversation_SlideToCancel: String { return self._s[905]! } + public var Appearance_ThemePreview_ChatList_4_Name: String { return self._s[906]! } + public var Passport_Identity_OneOfTypeInternalPassport: String { return self._s[907]! } + public var CheckoutInfo_ShippingInfoPostcode: String { return self._s[908]! } + public var Conversation_ReportSpamChannelConfirmation: String { return self._s[909]! } + public var AutoNightTheme_NotAvailable: String { return self._s[910]! } + public var Conversation_Owner: String { return self._s[911]! } + public var Common_Create: String { return self._s[912]! } + public var Settings_ApplyProxyAlertEnable: String { return self._s[913]! } + public var ContactList_Context_Call: String { return self._s[914]! } + public var Localization_ChooseLanguage: String { return self._s[916]! } + public var ChatList_Context_AddToContacts: String { return self._s[918]! } + public var OldChannels_NoticeTitle: String { return self._s[919]! } + public var Settings_Proxy: String { return self._s[921]! } + public var Privacy_TopPeersHelp: String { return self._s[922]! } + public var CheckoutInfo_ShippingInfoCountryPlaceholder: String { return self._s[923]! } + public var Chat_UnsendMyMessages: String { return self._s[924]! } public func VoiceOver_Chat_Duration(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[923]!, self._r[923]!, [_0]) + return formatWithArgumentRanges(self._s[925]!, self._r[925]!, [_0]) } - public var TwoStepAuth_ConfirmationAbort: String { return self._s[924]! } + public var TwoStepAuth_ConfirmationAbort: String { return self._s[926]! } public func Contacts_AccessDeniedHelpPortrait(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[926]!, self._r[926]!, [_0]) + return formatWithArgumentRanges(self._s[928]!, self._r[928]!, [_0]) } - public var Contacts_SortedByPresence: String { return self._s[927]! } - public var Passport_Identity_SurnamePlaceholder: String { return self._s[928]! } - public var Cache_Title: String { return self._s[929]! } + public var Contacts_SortedByPresence: String { return self._s[929]! } + public var Passport_Identity_SurnamePlaceholder: String { return self._s[930]! } + public var Cache_Title: String { return self._s[931]! } public func Login_PhoneBannedEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[930]!, self._r[930]!, [_0]) + return formatWithArgumentRanges(self._s[932]!, self._r[932]!, [_0]) } - public var TwoStepAuth_EmailCodeExpired: String { return self._s[931]! } - public var Channel_Moderator_Title: String { return self._s[932]! } - public var InstantPage_AutoNightTheme: String { return self._s[934]! } + public var TwoStepAuth_EmailCodeExpired: String { return self._s[933]! } + public var Channel_Moderator_Title: String { return self._s[934]! } + public var InstantPage_AutoNightTheme: String { return self._s[936]! } public func PUSH_MESSAGE_POLL(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[937]!, self._r[937]!, [_1]) + return formatWithArgumentRanges(self._s[939]!, self._r[939]!, [_1]) } - public var Passport_Scans_Upload: String { return self._s[938]! } - public var Undo_Undo: String { return self._s[940]! } - public var Contacts_AccessDeniedHelpON: String { return self._s[941]! } - public var TwoStepAuth_RemovePassword: String { return self._s[942]! } - public var Common_Delete: String { return self._s[943]! } - public var Contacts_AddPeopleNearby: String { return self._s[945]! } - public var Conversation_ContextMenuDelete: String { return self._s[946]! } - public var SocksProxySetup_Credentials: String { return self._s[947]! } - public var Appearance_EditTheme: String { return self._s[949]! } - public var ClearCache_StorageOtherApps: String { return self._s[950]! } - public var PasscodeSettings_AutoLock_Disabled: String { return self._s[951]! } - public var Wallet_Send_NetworkErrorText: String { return self._s[952]! } - public var AuthSessions_DevicesTitle: String { return self._s[954]! } - public var Passport_Address_OneOfTypeRentalAgreement: String { return self._s[956]! } - public var Conversation_ShareBotContactConfirmationTitle: String { return self._s[957]! } - public var Passport_Language_id: String { return self._s[959]! } - public var WallpaperSearch_ColorTeal: String { return self._s[960]! } - public var ChannelIntro_Title: String { return self._s[961]! } + public var Passport_Scans_Upload: String { return self._s[940]! } + public var Undo_Undo: String { return self._s[942]! } + public var Contacts_AccessDeniedHelpON: String { return self._s[943]! } + public var TwoStepAuth_RemovePassword: String { return self._s[944]! } + public var Common_Delete: String { return self._s[945]! } + public var Contacts_AddPeopleNearby: String { return self._s[947]! } + public var Conversation_ContextMenuDelete: String { return self._s[948]! } + public var SocksProxySetup_Credentials: String { return self._s[949]! } + public var Appearance_EditTheme: String { return self._s[951]! } + public var ClearCache_StorageOtherApps: String { return self._s[952]! } + public var PasscodeSettings_AutoLock_Disabled: String { return self._s[953]! } + public var Wallet_Send_NetworkErrorText: String { return self._s[954]! } + public var AuthSessions_DevicesTitle: String { return self._s[956]! } + public var Passport_Address_OneOfTypeRentalAgreement: String { return self._s[958]! } + public var Conversation_ShareBotContactConfirmationTitle: String { return self._s[959]! } + public var Passport_Language_id: String { return self._s[961]! } + public var WallpaperSearch_ColorTeal: String { return self._s[962]! } + public var ChannelIntro_Title: String { return self._s[963]! } public func Channel_AdminLog_MessageToggleSignaturesOff(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[962]!, self._r[962]!, [_0]) + return formatWithArgumentRanges(self._s[964]!, self._r[964]!, [_0]) } - public var VoiceOver_Chat_OpenLinkHint: String { return self._s[964]! } - public var VoiceOver_Chat_Reply: String { return self._s[965]! } - public var ScheduledMessages_BotActionUnavailable: String { return self._s[966]! } - public var Channel_Info_Description: String { return self._s[967]! } - public var Stickers_FavoriteStickers: String { return self._s[968]! } - public var Channel_BanUser_PermissionAddMembers: String { return self._s[969]! } - public var Notifications_DisplayNamesOnLockScreen: String { return self._s[970]! } - public var ChatSearch_ResultsTooltip: String { return self._s[971]! } - public var Wallet_VoiceOver_Editing_ClearText: String { return self._s[972]! } - public var Calls_NoMissedCallsPlacehoder: String { return self._s[973]! } - public var Group_PublicLink_Placeholder: String { return self._s[974]! } - public var Notifications_ExceptionsDefaultSound: String { return self._s[975]! } + public var VoiceOver_Chat_OpenLinkHint: String { return self._s[966]! } + public var VoiceOver_Chat_Reply: String { return self._s[967]! } + public var ScheduledMessages_BotActionUnavailable: String { return self._s[968]! } + public var Channel_Info_Description: String { return self._s[969]! } + public var Stickers_FavoriteStickers: String { return self._s[970]! } + public var Channel_BanUser_PermissionAddMembers: String { return self._s[971]! } + public var Notifications_DisplayNamesOnLockScreen: String { return self._s[972]! } + public var ChatSearch_ResultsTooltip: String { return self._s[973]! } + public var Wallet_VoiceOver_Editing_ClearText: String { return self._s[974]! } + public var Calls_NoMissedCallsPlacehoder: String { return self._s[975]! } + public var Group_PublicLink_Placeholder: String { return self._s[976]! } + public var Notifications_ExceptionsDefaultSound: String { return self._s[977]! } public func PUSH_CHANNEL_MESSAGE_POLL(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[976]!, self._r[976]!, [_1]) + return formatWithArgumentRanges(self._s[978]!, self._r[978]!, [_1]) } - public var TextFormat_Underline: String { return self._s[977]! } + public var TextFormat_Underline: String { return self._s[979]! } public func DialogList_SearchSubtitleFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[979]!, self._r[979]!, [_1, _2]) + return formatWithArgumentRanges(self._s[981]!, self._r[981]!, [_1, _2]) } public func Channel_AdminLog_MessageRemovedGroupStickerPack(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[980]!, self._r[980]!, [_0]) + return formatWithArgumentRanges(self._s[982]!, self._r[982]!, [_0]) } - public var Appearance_ThemePreview_ChatList_3_Name: String { return self._s[981]! } + public var Appearance_ThemePreview_ChatList_3_Name: String { return self._s[983]! } public func Channel_OwnershipTransfer_TransferCompleted(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[982]!, self._r[982]!, [_1, _2]) + return formatWithArgumentRanges(self._s[984]!, self._r[984]!, [_1, _2]) } - public var Wallet_Intro_ImportExisting: String { return self._s[983]! } - public var GroupPermission_Delete: String { return self._s[984]! } - public var Passport_Language_uk: String { return self._s[985]! } - public var StickerPack_HideStickers: String { return self._s[987]! } - public var ChangePhoneNumberNumber_NumberPlaceholder: String { return self._s[988]! } + public var Wallet_Intro_ImportExisting: String { return self._s[985]! } + public var GroupPermission_Delete: String { return self._s[986]! } + public var Passport_Language_uk: String { return self._s[987]! } + public var StickerPack_HideStickers: String { return self._s[989]! } + public var ChangePhoneNumberNumber_NumberPlaceholder: String { return self._s[990]! } public func PUSH_CHAT_MESSAGE_PHOTO(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[989]!, self._r[989]!, [_1, _2]) + return formatWithArgumentRanges(self._s[991]!, self._r[991]!, [_1, _2]) } - public var Activity_UploadingVideoMessage: String { return self._s[990]! } + public var Activity_UploadingVideoMessage: String { return self._s[992]! } public func GroupPermission_ApplyAlertText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[991]!, self._r[991]!, [_0]) + return formatWithArgumentRanges(self._s[993]!, self._r[993]!, [_0]) } - public var Channel_TitleInfo: String { return self._s[992]! } - public var StickerPacksSettings_ArchivedPacks_Info: String { return self._s[993]! } - public var Settings_CallSettings: String { return self._s[994]! } - public var Camera_SquareMode: String { return self._s[995]! } - public var Conversation_SendMessage_ScheduleMessage: String { return self._s[996]! } - public var GroupInfo_SharedMediaNone: String { return self._s[997]! } + public var Channel_TitleInfo: String { return self._s[994]! } + public var StickerPacksSettings_ArchivedPacks_Info: String { return self._s[995]! } + public var Settings_CallSettings: String { return self._s[996]! } + public var Camera_SquareMode: String { return self._s[997]! } + public var Conversation_SendMessage_ScheduleMessage: String { return self._s[998]! } + public var GroupInfo_SharedMediaNone: String { return self._s[999]! } public func PUSH_MESSAGE_VIDEO_SECRET(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[998]!, self._r[998]!, [_1]) + return formatWithArgumentRanges(self._s[1000]!, self._r[1000]!, [_1]) } - public var Bot_GenericBotStatus: String { return self._s[999]! } - public var Application_Update: String { return self._s[1001]! } - public var Month_ShortJanuary: String { return self._s[1002]! } - public var Contacts_PermissionsKeepDisabled: String { return self._s[1003]! } - public var Channel_AdminLog_BanReadMessages: String { return self._s[1004]! } - public var Settings_AppLanguage_Unofficial: String { return self._s[1005]! } - public var Passport_Address_Street2Placeholder: String { return self._s[1006]! } + public var Bot_GenericBotStatus: String { return self._s[1001]! } + public var Application_Update: String { return self._s[1003]! } + public var Month_ShortJanuary: String { return self._s[1004]! } + public var Contacts_PermissionsKeepDisabled: String { return self._s[1005]! } + public var Channel_AdminLog_BanReadMessages: String { return self._s[1006]! } + public var Settings_AppLanguage_Unofficial: String { return self._s[1007]! } + public var Passport_Address_Street2Placeholder: String { return self._s[1008]! } public func Map_LiveLocationShortHour(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1007]!, self._r[1007]!, [_0]) + return formatWithArgumentRanges(self._s[1009]!, self._r[1009]!, [_0]) } - public var NetworkUsageSettings_Cellular: String { return self._s[1008]! } - public var Appearance_PreviewOutgoingText: String { return self._s[1009]! } + public var NetworkUsageSettings_Cellular: String { return self._s[1010]! } + public var Appearance_PreviewOutgoingText: String { return self._s[1011]! } public func StickerPackActionInfo_RemovedText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1010]!, self._r[1010]!, [_0]) + return formatWithArgumentRanges(self._s[1012]!, self._r[1012]!, [_0]) } - public var Notifications_PermissionsAllowInSettings: String { return self._s[1011]! } - public var AutoDownloadSettings_OnForAll: String { return self._s[1013]! } - public var Map_Directions: String { return self._s[1014]! } - public var Passport_FieldIdentityTranslationHelp: String { return self._s[1016]! } - public var Appearance_ThemeDay: String { return self._s[1017]! } - public var LogoutOptions_LogOut: String { return self._s[1018]! } - public var Group_PublicLink_Title: String { return self._s[1020]! } - public var Channel_AddBotErrorNoRights: String { return self._s[1021]! } - public var ChatList_Search_ShowLess: String { return self._s[1022]! } - public var Passport_Identity_AddPassport: String { return self._s[1023]! } - public var LocalGroup_ButtonTitle: String { return self._s[1024]! } - public var Call_Message: String { return self._s[1025]! } - public var PhotoEditor_ExposureTool: String { return self._s[1026]! } - public var Wallet_Receive_CommentInfo: String { return self._s[1028]! } - public var Passport_FieldOneOf_Delimeter: String { return self._s[1029]! } - public var Channel_AdminLog_CanBanUsers: String { return self._s[1031]! } - public var Appearance_ThemePreview_ChatList_2_Name: String { return self._s[1032]! } - public var Appearance_Preview: String { return self._s[1033]! } - public var Compose_ChannelMembers: String { return self._s[1034]! } - public var Conversation_DeleteManyMessages: String { return self._s[1035]! } - public var ReportPeer_ReasonOther_Title: String { return self._s[1036]! } - public var Checkout_ErrorProviderAccountTimeout: String { return self._s[1037]! } - public var TwoStepAuth_ResetAccountConfirmation: String { return self._s[1038]! } - public var Channel_Stickers_CreateYourOwn: String { return self._s[1041]! } - public var Conversation_UpdateTelegram: String { return self._s[1042]! } - public var EditTheme_Create_TopInfo: String { return self._s[1043]! } + public var Notifications_PermissionsAllowInSettings: String { return self._s[1013]! } + public var AutoDownloadSettings_OnForAll: String { return self._s[1015]! } + public var Map_Directions: String { return self._s[1016]! } + public var Passport_FieldIdentityTranslationHelp: String { return self._s[1018]! } + public var Appearance_ThemeDay: String { return self._s[1019]! } + public var LogoutOptions_LogOut: String { return self._s[1020]! } + public var Group_PublicLink_Title: String { return self._s[1022]! } + public var Channel_AddBotErrorNoRights: String { return self._s[1023]! } + public var ChatList_Search_ShowLess: String { return self._s[1024]! } + public var Passport_Identity_AddPassport: String { return self._s[1025]! } + public var LocalGroup_ButtonTitle: String { return self._s[1026]! } + public var Call_Message: String { return self._s[1027]! } + public var PhotoEditor_ExposureTool: String { return self._s[1028]! } + public var Wallet_Receive_CommentInfo: String { return self._s[1030]! } + public var Passport_FieldOneOf_Delimeter: String { return self._s[1031]! } + public var Channel_AdminLog_CanBanUsers: String { return self._s[1033]! } + public var Appearance_ThemePreview_ChatList_2_Name: String { return self._s[1034]! } + public var Appearance_Preview: String { return self._s[1035]! } + public var Compose_ChannelMembers: String { return self._s[1036]! } + public var Conversation_DeleteManyMessages: String { return self._s[1037]! } + public var ReportPeer_ReasonOther_Title: String { return self._s[1038]! } + public var Checkout_ErrorProviderAccountTimeout: String { return self._s[1039]! } + public var TwoStepAuth_ResetAccountConfirmation: String { return self._s[1040]! } + public var Channel_Stickers_CreateYourOwn: String { return self._s[1043]! } + public var Conversation_UpdateTelegram: String { return self._s[1044]! } + public var EditTheme_Create_TopInfo: String { return self._s[1045]! } public func Notification_PinnedPhotoMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1044]!, self._r[1044]!, [_0]) + return formatWithArgumentRanges(self._s[1046]!, self._r[1046]!, [_0]) } - public var Wallet_WordCheck_Continue: String { return self._s[1045]! } - public var TwoFactorSetup_Hint_Action: String { return self._s[1046]! } - public var IntentsSettings_ResetAll: String { return self._s[1047]! } + public var Wallet_WordCheck_Continue: String { return self._s[1047]! } + public var TwoFactorSetup_Hint_Action: String { return self._s[1048]! } + public var IntentsSettings_ResetAll: String { return self._s[1049]! } public func PUSH_PINNED_GIF(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1048]!, self._r[1048]!, [_1]) + return formatWithArgumentRanges(self._s[1050]!, self._r[1050]!, [_1]) } - public var GroupInfo_Administrators_Title: String { return self._s[1049]! } - public var Privacy_Forwards_PreviewMessageText: String { return self._s[1050]! } + public var GroupInfo_Administrators_Title: String { return self._s[1051]! } + public var Privacy_Forwards_PreviewMessageText: String { return self._s[1052]! } public func PrivacySettings_LastSeenNobodyPlus(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1051]!, self._r[1051]!, [_0]) + return formatWithArgumentRanges(self._s[1053]!, self._r[1053]!, [_0]) } - public var Tour_Title3: String { return self._s[1052]! } - public var Channel_EditAdmin_PermissionInviteSubscribers: String { return self._s[1053]! } - public var Clipboard_SendPhoto: String { return self._s[1057]! } - public var MediaPicker_Videos: String { return self._s[1058]! } - public var Passport_Email_Title: String { return self._s[1059]! } + public var Tour_Title3: String { return self._s[1054]! } + public var Channel_EditAdmin_PermissionInviteSubscribers: String { return self._s[1055]! } + public var Clipboard_SendPhoto: String { return self._s[1059]! } + public var MediaPicker_Videos: String { return self._s[1060]! } + public var Passport_Email_Title: String { return self._s[1061]! } public func PrivacySettings_LastSeenEverybodyMinus(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1060]!, self._r[1060]!, [_0]) + return formatWithArgumentRanges(self._s[1062]!, self._r[1062]!, [_0]) } - public var StickerPacksSettings_Title: String { return self._s[1061]! } - public var Conversation_MessageDialogDelete: String { return self._s[1062]! } - public var Privacy_Calls_CustomHelp: String { return self._s[1064]! } - public var Message_Wallpaper: String { return self._s[1065]! } - public var MemberSearch_BotSection: String { return self._s[1066]! } - public var GroupInfo_SetSound: String { return self._s[1067]! } - public var Core_ServiceUserStatus: String { return self._s[1068]! } - public var LiveLocationUpdated_JustNow: String { return self._s[1069]! } - public var Call_StatusFailed: String { return self._s[1070]! } - public var TwoFactorSetup_Email_Placeholder: String { return self._s[1071]! } - public var TwoStepAuth_SetupPasswordDescription: String { return self._s[1072]! } - public var TwoStepAuth_SetPassword: String { return self._s[1073]! } - public var Permissions_PeopleNearbyText_v0: String { return self._s[1074]! } + public var StickerPacksSettings_Title: String { return self._s[1063]! } + public var Conversation_MessageDialogDelete: String { return self._s[1064]! } + public var Privacy_Calls_CustomHelp: String { return self._s[1066]! } + public var Message_Wallpaper: String { return self._s[1067]! } + public var MemberSearch_BotSection: String { return self._s[1068]! } + public var GroupInfo_SetSound: String { return self._s[1069]! } + public var Core_ServiceUserStatus: String { return self._s[1070]! } + public var LiveLocationUpdated_JustNow: String { return self._s[1071]! } + public var Call_StatusFailed: String { return self._s[1072]! } + public var TwoFactorSetup_Email_Placeholder: String { return self._s[1073]! } + public var TwoStepAuth_SetupPasswordDescription: String { return self._s[1074]! } + public var TwoStepAuth_SetPassword: String { return self._s[1075]! } + public var Permissions_PeopleNearbyText_v0: String { return self._s[1076]! } public func SocksProxySetup_ProxyStatusPing(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1076]!, self._r[1076]!, [_0]) + return formatWithArgumentRanges(self._s[1078]!, self._r[1078]!, [_0]) } - public var Calls_SubmitRating: String { return self._s[1077]! } - public var Map_NoPlacesNearby: String { return self._s[1078]! } - public var Profile_Username: String { return self._s[1079]! } - public var Bot_DescriptionTitle: String { return self._s[1080]! } - public var MaskStickerSettings_Title: String { return self._s[1081]! } - public var SharedMedia_CategoryOther: String { return self._s[1082]! } - public var GroupInfo_SetGroupPhoto: String { return self._s[1083]! } - public var Common_NotNow: String { return self._s[1084]! } - public var CallFeedback_IncludeLogsInfo: String { return self._s[1085]! } - public var Conversation_ShareMyPhoneNumber: String { return self._s[1086]! } - public var Map_Location: String { return self._s[1087]! } - public var Invitation_JoinGroup: String { return self._s[1088]! } - public var AutoDownloadSettings_Title: String { return self._s[1090]! } - public var Conversation_DiscardVoiceMessageDescription: String { return self._s[1091]! } - public var Channel_ErrorAddBlocked: String { return self._s[1092]! } - public var Conversation_UnblockUser: String { return self._s[1093]! } - public var EditTheme_Edit_TopInfo: String { return self._s[1094]! } - public var Watch_Bot_Restart: String { return self._s[1095]! } - public var TwoStepAuth_Title: String { return self._s[1096]! } - public var Channel_AdminLog_BanSendMessages: String { return self._s[1097]! } - public var Checkout_ShippingMethod: String { return self._s[1098]! } - public var Passport_Identity_OneOfTypeIdentityCard: String { return self._s[1099]! } + public var Calls_SubmitRating: String { return self._s[1079]! } + public var Map_NoPlacesNearby: String { return self._s[1080]! } + public var Profile_Username: String { return self._s[1081]! } + public var Bot_DescriptionTitle: String { return self._s[1082]! } + public var MaskStickerSettings_Title: String { return self._s[1083]! } + public var SharedMedia_CategoryOther: String { return self._s[1084]! } + public var GroupInfo_SetGroupPhoto: String { return self._s[1085]! } + public var Common_NotNow: String { return self._s[1086]! } + public var CallFeedback_IncludeLogsInfo: String { return self._s[1087]! } + public var Conversation_ShareMyPhoneNumber: String { return self._s[1088]! } + public var Map_Location: String { return self._s[1089]! } + public var Invitation_JoinGroup: String { return self._s[1090]! } + public var AutoDownloadSettings_Title: String { return self._s[1092]! } + public var Conversation_DiscardVoiceMessageDescription: String { return self._s[1093]! } + public var Channel_ErrorAddBlocked: String { return self._s[1094]! } + public var Conversation_UnblockUser: String { return self._s[1095]! } + public var EditTheme_Edit_TopInfo: String { return self._s[1096]! } + public var Watch_Bot_Restart: String { return self._s[1097]! } + public var TwoStepAuth_Title: String { return self._s[1098]! } + public var Channel_AdminLog_BanSendMessages: String { return self._s[1099]! } + public var Checkout_ShippingMethod: String { return self._s[1100]! } + public var Passport_Identity_OneOfTypeIdentityCard: String { return self._s[1101]! } public func PUSH_CHAT_MESSAGE_STICKER(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1100]!, self._r[1100]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1102]!, self._r[1102]!, [_1, _2, _3]) } - public var EditTheme_ChangeColors: String { return self._s[1102]! } + public var EditTheme_ChangeColors: String { return self._s[1104]! } public func Chat_UnsendMyMessagesAlertTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1103]!, self._r[1103]!, [_0]) + return formatWithArgumentRanges(self._s[1105]!, self._r[1105]!, [_0]) } public func Channel_Username_LinkHint(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1104]!, self._r[1104]!, [_0]) + return formatWithArgumentRanges(self._s[1106]!, self._r[1106]!, [_0]) } - public var Appearance_ThemePreview_ChatList_1_Name: String { return self._s[1105]! } - public var SettingsSearch_Synonyms_Data_AutoplayGifs: String { return self._s[1106]! } - public var AuthSessions_TerminateOtherSessions: String { return self._s[1107]! } - public var Contacts_FailedToSendInvitesMessage: String { return self._s[1108]! } - public var PrivacySettings_TwoStepAuth: String { return self._s[1109]! } - public var Notification_Exceptions_PreviewAlwaysOn: String { return self._s[1110]! } - public var SettingsSearch_Synonyms_Privacy_Passcode: String { return self._s[1111]! } - public var Conversation_EditingMessagePanelMedia: String { return self._s[1112]! } - public var Checkout_PaymentMethod_Title: String { return self._s[1113]! } - public var SocksProxySetup_Connection: String { return self._s[1114]! } - public var Group_MessagePhotoRemoved: String { return self._s[1115]! } - public var Channel_Stickers_NotFound: String { return self._s[1118]! } - public var Group_About_Help: String { return self._s[1119]! } - public var Notification_PassportValueProofOfIdentity: String { return self._s[1120]! } - public var PeopleNearby_Title: String { return self._s[1122]! } + public var Appearance_ThemePreview_ChatList_1_Name: String { return self._s[1107]! } + public var SettingsSearch_Synonyms_Data_AutoplayGifs: String { return self._s[1108]! } + public var AuthSessions_TerminateOtherSessions: String { return self._s[1109]! } + public var Contacts_FailedToSendInvitesMessage: String { return self._s[1110]! } + public var PrivacySettings_TwoStepAuth: String { return self._s[1111]! } + public var Notification_Exceptions_PreviewAlwaysOn: String { return self._s[1112]! } + public var SettingsSearch_Synonyms_Privacy_Passcode: String { return self._s[1113]! } + public var Conversation_EditingMessagePanelMedia: String { return self._s[1114]! } + public var Checkout_PaymentMethod_Title: String { return self._s[1115]! } + public var SocksProxySetup_Connection: String { return self._s[1116]! } + public var Group_MessagePhotoRemoved: String { return self._s[1117]! } + public var Channel_Stickers_NotFound: String { return self._s[1120]! } + public var Group_About_Help: String { return self._s[1121]! } + public var Notification_PassportValueProofOfIdentity: String { return self._s[1122]! } + public var PeopleNearby_Title: String { return self._s[1124]! } public func ApplyLanguage_ChangeLanguageOfficialText(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1123]!, self._r[1123]!, [_1]) + return formatWithArgumentRanges(self._s[1125]!, self._r[1125]!, [_1]) } - public var Map_Home: String { return self._s[1124]! } - public var CheckoutInfo_ShippingInfoStatePlaceholder: String { return self._s[1126]! } - public var Notifications_GroupNotificationsExceptionsHelp: String { return self._s[1127]! } - public var SocksProxySetup_Password: String { return self._s[1128]! } - public var Notifications_PermissionsEnable: String { return self._s[1129]! } - public var TwoStepAuth_ChangeEmail: String { return self._s[1131]! } + public var Map_Home: String { return self._s[1126]! } + public var CheckoutInfo_ShippingInfoStatePlaceholder: String { return self._s[1128]! } + public var Notifications_GroupNotificationsExceptionsHelp: String { return self._s[1129]! } + public var SocksProxySetup_Password: String { return self._s[1130]! } + public var Notifications_PermissionsEnable: String { return self._s[1131]! } + public var TwoStepAuth_ChangeEmail: String { return self._s[1133]! } public func Channel_AdminLog_MessageInvitedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1132]!, self._r[1132]!, [_1]) + return formatWithArgumentRanges(self._s[1134]!, self._r[1134]!, [_1]) } public func Time_MonthOfYear_m10(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1134]!, self._r[1134]!, [_0]) + return formatWithArgumentRanges(self._s[1136]!, self._r[1136]!, [_0]) } - public var Passport_Identity_TypeDriversLicense: String { return self._s[1135]! } - public var ArchivedPacksAlert_Title: String { return self._s[1136]! } - public var Wallet_Receive_InvoiceUrlCopied: String { return self._s[1137]! } - public var Map_PlacesNearby: String { return self._s[1138]! } + public var Passport_Identity_TypeDriversLicense: String { return self._s[1137]! } + public var ArchivedPacksAlert_Title: String { return self._s[1138]! } + public var Wallet_Receive_InvoiceUrlCopied: String { return self._s[1139]! } + public var Map_PlacesNearby: String { return self._s[1140]! } public func Time_PreciseDate_m7(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1139]!, self._r[1139]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1141]!, self._r[1141]!, [_1, _2, _3]) } - public var PrivacyLastSeenSettings_GroupsAndChannelsHelp: String { return self._s[1140]! } - public var Privacy_Calls_NeverAllow_Placeholder: String { return self._s[1142]! } - public var Conversation_StatusTyping: String { return self._s[1143]! } - public var Broadcast_AdminLog_EmptyText: String { return self._s[1144]! } - public var Notification_PassportValueProofOfAddress: String { return self._s[1145]! } - public var UserInfo_CreateNewContact: String { return self._s[1146]! } - public var Passport_Identity_FrontSide: String { return self._s[1147]! } - public var Login_PhoneNumberAlreadyAuthorizedSwitch: String { return self._s[1148]! } - public var Calls_CallTabTitle: String { return self._s[1149]! } - public var Channel_AdminLog_ChannelEmptyText: String { return self._s[1150]! } + public var PrivacyLastSeenSettings_GroupsAndChannelsHelp: String { return self._s[1142]! } + public var Privacy_Calls_NeverAllow_Placeholder: String { return self._s[1144]! } + public var Conversation_StatusTyping: String { return self._s[1145]! } + public var Broadcast_AdminLog_EmptyText: String { return self._s[1146]! } + public var Notification_PassportValueProofOfAddress: String { return self._s[1147]! } + public var UserInfo_CreateNewContact: String { return self._s[1148]! } + public var Passport_Identity_FrontSide: String { return self._s[1149]! } + public var Login_PhoneNumberAlreadyAuthorizedSwitch: String { return self._s[1150]! } + public var Calls_CallTabTitle: String { return self._s[1151]! } + public var Channel_AdminLog_ChannelEmptyText: String { return self._s[1152]! } public func Login_BannedPhoneBody(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1152]!, self._r[1152]!, [_0]) + return formatWithArgumentRanges(self._s[1154]!, self._r[1154]!, [_0]) } - public var Watch_UserInfo_MuteTitle: String { return self._s[1153]! } - public var Group_EditAdmin_RankAdminPlaceholder: String { return self._s[1154]! } - public var SharedMedia_EmptyMusicText: String { return self._s[1155]! } - public var Wallet_Completed_Text: String { return self._s[1156]! } - public var PasscodeSettings_AutoLock_IfAwayFor_1minute: String { return self._s[1157]! } - public var Paint_Stickers: String { return self._s[1158]! } - public var Privacy_GroupsAndChannels: String { return self._s[1159]! } - public var ChatList_Context_Delete: String { return self._s[1161]! } - public var UserInfo_AddContact: String { return self._s[1162]! } + public var Watch_UserInfo_MuteTitle: String { return self._s[1155]! } + public var Group_EditAdmin_RankAdminPlaceholder: String { return self._s[1156]! } + public var SharedMedia_EmptyMusicText: String { return self._s[1157]! } + public var Wallet_Completed_Text: String { return self._s[1158]! } + public var PasscodeSettings_AutoLock_IfAwayFor_1minute: String { return self._s[1159]! } + public var Paint_Stickers: String { return self._s[1160]! } + public var Privacy_GroupsAndChannels: String { return self._s[1161]! } + public var ChatList_Context_Delete: String { return self._s[1163]! } + public var UserInfo_AddContact: String { return self._s[1164]! } public func Conversation_MessageViaUser(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1163]!, self._r[1163]!, [_0]) + return formatWithArgumentRanges(self._s[1165]!, self._r[1165]!, [_0]) } - public var PhoneNumberHelp_ChangeNumber: String { return self._s[1165]! } + public var PhoneNumberHelp_ChangeNumber: String { return self._s[1167]! } public func ChatList_ClearChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1167]!, self._r[1167]!, [_0]) + return formatWithArgumentRanges(self._s[1169]!, self._r[1169]!, [_0]) } - public var DialogList_NoMessagesTitle: String { return self._s[1168]! } - public var EditProfile_NameAndPhotoHelp: String { return self._s[1169]! } - public var BlockedUsers_BlockUser: String { return self._s[1170]! } - public var Notifications_PermissionsOpenSettings: String { return self._s[1171]! } - public var MediaPicker_UngroupDescription: String { return self._s[1173]! } - public var Watch_NoConnection: String { return self._s[1174]! } - public var Month_GenSeptember: String { return self._s[1175]! } - public var Conversation_ViewGroup: String { return self._s[1177]! } - public var Channel_AdminLogFilter_EventsLeavingSubscribers: String { return self._s[1180]! } - public var Privacy_Forwards_AlwaysLink: String { return self._s[1181]! } - public var Channel_OwnershipTransfer_ErrorAdminsTooMuch: String { return self._s[1182]! } - public var Passport_FieldOneOf_FinalDelimeter: String { return self._s[1183]! } - public var Wallet_WordCheck_IncorrectHeader: String { return self._s[1184]! } - public var MediaPicker_CameraRoll: String { return self._s[1186]! } - public var Month_GenAugust: String { return self._s[1187]! } - public var Wallet_Configuration_SourceHeader: String { return self._s[1188]! } - public var AccessDenied_VideoMessageMicrophone: String { return self._s[1189]! } - public var SharedMedia_EmptyText: String { return self._s[1190]! } - public var Map_ShareLiveLocation: String { return self._s[1191]! } - public var Calls_All: String { return self._s[1192]! } - public var Map_SendThisPlace: String { return self._s[1194]! } - public var Appearance_ThemeNight: String { return self._s[1196]! } - public var Conversation_HoldForAudio: String { return self._s[1197]! } - public var SettingsSearch_Synonyms_Support: String { return self._s[1200]! } - public var GroupInfo_GroupHistoryHidden: String { return self._s[1201]! } - public var SocksProxySetup_Secret: String { return self._s[1202]! } + public var DialogList_NoMessagesTitle: String { return self._s[1170]! } + public var EditProfile_NameAndPhotoHelp: String { return self._s[1171]! } + public var BlockedUsers_BlockUser: String { return self._s[1172]! } + public var Notifications_PermissionsOpenSettings: String { return self._s[1173]! } + public var MediaPicker_UngroupDescription: String { return self._s[1175]! } + public var Watch_NoConnection: String { return self._s[1176]! } + public var Month_GenSeptember: String { return self._s[1177]! } + public var Conversation_ViewGroup: String { return self._s[1179]! } + public var Channel_AdminLogFilter_EventsLeavingSubscribers: String { return self._s[1182]! } + public var Privacy_Forwards_AlwaysLink: String { return self._s[1183]! } + public var Channel_OwnershipTransfer_ErrorAdminsTooMuch: String { return self._s[1184]! } + public var Passport_FieldOneOf_FinalDelimeter: String { return self._s[1185]! } + public var Wallet_WordCheck_IncorrectHeader: String { return self._s[1186]! } + public var MediaPicker_CameraRoll: String { return self._s[1188]! } + public var Month_GenAugust: String { return self._s[1189]! } + public var Wallet_Configuration_SourceHeader: String { return self._s[1190]! } + public var AccessDenied_VideoMessageMicrophone: String { return self._s[1191]! } + public var SharedMedia_EmptyText: String { return self._s[1192]! } + public var Map_ShareLiveLocation: String { return self._s[1193]! } + public var Calls_All: String { return self._s[1194]! } + public var Map_SendThisPlace: String { return self._s[1196]! } + public var Appearance_ThemeNight: String { return self._s[1198]! } + public var Conversation_HoldForAudio: String { return self._s[1199]! } + public var SettingsSearch_Synonyms_Support: String { return self._s[1202]! } + public var GroupInfo_GroupHistoryHidden: String { return self._s[1203]! } + public var SocksProxySetup_Secret: String { return self._s[1204]! } public func Activity_RemindAboutChannel(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1203]!, self._r[1203]!, [_0]) + return formatWithArgumentRanges(self._s[1205]!, self._r[1205]!, [_0]) } - public var Channel_BanList_RestrictedTitle: String { return self._s[1205]! } - public var Conversation_Location: String { return self._s[1206]! } + public var Channel_BanList_RestrictedTitle: String { return self._s[1207]! } + public var Conversation_Location: String { return self._s[1208]! } public func AutoDownloadSettings_UpToFor(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1207]!, self._r[1207]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1209]!, self._r[1209]!, [_1, _2]) } - public var ChatSettings_AutoDownloadPhotos: String { return self._s[1209]! } - public var SettingsSearch_Synonyms_Privacy_Title: String { return self._s[1210]! } - public var Notifications_PermissionsText: String { return self._s[1211]! } - public var SettingsSearch_Synonyms_Data_SaveIncomingPhotos: String { return self._s[1212]! } - public var Call_Flip: String { return self._s[1213]! } - public var Channel_AdminLog_CanDeleteMessagesOfOthers: String { return self._s[1215]! } - public var SocksProxySetup_ProxyStatusConnecting: String { return self._s[1216]! } - public var Wallet_TransactionInfo_StorageFeeInfoUrl: String { return self._s[1217]! } - public var PrivacyPhoneNumberSettings_DiscoveryHeader: String { return self._s[1218]! } - public var Channel_EditAdmin_PermissionPinMessages: String { return self._s[1220]! } - public var TwoStepAuth_ReEnterPasswordDescription: String { return self._s[1222]! } - public var Channel_TooMuchBots: String { return self._s[1224]! } - public var Passport_DeletePassportConfirmation: String { return self._s[1225]! } - public var Login_InvalidCodeError: String { return self._s[1226]! } - public var StickerPacksSettings_FeaturedPacks: String { return self._s[1227]! } + public var ChatSettings_AutoDownloadPhotos: String { return self._s[1211]! } + public var SettingsSearch_Synonyms_Privacy_Title: String { return self._s[1212]! } + public var Notifications_PermissionsText: String { return self._s[1213]! } + public var SettingsSearch_Synonyms_Data_SaveIncomingPhotos: String { return self._s[1214]! } + public var Call_Flip: String { return self._s[1215]! } + public var Channel_AdminLog_CanDeleteMessagesOfOthers: String { return self._s[1217]! } + public var SocksProxySetup_ProxyStatusConnecting: String { return self._s[1218]! } + public var Wallet_TransactionInfo_StorageFeeInfoUrl: String { return self._s[1219]! } + public var PrivacyPhoneNumberSettings_DiscoveryHeader: String { return self._s[1220]! } + public var Channel_EditAdmin_PermissionPinMessages: String { return self._s[1222]! } + public var TwoStepAuth_ReEnterPasswordDescription: String { return self._s[1224]! } + public var Channel_TooMuchBots: String { return self._s[1226]! } + public var Passport_DeletePassportConfirmation: String { return self._s[1227]! } + public var Login_InvalidCodeError: String { return self._s[1228]! } + public var StickerPacksSettings_FeaturedPacks: String { return self._s[1229]! } public func ChatList_DeleteSecretChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1228]!, self._r[1228]!, [_0]) + return formatWithArgumentRanges(self._s[1230]!, self._r[1230]!, [_0]) } public func GroupInfo_InvitationLinkAcceptChannel(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1229]!, self._r[1229]!, [_0]) + return formatWithArgumentRanges(self._s[1231]!, self._r[1231]!, [_0]) } - public var VoiceOver_Navigation_ProxySettings: String { return self._s[1230]! } - public var Call_CallInProgressTitle: String { return self._s[1231]! } - public var Month_ShortSeptember: String { return self._s[1232]! } - public var Watch_ChannelInfo_Title: String { return self._s[1233]! } - public var ChatList_DeleteSavedMessagesConfirmation: String { return self._s[1236]! } - public var DialogList_PasscodeLockHelp: String { return self._s[1237]! } - public var Chat_MultipleTextMessagesDisabled: String { return self._s[1238]! } - public var Wallet_Receive_Title: String { return self._s[1239]! } - public var Notifications_Badge_IncludePublicGroups: String { return self._s[1240]! } - public var Channel_AdminLogFilter_EventsTitle: String { return self._s[1241]! } - public var PhotoEditor_CropReset: String { return self._s[1242]! } - public var Group_Username_CreatePrivateLinkHelp: String { return self._s[1244]! } - public var Channel_Management_LabelEditor: String { return self._s[1245]! } - public var Passport_Identity_LatinNameHelp: String { return self._s[1247]! } - public var PhotoEditor_HighlightsTool: String { return self._s[1248]! } - public var Wallet_Info_WalletCreated: String { return self._s[1249]! } - public var UserInfo_Title: String { return self._s[1250]! } - public var ChatList_HideAction: String { return self._s[1251]! } - public var AccessDenied_Title: String { return self._s[1252]! } - public var DialogList_SearchLabel: String { return self._s[1253]! } - public var Group_Setup_HistoryHidden: String { return self._s[1254]! } - public var TwoStepAuth_PasswordChangeSuccess: String { return self._s[1255]! } - public var State_Updating: String { return self._s[1257]! } - public var Contacts_TabTitle: String { return self._s[1258]! } - public var Notifications_Badge_CountUnreadMessages: String { return self._s[1260]! } - public var GroupInfo_GroupHistory: String { return self._s[1261]! } - public var Conversation_UnsupportedMediaPlaceholder: String { return self._s[1262]! } - public var Wallpaper_SetColor: String { return self._s[1263]! } - public var CheckoutInfo_ShippingInfoCountry: String { return self._s[1264]! } - public var SettingsSearch_Synonyms_SavedMessages: String { return self._s[1265]! } - public var Chat_AttachmentLimitReached: String { return self._s[1266]! } - public var Passport_Identity_OneOfTypeDriversLicense: String { return self._s[1267]! } - public var Contacts_NotRegisteredSection: String { return self._s[1268]! } + public var VoiceOver_Navigation_ProxySettings: String { return self._s[1232]! } + public var Call_CallInProgressTitle: String { return self._s[1233]! } + public var Month_ShortSeptember: String { return self._s[1234]! } + public var Watch_ChannelInfo_Title: String { return self._s[1235]! } + public var ChatList_DeleteSavedMessagesConfirmation: String { return self._s[1238]! } + public var DialogList_PasscodeLockHelp: String { return self._s[1239]! } + public var Chat_MultipleTextMessagesDisabled: String { return self._s[1240]! } + public var Wallet_Receive_Title: String { return self._s[1241]! } + public var Notifications_Badge_IncludePublicGroups: String { return self._s[1242]! } + public var Channel_AdminLogFilter_EventsTitle: String { return self._s[1243]! } + public var PhotoEditor_CropReset: String { return self._s[1244]! } + public var Group_Username_CreatePrivateLinkHelp: String { return self._s[1246]! } + public var Channel_Management_LabelEditor: String { return self._s[1247]! } + public var Passport_Identity_LatinNameHelp: String { return self._s[1249]! } + public var PhotoEditor_HighlightsTool: String { return self._s[1250]! } + public var Wallet_Info_WalletCreated: String { return self._s[1251]! } + public var UserInfo_Title: String { return self._s[1252]! } + public var ChatList_HideAction: String { return self._s[1253]! } + public var AccessDenied_Title: String { return self._s[1254]! } + public var DialogList_SearchLabel: String { return self._s[1255]! } + public var Group_Setup_HistoryHidden: String { return self._s[1256]! } + public var TwoStepAuth_PasswordChangeSuccess: String { return self._s[1257]! } + public var State_Updating: String { return self._s[1259]! } + public var Contacts_TabTitle: String { return self._s[1260]! } + public var Notifications_Badge_CountUnreadMessages: String { return self._s[1262]! } + public var GroupInfo_GroupHistory: String { return self._s[1263]! } + public var Conversation_UnsupportedMediaPlaceholder: String { return self._s[1264]! } + public var Wallpaper_SetColor: String { return self._s[1265]! } + public var CheckoutInfo_ShippingInfoCountry: String { return self._s[1266]! } + public var SettingsSearch_Synonyms_SavedMessages: String { return self._s[1267]! } + public var Chat_AttachmentLimitReached: String { return self._s[1268]! } + public var Passport_Identity_OneOfTypeDriversLicense: String { return self._s[1269]! } + public var Contacts_NotRegisteredSection: String { return self._s[1270]! } public func Time_PreciseDate_m4(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1269]!, self._r[1269]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1271]!, self._r[1271]!, [_1, _2, _3]) } - public var Paint_Clear: String { return self._s[1270]! } - public var StickerPacksSettings_ArchivedMasks: String { return self._s[1271]! } - public var SocksProxySetup_Connecting: String { return self._s[1272]! } - public var ExplicitContent_AlertChannel: String { return self._s[1273]! } - public var CreatePoll_AllOptionsAdded: String { return self._s[1274]! } - public var Conversation_Contact: String { return self._s[1275]! } - public var Login_CodeExpired: String { return self._s[1276]! } - public var Passport_DiscardMessageAction: String { return self._s[1277]! } - public var ChatList_Context_Unpin: String { return self._s[1278]! } - public var Channel_AdminLog_MessagePreviousDescription: String { return self._s[1279]! } + public var Paint_Clear: String { return self._s[1272]! } + public var StickerPacksSettings_ArchivedMasks: String { return self._s[1273]! } + public var SocksProxySetup_Connecting: String { return self._s[1274]! } + public var ExplicitContent_AlertChannel: String { return self._s[1275]! } + public var CreatePoll_AllOptionsAdded: String { return self._s[1276]! } + public var Conversation_Contact: String { return self._s[1277]! } + public var Login_CodeExpired: String { return self._s[1278]! } + public var Passport_DiscardMessageAction: String { return self._s[1279]! } + public var ChatList_Context_Unpin: String { return self._s[1280]! } + public var Channel_AdminLog_MessagePreviousDescription: String { return self._s[1281]! } public func VoiceOver_Chat_MusicFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1280]!, self._r[1280]!, [_0]) + return formatWithArgumentRanges(self._s[1282]!, self._r[1282]!, [_0]) } - public var Channel_AdminLog_EmptyMessageText: String { return self._s[1281]! } - public var SettingsSearch_Synonyms_Data_NetworkUsage: String { return self._s[1282]! } + public var Channel_AdminLog_EmptyMessageText: String { return self._s[1283]! } + public var SettingsSearch_Synonyms_Data_NetworkUsage: String { return self._s[1284]! } public func Group_EditAdmin_RankInfo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1283]!, self._r[1283]!, [_0]) + return formatWithArgumentRanges(self._s[1285]!, self._r[1285]!, [_0]) } - public var Month_ShortApril: String { return self._s[1284]! } - public var AuthSessions_CurrentSession: String { return self._s[1285]! } - public var Chat_AttachmentMultipleFilesDisabled: String { return self._s[1288]! } - public var Wallet_Navigation_Cancel: String { return self._s[1290]! } - public var WallpaperPreview_CropTopText: String { return self._s[1291]! } - public var PrivacySettings_DeleteAccountIfAwayFor: String { return self._s[1292]! } - public var CheckoutInfo_ShippingInfoTitle: String { return self._s[1293]! } + public var Month_ShortApril: String { return self._s[1286]! } + public var AuthSessions_CurrentSession: String { return self._s[1287]! } + public var Chat_AttachmentMultipleFilesDisabled: String { return self._s[1290]! } + public var Wallet_Navigation_Cancel: String { return self._s[1292]! } + public var WallpaperPreview_CropTopText: String { return self._s[1293]! } + public var PrivacySettings_DeleteAccountIfAwayFor: String { return self._s[1294]! } + public var CheckoutInfo_ShippingInfoTitle: String { return self._s[1295]! } public func Conversation_ScheduleMessage_SendOn(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1294]!, self._r[1294]!, [_0, _1]) + return formatWithArgumentRanges(self._s[1296]!, self._r[1296]!, [_0, _1]) } - public var Appearance_ThemePreview_Chat_2_Text: String { return self._s[1295]! } - public var Channel_Setup_TypePrivate: String { return self._s[1297]! } - public var Forward_ChannelReadOnly: String { return self._s[1300]! } - public var PhotoEditor_CurvesBlue: String { return self._s[1301]! } - public var AddContact_SharedContactException: String { return self._s[1302]! } - public var UserInfo_BotPrivacy: String { return self._s[1304]! } - public var Wallet_CreateInvoice_Title: String { return self._s[1305]! } - public var Notification_PassportValueEmail: String { return self._s[1306]! } - public var EmptyGroupInfo_Subtitle: String { return self._s[1307]! } - public var GroupPermission_NewTitle: String { return self._s[1308]! } - public var CallFeedback_ReasonDropped: String { return self._s[1309]! } - public var GroupInfo_Permissions_AddException: String { return self._s[1310]! } - public var Channel_SignMessages_Help: String { return self._s[1312]! } - public var Undo_ChatDeleted: String { return self._s[1314]! } - public var Conversation_ChatBackground: String { return self._s[1315]! } + public var Appearance_ThemePreview_Chat_2_Text: String { return self._s[1297]! } + public var Channel_Setup_TypePrivate: String { return self._s[1299]! } + public var Forward_ChannelReadOnly: String { return self._s[1302]! } + public var PhotoEditor_CurvesBlue: String { return self._s[1303]! } + public var AddContact_SharedContactException: String { return self._s[1304]! } + public var UserInfo_BotPrivacy: String { return self._s[1306]! } + public var Wallet_CreateInvoice_Title: String { return self._s[1307]! } + public var Notification_PassportValueEmail: String { return self._s[1308]! } + public var EmptyGroupInfo_Subtitle: String { return self._s[1309]! } + public var GroupPermission_NewTitle: String { return self._s[1310]! } + public var CallFeedback_ReasonDropped: String { return self._s[1311]! } + public var GroupInfo_Permissions_AddException: String { return self._s[1312]! } + public var Channel_SignMessages_Help: String { return self._s[1314]! } + public var Undo_ChatDeleted: String { return self._s[1316]! } + public var Conversation_ChatBackground: String { return self._s[1317]! } public func Wallet_WordCheck_Text(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1316]!, self._r[1316]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1318]!, self._r[1318]!, [_1, _2, _3]) } public func PUSH_CHAT_MESSAGE_QUIZ(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1317]!, self._r[1317]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1319]!, self._r[1319]!, [_1, _2, _3]) } - public var ChannelMembers_WhoCanAddMembers_Admins: String { return self._s[1318]! } - public var FastTwoStepSetup_EmailPlaceholder: String { return self._s[1319]! } - public var Passport_Language_pt: String { return self._s[1320]! } - public var VoiceOver_Chat_YourVoiceMessage: String { return self._s[1321]! } - public var NotificationsSound_Popcorn: String { return self._s[1324]! } - public var AutoNightTheme_Disabled: String { return self._s[1325]! } - public var BlockedUsers_LeavePrefix: String { return self._s[1326]! } - public var WallpaperPreview_CustomColorTopText: String { return self._s[1327]! } - public var Contacts_PermissionsSuppressWarningText: String { return self._s[1328]! } - public var WallpaperSearch_ColorBlue: String { return self._s[1329]! } + public var ChannelMembers_WhoCanAddMembers_Admins: String { return self._s[1320]! } + public var FastTwoStepSetup_EmailPlaceholder: String { return self._s[1321]! } + public var Passport_Language_pt: String { return self._s[1322]! } + public var VoiceOver_Chat_YourVoiceMessage: String { return self._s[1323]! } + public var NotificationsSound_Popcorn: String { return self._s[1326]! } + public var AutoNightTheme_Disabled: String { return self._s[1327]! } + public var BlockedUsers_LeavePrefix: String { return self._s[1328]! } + public var WallpaperPreview_CustomColorTopText: String { return self._s[1329]! } + public var Contacts_PermissionsSuppressWarningText: String { return self._s[1330]! } + public var WallpaperSearch_ColorBlue: String { return self._s[1331]! } public func CancelResetAccount_TextSMS(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1330]!, self._r[1330]!, [_0]) + return formatWithArgumentRanges(self._s[1332]!, self._r[1332]!, [_0]) } - public var CheckoutInfo_ErrorNameInvalid: String { return self._s[1331]! } - public var SocksProxySetup_UseForCalls: String { return self._s[1332]! } - public var Passport_DeleteDocumentConfirmation: String { return self._s[1334]! } + public var CheckoutInfo_ErrorNameInvalid: String { return self._s[1333]! } + public var SocksProxySetup_UseForCalls: String { return self._s[1334]! } + public var Passport_DeleteDocumentConfirmation: String { return self._s[1336]! } public func Conversation_Megabytes(_ _0: Float) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1335]!, self._r[1335]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[1337]!, self._r[1337]!, ["\(_0)"]) } - public var SocksProxySetup_Hostname: String { return self._s[1338]! } - public var ChatSettings_AutoDownloadSettings_OffForAll: String { return self._s[1339]! } - public var Compose_NewEncryptedChat: String { return self._s[1340]! } - public var Login_CodeFloodError: String { return self._s[1341]! } - public var Calls_TabTitle: String { return self._s[1342]! } - public var Privacy_ProfilePhoto: String { return self._s[1343]! } - public var Passport_Language_he: String { return self._s[1344]! } + public var SocksProxySetup_Hostname: String { return self._s[1340]! } + public var ChatSettings_AutoDownloadSettings_OffForAll: String { return self._s[1341]! } + public var Compose_NewEncryptedChat: String { return self._s[1342]! } + public var Login_CodeFloodError: String { return self._s[1343]! } + public var Calls_TabTitle: String { return self._s[1344]! } + public var Privacy_ProfilePhoto: String { return self._s[1345]! } + public var Passport_Language_he: String { return self._s[1346]! } public func Conversation_SetReminder_RemindToday(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1345]!, self._r[1345]!, [_0]) - } - public var GroupPermission_Title: String { return self._s[1346]! } - public func Channel_AdminLog_MessageGroupPreHistoryHidden(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[1347]!, self._r[1347]!, [_0]) } - public var Wallet_TransactionInfo_SenderHeader: String { return self._s[1348]! } - public var GroupPermission_NoChangeInfo: String { return self._s[1349]! } - public var ChatList_DeleteForCurrentUser: String { return self._s[1350]! } - public var Tour_Text1: String { return self._s[1351]! } - public var Channel_EditAdmin_TransferOwnership: String { return self._s[1352]! } - public var Month_ShortFebruary: String { return self._s[1353]! } - public var TwoStepAuth_EmailSkip: String { return self._s[1354]! } + public var GroupPermission_Title: String { return self._s[1348]! } + public func Channel_AdminLog_MessageGroupPreHistoryHidden(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1349]!, self._r[1349]!, [_0]) + } + public var Wallet_TransactionInfo_SenderHeader: String { return self._s[1350]! } + public var GroupPermission_NoChangeInfo: String { return self._s[1351]! } + public var ChatList_DeleteForCurrentUser: String { return self._s[1352]! } + public var Tour_Text1: String { return self._s[1353]! } + public var Channel_EditAdmin_TransferOwnership: String { return self._s[1354]! } + public var Month_ShortFebruary: String { return self._s[1355]! } + public var TwoStepAuth_EmailSkip: String { return self._s[1356]! } public func Wallet_Time_PreciseDate_m4(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1355]!, self._r[1355]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1357]!, self._r[1357]!, [_1, _2, _3]) } - public var NotificationsSound_Glass: String { return self._s[1356]! } - public var Appearance_ThemeNightBlue: String { return self._s[1357]! } - public var CheckoutInfo_Pay: String { return self._s[1358]! } - public var Invite_LargeRecipientsCountWarning: String { return self._s[1360]! } - public var Call_CallAgain: String { return self._s[1362]! } - public var AttachmentMenu_SendAsFile: String { return self._s[1363]! } - public var AccessDenied_MicrophoneRestricted: String { return self._s[1364]! } - public var Passport_InvalidPasswordError: String { return self._s[1365]! } - public var Watch_Message_Game: String { return self._s[1366]! } - public var Stickers_Install: String { return self._s[1367]! } - public var VoiceOver_Chat_Message: String { return self._s[1368]! } - public var PrivacyLastSeenSettings_NeverShareWith: String { return self._s[1369]! } - public var Passport_Identity_ResidenceCountry: String { return self._s[1371]! } - public var Notifications_GroupNotificationsHelp: String { return self._s[1372]! } - public var AuthSessions_OtherSessions: String { return self._s[1373]! } - public var Channel_Username_Help: String { return self._s[1374]! } - public var Camera_Title: String { return self._s[1375]! } - public var IntentsSettings_Title: String { return self._s[1376]! } - public var GroupInfo_SetGroupPhotoDelete: String { return self._s[1378]! } - public var Privacy_ProfilePhoto_NeverShareWith_Title: String { return self._s[1379]! } - public var Channel_AdminLog_SendPolls: String { return self._s[1380]! } - public var Channel_AdminLog_TitleAllEvents: String { return self._s[1381]! } - public var Channel_EditAdmin_PermissionInviteMembers: String { return self._s[1382]! } - public var Contacts_MemberSearchSectionTitleGroup: String { return self._s[1383]! } - public var ScheduledMessages_DeleteMany: String { return self._s[1384]! } - public var Conversation_RestrictedStickers: String { return self._s[1385]! } - public var Notifications_ExceptionsResetToDefaults: String { return self._s[1387]! } - public var UserInfo_TelegramCall: String { return self._s[1389]! } - public var TwoStepAuth_SetupResendEmailCode: String { return self._s[1390]! } - public var CreatePoll_OptionsHeader: String { return self._s[1391]! } - public var SettingsSearch_Synonyms_Data_CallsUseLessData: String { return self._s[1392]! } - public var ArchivedChats_IntroTitle1: String { return self._s[1393]! } - public var Privacy_GroupsAndChannels_AlwaysAllow_Title: String { return self._s[1394]! } - public var Theme_Colors_Proceed: String { return self._s[1395]! } - public var Passport_Identity_EditPersonalDetails: String { return self._s[1396]! } + public var NotificationsSound_Glass: String { return self._s[1358]! } + public var Appearance_ThemeNightBlue: String { return self._s[1359]! } + public var CheckoutInfo_Pay: String { return self._s[1360]! } + public var Invite_LargeRecipientsCountWarning: String { return self._s[1362]! } + public var Call_CallAgain: String { return self._s[1364]! } + public var AttachmentMenu_SendAsFile: String { return self._s[1365]! } + public var AccessDenied_MicrophoneRestricted: String { return self._s[1366]! } + public var Passport_InvalidPasswordError: String { return self._s[1367]! } + public var Watch_Message_Game: String { return self._s[1368]! } + public var Stickers_Install: String { return self._s[1369]! } + public var VoiceOver_Chat_Message: String { return self._s[1370]! } + public var PrivacyLastSeenSettings_NeverShareWith: String { return self._s[1371]! } + public var Passport_Identity_ResidenceCountry: String { return self._s[1373]! } + public var Notifications_GroupNotificationsHelp: String { return self._s[1374]! } + public var AuthSessions_OtherSessions: String { return self._s[1375]! } + public var Channel_Username_Help: String { return self._s[1376]! } + public var Camera_Title: String { return self._s[1377]! } + public var IntentsSettings_Title: String { return self._s[1378]! } + public var GroupInfo_SetGroupPhotoDelete: String { return self._s[1380]! } + public var Privacy_ProfilePhoto_NeverShareWith_Title: String { return self._s[1381]! } + public var Channel_AdminLog_SendPolls: String { return self._s[1382]! } + public var Channel_AdminLog_TitleAllEvents: String { return self._s[1383]! } + public var Channel_EditAdmin_PermissionInviteMembers: String { return self._s[1384]! } + public var Contacts_MemberSearchSectionTitleGroup: String { return self._s[1385]! } + public var ScheduledMessages_DeleteMany: String { return self._s[1386]! } + public var Conversation_RestrictedStickers: String { return self._s[1387]! } + public var Notifications_ExceptionsResetToDefaults: String { return self._s[1389]! } + public var UserInfo_TelegramCall: String { return self._s[1391]! } + public var TwoStepAuth_SetupResendEmailCode: String { return self._s[1392]! } + public var CreatePoll_OptionsHeader: String { return self._s[1393]! } + public var SettingsSearch_Synonyms_Data_CallsUseLessData: String { return self._s[1394]! } + public var ArchivedChats_IntroTitle1: String { return self._s[1395]! } + public var Privacy_GroupsAndChannels_AlwaysAllow_Title: String { return self._s[1396]! } + public var Theme_Colors_Proceed: String { return self._s[1397]! } + public var Passport_Identity_EditPersonalDetails: String { return self._s[1398]! } public func Time_PreciseDate_m1(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1397]!, self._r[1397]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1399]!, self._r[1399]!, [_1, _2, _3]) } - public var Wallet_Month_GenAugust: String { return self._s[1398]! } - public var Settings_SaveEditedPhotos: String { return self._s[1399]! } - public var TwoStepAuth_ConfirmationTitle: String { return self._s[1400]! } - public var Privacy_GroupsAndChannels_NeverAllow_Title: String { return self._s[1401]! } - public var Conversation_MessageDialogRetry: String { return self._s[1402]! } - public var ChatList_Context_MarkAsUnread: String { return self._s[1403]! } - public var MessagePoll_SubmitVote: String { return self._s[1404]! } - public var Conversation_DiscardVoiceMessageAction: String { return self._s[1405]! } - public var Permissions_PeopleNearbyTitle_v0: String { return self._s[1406]! } - public var Group_Setup_TypeHeader: String { return self._s[1407]! } - public var Paint_RecentStickers: String { return self._s[1408]! } - public var PhotoEditor_GrainTool: String { return self._s[1409]! } - public var CheckoutInfo_ShippingInfoState: String { return self._s[1410]! } - public var EmptyGroupInfo_Line4: String { return self._s[1411]! } - public var Watch_AuthRequired: String { return self._s[1413]! } + public var Wallet_Month_GenAugust: String { return self._s[1400]! } + public var Settings_SaveEditedPhotos: String { return self._s[1401]! } + public var TwoStepAuth_ConfirmationTitle: String { return self._s[1402]! } + public var Privacy_GroupsAndChannels_NeverAllow_Title: String { return self._s[1403]! } + public var Conversation_MessageDialogRetry: String { return self._s[1404]! } + public var ChatList_Context_MarkAsUnread: String { return self._s[1405]! } + public var MessagePoll_SubmitVote: String { return self._s[1406]! } + public var Conversation_DiscardVoiceMessageAction: String { return self._s[1407]! } + public var Permissions_PeopleNearbyTitle_v0: String { return self._s[1408]! } + public var Group_Setup_TypeHeader: String { return self._s[1409]! } + public var Paint_RecentStickers: String { return self._s[1410]! } + public var PhotoEditor_GrainTool: String { return self._s[1411]! } + public var CheckoutInfo_ShippingInfoState: String { return self._s[1412]! } + public var EmptyGroupInfo_Line4: String { return self._s[1413]! } + public var Watch_AuthRequired: String { return self._s[1415]! } public func Passport_Email_UseTelegramEmail(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1414]!, self._r[1414]!, [_0]) + return formatWithArgumentRanges(self._s[1416]!, self._r[1416]!, [_0]) } - public var Conversation_EncryptedDescriptionTitle: String { return self._s[1415]! } - public var ChannelIntro_Text: String { return self._s[1416]! } - public var DialogList_DeleteBotConfirmation: String { return self._s[1417]! } - public var GroupPermission_NoSendMedia: String { return self._s[1418]! } - public var Calls_AddTab: String { return self._s[1419]! } - public var Message_ReplyActionButtonShowReceipt: String { return self._s[1420]! } - public var Channel_AdminLog_EmptyFilterText: String { return self._s[1421]! } - public var Conversation_WalletRequiredSetup: String { return self._s[1422]! } - public var Notification_MessageLifetime1d: String { return self._s[1423]! } - public var Notifications_ChannelNotificationsExceptionsHelp: String { return self._s[1424]! } - public var Channel_BanUser_PermissionsHeader: String { return self._s[1425]! } - public var Passport_Identity_GenderFemale: String { return self._s[1426]! } - public var BlockedUsers_BlockTitle: String { return self._s[1427]! } + public var Conversation_EncryptedDescriptionTitle: String { return self._s[1417]! } + public var ChannelIntro_Text: String { return self._s[1418]! } + public var DialogList_DeleteBotConfirmation: String { return self._s[1419]! } + public var GroupPermission_NoSendMedia: String { return self._s[1420]! } + public var Calls_AddTab: String { return self._s[1421]! } + public var Message_ReplyActionButtonShowReceipt: String { return self._s[1422]! } + public var Channel_AdminLog_EmptyFilterText: String { return self._s[1423]! } + public var Conversation_WalletRequiredSetup: String { return self._s[1424]! } + public var Notification_MessageLifetime1d: String { return self._s[1425]! } + public var Notifications_ChannelNotificationsExceptionsHelp: String { return self._s[1426]! } + public var Channel_BanUser_PermissionsHeader: String { return self._s[1427]! } + public var Passport_Identity_GenderFemale: String { return self._s[1428]! } + public var BlockedUsers_BlockTitle: String { return self._s[1429]! } public func PUSH_CHANNEL_MESSAGE_GIF(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1428]!, self._r[1428]!, [_1]) + return formatWithArgumentRanges(self._s[1430]!, self._r[1430]!, [_1]) } - public var Weekday_Yesterday: String { return self._s[1429]! } - public var WallpaperSearch_ColorBlack: String { return self._s[1430]! } - public var Settings_Context_Logout: String { return self._s[1431]! } - public var Wallet_Info_UnknownTransaction: String { return self._s[1432]! } - public var ChatList_ArchiveAction: String { return self._s[1433]! } - public var AutoNightTheme_Scheduled: String { return self._s[1434]! } - public var TwoFactorSetup_Email_SkipAction: String { return self._s[1435]! } - public var Settings_Devices: String { return self._s[1436]! } - public var ContactInfo_Note: String { return self._s[1437]! } + public var Weekday_Yesterday: String { return self._s[1431]! } + public var WallpaperSearch_ColorBlack: String { return self._s[1432]! } + public var Settings_Context_Logout: String { return self._s[1433]! } + public var Wallet_Info_UnknownTransaction: String { return self._s[1434]! } + public var ChatList_ArchiveAction: String { return self._s[1435]! } + public var AutoNightTheme_Scheduled: String { return self._s[1436]! } + public var TwoFactorSetup_Email_SkipAction: String { return self._s[1437]! } + public var Settings_Devices: String { return self._s[1438]! } + public var ContactInfo_Note: String { return self._s[1439]! } public func Login_PhoneGenericEmailBody(_ _1: String, _ _2: String, _ _3: String, _ _4: String, _ _5: String, _ _6: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1438]!, self._r[1438]!, [_1, _2, _3, _4, _5, _6]) + return formatWithArgumentRanges(self._s[1440]!, self._r[1440]!, [_1, _2, _3, _4, _5, _6]) } - public var EditTheme_ThemeTemplateAlertTitle: String { return self._s[1439]! } - public var Wallet_Receive_CreateInvoice: String { return self._s[1440]! } - public var PrivacyPolicy_DeclineDeleteNow: String { return self._s[1441]! } - public var Theme_Colors_ColorWallpaperWarningProceed: String { return self._s[1442]! } + public var EditTheme_ThemeTemplateAlertTitle: String { return self._s[1441]! } + public var Wallet_Receive_CreateInvoice: String { return self._s[1442]! } + public var PrivacyPolicy_DeclineDeleteNow: String { return self._s[1443]! } + public var Theme_Colors_ColorWallpaperWarningProceed: String { return self._s[1444]! } public func PUSH_CHAT_JOINED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1443]!, self._r[1443]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1445]!, self._r[1445]!, [_1, _2]) } - public var CreatePoll_Create: String { return self._s[1444]! } - public var Channel_Members_AddBannedErrorAdmin: String { return self._s[1445]! } + public var CreatePoll_Create: String { return self._s[1446]! } + public var Channel_Members_AddBannedErrorAdmin: String { return self._s[1447]! } public func Notification_CallFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1446]!, self._r[1446]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1448]!, self._r[1448]!, [_1, _2]) } - public var ScheduledMessages_ClearAllConfirmation: String { return self._s[1447]! } - public var Checkout_ErrorProviderAccountInvalid: String { return self._s[1448]! } - public var Notifications_InAppNotificationsSounds: String { return self._s[1450]! } + public var ScheduledMessages_ClearAllConfirmation: String { return self._s[1449]! } + public var Checkout_ErrorProviderAccountInvalid: String { return self._s[1450]! } + public var Notifications_InAppNotificationsSounds: String { return self._s[1452]! } public func PUSH_PINNED_GAME_SCORE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1451]!, self._r[1451]!, [_1]) + return formatWithArgumentRanges(self._s[1453]!, self._r[1453]!, [_1]) } - public var Preview_OpenInInstagram: String { return self._s[1452]! } - public var Notification_MessageLifetimeRemovedOutgoing: String { return self._s[1453]! } + public var Preview_OpenInInstagram: String { return self._s[1454]! } + public var Notification_MessageLifetimeRemovedOutgoing: String { return self._s[1455]! } public func PUSH_CHAT_ADD_MEMBER(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1454]!, self._r[1454]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1456]!, self._r[1456]!, [_1, _2, _3]) } public func Passport_PrivacyPolicy(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1455]!, self._r[1455]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1457]!, self._r[1457]!, [_1, _2]) } - public var Channel_AdminLog_InfoPanelAlertTitle: String { return self._s[1456]! } - public var ArchivedChats_IntroText3: String { return self._s[1457]! } - public var ChatList_UndoArchiveHiddenText: String { return self._s[1458]! } - public var NetworkUsageSettings_TotalSection: String { return self._s[1459]! } - public var Wallet_Month_GenSeptember: String { return self._s[1460]! } - public var Channel_Setup_TypePrivateHelp: String { return self._s[1461]! } + public var Channel_AdminLog_InfoPanelAlertTitle: String { return self._s[1458]! } + public var ArchivedChats_IntroText3: String { return self._s[1459]! } + public var ChatList_UndoArchiveHiddenText: String { return self._s[1460]! } + public var NetworkUsageSettings_TotalSection: String { return self._s[1461]! } + public var Wallet_Month_GenSeptember: String { return self._s[1462]! } + public var Channel_Setup_TypePrivateHelp: String { return self._s[1463]! } public func PUSH_CHAT_MESSAGE_POLL(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1462]!, self._r[1462]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1464]!, self._r[1464]!, [_1, _2, _3]) } - public var Privacy_GroupsAndChannels_NeverAllow_Placeholder: String { return self._s[1464]! } - public var FastTwoStepSetup_HintSection: String { return self._s[1465]! } - public var Wallpaper_PhotoLibrary: String { return self._s[1466]! } - public var TwoStepAuth_SetupResendEmailCodeAlert: String { return self._s[1467]! } - public var Gif_NoGifsFound: String { return self._s[1468]! } - public var Watch_LastSeen_WithinAMonth: String { return self._s[1469]! } - public var VoiceOver_MessageContextDelete: String { return self._s[1470]! } - public var EditTheme_Preview: String { return self._s[1471]! } + public var Privacy_GroupsAndChannels_NeverAllow_Placeholder: String { return self._s[1466]! } + public var FastTwoStepSetup_HintSection: String { return self._s[1467]! } + public var Wallpaper_PhotoLibrary: String { return self._s[1468]! } + public var TwoStepAuth_SetupResendEmailCodeAlert: String { return self._s[1469]! } + public var Gif_NoGifsFound: String { return self._s[1470]! } + public var Watch_LastSeen_WithinAMonth: String { return self._s[1471]! } + public var VoiceOver_MessageContextDelete: String { return self._s[1472]! } + public var EditTheme_Preview: String { return self._s[1473]! } public func ClearCache_StorageTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1472]!, self._r[1472]!, [_0]) + return formatWithArgumentRanges(self._s[1474]!, self._r[1474]!, [_0]) } - public var GroupInfo_ActionPromote: String { return self._s[1473]! } - public var PasscodeSettings_SimplePasscode: String { return self._s[1474]! } - public var GroupInfo_Permissions_Title: String { return self._s[1475]! } - public var Permissions_ContactsText_v0: String { return self._s[1476]! } - public var PrivacyPhoneNumberSettings_CustomDisabledHelp: String { return self._s[1477]! } - public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedPublicGroups: String { return self._s[1478]! } - public var PrivacySettings_DataSettingsHelp: String { return self._s[1481]! } - public var Passport_FieldEmailHelp: String { return self._s[1482]! } + public var GroupInfo_ActionPromote: String { return self._s[1475]! } + public var PasscodeSettings_SimplePasscode: String { return self._s[1476]! } + public var GroupInfo_Permissions_Title: String { return self._s[1477]! } + public var Permissions_ContactsText_v0: String { return self._s[1478]! } + public var PrivacyPhoneNumberSettings_CustomDisabledHelp: String { return self._s[1479]! } + public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedPublicGroups: String { return self._s[1480]! } + public var PrivacySettings_DataSettingsHelp: String { return self._s[1483]! } + public var Passport_FieldEmailHelp: String { return self._s[1484]! } public func Activity_RemindAboutUser(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1483]!, self._r[1483]!, [_0]) + return formatWithArgumentRanges(self._s[1485]!, self._r[1485]!, [_0]) } - public var Passport_Identity_GenderPlaceholder: String { return self._s[1484]! } - public var Weekday_ShortSaturday: String { return self._s[1485]! } - public var ContactInfo_PhoneLabelMain: String { return self._s[1486]! } - public var Watch_Conversation_UserInfo: String { return self._s[1487]! } - public var CheckoutInfo_ShippingInfoCityPlaceholder: String { return self._s[1488]! } - public var GroupPermission_PermissionDisabledByDefault: String { return self._s[1489]! } - public var PrivacyLastSeenSettings_Title: String { return self._s[1490]! } - public var Conversation_ShareBotLocationConfirmation: String { return self._s[1491]! } - public var PhotoEditor_VignetteTool: String { return self._s[1492]! } - public var Passport_Address_Street1Placeholder: String { return self._s[1493]! } - public var Passport_Language_et: String { return self._s[1494]! } - public var AppUpgrade_Running: String { return self._s[1495]! } - public var Channel_DiscussionGroup_Info: String { return self._s[1497]! } - public var EditTheme_Create_Preview_IncomingReplyName: String { return self._s[1498]! } - public var Passport_Language_bg: String { return self._s[1499]! } - public var Stickers_NoStickersFound: String { return self._s[1501]! } + public var Passport_Identity_GenderPlaceholder: String { return self._s[1486]! } + public var Weekday_ShortSaturday: String { return self._s[1487]! } + public var ContactInfo_PhoneLabelMain: String { return self._s[1488]! } + public var Watch_Conversation_UserInfo: String { return self._s[1489]! } + public var CheckoutInfo_ShippingInfoCityPlaceholder: String { return self._s[1490]! } + public var GroupPermission_PermissionDisabledByDefault: String { return self._s[1491]! } + public var PrivacyLastSeenSettings_Title: String { return self._s[1492]! } + public var Conversation_ShareBotLocationConfirmation: String { return self._s[1493]! } + public var PhotoEditor_VignetteTool: String { return self._s[1494]! } + public var Passport_Address_Street1Placeholder: String { return self._s[1495]! } + public var Passport_Language_et: String { return self._s[1496]! } + public var AppUpgrade_Running: String { return self._s[1497]! } + public var Channel_DiscussionGroup_Info: String { return self._s[1499]! } + public var EditTheme_Create_Preview_IncomingReplyName: String { return self._s[1500]! } + public var Passport_Language_bg: String { return self._s[1501]! } + public var Stickers_NoStickersFound: String { return self._s[1503]! } public func PUSH_CHANNEL_MESSAGE_TEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1503]!, self._r[1503]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1505]!, self._r[1505]!, [_1, _2]) } public func VoiceOver_Chat_ContactFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1504]!, self._r[1504]!, [_0]) + return formatWithArgumentRanges(self._s[1506]!, self._r[1506]!, [_0]) } - public var Wallet_Month_GenJuly: String { return self._s[1505]! } - public var Wallet_Receive_AddressHeader: String { return self._s[1506]! } - public var Wallet_Send_AmountText: String { return self._s[1507]! } - public var Settings_About: String { return self._s[1508]! } + public var Wallet_Month_GenJuly: String { return self._s[1507]! } + public var Wallet_Receive_AddressHeader: String { return self._s[1508]! } + public var Wallet_Send_AmountText: String { return self._s[1509]! } + public var Settings_About: String { return self._s[1510]! } public func Channel_AdminLog_MessageRestricted(_ _0: String, _ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1509]!, self._r[1509]!, [_0, _1, _2]) + return formatWithArgumentRanges(self._s[1511]!, self._r[1511]!, [_0, _1, _2]) } - public var ChatList_Context_MarkAsRead: String { return self._s[1511]! } - public var KeyCommand_NewMessage: String { return self._s[1512]! } - public var Group_ErrorAddBlocked: String { return self._s[1513]! } + public var ChatList_Context_MarkAsRead: String { return self._s[1513]! } + public var KeyCommand_NewMessage: String { return self._s[1514]! } + public var Group_ErrorAddBlocked: String { return self._s[1515]! } public func Message_PaymentSent(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1514]!, self._r[1514]!, [_0]) + return formatWithArgumentRanges(self._s[1516]!, self._r[1516]!, [_0]) } - public var Map_LocationTitle: String { return self._s[1515]! } - public var ReportGroupLocation_Title: String { return self._s[1516]! } - public var CallSettings_UseLessDataLongDescription: String { return self._s[1517]! } - public var Cache_ClearProgress: String { return self._s[1518]! } + public var Map_LocationTitle: String { return self._s[1517]! } + public var ReportGroupLocation_Title: String { return self._s[1518]! } + public var CallSettings_UseLessDataLongDescription: String { return self._s[1519]! } + public var Cache_ClearProgress: String { return self._s[1520]! } public func Channel_Management_ErrorNotMember(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1519]!, self._r[1519]!, [_0]) + return formatWithArgumentRanges(self._s[1521]!, self._r[1521]!, [_0]) } - public var GroupRemoved_AddToGroup: String { return self._s[1520]! } - public var Passport_UpdateRequiredError: String { return self._s[1521]! } - public var Wallet_SecureStorageNotAvailable_Text: String { return self._s[1522]! } + public var GroupRemoved_AddToGroup: String { return self._s[1522]! } + public var Passport_UpdateRequiredError: String { return self._s[1523]! } + public var Wallet_SecureStorageNotAvailable_Text: String { return self._s[1524]! } public func PUSH_MESSAGE_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1523]!, self._r[1523]!, [_1]) + return formatWithArgumentRanges(self._s[1525]!, self._r[1525]!, [_1]) } - public var Notifications_PermissionsSuppressWarningText: String { return self._s[1525]! } - public var Passport_Identity_MainPageHelp: String { return self._s[1526]! } - public var Conversation_StatusKickedFromGroup: String { return self._s[1527]! } - public var Passport_Language_ka: String { return self._s[1528]! } + public var Notifications_PermissionsSuppressWarningText: String { return self._s[1527]! } + public var Passport_Identity_MainPageHelp: String { return self._s[1528]! } + public var Conversation_StatusKickedFromGroup: String { return self._s[1529]! } + public var Passport_Language_ka: String { return self._s[1530]! } public func Wallet_Time_PreciseDate_m12(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1529]!, self._r[1529]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1531]!, self._r[1531]!, [_1, _2, _3]) } - public var Call_Decline: String { return self._s[1530]! } - public var SocksProxySetup_ProxyEnabled: String { return self._s[1531]! } - public var TwoFactorSetup_Email_SkipConfirmationText: String { return self._s[1534]! } + public var Call_Decline: String { return self._s[1532]! } + public var SocksProxySetup_ProxyEnabled: String { return self._s[1533]! } + public var TwoFactorSetup_Email_SkipConfirmationText: String { return self._s[1536]! } public func AuthCode_Alert(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1535]!, self._r[1535]!, [_0]) + return formatWithArgumentRanges(self._s[1537]!, self._r[1537]!, [_0]) } - public var CallFeedback_Send: String { return self._s[1536]! } - public var EditTheme_EditTitle: String { return self._s[1537]! } + public var CallFeedback_Send: String { return self._s[1538]! } + public var EditTheme_EditTitle: String { return self._s[1539]! } public func Channel_AdminLog_MessagePromotedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1538]!, self._r[1538]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1540]!, self._r[1540]!, [_1, _2]) } - public var Passport_Phone_UseTelegramNumberHelp: String { return self._s[1539]! } + public var Passport_Phone_UseTelegramNumberHelp: String { return self._s[1541]! } public func Wallet_Updated_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1541]!, self._r[1541]!, [_0]) + return formatWithArgumentRanges(self._s[1543]!, self._r[1543]!, [_0]) } - public var SettingsSearch_Synonyms_Data_Title: String { return self._s[1542]! } - public var Passport_DeletePassport: String { return self._s[1543]! } - public var Appearance_AppIconFilled: String { return self._s[1544]! } - public var Privacy_Calls_P2PAlways: String { return self._s[1545]! } - public var Month_ShortDecember: String { return self._s[1546]! } - public var Channel_AdminLog_CanEditMessages: String { return self._s[1548]! } + public var SettingsSearch_Synonyms_Data_Title: String { return self._s[1544]! } + public var Passport_DeletePassport: String { return self._s[1545]! } + public var Appearance_AppIconFilled: String { return self._s[1546]! } + public var Privacy_Calls_P2PAlways: String { return self._s[1547]! } + public var Month_ShortDecember: String { return self._s[1548]! } + public var Channel_AdminLog_CanEditMessages: String { return self._s[1550]! } public func Contacts_AccessDeniedHelpLandscape(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1549]!, self._r[1549]!, [_0]) + return formatWithArgumentRanges(self._s[1551]!, self._r[1551]!, [_0]) } - public var Channel_Stickers_Searching: String { return self._s[1550]! } - public var Conversation_EncryptedDescription1: String { return self._s[1551]! } - public var Conversation_EncryptedDescription2: String { return self._s[1552]! } - public var PasscodeSettings_PasscodeOptions: String { return self._s[1553]! } - public var Conversation_EncryptedDescription3: String { return self._s[1555]! } - public var PhotoEditor_SharpenTool: String { return self._s[1556]! } - public var Wallet_Configuration_Title: String { return self._s[1557]! } + public var Channel_Stickers_Searching: String { return self._s[1552]! } + public var Conversation_EncryptedDescription1: String { return self._s[1553]! } + public var Conversation_EncryptedDescription2: String { return self._s[1554]! } + public var PasscodeSettings_PasscodeOptions: String { return self._s[1555]! } + public var Conversation_EncryptedDescription3: String { return self._s[1557]! } + public var PhotoEditor_SharpenTool: String { return self._s[1558]! } + public var Wallet_Configuration_Title: String { return self._s[1559]! } public func Conversation_AddNameToContacts(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1558]!, self._r[1558]!, [_0]) + return formatWithArgumentRanges(self._s[1560]!, self._r[1560]!, [_0]) } - public var Conversation_EncryptedDescription4: String { return self._s[1560]! } - public var Channel_Members_AddMembers: String { return self._s[1561]! } - public var Wallpaper_Search: String { return self._s[1562]! } - public var Weekday_Friday: String { return self._s[1564]! } - public var Privacy_ContactsSync: String { return self._s[1565]! } - public var SettingsSearch_Synonyms_Privacy_Data_ContactsReset: String { return self._s[1566]! } - public var ApplyLanguage_ChangeLanguageAction: String { return self._s[1567]! } + public var Conversation_EncryptedDescription4: String { return self._s[1562]! } + public var Channel_Members_AddMembers: String { return self._s[1563]! } + public var Wallpaper_Search: String { return self._s[1564]! } + public var Weekday_Friday: String { return self._s[1566]! } + public var Privacy_ContactsSync: String { return self._s[1567]! } + public var SettingsSearch_Synonyms_Privacy_Data_ContactsReset: String { return self._s[1568]! } + public var ApplyLanguage_ChangeLanguageAction: String { return self._s[1569]! } public func Channel_Management_RestrictedBy(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1568]!, self._r[1568]!, [_0]) + return formatWithArgumentRanges(self._s[1570]!, self._r[1570]!, [_0]) } - public var Wallet_Configuration_BlockchainIdHeader: String { return self._s[1569]! } - public var GroupInfo_Permissions_Removed: String { return self._s[1570]! } - public var ScheduledMessages_ScheduledOnline: String { return self._s[1571]! } - public var Passport_Identity_GenderMale: String { return self._s[1572]! } + public var Wallet_Configuration_BlockchainIdHeader: String { return self._s[1571]! } + public var GroupInfo_Permissions_Removed: String { return self._s[1572]! } + public var ScheduledMessages_ScheduledOnline: String { return self._s[1573]! } + public var Passport_Identity_GenderMale: String { return self._s[1574]! } public func Call_StatusBar(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1573]!, self._r[1573]!, [_0]) + return formatWithArgumentRanges(self._s[1575]!, self._r[1575]!, [_0]) } - public var Notifications_PermissionsKeepDisabled: String { return self._s[1574]! } - public var Conversation_JumpToDate: String { return self._s[1575]! } - public var Contacts_GlobalSearch: String { return self._s[1576]! } - public var AutoDownloadSettings_ResetHelp: String { return self._s[1577]! } - public var SettingsSearch_Synonyms_FAQ: String { return self._s[1578]! } - public var Profile_MessageLifetime1d: String { return self._s[1579]! } + public var Notifications_PermissionsKeepDisabled: String { return self._s[1576]! } + public var Conversation_JumpToDate: String { return self._s[1577]! } + public var Contacts_GlobalSearch: String { return self._s[1578]! } + public var AutoDownloadSettings_ResetHelp: String { return self._s[1579]! } + public var SettingsSearch_Synonyms_FAQ: String { return self._s[1580]! } + public var Profile_MessageLifetime1d: String { return self._s[1581]! } public func MESSAGE_INVOICE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1580]!, self._r[1580]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1582]!, self._r[1582]!, [_1, _2]) } - public var StickerPack_BuiltinPackName: String { return self._s[1583]! } + public var StickerPack_BuiltinPackName: String { return self._s[1585]! } public func PUSH_CHAT_MESSAGE_AUDIO(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1584]!, self._r[1584]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1586]!, self._r[1586]!, [_1, _2]) } - public var VoiceOver_Chat_RecordModeVoiceMessageInfo: String { return self._s[1585]! } - public var Passport_InfoTitle: String { return self._s[1587]! } - public var Notifications_PermissionsUnreachableText: String { return self._s[1588]! } + public var VoiceOver_Chat_RecordModeVoiceMessageInfo: String { return self._s[1587]! } + public var Passport_InfoTitle: String { return self._s[1589]! } + public var Notifications_PermissionsUnreachableText: String { return self._s[1590]! } public func NetworkUsageSettings_CellularUsageSince(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1592]!, self._r[1592]!, [_0]) + return formatWithArgumentRanges(self._s[1594]!, self._r[1594]!, [_0]) } public func PUSH_CHAT_MESSAGE_GEO(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1593]!, self._r[1593]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1595]!, self._r[1595]!, [_1, _2]) } - public var Passport_Address_TypePassportRegistrationUploadScan: String { return self._s[1594]! } - public var Profile_BotInfo: String { return self._s[1595]! } - public var Watch_Compose_CreateMessage: String { return self._s[1596]! } - public var AutoDownloadSettings_VoiceMessagesInfo: String { return self._s[1597]! } - public var Month_ShortNovember: String { return self._s[1598]! } - public var Conversation_ScamWarning: String { return self._s[1599]! } - public var Wallpaper_SetCustomBackground: String { return self._s[1600]! } - public var Appearance_TextSize_Title: String { return self._s[1601]! } - public var Passport_Identity_TranslationsHelp: String { return self._s[1602]! } - public var NotificationsSound_Chime: String { return self._s[1603]! } - public var Passport_Language_ko: String { return self._s[1605]! } - public var InviteText_URL: String { return self._s[1606]! } - public var TextFormat_Monospace: String { return self._s[1607]! } + public var Passport_Address_TypePassportRegistrationUploadScan: String { return self._s[1596]! } + public var Profile_BotInfo: String { return self._s[1597]! } + public var Watch_Compose_CreateMessage: String { return self._s[1598]! } + public var AutoDownloadSettings_VoiceMessagesInfo: String { return self._s[1599]! } + public var Month_ShortNovember: String { return self._s[1600]! } + public var Conversation_ScamWarning: String { return self._s[1601]! } + public var Wallpaper_SetCustomBackground: String { return self._s[1602]! } + public var Appearance_TextSize_Title: String { return self._s[1603]! } + public var Passport_Identity_TranslationsHelp: String { return self._s[1604]! } + public var NotificationsSound_Chime: String { return self._s[1605]! } + public var Passport_Language_ko: String { return self._s[1607]! } + public var InviteText_URL: String { return self._s[1608]! } + public var TextFormat_Monospace: String { return self._s[1609]! } public func Time_PreciseDate_m11(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1608]!, self._r[1608]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1610]!, self._r[1610]!, [_1, _2, _3]) } - public var EditTheme_Edit_BottomInfo: String { return self._s[1609]! } + public var EditTheme_Edit_BottomInfo: String { return self._s[1611]! } public func Login_WillSendSms(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1610]!, self._r[1610]!, [_0]) + return formatWithArgumentRanges(self._s[1612]!, self._r[1612]!, [_0]) } public func Watch_Time_ShortWeekdayAt(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1611]!, self._r[1611]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1613]!, self._r[1613]!, [_1, _2]) } - public var Wallet_Words_Title: String { return self._s[1612]! } - public var Wallet_Month_ShortMay: String { return self._s[1613]! } - public var EditTheme_CreateTitle: String { return self._s[1615]! } - public var Passport_InfoLearnMore: String { return self._s[1616]! } - public var TwoStepAuth_EmailPlaceholder: String { return self._s[1617]! } - public var Passport_Identity_AddIdentityCard: String { return self._s[1618]! } - public var Your_card_has_expired: String { return self._s[1619]! } - public var StickerPacksSettings_StickerPacksSection: String { return self._s[1620]! } - public var GroupInfo_InviteLink_Help: String { return self._s[1621]! } - public var TwoFactorSetup_EmailVerification_ResendAction: String { return self._s[1625]! } - public var Conversation_Report: String { return self._s[1627]! } - public var Notifications_MessageNotificationsSound: String { return self._s[1628]! } - public var Notification_MessageLifetime1m: String { return self._s[1629]! } - public var Privacy_ContactsTitle: String { return self._s[1630]! } - public var Conversation_ShareMyContactInfo: String { return self._s[1631]! } - public var Wallet_WordCheck_Title: String { return self._s[1632]! } - public var ChannelMembers_WhoCanAddMembersAdminsHelp: String { return self._s[1633]! } - public var Channel_Members_Title: String { return self._s[1634]! } - public var Map_OpenInWaze: String { return self._s[1635]! } - public var Appearance_RemoveThemeColorConfirmation: String { return self._s[1636]! } - public var Login_PhoneBannedError: String { return self._s[1637]! } + public var Wallet_Words_Title: String { return self._s[1614]! } + public var Wallet_Month_ShortMay: String { return self._s[1615]! } + public var EditTheme_CreateTitle: String { return self._s[1617]! } + public var Passport_InfoLearnMore: String { return self._s[1618]! } + public var TwoStepAuth_EmailPlaceholder: String { return self._s[1619]! } + public var Passport_Identity_AddIdentityCard: String { return self._s[1620]! } + public var Your_card_has_expired: String { return self._s[1621]! } + public var StickerPacksSettings_StickerPacksSection: String { return self._s[1622]! } + public var GroupInfo_InviteLink_Help: String { return self._s[1623]! } + public var TwoFactorSetup_EmailVerification_ResendAction: String { return self._s[1627]! } + public var Conversation_Report: String { return self._s[1629]! } + public var Notifications_MessageNotificationsSound: String { return self._s[1630]! } + public var Notification_MessageLifetime1m: String { return self._s[1631]! } + public var Privacy_ContactsTitle: String { return self._s[1632]! } + public var Conversation_ShareMyContactInfo: String { return self._s[1633]! } + public var Wallet_WordCheck_Title: String { return self._s[1634]! } + public var ChannelMembers_WhoCanAddMembersAdminsHelp: String { return self._s[1635]! } + public var Channel_Members_Title: String { return self._s[1636]! } + public var Map_OpenInWaze: String { return self._s[1637]! } + public var Appearance_RemoveThemeColorConfirmation: String { return self._s[1638]! } + public var Login_PhoneBannedError: String { return self._s[1639]! } public func LiveLocationUpdated_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1638]!, self._r[1638]!, [_0]) + return formatWithArgumentRanges(self._s[1640]!, self._r[1640]!, [_0]) } - public var IntentsSettings_MainAccount: String { return self._s[1639]! } - public var Group_Management_AddModeratorHelp: String { return self._s[1640]! } - public var AutoDownloadSettings_WifiTitle: String { return self._s[1641]! } - public var Common_OK: String { return self._s[1642]! } - public var Passport_Address_TypeBankStatementUploadScan: String { return self._s[1643]! } - public var Wallet_Words_NotDoneResponse: String { return self._s[1644]! } - public var Cache_Music: String { return self._s[1645]! } - public var Wallet_Configuration_SourceURL: String { return self._s[1646]! } - public var SettingsSearch_Synonyms_EditProfile_PhoneNumber: String { return self._s[1647]! } - public var PasscodeSettings_UnlockWithTouchId: String { return self._s[1649]! } - public var TwoStepAuth_HintPlaceholder: String { return self._s[1650]! } + public var IntentsSettings_MainAccount: String { return self._s[1641]! } + public var Group_Management_AddModeratorHelp: String { return self._s[1642]! } + public var AutoDownloadSettings_WifiTitle: String { return self._s[1643]! } + public var Common_OK: String { return self._s[1644]! } + public var Passport_Address_TypeBankStatementUploadScan: String { return self._s[1645]! } + public var Wallet_Words_NotDoneResponse: String { return self._s[1646]! } + public var Cache_Music: String { return self._s[1647]! } + public var Wallet_Configuration_SourceURL: String { return self._s[1648]! } + public var SettingsSearch_Synonyms_EditProfile_PhoneNumber: String { return self._s[1649]! } + public var PasscodeSettings_UnlockWithTouchId: String { return self._s[1651]! } + public var TwoStepAuth_HintPlaceholder: String { return self._s[1652]! } public func PUSH_PINNED_INVOICE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1651]!, self._r[1651]!, [_1]) + return formatWithArgumentRanges(self._s[1653]!, self._r[1653]!, [_1]) } public func Passport_RequestHeader(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1652]!, self._r[1652]!, [_0]) - } - public var TwoFactorSetup_Done_Action: String { return self._s[1653]! } - public func VoiceOver_Chat_ContactOrganization(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[1654]!, self._r[1654]!, [_0]) } - public var Wallet_Send_ErrorNotEnoughFundsText: String { return self._s[1655]! } - public var Watch_MessageView_ViewOnPhone: String { return self._s[1657]! } - public var Privacy_Calls_CustomShareHelp: String { return self._s[1658]! } - public var Wallet_Receive_CreateInvoiceInfo: String { return self._s[1660]! } - public var ChangePhoneNumberNumber_Title: String { return self._s[1661]! } - public var State_ConnectingToProxyInfo: String { return self._s[1662]! } - public var Conversation_SwipeToReplyHintTitle: String { return self._s[1663]! } - public var Message_VideoMessage: String { return self._s[1665]! } - public var ChannelInfo_DeleteChannel: String { return self._s[1666]! } - public var ContactInfo_PhoneLabelOther: String { return self._s[1667]! } - public var Channel_EditAdmin_CannotEdit: String { return self._s[1668]! } - public var Passport_DeleteAddressConfirmation: String { return self._s[1669]! } - public func Wallet_Time_PreciseDate_m9(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1670]!, self._r[1670]!, [_1, _2, _3]) + public var TwoFactorSetup_Done_Action: String { return self._s[1655]! } + public func VoiceOver_Chat_ContactOrganization(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1656]!, self._r[1656]!, [_0]) } - public var WallpaperPreview_SwipeBottomText: String { return self._s[1671]! } - public var Activity_RecordingAudio: String { return self._s[1672]! } - public var SettingsSearch_Synonyms_Watch: String { return self._s[1673]! } - public var PasscodeSettings_TryAgainIn1Minute: String { return self._s[1674]! } - public var Wallet_Info_Address: String { return self._s[1675]! } + public var Wallet_Send_ErrorNotEnoughFundsText: String { return self._s[1657]! } + public var Watch_MessageView_ViewOnPhone: String { return self._s[1659]! } + public var Privacy_Calls_CustomShareHelp: String { return self._s[1660]! } + public var Wallet_Receive_CreateInvoiceInfo: String { return self._s[1662]! } + public var ChangePhoneNumberNumber_Title: String { return self._s[1663]! } + public var State_ConnectingToProxyInfo: String { return self._s[1664]! } + public var Conversation_SwipeToReplyHintTitle: String { return self._s[1665]! } + public var Message_VideoMessage: String { return self._s[1667]! } + public var ChannelInfo_DeleteChannel: String { return self._s[1668]! } + public var ContactInfo_PhoneLabelOther: String { return self._s[1669]! } + public var Channel_EditAdmin_CannotEdit: String { return self._s[1670]! } + public var Passport_DeleteAddressConfirmation: String { return self._s[1671]! } + public func Wallet_Time_PreciseDate_m9(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1672]!, self._r[1672]!, [_1, _2, _3]) + } + public var WallpaperPreview_SwipeBottomText: String { return self._s[1673]! } + public var Activity_RecordingAudio: String { return self._s[1674]! } + public var SettingsSearch_Synonyms_Watch: String { return self._s[1675]! } + public var PasscodeSettings_TryAgainIn1Minute: String { return self._s[1676]! } + public var Wallet_Info_Address: String { return self._s[1677]! } public func Notification_ChangedGroupName(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1677]!, self._r[1677]!, [_0, _1]) + return formatWithArgumentRanges(self._s[1679]!, self._r[1679]!, [_0, _1]) } public func EmptyGroupInfo_Line1(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1681]!, self._r[1681]!, [_0]) + return formatWithArgumentRanges(self._s[1683]!, self._r[1683]!, [_0]) } - public var Conversation_ApplyLocalization: String { return self._s[1682]! } - public var TwoFactorSetup_Intro_Action: String { return self._s[1683]! } - public var UserInfo_AddPhone: String { return self._s[1684]! } - public var Map_ShareLiveLocationHelp: String { return self._s[1685]! } + public var Conversation_ApplyLocalization: String { return self._s[1684]! } + public var TwoFactorSetup_Intro_Action: String { return self._s[1685]! } + public var UserInfo_AddPhone: String { return self._s[1686]! } + public var Map_ShareLiveLocationHelp: String { return self._s[1687]! } public func Passport_Identity_NativeNameGenericHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1686]!, self._r[1686]!, [_0]) + return formatWithArgumentRanges(self._s[1688]!, self._r[1688]!, [_0]) } - public var Passport_Scans: String { return self._s[1688]! } - public var BlockedUsers_Unblock: String { return self._s[1689]! } + public var Passport_Scans: String { return self._s[1690]! } + public var BlockedUsers_Unblock: String { return self._s[1691]! } public func PUSH_ENCRYPTION_REQUEST(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1690]!, self._r[1690]!, [_1]) + return formatWithArgumentRanges(self._s[1692]!, self._r[1692]!, [_1]) } - public var Channel_Management_LabelCreator: String { return self._s[1691]! } - public var Conversation_ReportSpamAndLeave: String { return self._s[1692]! } - public var SettingsSearch_Synonyms_EditProfile_Bio: String { return self._s[1693]! } - public var ChatList_UndoArchiveMultipleTitle: String { return self._s[1694]! } - public var Passport_Identity_NativeNameGenericTitle: String { return self._s[1695]! } + public var Channel_Management_LabelCreator: String { return self._s[1693]! } + public var Conversation_ReportSpamAndLeave: String { return self._s[1694]! } + public var SettingsSearch_Synonyms_EditProfile_Bio: String { return self._s[1695]! } + public var ChatList_UndoArchiveMultipleTitle: String { return self._s[1696]! } + public var Passport_Identity_NativeNameGenericTitle: String { return self._s[1697]! } public func Login_EmailPhoneBody(_ _0: String, _ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1696]!, self._r[1696]!, [_0, _1, _2]) + return formatWithArgumentRanges(self._s[1698]!, self._r[1698]!, [_0, _1, _2]) } - public var Login_PhoneNumberHelp: String { return self._s[1697]! } - public var LastSeen_ALongTimeAgo: String { return self._s[1698]! } - public var Channel_AdminLog_CanPinMessages: String { return self._s[1699]! } - public var ChannelIntro_CreateChannel: String { return self._s[1700]! } - public var Conversation_UnreadMessages: String { return self._s[1701]! } - public var SettingsSearch_Synonyms_Stickers_ArchivedPacks: String { return self._s[1702]! } - public var Channel_AdminLog_EmptyText: String { return self._s[1703]! } - public var Theme_Context_Apply: String { return self._s[1704]! } - public var Notification_GroupActivated: String { return self._s[1705]! } - public var NotificationSettings_ContactJoinedInfo: String { return self._s[1706]! } - public var Wallet_Intro_CreateWallet: String { return self._s[1707]! } + public var Login_PhoneNumberHelp: String { return self._s[1699]! } + public var LastSeen_ALongTimeAgo: String { return self._s[1700]! } + public var Channel_AdminLog_CanPinMessages: String { return self._s[1701]! } + public var ChannelIntro_CreateChannel: String { return self._s[1702]! } + public var Conversation_UnreadMessages: String { return self._s[1703]! } + public var SettingsSearch_Synonyms_Stickers_ArchivedPacks: String { return self._s[1704]! } + public var Channel_AdminLog_EmptyText: String { return self._s[1705]! } + public var Theme_Context_Apply: String { return self._s[1706]! } + public var Notification_GroupActivated: String { return self._s[1707]! } + public var NotificationSettings_ContactJoinedInfo: String { return self._s[1708]! } + public var Wallet_Intro_CreateWallet: String { return self._s[1709]! } public func Notification_PinnedContactMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1708]!, self._r[1708]!, [_0]) + return formatWithArgumentRanges(self._s[1710]!, self._r[1710]!, [_0]) } public func DownloadingStatus(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1709]!, self._r[1709]!, [_0, _1]) + return formatWithArgumentRanges(self._s[1711]!, self._r[1711]!, [_0, _1]) } - public var GroupInfo_ConvertToSupergroup: String { return self._s[1711]! } + public var GroupInfo_ConvertToSupergroup: String { return self._s[1713]! } public func PrivacyPolicy_AgeVerificationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1712]!, self._r[1712]!, [_0]) + return formatWithArgumentRanges(self._s[1714]!, self._r[1714]!, [_0]) } - public var Undo_DeletedChannel: String { return self._s[1713]! } - public var CallFeedback_AddComment: String { return self._s[1714]! } + public var Undo_DeletedChannel: String { return self._s[1715]! } + public var CallFeedback_AddComment: String { return self._s[1716]! } public func Conversation_OpenBotLinkAllowMessages(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1715]!, self._r[1715]!, [_0]) - } - public var Document_TargetConfirmationFormat: String { return self._s[1716]! } - public func Call_StatusOngoing(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[1717]!, self._r[1717]!, [_0]) } - public var LogoutOptions_SetPasscodeTitle: String { return self._s[1718]! } + public var Document_TargetConfirmationFormat: String { return self._s[1718]! } + public func Call_StatusOngoing(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1719]!, self._r[1719]!, [_0]) + } + public var LogoutOptions_SetPasscodeTitle: String { return self._s[1720]! } public func PUSH_CHAT_MESSAGE_GAME_SCORE(_ _1: String, _ _2: String, _ _3: String, _ _4: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1719]!, self._r[1719]!, [_1, _2, _3, _4]) + return formatWithArgumentRanges(self._s[1721]!, self._r[1721]!, [_1, _2, _3, _4]) } - public var Wallet_SecureStorageChanged_PasscodeText: String { return self._s[1720]! } - public var Theme_ErrorNotFound: String { return self._s[1721]! } - public var Contacts_SortByName: String { return self._s[1722]! } - public var SettingsSearch_Synonyms_Privacy_Forwards: String { return self._s[1723]! } + public var Wallet_SecureStorageChanged_PasscodeText: String { return self._s[1722]! } + public var Theme_ErrorNotFound: String { return self._s[1723]! } + public var Contacts_SortByName: String { return self._s[1724]! } + public var SettingsSearch_Synonyms_Privacy_Forwards: String { return self._s[1725]! } public func CHAT_MESSAGE_INVOICE(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1725]!, self._r[1725]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1727]!, self._r[1727]!, [_1, _2, _3]) } - public var Notification_Exceptions_RemoveFromExceptions: String { return self._s[1726]! } - public var ScheduledMessages_EditTime: String { return self._s[1727]! } - public var Conversation_ClearSelfHistory: String { return self._s[1728]! } - public var Checkout_NewCard_PostcodePlaceholder: String { return self._s[1729]! } - public var PasscodeSettings_DoNotMatch: String { return self._s[1730]! } - public var Stickers_SuggestNone: String { return self._s[1731]! } - public var ChatSettings_Cache: String { return self._s[1732]! } - public var Settings_SaveIncomingPhotos: String { return self._s[1733]! } - public var Media_ShareThisPhoto: String { return self._s[1734]! } - public var Chat_SlowmodeTooltipPending: String { return self._s[1735]! } - public var InfoPlist_NSContactsUsageDescription: String { return self._s[1736]! } - public var Conversation_ContextMenuCopyLink: String { return self._s[1737]! } - public var PrivacyPolicy_AgeVerificationTitle: String { return self._s[1738]! } - public var SettingsSearch_Synonyms_Stickers_Masks: String { return self._s[1739]! } - public var TwoStepAuth_SetupPasswordEnterPasswordNew: String { return self._s[1740]! } - public var Appearance_ThemePreview_Chat_6_Text: String { return self._s[1741]! } + public var Notification_Exceptions_RemoveFromExceptions: String { return self._s[1728]! } + public var ScheduledMessages_EditTime: String { return self._s[1729]! } + public var Conversation_ClearSelfHistory: String { return self._s[1730]! } + public var Checkout_NewCard_PostcodePlaceholder: String { return self._s[1731]! } + public var PasscodeSettings_DoNotMatch: String { return self._s[1732]! } + public var Stickers_SuggestNone: String { return self._s[1733]! } + public var ChatSettings_Cache: String { return self._s[1734]! } + public var Settings_SaveIncomingPhotos: String { return self._s[1735]! } + public var Media_ShareThisPhoto: String { return self._s[1736]! } + public var Chat_SlowmodeTooltipPending: String { return self._s[1737]! } + public var InfoPlist_NSContactsUsageDescription: String { return self._s[1738]! } + public var Conversation_ContextMenuCopyLink: String { return self._s[1739]! } + public var PrivacyPolicy_AgeVerificationTitle: String { return self._s[1740]! } + public var SettingsSearch_Synonyms_Stickers_Masks: String { return self._s[1741]! } + public var TwoStepAuth_SetupPasswordEnterPasswordNew: String { return self._s[1742]! } + public var Appearance_ThemePreview_Chat_6_Text: String { return self._s[1743]! } public func Wallet_SecureStorageReset_BiometryText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1742]!, self._r[1742]!, [_0]) + return formatWithArgumentRanges(self._s[1744]!, self._r[1744]!, [_0]) } - public var Permissions_CellularDataTitle_v0: String { return self._s[1743]! } - public var WallpaperSearch_ColorWhite: String { return self._s[1745]! } - public var Channel_AdminLog_DefaultRestrictionsUpdated: String { return self._s[1746]! } - public var Conversation_ErrorInaccessibleMessage: String { return self._s[1747]! } - public var Map_OpenIn: String { return self._s[1748]! } + public var Permissions_CellularDataTitle_v0: String { return self._s[1745]! } + public var WallpaperSearch_ColorWhite: String { return self._s[1747]! } + public var Channel_AdminLog_DefaultRestrictionsUpdated: String { return self._s[1748]! } + public var Conversation_ErrorInaccessibleMessage: String { return self._s[1749]! } + public var Map_OpenIn: String { return self._s[1750]! } public func PUSH_PHONE_CALL_MISSED(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1751]!, self._r[1751]!, [_1]) + return formatWithArgumentRanges(self._s[1753]!, self._r[1753]!, [_1]) } public func ChannelInfo_AddParticipantConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1752]!, self._r[1752]!, [_0]) + return formatWithArgumentRanges(self._s[1754]!, self._r[1754]!, [_0]) } - public var GroupInfo_Permissions_SlowmodeHeader: String { return self._s[1753]! } - public var MessagePoll_LabelClosed: String { return self._s[1754]! } - public var GroupPermission_PermissionGloballyDisabled: String { return self._s[1756]! } - public var Wallet_Send_SendAnyway: String { return self._s[1757]! } - public var Passport_Identity_MiddleNamePlaceholder: String { return self._s[1758]! } - public var UserInfo_FirstNamePlaceholder: String { return self._s[1759]! } - public var PrivacyLastSeenSettings_WhoCanSeeMyTimestamp: String { return self._s[1760]! } - public var Map_SetThisPlace: String { return self._s[1761]! } - public var Login_SelectCountry_Title: String { return self._s[1762]! } - public var Channel_EditAdmin_PermissionBanUsers: String { return self._s[1763]! } + public var GroupInfo_Permissions_SlowmodeHeader: String { return self._s[1755]! } + public var MessagePoll_LabelClosed: String { return self._s[1756]! } + public var GroupPermission_PermissionGloballyDisabled: String { return self._s[1758]! } + public var Wallet_Send_SendAnyway: String { return self._s[1759]! } + public var Passport_Identity_MiddleNamePlaceholder: String { return self._s[1760]! } + public var UserInfo_FirstNamePlaceholder: String { return self._s[1761]! } + public var PrivacyLastSeenSettings_WhoCanSeeMyTimestamp: String { return self._s[1762]! } + public var Map_SetThisPlace: String { return self._s[1763]! } + public var Login_SelectCountry_Title: String { return self._s[1764]! } + public var Channel_EditAdmin_PermissionBanUsers: String { return self._s[1765]! } public func Conversation_OpenBotLinkLogin(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1764]!, self._r[1764]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1766]!, self._r[1766]!, [_1, _2]) } - public var Channel_AdminLog_ChangeInfo: String { return self._s[1765]! } - public var Watch_Suggestion_BRB: String { return self._s[1766]! } - public var Passport_Identity_EditIdentityCard: String { return self._s[1767]! } - public var Contacts_PermissionsTitle: String { return self._s[1768]! } - public var Conversation_RestrictedInline: String { return self._s[1769]! } - public var Appearance_RemoveThemeColor: String { return self._s[1771]! } - public var StickerPack_ViewPack: String { return self._s[1772]! } - public var Wallet_UnknownError: String { return self._s[1773]! } + public var Channel_AdminLog_ChangeInfo: String { return self._s[1767]! } + public var Watch_Suggestion_BRB: String { return self._s[1768]! } + public var Passport_Identity_EditIdentityCard: String { return self._s[1769]! } + public var Contacts_PermissionsTitle: String { return self._s[1770]! } + public var Conversation_RestrictedInline: String { return self._s[1771]! } + public var Appearance_RemoveThemeColor: String { return self._s[1773]! } + public var StickerPack_ViewPack: String { return self._s[1774]! } + public var Wallet_UnknownError: String { return self._s[1775]! } public func Update_AppVersion(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1774]!, self._r[1774]!, [_0]) + return formatWithArgumentRanges(self._s[1776]!, self._r[1776]!, [_0]) } - public var Compose_NewChannel: String { return self._s[1776]! } - public var ChatSettings_AutoDownloadSettings_TypePhoto: String { return self._s[1779]! } - public var MessagePoll_LabelQuiz: String { return self._s[1781]! } - public var Conversation_ReportSpamGroupConfirmation: String { return self._s[1782]! } - public var Channel_Info_Stickers: String { return self._s[1783]! } - public var AutoNightTheme_PreferredTheme: String { return self._s[1784]! } - public var PrivacyPolicy_AgeVerificationAgree: String { return self._s[1785]! } - public var Passport_DeletePersonalDetails: String { return self._s[1786]! } - public var LogoutOptions_AddAccountTitle: String { return self._s[1787]! } - public var Channel_DiscussionGroupInfo: String { return self._s[1788]! } - public var Group_EditAdmin_RankOwnerPlaceholder: String { return self._s[1789]! } - public var Conversation_SearchNoResults: String { return self._s[1792]! } - public var Wallet_Configuration_ApplyErrorTextURLInvalid: String { return self._s[1793]! } - public var MessagePoll_LabelAnonymous: String { return self._s[1794]! } - public var Channel_Members_AddAdminErrorNotAMember: String { return self._s[1795]! } - public var Login_Code: String { return self._s[1796]! } - public var EditTheme_Create_BottomInfo: String { return self._s[1797]! } - public var Watch_Suggestion_WhatsUp: String { return self._s[1798]! } - public var Weekday_ShortThursday: String { return self._s[1799]! } - public var Resolve_ErrorNotFound: String { return self._s[1801]! } - public var LastSeen_Offline: String { return self._s[1802]! } - public var PeopleNearby_NoMembers: String { return self._s[1803]! } - public var GroupPermission_AddMembersNotAvailable: String { return self._s[1804]! } - public var Privacy_Calls_AlwaysAllow_Title: String { return self._s[1805]! } - public var GroupInfo_Title: String { return self._s[1807]! } - public var NotificationsSound_Note: String { return self._s[1808]! } - public var Conversation_EditingMessagePanelTitle: String { return self._s[1809]! } - public var Watch_Message_Poll: String { return self._s[1810]! } - public var Privacy_Calls: String { return self._s[1811]! } + public var Compose_NewChannel: String { return self._s[1778]! } + public var ChatSettings_AutoDownloadSettings_TypePhoto: String { return self._s[1781]! } + public var MessagePoll_LabelQuiz: String { return self._s[1783]! } + public var Conversation_ReportSpamGroupConfirmation: String { return self._s[1784]! } + public var Channel_Info_Stickers: String { return self._s[1785]! } + public var AutoNightTheme_PreferredTheme: String { return self._s[1786]! } + public var PrivacyPolicy_AgeVerificationAgree: String { return self._s[1787]! } + public var Passport_DeletePersonalDetails: String { return self._s[1788]! } + public var LogoutOptions_AddAccountTitle: String { return self._s[1789]! } + public var Channel_DiscussionGroupInfo: String { return self._s[1790]! } + public var Group_EditAdmin_RankOwnerPlaceholder: String { return self._s[1791]! } + public var Conversation_SearchNoResults: String { return self._s[1794]! } + public var Wallet_Configuration_ApplyErrorTextURLInvalid: String { return self._s[1795]! } + public var MessagePoll_LabelAnonymous: String { return self._s[1796]! } + public var Channel_Members_AddAdminErrorNotAMember: String { return self._s[1797]! } + public var Login_Code: String { return self._s[1798]! } + public var EditTheme_Create_BottomInfo: String { return self._s[1799]! } + public var Watch_Suggestion_WhatsUp: String { return self._s[1800]! } + public var Weekday_ShortThursday: String { return self._s[1801]! } + public var Resolve_ErrorNotFound: String { return self._s[1803]! } + public var LastSeen_Offline: String { return self._s[1804]! } + public var PeopleNearby_NoMembers: String { return self._s[1805]! } + public var GroupPermission_AddMembersNotAvailable: String { return self._s[1806]! } + public var Privacy_Calls_AlwaysAllow_Title: String { return self._s[1807]! } + public var GroupInfo_Title: String { return self._s[1809]! } + public var NotificationsSound_Note: String { return self._s[1810]! } + public var Conversation_EditingMessagePanelTitle: String { return self._s[1811]! } + public var Watch_Message_Poll: String { return self._s[1812]! } + public var Privacy_Calls: String { return self._s[1813]! } public func Channel_AdminLog_MessageRankUsername(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1812]!, self._r[1812]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1814]!, self._r[1814]!, [_1, _2, _3]) } - public var Month_ShortAugust: String { return self._s[1813]! } - public var TwoStepAuth_SetPasswordHelp: String { return self._s[1814]! } - public var Notifications_Reset: String { return self._s[1815]! } - public var Conversation_Pin: String { return self._s[1816]! } - public var Passport_Language_lv: String { return self._s[1817]! } - public var Permissions_PeopleNearbyAllowInSettings_v0: String { return self._s[1818]! } - public var BlockedUsers_Info: String { return self._s[1819]! } - public var SettingsSearch_Synonyms_Data_AutoplayVideos: String { return self._s[1821]! } - public var Watch_Conversation_Unblock: String { return self._s[1823]! } + public var Month_ShortAugust: String { return self._s[1815]! } + public var TwoStepAuth_SetPasswordHelp: String { return self._s[1816]! } + public var Notifications_Reset: String { return self._s[1817]! } + public var Conversation_Pin: String { return self._s[1818]! } + public var Passport_Language_lv: String { return self._s[1819]! } + public var Permissions_PeopleNearbyAllowInSettings_v0: String { return self._s[1820]! } + public var BlockedUsers_Info: String { return self._s[1821]! } + public var SettingsSearch_Synonyms_Data_AutoplayVideos: String { return self._s[1823]! } + public var Watch_Conversation_Unblock: String { return self._s[1825]! } public func Time_MonthOfYear_m9(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1824]!, self._r[1824]!, [_0]) + return formatWithArgumentRanges(self._s[1826]!, self._r[1826]!, [_0]) } - public var CloudStorage_Title: String { return self._s[1825]! } - public var GroupInfo_DeleteAndExitConfirmation: String { return self._s[1826]! } + public var CloudStorage_Title: String { return self._s[1827]! } + public var GroupInfo_DeleteAndExitConfirmation: String { return self._s[1828]! } public func NetworkUsageSettings_WifiUsageSince(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1827]!, self._r[1827]!, [_0]) + return formatWithArgumentRanges(self._s[1829]!, self._r[1829]!, [_0]) } - public var Channel_AdminLogFilter_AdminsTitle: String { return self._s[1828]! } - public var Watch_Suggestion_OnMyWay: String { return self._s[1829]! } - public var TwoStepAuth_RecoveryEmailTitle: String { return self._s[1830]! } - public var Passport_Address_EditBankStatement: String { return self._s[1831]! } + public var Channel_AdminLogFilter_AdminsTitle: String { return self._s[1830]! } + public var Watch_Suggestion_OnMyWay: String { return self._s[1831]! } + public var TwoStepAuth_RecoveryEmailTitle: String { return self._s[1832]! } + public var Passport_Address_EditBankStatement: String { return self._s[1833]! } public func Channel_AdminLog_MessageChangedUnlinkedGroup(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1832]!, self._r[1832]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1834]!, self._r[1834]!, [_1, _2]) } - public var ChatSettings_DownloadInBackgroundInfo: String { return self._s[1833]! } - public var ShareMenu_Comment: String { return self._s[1834]! } - public var Permissions_ContactsTitle_v0: String { return self._s[1835]! } - public var Notifications_PermissionsTitle: String { return self._s[1836]! } - public var GroupPermission_NoSendLinks: String { return self._s[1837]! } - public var Privacy_Forwards_NeverAllow_Title: String { return self._s[1838]! } - public var Wallet_SecureStorageChanged_ImportWallet: String { return self._s[1839]! } - public var Settings_Support: String { return self._s[1840]! } - public var Notifications_ChannelNotificationsSound: String { return self._s[1841]! } - public var SettingsSearch_Synonyms_Data_AutoDownloadReset: String { return self._s[1842]! } - public var Privacy_Forwards_Preview: String { return self._s[1843]! } - public var GroupPermission_ApplyAlertAction: String { return self._s[1844]! } - public var Watch_Stickers_StickerPacks: String { return self._s[1845]! } - public var Common_Select: String { return self._s[1847]! } - public var CheckoutInfo_ErrorEmailInvalid: String { return self._s[1848]! } - public var WallpaperSearch_ColorGray: String { return self._s[1851]! } - public var TwoFactorSetup_Password_PlaceholderPassword: String { return self._s[1852]! } - public var TwoFactorSetup_Hint_SkipAction: String { return self._s[1853]! } - public var ChatAdmins_AllMembersAreAdminsOffHelp: String { return self._s[1854]! } - public var PollResults_Title: String { return self._s[1855]! } - public var PasscodeSettings_AutoLock_IfAwayFor_5hours: String { return self._s[1856]! } - public var Appearance_PreviewReplyAuthor: String { return self._s[1857]! } - public var TwoStepAuth_RecoveryTitle: String { return self._s[1858]! } - public var Widget_AuthRequired: String { return self._s[1859]! } - public var Camera_FlashOn: String { return self._s[1860]! } - public var Conversation_ContextMenuLookUp: String { return self._s[1861]! } - public var Channel_Stickers_NotFoundHelp: String { return self._s[1862]! } - public var Watch_Suggestion_OK: String { return self._s[1863]! } + public var ChatSettings_DownloadInBackgroundInfo: String { return self._s[1835]! } + public var ShareMenu_Comment: String { return self._s[1836]! } + public var Permissions_ContactsTitle_v0: String { return self._s[1837]! } + public var Notifications_PermissionsTitle: String { return self._s[1838]! } + public var GroupPermission_NoSendLinks: String { return self._s[1839]! } + public var Privacy_Forwards_NeverAllow_Title: String { return self._s[1840]! } + public var Wallet_SecureStorageChanged_ImportWallet: String { return self._s[1841]! } + public var Settings_Support: String { return self._s[1842]! } + public var Notifications_ChannelNotificationsSound: String { return self._s[1843]! } + public var SettingsSearch_Synonyms_Data_AutoDownloadReset: String { return self._s[1844]! } + public var Privacy_Forwards_Preview: String { return self._s[1845]! } + public var GroupPermission_ApplyAlertAction: String { return self._s[1846]! } + public var Watch_Stickers_StickerPacks: String { return self._s[1847]! } + public var Common_Select: String { return self._s[1849]! } + public var CheckoutInfo_ErrorEmailInvalid: String { return self._s[1850]! } + public var WallpaperSearch_ColorGray: String { return self._s[1853]! } + public var TwoFactorSetup_Password_PlaceholderPassword: String { return self._s[1854]! } + public var TwoFactorSetup_Hint_SkipAction: String { return self._s[1855]! } + public var ChatAdmins_AllMembersAreAdminsOffHelp: String { return self._s[1856]! } + public var PollResults_Title: String { return self._s[1857]! } + public var PasscodeSettings_AutoLock_IfAwayFor_5hours: String { return self._s[1858]! } + public var Appearance_PreviewReplyAuthor: String { return self._s[1859]! } + public var TwoStepAuth_RecoveryTitle: String { return self._s[1860]! } + public var Widget_AuthRequired: String { return self._s[1861]! } + public var Camera_FlashOn: String { return self._s[1862]! } + public var Conversation_ContextMenuLookUp: String { return self._s[1863]! } + public var Channel_Stickers_NotFoundHelp: String { return self._s[1864]! } + public var Watch_Suggestion_OK: String { return self._s[1865]! } public func Username_LinkHint(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1865]!, self._r[1865]!, [_0]) - } - public func Notification_PinnedLiveLocationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[1867]!, self._r[1867]!, [_0]) } - public var TextFormat_Strikethrough: String { return self._s[1868]! } - public var DialogList_AdLabel: String { return self._s[1869]! } - public var WatchRemote_NotificationText: String { return self._s[1870]! } - public var IntentsSettings_SuggestedChatsSavedMessages: String { return self._s[1871]! } - public var SettingsSearch_Synonyms_Notifications_MessageNotificationsAlert: String { return self._s[1872]! } - public var Conversation_ReportSpam: String { return self._s[1873]! } - public var SettingsSearch_Synonyms_Privacy_Data_TopPeers: String { return self._s[1874]! } - public var Settings_LogoutConfirmationTitle: String { return self._s[1876]! } - public var PhoneLabel_Title: String { return self._s[1877]! } - public var Passport_Address_EditRentalAgreement: String { return self._s[1878]! } - public var Settings_ChangePhoneNumber: String { return self._s[1879]! } - public var Notifications_ExceptionsTitle: String { return self._s[1880]! } - public var Notifications_AlertTones: String { return self._s[1881]! } - public var Call_ReportIncludeLogDescription: String { return self._s[1882]! } - public var SettingsSearch_Synonyms_Notifications_ResetAllNotifications: String { return self._s[1883]! } - public var AutoDownloadSettings_PrivateChats: String { return self._s[1884]! } - public var VoiceOver_Chat_Photo: String { return self._s[1886]! } - public var TwoStepAuth_AddHintTitle: String { return self._s[1887]! } - public var ReportPeer_ReasonOther: String { return self._s[1888]! } - public var ChatList_Context_JoinChannel: String { return self._s[1889]! } - public var KeyCommand_ScrollDown: String { return self._s[1891]! } - public var Conversation_ScheduleMessage_Title: String { return self._s[1892]! } + public func Notification_PinnedLiveLocationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1869]!, self._r[1869]!, [_0]) + } + public var TextFormat_Strikethrough: String { return self._s[1870]! } + public var DialogList_AdLabel: String { return self._s[1871]! } + public var WatchRemote_NotificationText: String { return self._s[1872]! } + public var IntentsSettings_SuggestedChatsSavedMessages: String { return self._s[1873]! } + public var SettingsSearch_Synonyms_Notifications_MessageNotificationsAlert: String { return self._s[1874]! } + public var Conversation_ReportSpam: String { return self._s[1875]! } + public var SettingsSearch_Synonyms_Privacy_Data_TopPeers: String { return self._s[1876]! } + public var Settings_LogoutConfirmationTitle: String { return self._s[1878]! } + public var PhoneLabel_Title: String { return self._s[1879]! } + public var Passport_Address_EditRentalAgreement: String { return self._s[1880]! } + public var Settings_ChangePhoneNumber: String { return self._s[1881]! } + public var Notifications_ExceptionsTitle: String { return self._s[1882]! } + public var Notifications_AlertTones: String { return self._s[1883]! } + public var Call_ReportIncludeLogDescription: String { return self._s[1884]! } + public var SettingsSearch_Synonyms_Notifications_ResetAllNotifications: String { return self._s[1885]! } + public var AutoDownloadSettings_PrivateChats: String { return self._s[1886]! } + public var VoiceOver_Chat_Photo: String { return self._s[1888]! } + public var TwoStepAuth_AddHintTitle: String { return self._s[1889]! } + public var ReportPeer_ReasonOther: String { return self._s[1890]! } + public var ChatList_Context_JoinChannel: String { return self._s[1891]! } + public var KeyCommand_ScrollDown: String { return self._s[1893]! } + public var Conversation_ScheduleMessage_Title: String { return self._s[1894]! } public func Login_BannedPhoneSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1893]!, self._r[1893]!, [_0]) + return formatWithArgumentRanges(self._s[1895]!, self._r[1895]!, [_0]) } - public var NetworkUsageSettings_MediaVideoDataSection: String { return self._s[1894]! } - public var ChannelInfo_DeleteGroupConfirmation: String { return self._s[1895]! } - public var AuthSessions_LogOut: String { return self._s[1896]! } - public var Passport_Identity_TypeInternalPassport: String { return self._s[1897]! } - public var ChatSettings_AutoDownloadVoiceMessages: String { return self._s[1898]! } - public var Passport_Phone_Title: String { return self._s[1899]! } - public var ContactList_Context_StartSecretChat: String { return self._s[1900]! } - public var Settings_PhoneNumber: String { return self._s[1901]! } + public var NetworkUsageSettings_MediaVideoDataSection: String { return self._s[1896]! } + public var ChannelInfo_DeleteGroupConfirmation: String { return self._s[1897]! } + public var AuthSessions_LogOut: String { return self._s[1898]! } + public var Passport_Identity_TypeInternalPassport: String { return self._s[1899]! } + public var ChatSettings_AutoDownloadVoiceMessages: String { return self._s[1900]! } + public var Passport_Phone_Title: String { return self._s[1901]! } + public var ContactList_Context_StartSecretChat: String { return self._s[1902]! } + public var Settings_PhoneNumber: String { return self._s[1903]! } public func Conversation_ScheduleMessage_SendToday(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1902]!, self._r[1902]!, [_0]) + return formatWithArgumentRanges(self._s[1904]!, self._r[1904]!, [_0]) } - public var NotificationsSound_Alert: String { return self._s[1904]! } - public var Wallet_SecureStorageChanged_CreateWallet: String { return self._s[1905]! } - public var WebSearch_SearchNoResults: String { return self._s[1906]! } - public var Privacy_ProfilePhoto_AlwaysShareWith_Title: String { return self._s[1908]! } - public var Wallet_Configuration_SourceInfo: String { return self._s[1909]! } - public var LogoutOptions_AlternativeOptionsSection: String { return self._s[1910]! } - public var SettingsSearch_Synonyms_Passport: String { return self._s[1911]! } - public var PhotoEditor_CurvesTool: String { return self._s[1912]! } - public var Checkout_PaymentMethod: String { return self._s[1914]! } + public var NotificationsSound_Alert: String { return self._s[1906]! } + public var Wallet_SecureStorageChanged_CreateWallet: String { return self._s[1907]! } + public var WebSearch_SearchNoResults: String { return self._s[1908]! } + public var Privacy_ProfilePhoto_AlwaysShareWith_Title: String { return self._s[1910]! } + public var Wallet_Configuration_SourceInfo: String { return self._s[1911]! } + public var LogoutOptions_AlternativeOptionsSection: String { return self._s[1912]! } + public var SettingsSearch_Synonyms_Passport: String { return self._s[1913]! } + public var PhotoEditor_CurvesTool: String { return self._s[1914]! } + public var Checkout_PaymentMethod: String { return self._s[1916]! } public func PUSH_CHAT_ADD_YOU(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1915]!, self._r[1915]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1917]!, self._r[1917]!, [_1, _2]) } - public var Contacts_AccessDeniedError: String { return self._s[1916]! } - public var Camera_PhotoMode: String { return self._s[1919]! } - public var EditTheme_Expand_Preview_IncomingText: String { return self._s[1920]! } - public var Appearance_TextSize_Apply: String { return self._s[1921]! } - public var Passport_Address_AddUtilityBill: String { return self._s[1923]! } - public var CallSettings_OnMobile: String { return self._s[1924]! } - public var Tour_Text2: String { return self._s[1925]! } + public var Contacts_AccessDeniedError: String { return self._s[1918]! } + public var Camera_PhotoMode: String { return self._s[1921]! } + public var EditTheme_Expand_Preview_IncomingText: String { return self._s[1922]! } + public var Appearance_TextSize_Apply: String { return self._s[1923]! } + public var Passport_Address_AddUtilityBill: String { return self._s[1925]! } + public var CallSettings_OnMobile: String { return self._s[1926]! } + public var Tour_Text2: String { return self._s[1927]! } public func PUSH_CHAT_MESSAGE_ROUND(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1926]!, self._r[1926]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1928]!, self._r[1928]!, [_1, _2]) } - public var DialogList_EncryptionProcessing: String { return self._s[1928]! } - public var Permissions_Skip: String { return self._s[1929]! } - public var Wallet_Words_NotDoneOk: String { return self._s[1930]! } - public var SecretImage_Title: String { return self._s[1931]! } - public var Watch_MessageView_Title: String { return self._s[1932]! } - public var Channel_DiscussionGroupAdd: String { return self._s[1933]! } - public var AttachmentMenu_Poll: String { return self._s[1934]! } + public var DialogList_EncryptionProcessing: String { return self._s[1930]! } + public var Permissions_Skip: String { return self._s[1931]! } + public var Wallet_Words_NotDoneOk: String { return self._s[1932]! } + public var SecretImage_Title: String { return self._s[1933]! } + public var Watch_MessageView_Title: String { return self._s[1934]! } + public var Channel_DiscussionGroupAdd: String { return self._s[1935]! } + public var AttachmentMenu_Poll: String { return self._s[1936]! } public func Notification_GroupInviter(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1935]!, self._r[1935]!, [_0]) + return formatWithArgumentRanges(self._s[1937]!, self._r[1937]!, [_0]) } public func Channel_DiscussionGroup_PrivateChannelLink(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1936]!, self._r[1936]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1938]!, self._r[1938]!, [_1, _2]) } - public var Notification_CallCanceled: String { return self._s[1937]! } - public var WallpaperPreview_Title: String { return self._s[1938]! } - public var Privacy_PaymentsClear_PaymentInfo: String { return self._s[1939]! } - public var Settings_ProxyConnecting: String { return self._s[1940]! } - public var Settings_CheckPhoneNumberText: String { return self._s[1942]! } - public var VoiceOver_Chat_YourVideo: String { return self._s[1943]! } - public var Wallet_Intro_Title: String { return self._s[1944]! } - public var TwoFactorSetup_Password_Action: String { return self._s[1945]! } - public var Profile_MessageLifetime5s: String { return self._s[1946]! } - public var Username_InvalidCharacters: String { return self._s[1947]! } - public var VoiceOver_Media_PlaybackRateFast: String { return self._s[1948]! } - public var ScheduledMessages_ClearAll: String { return self._s[1949]! } - public var WallpaperPreview_CropBottomText: String { return self._s[1950]! } - public var AutoDownloadSettings_LimitBySize: String { return self._s[1951]! } - public var Settings_AddAccount: String { return self._s[1952]! } - public var Notification_CreatedChannel: String { return self._s[1955]! } + public var Notification_CallCanceled: String { return self._s[1939]! } + public var WallpaperPreview_Title: String { return self._s[1940]! } + public var Privacy_PaymentsClear_PaymentInfo: String { return self._s[1941]! } + public var Settings_ProxyConnecting: String { return self._s[1942]! } + public var Settings_CheckPhoneNumberText: String { return self._s[1944]! } + public var VoiceOver_Chat_YourVideo: String { return self._s[1945]! } + public var Wallet_Intro_Title: String { return self._s[1946]! } + public var TwoFactorSetup_Password_Action: String { return self._s[1947]! } + public var Profile_MessageLifetime5s: String { return self._s[1948]! } + public var Username_InvalidCharacters: String { return self._s[1949]! } + public var VoiceOver_Media_PlaybackRateFast: String { return self._s[1950]! } + public var ScheduledMessages_ClearAll: String { return self._s[1951]! } + public var WallpaperPreview_CropBottomText: String { return self._s[1952]! } + public var AutoDownloadSettings_LimitBySize: String { return self._s[1953]! } + public var Settings_AddAccount: String { return self._s[1954]! } + public var Notification_CreatedChannel: String { return self._s[1957]! } public func PUSH_CHAT_DELETE_MEMBER(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1956]!, self._r[1956]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1958]!, self._r[1958]!, [_1, _2, _3]) } - public var Passcode_AppLockedAlert: String { return self._s[1958]! } - public var StickerPacksSettings_AnimatedStickersInfo: String { return self._s[1959]! } - public var VoiceOver_Media_PlaybackStop: String { return self._s[1960]! } - public var Contacts_TopSection: String { return self._s[1961]! } - public var ChatList_DeleteForEveryoneConfirmationAction: String { return self._s[1962]! } + public var Passcode_AppLockedAlert: String { return self._s[1960]! } + public var StickerPacksSettings_AnimatedStickersInfo: String { return self._s[1961]! } + public var VoiceOver_Media_PlaybackStop: String { return self._s[1962]! } + public var Contacts_TopSection: String { return self._s[1963]! } + public var ChatList_DeleteForEveryoneConfirmationAction: String { return self._s[1964]! } public func Conversation_SetReminder_RemindOn(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1963]!, self._r[1963]!, [_0, _1]) + return formatWithArgumentRanges(self._s[1965]!, self._r[1965]!, [_0, _1]) } - public var Wallet_Info_Receive: String { return self._s[1964]! } - public var Wallet_Completed_ViewWallet: String { return self._s[1965]! } + public var Wallet_Info_Receive: String { return self._s[1966]! } + public var Wallet_Completed_ViewWallet: String { return self._s[1967]! } public func Time_MonthOfYear_m6(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1966]!, self._r[1966]!, [_0]) + return formatWithArgumentRanges(self._s[1968]!, self._r[1968]!, [_0]) } - public var ReportPeer_ReasonSpam: String { return self._s[1967]! } - public var UserInfo_TapToCall: String { return self._s[1968]! } - public var Conversation_ForwardAuthorHiddenTooltip: String { return self._s[1970]! } - public var AutoDownloadSettings_DataUsageCustom: String { return self._s[1971]! } - public var Common_Search: String { return self._s[1972]! } - public var ScheduledMessages_EmptyPlaceholder: String { return self._s[1973]! } + public var ReportPeer_ReasonSpam: String { return self._s[1969]! } + public var UserInfo_TapToCall: String { return self._s[1970]! } + public var Conversation_ForwardAuthorHiddenTooltip: String { return self._s[1972]! } + public var AutoDownloadSettings_DataUsageCustom: String { return self._s[1973]! } + public var Common_Search: String { return self._s[1974]! } + public var ScheduledMessages_EmptyPlaceholder: String { return self._s[1975]! } public func Channel_AdminLog_MessageChangedGroupGeoLocation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1974]!, self._r[1974]!, [_0]) + return formatWithArgumentRanges(self._s[1976]!, self._r[1976]!, [_0]) } - public var Wallet_Month_ShortJuly: String { return self._s[1975]! } - public var AuthSessions_IncompleteAttemptsInfo: String { return self._s[1977]! } - public var Message_InvoiceLabel: String { return self._s[1978]! } - public var Conversation_InputTextPlaceholder: String { return self._s[1979]! } - public var NetworkUsageSettings_MediaImageDataSection: String { return self._s[1980]! } + public var Wallet_Month_ShortJuly: String { return self._s[1977]! } + public var AuthSessions_IncompleteAttemptsInfo: String { return self._s[1979]! } + public var Message_InvoiceLabel: String { return self._s[1980]! } + public var Conversation_InputTextPlaceholder: String { return self._s[1981]! } + public var NetworkUsageSettings_MediaImageDataSection: String { return self._s[1982]! } public func Passport_Address_UploadOneOfScan(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1981]!, self._r[1981]!, [_0]) + return formatWithArgumentRanges(self._s[1983]!, self._r[1983]!, [_0]) } - public var IntentsSettings_Reset: String { return self._s[1982]! } - public var Conversation_Info: String { return self._s[1983]! } - public var Login_InfoDeletePhoto: String { return self._s[1984]! } - public var Passport_Language_vi: String { return self._s[1986]! } - public var UserInfo_ScamUserWarning: String { return self._s[1987]! } - public var Conversation_Search: String { return self._s[1988]! } - public var DialogList_DeleteBotConversationConfirmation: String { return self._s[1990]! } - public var ReportPeer_ReasonPornography: String { return self._s[1991]! } - public var AutoDownloadSettings_PhotosTitle: String { return self._s[1992]! } - public var Conversation_SendMessageErrorGroupRestricted: String { return self._s[1993]! } - public var Map_LiveLocationGroupDescription: String { return self._s[1994]! } - public var Channel_Setup_TypeHeader: String { return self._s[1995]! } - public var AuthSessions_LoggedIn: String { return self._s[1996]! } - public var Privacy_Forwards_AlwaysAllow_Title: String { return self._s[1997]! } - public var Login_SmsRequestState3: String { return self._s[1998]! } - public var Passport_Address_EditUtilityBill: String { return self._s[1999]! } - public var Appearance_ReduceMotionInfo: String { return self._s[2000]! } - public var Join_ChannelsTooMuch: String { return self._s[2001]! } - public var Channel_Edit_LinkItem: String { return self._s[2002]! } - public var Privacy_Calls_P2PNever: String { return self._s[2003]! } - public var Conversation_AddToReadingList: String { return self._s[2005]! } - public var Share_MultipleMessagesDisabled: String { return self._s[2006]! } - public var Message_Animation: String { return self._s[2007]! } - public var Conversation_DefaultRestrictedMedia: String { return self._s[2008]! } - public var Map_Unknown: String { return self._s[2009]! } - public var AutoDownloadSettings_LastDelimeter: String { return self._s[2010]! } + public var IntentsSettings_Reset: String { return self._s[1984]! } + public var Conversation_Info: String { return self._s[1985]! } + public var Login_InfoDeletePhoto: String { return self._s[1986]! } + public var Passport_Language_vi: String { return self._s[1988]! } + public var UserInfo_ScamUserWarning: String { return self._s[1989]! } + public var Conversation_Search: String { return self._s[1990]! } + public var DialogList_DeleteBotConversationConfirmation: String { return self._s[1992]! } + public var ReportPeer_ReasonPornography: String { return self._s[1993]! } + public var AutoDownloadSettings_PhotosTitle: String { return self._s[1994]! } + public var Conversation_SendMessageErrorGroupRestricted: String { return self._s[1995]! } + public var Map_LiveLocationGroupDescription: String { return self._s[1996]! } + public var Channel_Setup_TypeHeader: String { return self._s[1997]! } + public var AuthSessions_LoggedIn: String { return self._s[1998]! } + public var Privacy_Forwards_AlwaysAllow_Title: String { return self._s[1999]! } + public var Login_SmsRequestState3: String { return self._s[2000]! } + public var Passport_Address_EditUtilityBill: String { return self._s[2001]! } + public var Appearance_ReduceMotionInfo: String { return self._s[2002]! } + public var Join_ChannelsTooMuch: String { return self._s[2003]! } + public var Channel_Edit_LinkItem: String { return self._s[2004]! } + public var Privacy_Calls_P2PNever: String { return self._s[2005]! } + public var Conversation_AddToReadingList: String { return self._s[2007]! } + public var Share_MultipleMessagesDisabled: String { return self._s[2008]! } + public var Message_Animation: String { return self._s[2009]! } + public var Conversation_DefaultRestrictedMedia: String { return self._s[2010]! } + public var Map_Unknown: String { return self._s[2011]! } + public var AutoDownloadSettings_LastDelimeter: String { return self._s[2012]! } public func PUSH_PINNED_TEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2011]!, self._r[2011]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2013]!, self._r[2013]!, [_1, _2]) } public func Passport_FieldOneOf_Or(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2012]!, self._r[2012]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2014]!, self._r[2014]!, [_1, _2]) } - public var Call_StatusRequesting: String { return self._s[2013]! } - public var Conversation_SecretChatContextBotAlert: String { return self._s[2014]! } - public var SocksProxySetup_ProxyStatusChecking: String { return self._s[2015]! } + public var Call_StatusRequesting: String { return self._s[2015]! } + public var Conversation_SecretChatContextBotAlert: String { return self._s[2016]! } + public var SocksProxySetup_ProxyStatusChecking: String { return self._s[2017]! } public func PUSH_CHAT_MESSAGE_DOC(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2016]!, self._r[2016]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2018]!, self._r[2018]!, [_1, _2]) } public func Notification_PinnedLocationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2017]!, self._r[2017]!, [_0]) + return formatWithArgumentRanges(self._s[2019]!, self._r[2019]!, [_0]) } - public var Update_Skip: String { return self._s[2018]! } - public var Group_Username_RemoveExistingUsernamesInfo: String { return self._s[2019]! } - public var BlockedUsers_Title: String { return self._s[2020]! } - public var Weekday_Monday: String { return self._s[2021]! } + public var Update_Skip: String { return self._s[2020]! } + public var Group_Username_RemoveExistingUsernamesInfo: String { return self._s[2021]! } + public var BlockedUsers_Title: String { return self._s[2022]! } + public var Weekday_Monday: String { return self._s[2023]! } public func PUSH_CHANNEL_MESSAGE_AUDIO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2022]!, self._r[2022]!, [_1]) + return formatWithArgumentRanges(self._s[2024]!, self._r[2024]!, [_1]) } - public var Username_CheckingUsername: String { return self._s[2023]! } - public var NotificationsSound_Bell: String { return self._s[2024]! } - public var Conversation_SendMessageErrorFlood: String { return self._s[2025]! } - public var SettingsSearch_Synonyms_Notifications_DisplayNamesOnLockScreen: String { return self._s[2026]! } - public var ChannelMembers_ChannelAdminsTitle: String { return self._s[2027]! } - public var ChatSettings_Groups: String { return self._s[2028]! } - public var WallpaperPreview_PatternPaternDiscard: String { return self._s[2029]! } + public var Username_CheckingUsername: String { return self._s[2025]! } + public var NotificationsSound_Bell: String { return self._s[2026]! } + public var Conversation_SendMessageErrorFlood: String { return self._s[2027]! } + public var SettingsSearch_Synonyms_Notifications_DisplayNamesOnLockScreen: String { return self._s[2028]! } + public var ChannelMembers_ChannelAdminsTitle: String { return self._s[2029]! } + public var ChatSettings_Groups: String { return self._s[2030]! } + public var WallpaperPreview_PatternPaternDiscard: String { return self._s[2031]! } public func Conversation_SetReminder_RemindTomorrow(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2030]!, self._r[2030]!, [_0]) + return formatWithArgumentRanges(self._s[2032]!, self._r[2032]!, [_0]) } - public var Your_card_was_declined: String { return self._s[2031]! } - public var TwoStepAuth_EnterPasswordHelp: String { return self._s[2033]! } - public var Wallet_Month_ShortApril: String { return self._s[2034]! } - public var ChatList_Unmute: String { return self._s[2035]! } - public var AuthSessions_AddDevice_ScanTitle: String { return self._s[2036]! } - public var PhotoEditor_CurvesAll: String { return self._s[2037]! } - public var Weekday_ShortTuesday: String { return self._s[2038]! } - public var DialogList_Read: String { return self._s[2039]! } - public var Appearance_AppIconClassic: String { return self._s[2040]! } - public var ChannelMembers_WhoCanAddMembers_AllMembers: String { return self._s[2041]! } - public var Passport_Identity_Gender: String { return self._s[2042]! } + public var Your_card_was_declined: String { return self._s[2033]! } + public var TwoStepAuth_EnterPasswordHelp: String { return self._s[2035]! } + public var Wallet_Month_ShortApril: String { return self._s[2036]! } + public var ChatList_Unmute: String { return self._s[2037]! } + public var AuthSessions_AddDevice_ScanTitle: String { return self._s[2038]! } + public var PhotoEditor_CurvesAll: String { return self._s[2039]! } + public var Weekday_ShortTuesday: String { return self._s[2040]! } + public var DialogList_Read: String { return self._s[2041]! } + public var Appearance_AppIconClassic: String { return self._s[2042]! } + public var ChannelMembers_WhoCanAddMembers_AllMembers: String { return self._s[2043]! } + public var Passport_Identity_Gender: String { return self._s[2044]! } public func Target_ShareGameConfirmationPrivate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2043]!, self._r[2043]!, [_0]) + return formatWithArgumentRanges(self._s[2045]!, self._r[2045]!, [_0]) } - public var Target_SelectGroup: String { return self._s[2044]! } - public var Map_HomeAndWorkInfo: String { return self._s[2046]! } + public var Target_SelectGroup: String { return self._s[2046]! } + public var Map_HomeAndWorkInfo: String { return self._s[2048]! } public func DialogList_EncryptedChatStartedIncoming(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2047]!, self._r[2047]!, [_0]) + return formatWithArgumentRanges(self._s[2049]!, self._r[2049]!, [_0]) } - public var Passport_Language_en: String { return self._s[2048]! } - public var AutoDownloadSettings_AutodownloadPhotos: String { return self._s[2049]! } - public var Channel_Username_CreatePublicLinkHelp: String { return self._s[2050]! } - public var Login_CancelPhoneVerificationContinue: String { return self._s[2051]! } - public var ScheduledMessages_SendNow: String { return self._s[2052]! } - public var Checkout_NewCard_PaymentCard: String { return self._s[2054]! } - public var Login_InfoHelp: String { return self._s[2055]! } - public var Appearance_BubbleCorners_AdjustAdjacent: String { return self._s[2056]! } - public var Contacts_PermissionsSuppressWarningTitle: String { return self._s[2057]! } - public var SettingsSearch_Synonyms_Stickers_FeaturedPacks: String { return self._s[2058]! } + public var Passport_Language_en: String { return self._s[2050]! } + public var AutoDownloadSettings_AutodownloadPhotos: String { return self._s[2051]! } + public var Channel_Username_CreatePublicLinkHelp: String { return self._s[2052]! } + public var Login_CancelPhoneVerificationContinue: String { return self._s[2053]! } + public var ScheduledMessages_SendNow: String { return self._s[2054]! } + public var Checkout_NewCard_PaymentCard: String { return self._s[2056]! } + public var Login_InfoHelp: String { return self._s[2057]! } + public var Appearance_BubbleCorners_AdjustAdjacent: String { return self._s[2058]! } + public var Contacts_PermissionsSuppressWarningTitle: String { return self._s[2059]! } + public var SettingsSearch_Synonyms_Stickers_FeaturedPacks: String { return self._s[2060]! } public func Channel_AdminLog_MessageChangedLinkedChannel(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2059]!, self._r[2059]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2061]!, self._r[2061]!, [_1, _2]) } - public var SocksProxySetup_AddProxy: String { return self._s[2062]! } - public var CreatePoll_Title: String { return self._s[2063]! } - public var MessagePoll_QuizNoUsers: String { return self._s[2064]! } - public var Conversation_ViewTheme: String { return self._s[2065]! } - public var SettingsSearch_Synonyms_Privacy_Data_SecretChatLinkPreview: String { return self._s[2066]! } - public var PasscodeSettings_SimplePasscodeHelp: String { return self._s[2067]! } - public var TwoFactorSetup_Intro_Text: String { return self._s[2068]! } - public var UserInfo_GroupsInCommon: String { return self._s[2069]! } - public var TelegramWallet_Intro_TermsUrl: String { return self._s[2070]! } - public var Call_AudioRouteHide: String { return self._s[2071]! } + public var SocksProxySetup_AddProxy: String { return self._s[2064]! } + public var CreatePoll_Title: String { return self._s[2065]! } + public var MessagePoll_QuizNoUsers: String { return self._s[2066]! } + public var Conversation_ViewTheme: String { return self._s[2067]! } + public var SettingsSearch_Synonyms_Privacy_Data_SecretChatLinkPreview: String { return self._s[2068]! } + public var PasscodeSettings_SimplePasscodeHelp: String { return self._s[2069]! } + public var TwoFactorSetup_Intro_Text: String { return self._s[2070]! } + public var UserInfo_GroupsInCommon: String { return self._s[2071]! } + public var TelegramWallet_Intro_TermsUrl: String { return self._s[2072]! } + public var Call_AudioRouteHide: String { return self._s[2073]! } public func Wallet_Info_TransactionDateHeader(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2073]!, self._r[2073]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2075]!, self._r[2075]!, [_1, _2]) } - public var ContactInfo_PhoneLabelMobile: String { return self._s[2074]! } - public var IntentsSettings_SuggestedChatsInfo: String { return self._s[2075]! } - public var CreatePoll_QuizOptionsHeader: String { return self._s[2076]! } + public var ContactInfo_PhoneLabelMobile: String { return self._s[2076]! } + public var IntentsSettings_SuggestedChatsInfo: String { return self._s[2077]! } + public var CreatePoll_QuizOptionsHeader: String { return self._s[2078]! } public func ChatList_LeaveGroupConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2077]!, self._r[2077]!, [_0]) + return formatWithArgumentRanges(self._s[2079]!, self._r[2079]!, [_0]) } - public var TextFormat_Bold: String { return self._s[2078]! } - public var FastTwoStepSetup_EmailSection: String { return self._s[2079]! } - public var StickerPackActionInfo_AddedTitle: String { return self._s[2080]! } - public var Notifications_Title: String { return self._s[2081]! } - public var Group_Username_InvalidTooShort: String { return self._s[2082]! } - public var Channel_ErrorAddTooMuch: String { return self._s[2083]! } + public var TextFormat_Bold: String { return self._s[2080]! } + public var FastTwoStepSetup_EmailSection: String { return self._s[2081]! } + public var StickerPackActionInfo_AddedTitle: String { return self._s[2082]! } + public var Notifications_Title: String { return self._s[2083]! } + public var Group_Username_InvalidTooShort: String { return self._s[2084]! } + public var Channel_ErrorAddTooMuch: String { return self._s[2085]! } public func DialogList_MultipleTypingSuffix(_ _0: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2084]!, self._r[2084]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[2086]!, self._r[2086]!, ["\(_0)"]) } - public var VoiceOver_DiscardPreparedContent: String { return self._s[2086]! } - public var Stickers_SuggestAdded: String { return self._s[2087]! } - public var Login_CountryCode: String { return self._s[2088]! } - public var ChatSettings_AutoPlayVideos: String { return self._s[2089]! } - public var Map_GetDirections: String { return self._s[2090]! } - public var Wallet_Receive_ShareInvoiceUrl: String { return self._s[2091]! } - public var Login_PhoneFloodError: String { return self._s[2092]! } + public var VoiceOver_DiscardPreparedContent: String { return self._s[2088]! } + public var Stickers_SuggestAdded: String { return self._s[2089]! } + public var Login_CountryCode: String { return self._s[2090]! } + public var ChatSettings_AutoPlayVideos: String { return self._s[2091]! } + public var Map_GetDirections: String { return self._s[2092]! } + public var Wallet_Receive_ShareInvoiceUrl: String { return self._s[2093]! } + public var Login_PhoneFloodError: String { return self._s[2094]! } public func Time_MonthOfYear_m3(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2093]!, self._r[2093]!, [_0]) + return formatWithArgumentRanges(self._s[2095]!, self._r[2095]!, [_0]) } public func Wallet_Time_PreciseDate_m10(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2094]!, self._r[2094]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2096]!, self._r[2096]!, [_1, _2, _3]) } - public var IntentsSettings_SuggestedChatsPrivateChats: String { return self._s[2095]! } - public var Settings_SetUsername: String { return self._s[2097]! } - public var Group_Location_ChangeLocation: String { return self._s[2098]! } - public var Notification_GroupInviterSelf: String { return self._s[2099]! } - public var InstantPage_TapToOpenLink: String { return self._s[2100]! } + public var IntentsSettings_SuggestedChatsPrivateChats: String { return self._s[2097]! } + public var Settings_SetUsername: String { return self._s[2099]! } + public var Group_Location_ChangeLocation: String { return self._s[2100]! } + public var Notification_GroupInviterSelf: String { return self._s[2101]! } + public var InstantPage_TapToOpenLink: String { return self._s[2102]! } public func Notification_ChannelInviter(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2101]!, self._r[2101]!, [_0]) + return formatWithArgumentRanges(self._s[2103]!, self._r[2103]!, [_0]) } - public var Watch_Suggestion_TalkLater: String { return self._s[2102]! } - public var SecretChat_Title: String { return self._s[2103]! } - public var Group_UpgradeNoticeText1: String { return self._s[2104]! } - public var AuthSessions_Title: String { return self._s[2105]! } + public var Watch_Suggestion_TalkLater: String { return self._s[2104]! } + public var SecretChat_Title: String { return self._s[2105]! } + public var Group_UpgradeNoticeText1: String { return self._s[2106]! } + public var AuthSessions_Title: String { return self._s[2107]! } public func TextFormat_AddLinkText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2106]!, self._r[2106]!, [_0]) + return formatWithArgumentRanges(self._s[2108]!, self._r[2108]!, [_0]) } - public var PhotoEditor_CropAuto: String { return self._s[2107]! } - public var Channel_About_Title: String { return self._s[2108]! } - public var Theme_ThemeChanged: String { return self._s[2109]! } - public var FastTwoStepSetup_EmailHelp: String { return self._s[2110]! } + public var PhotoEditor_CropAuto: String { return self._s[2109]! } + public var Channel_About_Title: String { return self._s[2110]! } + public var Theme_ThemeChanged: String { return self._s[2111]! } + public var FastTwoStepSetup_EmailHelp: String { return self._s[2112]! } public func Conversation_Bytes(_ _0: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2112]!, self._r[2112]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[2114]!, self._r[2114]!, ["\(_0)"]) } - public var VoiceOver_MessageContextReport: String { return self._s[2113]! } - public var Conversation_PinMessageAlert_OnlyPin: String { return self._s[2115]! } - public var Group_Setup_HistoryVisibleHelp: String { return self._s[2116]! } + public var VoiceOver_MessageContextReport: String { return self._s[2115]! } + public var Conversation_PinMessageAlert_OnlyPin: String { return self._s[2117]! } + public var Group_Setup_HistoryVisibleHelp: String { return self._s[2118]! } public func PUSH_MESSAGE_GIF(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2117]!, self._r[2117]!, [_1]) + return formatWithArgumentRanges(self._s[2119]!, self._r[2119]!, [_1]) } public func SharedMedia_SearchNoResultsDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2119]!, self._r[2119]!, [_0]) + return formatWithArgumentRanges(self._s[2121]!, self._r[2121]!, [_0]) } public func TwoStepAuth_RecoveryEmailUnavailable(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2120]!, self._r[2120]!, [_0]) + return formatWithArgumentRanges(self._s[2122]!, self._r[2122]!, [_0]) } - public var Privacy_PaymentsClearInfoHelp: String { return self._s[2121]! } - public var Presence_online: String { return self._s[2124]! } - public var PasscodeSettings_Title: String { return self._s[2125]! } - public var Passport_Identity_ExpiryDatePlaceholder: String { return self._s[2126]! } - public var Web_OpenExternal: String { return self._s[2127]! } - public var AutoDownloadSettings_AutoDownload: String { return self._s[2129]! } - public var Channel_OwnershipTransfer_EnterPasswordText: String { return self._s[2130]! } - public var LocalGroup_Title: String { return self._s[2131]! } + public var Privacy_PaymentsClearInfoHelp: String { return self._s[2123]! } + public var Presence_online: String { return self._s[2126]! } + public var PasscodeSettings_Title: String { return self._s[2127]! } + public var Passport_Identity_ExpiryDatePlaceholder: String { return self._s[2128]! } + public var Web_OpenExternal: String { return self._s[2129]! } + public var AutoDownloadSettings_AutoDownload: String { return self._s[2131]! } + public var Channel_OwnershipTransfer_EnterPasswordText: String { return self._s[2132]! } + public var LocalGroup_Title: String { return self._s[2133]! } public func AutoNightTheme_AutomaticHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2132]!, self._r[2132]!, [_0]) + return formatWithArgumentRanges(self._s[2134]!, self._r[2134]!, [_0]) } - public var FastTwoStepSetup_PasswordConfirmationPlaceholder: String { return self._s[2133]! } - public var Conversation_StopQuizConfirmation: String { return self._s[2134]! } - public var Map_YouAreHere: String { return self._s[2135]! } + public var FastTwoStepSetup_PasswordConfirmationPlaceholder: String { return self._s[2135]! } + public var Conversation_StopQuizConfirmation: String { return self._s[2136]! } + public var Map_YouAreHere: String { return self._s[2137]! } public func AuthSessions_Message(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2136]!, self._r[2136]!, [_0]) + return formatWithArgumentRanges(self._s[2138]!, self._r[2138]!, [_0]) } public func ChatList_DeleteChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2137]!, self._r[2137]!, [_0]) + return formatWithArgumentRanges(self._s[2139]!, self._r[2139]!, [_0]) } - public var Theme_Context_ChangeColors: String { return self._s[2138]! } - public var PrivacyLastSeenSettings_AlwaysShareWith: String { return self._s[2139]! } - public var Target_InviteToGroupErrorAlreadyInvited: String { return self._s[2140]! } + public var Theme_Context_ChangeColors: String { return self._s[2140]! } + public var PrivacyLastSeenSettings_AlwaysShareWith: String { return self._s[2141]! } + public var Target_InviteToGroupErrorAlreadyInvited: String { return self._s[2142]! } public func AuthSessions_AppUnofficial(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2141]!, self._r[2141]!, [_0]) + return formatWithArgumentRanges(self._s[2143]!, self._r[2143]!, [_0]) } public func DialogList_LiveLocationSharingTo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2142]!, self._r[2142]!, [_0]) + return formatWithArgumentRanges(self._s[2144]!, self._r[2144]!, [_0]) } - public var SocksProxySetup_Username: String { return self._s[2143]! } - public var Bot_Start: String { return self._s[2144]! } + public var SocksProxySetup_Username: String { return self._s[2145]! } + public var Bot_Start: String { return self._s[2146]! } public func Channel_AdminLog_EmptyFilterQueryText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2145]!, self._r[2145]!, [_0]) + return formatWithArgumentRanges(self._s[2147]!, self._r[2147]!, [_0]) } public func Channel_AdminLog_MessagePinned(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2146]!, self._r[2146]!, [_0]) + return formatWithArgumentRanges(self._s[2148]!, self._r[2148]!, [_0]) } - public var Contacts_SortByPresence: String { return self._s[2147]! } - public var AccentColor_Title: String { return self._s[2149]! } - public var Conversation_DiscardVoiceMessageTitle: String { return self._s[2150]! } + public var Contacts_SortByPresence: String { return self._s[2149]! } + public var AccentColor_Title: String { return self._s[2151]! } + public var Conversation_DiscardVoiceMessageTitle: String { return self._s[2152]! } public func PUSH_CHAT_CREATED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2151]!, self._r[2151]!, [_1, _2]) - } - public func PrivacySettings_LastSeenContactsMinus(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2152]!, self._r[2152]!, [_0]) - } - public func Channel_AdminLog_MessageChangedLinkedGroup(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2153]!, self._r[2153]!, [_1, _2]) } - public var Passport_Email_EnterOtherEmail: String { return self._s[2154]! } - public var Login_InfoAvatarPhoto: String { return self._s[2155]! } - public var Privacy_PaymentsClear_ShippingInfo: String { return self._s[2156]! } - public var Tour_Title4: String { return self._s[2157]! } - public var Passport_Identity_Translation: String { return self._s[2158]! } - public var SettingsSearch_Synonyms_Notifications_ContactJoined: String { return self._s[2159]! } - public var Login_TermsOfServiceLabel: String { return self._s[2161]! } - public var Passport_Language_it: String { return self._s[2162]! } - public var KeyCommand_JumpToNextUnreadChat: String { return self._s[2163]! } - public var Passport_Identity_SelfieHelp: String { return self._s[2164]! } - public var Conversation_ClearAll: String { return self._s[2166]! } - public var Wallet_Send_UninitializedText: String { return self._s[2168]! } - public var Channel_OwnershipTransfer_Title: String { return self._s[2169]! } - public var TwoStepAuth_FloodError: String { return self._s[2170]! } + public func PrivacySettings_LastSeenContactsMinus(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2154]!, self._r[2154]!, [_0]) + } + public func Channel_AdminLog_MessageChangedLinkedGroup(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2155]!, self._r[2155]!, [_1, _2]) + } + public var Passport_Email_EnterOtherEmail: String { return self._s[2156]! } + public var Login_InfoAvatarPhoto: String { return self._s[2157]! } + public var Privacy_PaymentsClear_ShippingInfo: String { return self._s[2158]! } + public var Tour_Title4: String { return self._s[2159]! } + public var Passport_Identity_Translation: String { return self._s[2160]! } + public var SettingsSearch_Synonyms_Notifications_ContactJoined: String { return self._s[2161]! } + public var Login_TermsOfServiceLabel: String { return self._s[2163]! } + public var Passport_Language_it: String { return self._s[2164]! } + public var KeyCommand_JumpToNextUnreadChat: String { return self._s[2165]! } + public var Passport_Identity_SelfieHelp: String { return self._s[2166]! } + public var Conversation_ClearAll: String { return self._s[2168]! } + public var Wallet_Send_UninitializedText: String { return self._s[2170]! } + public var Channel_OwnershipTransfer_Title: String { return self._s[2171]! } + public var TwoStepAuth_FloodError: String { return self._s[2172]! } public func PUSH_CHANNEL_MESSAGE_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2171]!, self._r[2171]!, [_1]) + return formatWithArgumentRanges(self._s[2173]!, self._r[2173]!, [_1]) } - public var Paint_Delete: String { return self._s[2172]! } + public var Paint_Delete: String { return self._s[2174]! } public func Wallet_Sent_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2173]!, self._r[2173]!, [_0]) + return formatWithArgumentRanges(self._s[2175]!, self._r[2175]!, [_0]) } - public var Privacy_AddNewPeer: String { return self._s[2174]! } + public var Privacy_AddNewPeer: String { return self._s[2176]! } public func Channel_AdminLog_MessageRank(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2175]!, self._r[2175]!, [_1]) + return formatWithArgumentRanges(self._s[2177]!, self._r[2177]!, [_1]) } - public var LogoutOptions_SetPasscodeText: String { return self._s[2176]! } + public var LogoutOptions_SetPasscodeText: String { return self._s[2178]! } public func Passport_AcceptHelp(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2177]!, self._r[2177]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2179]!, self._r[2179]!, [_1, _2]) } - public var Message_PinnedAudioMessage: String { return self._s[2178]! } + public var Message_PinnedAudioMessage: String { return self._s[2180]! } public func Watch_Time_ShortTodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2179]!, self._r[2179]!, [_0]) + return formatWithArgumentRanges(self._s[2181]!, self._r[2181]!, [_0]) } - public var Notification_Mute1hMin: String { return self._s[2180]! } - public var Notifications_GroupNotificationsSound: String { return self._s[2181]! } - public var Wallet_Month_GenNovember: String { return self._s[2182]! } - public var SocksProxySetup_ShareProxyList: String { return self._s[2183]! } - public var Conversation_MessageEditedLabel: String { return self._s[2184]! } + public var Notification_Mute1hMin: String { return self._s[2182]! } + public var Notifications_GroupNotificationsSound: String { return self._s[2183]! } + public var Wallet_Month_GenNovember: String { return self._s[2184]! } + public var SocksProxySetup_ShareProxyList: String { return self._s[2185]! } + public var Conversation_MessageEditedLabel: String { return self._s[2186]! } public func ClearCache_Success(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2185]!, self._r[2185]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2187]!, self._r[2187]!, [_0, _1]) } - public var Notification_Exceptions_AlwaysOff: String { return self._s[2186]! } - public var Notification_Exceptions_NewException_MessagePreviewHeader: String { return self._s[2187]! } + public var Notification_Exceptions_AlwaysOff: String { return self._s[2188]! } + public var Notification_Exceptions_NewException_MessagePreviewHeader: String { return self._s[2189]! } public func Channel_AdminLog_MessageAdmin(_ _0: String, _ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2188]!, self._r[2188]!, [_0, _1, _2]) + return formatWithArgumentRanges(self._s[2190]!, self._r[2190]!, [_0, _1, _2]) } - public var NetworkUsageSettings_ResetStats: String { return self._s[2189]! } + public var NetworkUsageSettings_ResetStats: String { return self._s[2191]! } public func PUSH_MESSAGE_GEOLIVE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2190]!, self._r[2190]!, [_1]) + return formatWithArgumentRanges(self._s[2192]!, self._r[2192]!, [_1]) } - public var AccessDenied_LocationTracking: String { return self._s[2191]! } - public var Month_GenOctober: String { return self._s[2192]! } - public var GroupInfo_InviteLink_RevokeAlert_Revoke: String { return self._s[2193]! } - public var EnterPasscode_EnterPasscode: String { return self._s[2194]! } - public var MediaPicker_TimerTooltip: String { return self._s[2196]! } - public var SharedMedia_TitleAll: String { return self._s[2197]! } - public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsExceptions: String { return self._s[2200]! } - public var Conversation_RestrictedMedia: String { return self._s[2201]! } - public var AccessDenied_PhotosRestricted: String { return self._s[2202]! } - public var Privacy_Forwards_WhoCanForward: String { return self._s[2204]! } - public var ChangePhoneNumberCode_Called: String { return self._s[2205]! } + public var AccessDenied_LocationTracking: String { return self._s[2193]! } + public var Month_GenOctober: String { return self._s[2194]! } + public var GroupInfo_InviteLink_RevokeAlert_Revoke: String { return self._s[2195]! } + public var EnterPasscode_EnterPasscode: String { return self._s[2196]! } + public var MediaPicker_TimerTooltip: String { return self._s[2198]! } + public var SharedMedia_TitleAll: String { return self._s[2199]! } + public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsExceptions: String { return self._s[2202]! } + public var Conversation_RestrictedMedia: String { return self._s[2203]! } + public var AccessDenied_PhotosRestricted: String { return self._s[2204]! } + public var Privacy_Forwards_WhoCanForward: String { return self._s[2206]! } + public var ChangePhoneNumberCode_Called: String { return self._s[2207]! } public func Notification_PinnedDocumentMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2206]!, self._r[2206]!, [_0]) + return formatWithArgumentRanges(self._s[2208]!, self._r[2208]!, [_0]) } - public var Conversation_SavedMessages: String { return self._s[2209]! } - public var Your_cards_expiration_month_is_invalid: String { return self._s[2211]! } - public var FastTwoStepSetup_PasswordPlaceholder: String { return self._s[2212]! } + public var Conversation_SavedMessages: String { return self._s[2211]! } + public var Your_cards_expiration_month_is_invalid: String { return self._s[2213]! } + public var FastTwoStepSetup_PasswordPlaceholder: String { return self._s[2214]! } public func Target_ShareGameConfirmationGroup(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2214]!, self._r[2214]!, [_0]) - } - public var VoiceOver_Chat_YourMessage: String { return self._s[2215]! } - public func VoiceOver_Chat_Title(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2216]!, self._r[2216]!, [_0]) } - public var ReportPeer_AlertSuccess: String { return self._s[2217]! } - public var PhotoEditor_CropAspectRatioOriginal: String { return self._s[2218]! } + public var VoiceOver_Chat_YourMessage: String { return self._s[2217]! } + public func VoiceOver_Chat_Title(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2218]!, self._r[2218]!, [_0]) + } + public var ReportPeer_AlertSuccess: String { return self._s[2219]! } + public var PhotoEditor_CropAspectRatioOriginal: String { return self._s[2220]! } public func InstantPage_RelatedArticleAuthorAndDateTitle(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2219]!, self._r[2219]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2221]!, self._r[2221]!, [_1, _2]) } - public var Checkout_PasswordEntry_Title: String { return self._s[2220]! } - public var PhotoEditor_FadeTool: String { return self._s[2221]! } - public var Privacy_ContactsReset: String { return self._s[2222]! } + public var Checkout_PasswordEntry_Title: String { return self._s[2222]! } + public var PhotoEditor_FadeTool: String { return self._s[2223]! } + public var Privacy_ContactsReset: String { return self._s[2224]! } public func Channel_AdminLog_MessageRestrictedUntil(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2224]!, self._r[2224]!, [_0]) + return formatWithArgumentRanges(self._s[2226]!, self._r[2226]!, [_0]) } - public var Message_PinnedVideoMessage: String { return self._s[2225]! } - public var ChatList_Mute: String { return self._s[2226]! } + public var Message_PinnedVideoMessage: String { return self._s[2227]! } + public var ChatList_Mute: String { return self._s[2228]! } public func Wallet_Time_PreciseDate_m5(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2227]!, self._r[2227]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2229]!, self._r[2229]!, [_1, _2, _3]) } - public var Permissions_CellularDataText_v0: String { return self._s[2228]! } - public var Conversation_PinnedQuiz: String { return self._s[2230]! } - public var ShareMenu_SelectChats: String { return self._s[2232]! } - public var ChatList_Context_Unarchive: String { return self._s[2233]! } - public var MusicPlayer_VoiceNote: String { return self._s[2234]! } - public var Conversation_RestrictedText: String { return self._s[2235]! } - public var SettingsSearch_Synonyms_Privacy_Data_DeleteDrafts: String { return self._s[2236]! } - public var Wallet_Month_GenApril: String { return self._s[2237]! } - public var Wallet_Month_ShortMarch: String { return self._s[2238]! } - public var TwoStepAuth_DisableSuccess: String { return self._s[2239]! } - public var Cache_Videos: String { return self._s[2240]! } - public var PrivacySettings_PhoneNumber: String { return self._s[2241]! } - public var Wallet_Month_GenFebruary: String { return self._s[2242]! } - public var FeatureDisabled_Oops: String { return self._s[2244]! } - public var Passport_Address_PostcodePlaceholder: String { return self._s[2245]! } + public var Permissions_CellularDataText_v0: String { return self._s[2230]! } + public var Conversation_PinnedQuiz: String { return self._s[2232]! } + public var ShareMenu_SelectChats: String { return self._s[2234]! } + public var ChatList_Context_Unarchive: String { return self._s[2235]! } + public var MusicPlayer_VoiceNote: String { return self._s[2236]! } + public var Conversation_RestrictedText: String { return self._s[2237]! } + public var SettingsSearch_Synonyms_Privacy_Data_DeleteDrafts: String { return self._s[2238]! } + public var Wallet_Month_GenApril: String { return self._s[2239]! } + public var Wallet_Month_ShortMarch: String { return self._s[2240]! } + public var TwoStepAuth_DisableSuccess: String { return self._s[2241]! } + public var Cache_Videos: String { return self._s[2242]! } + public var PrivacySettings_PhoneNumber: String { return self._s[2243]! } + public var Wallet_Month_GenFebruary: String { return self._s[2244]! } + public var FeatureDisabled_Oops: String { return self._s[2246]! } + public var Passport_Address_PostcodePlaceholder: String { return self._s[2247]! } public func AddContact_StatusSuccess(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2246]!, self._r[2246]!, [_0]) + return formatWithArgumentRanges(self._s[2248]!, self._r[2248]!, [_0]) } - public var Stickers_GroupStickersHelp: String { return self._s[2247]! } - public var GroupPermission_NoSendPolls: String { return self._s[2248]! } - public var Wallet_Qr_ScanCode: String { return self._s[2249]! } - public var Message_VideoExpired: String { return self._s[2251]! } - public var GroupInfo_GroupHistoryVisible: String { return self._s[2252]! } - public var Notifications_Badge: String { return self._s[2253]! } - public var Wallet_Receive_AddressCopied: String { return self._s[2254]! } - public var CreatePoll_OptionPlaceholder: String { return self._s[2255]! } - public var Username_InvalidTooShort: String { return self._s[2256]! } - public var EnterPasscode_EnterNewPasscodeChange: String { return self._s[2257]! } - public var Channel_AdminLog_PinMessages: String { return self._s[2258]! } - public var ArchivedChats_IntroTitle3: String { return self._s[2259]! } + public var Stickers_GroupStickersHelp: String { return self._s[2249]! } + public var GroupPermission_NoSendPolls: String { return self._s[2250]! } + public var Wallet_Qr_ScanCode: String { return self._s[2251]! } + public var Message_VideoExpired: String { return self._s[2253]! } + public var GroupInfo_GroupHistoryVisible: String { return self._s[2254]! } + public var Notifications_Badge: String { return self._s[2255]! } + public var Wallet_Receive_AddressCopied: String { return self._s[2256]! } + public var CreatePoll_OptionPlaceholder: String { return self._s[2257]! } + public var Username_InvalidTooShort: String { return self._s[2258]! } + public var EnterPasscode_EnterNewPasscodeChange: String { return self._s[2259]! } + public var Channel_AdminLog_PinMessages: String { return self._s[2260]! } + public var ArchivedChats_IntroTitle3: String { return self._s[2261]! } public func Notification_MessageLifetimeRemoved(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2260]!, self._r[2260]!, [_1]) + return formatWithArgumentRanges(self._s[2262]!, self._r[2262]!, [_1]) } - public var Permissions_SiriAllowInSettings_v0: String { return self._s[2261]! } - public var Conversation_DefaultRestrictedText: String { return self._s[2262]! } - public var SharedMedia_CategoryDocs: String { return self._s[2265]! } + public var Permissions_SiriAllowInSettings_v0: String { return self._s[2263]! } + public var Conversation_DefaultRestrictedText: String { return self._s[2264]! } + public var SharedMedia_CategoryDocs: String { return self._s[2267]! } public func PUSH_MESSAGE_CONTACT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2266]!, self._r[2266]!, [_1]) + return formatWithArgumentRanges(self._s[2268]!, self._r[2268]!, [_1]) } - public var Wallet_Send_UninitializedTitle: String { return self._s[2267]! } - public var StickerPackActionInfo_ArchivedTitle: String { return self._s[2268]! } - public var Privacy_Forwards_NeverLink: String { return self._s[2270]! } + public var Wallet_Send_UninitializedTitle: String { return self._s[2269]! } + public var StickerPackActionInfo_ArchivedTitle: String { return self._s[2270]! } + public var Privacy_Forwards_NeverLink: String { return self._s[2272]! } public func Notification_MessageLifetimeChangedOutgoing(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2271]!, self._r[2271]!, [_1]) + return formatWithArgumentRanges(self._s[2273]!, self._r[2273]!, [_1]) } - public var CheckoutInfo_ErrorShippingNotAvailable: String { return self._s[2272]! } + public var CheckoutInfo_ErrorShippingNotAvailable: String { return self._s[2274]! } public func Time_MonthOfYear_m12(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2273]!, self._r[2273]!, [_0]) + return formatWithArgumentRanges(self._s[2275]!, self._r[2275]!, [_0]) } - public var ChatSettings_PrivateChats: String { return self._s[2274]! } - public var SettingsSearch_Synonyms_EditProfile_Logout: String { return self._s[2275]! } - public var Conversation_PrivateMessageLinkCopied: String { return self._s[2276]! } - public var Channel_UpdatePhotoItem: String { return self._s[2277]! } - public var GroupInfo_LeftStatus: String { return self._s[2278]! } - public var Watch_MessageView_Forward: String { return self._s[2280]! } - public var ReportPeer_ReasonChildAbuse: String { return self._s[2281]! } - public var Cache_ClearEmpty: String { return self._s[2283]! } - public var Localization_LanguageName: String { return self._s[2284]! } - public var Wallet_AccessDenied_Title: String { return self._s[2285]! } - public var WebSearch_GIFs: String { return self._s[2286]! } - public var Notifications_DisplayNamesOnLockScreenInfoWithLink: String { return self._s[2287]! } - public var Wallet_AccessDenied_Settings: String { return self._s[2288]! } - public var Username_InvalidStartsWithNumber: String { return self._s[2289]! } - public var Common_Back: String { return self._s[2290]! } - public var GroupInfo_Permissions_EditingDisabled: String { return self._s[2291]! } - public var Passport_Identity_DateOfBirthPlaceholder: String { return self._s[2292]! } - public var Wallet_Send_Send: String { return self._s[2293]! } + public var ChatSettings_PrivateChats: String { return self._s[2276]! } + public var SettingsSearch_Synonyms_EditProfile_Logout: String { return self._s[2277]! } + public var Conversation_PrivateMessageLinkCopied: String { return self._s[2278]! } + public var Channel_UpdatePhotoItem: String { return self._s[2279]! } + public var GroupInfo_LeftStatus: String { return self._s[2280]! } + public var Watch_MessageView_Forward: String { return self._s[2282]! } + public var ReportPeer_ReasonChildAbuse: String { return self._s[2283]! } + public var Cache_ClearEmpty: String { return self._s[2285]! } + public var Localization_LanguageName: String { return self._s[2286]! } + public var Wallet_AccessDenied_Title: String { return self._s[2287]! } + public var WebSearch_GIFs: String { return self._s[2288]! } + public var Notifications_DisplayNamesOnLockScreenInfoWithLink: String { return self._s[2289]! } + public var Wallet_AccessDenied_Settings: String { return self._s[2290]! } + public var Username_InvalidStartsWithNumber: String { return self._s[2291]! } + public var Common_Back: String { return self._s[2292]! } + public var GroupInfo_Permissions_EditingDisabled: String { return self._s[2293]! } + public var Passport_Identity_DateOfBirthPlaceholder: String { return self._s[2294]! } + public var Wallet_Send_Send: String { return self._s[2295]! } public func PUSH_CHANNEL_MESSAGE_STICKER(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2295]!, self._r[2295]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2297]!, self._r[2297]!, [_1, _2]) } - public var Wallet_Info_RefreshErrorTitle: String { return self._s[2296]! } - public var Wallet_Month_GenJune: String { return self._s[2297]! } - public var Passport_Email_Help: String { return self._s[2298]! } - public var Watch_Conversation_Reply: String { return self._s[2300]! } - public var Conversation_EditingMessageMediaChange: String { return self._s[2303]! } - public var Passport_Identity_IssueDatePlaceholder: String { return self._s[2304]! } - public var Channel_BanUser_Unban: String { return self._s[2306]! } - public var Channel_EditAdmin_PermissionPostMessages: String { return self._s[2307]! } - public var Group_Username_CreatePublicLinkHelp: String { return self._s[2308]! } - public var TwoStepAuth_ConfirmEmailCodePlaceholder: String { return self._s[2310]! } - public var Wallet_Send_AddressHeader: String { return self._s[2311]! } - public var Passport_Identity_Name: String { return self._s[2312]! } + public var Wallet_Info_RefreshErrorTitle: String { return self._s[2298]! } + public var Wallet_Month_GenJune: String { return self._s[2299]! } + public var Passport_Email_Help: String { return self._s[2300]! } + public var Watch_Conversation_Reply: String { return self._s[2302]! } + public var Conversation_EditingMessageMediaChange: String { return self._s[2305]! } + public var Passport_Identity_IssueDatePlaceholder: String { return self._s[2306]! } + public var Channel_BanUser_Unban: String { return self._s[2308]! } + public var Channel_EditAdmin_PermissionPostMessages: String { return self._s[2309]! } + public var Group_Username_CreatePublicLinkHelp: String { return self._s[2310]! } + public var TwoStepAuth_ConfirmEmailCodePlaceholder: String { return self._s[2312]! } + public var Wallet_Send_AddressHeader: String { return self._s[2313]! } + public var Passport_Identity_Name: String { return self._s[2314]! } public func Channel_DiscussionGroup_HeaderGroupSet(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2313]!, self._r[2313]!, [_0]) + return formatWithArgumentRanges(self._s[2315]!, self._r[2315]!, [_0]) } - public var GroupRemoved_ViewUserInfo: String { return self._s[2314]! } - public var Conversation_BlockUser: String { return self._s[2315]! } - public var Month_GenJanuary: String { return self._s[2316]! } - public var ChatSettings_TextSize: String { return self._s[2317]! } - public var Notification_PassportValuePhone: String { return self._s[2318]! } - public var MediaPlayer_UnknownArtist: String { return self._s[2319]! } - public var Passport_Language_ne: String { return self._s[2320]! } - public var Notification_CallBack: String { return self._s[2321]! } - public var Wallet_SecureStorageReset_BiometryTouchId: String { return self._s[2322]! } - public var TwoStepAuth_EmailHelp: String { return self._s[2323]! } + public var GroupRemoved_ViewUserInfo: String { return self._s[2316]! } + public var Conversation_BlockUser: String { return self._s[2317]! } + public var Month_GenJanuary: String { return self._s[2318]! } + public var ChatSettings_TextSize: String { return self._s[2319]! } + public var Notification_PassportValuePhone: String { return self._s[2320]! } + public var MediaPlayer_UnknownArtist: String { return self._s[2321]! } + public var Passport_Language_ne: String { return self._s[2322]! } + public var Notification_CallBack: String { return self._s[2323]! } + public var Wallet_SecureStorageReset_BiometryTouchId: String { return self._s[2324]! } + public var TwoStepAuth_EmailHelp: String { return self._s[2325]! } public func Time_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2324]!, self._r[2324]!, [_0]) + return formatWithArgumentRanges(self._s[2326]!, self._r[2326]!, [_0]) } - public var Channel_Info_Management: String { return self._s[2325]! } - public var Passport_FieldIdentityUploadHelp: String { return self._s[2326]! } - public var Stickers_FrequentlyUsed: String { return self._s[2327]! } - public var Channel_BanUser_PermissionSendMessages: String { return self._s[2328]! } - public var Passport_Address_OneOfTypeUtilityBill: String { return self._s[2330]! } + public var Channel_Info_Management: String { return self._s[2327]! } + public var Passport_FieldIdentityUploadHelp: String { return self._s[2328]! } + public var Stickers_FrequentlyUsed: String { return self._s[2329]! } + public var Channel_BanUser_PermissionSendMessages: String { return self._s[2330]! } + public var Passport_Address_OneOfTypeUtilityBill: String { return self._s[2332]! } public func LOCAL_CHANNEL_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2331]!, self._r[2331]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[2333]!, self._r[2333]!, [_1, "\(_2)"]) } - public var TwoFactorSetup_Password_Title: String { return self._s[2332]! } - public var Passport_Address_EditResidentialAddress: String { return self._s[2333]! } - public var PrivacyPolicy_DeclineTitle: String { return self._s[2334]! } - public var CreatePoll_TextHeader: String { return self._s[2335]! } + public var TwoFactorSetup_Password_Title: String { return self._s[2334]! } + public var Passport_Address_EditResidentialAddress: String { return self._s[2335]! } + public var PrivacyPolicy_DeclineTitle: String { return self._s[2336]! } + public var CreatePoll_TextHeader: String { return self._s[2337]! } public func Checkout_SavePasswordTimeoutAndTouchId(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2336]!, self._r[2336]!, [_0]) + return formatWithArgumentRanges(self._s[2338]!, self._r[2338]!, [_0]) } - public var PhotoEditor_QualityMedium: String { return self._s[2337]! } - public var InfoPlist_NSMicrophoneUsageDescription: String { return self._s[2338]! } - public var Conversation_StatusKickedFromChannel: String { return self._s[2340]! } - public var CheckoutInfo_ReceiverInfoName: String { return self._s[2341]! } - public var Group_ErrorSendRestrictedStickers: String { return self._s[2342]! } + public var PhotoEditor_QualityMedium: String { return self._s[2339]! } + public var InfoPlist_NSMicrophoneUsageDescription: String { return self._s[2340]! } + public var Conversation_StatusKickedFromChannel: String { return self._s[2342]! } + public var CheckoutInfo_ReceiverInfoName: String { return self._s[2343]! } + public var Group_ErrorSendRestrictedStickers: String { return self._s[2344]! } public func Conversation_RestrictedInlineTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2343]!, self._r[2343]!, [_0]) + return formatWithArgumentRanges(self._s[2345]!, self._r[2345]!, [_0]) } public func Channel_AdminLog_MessageTransferedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2344]!, self._r[2344]!, [_1]) + return formatWithArgumentRanges(self._s[2346]!, self._r[2346]!, [_1]) } - public var LogoutOptions_LogOutWalletInfo: String { return self._s[2345]! } - public var TwoFactorSetup_Email_SkipConfirmationTitle: String { return self._s[2346]! } - public var Conversation_LinkDialogOpen: String { return self._s[2348]! } - public var TwoFactorSetup_Hint_Title: String { return self._s[2349]! } - public var VoiceOver_Chat_PollNoVotes: String { return self._s[2350]! } - public var Settings_Username: String { return self._s[2352]! } - public var Conversation_Block: String { return self._s[2354]! } - public var Wallpaper_Wallpaper: String { return self._s[2355]! } - public var SocksProxySetup_UseProxy: String { return self._s[2357]! } - public var Wallet_Send_Confirmation: String { return self._s[2358]! } - public var EditTheme_UploadEditedTheme: String { return self._s[2359]! } - public var UserInfo_ShareMyContactInfo: String { return self._s[2360]! } - public var MessageTimer_Forever: String { return self._s[2361]! } - public var Privacy_Calls_WhoCanCallMe: String { return self._s[2362]! } - public var PhotoEditor_DiscardChanges: String { return self._s[2363]! } - public var AuthSessions_TerminateOtherSessionsHelp: String { return self._s[2364]! } - public var Passport_Language_da: String { return self._s[2365]! } - public var SocksProxySetup_PortPlaceholder: String { return self._s[2366]! } + public var LogoutOptions_LogOutWalletInfo: String { return self._s[2347]! } + public var TwoFactorSetup_Email_SkipConfirmationTitle: String { return self._s[2348]! } + public var Conversation_LinkDialogOpen: String { return self._s[2350]! } + public var TwoFactorSetup_Hint_Title: String { return self._s[2351]! } + public var VoiceOver_Chat_PollNoVotes: String { return self._s[2352]! } + public var Settings_Username: String { return self._s[2354]! } + public var Conversation_Block: String { return self._s[2356]! } + public var Wallpaper_Wallpaper: String { return self._s[2357]! } + public var SocksProxySetup_UseProxy: String { return self._s[2359]! } + public var Wallet_Send_Confirmation: String { return self._s[2360]! } + public var EditTheme_UploadEditedTheme: String { return self._s[2361]! } + public var UserInfo_ShareMyContactInfo: String { return self._s[2362]! } + public var MessageTimer_Forever: String { return self._s[2363]! } + public var Privacy_Calls_WhoCanCallMe: String { return self._s[2364]! } + public var PhotoEditor_DiscardChanges: String { return self._s[2365]! } + public var AuthSessions_TerminateOtherSessionsHelp: String { return self._s[2366]! } + public var Passport_Language_da: String { return self._s[2367]! } + public var SocksProxySetup_PortPlaceholder: String { return self._s[2368]! } public func SecretGIF_NotViewedYet(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2367]!, self._r[2367]!, [_0]) + return formatWithArgumentRanges(self._s[2369]!, self._r[2369]!, [_0]) } - public var Passport_Address_EditPassportRegistration: String { return self._s[2368]! } + public var Passport_Address_EditPassportRegistration: String { return self._s[2370]! } public func Channel_AdminLog_MessageChangedGroupAbout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2370]!, self._r[2370]!, [_0]) + return formatWithArgumentRanges(self._s[2372]!, self._r[2372]!, [_0]) } - public var Settings_AddDevice: String { return self._s[2371]! } - public var Passport_Identity_ResidenceCountryPlaceholder: String { return self._s[2373]! } - public var AuthSessions_AddDeviceIntro_Text1: String { return self._s[2374]! } - public var Conversation_SearchByName_Prefix: String { return self._s[2375]! } - public var Conversation_PinnedPoll: String { return self._s[2376]! } - public var AuthSessions_AddDeviceIntro_Text2: String { return self._s[2377]! } - public var Conversation_EmptyGifPanelPlaceholder: String { return self._s[2378]! } - public var AuthSessions_AddDeviceIntro_Text3: String { return self._s[2379]! } + public var Settings_AddDevice: String { return self._s[2373]! } + public var Passport_Identity_ResidenceCountryPlaceholder: String { return self._s[2375]! } + public var AuthSessions_AddDeviceIntro_Text1: String { return self._s[2376]! } + public var Conversation_SearchByName_Prefix: String { return self._s[2377]! } + public var Conversation_PinnedPoll: String { return self._s[2378]! } + public var AuthSessions_AddDeviceIntro_Text2: String { return self._s[2379]! } + public var Conversation_EmptyGifPanelPlaceholder: String { return self._s[2380]! } + public var AuthSessions_AddDeviceIntro_Text3: String { return self._s[2381]! } public func PUSH_ENCRYPTION_ACCEPT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2380]!, self._r[2380]!, [_1]) + return formatWithArgumentRanges(self._s[2382]!, self._r[2382]!, [_1]) } - public var WallpaperSearch_ColorPurple: String { return self._s[2381]! } - public var Cache_ByPeerHeader: String { return self._s[2382]! } + public var WallpaperSearch_ColorPurple: String { return self._s[2383]! } + public var Cache_ByPeerHeader: String { return self._s[2384]! } public func Conversation_EncryptedPlaceholderTitleIncoming(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2383]!, self._r[2383]!, [_0]) + return formatWithArgumentRanges(self._s[2385]!, self._r[2385]!, [_0]) } - public var ChatSettings_AutoDownloadDocuments: String { return self._s[2384]! } - public var Appearance_ThemePreview_Chat_3_Text: String { return self._s[2387]! } - public var Wallet_Completed_Title: String { return self._s[2388]! } - public var Notification_PinnedMessage: String { return self._s[2389]! } - public var TwoFactorSetup_EmailVerification_Placeholder: String { return self._s[2390]! } - public var VoiceOver_Chat_RecordModeVideoMessage: String { return self._s[2392]! } - public var Contacts_SortBy: String { return self._s[2393]! } + public var ChatSettings_AutoDownloadDocuments: String { return self._s[2386]! } + public var Appearance_ThemePreview_Chat_3_Text: String { return self._s[2389]! } + public var Wallet_Completed_Title: String { return self._s[2390]! } + public var Notification_PinnedMessage: String { return self._s[2391]! } + public var TwoFactorSetup_EmailVerification_Placeholder: String { return self._s[2392]! } + public var VoiceOver_Chat_RecordModeVideoMessage: String { return self._s[2394]! } + public var Contacts_SortBy: String { return self._s[2395]! } public func PUSH_CHANNEL_MESSAGE_NOTEXT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2394]!, self._r[2394]!, [_1]) + return formatWithArgumentRanges(self._s[2396]!, self._r[2396]!, [_1]) } - public var Appearance_ColorThemeNight: String { return self._s[2396]! } + public var Appearance_ColorThemeNight: String { return self._s[2398]! } public func PUSH_MESSAGE_GAME(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2397]!, self._r[2397]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2399]!, self._r[2399]!, [_1, _2]) } - public var Call_EncryptionKey_Title: String { return self._s[2398]! } - public var Watch_UserInfo_Service: String { return self._s[2399]! } - public var SettingsSearch_Synonyms_Data_SaveEditedPhotos: String { return self._s[2401]! } - public var Conversation_Unpin: String { return self._s[2403]! } - public var CancelResetAccount_Title: String { return self._s[2404]! } - public var Map_LiveLocationFor15Minutes: String { return self._s[2405]! } + public var Call_EncryptionKey_Title: String { return self._s[2400]! } + public var Watch_UserInfo_Service: String { return self._s[2401]! } + public var SettingsSearch_Synonyms_Data_SaveEditedPhotos: String { return self._s[2403]! } + public var Conversation_Unpin: String { return self._s[2405]! } + public var CancelResetAccount_Title: String { return self._s[2406]! } + public var Map_LiveLocationFor15Minutes: String { return self._s[2407]! } public func Time_PreciseDate_m8(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2407]!, self._r[2407]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2409]!, self._r[2409]!, [_1, _2, _3]) } - public var Group_Members_AddMemberBotErrorNotAllowed: String { return self._s[2408]! } - public var Appearance_BubbleCorners_Title: String { return self._s[2409]! } - public var CallSettings_Title: String { return self._s[2410]! } - public var SettingsSearch_Synonyms_Appearance_ChatBackground: String { return self._s[2411]! } - public var PasscodeSettings_EncryptDataHelp: String { return self._s[2413]! } - public var AutoDownloadSettings_Contacts: String { return self._s[2414]! } + public var Group_Members_AddMemberBotErrorNotAllowed: String { return self._s[2410]! } + public var Appearance_BubbleCorners_Title: String { return self._s[2411]! } + public var CallSettings_Title: String { return self._s[2412]! } + public var SettingsSearch_Synonyms_Appearance_ChatBackground: String { return self._s[2413]! } + public var PasscodeSettings_EncryptDataHelp: String { return self._s[2415]! } + public var AutoDownloadSettings_Contacts: String { return self._s[2416]! } public func Channel_AdminLog_MessageRankName(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2415]!, self._r[2415]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2417]!, self._r[2417]!, [_1, _2]) } - public var Passport_Identity_DocumentDetails: String { return self._s[2416]! } - public var LoginPassword_PasswordHelp: String { return self._s[2417]! } - public var SettingsSearch_Synonyms_Data_AutoDownloadUsingWifi: String { return self._s[2418]! } - public var PrivacyLastSeenSettings_CustomShareSettings_Delete: String { return self._s[2419]! } - public var ChatContextMenu_TextSelectionTip: String { return self._s[2420]! } - public var Checkout_TotalPaidAmount: String { return self._s[2421]! } + public var Passport_Identity_DocumentDetails: String { return self._s[2418]! } + public var LoginPassword_PasswordHelp: String { return self._s[2419]! } + public var SettingsSearch_Synonyms_Data_AutoDownloadUsingWifi: String { return self._s[2420]! } + public var PrivacyLastSeenSettings_CustomShareSettings_Delete: String { return self._s[2421]! } + public var ChatContextMenu_TextSelectionTip: String { return self._s[2422]! } + public var Checkout_TotalPaidAmount: String { return self._s[2423]! } public func FileSize_KB(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2422]!, self._r[2422]!, [_0]) + return formatWithArgumentRanges(self._s[2424]!, self._r[2424]!, [_0]) } - public var PasscodeSettings_ChangePasscode: String { return self._s[2423]! } - public var Conversation_SecretLinkPreviewAlert: String { return self._s[2425]! } - public var Privacy_SecretChatsLinkPreviews: String { return self._s[2426]! } + public var ChatState_Updating: String { return self._s[2425]! } + public var PasscodeSettings_ChangePasscode: String { return self._s[2426]! } + public var Conversation_SecretLinkPreviewAlert: String { return self._s[2428]! } + public var Privacy_SecretChatsLinkPreviews: String { return self._s[2429]! } public func PUSH_CHANNEL_MESSAGE_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2427]!, self._r[2427]!, [_1]) + return formatWithArgumentRanges(self._s[2430]!, self._r[2430]!, [_1]) } - public var VoiceOver_Chat_ReplyToYourMessage: String { return self._s[2428]! } - public var Contacts_InviteFriends: String { return self._s[2430]! } - public var Map_ChooseLocationTitle: String { return self._s[2431]! } - public var Conversation_StopPoll: String { return self._s[2433]! } + public var VoiceOver_Chat_ReplyToYourMessage: String { return self._s[2431]! } + public var Contacts_InviteFriends: String { return self._s[2433]! } + public var Map_ChooseLocationTitle: String { return self._s[2434]! } + public var Conversation_StopPoll: String { return self._s[2436]! } public func WebSearch_SearchNoResultsDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2434]!, self._r[2434]!, [_0]) + return formatWithArgumentRanges(self._s[2437]!, self._r[2437]!, [_0]) } - public var Call_Camera: String { return self._s[2435]! } - public var LogoutOptions_ChangePhoneNumberTitle: String { return self._s[2436]! } - public var AppWallet_Intro_Text: String { return self._s[2437]! } - public var Appearance_BubbleCornersSetting: String { return self._s[2438]! } - public var Calls_RatingFeedback: String { return self._s[2439]! } - public var GroupInfo_BroadcastListNamePlaceholder: String { return self._s[2441]! } - public var Wallet_Alert_OK: String { return self._s[2442]! } - public var NotificationsSound_Pulse: String { return self._s[2443]! } - public var Watch_LastSeen_Lately: String { return self._s[2444]! } - public var ReportGroupLocation_Report: String { return self._s[2447]! } - public var Widget_NoUsers: String { return self._s[2448]! } - public var Conversation_UnvotePoll: String { return self._s[2449]! } - public var SettingsSearch_Synonyms_Privacy_ProfilePhoto: String { return self._s[2451]! } - public var Privacy_ProfilePhoto_WhoCanSeeMyPhoto: String { return self._s[2452]! } - public var NotificationsSound_Circles: String { return self._s[2453]! } - public var PrivacyLastSeenSettings_AlwaysShareWith_Title: String { return self._s[2456]! } - public var Wallet_Settings_DeleteWallet: String { return self._s[2457]! } - public var TwoStepAuth_RecoveryCodeExpired: String { return self._s[2458]! } - public var Proxy_TooltipUnavailable: String { return self._s[2459]! } - public var Passport_Identity_CountryPlaceholder: String { return self._s[2461]! } - public var GroupInfo_Permissions_SlowmodeInfo: String { return self._s[2463]! } - public var Conversation_FileDropbox: String { return self._s[2464]! } - public var Notifications_ExceptionsUnmuted: String { return self._s[2465]! } - public var Tour_Text3: String { return self._s[2467]! } - public var Login_ResetAccountProtected_Title: String { return self._s[2469]! } - public var GroupPermission_NoSendMessages: String { return self._s[2470]! } - public var WallpaperSearch_ColorTitle: String { return self._s[2471]! } - public var ChatAdmins_AllMembersAreAdminsOnHelp: String { return self._s[2472]! } + public var Call_Camera: String { return self._s[2438]! } + public var LogoutOptions_ChangePhoneNumberTitle: String { return self._s[2439]! } + public var AppWallet_Intro_Text: String { return self._s[2440]! } + public var Appearance_BubbleCornersSetting: String { return self._s[2441]! } + public var Calls_RatingFeedback: String { return self._s[2442]! } + public var GroupInfo_BroadcastListNamePlaceholder: String { return self._s[2444]! } + public var Wallet_Alert_OK: String { return self._s[2445]! } + public var NotificationsSound_Pulse: String { return self._s[2446]! } + public var Watch_LastSeen_Lately: String { return self._s[2447]! } + public var ReportGroupLocation_Report: String { return self._s[2450]! } + public var Widget_NoUsers: String { return self._s[2451]! } + public var Conversation_UnvotePoll: String { return self._s[2452]! } + public var SettingsSearch_Synonyms_Privacy_ProfilePhoto: String { return self._s[2454]! } + public var Privacy_ProfilePhoto_WhoCanSeeMyPhoto: String { return self._s[2455]! } + public var NotificationsSound_Circles: String { return self._s[2456]! } + public var PrivacyLastSeenSettings_AlwaysShareWith_Title: String { return self._s[2459]! } + public var Wallet_Settings_DeleteWallet: String { return self._s[2460]! } + public var TwoStepAuth_RecoveryCodeExpired: String { return self._s[2461]! } + public var Proxy_TooltipUnavailable: String { return self._s[2462]! } + public var Passport_Identity_CountryPlaceholder: String { return self._s[2464]! } + public var GroupInfo_Permissions_SlowmodeInfo: String { return self._s[2466]! } + public var Conversation_FileDropbox: String { return self._s[2467]! } + public var Notifications_ExceptionsUnmuted: String { return self._s[2468]! } + public var Tour_Text3: String { return self._s[2470]! } + public var Login_ResetAccountProtected_Title: String { return self._s[2472]! } + public var GroupPermission_NoSendMessages: String { return self._s[2473]! } + public var WallpaperSearch_ColorTitle: String { return self._s[2474]! } + public var ChatAdmins_AllMembersAreAdminsOnHelp: String { return self._s[2475]! } public func Conversation_LiveLocationYouAnd(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2474]!, self._r[2474]!, [_0]) + return formatWithArgumentRanges(self._s[2477]!, self._r[2477]!, [_0]) } - public var GroupInfo_AddParticipantTitle: String { return self._s[2475]! } - public var Checkout_ShippingOption_Title: String { return self._s[2476]! } - public var ChatSettings_AutoDownloadTitle: String { return self._s[2477]! } + public var GroupInfo_AddParticipantTitle: String { return self._s[2478]! } + public var Checkout_ShippingOption_Title: String { return self._s[2479]! } + public var ChatSettings_AutoDownloadTitle: String { return self._s[2480]! } public func DialogList_SingleTypingSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2478]!, self._r[2478]!, [_0]) + return formatWithArgumentRanges(self._s[2481]!, self._r[2481]!, [_0]) } public func ChatSettings_AutoDownloadSettings_TypeVideo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2479]!, self._r[2479]!, [_0]) + return formatWithArgumentRanges(self._s[2482]!, self._r[2482]!, [_0]) } - public var Channel_Management_LabelAdministrator: String { return self._s[2480]! } - public var EditTheme_FileReadError: String { return self._s[2481]! } - public var OwnershipTransfer_ComeBackLater: String { return self._s[2482]! } - public var PrivacyLastSeenSettings_NeverShareWith_Placeholder: String { return self._s[2483]! } - public var AutoDownloadSettings_Photos: String { return self._s[2485]! } - public var Appearance_PreviewIncomingText: String { return self._s[2486]! } - public var ChatList_Context_MarkAllAsRead: String { return self._s[2487]! } - public var ChannelInfo_ConfirmLeave: String { return self._s[2488]! } - public var MediaPicker_MomentsDateRangeSameMonthYearFormat: String { return self._s[2489]! } - public var Passport_Identity_DocumentNumberPlaceholder: String { return self._s[2490]! } - public var Channel_AdminLogFilter_EventsNewMembers: String { return self._s[2491]! } - public var PasscodeSettings_AutoLock_IfAwayFor_5minutes: String { return self._s[2492]! } - public var GroupInfo_SetGroupPhotoStop: String { return self._s[2493]! } - public var Notification_SecretChatScreenshot: String { return self._s[2494]! } - public var AccessDenied_Wallpapers: String { return self._s[2495]! } - public var ChatList_Context_Mute: String { return self._s[2497]! } - public var Passport_Address_City: String { return self._s[2498]! } - public var InfoPlist_NSPhotoLibraryAddUsageDescription: String { return self._s[2499]! } - public var Appearance_ThemeCarouselClassic: String { return self._s[2500]! } - public var SocksProxySetup_SecretPlaceholder: String { return self._s[2501]! } - public var AccessDenied_LocationDisabled: String { return self._s[2502]! } - public var Group_Location_Title: String { return self._s[2503]! } - public var SocksProxySetup_HostnamePlaceholder: String { return self._s[2505]! } - public var GroupInfo_Sound: String { return self._s[2506]! } - public var SettingsSearch_Synonyms_ChatSettings_OpenLinksIn: String { return self._s[2507]! } - public var ChannelInfo_ScamChannelWarning: String { return self._s[2508]! } - public var Stickers_RemoveFromFavorites: String { return self._s[2509]! } - public var Contacts_Title: String { return self._s[2510]! } - public var EditTheme_ThemeTemplateAlertText: String { return self._s[2511]! } - public var Passport_Language_fr: String { return self._s[2512]! } - public var TwoFactorSetup_EmailVerification_Action: String { return self._s[2513]! } - public var Notifications_ResetAllNotifications: String { return self._s[2514]! } - public var IntentsSettings_SuggestedChats: String { return self._s[2516]! } - public var PrivacySettings_SecurityTitle: String { return self._s[2518]! } - public var Checkout_NewCard_Title: String { return self._s[2519]! } - public var Login_HaveNotReceivedCodeInternal: String { return self._s[2520]! } - public var Conversation_ForwardChats: String { return self._s[2521]! } - public var Wallet_SecureStorageReset_PasscodeText: String { return self._s[2523]! } - public var PasscodeSettings_4DigitCode: String { return self._s[2524]! } - public var Settings_FAQ: String { return self._s[2526]! } - public var AutoDownloadSettings_DocumentsTitle: String { return self._s[2527]! } - public var Conversation_ContextMenuForward: String { return self._s[2528]! } - public var VoiceOver_Chat_YourPhoto: String { return self._s[2531]! } - public var PrivacyPolicy_Title: String { return self._s[2534]! } - public var Notifications_TextTone: String { return self._s[2535]! } - public var Profile_CreateNewContact: String { return self._s[2536]! } - public var PrivacyPhoneNumberSettings_WhoCanSeeMyPhoneNumber: String { return self._s[2537]! } - public var TwoFactorSetup_EmailVerification_Title: String { return self._s[2539]! } - public var Call_Speaker: String { return self._s[2540]! } - public var AutoNightTheme_AutomaticSection: String { return self._s[2541]! } - public var Channel_OwnershipTransfer_EnterPassword: String { return self._s[2543]! } - public var Channel_Username_InvalidCharacters: String { return self._s[2544]! } + public var Channel_Management_LabelAdministrator: String { return self._s[2483]! } + public var EditTheme_FileReadError: String { return self._s[2484]! } + public var OwnershipTransfer_ComeBackLater: String { return self._s[2485]! } + public var PrivacyLastSeenSettings_NeverShareWith_Placeholder: String { return self._s[2486]! } + public var AutoDownloadSettings_Photos: String { return self._s[2488]! } + public var Appearance_PreviewIncomingText: String { return self._s[2489]! } + public var ChatList_Context_MarkAllAsRead: String { return self._s[2490]! } + public var ChannelInfo_ConfirmLeave: String { return self._s[2491]! } + public var MediaPicker_MomentsDateRangeSameMonthYearFormat: String { return self._s[2492]! } + public var Passport_Identity_DocumentNumberPlaceholder: String { return self._s[2493]! } + public var Channel_AdminLogFilter_EventsNewMembers: String { return self._s[2494]! } + public var PasscodeSettings_AutoLock_IfAwayFor_5minutes: String { return self._s[2495]! } + public var GroupInfo_SetGroupPhotoStop: String { return self._s[2496]! } + public var Notification_SecretChatScreenshot: String { return self._s[2497]! } + public var AccessDenied_Wallpapers: String { return self._s[2498]! } + public var ChatList_Context_Mute: String { return self._s[2500]! } + public var Passport_Address_City: String { return self._s[2501]! } + public var InfoPlist_NSPhotoLibraryAddUsageDescription: String { return self._s[2502]! } + public var Appearance_ThemeCarouselClassic: String { return self._s[2503]! } + public var SocksProxySetup_SecretPlaceholder: String { return self._s[2504]! } + public var AccessDenied_LocationDisabled: String { return self._s[2505]! } + public var Group_Location_Title: String { return self._s[2506]! } + public var SocksProxySetup_HostnamePlaceholder: String { return self._s[2508]! } + public var GroupInfo_Sound: String { return self._s[2509]! } + public var SettingsSearch_Synonyms_ChatSettings_OpenLinksIn: String { return self._s[2510]! } + public var ChannelInfo_ScamChannelWarning: String { return self._s[2511]! } + public var Stickers_RemoveFromFavorites: String { return self._s[2512]! } + public var Contacts_Title: String { return self._s[2513]! } + public var EditTheme_ThemeTemplateAlertText: String { return self._s[2514]! } + public var Passport_Language_fr: String { return self._s[2515]! } + public var TwoFactorSetup_EmailVerification_Action: String { return self._s[2516]! } + public var Notifications_ResetAllNotifications: String { return self._s[2517]! } + public var IntentsSettings_SuggestedChats: String { return self._s[2519]! } + public var PrivacySettings_SecurityTitle: String { return self._s[2521]! } + public var Checkout_NewCard_Title: String { return self._s[2522]! } + public var Login_HaveNotReceivedCodeInternal: String { return self._s[2523]! } + public var Conversation_ForwardChats: String { return self._s[2524]! } + public var Wallet_SecureStorageReset_PasscodeText: String { return self._s[2526]! } + public var PasscodeSettings_4DigitCode: String { return self._s[2527]! } + public var Settings_FAQ: String { return self._s[2529]! } + public var AutoDownloadSettings_DocumentsTitle: String { return self._s[2530]! } + public var Conversation_ContextMenuForward: String { return self._s[2531]! } + public var VoiceOver_Chat_YourPhoto: String { return self._s[2534]! } + public var PrivacyPolicy_Title: String { return self._s[2537]! } + public var Notifications_TextTone: String { return self._s[2538]! } + public var Profile_CreateNewContact: String { return self._s[2539]! } + public var PrivacyPhoneNumberSettings_WhoCanSeeMyPhoneNumber: String { return self._s[2540]! } + public var TwoFactorSetup_EmailVerification_Title: String { return self._s[2542]! } + public var Call_Speaker: String { return self._s[2543]! } + public var AutoNightTheme_AutomaticSection: String { return self._s[2544]! } + public var Channel_OwnershipTransfer_EnterPassword: String { return self._s[2546]! } + public var Channel_Username_InvalidCharacters: String { return self._s[2547]! } public func Channel_AdminLog_MessageChangedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2545]!, self._r[2545]!, [_0]) + return formatWithArgumentRanges(self._s[2548]!, self._r[2548]!, [_0]) } - public var AutoDownloadSettings_AutodownloadFiles: String { return self._s[2546]! } - public var PrivacySettings_LastSeenTitle: String { return self._s[2547]! } - public var Channel_AdminLog_CanInviteUsers: String { return self._s[2548]! } - public var SettingsSearch_Synonyms_Privacy_Data_ClearPaymentsInfo: String { return self._s[2549]! } - public var OwnershipTransfer_SecurityCheck: String { return self._s[2550]! } - public var Conversation_MessageDeliveryFailed: String { return self._s[2551]! } - public var Watch_ChatList_NoConversationsText: String { return self._s[2552]! } - public var Bot_Unblock: String { return self._s[2553]! } - public var TextFormat_Italic: String { return self._s[2554]! } - public var WallpaperSearch_ColorPink: String { return self._s[2555]! } - public var Settings_About_Help: String { return self._s[2557]! } - public var SearchImages_Title: String { return self._s[2558]! } - public var Weekday_Wednesday: String { return self._s[2559]! } - public var Conversation_ClousStorageInfo_Description1: String { return self._s[2560]! } - public var ExplicitContent_AlertTitle: String { return self._s[2561]! } + public var AutoDownloadSettings_AutodownloadFiles: String { return self._s[2549]! } + public var PrivacySettings_LastSeenTitle: String { return self._s[2550]! } + public var Channel_AdminLog_CanInviteUsers: String { return self._s[2551]! } + public var SettingsSearch_Synonyms_Privacy_Data_ClearPaymentsInfo: String { return self._s[2552]! } + public var OwnershipTransfer_SecurityCheck: String { return self._s[2553]! } + public var Conversation_MessageDeliveryFailed: String { return self._s[2554]! } + public var Watch_ChatList_NoConversationsText: String { return self._s[2555]! } + public var Bot_Unblock: String { return self._s[2556]! } + public var TextFormat_Italic: String { return self._s[2557]! } + public var WallpaperSearch_ColorPink: String { return self._s[2558]! } + public var Settings_About_Help: String { return self._s[2560]! } + public var SearchImages_Title: String { return self._s[2561]! } + public var Weekday_Wednesday: String { return self._s[2562]! } + public var Conversation_ClousStorageInfo_Description1: String { return self._s[2563]! } + public var ExplicitContent_AlertTitle: String { return self._s[2564]! } public func Time_PreciseDate_m5(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2562]!, self._r[2562]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2565]!, self._r[2565]!, [_1, _2, _3]) } - public var Channel_DiscussionGroup_Create: String { return self._s[2563]! } - public var Weekday_Thursday: String { return self._s[2564]! } - public var Channel_BanUser_PermissionChangeGroupInfo: String { return self._s[2565]! } - public var Channel_Members_AddMembersHelp: String { return self._s[2566]! } + public var Channel_DiscussionGroup_Create: String { return self._s[2566]! } + public var Weekday_Thursday: String { return self._s[2567]! } + public var Channel_BanUser_PermissionChangeGroupInfo: String { return self._s[2568]! } + public var Channel_Members_AddMembersHelp: String { return self._s[2569]! } public func Checkout_SavePasswordTimeout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2567]!, self._r[2567]!, [_0]) + return formatWithArgumentRanges(self._s[2570]!, self._r[2570]!, [_0]) } - public var Channel_DiscussionGroup_LinkGroup: String { return self._s[2568]! } - public var SettingsSearch_Synonyms_Notifications_InAppNotificationsVibrate: String { return self._s[2569]! } - public var Passport_RequestedInformation: String { return self._s[2570]! } - public var Login_PhoneAndCountryHelp: String { return self._s[2571]! } - public var Conversation_EncryptionProcessing: String { return self._s[2573]! } - public var Notifications_PermissionsSuppressWarningTitle: String { return self._s[2574]! } - public var PhotoEditor_EnhanceTool: String { return self._s[2576]! } - public var Channel_Setup_Title: String { return self._s[2577]! } - public var Conversation_SearchPlaceholder: String { return self._s[2578]! } - public var OldChannels_GroupEmptyFormat: String { return self._s[2579]! } - public var AccessDenied_LocationAlwaysDenied: String { return self._s[2580]! } - public var Checkout_ErrorGeneric: String { return self._s[2581]! } - public var Passport_Language_hu: String { return self._s[2582]! } - public var GroupPermission_EditingDisabled: String { return self._s[2583]! } - public var Wallet_Month_ShortSeptember: String { return self._s[2585]! } + public var Channel_DiscussionGroup_LinkGroup: String { return self._s[2571]! } + public var SettingsSearch_Synonyms_Notifications_InAppNotificationsVibrate: String { return self._s[2572]! } + public var Passport_RequestedInformation: String { return self._s[2573]! } + public var Login_PhoneAndCountryHelp: String { return self._s[2574]! } + public var Conversation_EncryptionProcessing: String { return self._s[2576]! } + public var Notifications_PermissionsSuppressWarningTitle: String { return self._s[2577]! } + public var PhotoEditor_EnhanceTool: String { return self._s[2579]! } + public var Channel_Setup_Title: String { return self._s[2580]! } + public var Conversation_SearchPlaceholder: String { return self._s[2581]! } + public var OldChannels_GroupEmptyFormat: String { return self._s[2582]! } + public var AccessDenied_LocationAlwaysDenied: String { return self._s[2583]! } + public var Checkout_ErrorGeneric: String { return self._s[2584]! } + public var Passport_Language_hu: String { return self._s[2585]! } + public var GroupPermission_EditingDisabled: String { return self._s[2586]! } + public var Wallet_Month_ShortSeptember: String { return self._s[2588]! } public func Passport_Identity_UploadOneOfScan(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2586]!, self._r[2586]!, [_0]) + return formatWithArgumentRanges(self._s[2589]!, self._r[2589]!, [_0]) } public func PUSH_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2589]!, self._r[2589]!, [_1]) + return formatWithArgumentRanges(self._s[2592]!, self._r[2592]!, [_1]) } - public var ChatList_DeleteSavedMessagesConfirmationTitle: String { return self._s[2590]! } + public var ChatList_DeleteSavedMessagesConfirmationTitle: String { return self._s[2593]! } public func UserInfo_BlockConfirmationTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2591]!, self._r[2591]!, [_0]) + return formatWithArgumentRanges(self._s[2594]!, self._r[2594]!, [_0]) } - public var Conversation_CloudStorageInfo_Title: String { return self._s[2592]! } - public var Group_Location_Info: String { return self._s[2593]! } - public var PhotoEditor_CropAspectRatioSquare: String { return self._s[2594]! } - public var Permissions_PeopleNearbyAllow_v0: String { return self._s[2595]! } + public var Conversation_CloudStorageInfo_Title: String { return self._s[2595]! } + public var Group_Location_Info: String { return self._s[2596]! } + public var PhotoEditor_CropAspectRatioSquare: String { return self._s[2597]! } + public var Permissions_PeopleNearbyAllow_v0: String { return self._s[2598]! } public func Notification_Exceptions_MutedUntil(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2596]!, self._r[2596]!, [_0]) + return formatWithArgumentRanges(self._s[2599]!, self._r[2599]!, [_0]) } - public var Conversation_ClearPrivateHistory: String { return self._s[2597]! } - public var ContactInfo_PhoneLabelHome: String { return self._s[2598]! } - public var Appearance_RemoveThemeConfirmation: String { return self._s[2599]! } - public var PrivacySettings_LastSeenContacts: String { return self._s[2600]! } + public var Conversation_ClearPrivateHistory: String { return self._s[2600]! } + public var ContactInfo_PhoneLabelHome: String { return self._s[2601]! } + public var Appearance_RemoveThemeConfirmation: String { return self._s[2602]! } + public var PrivacySettings_LastSeenContacts: String { return self._s[2603]! } public func ChangePhone_ErrorOccupied(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2601]!, self._r[2601]!, [_0]) + return formatWithArgumentRanges(self._s[2604]!, self._r[2604]!, [_0]) } public func Notification_PinnedQuizMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2602]!, self._r[2602]!, [_0]) + return formatWithArgumentRanges(self._s[2605]!, self._r[2605]!, [_0]) } - public var Passport_Language_cs: String { return self._s[2603]! } - public var Message_PinnedAnimationMessage: String { return self._s[2605]! } - public var Passport_Identity_ReverseSideHelp: String { return self._s[2607]! } - public var SettingsSearch_Synonyms_Data_Storage_Title: String { return self._s[2608]! } - public var Wallet_Info_TransactionTo: String { return self._s[2610]! } - public var ChatList_DeleteForEveryoneConfirmationText: String { return self._s[2611]! } - public var SettingsSearch_Synonyms_Privacy_PasscodeAndTouchId: String { return self._s[2612]! } - public var Embed_PlayingInPIP: String { return self._s[2613]! } - public var Appearance_ThemePreview_Chat_3_TextWithLink: String { return self._s[2614]! } - public var AutoNightTheme_ScheduleSection: String { return self._s[2615]! } + public var Passport_Language_cs: String { return self._s[2606]! } + public var Message_PinnedAnimationMessage: String { return self._s[2608]! } + public var Passport_Identity_ReverseSideHelp: String { return self._s[2610]! } + public var SettingsSearch_Synonyms_Data_Storage_Title: String { return self._s[2611]! } + public var Wallet_Info_TransactionTo: String { return self._s[2613]! } + public var ChatList_DeleteForEveryoneConfirmationText: String { return self._s[2614]! } + public var SettingsSearch_Synonyms_Privacy_PasscodeAndTouchId: String { return self._s[2615]! } + public var Embed_PlayingInPIP: String { return self._s[2616]! } + public var Appearance_ThemePreview_Chat_3_TextWithLink: String { return self._s[2617]! } + public var AutoNightTheme_ScheduleSection: String { return self._s[2618]! } public func Call_EmojiDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2616]!, self._r[2616]!, [_0]) + return formatWithArgumentRanges(self._s[2619]!, self._r[2619]!, [_0]) } - public var MediaPicker_LivePhotoDescription: String { return self._s[2617]! } + public var MediaPicker_LivePhotoDescription: String { return self._s[2620]! } public func Channel_AdminLog_MessageRestrictedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2618]!, self._r[2618]!, [_1]) + return formatWithArgumentRanges(self._s[2621]!, self._r[2621]!, [_1]) } - public var Notification_PaymentSent: String { return self._s[2619]! } - public var PhotoEditor_CurvesGreen: String { return self._s[2620]! } - public var Notification_Exceptions_PreviewAlwaysOff: String { return self._s[2621]! } - public var AutoNightTheme_System: String { return self._s[2622]! } - public var SaveIncomingPhotosSettings_Title: String { return self._s[2623]! } - public var CreatePoll_QuizTitle: String { return self._s[2624]! } - public var NotificationSettings_ShowNotificationsAllAccounts: String { return self._s[2625]! } - public var VoiceOver_Chat_PagePreview: String { return self._s[2626]! } + public var Notification_PaymentSent: String { return self._s[2622]! } + public var PhotoEditor_CurvesGreen: String { return self._s[2623]! } + public var Notification_Exceptions_PreviewAlwaysOff: String { return self._s[2624]! } + public var AutoNightTheme_System: String { return self._s[2625]! } + public var SaveIncomingPhotosSettings_Title: String { return self._s[2626]! } + public var CreatePoll_QuizTitle: String { return self._s[2627]! } + public var NotificationSettings_ShowNotificationsAllAccounts: String { return self._s[2628]! } + public var VoiceOver_Chat_PagePreview: String { return self._s[2629]! } public func PUSH_MESSAGE_SCREENSHOT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2629]!, self._r[2629]!, [_1]) + return formatWithArgumentRanges(self._s[2632]!, self._r[2632]!, [_1]) } public func PUSH_MESSAGE_PHOTO_SECRET(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2630]!, self._r[2630]!, [_1]) + return formatWithArgumentRanges(self._s[2633]!, self._r[2633]!, [_1]) } public func ApplyLanguage_UnsufficientDataText(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2631]!, self._r[2631]!, [_1]) + return formatWithArgumentRanges(self._s[2634]!, self._r[2634]!, [_1]) } - public var NetworkUsageSettings_CallDataSection: String { return self._s[2633]! } - public var PasscodeSettings_HelpTop: String { return self._s[2634]! } - public var Conversation_WalletRequiredTitle: String { return self._s[2635]! } - public var Group_OwnershipTransfer_ErrorAdminsTooMuch: String { return self._s[2636]! } - public var Passport_Address_TypeRentalAgreement: String { return self._s[2637]! } - public var EditTheme_ShortLink: String { return self._s[2638]! } - public var Theme_Colors_ColorWallpaperWarning: String { return self._s[2639]! } - public var ProxyServer_VoiceOver_Active: String { return self._s[2640]! } - public var ReportPeer_ReasonOther_Placeholder: String { return self._s[2641]! } - public var CheckoutInfo_ErrorPhoneInvalid: String { return self._s[2642]! } - public var Call_Accept: String { return self._s[2644]! } - public var GroupRemoved_RemoveInfo: String { return self._s[2645]! } - public var Month_GenMarch: String { return self._s[2647]! } - public var PhotoEditor_ShadowsTool: String { return self._s[2648]! } - public var LoginPassword_Title: String { return self._s[2649]! } - public var Call_End: String { return self._s[2650]! } - public var Watch_Conversation_GroupInfo: String { return self._s[2651]! } - public var VoiceOver_Chat_Contact: String { return self._s[2652]! } - public var EditTheme_Create_Preview_IncomingText: String { return self._s[2653]! } - public var CallSettings_Always: String { return self._s[2654]! } - public var CallFeedback_Success: String { return self._s[2655]! } - public var TwoStepAuth_SetupHint: String { return self._s[2656]! } + public var NetworkUsageSettings_CallDataSection: String { return self._s[2636]! } + public var PasscodeSettings_HelpTop: String { return self._s[2637]! } + public var Conversation_WalletRequiredTitle: String { return self._s[2638]! } + public var Group_OwnershipTransfer_ErrorAdminsTooMuch: String { return self._s[2639]! } + public var Passport_Address_TypeRentalAgreement: String { return self._s[2640]! } + public var EditTheme_ShortLink: String { return self._s[2641]! } + public var Theme_Colors_ColorWallpaperWarning: String { return self._s[2642]! } + public var ProxyServer_VoiceOver_Active: String { return self._s[2643]! } + public var ReportPeer_ReasonOther_Placeholder: String { return self._s[2644]! } + public var CheckoutInfo_ErrorPhoneInvalid: String { return self._s[2645]! } + public var Call_Accept: String { return self._s[2647]! } + public var GroupRemoved_RemoveInfo: String { return self._s[2648]! } + public var Month_GenMarch: String { return self._s[2650]! } + public var PhotoEditor_ShadowsTool: String { return self._s[2651]! } + public var LoginPassword_Title: String { return self._s[2652]! } + public var Call_End: String { return self._s[2653]! } + public var Watch_Conversation_GroupInfo: String { return self._s[2654]! } + public var VoiceOver_Chat_Contact: String { return self._s[2655]! } + public var EditTheme_Create_Preview_IncomingText: String { return self._s[2656]! } + public var CallSettings_Always: String { return self._s[2657]! } + public var CallFeedback_Success: String { return self._s[2658]! } + public var TwoStepAuth_SetupHint: String { return self._s[2659]! } public func AddContact_ContactWillBeSharedAfterMutual(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2657]!, self._r[2657]!, [_1]) + return formatWithArgumentRanges(self._s[2660]!, self._r[2660]!, [_1]) } - public var ConversationProfile_UsersTooMuchError: String { return self._s[2658]! } - public var Login_PhoneTitle: String { return self._s[2659]! } - public var Passport_FieldPhoneHelp: String { return self._s[2660]! } - public var Weekday_ShortSunday: String { return self._s[2661]! } - public var Passport_InfoFAQ_URL: String { return self._s[2662]! } - public var ContactInfo_Job: String { return self._s[2664]! } - public var UserInfo_InviteBotToGroup: String { return self._s[2665]! } - public var Appearance_ThemeCarouselNightBlue: String { return self._s[2666]! } - public var CreatePoll_QuizTip: String { return self._s[2667]! } - public var TwoFactorSetup_Email_Text: String { return self._s[2668]! } - public var TwoStepAuth_PasswordRemovePassportConfirmation: String { return self._s[2669]! } - public var Invite_ChannelsTooMuch: String { return self._s[2670]! } - public var Wallet_Send_ConfirmationConfirm: String { return self._s[2671]! } - public var Wallet_TransactionInfo_OtherFeeInfo: String { return self._s[2672]! } - public var SettingsSearch_Synonyms_Notifications_InAppNotificationsPreview: String { return self._s[2673]! } - public var Wallet_Receive_AmountText: String { return self._s[2674]! } - public var Passport_DeletePersonalDetailsConfirmation: String { return self._s[2675]! } - public var CallFeedback_ReasonNoise: String { return self._s[2676]! } - public var Appearance_AppIconDefault: String { return self._s[2678]! } - public var Passport_Identity_AddInternalPassport: String { return self._s[2679]! } - public var MediaPicker_AddCaption: String { return self._s[2680]! } - public var CallSettings_TabIconDescription: String { return self._s[2681]! } + public var ConversationProfile_UsersTooMuchError: String { return self._s[2661]! } + public var Login_PhoneTitle: String { return self._s[2662]! } + public var Passport_FieldPhoneHelp: String { return self._s[2663]! } + public var Weekday_ShortSunday: String { return self._s[2664]! } + public var Passport_InfoFAQ_URL: String { return self._s[2665]! } + public var ContactInfo_Job: String { return self._s[2667]! } + public var UserInfo_InviteBotToGroup: String { return self._s[2668]! } + public var Appearance_ThemeCarouselNightBlue: String { return self._s[2669]! } + public var CreatePoll_QuizTip: String { return self._s[2670]! } + public var TwoFactorSetup_Email_Text: String { return self._s[2671]! } + public var TwoStepAuth_PasswordRemovePassportConfirmation: String { return self._s[2672]! } + public var Invite_ChannelsTooMuch: String { return self._s[2673]! } + public var Wallet_Send_ConfirmationConfirm: String { return self._s[2674]! } + public var Wallet_TransactionInfo_OtherFeeInfo: String { return self._s[2675]! } + public var SettingsSearch_Synonyms_Notifications_InAppNotificationsPreview: String { return self._s[2676]! } + public var Wallet_Receive_AmountText: String { return self._s[2677]! } + public var Passport_DeletePersonalDetailsConfirmation: String { return self._s[2678]! } + public var CallFeedback_ReasonNoise: String { return self._s[2679]! } + public var Appearance_AppIconDefault: String { return self._s[2681]! } + public var Passport_Identity_AddInternalPassport: String { return self._s[2682]! } + public var MediaPicker_AddCaption: String { return self._s[2683]! } + public var CallSettings_TabIconDescription: String { return self._s[2684]! } public func VoiceOver_Chat_Caption(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2682]!, self._r[2682]!, [_0]) + return formatWithArgumentRanges(self._s[2685]!, self._r[2685]!, [_0]) } - public var IntentsSettings_SuggestedChatsGroups: String { return self._s[2683]! } + public var IntentsSettings_SuggestedChatsGroups: String { return self._s[2686]! } public func Map_SearchNoResultsDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2684]!, self._r[2684]!, [_0]) + return formatWithArgumentRanges(self._s[2687]!, self._r[2687]!, [_0]) } - public var ChatList_UndoArchiveHiddenTitle: String { return self._s[2685]! } - public var Privacy_GroupsAndChannels_AlwaysAllow: String { return self._s[2686]! } - public var Passport_Identity_TypePersonalDetails: String { return self._s[2687]! } - public var DialogList_SearchSectionRecent: String { return self._s[2688]! } - public var PrivacyPolicy_DeclineMessage: String { return self._s[2689]! } - public var CreatePoll_Anonymous: String { return self._s[2690]! } - public var LogoutOptions_ClearCacheText: String { return self._s[2693]! } - public var LastSeen_WithinAWeek: String { return self._s[2694]! } - public var ChannelMembers_GroupAdminsTitle: String { return self._s[2695]! } - public var Conversation_CloudStorage_ChatStatus: String { return self._s[2697]! } - public var VoiceOver_Media_PlaybackRateNormal: String { return self._s[2698]! } + public var ChatList_UndoArchiveHiddenTitle: String { return self._s[2688]! } + public var Privacy_GroupsAndChannels_AlwaysAllow: String { return self._s[2689]! } + public var Passport_Identity_TypePersonalDetails: String { return self._s[2690]! } + public var DialogList_SearchSectionRecent: String { return self._s[2691]! } + public var PrivacyPolicy_DeclineMessage: String { return self._s[2692]! } + public var CreatePoll_Anonymous: String { return self._s[2693]! } + public var LogoutOptions_ClearCacheText: String { return self._s[2696]! } + public var LastSeen_WithinAWeek: String { return self._s[2697]! } + public var ChannelMembers_GroupAdminsTitle: String { return self._s[2698]! } + public var Conversation_CloudStorage_ChatStatus: String { return self._s[2700]! } + public var VoiceOver_Media_PlaybackRateNormal: String { return self._s[2701]! } public func AddContact_SharedContactExceptionInfo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2699]!, self._r[2699]!, [_0]) + return formatWithArgumentRanges(self._s[2702]!, self._r[2702]!, [_0]) } - public var Passport_Address_TypeResidentialAddress: String { return self._s[2700]! } - public var Conversation_StatusLeftGroup: String { return self._s[2701]! } - public var SocksProxySetup_ProxyDetailsTitle: String { return self._s[2702]! } - public var SettingsSearch_Synonyms_Calls_Title: String { return self._s[2704]! } - public var GroupPermission_AddSuccess: String { return self._s[2705]! } - public var PhotoEditor_BlurToolRadial: String { return self._s[2707]! } - public var Conversation_ContextMenuCopy: String { return self._s[2708]! } - public var AccessDenied_CallMicrophone: String { return self._s[2709]! } + public var Passport_Address_TypeResidentialAddress: String { return self._s[2703]! } + public var Conversation_StatusLeftGroup: String { return self._s[2704]! } + public var SocksProxySetup_ProxyDetailsTitle: String { return self._s[2705]! } + public var SettingsSearch_Synonyms_Calls_Title: String { return self._s[2707]! } + public var GroupPermission_AddSuccess: String { return self._s[2708]! } + public var PhotoEditor_BlurToolRadial: String { return self._s[2710]! } + public var Conversation_ContextMenuCopy: String { return self._s[2711]! } + public var AccessDenied_CallMicrophone: String { return self._s[2712]! } public func Time_PreciseDate_m2(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2710]!, self._r[2710]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2713]!, self._r[2713]!, [_1, _2, _3]) } - public var Login_InvalidFirstNameError: String { return self._s[2711]! } - public var Notifications_Badge_CountUnreadMessages_InfoOn: String { return self._s[2712]! } - public var Checkout_PaymentMethod_New: String { return self._s[2713]! } - public var ShareMenu_CopyShareLinkGame: String { return self._s[2714]! } - public var PhotoEditor_QualityTool: String { return self._s[2715]! } - public var Login_SendCodeViaSms: String { return self._s[2716]! } - public var SettingsSearch_Synonyms_Privacy_DeleteAccountIfAwayFor: String { return self._s[2717]! } - public var Chat_SlowmodeAttachmentLimitReached: String { return self._s[2718]! } - public var Wallet_Receive_CopyAddress: String { return self._s[2719]! } - public var Login_EmailNotConfiguredError: String { return self._s[2720]! } - public var SocksProxySetup_Status: String { return self._s[2721]! } - public var Conversation_ScheduleMessage_SendWhenOnline: String { return self._s[2722]! } - public var PrivacyPolicy_Accept: String { return self._s[2723]! } - public var Notifications_ExceptionsMessagePlaceholder: String { return self._s[2724]! } - public var Appearance_AppIconClassicX: String { return self._s[2725]! } + public var Login_InvalidFirstNameError: String { return self._s[2714]! } + public var Notifications_Badge_CountUnreadMessages_InfoOn: String { return self._s[2715]! } + public var Checkout_PaymentMethod_New: String { return self._s[2716]! } + public var ShareMenu_CopyShareLinkGame: String { return self._s[2717]! } + public var PhotoEditor_QualityTool: String { return self._s[2718]! } + public var Login_SendCodeViaSms: String { return self._s[2719]! } + public var SettingsSearch_Synonyms_Privacy_DeleteAccountIfAwayFor: String { return self._s[2720]! } + public var Chat_SlowmodeAttachmentLimitReached: String { return self._s[2721]! } + public var Wallet_Receive_CopyAddress: String { return self._s[2722]! } + public var Login_EmailNotConfiguredError: String { return self._s[2723]! } + public var SocksProxySetup_Status: String { return self._s[2724]! } + public var Conversation_ScheduleMessage_SendWhenOnline: String { return self._s[2725]! } + public var PrivacyPolicy_Accept: String { return self._s[2726]! } + public var Notifications_ExceptionsMessagePlaceholder: String { return self._s[2727]! } + public var Appearance_AppIconClassicX: String { return self._s[2728]! } public func PUSH_CHAT_MESSAGE_TEXT(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2726]!, self._r[2726]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2729]!, self._r[2729]!, [_1, _2, _3]) } - public var OwnershipTransfer_SecurityRequirements: String { return self._s[2727]! } - public var InfoPlist_NSLocationAlwaysUsageDescription: String { return self._s[2729]! } - public var AutoNightTheme_Automatic: String { return self._s[2730]! } - public var Channel_Username_InvalidStartsWithNumber: String { return self._s[2731]! } - public var Privacy_ContactsSyncHelp: String { return self._s[2732]! } - public var Cache_Help: String { return self._s[2733]! } - public var Group_ErrorAccessDenied: String { return self._s[2734]! } - public var Passport_Language_fa: String { return self._s[2735]! } - public var Wallet_Intro_Text: String { return self._s[2736]! } - public var Login_ResetAccountProtected_TimerTitle: String { return self._s[2737]! } - public var VoiceOver_Chat_YourVideoMessage: String { return self._s[2738]! } - public var PrivacySettings_LastSeen: String { return self._s[2739]! } + public var OwnershipTransfer_SecurityRequirements: String { return self._s[2730]! } + public var InfoPlist_NSLocationAlwaysUsageDescription: String { return self._s[2732]! } + public var AutoNightTheme_Automatic: String { return self._s[2733]! } + public var Channel_Username_InvalidStartsWithNumber: String { return self._s[2734]! } + public var Privacy_ContactsSyncHelp: String { return self._s[2735]! } + public var Cache_Help: String { return self._s[2736]! } + public var Group_ErrorAccessDenied: String { return self._s[2737]! } + public var Passport_Language_fa: String { return self._s[2738]! } + public var Wallet_Intro_Text: String { return self._s[2739]! } + public var Login_ResetAccountProtected_TimerTitle: String { return self._s[2740]! } + public var VoiceOver_Chat_YourVideoMessage: String { return self._s[2741]! } + public var PrivacySettings_LastSeen: String { return self._s[2742]! } public func DialogList_MultipleTyping(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2740]!, self._r[2740]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2743]!, self._r[2743]!, [_0, _1]) } - public var Wallet_Configuration_Apply: String { return self._s[2744]! } - public var Preview_SaveGif: String { return self._s[2745]! } - public var SettingsSearch_Synonyms_Privacy_TwoStepAuth: String { return self._s[2746]! } - public var Profile_About: String { return self._s[2747]! } - public var Channel_About_Placeholder: String { return self._s[2748]! } - public var Login_InfoTitle: String { return self._s[2749]! } + public var Wallet_Configuration_Apply: String { return self._s[2747]! } + public var Preview_SaveGif: String { return self._s[2748]! } + public var SettingsSearch_Synonyms_Privacy_TwoStepAuth: String { return self._s[2749]! } + public var Profile_About: String { return self._s[2750]! } + public var Channel_About_Placeholder: String { return self._s[2751]! } + public var Login_InfoTitle: String { return self._s[2752]! } public func TwoStepAuth_SetupPendingEmail(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2750]!, self._r[2750]!, [_0]) + return formatWithArgumentRanges(self._s[2753]!, self._r[2753]!, [_0]) } - public var EditTheme_Expand_Preview_IncomingReplyText: String { return self._s[2751]! } - public var Watch_Suggestion_CantTalk: String { return self._s[2753]! } - public var ContactInfo_Title: String { return self._s[2754]! } - public var Media_ShareThisVideo: String { return self._s[2755]! } - public var Weekday_ShortFriday: String { return self._s[2756]! } - public var AccessDenied_Contacts: String { return self._s[2758]! } - public var Notification_CallIncomingShort: String { return self._s[2759]! } - public var Group_Setup_TypePublic: String { return self._s[2760]! } - public var Notifications_MessageNotificationsExceptions: String { return self._s[2761]! } - public var Notifications_Badge_IncludeChannels: String { return self._s[2762]! } - public var Notifications_MessageNotificationsPreview: String { return self._s[2765]! } - public var ConversationProfile_ErrorCreatingConversation: String { return self._s[2766]! } - public var Group_ErrorAddTooMuchBots: String { return self._s[2767]! } - public var Privacy_GroupsAndChannels_CustomShareHelp: String { return self._s[2768]! } - public var Permissions_CellularDataAllowInSettings_v0: String { return self._s[2769]! } + public var EditTheme_Expand_Preview_IncomingReplyText: String { return self._s[2754]! } + public var Watch_Suggestion_CantTalk: String { return self._s[2756]! } + public var ContactInfo_Title: String { return self._s[2757]! } + public var Media_ShareThisVideo: String { return self._s[2758]! } + public var Weekday_ShortFriday: String { return self._s[2759]! } + public var AccessDenied_Contacts: String { return self._s[2761]! } + public var Notification_CallIncomingShort: String { return self._s[2762]! } + public var Group_Setup_TypePublic: String { return self._s[2763]! } + public var Notifications_MessageNotificationsExceptions: String { return self._s[2764]! } + public var Notifications_Badge_IncludeChannels: String { return self._s[2765]! } + public var Notifications_MessageNotificationsPreview: String { return self._s[2768]! } + public var ConversationProfile_ErrorCreatingConversation: String { return self._s[2769]! } + public var Group_ErrorAddTooMuchBots: String { return self._s[2770]! } + public var Privacy_GroupsAndChannels_CustomShareHelp: String { return self._s[2771]! } + public var Permissions_CellularDataAllowInSettings_v0: String { return self._s[2772]! } public func Wallet_SecureStorageChanged_BiometryText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2770]!, self._r[2770]!, [_0]) + return formatWithArgumentRanges(self._s[2773]!, self._r[2773]!, [_0]) } - public var DialogList_Typing: String { return self._s[2771]! } - public var CallFeedback_IncludeLogs: String { return self._s[2773]! } - public var Checkout_Phone: String { return self._s[2775]! } - public var Login_InfoFirstNamePlaceholder: String { return self._s[2778]! } - public var Privacy_Calls_Integration: String { return self._s[2779]! } - public var Notifications_PermissionsAllow: String { return self._s[2780]! } - public var TwoStepAuth_AddHintDescription: String { return self._s[2784]! } - public var Settings_ChatSettings: String { return self._s[2785]! } - public var Conversation_SendingOptionsTooltip: String { return self._s[2786]! } + public var DialogList_Typing: String { return self._s[2774]! } + public var CallFeedback_IncludeLogs: String { return self._s[2776]! } + public var Checkout_Phone: String { return self._s[2778]! } + public var Login_InfoFirstNamePlaceholder: String { return self._s[2781]! } + public var Privacy_Calls_Integration: String { return self._s[2782]! } + public var Notifications_PermissionsAllow: String { return self._s[2783]! } + public var TwoStepAuth_AddHintDescription: String { return self._s[2787]! } + public var Settings_ChatSettings: String { return self._s[2788]! } + public var Conversation_SendingOptionsTooltip: String { return self._s[2789]! } public func UserInfo_StartSecretChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2788]!, self._r[2788]!, [_0]) + return formatWithArgumentRanges(self._s[2791]!, self._r[2791]!, [_0]) } public func Channel_AdminLog_MessageInvitedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2789]!, self._r[2789]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2792]!, self._r[2792]!, [_1, _2]) } - public var GroupRemoved_DeleteUser: String { return self._s[2791]! } + public var GroupRemoved_DeleteUser: String { return self._s[2794]! } public func Channel_AdminLog_PollStopped(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2792]!, self._r[2792]!, [_0]) + return formatWithArgumentRanges(self._s[2795]!, self._r[2795]!, [_0]) } public func PUSH_MESSAGE_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2793]!, self._r[2793]!, [_1]) + return formatWithArgumentRanges(self._s[2796]!, self._r[2796]!, [_1]) } - public var Login_ContinueWithLocalization: String { return self._s[2794]! } - public var Watch_Message_ForwardedFrom: String { return self._s[2795]! } - public var TwoStepAuth_EnterEmailCode: String { return self._s[2797]! } - public var Conversation_Unblock: String { return self._s[2798]! } - public var PrivacySettings_DataSettings: String { return self._s[2799]! } - public var WallpaperPreview_PatternPaternApply: String { return self._s[2800]! } - public var Group_PublicLink_Info: String { return self._s[2801]! } + public var Login_ContinueWithLocalization: String { return self._s[2797]! } + public var Watch_Message_ForwardedFrom: String { return self._s[2798]! } + public var TwoStepAuth_EnterEmailCode: String { return self._s[2800]! } + public var Conversation_Unblock: String { return self._s[2801]! } + public var PrivacySettings_DataSettings: String { return self._s[2802]! } + public var WallpaperPreview_PatternPaternApply: String { return self._s[2803]! } + public var Group_PublicLink_Info: String { return self._s[2804]! } public func Wallet_Time_PreciseDate_m1(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2802]!, self._r[2802]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2805]!, self._r[2805]!, [_1, _2, _3]) } - public var Notifications_InAppNotificationsVibrate: String { return self._s[2803]! } + public var Notifications_InAppNotificationsVibrate: String { return self._s[2806]! } public func Privacy_GroupsAndChannels_InviteToChannelError(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2804]!, self._r[2804]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2807]!, self._r[2807]!, [_0, _1]) } - public var OldChannels_ChannelsHeader: String { return self._s[2806]! } - public var Wallet_RestoreFailed_CreateWallet: String { return self._s[2807]! } - public var PrivacySettings_Passcode: String { return self._s[2809]! } - public var Call_Mute: String { return self._s[2810]! } - public var Wallet_Weekday_Yesterday: String { return self._s[2811]! } - public var Passport_Language_dz: String { return self._s[2812]! } - public var Wallet_Receive_AmountHeader: String { return self._s[2813]! } - public var Wallet_TransactionInfo_OtherFeeInfoUrl: String { return self._s[2814]! } - public var Passport_Language_tk: String { return self._s[2815]! } + public var OldChannels_ChannelsHeader: String { return self._s[2809]! } + public var Wallet_RestoreFailed_CreateWallet: String { return self._s[2810]! } + public var PrivacySettings_Passcode: String { return self._s[2812]! } + public var Call_Mute: String { return self._s[2813]! } + public var Wallet_Weekday_Yesterday: String { return self._s[2814]! } + public var Passport_Language_dz: String { return self._s[2815]! } + public var Wallet_Receive_AmountHeader: String { return self._s[2816]! } + public var Wallet_TransactionInfo_OtherFeeInfoUrl: String { return self._s[2817]! } + public var Passport_Language_tk: String { return self._s[2818]! } public func Login_EmailCodeSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2816]!, self._r[2816]!, [_0]) + return formatWithArgumentRanges(self._s[2819]!, self._r[2819]!, [_0]) } - public var Settings_Search: String { return self._s[2817]! } - public var Wallet_Month_ShortFebruary: String { return self._s[2818]! } - public var InfoPlist_NSPhotoLibraryUsageDescription: String { return self._s[2819]! } - public var Wallet_Configuration_SourceJSON: String { return self._s[2820]! } - public var Conversation_ContextMenuReply: String { return self._s[2821]! } - public var WallpaperSearch_ColorBrown: String { return self._s[2822]! } - public var Chat_AttachmentMultipleForwardDisabled: String { return self._s[2823]! } - public var Tour_Title1: String { return self._s[2824]! } - public var Wallet_Alert_Cancel: String { return self._s[2825]! } - public var Conversation_ClearGroupHistory: String { return self._s[2827]! } - public var Wallet_TransactionInfo_RecipientHeader: String { return self._s[2828]! } - public var WallpaperPreview_Motion: String { return self._s[2829]! } + public var Settings_Search: String { return self._s[2820]! } + public var Wallet_Month_ShortFebruary: String { return self._s[2821]! } + public var InfoPlist_NSPhotoLibraryUsageDescription: String { return self._s[2822]! } + public var Wallet_Configuration_SourceJSON: String { return self._s[2823]! } + public var Conversation_ContextMenuReply: String { return self._s[2824]! } + public var WallpaperSearch_ColorBrown: String { return self._s[2825]! } + public var Chat_AttachmentMultipleForwardDisabled: String { return self._s[2826]! } + public var Tour_Title1: String { return self._s[2827]! } + public var Wallet_Alert_Cancel: String { return self._s[2828]! } + public var Conversation_ClearGroupHistory: String { return self._s[2830]! } + public var Wallet_TransactionInfo_RecipientHeader: String { return self._s[2831]! } + public var WallpaperPreview_Motion: String { return self._s[2832]! } public func Checkout_PasswordEntry_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2830]!, self._r[2830]!, [_0]) + return formatWithArgumentRanges(self._s[2833]!, self._r[2833]!, [_0]) } - public var Wallet_Configuration_ApplyErrorTextJSONInvalidData: String { return self._s[2831]! } - public var Call_RateCall: String { return self._s[2832]! } - public var Channel_AdminLog_BanSendStickersAndGifs: String { return self._s[2833]! } - public var Passport_PasswordCompleteSetup: String { return self._s[2834]! } - public var Conversation_InputTextSilentBroadcastPlaceholder: String { return self._s[2835]! } - public var UserInfo_LastNamePlaceholder: String { return self._s[2837]! } + public var Wallet_Configuration_ApplyErrorTextJSONInvalidData: String { return self._s[2834]! } + public var Call_RateCall: String { return self._s[2835]! } + public var Channel_AdminLog_BanSendStickersAndGifs: String { return self._s[2836]! } + public var Passport_PasswordCompleteSetup: String { return self._s[2837]! } + public var Conversation_InputTextSilentBroadcastPlaceholder: String { return self._s[2838]! } + public var UserInfo_LastNamePlaceholder: String { return self._s[2840]! } public func Login_WillCallYou(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2839]!, self._r[2839]!, [_0]) + return formatWithArgumentRanges(self._s[2842]!, self._r[2842]!, [_0]) } - public var Compose_Create: String { return self._s[2840]! } - public var Contacts_InviteToTelegram: String { return self._s[2841]! } - public var GroupInfo_Notifications: String { return self._s[2842]! } - public var ChatList_DeleteSavedMessagesConfirmationAction: String { return self._s[2844]! } - public var Message_PinnedLiveLocationMessage: String { return self._s[2845]! } - public var Month_GenApril: String { return self._s[2846]! } - public var Appearance_AutoNightTheme: String { return self._s[2847]! } - public var ChatSettings_AutomaticAudioDownload: String { return self._s[2849]! } - public var Login_CodeSentSms: String { return self._s[2851]! } + public var Compose_Create: String { return self._s[2843]! } + public var Contacts_InviteToTelegram: String { return self._s[2844]! } + public var GroupInfo_Notifications: String { return self._s[2845]! } + public var ChatList_DeleteSavedMessagesConfirmationAction: String { return self._s[2847]! } + public var Message_PinnedLiveLocationMessage: String { return self._s[2848]! } + public var Month_GenApril: String { return self._s[2849]! } + public var Appearance_AutoNightTheme: String { return self._s[2850]! } + public var ChatSettings_AutomaticAudioDownload: String { return self._s[2852]! } + public var Login_CodeSentSms: String { return self._s[2854]! } public func UserInfo_UnblockConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2852]!, self._r[2852]!, [_0]) + return formatWithArgumentRanges(self._s[2855]!, self._r[2855]!, [_0]) } - public var EmptyGroupInfo_Line3: String { return self._s[2853]! } - public var LogoutOptions_ContactSupportText: String { return self._s[2854]! } - public var Passport_Language_hr: String { return self._s[2855]! } - public var Common_ActionNotAllowedError: String { return self._s[2856]! } + public var EmptyGroupInfo_Line3: String { return self._s[2856]! } + public var LogoutOptions_ContactSupportText: String { return self._s[2857]! } + public var Passport_Language_hr: String { return self._s[2858]! } + public var Common_ActionNotAllowedError: String { return self._s[2859]! } public func Channel_AdminLog_MessageRestrictedNewSetting(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2857]!, self._r[2857]!, [_0]) + return formatWithArgumentRanges(self._s[2860]!, self._r[2860]!, [_0]) } - public var GroupInfo_InviteLink_CopyLink: String { return self._s[2858]! } - public var Wallet_Info_TransactionFrom: String { return self._s[2859]! } - public var Wallet_Send_ErrorDecryptionFailed: String { return self._s[2860]! } - public var Conversation_InputTextBroadcastPlaceholder: String { return self._s[2861]! } - public var Privacy_SecretChatsTitle: String { return self._s[2862]! } - public var Notification_SecretChatMessageScreenshotSelf: String { return self._s[2864]! } - public var GroupInfo_AddUserLeftError: String { return self._s[2865]! } - public var AutoDownloadSettings_TypePrivateChats: String { return self._s[2866]! } - public var LogoutOptions_ContactSupportTitle: String { return self._s[2867]! } - public var Appearance_ThemePreview_Chat_7_Text: String { return self._s[2868]! } - public var Channel_AddBotErrorHaveRights: String { return self._s[2869]! } - public var Preview_DeleteGif: String { return self._s[2870]! } - public var GroupInfo_Permissions_Exceptions: String { return self._s[2871]! } - public var Group_ErrorNotMutualContact: String { return self._s[2872]! } - public var Notification_MessageLifetime5s: String { return self._s[2873]! } - public var Wallet_Send_OwnAddressAlertText: String { return self._s[2874]! } - public var OldChannels_ChannelFormat: String { return self._s[2875]! } + public var GroupInfo_InviteLink_CopyLink: String { return self._s[2861]! } + public var Wallet_Info_TransactionFrom: String { return self._s[2862]! } + public var Wallet_Send_ErrorDecryptionFailed: String { return self._s[2863]! } + public var Conversation_InputTextBroadcastPlaceholder: String { return self._s[2864]! } + public var Privacy_SecretChatsTitle: String { return self._s[2865]! } + public var Notification_SecretChatMessageScreenshotSelf: String { return self._s[2867]! } + public var GroupInfo_AddUserLeftError: String { return self._s[2868]! } + public var AutoDownloadSettings_TypePrivateChats: String { return self._s[2869]! } + public var LogoutOptions_ContactSupportTitle: String { return self._s[2870]! } + public var Appearance_ThemePreview_Chat_7_Text: String { return self._s[2871]! } + public var Channel_AddBotErrorHaveRights: String { return self._s[2872]! } + public var Preview_DeleteGif: String { return self._s[2873]! } + public var GroupInfo_Permissions_Exceptions: String { return self._s[2874]! } + public var Group_ErrorNotMutualContact: String { return self._s[2875]! } + public var Notification_MessageLifetime5s: String { return self._s[2876]! } + public var Wallet_Send_OwnAddressAlertText: String { return self._s[2877]! } + public var OldChannels_ChannelFormat: String { return self._s[2878]! } public func Watch_LastSeen_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2876]!, self._r[2876]!, [_0]) + return formatWithArgumentRanges(self._s[2879]!, self._r[2879]!, [_0]) } - public var VoiceOver_Chat_Video: String { return self._s[2877]! } - public var Channel_OwnershipTransfer_ErrorPublicChannelsTooMuch: String { return self._s[2879]! } - public var ReportSpam_DeleteThisChat: String { return self._s[2880]! } - public var Passport_Address_AddBankStatement: String { return self._s[2881]! } - public var Notification_CallIncoming: String { return self._s[2882]! } - public var Wallet_Words_NotDoneTitle: String { return self._s[2883]! } - public var Compose_NewGroupTitle: String { return self._s[2884]! } - public var TwoStepAuth_RecoveryCodeHelp: String { return self._s[2886]! } - public var Passport_Address_Postcode: String { return self._s[2888]! } + public var VoiceOver_Chat_Video: String { return self._s[2880]! } + public var Channel_OwnershipTransfer_ErrorPublicChannelsTooMuch: String { return self._s[2882]! } + public var ReportSpam_DeleteThisChat: String { return self._s[2883]! } + public var Passport_Address_AddBankStatement: String { return self._s[2884]! } + public var Notification_CallIncoming: String { return self._s[2885]! } + public var Wallet_Words_NotDoneTitle: String { return self._s[2886]! } + public var Compose_NewGroupTitle: String { return self._s[2887]! } + public var TwoStepAuth_RecoveryCodeHelp: String { return self._s[2889]! } + public var Passport_Address_Postcode: String { return self._s[2891]! } public func LastSeen_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2889]!, self._r[2889]!, [_0]) + return formatWithArgumentRanges(self._s[2892]!, self._r[2892]!, [_0]) } - public var Checkout_NewCard_SaveInfoHelp: String { return self._s[2890]! } - public var Wallet_Month_ShortOctober: String { return self._s[2891]! } - public var VoiceOver_Chat_YourMusic: String { return self._s[2892]! } - public var WallpaperColors_Title: String { return self._s[2893]! } - public var SocksProxySetup_ShareQRCodeInfo: String { return self._s[2894]! } - public var VoiceOver_MessageContextForward: String { return self._s[2895]! } - public var GroupPermission_Duration: String { return self._s[2896]! } + public var Checkout_NewCard_SaveInfoHelp: String { return self._s[2893]! } + public var Wallet_Month_ShortOctober: String { return self._s[2894]! } + public var VoiceOver_Chat_YourMusic: String { return self._s[2895]! } + public var WallpaperColors_Title: String { return self._s[2896]! } + public var SocksProxySetup_ShareQRCodeInfo: String { return self._s[2897]! } + public var VoiceOver_MessageContextForward: String { return self._s[2898]! } + public var GroupPermission_Duration: String { return self._s[2899]! } public func Cache_Clear(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2897]!, self._r[2897]!, [_0]) + return formatWithArgumentRanges(self._s[2900]!, self._r[2900]!, [_0]) } - public var Bot_GroupStatusDoesNotReadHistory: String { return self._s[2898]! } - public var Username_Placeholder: String { return self._s[2899]! } - public var CallFeedback_WhatWentWrong: String { return self._s[2900]! } - public var Passport_FieldAddressUploadHelp: String { return self._s[2901]! } - public var Permissions_NotificationsAllowInSettings_v0: String { return self._s[2902]! } + public var Bot_GroupStatusDoesNotReadHistory: String { return self._s[2901]! } + public var Username_Placeholder: String { return self._s[2902]! } + public var CallFeedback_WhatWentWrong: String { return self._s[2903]! } + public var Passport_FieldAddressUploadHelp: String { return self._s[2904]! } + public var Permissions_NotificationsAllowInSettings_v0: String { return self._s[2905]! } public func Channel_AdminLog_MessageChangedUnlinkedChannel(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2904]!, self._r[2904]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2907]!, self._r[2907]!, [_1, _2]) } - public var Passport_PasswordDescription: String { return self._s[2905]! } - public var Channel_MessagePhotoUpdated: String { return self._s[2906]! } - public var MediaPicker_TapToUngroupDescription: String { return self._s[2907]! } - public var SettingsSearch_Synonyms_Notifications_BadgeCountUnreadMessages: String { return self._s[2908]! } - public var AttachmentMenu_PhotoOrVideo: String { return self._s[2909]! } - public var Conversation_ContextMenuMore: String { return self._s[2910]! } - public var Privacy_PaymentsClearInfo: String { return self._s[2911]! } - public var CallSettings_TabIcon: String { return self._s[2912]! } - public var KeyCommand_Find: String { return self._s[2913]! } - public var ClearCache_FreeSpaceDescription: String { return self._s[2914]! } - public var Appearance_ThemePreview_ChatList_7_Text: String { return self._s[2915]! } - public var EditTheme_Edit_Preview_IncomingText: String { return self._s[2916]! } - public var Message_PinnedGame: String { return self._s[2917]! } - public var VoiceOver_Chat_ForwardedFromYou: String { return self._s[2918]! } - public var Notifications_Badge_CountUnreadMessages_InfoOff: String { return self._s[2920]! } - public var Login_CallRequestState2: String { return self._s[2922]! } - public var CheckoutInfo_ReceiverInfoNamePlaceholder: String { return self._s[2924]! } + public var Passport_PasswordDescription: String { return self._s[2908]! } + public var Channel_MessagePhotoUpdated: String { return self._s[2909]! } + public var MediaPicker_TapToUngroupDescription: String { return self._s[2910]! } + public var SettingsSearch_Synonyms_Notifications_BadgeCountUnreadMessages: String { return self._s[2911]! } + public var AttachmentMenu_PhotoOrVideo: String { return self._s[2912]! } + public var Conversation_ContextMenuMore: String { return self._s[2913]! } + public var Privacy_PaymentsClearInfo: String { return self._s[2914]! } + public var CallSettings_TabIcon: String { return self._s[2915]! } + public var KeyCommand_Find: String { return self._s[2916]! } + public var ClearCache_FreeSpaceDescription: String { return self._s[2917]! } + public var Appearance_ThemePreview_ChatList_7_Text: String { return self._s[2918]! } + public var EditTheme_Edit_Preview_IncomingText: String { return self._s[2919]! } + public var Message_PinnedGame: String { return self._s[2920]! } + public var VoiceOver_Chat_ForwardedFromYou: String { return self._s[2921]! } + public var Notifications_Badge_CountUnreadMessages_InfoOff: String { return self._s[2923]! } + public var Login_CallRequestState2: String { return self._s[2925]! } + public var CheckoutInfo_ReceiverInfoNamePlaceholder: String { return self._s[2927]! } public func VoiceOver_Chat_PhotoFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2925]!, self._r[2925]!, [_0]) + return formatWithArgumentRanges(self._s[2928]!, self._r[2928]!, [_0]) } public func Checkout_PayPrice(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2927]!, self._r[2927]!, [_0]) + return formatWithArgumentRanges(self._s[2930]!, self._r[2930]!, [_0]) } - public var AuthSessions_AddDevice: String { return self._s[2928]! } - public var WallpaperPreview_Blurred: String { return self._s[2929]! } - public var Conversation_InstantPagePreview: String { return self._s[2930]! } + public var AuthSessions_AddDevice: String { return self._s[2931]! } + public var WallpaperPreview_Blurred: String { return self._s[2932]! } + public var Conversation_InstantPagePreview: String { return self._s[2933]! } public func DialogList_SingleUploadingVideoSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2931]!, self._r[2931]!, [_0]) + return formatWithArgumentRanges(self._s[2934]!, self._r[2934]!, [_0]) } - public var SecretTimer_VideoDescription: String { return self._s[2934]! } - public var WallpaperSearch_ColorRed: String { return self._s[2935]! } - public var GroupPermission_NoPinMessages: String { return self._s[2936]! } - public var Passport_Language_es: String { return self._s[2937]! } - public var Permissions_ContactsAllow_v0: String { return self._s[2939]! } - public var Conversation_EditingMessageMediaEditCurrentVideo: String { return self._s[2940]! } + public var SecretTimer_VideoDescription: String { return self._s[2937]! } + public var WallpaperSearch_ColorRed: String { return self._s[2938]! } + public var GroupPermission_NoPinMessages: String { return self._s[2939]! } + public var Passport_Language_es: String { return self._s[2940]! } + public var Permissions_ContactsAllow_v0: String { return self._s[2942]! } + public var Conversation_EditingMessageMediaEditCurrentVideo: String { return self._s[2943]! } public func PUSH_CHAT_MESSAGE_CONTACT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2941]!, self._r[2941]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2944]!, self._r[2944]!, [_1, _2]) } - public var Privacy_Forwards_CustomHelp: String { return self._s[2942]! } - public var WebPreview_GettingLinkInfo: String { return self._s[2943]! } - public var Watch_UserInfo_Unmute: String { return self._s[2944]! } - public var GroupInfo_ChannelListNamePlaceholder: String { return self._s[2945]! } - public var AccessDenied_CameraRestricted: String { return self._s[2947]! } + public var Privacy_Forwards_CustomHelp: String { return self._s[2945]! } + public var WebPreview_GettingLinkInfo: String { return self._s[2946]! } + public var Watch_UserInfo_Unmute: String { return self._s[2947]! } + public var GroupInfo_ChannelListNamePlaceholder: String { return self._s[2948]! } + public var AccessDenied_CameraRestricted: String { return self._s[2950]! } public func Conversation_Kilobytes(_ _0: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2948]!, self._r[2948]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[2951]!, self._r[2951]!, ["\(_0)"]) } - public var ChatList_ReadAll: String { return self._s[2950]! } - public var Settings_CopyUsername: String { return self._s[2951]! } - public var Contacts_SearchLabel: String { return self._s[2952]! } - public var Map_OpenInYandexNavigator: String { return self._s[2954]! } - public var PasscodeSettings_EncryptData: String { return self._s[2955]! } - public var Settings_Wallet: String { return self._s[2956]! } - public var Group_ErrorSupergroupConversionNotPossible: String { return self._s[2957]! } - public var WallpaperSearch_ColorPrefix: String { return self._s[2958]! } - public var Notifications_GroupNotificationsPreview: String { return self._s[2959]! } - public var DialogList_AdNoticeAlert: String { return self._s[2960]! } - public var Wallet_Month_GenMay: String { return self._s[2962]! } - public var CheckoutInfo_ShippingInfoAddress1: String { return self._s[2963]! } - public var CheckoutInfo_ShippingInfoAddress2: String { return self._s[2964]! } - public var Localization_LanguageCustom: String { return self._s[2965]! } - public var Passport_Identity_TypeDriversLicenseUploadScan: String { return self._s[2966]! } - public var CallFeedback_Title: String { return self._s[2967]! } - public var VoiceOver_Chat_RecordPreviewVoiceMessage: String { return self._s[2970]! } - public var Passport_Address_OneOfTypePassportRegistration: String { return self._s[2971]! } - public var Wallet_Intro_CreateErrorTitle: String { return self._s[2972]! } - public var Conversation_InfoGroup: String { return self._s[2973]! } - public var Compose_NewMessage: String { return self._s[2974]! } - public var FastTwoStepSetup_HintPlaceholder: String { return self._s[2975]! } - public var ChatSettings_AutoDownloadVideoMessages: String { return self._s[2976]! } - public var Wallet_SecureStorageReset_BiometryFaceId: String { return self._s[2977]! } - public var Channel_DiscussionGroup_UnlinkChannel: String { return self._s[2978]! } + public var ChatList_ReadAll: String { return self._s[2953]! } + public var Settings_CopyUsername: String { return self._s[2954]! } + public var Contacts_SearchLabel: String { return self._s[2955]! } + public var Map_OpenInYandexNavigator: String { return self._s[2957]! } + public var PasscodeSettings_EncryptData: String { return self._s[2958]! } + public var Settings_Wallet: String { return self._s[2959]! } + public var Group_ErrorSupergroupConversionNotPossible: String { return self._s[2960]! } + public var WallpaperSearch_ColorPrefix: String { return self._s[2961]! } + public var Notifications_GroupNotificationsPreview: String { return self._s[2962]! } + public var DialogList_AdNoticeAlert: String { return self._s[2963]! } + public var Wallet_Month_GenMay: String { return self._s[2965]! } + public var CheckoutInfo_ShippingInfoAddress1: String { return self._s[2966]! } + public var CheckoutInfo_ShippingInfoAddress2: String { return self._s[2967]! } + public var Localization_LanguageCustom: String { return self._s[2968]! } + public var Passport_Identity_TypeDriversLicenseUploadScan: String { return self._s[2969]! } + public var CallFeedback_Title: String { return self._s[2970]! } + public var VoiceOver_Chat_RecordPreviewVoiceMessage: String { return self._s[2973]! } + public var Passport_Address_OneOfTypePassportRegistration: String { return self._s[2974]! } + public var Wallet_Intro_CreateErrorTitle: String { return self._s[2975]! } + public var Conversation_InfoGroup: String { return self._s[2976]! } + public var Compose_NewMessage: String { return self._s[2977]! } + public var FastTwoStepSetup_HintPlaceholder: String { return self._s[2978]! } + public var ChatSettings_AutoDownloadVideoMessages: String { return self._s[2979]! } + public var Wallet_SecureStorageReset_BiometryFaceId: String { return self._s[2980]! } + public var Channel_DiscussionGroup_UnlinkChannel: String { return self._s[2981]! } public func Passport_Scans_ScanIndex(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2979]!, self._r[2979]!, [_0]) + return formatWithArgumentRanges(self._s[2982]!, self._r[2982]!, [_0]) } - public var Channel_AdminLog_CanDeleteMessages: String { return self._s[2980]! } - public var Login_CancelSignUpConfirmation: String { return self._s[2981]! } - public var ChangePhoneNumberCode_Help: String { return self._s[2982]! } - public var PrivacySettings_DeleteAccountHelp: String { return self._s[2983]! } - public var Channel_BlackList_Title: String { return self._s[2984]! } - public var UserInfo_PhoneCall: String { return self._s[2985]! } - public var Passport_Address_OneOfTypeBankStatement: String { return self._s[2987]! } - public var Wallet_Month_ShortJanuary: String { return self._s[2988]! } - public var State_connecting: String { return self._s[2989]! } - public var Appearance_ThemePreview_ChatList_6_Text: String { return self._s[2990]! } - public var Wallet_Month_GenMarch: String { return self._s[2991]! } - public var EditTheme_Expand_BottomInfo: String { return self._s[2992]! } - public var AuthSessions_AddedDeviceTerminate: String { return self._s[2993]! } + public var Channel_AdminLog_CanDeleteMessages: String { return self._s[2983]! } + public var Login_CancelSignUpConfirmation: String { return self._s[2984]! } + public var ChangePhoneNumberCode_Help: String { return self._s[2985]! } + public var PrivacySettings_DeleteAccountHelp: String { return self._s[2986]! } + public var Channel_BlackList_Title: String { return self._s[2987]! } + public var UserInfo_PhoneCall: String { return self._s[2988]! } + public var Passport_Address_OneOfTypeBankStatement: String { return self._s[2990]! } + public var Wallet_Month_ShortJanuary: String { return self._s[2991]! } + public var State_connecting: String { return self._s[2992]! } + public var Appearance_ThemePreview_ChatList_6_Text: String { return self._s[2993]! } + public var Wallet_Month_GenMarch: String { return self._s[2994]! } + public var EditTheme_Expand_BottomInfo: String { return self._s[2995]! } + public var AuthSessions_AddedDeviceTerminate: String { return self._s[2996]! } public func LastSeen_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2994]!, self._r[2994]!, [_0]) + return formatWithArgumentRanges(self._s[2997]!, self._r[2997]!, [_0]) } public func DialogList_SingleRecordingAudioSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2995]!, self._r[2995]!, [_0]) + return formatWithArgumentRanges(self._s[2998]!, self._r[2998]!, [_0]) } - public var Notifications_GroupNotifications: String { return self._s[2996]! } - public var Conversation_SendMessageErrorTooMuchScheduled: String { return self._s[2997]! } - public var Passport_Identity_EditPassport: String { return self._s[2998]! } - public var EnterPasscode_RepeatNewPasscode: String { return self._s[3000]! } - public var Localization_EnglishLanguageName: String { return self._s[3001]! } - public var Share_AuthDescription: String { return self._s[3002]! } - public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsAlert: String { return self._s[3003]! } - public var Passport_Identity_Surname: String { return self._s[3004]! } - public var Compose_TokenListPlaceholder: String { return self._s[3005]! } - public var Wallet_AccessDenied_Camera: String { return self._s[3006]! } - public var Passport_Identity_OneOfTypePassport: String { return self._s[3007]! } - public var Settings_AboutEmpty: String { return self._s[3008]! } - public var Conversation_Unmute: String { return self._s[3009]! } - public var CreateGroup_ChannelsTooMuch: String { return self._s[3011]! } - public var Wallet_Sending_Text: String { return self._s[3012]! } + public var Notifications_GroupNotifications: String { return self._s[2999]! } + public var Conversation_SendMessageErrorTooMuchScheduled: String { return self._s[3000]! } + public var Passport_Identity_EditPassport: String { return self._s[3001]! } + public var EnterPasscode_RepeatNewPasscode: String { return self._s[3003]! } + public var Localization_EnglishLanguageName: String { return self._s[3004]! } + public var Share_AuthDescription: String { return self._s[3005]! } + public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsAlert: String { return self._s[3006]! } + public var Passport_Identity_Surname: String { return self._s[3007]! } + public var Compose_TokenListPlaceholder: String { return self._s[3008]! } + public var Wallet_AccessDenied_Camera: String { return self._s[3009]! } + public var Passport_Identity_OneOfTypePassport: String { return self._s[3010]! } + public var Settings_AboutEmpty: String { return self._s[3011]! } + public var Conversation_Unmute: String { return self._s[3012]! } + public var CreateGroup_ChannelsTooMuch: String { return self._s[3014]! } + public var Wallet_Sending_Text: String { return self._s[3015]! } public func PUSH_CONTACT_JOINED(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3013]!, self._r[3013]!, [_1]) + return formatWithArgumentRanges(self._s[3016]!, self._r[3016]!, [_1]) } - public var Login_CodeSentCall: String { return self._s[3014]! } - public var ContactInfo_PhoneLabelHomeFax: String { return self._s[3016]! } - public var ChatSettings_Appearance: String { return self._s[3017]! } - public var ClearCache_StorageUsage: String { return self._s[3018]! } - public var Appearance_PickAccentColor: String { return self._s[3019]! } + public var Login_CodeSentCall: String { return self._s[3017]! } + public var ContactInfo_PhoneLabelHomeFax: String { return self._s[3019]! } + public var ChatSettings_Appearance: String { return self._s[3020]! } + public var ClearCache_StorageUsage: String { return self._s[3021]! } + public var Appearance_PickAccentColor: String { return self._s[3022]! } public func PUSH_CHAT_MESSAGE_NOTEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3020]!, self._r[3020]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3023]!, self._r[3023]!, [_1, _2]) } public func PUSH_MESSAGE_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3021]!, self._r[3021]!, [_1]) + return formatWithArgumentRanges(self._s[3024]!, self._r[3024]!, [_1]) } - public var Notification_CallMissed: String { return self._s[3022]! } - public var SettingsSearch_Synonyms_Appearance_ChatBackground_Custom: String { return self._s[3023]! } - public var Channel_AdminLogFilter_EventsInfo: String { return self._s[3024]! } - public var Wallet_Month_GenOctober: String { return self._s[3026]! } - public var ChatAdmins_AdminLabel: String { return self._s[3027]! } - public var KeyCommand_JumpToNextChat: String { return self._s[3028]! } - public var Conversation_StopPollConfirmationTitle: String { return self._s[3030]! } - public var ChangePhoneNumberCode_CodePlaceholder: String { return self._s[3031]! } - public var Month_GenJune: String { return self._s[3032]! } - public var IntentsSettings_MainAccountInfo: String { return self._s[3033]! } - public var Watch_Location_Current: String { return self._s[3034]! } - public var Wallet_Receive_CopyInvoiceUrl: String { return self._s[3035]! } - public var Conversation_TitleMute: String { return self._s[3036]! } - public var Map_PlacesInThisArea: String { return self._s[3037]! } + public var Notification_CallMissed: String { return self._s[3025]! } + public var SettingsSearch_Synonyms_Appearance_ChatBackground_Custom: String { return self._s[3026]! } + public var Channel_AdminLogFilter_EventsInfo: String { return self._s[3027]! } + public var Wallet_Month_GenOctober: String { return self._s[3029]! } + public var ChatAdmins_AdminLabel: String { return self._s[3030]! } + public var KeyCommand_JumpToNextChat: String { return self._s[3031]! } + public var Conversation_StopPollConfirmationTitle: String { return self._s[3033]! } + public var ChangePhoneNumberCode_CodePlaceholder: String { return self._s[3034]! } + public var Month_GenJune: String { return self._s[3035]! } + public var IntentsSettings_MainAccountInfo: String { return self._s[3036]! } + public var Watch_Location_Current: String { return self._s[3037]! } + public var Wallet_Receive_CopyInvoiceUrl: String { return self._s[3038]! } + public var Conversation_TitleMute: String { return self._s[3039]! } + public var Map_PlacesInThisArea: String { return self._s[3040]! } public func PUSH_CHANNEL_MESSAGE_ROUND(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3038]!, self._r[3038]!, [_1]) + return formatWithArgumentRanges(self._s[3041]!, self._r[3041]!, [_1]) } - public var GroupInfo_DeleteAndExit: String { return self._s[3039]! } + public var GroupInfo_DeleteAndExit: String { return self._s[3042]! } public func Conversation_Moderate_DeleteAllMessages(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3040]!, self._r[3040]!, [_0]) + return formatWithArgumentRanges(self._s[3043]!, self._r[3043]!, [_0]) } - public var Call_ReportPlaceholder: String { return self._s[3041]! } - public var Chat_SlowmodeSendError: String { return self._s[3042]! } - public var MaskStickerSettings_Info: String { return self._s[3043]! } - public var EditTheme_Expand_TopInfo: String { return self._s[3044]! } + public var Call_ReportPlaceholder: String { return self._s[3044]! } + public var Chat_SlowmodeSendError: String { return self._s[3045]! } + public var MaskStickerSettings_Info: String { return self._s[3046]! } + public var EditTheme_Expand_TopInfo: String { return self._s[3047]! } public func GroupInfo_AddParticipantConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3045]!, self._r[3045]!, [_0]) + return formatWithArgumentRanges(self._s[3048]!, self._r[3048]!, [_0]) } - public var Checkout_NewCard_PostcodeTitle: String { return self._s[3046]! } - public var Passport_Address_RegionPlaceholder: String { return self._s[3048]! } - public var Contacts_ShareTelegram: String { return self._s[3049]! } - public var EnterPasscode_EnterNewPasscodeNew: String { return self._s[3050]! } - public var Map_AddressOnMap: String { return self._s[3051]! } - public var Channel_ErrorAccessDenied: String { return self._s[3052]! } - public var UserInfo_ScamBotWarning: String { return self._s[3054]! } - public var Stickers_GroupChooseStickerPack: String { return self._s[3055]! } - public var Call_ConnectionErrorTitle: String { return self._s[3056]! } - public var UserInfo_NotificationsEnable: String { return self._s[3057]! } - public var ArchivedChats_IntroText1: String { return self._s[3058]! } - public var Tour_Text4: String { return self._s[3061]! } - public var WallpaperSearch_Recent: String { return self._s[3062]! } - public var GroupInfo_ScamGroupWarning: String { return self._s[3063]! } - public var Profile_MessageLifetime2s: String { return self._s[3065]! } - public var Appearance_ThemePreview_ChatList_5_Text: String { return self._s[3066]! } - public var Notification_MessageLifetime2s: String { return self._s[3067]! } + public var Checkout_NewCard_PostcodeTitle: String { return self._s[3049]! } + public var Passport_Address_RegionPlaceholder: String { return self._s[3051]! } + public var Contacts_ShareTelegram: String { return self._s[3052]! } + public var EnterPasscode_EnterNewPasscodeNew: String { return self._s[3053]! } + public var Map_AddressOnMap: String { return self._s[3054]! } + public var Channel_ErrorAccessDenied: String { return self._s[3055]! } + public var UserInfo_ScamBotWarning: String { return self._s[3057]! } + public var Stickers_GroupChooseStickerPack: String { return self._s[3058]! } + public var Call_ConnectionErrorTitle: String { return self._s[3059]! } + public var UserInfo_NotificationsEnable: String { return self._s[3060]! } + public var ArchivedChats_IntroText1: String { return self._s[3061]! } + public var Tour_Text4: String { return self._s[3064]! } + public var WallpaperSearch_Recent: String { return self._s[3065]! } + public var GroupInfo_ScamGroupWarning: String { return self._s[3066]! } + public var Profile_MessageLifetime2s: String { return self._s[3068]! } + public var Appearance_ThemePreview_ChatList_5_Text: String { return self._s[3069]! } + public var Notification_MessageLifetime2s: String { return self._s[3070]! } public func Time_PreciseDate_m10(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3068]!, self._r[3068]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3071]!, self._r[3071]!, [_1, _2, _3]) } - public var Cache_ClearCache: String { return self._s[3069]! } - public var AutoNightTheme_UpdateLocation: String { return self._s[3070]! } - public var Permissions_NotificationsUnreachableText_v0: String { return self._s[3071]! } + public var Cache_ClearCache: String { return self._s[3072]! } + public var AutoNightTheme_UpdateLocation: String { return self._s[3073]! } + public var Permissions_NotificationsUnreachableText_v0: String { return self._s[3074]! } public func Channel_AdminLog_MessageChangedGroupUsername(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3075]!, self._r[3075]!, [_0]) + return formatWithArgumentRanges(self._s[3078]!, self._r[3078]!, [_0]) } public func Conversation_ShareMyPhoneNumber_StatusSuccess(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3077]!, self._r[3077]!, [_0]) + return formatWithArgumentRanges(self._s[3080]!, self._r[3080]!, [_0]) } - public var LocalGroup_Text: String { return self._s[3078]! } - public var Channel_AdminLog_EmptyFilterTitle: String { return self._s[3079]! } - public var SocksProxySetup_TypeSocks: String { return self._s[3080]! } - public var ChatList_UnarchiveAction: String { return self._s[3081]! } - public var AutoNightTheme_Title: String { return self._s[3082]! } - public var InstantPage_FeedbackButton: String { return self._s[3083]! } - public var Passport_FieldAddress: String { return self._s[3084]! } + public var LocalGroup_Text: String { return self._s[3081]! } + public var Channel_AdminLog_EmptyFilterTitle: String { return self._s[3082]! } + public var SocksProxySetup_TypeSocks: String { return self._s[3083]! } + public var ChatList_UnarchiveAction: String { return self._s[3084]! } + public var AutoNightTheme_Title: String { return self._s[3085]! } + public var InstantPage_FeedbackButton: String { return self._s[3086]! } + public var Passport_FieldAddress: String { return self._s[3087]! } public func Channel_AdminLog_SetSlowmode(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3085]!, self._r[3085]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3088]!, self._r[3088]!, [_1, _2]) } - public var Month_ShortMarch: String { return self._s[3086]! } + public var Month_ShortMarch: String { return self._s[3089]! } public func PUSH_MESSAGE_INVOICE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3087]!, self._r[3087]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3090]!, self._r[3090]!, [_1, _2]) } - public var SocksProxySetup_UsernamePlaceholder: String { return self._s[3088]! } - public var Conversation_ShareInlineBotLocationConfirmation: String { return self._s[3089]! } - public var Passport_FloodError: String { return self._s[3090]! } - public var SecretGif_Title: String { return self._s[3091]! } - public var NotificationSettings_ShowNotificationsAllAccountsInfoOn: String { return self._s[3092]! } - public var ChatList_Context_UnhideArchive: String { return self._s[3093]! } - public var Passport_Language_th: String { return self._s[3095]! } - public var Passport_Address_Address: String { return self._s[3096]! } - public var Login_InvalidLastNameError: String { return self._s[3097]! } - public var Notifications_InAppNotificationsPreview: String { return self._s[3098]! } - public var Notifications_PermissionsUnreachableTitle: String { return self._s[3099]! } - public var ChatList_Context_Archive: String { return self._s[3100]! } - public var SettingsSearch_FAQ: String { return self._s[3101]! } - public var ShareMenu_Send: String { return self._s[3102]! } - public var WallpaperSearch_ColorYellow: String { return self._s[3104]! } - public var Month_GenNovember: String { return self._s[3106]! } - public var SettingsSearch_Synonyms_Appearance_LargeEmoji: String { return self._s[3108]! } + public var SocksProxySetup_UsernamePlaceholder: String { return self._s[3091]! } + public var Conversation_ShareInlineBotLocationConfirmation: String { return self._s[3092]! } + public var Passport_FloodError: String { return self._s[3093]! } + public var SecretGif_Title: String { return self._s[3094]! } + public var NotificationSettings_ShowNotificationsAllAccountsInfoOn: String { return self._s[3095]! } + public var ChatList_Context_UnhideArchive: String { return self._s[3096]! } + public var Passport_Language_th: String { return self._s[3098]! } + public var Passport_Address_Address: String { return self._s[3099]! } + public var Login_InvalidLastNameError: String { return self._s[3100]! } + public var Notifications_InAppNotificationsPreview: String { return self._s[3101]! } + public var Notifications_PermissionsUnreachableTitle: String { return self._s[3102]! } + public var ChatList_Context_Archive: String { return self._s[3103]! } + public var SettingsSearch_FAQ: String { return self._s[3104]! } + public var ShareMenu_Send: String { return self._s[3105]! } + public var ChatState_Connecting: String { return self._s[3106]! } + public var WallpaperSearch_ColorYellow: String { return self._s[3108]! } + public var Month_GenNovember: String { return self._s[3110]! } + public var SettingsSearch_Synonyms_Appearance_LargeEmoji: String { return self._s[3112]! } public func Conversation_ShareMyPhoneNumberConfirmation(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3109]!, self._r[3109]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3113]!, self._r[3113]!, [_1, _2]) } - public var Conversation_SwipeToReplyHintText: String { return self._s[3110]! } - public var Checkout_Email: String { return self._s[3111]! } - public var NotificationsSound_Tritone: String { return self._s[3112]! } - public var StickerPacksSettings_ManagingHelp: String { return self._s[3114]! } - public var Wallet_ContextMenuCopy: String { return self._s[3116]! } + public var Conversation_SwipeToReplyHintText: String { return self._s[3114]! } + public var Checkout_Email: String { return self._s[3115]! } + public var NotificationsSound_Tritone: String { return self._s[3116]! } + public var StickerPacksSettings_ManagingHelp: String { return self._s[3118]! } + public var Wallet_ContextMenuCopy: String { return self._s[3120]! } public func Wallet_Time_PreciseDate_m6(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3118]!, self._r[3118]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3122]!, self._r[3122]!, [_1, _2, _3]) } - public var Appearance_TextSize_Automatic: String { return self._s[3119]! } + public var Appearance_TextSize_Automatic: String { return self._s[3123]! } public func PUSH_PINNED_ROUND(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3120]!, self._r[3120]!, [_1]) + return formatWithArgumentRanges(self._s[3124]!, self._r[3124]!, [_1]) } public func StickerPackActionInfo_AddedText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3121]!, self._r[3121]!, [_0]) + return formatWithArgumentRanges(self._s[3125]!, self._r[3125]!, [_0]) } - public var ChangePhoneNumberNumber_Help: String { return self._s[3122]! } + public var ChangePhoneNumberNumber_Help: String { return self._s[3126]! } public func Checkout_LiabilityAlert(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3123]!, self._r[3123]!, [_1, _1, _1, _2]) + return formatWithArgumentRanges(self._s[3127]!, self._r[3127]!, [_1, _1, _1, _2]) } - public var ChatList_UndoArchiveTitle: String { return self._s[3124]! } - public var Notification_Exceptions_Add: String { return self._s[3125]! } - public var DialogList_You: String { return self._s[3126]! } - public var MediaPicker_Send: String { return self._s[3129]! } - public var SettingsSearch_Synonyms_Stickers_Title: String { return self._s[3130]! } - public var Appearance_ThemePreview_ChatList_4_Text: String { return self._s[3131]! } - public var Call_AudioRouteSpeaker: String { return self._s[3132]! } - public var Watch_UserInfo_Title: String { return self._s[3133]! } - public var VoiceOver_Chat_PollFinalResults: String { return self._s[3134]! } - public var Appearance_AccentColor: String { return self._s[3136]! } + public var ChatList_UndoArchiveTitle: String { return self._s[3128]! } + public var Notification_Exceptions_Add: String { return self._s[3129]! } + public var DialogList_You: String { return self._s[3130]! } + public var MediaPicker_Send: String { return self._s[3133]! } + public var SettingsSearch_Synonyms_Stickers_Title: String { return self._s[3134]! } + public var Appearance_ThemePreview_ChatList_4_Text: String { return self._s[3135]! } + public var Call_AudioRouteSpeaker: String { return self._s[3136]! } + public var Watch_UserInfo_Title: String { return self._s[3137]! } + public var VoiceOver_Chat_PollFinalResults: String { return self._s[3138]! } + public var Appearance_AccentColor: String { return self._s[3140]! } public func Login_EmailPhoneSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3137]!, self._r[3137]!, [_0]) + return formatWithArgumentRanges(self._s[3141]!, self._r[3141]!, [_0]) } - public var Permissions_ContactsAllowInSettings_v0: String { return self._s[3138]! } + public var Permissions_ContactsAllowInSettings_v0: String { return self._s[3142]! } public func PUSH_CHANNEL_MESSAGE_GAME(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3139]!, self._r[3139]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3143]!, self._r[3143]!, [_1, _2]) } - public var Conversation_ClousStorageInfo_Description2: String { return self._s[3140]! } - public var WebSearch_RecentClearConfirmation: String { return self._s[3141]! } - public var Notification_CallOutgoing: String { return self._s[3142]! } - public var PrivacySettings_PasscodeAndFaceId: String { return self._s[3143]! } - public var Channel_DiscussionGroup_MakeHistoryPublic: String { return self._s[3144]! } - public var Call_RecordingDisabledMessage: String { return self._s[3145]! } - public var Message_Game: String { return self._s[3146]! } - public var Conversation_PressVolumeButtonForSound: String { return self._s[3147]! } - public var PrivacyLastSeenSettings_CustomHelp: String { return self._s[3148]! } - public var Channel_DiscussionGroup_PrivateGroup: String { return self._s[3149]! } - public var Channel_EditAdmin_PermissionAddAdmins: String { return self._s[3150]! } - public var Date_DialogDateFormat: String { return self._s[3152]! } - public var WallpaperColors_SetCustomColor: String { return self._s[3153]! } - public var Notifications_InAppNotifications: String { return self._s[3154]! } + public var Conversation_ClousStorageInfo_Description2: String { return self._s[3144]! } + public var WebSearch_RecentClearConfirmation: String { return self._s[3145]! } + public var Notification_CallOutgoing: String { return self._s[3146]! } + public var PrivacySettings_PasscodeAndFaceId: String { return self._s[3147]! } + public var Channel_DiscussionGroup_MakeHistoryPublic: String { return self._s[3148]! } + public var Call_RecordingDisabledMessage: String { return self._s[3149]! } + public var Message_Game: String { return self._s[3150]! } + public var Conversation_PressVolumeButtonForSound: String { return self._s[3151]! } + public var PrivacyLastSeenSettings_CustomHelp: String { return self._s[3152]! } + public var Channel_DiscussionGroup_PrivateGroup: String { return self._s[3153]! } + public var Channel_EditAdmin_PermissionAddAdmins: String { return self._s[3154]! } + public var Date_DialogDateFormat: String { return self._s[3156]! } + public var WallpaperColors_SetCustomColor: String { return self._s[3157]! } + public var Notifications_InAppNotifications: String { return self._s[3158]! } public func Channel_Management_RemovedBy(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3155]!, self._r[3155]!, [_0]) + return formatWithArgumentRanges(self._s[3159]!, self._r[3159]!, [_0]) } public func Settings_ApplyProxyAlert(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3156]!, self._r[3156]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3160]!, self._r[3160]!, [_1, _2]) } - public var NewContact_Title: String { return self._s[3157]! } + public var NewContact_Title: String { return self._s[3161]! } public func AutoDownloadSettings_UpToForAll(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3158]!, self._r[3158]!, [_0]) + return formatWithArgumentRanges(self._s[3162]!, self._r[3162]!, [_0]) } - public var Conversation_ViewContactDetails: String { return self._s[3159]! } + public var Conversation_ViewContactDetails: String { return self._s[3163]! } public func PUSH_CHANNEL_MESSAGE_CONTACT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3161]!, self._r[3161]!, [_1]) + return formatWithArgumentRanges(self._s[3165]!, self._r[3165]!, [_1]) } - public var Checkout_NewCard_CardholderNameTitle: String { return self._s[3162]! } - public var Passport_Identity_ExpiryDateNone: String { return self._s[3163]! } - public var PrivacySettings_Title: String { return self._s[3164]! } - public var Conversation_SilentBroadcastTooltipOff: String { return self._s[3167]! } - public var GroupRemoved_UsersSectionTitle: String { return self._s[3168]! } - public var VoiceOver_Chat_ContactEmail: String { return self._s[3169]! } - public var Contacts_PhoneNumber: String { return self._s[3170]! } - public var TwoFactorSetup_Password_PlaceholderConfirmPassword: String { return self._s[3172]! } - public var Map_ShowPlaces: String { return self._s[3173]! } - public var ChatAdmins_Title: String { return self._s[3174]! } - public var InstantPage_Reference: String { return self._s[3176]! } - public var Wallet_Info_Updating: String { return self._s[3177]! } - public var ReportGroupLocation_Text: String { return self._s[3178]! } + public var Checkout_NewCard_CardholderNameTitle: String { return self._s[3166]! } + public var Passport_Identity_ExpiryDateNone: String { return self._s[3167]! } + public var PrivacySettings_Title: String { return self._s[3168]! } + public var Conversation_SilentBroadcastTooltipOff: String { return self._s[3171]! } + public var GroupRemoved_UsersSectionTitle: String { return self._s[3172]! } + public var VoiceOver_Chat_ContactEmail: String { return self._s[3173]! } + public var Contacts_PhoneNumber: String { return self._s[3174]! } + public var TwoFactorSetup_Password_PlaceholderConfirmPassword: String { return self._s[3176]! } + public var Map_ShowPlaces: String { return self._s[3177]! } + public var ChatAdmins_Title: String { return self._s[3178]! } + public var InstantPage_Reference: String { return self._s[3180]! } + public var Wallet_Info_Updating: String { return self._s[3181]! } + public var ReportGroupLocation_Text: String { return self._s[3182]! } public func PUSH_CHAT_MESSAGE_FWD(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3179]!, self._r[3179]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3183]!, self._r[3183]!, [_1, _2]) } - public var Camera_FlashOff: String { return self._s[3180]! } - public var Watch_UserInfo_Block: String { return self._s[3181]! } - public var ChatSettings_Stickers: String { return self._s[3182]! } - public var ChatSettings_DownloadInBackground: String { return self._s[3183]! } - public var Appearance_ThemeCarouselTintedNight: String { return self._s[3184]! } + public var Camera_FlashOff: String { return self._s[3184]! } + public var Watch_UserInfo_Block: String { return self._s[3185]! } + public var ChatSettings_Stickers: String { return self._s[3186]! } + public var ChatSettings_DownloadInBackground: String { return self._s[3187]! } + public var Appearance_ThemeCarouselTintedNight: String { return self._s[3188]! } public func UserInfo_BlockConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3185]!, self._r[3185]!, [_0]) + return formatWithArgumentRanges(self._s[3189]!, self._r[3189]!, [_0]) } - public var Settings_ViewPhoto: String { return self._s[3186]! } - public var Login_CheckOtherSessionMessages: String { return self._s[3187]! } - public var AutoDownloadSettings_Cellular: String { return self._s[3188]! } - public var Wallet_Created_ExportErrorTitle: String { return self._s[3189]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsExceptions: String { return self._s[3190]! } - public var VoiceOver_MessageContextShare: String { return self._s[3191]! } + public var Settings_ViewPhoto: String { return self._s[3190]! } + public var Login_CheckOtherSessionMessages: String { return self._s[3191]! } + public var AutoDownloadSettings_Cellular: String { return self._s[3192]! } + public var Wallet_Created_ExportErrorTitle: String { return self._s[3193]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsExceptions: String { return self._s[3194]! } + public var VoiceOver_MessageContextShare: String { return self._s[3195]! } public func Target_InviteToGroupConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3193]!, self._r[3193]!, [_0]) + return formatWithArgumentRanges(self._s[3197]!, self._r[3197]!, [_0]) } - public var Privacy_DeleteDrafts: String { return self._s[3194]! } - public var Wallpaper_SetCustomBackgroundInfo: String { return self._s[3195]! } + public var Privacy_DeleteDrafts: String { return self._s[3198]! } + public var Wallpaper_SetCustomBackgroundInfo: String { return self._s[3199]! } public func LastSeen_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3196]!, self._r[3196]!, [_0]) + return formatWithArgumentRanges(self._s[3200]!, self._r[3200]!, [_0]) } - public var DialogList_SavedMessagesHelp: String { return self._s[3197]! } - public var Wallet_SecureStorageNotAvailable_Title: String { return self._s[3198]! } - public var DialogList_SavedMessages: String { return self._s[3199]! } - public var GroupInfo_UpgradeButton: String { return self._s[3200]! } - public var Appearance_ThemePreview_ChatList_3_Text: String { return self._s[3202]! } - public var DialogList_Pin: String { return self._s[3203]! } + public var DialogList_SavedMessagesHelp: String { return self._s[3201]! } + public var Wallet_SecureStorageNotAvailable_Title: String { return self._s[3202]! } + public var DialogList_SavedMessages: String { return self._s[3203]! } + public var GroupInfo_UpgradeButton: String { return self._s[3204]! } + public var Appearance_ThemePreview_ChatList_3_Text: String { return self._s[3206]! } + public var DialogList_Pin: String { return self._s[3207]! } public func ForwardedAuthors2(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3204]!, self._r[3204]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3208]!, self._r[3208]!, [_0, _1]) } public func Login_PhoneGenericEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3205]!, self._r[3205]!, [_0]) + return formatWithArgumentRanges(self._s[3209]!, self._r[3209]!, [_0]) } - public var Notification_Exceptions_AlwaysOn: String { return self._s[3206]! } - public var UserInfo_NotificationsDisable: String { return self._s[3207]! } - public var Conversation_ContextMenuCancelEditing: String { return self._s[3208]! } - public var Paint_Outlined: String { return self._s[3209]! } - public var Activity_PlayingGame: String { return self._s[3210]! } - public var SearchImages_NoImagesFound: String { return self._s[3211]! } - public var SocksProxySetup_ProxyType: String { return self._s[3212]! } - public var AppleWatch_ReplyPresetsHelp: String { return self._s[3214]! } - public var Conversation_ContextMenuCancelSending: String { return self._s[3215]! } - public var Settings_AppLanguage: String { return self._s[3216]! } - public var TwoStepAuth_ResetAccountHelp: String { return self._s[3217]! } - public var Common_ChoosePhoto: String { return self._s[3218]! } - public var AuthSessions_AddDevice_InvalidQRCode: String { return self._s[3219]! } - public var CallFeedback_ReasonEcho: String { return self._s[3220]! } + public var Notification_Exceptions_AlwaysOn: String { return self._s[3210]! } + public var UserInfo_NotificationsDisable: String { return self._s[3211]! } + public var Conversation_ContextMenuCancelEditing: String { return self._s[3212]! } + public var Paint_Outlined: String { return self._s[3213]! } + public var Activity_PlayingGame: String { return self._s[3214]! } + public var SearchImages_NoImagesFound: String { return self._s[3215]! } + public var SocksProxySetup_ProxyType: String { return self._s[3216]! } + public var AppleWatch_ReplyPresetsHelp: String { return self._s[3218]! } + public var Conversation_ContextMenuCancelSending: String { return self._s[3219]! } + public var Settings_AppLanguage: String { return self._s[3220]! } + public var TwoStepAuth_ResetAccountHelp: String { return self._s[3221]! } + public var Common_ChoosePhoto: String { return self._s[3222]! } + public var AuthSessions_AddDevice_InvalidQRCode: String { return self._s[3223]! } + public var CallFeedback_ReasonEcho: String { return self._s[3224]! } public func PUSH_PINNED_AUDIO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3221]!, self._r[3221]!, [_1]) + return formatWithArgumentRanges(self._s[3225]!, self._r[3225]!, [_1]) } - public var Privacy_Calls_AlwaysAllow: String { return self._s[3222]! } - public var PollResults_Collapse: String { return self._s[3223]! } - public var Activity_UploadingVideo: String { return self._s[3224]! } - public var Conversation_WalletRequiredNotNow: String { return self._s[3225]! } - public var ChannelInfo_DeleteChannelConfirmation: String { return self._s[3226]! } - public var NetworkUsageSettings_Wifi: String { return self._s[3227]! } - public var VoiceOver_Editing_ClearText: String { return self._s[3228]! } - public var PUSH_SENDER_YOU: String { return self._s[3229]! } - public var Channel_BanUser_PermissionReadMessages: String { return self._s[3230]! } - public var Checkout_PayWithTouchId: String { return self._s[3231]! } - public var Wallpaper_ResetWallpapersConfirmation: String { return self._s[3232]! } + public var Privacy_Calls_AlwaysAllow: String { return self._s[3226]! } + public var PollResults_Collapse: String { return self._s[3227]! } + public var Activity_UploadingVideo: String { return self._s[3228]! } + public var Conversation_WalletRequiredNotNow: String { return self._s[3229]! } + public var ChannelInfo_DeleteChannelConfirmation: String { return self._s[3230]! } + public var NetworkUsageSettings_Wifi: String { return self._s[3231]! } + public var VoiceOver_Editing_ClearText: String { return self._s[3232]! } + public var PUSH_SENDER_YOU: String { return self._s[3233]! } + public var Channel_BanUser_PermissionReadMessages: String { return self._s[3234]! } + public var Checkout_PayWithTouchId: String { return self._s[3235]! } + public var Wallpaper_ResetWallpapersConfirmation: String { return self._s[3236]! } public func PUSH_LOCKED_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3234]!, self._r[3234]!, [_1]) + return formatWithArgumentRanges(self._s[3238]!, self._r[3238]!, [_1]) } - public var Notifications_ExceptionsNone: String { return self._s[3235]! } + public var Notifications_ExceptionsNone: String { return self._s[3239]! } public func Message_ForwardedMessageShort(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3236]!, self._r[3236]!, [_0]) + return formatWithArgumentRanges(self._s[3240]!, self._r[3240]!, [_0]) } public func PUSH_PINNED_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3237]!, self._r[3237]!, [_1]) + return formatWithArgumentRanges(self._s[3241]!, self._r[3241]!, [_1]) } - public var AuthSessions_IncompleteAttempts: String { return self._s[3239]! } - public var Passport_Address_Region: String { return self._s[3242]! } - public var ChatList_DeleteChat: String { return self._s[3243]! } - public var LogoutOptions_ClearCacheTitle: String { return self._s[3244]! } - public var PhotoEditor_TiltShift: String { return self._s[3245]! } - public var Settings_FAQ_URL: String { return self._s[3246]! } - public var TwoFactorSetup_EmailVerification_ChangeAction: String { return self._s[3247]! } - public var Passport_Language_sl: String { return self._s[3248]! } - public var Settings_PrivacySettings: String { return self._s[3250]! } - public var SharedMedia_TitleLink: String { return self._s[3251]! } - public var Passport_Identity_TypePassportUploadScan: String { return self._s[3252]! } - public var Settings_SetProfilePhoto: String { return self._s[3253]! } - public var Channel_About_Help: String { return self._s[3254]! } - public var Contacts_PermissionsEnable: String { return self._s[3255]! } - public var Wallet_Sending_Title: String { return self._s[3256]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsAlert: String { return self._s[3257]! } - public var AttachmentMenu_SendAsFiles: String { return self._s[3258]! } - public var CallFeedback_ReasonInterruption: String { return self._s[3260]! } - public var Passport_Address_AddTemporaryRegistration: String { return self._s[3261]! } - public var AutoDownloadSettings_AutodownloadVideos: String { return self._s[3262]! } - public var ChatSettings_AutoDownloadSettings_Delimeter: String { return self._s[3263]! } - public var OldChannels_Title: String { return self._s[3264]! } - public var PrivacySettings_DeleteAccountTitle: String { return self._s[3265]! } - public var AccessDenied_VideoMessageCamera: String { return self._s[3267]! } - public var Map_OpenInYandexMaps: String { return self._s[3269]! } - public var CreateGroup_ErrorLocatedGroupsTooMuch: String { return self._s[3270]! } - public var VoiceOver_MessageContextReply: String { return self._s[3271]! } - public var PhotoEditor_SaturationTool: String { return self._s[3273]! } + public var AuthSessions_IncompleteAttempts: String { return self._s[3243]! } + public var Passport_Address_Region: String { return self._s[3246]! } + public var ChatList_DeleteChat: String { return self._s[3247]! } + public var LogoutOptions_ClearCacheTitle: String { return self._s[3248]! } + public var PhotoEditor_TiltShift: String { return self._s[3249]! } + public var Settings_FAQ_URL: String { return self._s[3250]! } + public var TwoFactorSetup_EmailVerification_ChangeAction: String { return self._s[3251]! } + public var Passport_Language_sl: String { return self._s[3252]! } + public var Settings_PrivacySettings: String { return self._s[3254]! } + public var SharedMedia_TitleLink: String { return self._s[3255]! } + public var Passport_Identity_TypePassportUploadScan: String { return self._s[3256]! } + public var Settings_SetProfilePhoto: String { return self._s[3257]! } + public var Channel_About_Help: String { return self._s[3258]! } + public var Contacts_PermissionsEnable: String { return self._s[3259]! } + public var Wallet_Sending_Title: String { return self._s[3260]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsAlert: String { return self._s[3261]! } + public var AttachmentMenu_SendAsFiles: String { return self._s[3262]! } + public var CallFeedback_ReasonInterruption: String { return self._s[3264]! } + public var Passport_Address_AddTemporaryRegistration: String { return self._s[3265]! } + public var AutoDownloadSettings_AutodownloadVideos: String { return self._s[3266]! } + public var ChatSettings_AutoDownloadSettings_Delimeter: String { return self._s[3267]! } + public var OldChannels_Title: String { return self._s[3268]! } + public var PrivacySettings_DeleteAccountTitle: String { return self._s[3269]! } + public var AccessDenied_VideoMessageCamera: String { return self._s[3271]! } + public var Map_OpenInYandexMaps: String { return self._s[3273]! } + public var CreateGroup_ErrorLocatedGroupsTooMuch: String { return self._s[3274]! } + public var VoiceOver_MessageContextReply: String { return self._s[3275]! } + public var PhotoEditor_SaturationTool: String { return self._s[3277]! } public func PUSH_MESSAGE_STICKER(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3274]!, self._r[3274]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3278]!, self._r[3278]!, [_1, _2]) } - public var PrivacyPhoneNumberSettings_CustomHelp: String { return self._s[3275]! } - public var Notification_Exceptions_NewException_NotificationHeader: String { return self._s[3276]! } - public var Group_OwnershipTransfer_ErrorLocatedGroupsTooMuch: String { return self._s[3277]! } + public var PrivacyPhoneNumberSettings_CustomHelp: String { return self._s[3279]! } + public var Notification_Exceptions_NewException_NotificationHeader: String { return self._s[3280]! } + public var Group_OwnershipTransfer_ErrorLocatedGroupsTooMuch: String { return self._s[3281]! } public func LOCAL_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3278]!, self._r[3278]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[3282]!, self._r[3282]!, [_1, "\(_2)"]) } - public var Appearance_ThemePreview_ChatList_2_Text: String { return self._s[3279]! } - public var Channel_Username_InvalidTooShort: String { return self._s[3281]! } - public var SettingsSearch_Synonyms_Wallet: String { return self._s[3282]! } + public var Appearance_ThemePreview_ChatList_2_Text: String { return self._s[3283]! } + public var Channel_Username_InvalidTooShort: String { return self._s[3285]! } + public var SettingsSearch_Synonyms_Wallet: String { return self._s[3286]! } public func Group_OwnershipTransfer_DescriptionInfo(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3283]!, self._r[3283]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3287]!, self._r[3287]!, [_1, _2]) } - public var Forward_ErrorPublicPollDisabledInChannels: String { return self._s[3284]! } + public var Forward_ErrorPublicPollDisabledInChannels: String { return self._s[3288]! } public func PUSH_CHAT_MESSAGE_GAME(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3285]!, self._r[3285]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3289]!, self._r[3289]!, [_1, _2, _3]) } - public var WallpaperPreview_PatternTitle: String { return self._s[3286]! } - public var GroupInfo_PublicLinkAdd: String { return self._s[3287]! } - public var Passport_PassportInformation: String { return self._s[3290]! } - public var Theme_Unsupported: String { return self._s[3291]! } - public var WatchRemote_AlertTitle: String { return self._s[3292]! } - public var Privacy_GroupsAndChannels_NeverAllow: String { return self._s[3293]! } - public var ConvertToSupergroup_HelpText: String { return self._s[3295]! } + public var WallpaperPreview_PatternTitle: String { return self._s[3290]! } + public var GroupInfo_PublicLinkAdd: String { return self._s[3291]! } + public var Passport_PassportInformation: String { return self._s[3294]! } + public var Theme_Unsupported: String { return self._s[3295]! } + public var WatchRemote_AlertTitle: String { return self._s[3296]! } + public var Privacy_GroupsAndChannels_NeverAllow: String { return self._s[3297]! } + public var ConvertToSupergroup_HelpText: String { return self._s[3299]! } public func Time_MonthOfYear_m7(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3296]!, self._r[3296]!, [_0]) + return formatWithArgumentRanges(self._s[3300]!, self._r[3300]!, [_0]) } public func PUSH_PHONE_CALL_REQUEST(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3297]!, self._r[3297]!, [_1]) + return formatWithArgumentRanges(self._s[3301]!, self._r[3301]!, [_1]) } - public var Privacy_GroupsAndChannels_CustomHelp: String { return self._s[3298]! } - public var Wallet_Navigation_Done: String { return self._s[3300]! } - public var TwoStepAuth_RecoveryCodeInvalid: String { return self._s[3301]! } - public var AccessDenied_CameraDisabled: String { return self._s[3302]! } + public var Privacy_GroupsAndChannels_CustomHelp: String { return self._s[3302]! } + public var Wallet_Navigation_Done: String { return self._s[3304]! } + public var TwoStepAuth_RecoveryCodeInvalid: String { return self._s[3305]! } + public var AccessDenied_CameraDisabled: String { return self._s[3306]! } public func Channel_Username_UsernameIsAvailable(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3303]!, self._r[3303]!, [_0]) + return formatWithArgumentRanges(self._s[3307]!, self._r[3307]!, [_0]) } - public var ClearCache_Forever: String { return self._s[3304]! } - public var AuthSessions_AddDeviceIntro_Title: String { return self._s[3305]! } - public var CreatePoll_Quiz: String { return self._s[3306]! } - public var PhotoEditor_ContrastTool: String { return self._s[3309]! } + public var ClearCache_Forever: String { return self._s[3308]! } + public var AuthSessions_AddDeviceIntro_Title: String { return self._s[3309]! } + public var CreatePoll_Quiz: String { return self._s[3310]! } + public var PhotoEditor_ContrastTool: String { return self._s[3313]! } public func PUSH_PINNED_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3310]!, self._r[3310]!, [_1]) + return formatWithArgumentRanges(self._s[3314]!, self._r[3314]!, [_1]) } - public var DialogList_Draft: String { return self._s[3311]! } - public var Wallet_Configuration_BlockchainIdInfo: String { return self._s[3312]! } - public var Privacy_TopPeersDelete: String { return self._s[3314]! } - public var LoginPassword_PasswordPlaceholder: String { return self._s[3315]! } - public var Passport_Identity_TypeIdentityCardUploadScan: String { return self._s[3316]! } - public var WebSearch_RecentSectionClear: String { return self._s[3317]! } - public var EditTheme_ErrorInvalidCharacters: String { return self._s[3318]! } - public var Watch_ChatList_NoConversationsTitle: String { return self._s[3320]! } - public var Common_Done: String { return self._s[3322]! } - public var Shortcut_SwitchAccount: String { return self._s[3323]! } - public var AuthSessions_EmptyText: String { return self._s[3324]! } - public var Wallet_Configuration_BlockchainNameChangedTitle: String { return self._s[3325]! } - public var Conversation_ShareBotContactConfirmation: String { return self._s[3326]! } - public var Tour_Title5: String { return self._s[3327]! } - public var Wallet_Settings_Title: String { return self._s[3328]! } + public var DialogList_Draft: String { return self._s[3315]! } + public var Wallet_Configuration_BlockchainIdInfo: String { return self._s[3316]! } + public var Privacy_TopPeersDelete: String { return self._s[3318]! } + public var LoginPassword_PasswordPlaceholder: String { return self._s[3319]! } + public var Passport_Identity_TypeIdentityCardUploadScan: String { return self._s[3320]! } + public var WebSearch_RecentSectionClear: String { return self._s[3321]! } + public var EditTheme_ErrorInvalidCharacters: String { return self._s[3322]! } + public var Watch_ChatList_NoConversationsTitle: String { return self._s[3324]! } + public var Common_Done: String { return self._s[3326]! } + public var Shortcut_SwitchAccount: String { return self._s[3327]! } + public var AuthSessions_EmptyText: String { return self._s[3328]! } + public var Wallet_Configuration_BlockchainNameChangedTitle: String { return self._s[3329]! } + public var Conversation_ShareBotContactConfirmation: String { return self._s[3330]! } + public var Tour_Title5: String { return self._s[3331]! } + public var Wallet_Settings_Title: String { return self._s[3332]! } public func Map_DirectionsDriveEta(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3329]!, self._r[3329]!, [_0]) + return formatWithArgumentRanges(self._s[3333]!, self._r[3333]!, [_0]) } - public var ApplyLanguage_UnsufficientDataTitle: String { return self._s[3330]! } - public var Conversation_LinkDialogSave: String { return self._s[3331]! } - public var GroupInfo_ActionRestrict: String { return self._s[3332]! } - public var Checkout_Title: String { return self._s[3333]! } - public var Channel_DiscussionGroup_HeaderLabel: String { return self._s[3335]! } - public var Channel_AdminLog_CanChangeInfo: String { return self._s[3337]! } - public var Notification_RenamedGroup: String { return self._s[3338]! } - public var PeopleNearby_Groups: String { return self._s[3339]! } - public var Checkout_PayWithFaceId: String { return self._s[3340]! } - public var Channel_BanList_BlockedTitle: String { return self._s[3341]! } - public var SettingsSearch_Synonyms_Notifications_InAppNotificationsSound: String { return self._s[3343]! } - public var Checkout_WebConfirmation_Title: String { return self._s[3344]! } - public var Notifications_MessageNotificationsAlert: String { return self._s[3345]! } + public var ApplyLanguage_UnsufficientDataTitle: String { return self._s[3334]! } + public var Conversation_LinkDialogSave: String { return self._s[3335]! } + public var GroupInfo_ActionRestrict: String { return self._s[3336]! } + public var Checkout_Title: String { return self._s[3337]! } + public var Channel_DiscussionGroup_HeaderLabel: String { return self._s[3339]! } + public var Channel_AdminLog_CanChangeInfo: String { return self._s[3341]! } + public var Notification_RenamedGroup: String { return self._s[3342]! } + public var PeopleNearby_Groups: String { return self._s[3343]! } + public var Checkout_PayWithFaceId: String { return self._s[3344]! } + public var Channel_BanList_BlockedTitle: String { return self._s[3345]! } + public var SettingsSearch_Synonyms_Notifications_InAppNotificationsSound: String { return self._s[3347]! } + public var Checkout_WebConfirmation_Title: String { return self._s[3348]! } + public var Notifications_MessageNotificationsAlert: String { return self._s[3349]! } public func Activity_RemindAboutGroup(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3346]!, self._r[3346]!, [_0]) + return formatWithArgumentRanges(self._s[3350]!, self._r[3350]!, [_0]) } - public var Profile_AddToExisting: String { return self._s[3348]! } + public var Profile_AddToExisting: String { return self._s[3352]! } public func Profile_CreateEncryptedChatOutdatedError(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3349]!, self._r[3349]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3353]!, self._r[3353]!, [_0, _1]) } - public var Cache_Files: String { return self._s[3351]! } - public var Permissions_PrivacyPolicy: String { return self._s[3352]! } - public var SocksProxySetup_ConnectAndSave: String { return self._s[3353]! } - public var UserInfo_NotificationsDefaultDisabled: String { return self._s[3354]! } - public var AutoDownloadSettings_TypeContacts: String { return self._s[3356]! } - public var Appearance_ThemePreview_ChatList_1_Text: String { return self._s[3358]! } - public var Calls_NoCallsPlaceholder: String { return self._s[3359]! } + public var Cache_Files: String { return self._s[3355]! } + public var Permissions_PrivacyPolicy: String { return self._s[3356]! } + public var SocksProxySetup_ConnectAndSave: String { return self._s[3357]! } + public var UserInfo_NotificationsDefaultDisabled: String { return self._s[3358]! } + public var AutoDownloadSettings_TypeContacts: String { return self._s[3360]! } + public var Appearance_ThemePreview_ChatList_1_Text: String { return self._s[3362]! } + public var Calls_NoCallsPlaceholder: String { return self._s[3363]! } public func Wallet_Receive_ShareInvoiceUrlInfo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3360]!, self._r[3360]!, [_0]) + return formatWithArgumentRanges(self._s[3364]!, self._r[3364]!, [_0]) } - public var Channel_Username_RevokeExistingUsernamesInfo: String { return self._s[3361]! } - public var VoiceOver_AttachMedia: String { return self._s[3364]! } - public var Notifications_ExceptionsGroupPlaceholder: String { return self._s[3365]! } + public var Channel_Username_RevokeExistingUsernamesInfo: String { return self._s[3365]! } + public var VoiceOver_AttachMedia: String { return self._s[3368]! } + public var Notifications_ExceptionsGroupPlaceholder: String { return self._s[3369]! } public func PUSH_CHAT_MESSAGE_INVOICE(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3366]!, self._r[3366]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3370]!, self._r[3370]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsSound: String { return self._s[3367]! } - public var Conversation_SetReminder_Title: String { return self._s[3368]! } - public var Passport_FieldAddressHelp: String { return self._s[3369]! } - public var Privacy_GroupsAndChannels_InviteToChannelMultipleError: String { return self._s[3370]! } - public var PUSH_REMINDER_TITLE: String { return self._s[3371]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsSound: String { return self._s[3371]! } + public var Conversation_SetReminder_Title: String { return self._s[3372]! } + public var Passport_FieldAddressHelp: String { return self._s[3373]! } + public var Privacy_GroupsAndChannels_InviteToChannelMultipleError: String { return self._s[3374]! } + public var PUSH_REMINDER_TITLE: String { return self._s[3375]! } public func Login_TermsOfService_ProceedBot(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3372]!, self._r[3372]!, [_0]) + return formatWithArgumentRanges(self._s[3376]!, self._r[3376]!, [_0]) } - public var Channel_AdminLog_EmptyTitle: String { return self._s[3373]! } - public var Privacy_Calls_NeverAllow_Title: String { return self._s[3374]! } - public var Login_UnknownError: String { return self._s[3375]! } - public var Group_UpgradeNoticeText2: String { return self._s[3378]! } - public var Watch_Compose_AddContact: String { return self._s[3379]! } - public var ClearCache_StorageServiceFiles: String { return self._s[3380]! } - public var Web_Error: String { return self._s[3381]! } - public var Gif_Search: String { return self._s[3382]! } - public var Profile_MessageLifetime1h: String { return self._s[3383]! } - public var CheckoutInfo_ReceiverInfoEmailPlaceholder: String { return self._s[3384]! } - public var Channel_Username_CheckingUsername: String { return self._s[3385]! } - public var CallFeedback_ReasonSilentRemote: String { return self._s[3386]! } - public var AutoDownloadSettings_TypeChannels: String { return self._s[3387]! } - public var Channel_AboutItem: String { return self._s[3388]! } - public var Privacy_GroupsAndChannels_AlwaysAllow_Placeholder: String { return self._s[3390]! } - public var VoiceOver_Chat_VoiceMessage: String { return self._s[3391]! } - public var GroupInfo_SharedMedia: String { return self._s[3392]! } + public var Channel_AdminLog_EmptyTitle: String { return self._s[3377]! } + public var Privacy_Calls_NeverAllow_Title: String { return self._s[3378]! } + public var Login_UnknownError: String { return self._s[3379]! } + public var Group_UpgradeNoticeText2: String { return self._s[3382]! } + public var Watch_Compose_AddContact: String { return self._s[3383]! } + public var ClearCache_StorageServiceFiles: String { return self._s[3384]! } + public var Web_Error: String { return self._s[3385]! } + public var Gif_Search: String { return self._s[3386]! } + public var Profile_MessageLifetime1h: String { return self._s[3387]! } + public var CheckoutInfo_ReceiverInfoEmailPlaceholder: String { return self._s[3388]! } + public var Channel_Username_CheckingUsername: String { return self._s[3389]! } + public var CallFeedback_ReasonSilentRemote: String { return self._s[3390]! } + public var AutoDownloadSettings_TypeChannels: String { return self._s[3391]! } + public var Channel_AboutItem: String { return self._s[3392]! } + public var Privacy_GroupsAndChannels_AlwaysAllow_Placeholder: String { return self._s[3394]! } + public var VoiceOver_Chat_VoiceMessage: String { return self._s[3395]! } + public var GroupInfo_SharedMedia: String { return self._s[3396]! } public func Channel_AdminLog_MessagePromotedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3393]!, self._r[3393]!, [_1]) + return formatWithArgumentRanges(self._s[3397]!, self._r[3397]!, [_1]) } - public var Call_PhoneCallInProgressMessage: String { return self._s[3394]! } + public var Call_PhoneCallInProgressMessage: String { return self._s[3398]! } public func PUSH_CHANNEL_ALBUM(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3395]!, self._r[3395]!, [_1]) + return formatWithArgumentRanges(self._s[3399]!, self._r[3399]!, [_1]) } - public var ChatList_UndoArchiveRevealedText: String { return self._s[3396]! } - public var GroupInfo_InviteLink_RevokeAlert_Text: String { return self._s[3397]! } - public var Conversation_SearchByName_Placeholder: String { return self._s[3398]! } - public var CreatePoll_AddOption: String { return self._s[3399]! } - public var GroupInfo_Permissions_SearchPlaceholder: String { return self._s[3400]! } - public var Group_UpgradeNoticeHeader: String { return self._s[3401]! } - public var Channel_Management_AddModerator: String { return self._s[3402]! } - public var AutoDownloadSettings_MaxFileSize: String { return self._s[3403]! } - public var StickerPacksSettings_ShowStickersButton: String { return self._s[3404]! } - public var Wallet_Info_RefreshErrorNetworkText: String { return self._s[3405]! } - public var Theme_Colors_Background: String { return self._s[3406]! } - public var NotificationsSound_Hello: String { return self._s[3408]! } - public var SocksProxySetup_SavedProxies: String { return self._s[3409]! } - public var Channel_Stickers_Placeholder: String { return self._s[3411]! } + public var ChatList_UndoArchiveRevealedText: String { return self._s[3400]! } + public var GroupInfo_InviteLink_RevokeAlert_Text: String { return self._s[3401]! } + public var Conversation_SearchByName_Placeholder: String { return self._s[3402]! } + public var CreatePoll_AddOption: String { return self._s[3403]! } + public var GroupInfo_Permissions_SearchPlaceholder: String { return self._s[3404]! } + public var Group_UpgradeNoticeHeader: String { return self._s[3405]! } + public var Channel_Management_AddModerator: String { return self._s[3406]! } + public var AutoDownloadSettings_MaxFileSize: String { return self._s[3407]! } + public var StickerPacksSettings_ShowStickersButton: String { return self._s[3408]! } + public var Wallet_Info_RefreshErrorNetworkText: String { return self._s[3409]! } + public var Theme_Colors_Background: String { return self._s[3410]! } + public var NotificationsSound_Hello: String { return self._s[3412]! } + public var SocksProxySetup_SavedProxies: String { return self._s[3413]! } + public var Channel_Stickers_Placeholder: String { return self._s[3415]! } public func Login_EmailCodeBody(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3412]!, self._r[3412]!, [_0]) + return formatWithArgumentRanges(self._s[3416]!, self._r[3416]!, [_0]) } - public var PrivacyPolicy_DeclineDeclineAndDelete: String { return self._s[3413]! } - public var Channel_Management_AddModeratorHelp: String { return self._s[3414]! } - public var ContactInfo_BirthdayLabel: String { return self._s[3415]! } - public var ChangePhoneNumberCode_RequestingACall: String { return self._s[3416]! } - public var AutoDownloadSettings_Channels: String { return self._s[3417]! } - public var Passport_Language_mn: String { return self._s[3418]! } - public var Notifications_ResetAllNotificationsHelp: String { return self._s[3421]! } - public var GroupInfo_Permissions_SlowmodeValue_Off: String { return self._s[3422]! } - public var Passport_Language_ja: String { return self._s[3424]! } - public var Settings_About_Title: String { return self._s[3425]! } - public var Settings_NotificationsAndSounds: String { return self._s[3426]! } - public var ChannelInfo_DeleteGroup: String { return self._s[3427]! } - public var Settings_BlockedUsers: String { return self._s[3428]! } + public var PrivacyPolicy_DeclineDeclineAndDelete: String { return self._s[3417]! } + public var Channel_Management_AddModeratorHelp: String { return self._s[3418]! } + public var ContactInfo_BirthdayLabel: String { return self._s[3419]! } + public var ChangePhoneNumberCode_RequestingACall: String { return self._s[3420]! } + public var AutoDownloadSettings_Channels: String { return self._s[3421]! } + public var Passport_Language_mn: String { return self._s[3422]! } + public var Notifications_ResetAllNotificationsHelp: String { return self._s[3425]! } + public var GroupInfo_Permissions_SlowmodeValue_Off: String { return self._s[3426]! } + public var Passport_Language_ja: String { return self._s[3428]! } + public var Settings_About_Title: String { return self._s[3429]! } + public var Settings_NotificationsAndSounds: String { return self._s[3430]! } + public var ChannelInfo_DeleteGroup: String { return self._s[3431]! } + public var Settings_BlockedUsers: String { return self._s[3432]! } public func Time_MonthOfYear_m4(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3429]!, self._r[3429]!, [_0]) + return formatWithArgumentRanges(self._s[3433]!, self._r[3433]!, [_0]) } - public var EditTheme_Create_Preview_OutgoingText: String { return self._s[3430]! } - public var Wallet_Weekday_Today: String { return self._s[3431]! } - public var AutoDownloadSettings_PreloadVideo: String { return self._s[3432]! } - public var Widget_ApplicationLocked: String { return self._s[3433]! } - public var Passport_Address_AddResidentialAddress: String { return self._s[3434]! } - public var Channel_Username_Title: String { return self._s[3435]! } + public var EditTheme_Create_Preview_OutgoingText: String { return self._s[3434]! } + public var Wallet_Weekday_Today: String { return self._s[3435]! } + public var AutoDownloadSettings_PreloadVideo: String { return self._s[3436]! } + public var Widget_ApplicationLocked: String { return self._s[3437]! } + public var Passport_Address_AddResidentialAddress: String { return self._s[3438]! } + public var Channel_Username_Title: String { return self._s[3439]! } public func Notification_RemovedGroupPhoto(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3436]!, self._r[3436]!, [_0]) + return formatWithArgumentRanges(self._s[3440]!, self._r[3440]!, [_0]) } - public var AttachmentMenu_File: String { return self._s[3438]! } - public var AppleWatch_Title: String { return self._s[3439]! } - public var Activity_RecordingVideoMessage: String { return self._s[3440]! } + public var AttachmentMenu_File: String { return self._s[3442]! } + public var AppleWatch_Title: String { return self._s[3443]! } + public var Activity_RecordingVideoMessage: String { return self._s[3444]! } public func Channel_DiscussionGroup_PublicChannelLink(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3441]!, self._r[3441]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3445]!, self._r[3445]!, [_1, _2]) } - public var Theme_Colors_Messages: String { return self._s[3442]! } - public var Weekday_Saturday: String { return self._s[3443]! } - public var WallpaperPreview_SwipeColorsTopText: String { return self._s[3444]! } - public var Profile_CreateEncryptedChatError: String { return self._s[3445]! } - public var Common_Next: String { return self._s[3447]! } - public var Channel_Stickers_YourStickers: String { return self._s[3449]! } - public var Message_Theme: String { return self._s[3450]! } - public var Call_AudioRouteHeadphones: String { return self._s[3451]! } - public var TwoStepAuth_EnterPasswordForgot: String { return self._s[3453]! } - public var Watch_Contacts_NoResults: String { return self._s[3455]! } - public var PhotoEditor_TintTool: String { return self._s[3458]! } - public var LoginPassword_ResetAccount: String { return self._s[3460]! } - public var Settings_SavedMessages: String { return self._s[3461]! } - public var SettingsSearch_Synonyms_Appearance_Animations: String { return self._s[3462]! } - public var Bot_GenericSupportStatus: String { return self._s[3463]! } - public var StickerPack_Add: String { return self._s[3464]! } - public var Checkout_TotalAmount: String { return self._s[3465]! } - public var Your_cards_number_is_invalid: String { return self._s[3466]! } - public var SettingsSearch_Synonyms_Appearance_AutoNightTheme: String { return self._s[3467]! } - public var VoiceOver_Chat_VideoMessage: String { return self._s[3468]! } + public var Theme_Colors_Messages: String { return self._s[3446]! } + public var Weekday_Saturday: String { return self._s[3447]! } + public var WallpaperPreview_SwipeColorsTopText: String { return self._s[3448]! } + public var Profile_CreateEncryptedChatError: String { return self._s[3449]! } + public var Common_Next: String { return self._s[3451]! } + public var Channel_Stickers_YourStickers: String { return self._s[3453]! } + public var Message_Theme: String { return self._s[3454]! } + public var Call_AudioRouteHeadphones: String { return self._s[3455]! } + public var TwoStepAuth_EnterPasswordForgot: String { return self._s[3457]! } + public var Watch_Contacts_NoResults: String { return self._s[3459]! } + public var PhotoEditor_TintTool: String { return self._s[3462]! } + public var LoginPassword_ResetAccount: String { return self._s[3464]! } + public var Settings_SavedMessages: String { return self._s[3465]! } + public var SettingsSearch_Synonyms_Appearance_Animations: String { return self._s[3466]! } + public var Bot_GenericSupportStatus: String { return self._s[3467]! } + public var StickerPack_Add: String { return self._s[3468]! } + public var Checkout_TotalAmount: String { return self._s[3469]! } + public var Your_cards_number_is_invalid: String { return self._s[3470]! } + public var SettingsSearch_Synonyms_Appearance_AutoNightTheme: String { return self._s[3471]! } + public var VoiceOver_Chat_VideoMessage: String { return self._s[3472]! } public func ChangePhoneNumberCode_CallTimer(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3469]!, self._r[3469]!, [_0]) + return formatWithArgumentRanges(self._s[3473]!, self._r[3473]!, [_0]) } public func GroupPermission_AddedInfo(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3470]!, self._r[3470]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3474]!, self._r[3474]!, [_1, _2]) } - public var ChatSettings_ConnectionType_UseSocks5: String { return self._s[3471]! } + public var ChatSettings_ConnectionType_UseSocks5: String { return self._s[3475]! } public func PUSH_CHAT_PHOTO_EDITED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3473]!, self._r[3473]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3477]!, self._r[3477]!, [_1, _2]) } public func Conversation_RestrictedTextTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3474]!, self._r[3474]!, [_0]) + return formatWithArgumentRanges(self._s[3478]!, self._r[3478]!, [_0]) } - public var GroupInfo_InviteLink_ShareLink: String { return self._s[3475]! } - public var StickerPack_Share: String { return self._s[3476]! } - public var Passport_DeleteAddress: String { return self._s[3477]! } - public var Settings_Passport: String { return self._s[3478]! } - public var SharedMedia_EmptyFilesText: String { return self._s[3479]! } - public var Conversation_DeleteMessagesForMe: String { return self._s[3480]! } - public var PasscodeSettings_AutoLock_IfAwayFor_1hour: String { return self._s[3481]! } - public var Contacts_PermissionsText: String { return self._s[3482]! } - public var Group_Setup_HistoryVisible: String { return self._s[3483]! } - public var Wallet_Month_ShortDecember: String { return self._s[3485]! } - public var Channel_EditAdmin_PermissionEnabledByDefault: String { return self._s[3486]! } - public var Passport_Address_AddRentalAgreement: String { return self._s[3487]! } - public var SocksProxySetup_Title: String { return self._s[3488]! } - public var Notification_Mute1h: String { return self._s[3489]! } + public var GroupInfo_InviteLink_ShareLink: String { return self._s[3479]! } + public var StickerPack_Share: String { return self._s[3480]! } + public var Passport_DeleteAddress: String { return self._s[3481]! } + public var Settings_Passport: String { return self._s[3482]! } + public var SharedMedia_EmptyFilesText: String { return self._s[3483]! } + public var Conversation_DeleteMessagesForMe: String { return self._s[3484]! } + public var PasscodeSettings_AutoLock_IfAwayFor_1hour: String { return self._s[3485]! } + public var Contacts_PermissionsText: String { return self._s[3486]! } + public var Group_Setup_HistoryVisible: String { return self._s[3487]! } + public var Wallet_Month_ShortDecember: String { return self._s[3489]! } + public var Channel_EditAdmin_PermissionEnabledByDefault: String { return self._s[3490]! } + public var Passport_Address_AddRentalAgreement: String { return self._s[3491]! } + public var SocksProxySetup_Title: String { return self._s[3492]! } + public var Notification_Mute1h: String { return self._s[3493]! } public func Passport_Email_CodeHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3490]!, self._r[3490]!, [_0]) + return formatWithArgumentRanges(self._s[3494]!, self._r[3494]!, [_0]) } - public var NotificationSettings_ShowNotificationsAllAccountsInfoOff: String { return self._s[3491]! } + public var NotificationSettings_ShowNotificationsAllAccountsInfoOff: String { return self._s[3495]! } public func PUSH_PINNED_GEOLIVE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3492]!, self._r[3492]!, [_1]) + return formatWithArgumentRanges(self._s[3496]!, self._r[3496]!, [_1]) } - public var FastTwoStepSetup_PasswordSection: String { return self._s[3493]! } - public var NetworkUsageSettings_ResetStatsConfirmation: String { return self._s[3496]! } - public var InfoPlist_NSFaceIDUsageDescription: String { return self._s[3498]! } - public var DialogList_NoMessagesText: String { return self._s[3499]! } - public var Privacy_ContactsResetConfirmation: String { return self._s[3500]! } - public var Privacy_Calls_P2PHelp: String { return self._s[3501]! } - public var Channel_DiscussionGroup_SearchPlaceholder: String { return self._s[3503]! } - public var Your_cards_expiration_year_is_invalid: String { return self._s[3504]! } - public var Common_TakePhotoOrVideo: String { return self._s[3505]! } - public var Wallet_Words_Text: String { return self._s[3506]! } - public var Call_StatusBusy: String { return self._s[3507]! } - public var Conversation_PinnedMessage: String { return self._s[3508]! } - public var AutoDownloadSettings_VoiceMessagesTitle: String { return self._s[3509]! } - public var Wallet_Configuration_BlockchainNameChangedProceed: String { return self._s[3510]! } - public var TwoStepAuth_SetupPasswordConfirmFailed: String { return self._s[3511]! } - public var Undo_ChatCleared: String { return self._s[3512]! } - public var AppleWatch_ReplyPresets: String { return self._s[3513]! } - public var Passport_DiscardMessageDescription: String { return self._s[3515]! } - public var Login_NetworkError: String { return self._s[3516]! } + public var FastTwoStepSetup_PasswordSection: String { return self._s[3497]! } + public var NetworkUsageSettings_ResetStatsConfirmation: String { return self._s[3500]! } + public var InfoPlist_NSFaceIDUsageDescription: String { return self._s[3502]! } + public var DialogList_NoMessagesText: String { return self._s[3503]! } + public var Privacy_ContactsResetConfirmation: String { return self._s[3504]! } + public var Privacy_Calls_P2PHelp: String { return self._s[3505]! } + public var Channel_DiscussionGroup_SearchPlaceholder: String { return self._s[3507]! } + public var Your_cards_expiration_year_is_invalid: String { return self._s[3508]! } + public var Common_TakePhotoOrVideo: String { return self._s[3509]! } + public var Wallet_Words_Text: String { return self._s[3510]! } + public var Call_StatusBusy: String { return self._s[3511]! } + public var Conversation_PinnedMessage: String { return self._s[3512]! } + public var AutoDownloadSettings_VoiceMessagesTitle: String { return self._s[3513]! } + public var Wallet_Configuration_BlockchainNameChangedProceed: String { return self._s[3514]! } + public var TwoStepAuth_SetupPasswordConfirmFailed: String { return self._s[3515]! } + public var Undo_ChatCleared: String { return self._s[3516]! } + public var AppleWatch_ReplyPresets: String { return self._s[3517]! } + public var Passport_DiscardMessageDescription: String { return self._s[3519]! } + public var Login_NetworkError: String { return self._s[3520]! } public func Notification_PinnedRoundMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3517]!, self._r[3517]!, [_0]) + return formatWithArgumentRanges(self._s[3521]!, self._r[3521]!, [_0]) } public func Channel_AdminLog_MessageRemovedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3518]!, self._r[3518]!, [_0]) + return formatWithArgumentRanges(self._s[3522]!, self._r[3522]!, [_0]) } - public var SocksProxySetup_PasswordPlaceholder: String { return self._s[3519]! } - public var Wallet_WordCheck_ViewWords: String { return self._s[3521]! } - public var Login_ResetAccountProtected_LimitExceeded: String { return self._s[3522]! } + public var SocksProxySetup_PasswordPlaceholder: String { return self._s[3523]! } + public var Wallet_WordCheck_ViewWords: String { return self._s[3525]! } + public var Login_ResetAccountProtected_LimitExceeded: String { return self._s[3526]! } public func Watch_LastSeen_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3524]!, self._r[3524]!, [_0]) + return formatWithArgumentRanges(self._s[3528]!, self._r[3528]!, [_0]) } - public var Call_ConnectionErrorMessage: String { return self._s[3525]! } - public var VoiceOver_Chat_Music: String { return self._s[3526]! } - public var SettingsSearch_Synonyms_Notifications_MessageNotificationsSound: String { return self._s[3527]! } - public var Compose_GroupTokenListPlaceholder: String { return self._s[3529]! } - public var ConversationMedia_Title: String { return self._s[3530]! } - public var EncryptionKey_Title: String { return self._s[3532]! } - public var TwoStepAuth_EnterPasswordTitle: String { return self._s[3533]! } - public var Notification_Exceptions_AddException: String { return self._s[3534]! } - public var PrivacySettings_BlockedPeersEmpty: String { return self._s[3535]! } - public var Profile_MessageLifetime1m: String { return self._s[3536]! } + public var Call_ConnectionErrorMessage: String { return self._s[3529]! } + public var VoiceOver_Chat_Music: String { return self._s[3530]! } + public var SettingsSearch_Synonyms_Notifications_MessageNotificationsSound: String { return self._s[3531]! } + public var Compose_GroupTokenListPlaceholder: String { return self._s[3533]! } + public var ConversationMedia_Title: String { return self._s[3534]! } + public var EncryptionKey_Title: String { return self._s[3536]! } + public var TwoStepAuth_EnterPasswordTitle: String { return self._s[3537]! } + public var Notification_Exceptions_AddException: String { return self._s[3538]! } + public var PrivacySettings_BlockedPeersEmpty: String { return self._s[3539]! } + public var Profile_MessageLifetime1m: String { return self._s[3540]! } public func Channel_AdminLog_MessageUnkickedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3537]!, self._r[3537]!, [_1]) + return formatWithArgumentRanges(self._s[3541]!, self._r[3541]!, [_1]) } - public var Month_GenMay: String { return self._s[3538]! } + public var Month_GenMay: String { return self._s[3542]! } public func LiveLocationUpdated_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3539]!, self._r[3539]!, [_0]) + return formatWithArgumentRanges(self._s[3543]!, self._r[3543]!, [_0]) } - public var PeopleNearby_Users: String { return self._s[3540]! } - public var Wallet_Send_AddressInfo: String { return self._s[3541]! } - public var ChannelMembers_WhoCanAddMembersAllHelp: String { return self._s[3542]! } - public var AutoDownloadSettings_ResetSettings: String { return self._s[3543]! } + public var PeopleNearby_Users: String { return self._s[3544]! } + public var Wallet_Send_AddressInfo: String { return self._s[3545]! } + public var ChannelMembers_WhoCanAddMembersAllHelp: String { return self._s[3546]! } + public var AutoDownloadSettings_ResetSettings: String { return self._s[3547]! } public func Wallet_Updated_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3545]!, self._r[3545]!, [_0]) + return formatWithArgumentRanges(self._s[3549]!, self._r[3549]!, [_0]) } - public var Conversation_EmptyPlaceholder: String { return self._s[3546]! } - public var Passport_Address_AddPassportRegistration: String { return self._s[3547]! } - public var Notifications_ChannelNotificationsAlert: String { return self._s[3548]! } - public var ChatSettings_AutoDownloadUsingCellular: String { return self._s[3549]! } - public var Camera_TapAndHoldForVideo: String { return self._s[3550]! } - public var Channel_JoinChannel: String { return self._s[3552]! } - public var Appearance_Animations: String { return self._s[3555]! } + public var Conversation_EmptyPlaceholder: String { return self._s[3550]! } + public var Passport_Address_AddPassportRegistration: String { return self._s[3551]! } + public var Notifications_ChannelNotificationsAlert: String { return self._s[3552]! } + public var ChatSettings_AutoDownloadUsingCellular: String { return self._s[3553]! } + public var Camera_TapAndHoldForVideo: String { return self._s[3554]! } + public var Channel_JoinChannel: String { return self._s[3556]! } + public var Appearance_Animations: String { return self._s[3559]! } public func Notification_MessageLifetimeChanged(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3556]!, self._r[3556]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3560]!, self._r[3560]!, [_1, _2]) } - public var Stickers_GroupStickers: String { return self._s[3558]! } - public var Appearance_ShareTheme: String { return self._s[3559]! } - public var TwoFactorSetup_Hint_Placeholder: String { return self._s[3560]! } - public var ConvertToSupergroup_HelpTitle: String { return self._s[3562]! } - public var StickerPackActionInfo_RemovedTitle: String { return self._s[3563]! } - public var Passport_Address_Street: String { return self._s[3564]! } - public var Conversation_AddContact: String { return self._s[3565]! } - public var Login_PhonePlaceholder: String { return self._s[3566]! } - public var Channel_Members_InviteLink: String { return self._s[3568]! } - public var Bot_Stop: String { return self._s[3569]! } - public var SettingsSearch_Synonyms_Proxy_UseForCalls: String { return self._s[3571]! } - public var Notification_PassportValueAddress: String { return self._s[3572]! } - public var Month_ShortJuly: String { return self._s[3573]! } - public var Passport_Address_TypeTemporaryRegistrationUploadScan: String { return self._s[3574]! } - public var Channel_AdminLog_BanSendMedia: String { return self._s[3575]! } - public var Passport_Identity_ReverseSide: String { return self._s[3576]! } - public var Watch_Stickers_Recents: String { return self._s[3579]! } - public var PrivacyLastSeenSettings_EmpryUsersPlaceholder: String { return self._s[3581]! } - public var Map_SendThisLocation: String { return self._s[3582]! } + public var Stickers_GroupStickers: String { return self._s[3562]! } + public var Appearance_ShareTheme: String { return self._s[3563]! } + public var TwoFactorSetup_Hint_Placeholder: String { return self._s[3564]! } + public var ConvertToSupergroup_HelpTitle: String { return self._s[3566]! } + public var StickerPackActionInfo_RemovedTitle: String { return self._s[3567]! } + public var Passport_Address_Street: String { return self._s[3568]! } + public var Conversation_AddContact: String { return self._s[3569]! } + public var Login_PhonePlaceholder: String { return self._s[3570]! } + public var Channel_Members_InviteLink: String { return self._s[3572]! } + public var Bot_Stop: String { return self._s[3573]! } + public var SettingsSearch_Synonyms_Proxy_UseForCalls: String { return self._s[3575]! } + public var Notification_PassportValueAddress: String { return self._s[3576]! } + public var Month_ShortJuly: String { return self._s[3577]! } + public var Passport_Address_TypeTemporaryRegistrationUploadScan: String { return self._s[3578]! } + public var Channel_AdminLog_BanSendMedia: String { return self._s[3579]! } + public var Passport_Identity_ReverseSide: String { return self._s[3580]! } + public var Watch_Stickers_Recents: String { return self._s[3583]! } + public var PrivacyLastSeenSettings_EmpryUsersPlaceholder: String { return self._s[3585]! } + public var Map_SendThisLocation: String { return self._s[3586]! } public func Time_MonthOfYear_m1(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3583]!, self._r[3583]!, [_0]) - } - public func InviteText_SingleContact(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3584]!, self._r[3584]!, [_0]) - } - public var ConvertToSupergroup_Note: String { return self._s[3585]! } - public var Wallet_Intro_NotNow: String { return self._s[3586]! } - public func FileSize_MB(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3587]!, self._r[3587]!, [_0]) } - public var NetworkUsageSettings_GeneralDataSection: String { return self._s[3588]! } + public func InviteText_SingleContact(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3588]!, self._r[3588]!, [_0]) + } + public var ConvertToSupergroup_Note: String { return self._s[3589]! } + public var Wallet_Intro_NotNow: String { return self._s[3590]! } + public func FileSize_MB(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3591]!, self._r[3591]!, [_0]) + } + public var NetworkUsageSettings_GeneralDataSection: String { return self._s[3592]! } public func Compatibility_SecretMediaVersionTooLow(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3589]!, self._r[3589]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3593]!, self._r[3593]!, [_0, _1]) } - public var Login_CallRequestState3: String { return self._s[3591]! } - public var Wallpaper_SearchShort: String { return self._s[3592]! } - public var SettingsSearch_Synonyms_Appearance_ColorTheme: String { return self._s[3594]! } - public var PasscodeSettings_UnlockWithFaceId: String { return self._s[3595]! } - public var Channel_BotDoesntSupportGroups: String { return self._s[3596]! } + public var Login_CallRequestState3: String { return self._s[3595]! } + public var Wallpaper_SearchShort: String { return self._s[3596]! } + public var SettingsSearch_Synonyms_Appearance_ColorTheme: String { return self._s[3598]! } + public var PasscodeSettings_UnlockWithFaceId: String { return self._s[3599]! } + public var Channel_BotDoesntSupportGroups: String { return self._s[3600]! } public func PUSH_CHAT_MESSAGE_GEOLIVE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3597]!, self._r[3597]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3601]!, self._r[3601]!, [_1, _2]) } - public var Channel_AdminLogFilter_Title: String { return self._s[3598]! } - public var Appearance_ThemePreview_Chat_4_Text: String { return self._s[3600]! } - public var Notifications_GroupNotificationsExceptions: String { return self._s[3603]! } + public var Channel_AdminLogFilter_Title: String { return self._s[3602]! } + public var Appearance_ThemePreview_Chat_4_Text: String { return self._s[3604]! } + public var Notifications_GroupNotificationsExceptions: String { return self._s[3607]! } public func FileSize_B(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3604]!, self._r[3604]!, [_0]) + return formatWithArgumentRanges(self._s[3608]!, self._r[3608]!, [_0]) } - public var Passport_CorrectErrors: String { return self._s[3605]! } - public var VoiceOver_Chat_YourAnonymousPoll: String { return self._s[3606]! } + public var Passport_CorrectErrors: String { return self._s[3609]! } + public var VoiceOver_Chat_YourAnonymousPoll: String { return self._s[3610]! } public func Channel_MessageTitleUpdated(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3607]!, self._r[3607]!, [_0]) + return formatWithArgumentRanges(self._s[3611]!, self._r[3611]!, [_0]) } - public var Map_SendMyCurrentLocation: String { return self._s[3608]! } - public var Channel_DiscussionGroup: String { return self._s[3609]! } - public var TwoFactorSetup_Email_SkipConfirmationSkip: String { return self._s[3610]! } + public var Map_SendMyCurrentLocation: String { return self._s[3612]! } + public var Channel_DiscussionGroup: String { return self._s[3613]! } + public var TwoFactorSetup_Email_SkipConfirmationSkip: String { return self._s[3614]! } public func PUSH_PINNED_CONTACT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3611]!, self._r[3611]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3615]!, self._r[3615]!, [_1, _2]) } - public var SharedMedia_SearchNoResults: String { return self._s[3612]! } - public var Permissions_NotificationsText_v0: String { return self._s[3613]! } - public var Channel_EditAdmin_PermissionDeleteMessagesOfOthers: String { return self._s[3614]! } - public var Appearance_AppIcon: String { return self._s[3615]! } - public var Appearance_ThemePreview_ChatList_3_AuthorName: String { return self._s[3616]! } - public var LoginPassword_FloodError: String { return self._s[3617]! } - public var Wallet_Send_OwnAddressAlertProceed: String { return self._s[3619]! } - public var Group_Setup_HistoryHiddenHelp: String { return self._s[3620]! } + public var SharedMedia_SearchNoResults: String { return self._s[3616]! } + public var Permissions_NotificationsText_v0: String { return self._s[3617]! } + public var Channel_EditAdmin_PermissionDeleteMessagesOfOthers: String { return self._s[3618]! } + public var Appearance_AppIcon: String { return self._s[3619]! } + public var Appearance_ThemePreview_ChatList_3_AuthorName: String { return self._s[3620]! } + public var LoginPassword_FloodError: String { return self._s[3621]! } + public var Wallet_Send_OwnAddressAlertProceed: String { return self._s[3623]! } + public var Group_Setup_HistoryHiddenHelp: String { return self._s[3624]! } public func TwoStepAuth_PendingEmailHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3621]!, self._r[3621]!, [_0]) - } - public var Passport_Language_bn: String { return self._s[3622]! } - public func DialogList_SingleUploadingPhotoSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3623]!, self._r[3623]!, [_0]) - } - public var ChatList_Context_Pin: String { return self._s[3624]! } - public func Notification_PinnedAudioMessage(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3625]!, self._r[3625]!, [_0]) } + public var Passport_Language_bn: String { return self._s[3626]! } + public func DialogList_SingleUploadingPhotoSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3627]!, self._r[3627]!, [_0]) + } + public var ChatList_Context_Pin: String { return self._s[3628]! } + public func Notification_PinnedAudioMessage(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3629]!, self._r[3629]!, [_0]) + } public func Channel_AdminLog_MessageChangedGroupStickerPack(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3626]!, self._r[3626]!, [_0]) + return formatWithArgumentRanges(self._s[3630]!, self._r[3630]!, [_0]) } - public var Wallet_Navigation_Close: String { return self._s[3627]! } - public var GroupInfo_InvitationLinkGroupFull: String { return self._s[3631]! } - public var Group_EditAdmin_PermissionChangeInfo: String { return self._s[3633]! } - public var Wallet_Month_GenDecember: String { return self._s[3634]! } - public var Contacts_PermissionsAllow: String { return self._s[3635]! } - public var ReportPeer_ReasonCopyright: String { return self._s[3636]! } - public var Channel_EditAdmin_PermissinAddAdminOn: String { return self._s[3637]! } - public var WallpaperPreview_Pattern: String { return self._s[3638]! } - public var Paint_Duplicate: String { return self._s[3639]! } - public var Passport_Address_Country: String { return self._s[3640]! } - public var Notification_RenamedChannel: String { return self._s[3642]! } - public var ChatList_Context_Unmute: String { return self._s[3643]! } - public var CheckoutInfo_ErrorPostcodeInvalid: String { return self._s[3644]! } - public var Group_MessagePhotoUpdated: String { return self._s[3645]! } - public var Channel_BanUser_PermissionSendMedia: String { return self._s[3646]! } - public var Conversation_ContextMenuBan: String { return self._s[3647]! } - public var TwoStepAuth_EmailSent: String { return self._s[3648]! } - public var MessagePoll_NoVotes: String { return self._s[3649]! } - public var Wallet_Send_ErrorNotEnoughFundsTitle: String { return self._s[3650]! } - public var Passport_Language_is: String { return self._s[3652]! } - public var PeopleNearby_UsersEmpty: String { return self._s[3654]! } - public var Tour_Text5: String { return self._s[3655]! } + public var Wallet_Navigation_Close: String { return self._s[3631]! } + public var GroupInfo_InvitationLinkGroupFull: String { return self._s[3635]! } + public var Group_EditAdmin_PermissionChangeInfo: String { return self._s[3637]! } + public var Wallet_Month_GenDecember: String { return self._s[3638]! } + public var Contacts_PermissionsAllow: String { return self._s[3639]! } + public var ReportPeer_ReasonCopyright: String { return self._s[3640]! } + public var Channel_EditAdmin_PermissinAddAdminOn: String { return self._s[3641]! } + public var WallpaperPreview_Pattern: String { return self._s[3642]! } + public var Paint_Duplicate: String { return self._s[3643]! } + public var Passport_Address_Country: String { return self._s[3644]! } + public var Notification_RenamedChannel: String { return self._s[3646]! } + public var ChatList_Context_Unmute: String { return self._s[3647]! } + public var CheckoutInfo_ErrorPostcodeInvalid: String { return self._s[3648]! } + public var Group_MessagePhotoUpdated: String { return self._s[3649]! } + public var Channel_BanUser_PermissionSendMedia: String { return self._s[3650]! } + public var Conversation_ContextMenuBan: String { return self._s[3651]! } + public var TwoStepAuth_EmailSent: String { return self._s[3652]! } + public var MessagePoll_NoVotes: String { return self._s[3653]! } + public var Wallet_Send_ErrorNotEnoughFundsTitle: String { return self._s[3654]! } + public var Passport_Language_is: String { return self._s[3656]! } + public var PeopleNearby_UsersEmpty: String { return self._s[3658]! } + public var Tour_Text5: String { return self._s[3659]! } public func Call_GroupFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3658]!, self._r[3658]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3662]!, self._r[3662]!, [_1, _2]) } - public var Undo_SecretChatDeleted: String { return self._s[3659]! } - public var SocksProxySetup_ShareQRCode: String { return self._s[3660]! } + public var Undo_SecretChatDeleted: String { return self._s[3663]! } + public var SocksProxySetup_ShareQRCode: String { return self._s[3664]! } public func VoiceOver_Chat_Size(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3661]!, self._r[3661]!, [_0]) + return formatWithArgumentRanges(self._s[3665]!, self._r[3665]!, [_0]) } - public var Forward_ErrorDisabledForChat: String { return self._s[3662]! } - public var LogoutOptions_ChangePhoneNumberText: String { return self._s[3663]! } - public var Paint_Edit: String { return self._s[3665]! } - public var ScheduledMessages_ReminderNotification: String { return self._s[3667]! } - public var Undo_DeletedGroup: String { return self._s[3669]! } - public var LoginPassword_ForgotPassword: String { return self._s[3670]! } - public var Wallet_WordImport_IncorrectTitle: String { return self._s[3671]! } - public var GroupInfo_GroupNamePlaceholder: String { return self._s[3672]! } + public var Forward_ErrorDisabledForChat: String { return self._s[3666]! } + public var LogoutOptions_ChangePhoneNumberText: String { return self._s[3667]! } + public var Paint_Edit: String { return self._s[3669]! } + public var ScheduledMessages_ReminderNotification: String { return self._s[3671]! } + public var Undo_DeletedGroup: String { return self._s[3673]! } + public var LoginPassword_ForgotPassword: String { return self._s[3674]! } + public var Wallet_WordImport_IncorrectTitle: String { return self._s[3675]! } + public var GroupInfo_GroupNamePlaceholder: String { return self._s[3676]! } public func Notification_Kicked(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3673]!, self._r[3673]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3677]!, self._r[3677]!, [_0, _1]) } - public var AppWallet_TransactionInfo_FeeInfoURL: String { return self._s[3674]! } - public var Conversation_InputTextCaptionPlaceholder: String { return self._s[3675]! } - public var AutoDownloadSettings_VideoMessagesTitle: String { return self._s[3676]! } - public var Passport_Language_uz: String { return self._s[3677]! } - public var Conversation_PinMessageAlertGroup: String { return self._s[3678]! } - public var SettingsSearch_Synonyms_Privacy_GroupsAndChannels: String { return self._s[3679]! } - public var Map_StopLiveLocation: String { return self._s[3681]! } - public var VoiceOver_MessageContextSend: String { return self._s[3683]! } - public var PasscodeSettings_Help: String { return self._s[3684]! } - public var NotificationsSound_Input: String { return self._s[3685]! } - public var Share_Title: String { return self._s[3688]! } - public var LogoutOptions_Title: String { return self._s[3689]! } - public var Wallet_Send_AddressText: String { return self._s[3690]! } - public var Login_TermsOfServiceAgree: String { return self._s[3691]! } - public var Compose_NewEncryptedChatTitle: String { return self._s[3692]! } - public var Channel_AdminLog_TitleSelectedEvents: String { return self._s[3693]! } - public var Channel_EditAdmin_PermissionEditMessages: String { return self._s[3694]! } - public var EnterPasscode_EnterTitle: String { return self._s[3695]! } + public var AppWallet_TransactionInfo_FeeInfoURL: String { return self._s[3678]! } + public var Conversation_InputTextCaptionPlaceholder: String { return self._s[3679]! } + public var AutoDownloadSettings_VideoMessagesTitle: String { return self._s[3680]! } + public var Passport_Language_uz: String { return self._s[3681]! } + public var Conversation_PinMessageAlertGroup: String { return self._s[3682]! } + public var SettingsSearch_Synonyms_Privacy_GroupsAndChannels: String { return self._s[3683]! } + public var Map_StopLiveLocation: String { return self._s[3685]! } + public var VoiceOver_MessageContextSend: String { return self._s[3687]! } + public var PasscodeSettings_Help: String { return self._s[3688]! } + public var NotificationsSound_Input: String { return self._s[3689]! } + public var Share_Title: String { return self._s[3692]! } + public var LogoutOptions_Title: String { return self._s[3693]! } + public var Wallet_Send_AddressText: String { return self._s[3694]! } + public var Login_TermsOfServiceAgree: String { return self._s[3695]! } + public var Compose_NewEncryptedChatTitle: String { return self._s[3696]! } + public var Channel_AdminLog_TitleSelectedEvents: String { return self._s[3697]! } + public var Channel_EditAdmin_PermissionEditMessages: String { return self._s[3698]! } + public var EnterPasscode_EnterTitle: String { return self._s[3699]! } public func Call_PrivacyErrorMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3696]!, self._r[3696]!, [_0]) + return formatWithArgumentRanges(self._s[3700]!, self._r[3700]!, [_0]) } - public var Settings_CopyPhoneNumber: String { return self._s[3697]! } - public var Conversation_AddToContacts: String { return self._s[3698]! } + public var Settings_CopyPhoneNumber: String { return self._s[3701]! } + public var Conversation_AddToContacts: String { return self._s[3702]! } public func VoiceOver_Chat_ReplyFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3699]!, self._r[3699]!, [_0]) + return formatWithArgumentRanges(self._s[3703]!, self._r[3703]!, [_0]) } - public var NotificationsSound_Keys: String { return self._s[3700]! } + public var NotificationsSound_Keys: String { return self._s[3704]! } public func Call_ParticipantVersionOutdatedError(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3701]!, self._r[3701]!, [_0]) + return formatWithArgumentRanges(self._s[3705]!, self._r[3705]!, [_0]) } - public var Notification_MessageLifetime1w: String { return self._s[3702]! } - public var Message_Video: String { return self._s[3703]! } - public var AutoDownloadSettings_CellularTitle: String { return self._s[3704]! } + public var Notification_MessageLifetime1w: String { return self._s[3706]! } + public var Message_Video: String { return self._s[3707]! } + public var AutoDownloadSettings_CellularTitle: String { return self._s[3708]! } public func PUSH_CHANNEL_MESSAGE_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3705]!, self._r[3705]!, [_1]) + return formatWithArgumentRanges(self._s[3709]!, self._r[3709]!, [_1]) } - public var Wallet_Receive_AmountInfo: String { return self._s[3708]! } + public var Wallet_Receive_AmountInfo: String { return self._s[3712]! } public func Notification_JoinedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3709]!, self._r[3709]!, [_0]) + return formatWithArgumentRanges(self._s[3713]!, self._r[3713]!, [_0]) } public func PrivacySettings_LastSeenContactsPlus(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3710]!, self._r[3710]!, [_0]) + return formatWithArgumentRanges(self._s[3714]!, self._r[3714]!, [_0]) } - public var Passport_Language_mk: String { return self._s[3711]! } + public var Passport_Language_mk: String { return self._s[3715]! } public func Wallet_Time_PreciseDate_m2(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3712]!, self._r[3712]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3716]!, self._r[3716]!, [_1, _2, _3]) } - public var CreatePoll_CancelConfirmation: String { return self._s[3713]! } - public var MessagePoll_LabelAnonymousQuiz: String { return self._s[3714]! } - public var Conversation_SilentBroadcastTooltipOn: String { return self._s[3716]! } - public var PrivacyPolicy_Decline: String { return self._s[3717]! } - public var Passport_Identity_DoesNotExpire: String { return self._s[3718]! } - public var Channel_AdminLogFilter_EventsRestrictions: String { return self._s[3719]! } - public var AuthSessions_AddDeviceIntro_Action: String { return self._s[3720]! } - public var Permissions_SiriAllow_v0: String { return self._s[3722]! } - public var Wallet_Month_ShortAugust: String { return self._s[3723]! } - public var Appearance_ThemeCarouselNight: String { return self._s[3724]! } + public var CreatePoll_CancelConfirmation: String { return self._s[3717]! } + public var MessagePoll_LabelAnonymousQuiz: String { return self._s[3718]! } + public var Conversation_SilentBroadcastTooltipOn: String { return self._s[3720]! } + public var PrivacyPolicy_Decline: String { return self._s[3721]! } + public var Passport_Identity_DoesNotExpire: String { return self._s[3722]! } + public var Channel_AdminLogFilter_EventsRestrictions: String { return self._s[3723]! } + public var AuthSessions_AddDeviceIntro_Action: String { return self._s[3724]! } + public var Permissions_SiriAllow_v0: String { return self._s[3726]! } + public var Wallet_Month_ShortAugust: String { return self._s[3727]! } + public var Appearance_ThemeCarouselNight: String { return self._s[3728]! } public func LOCAL_CHAT_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3725]!, self._r[3725]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[3729]!, self._r[3729]!, [_1, "\(_2)"]) } public func Notification_RenamedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3726]!, self._r[3726]!, [_0]) + return formatWithArgumentRanges(self._s[3730]!, self._r[3730]!, [_0]) } - public var Paint_Regular: String { return self._s[3727]! } - public var ChatSettings_AutoDownloadReset: String { return self._s[3728]! } - public var SocksProxySetup_ShareLink: String { return self._s[3729]! } - public var Wallet_Qr_Title: String { return self._s[3730]! } - public var BlockedUsers_SelectUserTitle: String { return self._s[3731]! } - public var VoiceOver_Chat_RecordModeVoiceMessage: String { return self._s[3733]! } - public var Wallet_Settings_Configuration: String { return self._s[3734]! } - public var GroupInfo_InviteByLink: String { return self._s[3735]! } - public var MessageTimer_Custom: String { return self._s[3736]! } - public var UserInfo_NotificationsDefaultEnabled: String { return self._s[3737]! } - public var Conversation_StopQuizConfirmationTitle: String { return self._s[3738]! } - public var Passport_Address_TypeTemporaryRegistration: String { return self._s[3740]! } - public var Conversation_SendMessage_SetReminder: String { return self._s[3741]! } - public var VoiceOver_Chat_Selected: String { return self._s[3742]! } - public var ChatSettings_AutoDownloadUsingWiFi: String { return self._s[3743]! } - public var Channel_Username_InvalidTaken: String { return self._s[3744]! } - public var Conversation_ClousStorageInfo_Description3: String { return self._s[3745]! } - public var Wallet_WordCheck_TryAgain: String { return self._s[3746]! } - public var Wallet_Info_TransactionPendingHeader: String { return self._s[3747]! } - public var Settings_ChatBackground: String { return self._s[3748]! } - public var Channel_Subscribers_Title: String { return self._s[3749]! } - public var Wallet_Receive_InvoiceUrlHeader: String { return self._s[3750]! } - public var ApplyLanguage_ChangeLanguageTitle: String { return self._s[3751]! } - public var Watch_ConnectionDescription: String { return self._s[3752]! } - public var OldChannels_NoticeText: String { return self._s[3755]! } - public var Wallet_Configuration_ApplyErrorTitle: String { return self._s[3756]! } - public var IntentsSettings_SuggestBy: String { return self._s[3758]! } - public var Theme_ThemeChangedText: String { return self._s[3759]! } - public var ChatList_ArchivedChatsTitle: String { return self._s[3760]! } - public var Wallpaper_ResetWallpapers: String { return self._s[3761]! } - public var Wallet_Send_TransactionInProgress: String { return self._s[3762]! } - public var EditProfile_Title: String { return self._s[3763]! } - public var NotificationsSound_Bamboo: String { return self._s[3765]! } - public var Channel_AdminLog_MessagePreviousMessage: String { return self._s[3767]! } - public var Login_SmsRequestState2: String { return self._s[3768]! } - public var Passport_Language_ar: String { return self._s[3769]! } + public var Paint_Regular: String { return self._s[3731]! } + public var ChatSettings_AutoDownloadReset: String { return self._s[3732]! } + public var SocksProxySetup_ShareLink: String { return self._s[3733]! } + public var Wallet_Qr_Title: String { return self._s[3734]! } + public var BlockedUsers_SelectUserTitle: String { return self._s[3735]! } + public var VoiceOver_Chat_RecordModeVoiceMessage: String { return self._s[3737]! } + public var Wallet_Settings_Configuration: String { return self._s[3738]! } + public var GroupInfo_InviteByLink: String { return self._s[3739]! } + public var MessageTimer_Custom: String { return self._s[3740]! } + public var UserInfo_NotificationsDefaultEnabled: String { return self._s[3741]! } + public var Conversation_StopQuizConfirmationTitle: String { return self._s[3742]! } + public var Passport_Address_TypeTemporaryRegistration: String { return self._s[3744]! } + public var Conversation_SendMessage_SetReminder: String { return self._s[3745]! } + public var VoiceOver_Chat_Selected: String { return self._s[3746]! } + public var ChatSettings_AutoDownloadUsingWiFi: String { return self._s[3747]! } + public var Channel_Username_InvalidTaken: String { return self._s[3748]! } + public var Conversation_ClousStorageInfo_Description3: String { return self._s[3749]! } + public var Wallet_WordCheck_TryAgain: String { return self._s[3750]! } + public var Wallet_Info_TransactionPendingHeader: String { return self._s[3751]! } + public var Settings_ChatBackground: String { return self._s[3752]! } + public var Channel_Subscribers_Title: String { return self._s[3753]! } + public var Wallet_Receive_InvoiceUrlHeader: String { return self._s[3754]! } + public var ApplyLanguage_ChangeLanguageTitle: String { return self._s[3755]! } + public var Watch_ConnectionDescription: String { return self._s[3756]! } + public var OldChannels_NoticeText: String { return self._s[3759]! } + public var Wallet_Configuration_ApplyErrorTitle: String { return self._s[3760]! } + public var IntentsSettings_SuggestBy: String { return self._s[3762]! } + public var Theme_ThemeChangedText: String { return self._s[3763]! } + public var ChatList_ArchivedChatsTitle: String { return self._s[3764]! } + public var Wallpaper_ResetWallpapers: String { return self._s[3765]! } + public var Wallet_Send_TransactionInProgress: String { return self._s[3766]! } + public var EditProfile_Title: String { return self._s[3767]! } + public var NotificationsSound_Bamboo: String { return self._s[3769]! } + public var Channel_AdminLog_MessagePreviousMessage: String { return self._s[3771]! } + public var Login_SmsRequestState2: String { return self._s[3772]! } + public var Passport_Language_ar: String { return self._s[3773]! } public func Message_AuthorPinnedGame(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3770]!, self._r[3770]!, [_0]) + return formatWithArgumentRanges(self._s[3774]!, self._r[3774]!, [_0]) } - public var SettingsSearch_Synonyms_EditProfile_Title: String { return self._s[3771]! } - public var Wallet_Created_Text: String { return self._s[3772]! } - public var Conversation_MessageDialogEdit: String { return self._s[3774]! } - public var Wallet_Created_Proceed: String { return self._s[3775]! } - public var Wallet_Words_Done: String { return self._s[3776]! } - public var VoiceOver_Media_PlaybackPause: String { return self._s[3777]! } + public var SettingsSearch_Synonyms_EditProfile_Title: String { return self._s[3775]! } + public var Wallet_Created_Text: String { return self._s[3776]! } + public var Conversation_MessageDialogEdit: String { return self._s[3778]! } + public var Wallet_Created_Proceed: String { return self._s[3779]! } + public var Wallet_Words_Done: String { return self._s[3780]! } + public var VoiceOver_Media_PlaybackPause: String { return self._s[3781]! } public func PUSH_AUTH_UNKNOWN(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3778]!, self._r[3778]!, [_1]) + return formatWithArgumentRanges(self._s[3782]!, self._r[3782]!, [_1]) } - public var Common_Close: String { return self._s[3779]! } - public var GroupInfo_PublicLink: String { return self._s[3780]! } - public var Channel_OwnershipTransfer_ErrorPrivacyRestricted: String { return self._s[3781]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsPreview: String { return self._s[3782]! } + public var Common_Close: String { return self._s[3783]! } + public var GroupInfo_PublicLink: String { return self._s[3784]! } + public var Channel_OwnershipTransfer_ErrorPrivacyRestricted: String { return self._s[3785]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsPreview: String { return self._s[3786]! } public func Channel_AdminLog_MessageToggleInvitesOff(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3786]!, self._r[3786]!, [_0]) + return formatWithArgumentRanges(self._s[3790]!, self._r[3790]!, [_0]) } - public var UserInfo_About_Placeholder: String { return self._s[3787]! } + public var UserInfo_About_Placeholder: String { return self._s[3791]! } public func Conversation_FileHowToText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3788]!, self._r[3788]!, [_0]) - } - public var GroupInfo_Permissions_SectionTitle: String { return self._s[3789]! } - public var Channel_Info_Banned: String { return self._s[3791]! } - public func Time_MonthOfYear_m11(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3792]!, self._r[3792]!, [_0]) } - public var Appearance_Other: String { return self._s[3793]! } - public var Passport_Language_my: String { return self._s[3794]! } - public var Group_Setup_BasicHistoryHiddenHelp: String { return self._s[3795]! } + public var GroupInfo_Permissions_SectionTitle: String { return self._s[3793]! } + public var Channel_Info_Banned: String { return self._s[3795]! } + public func Time_MonthOfYear_m11(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3796]!, self._r[3796]!, [_0]) + } + public var Appearance_Other: String { return self._s[3797]! } + public var Passport_Language_my: String { return self._s[3798]! } + public var Group_Setup_BasicHistoryHiddenHelp: String { return self._s[3799]! } public func Time_PreciseDate_m9(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3796]!, self._r[3796]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3800]!, self._r[3800]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_Privacy_PasscodeAndFaceId: String { return self._s[3797]! } - public var IntentsSettings_SuggestedAndSpotlightChatsInfo: String { return self._s[3798]! } - public var Preview_CopyAddress: String { return self._s[3799]! } + public var SettingsSearch_Synonyms_Privacy_PasscodeAndFaceId: String { return self._s[3801]! } + public var IntentsSettings_SuggestedAndSpotlightChatsInfo: String { return self._s[3802]! } + public var Preview_CopyAddress: String { return self._s[3803]! } public func DialogList_SinglePlayingGameSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3800]!, self._r[3800]!, [_0]) + return formatWithArgumentRanges(self._s[3804]!, self._r[3804]!, [_0]) } - public var KeyCommand_JumpToPreviousChat: String { return self._s[3801]! } - public var UserInfo_BotSettings: String { return self._s[3802]! } - public var LiveLocation_MenuStopAll: String { return self._s[3804]! } - public var Passport_PasswordCreate: String { return self._s[3805]! } - public var StickerSettings_MaskContextInfo: String { return self._s[3806]! } - public var Message_PinnedLocationMessage: String { return self._s[3807]! } - public var Map_Satellite: String { return self._s[3808]! } - public var Watch_Message_Unsupported: String { return self._s[3809]! } - public var Username_TooManyPublicUsernamesError: String { return self._s[3810]! } - public var TwoStepAuth_EnterPasswordInvalid: String { return self._s[3811]! } + public var KeyCommand_JumpToPreviousChat: String { return self._s[3805]! } + public var UserInfo_BotSettings: String { return self._s[3806]! } + public var LiveLocation_MenuStopAll: String { return self._s[3808]! } + public var Passport_PasswordCreate: String { return self._s[3809]! } + public var StickerSettings_MaskContextInfo: String { return self._s[3810]! } + public var Message_PinnedLocationMessage: String { return self._s[3811]! } + public var Map_Satellite: String { return self._s[3812]! } + public var Watch_Message_Unsupported: String { return self._s[3813]! } + public var Username_TooManyPublicUsernamesError: String { return self._s[3814]! } + public var TwoStepAuth_EnterPasswordInvalid: String { return self._s[3815]! } public func Notification_PinnedTextMessage(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3812]!, self._r[3812]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3816]!, self._r[3816]!, [_0, _1]) } public func Conversation_OpenBotLinkText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3813]!, self._r[3813]!, [_0]) + return formatWithArgumentRanges(self._s[3817]!, self._r[3817]!, [_0]) } - public var Wallet_WordImport_Continue: String { return self._s[3814]! } + public var Wallet_WordImport_Continue: String { return self._s[3818]! } public func TwoFactorSetup_EmailVerification_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3815]!, self._r[3815]!, [_0]) + return formatWithArgumentRanges(self._s[3819]!, self._r[3819]!, [_0]) } - public var Notifications_ChannelNotificationsHelp: String { return self._s[3816]! } - public var Privacy_Calls_P2PContacts: String { return self._s[3817]! } - public var NotificationsSound_None: String { return self._s[3818]! } - public var Wallet_TransactionInfo_StorageFeeHeader: String { return self._s[3819]! } - public var Channel_DiscussionGroup_UnlinkGroup: String { return self._s[3821]! } - public var AccessDenied_VoiceMicrophone: String { return self._s[3822]! } + public var Notifications_ChannelNotificationsHelp: String { return self._s[3820]! } + public var Privacy_Calls_P2PContacts: String { return self._s[3821]! } + public var NotificationsSound_None: String { return self._s[3822]! } + public var Wallet_TransactionInfo_StorageFeeHeader: String { return self._s[3823]! } + public var Channel_DiscussionGroup_UnlinkGroup: String { return self._s[3825]! } + public var AccessDenied_VoiceMicrophone: String { return self._s[3826]! } public func ApplyLanguage_ChangeLanguageAlreadyActive(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3823]!, self._r[3823]!, [_1]) + return formatWithArgumentRanges(self._s[3827]!, self._r[3827]!, [_1]) } - public var Cache_Indexing: String { return self._s[3824]! } - public var DialogList_RecentTitlePeople: String { return self._s[3826]! } - public var DialogList_EncryptionRejected: String { return self._s[3827]! } - public var GroupInfo_Administrators: String { return self._s[3828]! } - public var Passport_ScanPassportHelp: String { return self._s[3829]! } - public var Application_Name: String { return self._s[3830]! } - public var Channel_AdminLogFilter_ChannelEventsInfo: String { return self._s[3831]! } - public var Appearance_ThemeCarouselDay: String { return self._s[3833]! } - public var Passport_Identity_TranslationHelp: String { return self._s[3834]! } + public var Cache_Indexing: String { return self._s[3828]! } + public var DialogList_RecentTitlePeople: String { return self._s[3830]! } + public var DialogList_EncryptionRejected: String { return self._s[3831]! } + public var GroupInfo_Administrators: String { return self._s[3832]! } + public var Passport_ScanPassportHelp: String { return self._s[3833]! } + public var Application_Name: String { return self._s[3834]! } + public var Channel_AdminLogFilter_ChannelEventsInfo: String { return self._s[3835]! } + public var Appearance_ThemeCarouselDay: String { return self._s[3837]! } + public var Passport_Identity_TranslationHelp: String { return self._s[3838]! } public func VoiceOver_Chat_VideoMessageFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3835]!, self._r[3835]!, [_0]) + return formatWithArgumentRanges(self._s[3839]!, self._r[3839]!, [_0]) } public func Notification_JoinedGroupByLink(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3836]!, self._r[3836]!, [_0]) + return formatWithArgumentRanges(self._s[3840]!, self._r[3840]!, [_0]) } public func DialogList_EncryptedChatStartedOutgoing(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3837]!, self._r[3837]!, [_0]) + return formatWithArgumentRanges(self._s[3841]!, self._r[3841]!, [_0]) } - public var Channel_EditAdmin_PermissionDeleteMessages: String { return self._s[3838]! } - public var Privacy_ChatsTitle: String { return self._s[3839]! } - public var DialogList_ClearHistoryConfirmation: String { return self._s[3840]! } - public var SettingsSearch_Synonyms_Data_Storage_ClearCache: String { return self._s[3841]! } - public var Watch_Suggestion_HoldOn: String { return self._s[3842]! } - public var Group_EditAdmin_TransferOwnership: String { return self._s[3843]! } - public var WebBrowser_Title: String { return self._s[3844]! } - public var Group_LinkedChannel: String { return self._s[3845]! } - public var VoiceOver_Chat_SeenByRecipient: String { return self._s[3846]! } - public var SocksProxySetup_RequiredCredentials: String { return self._s[3847]! } - public var Passport_Address_TypeRentalAgreementUploadScan: String { return self._s[3848]! } - public var Appearance_TextSize_UseSystem: String { return self._s[3849]! } - public var TwoStepAuth_EmailSkipAlert: String { return self._s[3850]! } - public var ScheduledMessages_RemindersTitle: String { return self._s[3852]! } - public var Channel_Setup_TypePublic: String { return self._s[3854]! } + public var Channel_EditAdmin_PermissionDeleteMessages: String { return self._s[3842]! } + public var Privacy_ChatsTitle: String { return self._s[3843]! } + public var DialogList_ClearHistoryConfirmation: String { return self._s[3844]! } + public var SettingsSearch_Synonyms_Data_Storage_ClearCache: String { return self._s[3845]! } + public var Watch_Suggestion_HoldOn: String { return self._s[3846]! } + public var Group_EditAdmin_TransferOwnership: String { return self._s[3847]! } + public var WebBrowser_Title: String { return self._s[3848]! } + public var Group_LinkedChannel: String { return self._s[3849]! } + public var VoiceOver_Chat_SeenByRecipient: String { return self._s[3850]! } + public var SocksProxySetup_RequiredCredentials: String { return self._s[3851]! } + public var Passport_Address_TypeRentalAgreementUploadScan: String { return self._s[3852]! } + public var Appearance_TextSize_UseSystem: String { return self._s[3853]! } + public var TwoStepAuth_EmailSkipAlert: String { return self._s[3854]! } + public var ScheduledMessages_RemindersTitle: String { return self._s[3856]! } + public var Channel_Setup_TypePublic: String { return self._s[3858]! } public func Channel_AdminLog_MessageToggleInvitesOn(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3855]!, self._r[3855]!, [_0]) + return formatWithArgumentRanges(self._s[3859]!, self._r[3859]!, [_0]) } - public var Channel_TypeSetup_Title: String { return self._s[3857]! } - public var MessagePoll_ViewResults: String { return self._s[3858]! } - public var Map_OpenInMaps: String { return self._s[3860]! } + public var Channel_TypeSetup_Title: String { return self._s[3861]! } + public var MessagePoll_ViewResults: String { return self._s[3862]! } + public var Map_OpenInMaps: String { return self._s[3864]! } public func PUSH_PINNED_NOTEXT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3861]!, self._r[3861]!, [_1]) + return formatWithArgumentRanges(self._s[3865]!, self._r[3865]!, [_1]) } - public var NotificationsSound_Tremolo: String { return self._s[3863]! } + public var NotificationsSound_Tremolo: String { return self._s[3867]! } public func Date_ChatDateHeaderYear(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3864]!, self._r[3864]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3868]!, self._r[3868]!, [_1, _2, _3]) } - public var ConversationProfile_UnknownAddMemberError: String { return self._s[3865]! } - public var Channel_OwnershipTransfer_PasswordPlaceholder: String { return self._s[3866]! } - public var Passport_PasswordHelp: String { return self._s[3867]! } - public var Login_CodeExpiredError: String { return self._s[3868]! } - public var Channel_EditAdmin_PermissionChangeInfo: String { return self._s[3869]! } - public var Conversation_TitleUnmute: String { return self._s[3870]! } - public var Passport_Identity_ScansHelp: String { return self._s[3871]! } - public var Passport_Language_lo: String { return self._s[3872]! } - public var Camera_FlashAuto: String { return self._s[3873]! } - public var Conversation_OpenBotLinkOpen: String { return self._s[3874]! } - public var Common_Cancel: String { return self._s[3875]! } - public var DialogList_SavedMessagesTooltip: String { return self._s[3876]! } - public var TwoStepAuth_SetupPasswordTitle: String { return self._s[3877]! } - public var Appearance_TintAllColors: String { return self._s[3878]! } + public var ConversationProfile_UnknownAddMemberError: String { return self._s[3869]! } + public var Channel_OwnershipTransfer_PasswordPlaceholder: String { return self._s[3870]! } + public var Passport_PasswordHelp: String { return self._s[3871]! } + public var Login_CodeExpiredError: String { return self._s[3872]! } + public var Channel_EditAdmin_PermissionChangeInfo: String { return self._s[3873]! } + public var Conversation_TitleUnmute: String { return self._s[3874]! } + public var Passport_Identity_ScansHelp: String { return self._s[3875]! } + public var Passport_Language_lo: String { return self._s[3876]! } + public var Camera_FlashAuto: String { return self._s[3877]! } + public var Conversation_OpenBotLinkOpen: String { return self._s[3878]! } + public var Common_Cancel: String { return self._s[3879]! } + public var DialogList_SavedMessagesTooltip: String { return self._s[3880]! } + public var TwoStepAuth_SetupPasswordTitle: String { return self._s[3881]! } + public var Appearance_TintAllColors: String { return self._s[3882]! } public func PUSH_MESSAGE_FWD(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3879]!, self._r[3879]!, [_1]) + return formatWithArgumentRanges(self._s[3883]!, self._r[3883]!, [_1]) } - public var Conversation_ReportSpamConfirmation: String { return self._s[3880]! } - public var ChatSettings_Title: String { return self._s[3882]! } - public var Passport_PasswordReset: String { return self._s[3883]! } - public var SocksProxySetup_TypeNone: String { return self._s[3884]! } - public var EditTheme_Title: String { return self._s[3887]! } - public var PhoneNumberHelp_Help: String { return self._s[3888]! } - public var Checkout_EnterPassword: String { return self._s[3889]! } - public var Activity_UploadingDocument: String { return self._s[3891]! } - public var Share_AuthTitle: String { return self._s[3892]! } - public var State_Connecting: String { return self._s[3893]! } - public var Profile_MessageLifetime1w: String { return self._s[3894]! } - public var Conversation_ContextMenuReport: String { return self._s[3895]! } - public var CheckoutInfo_ReceiverInfoPhone: String { return self._s[3896]! } - public var AutoNightTheme_ScheduledTo: String { return self._s[3897]! } + public var Conversation_ReportSpamConfirmation: String { return self._s[3884]! } + public var ChatSettings_Title: String { return self._s[3886]! } + public var Passport_PasswordReset: String { return self._s[3887]! } + public var SocksProxySetup_TypeNone: String { return self._s[3888]! } + public var EditTheme_Title: String { return self._s[3891]! } + public var PhoneNumberHelp_Help: String { return self._s[3892]! } + public var Checkout_EnterPassword: String { return self._s[3893]! } + public var Activity_UploadingDocument: String { return self._s[3895]! } + public var Share_AuthTitle: String { return self._s[3896]! } + public var State_Connecting: String { return self._s[3897]! } + public var Profile_MessageLifetime1w: String { return self._s[3898]! } + public var Conversation_ContextMenuReport: String { return self._s[3899]! } + public var CheckoutInfo_ReceiverInfoPhone: String { return self._s[3900]! } + public var AutoNightTheme_ScheduledTo: String { return self._s[3901]! } public func VoiceOver_Chat_AnonymousPollFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3898]!, self._r[3898]!, [_0]) + return formatWithArgumentRanges(self._s[3902]!, self._r[3902]!, [_0]) } - public var AuthSessions_Terminate: String { return self._s[3899]! } - public var Wallet_WordImport_CanNotRemember: String { return self._s[3900]! } - public var Checkout_NewCard_CardholderNamePlaceholder: String { return self._s[3902]! } - public var KeyCommand_JumpToPreviousUnreadChat: String { return self._s[3903]! } - public var PhotoEditor_Set: String { return self._s[3904]! } - public var EmptyGroupInfo_Title: String { return self._s[3905]! } - public var Login_PadPhoneHelp: String { return self._s[3906]! } - public var AutoDownloadSettings_TypeGroupChats: String { return self._s[3908]! } - public var PrivacyPolicy_DeclineLastWarning: String { return self._s[3910]! } - public var NotificationsSound_Complete: String { return self._s[3911]! } - public var SettingsSearch_Synonyms_Privacy_Data_Title: String { return self._s[3912]! } - public var Group_Info_AdminLog: String { return self._s[3913]! } - public var GroupPermission_NotAvailableInPublicGroups: String { return self._s[3914]! } + public var AuthSessions_Terminate: String { return self._s[3903]! } + public var Wallet_WordImport_CanNotRemember: String { return self._s[3904]! } + public var Checkout_NewCard_CardholderNamePlaceholder: String { return self._s[3906]! } + public var KeyCommand_JumpToPreviousUnreadChat: String { return self._s[3907]! } + public var PhotoEditor_Set: String { return self._s[3908]! } + public var EmptyGroupInfo_Title: String { return self._s[3909]! } + public var Login_PadPhoneHelp: String { return self._s[3910]! } + public var AutoDownloadSettings_TypeGroupChats: String { return self._s[3912]! } + public var PrivacyPolicy_DeclineLastWarning: String { return self._s[3914]! } + public var NotificationsSound_Complete: String { return self._s[3915]! } + public var SettingsSearch_Synonyms_Privacy_Data_Title: String { return self._s[3916]! } + public var Group_Info_AdminLog: String { return self._s[3917]! } + public var GroupPermission_NotAvailableInPublicGroups: String { return self._s[3918]! } public func Wallet_Time_PreciseDate_m11(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3915]!, self._r[3915]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3919]!, self._r[3919]!, [_1, _2, _3]) } - public var Channel_AdminLog_InfoPanelAlertText: String { return self._s[3916]! } - public var Group_Location_CreateInThisPlace: String { return self._s[3918]! } - public var Conversation_Admin: String { return self._s[3919]! } - public var Conversation_GifTooltip: String { return self._s[3920]! } - public var Passport_NotLoggedInMessage: String { return self._s[3921]! } + public var Channel_AdminLog_InfoPanelAlertText: String { return self._s[3920]! } + public var Group_Location_CreateInThisPlace: String { return self._s[3922]! } + public var Conversation_Admin: String { return self._s[3923]! } + public var Conversation_GifTooltip: String { return self._s[3924]! } + public var Passport_NotLoggedInMessage: String { return self._s[3925]! } public func AutoDownloadSettings_OnFor(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3923]!, self._r[3923]!, [_0]) + return formatWithArgumentRanges(self._s[3927]!, self._r[3927]!, [_0]) } - public var Profile_MessageLifetimeForever: String { return self._s[3924]! } - public var SharedMedia_EmptyTitle: String { return self._s[3926]! } - public var Channel_Edit_PrivatePublicLinkAlert: String { return self._s[3928]! } - public var Username_Help: String { return self._s[3929]! } - public var DialogList_LanguageTooltip: String { return self._s[3931]! } - public var Map_LoadError: String { return self._s[3932]! } - public var Login_PhoneNumberAlreadyAuthorized: String { return self._s[3933]! } - public var Channel_AdminLog_AddMembers: String { return self._s[3934]! } - public var ArchivedChats_IntroTitle2: String { return self._s[3935]! } - public var Notification_Exceptions_NewException: String { return self._s[3936]! } - public var TwoStepAuth_EmailTitle: String { return self._s[3937]! } - public var WatchRemote_AlertText: String { return self._s[3938]! } + public var Profile_MessageLifetimeForever: String { return self._s[3928]! } + public var SharedMedia_EmptyTitle: String { return self._s[3930]! } + public var Channel_Edit_PrivatePublicLinkAlert: String { return self._s[3932]! } + public var Username_Help: String { return self._s[3933]! } + public var DialogList_LanguageTooltip: String { return self._s[3935]! } + public var Map_LoadError: String { return self._s[3936]! } + public var Login_PhoneNumberAlreadyAuthorized: String { return self._s[3937]! } + public var Channel_AdminLog_AddMembers: String { return self._s[3938]! } + public var ArchivedChats_IntroTitle2: String { return self._s[3939]! } + public var Notification_Exceptions_NewException: String { return self._s[3940]! } + public var TwoStepAuth_EmailTitle: String { return self._s[3941]! } + public var WatchRemote_AlertText: String { return self._s[3942]! } public func Wallet_Send_ConfirmationText(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3939]!, self._r[3939]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3943]!, self._r[3943]!, [_1, _2, _3]) } - public var ChatSettings_ConnectionType_Title: String { return self._s[3943]! } + public var ChatSettings_ConnectionType_Title: String { return self._s[3947]! } public func PUSH_PINNED_QUIZ(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3944]!, self._r[3944]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3948]!, self._r[3948]!, [_1, _2]) } public func Settings_CheckPhoneNumberTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3945]!, self._r[3945]!, [_0]) - } - public var SettingsSearch_Synonyms_Calls_CallTab: String { return self._s[3946]! } - public var WebBrowser_DefaultBrowser: String { return self._s[3947]! } - public var Passport_Address_CountryPlaceholder: String { return self._s[3948]! } - public func DialogList_AwaitingEncryption(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3949]!, self._r[3949]!, [_0]) } + public var SettingsSearch_Synonyms_Calls_CallTab: String { return self._s[3950]! } + public var WebBrowser_DefaultBrowser: String { return self._s[3951]! } + public var Passport_Address_CountryPlaceholder: String { return self._s[3952]! } + public func DialogList_AwaitingEncryption(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3953]!, self._r[3953]!, [_0]) + } public func Time_PreciseDate_m6(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3950]!, self._r[3950]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3954]!, self._r[3954]!, [_1, _2, _3]) } - public var Group_AdminLog_EmptyText: String { return self._s[3951]! } - public var SettingsSearch_Synonyms_Appearance_Title: String { return self._s[3952]! } - public var Conversation_PrivateChannelTooltip: String { return self._s[3954]! } - public var Wallet_Created_ExportErrorText: String { return self._s[3955]! } - public var ChatList_UndoArchiveText1: String { return self._s[3956]! } - public var AccessDenied_VideoMicrophone: String { return self._s[3957]! } - public var Conversation_ContextMenuStickerPackAdd: String { return self._s[3958]! } - public var Cache_ClearNone: String { return self._s[3959]! } - public var SocksProxySetup_FailedToConnect: String { return self._s[3960]! } - public var Permissions_NotificationsTitle_v0: String { return self._s[3961]! } + public var Group_AdminLog_EmptyText: String { return self._s[3955]! } + public var SettingsSearch_Synonyms_Appearance_Title: String { return self._s[3956]! } + public var Conversation_PrivateChannelTooltip: String { return self._s[3958]! } + public var Wallet_Created_ExportErrorText: String { return self._s[3959]! } + public var ChatList_UndoArchiveText1: String { return self._s[3960]! } + public var AccessDenied_VideoMicrophone: String { return self._s[3961]! } + public var Conversation_ContextMenuStickerPackAdd: String { return self._s[3962]! } + public var Cache_ClearNone: String { return self._s[3963]! } + public var SocksProxySetup_FailedToConnect: String { return self._s[3964]! } + public var Permissions_NotificationsTitle_v0: String { return self._s[3965]! } public func Channel_AdminLog_MessageEdited(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3962]!, self._r[3962]!, [_0]) + return formatWithArgumentRanges(self._s[3966]!, self._r[3966]!, [_0]) } - public var Passport_Identity_Country: String { return self._s[3963]! } + public var Passport_Identity_Country: String { return self._s[3967]! } public func ChatSettings_AutoDownloadSettings_TypeFile(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3964]!, self._r[3964]!, [_0]) + return formatWithArgumentRanges(self._s[3968]!, self._r[3968]!, [_0]) } public func Notification_CreatedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3965]!, self._r[3965]!, [_0]) + return formatWithArgumentRanges(self._s[3969]!, self._r[3969]!, [_0]) } - public var Exceptions_AddToExceptions: String { return self._s[3966]! } - public var AccessDenied_Settings: String { return self._s[3967]! } - public var Passport_Address_TypeUtilityBillUploadScan: String { return self._s[3968]! } - public var Month_ShortMay: String { return self._s[3969]! } - public var Compose_NewGroup: String { return self._s[3971]! } - public var Group_Setup_TypePrivate: String { return self._s[3973]! } - public var Login_PadPhoneHelpTitle: String { return self._s[3975]! } - public var Appearance_ThemeDayClassic: String { return self._s[3976]! } - public var Channel_AdminLog_MessagePreviousCaption: String { return self._s[3977]! } - public var AutoDownloadSettings_OffForAll: String { return self._s[3978]! } - public var Privacy_GroupsAndChannels_WhoCanAddMe: String { return self._s[3979]! } - public var Conversation_typing: String { return self._s[3981]! } - public var Undo_ScheduledMessagesCleared: String { return self._s[3982]! } - public var Paint_Masks: String { return self._s[3983]! } - public var Contacts_DeselectAll: String { return self._s[3984]! } + public var Exceptions_AddToExceptions: String { return self._s[3970]! } + public var AccessDenied_Settings: String { return self._s[3971]! } + public var Passport_Address_TypeUtilityBillUploadScan: String { return self._s[3972]! } + public var Month_ShortMay: String { return self._s[3973]! } + public var Compose_NewGroup: String { return self._s[3975]! } + public var Group_Setup_TypePrivate: String { return self._s[3977]! } + public var Login_PadPhoneHelpTitle: String { return self._s[3979]! } + public var Appearance_ThemeDayClassic: String { return self._s[3980]! } + public var Channel_AdminLog_MessagePreviousCaption: String { return self._s[3981]! } + public var AutoDownloadSettings_OffForAll: String { return self._s[3982]! } + public var Privacy_GroupsAndChannels_WhoCanAddMe: String { return self._s[3983]! } + public var Conversation_typing: String { return self._s[3985]! } + public var Undo_ScheduledMessagesCleared: String { return self._s[3986]! } + public var Paint_Masks: String { return self._s[3987]! } + public var Contacts_DeselectAll: String { return self._s[3988]! } public func Wallet_Updated_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3985]!, self._r[3985]!, [_0]) + return formatWithArgumentRanges(self._s[3989]!, self._r[3989]!, [_0]) } - public var CreatePoll_MultipleChoiceQuizAlert: String { return self._s[3986]! } - public var Username_InvalidTaken: String { return self._s[3987]! } - public var Call_StatusNoAnswer: String { return self._s[3988]! } - public var TwoStepAuth_EmailAddSuccess: String { return self._s[3989]! } - public var SettingsSearch_Synonyms_Privacy_BlockedUsers: String { return self._s[3990]! } - public var Passport_Identity_Selfie: String { return self._s[3991]! } - public var Login_InfoLastNamePlaceholder: String { return self._s[3992]! } - public var Privacy_SecretChatsLinkPreviewsHelp: String { return self._s[3993]! } - public var Conversation_ClearSecretHistory: String { return self._s[3994]! } - public var PeopleNearby_Description: String { return self._s[3996]! } - public var NetworkUsageSettings_Title: String { return self._s[3997]! } - public var Your_cards_security_code_is_invalid: String { return self._s[3999]! } + public var CreatePoll_MultipleChoiceQuizAlert: String { return self._s[3990]! } + public var Username_InvalidTaken: String { return self._s[3991]! } + public var Call_StatusNoAnswer: String { return self._s[3992]! } + public var TwoStepAuth_EmailAddSuccess: String { return self._s[3993]! } + public var SettingsSearch_Synonyms_Privacy_BlockedUsers: String { return self._s[3994]! } + public var Passport_Identity_Selfie: String { return self._s[3995]! } + public var Login_InfoLastNamePlaceholder: String { return self._s[3996]! } + public var Privacy_SecretChatsLinkPreviewsHelp: String { return self._s[3997]! } + public var Conversation_ClearSecretHistory: String { return self._s[3998]! } + public var PeopleNearby_Description: String { return self._s[4000]! } + public var NetworkUsageSettings_Title: String { return self._s[4001]! } + public var Your_cards_security_code_is_invalid: String { return self._s[4003]! } public func Notification_LeftChannel(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4001]!, self._r[4001]!, [_0]) + return formatWithArgumentRanges(self._s[4005]!, self._r[4005]!, [_0]) } public func Call_CallInProgressMessage(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4002]!, self._r[4002]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4006]!, self._r[4006]!, [_1, _2]) } - public var SaveIncomingPhotosSettings_From: String { return self._s[4004]! } - public var VoiceOver_Navigation_Search: String { return self._s[4005]! } - public var Map_LiveLocationTitle: String { return self._s[4006]! } - public var Login_InfoAvatarAdd: String { return self._s[4007]! } - public var Passport_Identity_FilesView: String { return self._s[4008]! } - public var UserInfo_GenericPhoneLabel: String { return self._s[4009]! } - public var Privacy_Calls_NeverAllow: String { return self._s[4010]! } - public var VoiceOver_Chat_File: String { return self._s[4011]! } - public var Wallet_Settings_DeleteWalletInfo: String { return self._s[4012]! } + public var SaveIncomingPhotosSettings_From: String { return self._s[4008]! } + public var VoiceOver_Navigation_Search: String { return self._s[4009]! } + public var Map_LiveLocationTitle: String { return self._s[4010]! } + public var Login_InfoAvatarAdd: String { return self._s[4011]! } + public var Passport_Identity_FilesView: String { return self._s[4012]! } + public var UserInfo_GenericPhoneLabel: String { return self._s[4013]! } + public var Privacy_Calls_NeverAllow: String { return self._s[4014]! } + public var VoiceOver_Chat_File: String { return self._s[4015]! } + public var Wallet_Settings_DeleteWalletInfo: String { return self._s[4016]! } public func Contacts_AddPhoneNumber(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4013]!, self._r[4013]!, [_0]) + return formatWithArgumentRanges(self._s[4017]!, self._r[4017]!, [_0]) } - public var ContactInfo_PhoneNumberHidden: String { return self._s[4014]! } - public var TwoStepAuth_ConfirmationText: String { return self._s[4015]! } - public var ChatSettings_AutomaticVideoMessageDownload: String { return self._s[4016]! } + public var ContactInfo_PhoneNumberHidden: String { return self._s[4018]! } + public var TwoStepAuth_ConfirmationText: String { return self._s[4019]! } + public var ChatSettings_AutomaticVideoMessageDownload: String { return self._s[4020]! } public func PUSH_CHAT_MESSAGE_VIDEOS(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4017]!, self._r[4017]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[4021]!, self._r[4021]!, [_1, _2, _3]) } - public var Channel_AdminLogFilter_AdminsAll: String { return self._s[4018]! } - public var Wallet_Intro_CreateErrorText: String { return self._s[4019]! } - public var Tour_Title2: String { return self._s[4020]! } - public var Wallet_Sent_ViewWallet: String { return self._s[4021]! } - public var Conversation_FileOpenIn: String { return self._s[4022]! } - public var Checkout_ErrorPrecheckoutFailed: String { return self._s[4023]! } - public var Wallet_Send_ErrorInvalidAddress: String { return self._s[4024]! } - public var Wallpaper_Set: String { return self._s[4025]! } - public var Passport_Identity_Translations: String { return self._s[4027]! } + public var Channel_AdminLogFilter_AdminsAll: String { return self._s[4022]! } + public var Wallet_Intro_CreateErrorText: String { return self._s[4023]! } + public var Tour_Title2: String { return self._s[4024]! } + public var Wallet_Sent_ViewWallet: String { return self._s[4025]! } + public var Conversation_FileOpenIn: String { return self._s[4026]! } + public var Checkout_ErrorPrecheckoutFailed: String { return self._s[4027]! } + public var Wallet_Send_ErrorInvalidAddress: String { return self._s[4028]! } + public var Wallpaper_Set: String { return self._s[4029]! } + public var Passport_Identity_Translations: String { return self._s[4031]! } public func Channel_AdminLog_MessageChangedChannelAbout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4028]!, self._r[4028]!, [_0]) + return formatWithArgumentRanges(self._s[4032]!, self._r[4032]!, [_0]) } - public var Channel_LeaveChannel: String { return self._s[4029]! } + public var Channel_LeaveChannel: String { return self._s[4033]! } public func PINNED_INVOICE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4030]!, self._r[4030]!, [_1]) + return formatWithArgumentRanges(self._s[4034]!, self._r[4034]!, [_1]) } - public var SettingsSearch_Synonyms_Proxy_AddProxy: String { return self._s[4032]! } - public var PhotoEditor_HighlightsTint: String { return self._s[4033]! } - public var MessagePoll_LabelPoll: String { return self._s[4034]! } - public var Passport_Email_Delete: String { return self._s[4035]! } - public var Conversation_Mute: String { return self._s[4037]! } - public var Channel_AddBotAsAdmin: String { return self._s[4038]! } - public var Channel_AdminLog_CanSendMessages: String { return self._s[4040]! } - public var Wallet_Configuration_BlockchainNameChangedText: String { return self._s[4041]! } - public var ChatSettings_IntentsSettings: String { return self._s[4043]! } - public var Channel_Management_LabelOwner: String { return self._s[4044]! } + public var SettingsSearch_Synonyms_Proxy_AddProxy: String { return self._s[4036]! } + public var PhotoEditor_HighlightsTint: String { return self._s[4037]! } + public var MessagePoll_LabelPoll: String { return self._s[4038]! } + public var Passport_Email_Delete: String { return self._s[4039]! } + public var Conversation_Mute: String { return self._s[4041]! } + public var Channel_AddBotAsAdmin: String { return self._s[4042]! } + public var Channel_AdminLog_CanSendMessages: String { return self._s[4044]! } + public var Wallet_Configuration_BlockchainNameChangedText: String { return self._s[4045]! } + public var ChatSettings_IntentsSettings: String { return self._s[4047]! } + public var Channel_Management_LabelOwner: String { return self._s[4048]! } public func Notification_PassportValuesSentMessage(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4045]!, self._r[4045]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4049]!, self._r[4049]!, [_1, _2]) } - public var Calls_CallTabDescription: String { return self._s[4046]! } - public var Passport_Identity_NativeNameHelp: String { return self._s[4047]! } - public var Common_No: String { return self._s[4048]! } - public var Weekday_Sunday: String { return self._s[4049]! } - public var Notification_Reply: String { return self._s[4050]! } - public var Conversation_ViewMessage: String { return self._s[4051]! } + public var Calls_CallTabDescription: String { return self._s[4050]! } + public var Passport_Identity_NativeNameHelp: String { return self._s[4051]! } + public var Common_No: String { return self._s[4052]! } + public var Weekday_Sunday: String { return self._s[4053]! } + public var Notification_Reply: String { return self._s[4054]! } + public var Conversation_ViewMessage: String { return self._s[4055]! } public func Checkout_SavePasswordTimeoutAndFaceId(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4052]!, self._r[4052]!, [_0]) + return formatWithArgumentRanges(self._s[4056]!, self._r[4056]!, [_0]) } public func Map_LiveLocationPrivateDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4053]!, self._r[4053]!, [_0]) + return formatWithArgumentRanges(self._s[4057]!, self._r[4057]!, [_0]) } public func Wallet_Time_PreciseDate_m7(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4054]!, self._r[4054]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[4058]!, self._r[4058]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_EditProfile_AddAccount: String { return self._s[4055]! } - public var Wallet_Send_Title: String { return self._s[4056]! } - public var Message_PinnedDocumentMessage: String { return self._s[4057]! } - public var Wallet_Info_RefreshErrorText: String { return self._s[4058]! } - public var DialogList_TabTitle: String { return self._s[4060]! } - public var ChatSettings_AutoPlayTitle: String { return self._s[4061]! } - public var Passport_FieldEmail: String { return self._s[4062]! } - public var Conversation_UnpinMessageAlert: String { return self._s[4063]! } - public var Passport_Address_TypeBankStatement: String { return self._s[4064]! } - public var Wallet_SecureStorageReset_Title: String { return self._s[4065]! } - public var Passport_Identity_ExpiryDate: String { return self._s[4066]! } - public var Privacy_Calls_P2P: String { return self._s[4067]! } + public var SettingsSearch_Synonyms_EditProfile_AddAccount: String { return self._s[4059]! } + public var Wallet_Send_Title: String { return self._s[4060]! } + public var Message_PinnedDocumentMessage: String { return self._s[4061]! } + public var Wallet_Info_RefreshErrorText: String { return self._s[4062]! } + public var DialogList_TabTitle: String { return self._s[4064]! } + public var ChatSettings_AutoPlayTitle: String { return self._s[4065]! } + public var Passport_FieldEmail: String { return self._s[4066]! } + public var Conversation_UnpinMessageAlert: String { return self._s[4067]! } + public var Passport_Address_TypeBankStatement: String { return self._s[4068]! } + public var Wallet_SecureStorageReset_Title: String { return self._s[4069]! } + public var Passport_Identity_ExpiryDate: String { return self._s[4070]! } + public var Privacy_Calls_P2P: String { return self._s[4071]! } public func CancelResetAccount_Success(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4069]!, self._r[4069]!, [_0]) + return formatWithArgumentRanges(self._s[4073]!, self._r[4073]!, [_0]) } - public var SocksProxySetup_UseForCallsHelp: String { return self._s[4070]! } + public var SocksProxySetup_UseForCallsHelp: String { return self._s[4074]! } public func PUSH_CHAT_ALBUM(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4071]!, self._r[4071]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4075]!, self._r[4075]!, [_1, _2]) } - public var Stickers_ClearRecent: String { return self._s[4072]! } - public var EnterPasscode_ChangeTitle: String { return self._s[4073]! } - public var TwoFactorSetup_Email_Title: String { return self._s[4074]! } - public var Passport_InfoText: String { return self._s[4075]! } - public var Checkout_NewCard_SaveInfoEnableHelp: String { return self._s[4076]! } + public var Stickers_ClearRecent: String { return self._s[4076]! } + public var EnterPasscode_ChangeTitle: String { return self._s[4077]! } + public var TwoFactorSetup_Email_Title: String { return self._s[4078]! } + public var Passport_InfoText: String { return self._s[4079]! } + public var Checkout_NewCard_SaveInfoEnableHelp: String { return self._s[4080]! } public func Login_InvalidPhoneEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4077]!, self._r[4077]!, [_0]) + return formatWithArgumentRanges(self._s[4081]!, self._r[4081]!, [_0]) } public func Time_PreciseDate_m3(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4078]!, self._r[4078]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[4082]!, self._r[4082]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChannels: String { return self._s[4079]! } - public var ScheduledMessages_PollUnavailable: String { return self._s[4080]! } - public var VoiceOver_Navigation_Compose: String { return self._s[4081]! } - public var Passport_Identity_EditDriversLicense: String { return self._s[4082]! } - public var Conversation_TapAndHoldToRecord: String { return self._s[4084]! } - public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChats: String { return self._s[4085]! } + public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChannels: String { return self._s[4083]! } + public var ScheduledMessages_PollUnavailable: String { return self._s[4084]! } + public var VoiceOver_Navigation_Compose: String { return self._s[4085]! } + public var Passport_Identity_EditDriversLicense: String { return self._s[4086]! } + public var Conversation_TapAndHoldToRecord: String { return self._s[4088]! } + public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChats: String { return self._s[4089]! } public func Notification_CallTimeFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4086]!, self._r[4086]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4090]!, self._r[4090]!, [_1, _2]) } - public var Channel_EditAdmin_PermissionInviteViaLink: String { return self._s[4088]! } - public var ChatSettings_OpenLinksIn: String { return self._s[4089]! } - public var Map_HomeAndWorkTitle: String { return self._s[4090]! } + public var Channel_EditAdmin_PermissionInviteViaLink: String { return self._s[4092]! } + public var ChatSettings_OpenLinksIn: String { return self._s[4093]! } + public var Map_HomeAndWorkTitle: String { return self._s[4094]! } public func Generic_OpenHiddenLinkAlert(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4092]!, self._r[4092]!, [_0]) + return formatWithArgumentRanges(self._s[4096]!, self._r[4096]!, [_0]) } - public var DialogList_Unread: String { return self._s[4093]! } + public var DialogList_Unread: String { return self._s[4097]! } public func PUSH_CHAT_MESSAGE_GIF(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4094]!, self._r[4094]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4098]!, self._r[4098]!, [_1, _2]) } - public var User_DeletedAccount: String { return self._s[4095]! } - public var OwnershipTransfer_SetupTwoStepAuth: String { return self._s[4096]! } + public var User_DeletedAccount: String { return self._s[4099]! } + public var OwnershipTransfer_SetupTwoStepAuth: String { return self._s[4100]! } public func Watch_Time_ShortYesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4097]!, self._r[4097]!, [_0]) + return formatWithArgumentRanges(self._s[4101]!, self._r[4101]!, [_0]) } - public var UserInfo_NotificationsDefault: String { return self._s[4098]! } - public var SharedMedia_CategoryMedia: String { return self._s[4099]! } - public var SocksProxySetup_ProxyStatusUnavailable: String { return self._s[4100]! } - public var Channel_AdminLog_MessageRestrictedForever: String { return self._s[4101]! } - public var Watch_ChatList_Compose: String { return self._s[4102]! } - public var Notifications_MessageNotificationsExceptionsHelp: String { return self._s[4103]! } - public var AutoDownloadSettings_Delimeter: String { return self._s[4104]! } - public var Watch_Microphone_Access: String { return self._s[4105]! } - public var Group_Setup_HistoryHeader: String { return self._s[4106]! } - public var Map_SetThisLocation: String { return self._s[4107]! } - public var Appearance_ThemePreview_Chat_2_ReplyName: String { return self._s[4108]! } - public var Activity_UploadingPhoto: String { return self._s[4109]! } - public var Conversation_Edit: String { return self._s[4111]! } - public var Group_ErrorSendRestrictedMedia: String { return self._s[4112]! } - public var Login_TermsOfServiceDecline: String { return self._s[4113]! } - public var Message_PinnedContactMessage: String { return self._s[4114]! } + public var UserInfo_NotificationsDefault: String { return self._s[4102]! } + public var SharedMedia_CategoryMedia: String { return self._s[4103]! } + public var SocksProxySetup_ProxyStatusUnavailable: String { return self._s[4104]! } + public var Channel_AdminLog_MessageRestrictedForever: String { return self._s[4105]! } + public var Watch_ChatList_Compose: String { return self._s[4106]! } + public var Notifications_MessageNotificationsExceptionsHelp: String { return self._s[4107]! } + public var AutoDownloadSettings_Delimeter: String { return self._s[4108]! } + public var Watch_Microphone_Access: String { return self._s[4109]! } + public var Group_Setup_HistoryHeader: String { return self._s[4110]! } + public var Map_SetThisLocation: String { return self._s[4111]! } + public var Appearance_ThemePreview_Chat_2_ReplyName: String { return self._s[4112]! } + public var Activity_UploadingPhoto: String { return self._s[4113]! } + public var Conversation_Edit: String { return self._s[4115]! } + public var Group_ErrorSendRestrictedMedia: String { return self._s[4116]! } + public var Login_TermsOfServiceDecline: String { return self._s[4117]! } + public var Message_PinnedContactMessage: String { return self._s[4118]! } public func Channel_AdminLog_MessageRestrictedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4115]!, self._r[4115]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4119]!, self._r[4119]!, [_1, _2]) } public func Login_PhoneBannedEmailBody(_ _1: String, _ _2: String, _ _3: String, _ _4: String, _ _5: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4116]!, self._r[4116]!, [_1, _2, _3, _4, _5]) + return formatWithArgumentRanges(self._s[4120]!, self._r[4120]!, [_1, _2, _3, _4, _5]) } - public var Appearance_LargeEmoji: String { return self._s[4117]! } - public var TwoStepAuth_AdditionalPassword: String { return self._s[4119]! } - public var EditTheme_Edit_Preview_IncomingReplyText: String { return self._s[4120]! } + public var Appearance_LargeEmoji: String { return self._s[4121]! } + public var TwoStepAuth_AdditionalPassword: String { return self._s[4123]! } + public var EditTheme_Edit_Preview_IncomingReplyText: String { return self._s[4124]! } public func PUSH_CHAT_DELETE_YOU(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4121]!, self._r[4121]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4125]!, self._r[4125]!, [_1, _2]) } - public var Passport_Phone_EnterOtherNumber: String { return self._s[4122]! } - public var Message_PinnedPhotoMessage: String { return self._s[4123]! } - public var Passport_FieldPhone: String { return self._s[4124]! } - public var TwoStepAuth_RecoveryEmailAddDescription: String { return self._s[4125]! } - public var ChatSettings_AutoPlayGifs: String { return self._s[4126]! } - public var InfoPlist_NSCameraUsageDescription: String { return self._s[4128]! } - public var Conversation_Call: String { return self._s[4129]! } - public var Common_TakePhoto: String { return self._s[4131]! } - public var Group_EditAdmin_RankTitle: String { return self._s[4132]! } - public var Wallet_Receive_CommentHeader: String { return self._s[4133]! } - public var Channel_NotificationLoading: String { return self._s[4134]! } + public var Passport_Phone_EnterOtherNumber: String { return self._s[4126]! } + public var Message_PinnedPhotoMessage: String { return self._s[4127]! } + public var Passport_FieldPhone: String { return self._s[4128]! } + public var TwoStepAuth_RecoveryEmailAddDescription: String { return self._s[4129]! } + public var ChatSettings_AutoPlayGifs: String { return self._s[4130]! } + public var InfoPlist_NSCameraUsageDescription: String { return self._s[4132]! } + public var Conversation_Call: String { return self._s[4133]! } + public var Common_TakePhoto: String { return self._s[4135]! } + public var Group_EditAdmin_RankTitle: String { return self._s[4136]! } + public var Wallet_Receive_CommentHeader: String { return self._s[4137]! } + public var Channel_NotificationLoading: String { return self._s[4138]! } public func Notification_Exceptions_Sound(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4135]!, self._r[4135]!, [_0]) - } - public func ScheduledMessages_ScheduledDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4136]!, self._r[4136]!, [_0]) - } - public func PUSH_CHANNEL_MESSAGE_VIDEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4137]!, self._r[4137]!, [_1]) - } - public var Permissions_SiriTitle_v0: String { return self._s[4138]! } - public func VoiceOver_Chat_VoiceMessageFrom(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[4139]!, self._r[4139]!, [_0]) } - public func Login_ResetAccountProtected_Text(_ _0: String) -> (String, [(Int, NSRange)]) { + public func ScheduledMessages_ScheduledDate(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[4140]!, self._r[4140]!, [_0]) } - public var Channel_MessagePhotoRemoved: String { return self._s[4141]! } - public var Wallet_Info_ReceiveGrams: String { return self._s[4142]! } - public var ClearCache_FreeSpace: String { return self._s[4143]! } - public var Appearance_BubbleCorners_Apply: String { return self._s[4144]! } - public var Common_edit: String { return self._s[4145]! } - public var PrivacySettings_AuthSessions: String { return self._s[4146]! } - public var Month_ShortJune: String { return self._s[4147]! } - public var PrivacyLastSeenSettings_AlwaysShareWith_Placeholder: String { return self._s[4148]! } - public var Call_ReportSend: String { return self._s[4149]! } - public var Watch_LastSeen_JustNow: String { return self._s[4150]! } - public var Notifications_MessageNotifications: String { return self._s[4151]! } - public var WallpaperSearch_ColorGreen: String { return self._s[4152]! } - public var BroadcastListInfo_AddRecipient: String { return self._s[4154]! } - public var Group_Status: String { return self._s[4155]! } + public func PUSH_CHANNEL_MESSAGE_VIDEO(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[4141]!, self._r[4141]!, [_1]) + } + public var Permissions_SiriTitle_v0: String { return self._s[4142]! } + public func VoiceOver_Chat_VoiceMessageFrom(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[4143]!, self._r[4143]!, [_0]) + } + public func Login_ResetAccountProtected_Text(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[4144]!, self._r[4144]!, [_0]) + } + public var Channel_MessagePhotoRemoved: String { return self._s[4145]! } + public var Wallet_Info_ReceiveGrams: String { return self._s[4146]! } + public var ClearCache_FreeSpace: String { return self._s[4147]! } + public var Appearance_BubbleCorners_Apply: String { return self._s[4148]! } + public var Common_edit: String { return self._s[4149]! } + public var PrivacySettings_AuthSessions: String { return self._s[4150]! } + public var Month_ShortJune: String { return self._s[4151]! } + public var PrivacyLastSeenSettings_AlwaysShareWith_Placeholder: String { return self._s[4152]! } + public var Call_ReportSend: String { return self._s[4153]! } + public var Watch_LastSeen_JustNow: String { return self._s[4154]! } + public var Notifications_MessageNotifications: String { return self._s[4155]! } + public var WallpaperSearch_ColorGreen: String { return self._s[4156]! } + public var BroadcastListInfo_AddRecipient: String { return self._s[4158]! } + public var Group_Status: String { return self._s[4159]! } public func AutoNightTheme_LocationHelp(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4156]!, self._r[4156]!, [_0, _1]) + return formatWithArgumentRanges(self._s[4160]!, self._r[4160]!, [_0, _1]) } - public var TextFormat_AddLinkTitle: String { return self._s[4157]! } - public var ShareMenu_ShareTo: String { return self._s[4158]! } - public var Conversation_Moderate_Ban: String { return self._s[4159]! } + public var TextFormat_AddLinkTitle: String { return self._s[4161]! } + public var ShareMenu_ShareTo: String { return self._s[4162]! } + public var Conversation_Moderate_Ban: String { return self._s[4163]! } public func Conversation_DeleteMessagesFor(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4160]!, self._r[4160]!, [_0]) + return formatWithArgumentRanges(self._s[4164]!, self._r[4164]!, [_0]) } - public var SharedMedia_ViewInChat: String { return self._s[4161]! } - public var Map_LiveLocationFor8Hours: String { return self._s[4162]! } + public var SharedMedia_ViewInChat: String { return self._s[4165]! } + public var Map_LiveLocationFor8Hours: String { return self._s[4166]! } public func PUSH_PINNED_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4163]!, self._r[4163]!, [_1]) + return formatWithArgumentRanges(self._s[4167]!, self._r[4167]!, [_1]) } public func PUSH_PINNED_POLL(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4164]!, self._r[4164]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4168]!, self._r[4168]!, [_1, _2]) } public func Map_AccurateTo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4166]!, self._r[4166]!, [_0]) + return formatWithArgumentRanges(self._s[4170]!, self._r[4170]!, [_0]) } - public var Map_OpenInHereMaps: String { return self._s[4167]! } - public var Appearance_ReduceMotion: String { return self._s[4168]! } + public var Map_OpenInHereMaps: String { return self._s[4171]! } + public var Appearance_ReduceMotion: String { return self._s[4172]! } public func PUSH_MESSAGE_TEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4169]!, self._r[4169]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4173]!, self._r[4173]!, [_1, _2]) } - public var Channel_Setup_TypePublicHelp: String { return self._s[4170]! } - public var Passport_Identity_EditInternalPassport: String { return self._s[4171]! } - public var PhotoEditor_Skip: String { return self._s[4172]! } - public func LiveLocationUpdated_MinutesAgo(_ value: Int32) -> String { + public var Channel_Setup_TypePublicHelp: String { return self._s[4174]! } + public var Passport_Identity_EditInternalPassport: String { return self._s[4175]! } + public var PhotoEditor_Skip: String { return self._s[4176]! } + public func ChatList_DeleteConfirmation(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, stringValue) } - public func LastSeen_MinutesAgo(_ value: Int32) -> String { + public func Wallpaper_DeleteConfirmation(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, stringValue) } - public func CreatePoll_AddMoreOptions(_ value: Int32) -> String { + public func AttachmentMenu_SendPhoto(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[2 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedLocations(_ value: Int32) -> String { + public func ForwardedVideos(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[3 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_Weeks(_ value: Int32) -> String { + public func SharedMedia_Video(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[4 * 6 + Int(form.rawValue)]!, stringValue) } - public func AttachmentMenu_SendVideo(_ value: Int32) -> String { + public func Theme_UsersCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[5 * 6 + Int(form.rawValue)]!, stringValue) } - public func SharedMedia_Photo(_ value: Int32) -> String { + public func SharedMedia_Link(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[6 * 6 + Int(form.rawValue)]!, stringValue) } - public func PUSH_CHANNEL_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[7 * 6 + Int(form.rawValue)]!, _1, _2) + public func Notifications_ExceptionMuteExpires_Days(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[7 * 6 + Int(form.rawValue)]!, stringValue) } - public func Notification_GameScoreExtended(_ value: Int32) -> String { + public func SharedMedia_DeleteItemsConfirmation(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[8 * 6 + Int(form.rawValue)]!, stringValue) } - public func MuteFor_Days(_ value: Int32) -> String { + public func ChatList_DeletedChats(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[9 * 6 + Int(form.rawValue)]!, stringValue) } - public func Wallpaper_DeleteConfirmation(_ value: Int32) -> String { + public func MuteFor_Days(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[10 * 6 + Int(form.rawValue)]!, stringValue) } - public func Conversation_LiveLocationMembersCount(_ value: Int32) -> String { + public func ServiceMessage_GameScoreSelfExtended(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[11 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedVideoMessages(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[12 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Contacts_ImportersCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[13 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedMessages(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[14 * 6 + Int(form.rawValue)]!, stringValue) - } public func PUSH_CHANNEL_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[15 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func AttachmentMenu_SendItem(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[16 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ServiceMessage_GameScoreSelfExtended(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[17 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Forward_ConfirmMultipleFiles(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[18 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PollResults_ShowMore(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[19 * 6 + Int(form.rawValue)]!, stringValue) - } - public func DialogList_LiveLocationChatsCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[20 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Call_Minutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[21 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Conversation_SelectedMessages(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[22 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Media_SharePhoto(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[23 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[12 * 6 + Int(form.rawValue)]!, _1, _2) } public func OldChannels_InactiveWeek(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[24 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGE_VIDEOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[25 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func MuteFor_Hours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[26 * 6 + Int(form.rawValue)]!, stringValue) - } - public func OldChannels_GroupFormat(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[27 * 6 + Int(form.rawValue)]!, stringValue) - } - public func UserCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[28 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notification_GameScoreSelfExtended(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[29 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Watch_UserInfo_Mute(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[30 * 6 + Int(form.rawValue)]!, stringValue) - } - public func AttachmentMenu_SendGif(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[31 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MuteExpires_Days(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[32 * 6 + Int(form.rawValue)]!, stringValue) - } - public func InviteText_ContactsCountText(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[33 * 6 + Int(form.rawValue)]!, stringValue) - } - public func StickerPack_StickerCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[34 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHANNEL_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[35 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func ForwardedGifs(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[36 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Map_ETAHours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[37 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ChatList_SelectedChats(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[38 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Call_ShortMinutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[39 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Media_ShareItem(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[40 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Media_ShareVideo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[41 * 6 + Int(form.rawValue)]!, stringValue) - } - public func OldChannels_InactiveYear(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[42 * 6 + Int(form.rawValue)]!, stringValue) - } - public func VoiceOver_Chat_PollOptionCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[43 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessagePoll_VotedCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[44 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[45 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func PUSH_CHAT_MESSAGES(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[46 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func MessageTimer_ShortSeconds(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[47 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ServiceMessage_GameScoreSimple(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[48 * 6 + Int(form.rawValue)]!, stringValue) - } - public func SharedMedia_Generic(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[49 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[13 * 6 + Int(form.rawValue)]!, stringValue) } public func MessageTimer_Days(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[14 * 6 + Int(form.rawValue)]!, stringValue) + } + public func OldChannels_InactiveMonth(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[15 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Minutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[16 * 6 + Int(form.rawValue)]!, stringValue) + } + public func DialogList_LiveLocationChatsCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[17 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[18 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func Call_ShortMinutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[19 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notification_GameScoreSelfExtended(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[20 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Conversation_LiveLocationMembersCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[21 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notifications_Exceptions(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[22 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Months(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[23 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Conversation_StatusSubscribers(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[24 * 6 + Int(form.rawValue)]!, stringValue) + } + public func VoiceOver_Chat_PollVotes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[25 * 6 + Int(form.rawValue)]!, stringValue) + } + public func QuickSend_Photos(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[26 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[27 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func OldChannels_Leave(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[28 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Map_ETAMinutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[29 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PollResults_ShowMore(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[30 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Hours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[31 * 6 + Int(form.rawValue)]!, stringValue) + } + public func LiveLocation_MenuChatsCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[32 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Map_ETAHours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[33 * 6 + Int(form.rawValue)]!, stringValue) + } + public func StickerPack_RemoveStickerCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[34 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PrivacyLastSeenSettings_AddUsers(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[35 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MuteExpires_Days(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[36 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessagePoll_VotedCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[37 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedFiles(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[38 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ServiceMessage_GameScoreSimple(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[39 * 6 + Int(form.rawValue)]!, stringValue) + } + public func VoiceOver_Chat_ContactEmailCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[40 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Media_ShareItem(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[41 * 6 + Int(form.rawValue)]!, stringValue) + } + public func OldChannels_GroupFormat(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[42 * 6 + Int(form.rawValue)]!, stringValue) + } + public func SharedMedia_File(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[43 * 6 + Int(form.rawValue)]!, stringValue) + } + public func InviteText_ContactsCountText(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[44 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Watch_UserInfo_Mute(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[45 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedPhotos(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[46 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notification_GameScoreSelfSimple(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[47 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedContacts(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[48 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Call_Seconds(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[49 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Media_SharePhoto(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[50 * 6 + Int(form.rawValue)]!, stringValue) } - public func Conversation_StatusMembers(_ value: Int32) -> String { + public func VoiceOver_Chat_PollOptionCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[51 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_ShortMinutes(_ value: Int32) -> String { + public func Invitation_Members(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[52 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_Seconds(_ value: Int32) -> String { + public func ForwardedLocations(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[53 * 6 + Int(form.rawValue)]!, stringValue) } - public func GroupInfo_ShowMoreMembers(_ value: Int32) -> String { + public func ForwardedVideoMessages(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[54 * 6 + Int(form.rawValue)]!, stringValue) @@ -4981,345 +4988,342 @@ public final class PresentationStrings: Equatable { let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[55 * 6 + Int(form.rawValue)]!, stringValue) } - public func OldChannels_Leave(_ value: Int32) -> String { + public func UserCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[56 * 6 + Int(form.rawValue)]!, stringValue) } - public func PUSH_CHAT_MESSAGE_PHOTOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[57 * 6 + Int(form.rawValue)]!, _2, _1, _3) + public func ForwardedMessages(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[57 * 6 + Int(form.rawValue)]!, stringValue) } - public func VoiceOver_Chat_ContactEmailCount(_ value: Int32) -> String { + public func SharedMedia_Photo(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[58 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_Years(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[59 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessagePoll_QuizCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[60 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[61 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func SharedMedia_Link(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[62 * 6 + Int(form.rawValue)]!, stringValue) - } - public func StickerPack_RemoveMaskCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[63 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notifications_ExceptionMuteExpires_Hours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[64 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Theme_UsersCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[65 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedAuthorsOthers(_ selector: Int32, _ _0: String, _ _1: String) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[66 * 6 + Int(form.rawValue)]!, _0, _1) - } - public func Watch_LastSeen_MinutesAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[67 * 6 + Int(form.rawValue)]!, stringValue) - } - public func QuickSend_Photos(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[68 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_ShortDays(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[69 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_ShortWeeks(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[70 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Watch_LastSeen_HoursAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[71 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Chat_DeleteMessagesConfirmation(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[72 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PasscodeSettings_FailedAttempts(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[73 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Call_Seconds(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[74 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MuteExpires_Hours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[75 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Contacts_InviteContacts(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[76 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedFiles(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[77 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHANNEL_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[78 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func Notifications_ExceptionMuteExpires_Days(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[79 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Wallet_Updated_HoursAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[80 * 6 + Int(form.rawValue)]!, stringValue) - } - public func StickerPack_AddStickerCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[81 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedContacts(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[82 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedAudios(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[83 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notification_GameScoreSelfSimple(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[84 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ServiceMessage_GameScoreExtended(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[85 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ServiceMessage_GameScoreSelfSimple(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[86 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PrivacyLastSeenSettings_AddUsers(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[87 * 6 + Int(form.rawValue)]!, stringValue) - } - public func VoiceOver_Chat_PollVotes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[88 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedStickers(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[89 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedPolls(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[90 * 6 + Int(form.rawValue)]!, stringValue) - } - public func AttachmentMenu_SendPhoto(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[91 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_ShortHours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[92 * 6 + Int(form.rawValue)]!, stringValue) - } - public func LiveLocation_MenuChatsCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[93 * 6 + Int(form.rawValue)]!, stringValue) - } - public func VoiceOver_Chat_ContactPhoneNumberCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[94 * 6 + Int(form.rawValue)]!, stringValue) - } - public func LastSeen_HoursAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[95 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ChatList_DeleteConfirmation(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[96 * 6 + Int(form.rawValue)]!, stringValue) - } - public func OldChannels_InactiveMonth(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[97 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedVideos(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[98 * 6 + Int(form.rawValue)]!, stringValue) - } - public func SharedMedia_Video(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[99 * 6 + Int(form.rawValue)]!, stringValue) - } - public func StickerPack_AddMaskCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[100 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Map_ETAMinutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[101 * 6 + Int(form.rawValue)]!, stringValue) - } - public func SharedMedia_File(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[102 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Minutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[103 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Invitation_Members(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[104 * 6 + Int(form.rawValue)]!, stringValue) - } - public func StickerPack_RemoveStickerCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[105 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ChatList_DeletedChats(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[106 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGE_ROUNDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[107 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func MessageTimer_Hours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[108 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notifications_ExceptionMuteExpires_Minutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[109 * 6 + Int(form.rawValue)]!, stringValue) - } - public func SharedMedia_DeleteItemsConfirmation(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[110 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[111 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func Passport_Scans(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[112 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHANNEL_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[113 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func MessageTimer_Months(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[114 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGE_FWDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[115 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func MuteExpires_Minutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[116 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[117 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notifications_Exceptions(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[118 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Call_ShortSeconds(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[119 * 6 + Int(form.rawValue)]!, stringValue) - } - public func GroupInfo_ParticipantCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[120 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Conversation_StatusSubscribers(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[121 * 6 + Int(form.rawValue)]!, stringValue) - } public func PUSH_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[122 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func PUSH_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[123 * 6 + Int(form.rawValue)]!, _1, _2) + return String(format: self._ps[59 * 6 + Int(form.rawValue)]!, _1, _2) } public func Conversation_StatusOnline(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[124 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[60 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedPhotos(_ value: Int32) -> String { + public func ServiceMessage_GameScoreExtended(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[125 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[61 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[62 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func Call_ShortSeconds(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[63 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Watch_LastSeen_HoursAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[64 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHAT_MESSAGE_FWDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[65 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func LastSeen_HoursAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[66 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ServiceMessage_GameScoreSelfSimple(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[67 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Wallet_Updated_HoursAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[68 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Watch_LastSeen_MinutesAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[69 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHAT_MESSAGE_VIDEOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[70 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func PUSH_CHAT_MESSAGE_ROUNDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[71 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func OldChannels_InactiveYear(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[72 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notifications_ExceptionMuteExpires_Minutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[73 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Call_Minutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[74 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedAudios(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[75 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortHours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[76 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortSeconds(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[77 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Weeks(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[78 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[79 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedPolls(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[80 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Media_ShareVideo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[81 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Forward_ConfirmMultipleFiles(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[82 * 6 + Int(form.rawValue)]!, stringValue) + } + public func GroupInfo_ParticipantCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[83 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MuteExpires_Minutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[84 * 6 + Int(form.rawValue)]!, stringValue) + } + public func VoiceOver_Chat_ContactPhoneNumberCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[85 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ChatList_SelectedChats(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[86 * 6 + Int(form.rawValue)]!, stringValue) + } + public func StickerPack_AddStickerCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[87 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[88 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func PasscodeSettings_FailedAttempts(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[89 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notifications_ExceptionMuteExpires_Hours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[90 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Conversation_SelectedMessages(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[91 * 6 + Int(form.rawValue)]!, stringValue) + } + public func AttachmentMenu_SendItem(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[92 * 6 + Int(form.rawValue)]!, stringValue) + } + public func StickerPack_AddMaskCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[93 * 6 + Int(form.rawValue)]!, stringValue) + } + public func StickerPack_RemoveMaskCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[94 * 6 + Int(form.rawValue)]!, stringValue) + } + public func CreatePoll_AddMoreOptions(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[95 * 6 + Int(form.rawValue)]!, stringValue) + } + public func GroupInfo_ShowMoreMembers(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[96 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MuteExpires_Hours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[97 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Contacts_ImportersCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[98 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedGifs(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[99 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[100 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func AttachmentMenu_SendGif(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[101 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notification_GameScoreExtended(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[102 * 6 + Int(form.rawValue)]!, stringValue) + } + public func LiveLocationUpdated_MinutesAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[103 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Years(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[104 * 6 + Int(form.rawValue)]!, stringValue) + } + public func StickerPack_StickerCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[105 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortMinutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[106 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedAuthorsOthers(_ selector: Int32, _ _0: String, _ _1: String) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[107 * 6 + Int(form.rawValue)]!, _0, _1) + } + public func AttachmentMenu_SendVideo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[108 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedStickers(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[109 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHAT_MESSAGE_PHOTOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[110 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func Chat_DeleteMessagesConfirmation(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[111 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortDays(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[112 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortWeeks(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[113 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Conversation_StatusMembers(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[114 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Contacts_InviteContacts(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[115 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[116 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func MessageTimer_Seconds(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[117 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Passport_Scans(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[118 * 6 + Int(form.rawValue)]!, stringValue) + } + public func SharedMedia_Generic(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[119 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MuteFor_Hours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[120 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessagePoll_QuizCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[121 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[122 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func PUSH_CHAT_MESSAGES(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[123 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func LastSeen_MinutesAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[124 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[125 * 6 + Int(form.rawValue)]!, _1, _2) } public init(primaryComponent: PresentationStringsComponent, secondaryComponent: PresentationStringsComponent?, groupingSeparator: String) { diff --git a/submodules/TelegramUI/TelegramUI/ChatController.swift b/submodules/TelegramUI/TelegramUI/ChatController.swift index ee1d46ff01..09d4a6ebdb 100644 --- a/submodules/TelegramUI/TelegramUI/ChatController.swift +++ b/submodules/TelegramUI/TelegramUI/ChatController.swift @@ -1892,7 +1892,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.presentInGlobalOverlay(contextController) } avatarNode.tapped = { [weak self] in - self?.navigationButtonAction(.openChatInfo(expandAvatar: true)) + guard let strongSelf = self else { + return + } + var expandAvatar = false + if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer, peer.smallProfileImage != nil { + expandAvatar = true + } + strongSelf.navigationButtonAction(.openChatInfo(expandAvatar: expandAvatar)) } } self.navigationItem.titleView = self.chatTitleView diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveMediaBadge.swift b/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveMediaBadge.swift index d71b6f4a6f..b713b25614 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveMediaBadge.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveMediaBadge.swift @@ -87,7 +87,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, badgeAnimated: Bool = true) { + 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 @@ -263,7 +263,7 @@ final class ChatMessageInteractiveMediaBadge: ASDisplayNode { var originY: CGFloat = 5.0 switch mediaDownloadState { case .remote: - if let image = PresentationResourcesChat.chatBubbleFileCloudFetchMediaIcon(theme) { + if let theme = theme, let image = PresentationResourcesChat.chatBubbleFileCloudFetchMediaIcon(theme) { state = .customIcon(image) } else { state = .none diff --git a/submodules/TelegramUI/TelegramUI/ChatTitleView.swift b/submodules/TelegramUI/TelegramUI/ChatTitleView.swift index bc988e496b..27802c7185 100644 --- a/submodules/TelegramUI/TelegramUI/ChatTitleView.swift +++ b/submodules/TelegramUI/TelegramUI/ChatTitleView.swift @@ -60,7 +60,7 @@ private final class ChatTitleNetworkStatusNode: ASDisplayNode { func updateTheme(theme: PresentationTheme) { self.theme = theme - self.titleNode.attributedText = NSAttributedString(string: self.title, font: Font.bold(17.0), textColor: self.theme.rootController.navigationBar.primaryTextColor) + self.titleNode.attributedText = NSAttributedString(string: self.title, font: Font.medium(24.0), textColor: self.theme.rootController.navigationBar.primaryTextColor) self.activityIndicator.type = .custom(self.theme.rootController.navigationBar.primaryTextColor, 22.0, 1.5, false) } @@ -109,7 +109,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView { private var titleRightIcon: ChatTitleIcon = .none private var titleScamIcon = false - private var networkStatusNode: ChatTitleNetworkStatusNode? + //private var networkStatusNode: ChatTitleNetworkStatusNode? private var presenceManager: PeerPresenceStatusManager? @@ -125,7 +125,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView { isOnline = true } - if isOnline || layout?.metrics.widthClass == .regular { + /*if isOnline || layout?.metrics.widthClass == .regular { self.contentContainer.isHidden = false if let networkStatusNode = self.networkStatusNode { self.networkStatusNode = nil @@ -155,7 +155,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView { case .online: break } - } + }*/ self.setNeedsLayout() } @@ -164,6 +164,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView { didSet { if self.networkState != oldValue { updateNetworkStatusNode(networkState: self.networkState, layout: self.layout) + self.updateStatus() } } } @@ -277,175 +278,191 @@ final class ChatTitleView: UIView, NavigationBarTitleView { } var state = ChatTitleActivityNodeState.none - if let (peerId, inputActivities) = self.inputActivities, !inputActivities.isEmpty, inputActivitiesAllowed { - var stringValue = "" - var first = true - var mergedActivity = inputActivities[0].1 - for (_, activity) in inputActivities { - if activity != mergedActivity { - mergedActivity = .typingText - break - } + switch self.networkState { + case .waitingForNetwork, .connecting, .updating: + var infoText: String + switch self.networkState { + case .waitingForNetwork: + infoText = self.strings.ChatState_WaitingForNetwork + case let .connecting(proxy): + infoText = self.strings.ChatState_Connecting + case .updating: + infoText = self.strings.ChatState_Updating + case .online: + infoText = "" } - if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.SecretChat { - switch mergedActivity { - case .typingText: - stringValue = strings.Conversation_typing - case .uploadingFile: - stringValue = strings.Activity_UploadingDocument - case .recordingVoice: - stringValue = strings.Activity_RecordingAudio - case .uploadingPhoto: - stringValue = strings.Activity_UploadingPhoto - case .uploadingVideo: - stringValue = strings.Activity_UploadingVideo - case .playingGame: - stringValue = strings.Activity_PlayingGame - case .recordingInstantVideo: - stringValue = strings.Activity_RecordingVideoMessage - case .uploadingInstantVideo: - stringValue = strings.Activity_UploadingVideoMessage - } - } else { - for (peer, _) in inputActivities { - let title = peer.compactDisplayTitle - if !title.isEmpty { - if first { - first = false - } else { - stringValue += ", " - } - stringValue += title + state = .info(NSAttributedString(string: infoText, font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor), .generic) + case .online: + if let (peerId, inputActivities) = self.inputActivities, !inputActivities.isEmpty, inputActivitiesAllowed { + var stringValue = "" + var first = true + var mergedActivity = inputActivities[0].1 + for (_, activity) in inputActivities { + if activity != mergedActivity { + mergedActivity = .typingText + break } } - } - let color = self.theme.rootController.navigationBar.accentTextColor - let string = NSAttributedString(string: stringValue, font: Font.regular(13.0), textColor: color) - switch mergedActivity { - case .typingText: - state = .typingText(string, color) - case .recordingVoice: - state = .recordingVoice(string, color) - case .recordingInstantVideo: - state = .recordingVideo(string, color) - case .uploadingFile, .uploadingInstantVideo, .uploadingPhoto, .uploadingVideo: - state = .uploading(string, color) - case .playingGame: - state = .playingGame(string, color) - } - } else { - if let titleContent = self.titleContent { - switch titleContent { - case let .peer(peerView, onlineMemberCount, isScheduledMessages): - if let peer = peerViewMainPeer(peerView) { - let servicePeer = isServicePeer(peer) - if peer.id == self.account.peerId || isScheduledMessages { - let string = NSAttributedString(string: "", font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) - state = .info(string, .generic) - } else if let user = peer as? TelegramUser { - if servicePeer { + if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.SecretChat { + switch mergedActivity { + case .typingText: + stringValue = strings.Conversation_typing + case .uploadingFile: + stringValue = strings.Activity_UploadingDocument + case .recordingVoice: + stringValue = strings.Activity_RecordingAudio + case .uploadingPhoto: + stringValue = strings.Activity_UploadingPhoto + case .uploadingVideo: + stringValue = strings.Activity_UploadingVideo + case .playingGame: + stringValue = strings.Activity_PlayingGame + case .recordingInstantVideo: + stringValue = strings.Activity_RecordingVideoMessage + case .uploadingInstantVideo: + stringValue = strings.Activity_UploadingVideoMessage + } + } else { + for (peer, _) in inputActivities { + let title = peer.compactDisplayTitle + if !title.isEmpty { + if first { + first = false + } else { + stringValue += ", " + } + stringValue += title + } + } + } + let color = self.theme.rootController.navigationBar.accentTextColor + let string = NSAttributedString(string: stringValue, font: Font.regular(13.0), textColor: color) + switch mergedActivity { + case .typingText: + state = .typingText(string, color) + case .recordingVoice: + state = .recordingVoice(string, color) + case .recordingInstantVideo: + state = .recordingVideo(string, color) + case .uploadingFile, .uploadingInstantVideo, .uploadingPhoto, .uploadingVideo: + state = .uploading(string, color) + case .playingGame: + state = .playingGame(string, color) + } + } else { + if let titleContent = self.titleContent { + switch titleContent { + case let .peer(peerView, onlineMemberCount, isScheduledMessages): + if let peer = peerViewMainPeer(peerView) { + let servicePeer = isServicePeer(peer) + if peer.id == self.account.peerId || isScheduledMessages { let string = NSAttributedString(string: "", font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) state = .info(string, .generic) - } else if user.flags.contains(.isSupport) { - let statusText = self.strings.Bot_GenericSupportStatus - - let string = NSAttributedString(string: statusText, font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) - state = .info(string, .generic) - } else if let _ = user.botInfo { - let statusText = self.strings.Bot_GenericBotStatus - - let string = NSAttributedString(string: statusText, font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) - state = .info(string, .generic) - } else if let peer = peerViewMainPeer(peerView) { - let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 - let userPresence: TelegramUserPresence - if let presence = peerView.peerPresences[peer.id] as? TelegramUserPresence { - userPresence = presence - self.presenceManager?.reset(presence: presence) + } else if let user = peer as? TelegramUser { + if servicePeer { + let string = NSAttributedString(string: "", font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) + state = .info(string, .generic) + } else if user.flags.contains(.isSupport) { + let statusText = self.strings.Bot_GenericSupportStatus + + let string = NSAttributedString(string: statusText, font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) + state = .info(string, .generic) + } else if let _ = user.botInfo { + let statusText = self.strings.Bot_GenericBotStatus + + let string = NSAttributedString(string: statusText, font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) + state = .info(string, .generic) + } else if let peer = peerViewMainPeer(peerView) { + let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 + let userPresence: TelegramUserPresence + if let presence = peerView.peerPresences[peer.id] as? TelegramUserPresence { + userPresence = presence + self.presenceManager?.reset(presence: presence) + } else { + userPresence = TelegramUserPresence(status: .none, lastActivity: 0) + } + let (string, activity) = stringAndActivityForUserPresence(strings: self.strings, dateTimeFormat: self.dateTimeFormat, presence: userPresence, relativeTo: Int32(timestamp)) + let attributedString = NSAttributedString(string: string, font: Font.regular(13.0), textColor: activity ? self.theme.rootController.navigationBar.accentTextColor : self.theme.rootController.navigationBar.secondaryTextColor) + state = .info(attributedString, activity ? .online : .lastSeenTime) } else { - userPresence = TelegramUserPresence(status: .none, lastActivity: 0) + let string = NSAttributedString(string: "", font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) + state = .info(string, .generic) } - let (string, activity) = stringAndActivityForUserPresence(strings: self.strings, dateTimeFormat: self.dateTimeFormat, presence: userPresence, relativeTo: Int32(timestamp)) - let attributedString = NSAttributedString(string: string, font: Font.regular(13.0), textColor: activity ? self.theme.rootController.navigationBar.accentTextColor : self.theme.rootController.navigationBar.secondaryTextColor) - state = .info(attributedString, activity ? .online : .lastSeenTime) - } else { - let string = NSAttributedString(string: "", font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) - state = .info(string, .generic) - } - } else if let group = peer as? TelegramGroup { - var onlineCount = 0 - if let cachedGroupData = peerView.cachedData as? CachedGroupData, let participants = cachedGroupData.participants { - let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 - for participant in participants.participants { - if let presence = peerView.peerPresences[participant.peerId] as? TelegramUserPresence { - let relativeStatus = relativeUserPresenceStatus(presence, relativeTo: Int32(timestamp)) - switch relativeStatus { - case .online: - onlineCount += 1 - default: - break + } else if let group = peer as? TelegramGroup { + var onlineCount = 0 + if let cachedGroupData = peerView.cachedData as? CachedGroupData, let participants = cachedGroupData.participants { + let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 + for participant in participants.participants { + if let presence = peerView.peerPresences[participant.peerId] as? TelegramUserPresence { + let relativeStatus = relativeUserPresenceStatus(presence, relativeTo: Int32(timestamp)) + switch relativeStatus { + case .online: + onlineCount += 1 + default: + break + } } } } - } - if onlineCount > 1 { - let string = NSMutableAttributedString() - - string.append(NSAttributedString(string: "\(strings.Conversation_StatusMembers(Int32(group.participantCount))), ", font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor)) - string.append(NSAttributedString(string: strings.Conversation_StatusOnline(Int32(onlineCount)), font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor)) - state = .info(string, .generic) - } else { - let string = NSAttributedString(string: strings.Conversation_StatusMembers(Int32(group.participantCount)), font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) - state = .info(string, .generic) - } - } else if let channel = peer as? TelegramChannel { - if let cachedChannelData = peerView.cachedData as? CachedChannelData, let memberCount = cachedChannelData.participantsSummary.memberCount { - if memberCount == 0 { - let string: NSAttributedString - if case .group = channel.info { - string = NSAttributedString(string: strings.Group_Status, font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) - } else { - string = NSAttributedString(string: strings.Channel_Status, font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) - } + if onlineCount > 1 { + let string = NSMutableAttributedString() + + string.append(NSAttributedString(string: "\(strings.Conversation_StatusMembers(Int32(group.participantCount))), ", font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor)) + string.append(NSAttributedString(string: strings.Conversation_StatusOnline(Int32(onlineCount)), font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor)) state = .info(string, .generic) } else { - if case .group = channel.info, let onlineMemberCount = onlineMemberCount, onlineMemberCount > 1 { - let string = NSMutableAttributedString() - - string.append(NSAttributedString(string: "\(strings.Conversation_StatusMembers(Int32(memberCount))), ", font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor)) - string.append(NSAttributedString(string: strings.Conversation_StatusOnline(Int32(onlineMemberCount)), font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor)) + let string = NSAttributedString(string: strings.Conversation_StatusMembers(Int32(group.participantCount)), font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) + state = .info(string, .generic) + } + } else if let channel = peer as? TelegramChannel { + if let cachedChannelData = peerView.cachedData as? CachedChannelData, let memberCount = cachedChannelData.participantsSummary.memberCount { + if memberCount == 0 { + let string: NSAttributedString + if case .group = channel.info { + string = NSAttributedString(string: strings.Group_Status, font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) + } else { + string = NSAttributedString(string: strings.Channel_Status, font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) + } state = .info(string, .generic) } else { - let membersString: String - if case .group = channel.info { - membersString = strings.Conversation_StatusMembers(memberCount) + if case .group = channel.info, let onlineMemberCount = onlineMemberCount, onlineMemberCount > 1 { + let string = NSMutableAttributedString() + + string.append(NSAttributedString(string: "\(strings.Conversation_StatusMembers(Int32(memberCount))), ", font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor)) + string.append(NSAttributedString(string: strings.Conversation_StatusOnline(Int32(onlineMemberCount)), font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor)) + state = .info(string, .generic) } else { - membersString = strings.Conversation_StatusSubscribers(memberCount) + let membersString: String + if case .group = channel.info { + membersString = strings.Conversation_StatusMembers(memberCount) + } else { + membersString = strings.Conversation_StatusSubscribers(memberCount) + } + let string = NSAttributedString(string: membersString, font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) + state = .info(string, .generic) } - let string = NSAttributedString(string: membersString, font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) - state = .info(string, .generic) } - } - } else { - switch channel.info { - case .group: - let string = NSAttributedString(string: strings.Group_Status, font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) - state = .info(string, .generic) - case .broadcast: - let string = NSAttributedString(string: strings.Channel_Status, font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) - state = .info(string, .generic) + } else { + switch channel.info { + case .group: + let string = NSAttributedString(string: strings.Group_Status, font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) + state = .info(string, .generic) + case .broadcast: + let string = NSAttributedString(string: strings.Channel_Status, font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) + state = .info(string, .generic) + } } } } - } - default: - break + default: + break + } + + self.accessibilityLabel = self.titleNode.attributedText?.string + self.accessibilityValue = state.string + } else { + self.accessibilityLabel = nil } - - self.accessibilityLabel = self.titleNode.attributedText?.string - self.accessibilityValue = state.string - } else { - self.accessibilityLabel = nil } } @@ -552,7 +569,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView { self.theme = theme self.strings = strings - self.networkStatusNode?.updateTheme(theme: theme) + //self.networkStatusNode?.updateTheme(theme: theme) let titleContent = self.titleContent self.titleContent = titleContent self.updateStatus() @@ -612,7 +629,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView { let titleSideInset: CGFloat = 3.0 if size.height > 40.0 { - var titleSize = self.titleNode.updateLayout(CGSize(width: clearBounds.width - leftIconWidth - credibilityIconWidth - rightIconWidth - titleSideInset * 2.0, height: size.height)) + var titleSize = self.titleNode.updateLayout(CGSize(width: clearBounds.width - leftIconWidth - credibilityIconWidth - rightIconWidth - titleSideInset * 2.0 - leftInset, height: size.height)) titleSize.width += credibilityIconWidth let activitySize = self.activityNode.updateLayout(clearBounds.size, alignment: .left) let titleInfoSpacing: CGFloat = 0.0 @@ -663,10 +680,10 @@ final class ChatTitleView: UIView, NavigationBarTitleView { } } - if let networkStatusNode = self.networkStatusNode { + /*if let networkStatusNode = self.networkStatusNode { transition.updateFrame(node: networkStatusNode, frame: CGRect(origin: CGPoint(), size: size)) networkStatusNode.updateLayout(size: size, transition: transition) - } + }*/ } @objc func buttonPressed() { diff --git a/submodules/TelegramUI/TelegramUI/FileMediaResourceStatus.swift b/submodules/TelegramUI/TelegramUI/FileMediaResourceStatus.swift index df635fa8b4..03980fc8e1 100644 --- a/submodules/TelegramUI/TelegramUI/FileMediaResourceStatus.swift +++ b/submodules/TelegramUI/TelegramUI/FileMediaResourceStatus.swift @@ -33,7 +33,7 @@ func messageFileMediaPlaybackStatus(context: AccountContext, file: TelegramMedia } } -func messageFileMediaResourceStatus(context: AccountContext, file: TelegramMediaFile, message: Message, isRecentActions: Bool) -> Signal { +func messageFileMediaResourceStatus(context: AccountContext, file: TelegramMediaFile, message: Message, isRecentActions: Bool, isSharedMedia: Bool = false) -> Signal { let playbackStatus = internalMessageFileMediaPlaybackStatus(context: context, file: file, message: message, isRecentActions: isRecentActions) |> map { status -> MediaPlayerPlaybackStatus? in return status?.status } diff --git a/submodules/TelegramUI/TelegramUI/ListMessageFileItemNode.swift b/submodules/TelegramUI/TelegramUI/ListMessageFileItemNode.swift index b6e759f72f..57daa968c1 100644 --- a/submodules/TelegramUI/TelegramUI/ListMessageFileItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ListMessageFileItemNode.swift @@ -15,6 +15,7 @@ import AccountContext import RadialStatusNode import PhotoResources import MusicAlbumArtResources +import UniversalMediaPlayer private let extensionImageCache = Atomic<[UInt32: UIImage]>(value: [:]) @@ -124,6 +125,7 @@ private struct FetchControls { private enum FileIconImage: Equatable { case imageRepresentation(TelegramMediaFile, TelegramMediaImageRepresentation) case albumArt(TelegramMediaFile, SharedMediaPlaybackAlbumArt) + case roundVideo(TelegramMediaFile) static func ==(lhs: FileIconImage, rhs: FileIconImage) -> Bool { switch lhs { @@ -139,6 +141,12 @@ private enum FileIconImage: Equatable { } else { return false } + case let .roundVideo(file): + if case .roundVideo(file) = rhs { + return true + } else { + return false + } } } } @@ -159,6 +167,10 @@ final class ListMessageFileItemNode: ListMessageNode { private let statusButtonNode: HighlightTrackingButtonNode private let statusNode: RadialStatusNode + private var waveformNode: AudioWaveformNode? + private var waveformForegroundNode: AudioWaveformNode? + private var waveformScrubbingNode: MediaPlayerScrubbingNode? + private var currentIconImage: FileIconImage? private var currentMedia: Media? @@ -167,6 +179,8 @@ final class ListMessageFileItemNode: ListMessageNode { private var fetchStatus: MediaResourceStatus? private var resourceStatus: FileMediaResourceMediaStatus? private let fetchDisposable = MetaDisposable() + private let playbackStatusDisposable = MetaDisposable() + private let playbackStatus = Promise() private var downloadStatusIconNode: ASImageNode private var linearProgressNode: ASDisplayNode @@ -226,7 +240,7 @@ final class ListMessageFileItemNode: ListMessageNode { self.downloadStatusIconNode.displayWithoutProcessing = true self.progressNode = RadialProgressNode(theme: RadialProgressTheme(backgroundColor: .black, foregroundColor: .white, icon: nil)) - self.progressNode.isLayerBacked = true + //self.progressNode.isLayerBacked = true self.linearProgressNode = ASDisplayNode() self.linearProgressNode.isLayerBacked = true @@ -235,6 +249,7 @@ final class ListMessageFileItemNode: ListMessageNode { self.addSubnode(self.separatorNode) self.addSubnode(self.titleNode) + self.addSubnode(self.progressNode) self.addSubnode(self.descriptionNode) self.addSubnode(self.descriptionProgressNode) self.addSubnode(self.extensionIconNode) @@ -335,9 +350,13 @@ final class ListMessageFileItemNode: ListMessageNode { var iconImage: FileIconImage? var updateIconImageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>? var updatedStatusSignal: Signal? + var updatedPlaybackStatusSignal: Signal? var updatedFetchControls: FetchControls? + var waveform: AudioWaveform? var isAudio = false + var isVoice = false + var isInstantVideo = false let message = item.message @@ -346,9 +365,12 @@ final class ListMessageFileItemNode: ListMessageNode { if let file = media as? TelegramMediaFile { selectedMedia = file + isInstantVideo = file.isInstantVideo + for attribute in file.attributes { - if case let .Audio(voice, _, title, performer, _) = attribute { + if case let .Audio(voice, _, title, performer, waveformValue) = attribute { isAudio = true + isVoice = voice titleText = NSAttributedString(string: title ?? (file.fileName ?? "Unknown Track"), font: audioTitleFont, textColor: item.theme.list.itemPrimaryTextColor) @@ -365,11 +387,21 @@ final class ListMessageFileItemNode: ListMessageNode { if !voice { iconImage = .albumArt(file, SharedMediaPlaybackAlbumArt(thumbnailResource: ExternalMusicAlbumArtResource(title: title ?? "", performer: performer ?? "", isThumbnail: true), fullSizeResource: ExternalMusicAlbumArtResource(title: title ?? "", performer: performer ?? "", isThumbnail: false))) + } else { + titleText = NSAttributedString(string: " ", font: audioTitleFont, textColor: item.theme.list.itemPrimaryTextColor) + descriptionText = NSAttributedString(string: item.message.author?.displayTitle(strings: item.strings, displayOrder: .firstLast) ?? " ", font: descriptionFont, textColor: item.theme.list.itemSecondaryTextColor) + waveformValue?.withDataNoCopy { data in + waveform = AudioWaveform(bitstream: data, bitsPerSample: 5) + } } } } - if !isAudio { + if isInstantVideo { + titleText = NSAttributedString(string: item.strings.Message_VideoMessage, font: audioTitleFont, textColor: item.theme.list.itemPrimaryTextColor) + descriptionText = NSAttributedString(string: item.message.author?.displayTitle(strings: item.strings, displayOrder: .firstLast) ?? " ", font: descriptionFont, textColor: item.theme.list.itemSecondaryTextColor) + iconImage = .roundVideo(file) + } else if !isAudio { let fileName: String = file.fileName ?? "" titleText = NSAttributedString(string: fileName, font: titleFont, textColor: item.theme.list.itemPrimaryTextColor) @@ -402,7 +434,7 @@ final class ListMessageFileItemNode: ListMessageNode { } } - if isAudio { + if isAudio && !isVoice { leftInset += 14.0 } @@ -435,9 +467,9 @@ final class ListMessageFileItemNode: ListMessageNode { } if statusUpdated { - updatedStatusSignal = messageFileMediaResourceStatus(context: item.context, file: selectedMedia, message: message, isRecentActions: false) + updatedStatusSignal = messageFileMediaResourceStatus(context: item.context, file: selectedMedia, message: message, isRecentActions: false, isSharedMedia: true) - if isAudio { + if isAudio || isInstantVideo { if let currentUpdatedStatusSignal = updatedStatusSignal { updatedStatusSignal = currentUpdatedStatusSignal |> map { status in @@ -450,6 +482,9 @@ final class ListMessageFileItemNode: ListMessageNode { } } } + if isVoice { + updatedPlaybackStatusSignal = messageFileMediaPlaybackStatus(context: item.context, file: selectedMedia, message: message, isRecentActions: false) + } } } @@ -472,6 +507,11 @@ final class ListMessageFileItemNode: ListMessageNode { let imageCorners = ImageCorners(topLeft: .Corner(4.0), topRight: .Corner(4.0), bottomLeft: .Corner(4.0), bottomRight: .Corner(4.0)) let arguments = TransformImageArguments(corners: imageCorners, imageSize: iconSize, boundingSize: iconSize, intrinsicInsets: UIEdgeInsets(), emptyColor: item.theme.list.mediaPlaceholderColor) iconImageApply = iconImageLayout(arguments) + case let .roundVideo(file): + let iconSize = CGSize(width: 42.0, height: 42.0) + let imageCorners = ImageCorners(topLeft: .Corner(iconSize.width / 2.0), topRight: .Corner(iconSize.width / 2.0), bottomLeft: .Corner(iconSize.width / 2.0), bottomRight: .Corner(iconSize.width / 2.0)) + let arguments = TransformImageArguments(corners: imageCorners, imageSize: (file.dimensions ?? PixelDimensions(width: 320, height: 320)).cgSize.aspectFilled(iconSize), boundingSize: iconSize, intrinsicInsets: UIEdgeInsets(), emptyColor: item.theme.list.mediaPlaceholderColor) + iconImageApply = iconImageLayout(arguments) } } @@ -482,7 +522,8 @@ final class ListMessageFileItemNode: ListMessageNode { updateIconImageSignal = chatWebpageSnippetFile(account: item.context.account, fileReference: .message(message: MessageReference(message), media: file), representation: representation) case let .albumArt(file, albumArt): updateIconImageSignal = playerAlbumArt(postbox: item.context.account.postbox, fileReference: .message(message: MessageReference(message), media: file), albumArt: albumArt, thumbnail: true) - + case let .roundVideo(file): + updateIconImageSignal = mediaGridMessageVideo(postbox: item.context.account.postbox, videoReference: FileMediaReference.message(message: MessageReference(message), media: file), autoFetchFullSizeThumbnail: true) } } else { updateIconImageSignal = .complete() @@ -581,6 +622,48 @@ final class ListMessageFileItemNode: ListMessageNode { strongSelf.currentIconImage = iconImage + if isVoice { + let waveformNode: AudioWaveformNode + let waveformForegroundNode: AudioWaveformNode + let waveformScrubbingNode: MediaPlayerScrubbingNode + if let current = strongSelf.waveformNode { + waveformNode = current + } else { + waveformNode = AudioWaveformNode() + waveformNode.isLayerBacked = true + strongSelf.waveformNode = waveformNode + strongSelf.addSubnode(waveformNode) + } + if let current = strongSelf.waveformForegroundNode { + waveformForegroundNode = current + } else { + waveformForegroundNode = AudioWaveformNode() + waveformForegroundNode.isLayerBacked = true + strongSelf.waveformForegroundNode = waveformForegroundNode + strongSelf.addSubnode(waveformForegroundNode) + } + if let current = strongSelf.waveformScrubbingNode { + waveformScrubbingNode = current + } else { + waveformScrubbingNode = MediaPlayerScrubbingNode(content: .custom(backgroundNode: waveformNode, foregroundContentNode: waveformForegroundNode)) + waveformScrubbingNode.hitTestSlop = UIEdgeInsets(top: -10.0, left: 0.0, bottom: -10.0, right: 0.0) + waveformScrubbingNode.seek = { timestamp in + if let strongSelf = self, let context = strongSelf.context, let message = strongSelf.message, let type = peerMessageMediaPlayerType(message) { + context.sharedContext.mediaManager.playlistControl(.seek(timestamp), type: type) + } + } + waveformScrubbingNode.enableScrubbing = false + waveformScrubbingNode.status = strongSelf.playbackStatus.get() + strongSelf.waveformScrubbingNode = waveformScrubbingNode + strongSelf.addSubnode(waveformScrubbingNode) + } + + strongSelf.waveformScrubbingNode?.frame = CGRect(origin: CGPoint(x: leftOffset + leftInset, y: 10.0), size: CGSize(width: params.width - (leftOffset + leftInset) - 16.0, height: 12.0)) + + waveformNode.setup(color: item.theme.list.controlSecondaryColor, waveform: waveform) + waveformForegroundNode.setup(color: item.theme.list.itemAccentColor, waveform: waveform) + } + if let iconImageApply = iconImageApply { if let updateImageSignal = updateIconImageSignal { strongSelf.iconImageNode.setSignal(updateImageSignal) @@ -632,10 +715,24 @@ final class ListMessageFileItemNode: ListMessageNode { transition.updateFrame(node: strongSelf.downloadStatusIconNode, frame: CGRect(origin: CGPoint(x: leftOffset + leftInset, y: strongSelf.descriptionNode.frame.minY + floor((strongSelf.descriptionNode.frame.height - 11.0) / 2.0)), size: CGSize(width: 11.0, height: 11.0))) + let progressSize: CGFloat = 40.0 + transition.updateFrame(node: strongSelf.progressNode, frame: CGRect(origin: CGPoint(x: leftOffset + params.leftInset + floor((leftInset - params.leftInset - progressSize) / 2.0), y: floor((nodeLayout.contentSize.height - progressSize) / 2.0)), size: CGSize(width: progressSize, height: progressSize))) + if let updatedFetchControls = updatedFetchControls { let _ = strongSelf.fetchControls.swap(updatedFetchControls) } + if let updatedPlaybackStatusSignal = updatedPlaybackStatusSignal { + strongSelf.playbackStatus.set(updatedPlaybackStatusSignal) + /*strongSelf.playbackStatusDisposable.set((updatedPlaybackStatusSignal |> deliverOnMainQueue).start(next: { [weak strongSelf] status in + displayLinkDispatcher.dispatch { + if let strongSelf = strongSelf { + strongSelf.playerStatus = status + } + } + }))*/ + } + strongSelf.updateStatus(transition: transition) } }) @@ -648,25 +745,34 @@ final class ListMessageFileItemNode: ListMessageNode { } var isAudio = false + var isVoice = false + var isInstantVideo = false if let file = media as? TelegramMediaFile { isAudio = file.isMusic || file.isVoice + isVoice = file.isVoice + isInstantVideo = file.isInstantVideo } + self.progressNode.isHidden = !isVoice + + var enableScrubbing = false var musicIsPlaying: Bool? var statusState: RadialStatusNodeState = .none - if !isAudio { + if !isAudio && !isInstantVideo { self.updateProgressFrame(size: contentSize, leftInset: layoutParams.leftInset, rightInset: layoutParams.rightInset, transition: .immediate) } else { - switch fetchStatus { - case let .Fetching(_, progress): - let adjustedProgress = max(progress, 0.027) - statusState = .cloudProgress(color: item.theme.list.itemAccentColor, strokeBackgroundColor: item.theme.list.itemAccentColor.withAlphaComponent(0.5), lineWidth: 2.0, value: CGFloat(adjustedProgress)) - case .Local: - break - case .Remote: - if let image = PresentationResourcesItemList.cloudFetchIcon(item.theme) { - statusState = .customIcon(image) - } + if !isVoice && !isInstantVideo { + switch fetchStatus { + case let .Fetching(_, progress): + let adjustedProgress = max(progress, 0.027) + statusState = .cloudProgress(color: item.theme.list.itemAccentColor, strokeBackgroundColor: item.theme.list.itemAccentColor.withAlphaComponent(0.5), lineWidth: 2.0, value: CGFloat(adjustedProgress)) + case .Local: + break + case .Remote: + if let image = PresentationResourcesItemList.cloudFetchIcon(item.theme) { + statusState = .customIcon(image) + } + } } self.statusNode.transitionToState(statusState, completion: {}) self.statusButtonNode.isUserInteractionEnabled = statusState != .none @@ -691,6 +797,7 @@ final class ListMessageFileItemNode: ListMessageNode { } } case let .playbackStatus(playbackStatus): + enableScrubbing = true switch playbackStatus { case .playing: musicIsPlaying = true @@ -701,7 +808,8 @@ final class ListMessageFileItemNode: ListMessageNode { } } } - if let musicIsPlaying = musicIsPlaying { + self.waveformScrubbingNode?.enableScrubbing = enableScrubbing + if let musicIsPlaying = musicIsPlaying, !isVoice { if self.playbackOverlayNode == nil { let playbackOverlayNode = ListMessagePlaybackOverlayNode() playbackOverlayNode.frame = self.iconImageNode.frame diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoFilesPane.swift b/submodules/TelegramUI/TelegramUI/PeerInfoFilesPane.swift index 112682fe33..e5b8b0bc22 100644 --- a/submodules/TelegramUI/TelegramUI/PeerInfoFilesPane.swift +++ b/submodules/TelegramUI/TelegramUI/PeerInfoFilesPane.swift @@ -13,6 +13,8 @@ import TelegramUIPreferences final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode { private let context: AccountContext private let peerId: PeerId + private let paneInteraction: PeerInfoPaneInteraction + private let controllerInteraction: ChatControllerInteraction private let listNode: ChatHistoryListNode @@ -24,14 +26,25 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode { return self.ready.get() } + private let selectedMessagesPromise = Promise?>(nil) + private var selectedMessages: Set? { + didSet { + if self.selectedMessages != oldValue { + self.selectedMessagesPromise.set(.single(self.selectedMessages)) + } + } + } + private var hiddenMediaDisposable: Disposable? - init(context: AccountContext, openMessage: @escaping (MessageId) -> Bool, peerId: PeerId, tagMask: MessageTags) { + init(context: AccountContext, openMessage: @escaping (MessageId) -> Bool, peerId: PeerId, tagMask: MessageTags, interaction: PeerInfoPaneInteraction) { self.context = context self.peerId = peerId + self.paneInteraction = interaction var openMessageImpl: ((MessageId) -> Bool)? - let controllerInteraction = ChatControllerInteraction(openMessage: { message, _ in + var toggleMessageSelectionImpl: (([MessageId]) -> Void)? + self.controllerInteraction = ChatControllerInteraction(openMessage: { message, _ in return openMessageImpl?(message.id) ?? false }, openPeer: { _, _, _ in }, openPeerMention: { _ in @@ -39,7 +52,8 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode { }, openMessageContextActions: { _, _, _, _ in }, navigateToMessage: { _, _ in }, tapMessage: nil, clickThroughMessage: { - }, toggleMessagesSelection: { _, _ in + }, toggleMessagesSelection: { ids, _ in + toggleMessageSelectionImpl?(ids) }, sendCurrentMessage: { _ in }, sendMessage: { _ in }, sendSticker: { _, _, _, _ in @@ -97,8 +111,13 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode { }, requestMessageUpdate: { _ in }, cancelInteractiveKeyboardGestures: { }, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: false)) + self.controllerInteraction.selectionState = self.paneInteraction.selectedMessageIds.flatMap { ids in + return ChatInterfaceSelectionState(selectedIds: ids) + } + self.selectedMessages = self.paneInteraction.selectedMessageIds + self.selectedMessagesPromise.set(.single(self.selectedMessages)) - self.listNode = ChatHistoryListNode(context: context, chatLocation: .peer(peerId), tagMask: tagMask, subject: nil, controllerInteraction: controllerInteraction, selectedMessages: .single(nil), mode: .list(search: false, reversed: false)) + self.listNode = ChatHistoryListNode(context: context, chatLocation: .peer(peerId), tagMask: tagMask, subject: nil, controllerInteraction: controllerInteraction, selectedMessages: self.selectedMessagesPromise.get(), mode: .list(search: false, reversed: false)) super.init() @@ -106,6 +125,12 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode { return openMessage(id) } + toggleMessageSelectionImpl = { [weak self] ids in + for id in ids { + self?.paneInteraction.toggleMessageSelected(id) + } + } + self.hiddenMediaDisposable = context.sharedContext.mediaManager.galleryHiddenMediaManager.hiddenIds().start(next: { [weak self] ids in guard let strongSelf = self else { return @@ -116,7 +141,7 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode { hiddenMedia[messageId] = [media] } } - controllerInteraction.hiddenMedia = hiddenMedia + strongSelf.controllerInteraction.hiddenMedia = hiddenMedia strongSelf.listNode.forEachItemNode { itemNode in if let itemNode = itemNode as? ListMessageNode { itemNode.updateHiddenMedia() @@ -171,4 +196,16 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode { } return transitionNode } + + func updateSelectedMessages(animated: Bool) { + self.controllerInteraction.selectionState = self.paneInteraction.selectedMessageIds.flatMap { ids in + return ChatInterfaceSelectionState(selectedIds: ids) + } + self.listNode.forEachItemNode { itemNode in + if let itemNode = itemNode as? ChatMessageItemView { + itemNode.updateSelectionState(animated: animated) + } + } + self.selectedMessages = self.paneInteraction.selectedMessageIds + } } diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoGroupsInCommonPaneNode.swift b/submodules/TelegramUI/TelegramUI/PeerInfoGroupsInCommonPaneNode.swift new file mode 100644 index 0000000000..82c1c0b91f --- /dev/null +++ b/submodules/TelegramUI/TelegramUI/PeerInfoGroupsInCommonPaneNode.swift @@ -0,0 +1,165 @@ +import AsyncDisplayKit +import Display +import TelegramCore +import SyncCore +import SwiftSignalKit +import Postbox +import TelegramPresentationData +import AccountContext +import ContextUI +import PhotoResources +import TelegramUIPreferences +import ItemListPeerItem +import MergeLists +import ItemListUI + +private struct GroupsInCommonListTransaction { + let deletions: [ListViewDeleteItem] + let insertions: [ListViewInsertItem] + let updates: [ListViewUpdateItem] +} + +private struct GroupsInCommonListEntry: Comparable, Identifiable { + var index: Int + var peer: Peer + + var stableId: PeerId { + return self.peer.id + } + + static func ==(lhs: GroupsInCommonListEntry, rhs: GroupsInCommonListEntry) -> Bool { + return lhs.peer.isEqual(rhs.peer) + } + + static func <(lhs: GroupsInCommonListEntry, rhs: GroupsInCommonListEntry) -> Bool { + return lhs.index < rhs.index + } + + func item(context: AccountContext, presentationData: PresentationData, openPeer: @escaping (Peer) -> Void) -> ListViewItem { + let peer = self.peer + return ItemListPeerItem(presentationData: ItemListPresentationData(presentationData), dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, context: context, peer: self.peer, presence: nil, text: .none, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), switchValue: nil, enabled: true, selectable: true, sectionId: 0, action: { + openPeer(peer) + }, setPeerIdWithRevealedOptions: { _, _ in + }, removePeer: { _ in + }, contextAction: { node, gesture in + //arguments.contextAction(peer, node, gesture) + }, hasTopStripe: false, noInsets: true) + } +} + +private func preparedTransition(from fromEntries: [GroupsInCommonListEntry], to toEntries: [GroupsInCommonListEntry], context: AccountContext, presentationData: PresentationData, openPeer: @escaping (Peer) -> Void) -> GroupsInCommonListTransaction { + let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries) + + let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) } + let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, openPeer: openPeer), directionHint: nil) } + let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, openPeer: openPeer), directionHint: nil) } + + return GroupsInCommonListTransaction(deletions: deletions, insertions: insertions, updates: updates) +} + +final class PeerInfoGroupsInCommonPaneNode: ASDisplayNode, PeerInfoPaneNode { + private let context: AccountContext + private let peerId: PeerId + private let paneInteraction: PeerInfoPaneInteraction + + private let listNode: ListView + private var peers: [Peer] = [] + private var currentEntries: [GroupsInCommonListEntry] = [] + private var enqueuedTransactions: [GroupsInCommonListTransaction] = [] + + private var currentParams: (size: CGSize, isScrollingLockedAtTop: Bool, presentationData: PresentationData)? + + private let ready = Promise() + private var didSetReady: Bool = false + var isReady: Signal { + return self.ready.get() + } + + init(context: AccountContext, peerId: PeerId, interaction: PeerInfoPaneInteraction, peers: [Peer]) { + self.context = context + self.peerId = peerId + self.paneInteraction = interaction + + self.listNode = ListView() + + super.init() + + self.listNode.preloadPages = true + self.addSubnode(self.listNode) + + self.peers = peers + } + + deinit { + } + + func scrollToTop() -> Bool { + if !self.listNode.scrollToOffsetFromTop(0.0) { + self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: .Spring(duration: 0.4), directionHint: .Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in }) + return true + } else { + return false + } + } + + func update(size: CGSize, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) { + let isFirstLayout = self.currentParams == nil + self.currentParams = (size, isScrollingLockedAtTop, presentationData) + + transition.updateFrame(node: self.listNode, frame: CGRect(origin: CGPoint(), size: size)) + let (duration, curve) = listViewAnimationDurationAndCurve(transition: transition) + + self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: nil, updateSizeAndInsets: ListViewUpdateSizeAndInsets(size: size, insets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0), headerInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0), scrollIndicatorInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0), duration: duration, curve: curve), stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in }) + + self.listNode.scrollEnabled = !isScrollingLockedAtTop + + if isFirstLayout { + self.updatePeers(peers: self.peers, presentationData: presentationData) + } + } + + private func updatePeers(peers: [Peer], presentationData: PresentationData) { + var entries: [GroupsInCommonListEntry] = [] + for peer in peers { + entries.append(GroupsInCommonListEntry(index: entries.count, peer: peer)) + } + let transaction = preparedTransition(from: self.currentEntries, to: entries, context: self.context, presentationData: presentationData, openPeer: { [weak self] peer in + self?.paneInteraction.openPeer(peer) + }) + self.currentEntries = entries + self.enqueuedTransactions.append(transaction) + self.dequeueTransaction() + } + + private func dequeueTransaction() { + guard let (layout, _, _) = self.currentParams, let transaction = self.enqueuedTransactions.first else { + return + } + + self.enqueuedTransactions.remove(at: 0) + + var options = ListViewDeleteAndInsertOptions() + options.insert(.Synchronous) + + self.listNode.transaction(deleteIndices: transaction.deletions, insertIndicesAndItems: transaction.insertions, updateIndicesAndItems: transaction.updates, options: options, updateSizeAndInsets: nil, updateOpaqueState: nil, completion: { [weak self] _ in + guard let strongSelf = self else { + return + } + if !strongSelf.didSetReady { + strongSelf.didSetReady = true + strongSelf.ready.set(.single(true)) + } + }) + } + + func findLoadedMessage(id: MessageId) -> Message? { + return nil + } + + func transitionNodeForGallery(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + return nil + } + + func updateSelectedMessages(animated: Bool) { + } +} diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoScreen.swift b/submodules/TelegramUI/TelegramUI/PeerInfoScreen.swift index 06811f13db..fe64232ab7 100644 --- a/submodules/TelegramUI/TelegramUI/PeerInfoScreen.swift +++ b/submodules/TelegramUI/TelegramUI/PeerInfoScreen.swift @@ -20,8 +20,10 @@ import OverlayStatusController import ShareController import PhotoResources import PeerAvatarGalleryUI - -private let avatarFont = avatarPlaceholderFont(size: 28.0) +import TelegramIntents +import PeerInfoUI +import SearchBarNode +import SearchUI private enum PeerInfoHeaderButtonKey: Hashable { case message @@ -196,16 +198,21 @@ private final class PeerInfoAvatarListItemNode: ASDisplayNode { } func update(size: CGSize, transition: ContainedViewLayoutTransition) { + let imageSize = CGSize(width: min(size.width, size.height), height: min(size.width, size.height)) let makeLayout = self.imageNode.asyncLayout() - let applyLayout = makeLayout(TransformImageArguments(corners: ImageCorners(), imageSize: size, boundingSize: size, intrinsicInsets: UIEdgeInsets())) + let applyLayout = makeLayout(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets())) let _ = applyLayout() - transition.updateFrame(node: self.imageNode, frame: CGRect(origin: CGPoint(), size: size)) + transition.updateFrame(node: self.imageNode, frame: CGRect(origin: CGPoint(x: floor((size.width - imageSize.width) / 2.0), y: floor((size.height - imageSize.height) / 2.0)), size: imageSize)) } } private final class PeerInfoAvatarListContainerNode: ASDisplayNode { private let context: AccountContext + let controlsContainerNode: ASDisplayNode + let controlsContainerTransformNode: ASDisplayNode + let shadowNode: ASDisplayNode + let contentNode: ASDisplayNode private var items: [PeerInfoAvatarListItem] = [] private var itemNodes: [WrappedMediaResourceId: PeerInfoAvatarListItemNode] = [:] @@ -225,12 +232,25 @@ private final class PeerInfoAvatarListContainerNode: ASDisplayNode { self.contentNode = ASDisplayNode() + self.controlsContainerNode = ASDisplayNode() + self.controlsContainerNode.isUserInteractionEnabled = false + + self.controlsContainerTransformNode = ASDisplayNode() + self.controlsContainerTransformNode.isUserInteractionEnabled = false + + self.shadowNode = ASDisplayNode() + //self.shadowNode.backgroundColor = .green + super.init() self.backgroundColor = .black self.addSubnode(self.contentNode) + self.controlsContainerNode.addSubnode(self.shadowNode) + self.controlsContainerTransformNode.addSubnode(self.controlsContainerNode) + self.addSubnode(self.controlsContainerTransformNode) + self.view.disablesInteractiveTransitionGestureRecognizer = true self.view.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:)))) } @@ -381,6 +401,7 @@ private final class PeerInfoAvatarTransformContainerNode: ASDisplayNode { init(context: AccountContext) { self.context = context + let avatarFont = avatarPlaceholderFont(size: floor(100.0 * 16.0 / 37.0)) self.avatarNode = AvatarNode(font: avatarFont) super.init() @@ -405,6 +426,38 @@ private final class PeerInfoAvatarTransformContainerNode: ASDisplayNode { } } +private final class PeerInfoEditingAvatarNode: ASDisplayNode { + let context: AccountContext + let avatarNode: AvatarNode + + var tapped: (() -> Void)? + + init(context: AccountContext) { + self.context = context + let avatarFont = avatarPlaceholderFont(size: floor(100.0 * 16.0 / 37.0)) + self.avatarNode = AvatarNode(font: avatarFont) + + super.init() + + self.addSubnode(self.avatarNode) + self.avatarNode.frame = CGRect(origin: CGPoint(x: -50.0, y: -50.0), size: CGSize(width: 100.0, height: 100.0)) + + self.avatarNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) + } + + @objc private func tapGesture(_ recognizer: UITapGestureRecognizer) { + if case .ended = recognizer.state { + self.tapped?() + } + } + + func update(peer: Peer?, theme: PresentationTheme) { + if let peer = peer { + self.avatarNode.setPeer(context: self.context, theme: theme, peer: peer, synchronousLoad: false, displayDimensions: CGSize(width: 100.0, height: 100.0)) + } + } +} + private final class PeerInfoAvatarListNode: ASDisplayNode { let avatarContainerNode: PeerInfoAvatarTransformContainerNode let listContainerTransformNode: ASDisplayNode @@ -472,6 +525,379 @@ private final class PeerInfoAvatarListNode: ASDisplayNode { } } +private final class PeerInfoHeaderNavigationButton: HighlightableButtonNode { + private let regularTextNode: ImmediateTextNode + private let whiteTextNode: ImmediateTextNode + private let iconNode: ASImageNode + + private var key: PeerInfoHeaderNavigationButtonKey? + private var theme: PresentationTheme? + + var isWhite: Bool = false { + didSet { + if self.isWhite != oldValue { + self.regularTextNode.isHidden = self.isWhite + self.whiteTextNode.isHidden = !self.isWhite + } + } + } + + var action: (() -> Void)? + + override init() { + self.regularTextNode = ImmediateTextNode() + self.whiteTextNode = ImmediateTextNode() + self.whiteTextNode.isHidden = true + + self.iconNode = ASImageNode() + self.iconNode.displaysAsynchronously = false + self.iconNode.displayWithoutProcessing = true + + super.init() + + self.addSubnode(self.regularTextNode) + self.addSubnode(self.whiteTextNode) + self.addSubnode(self.iconNode) + + self.addTarget(self, action: #selector(self.pressed), forControlEvents: .touchUpInside) + } + + @objc private func pressed() { + self.action?() + } + + func update(key: PeerInfoHeaderNavigationButtonKey, presentationData: PresentationData) -> CGSize { + let textSize: CGSize + if self.key != key || self.theme !== presentationData.theme { + self.key = key + self.theme = presentationData.theme + + let text: String + var icon: UIImage? + var isBold = false + switch key { + case .edit: + text = presentationData.strings.Common_Edit + case .done, .cancel, .selectionDone: + text = presentationData.strings.Common_Done + isBold = true + case .select: + text = presentationData.strings.Common_Select + case .search: + text = "" + icon = PresentationResourcesRootController.navigationCompactSearchIcon(presentationData.theme) + } + + let font: UIFont = isBold ? Font.semibold(17.0) : Font.regular(17.0) + + self.regularTextNode.attributedText = NSAttributedString(string: text, font: font, textColor: presentationData.theme.rootController.navigationBar.accentTextColor) + self.whiteTextNode.attributedText = NSAttributedString(string: text, font: font, textColor: .white) + self.iconNode.image = icon + + textSize = self.regularTextNode.updateLayout(CGSize(width: 200.0, height: .greatestFiniteMagnitude)) + let _ = self.whiteTextNode.updateLayout(CGSize(width: 200.0, height: .greatestFiniteMagnitude)) + } else { + textSize = self.regularTextNode.bounds.size + } + + let inset: CGFloat = 0.0 + let height: CGFloat = 44.0 + + let textFrame = CGRect(origin: CGPoint(x: inset, y: floor((height - textSize.height) / 2.0)), size: textSize) + self.regularTextNode.frame = textFrame + self.whiteTextNode.frame = textFrame + + if let image = self.iconNode.image { + self.iconNode.frame = CGRect(origin: CGPoint(x: inset, y: floor((height - image.size.height) / 2.0)), size: image.size) + + return CGSize(width: image.size.width + inset * 2.0, height: height) + } else { + return CGSize(width: textSize.width + inset * 2.0, height: height) + } + } +} + +private enum PeerInfoHeaderNavigationButtonKey { + case edit + case done + case cancel + case select + case selectionDone + case search +} + +private struct PeerInfoHeaderNavigationButtonSpec: Equatable { + let key: PeerInfoHeaderNavigationButtonKey + let isForExpandedView: Bool +} + +private final class PeerInfoHeaderNavigationButtonContainerNode: ASDisplayNode { + private var buttonNodes: [PeerInfoHeaderNavigationButtonKey: PeerInfoHeaderNavigationButton] = [:] + + private var currentButtons: [PeerInfoHeaderNavigationButtonSpec] = [] + + var isWhite: Bool = false { + didSet { + if self.isWhite != oldValue { + for (_, buttonNode) in self.buttonNodes { + buttonNode.isWhite = self.isWhite + } + } + } + } + + var performAction: ((PeerInfoHeaderNavigationButtonKey) -> Void)? + + override init() { + super.init() + } + + func update(size: CGSize, presentationData: PresentationData, buttons: [PeerInfoHeaderNavigationButtonSpec], expandFraction: CGFloat, transition: ContainedViewLayoutTransition) { + let maximumExpandOffset: CGFloat = 14.0 + let expandOffset: CGFloat = -expandFraction * maximumExpandOffset + if self.currentButtons != buttons { + self.currentButtons = buttons + + var nextRegularButtonOrigin = size.width - 16.0 + var nextExpandedButtonOrigin = size.width - 16.0 + for spec in buttons.reversed() { + let buttonNode: PeerInfoHeaderNavigationButton + var wasAdded = false + if let current = self.buttonNodes[spec.key] { + buttonNode = current + } else { + wasAdded = true + buttonNode = PeerInfoHeaderNavigationButton() + self.buttonNodes[spec.key] = buttonNode + self.addSubnode(buttonNode) + buttonNode.isWhite = self.isWhite + buttonNode.action = { [weak self] in + self?.performAction?(spec.key) + } + } + let buttonSize = buttonNode.update(key: spec.key, presentationData: presentationData) + var nextButtonOrigin = spec.isForExpandedView ? nextExpandedButtonOrigin : nextRegularButtonOrigin + let buttonFrame = CGRect(origin: CGPoint(x: nextButtonOrigin - buttonSize.width, y: expandOffset + (spec.isForExpandedView ? maximumExpandOffset : 0.0)), size: buttonSize) + nextButtonOrigin -= buttonSize.width + 4.0 + if spec.isForExpandedView { + nextExpandedButtonOrigin = nextButtonOrigin + } else { + nextRegularButtonOrigin = nextButtonOrigin + } + if wasAdded { + buttonNode.frame = buttonFrame + } else { + transition.updateFrameAdditiveToCenter(node: buttonNode, frame: buttonFrame) + } + let alphaFactor: CGFloat = spec.isForExpandedView ? expandFraction : (1.0 - expandFraction) + transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor) + } + var removeKeys: [PeerInfoHeaderNavigationButtonKey] = [] + for (key, _) in self.buttonNodes { + if !buttons.contains(where: { $0.key == key }) { + removeKeys.append(key) + } + } + for key in removeKeys { + if let buttonNode = self.buttonNodes.removeValue(forKey: key) { + buttonNode.removeFromSupernode() + } + } + } else { + var nextRegularButtonOrigin = size.width - 16.0 + var nextExpandedButtonOrigin = size.width - 16.0 + for spec in buttons.reversed() { + if let buttonNode = self.buttonNodes[spec.key] { + let buttonSize = buttonNode.bounds.size + var nextButtonOrigin = spec.isForExpandedView ? nextExpandedButtonOrigin : nextRegularButtonOrigin + let buttonFrame = CGRect(origin: CGPoint(x: nextButtonOrigin - buttonSize.width, y: expandOffset + (spec.isForExpandedView ? maximumExpandOffset : 0.0)), size: buttonSize) + nextButtonOrigin -= buttonSize.width + 4.0 + if spec.isForExpandedView { + nextExpandedButtonOrigin = nextButtonOrigin + } else { + nextRegularButtonOrigin = nextButtonOrigin + } + transition.updateFrameAdditiveToCenter(node: buttonNode, frame: buttonFrame) + let alphaFactor: CGFloat = spec.isForExpandedView ? expandFraction : (1.0 - expandFraction) + transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor) + } + } + } + } +} + +private final class PeerInfoHeaderRegularContentNode: ASDisplayNode { + +} + +private enum PeerInfoHeaderTextFieldNodeKey { + case firstName + case lastName + case title + case description +} + +private protocol PeerInfoHeaderTextFieldNode: ASDisplayNode { + var text: String { get } + + func update(width: CGFloat, safeInset: CGFloat, hasPrevious: Bool, placeholder: String, isEnabled: Bool, presentationData: PresentationData, updateText: String?) -> CGFloat +} + +private final class PeerInfoHeaderSingleLineTextFieldNode: ASDisplayNode, PeerInfoHeaderTextFieldNode { + private let textNode: TextFieldNode + private let topSeparator: ASDisplayNode + + private var theme: PresentationTheme? + + var text: String { + return self.textNode.textField.text ?? "" + } + + override init() { + self.textNode = TextFieldNode() + self.topSeparator = ASDisplayNode() + + super.init() + + self.addSubnode(self.textNode) + self.addSubnode(self.topSeparator) + } + + func update(width: CGFloat, safeInset: CGFloat, hasPrevious: Bool, placeholder: String, isEnabled: Bool, presentationData: PresentationData, updateText: String?) -> CGFloat { + if self.theme !== presentationData.theme { + self.theme = presentationData.theme + self.textNode.textField.textColor = presentationData.theme.list.itemPrimaryTextColor + //self.textNode.textField.keyboardAppearance = presentationData.theme.keyboardAppearance + self.textNode.textField.tintColor = presentationData.theme.list.itemAccentColor + } + + let attributedPlaceholderText = NSAttributedString(string: placeholder, font: Font.regular(17.0), textColor: presentationData.theme.list.itemPlaceholderTextColor) + if self.textNode.textField.attributedPlaceholder == nil || !self.textNode.textField.attributedPlaceholder!.isEqual(to: attributedPlaceholderText) { + self.textNode.textField.attributedPlaceholder = attributedPlaceholderText + self.textNode.textField.accessibilityHint = attributedPlaceholderText.string + } + + if let updateText = updateText { + self.textNode.textField.text = updateText + } + + self.topSeparator.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor + self.topSeparator.frame = CGRect(origin: CGPoint(x: safeInset + (hasPrevious ? 16.0 : 0.0), y: 0.0), size: CGSize(width: width, height: UIScreenPixel)) + + let height: CGFloat = 44.0 + + self.textNode.frame = CGRect(origin: CGPoint(x: safeInset + 16.0, y: floor((height - 40.0) / 2.0)), size: CGSize(width: max(1.0, width - 16.0 * 2.0), height: 40.0)) + + self.textNode.isUserInteractionEnabled = isEnabled + self.textNode.alpha = isEnabled ? 1.0 : 0.6 + + return height + } +} + +/*private final class PeerInfoHeaderMultiLineTextFieldNode: ASDisplayNode, PeerInfoHeaderTextFieldNode { + private let textNode: TextFieldNode + private let topSeparator: ASDisplayNode + + override init() { + self.textNode = TextFieldNode() + self.topSeparator = ASDisplayNode() + + super.init() + } + + func update(width: CGFloat, safeInset: CGFloat) -> CGFloat { + return 44.0 + } +}*/ + +private final class PeerInfoHeaderEditingContentNode: ASDisplayNode { + private let context: AccountContext + let avatarNode: PeerInfoEditingAvatarNode + + var itemNodes: [PeerInfoHeaderTextFieldNodeKey: PeerInfoHeaderTextFieldNode] = [:] + + init(context: AccountContext) { + self.context = context + self.avatarNode = PeerInfoEditingAvatarNode(context: context) + + super.init() + + self.addSubnode(self.avatarNode) + } + + func editingTextForKey(_ key: PeerInfoHeaderTextFieldNodeKey) -> String? { + return self.itemNodes[key]?.text + } + + func update(width: CGFloat, safeInset: CGFloat, statusBarHeight: CGFloat, navigationHeight: CGFloat, peer: Peer?, isContact: Bool, presentationData: PresentationData, transition: ContainedViewLayoutTransition) -> CGFloat { + let avatarSize: CGFloat = 100.0 + let avatarFrame = CGRect(origin: CGPoint(x: floor((width - avatarSize) / 2.0), y: statusBarHeight + 10.0), size: CGSize(width: avatarSize, height: avatarSize)) + transition.updateFrameAdditiveToCenter(node: self.avatarNode, frame: CGRect(origin: avatarFrame.center, size: CGSize())) + + var contentHeight: CGFloat = statusBarHeight + 10.0 + 100.0 + 20.0 + + var fieldKeys: [PeerInfoHeaderTextFieldNodeKey] = [] + if let _ = peer as? TelegramUser { + fieldKeys.append(.firstName) + fieldKeys.append(.lastName) + } + var hasPrevious = false + for key in fieldKeys { + let itemNode: PeerInfoHeaderTextFieldNode + var updateText: String? + if let current = self.itemNodes[key] { + itemNode = current + } else { + switch key { + case .firstName: + updateText = (peer as? TelegramUser)?.firstName ?? "" + case .lastName: + updateText = (peer as? TelegramUser)?.lastName ?? "" + case .title: + updateText = (peer as? TelegramUser)?.debugDisplayTitle ?? "" + case .description: + break + } + itemNode = PeerInfoHeaderSingleLineTextFieldNode() + self.itemNodes[key] = itemNode + self.addSubnode(itemNode) + } + let placeholder: String + var isEnabled = true + switch key { + case .firstName: + placeholder = "First Name" + isEnabled = isContact + case .lastName: + placeholder = "Last Name" + isEnabled = isContact + case .title: + placeholder = "Title" + case .description: + placeholder = "Description" + } + let itemHeight = itemNode.update(width: width, safeInset: safeInset, hasPrevious: hasPrevious, placeholder: placeholder, isEnabled: isEnabled, presentationData: presentationData, updateText: updateText) + transition.updateFrame(node: itemNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: width, height: itemHeight))) + contentHeight += itemHeight + hasPrevious = true + } + var removeKeys: [PeerInfoHeaderTextFieldNodeKey] = [] + for (key, _) in self.itemNodes { + if !fieldKeys.contains(key) { + removeKeys.append(key) + } + } + for key in removeKeys { + if let itemNode = self.itemNodes.removeValue(forKey: key) { + itemNode.removeFromSupernode() + } + } + + return contentHeight + } +} + private final class PeerInfoHeaderNode: ASDisplayNode { private var context: AccountContext private var presentationData: PresentationData? @@ -479,6 +905,9 @@ private final class PeerInfoHeaderNode: ASDisplayNode { private(set) var isAvatarExpanded: Bool private let avatarListNode: PeerInfoAvatarListNode + + let regularContentNode: PeerInfoHeaderRegularContentNode + let editingContentNode: PeerInfoHeaderEditingContentNode let titleNodeContainer: ASDisplayNode let titleNodeRawContainer: ASDisplayNode let titleNode: ImmediateTextNode @@ -487,7 +916,9 @@ private final class PeerInfoHeaderNode: ASDisplayNode { let subtitleNode: ImmediateTextNode private var buttonNodes: [PeerInfoHeaderButtonKey: PeerInfoHeaderButtonNode] = [:] private let backgroundNode: ASDisplayNode + private let expandedBackgroundNode: ASDisplayNode let separatorNode: ASDisplayNode + let navigationButtonContainer: PeerInfoHeaderNavigationButtonContainerNode var performButtonAction: ((PeerInfoHeaderButtonKey) -> Void)? var requestAvatarExpansion: (() -> Void)? @@ -510,8 +941,16 @@ private final class PeerInfoHeaderNode: ASDisplayNode { self.subtitleNode = ImmediateTextNode() self.subtitleNode.displaysAsynchronously = false + self.regularContentNode = PeerInfoHeaderRegularContentNode() + self.editingContentNode = PeerInfoHeaderEditingContentNode(context: context) + self.editingContentNode.alpha = 0.0 + + self.navigationButtonContainer = PeerInfoHeaderNavigationButtonContainerNode() + self.backgroundNode = ASDisplayNode() self.backgroundNode.isLayerBacked = true + self.expandedBackgroundNode = ASDisplayNode() + self.expandedBackgroundNode.isLayerBacked = true self.separatorNode = ASDisplayNode() self.separatorNode.isLayerBacked = true @@ -519,12 +958,16 @@ private final class PeerInfoHeaderNode: ASDisplayNode { super.init() self.addSubnode(self.backgroundNode) + self.addSubnode(self.expandedBackgroundNode) self.addSubnode(self.separatorNode) - self.addSubnode(self.avatarListNode) self.titleNodeContainer.addSubnode(self.titleNode) - self.addSubnode(self.titleNodeContainer) + self.regularContentNode.addSubnode(self.titleNodeContainer) self.subtitleNodeContainer.addSubnode(self.subtitleNode) - self.addSubnode(self.subtitleNodeContainer) + self.regularContentNode.addSubnode(self.subtitleNodeContainer) + self.regularContentNode.addSubnode(self.avatarListNode) + self.addSubnode(self.regularContentNode) + self.addSubnode(self.editingContentNode) + self.addSubnode(self.navigationButtonContainer) self.avatarListNode.avatarContainerNode.tapped = { [weak self] in guard let strongSelf = self else { @@ -536,14 +979,24 @@ private final class PeerInfoHeaderNode: ASDisplayNode { } } - func update(width: CGFloat, statusBarHeight: CGFloat, navigationHeight: CGFloat, contentOffset: CGFloat, presentationData: PresentationData, peer: Peer?, cachedData: CachedPeerData?, notificationSettings: TelegramPeerNotificationSettings?, presence: TelegramUserPresence?, transition: ContainedViewLayoutTransition, additive: Bool) -> CGFloat { + func update(width: CGFloat, containerHeight: CGFloat, containerInset: CGFloat, statusBarHeight: CGFloat, navigationHeight: CGFloat, contentOffset: CGFloat, presentationData: PresentationData, peer: Peer?, cachedData: CachedPeerData?, notificationSettings: TelegramPeerNotificationSettings?, presence: TelegramUserPresence?, isContact: Bool, state: PeerInfoState, transition: ContainedViewLayoutTransition, additive: Bool) -> CGFloat { self.presentationData = presentationData + self.regularContentNode.alpha = state.isEditing ? 0.0 : 1.0 + self.editingContentNode.alpha = state.isEditing ? 1.0 : 0.0 + + let editingContentHeight = self.editingContentNode.update(width: width, safeInset: containerInset, statusBarHeight: statusBarHeight, navigationHeight: navigationHeight, peer: state.isEditing ? peer : nil, isContact: isContact, presentationData: presentationData, transition: transition) + transition.updateFrame(node: self.editingContentNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -contentOffset), size: CGSize(width: width, height: editingContentHeight))) + var transitionSourceHeight: CGFloat = 0.0 var transitionFraction: CGFloat = 0.0 var transitionSourceAvatarFrame = CGRect() var transitionSourceTitleFrame = CGRect() var transitionSourceSubtitleFrame = CGRect() + + self.backgroundNode.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor + self.expandedBackgroundNode.backgroundColor = presentationData.theme.rootController.navigationBar.backgroundColor + if let navigationTransition = self.navigationTransition, let sourceAvatarNode = navigationTransition.sourceTitleView.avatarNode?.avatarNode { transitionSourceHeight = navigationTransition.sourceNavigationBar.bounds.height transitionFraction = navigationTransition.fraction @@ -551,18 +1004,20 @@ private final class PeerInfoHeaderNode: ASDisplayNode { transitionSourceTitleFrame = navigationTransition.sourceTitleFrame transitionSourceSubtitleFrame = navigationTransition.sourceSubtitleFrame - transition.updateBackgroundColor(node: self.backgroundNode, color: presentationData.theme.list.itemBlocksBackgroundColor.interpolateTo(presentationData.theme.rootController.navigationBar.backgroundColor, fraction: transitionFraction)!) + //transition.updateBackgroundColor(node: self.backgroundNode, color: presentationData.theme.list.itemBlocksBackgroundColor.interpolateTo(presentationData.theme.rootController.navigationBar.backgroundColor, fraction: transitionFraction)!) + transition.updateAlpha(node: self.expandedBackgroundNode, alpha: transitionFraction) } else { - self.backgroundNode.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor - let backgroundTransitionFraction: CGFloat = max(0.0, min(1.0, contentOffset / (212.0))) - transition.updateBackgroundColor(node: self.backgroundNode, color: presentationData.theme.list.itemBlocksBackgroundColor.interpolateTo(presentationData.theme.rootController.navigationBar.backgroundColor, fraction: backgroundTransitionFraction)!) + transition.updateAlpha(node: self.expandedBackgroundNode, alpha: backgroundTransitionFraction) + //transition.updateBackgroundColor(node: self.backgroundNode, color: presentationData.theme.list.itemBlocksBackgroundColor.interpolateTo(presentationData.theme.rootController.navigationBar.backgroundColor, fraction: backgroundTransitionFraction)!) } self.separatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor let defaultButtonSize: CGFloat = 40.0 let defaultMaxButtonSpacing: CGFloat = 40.0 + let expandedAvatarListHeight = min(width, containerHeight - 64.0) + let expandedAvatarListSize = CGSize(width: width, height: expandedAvatarListHeight) var buttonKeys: [PeerInfoHeaderButtonKey] = [] @@ -572,7 +1027,7 @@ private final class PeerInfoHeaderNode: ASDisplayNode { buttonKeys.append(.mute) buttonKeys.append(.more) - self.titleNode.attributedText = NSAttributedString(string: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), font: Font.semibold(24.0), textColor: presentationData.theme.list.itemPrimaryTextColor) + self.titleNode.attributedText = NSAttributedString(string: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), font: Font.medium(24.0), textColor: presentationData.theme.list.itemPrimaryTextColor) let presence = presence ?? TelegramUserPresence(status: .none, lastActivity: 0) let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 @@ -588,7 +1043,7 @@ private final class PeerInfoHeaderNode: ASDisplayNode { let textSideInset: CGFloat = 16.0 let expandedAvatarControlsHeight: CGFloat = 64.0 - let expandedAvatarHeight: CGFloat = width + expandedAvatarControlsHeight + let expandedAvatarHeight: CGFloat = expandedAvatarListSize.height + expandedAvatarControlsHeight let avatarSize: CGFloat = 100.0 let avatarFrame = CGRect(origin: CGPoint(x: floor((width - avatarSize) / 2.0), y: statusBarHeight + 10.0), size: CGSize(width: avatarSize, height: avatarSize)) @@ -628,7 +1083,7 @@ private final class PeerInfoHeaderNode: ASDisplayNode { avatarScale = 1.0 * (1.0 - titleCollapseFraction) + avatarMinScale * titleCollapseFraction avatarOffset = apparentTitleLockOffset + 0.0 * (1.0 - titleCollapseFraction) + 10.0 * titleCollapseFraction } - let avatarListFrame = CGRect(origin: CGPoint(), size: CGSize(width: width, height: width)) + let avatarListFrame = CGRect(origin: CGPoint(), size: expandedAvatarListSize) if self.isAvatarExpanded { self.avatarListNode.listContainerNode.isHidden = false @@ -647,6 +1102,7 @@ private final class PeerInfoHeaderNode: ASDisplayNode { } self.avatarListNode.update(size: CGSize(), isExpanded: self.isAvatarExpanded, peer: peer, theme: presentationData.theme, transition: transition) + self.editingContentNode.avatarNode.update(peer: peer, theme: presentationData.theme) if additive { transition.updateSublayerTransformScaleAdditive(node: self.avatarListNode.avatarContainerNode, scale: avatarScale) } else { @@ -654,12 +1110,12 @@ private final class PeerInfoHeaderNode: ASDisplayNode { } let apparentAvatarFrame: CGRect if self.isAvatarExpanded { - let expandedAvatarCenter = CGPoint(x: width / 2.0, y: width / 2.0 - contentOffset / 2.0) + let expandedAvatarCenter = CGPoint(x: expandedAvatarListSize.width / 2.0, y: expandedAvatarListSize.height / 2.0 - contentOffset / 2.0) apparentAvatarFrame = CGRect(origin: CGPoint(x: expandedAvatarCenter.x * (1.0 - transitionFraction) + transitionFraction * avatarCenter.x, y: expandedAvatarCenter.y * (1.0 - transitionFraction) + transitionFraction * avatarCenter.y), size: CGSize()) } else { apparentAvatarFrame = CGRect(origin: CGPoint(x: avatarCenter.x - avatarFrame.width / 2.0, y: -contentOffset + avatarOffset + avatarCenter.y - avatarFrame.height / 2.0), size: avatarFrame.size) } - if case let .animated(duration, curve) = transition, !transitionSourceAvatarFrame.width.isZero { + if case let .animated(duration, curve) = transition, !transitionSourceAvatarFrame.width.isZero, false { let previousFrame = self.avatarListNode.frame self.avatarListNode.frame = CGRect(origin: apparentAvatarFrame.center, size: CGSize()) let horizontalTransition: ContainedViewLayoutTransition @@ -681,22 +1137,28 @@ private final class PeerInfoHeaderNode: ASDisplayNode { let avatarListContainerScale: CGFloat if self.isAvatarExpanded { if !transitionSourceAvatarFrame.width.isZero { - let neutralAvatarListContainerSize = CGSize(width: width, height: width) + let neutralAvatarListContainerSize = expandedAvatarListSize let avatarListContainerSize = CGSize(width: neutralAvatarListContainerSize.width * (1.0 - transitionFraction) + transitionSourceAvatarFrame.width * transitionFraction, height: neutralAvatarListContainerSize.height * (1.0 - transitionFraction) + transitionSourceAvatarFrame.height * transitionFraction) avatarListContainerFrame = CGRect(origin: CGPoint(x: -avatarListContainerSize.width / 2.0, y: -avatarListContainerSize.height / 2.0), size: avatarListContainerSize) } else { - avatarListContainerFrame = CGRect(origin: CGPoint(x: -width / 2.0, y: -width / 2.0), size: CGSize(width: width, height: width)) + avatarListContainerFrame = CGRect(origin: CGPoint(x: -expandedAvatarListSize.width / 2.0, y: -expandedAvatarListSize.height / 2.0), size: expandedAvatarListSize) } - avatarListContainerScale = 1.0 + max(0.0, -contentOffset / avatarListContainerFrame.width) + avatarListContainerScale = 1.0 + max(0.0, -contentOffset / avatarListContainerFrame.height) } else { avatarListContainerFrame = CGRect(origin: CGPoint(x: -apparentAvatarFrame.width / 2.0, y: -apparentAvatarFrame.height / 2.0), size: apparentAvatarFrame.size) avatarListContainerScale = avatarScale } transition.updateFrame(node: self.avatarListNode.listContainerNode, frame: avatarListContainerFrame) - let innerScale = avatarListContainerFrame.width / width - let innerDelta = (avatarListContainerFrame.width - width) / 2.0 + let innerScale = avatarListContainerFrame.height / expandedAvatarListSize.height + let innerDeltaX = (avatarListContainerFrame.width - expandedAvatarListSize.width) / 2.0 + let innerDeltaY = (avatarListContainerFrame.height - expandedAvatarListSize.height) / 2.0 transition.updateSublayerTransformScale(node: self.avatarListNode.listContainerNode, scale: innerScale) - transition.updateFrameAdditive(node: self.avatarListNode.listContainerNode.contentNode, frame: CGRect(origin: CGPoint(x: innerDelta + width / 2.0, y: innerDelta + width / 2.0), size: CGSize())) + transition.updateFrameAdditive(node: self.avatarListNode.listContainerNode.contentNode, frame: CGRect(origin: CGPoint(x: innerDeltaX + expandedAvatarListSize.width / 2.0, y: innerDeltaY + expandedAvatarListSize.height / 2.0), size: CGSize())) + + transition.updateFrameAdditive(node: self.avatarListNode.listContainerNode.controlsContainerTransformNode, frame: CGRect(origin: CGPoint(x: expandedAvatarListSize.width / 2.0, y: expandedAvatarListSize.height / 2.0 - innerDeltaY), size: CGSize())) + transition.updateSublayerTransformScale(node: self.avatarListNode.listContainerNode.controlsContainerNode, scale: 1.0 / innerScale) + transition.updateSublayerTransformScaleAdditive(node: self.avatarListNode.listContainerNode.controlsContainerTransformNode, scale: 1.0 / avatarListContainerScale) + transition.updateFrameAdditive(node: self.avatarListNode.listContainerNode.shadowNode, frame: CGRect(origin: CGPoint(x: -apparentAvatarFrame.minX, y: -apparentAvatarFrame.minY), size: CGSize(width: expandedAvatarListSize.width, height: navigationHeight))) if additive { transition.updateSublayerTransformScaleAdditive(node: self.avatarListNode.listContainerTransformNode, scale: avatarListContainerScale) @@ -704,7 +1166,7 @@ private final class PeerInfoHeaderNode: ASDisplayNode { transition.updateSublayerTransformScale(node: self.avatarListNode.listContainerTransformNode, scale: avatarListContainerScale) } - self.avatarListNode.listContainerNode.update(size: CGSize(width: width, height: width), peer: peer, transition: transition) + self.avatarListNode.listContainerNode.update(size: expandedAvatarListSize, peer: peer, transition: transition) let buttonsCollapseStart = titleCollapseOffset let buttonsCollapseEnd = 212.0 - (navigationHeight - statusBarHeight) + 10.0 @@ -837,7 +1299,7 @@ private final class PeerInfoHeaderNode: ASDisplayNode { self?.buttonPressed(buttonNode) }) self.buttonNodes[buttonKey] = buttonNode - self.addSubnode(buttonNode) + self.regularContentNode.addSubnode(buttonNode) } let buttonFrame = CGRect(origin: CGPoint(x: buttonRightOrigin.x - defaultButtonSize + buttonsScaledOffset, y: buttonRightOrigin.y), size: CGSize(width: defaultButtonSize, height: defaultButtonSize)) @@ -877,7 +1339,16 @@ private final class PeerInfoHeaderNode: ASDisplayNode { transition.updateSublayerTransformScaleAdditive(node: buttonNode, scale: buttonsScale) transition.updateAlpha(node: buttonNode, alpha: buttonsAlpha) - if self.isAvatarExpanded, case .mute = buttonKey { + + let hiddenWhileExpanded: Bool + switch buttonKey { + case .more: + hiddenWhileExpanded = false + default: + hiddenWhileExpanded = true + } + + if self.isAvatarExpanded, hiddenWhileExpanded { if case let .animated(duration, curve) = transition { ContainedViewLayoutTransition.animated(duration: duration * 0.3, curve: curve).updateAlpha(node: buttonNode.containerNode, alpha: 0.0) } else { @@ -906,21 +1377,40 @@ private final class PeerInfoHeaderNode: ASDisplayNode { } } - let backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: -2000.0 + apparentHeight), size: CGSize(width: width, height: 2000.0)) - let separatorFrame = CGRect(origin: CGPoint(x: 0.0, y: apparentHeight), size: CGSize(width: width, height: UIScreenPixel)) + let resolvedRegularHeight: CGFloat + if self.isAvatarExpanded { + resolvedRegularHeight = expandedAvatarListSize.height + expandedAvatarControlsHeight + } else { + resolvedRegularHeight = 212.0 + navigationHeight + } + + let backgroundFrame: CGRect + let separatorFrame: CGRect + + let resolvedHeight: CGFloat + if state.isEditing { + resolvedHeight = editingContentHeight + backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: -2000.0 + resolvedHeight - contentOffset), size: CGSize(width: width, height: 2000.0)) + separatorFrame = CGRect(origin: CGPoint(x: 0.0, y: resolvedHeight - contentOffset), size: CGSize(width: width, height: UIScreenPixel)) + } else { + resolvedHeight = resolvedRegularHeight + backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: -2000.0 + apparentHeight), size: CGSize(width: width, height: 2000.0)) + separatorFrame = CGRect(origin: CGPoint(x: 0.0, y: apparentHeight), size: CGSize(width: width, height: UIScreenPixel)) + } + + transition.updateFrame(node: self.regularContentNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: resolvedHeight))) + if additive { transition.updateFrameAdditive(node: self.backgroundNode, frame: backgroundFrame) + transition.updateFrameAdditive(node: self.expandedBackgroundNode, frame: backgroundFrame) transition.updateFrameAdditive(node: self.separatorNode, frame: separatorFrame) } else { transition.updateFrame(node: self.backgroundNode, frame: backgroundFrame) + transition.updateFrame(node: self.expandedBackgroundNode, frame: backgroundFrame) transition.updateFrame(node: self.separatorNode, frame: separatorFrame) } - if self.isAvatarExpanded { - return width + expandedAvatarControlsHeight - } else { - return 212.0 + navigationHeight - } + return resolvedHeight } private func buttonPressed(_ buttonNode: PeerInfoHeaderButtonNode) { @@ -928,13 +1418,16 @@ private final class PeerInfoHeaderNode: ASDisplayNode { } override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { - if !self.backgroundNode.frame.contains(point) { - return nil - } guard let result = super.hitTest(point, with: event) else { return nil } - if result == self.view { + if result.isDescendant(of: self.navigationButtonContainer.view) { + return result + } + if !self.backgroundNode.frame.contains(point) { + return nil + } + if result == self.view || result == self.regularContentNode.view || result == self.editingContentNode.view { return nil } return result @@ -952,6 +1445,22 @@ protocol PeerInfoPaneNode: ASDisplayNode { func scrollToTop() -> Bool func findLoadedMessage(id: MessageId) -> Message? func transitionNodeForGallery(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? + func updateSelectedMessages(animated: Bool) +} + +final class PeerInfoPaneInteraction { + var selectedMessageIds: Set? + + let toggleMessageSelected: (MessageId) -> Void + let openPeer: (Peer) -> Void + + init( + toggleMessageSelected: @escaping (MessageId) -> Void, + openPeer: @escaping (Peer) -> Void + ) { + self.toggleMessageSelected = toggleMessageSelected + self.openPeer = openPeer + } } private final class PeerInfoPaneWrapper { @@ -979,7 +1488,9 @@ private enum PeerInfoPaneKey { case media case files case links + case voice case music + case groupsInCommon } private final class PeerInfoPaneTabsContainerPaneNode: ASDisplayNode { @@ -1057,6 +1568,7 @@ private final class PeerInfoPaneTabsContainerNode: ASDisplayNode { super.init() + self.scrollNode.view.disablesInteractiveTransitionGestureRecognizer = true self.scrollNode.view.showsHorizontalScrollIndicator = false self.scrollNode.view.scrollsToTop = false if #available(iOS 11.0, *) { @@ -1183,15 +1695,24 @@ private final class PeerInfoPaneContainerNode: ASDisplayNode { let isReady = Promise() var didSetIsReady = false - private var currentParams: (size: CGSize, expansionFraction: CGFloat, presentationData: PresentationData)? - - private var availablePanes: [PeerInfoPaneKey] = [] - private var currentPaneKey: PeerInfoPaneKey? + private var currentParams: (size: CGSize, expansionFraction: CGFloat, presentationData: PresentationData, data: PeerInfoScreenData?)? + private(set) var currentPaneKey: PeerInfoPaneKey? private var currentPane: PeerInfoPaneWrapper? - private var candidatePane: (PeerInfoPaneWrapper, Disposable)? + private var currentCandidatePaneKey: PeerInfoPaneKey? + private var candidatePane: (PeerInfoPaneWrapper, Disposable, Bool)? + + var selectionPanelNode: PeerInfoSelectionPanelNode? + + var _paneInteraction: PeerInfoPaneInteraction? + var paneInteraction: PeerInfoPaneInteraction { + return self._paneInteraction! + } var openMessage: ((MessageId) -> Bool)? + var toggleMessageSelected: ((MessageId) -> Void)? + var openPeer: ((Peer) -> Void)? + var currentPaneUpdated: (() -> Void)? init(context: AccountContext, peerId: PeerId) { self.context = context @@ -1210,14 +1731,26 @@ private final class PeerInfoPaneContainerNode: ASDisplayNode { super.init() + self._paneInteraction = PeerInfoPaneInteraction( + toggleMessageSelected: { [weak self] id in + guard let strongSelf = self else { + return + } + strongSelf.toggleMessageSelected?(id) + }, + openPeer: { [weak self] peer in + guard let strongSelf = self else { + return + } + strongSelf.openPeer?(peer) + } + ) + self.addSubnode(self.separatorNode) self.addSubnode(self.coveringBackgroundNode) self.addSubnode(self.tabsContainerNode) self.addSubnode(self.tapsSeparatorNode) - self.availablePanes = [.media, .files, .links, .music] - self.currentPaneKey = .media - self.tabsContainerNode.requestSelectPane = { [weak self] key in guard let strongSelf = self else { return @@ -1225,75 +1758,14 @@ private final class PeerInfoPaneContainerNode: ASDisplayNode { if strongSelf.currentPaneKey == key { return } - - let paneNode: PeerInfoPaneNode - switch key { - case .media: - paneNode = PeerInfoVisualMediaPaneNode(context: strongSelf.context, openMessage: { id in - return self?.openMessage?(id) ?? false - }, peerId: strongSelf.peerId) - case .files: - paneNode = PeerInfoListPaneNode(context: strongSelf.context, openMessage: { id in - return self?.openMessage?(id) ?? false - }, peerId: strongSelf.peerId, tagMask: .file) - case .links: - paneNode = PeerInfoListPaneNode(context: strongSelf.context, openMessage: { id in - return self?.openMessage?(id) ?? false - }, peerId: strongSelf.peerId, tagMask: .webPage) - case .music: - paneNode = PeerInfoListPaneNode(context: strongSelf.context, openMessage: { id in - return self?.openMessage?(id) ?? false - }, peerId: strongSelf.peerId, tagMask: .music) + if strongSelf.currentCandidatePaneKey == key { + return } + strongSelf.currentCandidatePaneKey = key - if let (_, disposable) = strongSelf.candidatePane { - disposable.dispose() + if let (size, expansionFraction, presentationData, data) = strongSelf.currentParams { + strongSelf.update(size: size, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: .immediate) } - - let disposable = MetaDisposable() - strongSelf.candidatePane = (PeerInfoPaneWrapper(key: key, node: paneNode), disposable) - - if let (size, expansionFraction, presentationData) = strongSelf.currentParams { - strongSelf.update(size: size, expansionFraction: expansionFraction, presentationData: presentationData, transition: .immediate) - } - - disposable.set((paneNode.isReady - |> take(1) - |> deliverOnMainQueue).start(next: { _ in - guard let strongSelf = self else { - return - } - if let (candidatePane, _) = strongSelf.candidatePane { - let previousPane = strongSelf.currentPane - strongSelf.candidatePane = nil - strongSelf.currentPaneKey = candidatePane.key - strongSelf.currentPane = candidatePane - - if let (size, expansionFraction, presentationData) = strongSelf.currentParams { - strongSelf.update(size: size, expansionFraction: expansionFraction, presentationData: presentationData, transition: .animated(duration: 0.35, curve: .spring)) - - if let previousPane = previousPane { - let directionToRight: Bool - if let previousIndex = strongSelf.availablePanes.index(of: previousPane.key), let updatedIndex = strongSelf.availablePanes.index(of: candidatePane.key) { - directionToRight = previousIndex < updatedIndex - } else { - directionToRight = false - } - - let offset: CGFloat = directionToRight ? previousPane.node.bounds.width : -previousPane.node.bounds.width - candidatePane.node.layer.animatePosition(from: CGPoint(x: offset, y: 0.0), to: CGPoint(), duration: 0.35, timingFunction: kCAMediaTimingFunctionSpring, additive: true) - let previousNode = previousPane.node - previousNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: -offset, y: 0.0), duration: 0.35, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, additive: true, completion: { [weak previousNode] _ in - previousNode?.removeFromSupernode() - }) - } - } else { - if let previousPane = previousPane { - previousPane.node.removeFromSupernode() - } - } - } - })) } } @@ -1313,8 +1785,34 @@ private final class PeerInfoPaneContainerNode: ASDisplayNode { return self.currentPane?.node.transitionNodeForGallery(messageId: messageId, media: media) } - func update(size: CGSize, expansionFraction: CGFloat, presentationData: PresentationData, transition: ContainedViewLayoutTransition) { - self.currentParams = (size, expansionFraction, presentationData) + func updateSelectedMessageIds(_ selectedMessageIds: Set?, animated: Bool) { + if self.paneInteraction.selectedMessageIds != selectedMessageIds { + self.paneInteraction.selectedMessageIds = selectedMessageIds + self.currentPane?.node.updateSelectedMessages(animated: animated) + self.candidatePane?.0.node.updateSelectedMessages(animated: animated) + } + } + + func update(size: CGSize, expansionFraction: CGFloat, presentationData: PresentationData, data: PeerInfoScreenData?, transition: ContainedViewLayoutTransition) { + let availablePanes = data?.availablePanes ?? [] + + let previousCurrentPaneKey = self.currentPaneKey + if availablePanes.isEmpty { + self.currentPaneKey = nil + self.currentCandidatePaneKey = nil + if let (_, disposable, _) = self.candidatePane { + disposable.dispose() + self.candidatePane = nil + } + if let currentPane = self.currentPane { + self.currentPane = nil + currentPane.node.removeFromSupernode() + } + } else if (self.currentParams?.data?.availablePanes ?? []).isEmpty { + self.currentCandidatePaneKey = availablePanes.first + } + + self.currentParams = (size, expansionFraction, presentationData, data) transition.updateAlpha(node: self.coveringBackgroundNode, alpha: expansionFraction) @@ -1330,55 +1828,94 @@ private final class PeerInfoPaneContainerNode: ASDisplayNode { transition.updateFrame(node: self.tapsSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: tabsHeight - UIScreenPixel), size: CGSize(width: size.width, height: UIScreenPixel))) - transition.updateFrame(node: self.tabsContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: tabsHeight))) - self.tabsContainerNode.update(size: CGSize(width: size.width, height: tabsHeight), presentationData: presentationData, paneList: self.availablePanes.map { key in - let title: String - switch key { - case .media: - title = "Media" - case .files: - title = "Files" - case .links: - title = "Links" - case .music: - title = "Audio" - } - return PeerInfoPaneSpecifier(key: key, title: title) - }, selectedPane: self.currentPaneKey, transition: transition) - let paneFrame = CGRect(origin: CGPoint(x: 0.0, y: tabsHeight), size: CGSize(width: size.width, height: size.height - tabsHeight)) - if self.currentPane?.key != self.currentPaneKey { - if let currentPane = self.currentPane { - currentPane.node.removeFromSupernode() - self.currentPane = nil - } - - if let currentPaneKey = self.currentPaneKey { + if let currentCandidatePaneKey = self.currentCandidatePaneKey { + if self.candidatePane?.0.key != currentCandidatePaneKey { + self.candidatePane?.1.dispose() + let paneNode: PeerInfoPaneNode - switch currentPaneKey { + switch currentCandidatePaneKey { case .media: paneNode = PeerInfoVisualMediaPaneNode(context: self.context, openMessage: { [weak self] id in return self?.openMessage?(id) ?? false - }, peerId: self.peerId) + }, peerId: self.peerId, interaction: self.paneInteraction) case .files: paneNode = PeerInfoListPaneNode(context: self.context, openMessage: { [weak self] id in return self?.openMessage?(id) ?? false - }, peerId: self.peerId, tagMask: .file) + }, peerId: self.peerId, tagMask: .file, interaction: self.paneInteraction) case .links: - paneNode = PeerInfoListPaneNode(context: self.context, openMessage: { [weak self] id in + paneNode = PeerInfoListPaneNode(context: self.context, openMessage: { [weak self] id in return self?.openMessage?(id) ?? false - }, peerId: self.peerId, tagMask: .webPage) + }, peerId: self.peerId, tagMask: .webPage, interaction: self.paneInteraction) + case .voice: + paneNode = PeerInfoListPaneNode(context: self.context, openMessage: { [weak self] id in + return self?.openMessage?(id) ?? false + }, peerId: self.peerId, tagMask: .voiceOrInstantVideo, interaction: self.paneInteraction) case .music: - paneNode = PeerInfoListPaneNode(context: self.context, openMessage: { [weak self] id in + paneNode = PeerInfoListPaneNode(context: self.context, openMessage: { [weak self] id in return self?.openMessage?(id) ?? false - }, peerId: self.peerId, tagMask: .music) + }, peerId: self.peerId, tagMask: .music, interaction: self.paneInteraction) + case .groupsInCommon: + paneNode = PeerInfoGroupsInCommonPaneNode(context: self.context, peerId: peerId, interaction: self.paneInteraction, peers: data?.groupsInCommon ?? []) } - self.currentPane = PeerInfoPaneWrapper(key: currentPaneKey, node: paneNode) + + let disposable = MetaDisposable() + self.candidatePane = (PeerInfoPaneWrapper(key: currentCandidatePaneKey, node: paneNode), disposable, false) + + var shouldReLayout = false + disposable.set((paneNode.isReady + |> take(1) + |> deliverOnMainQueue).start(next: { [weak self] _ in + guard let strongSelf = self else { + return + } + if let (candidatePane, disposable, _) = strongSelf.candidatePane { + strongSelf.candidatePane = (candidatePane, disposable, true) + + if shouldReLayout { + if let (size, expansionFraction, presentationData, data) = strongSelf.currentParams { + strongSelf.update(size: size, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: strongSelf.currentPane != nil ? .animated(duration: 0.35, curve: .spring) : .immediate) + } + } + } + })) + shouldReLayout = true } } - if let currentPane = self.currentPane { + if let (candidatePane, _, isReady) = self.candidatePane, isReady { + let previousPane = self.currentPane + self.candidatePane = nil + self.currentPaneKey = candidatePane.key + self.currentCandidatePaneKey = nil + self.currentPane = candidatePane + + if let selectionPanelNode = self.selectionPanelNode { + self.insertSubnode(candidatePane.node, belowSubnode: selectionPanelNode) + } else { + self.addSubnode(candidatePane.node) + } + candidatePane.node.frame = paneFrame + candidatePane.update(size: paneFrame.size, isScrollingLockedAtTop: expansionFraction < 1.0 - CGFloat.ulpOfOne, presentationData: presentationData, synchronous: true, transition: .immediate) + + if let previousPane = previousPane { + let directionToRight: Bool + if let previousIndex = availablePanes.index(of: previousPane.key), let updatedIndex = availablePanes.index(of: candidatePane.key) { + directionToRight = previousIndex < updatedIndex + } else { + directionToRight = false + } + + let offset: CGFloat = directionToRight ? previousPane.node.bounds.width : -previousPane.node.bounds.width + + transition.animatePositionAdditive(node: candidatePane.node, offset: CGPoint(x: offset, y: 0.0)) + let previousNode = previousPane.node + transition.updateFrame(node: previousNode, frame: paneFrame.offsetBy(dx: -offset, dy: 0.0), completion: { [weak previousNode] _ in + previousNode?.removeFromSupernode() + }) + } + } else if let currentPane = self.currentPane { let paneWasAdded = currentPane.node.supernode == nil if paneWasAdded { self.addSubnode(currentPane.node) @@ -1388,7 +1925,28 @@ private final class PeerInfoPaneContainerNode: ASDisplayNode { paneTransition.updateFrame(node: currentPane.node, frame: paneFrame) currentPane.update(size: paneFrame.size, isScrollingLockedAtTop: expansionFraction < 1.0 - CGFloat.ulpOfOne, presentationData: presentationData, synchronous: paneWasAdded, transition: paneTransition) } - if let (candidatePane, _) = self.candidatePane { + + transition.updateFrame(node: self.tabsContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: tabsHeight))) + self.tabsContainerNode.update(size: CGSize(width: size.width, height: tabsHeight), presentationData: presentationData, paneList: availablePanes.map { key in + let title: String + switch key { + case .media: + title = "Media" + case .files: + title = "Files" + case .links: + title = "Links" + case .voice: + title = "Voice Messages" + case .music: + title = "Audio" + case .groupsInCommon: + title = "Groups" + } + return PeerInfoPaneSpecifier(key: key, title: title) + }, selectedPane: self.currentPaneKey, transition: transition) + + if let (candidatePane, _, _) = self.candidatePane { let paneTransition: ContainedViewLayoutTransition = .immediate paneTransition.updateFrame(node: candidatePane.node, frame: paneFrame) candidatePane.update(size: paneFrame.size, isScrollingLockedAtTop: expansionFraction < 1.0 - CGFloat.ulpOfOne, presentationData: presentationData, synchronous: true, transition: paneTransition) @@ -1401,6 +1959,9 @@ private final class PeerInfoPaneContainerNode: ASDisplayNode { self.isReady.set(.single(true)) } } + if let previousCurrentPaneKey = previousCurrentPaneKey, self.currentPaneKey != previousCurrentPaneKey { + self.currentPaneUpdated?() + } } } @@ -1492,7 +2053,7 @@ private final class PeerInfoScreenItemSectionContainerNode: ASDisplayNode { } } for id in removeIds { - if let itemNode = self.itemNodes[id] { + if let itemNode = self.itemNodes.removeValue(forKey: id) { transition.updateAlpha(node: itemNode, alpha: 0.0, completion: { [weak itemNode] _ in itemNode?.removeFromSupernode() }) @@ -1503,26 +2064,209 @@ private final class PeerInfoScreenItemSectionContainerNode: ASDisplayNode { transition.updateFrame(node: self.topSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: width, height: UIScreenPixel))) transition.updateFrame(node: self.bottomSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: width, height: UIScreenPixel))) + if contentHeight.isZero { + transition.updateAlpha(node: self.topSeparatorNode, alpha: 0.0) + transition.updateAlpha(node: self.bottomSeparatorNode, alpha: 0.0) + } else { + transition.updateAlpha(node: self.topSeparatorNode, alpha: 1.0) + transition.updateAlpha(node: self.bottomSeparatorNode, alpha: 1.0) + } + return contentHeight } } +private final class PeerInfoSelectionPanelNode: ASDisplayNode { + private let context: AccountContext + private let peerId: PeerId + + private let deleteMessages: () -> Void + private let shareMessages: () -> Void + private let forwardMessages: () -> Void + private let reportMessages: () -> Void + + let selectionPanel: ChatMessageSelectionInputPanelNode + let separatorNode: ASDisplayNode + let backgroundNode: ASDisplayNode + + init(context: AccountContext, peerId: PeerId, deleteMessages: @escaping () -> Void, shareMessages: @escaping () -> Void, forwardMessages: @escaping () -> Void, reportMessages: @escaping () -> Void) { + self.context = context + self.peerId = peerId + self.deleteMessages = deleteMessages + self.shareMessages = shareMessages + self.forwardMessages = forwardMessages + self.reportMessages = reportMessages + + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + + self.separatorNode = ASDisplayNode() + self.backgroundNode = ASDisplayNode() + + self.selectionPanel = ChatMessageSelectionInputPanelNode(theme: presentationData.theme, strings: presentationData.strings, peerMedia: true) + self.selectionPanel.context = context + self.selectionPanel.backgroundColor = presentationData.theme.chat.inputPanel.panelBackgroundColor + + let interfaceInteraction = ChatPanelInterfaceInteraction(setupReplyMessage: { _, _ in + }, setupEditMessage: { _, _ in + }, beginMessageSelection: { _, _ in + }, deleteSelectedMessages: { + deleteMessages() + }, reportSelectedMessages: { + reportMessages() + }, reportMessages: { _, _ in + }, deleteMessages: { _, _, f in + f(.default) + }, forwardSelectedMessages: { + forwardMessages() + }, forwardCurrentForwardMessages: { + }, forwardMessages: { _ in + }, shareSelectedMessages: { + shareMessages() + }, updateTextInputStateAndMode: { _ in + }, updateInputModeAndDismissedButtonKeyboardMessageId: { _ in + }, openStickers: { + }, editMessage: { + }, beginMessageSearch: { _, _ in + }, dismissMessageSearch: { + }, updateMessageSearch: { _ in + }, openSearchResults: { + }, navigateMessageSearch: { _ in + }, openCalendarSearch: { + }, toggleMembersSearch: { _ in + }, navigateToMessage: { _ in + }, navigateToChat: { _ in + }, openPeerInfo: { + }, togglePeerNotifications: { + }, sendContextResult: { _, _, _, _ in + return false + }, sendBotCommand: { _, _ in + }, sendBotStart: { _ in + }, botSwitchChatWithPayload: { _, _ in + }, beginMediaRecording: { _ in + }, finishMediaRecording: { _ in + }, stopMediaRecording: { + }, lockMediaRecording: { + }, deleteRecordedMedia: { + }, sendRecordedMedia: { + }, displayRestrictedInfo: { _, _ in + }, displayVideoUnmuteTip: { _ in + }, switchMediaRecordingMode: { + }, setupMessageAutoremoveTimeout: { + }, sendSticker: { _, _, _ in + return false + }, unblockPeer: { + }, pinMessage: { _ in + }, unpinMessage: { + }, shareAccountContact: { + }, reportPeer: { + }, presentPeerContact: { + }, dismissReportPeer: { + }, deleteChat: { + }, beginCall: { + }, toggleMessageStickerStarred: { _ in + }, presentController: { _, _ in + }, getNavigationController: { + return nil + }, presentGlobalOverlayController: { _, _ in + }, navigateFeed: { + }, openGrouping: { + }, toggleSilentPost: { + }, requestUnvoteInMessage: { _ in + }, requestStopPollInMessage: { _ in + }, updateInputLanguage: { _ in + }, unarchiveChat: { + }, openLinkEditing: { + }, reportPeerIrrelevantGeoLocation: { + }, displaySlowmodeTooltip: { _, _ in + }, displaySendMessageOptions: { _, _ in + }, openScheduledMessages: { + }, displaySearchResultsTooltip: { _, _ in + }, statuses: nil) + + selectionPanel.interfaceInteraction = interfaceInteraction + + super.init() + + self.addSubnode(self.backgroundNode) + self.addSubnode(self.separatorNode) + self.addSubnode(self.selectionPanel) + } + + func update(width: CGFloat, safeInset: CGFloat, metrics: LayoutMetrics, presentationData: PresentationData, transition: ContainedViewLayoutTransition) -> CGFloat { + self.backgroundNode.backgroundColor = presentationData.theme.rootController.navigationBar.backgroundColor + self.separatorNode.backgroundColor = presentationData.theme.rootController.navigationBar.separatorColor + + let interfaceState = ChatPresentationInterfaceState(chatWallpaper: .color(0), theme: presentationData.theme, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, limitsConfiguration: .defaultValue, fontSize: .regular, bubbleCorners: PresentationChatBubbleCorners(mainRadius: 16.0, auxiliaryRadius: 8.0, mergeBubbleCorners: true), accountPeerId: self.context.account.peerId, mode: .standard(previewing: false), chatLocation: .peer(self.peerId), isScheduledMessages: false) + let panelHeight = self.selectionPanel.updateLayout(width: width, leftInset: safeInset, rightInset: safeInset, maxHeight: 0.0, isSecondary: false, transition: transition, interfaceState: interfaceState, metrics: metrics) + + transition.updateFrame(node: self.selectionPanel, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: panelHeight))) + transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: panelHeight))) + transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: width, height: UIScreenPixel))) + + return panelHeight + } +} + +private final class PeerInfoState { + let isEditing: Bool + let isSearching: Bool + let selectedMessageIds: Set? + + init( + isEditing: Bool, + isSearching: Bool, + selectedMessageIds: Set? + ) { + self.isEditing = isEditing + self.isSearching = isSearching + self.selectedMessageIds = selectedMessageIds + } + + func withIsEditing(_ isEditing: Bool) -> PeerInfoState { + return PeerInfoState( + isEditing: isEditing, + isSearching: self.isSearching, + selectedMessageIds: self.selectedMessageIds + ) + } + + func withSelectedMessageIds(_ selectedMessageIds: Set?) -> PeerInfoState { + return PeerInfoState( + isEditing: self.isEditing, + isSearching: self.isSearching, + selectedMessageIds: selectedMessageIds + ) + } +} + private final class PeerInfoScreenData { let peer: Peer? let cachedData: CachedPeerData? let presence: TelegramUserPresence? let notificationSettings: TelegramPeerNotificationSettings? + let globalNotificationSettings: GlobalNotificationSettings? + let isContact: Bool + let availablePanes: [PeerInfoPaneKey] + let groupsInCommon: [Peer]? init( peer: Peer?, cachedData: CachedPeerData?, presence: TelegramUserPresence?, - notificationSettings: TelegramPeerNotificationSettings? + notificationSettings: TelegramPeerNotificationSettings?, + globalNotificationSettings: GlobalNotificationSettings?, + isContact: Bool, + availablePanes: [PeerInfoPaneKey], + groupsInCommon: [Peer]? ) { self.peer = peer self.cachedData = cachedData self.presence = presence self.notificationSettings = notificationSettings + self.globalNotificationSettings = globalNotificationSettings + self.isContact = isContact + self.availablePanes = availablePanes + self.groupsInCommon = groupsInCommon } } @@ -1531,6 +2275,44 @@ private enum PeerInfoScreenInputData: Equatable { case user } +private func peerInfoAvailableMediaPanes(context: AccountContext, peerId: PeerId) -> Signal<[PeerInfoPaneKey], NoError> { + let tags: [(MessageTags, PeerInfoPaneKey)] = [ + (.photoOrVideo, .media), + (.file, .files), + (.music, .music), + (.voiceOrInstantVideo, .voice), + (.webPage, .links) + ] + return combineLatest(tags.map { tagAndKey -> Signal in + let (tag, key) = tagAndKey + return context.account.viewTracker.aroundMessageHistoryViewForLocation(.peer(peerId), index: .upperBound, anchorIndex: .upperBound, count: 2, clipHoles: false, fixedCombinedReadStates: nil, tagMask: tag) + |> map { (view, _, _) -> PeerInfoPaneKey? in + if view.entries.isEmpty { + return nil + } else { + return key + } + } + }) + |> map { keys -> [PeerInfoPaneKey] in + return keys.compactMap { $0 } + } + |> distinctUntilChanged + /*return context.account.postbox.combinedView(keys: tags.map { (tag, _) -> PostboxViewKey in + return .historyTagInfo(peerId: peerId, tag: tag) + }) + |> map { view -> [PeerInfoPaneKey] in + return tags.compactMap { (tag, key) -> PeerInfoPaneKey? in + if let info = view.views[.historyTagInfo(peerId: peerId, tag: tag)] as? HistoryTagInfoView, !info.isEmpty { + return key + } else { + return nil + } + } + } + |> distinctUntilChanged*/ +} + private func peerInfoScreenData(context: AccountContext, peerId: PeerId) -> Signal { return context.account.postbox.combinedView(keys: [.basicPeer(peerId)]) |> map { view -> PeerInfoScreenInputData in @@ -1551,16 +2333,47 @@ private func peerInfoScreenData(context: AccountContext, peerId: PeerId) -> Sign peer: nil, cachedData: nil, presence: nil, - notificationSettings: nil + notificationSettings: nil, + globalNotificationSettings: nil, + isContact: false, + availablePanes: [], + groupsInCommon: nil )) case .user: - return context.account.viewTracker.peerView(peerId, updateData: true) - |> map { view -> PeerInfoScreenData in + let groupsInCommonSignal: Signal<[Peer]?, NoError> = .single(nil) + |> then( + groupsInCommon(account: context.account, peerId: peerId) + |> map(Optional.init) + ) + let globalNotificationsKey: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.globalNotifications])) + return combineLatest( + context.account.viewTracker.peerView(peerId, updateData: true), + peerInfoAvailableMediaPanes(context: context, peerId: peerId), + context.account.postbox.combinedView(keys: [.peerChatState(peerId: peerId), globalNotificationsKey]), + groupsInCommonSignal + ) + |> map { peerView, availablePanes, combinedView, groupsInCommon -> PeerInfoScreenData in + var globalNotificationSettings: GlobalNotificationSettings = .defaultSettings + if let preferencesView = combinedView.views[globalNotificationsKey] as? PreferencesView { + if let settings = preferencesView.values[PreferencesKeys.globalNotifications] as? GlobalNotificationSettings { + globalNotificationSettings = settings + } + } + + var availablePanes = availablePanes + if let groupsInCommon = groupsInCommon, !groupsInCommon.isEmpty { + availablePanes.append(.groupsInCommon) + } + return PeerInfoScreenData( - peer: view.peers[peerId], - cachedData: view.cachedData, - presence: view.peerPresences[peerId] as? TelegramUserPresence, - notificationSettings: view.notificationSettings as? TelegramPeerNotificationSettings + peer: peerView.peers[peerId], + cachedData: peerView.cachedData, + presence: peerView.peerPresences[peerId] as? TelegramUserPresence, + notificationSettings: peerView.notificationSettings as? TelegramPeerNotificationSettings, + globalNotificationSettings: globalNotificationSettings, + isContact: peerView.peerIsContact, + availablePanes: availablePanes, + groupsInCommon: groupsInCommon ) } } @@ -1570,32 +2383,123 @@ private func peerInfoScreenData(context: AccountContext, peerId: PeerId) -> Sign private final class PeerInfoInteraction { let openUsername: (String) -> Void let openPhone: (String) -> Void + let editingOpenNotificationSettings: () -> Void + let editingOpenSoundSettings: () -> Void + let editingToggleShowMessageText: (Bool) -> Void + let requestDeleteContact: () -> Void + let openAddContact: () -> Void + let updateBlocked: (Bool) -> Void init( openUsername: @escaping (String) -> Void, - openPhone: @escaping (String) -> Void + openPhone: @escaping (String) -> Void, + editingOpenNotificationSettings: @escaping () -> Void, + editingOpenSoundSettings: @escaping () -> Void, + editingToggleShowMessageText: @escaping (Bool) -> Void, + requestDeleteContact: @escaping () -> Void, + openAddContact: @escaping () -> Void, + updateBlocked: @escaping (Bool) -> Void ) { self.openUsername = openUsername self.openPhone = openPhone + self.editingOpenNotificationSettings = editingOpenNotificationSettings + self.editingOpenSoundSettings = editingOpenSoundSettings + self.editingToggleShowMessageText = editingToggleShowMessageText + self.requestDeleteContact = requestDeleteContact + self.openAddContact = openAddContact + self.updateBlocked = updateBlocked } } private func peerInfoSectionItems(data: PeerInfoScreenData?, presentationData: PresentationData, interaction: PeerInfoInteraction) -> [PeerInfoScreenItem] { + guard let data = data else { + return [] + } var items: [PeerInfoScreenItem] = [] - if let user = data?.peer as? TelegramUser { - if let cachedData = data?.cachedData as? CachedUserData { - if let about = cachedData.about { - items.append(PeerInfoScreenLabeledValueItem(id: 0, label: "bio", text: about, textColor: .primary, textBehavior: .multiLine(maxLines: 10), action: nil)) - } + if let user = data.peer as? TelegramUser { + if let phone = user.phone { + items.append(PeerInfoScreenLabeledValueItem(id: 2, label: "mobile", text: "\(formatPhoneNumber(phone))", textColor: .accent, action: { + interaction.openPhone(phone) + })) } if let username = user.username { items.append(PeerInfoScreenLabeledValueItem(id: 1, label: "username", text: "@\(username)", textColor: .accent, action: { interaction.openUsername(username) })) } - if let phone = user.phone { - items.append(PeerInfoScreenLabeledValueItem(id: 2, label: "mobile", text: "\(formatPhoneNumber(phone))", textColor: .accent, action: { - interaction.openPhone(phone) + if let cachedData = data.cachedData as? CachedUserData { + if let about = cachedData.about { + items.append(PeerInfoScreenLabeledValueItem(id: 0, label: "bio", text: about, textColor: .primary, textBehavior: .multiLine(maxLines: 10), action: nil)) + } + } + if !data.isContact { + items.append(PeerInfoScreenActionItem(id: 3, text: "Add Contact", action: { + interaction.openAddContact() + })) + if let cachedData = data.cachedData as? CachedUserData { + if cachedData.isBlocked { + items.append(PeerInfoScreenActionItem(id: 4, text: "Unblock", action: { + interaction.updateBlocked(false) + })) + } else { + if user.flags.contains(.isSupport) { + } else { + items.append(PeerInfoScreenActionItem(id: 4, text: "Block User", color: .destructive, action: { + interaction.updateBlocked(true) + })) + } + } + } + } + } + return items +} + +private func editingInfoSectionItems(data: PeerInfoScreenData?, presentationData: PresentationData, interaction: PeerInfoInteraction) -> [PeerInfoScreenItem] { + guard let data = data else { + return [] + } + var items: [PeerInfoScreenItem] = [] + + if let _ = data.peer as? TelegramUser { + if let notificationSettings = data.notificationSettings { + let notificationsLabel: String + let soundLabel: String + let notificationSettings = notificationSettings as? TelegramPeerNotificationSettings ?? TelegramPeerNotificationSettings.defaultSettings + if case let .muted(until) = notificationSettings.muteState, until >= Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970) { + if until < Int32.max - 1 { + notificationsLabel = stringForRemainingMuteInterval(strings: presentationData.strings, muteInterval: until) + } else { + notificationsLabel = presentationData.strings.UserInfo_NotificationsDisabled + } + } else { + notificationsLabel = presentationData.strings.UserInfo_NotificationsEnabled + } + + let globalNotificationSettings: GlobalNotificationSettings = data.globalNotificationSettings ?? GlobalNotificationSettings.defaultSettings + soundLabel = localizedPeerNotificationSoundString(strings: presentationData.strings, sound: notificationSettings.messageSound, default: globalNotificationSettings.effective.privateChats.sound) + + items.append(PeerInfoScreenDisclosureItem(id: 0, label: notificationsLabel, text: "Notifications", action: { + interaction.editingOpenNotificationSettings() + })) + items.append(PeerInfoScreenDisclosureItem(id: 1, label: soundLabel, text: "Sound", action: { + interaction.editingOpenSoundSettings() + })) + items.append(PeerInfoScreenSwitchItem(id: 2, text: "Show Message Text", value: notificationSettings.displayPreviews != .hide, toggled: { value in + interaction.editingToggleShowMessageText(value) + })) + } + } + + return items +} + +private func editingActionsSectionItems(data: PeerInfoScreenData?, presentationData: PresentationData, interaction: PeerInfoInteraction) -> [PeerInfoScreenItem] { + var items: [PeerInfoScreenItem] = [] + if let data = data { + if data.isContact { + items.append(PeerInfoScreenActionItem(id: 0, text: "Delete Contact", color: .destructive, action: { + interaction.requestDeleteContact() })) } } @@ -1612,19 +2516,35 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD let headerNode: PeerInfoHeaderNode private let infoSection: PeerInfoScreenItemSectionContainerNode + private let editingInfoSection: PeerInfoScreenItemSectionContainerNode + private let editingActionsSection: PeerInfoScreenItemSectionContainerNode private let paneContainerNode: PeerInfoPaneContainerNode private var ignoreScrolling: Bool = false private var hapticFeedback: HapticFeedback? + private var searchDisplayController: SearchDisplayController? + private var _interaction: PeerInfoInteraction? private var interaction: PeerInfoInteraction { return self._interaction! } + private var _chatInterfaceInteraction: ChatControllerInteraction? + private var chatInterfaceInteraction: ChatControllerInteraction { + return self._chatInterfaceInteraction! + } + private(set) var validLayout: (ContainerViewLayout, CGFloat)? private(set) var data: PeerInfoScreenData? + private(set) var state = PeerInfoState( + isEditing: false, + isSearching: false, + selectedMessageIds: nil + ) private var dataDisposable: Disposable? + private let activeActionDisposable = MetaDisposable() + private let _ready = Promise() var ready: Promise { return self._ready @@ -1641,6 +2561,8 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD self.headerNode = PeerInfoHeaderNode(context: context, avatarInitiallyExpanded: avatarInitiallyExpanded) self.infoSection = PeerInfoScreenItemSectionContainerNode(id: 0) + self.editingInfoSection = PeerInfoScreenItemSectionContainerNode(id: 1) + self.editingActionsSection = PeerInfoScreenItemSectionContainerNode(id: 2) self.paneContainerNode = PeerInfoPaneContainerNode(context: context, peerId: peerId) super.init() @@ -1651,19 +2573,367 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD }, openPhone: { [weak self] value in self?.openPhone(value: value) + }, + editingOpenNotificationSettings: { [weak self] in + self?.editingOpenNotificationSettings() + }, + editingOpenSoundSettings: { [weak self] in + self?.editingOpenSoundSettings() + }, + editingToggleShowMessageText: { [weak self] value in + self?.editingToggleShowMessageText(value: value) + }, + requestDeleteContact: { [weak self] in + self?.requestDeleteContact() + }, + openAddContact: { [weak self] in + self?.openAddContact() + }, + updateBlocked: { [weak self] block in + self?.updateBlocked(block: block) } ) + self._chatInterfaceInteraction = ChatControllerInteraction(openMessage: { message, mode in + /*if let strongSelf = self, strongSelf.isNodeLoaded, let galleryMessage = strongSelf.mediaCollectionDisplayNode.messageForGallery(message.id) { + guard let navigationController = strongSelf.navigationController as? NavigationController else { + return false + } + strongSelf.mediaCollectionDisplayNode.view.endEditing(true) + return context.sharedContext.openChatMessage(OpenChatMessageParams(context: context, message: galleryMessage.message, standalone: false, reverseMessageGalleryOrder: true, navigationController: navigationController, dismissInput: { + self?.mediaCollectionDisplayNode.view.endEditing(true) + }, present: { c, a in + self?.present(c, in: .window(.root), with: a, blockInteraction: true) + }, transitionNode: { messageId, media in + if let strongSelf = self { + return strongSelf.mediaCollectionDisplayNode.transitionNodeForGallery(messageId: messageId, media: media) + } + return nil + }, addToTransitionSurface: { view in + if let strongSelf = self { + var belowSubview: UIView? + if let historyNode = strongSelf.mediaCollectionDisplayNode.historyNode as? ChatHistoryGridNode { + if let lowestSectionNode = historyNode.lowestSectionNode() { + belowSubview = lowestSectionNode.view + } + } + strongSelf.mediaCollectionDisplayNode.historyNode + if let belowSubview = belowSubview { + strongSelf.mediaCollectionDisplayNode.historyNode.view.insertSubview(view, belowSubview: belowSubview) + } else { + strongSelf.mediaCollectionDisplayNode.historyNode.view.addSubview(view) + } + } + }, openUrl: { url in + self?.openUrl(url) + }, openPeer: { peer, navigation in + self?.controllerInteraction?.openPeer(peer.id, navigation, nil) + }, callPeer: { peerId in + self?.controllerInteraction?.callPeer(peerId) + }, enqueueMessage: { _ in + }, sendSticker: nil, setupTemporaryHiddenMedia: { _, _, _ in }, chatAvatarHiddenMedia: { _, _ in })) + }*/ + return false + }, openPeer: { id, navigation, _ in + /*if let strongSelf = self, let id = id, let navigationController = strongSelf.navigationController as? NavigationController { + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id))) + }*/ + }, openPeerMention: { _ in + }, openMessageContextMenu: { message, _, _, _, _ in + /*guard let strongSelf = self else { + return + } + let items = (chatAvailableMessageActionsImpl(postbox: strongSelf.context.account.postbox, accountPeerId: strongSelf.context.account.peerId, messageIds: [message.id]) + |> deliverOnMainQueue).start(next: { actions in + var messageIds = Set() + messageIds.insert(message.id) + + if let strongSelf = self, strongSelf.isNodeLoaded { + if let message = strongSelf.mediaCollectionDisplayNode.messageForGallery(message.id)?.message { + let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData) + var items: [ActionSheetButtonItem] = [] + + items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.SharedMedia_ViewInChat, color: .accent, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController { + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(strongSelf.peerId), subject: .message(message.id))) + } + })) + items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_ContextMenuForward, color: .accent, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + if let strongSelf = self { + strongSelf.forwardMessages(messageIds) + } + })) + if actions.options.contains(.deleteLocally) || actions.options.contains(.deleteGlobally) { + items.append( ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_ContextMenuDelete, color: .destructive, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + if let strongSelf = self { + strongSelf.deleteMessages(messageIds) + } + })) + } + actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ + ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + }) + ])]) + strongSelf.mediaCollectionDisplayNode.view.endEditing(true) + strongSelf.present(actionSheet, in: .window(.root)) + } + } + })*/ + }, openMessageContextActions: { message, node, rect, gesture in + /*guard let strongSelf = self else { + gesture?.cancel() + return + } + + let _ = (chatMediaListPreviewControllerData(context: strongSelf.context, message: message, standalone: false, reverseMessageGalleryOrder: false, navigationController: strongSelf.navigationController as? NavigationController) + |> deliverOnMainQueue).start(next: { previewData in + guard let strongSelf = self else { + gesture?.cancel() + return + } + if let previewData = previewData { + let context = strongSelf.context + let strings = strongSelf.presentationData.strings + let items = chatAvailableMessageActionsImpl(postbox: strongSelf.context.account.postbox, accountPeerId: strongSelf.context.account.peerId, messageIds: [message.id]) + |> map { actions -> [ContextMenuItem] in + var items: [ContextMenuItem] = [] + + items.append(.action(ContextMenuActionItem(text: strings.SharedMedia_ViewInChat, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/GoToMessage"), color: theme.contextMenu.primaryColor) }, action: { c, f in + c.dismiss(completion: { + if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController { + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(strongSelf.peerId), subject: .message(message.id))) + } + }) + }))) + + items.append(.action(ContextMenuActionItem(text: strings.Conversation_ContextMenuForward, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.contextMenu.primaryColor) }, action: { c, f in + c.dismiss(completion: { + if let strongSelf = self { + strongSelf.forwardMessages([message.id]) + } + }) + }))) + + if actions.options.contains(.deleteLocally) || actions.options.contains(.deleteGlobally) { + items.append(.action(ContextMenuActionItem(text: strings.Conversation_ContextMenuDelete, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor) }, action: { c, f in + c.setItems(context.account.postbox.transaction { transaction -> [ContextMenuItem] in + var items: [ContextMenuItem] = [] + let messageIds = [message.id] + + if let peer = transaction.getPeer(message.id.peerId) { + var personalPeerName: String? + var isChannel = false + if let user = peer as? TelegramUser { + personalPeerName = user.compactDisplayTitle + } else if let channel = peer as? TelegramChannel, case .broadcast = channel.info { + isChannel = true + } + + if actions.options.contains(.deleteGlobally) { + let globalTitle: String + if isChannel { + globalTitle = strongSelf.presentationData.strings.Conversation_DeleteMessagesForMe + } else if let personalPeerName = personalPeerName { + globalTitle = strongSelf.presentationData.strings.Conversation_DeleteMessagesFor(personalPeerName).0 + } else { + globalTitle = strongSelf.presentationData.strings.Conversation_DeleteMessagesForEveryone + } + items.append(.action(ContextMenuActionItem(text: globalTitle, textColor: .destructive, icon: { _ in nil }, action: { c, f in + c.dismiss(completion: { + if let strongSelf = self { + strongSelf.updateInterfaceState(animated: true, { $0.withoutSelectionState() }) + let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: .forEveryone).start() + } + }) + }))) + } + + if actions.options.contains(.deleteLocally) { + var localOptionText = strongSelf.presentationData.strings.Conversation_DeleteMessagesForMe + if strongSelf.context.account.peerId == strongSelf.peerId { + if messageIds.count == 1 { + localOptionText = strongSelf.presentationData.strings.Conversation_Moderate_Delete + } else { + localOptionText = strongSelf.presentationData.strings.Conversation_DeleteManyMessages + } + } + items.append(.action(ContextMenuActionItem(text: localOptionText, textColor: .destructive, icon: { _ in nil }, action: { c, f in + c.dismiss(completion: { + if let strongSelf = self { + strongSelf.updateInterfaceState(animated: true, { $0.withoutSelectionState() }) + let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: .forLocalPeer).start() + } + }) + }))) + } + } + + return items + }) + }))) + } + + return items + } + + switch previewData { + case let .gallery(gallery): + gallery.setHintWillBePresentedInPreviewingContext(true) + let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: gallery, sourceNode: node)), items: items, reactionItems: [], gesture: gesture) + strongSelf.presentInGlobalOverlay(contextController) + case .instantPage: + break + } + } + })*/ + }, navigateToMessage: { fromId, id in + /*if let strongSelf = self, strongSelf.isNodeLoaded { + if id.peerId == strongSelf.peerId { + var fromIndex: MessageIndex? + + if let message = strongSelf.mediaCollectionDisplayNode.historyNode.messageInCurrentHistoryView(fromId) { + fromIndex = message.index + } + } else { + (strongSelf.navigationController as? NavigationController)?.pushViewController(ChatControllerImpl(context: strongSelf.context, chatLocation: .peer(id.peerId), subject: .message(id))) + } + }*/ + }, tapMessage: nil, clickThroughMessage: { + //self?.view.endEditing(true) + }, toggleMessagesSelection: { ids, value in + /*if let strongSelf = self, strongSelf.isNodeLoaded { + strongSelf.updateInterfaceState(animated: true, { $0.withToggledSelectedMessages(ids, value: value) }) + }*/ + }, sendCurrentMessage: { _ in + }, sendMessage: { _ in + }, sendSticker: { _, _, _, _ in + return false + }, sendGif: { _, _, _ in + return false + }, requestMessageActionCallback: { _, _, _ in + }, requestMessageActionUrlAuth: { _, _, _ in + }, activateSwitchInline: { _, _ in + }, openUrl: { url, _, external, _ in + //self?.openUrl(url, external: external ?? false) + }, shareCurrentLocation: { + }, shareAccountContact: { + }, sendBotCommand: { _, _ in + }, openInstantPage: { message, associatedData in + /*if let strongSelf = self, strongSelf.isNodeLoaded, let navigationController = strongSelf.navigationController as? NavigationController, let message = strongSelf.mediaCollectionDisplayNode.messageForGallery(message.id)?.message { + openChatInstantPage(context: strongSelf.context, message: message, sourcePeerType: associatedData?.automaticDownloadPeerType, navigationController: navigationController) + }*/ + }, openWallpaper: { message in + /*if let strongSelf = self, strongSelf.isNodeLoaded, let message = strongSelf.mediaCollectionDisplayNode.messageForGallery(message.id)?.message { + openChatWallpaper(context: strongSelf.context, message: message, present: { [weak self] c, a in + self?.present(c, in: .window(.root), with: a, blockInteraction: true) + }) + }*/ + }, openTheme: { _ in + }, openHashtag: { _, _ in + }, updateInputState: { _ in + }, updateInputMode: { _ in + }, openMessageShareMenu: { _ in + }, presentController: { _, _ in + }, navigationController: { + return nil + }, chatControllerNode: { + return nil + }, reactionContainerNode: { + return nil + }, presentGlobalOverlayController: { _, _ in }, callPeer: { _ in + }, longTap: { content, _ in + /*if let strongSelf = self { + strongSelf.view.endEditing(true) + switch content { + case let .url(url): + let canOpenIn = availableOpenInOptions(context: strongSelf.context, item: .url(url: url)).count > 1 + let openText = canOpenIn ? strongSelf.presentationData.strings.Conversation_FileOpenIn : strongSelf.presentationData.strings.Conversation_LinkDialogOpen + let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData) + actionSheet.setItemGroups([ActionSheetItemGroup(items: [ + ActionSheetTextItem(title: url), + ActionSheetButtonItem(title: openText, color: .accent, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + if let strongSelf = self { + if canOpenIn { + let actionSheet = OpenInActionSheetController(context: strongSelf.context, item: .url(url: url), openUrl: { [weak self] url in + if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController { + strongSelf.context.sharedContext.openExternalUrl(context: strongSelf.context, urlContext: .generic, url: url, forceExternal: true, presentationData: strongSelf.presentationData, navigationController: navigationController, dismissInput: { + }) + } + }) + strongSelf.present(actionSheet, in: .window(.root)) + } else { + strongSelf.context.sharedContext.applicationBindings.openUrl(url) + } + } + }), + ActionSheetButtonItem(title: strongSelf.presentationData.strings.ShareMenu_CopyShareLink, color: .accent, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + UIPasteboard.general.string = url + }), + ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_AddToReadingList, color: .accent, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + if let link = URL(string: url) { + let _ = try? SSReadingList.default()?.addItem(with: link, title: nil, previewText: nil) + } + }) + ]), ActionSheetItemGroup(items: [ + ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + }) + ])]) + strongSelf.present(actionSheet, in: .window(.root)) + default: + break + } + }*/ + }, openCheckoutOrReceipt: { _ in + }, openSearch: { + //self?.activateSearch() + }, setupReply: { _ in + }, canSetupReply: { _ in + return false + }, navigateToFirstDateMessage: { _ in + }, requestRedeliveryOfFailedMessages: { _ in + }, addContact: { _ in + }, rateCall: { _, _ in + }, requestSelectMessagePollOptions: { _, _ in + }, requestOpenMessagePollResults: { _, _ in + }, openAppStorePage: { + }, displayMessageTooltip: { _, _, _, _ in + }, seekToTimecode: { _, _, _ in + }, scheduleCurrentMessage: { + }, sendScheduledMessagesNow: { _ in + }, editScheduledMessagesTime: { _ in + }, performTextSelectionAction: { _, _, _ in + }, updateMessageReaction: { _, _ in + }, openMessageReactions: { _ in + }, displaySwipeToReplyHint: { + }, dismissReplyMarkupMessage: { _ in + }, openMessagePollResults: { _, _ in + }, openPollCreation: { _ in + }, requestMessageUpdate: { _ in + }, cancelInteractiveKeyboardGestures: { + }, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, + pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: false)) + self.backgroundColor = self.presentationData.theme.list.blocksBackgroundColor self.scrollNode.view.showsVerticalScrollIndicator = false if #available(iOS 11.0, *) { self.scrollNode.view.contentInsetAdjustmentBehavior = .never } + self.scrollNode.view.alwaysBounceVertical = true self.scrollNode.view.scrollsToTop = false self.scrollNode.view.delegate = self self.addSubnode(self.scrollNode) self.scrollNode.addSubnode(self.infoSection) + self.scrollNode.addSubnode(self.editingInfoSection) + self.scrollNode.addSubnode(self.editingActionsSection) self.scrollNode.addSubnode(self.paneContainerNode) self.addSubnode(self.headerNode) @@ -1671,14 +2941,52 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD return self?.openMessage(id: id) ?? false } + self.paneContainerNode.toggleMessageSelected = { [weak self] id in + guard let strongSelf = self else { + return + } + if var selectedMessageIds = strongSelf.state.selectedMessageIds { + if selectedMessageIds.contains(id) { + selectedMessageIds.remove(id) + } else { + selectedMessageIds.insert(id) + } + strongSelf.state = strongSelf.state.withSelectedMessageIds(selectedMessageIds) + strongSelf.paneContainerNode.updateSelectedMessageIds(strongSelf.state.selectedMessageIds, animated: true) + if let (layout, navigationHeight) = strongSelf.validLayout { + strongSelf.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .animated(duration: 0.4, curve: .spring), additive: false) + } + } + } + + self.paneContainerNode.openPeer = { [weak self] peer in + guard let strongSelf = self else { + return + } + if let navigationController = strongSelf.controller?.navigationController as? NavigationController { + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), keepStack: .always)) + } + } + + self.paneContainerNode.currentPaneUpdated = { [weak self] in + guard let strongSelf = self else { + return + } + if let (layout, navigationHeight) = strongSelf.validLayout { + strongSelf.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate, additive: false) + strongSelf.scrollNode.view.setContentOffset(CGPoint(x: 0.0, y: strongSelf.paneContainerNode.frame.minY - navigationHeight), animated: true) + } + } + self.headerNode.performButtonAction = { [weak self] key in self?.performButtonAction(key: key) } self.headerNode.requestAvatarExpansion = { [weak self] in - guard let strongSelf = self else { + guard let strongSelf = self, let peer = strongSelf.data?.peer, peer.smallProfileImage != nil else { return } + let transition: ContainedViewLayoutTransition = .animated(duration: 0.35, curve: .spring) strongSelf.headerNode.updateIsAvatarExpanded(true) @@ -1689,6 +2997,99 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } } + self.headerNode.navigationButtonContainer.performAction = { [weak self] key in + guard let strongSelf = self else { + return + } + switch key { + case .edit: + strongSelf.state = strongSelf.state.withIsEditing(true) + if strongSelf.headerNode.isAvatarExpanded { + strongSelf.headerNode.updateIsAvatarExpanded(false) + strongSelf.updateNavigationExpansionPresentation(isExpanded: false, animated: true) + } + if let (layout, navigationHeight) = strongSelf.validLayout { + strongSelf.scrollNode.view.setContentOffset(CGPoint(), animated: false) + strongSelf.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate, additive: false) + } + UIView.transition(with: strongSelf.view, duration: 0.3, options: [.transitionCrossDissolve], animations: { + }, completion: nil) + strongSelf.controller?.navigationItem.setLeftBarButton(UIBarButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, style: .plain, target: strongSelf, action: #selector(strongSelf.editingCancelPressed)), animated: true) + case .done, .cancel: + if case .done = key { + if let data = strongSelf.data, data.isContact { + if let peer = data.peer as? TelegramUser { + let firstName = strongSelf.headerNode.editingContentNode.editingTextForKey(.firstName) ?? "" + let lastName = strongSelf.headerNode.editingContentNode.editingTextForKey(.lastName) ?? "" + + if peer.firstName != firstName || peer.lastName != lastName { + strongSelf.activeActionDisposable.set((updateContactName(account: context.account, peerId: peer.id, firstName: firstName, lastName: lastName) + |> deliverOnMainQueue).start(error: { _ in + guard let strongSelf = self else { + return + } + strongSelf.headerNode.navigationButtonContainer.performAction?(.cancel) + }, completed: { + guard let strongSelf = self else { + return + } + let context = strongSelf.context + let _ = (getUserPeer(postbox: strongSelf.context.account.postbox, peerId: peer.id) + |> mapToSignal { peer, _ -> Signal in + guard let peer = peer as? TelegramUser, let phone = peer.phone, !phone.isEmpty else { + return .complete() + } + return (context.sharedContext.contactDataManager?.basicDataForNormalizedPhoneNumber(DeviceContactNormalizedPhoneNumber(rawValue: formatPhoneNumber(phone))) ?? .single([])) + |> take(1) + |> mapToSignal { records -> Signal in + var signals: [Signal] = [] + if let contactDataManager = context.sharedContext.contactDataManager { + for (id, basicData) in records { + signals.append(contactDataManager.appendContactData(DeviceContactExtendedData(basicData: DeviceContactBasicData(firstName: firstName, lastName: lastName, phoneNumbers: basicData.phoneNumbers), middleName: "", prefix: "", suffix: "", organization: "", jobTitle: "", department: "", emailAddresses: [], urls: [], addresses: [], birthdayDate: nil, socialProfiles: [], instantMessagingProfiles: [], note: ""), to: id)) + } + } + return combineLatest(signals) + |> mapToSignal { _ -> Signal in + return .complete() + } + } + }).start() + strongSelf.headerNode.navigationButtonContainer.performAction?(.cancel) + })) + } else { + strongSelf.headerNode.navigationButtonContainer.performAction?(.cancel) + } + } + } else { + strongSelf.headerNode.navigationButtonContainer.performAction?(.cancel) + } + } else { + strongSelf.state = strongSelf.state.withIsEditing(false) + if let (layout, navigationHeight) = strongSelf.validLayout { + strongSelf.scrollNode.view.setContentOffset(CGPoint(), animated: false) + strongSelf.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate, additive: false) + } + UIView.transition(with: strongSelf.view, duration: 0.3, options: [.transitionCrossDissolve], animations: { + }, completion: nil) + strongSelf.controller?.navigationItem.setLeftBarButton(nil, animated: true) + } + case .select: + strongSelf.state = strongSelf.state.withSelectedMessageIds(Set()) + if let (layout, navigationHeight) = strongSelf.validLayout { + strongSelf.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .animated(duration: 0.4, curve: .spring), additive: false) + } + strongSelf.paneContainerNode.updateSelectedMessageIds(strongSelf.state.selectedMessageIds, animated: true) + case .selectionDone: + strongSelf.state = strongSelf.state.withSelectedMessageIds(nil) + if let (layout, navigationHeight) = strongSelf.validLayout { + strongSelf.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .animated(duration: 0.4, curve: .spring), additive: false) + } + strongSelf.paneContainerNode.updateSelectedMessageIds(strongSelf.state.selectedMessageIds, animated: true) + case .search: + strongSelf.activateSearch() + } + } + self.dataDisposable = (peerInfoScreenData(context: context, peerId: peerId) |> deliverOnMainQueue).start(next: { [weak self] data in guard let strongSelf = self else { @@ -1700,6 +3101,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD deinit { self.dataDisposable?.dispose() + self.activeActionDisposable.dispose() } override func didLoad() { @@ -1717,6 +3119,10 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD self.scrollNode.view.setContentOffset(CGPoint(), animated: true) } + @objc private func editingCancelPressed() { + self.headerNode.navigationButtonContainer.performAction?(.cancel) + } + private func openMessage(id: MessageId) -> Bool { guard let galleryMessage = self.paneContainerNode.findLoadedMessage(id: id), let controller = self.controller, let navigationController = controller.navigationController as? NavigationController else { return false @@ -1801,13 +3207,27 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } var reportSpam = false var deleteChat = false + var items: [ActionSheetItem] = [] + if self.headerNode.isAvatarExpanded { + items.append(ActionSheetButtonItem(title: "Message", color: .accent, action: { [weak self] in + dismissAction() + self?.performButtonAction(key: .message) + })) + items.append(ActionSheetButtonItem(title: "Call", color: .accent, action: { [weak self] in + dismissAction() + self?.performButtonAction(key: .call) + })) + items.append(ActionSheetButtonItem(title: "Mute", color: .accent, action: { [weak self] in + dismissAction() + self?.performButtonAction(key: .mute) + })) + } + items.append(ActionSheetButtonItem(title: presentationData.strings.UserInfo_StartSecretChat, color: .accent, action: { [weak self] in + dismissAction() + self?.openStartSecretChat() + })) actionSheet.setItemGroups([ - ActionSheetItemGroup(items: [ - ActionSheetButtonItem(title: presentationData.strings.UserInfo_StartSecretChat, color: .accent, action: { [weak self] in - dismissAction() - self?.openStartSecretChat() - }) - ]), + ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ActionSheetButtonItem(title: self.presentationData.strings.Common_Cancel, action: { dismissAction() })]) ]) controller.present(actionSheet, in: .window(.root)) @@ -1980,9 +3400,430 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD }) } + private func editingOpenNotificationSettings() { + let peerId = self.peerId + let _ = (self.context.account.postbox.transaction { transaction -> (TelegramPeerNotificationSettings, GlobalNotificationSettings) in + let peerSettings: TelegramPeerNotificationSettings = (transaction.getPeerNotificationSettings(peerId) as? TelegramPeerNotificationSettings) ?? TelegramPeerNotificationSettings.defaultSettings + let globalSettings: GlobalNotificationSettings = (transaction.getPreferencesEntry(key: PreferencesKeys.globalNotifications) as? GlobalNotificationSettings) ?? GlobalNotificationSettings.defaultSettings + return (peerSettings, globalSettings) + } + |> deliverOnMainQueue).start(next: { [weak self] peerSettings, globalSettings in + guard let strongSelf = self else { + return + } + let soundSettings: NotificationSoundSettings? + if case .default = peerSettings.messageSound { + soundSettings = NotificationSoundSettings(value: nil) + } else { + soundSettings = NotificationSoundSettings(value: peerSettings.messageSound) + } + let muteSettingsController = notificationMuteSettingsController(presentationData: strongSelf.presentationData, notificationSettings: globalSettings.effective.groupChats, soundSettings: nil, openSoundSettings: { + guard let strongSelf = self else { + return + } + let soundController = notificationSoundSelectionController(context: strongSelf.context, isModal: true, currentSound: peerSettings.messageSound, defaultSound: globalSettings.effective.groupChats.sound, completion: { sound in + guard let strongSelf = self else { + return + } + let _ = updatePeerNotificationSoundInteractive(account: strongSelf.context.account, peerId: strongSelf.peerId, sound: sound).start() + }) + strongSelf.controller?.push(soundController) + }, updateSettings: { value in + guard let strongSelf = self else { + return + } + let _ = updatePeerMuteSetting(account: strongSelf.context.account, peerId: strongSelf.peerId, muteInterval: value).start() + }) + strongSelf.controller?.present(muteSettingsController, in: .window(.root)) + }) + } + + private func editingOpenSoundSettings() { + let peerId = self.peerId + let _ = (self.context.account.postbox.transaction { transaction -> (TelegramPeerNotificationSettings, GlobalNotificationSettings) in + let peerSettings: TelegramPeerNotificationSettings = (transaction.getPeerNotificationSettings(peerId) as? TelegramPeerNotificationSettings) ?? TelegramPeerNotificationSettings.defaultSettings + let globalSettings: GlobalNotificationSettings = (transaction.getPreferencesEntry(key: PreferencesKeys.globalNotifications) as? GlobalNotificationSettings) ?? GlobalNotificationSettings.defaultSettings + return (peerSettings, globalSettings) + } + |> deliverOnMainQueue).start(next: { [weak self] peerSettings, globalSettings in + guard let strongSelf = self else { + return + } + let soundSettings: NotificationSoundSettings? + if case .default = peerSettings.messageSound { + soundSettings = NotificationSoundSettings(value: nil) + } else { + soundSettings = NotificationSoundSettings(value: peerSettings.messageSound) + } + + let soundController = notificationSoundSelectionController(context: strongSelf.context, isModal: true, currentSound: peerSettings.messageSound, defaultSound: globalSettings.effective.groupChats.sound, completion: { sound in + guard let strongSelf = self else { + return + } + let _ = updatePeerNotificationSoundInteractive(account: strongSelf.context.account, peerId: strongSelf.peerId, sound: sound).start() + }) + strongSelf.controller?.push(soundController) + }) + } + + private func editingToggleShowMessageText(value: Bool) { + let _ = (getUserPeer(postbox: self.context.account.postbox, peerId: self.peerId) + |> deliverOnMainQueue).start(next: { [weak self] peer, _ in + guard let strongSelf = self, let peer = peer else { + return + } + let _ = updatePeerDisplayPreviewsSetting(account: strongSelf.context.account, peerId: peer.id, displayPreviews: value ? .show : .hide).start() + }) + } + + private func requestDeleteContact() { + let actionSheet = ActionSheetController(presentationData: self.presentationData) + let dismissAction: () -> Void = { [weak actionSheet] in + actionSheet?.dismissAnimated() + } + actionSheet.setItemGroups([ + ActionSheetItemGroup(items: [ + ActionSheetButtonItem(title: self.presentationData.strings.UserInfo_DeleteContact, color: .destructive, action: { [weak self] in + dismissAction() + guard let strongSelf = self else { + return + } + let _ = (getUserPeer(postbox: strongSelf.context.account.postbox, peerId: strongSelf.peerId) + |> deliverOnMainQueue).start(next: { peer, _ in + guard let peer = peer, let strongSelf = self else { + return + } + let deleteContactFromDevice: Signal + if let contactDataManager = strongSelf.context.sharedContext.contactDataManager { + deleteContactFromDevice = contactDataManager.deleteContactWithAppSpecificReference(peerId: peer.id) + } else { + deleteContactFromDevice = .complete() + } + + var deleteSignal = deleteContactPeerInteractively(account: strongSelf.context.account, peerId: peer.id) + |> then(deleteContactFromDevice) + + let progressSignal = Signal { subscriber in + guard let strongSelf = self else { + return EmptyDisposable + } + let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } + let statusController = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil)) + strongSelf.controller?.present(statusController, in: .window(.root)) + return ActionDisposable { [weak statusController] in + Queue.mainQueue().async() { + statusController?.dismiss() + } + } + } + |> runOn(Queue.mainQueue()) + |> delay(0.15, queue: Queue.mainQueue()) + let progressDisposable = progressSignal.start() + + deleteSignal = deleteSignal + |> afterDisposed { + Queue.mainQueue().async { + progressDisposable.dispose() + } + } + + strongSelf.activeActionDisposable.set((deleteSignal + |> deliverOnMainQueue).start(completed: { + self?.controller?.dismiss() + })) + + deleteSendMessageIntents(peerId: strongSelf.peerId) + }) + }) + ]), + ActionSheetItemGroup(items: [ActionSheetButtonItem(title: self.presentationData.strings.Common_Cancel, action: { dismissAction() })]) + ]) + self.controller?.present(actionSheet, in: .window(.root)) + } + + private func openAddContact() { + let _ = (getUserPeer(postbox: self.context.account.postbox, peerId: self.peerId) + |> deliverOnMainQueue).start(next: { [weak self] peer, _ in + guard let strongSelf = self, let peer = peer else { + return + } + openAddPersonContactImpl(context: strongSelf.context, peerId: peer.id, pushController: { c in + self?.controller?.push(c) + }, present: { c, a in + self?.controller?.present(c, in: .window(.root), with: a) + }) + }) + } + + private func updateBlocked(block: Bool) { + let _ = (getUserPeer(postbox: self.context.account.postbox, peerId: self.peerId) + |> take(1) + |> deliverOnMainQueue).start(next: { [weak self] peer, _ in + guard let strongSelf = self, let peer = peer else { + return + } + + let presentationData = strongSelf.presentationData + if let peer = peer as? TelegramUser, let _ = peer.botInfo { + strongSelf.activeActionDisposable.set(requestUpdatePeerIsBlocked(account: strongSelf.context.account, peerId: peer.id, isBlocked: block).start()) + if !block { + let _ = enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: "/start", attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil)]).start() + if let navigationController = strongSelf.controller?.navigationController as? NavigationController { + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id))) + } + } + } else { + if block { + let presentationData = strongSelf.presentationData + let actionSheet = ActionSheetController(presentationData: presentationData) + let dismissAction: () -> Void = { [weak actionSheet] in + actionSheet?.dismissAnimated() + } + var reportSpam = false + var deleteChat = false + actionSheet.setItemGroups([ + ActionSheetItemGroup(items: [ + ActionSheetTextItem(title: presentationData.strings.UserInfo_BlockConfirmationTitle(peer.compactDisplayTitle).0), + ActionSheetButtonItem(title: presentationData.strings.UserInfo_BlockActionTitle(peer.compactDisplayTitle).0, color: .destructive, action: { + dismissAction() + guard let strongSelf = self else { + return + } + + strongSelf.activeActionDisposable.set(requestUpdatePeerIsBlocked(account: strongSelf.context.account, peerId: peer.id, isBlocked: true).start()) + if deleteChat { + let _ = removePeerChat(account: strongSelf.context.account, peerId: strongSelf.peerId, reportChatSpam: reportSpam).start() + (strongSelf.controller?.navigationController as? NavigationController)?.popToRoot(animated: true) + } else if reportSpam { + let _ = reportPeer(account: strongSelf.context.account, peerId: strongSelf.peerId, reason: .spam).start() + } + + deleteSendMessageIntents(peerId: strongSelf.peerId) + }) + ]), + ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })]) + ]) + strongSelf.controller?.present(actionSheet, in: .window(.root)) + } else { + let text: String + if block { + text = presentationData.strings.UserInfo_BlockConfirmation(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).0 + } else { + text = presentationData.strings.UserInfo_UnblockConfirmation(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).0 + } + strongSelf.controller?.present(textAlertController(context: strongSelf.context, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_No, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Yes, action: { + guard let strongSelf = self else { + return + } + strongSelf.activeActionDisposable.set(requestUpdatePeerIsBlocked(account: strongSelf.context.account, peerId: peer.id, isBlocked: block).start()) + })]), in: .window(.root)) + } + } + }) + } + + func deleteMessages() { + if let messageIds = self.state.selectedMessageIds, !messageIds.isEmpty { + self.activeActionDisposable.set((self.context.sharedContext.chatAvailableMessageActions(postbox: self.context.account.postbox, accountPeerId: self.context.account.peerId, messageIds: messageIds) + |> deliverOnMainQueue).start(next: { [weak self] actions in + if let strongSelf = self, let peer = strongSelf.data?.peer, !actions.options.isEmpty { + let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData) + var items: [ActionSheetItem] = [] + var personalPeerName: String? + var isChannel = false + if let user = peer as? TelegramUser { + personalPeerName = user.compactDisplayTitle + } else if let channel = peer as? TelegramChannel, case .broadcast = channel.info { + isChannel = true + } + + if actions.options.contains(.deleteGlobally) { + let globalTitle: String + if isChannel { + globalTitle = strongSelf.presentationData.strings.Conversation_DeleteMessagesForMe + } else if let personalPeerName = personalPeerName { + globalTitle = strongSelf.presentationData.strings.Conversation_DeleteMessagesFor(personalPeerName).0 + } else { + globalTitle = strongSelf.presentationData.strings.Conversation_DeleteMessagesForEveryone + } + items.append(ActionSheetButtonItem(title: globalTitle, color: .destructive, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + if let strongSelf = self { + strongSelf.headerNode.navigationButtonContainer.performAction?(.selectionDone) + let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: .forEveryone).start() + } + })) + } + if actions.options.contains(.deleteLocally) { + var localOptionText = strongSelf.presentationData.strings.Conversation_DeleteMessagesForMe + if strongSelf.context.account.peerId == strongSelf.peerId { + if messageIds.count == 1 { + localOptionText = strongSelf.presentationData.strings.Conversation_Moderate_Delete + } else { + localOptionText = strongSelf.presentationData.strings.Conversation_DeleteManyMessages + } + } + items.append(ActionSheetButtonItem(title: localOptionText, color: .destructive, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + if let strongSelf = self { + strongSelf.headerNode.navigationButtonContainer.performAction?(.selectionDone) + let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: .forLocalPeer).start() + } + })) + } + actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ + ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + }) + ])]) + strongSelf.controller?.present(actionSheet, in: .window(.root)) + } + })) + } + } + + func forwardMessages() { + if let messageIds = self.state.selectedMessageIds, !messageIds.isEmpty { + let peerSelectionController = self.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: self.context, filter: [.onlyWriteable, .excludeDisabled])) + peerSelectionController.peerSelected = { [weak self, weak peerSelectionController] peerId in + if let strongSelf = self, let _ = peerSelectionController { + if peerId == strongSelf.context.account.peerId { + strongSelf.headerNode.navigationButtonContainer.performAction?(.selectionDone) + + let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: messageIds.map { id -> EnqueueMessage in + return .forward(source: id, grouping: .auto, attributes: []) + }) + |> deliverOnMainQueue).start(next: { [weak self] messageIds in + if let strongSelf = self { + let signals: [Signal] = messageIds.compactMap({ id -> Signal? in + guard let id = id else { + return nil + } + return strongSelf.context.account.pendingMessageManager.pendingMessageStatus(id) + |> mapToSignal { status, _ -> Signal in + if status != nil { + return .never() + } else { + return .single(true) + } + } + |> take(1) + }) + strongSelf.activeActionDisposable.set((combineLatest(signals) + |> deliverOnMainQueue).start(completed: { + guard let strongSelf = self else { + return + } + strongSelf.controller?.present(OverlayStatusController(theme: strongSelf.presentationData.theme, type: .success), in: .window(.root)) + })) + } + }) + if let peerSelectionController = peerSelectionController { + peerSelectionController.dismiss() + } + } else { + let _ = (strongSelf.context.account.postbox.transaction({ transaction -> Void in + transaction.updatePeerChatInterfaceState(peerId, update: { currentState in + if let currentState = currentState as? ChatInterfaceState { + return currentState.withUpdatedForwardMessageIds(Array(messageIds)) + } else { + return ChatInterfaceState().withUpdatedForwardMessageIds(Array(messageIds)) + } + }) + }) |> deliverOnMainQueue).start(completed: { + if let strongSelf = self { + strongSelf.headerNode.navigationButtonContainer.performAction?(.selectionDone) + + let ready = ValuePromise() + strongSelf.activeActionDisposable.set((ready.get() |> take(1) |> deliverOnMainQueue).start(next: { _ in + if let peerSelectionController = peerSelectionController { + peerSelectionController.dismiss() + } + })) + + (strongSelf.controller?.navigationController as? NavigationController)?.replaceTopController(ChatControllerImpl(context: strongSelf.context, chatLocation: .peer(peerId)), animated: false, ready: ready) + } + }) + } + } + } + self.controller?.push(peerSelectionController) + } + } + + private func activateSearch() { + guard let (layout, navigationBarHeight) = self.validLayout else { + return + } + + var maybePlaceholderNode: SearchBarPlaceholderNode? + /*if let listNode = historyNode as? ListView { + listNode.forEachItemNode { node in + if let node = node as? ChatListSearchItemNode { + maybePlaceholderNode = node.searchBarNode + } + } + }*/ + + if let _ = self.searchDisplayController { + return + } + + var tagMask: MessageTags = .file + if let currentPaneKey = self.paneContainerNode.currentPaneKey { + switch currentPaneKey { + case .links: + tagMask = .webPage + case .music: + tagMask = .music + default: + break + } + } + + self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, mode: .list, contentNode: ChatHistorySearchContainerNode(context: self.context, peerId: self.peerId, tagMask: tagMask, interfaceInteraction: self.chatInterfaceInteraction), cancel: { [weak self] in + self?.deactivateSearch() + }) + let transition: ContainedViewLayoutTransition = .animated(duration: 0.2, curve: .easeInOut) + if let navigationBar = self.controller?.navigationBar { + transition.updateAlpha(node: navigationBar, alpha: 0.0) + } + + self.searchDisplayController?.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate) + self.searchDisplayController?.activate(insertSubnode: { [weak self] subnode, isSearchBar in + if let strongSelf = self, let navigationBar = strongSelf.controller?.navigationBar { + strongSelf.insertSubnode(subnode, belowSubnode: navigationBar) + } + }, placeholder: nil) + + if let (layout, navigationHeight) = self.validLayout { + self.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate) + } + } + + private func deactivateSearch() { + guard let searchDisplayController = self.searchDisplayController else { + return + } + self.searchDisplayController = nil + searchDisplayController.deactivate(placeholder: nil) + + let transition: ContainedViewLayoutTransition = .animated(duration: 0.35, curve: .easeInOut) + if let navigationBar = self.controller?.navigationBar { + transition.updateAlpha(node: navigationBar, alpha: 1.0) + } + } + func containerLayoutUpdated(layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition, additive: Bool = false) { self.validLayout = (layout, navigationHeight) + if let searchDisplayController = self.searchDisplayController { + searchDisplayController.containerLayoutUpdated(layout, navigationBarHeight: navigationHeight, transition: transition) + if !searchDisplayController.isDeactivating { + //vanillaInsets.top += (layout.statusBarHeight ?? 0.0) - navigationBarHeightDelta + } + } + self.ignoreScrolling = true transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: layout.size)) @@ -1991,7 +3832,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD var contentHeight: CGFloat = 0.0 - let headerHeight = self.headerNode.update(width: layout.size.width, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, contentOffset: self.scrollNode.view.contentOffset.y, presentationData: self.presentationData, peer: self.data?.peer, cachedData: self.data?.cachedData, notificationSettings: self.data?.notificationSettings, presence: self.data?.presence, transition: transition, additive: additive) + let headerHeight = self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: layout.safeInsets.left, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, contentOffset: self.scrollNode.view.contentOffset.y, presentationData: self.presentationData, peer: self.data?.peer, cachedData: self.data?.cachedData, notificationSettings: self.data?.notificationSettings, presence: self.data?.presence, isContact: self.data?.isContact ?? false, state: self.state, transition: transition, additive: additive) let headerFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: layout.size.width, height: headerHeight)) if additive { transition.updateFrameAdditive(node: self.headerNode, frame: headerFrame) @@ -2008,31 +3849,141 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } else { transition.updateFrame(node: self.infoSection, frame: infoSectionFrame) } - contentHeight += infoSectionHeight - contentHeight += sectionSpacing + + let editingInfoSectionHeight = self.editingInfoSection.update(width: layout.size.width, presentationData: self.presentationData, items: editingInfoSectionItems(data: self.data, presentationData: self.presentationData, interaction: self.interaction), transition: transition) + let editingInfoSectionFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: layout.size.width, height: infoSectionHeight)) + if additive { + transition.updateFrameAdditive(node: self.editingInfoSection, frame: editingInfoSectionFrame) + } else { + transition.updateFrame(node: self.editingInfoSection, frame: editingInfoSectionFrame) + } + + if self.state.isEditing { + transition.updateAlpha(node: self.infoSection, alpha: 0.0) + transition.updateAlpha(node: self.editingInfoSection, alpha: 1.0) + transition.updateAlpha(node: self.editingActionsSection, alpha: 1.0) + if !editingInfoSectionHeight.isZero { + contentHeight += editingInfoSectionHeight + contentHeight += sectionSpacing + } + } else { + transition.updateAlpha(node: self.infoSection, alpha: 1.0) + transition.updateAlpha(node: self.editingInfoSection, alpha: 0.0) + transition.updateAlpha(node: self.editingActionsSection, alpha: 0.0) + if !infoSectionHeight.isZero { + contentHeight += infoSectionHeight + contentHeight += sectionSpacing + } + } + + let editingActionsSectionHeight = self.editingActionsSection.update(width: layout.size.width, presentationData: self.presentationData, items: editingActionsSectionItems(data: self.data, presentationData: self.presentationData, interaction: self.interaction), transition: transition) + let editingActionsSectionFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: layout.size.width, height: editingActionsSectionHeight)) + if additive { + transition.updateFrameAdditive(node: self.editingActionsSection, frame: editingActionsSectionFrame) + } else { + transition.updateFrame(node: self.editingActionsSection, frame: editingActionsSectionFrame) + } + + if self.state.isEditing { + if !editingActionsSectionHeight.isZero { + contentHeight += editingActionsSectionHeight + contentHeight += sectionSpacing + } + } let paneContainerSize = CGSize(width: layout.size.width, height: layout.size.height - navigationHeight) var restoreContentOffset: CGPoint? if additive { restoreContentOffset = self.scrollNode.view.contentOffset } - self.scrollNode.view.contentSize = CGSize(width: layout.size.width, height: contentHeight + paneContainerSize.height) + + let paneContainerFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: paneContainerSize) + if self.state.isEditing || (self.data?.availablePanes ?? []).isEmpty { + transition.updateAlpha(node: self.paneContainerNode, alpha: 0.0) + } else { + contentHeight += layout.size.height - navigationHeight + transition.updateAlpha(node: self.paneContainerNode, alpha: 1.0) + } + + if let selectedMessageIds = self.state.selectedMessageIds { + var wasAdded = false + let selectionPanelNode: PeerInfoSelectionPanelNode + if let current = self.paneContainerNode.selectionPanelNode { + selectionPanelNode = current + } else { + wasAdded = true + selectionPanelNode = PeerInfoSelectionPanelNode(context: self.context, peerId: self.peerId, deleteMessages: { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.deleteMessages() + }, shareMessages: { [weak self] in + guard let strongSelf = self, let messageIds = strongSelf.state.selectedMessageIds, !messageIds.isEmpty else { + return + } + let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Message] in + var messages: [Message] = [] + for id in messageIds { + if let message = transaction.getMessage(id) { + messages.append(message) + } + } + return messages + } + |> deliverOnMainQueue).start(next: { messages in + if let strongSelf = self, !messages.isEmpty { + strongSelf.headerNode.navigationButtonContainer.performAction?(.selectionDone) + + let shareController = ShareController(context: strongSelf.context, subject: .messages(messages.sorted(by: { lhs, rhs in + return lhs.index < rhs.index + })), externalShare: true, immediateExternalShare: true) + strongSelf.controller?.present(shareController, in: .window(.root)) + } + }) + }, forwardMessages: { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.forwardMessages() + }, reportMessages: { [weak self] in + guard let strongSelf = self, let messageIds = strongSelf.state.selectedMessageIds, !messageIds.isEmpty else { + return + } + strongSelf.controller?.present(peerReportOptionsController(context: strongSelf.context, subject: .messages(Array(messageIds).sorted()), present: { c, a in + self?.controller?.present(c, in: .window(.root), with: a) + }, push: { c in + self?.controller?.push(c) + }, completion: { _ in }), in: .window(.root)) + }) + self.paneContainerNode.selectionPanelNode = selectionPanelNode + self.paneContainerNode.addSubnode(selectionPanelNode) + } + selectionPanelNode.selectionPanel.selectedMessages = selectedMessageIds + let panelHeight = selectionPanelNode.update(width: layout.size.width, safeInset: layout.safeInsets.left, metrics: layout.metrics, presentationData: self.presentationData, transition: wasAdded ? .immediate : transition) + let panelFrame = CGRect(origin: CGPoint(x: 0.0, y: paneContainerSize.height - panelHeight), size: CGSize(width: layout.size.width, height: panelHeight)) + if wasAdded { + selectionPanelNode.frame = panelFrame + transition.animatePositionAdditive(node: selectionPanelNode, offset: CGPoint(x: 0.0, y: panelHeight)) + } else { + transition.updateFrame(node: selectionPanelNode, frame: panelFrame) + } + } else if let selectionPanelNode = self.paneContainerNode.selectionPanelNode { + self.paneContainerNode.selectionPanelNode = nil + transition.updateFrame(node: selectionPanelNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height), size: selectionPanelNode.bounds.size), completion: { [weak selectionPanelNode] _ in + selectionPanelNode?.removeFromSupernode() + }) + } + + self.scrollNode.view.contentSize = CGSize(width: layout.size.width, height: contentHeight) if let restoreContentOffset = restoreContentOffset { self.scrollNode.view.contentOffset = restoreContentOffset } - let paneAreaExpansionDistance: CGFloat = 32.0 - var paneAreaExpansionDelta = (contentHeight - navigationHeight) - self.scrollNode.view.contentOffset.y - paneAreaExpansionDelta = max(0.0, min(paneAreaExpansionDelta, paneAreaExpansionDistance)) - let paneAreaExpansionFraction: CGFloat = 1.0 - paneAreaExpansionDelta / paneAreaExpansionDistance - - let paneContainerFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: paneContainerSize) if additive { transition.updateFrameAdditive(node: self.paneContainerNode, frame: paneContainerFrame) } else { transition.updateFrame(node: self.paneContainerNode, frame: paneContainerFrame) } - contentHeight += layout.size.height - navigationHeight self.ignoreScrolling = false self.updateNavigation(transition: transition, additive: additive) @@ -2046,25 +3997,58 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD private func updateNavigation(transition: ContainedViewLayoutTransition, additive: Bool) { let offsetY = self.scrollNode.view.contentOffset.y - if offsetY <= 50.0 { + if self.state.isEditing || offsetY <= 50.0 { self.scrollNode.view.bounces = true + self.scrollNode.view.alwaysBounceVertical = true } else { self.scrollNode.view.bounces = false + self.scrollNode.view.alwaysBounceVertical = false } if let (layout, navigationHeight) = self.validLayout { if !additive { - self.headerNode.update(width: layout.size.width, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, contentOffset: offsetY, presentationData: self.presentationData, peer: self.data?.peer, cachedData: self.data?.cachedData, notificationSettings: self.data?.notificationSettings, presence: self.data?.presence, transition: transition, additive: additive) + self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: layout.safeInsets.left, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, contentOffset: offsetY, presentationData: self.presentationData, peer: self.data?.peer, cachedData: self.data?.cachedData, notificationSettings: self.data?.notificationSettings, presence: self.data?.presence, isContact: self.data?.isContact ?? false, state: self.state, transition: transition, additive: additive) } let paneAreaExpansionDistance: CGFloat = 32.0 var paneAreaExpansionDelta = (self.paneContainerNode.frame.minY - navigationHeight) - self.scrollNode.view.contentOffset.y paneAreaExpansionDelta = max(0.0, min(paneAreaExpansionDelta, paneAreaExpansionDistance)) + let paneAreaExpansionFraction: CGFloat = 1.0 - paneAreaExpansionDelta / paneAreaExpansionDistance - transition.updateAlpha(node: self.headerNode.separatorNode, alpha: 1.0 - paneAreaExpansionFraction) + let effectiveAreaExpansionFraction: CGFloat + if self.state.isEditing { + effectiveAreaExpansionFraction = 0.0 + } else { + effectiveAreaExpansionFraction = paneAreaExpansionFraction + } - self.paneContainerNode.update(size: self.paneContainerNode.bounds.size, expansionFraction: paneAreaExpansionFraction, presentationData: self.presentationData, transition: transition) + transition.updateAlpha(node: self.headerNode.separatorNode, alpha: 1.0 - effectiveAreaExpansionFraction) + + self.paneContainerNode.update(size: self.paneContainerNode.bounds.size, expansionFraction: paneAreaExpansionFraction, presentationData: self.presentationData, data: self.data, transition: transition) + self.headerNode.navigationButtonContainer.frame = CGRect(origin: CGPoint(x: layout.safeInsets.left, y: layout.statusBarHeight ?? 0.0), size: CGSize(width: layout.size.width - layout.safeInsets.left * 2.0, height: 44.0)) + self.headerNode.navigationButtonContainer.isWhite = self.headerNode.isAvatarExpanded + + var navigationButtons: [PeerInfoHeaderNavigationButtonSpec] = [] + if self.state.isEditing { + navigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .done, isForExpandedView: false)) + } else { + navigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .edit, isForExpandedView: false)) + if self.state.selectedMessageIds == nil { + if let currentPaneKey = self.paneContainerNode.currentPaneKey { + switch currentPaneKey { + case .files, .music, .links: + navigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .search, isForExpandedView: true)) + default: + break + } + } + navigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .select, isForExpandedView: true)) + } else { + navigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .selectionDone, isForExpandedView: true)) + } + } + self.headerNode.navigationButtonContainer.update(size: CGSize(width: layout.size.width - layout.safeInsets.left * 2.0, height: 44.0), presentationData: self.presentationData, buttons: navigationButtons, expandFraction: effectiveAreaExpansionFraction, transition: transition) } } @@ -2080,12 +4064,14 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } self.updateNavigation(transition: .immediate, additive: false) - if scrollView.isDragging && scrollView.isTracking { + if !self.state.isEditing { let offsetY = self.scrollNode.view.contentOffset.y var shouldBeExpanded: Bool? - if offsetY <= -32.0 { - shouldBeExpanded = true - } else if offsetY >= 4.0 { + if offsetY <= -32.0 && scrollView.isDragging && scrollView.isTracking { + if let peer = self.data?.peer, peer.smallProfileImage != nil { + shouldBeExpanded = true + } + } else if offsetY >= 1.0 { shouldBeExpanded = false } if let shouldBeExpanded = shouldBeExpanded, self.canUpdateAvatarExpansion, shouldBeExpanded != self.headerNode.isAvatarExpanded { @@ -2106,10 +4092,6 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD if let (layout, navigationHeight) = self.validLayout { self.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: transition, additive: true) } - - if !shouldBeExpanded { - //scrollView.setContentOffset(CGPoint(), animated: true) - } } } } @@ -2118,6 +4100,11 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD if let controller = self.controller { controller.statusBar.updateStatusBarStyle(isExpanded ? .White : self.presentationData.theme.rootController.statusBarStyle.style, animated: animated) + if animated { + UIView.transition(with: controller.controllerNode.headerNode.navigationButtonContainer.view, duration: 0.3, options: [.transitionCrossDissolve], animations: { + }, completion: nil) + } + let baseNavigationBarPresentationData = NavigationBarPresentationData(presentationData: self.presentationData) let navigationBarPresentationData = NavigationBarPresentationData( theme: NavigationBarTheme( @@ -2145,11 +4132,18 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD guard let (_, navigationHeight) = self.validLayout else { return } - if targetContentOffset.pointee.y < 212.0 { - if targetContentOffset.pointee.y < 212.0 / 2.0 { - targetContentOffset.pointee.y = 0.0 - } else { - targetContentOffset.pointee.y = 212.0 + if !self.state.isEditing { + if targetContentOffset.pointee.y < 212.0 { + if targetContentOffset.pointee.y < 212.0 / 2.0 { + targetContentOffset.pointee.y = 0.0 + } else { + targetContentOffset.pointee.y = 212.0 + } + } + let paneAreaExpansionDistance: CGFloat = 32.0 + let paneAreaExpansionFinalPoint: CGFloat = self.paneContainerNode.frame.minY - navigationHeight + if targetContentOffset.pointee.y > paneAreaExpansionFinalPoint - paneAreaExpansionDistance && targetContentOffset.pointee.y < paneAreaExpansionFinalPoint { + targetContentOffset.pointee.y = paneAreaExpansionFinalPoint } } } @@ -2189,7 +4183,7 @@ public final class PeerInfoScreen: ViewController { private var presentationData: PresentationData - private var controllerNode: PeerInfoScreenNode { + fileprivate var controllerNode: PeerInfoScreenNode { return self.displayNode as! PeerInfoScreenNode } @@ -2221,6 +4215,9 @@ public final class PeerInfoScreen: ViewController { guard let strongSelf = self else { return nil } + if strongSelf.navigationItem.leftBarButtonItem != nil { + return nil + } if strongSelf.controllerNode.scrollNode.view.contentOffset.y > .ulpOfOne { return nil } @@ -2289,6 +4286,7 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig private var topNavigationBar: NavigationBar? private var bottomNavigationBar: NavigationBar? + private var reverseFraction: Bool = false private let headerNode: PeerInfoHeaderNode @@ -2314,44 +4312,52 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig } func setup(topNavigationBar: NavigationBar, bottomNavigationBar: NavigationBar) { - self.topNavigationBar = topNavigationBar - self.bottomNavigationBar = bottomNavigationBar + if let _ = bottomNavigationBar.userInfo as? PeerInfoNavigationSourceTag { + self.topNavigationBar = topNavigationBar + self.bottomNavigationBar = bottomNavigationBar + } else { + self.topNavigationBar = bottomNavigationBar + self.bottomNavigationBar = topNavigationBar + self.reverseFraction = true + } topNavigationBar.isHidden = true bottomNavigationBar.isHidden = true - if let previousBackButtonArrow = bottomNavigationBar.makeTransitionBackArrowNode(accentColor: self.presentationData.theme.rootController.navigationBar.accentTextColor) { - self.previousBackButtonArrow = previousBackButtonArrow - self.addSubnode(previousBackButtonArrow) - } - if self.screenNode.headerNode.isAvatarExpanded, let currentBackButtonArrow = topNavigationBar.makeTransitionBackArrowNode(accentColor: self.screenNode.headerNode.isAvatarExpanded ? .white : self.presentationData.theme.rootController.navigationBar.accentTextColor) { - self.currentBackButtonArrow = currentBackButtonArrow - self.addSubnode(currentBackButtonArrow) - } - if let previousBackButtonBadge = bottomNavigationBar.makeTransitionBadgeNode() { - self.previousBackButtonBadge = previousBackButtonBadge - self.addSubnode(previousBackButtonBadge) - } - if let previousRightButton = bottomNavigationBar.makeTransitionRightButtonNode(accentColor: self.presentationData.theme.rootController.navigationBar.accentTextColor) { - self.previousRightButton = previousRightButton - self.addSubnode(previousRightButton) - } - if let currentBackButton = topNavigationBar.makeTransitionBackButtonNode(accentColor: self.screenNode.headerNode.isAvatarExpanded ? .white : self.presentationData.theme.rootController.navigationBar.accentTextColor) { - self.currentBackButton = currentBackButton - self.addSubnode(currentBackButton) - } - if let previousTitleView = bottomNavigationBar.titleView as? ChatTitleView { - let previousTitleNode = previousTitleView.titleNode.makeCopy() - let previousTitleContainerNode = ASDisplayNode() - previousTitleContainerNode.addSubnode(previousTitleNode) - self.previousTitleNode = (previousTitleContainerNode, previousTitleNode) - self.addSubnode(previousTitleContainerNode) - - let previousStatusNode = previousTitleView.activityNode.makeCopy() - let previousStatusContainerNode = ASDisplayNode() - previousStatusContainerNode.addSubnode(previousStatusNode) - self.previousStatusNode = (previousStatusContainerNode, previousStatusNode) - self.addSubnode(previousStatusContainerNode) + if let topNavigationBar = self.topNavigationBar, let bottomNavigationBar = self.bottomNavigationBar { + if let previousBackButtonArrow = bottomNavigationBar.makeTransitionBackArrowNode(accentColor: self.presentationData.theme.rootController.navigationBar.accentTextColor) { + self.previousBackButtonArrow = previousBackButtonArrow + self.addSubnode(previousBackButtonArrow) + } + if self.screenNode.headerNode.isAvatarExpanded, let currentBackButtonArrow = topNavigationBar.makeTransitionBackArrowNode(accentColor: self.screenNode.headerNode.isAvatarExpanded ? .white : self.presentationData.theme.rootController.navigationBar.accentTextColor) { + self.currentBackButtonArrow = currentBackButtonArrow + self.addSubnode(currentBackButtonArrow) + } + if let previousBackButtonBadge = bottomNavigationBar.makeTransitionBadgeNode() { + self.previousBackButtonBadge = previousBackButtonBadge + self.addSubnode(previousBackButtonBadge) + } + if let previousRightButton = bottomNavigationBar.makeTransitionRightButtonNode(accentColor: self.presentationData.theme.rootController.navigationBar.accentTextColor) { + self.previousRightButton = previousRightButton + self.addSubnode(previousRightButton) + } + if let currentBackButton = topNavigationBar.makeTransitionBackButtonNode(accentColor: self.screenNode.headerNode.isAvatarExpanded ? .white : self.presentationData.theme.rootController.navigationBar.accentTextColor) { + self.currentBackButton = currentBackButton + self.addSubnode(currentBackButton) + } + if let previousTitleView = bottomNavigationBar.titleView as? ChatTitleView { + let previousTitleNode = previousTitleView.titleNode.makeCopy() + let previousTitleContainerNode = ASDisplayNode() + previousTitleContainerNode.addSubnode(previousTitleNode) + self.previousTitleNode = (previousTitleContainerNode, previousTitleNode) + self.addSubnode(previousTitleContainerNode) + + let previousStatusNode = previousTitleView.activityNode.makeCopy() + let previousStatusContainerNode = ASDisplayNode() + previousStatusContainerNode.addSubnode(previousStatusNode) + self.previousStatusNode = (previousStatusContainerNode, previousStatusNode) + self.addSubnode(previousStatusContainerNode) + } } } @@ -2360,6 +4366,8 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig return } + let fraction = self.reverseFraction ? (1.0 - fraction) : fraction + if let previousBackButtonArrow = self.previousBackButtonArrow { let previousBackButtonArrowFrame = bottomNavigationBar.backButtonArrow.view.convert(bottomNavigationBar.backButtonArrow.view.bounds, to: bottomNavigationBar.view) previousBackButtonArrow.frame = previousBackButtonArrowFrame @@ -2401,7 +4409,7 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig self.headerNode.navigationTransition = PeerInfoHeaderNavigationTransition(sourceNavigationBar: bottomNavigationBar, sourceTitleView: previousTitleView, sourceTitleFrame: previousTitleFrame, sourceSubtitleFrame: previousStatusFrame, fraction: fraction) if let (layout, navigationHeight) = self.screenNode.validLayout { - self.headerNode.update(width: layout.size.width, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: topNavigationBar.bounds.height, contentOffset: 0.0, presentationData: self.presentationData, peer: self.screenNode.data?.peer, cachedData: self.screenNode.data?.cachedData, notificationSettings: self.screenNode.data?.notificationSettings, presence: self.screenNode.data?.presence, transition: transition, additive: false) + self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: layout.safeInsets.left, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: topNavigationBar.bounds.height, contentOffset: 0.0, presentationData: self.presentationData, peer: self.screenNode.data?.peer, cachedData: self.screenNode.data?.cachedData, notificationSettings: self.screenNode.data?.notificationSettings, presence: self.screenNode.data?.presence, isContact: self.screenNode.data?.isContact ?? false, state: self.screenNode.state, transition: transition, additive: false) } let titleScale = (fraction * previousTitleNode.bounds.height + (1.0 - fraction) * self.headerNode.titleNode.bounds.height) / previousTitleNode.bounds.height @@ -2419,6 +4427,8 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig transition.updateAlpha(node: previousTitleNode, alpha: fraction) transition.updateAlpha(node: self.headerNode.subtitleNode, alpha: (1.0 - fraction)) transition.updateAlpha(node: previousStatusNode, alpha: fraction) + + transition.updateAlpha(node: self.headerNode.navigationButtonContainer, alpha: (1.0 - fraction)) } } diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoScreenActionItem.swift b/submodules/TelegramUI/TelegramUI/PeerInfoScreenActionItem.swift new file mode 100644 index 0000000000..c7b9fb361f --- /dev/null +++ b/submodules/TelegramUI/TelegramUI/PeerInfoScreenActionItem.swift @@ -0,0 +1,98 @@ +import AsyncDisplayKit +import Display +import TelegramPresentationData + +enum PeerInfoScreenActionColor { + case accent + case destructive +} + +final class PeerInfoScreenActionItem: PeerInfoScreenItem { + let id: AnyHashable + let text: String + let color: PeerInfoScreenActionColor + let action: (() -> Void)? + + init(id: AnyHashable, text: String, color: PeerInfoScreenActionColor = .accent, action: (() -> Void)?) { + self.id = id + self.text = text + self.color = color + self.action = action + } + + func node() -> PeerInfoScreenItemNode { + return PeerInfoScreenActionItemNode() + } +} + +private final class PeerInfoScreenActionItemNode: PeerInfoScreenItemNode { + private let selectionNode: PeerInfoScreenSelectableBackgroundNode + private let textNode: ImmediateTextNode + private let bottomSeparatorNode: ASDisplayNode + + private var item: PeerInfoScreenActionItem? + + override init() { + var bringToFrontForHighlightImpl: (() -> Void)? + self.selectionNode = PeerInfoScreenSelectableBackgroundNode(bringToFrontForHighlight: { bringToFrontForHighlightImpl?() }) + + self.textNode = ImmediateTextNode() + self.textNode.displaysAsynchronously = false + self.textNode.isUserInteractionEnabled = false + + self.bottomSeparatorNode = ASDisplayNode() + self.bottomSeparatorNode.isLayerBacked = true + + super.init() + + bringToFrontForHighlightImpl = { [weak self] in + self?.bringToFrontForHighlight?() + } + + self.addSubnode(self.bottomSeparatorNode) + self.addSubnode(self.selectionNode) + self.addSubnode(self.textNode) + } + + override func update(width: CGFloat, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, transition: ContainedViewLayoutTransition) -> CGFloat { + guard let item = item as? PeerInfoScreenActionItem else { + return 10.0 + } + + self.item = item + + self.selectionNode.pressed = item.action + + let sideInset: CGFloat = 16.0 + + self.bottomSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor + + let textColorValue: UIColor + switch item.color { + case .accent: + textColorValue = presentationData.theme.list.itemAccentColor + case .destructive: + textColorValue = presentationData.theme.list.itemDestructiveColor + } + + self.textNode.maximumNumberOfLines = 1 + self.textNode.attributedText = NSAttributedString(string: item.text, font: Font.regular(17.0), textColor: textColorValue) + + let textSize = self.textNode.updateLayout(CGSize(width: width - sideInset * 2.0, height: .greatestFiniteMagnitude)) + + let textFrame = CGRect(origin: CGPoint(x: sideInset, y: 11.0), size: textSize) + + let height = textSize.height + 22.0 + + transition.updateFrame(node: self.textNode, frame: textFrame) + + let highlightNodeOffset: CGFloat = topItem == nil ? 0.0 : UIScreenPixel + self.selectionNode.update(size: CGSize(width: width, height: height + highlightNodeOffset), theme: presentationData.theme, transition: transition) + transition.updateFrame(node: self.selectionNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -highlightNodeOffset), size: CGSize(width: width, height: height + highlightNodeOffset))) + + transition.updateFrame(node: self.bottomSeparatorNode, frame: CGRect(origin: CGPoint(x: sideInset, y: height - UIScreenPixel), size: CGSize(width: width - sideInset, height: UIScreenPixel))) + transition.updateAlpha(node: self.bottomSeparatorNode, alpha: bottomItem == nil ? 0.0 : 1.0) + + return height + } +} diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoScreenDisclosureItem.swift b/submodules/TelegramUI/TelegramUI/PeerInfoScreenDisclosureItem.swift new file mode 100644 index 0000000000..ca27a09e75 --- /dev/null +++ b/submodules/TelegramUI/TelegramUI/PeerInfoScreenDisclosureItem.swift @@ -0,0 +1,115 @@ +import AsyncDisplayKit +import Display +import TelegramPresentationData + +final class PeerInfoScreenDisclosureItem: PeerInfoScreenItem { + let id: AnyHashable + let label: String + let text: String + let action: (() -> Void)? + + init(id: AnyHashable, label: String, text: String, action: (() -> Void)?) { + self.id = id + self.label = label + self.text = text + self.action = action + } + + func node() -> PeerInfoScreenItemNode { + return PeerInfoScreenDisclosureItemNode() + } +} + +private final class PeerInfoScreenDisclosureItemNode: PeerInfoScreenItemNode { + private let selectionNode: PeerInfoScreenSelectableBackgroundNode + private let labelNode: ImmediateTextNode + private let textNode: ImmediateTextNode + private let arrowNode: ASImageNode + private let bottomSeparatorNode: ASDisplayNode + + private var item: PeerInfoScreenDisclosureItem? + + override init() { + var bringToFrontForHighlightImpl: (() -> Void)? + self.selectionNode = PeerInfoScreenSelectableBackgroundNode(bringToFrontForHighlight: { bringToFrontForHighlightImpl?() }) + + self.labelNode = ImmediateTextNode() + self.labelNode.displaysAsynchronously = false + self.labelNode.isUserInteractionEnabled = false + + self.textNode = ImmediateTextNode() + self.textNode.displaysAsynchronously = false + self.textNode.isUserInteractionEnabled = false + + self.arrowNode = ASImageNode() + self.arrowNode.isLayerBacked = true + self.arrowNode.displaysAsynchronously = false + self.arrowNode.displayWithoutProcessing = true + self.arrowNode.isUserInteractionEnabled = false + + self.bottomSeparatorNode = ASDisplayNode() + self.bottomSeparatorNode.isLayerBacked = true + + super.init() + + bringToFrontForHighlightImpl = { [weak self] in + self?.bringToFrontForHighlight?() + } + + self.addSubnode(self.bottomSeparatorNode) + self.addSubnode(self.selectionNode) + self.addSubnode(self.labelNode) + self.addSubnode(self.textNode) + self.addSubnode(self.arrowNode) + } + + override func update(width: CGFloat, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, transition: ContainedViewLayoutTransition) -> CGFloat { + guard let item = item as? PeerInfoScreenDisclosureItem else { + return 10.0 + } + + self.item = item + + self.selectionNode.pressed = item.action + + let sideInset: CGFloat = 16.0 + + self.bottomSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor + + let textColorValue: UIColor = presentationData.theme.list.itemPrimaryTextColor + let labelColorValue: UIColor = presentationData.theme.list.itemSecondaryTextColor + + self.labelNode.attributedText = NSAttributedString(string: item.label, font: Font.regular(17.0), textColor: labelColorValue) + + self.textNode.maximumNumberOfLines = 1 + self.textNode.attributedText = NSAttributedString(string: item.text, font: Font.regular(17.0), textColor: textColorValue) + + let textSize = self.textNode.updateLayout(CGSize(width: width - sideInset * 2.0, height: .greatestFiniteMagnitude)) + let labelSize = self.labelNode.updateLayout(CGSize(width: width - textSize.width - sideInset * 2.0, height: .greatestFiniteMagnitude)) + + let arrowInset: CGFloat = 18.0 + + let textFrame = CGRect(origin: CGPoint(x: sideInset, y: 11.0), size: textSize) + let labelFrame = CGRect(origin: CGPoint(x: width - sideInset - arrowInset - labelSize.width, y: 11.0), size: labelSize) + + let height = textSize.height + 22.0 + + if let arrowImage = PresentationResourcesItemList.disclosureArrowImage(presentationData.theme) { + self.arrowNode.image = arrowImage + let arrowFrame = CGRect(origin: CGPoint(x: width - 7.0 - arrowImage.size.width, y: floorToScreenPixels((height - arrowImage.size.height) / 2.0)), size: arrowImage.size) + transition.updateFrame(node: self.arrowNode, frame: arrowFrame) + } + + transition.updateFrame(node: self.labelNode, frame: labelFrame) + transition.updateFrame(node: self.textNode, frame: textFrame) + + let highlightNodeOffset: CGFloat = topItem == nil ? 0.0 : UIScreenPixel + self.selectionNode.update(size: CGSize(width: width, height: height + highlightNodeOffset), theme: presentationData.theme, transition: transition) + transition.updateFrame(node: self.selectionNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -highlightNodeOffset), size: CGSize(width: width, height: height + highlightNodeOffset))) + + transition.updateFrame(node: self.bottomSeparatorNode, frame: CGRect(origin: CGPoint(x: sideInset, y: height - UIScreenPixel), size: CGSize(width: width - sideInset, height: UIScreenPixel))) + transition.updateAlpha(node: self.bottomSeparatorNode, alpha: bottomItem == nil ? 0.0 : 1.0) + + return height + } +} diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoScreenSwitchItem.swift b/submodules/TelegramUI/TelegramUI/PeerInfoScreenSwitchItem.swift new file mode 100644 index 0000000000..8a798af589 --- /dev/null +++ b/submodules/TelegramUI/TelegramUI/PeerInfoScreenSwitchItem.swift @@ -0,0 +1,121 @@ +import AsyncDisplayKit +import Display +import TelegramPresentationData + +final class PeerInfoScreenSwitchItem: PeerInfoScreenItem { + let id: AnyHashable + let text: String + let value: Bool + let toggled: ((Bool) -> Void)? + + init(id: AnyHashable, text: String, value: Bool, toggled: ((Bool) -> Void)?) { + self.id = id + self.text = text + self.value = value + self.toggled = toggled + } + + func node() -> PeerInfoScreenItemNode { + return PeerInfoScreenSwitchItemNode() + } +} + +private final class PeerInfoScreenSwitchItemNode: PeerInfoScreenItemNode { + private let selectionNode: PeerInfoScreenSelectableBackgroundNode + private let textNode: ImmediateTextNode + private let switchNode: SwitchNode + private let bottomSeparatorNode: ASDisplayNode + + private var item: PeerInfoScreenSwitchItem? + + private var theme: PresentationTheme? + + override init() { + var bringToFrontForHighlightImpl: (() -> Void)? + self.selectionNode = PeerInfoScreenSelectableBackgroundNode(bringToFrontForHighlight: { bringToFrontForHighlightImpl?() }) + + self.textNode = ImmediateTextNode() + self.textNode.displaysAsynchronously = false + self.textNode.isUserInteractionEnabled = false + + self.switchNode = SwitchNode() + + self.bottomSeparatorNode = ASDisplayNode() + self.bottomSeparatorNode.isLayerBacked = true + + super.init() + + bringToFrontForHighlightImpl = { [weak self] in + self?.bringToFrontForHighlight?() + } + + self.addSubnode(self.bottomSeparatorNode) + self.addSubnode(self.selectionNode) + self.addSubnode(self.textNode) + self.addSubnode(self.switchNode) + + self.switchNode.valueUpdated = { [weak self] value in + self?.item?.toggled?(value) + } + } + + override func update(width: CGFloat, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, transition: ContainedViewLayoutTransition) -> CGFloat { + guard let item = item as? PeerInfoScreenSwitchItem else { + return 10.0 + } + + let firstTime = self.item == nil + + if self.theme !== presentationData.theme { + self.theme = presentationData.theme + + self.switchNode.frameColor = presentationData.theme.list.itemSwitchColors.frameColor + self.switchNode.contentColor = presentationData.theme.list.itemSwitchColors.contentColor + self.switchNode.handleColor = presentationData.theme.list.itemSwitchColors.handleColor + } + + self.item = item + + self.selectionNode.pressed = nil + + let sideInset: CGFloat = 16.0 + + self.bottomSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor + + let textColorValue: UIColor = presentationData.theme.list.itemPrimaryTextColor + + self.textNode.maximumNumberOfLines = 1 + self.textNode.attributedText = NSAttributedString(string: item.text, font: Font.regular(17.0), textColor: textColorValue) + + let textSize = self.textNode.updateLayout(CGSize(width: width - sideInset * 2.0 - 56.0, height: .greatestFiniteMagnitude)) + + let arrowInset: CGFloat = 18.0 + + let textFrame = CGRect(origin: CGPoint(x: sideInset, y: 11.0), size: textSize) + + let height = textSize.height + 22.0 + + transition.updateFrame(node: self.textNode, frame: textFrame) + + if let switchView = self.switchNode.view as? UISwitch { + if self.switchNode.bounds.size.width.isZero { + switchView.sizeToFit() + } + let switchSize = switchView.bounds.size + + self.switchNode.frame = CGRect(origin: CGPoint(x: width - switchSize.width - 15.0, y: floor((height - switchSize.height) / 2.0)), size: switchSize) + if switchView.isOn != item.value { + switchView.setOn(item.value, animated: !firstTime) + } + } + + let highlightNodeOffset: CGFloat = topItem == nil ? 0.0 : UIScreenPixel + self.selectionNode.update(size: CGSize(width: width, height: height + highlightNodeOffset), theme: presentationData.theme, transition: transition) + transition.updateFrame(node: self.selectionNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -highlightNodeOffset), size: CGSize(width: width, height: height + highlightNodeOffset))) + + transition.updateFrame(node: self.bottomSeparatorNode, frame: CGRect(origin: CGPoint(x: sideInset, y: height - UIScreenPixel), size: CGSize(width: width - sideInset, height: UIScreenPixel))) + transition.updateAlpha(node: self.bottomSeparatorNode, alpha: bottomItem == nil ? 0.0 : 1.0) + + return height + } +} diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoVisualMediaPane.swift b/submodules/TelegramUI/TelegramUI/PeerInfoVisualMediaPane.swift index f49d9978e6..5cca69a898 100644 --- a/submodules/TelegramUI/TelegramUI/PeerInfoVisualMediaPane.swift +++ b/submodules/TelegramUI/TelegramUI/PeerInfoVisualMediaPane.swift @@ -8,13 +8,26 @@ import TelegramPresentationData import AccountContext import ContextUI import PhotoResources +import RadialStatusNode +import TelegramStringFormatting +import GridMessageSelectionNode + +private let mediaBadgeBackgroundColor = UIColor(white: 0.0, alpha: 0.6) +private let mediaBadgeTextColor = UIColor.white private final class VisualMediaItemInteraction { let openMessage: (MessageId) -> Void - var hiddenMedia: [MessageId: [Media]] = [:] + let toggleSelection: (MessageId) -> Void - init(openMessage: @escaping (MessageId) -> Void) { + var hiddenMedia: [MessageId: [Media]] = [:] + var selectedMessageIds: Set? + + init( + openMessage: @escaping (MessageId) -> Void, + toggleSelection: @escaping (MessageId) -> Void + ) { self.openMessage = openMessage + self.toggleSelection = toggleSelection } } @@ -24,12 +37,16 @@ private final class VisualMediaItemNode: ASDisplayNode { private let containerNode: ContextControllerSourceNode private let imageNode: TransformImageNode + private var statusNode: RadialStatusNode + private let mediaBadgeNode: ChatMessageInteractiveMediaBadge + private var selectionNode: GridMessageSelectionNode? private let fetchStatusDisposable = MetaDisposable() private let fetchDisposable = MetaDisposable() private var resourceStatus: MediaResourceStatus? private var item: (VisualMediaItem, Media?, CGSize, CGSize?)? + private var theme: PresentationTheme? init(context: AccountContext, interaction: VisualMediaItemInteraction) { self.context = context @@ -37,11 +54,19 @@ private final class VisualMediaItemNode: ASDisplayNode { self.containerNode = ContextControllerSourceNode() self.imageNode = TransformImageNode() + self.statusNode = RadialStatusNode(backgroundNodeColor: UIColor(white: 0.0, alpha: 0.6)) + let progressDiameter: CGFloat = 40.0 + self.statusNode.frame = CGRect(x: 0.0, y: 0.0, width: progressDiameter, height: progressDiameter) + self.statusNode.isUserInteractionEnabled = false + + self.mediaBadgeNode = ChatMessageInteractiveMediaBadge() + self.mediaBadgeNode.frame = CGRect(origin: CGPoint(x: 6.0, y: 6.0), size: CGSize(width: 50.0, height: 50.0)) super.init() self.addSubnode(self.containerNode) self.containerNode.addSubnode(self.imageNode) + self.containerNode.addSubnode(self.mediaBadgeNode) self.containerNode.isGestureEnabled = false } @@ -69,6 +94,7 @@ private final class VisualMediaItemNode: ASDisplayNode { if item === self.item?.0 && size == self.item?.2 { return } + self.theme = theme var media: Media? for value in item.message.media { if let image = value as? TelegramMediaImage { @@ -88,20 +114,20 @@ private final class VisualMediaItemNode: ASDisplayNode { self.imageNode.setSignal(mediaGridMessagePhoto(account: context.account, photoReference: .message(message: MessageReference(item.message), media: image), fullRepresentationSize: CGSize(width: 300.0, height: 300.0), synchronousLoad: synchronousLoad), attemptSynchronously: synchronousLoad, dispatchOnDisplayLink: true) self.fetchStatusDisposable.set(nil) - /*self.statusNode.transitionToState(.none, completion: { [weak self] in + self.statusNode.transitionToState(.none, completion: { [weak self] in self?.statusNode.isHidden = true - })*/ - //self.mediaBadgeNode.isHidden = true + }) + self.mediaBadgeNode.isHidden = true self.resourceStatus = nil } else if let file = media as? TelegramMediaFile, file.isVideo { mediaDimensions = file.dimensions?.cgSize self.imageNode.setSignal(mediaGridMessageVideo(postbox: context.account.postbox, videoReference: .message(message: MessageReference(item.message), media: file), synchronousLoad: synchronousLoad, autoFetchFullSizeThumbnail: true), attemptSynchronously: synchronousLoad) - /*self.mediaBadgeNode.isHidden = false + self.mediaBadgeNode.isHidden = false self.resourceStatus = nil - self.fetchStatusDisposable.set((messageMediaFileStatus(context: context, messageId: messageId, file: file) |> deliverOnMainQueue).start(next: { [weak self] status in - if let strongSelf = self, let item = strongSelf.item { + self.fetchStatusDisposable.set((messageMediaFileStatus(context: context, messageId: item.message.id, file: file) |> deliverOnMainQueue).start(next: { [weak self] status in + if let strongSelf = self, let (item, _, _, _) = strongSelf.item { strongSelf.resourceStatus = status let isStreamable = isMediaStreamable(message: item.message, media: file) @@ -158,18 +184,25 @@ private final class VisualMediaItemNode: ASDisplayNode { badgeContent = .text(inset: 0.0, backgroundColor: mediaBadgeBackgroundColor, foregroundColor: mediaBadgeTextColor, text: NSAttributedString(string: durationString)) } - strongSelf.mediaBadgeNode.update(theme: item.theme, content: badgeContent, mediaDownloadState: mediaDownloadState, alignment: .right, animated: false, badgeAnimated: false) + strongSelf.mediaBadgeNode.update(theme: nil, content: badgeContent, mediaDownloadState: mediaDownloadState, alignment: .right, animated: false, badgeAnimated: false) } } })) if self.statusNode.supernode == nil { self.imageNode.addSubnode(self.statusNode) - }*/ + } } else { - //self.mediaBadgeNode.isHidden = true + self.mediaBadgeNode.isHidden = true } self.item = (item, media, size, mediaDimensions) + let progressDiameter: CGFloat = 40.0 + self.statusNode.frame = CGRect(origin: CGPoint(x: floor((size.width - progressDiameter) / 2.0), y: floor((size.height - progressDiameter) / 2.0)), size: CGSize(width: progressDiameter, height: progressDiameter)) + + self.mediaBadgeNode.frame = CGRect(origin: CGPoint(x: size.width - 3.0, y: size.height - 18.0 - 3.0), size: CGSize(width: 50.0, height: 50.0)) + + self.selectionNode?.frame = CGRect(origin: CGPoint(), size: size) + self.updateHiddenMedia() } @@ -185,6 +218,46 @@ private final class VisualMediaItemNode: ASDisplayNode { let imageSize = mediaDimensions.aspectFilled(imageFrame.size) self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageFrame.size, intrinsicInsets: UIEdgeInsets(), emptyColor: theme.list.mediaPlaceholderColor))() } + + self.updateSelectionState(animated: false) + } + } + + func updateSelectionState(animated: Bool) { + if let (item, media, _, mediaDimensions) = self.item, let theme = self.theme { + if let selectedIds = self.interaction.selectedMessageIds { + let selected = selectedIds.contains(item.message.id) + + if let selectionNode = self.selectionNode { + selectionNode.updateSelected(selected, animated: animated) + selectionNode.frame = CGRect(origin: CGPoint(), size: self.bounds.size) + } else { + let selectionNode = GridMessageSelectionNode(theme: theme, toggle: { [weak self] value in + if let strongSelf = self, let messageId = strongSelf.item?.0.message.id { + strongSelf.interaction.toggleSelection(messageId) + } + }) + + selectionNode.frame = CGRect(origin: CGPoint(), size: self.bounds.size) + self.containerNode.addSubnode(selectionNode) + self.selectionNode = selectionNode + selectionNode.updateSelected(selected, animated: false) + if animated { + selectionNode.animateIn() + } + } + } else { + if let selectionNode = self.selectionNode { + self.selectionNode = nil + if animated { + selectionNode.animateOut { [weak selectionNode] in + selectionNode?.removeFromSupernode() + } + } else { + selectionNode.removeFromSupernode() + } + } + } } } @@ -194,15 +267,15 @@ private final class VisualMediaItemNode: ASDisplayNode { var statusNodeHidden = false var accessoryHidden = false if let strongSelf = self { - //statusNodeHidden = strongSelf.statusNode.isHidden - //accessoryHidden = strongSelf.mediaBadgeNode.isHidden - //strongSelf.statusNode.isHidden = true - //strongSelf.mediaBadgeNode.isHidden = true + statusNodeHidden = strongSelf.statusNode.isHidden + accessoryHidden = strongSelf.mediaBadgeNode.isHidden + strongSelf.statusNode.isHidden = true + strongSelf.mediaBadgeNode.isHidden = true } let view = imageNode?.view.snapshotContentTree(unhide: true) if let strongSelf = self { - //strongSelf.statusNode.isHidden = statusNodeHidden - //strongSelf.mediaBadgeNode.isHidden = accessoryHidden + strongSelf.statusNode.isHidden = statusNodeHidden + strongSelf.mediaBadgeNode.isHidden = accessoryHidden } return (view, nil) }) @@ -232,6 +305,8 @@ private final class VisualMediaItem { final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScrollViewDelegate { private let context: AccountContext private let peerId: PeerId + private let interaction: PeerInfoPaneInteraction + private let scrollNode: ASScrollNode private var _itemInteraction: VisualMediaItemInteraction? @@ -257,17 +332,24 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro private var isRequestingView: Bool = false private var isFirstHistoryView: Bool = true - init(context: AccountContext, openMessage: @escaping (MessageId) -> Bool, peerId: PeerId) { + init(context: AccountContext, openMessage: @escaping (MessageId) -> Bool, peerId: PeerId, interaction: PeerInfoPaneInteraction) { self.context = context self.peerId = peerId + self.interaction = interaction self.scrollNode = ASScrollNode() super.init() - self._itemInteraction = VisualMediaItemInteraction(openMessage: { id in - openMessage(id) - }) + self._itemInteraction = VisualMediaItemInteraction( + openMessage: { id in + openMessage(id) + }, + toggleSelection: { id in + interaction.toggleMessageSelected(id) + } + ) + self.itemInteraction.selectedMessageIds = self.interaction.selectedMessageIds self.scrollNode.view.showsVerticalScrollIndicator = false if #available(iOS 11.0, *) { @@ -372,6 +454,13 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro return nil } + func updateSelectedMessages(animated: Bool) { + self.itemInteraction.selectedMessageIds = self.interaction.selectedMessageIds + for (_, itemNode) in self.visibleMediaItems { + itemNode.updateSelectionState(animated: animated) + } + } + func update(size: CGSize, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) { self.currentParams = (size, isScrollingLockedAtTop, presentationData) @@ -420,10 +509,10 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro maxVisibleRow = min(rowCount - 1, maxVisibleRow) let minVisibleIndex = minVisibleRow * itemsInRow - let maxVisibleIndex = min(self.mediaItems.count - 1, maxVisibleRow * itemsInRow - 1) + let maxVisibleIndex = min(self.mediaItems.count - 1, (maxVisibleRow + 1) * itemsInRow - 1) var validIds = Set() - if minVisibleIndex < maxVisibleIndex { + if minVisibleIndex <= maxVisibleIndex { for i in minVisibleIndex ... maxVisibleIndex { let stableId = self.mediaItems[i].message.stableId validIds.insert(stableId) diff --git a/submodules/TelegramUI/TelegramUI/Resources/PresentationStrings.mapping b/submodules/TelegramUI/TelegramUI/Resources/PresentationStrings.mapping index 7a9fbcb92d1b736e700de3e9ded72262041c5c91..710b3a4ac155ae2009ce9a760e2bab73654950da 100644 GIT binary patch delta 43885 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 delta 44333 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 M)aE$~3WXQ_A0_%ee*gdg diff --git a/submodules/WalletUI/Resources/WalletStrings.mapping b/submodules/WalletUI/Resources/WalletStrings.mapping index 589c6fe85e4fa03a50b6adefffe67915bd39bf1c..9f7c34892095545bdfb3f1e1871a24394137ff12 100644 GIT binary patch delta 17 YcmX@$c))Q(i^Al^3bKrhlN%M}070t;9smFU delta 40 vcmX@$c))Q(i-L?e0|P^NVopwKiC$ String { + public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, stringValue) } - public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String { + public func Wallet_Updated_HoursAgo(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, stringValue) From e2b36c872de8140baee44c9413a4aa86018ab05d Mon Sep 17 00:00:00 2001 From: overtake Date: Fri, 7 Feb 2020 18:53:36 +0400 Subject: [PATCH 44/50] no message --- submodules/Postbox/Sources/Coding.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submodules/Postbox/Sources/Coding.swift b/submodules/Postbox/Sources/Coding.swift index 0e73649666..e25c870781 100644 --- a/submodules/Postbox/Sources/Coding.swift +++ b/submodules/Postbox/Sources/Coding.swift @@ -77,7 +77,7 @@ public class MemoryBuffer: Equatable, CustomStringConvertible { data.copyBytes(to: self.memory.assumingMemoryBound(to: UInt8.self), count: data.count) self.capacity = data.count self.length = data.count - self.freeWhenDone = false + self.freeWhenDone = true } } From 9f73cc401853620b376ba77d849a37430653faf1 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 7 Feb 2020 22:09:58 +0000 Subject: [PATCH 45/50] Mixed WIP --- NotificationService/Serialization.m | 2 +- .../Sources/ChatListController.swift | 49 +-- .../Sources/ChatListControllerNode.swift | 4 +- .../ChatListFilterPresetController.swift | 47 +- .../ChatListFilterPresetListController.swift | 50 +-- .../ChatListFilterPresetListItem.swift | 12 +- .../Sources/Node/ChatListNode.swift | 24 +- .../Sources/Node/ChatListNodeLocation.swift | 26 +- .../Sources/Node/ChatListViewTransition.swift | 2 +- .../TabBarChatListFilterController.swift | 46 +- submodules/Display/Display/ListView.swift | 48 +++ submodules/SyncCore/Sources/Namespaces.swift | 7 + .../TextEntitiesMessageAttribute.swift | 5 + submodules/TelegramApi/Sources/Api0.swift | 32 +- submodules/TelegramApi/Sources/Api1.swift | 404 +++++++++++++++++- submodules/TelegramApi/Sources/Api2.swift | 178 ++++++++ submodules/TelegramApi/Sources/Api3.swift | 92 ++++ submodules/TelegramCore/Sources/Account.swift | 1 + .../TelegramCore/Sources/AccountManager.swift | 1 + .../Sources/ChatListFiltering.swift | 378 ++++++++++++++++ .../ManagedSecretChatOutgoingOperations.swift | 4 + .../TelegramCore/Sources/Serialization.swift | 2 +- .../Sources/StoreMessage_Telegram.swift | 2 + .../TextEntitiesMessageAttribute.swift | 2 + .../Sources/UpdateCachedPeerData.swift | 2 +- .../TelegramUI/DeclareEncodables.swift | 1 - .../TelegramUI/PeerInfoFilesPane.swift | 8 +- .../PeerInfoGroupsInCommonPaneNode.swift | 5 +- .../TelegramUI/PeerInfoScreen.swift | 106 +++-- .../TelegramUI/PeerInfoVisualMediaPane.swift | 83 +++- .../Sources/ChatListFilterSettings.swift | 135 ------ 31 files changed, 1424 insertions(+), 334 deletions(-) create mode 100644 submodules/TelegramCore/Sources/ChatListFiltering.swift delete mode 100644 submodules/TelegramUIPreferences/Sources/ChatListFilterSettings.swift diff --git a/NotificationService/Serialization.m b/NotificationService/Serialization.m index 00a0621e3e..f7eea7807e 100644 --- a/NotificationService/Serialization.m +++ b/NotificationService/Serialization.m @@ -3,7 +3,7 @@ @implementation Serialization - (NSUInteger)currentLayer { - return 109; + return 110; } - (id _Nullable)parseMessage:(NSData * _Nullable)data { diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 57510f6e06..19bdb612a4 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -107,6 +107,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, private let hideNetworkActivityStatus: Bool public let groupId: PeerGroupId + public let filter: ChatListFilter? public let previewing: Bool let openMessageFromSearchDisposable: MetaDisposable = MetaDisposable() @@ -145,12 +146,13 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, } } - public init(context: AccountContext, groupId: PeerGroupId, controlsHistoryPreload: Bool, hideNetworkActivityStatus: Bool = false, previewing: Bool = false, enableDebugActions: Bool) { + public init(context: AccountContext, groupId: PeerGroupId, filter: ChatListFilter? = nil, controlsHistoryPreload: Bool, hideNetworkActivityStatus: Bool = false, previewing: Bool = false, enableDebugActions: Bool) { self.context = context self.controlsHistoryPreload = controlsHistoryPreload self.hideNetworkActivityStatus = hideNetworkActivityStatus self.groupId = groupId + self.filter = filter self.previewing = previewing self.presentationData = (context.sharedContext.currentPresentationData.with { $0 }) @@ -163,7 +165,9 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style let title: String - if case .root = self.groupId { + if let filter = self.filter { + title = filter.title ?? "" + } else if self.groupId == .root { title = self.presentationData.strings.DialogList_Title self.navigationBar?.item = nil } else { @@ -174,7 +178,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, self.navigationItem.titleView = self.titleView if !previewing { - if case .root = groupId { + if self.groupId == .root && self.filter == nil { self.tabBarItem.title = self.presentationData.strings.DialogList_Title let icon: UIImage? @@ -270,15 +274,9 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, ).start(next: { [weak self] networkState, proxy, passcode, state, chatListFilter in if let strongSelf = self { let defaultTitle: String - if case .root = strongSelf.groupId { + if strongSelf.groupId == .root { if let chatListFilter = chatListFilter { - let title: String - switch chatListFilter.name { - case .unread: - title = "Unread" - case let .custom(value): - title = value - } + let title: String = chatListFilter.title ?? "" defaultTitle = title } else { defaultTitle = strongSelf.presentationData.strings.DialogList_Title @@ -287,7 +285,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, defaultTitle = strongSelf.presentationData.strings.ChatList_ArchivedChatsTitle } if state.editing { - if case .root = strongSelf.groupId { + if strongSelf.groupId == .root && strongSelf.filter == nil { strongSelf.navigationItem.rightBarButtonItem = nil } @@ -297,9 +295,11 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, var isRoot = false if case .root = strongSelf.groupId { isRoot = true - let rightBarButtonItem = UIBarButtonItem(image: PresentationResourcesRootController.navigationComposeIcon(strongSelf.presentationData.theme), style: .plain, target: strongSelf, action: #selector(strongSelf.composePressed)) - rightBarButtonItem.accessibilityLabel = strongSelf.presentationData.strings.VoiceOver_Navigation_Compose - strongSelf.navigationItem.rightBarButtonItem = rightBarButtonItem + if strongSelf.filter == nil { + let rightBarButtonItem = UIBarButtonItem(image: PresentationResourcesRootController.navigationComposeIcon(strongSelf.presentationData.theme), style: .plain, target: strongSelf, action: #selector(strongSelf.composePressed)) + rightBarButtonItem.accessibilityLabel = strongSelf.presentationData.strings.VoiceOver_Navigation_Compose + strongSelf.navigationItem.rightBarButtonItem = rightBarButtonItem + } } let (hasProxy, connectsViaProxy) = proxy @@ -322,7 +322,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, case .online: strongSelf.titleView.title = NetworkStatusTitle(text: defaultTitle, activity: false, hasProxy: isRoot && hasProxy, connectsViaProxy: connectsViaProxy, isPasscodeSet: isRoot && isPasscodeSet, isManuallyLocked: isRoot && isManuallyLocked) } - if case .root = groupId, checkProxy { + if groupId == .root && filter == nil && checkProxy { if strongSelf.proxyUnavailableTooltipController == nil && !strongSelf.didShowProxyUnavailableTooltipController && strongSelf.isNodeLoaded && strongSelf.displayNode.view.window != nil && strongSelf.navigationController?.topViewController === self { strongSelf.didShowProxyUnavailableTooltipController = true let tooltipController = TooltipController(content: .text(strongSelf.presentationData.strings.Proxy_TooltipUnavailable), baseFontSize: strongSelf.presentationData.listsFontSize.baseDisplaySize, timeout: 60.0, dismissByTapOutside: true) @@ -444,7 +444,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, editItem = UIBarButtonItem(title: self.presentationData.strings.Common_Edit, style: .plain, target: self, action: #selector(self.editPressed)) editItem.accessibilityLabel = self.presentationData.strings.Common_Edit } - if case .root = self.groupId { + if self.groupId == .root && self.filter == nil { self.navigationItem.leftBarButtonItem = editItem let rightBarButtonItem = UIBarButtonItem(image: PresentationResourcesRootController.navigationComposeIcon(self.presentationData.theme), style: .plain, target: self, action: #selector(self.composePressed)) rightBarButtonItem.accessibilityLabel = self.presentationData.strings.VoiceOver_Navigation_Compose @@ -464,7 +464,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, } override public func loadDisplayNode() { - self.displayNode = ChatListControllerNode(context: self.context, groupId: self.groupId, previewing: self.previewing, controlsHistoryPreload: self.controlsHistoryPreload, presentationData: self.presentationData, controller: self) + self.displayNode = ChatListControllerNode(context: self.context, groupId: self.groupId, filter: self.filter, previewing: self.previewing, controlsHistoryPreload: self.controlsHistoryPreload, presentationData: self.presentationData, controller: self) self.chatListDisplayNode.navigationBar = self.navigationBar @@ -1810,9 +1810,9 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, public func presentTabBarPreviewingController(sourceNodes: [ASDisplayNode]) { if self.isNodeLoaded { - let _ = (self.context.account.postbox.transaction { transaction -> [ChatListFilterPreset] in - let settings = transaction.getPreferencesEntry(key: ApplicationSpecificPreferencesKeys.chatListFilterSettings) as? ChatListFilterSettings ?? ChatListFilterSettings.default - return settings.presets + let _ = (self.context.account.postbox.transaction { transaction -> [ChatListFilter] in + let settings = transaction.getPreferencesEntry(key: PreferencesKeys.chatListFilters) as? ChatListFiltersState ?? ChatListFiltersState.default + return settings.filters } |> deliverOnMainQueue).start(next: { [weak self] presetList in guard let strongSelf = self else { @@ -1826,7 +1826,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, guard let strongSelf = self else { return } - if let currentPreset = strongSelf.chatListDisplayNode.chatListNode.chatListFilter { + /*if let currentPreset = strongSelf.chatListDisplayNode.chatListNode.chatListFilter { var found = false if let index = presets.index(where: { $0.id == currentPreset.id }) { found = true @@ -1837,13 +1837,14 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, if !found { strongSelf.chatListDisplayNode.chatListNode.chatListFilter = nil } - } + }*/ })) }, updatePreset: { value in guard let strongSelf = self else { return } - strongSelf.chatListDisplayNode.chatListNode.chatListFilter = value + strongSelf.push(ChatListControllerImpl(context: strongSelf.context, groupId: .root, filter: value, controlsHistoryPreload: false, hideNetworkActivityStatus: true, previewing: false, enableDebugActions: false)) + //strongSelf.chatListDisplayNode.chatListNode.chatListFilter = value }) strongSelf.context.sharedContext.mainWindow?.present(controller, on: .root) }) diff --git a/submodules/ChatListUI/Sources/ChatListControllerNode.swift b/submodules/ChatListUI/Sources/ChatListControllerNode.swift index 3dd78330a6..9eb336e963 100644 --- a/submodules/ChatListUI/Sources/ChatListControllerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListControllerNode.swift @@ -72,12 +72,12 @@ final class ChatListControllerNode: ASDisplayNode { let debugListView = ListView() - init(context: AccountContext, groupId: PeerGroupId, previewing: Bool, controlsHistoryPreload: Bool, presentationData: PresentationData, controller: ChatListControllerImpl) { + init(context: AccountContext, groupId: PeerGroupId, filter: ChatListFilter?, previewing: Bool, controlsHistoryPreload: Bool, presentationData: PresentationData, controller: ChatListControllerImpl) { self.context = context self.groupId = groupId self.presentationData = presentationData - self.chatListNode = ChatListNode(context: context, groupId: groupId, previewing: previewing, controlsHistoryPreload: controlsHistoryPreload, mode: .chatList, theme: presentationData.theme, fontSize: presentationData.listsFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations) + self.chatListNode = ChatListNode(context: context, groupId: groupId, chatListFilter: filter, previewing: previewing, controlsHistoryPreload: controlsHistoryPreload, mode: .chatList, theme: presentationData.theme, fontSize: presentationData.listsFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations) self.controller = controller diff --git a/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift b/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift index 890a6414cc..27052bb641 100644 --- a/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift +++ b/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift @@ -35,7 +35,7 @@ private enum ChatListFilterPresetControllerSection: Int32 { case additionalPeers } -private func filterEntry(presentationData: ItemListPresentationData, arguments: ChatListFilterPresetControllerArguments, title: String, value: Bool, filter: ChatListIncludeCategoryFilter, section: Int32) -> ItemListCheckboxItem { +private func filterEntry(presentationData: ItemListPresentationData, arguments: ChatListFilterPresetControllerArguments, title: String, value: Bool, filter: ChatListFilterPeerCategories, section: Int32) -> ItemListCheckboxItem { return ItemListCheckboxItem(presentationData: presentationData, title: title, style: .left, checked: value, zeroSeparatorInsets: false, sectionId: section, action: { arguments.updateState { current in var state = current @@ -188,11 +188,7 @@ private enum ChatListFilterPresetEntry: ItemListNodeEntry { return ItemListSwitchItem(presentationData: presentationData, title: title, value: value, sectionId: self.section, style: .blocks, updated: { _ in arguments.updateState { current in var state = current - if state.includeCategories.contains(.muted) { - state.includeCategories.remove(.muted) - } else { - state.includeCategories.insert(.muted) - } + state.excludeMuted = !state.excludeMuted return state } }) @@ -200,11 +196,7 @@ private enum ChatListFilterPresetEntry: ItemListNodeEntry { return ItemListSwitchItem(presentationData: presentationData, title: title, value: value, sectionId: self.section, style: .blocks, updated: { _ in arguments.updateState { current in var state = current - if state.includeCategories.contains(.read) { - state.includeCategories.remove(.read) - } else { - state.includeCategories.insert(.read) - } + state.excludeRead = !state.excludeRead return state } }) @@ -230,7 +222,9 @@ private enum ChatListFilterPresetEntry: ItemListNodeEntry { private struct ChatListFilterPresetControllerState: Equatable { var name: String - var includeCategories: ChatListIncludeCategoryFilter + var includeCategories: ChatListFilterPeerCategories + var excludeMuted: Bool + var excludeRead: Bool var additionallyIncludePeers: [PeerId] var revealedPeerId: PeerId? @@ -239,7 +233,7 @@ private struct ChatListFilterPresetControllerState: Equatable { if self.name.isEmpty { return false } - if self.includeCategories.isEmpty && self.additionallyIncludePeers.isEmpty { + if self.includeCategories.isEmpty && self.additionallyIncludePeers.isEmpty && !self.excludeMuted && !self.excludeRead { return false } return true @@ -259,8 +253,8 @@ private func chatListFilterPresetControllerEntries(presentationData: Presentatio entries.append(.filterPublicGroups(title: "Public Groups", value: state.includeCategories.contains(.publicGroups))) entries.append(.filterChannels(title: "Channels", value: state.includeCategories.contains(.channels))) - entries.append(.filterMuted(title: "Exclude Muted", value: !state.includeCategories.contains(.muted))) - entries.append(.filterRead(title: "Exclude Read", value: !state.includeCategories.contains(.read))) + entries.append(.filterMuted(title: "Exclude Muted", value: state.excludeMuted)) + entries.append(.filterRead(title: "Exclude Read", value: state.excludeRead)) entries.append(.additionalPeersHeader("ALWAYS INCLUDE")) entries.append(.addAdditionalPeer(title: "Add")) @@ -274,19 +268,14 @@ private func chatListFilterPresetControllerEntries(presentationData: Presentatio return entries } -func chatListFilterPresetController(context: AccountContext, currentPreset: ChatListFilterPreset?, updated: @escaping ([ChatListFilterPreset]) -> Void) -> ViewController { +func chatListFilterPresetController(context: AccountContext, currentPreset: ChatListFilter?, updated: @escaping ([ChatListFilter]) -> Void) -> ViewController { let initialName: String if let currentPreset = currentPreset { - switch currentPreset.name { - case .unread: - initialName = "Unread" - case let .custom(value): - initialName = value - } + initialName = currentPreset.title ?? "" } else { initialName = "New Preset" } - let initialState = ChatListFilterPresetControllerState(name: initialName, includeCategories: currentPreset?.includeCategories ?? .all, additionallyIncludePeers: currentPreset?.additionallyIncludePeers ?? []) + let initialState = ChatListFilterPresetControllerState(name: initialName, includeCategories: currentPreset?.categories ?? .all, excludeMuted: currentPreset?.excludeMuted ?? false, excludeRead: currentPreset?.excludeRead ?? false, additionallyIncludePeers: currentPreset?.includePeers ?? []) let stateValue = Atomic(value: initialState) let statePromise = ValuePromise(initialState, ignoreRepeated: true) let updateState: ((ChatListFilterPresetControllerState) -> ChatListFilterPresetControllerState) -> Void = { f in @@ -378,15 +367,19 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat }) let rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Done), style: .bold, enabled: state.isComplete, action: { let state = stateValue.with { $0 } - let preset = ChatListFilterPreset(id: currentPreset?.id ?? arc4random64(), name: .custom(state.name), includeCategories: state.includeCategories, additionallyIncludePeers: state.additionallyIncludePeers) + let preset = ChatListFilter(id: currentPreset?.id ?? -1, title: state.name, categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, includePeers: state.additionallyIncludePeers) let _ = (updateChatListFilterSettingsInteractively(postbox: context.account.postbox, { settings in + var preset = preset + if currentPreset == nil { + preset.id = max(1, settings.filters.map({ $0.id }).max() ?? 1) + } var settings = settings - settings.presets = settings.presets.filter { $0 != preset && $0 != currentPreset } - settings.presets.append(preset) + settings.filters = settings.filters.filter { $0 != preset && $0 != currentPreset } + settings.filters.append(preset) return settings }) |> deliverOnMainQueue).start(next: { settings in - updated(settings.presets) + updated(settings.filters) dismissImpl?() }) }) diff --git a/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift b/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift index a3900429f8..c71904a4af 100644 --- a/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift +++ b/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift @@ -13,12 +13,12 @@ import AccountContext private final class ChatListFilterPresetListControllerArguments { let context: AccountContext - let openPreset: (ChatListFilterPreset) -> Void + let openPreset: (ChatListFilter) -> Void let addNew: () -> Void - let setItemWithRevealedOptions: (ChatListFilterPreset?, ChatListFilterPreset?) -> Void - let removePreset: (ChatListFilterPreset) -> Void + let setItemWithRevealedOptions: (Int32?, Int32?) -> Void + let removePreset: (Int32) -> Void - init(context: AccountContext, openPreset: @escaping (ChatListFilterPreset) -> Void, addNew: @escaping () -> Void, setItemWithRevealedOptions: @escaping (ChatListFilterPreset?, ChatListFilterPreset?) -> Void, removePreset: @escaping (ChatListFilterPreset) -> Void) { + init(context: AccountContext, openPreset: @escaping (ChatListFilter) -> Void, addNew: @escaping () -> Void, setItemWithRevealedOptions: @escaping (Int32?, Int32?) -> Void, removePreset: @escaping (Int32) -> Void) { self.context = context self.openPreset = openPreset self.addNew = addNew @@ -45,14 +45,14 @@ private func stringForUserCount(_ peers: [PeerId: SelectivePrivacyPeer], strings private enum ChatListFilterPresetListEntryStableId: Hashable { case listHeader - case preset(Int64) + case preset(Int32) case addItem case listFooter } private enum ChatListFilterPresetListEntry: ItemListNodeEntry { case listHeader(String) - case preset(index: Int, title: String, preset: ChatListFilterPreset, canBeReordered: Bool, canBeDeleted: Bool) + case preset(index: Int, title: String?, preset: ChatListFilter, canBeReordered: Bool, canBeDeleted: Bool) case addItem(String) case listFooter(String) @@ -99,12 +99,12 @@ private enum ChatListFilterPresetListEntry: ItemListNodeEntry { case let .listHeader(text): return ItemListSectionHeaderItem(presentationData: presentationData, text: text, multiline: true, sectionId: self.section) case let .preset(index, title, preset, canBeReordered, canBeDeleted): - return ChatListFilterPresetListItem(presentationData: presentationData, preset: preset, title: title, editing: ChatListFilterPresetListItemEditing(editable: true, editing: false, revealed: false), canBeReordered: canBeReordered, canBeDeleted: canBeDeleted, sectionId: self.section, action: { + return ChatListFilterPresetListItem(presentationData: presentationData, preset: preset, title: title ?? "", editing: ChatListFilterPresetListItemEditing(editable: true, editing: false, revealed: false), canBeReordered: canBeReordered, canBeDeleted: canBeDeleted, sectionId: self.section, action: { arguments.openPreset(preset) }, setItemWithRevealedOptions: { lhs, rhs in arguments.setItemWithRevealedOptions(lhs, rhs) }, remove: { - arguments.removePreset(preset) + arguments.removePreset(preset.id) }) case let .addItem(text): return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: { @@ -117,22 +117,15 @@ private enum ChatListFilterPresetListEntry: ItemListNodeEntry { } private struct ChatListFilterPresetListControllerState: Equatable { - var revealedPreset: ChatListFilterPreset? = nil + var revealedPreset: Int32? = nil } -private func chatListFilterPresetListControllerEntries(presentationData: PresentationData, state: ChatListFilterPresetListControllerState, settings: ChatListFilterSettings) -> [ChatListFilterPresetListEntry] { +private func chatListFilterPresetListControllerEntries(presentationData: PresentationData, state: ChatListFilterPresetListControllerState, settings: ChatListFiltersState) -> [ChatListFilterPresetListEntry] { var entries: [ChatListFilterPresetListEntry] = [] - entries.append(.listHeader("PRESETS")) - for preset in settings.presets { - let title: String - switch preset.name { - case .unread: - title = "Unread" - case let .custom(value): - title = value - } - entries.append(.preset(index: entries.count, title: title, preset: preset, canBeReordered: settings.presets.count > 1, canBeDeleted: true)) + entries.append(.listHeader("FILTERS")) + for preset in settings.filters { + entries.append(.preset(index: entries.count, title: preset.title, preset: preset, canBeReordered: settings.filters.count > 1, canBeDeleted: true)) } entries.append(.addItem("Add New")) entries.append(.listFooter("Add custom presets")) @@ -140,7 +133,7 @@ private func chatListFilterPresetListControllerEntries(presentationData: Present return entries } -func chatListFilterPresetListController(context: AccountContext, updated: @escaping ([ChatListFilterPreset]) -> Void) -> ViewController { +func chatListFilterPresetListController(context: AccountContext, updated: @escaping ([ChatListFilter]) -> Void) -> ViewController { let initialState = ChatListFilterPresetListControllerState() let statePromise = ValuePromise(initialState, ignoreRepeated: true) let stateValue = Atomic(value: initialState) @@ -164,20 +157,20 @@ func chatListFilterPresetListController(context: AccountContext, updated: @escap } return state } - }, removePreset: { preset in + }, removePreset: { id in let _ = (updateChatListFilterSettingsInteractively(postbox: context.account.postbox, { settings in var settings = settings - if let index = settings.presets.index(of: preset) { - settings.presets.remove(at: index) + if let index = settings.filters.index(where: { $0.id == id }) { + settings.filters.remove(at: index) } return settings }) |> deliverOnMainQueue).start(next: { settings in - updated(settings.presets) + updated(settings.filters) }) }) - let preferences = context.account.postbox.preferencesView(keys: [ApplicationSpecificPreferencesKeys.chatListFilterSettings]) + let preferences = context.account.postbox.preferencesView(keys: [PreferencesKeys.chatListFilters]) let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, @@ -185,12 +178,13 @@ func chatListFilterPresetListController(context: AccountContext, updated: @escap preferences ) |> map { presentationData, state, preferences -> (ItemListControllerState, (ItemListNodeState, Any)) in - let settings = preferences.values[ApplicationSpecificPreferencesKeys.chatListFilterSettings] as? ChatListFilterSettings ?? ChatListFilterSettings.default + let settings = preferences.values[PreferencesKeys.chatListFilters] as? ChatListFiltersState ?? ChatListFiltersState.default let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Close), style: .regular, enabled: true, action: { + let _ = replaceRemoteChatListFilters(account: context.account).start() dismissImpl?() }) - let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text("Filter Presets"), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false) + let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text("Filter Presets"), leftNavigationButton: leftNavigationButton, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false) let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: chatListFilterPresetListControllerEntries(presentationData: presentationData, state: state, settings: settings), style: .blocks, animateChanges: true) return (controllerState, (listState, arguments)) diff --git a/submodules/ChatListUI/Sources/ChatListFilterPresetListItem.swift b/submodules/ChatListUI/Sources/ChatListFilterPresetListItem.swift index 4e8454897f..adad852881 100644 --- a/submodules/ChatListUI/Sources/ChatListFilterPresetListItem.swift +++ b/submodules/ChatListUI/Sources/ChatListFilterPresetListItem.swift @@ -18,26 +18,26 @@ struct ChatListFilterPresetListItemEditing: Equatable { final class ChatListFilterPresetListItem: ListViewItem, ItemListItem { let presentationData: ItemListPresentationData - let preset: ChatListFilterPreset + let preset: ChatListFilter let title: String let editing: ChatListFilterPresetListItemEditing let canBeReordered: Bool let canBeDeleted: Bool let sectionId: ItemListSectionId let action: () -> Void - let setItemWithRevealedOptions: (ChatListFilterPreset?, ChatListFilterPreset?) -> Void + let setItemWithRevealedOptions: (Int32?, Int32?) -> Void let remove: () -> Void init( presentationData: ItemListPresentationData, - preset: ChatListFilterPreset, + preset: ChatListFilter, title: String, editing: ChatListFilterPresetListItemEditing, canBeReordered: Bool, canBeDeleted: Bool, sectionId: ItemListSectionId, action: @escaping () -> Void, - setItemWithRevealedOptions: @escaping (ChatListFilterPreset?, ChatListFilterPreset?) -> Void, + setItemWithRevealedOptions: @escaping (Int32?, Int32?) -> Void, remove: @escaping () -> Void ) { self.presentationData = presentationData @@ -409,13 +409,13 @@ private final class ChatListFilterPresetListItemNode: ItemListRevealOptionsItemN override func revealOptionsInteractivelyOpened() { if let item = self.item { - item.setItemWithRevealedOptions(item.preset, nil) + item.setItemWithRevealedOptions(item.preset.id, nil) } } override func revealOptionsInteractivelyClosed() { if let item = self.item { - item.setItemWithRevealedOptions(nil, item.preset) + item.setItemWithRevealedOptions(nil, item.preset.id) } } diff --git a/submodules/ChatListUI/Sources/Node/ChatListNode.swift b/submodules/ChatListUI/Sources/Node/ChatListNode.swift index 3bd95959cd..fdd814e57a 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNode.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNode.swift @@ -366,21 +366,9 @@ public final class ChatListNode: ListView { } private var currentLocation: ChatListNodeLocation? - var chatListFilter: ChatListFilterPreset? { - didSet { - if self.chatListFilter != oldValue { - self.chatListFilterValue.set(self.chatListFilter) - - if self.chatListFilter?.includeCategories != oldValue?.includeCategories || self.chatListFilter?.additionallyIncludePeers != oldValue?.additionallyIncludePeers { - if let currentLocation = self.currentLocation { - self.setChatListLocation(.initial(count: 50, filter: self.chatListFilter)) - } - } - } - } - } - private let chatListFilterValue = ValuePromise(nil) - var chatListFilterSignal: Signal { + let chatListFilter: ChatListFilter? + private let chatListFilterValue = Promise() + var chatListFilterSignal: Signal { return self.chatListFilterValue.get() } private let chatListLocation = ValuePromise() @@ -425,9 +413,11 @@ public final class ChatListNode: ListView { private var hapticFeedback: HapticFeedback? - public init(context: AccountContext, groupId: PeerGroupId, previewing: Bool, controlsHistoryPreload: Bool, mode: ChatListNodeMode, theme: PresentationTheme, fontSize: PresentationFontSize, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, disableAnimations: Bool) { + public init(context: AccountContext, groupId: PeerGroupId, chatListFilter: ChatListFilter? = nil, previewing: Bool, controlsHistoryPreload: Bool, mode: ChatListNodeMode, theme: PresentationTheme, fontSize: PresentationFontSize, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, disableAnimations: Bool) { self.context = context self.groupId = groupId + self.chatListFilter = chatListFilter + self.chatListFilterValue.set(.single(chatListFilter)) self.controlsHistoryPreload = controlsHistoryPreload self.mode = mode @@ -541,7 +531,7 @@ public final class ChatListNode: ListView { let chatListViewUpdate = self.chatListLocation.get() |> distinctUntilChanged - |> mapToSignal { location -> Signal<(ChatListNodeViewUpdate, ChatListFilterPreset?), NoError> in + |> mapToSignal { location -> Signal<(ChatListNodeViewUpdate, ChatListFilter?), NoError> in return chatListViewForLocation(groupId: groupId, location: location, account: context.account) |> map { update in return (update, location.filter) diff --git a/submodules/ChatListUI/Sources/Node/ChatListNodeLocation.swift b/submodules/ChatListUI/Sources/Node/ChatListNodeLocation.swift index 314f319a9d..5878d7df08 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNodeLocation.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNodeLocation.swift @@ -7,11 +7,11 @@ import Display import TelegramUIPreferences enum ChatListNodeLocation: Equatable { - case initial(count: Int, filter: ChatListFilterPreset?) - case navigation(index: ChatListIndex, filter: ChatListFilterPreset?) - case scroll(index: ChatListIndex, sourceIndex: ChatListIndex, scrollPosition: ListViewScrollPosition, animated: Bool, filter: ChatListFilterPreset?) + case initial(count: Int, filter: ChatListFilter?) + case navigation(index: ChatListIndex, filter: ChatListFilter?) + case scroll(index: ChatListIndex, sourceIndex: ChatListIndex, scrollPosition: ListViewScrollPosition, animated: Bool, filter: ChatListFilter?) - var filter: ChatListFilterPreset? { + var filter: ChatListFilter? { switch self { case let .initial(initial): return initial.filter @@ -32,17 +32,17 @@ struct ChatListNodeViewUpdate { func chatListViewForLocation(groupId: PeerGroupId, location: ChatListNodeLocation, account: Account) -> Signal { let filterPredicate: ((Peer, PeerNotificationSettings?, Bool) -> Bool)? if let filter = location.filter { - let includePeers = Set(filter.additionallyIncludePeers) + let includePeers = Set(filter.includePeers) filterPredicate = { peer, notificationSettings, isUnread in if includePeers.contains(peer.id) { return true } - if !filter.includeCategories.contains(.read) { + if filter.excludeRead { if !isUnread { return false } } - if !filter.includeCategories.contains(.muted) { + if filter.excludeMuted { if let notificationSettings = notificationSettings as? TelegramPeerNotificationSettings { if case .muted = notificationSettings.muteState { return false @@ -51,26 +51,26 @@ func chatListViewForLocation(groupId: PeerGroupId, location: ChatListNodeLocatio return false } } - if !filter.includeCategories.contains(.privateChats) { + if !filter.categories.contains(.privateChats) { if let user = peer as? TelegramUser { if user.botInfo == nil { return false } } } - if !filter.includeCategories.contains(.secretChats) { + if !filter.categories.contains(.secretChats) { if let _ = peer as? TelegramSecretChat { return false } } - if !filter.includeCategories.contains(.bots) { + if !filter.categories.contains(.bots) { if let user = peer as? TelegramUser { if user.botInfo != nil { return false } } } - if !filter.includeCategories.contains(.privateGroups) { + if !filter.categories.contains(.privateGroups) { if let _ = peer as? TelegramGroup { return false } else if let channel = peer as? TelegramChannel { @@ -81,7 +81,7 @@ func chatListViewForLocation(groupId: PeerGroupId, location: ChatListNodeLocatio } } } - if !filter.includeCategories.contains(.publicGroups) { + if !filter.categories.contains(.publicGroups) { if let channel = peer as? TelegramChannel { if case .group = channel.info { if channel.username != nil { @@ -90,7 +90,7 @@ func chatListViewForLocation(groupId: PeerGroupId, location: ChatListNodeLocatio } } } - if !filter.includeCategories.contains(.channels) { + if !filter.categories.contains(.channels) { if let channel = peer as? TelegramChannel { if case .broadcast = channel.info { return false diff --git a/submodules/ChatListUI/Sources/Node/ChatListViewTransition.swift b/submodules/ChatListUI/Sources/Node/ChatListViewTransition.swift index 4b0f09f8c2..d7997ee48c 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListViewTransition.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListViewTransition.swift @@ -12,7 +12,7 @@ struct ChatListNodeView { let originalView: ChatListView let filteredEntries: [ChatListNodeEntry] let isLoading: Bool - let filter: ChatListFilterPreset? + let filter: ChatListFilter? } enum ChatListNodeViewTransitionReason { diff --git a/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift b/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift index 79e09e3b11..6cb265b924 100644 --- a/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift +++ b/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift @@ -8,6 +8,7 @@ import AccountContext import SyncCore import Postbox import TelegramUIPreferences +import TelegramCore final class TabBarChatListFilterController: ViewController { private var controllerNode: TabBarChatListFilterControllerNode { @@ -21,17 +22,17 @@ final class TabBarChatListFilterController: ViewController { private let context: AccountContext private let sourceNodes: [ASDisplayNode] - private let presetList: [ChatListFilterPreset] - private let currentPreset: ChatListFilterPreset? + private let presetList: [ChatListFilter] + private let currentPreset: ChatListFilter? private let setup: () -> Void - private let updatePreset: (ChatListFilterPreset?) -> Void + private let updatePreset: (ChatListFilter?) -> Void private var presentationData: PresentationData private var didPlayPresentationAnimation = false private let hapticFeedback = HapticFeedback() - public init(context: AccountContext, sourceNodes: [ASDisplayNode], presetList: [ChatListFilterPreset], currentPreset: ChatListFilterPreset?, setup: @escaping () -> Void, updatePreset: @escaping (ChatListFilterPreset?) -> Void) { + public init(context: AccountContext, sourceNodes: [ASDisplayNode], presetList: [ChatListFilter], currentPreset: ChatListFilter?, setup: @escaping () -> Void, updatePreset: @escaping (ChatListFilter?) -> Void) { self.context = context self.sourceNodes = sourceNodes self.presetList = presetList @@ -184,7 +185,7 @@ private final class AddFilterItemNode: ASDisplayNode, AbstractTabBarChatListFilt private final class FilterItemNode: ASDisplayNode, AbstractTabBarChatListFilterItemNode { private let context: AccountContext private let title: String - let preset: ChatListFilterPreset? + let preset: ChatListFilter? private let isCurrent: Bool private let presentationData: PresentationData private let action: () -> Bool @@ -199,7 +200,7 @@ private final class FilterItemNode: ASDisplayNode, AbstractTabBarChatListFilterI private let badgeTitleNode: ImmediateTextNode private var badgeText: String = "" - init(context: AccountContext, title: String, preset: ChatListFilterPreset?, isCurrent: Bool, displaySeparator: Bool, presentationData: PresentationData, action: @escaping () -> Bool) { + init(context: AccountContext, title: String, preset: ChatListFilter?, isCurrent: Bool, displaySeparator: Bool, presentationData: PresentationData, action: @escaping () -> Bool) { self.context = context self.title = title self.preset = preset @@ -324,7 +325,7 @@ private final class TabBarChatListFilterControllerNode: ViewControllerTracingNod let isReady = Promise() private var didSetIsReady = false - init(context: AccountContext, presentationData: PresentationData, cancel: @escaping () -> Void, sourceNodes: [ASDisplayNode], presetList: [ChatListFilterPreset], currentPreset: ChatListFilterPreset?, setup: @escaping () -> Void, updatePreset: @escaping (ChatListFilterPreset?) -> Void) { + init(context: AccountContext, presentationData: PresentationData, cancel: @escaping () -> Void, sourceNodes: [ASDisplayNode], presetList: [ChatListFilter], currentPreset: ChatListFilter?, setup: @escaping () -> Void, updatePreset: @escaping (ChatListFilter?) -> Void) { self.presentationData = presentationData self.cancel = cancel self.sourceNodes = sourceNodes @@ -358,21 +359,10 @@ private final class TabBarChatListFilterControllerNode: ViewControllerTracingNod setup() })) - contentNodes.append(FilterItemNode(context: context, title: "All", preset: nil, isCurrent: currentPreset == nil, displaySeparator: !presetList.isEmpty, presentationData: presentationData, action: { - updatePreset(nil) - return false - })) - for i in 0 ..< presetList.count { let preset = presetList[i] - let title: String - switch preset.name { - case .unread: - title = "Unread" - case let .custom(value): - title = value - } + let title: String = preset.title ?? "" contentNodes.append(FilterItemNode(context: context, title: title, preset: preset, isCurrent: currentPreset == preset, displaySeparator: i != presetList.count - 1, presentationData: presentationData, action: { updatePreset(preset) return false @@ -393,7 +383,7 @@ private final class TabBarChatListFilterControllerNode: ViewControllerTracingNod unreadCountItems.append(.total(nil)) var additionalPeerIds = Set() for preset in presetList { - additionalPeerIds.formUnion(preset.additionallyIncludePeers) + additionalPeerIds.formUnion(preset.includePeers) } if !additionalPeerIds.isEmpty { for peerId in additionalPeerIds { @@ -447,36 +437,34 @@ private final class TabBarChatListFilterControllerNode: ViewControllerTracingNod let badgeString: String if let preset = contentNode.preset { var tags: [PeerSummaryCounterTags] = [] - if preset.includeCategories.contains(.privateChats) { + if preset.categories.contains(.privateChats) { tags.append(.privateChat) } - if preset.includeCategories.contains(.secretChats) { + if preset.categories.contains(.secretChats) { tags.append(.secretChat) } - if preset.includeCategories.contains(.privateGroups) { + if preset.categories.contains(.privateGroups) { tags.append(.privateGroup) } - if preset.includeCategories.contains(.bots) { + if preset.categories.contains(.bots) { tags.append(.bot) } - if preset.includeCategories.contains(.publicGroups) { + if preset.categories.contains(.publicGroups) { tags.append(.publicGroup) } - if preset.includeCategories.contains(.channels) { + if preset.categories.contains(.channels) { tags.append(.channel) } var count = 0 if let totalState = totalState { for tag in tags { - if preset.includeCategories.contains(.muted) { - } if let value = totalState.filteredCounters[tag] { count += Int(value.chatCount) } } } - for peerId in preset.additionallyIncludePeers { + for peerId in preset.includePeers { if let (tag, peerCount) = peerTagAndCount[peerId] { if !tags.contains(tag) { count += peerCount diff --git a/submodules/Display/Display/ListView.swift b/submodules/Display/Display/ListView.swift index 7a65d3b39e..9e231040b7 100644 --- a/submodules/Display/Display/ListView.swift +++ b/submodules/Display/Display/ListView.swift @@ -60,6 +60,12 @@ public final class ListViewBackingView: UIView { override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { if !self.isHidden, let target = self.target { + if target.bounds.contains(point) { + if target.decelerationAnimator != nil { + target.decelerationAnimator?.isPaused = true + target.decelerationAnimator = nil + } + } if target.limitHitTestToNodes, !target.internalHitTest(point, with: event) { return nil } @@ -685,6 +691,48 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture } } + fileprivate var decelerationAnimator: ConstantDisplayLinkAnimator? + private var accumulatedTransferVelocityOffset: CGFloat = 0.0 + + public func transferVelocity(_ velocity: CGFloat) { + self.decelerationAnimator?.isPaused = true + let startTime = CACurrentMediaTime() + let decelerationRate: CGFloat = 0.998 + self.decelerationAnimator = ConstantDisplayLinkAnimator(update: { [weak self] in + guard let strongSelf = self else { + return + } + let t = CACurrentMediaTime() - startTime + var currentVelocity = velocity * 15.0 * CGFloat(pow(Double(decelerationRate), 1000.0 * t)) + strongSelf.accumulatedTransferVelocityOffset += currentVelocity + let signFactor: CGFloat = strongSelf.accumulatedTransferVelocityOffset >= 0.0 ? 1.0 : -1.0 + let remainder = abs(strongSelf.accumulatedTransferVelocityOffset).remainder(dividingBy: UIScreenPixel) + //print("accumulated \(strongSelf.accumulatedTransferVelocityOffset), \(remainder), resulting accumulated \(strongSelf.accumulatedTransferVelocityOffset - remainder * signFactor) add delta \(strongSelf.accumulatedTransferVelocityOffset - remainder * signFactor)") + var currentOffset = strongSelf.scroller.contentOffset + let addedDela = strongSelf.accumulatedTransferVelocityOffset - remainder * signFactor + currentOffset.y += addedDela + strongSelf.accumulatedTransferVelocityOffset -= addedDela + let maxOffset = strongSelf.scroller.contentSize.height - strongSelf.scroller.bounds.height + if currentOffset.y >= maxOffset { + currentOffset.y = maxOffset + currentVelocity = 0.0 + } + if currentOffset.y < 0.0 { + currentOffset.y = 0.0 + currentVelocity = 0.0 + } + + if abs(currentVelocity) < 0.1 { + strongSelf.decelerationAnimator?.isPaused = true + strongSelf.decelerationAnimator = nil + } + var contentOffset = strongSelf.scroller.contentOffset + contentOffset.y = floorToScreenPixels(currentOffset.y) + strongSelf.scroller.setContentOffset(contentOffset, animated: false) + }) + self.decelerationAnimator?.isPaused = false + } + public func scrollViewDidScroll(_ scrollView: UIScrollView) { self.updateScrollViewDidScroll(scrollView, synchronous: false) } diff --git a/submodules/SyncCore/Sources/Namespaces.swift b/submodules/SyncCore/Sources/Namespaces.swift index 5317234ea5..76d058ee03 100644 --- a/submodules/SyncCore/Sources/Namespaces.swift +++ b/submodules/SyncCore/Sources/Namespaces.swift @@ -196,6 +196,7 @@ private enum PreferencesKeyValues: Int32 { case secretChatSettings = 17 case walletCollection = 18 case contentSettings = 19 + case chatListFilters = 20 } public func applicationSpecificPreferencesKey(_ value: Int32) -> ValueBoxKey { @@ -306,6 +307,12 @@ public struct PreferencesKeys { key.setInt32(0, value: PreferencesKeyValues.contentSettings.rawValue) return key }() + + public static let chatListFilters: ValueBoxKey = { + let key = ValueBoxKey(length: 4) + key.setInt32(0, value: PreferencesKeyValues.chatListFilters.rawValue) + return key + }() } private enum SharedDataKeyValues: Int32 { diff --git a/submodules/SyncCore/Sources/TextEntitiesMessageAttribute.swift b/submodules/SyncCore/Sources/TextEntitiesMessageAttribute.swift index 79fe68a5ed..e0c3f565a9 100644 --- a/submodules/SyncCore/Sources/TextEntitiesMessageAttribute.swift +++ b/submodules/SyncCore/Sources/TextEntitiesMessageAttribute.swift @@ -19,6 +19,7 @@ public enum MessageTextEntityType: Equatable { case Strikethrough case BlockQuote case Underline + case BankCard case Custom(type: CustomEntityType) } @@ -65,6 +66,8 @@ public struct MessageTextEntity: PostboxCoding, Equatable { self.type = .BlockQuote case 15: self.type = .Underline + case 16: + self.type = .BankCard case Int32.max: self.type = .Custom(type: decoder.decodeInt32ForKey("type", orElse: 0)) default: @@ -110,6 +113,8 @@ public struct MessageTextEntity: PostboxCoding, Equatable { encoder.encodeInt32(14, forKey: "_rawValue") case .Underline: encoder.encodeInt32(15, forKey: "_rawValue") + case .BankCard: + encoder.encodeInt32(16, forKey: "_rawValue") case let .Custom(type): encoder.encodeInt32(Int32.max, forKey: "_rawValue") encoder.encodeInt32(type, forKey: "type") diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index ab2f4a7b7b..8816246c2f 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -10,7 +10,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-206066487] = { return Api.InputGeoPoint.parse_inputGeoPoint($0) } dict[-784000893] = { return Api.payments.ValidatedRequestedInfo.parse_validatedRequestedInfo($0) } dict[461151667] = { return Api.ChatFull.parse_chatFull($0) } - dict[763976820] = { return Api.ChatFull.parse_channelFull($0) } + dict[-253335766] = { return Api.ChatFull.parse_channelFull($0) } dict[-932174686] = { return Api.PollResults.parse_pollResults($0) } dict[-925415106] = { return Api.ChatParticipant.parse_chatParticipant($0) } dict[-636267638] = { return Api.ChatParticipant.parse_chatParticipantCreator($0) } @@ -247,6 +247,9 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-2027964103] = { return Api.Update.parse_updateGeoLiveViewed($0) } dict[1448076945] = { return Api.Update.parse_updateLoginToken($0) } dict[1123585836] = { return Api.Update.parse_updateMessagePollVote($0) } + dict[654302845] = { return Api.Update.parse_updateDialogFilter($0) } + dict[-1512627963] = { return Api.Update.parse_updateDialogFilterOrder($0) } + dict[889491791] = { return Api.Update.parse_updateDialogFilters($0) } dict[136574537] = { return Api.messages.VotesList.parse_votesList($0) } dict[1558266229] = { return Api.PopularContact.parse_popularContact($0) } dict[-373643672] = { return Api.FolderPeer.parse_folderPeer($0) } @@ -412,6 +415,9 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[2103482845] = { return Api.SecurePlainData.parse_securePlainPhone($0) } dict[569137759] = { return Api.SecurePlainData.parse_securePlainEmail($0) } dict[-1269012015] = { return Api.messages.AffectedHistory.parse_affectedHistory($0) } + dict[1244130093] = { return Api.StatsGraph.parse_statsGraphAsync($0) } + dict[-1092839390] = { return Api.StatsGraph.parse_statsGraphError($0) } + dict[-1057809608] = { return Api.StatsGraph.parse_statsGraph($0) } dict[-1036572727] = { return Api.account.PasswordInputSettings.parse_passwordInputSettings($0) } dict[878078826] = { return Api.PageTableCell.parse_pageTableCell($0) } dict[-1626209256] = { return Api.ChatBannedRights.parse_chatBannedRights($0) } @@ -480,6 +486,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-668391402] = { return Api.InputUser.parse_inputUser($0) } dict[-1366746132] = { return Api.Page.parse_page($0) } dict[871426631] = { return Api.SecureCredentialsEncrypted.parse_secureCredentialsEncrypted($0) } + dict[-875679776] = { return Api.StatsPercentValue.parse_statsPercentValue($0) } dict[157948117] = { return Api.upload.File.parse_file($0) } dict[-242427324] = { return Api.upload.File.parse_fileCdnRedirect($0) } dict[-1078612597] = { return Api.ChannelLocation.parse_channelLocationEmpty($0) } @@ -506,6 +513,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-1160215659] = { return Api.InputMessage.parse_inputMessageReplyTo($0) } dict[-2037963464] = { return Api.InputMessage.parse_inputMessagePinned($0) } dict[-1564789301] = { return Api.PhoneCallProtocol.parse_phoneCallProtocol($0) } + dict[-1237848657] = { return Api.StatsDateRangeDays.parse_statsDateRangeDays($0) } dict[-1567175714] = { return Api.MessageFwdAuthor.parse_messageFwdAuthor($0) } dict[-1539849235] = { return Api.WallPaper.parse_wallPaper($0) } dict[-1963717851] = { return Api.WallPaper.parse_wallPaperNoFile($0) } @@ -520,6 +528,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-1837345356] = { return Api.InputChatPhoto.parse_inputChatUploadedPhoto($0) } dict[-1991004873] = { return Api.InputChatPhoto.parse_inputChatPhoto($0) } dict[-368917890] = { return Api.PaymentCharge.parse_paymentCharge($0) } + dict[205195937] = { return Api.stats.BroadcastStats.parse_broadcastStats($0) } dict[-484987010] = { return Api.Updates.parse_updatesTooLong($0) } dict[-1857044719] = { return Api.Updates.parse_updateShortMessage($0) } dict[377562760] = { return Api.Updates.parse_updateShortChatMessage($0) } @@ -527,6 +536,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[1918567619] = { return Api.Updates.parse_updatesCombined($0) } dict[1957577280] = { return Api.Updates.parse_updates($0) } dict[301019932] = { return Api.Updates.parse_updateShortSentMessage($0) } + dict[-884757282] = { return Api.StatsAbsValueAndPrev.parse_statsAbsValueAndPrev($0) } dict[1038967584] = { return Api.MessageMedia.parse_messageMediaEmpty($0) } dict[1457575028] = { return Api.MessageMedia.parse_messageMediaGeo($0) } dict[-1618676578] = { return Api.MessageMedia.parse_messageMediaUnsupported($0) } @@ -589,6 +599,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-1551583367] = { return Api.ReceivedNotifyMessage.parse_receivedNotifyMessage($0) } dict[-57668565] = { return Api.ChatParticipants.parse_chatParticipantsForbidden($0) } dict[1061556205] = { return Api.ChatParticipants.parse_chatParticipants($0) } + dict[351868460] = { return Api.DialogFilter.parse_dialogFilter($0) } dict[-1056001329] = { return Api.InputPaymentCredentials.parse_inputPaymentCredentialsSaved($0) } dict[873977640] = { return Api.InputPaymentCredentials.parse_inputPaymentCredentials($0) } dict[178373535] = { return Api.InputPaymentCredentials.parse_inputPaymentCredentialsApplePay($0) } @@ -761,6 +772,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[1041346555] = { return Api.updates.ChannelDifference.parse_channelDifferenceEmpty($0) } dict[543450958] = { return Api.updates.ChannelDifference.parse_channelDifference($0) } dict[-1531132162] = { return Api.updates.ChannelDifference.parse_channelDifferenceTooLong($0) } + dict[-581804346] = { return Api.StatsRowAbsValueAndPrev.parse_statsRowAbsValueAndPrev($0) } dict[-309659827] = { return Api.channels.AdminLogResults.parse_adminLogResults($0) } dict[-264117680] = { return Api.ChatOnlines.parse_chatOnlines($0) } dict[488313413] = { return Api.InputAppEvent.parse_inputAppEvent($0) } @@ -782,6 +794,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-1672577397] = { return Api.MessageEntity.parse_messageEntityUnderline($0) } dict[-1090087980] = { return Api.MessageEntity.parse_messageEntityStrike($0) } dict[34469328] = { return Api.MessageEntity.parse_messageEntityBlockquote($0) } + dict[1981704948] = { return Api.MessageEntity.parse_messageEntityBankCard($0) } dict[483901197] = { return Api.InputPhoto.parse_inputPhotoEmpty($0) } dict[1001634122] = { return Api.InputPhoto.parse_inputPhoto($0) } dict[-567906571] = { return Api.contacts.TopPeers.parse_topPeersNotModified($0) } @@ -804,6 +817,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-1707344487] = { return Api.messages.HighScores.parse_highScores($0) } dict[-892779534] = { return Api.WebAuthorization.parse_webAuthorization($0) } dict[-805141448] = { return Api.ImportedContact.parse_importedContact($0) } + dict[-1165694006] = { return Api.payments.BankCardData.parse_bankCardData($0) } return dict }() @@ -1081,6 +1095,8 @@ public struct Api { _1.serialize(buffer, boxed) case let _1 as Api.messages.AffectedHistory: _1.serialize(buffer, boxed) + case let _1 as Api.StatsGraph: + _1.serialize(buffer, boxed) case let _1 as Api.account.PasswordInputSettings: _1.serialize(buffer, boxed) case let _1 as Api.PageTableCell: @@ -1151,6 +1167,8 @@ public struct Api { _1.serialize(buffer, boxed) case let _1 as Api.SecureCredentialsEncrypted: _1.serialize(buffer, boxed) + case let _1 as Api.StatsPercentValue: + _1.serialize(buffer, boxed) case let _1 as Api.upload.File: _1.serialize(buffer, boxed) case let _1 as Api.ChannelLocation: @@ -1185,6 +1203,8 @@ public struct Api { _1.serialize(buffer, boxed) case let _1 as Api.PhoneCallProtocol: _1.serialize(buffer, boxed) + case let _1 as Api.StatsDateRangeDays: + _1.serialize(buffer, boxed) case let _1 as Api.MessageFwdAuthor: _1.serialize(buffer, boxed) case let _1 as Api.WallPaper: @@ -1201,8 +1221,12 @@ public struct Api { _1.serialize(buffer, boxed) case let _1 as Api.PaymentCharge: _1.serialize(buffer, boxed) + case let _1 as Api.stats.BroadcastStats: + _1.serialize(buffer, boxed) case let _1 as Api.Updates: _1.serialize(buffer, boxed) + case let _1 as Api.StatsAbsValueAndPrev: + _1.serialize(buffer, boxed) case let _1 as Api.MessageMedia: _1.serialize(buffer, boxed) case let _1 as Api.PaymentSavedCredentials: @@ -1251,6 +1275,8 @@ public struct Api { _1.serialize(buffer, boxed) case let _1 as Api.ChatParticipants: _1.serialize(buffer, boxed) + case let _1 as Api.DialogFilter: + _1.serialize(buffer, boxed) case let _1 as Api.InputPaymentCredentials: _1.serialize(buffer, boxed) case let _1 as Api.ShippingOption: @@ -1381,6 +1407,8 @@ public struct Api { _1.serialize(buffer, boxed) case let _1 as Api.updates.ChannelDifference: _1.serialize(buffer, boxed) + case let _1 as Api.StatsRowAbsValueAndPrev: + _1.serialize(buffer, boxed) case let _1 as Api.channels.AdminLogResults: _1.serialize(buffer, boxed) case let _1 as Api.ChatOnlines: @@ -1409,6 +1437,8 @@ public struct Api { _1.serialize(buffer, boxed) case let _1 as Api.ImportedContact: _1.serialize(buffer, boxed) + case let _1 as Api.payments.BankCardData: + _1.serialize(buffer, boxed) default: break } diff --git a/submodules/TelegramApi/Sources/Api1.swift b/submodules/TelegramApi/Sources/Api1.swift index 9e6d38f6d1..fbad69a990 100644 --- a/submodules/TelegramApi/Sources/Api1.swift +++ b/submodules/TelegramApi/Sources/Api1.swift @@ -1805,7 +1805,7 @@ public extension Api { } public enum ChatFull: TypeConstructorDescription { case chatFull(flags: Int32, id: Int32, about: String, participants: Api.ChatParticipants, chatPhoto: Api.Photo?, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite, botInfo: [Api.BotInfo]?, pinnedMsgId: Int32?, folderId: Int32?) - case channelFull(flags: Int32, id: Int32, about: String, participantsCount: Int32?, adminsCount: Int32?, kickedCount: Int32?, bannedCount: Int32?, onlineCount: Int32?, readInboxMaxId: Int32, readOutboxMaxId: Int32, unreadCount: Int32, chatPhoto: Api.Photo, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite, botInfo: [Api.BotInfo], migratedFromChatId: Int32?, migratedFromMaxId: Int32?, pinnedMsgId: Int32?, stickerset: Api.StickerSet?, availableMinId: Int32?, folderId: Int32?, linkedChatId: Int32?, location: Api.ChannelLocation?, slowmodeSeconds: Int32?, slowmodeNextSendDate: Int32?, pts: Int32) + case channelFull(flags: Int32, id: Int32, about: String, participantsCount: Int32?, adminsCount: Int32?, kickedCount: Int32?, bannedCount: Int32?, onlineCount: Int32?, readInboxMaxId: Int32, readOutboxMaxId: Int32, unreadCount: Int32, chatPhoto: Api.Photo, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite, botInfo: [Api.BotInfo], migratedFromChatId: Int32?, migratedFromMaxId: Int32?, pinnedMsgId: Int32?, stickerset: Api.StickerSet?, availableMinId: Int32?, folderId: Int32?, linkedChatId: Int32?, location: Api.ChannelLocation?, slowmodeSeconds: Int32?, slowmodeNextSendDate: Int32?, statsDc: Int32?, pts: Int32) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { @@ -1828,9 +1828,9 @@ public extension Api { if Int(flags) & Int(1 << 6) != 0 {serializeInt32(pinnedMsgId!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 11) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)} break - case .channelFull(let flags, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId, let folderId, let linkedChatId, let location, let slowmodeSeconds, let slowmodeNextSendDate, let pts): + case .channelFull(let flags, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId, let folderId, let linkedChatId, let location, let slowmodeSeconds, let slowmodeNextSendDate, let statsDc, let pts): if boxed { - buffer.appendInt32(763976820) + buffer.appendInt32(-253335766) } serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(id, buffer: buffer, boxed: false) @@ -1861,6 +1861,7 @@ public extension Api { if Int(flags) & Int(1 << 15) != 0 {location!.serialize(buffer, true)} if Int(flags) & Int(1 << 17) != 0 {serializeInt32(slowmodeSeconds!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 18) != 0 {serializeInt32(slowmodeNextSendDate!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 12) != 0 {serializeInt32(statsDc!, buffer: buffer, boxed: false)} serializeInt32(pts, buffer: buffer, boxed: false) break } @@ -1870,8 +1871,8 @@ public extension Api { switch self { case .chatFull(let flags, let id, let about, let participants, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let pinnedMsgId, let folderId): return ("chatFull", [("flags", flags), ("id", id), ("about", about), ("participants", participants), ("chatPhoto", chatPhoto), ("notifySettings", notifySettings), ("exportedInvite", exportedInvite), ("botInfo", botInfo), ("pinnedMsgId", pinnedMsgId), ("folderId", folderId)]) - case .channelFull(let flags, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId, let folderId, let linkedChatId, let location, let slowmodeSeconds, let slowmodeNextSendDate, let pts): - return ("channelFull", [("flags", flags), ("id", id), ("about", about), ("participantsCount", participantsCount), ("adminsCount", adminsCount), ("kickedCount", kickedCount), ("bannedCount", bannedCount), ("onlineCount", onlineCount), ("readInboxMaxId", readInboxMaxId), ("readOutboxMaxId", readOutboxMaxId), ("unreadCount", unreadCount), ("chatPhoto", chatPhoto), ("notifySettings", notifySettings), ("exportedInvite", exportedInvite), ("botInfo", botInfo), ("migratedFromChatId", migratedFromChatId), ("migratedFromMaxId", migratedFromMaxId), ("pinnedMsgId", pinnedMsgId), ("stickerset", stickerset), ("availableMinId", availableMinId), ("folderId", folderId), ("linkedChatId", linkedChatId), ("location", location), ("slowmodeSeconds", slowmodeSeconds), ("slowmodeNextSendDate", slowmodeNextSendDate), ("pts", pts)]) + case .channelFull(let flags, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId, let folderId, let linkedChatId, let location, let slowmodeSeconds, let slowmodeNextSendDate, let statsDc, let pts): + return ("channelFull", [("flags", flags), ("id", id), ("about", about), ("participantsCount", participantsCount), ("adminsCount", adminsCount), ("kickedCount", kickedCount), ("bannedCount", bannedCount), ("onlineCount", onlineCount), ("readInboxMaxId", readInboxMaxId), ("readOutboxMaxId", readOutboxMaxId), ("unreadCount", unreadCount), ("chatPhoto", chatPhoto), ("notifySettings", notifySettings), ("exportedInvite", exportedInvite), ("botInfo", botInfo), ("migratedFromChatId", migratedFromChatId), ("migratedFromMaxId", migratedFromMaxId), ("pinnedMsgId", pinnedMsgId), ("stickerset", stickerset), ("availableMinId", availableMinId), ("folderId", folderId), ("linkedChatId", linkedChatId), ("location", location), ("slowmodeSeconds", slowmodeSeconds), ("slowmodeNextSendDate", slowmodeNextSendDate), ("statsDc", statsDc), ("pts", pts)]) } } @@ -1987,7 +1988,9 @@ public extension Api { var _25: Int32? if Int(_1!) & Int(1 << 18) != 0 {_25 = reader.readInt32() } var _26: Int32? - _26 = reader.readInt32() + if Int(_1!) & Int(1 << 12) != 0 {_26 = reader.readInt32() } + var _27: Int32? + _27 = reader.readInt32() let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil @@ -2013,9 +2016,10 @@ public extension Api { let _c23 = (Int(_1!) & Int(1 << 15) == 0) || _23 != nil let _c24 = (Int(_1!) & Int(1 << 17) == 0) || _24 != nil let _c25 = (Int(_1!) & Int(1 << 18) == 0) || _25 != nil - let _c26 = _26 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 && _c25 && _c26 { - return Api.ChatFull.channelFull(flags: _1!, id: _2!, about: _3!, participantsCount: _4, adminsCount: _5, kickedCount: _6, bannedCount: _7, onlineCount: _8, readInboxMaxId: _9!, readOutboxMaxId: _10!, unreadCount: _11!, chatPhoto: _12!, notifySettings: _13!, exportedInvite: _14!, botInfo: _15!, migratedFromChatId: _16, migratedFromMaxId: _17, pinnedMsgId: _18, stickerset: _19, availableMinId: _20, folderId: _21, linkedChatId: _22, location: _23, slowmodeSeconds: _24, slowmodeNextSendDate: _25, pts: _26!) + let _c26 = (Int(_1!) & Int(1 << 12) == 0) || _26 != nil + let _c27 = _27 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 && _c25 && _c26 && _c27 { + return Api.ChatFull.channelFull(flags: _1!, id: _2!, about: _3!, participantsCount: _4, adminsCount: _5, kickedCount: _6, bannedCount: _7, onlineCount: _8, readInboxMaxId: _9!, readOutboxMaxId: _10!, unreadCount: _11!, chatPhoto: _12!, notifySettings: _13!, exportedInvite: _14!, botInfo: _15!, migratedFromChatId: _16, migratedFromMaxId: _17, pinnedMsgId: _18, stickerset: _19, availableMinId: _20, folderId: _21, linkedChatId: _22, location: _23, slowmodeSeconds: _24, slowmodeNextSendDate: _25, statsDc: _26, pts: _27!) } else { return nil @@ -5861,6 +5865,9 @@ public extension Api { case updateGeoLiveViewed(peer: Api.Peer, msgId: Int32) case updateLoginToken case updateMessagePollVote(pollId: Int64, userId: Int32, options: [Buffer]) + case updateDialogFilter(flags: Int32, id: Int32, filter: Api.DialogFilter?) + case updateDialogFilterOrder(order: [Int32]) + case updateDialogFilters public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { @@ -6509,6 +6516,30 @@ public extension Api { for item in options { serializeBytes(item, buffer: buffer, boxed: false) } + break + case .updateDialogFilter(let flags, let id, let filter): + if boxed { + buffer.appendInt32(654302845) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(id, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {filter!.serialize(buffer, true)} + break + case .updateDialogFilterOrder(let order): + if boxed { + buffer.appendInt32(-1512627963) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(order.count)) + for item in order { + serializeInt32(item, buffer: buffer, boxed: false) + } + break + case .updateDialogFilters: + if boxed { + buffer.appendInt32(889491791) + } + break } } @@ -6669,6 +6700,12 @@ public extension Api { return ("updateLoginToken", []) case .updateMessagePollVote(let pollId, let userId, let options): return ("updateMessagePollVote", [("pollId", pollId), ("userId", userId), ("options", options)]) + case .updateDialogFilter(let flags, let id, let filter): + return ("updateDialogFilter", [("flags", flags), ("id", id), ("filter", filter)]) + case .updateDialogFilterOrder(let order): + return ("updateDialogFilterOrder", [("order", order)]) + case .updateDialogFilters: + return ("updateDialogFilters", []) } } @@ -7965,6 +8002,41 @@ public extension Api { return nil } } + public static func parse_updateDialogFilter(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: Api.DialogFilter? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.DialogFilter + } } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updateDialogFilter(flags: _1!, id: _2!, filter: _3) + } + else { + return nil + } + } + public static func parse_updateDialogFilterOrder(_ reader: BufferReader) -> Update? { + var _1: [Int32]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.Update.updateDialogFilterOrder(order: _1!) + } + else { + return nil + } + } + public static func parse_updateDialogFilters(_ reader: BufferReader) -> Update? { + return Api.Update.updateDialogFilters + } } public enum PopularContact: TypeConstructorDescription { @@ -11956,6 +12028,82 @@ public extension Api { } } + } + public enum StatsGraph: TypeConstructorDescription { + case statsGraphAsync(token: String) + case statsGraphError(error: String) + case statsGraph(json: Api.DataJSON) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .statsGraphAsync(let token): + if boxed { + buffer.appendInt32(1244130093) + } + serializeString(token, buffer: buffer, boxed: false) + break + case .statsGraphError(let error): + if boxed { + buffer.appendInt32(-1092839390) + } + serializeString(error, buffer: buffer, boxed: false) + break + case .statsGraph(let json): + if boxed { + buffer.appendInt32(-1057809608) + } + json.serialize(buffer, true) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .statsGraphAsync(let token): + return ("statsGraphAsync", [("token", token)]) + case .statsGraphError(let error): + return ("statsGraphError", [("error", error)]) + case .statsGraph(let json): + return ("statsGraph", [("json", json)]) + } + } + + public static func parse_statsGraphAsync(_ reader: BufferReader) -> StatsGraph? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.StatsGraph.statsGraphAsync(token: _1!) + } + else { + return nil + } + } + public static func parse_statsGraphError(_ reader: BufferReader) -> StatsGraph? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.StatsGraph.statsGraphError(error: _1!) + } + else { + return nil + } + } + public static func parse_statsGraph(_ reader: BufferReader) -> StatsGraph? { + var _1: Api.DataJSON? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.DataJSON + } + let _c1 = _1 != nil + if _c1 { + return Api.StatsGraph.statsGraph(json: _1!) + } + else { + return nil + } + } + } public enum PageTableCell: TypeConstructorDescription { case pageTableCell(flags: Int32, text: Api.RichText?, colspan: Int32?, rowspan: Int32?) @@ -13662,6 +13810,44 @@ public extension Api { } } + } + public enum StatsPercentValue: TypeConstructorDescription { + case statsPercentValue(part: Double, total: Double) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .statsPercentValue(let part, let total): + if boxed { + buffer.appendInt32(-875679776) + } + serializeDouble(part, buffer: buffer, boxed: false) + serializeDouble(total, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .statsPercentValue(let part, let total): + return ("statsPercentValue", [("part", part), ("total", total)]) + } + } + + public static func parse_statsPercentValue(_ reader: BufferReader) -> StatsPercentValue? { + var _1: Double? + _1 = reader.readDouble() + var _2: Double? + _2 = reader.readDouble() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.StatsPercentValue.statsPercentValue(part: _1!, total: _2!) + } + else { + return nil + } + } + } public enum ChannelLocation: TypeConstructorDescription { case channelLocationEmpty @@ -14434,6 +14620,44 @@ public extension Api { } } + } + public enum StatsDateRangeDays: TypeConstructorDescription { + case statsDateRangeDays(minDate: Int32, maxDate: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .statsDateRangeDays(let minDate, let maxDate): + if boxed { + buffer.appendInt32(-1237848657) + } + serializeInt32(minDate, buffer: buffer, boxed: false) + serializeInt32(maxDate, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .statsDateRangeDays(let minDate, let maxDate): + return ("statsDateRangeDays", [("minDate", minDate), ("maxDate", maxDate)]) + } + } + + public static func parse_statsDateRangeDays(_ reader: BufferReader) -> StatsDateRangeDays? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.StatsDateRangeDays.statsDateRangeDays(minDate: _1!, maxDate: _2!) + } + else { + return nil + } + } + } public enum MessageFwdAuthor: TypeConstructorDescription { case messageFwdAuthor(channelId: Int32) @@ -15098,6 +15322,44 @@ public extension Api { } } + } + public enum StatsAbsValueAndPrev: TypeConstructorDescription { + case statsAbsValueAndPrev(current: Double, previous: Double) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .statsAbsValueAndPrev(let current, let previous): + if boxed { + buffer.appendInt32(-884757282) + } + serializeDouble(current, buffer: buffer, boxed: false) + serializeDouble(previous, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .statsAbsValueAndPrev(let current, let previous): + return ("statsAbsValueAndPrev", [("current", current), ("previous", previous)]) + } + } + + public static func parse_statsAbsValueAndPrev(_ reader: BufferReader) -> StatsAbsValueAndPrev? { + var _1: Double? + _1 = reader.readDouble() + var _2: Double? + _2 = reader.readDouble() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.StatsAbsValueAndPrev.statsAbsValueAndPrev(current: _1!, previous: _2!) + } + else { + return nil + } + } + } public enum MessageMedia: TypeConstructorDescription { case messageMediaEmpty @@ -16814,6 +17076,58 @@ public extension Api { } } + } + public enum DialogFilter: TypeConstructorDescription { + case dialogFilter(flags: Int32, id: Int32, title: String, includePeers: [Api.InputPeer]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .dialogFilter(let flags, let id, let title, let includePeers): + if boxed { + buffer.appendInt32(351868460) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(id, buffer: buffer, boxed: false) + serializeString(title, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(includePeers.count)) + for item in includePeers { + item.serialize(buffer, true) + } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .dialogFilter(let flags, let id, let title, let includePeers): + return ("dialogFilter", [("flags", flags), ("id", id), ("title", title), ("includePeers", includePeers)]) + } + } + + public static func parse_dialogFilter(_ reader: BufferReader) -> DialogFilter? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: String? + _3 = parseString(reader) + var _4: [Api.InputPeer]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.InputPeer.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.DialogFilter.dialogFilter(flags: _1!, id: _2!, title: _3!, includePeers: _4!) + } + else { + return nil + } + } + } public enum InputPaymentCredentials: TypeConstructorDescription { case inputPaymentCredentialsSaved(id: String, tmpPassword: Buffer) @@ -20880,6 +21194,54 @@ public extension Api { } } + } + public enum StatsRowAbsValueAndPrev: TypeConstructorDescription { + case statsRowAbsValueAndPrev(id: String, title: String, shortTitle: String, values: Api.StatsAbsValueAndPrev) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .statsRowAbsValueAndPrev(let id, let title, let shortTitle, let values): + if boxed { + buffer.appendInt32(-581804346) + } + serializeString(id, buffer: buffer, boxed: false) + serializeString(title, buffer: buffer, boxed: false) + serializeString(shortTitle, buffer: buffer, boxed: false) + values.serialize(buffer, true) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .statsRowAbsValueAndPrev(let id, let title, let shortTitle, let values): + return ("statsRowAbsValueAndPrev", [("id", id), ("title", title), ("shortTitle", shortTitle), ("values", values)]) + } + } + + public static func parse_statsRowAbsValueAndPrev(_ reader: BufferReader) -> StatsRowAbsValueAndPrev? { + var _1: String? + _1 = parseString(reader) + var _2: String? + _2 = parseString(reader) + var _3: String? + _3 = parseString(reader) + var _4: Api.StatsAbsValueAndPrev? + if let signature = reader.readInt32() { + _4 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.StatsRowAbsValueAndPrev.statsRowAbsValueAndPrev(id: _1!, title: _2!, shortTitle: _3!, values: _4!) + } + else { + return nil + } + } + } public enum ChatOnlines: TypeConstructorDescription { case chatOnlines(onlines: Int32) @@ -20982,6 +21344,7 @@ public extension Api { case messageEntityUnderline(offset: Int32, length: Int32) case messageEntityStrike(offset: Int32, length: Int32) case messageEntityBlockquote(offset: Int32, length: Int32) + case messageEntityBankCard(offset: Int32, length: Int32) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { @@ -21115,6 +21478,13 @@ public extension Api { serializeInt32(offset, buffer: buffer, boxed: false) serializeInt32(length, buffer: buffer, boxed: false) break + case .messageEntityBankCard(let offset, let length): + if boxed { + buffer.appendInt32(1981704948) + } + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) + break } } @@ -21156,6 +21526,8 @@ public extension Api { return ("messageEntityStrike", [("offset", offset), ("length", length)]) case .messageEntityBlockquote(let offset, let length): return ("messageEntityBlockquote", [("offset", offset), ("length", length)]) + case .messageEntityBankCard(let offset, let length): + return ("messageEntityBankCard", [("offset", offset), ("length", length)]) } } @@ -21425,6 +21797,20 @@ public extension Api { return nil } } + public static func parse_messageEntityBankCard(_ reader: BufferReader) -> MessageEntity? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageEntity.messageEntityBankCard(offset: _1!, length: _2!) + } + else { + return nil + } + } } public enum InputPhoto: TypeConstructorDescription { diff --git a/submodules/TelegramApi/Sources/Api2.swift b/submodules/TelegramApi/Sources/Api2.swift index f0cb6195e9..f279ddec30 100644 --- a/submodules/TelegramApi/Sources/Api2.swift +++ b/submodules/TelegramApi/Sources/Api2.swift @@ -490,6 +490,184 @@ public struct payments { } } + public enum BankCardData: TypeConstructorDescription { + case bankCardData(flags: Int32, brand: String?, country: String?, organization: String?, url: String?, urlName: String?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .bankCardData(let flags, let brand, let country, let organization, let url, let urlName): + if boxed { + buffer.appendInt32(-1165694006) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeString(brand!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {serializeString(country!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {serializeString(organization!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 3) != 0 {serializeString(url!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 3) != 0 {serializeString(urlName!, buffer: buffer, boxed: false)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .bankCardData(let flags, let brand, let country, let organization, let url, let urlName): + return ("bankCardData", [("flags", flags), ("brand", brand), ("country", country), ("organization", organization), ("url", url), ("urlName", urlName)]) + } + } + + public static func parse_bankCardData(_ reader: BufferReader) -> BankCardData? { + var _1: Int32? + _1 = reader.readInt32() + var _2: String? + if Int(_1!) & Int(1 << 0) != 0 {_2 = parseString(reader) } + var _3: String? + if Int(_1!) & Int(1 << 1) != 0 {_3 = parseString(reader) } + var _4: String? + if Int(_1!) & Int(1 << 2) != 0 {_4 = parseString(reader) } + var _5: String? + if Int(_1!) & Int(1 << 3) != 0 {_5 = parseString(reader) } + var _6: String? + if Int(_1!) & Int(1 << 3) != 0 {_6 = parseString(reader) } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil + let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil + let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil + let _c5 = (Int(_1!) & Int(1 << 3) == 0) || _5 != nil + let _c6 = (Int(_1!) & Int(1 << 3) == 0) || _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.payments.BankCardData.bankCardData(flags: _1!, brand: _2, country: _3, organization: _4, url: _5, urlName: _6) + } + else { + return nil + } + } + + } +} +} +public extension Api { +public struct stats { + public enum BroadcastStats: TypeConstructorDescription { + case broadcastStats(period: Api.StatsDateRangeDays, followers: Api.StatsAbsValueAndPrev, viewsPerPost: Api.StatsAbsValueAndPrev, sharesPerPost: Api.StatsAbsValueAndPrev, enabledNotifications: Api.StatsPercentValue, viewsBySource: [Api.StatsRowAbsValueAndPrev], newFollowersBySource: [Api.StatsRowAbsValueAndPrev], languages: [Api.StatsRowAbsValueAndPrev], growthGraph: Api.StatsGraph, followersGraph: Api.StatsGraph, muteGraph: Api.StatsGraph, topHoursGraph: Api.StatsGraph, interactionsGraph: Api.StatsGraph) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .broadcastStats(let period, let followers, let viewsPerPost, let sharesPerPost, let enabledNotifications, let viewsBySource, let newFollowersBySource, let languages, let growthGraph, let followersGraph, let muteGraph, let topHoursGraph, let interactionsGraph): + if boxed { + buffer.appendInt32(205195937) + } + period.serialize(buffer, true) + followers.serialize(buffer, true) + viewsPerPost.serialize(buffer, true) + sharesPerPost.serialize(buffer, true) + enabledNotifications.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(viewsBySource.count)) + for item in viewsBySource { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(newFollowersBySource.count)) + for item in newFollowersBySource { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(languages.count)) + for item in languages { + item.serialize(buffer, true) + } + growthGraph.serialize(buffer, true) + followersGraph.serialize(buffer, true) + muteGraph.serialize(buffer, true) + topHoursGraph.serialize(buffer, true) + interactionsGraph.serialize(buffer, true) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .broadcastStats(let period, let followers, let viewsPerPost, let sharesPerPost, let enabledNotifications, let viewsBySource, let newFollowersBySource, let languages, let growthGraph, let followersGraph, let muteGraph, let topHoursGraph, let interactionsGraph): + return ("broadcastStats", [("period", period), ("followers", followers), ("viewsPerPost", viewsPerPost), ("sharesPerPost", sharesPerPost), ("enabledNotifications", enabledNotifications), ("viewsBySource", viewsBySource), ("newFollowersBySource", newFollowersBySource), ("languages", languages), ("growthGraph", growthGraph), ("followersGraph", followersGraph), ("muteGraph", muteGraph), ("topHoursGraph", topHoursGraph), ("interactionsGraph", interactionsGraph)]) + } + } + + public static func parse_broadcastStats(_ reader: BufferReader) -> BroadcastStats? { + var _1: Api.StatsDateRangeDays? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.StatsDateRangeDays + } + var _2: Api.StatsAbsValueAndPrev? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev + } + var _3: Api.StatsAbsValueAndPrev? + if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev + } + var _4: Api.StatsAbsValueAndPrev? + if let signature = reader.readInt32() { + _4 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev + } + var _5: Api.StatsPercentValue? + if let signature = reader.readInt32() { + _5 = Api.parse(reader, signature: signature) as? Api.StatsPercentValue + } + var _6: [Api.StatsRowAbsValueAndPrev]? + if let _ = reader.readInt32() { + _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsRowAbsValueAndPrev.self) + } + var _7: [Api.StatsRowAbsValueAndPrev]? + if let _ = reader.readInt32() { + _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsRowAbsValueAndPrev.self) + } + var _8: [Api.StatsRowAbsValueAndPrev]? + if let _ = reader.readInt32() { + _8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsRowAbsValueAndPrev.self) + } + var _9: Api.StatsGraph? + if let signature = reader.readInt32() { + _9 = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + var _10: Api.StatsGraph? + if let signature = reader.readInt32() { + _10 = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + var _11: Api.StatsGraph? + if let signature = reader.readInt32() { + _11 = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + var _12: Api.StatsGraph? + if let signature = reader.readInt32() { + _12 = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + var _13: Api.StatsGraph? + if let signature = reader.readInt32() { + _13 = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + let _c8 = _8 != nil + let _c9 = _9 != nil + let _c10 = _10 != nil + let _c11 = _11 != nil + let _c12 = _12 != nil + let _c13 = _13 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 { + return Api.stats.BroadcastStats.broadcastStats(period: _1!, followers: _2!, viewsPerPost: _3!, sharesPerPost: _4!, enabledNotifications: _5!, viewsBySource: _6!, newFollowersBySource: _7!, languages: _8!, growthGraph: _9!, followersGraph: _10!, muteGraph: _11!, topHoursGraph: _12!, interactionsGraph: _13!) + } + else { + return nil + } + } + + } } } public extension Api { diff --git a/submodules/TelegramApi/Sources/Api3.swift b/submodules/TelegramApi/Sources/Api3.swift index 74e4884bf6..2c7411ffbc 100644 --- a/submodules/TelegramApi/Sources/Api3.swift +++ b/submodules/TelegramApi/Sources/Api3.swift @@ -3214,6 +3214,54 @@ public extension Api { return result }) } + + public static func getDialogFilters() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.DialogFilter]>) { + let buffer = Buffer() + buffer.appendInt32(-241247891) + + return (FunctionDescription(name: "messages.getDialogFilters", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.DialogFilter]? in + let reader = BufferReader(buffer) + var result: [Api.DialogFilter]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 0, elementType: Api.DialogFilter.self) + } + return result + }) + } + + public static func updateDialogFilter(flags: Int32, id: Int32, filter: Api.DialogFilter?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(450142282) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(id, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {filter!.serialize(buffer, true)} + return (FunctionDescription(name: "messages.updateDialogFilter", parameters: [("flags", flags), ("id", id), ("filter", filter)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } + + public static func updateDialogFiltersOrder(order: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-983318044) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(order.count)) + for item in order { + serializeInt32(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "messages.updateDialogFiltersOrder", parameters: [("order", order)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } } public struct channels { public static func readHistory(channel: Api.InputChannel, maxId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { @@ -3885,6 +3933,50 @@ public extension Api { return result }) } + + public static func getBankCardData(number: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(779736953) + serializeString(number, buffer: buffer, boxed: false) + return (FunctionDescription(name: "payments.getBankCardData", parameters: [("number", number)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.BankCardData? in + let reader = BufferReader(buffer) + var result: Api.payments.BankCardData? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.payments.BankCardData + } + return result + }) + } + } + public struct stats { + public static func getBroadcastStats(flags: Int32, channel: Api.InputChannel) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1421720550) + serializeInt32(flags, buffer: buffer, boxed: false) + channel.serialize(buffer, true) + return (FunctionDescription(name: "stats.getBroadcastStats", parameters: [("flags", flags), ("channel", channel)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.stats.BroadcastStats? in + let reader = BufferReader(buffer) + var result: Api.stats.BroadcastStats? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.stats.BroadcastStats + } + return result + }) + } + + public static func loadAsyncGraph(token: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1749505346) + serializeString(token, buffer: buffer, boxed: false) + return (FunctionDescription(name: "stats.loadAsyncGraph", parameters: [("token", token)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.StatsGraph? in + let reader = BufferReader(buffer) + var result: Api.StatsGraph? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + return result + }) + } } public struct auth { public static func checkPhone(phoneNumber: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { diff --git a/submodules/TelegramCore/Sources/Account.swift b/submodules/TelegramCore/Sources/Account.swift index 65f1145eae..cec053cf33 100644 --- a/submodules/TelegramCore/Sources/Account.swift +++ b/submodules/TelegramCore/Sources/Account.swift @@ -1044,6 +1044,7 @@ public class Account { self.managedOperationsDisposable.add(managedApplyPendingMessageReactionsActions(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start()) self.managedOperationsDisposable.add(managedSynchronizeEmojiKeywordsOperations(postbox: self.postbox, network: self.network).start()) self.managedOperationsDisposable.add(managedApplyPendingScheduledMessagesActions(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start()) + self.managedOperationsDisposable.add(managedChatListFilters(postbox: self.postbox, network: self.network).start()) let importantBackgroundOperations: [Signal] = [ managedSynchronizeChatInputStateOperations(postbox: self.postbox, network: self.network) |> map { $0 ? AccountRunningImportantTasks.other : [] }, diff --git a/submodules/TelegramCore/Sources/AccountManager.swift b/submodules/TelegramCore/Sources/AccountManager.swift index f4e0043af9..eb61eb0fec 100644 --- a/submodules/TelegramCore/Sources/AccountManager.swift +++ b/submodules/TelegramCore/Sources/AccountManager.swift @@ -152,6 +152,7 @@ private var declaredEncodables: Void = { declareEncodable(EmbeddedMediaStickersMessageAttribute.self, f: { EmbeddedMediaStickersMessageAttribute(decoder: $0) }) declareEncodable(TelegramMediaWebpageAttribute.self, f: { TelegramMediaWebpageAttribute(decoder: $0) }) declareEncodable(CachedPollOptionResult.self, f: { CachedPollOptionResult(decoder: $0) }) + declareEncodable(ChatListFiltersState.self, f: { ChatListFiltersState(decoder: $0) }) return }() diff --git a/submodules/TelegramCore/Sources/ChatListFiltering.swift b/submodules/TelegramCore/Sources/ChatListFiltering.swift new file mode 100644 index 0000000000..1e01e92c02 --- /dev/null +++ b/submodules/TelegramCore/Sources/ChatListFiltering.swift @@ -0,0 +1,378 @@ +import Foundation +import Postbox +import SwiftSignalKit +import TelegramApi + +import SyncCore + +public struct ChatListFilterPeerCategories: OptionSet { + public var rawValue: Int32 + + public init(rawValue: Int32) { + self.rawValue = rawValue + } + + public static let privateChats = ChatListFilterPeerCategories(rawValue: 1 << 0) + public static let secretChats = ChatListFilterPeerCategories(rawValue: 1 << 1) + public static let privateGroups = ChatListFilterPeerCategories(rawValue: 1 << 2) + public static let bots = ChatListFilterPeerCategories(rawValue: 1 << 3) + public static let publicGroups = ChatListFilterPeerCategories(rawValue: 1 << 4) + public static let channels = ChatListFilterPeerCategories(rawValue: 1 << 5) + + public static let all: ChatListFilterPeerCategories = [ + .privateChats, + .secretChats, + .privateGroups, + .bots, + .publicGroups, + .channels + ] +} + +private struct ChatListFilterPeerApiCategories: OptionSet { + var rawValue: Int32 + + init(rawValue: Int32) { + self.rawValue = rawValue + } + + static let privateChats = ChatListFilterPeerApiCategories(rawValue: 1 << 0) + static let secretChats = ChatListFilterPeerApiCategories(rawValue: 1 << 1) + static let privateGroups = ChatListFilterPeerApiCategories(rawValue: 1 << 2) + static let publicGroups = ChatListFilterPeerApiCategories(rawValue: 1 << 3) + static let channels = ChatListFilterPeerApiCategories(rawValue: 1 << 4) + static let bots = ChatListFilterPeerApiCategories(rawValue: 1 << 5) +} + +extension ChatListFilterPeerCategories { + init(apiFlags: Int32) { + let flags = ChatListFilterPeerApiCategories(rawValue: apiFlags) + var result: ChatListFilterPeerCategories = [] + if flags.contains(.privateChats) { + result.insert(.privateChats) + } + if flags.contains(.secretChats) { + result.insert(.secretChats) + } + if flags.contains(.privateGroups) { + result.insert(.privateGroups) + } + if flags.contains(.publicGroups) { + result.insert(.publicGroups) + } + if flags.contains(.channels) { + result.insert(.channels) + } + if flags.contains(.bots) { + result.insert(.bots) + } + self = result + } + + var apiFlags: Int32 { + var result: ChatListFilterPeerApiCategories = [] + if self.contains(.privateChats) { + result.insert(.privateChats) + } + if self.contains(.secretChats) { + result.insert(.secretChats) + } + if self.contains(.privateGroups) { + result.insert(.privateGroups) + } + if self.contains(.publicGroups) { + result.insert(.publicGroups) + } + if self.contains(.channels) { + result.insert(.channels) + } + if self.contains(.bots) { + result.insert(.bots) + } + return result.rawValue + } +} + +public struct ChatListFilter: PostboxCoding, Equatable { + public var id: Int32 + public var title: String? + public var categories: ChatListFilterPeerCategories + public var excludeMuted: Bool + public var excludeRead: Bool + public var includePeers: [PeerId] + + public init( + id: Int32, + title: String?, + categories: ChatListFilterPeerCategories, + excludeMuted: Bool, + excludeRead: Bool, + includePeers: [PeerId] + ) { + self.id = id + self.title = title + self.categories = categories + self.excludeMuted = excludeMuted + self.excludeRead = excludeRead + self.includePeers = includePeers + } + + public init(decoder: PostboxDecoder) { + self.id = decoder.decodeInt32ForKey("id", orElse: 0) + self.title = decoder.decodeOptionalStringForKey("title") + self.categories = ChatListFilterPeerCategories(rawValue: decoder.decodeInt32ForKey("categories", orElse: 0)) + self.excludeMuted = decoder.decodeInt32ForKey("excludeMuted", orElse: 0) != 0 + self.excludeRead = decoder.decodeInt32ForKey("excludeRead", orElse: 0) != 0 + self.includePeers = decoder.decodeInt64ArrayForKey("includePeers").map(PeerId.init) + } + + public func encode(_ encoder: PostboxEncoder) { + encoder.encodeInt32(self.id, forKey: "id") + if let title = self.title { + encoder.encodeString(title, forKey: "title") + } else { + encoder.encodeNil(forKey: "title") + } + encoder.encodeInt32(self.categories.rawValue, forKey: "categories") + encoder.encodeInt32(self.excludeMuted ? 1 : 0, forKey: "excludeMuted") + encoder.encodeInt32(self.excludeRead ? 1 : 0, forKey: "excludeRead") + encoder.encodeInt64Array(self.includePeers.map { $0.toInt64() }, forKey: "includePeers") + } +} + +extension ChatListFilter { + init(apiFilter: Api.DialogFilter) { + switch apiFilter { + case let .dialogFilter(flags, id, title, includePeers): + self.init( + id: id, + title: title.isEmpty ? nil : title, + categories: ChatListFilterPeerCategories(apiFlags: flags), + excludeMuted: (flags & (1 << 11)) != 0, + excludeRead: (flags & (1 << 12)) != 0, + includePeers: includePeers.compactMap { peer -> PeerId? in + switch peer { + case let .inputPeerUser(userId, _): + return PeerId(namespace: Namespaces.Peer.CloudUser, id: userId) + case let .inputPeerChat(chatId): + return PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId) + case let .inputPeerChannel(channelId, _): + return PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId) + default: + return nil + } + } + ) + } + } + + func apiFilter(transaction: Transaction) -> Api.DialogFilter { + var flags: Int32 = 0 + if self.excludeMuted { + flags |= 1 << 11 + } + if self.excludeRead { + flags |= 1 << 12 + } + flags |= self.categories.apiFlags + return .dialogFilter(flags: flags, id: self.id, title: self.title ?? "", includePeers: self.includePeers.compactMap { peerId -> Api.InputPeer? in + return transaction.getPeer(peerId).flatMap(apiInputPeer) + }) + } +} + +public enum RequestUpdateChatListFilterError { + case generic +} + +public func requestUpdateChatListFilter(account: Account, id: Int32, filter: ChatListFilter?) -> Signal { + return account.postbox.transaction { transaction -> Api.DialogFilter? in + return filter?.apiFilter(transaction: transaction) + } + |> castError(RequestUpdateChatListFilterError.self) + |> mapToSignal { inputFilter -> Signal in + var flags: Int32 = 0 + if inputFilter != nil { + flags |= 1 << 0 + } + return account.network.request(Api.functions.messages.updateDialogFilter(flags: flags, id: id, filter: inputFilter)) + |> mapError { _ -> RequestUpdateChatListFilterError in + return .generic + } + |> mapToSignal { _ -> Signal in + return .complete() + } + } +} + +public enum RequestUpdateChatListFilterOrderError { + case generic +} + +public func requestUpdateChatListFilterOrder(account: Account, ids: [Int32]) -> Signal { + return account.network.request(Api.functions.messages.updateDialogFiltersOrder(order: ids)) + |> mapError { _ -> RequestUpdateChatListFilterOrderError in + return .generic + } + |> mapToSignal { _ -> Signal in + return .complete() + } +} + +private enum RequestChatListFiltersError { + case generic +} + +private func requestChatListFilters(postbox: Postbox, network: Network) -> Signal<[ChatListFilter], RequestChatListFiltersError> { + return network.request(Api.functions.messages.getDialogFilters()) + |> mapError { _ -> RequestChatListFiltersError in + return .generic + } + |> mapToSignal { result -> Signal<[ChatListFilter], RequestChatListFiltersError> in + return postbox.transaction { transaction -> ([ChatListFilter], [Api.InputPeer]) in + var filters: [ChatListFilter] = [] + var missingPeers: [Api.InputPeer] = [] + var missingPeerIds = Set() + for apiFilter in result { + let filter = ChatListFilter(apiFilter: apiFilter) + filters.append(filter) + switch apiFilter { + case let .dialogFilter(_, _, _, includePeers): + for peer in includePeers { + var peerId: PeerId? + switch peer { + case let .inputPeerUser(userId, _): + peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId) + case let .inputPeerChat(chatId): + peerId = PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId) + case let .inputPeerChannel(channelId, _): + peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId) + default: + break + } + if let peerId = peerId { + if transaction.getPeer(peerId) == nil && !missingPeerIds.contains(peerId) { + missingPeerIds.insert(peerId) + missingPeers.append(peer) + } + } + } + } + } + return (filters, missingPeers) + } + |> castError(RequestChatListFiltersError.self) + |> mapToSignal { filtersAndMissingPeers -> Signal<[ChatListFilter], RequestChatListFiltersError> in + let (filters, missingPeers) = filtersAndMissingPeers + return .single(filters) + } + } +} + +func managedChatListFilters(postbox: Postbox, network: Network) -> Signal { + return requestChatListFilters(postbox: postbox, network: network) + |> `catch` { _ -> Signal<[ChatListFilter], NoError> in + return .complete() + } + |> mapToSignal { filters -> Signal in + return postbox.transaction { transaction in + transaction.updatePreferencesEntry(key: PreferencesKeys.chatListFilters, { entry in + var settings = entry as? ChatListFiltersState ?? ChatListFiltersState.default + settings.filters = filters + return settings + }) + } + |> ignoreValues + } +} + +public func replaceRemoteChatListFilters(account: Account) -> Signal { + return requestChatListFilters(postbox: account.postbox, network: account.network) + |> `catch` { _ -> Signal<[ChatListFilter], NoError> in + return .complete() + } + |> mapToSignal { remoteFilters -> Signal in + var deleteSignals: [Signal] = [] + for filter in remoteFilters { + deleteSignals.append(requestUpdateChatListFilter(account: account, id: filter.id, filter: nil) + |> `catch` { _ -> Signal in + return .complete() + } + |> ignoreValues) + } + + let addFilters = account.postbox.transaction { transaction -> [(Int32, ChatListFilter)] in + let settings = transaction.getPreferencesEntry(key: PreferencesKeys.chatListFilters) as? ChatListFiltersState ?? ChatListFiltersState.default + return settings.filters.map { filter -> (Int32, ChatListFilter) in + return (filter.id, filter) + } + } + |> mapToSignal { filters -> Signal in + var signals: [Signal] = [] + for (id, filter) in filters { + signals.append(requestUpdateChatListFilter(account: account, id: id, filter: filter) + |> `catch` { _ -> Signal in + return .complete() + } + |> ignoreValues) + } + return combineLatest(signals) + |> ignoreValues + } + + return combineLatest( + deleteSignals + ) + |> ignoreValues + |> then( + addFilters + ) + } +} + +public struct ChatListFiltersState: PreferencesEntry, Equatable { + public var filters: [ChatListFilter] + public var remoteFilters: [ChatListFilter]? + + public static var `default` = ChatListFiltersState(filters: [], remoteFilters: nil) + + public init(filters: [ChatListFilter], remoteFilters: [ChatListFilter]?) { + self.filters = filters + self.remoteFilters = remoteFilters + } + + public init(decoder: PostboxDecoder) { + self.filters = decoder.decodeObjectArrayWithDecoderForKey("filters") + self.remoteFilters = decoder.decodeOptionalObjectArrayWithDecoderForKey("remoteFilters") + } + + public func encode(_ encoder: PostboxEncoder) { + encoder.encodeObjectArray(self.filters, forKey: "filters") + if let remoteFilters = self.remoteFilters { + encoder.encodeObjectArray(remoteFilters, forKey: "remoteFilters") + } else { + encoder.encodeNil(forKey: "remoteFilters") + } + } + + public func isEqual(to: PreferencesEntry) -> Bool { + if let to = to as? ChatListFiltersState, self == to { + return true + } else { + return false + } + } +} + +public func updateChatListFilterSettingsInteractively(postbox: Postbox, _ f: @escaping (ChatListFiltersState) -> ChatListFiltersState) -> Signal { + return postbox.transaction { transaction -> ChatListFiltersState in + var result: ChatListFiltersState? + transaction.updatePreferencesEntry(key: PreferencesKeys.chatListFilters, { entry in + var settings = entry as? ChatListFiltersState ?? ChatListFiltersState.default + let updated = f(settings) + result = updated + return updated + }) + return result ?? .default + } +} diff --git a/submodules/TelegramCore/Sources/ManagedSecretChatOutgoingOperations.swift b/submodules/TelegramCore/Sources/ManagedSecretChatOutgoingOperations.swift index 7754b00b97..d490602165 100644 --- a/submodules/TelegramCore/Sources/ManagedSecretChatOutgoingOperations.swift +++ b/submodules/TelegramCore/Sources/ManagedSecretChatOutgoingOperations.swift @@ -676,6 +676,8 @@ private func decryptedEntities73(_ entities: [MessageTextEntity]?) -> [SecretApi break case .Underline: break + case .BankCard: + break case .Custom: break } @@ -723,6 +725,8 @@ private func decryptedEntities101(_ entities: [MessageTextEntity]?) -> [SecretAp result.append(.messageEntityBlockquote(offset: Int32(entity.range.lowerBound), length: Int32(entity.range.count))) case .Underline: result.append(.messageEntityUnderline(offset: Int32(entity.range.lowerBound), length: Int32(entity.range.count))) + case .BankCard: + break case .Custom: break } diff --git a/submodules/TelegramCore/Sources/Serialization.swift b/submodules/TelegramCore/Sources/Serialization.swift index 02470ccbac..15b20dd3d8 100644 --- a/submodules/TelegramCore/Sources/Serialization.swift +++ b/submodules/TelegramCore/Sources/Serialization.swift @@ -210,7 +210,7 @@ public class BoxedMessage: NSObject { public class Serialization: NSObject, MTSerialization { public func currentLayer() -> UInt { - return 109 + return 110 } public func parseMessage(_ data: Data!) -> Any! { diff --git a/submodules/TelegramCore/Sources/StoreMessage_Telegram.swift b/submodules/TelegramCore/Sources/StoreMessage_Telegram.swift index d5c0b31029..44751ce910 100644 --- a/submodules/TelegramCore/Sources/StoreMessage_Telegram.swift +++ b/submodules/TelegramCore/Sources/StoreMessage_Telegram.swift @@ -386,6 +386,8 @@ func messageTextEntitiesFromApiEntities(_ entities: [Api.MessageEntity]) -> [Mes result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .Strikethrough)) case let .messageEntityBlockquote(offset, length): result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .BlockQuote)) + case let .messageEntityBankCard(offset, length): + result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .BankCard)) } } return result diff --git a/submodules/TelegramCore/Sources/TextEntitiesMessageAttribute.swift b/submodules/TelegramCore/Sources/TextEntitiesMessageAttribute.swift index c898bed30f..1702002184 100644 --- a/submodules/TelegramCore/Sources/TextEntitiesMessageAttribute.swift +++ b/submodules/TelegramCore/Sources/TextEntitiesMessageAttribute.swift @@ -45,6 +45,8 @@ func apiEntitiesFromMessageTextEntities(_ entities: [MessageTextEntity], associa apiEntities.append(.messageEntityBlockquote(offset: offset, length: length)) case .Underline: apiEntities.append(.messageEntityUnderline(offset: offset, length: length)) + case .BankCard: + apiEntities.append(.messageEntityBankCard(offset: offset, length: length)) case .Custom: break } diff --git a/submodules/TelegramCore/Sources/UpdateCachedPeerData.swift b/submodules/TelegramCore/Sources/UpdateCachedPeerData.swift index 1050b92be7..d9d7142db3 100644 --- a/submodules/TelegramCore/Sources/UpdateCachedPeerData.swift +++ b/submodules/TelegramCore/Sources/UpdateCachedPeerData.swift @@ -319,7 +319,7 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerI } switch fullChat { - case let .channelFull(flags, _, about, participantsCount, adminsCount, kickedCount, bannedCount, _, _, _, _, _, _, apiExportedInvite, apiBotInfos, migratedFromChatId, migratedFromMaxId, pinnedMsgId, stickerSet, minAvailableMsgId, folderId, linkedChatId, location, slowmodeSeconds, slowmodeNextSendDate, pts): + case let .channelFull(flags, _, about, participantsCount, adminsCount, kickedCount, bannedCount, _, _, _, _, _, _, apiExportedInvite, apiBotInfos, migratedFromChatId, migratedFromMaxId, pinnedMsgId, stickerSet, minAvailableMsgId, folderId, linkedChatId, location, slowmodeSeconds, slowmodeNextSendDate, _, pts): var channelFlags = CachedChannelFlags() if (flags & (1 << 3)) != 0 { channelFlags.insert(.canDisplayParticipants) diff --git a/submodules/TelegramUI/TelegramUI/DeclareEncodables.swift b/submodules/TelegramUI/TelegramUI/DeclareEncodables.swift index 01c3ef9546..8de131f329 100644 --- a/submodules/TelegramUI/TelegramUI/DeclareEncodables.swift +++ b/submodules/TelegramUI/TelegramUI/DeclareEncodables.swift @@ -54,7 +54,6 @@ private var telegramUIDeclaredEncodables: Void = { declareEncodable(WebBrowserSettings.self, f: { WebBrowserSettings(decoder: $0) }) declareEncodable(IntentsSettings.self, f: { IntentsSettings(decoder: $0) }) declareEncodable(CachedGeocode.self, f: { CachedGeocode(decoder: $0) }) - declareEncodable(ChatListFilterSettings.self, f: { ChatListFilterSettings(decoder: $0) }) return }() diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoFilesPane.swift b/submodules/TelegramUI/TelegramUI/PeerInfoFilesPane.swift index e5b8b0bc22..1a2b77ee30 100644 --- a/submodules/TelegramUI/TelegramUI/PeerInfoFilesPane.swift +++ b/submodules/TelegramUI/TelegramUI/PeerInfoFilesPane.swift @@ -172,7 +172,7 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode { } } - func update(size: CGSize, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) { + func update(size: CGSize, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) { self.currentParams = (size, isScrollingLockedAtTop, presentationData) transition.updateFrame(node: self.listNode, frame: CGRect(origin: CGPoint(), size: size)) @@ -185,6 +185,12 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode { self.listNode.messageInCurrentHistoryView(id) } + func transferVelocity(_ velocity: CGFloat) { + if velocity > 0.0 { + self.listNode.transferVelocity(velocity) + } + } + func transitionNodeForGallery(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { var transitionNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? self.listNode.forEachItemNode { itemNode in diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoGroupsInCommonPaneNode.swift b/submodules/TelegramUI/TelegramUI/PeerInfoGroupsInCommonPaneNode.swift index 82c1c0b91f..89477a9ce3 100644 --- a/submodules/TelegramUI/TelegramUI/PeerInfoGroupsInCommonPaneNode.swift +++ b/submodules/TelegramUI/TelegramUI/PeerInfoGroupsInCommonPaneNode.swift @@ -102,7 +102,7 @@ final class PeerInfoGroupsInCommonPaneNode: ASDisplayNode, PeerInfoPaneNode { } } - func update(size: CGSize, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) { + func update(size: CGSize, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) { let isFirstLayout = self.currentParams == nil self.currentParams = (size, isScrollingLockedAtTop, presentationData) @@ -156,6 +156,9 @@ final class PeerInfoGroupsInCommonPaneNode: ASDisplayNode, PeerInfoPaneNode { return nil } + func transferVelocity(_ velocity: CGFloat) { + } + func transitionNodeForGallery(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { return nil } diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoScreen.swift b/submodules/TelegramUI/TelegramUI/PeerInfoScreen.swift index fe64232ab7..1c4c6b0612 100644 --- a/submodules/TelegramUI/TelegramUI/PeerInfoScreen.swift +++ b/submodules/TelegramUI/TelegramUI/PeerInfoScreen.swift @@ -904,7 +904,7 @@ private final class PeerInfoHeaderNode: ASDisplayNode { private(set) var isAvatarExpanded: Bool - private let avatarListNode: PeerInfoAvatarListNode + let avatarListNode: PeerInfoAvatarListNode let regularContentNode: PeerInfoHeaderRegularContentNode let editingContentNode: PeerInfoHeaderEditingContentNode @@ -1195,7 +1195,7 @@ private final class PeerInfoHeaderNode: ASDisplayNode { } let titleScale = (transitionFraction * transitionSourceTitleFrame.height + (1.0 - transitionFraction) * titleFrame.height * neutralTitleScale) / (titleFrame.height) - let subtitleScale = (transitionFraction * transitionSourceSubtitleFrame.height + (1.0 - transitionFraction) * subtitleFrame.height * neutralSubtitleScale) / (subtitleFrame.height) + let subtitleScale = max(0.01, min(10.0, (transitionFraction * transitionSourceSubtitleFrame.height + (1.0 - transitionFraction) * subtitleFrame.height * neutralSubtitleScale) / (subtitleFrame.height))) let titleOrigin = CGPoint(x: transitionFraction * transitionSourceTitleFrame.minX + (1.0 - transitionFraction) * titleFrame.minX, y: transitionFraction * transitionSourceTitleFrame.minY + (1.0 - transitionFraction) * titleFrame.minY) let subtitleOrigin = CGPoint(x: transitionFraction * transitionSourceSubtitleFrame.minX + (1.0 - transitionFraction) * subtitleFrame.minX, y: transitionFraction * transitionSourceSubtitleFrame.minY + (1.0 - transitionFraction) * subtitleFrame.minY) @@ -1441,8 +1441,9 @@ private final class PeerInfoHeaderNode: ASDisplayNode { protocol PeerInfoPaneNode: ASDisplayNode { var isReady: Signal { get } - func update(size: CGSize, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) + func update(size: CGSize, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) func scrollToTop() -> Bool + func transferVelocity(_ velocity: CGFloat) func findLoadedMessage(id: MessageId) -> Message? func transitionNodeForGallery(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? func updateSelectedMessages(animated: Bool) @@ -1466,21 +1467,21 @@ final class PeerInfoPaneInteraction { private final class PeerInfoPaneWrapper { let key: PeerInfoPaneKey let node: PeerInfoPaneNode - private var appliedParams: (CGSize, Bool, PresentationData)? + private var appliedParams: (CGSize, CGFloat, Bool, PresentationData)? init(key: PeerInfoPaneKey, node: PeerInfoPaneNode) { self.key = key self.node = node } - func update(size: CGSize, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) { - if let (currentSize, currentIsScrollingLockedAtTop, currentPresentationData) = self.appliedParams { + func update(size: CGSize, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) { + if let (currentSize, visibleHeight, currentIsScrollingLockedAtTop, currentPresentationData) = self.appliedParams { if currentSize == size && currentIsScrollingLockedAtTop == isScrollingLockedAtTop && currentPresentationData === presentationData { return } } - self.appliedParams = (size, isScrollingLockedAtTop, presentationData) - self.node.update(size: size, isScrollingLockedAtTop: isScrollingLockedAtTop, presentationData: presentationData, synchronous: synchronous, transition: transition) + self.appliedParams = (size, visibleHeight, isScrollingLockedAtTop, presentationData) + self.node.update(size: size, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, presentationData: presentationData, synchronous: synchronous, transition: transition) } } @@ -1582,6 +1583,8 @@ private final class PeerInfoPaneTabsContainerNode: ASDisplayNode { func update(size: CGSize, presentationData: PresentationData, paneList: [PeerInfoPaneSpecifier], selectedPane: PeerInfoPaneKey?, transition: ContainedViewLayoutTransition) { transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: size)) + let focusOnSelectedPane = self.currentParams?.1 != selectedPane + if self.currentParams?.2.theme !== presentationData.theme { self.selectedLineNode.image = generateImage(CGSize(width: 7.0, height: 4.0), rotatedContext: { size, context in context.clear(CGRect(origin: CGPoint(), size: size)) @@ -1673,6 +1676,16 @@ private final class PeerInfoPaneTabsContainerNode: ASDisplayNode { if let selectedFrame = selectedFrame { self.selectedLineNode.isHidden = false transition.updateFrame(node: self.selectedLineNode, frame: CGRect(origin: CGPoint(x: selectedFrame.minX, y: size.height - 4.0), size: CGSize(width: selectedFrame.width, height: 4.0))) + if focusOnSelectedPane { + if selectedPane == paneList.first?.key { + transition.updateBounds(node: self.scrollNode, bounds: CGRect(origin: CGPoint(), size: self.scrollNode.bounds.size)) + } else if selectedPane == paneList.last?.key { + transition.updateBounds(node: self.scrollNode, bounds: CGRect(origin: CGPoint(x: self.scrollNode.view.contentSize.width - self.scrollNode.bounds.width, y: 0.0), size: self.scrollNode.bounds.size)) + } else { + let contentOffsetX = max(0.0, min(self.scrollNode.view.contentSize.width - self.scrollNode.bounds.width, floor(selectedFrame.midX - self.scrollNode.bounds.width / 2.0))) + transition.updateBounds(node: self.scrollNode, bounds: CGRect(origin: CGPoint(x: contentOffsetX, y: 0.0), size: self.scrollNode.bounds.size)) + } + } } else { self.selectedLineNode.isHidden = true } @@ -1695,9 +1708,9 @@ private final class PeerInfoPaneContainerNode: ASDisplayNode { let isReady = Promise() var didSetIsReady = false - private var currentParams: (size: CGSize, expansionFraction: CGFloat, presentationData: PresentationData, data: PeerInfoScreenData?)? + private var currentParams: (size: CGSize, visibleHeight: CGFloat, expansionFraction: CGFloat, presentationData: PresentationData, data: PeerInfoScreenData?)? private(set) var currentPaneKey: PeerInfoPaneKey? - private var currentPane: PeerInfoPaneWrapper? + private(set) var currentPane: PeerInfoPaneWrapper? private var currentCandidatePaneKey: PeerInfoPaneKey? private var candidatePane: (PeerInfoPaneWrapper, Disposable, Bool)? @@ -1763,8 +1776,8 @@ private final class PeerInfoPaneContainerNode: ASDisplayNode { } strongSelf.currentCandidatePaneKey = key - if let (size, expansionFraction, presentationData, data) = strongSelf.currentParams { - strongSelf.update(size: size, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: .immediate) + if let (size, visibleHeight, expansionFraction, presentationData, data) = strongSelf.currentParams { + strongSelf.update(size: size, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: .immediate) } } } @@ -1793,7 +1806,7 @@ private final class PeerInfoPaneContainerNode: ASDisplayNode { } } - func update(size: CGSize, expansionFraction: CGFloat, presentationData: PresentationData, data: PeerInfoScreenData?, transition: ContainedViewLayoutTransition) { + func update(size: CGSize, visibleHeight: CGFloat, expansionFraction: CGFloat, presentationData: PresentationData, data: PeerInfoScreenData?, transition: ContainedViewLayoutTransition) { let availablePanes = data?.availablePanes ?? [] let previousCurrentPaneKey = self.currentPaneKey @@ -1812,7 +1825,7 @@ private final class PeerInfoPaneContainerNode: ASDisplayNode { self.currentCandidatePaneKey = availablePanes.first } - self.currentParams = (size, expansionFraction, presentationData, data) + self.currentParams = (size, visibleHeight, expansionFraction, presentationData, data) transition.updateAlpha(node: self.coveringBackgroundNode, alpha: expansionFraction) @@ -1874,8 +1887,8 @@ private final class PeerInfoPaneContainerNode: ASDisplayNode { strongSelf.candidatePane = (candidatePane, disposable, true) if shouldReLayout { - if let (size, expansionFraction, presentationData, data) = strongSelf.currentParams { - strongSelf.update(size: size, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: strongSelf.currentPane != nil ? .animated(duration: 0.35, curve: .spring) : .immediate) + if let (size, visibleHeight, expansionFraction, presentationData, data) = strongSelf.currentParams { + strongSelf.update(size: size, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: strongSelf.currentPane != nil ? .animated(duration: 0.35, curve: .spring) : .immediate) } } } @@ -1897,7 +1910,7 @@ private final class PeerInfoPaneContainerNode: ASDisplayNode { self.addSubnode(candidatePane.node) } candidatePane.node.frame = paneFrame - candidatePane.update(size: paneFrame.size, isScrollingLockedAtTop: expansionFraction < 1.0 - CGFloat.ulpOfOne, presentationData: presentationData, synchronous: true, transition: .immediate) + candidatePane.update(size: paneFrame.size, visibleHeight: max(0.0, visibleHeight - paneFrame.minY), isScrollingLockedAtTop: expansionFraction < 1.0 - CGFloat.ulpOfOne, presentationData: presentationData, synchronous: true, transition: .immediate) if let previousPane = previousPane { let directionToRight: Bool @@ -1923,7 +1936,7 @@ private final class PeerInfoPaneContainerNode: ASDisplayNode { let paneTransition: ContainedViewLayoutTransition = paneWasAdded ? .immediate : transition paneTransition.updateFrame(node: currentPane.node, frame: paneFrame) - currentPane.update(size: paneFrame.size, isScrollingLockedAtTop: expansionFraction < 1.0 - CGFloat.ulpOfOne, presentationData: presentationData, synchronous: paneWasAdded, transition: paneTransition) + currentPane.update(size: paneFrame.size, visibleHeight: visibleHeight, isScrollingLockedAtTop: expansionFraction < 1.0 - CGFloat.ulpOfOne, presentationData: presentationData, synchronous: paneWasAdded, transition: paneTransition) } transition.updateFrame(node: self.tabsContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: tabsHeight))) @@ -1949,13 +1962,14 @@ private final class PeerInfoPaneContainerNode: ASDisplayNode { if let (candidatePane, _, _) = self.candidatePane { let paneTransition: ContainedViewLayoutTransition = .immediate paneTransition.updateFrame(node: candidatePane.node, frame: paneFrame) - candidatePane.update(size: paneFrame.size, isScrollingLockedAtTop: expansionFraction < 1.0 - CGFloat.ulpOfOne, presentationData: presentationData, synchronous: true, transition: paneTransition) + candidatePane.update(size: paneFrame.size, visibleHeight: visibleHeight, isScrollingLockedAtTop: expansionFraction < 1.0 - CGFloat.ulpOfOne, presentationData: presentationData, synchronous: true, transition: paneTransition) } - if !self.didSetIsReady { - self.didSetIsReady = true + if !self.didSetIsReady && data != nil { if let currentPane = self.currentPane { + self.didSetIsReady = true self.isReady.set(currentPane.node.isReady) - } else { + } else if self.candidatePane == nil { + self.didSetIsReady = true self.isReady.set(.single(true)) } } @@ -3990,7 +4004,17 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD if !self.didSetReady && self.data != nil { self.didSetReady = true - self._ready.set(self.paneContainerNode.isReady.get()) + let avatarReady = self.headerNode.avatarListNode.isReady.get() + let combinedSignal = combineLatest(queue: .mainQueue(), + avatarReady, + self.paneContainerNode.isReady.get() + ) + |> map { lhs, rhs in + return lhs && rhs + } + self._ready.set(combinedSignal + |> filter { $0 } + |> take(1)) } } @@ -4025,7 +4049,9 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD transition.updateAlpha(node: self.headerNode.separatorNode, alpha: 1.0 - effectiveAreaExpansionFraction) - self.paneContainerNode.update(size: self.paneContainerNode.bounds.size, expansionFraction: paneAreaExpansionFraction, presentationData: self.presentationData, data: self.data, transition: transition) + let visibleHeight = self.scrollNode.view.contentOffset.y + self.scrollNode.view.bounds.height - self.paneContainerNode.frame.minY + + self.paneContainerNode.update(size: self.paneContainerNode.bounds.size, visibleHeight: visibleHeight, expansionFraction: paneAreaExpansionFraction, presentationData: self.presentationData, data: self.data, transition: transition) self.headerNode.navigationButtonContainer.frame = CGRect(origin: CGPoint(x: layout.safeInsets.left, y: layout.statusBarHeight ?? 0.0), size: CGSize(width: layout.size.width - layout.safeInsets.left * 2.0, height: 44.0)) self.headerNode.navigationButtonContainer.isWhite = self.headerNode.isAvatarExpanded @@ -4058,6 +4084,11 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD self.canUpdateAvatarExpansion = true } + private var previousVelocityM1: CGFloat = 0.0 + private var previousVelocity: CGFloat = 0.0 + + private let velocityKey: String = encodeText("`wfsujdbmWfmpdjuz", -1) + func scrollViewDidScroll(_ scrollView: UIScrollView) { if self.ignoreScrolling { return @@ -4065,6 +4096,12 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD self.updateNavigation(transition: .immediate, additive: false) if !self.state.isEditing { + self.previousVelocityM1 = self.previousVelocity + if let value = (scrollView.value(forKey: self.velocityKey) as? NSNumber)?.doubleValue { + //print("previousVelocity \(CGFloat(value))") + self.previousVelocity = CGFloat(value) + } + let offsetY = self.scrollNode.view.contentOffset.y var shouldBeExpanded: Bool? if offsetY <= -32.0 && scrollView.isDragging && scrollView.isTracking { @@ -4096,6 +4133,17 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } } + func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { + guard let (_, navigationHeight) = self.validLayout else { + return + } + + let paneAreaExpansionFinalPoint: CGFloat = self.paneContainerNode.frame.minY - navigationHeight + if abs(scrollView.contentOffset.y - paneAreaExpansionFinalPoint) < .ulpOfOne { + self.paneContainerNode.currentPane?.node.transferVelocity(self.previousVelocityM1) + } + } + private func updateNavigationExpansionPresentation(isExpanded: Bool, animated: Bool) { if let controller = self.controller { controller.statusBar.updateStatusBarStyle(isExpanded ? .White : self.presentationData.theme.rootController.statusBarStyle.style, animated: animated) @@ -4413,7 +4461,7 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig } let titleScale = (fraction * previousTitleNode.bounds.height + (1.0 - fraction) * self.headerNode.titleNode.bounds.height) / previousTitleNode.bounds.height - let subtitleScale = (fraction * previousStatusNode.bounds.height + (1.0 - fraction) * self.headerNode.subtitleNode.bounds.height) / previousStatusNode.bounds.height + let subtitleScale = max(0.01, min(10.0, (fraction * previousStatusNode.bounds.height + (1.0 - fraction) * self.headerNode.subtitleNode.bounds.height) / previousStatusNode.bounds.height)) transition.updateFrame(node: previousTitleContainerNode, frame: CGRect(origin: self.headerNode.titleNodeRawContainer.frame.origin.offsetBy(dx: previousTitleFrame.size.width * 0.5 * (titleScale - 1.0), dy: previousTitleFrame.size.height * 0.5 * (titleScale - 1.0)), size: previousTitleFrame.size)) transition.updateFrame(node: previousTitleNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: previousTitleFrame.size)) @@ -4443,3 +4491,11 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig self.screenNode.insertSubnode(self.headerNode, aboveSubnode: self.screenNode.scrollNode) } } + +private func encodeText(_ string: String, _ key: Int) -> String { + var result = "" + for c in string.unicodeScalars { + result.append(Character(UnicodeScalar(UInt32(Int(c.value) + key))!)) + } + return result +} diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoVisualMediaPane.swift b/submodules/TelegramUI/TelegramUI/PeerInfoVisualMediaPane.swift index 5cca69a898..395b578a67 100644 --- a/submodules/TelegramUI/TelegramUI/PeerInfoVisualMediaPane.swift +++ b/submodules/TelegramUI/TelegramUI/PeerInfoVisualMediaPane.swift @@ -314,7 +314,7 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro return self._itemInteraction! } - private var currentParams: (size: CGSize, isScrollingLockedAtTop: Bool, presentationData: PresentationData)? + private var currentParams: (size: CGSize, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, presentationData: PresentationData)? private let ready = Promise() private var didSetReady: Bool = false @@ -332,6 +332,8 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro private var isRequestingView: Bool = false private var isFirstHistoryView: Bool = true + private var decelerationAnimator: ConstantDisplayLinkAnimator? + init(context: AccountContext, openMessage: @escaping (MessageId) -> Bool, peerId: PeerId, interaction: PeerInfoPaneInteraction) { self.context = context self.peerId = peerId @@ -414,8 +416,8 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro let wasFirstHistoryView = self.isFirstHistoryView self.isFirstHistoryView = false - if let (size, isScrollingLockedAtTop, presentationData) = self.currentParams { - self.update(size: size, isScrollingLockedAtTop: isScrollingLockedAtTop, presentationData: presentationData, synchronous: wasFirstHistoryView, transition: .immediate) + if let (size, visibleHeight, isScrollingLockedAtTop, presentationData) = self.currentParams { + self.update(size: size, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, presentationData: presentationData, synchronous: wasFirstHistoryView, transition: .immediate) if !self.didSetReady { self.didSetReady = true self.ready.set(.single(true)) @@ -442,6 +444,43 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro return nil } + func transferVelocity(_ velocity: CGFloat) { + if velocity > 0.0 { + //print("transferVelocity \(velocity)") + self.decelerationAnimator?.isPaused = true + let startTime = CACurrentMediaTime() + var currentOffset = self.scrollNode.view.contentOffset + let decelerationRate: CGFloat = 0.998 + self.decelerationAnimator = ConstantDisplayLinkAnimator(update: { [weak self] in + guard let strongSelf = self else { + return + } + let t = CACurrentMediaTime() - startTime + var currentVelocity = velocity * 15.0 * CGFloat(pow(Double(decelerationRate), 1000.0 * t)) + //print("value at \(t) = \(currentVelocity)") + currentOffset.y += currentVelocity + let maxOffset = strongSelf.scrollNode.view.contentSize.height - strongSelf.scrollNode.bounds.height + if currentOffset.y >= maxOffset { + currentOffset.y = maxOffset + currentVelocity = 0.0 + } + if currentOffset.y < 0.0 { + currentOffset.y = 0.0 + currentVelocity = 0.0 + } + + if abs(currentVelocity) < 0.1 { + strongSelf.decelerationAnimator?.isPaused = true + strongSelf.decelerationAnimator = nil + } + var contentOffset = strongSelf.scrollNode.view.contentOffset + contentOffset.y = floorToScreenPixels(currentOffset.y) + strongSelf.scrollNode.view.setContentOffset(contentOffset, animated: false) + }) + self.decelerationAnimator?.isPaused = false + } + } + func transitionNodeForGallery(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { for item in self.mediaItems { if item.message.id == messageId { @@ -461,8 +500,8 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro } } - func update(size: CGSize, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) { - self.currentParams = (size, isScrollingLockedAtTop, presentationData) + func update(size: CGSize, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) { + self.currentParams = (size, visibleHeight, isScrollingLockedAtTop, presentationData) transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: size)) @@ -474,7 +513,7 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro let contentHeight = CGFloat(rowCount + 1) * itemSpacing + CGFloat(rowCount) * itemSize self.scrollNode.view.contentSize = CGSize(width: size.width, height: contentHeight) - self.updateVisibleItems(size: size, theme: presentationData.theme, synchronousLoad: synchronous) + self.updateVisibleItems(size: size, visibleHeight: visibleHeight, theme: presentationData.theme, synchronousLoad: synchronous) if isScrollingLockedAtTop { transition.updateBounds(node: self.scrollNode, bounds: CGRect(origin: CGPoint(), size: self.scrollNode.bounds.size)) @@ -482,9 +521,14 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro self.scrollNode.view.isScrollEnabled = !isScrollingLockedAtTop } + func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { + self.decelerationAnimator?.isPaused = true + self.decelerationAnimator = nil + } + func scrollViewDidScroll(_ scrollView: UIScrollView) { - if let (size, _, presentationData) = self.currentParams { - self.updateVisibleItems(size: size, theme: presentationData.theme, synchronousLoad: false) + if let (size, visibleHeight, _, presentationData) = self.currentParams { + self.updateVisibleItems(size: size, visibleHeight: visibleHeight, theme: presentationData.theme, synchronousLoad: false) if scrollView.contentOffset.y >= scrollView.contentSize.height - scrollView.bounds.height * 2.0, let currentView = self.currentView, currentView.earlierId != nil { if !self.isRequestingView { @@ -495,9 +539,9 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro } } - private func updateVisibleItems(size: CGSize, theme: PresentationTheme, synchronousLoad: Bool) { + private func updateVisibleItems(size: CGSize, visibleHeight: CGFloat, theme: PresentationTheme, synchronousLoad: Bool) { let itemSpacing: CGFloat = 1.0 - let itemsInRow: Int = max(3, min(6, Int(size.width / 100.0))) + let itemsInRow: Int = max(3, min(6, Int(size.width / 140.0))) let itemSize: CGFloat = floor(size.width / CGFloat(itemsInRow)) let rowCount: Int = self.mediaItems.count / itemsInRow + (self.mediaItems.count % itemsInRow == 0 ? 0 : 1) @@ -529,7 +573,11 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro self.scrollNode.addSubnode(itemNode) } itemNode.frame = itemFrame - itemNode.update(size: itemFrame.size, item: self.mediaItems[i], theme: theme, synchronousLoad: synchronousLoad) + var itemSynchronousLoad = false + if itemFrame.maxY <= visibleHeight { + itemSynchronousLoad = synchronousLoad + } + itemNode.update(size: itemFrame.size, item: self.mediaItems[i], theme: theme, synchronousLoad: itemSynchronousLoad) } } var removeKeys: [UInt32] = [] @@ -544,4 +592,17 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro } } } + + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + guard let result = super.hitTest(point, with: event) else { + return nil + } + if self.decelerationAnimator != nil { + self.decelerationAnimator?.isPaused = true + self.decelerationAnimator = nil + + return self.scrollNode.view + } + return result + } } diff --git a/submodules/TelegramUIPreferences/Sources/ChatListFilterSettings.swift b/submodules/TelegramUIPreferences/Sources/ChatListFilterSettings.swift deleted file mode 100644 index 684bdbaa1a..0000000000 --- a/submodules/TelegramUIPreferences/Sources/ChatListFilterSettings.swift +++ /dev/null @@ -1,135 +0,0 @@ -import Foundation -import Postbox -import SwiftSignalKit -import SyncCore - -public struct ChatListIncludeCategoryFilter: OptionSet { - public var rawValue: Int32 - - public init(rawValue: Int32) { - self.rawValue = rawValue - } - - public static let muted = ChatListIncludeCategoryFilter(rawValue: 1 << 1) - public static let privateChats = ChatListIncludeCategoryFilter(rawValue: 1 << 2) - public static let secretChats = ChatListIncludeCategoryFilter(rawValue: 1 << 3) - public static let privateGroups = ChatListIncludeCategoryFilter(rawValue: 1 << 4) - public static let bots = ChatListIncludeCategoryFilter(rawValue: 1 << 5) - public static let publicGroups = ChatListIncludeCategoryFilter(rawValue: 1 << 6) - public static let channels = ChatListIncludeCategoryFilter(rawValue: 1 << 7) - public static let read = ChatListIncludeCategoryFilter(rawValue: 1 << 8) - - public static let all: ChatListIncludeCategoryFilter = [ - .muted, - .privateChats, - .secretChats, - .privateGroups, - .bots, - .publicGroups, - .channels, - .read - ] -} - -public enum ChatListFilterPresetName: Equatable, Hashable, PostboxCoding { - case unread - case custom(String) - - public init(decoder: PostboxDecoder) { - switch decoder.decodeInt32ForKey("_t", orElse: 0) { - case 0: - self = .unread - case 1: - self = .custom(decoder.decodeStringForKey("title", orElse: "Preset")) - default: - assertionFailure() - self = .custom("Preset") - } - } - - public func encode(_ encoder: PostboxEncoder) { - switch self { - case .unread: - encoder.encodeInt32(0, forKey: "_t") - case let .custom(title): - encoder.encodeInt32(1, forKey: "_t") - encoder.encodeString(title, forKey: "title") - } - } -} - -public struct ChatListFilterPreset: Equatable, PostboxCoding { - public var id: Int64 - public var name: ChatListFilterPresetName - public var includeCategories: ChatListIncludeCategoryFilter - public var additionallyIncludePeers: [PeerId] - - public init(id: Int64, name: ChatListFilterPresetName, includeCategories: ChatListIncludeCategoryFilter, additionallyIncludePeers: [PeerId]) { - self.id = id - self.name = name - self.includeCategories = includeCategories - self.additionallyIncludePeers = additionallyIncludePeers - } - - public init(decoder: PostboxDecoder) { - self.id = decoder.decodeInt64ForKey("id", orElse: 0) - self.name = decoder.decodeObjectForKey("name", decoder: { ChatListFilterPresetName(decoder: $0) }) as? ChatListFilterPresetName ?? ChatListFilterPresetName.custom("Preset") - self.includeCategories = ChatListIncludeCategoryFilter(rawValue: decoder.decodeInt32ForKey("includeCategories", orElse: 0)) - self.additionallyIncludePeers = decoder.decodeInt64ArrayForKey("additionallyIncludePeers").map(PeerId.init) - } - - public func encode(_ encoder: PostboxEncoder) { - encoder.encodeInt64(self.id, forKey: "id") - encoder.encodeObject(self.name, forKey: "name") - encoder.encodeInt32(self.includeCategories.rawValue, forKey: "includeCategories") - encoder.encodeInt64Array(self.additionallyIncludePeers.map { $0.toInt64() }, forKey: "additionallyIncludePeers") - } -} - -public struct ChatListFilterSettings: PreferencesEntry, Equatable { - public var presets: [ChatListFilterPreset] - - public static var `default`: ChatListFilterSettings { - return ChatListFilterSettings(presets: [ - ChatListFilterPreset( - id: Int64(arc4random()), - name: .unread, - includeCategories: ChatListIncludeCategoryFilter.all.subtracting(.read), - additionallyIncludePeers: [] - ) - ]) - } - - public init(presets: [ChatListFilterPreset]) { - self.presets = presets - } - - public init(decoder: PostboxDecoder) { - self.presets = decoder.decodeObjectArrayWithDecoderForKey("presets") - } - - public func encode(_ encoder: PostboxEncoder) { - encoder.encodeObjectArray(self.presets, forKey: "presets") - } - - public func isEqual(to: PreferencesEntry) -> Bool { - if let to = to as? ChatListFilterSettings { - return self == to - } else { - return false - } - } -} - -public func updateChatListFilterSettingsInteractively(postbox: Postbox, _ f: @escaping (ChatListFilterSettings) -> ChatListFilterSettings) -> Signal { - return postbox.transaction { transaction -> ChatListFilterSettings in - var result: ChatListFilterSettings? - transaction.updatePreferencesEntry(key: ApplicationSpecificPreferencesKeys.chatListFilterSettings, { entry in - var settings = entry as? ChatListFilterSettings ?? ChatListFilterSettings.default - let updated = f(settings) - result = updated - return updated - }) - return result ?? .default - } -} From 65b22f6ca50696b912c1c31440a21c48704af00c Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sat, 8 Feb 2020 23:07:06 +0000 Subject: [PATCH 46/50] User Info UI improvements --- .../ChatListFilterPresetController.swift | 2 +- .../Sources/ChatListSearchContainerNode.swift | 6 +- .../ContainedViewLayoutTransition.swift | 24 + .../Display/Display/ImmediateTextNode.swift | 14 + .../Navigation/NavigationContainer.swift | 24 +- .../Navigation/NavigationController.swift | 35 +- .../Navigation/NavigationSplitContainer.swift | 10 + .../Display/Display/ViewController.swift | 2 + submodules/LocalMediaResources/BUCK | 4 +- submodules/PeerAvatarGalleryUI/BUCK | 4 +- submodules/SaveToCameraRoll/BUCK | 4 +- .../Sources/SearchDisplayController.swift | 6 +- submodules/SettingsUI/BUCK | 4 +- .../TelegramUI/ChatAvatarNavigationNode.swift | 14 +- .../TelegramUI/ChatController.swift | 20 +- .../ChatInterfaceStateNavigationButtons.swift | 5 + .../TelegramUI/TelegramUI/ChatTitleView.swift | 100 +- .../TelegramUI/ListMessageFileItemNode.swift | 4 +- .../ListItems}/PeerInfoScreenActionItem.swift | 0 .../PeerInfoScreenDisclosureItem.swift | 0 .../PeerInfoScreenLabeledValueItem.swift | 0 ...erInfoScreenSelectableBackgroundNode.swift | 0 .../ListItems}/PeerInfoScreenSwitchItem.swift | 0 .../PeerInfoGroupsInCommonPaneNode.swift | 35 +- .../PeerInfo/Panes/PeerInfoListPaneNode.swift | 125 + .../Panes/PeerInfoVisualMediaPaneNode.swift} | 103 +- .../TelegramUI/PeerInfo/PeerInfoData.swift | 306 ++ .../PeerInfo/PeerInfoHeaderNode.swift | 1497 +++++++++ .../PeerInfo/PeerInfoPaneContainerNode.swift | 553 ++++ .../{ => PeerInfo}/PeerInfoScreen.swift | 2880 +++-------------- .../TelegramUI/PeerInfoFilesPane.swift | 217 -- 31 files changed, 3264 insertions(+), 2734 deletions(-) rename submodules/TelegramUI/TelegramUI/{ => PeerInfo/ListItems}/PeerInfoScreenActionItem.swift (100%) rename submodules/TelegramUI/TelegramUI/{ => PeerInfo/ListItems}/PeerInfoScreenDisclosureItem.swift (100%) rename submodules/TelegramUI/TelegramUI/{ => PeerInfo/ListItems}/PeerInfoScreenLabeledValueItem.swift (100%) rename submodules/TelegramUI/TelegramUI/{ => PeerInfo/ListItems}/PeerInfoScreenSelectableBackgroundNode.swift (100%) rename submodules/TelegramUI/TelegramUI/{ => PeerInfo/ListItems}/PeerInfoScreenSwitchItem.swift (100%) rename submodules/TelegramUI/TelegramUI/{ => PeerInfo/Panes}/PeerInfoGroupsInCommonPaneNode.swift (77%) create mode 100644 submodules/TelegramUI/TelegramUI/PeerInfo/Panes/PeerInfoListPaneNode.swift rename submodules/TelegramUI/TelegramUI/{PeerInfoVisualMediaPane.swift => PeerInfo/Panes/PeerInfoVisualMediaPaneNode.swift} (82%) create mode 100644 submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoData.swift create mode 100644 submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoHeaderNode.swift create mode 100644 submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoPaneContainerNode.swift rename submodules/TelegramUI/TelegramUI/{ => PeerInfo}/PeerInfoScreen.swift (51%) delete mode 100644 submodules/TelegramUI/TelegramUI/PeerInfoFilesPane.swift diff --git a/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift b/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift index 27052bb641..49065df51e 100644 --- a/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift +++ b/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift @@ -371,7 +371,7 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat let _ = (updateChatListFilterSettingsInteractively(postbox: context.account.postbox, { settings in var preset = preset if currentPreset == nil { - preset.id = max(1, settings.filters.map({ $0.id }).max() ?? 1) + preset.id = max(2, settings.filters.map({ $0.id }).max() ?? 2) } var settings = settings settings.filters = settings.filters.filter { $0 != preset && $0 != currentPreset } diff --git a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift index 79fa26f3f7..19cb9e585f 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift @@ -193,8 +193,10 @@ private enum ChatListRecentEntry: Comparable, Identifiable { } }, setPeerIdWithRevealedOptions: setPeerIdWithRevealedOptions, deletePeer: deletePeer, contextAction: peerContextAction.flatMap { peerContextAction in return { node, gesture in - if let chatPeer = peer.peer.peers[peer.peer.peerId] { + if let chatPeer = peer.peer.peers[peer.peer.peerId], chatPeer.id.namespace != Namespaces.Peer.SecretChat { peerContextAction(chatPeer, .recentSearch, node, gesture) + } else { + gesture?.cancel() } } }) @@ -415,7 +417,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable { interaction.peerSelected(peer) }, contextAction: peerContextAction.flatMap { peerContextAction in return { node, gesture in - if let chatPeer = chatPeer { + if let chatPeer = chatPeer, chatPeer.id.namespace != Namespaces.Peer.SecretChat { peerContextAction(chatPeer, .search, node, gesture) } else { gesture?.cancel() diff --git a/submodules/Display/Display/ContainedViewLayoutTransition.swift b/submodules/Display/Display/ContainedViewLayoutTransition.swift index 0200f6f212..7635ad88ba 100644 --- a/submodules/Display/Display/ContainedViewLayoutTransition.swift +++ b/submodules/Display/Display/ContainedViewLayoutTransition.swift @@ -567,6 +567,30 @@ public extension ContainedViewLayoutTransition { } } + func animateTransformScale(view: UIView, from fromScale: CGFloat, completion: ((Bool) -> Void)? = nil) { + let t = view.layer.transform + let currentScale = sqrt((t.m11 * t.m11) + (t.m12 * t.m12) + (t.m13 * t.m13)) + if currentScale.isEqual(to: fromScale) { + if let completion = completion { + completion(true) + } + return + } + + switch self { + case .immediate: + if let completion = completion { + completion(true) + } + case let .animated(duration, curve): + view.layer.animateScale(from: fromScale, to: currentScale, duration: duration, timingFunction: curve.timingFunction, mediaTimingFunction: curve.mediaTimingFunction, completion: { result in + if let completion = completion { + completion(result) + } + }) + } + } + func updateTransformScale(node: ASDisplayNode, scale: CGFloat, beginWithCurrentState: Bool = false, completion: ((Bool) -> Void)? = nil) { let t = node.layer.transform let currentScale = sqrt((t.m11 * t.m11) + (t.m12 * t.m12) + (t.m13 * t.m13)) diff --git a/submodules/Display/Display/ImmediateTextNode.swift b/submodules/Display/Display/ImmediateTextNode.swift index 38488ecda3..25d8fb69e7 100644 --- a/submodules/Display/Display/ImmediateTextNode.swift +++ b/submodules/Display/Display/ImmediateTextNode.swift @@ -38,6 +38,20 @@ public class ImmediateTextNode: TextNode { let node = TextNode() node.cachedLayout = self.cachedLayout node.frame = self.frame + if let subnodes = self.subnodes { + for subnode in subnodes { + if let subnode = subnode as? ASImageNode { + let copySubnode = ASImageNode() + copySubnode.isLayerBacked = subnode.isLayerBacked + copySubnode.image = subnode.image + copySubnode.displaysAsynchronously = false + copySubnode.displayWithoutProcessing = true + copySubnode.frame = subnode.frame + copySubnode.alpha = subnode.alpha + node.addSubnode(copySubnode) + } + } + } return node } diff --git a/submodules/Display/Display/Navigation/NavigationContainer.swift b/submodules/Display/Display/Navigation/NavigationContainer.swift index ec6f8803d5..fe79956916 100644 --- a/submodules/Display/Display/Navigation/NavigationContainer.swift +++ b/submodules/Display/Display/Navigation/NavigationContainer.swift @@ -133,6 +133,13 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate { }*/ } + func hasNonReadyControllers() -> Bool { + if let pending = self.state.pending, !pending.isReady { + return true + } + return false + } + public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { return false } @@ -185,6 +192,17 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate { if let strongSelf = self { if let top = strongSelf.state.top { strongSelf.syncKeyboard(leftEdge: top.value.displayNode.frame.minX, transition: transition) + + var updatedStatusBarStyle = strongSelf.statusBarStyle + if let childTransition = strongSelf.state.transition, childTransition.coordinator.progress >= 0.3 { + updatedStatusBarStyle = childTransition.previous.value.statusBar.statusBarStyle + } else { + updatedStatusBarStyle = top.value.statusBar.statusBarStyle + } + if strongSelf.statusBarStyle != updatedStatusBarStyle { + strongSelf.statusBarStyle = updatedStatusBarStyle + strongSelf.statusBarStyleUpdated?(.animated(duration: 0.3, curve: .easeInOut)) + } } } }) @@ -337,7 +355,11 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate { } } self.applyLayout(layout: updatedLayout, to: top, isMaster: true, transition: transition) - updatedStatusBarStyle = top.value.statusBar.statusBarStyle + if let childTransition = self.state.transition, childTransition.coordinator.progress >= 0.3 { + updatedStatusBarStyle = childTransition.previous.value.statusBar.statusBarStyle + } else { + updatedStatusBarStyle = top.value.statusBar.statusBarStyle + } } else { updatedStatusBarStyle = .Ignore } diff --git a/submodules/Display/Display/Navigation/NavigationController.swift b/submodules/Display/Display/Navigation/NavigationController.swift index 037b2fc65d..b709a8a5fd 100644 --- a/submodules/Display/Display/Navigation/NavigationController.swift +++ b/submodules/Display/Display/Navigation/NavigationController.swift @@ -274,6 +274,18 @@ open class NavigationController: UINavigationController, ContainableController, return true } } + if let rootContainer = self.rootContainer { + switch rootContainer { + case let .flat(container): + if container.hasNonReadyControllers() { + return true + } + case let .split(splitContainer): + if splitContainer.hasNonReadyControllers() { + return true + } + } + } return false } @@ -1001,27 +1013,8 @@ open class NavigationController: UINavigationController, ContainableController, } public func pushViewController(_ controller: ViewController, animated: Bool = true, completion: @escaping () -> Void) { - let navigateAction: () -> Void = { [weak self] in - guard let strongSelf = self else { - return - } - - if !controller.hasActiveInput { - //strongSelf.view.endEditing(true) - } - /*strongSelf.scheduleAfterLayout({ - guard let strongSelf = self else { - return - }*/ - strongSelf.pushViewController(controller, animated: animated) - completion() - //}) - } - - /*if let lastController = self.viewControllers.last as? ViewController, !lastController.attemptNavigation(navigateAction) { - } else {*/ - navigateAction() - //} + self.pushViewController(controller, animated: animated) + completion() } open override func pushViewController(_ viewController: UIViewController, animated: Bool) { diff --git a/submodules/Display/Display/Navigation/NavigationSplitContainer.swift b/submodules/Display/Display/Navigation/NavigationSplitContainer.swift index 155fd2a186..ac6c7772db 100644 --- a/submodules/Display/Display/Navigation/NavigationSplitContainer.swift +++ b/submodules/Display/Display/Navigation/NavigationSplitContainer.swift @@ -57,6 +57,16 @@ final class NavigationSplitContainer: ASDisplayNode { self.view.addSubview(self.detailScrollToTopView) } + func hasNonReadyControllers() -> Bool { + if self.masterContainer.hasNonReadyControllers() { + return true + } + if self.detailContainer.hasNonReadyControllers() { + return true + } + return false + } + func updateTheme(theme: NavigationControllerTheme) { self.separator.backgroundColor = theme.navigationBar.separatorColor } diff --git a/submodules/Display/Display/ViewController.swift b/submodules/Display/Display/ViewController.swift index 392644c300..a8d2ca9516 100644 --- a/submodules/Display/Display/ViewController.swift +++ b/submodules/Display/Display/ViewController.swift @@ -93,6 +93,8 @@ public enum ViewControllerNavigationPresentation { } } + var blocksInteractionUntilReady: Bool = false + public final var isOpaqueWhenInOverlay: Bool = false public final var blocksBackgroundWhenInOverlay: Bool = false public final var automaticallyControlPresentationContextLayout: Bool = true diff --git a/submodules/LocalMediaResources/BUCK b/submodules/LocalMediaResources/BUCK index 6739a9b6cf..12b32376f0 100644 --- a/submodules/LocalMediaResources/BUCK +++ b/submodules/LocalMediaResources/BUCK @@ -15,6 +15,8 @@ static_library( frameworks = [ "$SDKROOT/System/Library/Frameworks/Foundation.framework", "$SDKROOT/System/Library/Frameworks/UIKit.framework", - "$SDKROOT/System/Library/Frameworks/Photos.framework", + ], + weak_frameworks = [ + "Photos", ], ) diff --git a/submodules/PeerAvatarGalleryUI/BUCK b/submodules/PeerAvatarGalleryUI/BUCK index bde6746427..f61fd2951b 100644 --- a/submodules/PeerAvatarGalleryUI/BUCK +++ b/submodules/PeerAvatarGalleryUI/BUCK @@ -26,6 +26,8 @@ static_library( "$SDKROOT/System/Library/Frameworks/Foundation.framework", "$SDKROOT/System/Library/Frameworks/UIKit.framework", "$SDKROOT/System/Library/Frameworks/QuickLook.framework", - "$SDKROOT/System/Library/Frameworks/Photos.framework", + ], + weak_frameworks = [ + "Photos", ], ) diff --git a/submodules/SaveToCameraRoll/BUCK b/submodules/SaveToCameraRoll/BUCK index d594ecc651..b75130a540 100644 --- a/submodules/SaveToCameraRoll/BUCK +++ b/submodules/SaveToCameraRoll/BUCK @@ -18,6 +18,8 @@ static_library( "$SDKROOT/System/Library/Frameworks/Foundation.framework", "$SDKROOT/System/Library/Frameworks/UIKit.framework", "$SDKROOT/System/Library/Frameworks/MobileCoreServices.framework", - "$SDKROOT/System/Library/Frameworks/Photos.framework", + ], + weak_frameworks = [ + "Photos", ], ) diff --git a/submodules/SearchUI/Sources/SearchDisplayController.swift b/submodules/SearchUI/Sources/SearchDisplayController.swift index 66d5fd6e9b..d3c6254589 100644 --- a/submodules/SearchUI/Sources/SearchDisplayController.swift +++ b/submodules/SearchUI/Sources/SearchDisplayController.swift @@ -22,7 +22,7 @@ public final class SearchDisplayController { private var isSearchingDisposable: Disposable? - public init(presentationData: PresentationData, mode: SearchDisplayControllerMode = .navigation, contentNode: SearchDisplayControllerContentNode, cancel: @escaping () -> Void) { + public init(presentationData: PresentationData, mode: SearchDisplayControllerMode = .navigation, placeholder: String? = nil, contentNode: SearchDisplayControllerContentNode, cancel: @escaping () -> Void) { self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: presentationData.theme, hasSeparator: false), strings: presentationData.strings, fieldStyle: .modern) self.mode = mode self.contentNode = contentNode @@ -48,6 +48,9 @@ public final class SearchDisplayController { self?.searchBar.prefixString = prefix self?.searchBar.text = query } + if let placeholder = placeholder { + self.searchBar.placeholderString = NSAttributedString(string: placeholder, font: Font.regular(17.0), textColor: presentationData.theme.rootController.navigationSearchBar.inputPlaceholderTextColor) + } self.contentNode.setPlaceholder = { [weak self] string in guard string != self?.searchBar.placeholderString?.string else { return @@ -153,6 +156,7 @@ public final class SearchDisplayController { if let placeholder = placeholder { self.searchBar.animateIn(from: placeholder, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring) } else { + self.searchBar.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue) self.contentNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue) } } diff --git a/submodules/SettingsUI/BUCK b/submodules/SettingsUI/BUCK index df9f9d6aa7..49fcfda198 100644 --- a/submodules/SettingsUI/BUCK +++ b/submodules/SettingsUI/BUCK @@ -92,8 +92,10 @@ static_library( "$SDKROOT/System/Library/Frameworks/UIKit.framework", "$SDKROOT/System/Library/Frameworks/MessageUI.framework", "$SDKROOT/System/Library/Frameworks/LocalAuthentication.framework", - "$SDKROOT/System/Library/Frameworks/Photos.framework", "$SDKROOT/System/Library/Frameworks/QuickLook.framework", "$SDKROOT/System/Library/Frameworks/CoreTelephony.framework", ], + weak_frameworks = [ + "Photos", + ], ) diff --git a/submodules/TelegramUI/TelegramUI/ChatAvatarNavigationNode.swift b/submodules/TelegramUI/TelegramUI/ChatAvatarNavigationNode.swift index 30d69469e3..4e63ec7863 100644 --- a/submodules/TelegramUI/TelegramUI/ChatAvatarNavigationNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatAvatarNavigationNode.swift @@ -80,12 +80,20 @@ final class ChatAvatarNavigationNode: ASDisplayNode { (self.view as? ChatAvatarNavigationNodeView)?.targetNode = self (self.view as? ChatAvatarNavigationNodeView)?.chatController = self.chatController - self.avatarNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.avatarTapGesture(_:)))) + let tapRecognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.avatarTapGesture(_:))) + self.avatarNode.view.addGestureRecognizer(tapRecognizer) } - @objc private func avatarTapGesture(_ recognizer: UITapGestureRecognizer) { + @objc private func avatarTapGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) { if case .ended = recognizer.state { - self.tapped?() + if let (gesture, location) = recognizer.lastRecognizedGestureAndLocation { + switch gesture { + case .tap: + self.tapped?() + default: + break + } + } } } diff --git a/submodules/TelegramUI/TelegramUI/ChatController.swift b/submodules/TelegramUI/TelegramUI/ChatController.swift index 09d4a6ebdb..b2fa3154bc 100644 --- a/submodules/TelegramUI/TelegramUI/ChatController.swift +++ b/submodules/TelegramUI/TelegramUI/ChatController.swift @@ -1866,12 +1866,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.controllerInteraction = controllerInteraction - var displayNavigationAvatar = false - if case let .peer(peerId) = chatLocation, peerId != context.account.peerId { - displayNavigationAvatar = true + if case let .peer(peerId) = chatLocation, peerId != context.account.peerId, subject != .scheduledMessages { self.navigationBar?.userInfo = PeerInfoNavigationSourceTag(peerId: peerId) } - self.chatTitleView = ChatTitleView(account: self.context.account, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, displayAvatar: displayNavigationAvatar) + self.chatTitleView = ChatTitleView(account: self.context.account, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, displayAvatar: true) if let avatarNode = self.chatTitleView?.avatarNode { avatarNode.chatController = self avatarNode.contextAction = { [weak self] node, gesture in @@ -1988,8 +1986,16 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let strongSelf = self { if let peer = peerViewMainPeer(peerView) { strongSelf.chatTitleView?.titleContent = .peer(peerView: peerView, onlineMemberCount: onlineMemberCount, isScheduledMessages: isScheduledMessages) - strongSelf.chatTitleView?.avatarNode?.avatarNode.setPeer(context: strongSelf.context, theme: strongSelf.presentationData.theme, peer: peer, overrideImage: peer.isDeleted ? .deletedIcon : .none) - (strongSelf.chatInfoNavigationButton?.buttonItem.customDisplayNode as? ChatAvatarNavigationNode)?.contextActionIsEnabled = peer.restrictionText(platform: "ios", contentSettings: strongSelf.context.currentContentSettings.with { $0 }) == nil + let imageOverride: AvatarNodeImageOverride? + if strongSelf.context.account.peerId == peer.id { + imageOverride = .savedMessagesIcon + } else if peer.isDeleted { + imageOverride = .deletedIcon + } else { + imageOverride = nil + } + strongSelf.chatTitleView?.avatarNode?.avatarNode.setPeer(context: strongSelf.context, theme: strongSelf.presentationData.theme, peer: peer, overrideImage: imageOverride) + strongSelf.chatTitleView?.avatarNode?.contextActionIsEnabled = peer.restrictionText(platform: "ios", contentSettings: strongSelf.context.currentContentSettings.with { $0 }) == nil && imageOverride == nil && peer.smallProfileImage != nil } if strongSelf.peerView === peerView && strongSelf.reportIrrelvantGeoNotice == peerReportNotice && strongSelf.hasScheduledMessages == hasScheduledMessages { @@ -5075,6 +5081,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.leftNavigationButton = nil } + self.chatTitleView?.displayAvatar = updatedChatPresentationInterfaceState.interfaceState.selectionState == nil + if let button = rightNavigationButtonForChatInterfaceState(updatedChatPresentationInterfaceState, strings: updatedChatPresentationInterfaceState.strings, currentButton: self.rightNavigationButton, target: self, selector: #selector(self.rightNavigationButtonAction), chatInfoNavigationButton: self.chatInfoNavigationButton) { if self.rightNavigationButton != button { var animated = transition.isAnimated diff --git a/submodules/TelegramUI/TelegramUI/ChatInterfaceStateNavigationButtons.swift b/submodules/TelegramUI/TelegramUI/ChatInterfaceStateNavigationButtons.swift index 3e0f9c33a0..12964d2a8b 100644 --- a/submodules/TelegramUI/TelegramUI/ChatInterfaceStateNavigationButtons.swift +++ b/submodules/TelegramUI/TelegramUI/ChatInterfaceStateNavigationButtons.swift @@ -72,7 +72,12 @@ func rightNavigationButtonForChatInterfaceState(_ presentationInterfaceState: Ch } } + if presentationInterfaceState.isScheduledMessages { + return nil + } + if case .standard(true) = presentationInterfaceState.mode { + return nil } else if let peer = presentationInterfaceState.renderedPeer?.peer { if presentationInterfaceState.accountPeerId == peer.id { if presentationInterfaceState.isScheduledMessages { diff --git a/submodules/TelegramUI/TelegramUI/ChatTitleView.swift b/submodules/TelegramUI/TelegramUI/ChatTitleView.swift index 27802c7185..d399138c28 100644 --- a/submodules/TelegramUI/TelegramUI/ChatTitleView.swift +++ b/submodules/TelegramUI/TelegramUI/ChatTitleView.swift @@ -179,6 +179,15 @@ final class ChatTitleView: UIView, NavigationBarTitleView { var pressed: (() -> Void)? + var displayAvatar: Bool = true { + didSet { + if self.displayAvatar != oldValue { + self.avatarNode?.isHidden = !self.displayAvatar + self.setNeedsLayout() + } + } + } + var titleContent: ChatTitleContent? { didSet { if let titleContent = self.titleContent { @@ -529,19 +538,13 @@ final class ChatTitleView: UIView, NavigationBarTitleView { if highlighted { strongSelf.titleNode.layer.removeAnimation(forKey: "opacity") strongSelf.activityNode.layer.removeAnimation(forKey: "opacity") - strongSelf.titleLeftIconNode.layer.removeAnimation(forKey: "opacity") - strongSelf.titleRightIconNode.layer.removeAnimation(forKey: "opacity") strongSelf.titleCredibilityIconNode.layer.removeAnimation(forKey: "opacity") strongSelf.titleNode.alpha = 0.4 strongSelf.activityNode.alpha = 0.4 - strongSelf.titleLeftIconNode.alpha = 0.4 - strongSelf.titleRightIconNode.alpha = 0.4 strongSelf.titleCredibilityIconNode.alpha = 0.4 } else { strongSelf.titleNode.alpha = 1.0 strongSelf.activityNode.alpha = 1.0 - strongSelf.titleLeftIconNode.alpha = 1.0 - strongSelf.titleRightIconNode.alpha = 1.0 strongSelf.titleCredibilityIconNode.alpha = 1.0 strongSelf.titleNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) strongSelf.activityNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) @@ -592,7 +595,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView { if let image = self.titleLeftIconNode.image { if self.titleLeftIconNode.supernode == nil { - self.contentContainer.addSubnode(self.titleLeftIconNode) + self.titleNode.addSubnode(self.titleLeftIconNode) } leftIconWidth = image.size.width + 6.0 } else if self.titleLeftIconNode.supernode != nil { @@ -610,7 +613,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView { if let image = self.titleRightIconNode.image { if self.titleRightIconNode.supernode == nil { - self.contentContainer.addSubnode(self.titleRightIconNode) + self.titleNode.addSubnode(self.titleRightIconNode) } rightIconWidth = image.size.width + 3.0 } else if self.titleRightIconNode.supernode != nil { @@ -622,68 +625,43 @@ final class ChatTitleView: UIView, NavigationBarTitleView { let avatarSize = CGSize(width: 37.0, height: 37.0) let avatarFrame = CGRect(origin: CGPoint(x: leftInset + 10.0, y: floor((size.height - avatarSize.height) / 2.0)), size: avatarSize) avatarNode.frame = avatarFrame - leftInset += avatarSize.width + 10.0 + 8.0 + if self.displayAvatar { + leftInset += avatarSize.width + 10.0 + 8.0 + } } self.button.frame = CGRect(origin: CGPoint(x: leftInset - 20.0, y: 0.0), size: CGSize(width: clearBounds.width - leftInset, height: size.height)) let titleSideInset: CGFloat = 3.0 - if size.height > 40.0 { - var titleSize = self.titleNode.updateLayout(CGSize(width: clearBounds.width - leftIconWidth - credibilityIconWidth - rightIconWidth - titleSideInset * 2.0 - leftInset, height: size.height)) - titleSize.width += credibilityIconWidth - let activitySize = self.activityNode.updateLayout(clearBounds.size, alignment: .left) - let titleInfoSpacing: CGFloat = 0.0 - - var titleFrame: CGRect - - if activitySize.height.isZero { - titleFrame = CGRect(origin: CGPoint(x: leftInset + leftIconWidth, y: floor((size.height - titleSize.height) / 2.0)), size: titleSize) - self.titleNode.frame = titleFrame - } else { - let combinedHeight = titleSize.height + activitySize.height + titleInfoSpacing - - titleFrame = CGRect(origin: CGPoint(x: leftInset + leftIconWidth, y: floor((size.height - combinedHeight) / 2.0)), size: titleSize) - self.titleNode.frame = titleFrame - - var activityFrame = CGRect(origin: CGPoint(x: leftInset, y: floor((size.height - combinedHeight) / 2.0) + titleSize.height + titleInfoSpacing), size: activitySize) - self.activityNode.frame = activityFrame - } - - if let image = self.titleLeftIconNode.image { - self.titleLeftIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.minX - image.size.width - 3.0 - UIScreenPixel, y: titleFrame.minY + 4.0), size: image.size) - } - if let image = self.titleCredibilityIconNode.image { - self.titleCredibilityIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.maxX - image.size.width - 1.0, y: titleFrame.minY + 2.0), size: image.size) - } - if let image = self.titleRightIconNode.image { - self.titleRightIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.maxX + 3.0, y: titleFrame.minY + 6.0), size: image.size) - } - } else { - let titleSize = self.titleNode.updateLayout(CGSize(width: floor(clearBounds.width / 2.0 - leftIconWidth - credibilityIconWidth - rightIconWidth - titleSideInset * 2.0), height: size.height)) - let activitySize = self.activityNode.updateLayout(CGSize(width: floor(clearBounds.width / 2.0), height: size.height), alignment: .center) - - let titleInfoSpacing: CGFloat = 8.0 - let combinedWidth = titleSize.width + leftIconWidth + credibilityIconWidth + rightIconWidth + activitySize.width + titleInfoSpacing - - let titleFrame = CGRect(origin: CGPoint(x: leftIconWidth + floor((clearBounds.width - combinedWidth) / 2.0), y: floor((size.height - titleSize.height) / 2.0)), size: titleSize) + var titleSize = self.titleNode.updateLayout(CGSize(width: clearBounds.width - leftIconWidth - credibilityIconWidth - rightIconWidth - titleSideInset * 2.0 - leftInset, height: size.height)) + titleSize.width += credibilityIconWidth + let activitySize = self.activityNode.updateLayout(clearBounds.size, alignment: .left) + let titleInfoSpacing: CGFloat = 0.0 + + var titleFrame: CGRect + + if activitySize.height.isZero { + titleFrame = CGRect(origin: CGPoint(x: leftInset + leftIconWidth, y: floor((size.height - titleSize.height) / 2.0)), size: titleSize) self.titleNode.frame = titleFrame - self.activityNode.frame = CGRect(origin: CGPoint(x: floor((clearBounds.width - combinedWidth) / 2.0 + titleSize.width + leftIconWidth + credibilityIconWidth + rightIconWidth + titleInfoSpacing), y: floor((size.height - activitySize.height) / 2.0)), size: activitySize) + } else { + let combinedHeight = titleSize.height + activitySize.height + titleInfoSpacing - if let image = self.titleLeftIconNode.image { - self.titleLeftIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.minX, y: titleFrame.minY + 4.0), size: image.size) - } - if let image = self.titleCredibilityIconNode.image { - self.titleCredibilityIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.maxX - image.size.width - 1.0, y: titleFrame.minY + 6.0), size: image.size) - } - if let image = self.titleRightIconNode.image { - self.titleRightIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.maxX - image.size.width - 1.0, y: titleFrame.minY + 6.0), size: image.size) - } + titleFrame = CGRect(origin: CGPoint(x: leftInset + leftIconWidth, y: floor((size.height - combinedHeight) / 2.0)), size: titleSize) + self.titleNode.frame = titleFrame + + var activityFrame = CGRect(origin: CGPoint(x: leftInset, y: floor((size.height - combinedHeight) / 2.0) + titleSize.height + titleInfoSpacing), size: activitySize) + self.activityNode.frame = activityFrame } - /*if let networkStatusNode = self.networkStatusNode { - transition.updateFrame(node: networkStatusNode, frame: CGRect(origin: CGPoint(), size: size)) - networkStatusNode.updateLayout(size: size, transition: transition) - }*/ + if let image = self.titleLeftIconNode.image { + self.titleLeftIconNode.frame = CGRect(origin: CGPoint(x: -image.size.width - 3.0 - UIScreenPixel, y: 4.0), size: image.size) + } + if let image = self.titleCredibilityIconNode.image { + self.titleCredibilityIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.maxX - image.size.width - 1.0, y: titleFrame.minY + 2.0), size: image.size) + } + if let image = self.titleRightIconNode.image { + self.titleRightIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.width + 3.0, y: 6.0), size: image.size) + } } @objc func buttonPressed() { diff --git a/submodules/TelegramUI/TelegramUI/ListMessageFileItemNode.swift b/submodules/TelegramUI/TelegramUI/ListMessageFileItemNode.swift index 57daa968c1..43ce473a32 100644 --- a/submodules/TelegramUI/TelegramUI/ListMessageFileItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ListMessageFileItemNode.swift @@ -658,7 +658,7 @@ final class ListMessageFileItemNode: ListMessageNode { strongSelf.addSubnode(waveformScrubbingNode) } - strongSelf.waveformScrubbingNode?.frame = CGRect(origin: CGPoint(x: leftOffset + leftInset, y: 10.0), size: CGSize(width: params.width - (leftOffset + leftInset) - 16.0, height: 12.0)) + transition.updateFrame(node: waveformScrubbingNode, frame: CGRect(origin: CGPoint(x: leftOffset + leftInset, y: 10.0), size: CGSize(width: params.width - leftInset - 16.0, height: 12.0))) waveformNode.setup(color: item.theme.list.controlSecondaryColor, waveform: waveform) waveformForegroundNode.setup(color: item.theme.list.itemAccentColor, waveform: waveform) @@ -809,7 +809,7 @@ final class ListMessageFileItemNode: ListMessageNode { } } self.waveformScrubbingNode?.enableScrubbing = enableScrubbing - if let musicIsPlaying = musicIsPlaying, !isVoice { + if let musicIsPlaying = musicIsPlaying, !isVoice, !isInstantVideo { if self.playbackOverlayNode == nil { let playbackOverlayNode = ListMessagePlaybackOverlayNode() playbackOverlayNode.frame = self.iconImageNode.frame diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoScreenActionItem.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/ListItems/PeerInfoScreenActionItem.swift similarity index 100% rename from submodules/TelegramUI/TelegramUI/PeerInfoScreenActionItem.swift rename to submodules/TelegramUI/TelegramUI/PeerInfo/ListItems/PeerInfoScreenActionItem.swift diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoScreenDisclosureItem.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/ListItems/PeerInfoScreenDisclosureItem.swift similarity index 100% rename from submodules/TelegramUI/TelegramUI/PeerInfoScreenDisclosureItem.swift rename to submodules/TelegramUI/TelegramUI/PeerInfo/ListItems/PeerInfoScreenDisclosureItem.swift diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoScreenLabeledValueItem.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/ListItems/PeerInfoScreenLabeledValueItem.swift similarity index 100% rename from submodules/TelegramUI/TelegramUI/PeerInfoScreenLabeledValueItem.swift rename to submodules/TelegramUI/TelegramUI/PeerInfo/ListItems/PeerInfoScreenLabeledValueItem.swift diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoScreenSelectableBackgroundNode.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/ListItems/PeerInfoScreenSelectableBackgroundNode.swift similarity index 100% rename from submodules/TelegramUI/TelegramUI/PeerInfoScreenSelectableBackgroundNode.swift rename to submodules/TelegramUI/TelegramUI/PeerInfo/ListItems/PeerInfoScreenSelectableBackgroundNode.swift diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoScreenSwitchItem.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/ListItems/PeerInfoScreenSwitchItem.swift similarity index 100% rename from submodules/TelegramUI/TelegramUI/PeerInfoScreenSwitchItem.swift rename to submodules/TelegramUI/TelegramUI/PeerInfo/ListItems/PeerInfoScreenSwitchItem.swift diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoGroupsInCommonPaneNode.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/Panes/PeerInfoGroupsInCommonPaneNode.swift similarity index 77% rename from submodules/TelegramUI/TelegramUI/PeerInfoGroupsInCommonPaneNode.swift rename to submodules/TelegramUI/TelegramUI/PeerInfo/Panes/PeerInfoGroupsInCommonPaneNode.swift index 89477a9ce3..04db539477 100644 --- a/submodules/TelegramUI/TelegramUI/PeerInfoGroupsInCommonPaneNode.swift +++ b/submodules/TelegramUI/TelegramUI/PeerInfo/Panes/PeerInfoGroupsInCommonPaneNode.swift @@ -35,24 +35,24 @@ private struct GroupsInCommonListEntry: Comparable, Identifiable { return lhs.index < rhs.index } - func item(context: AccountContext, presentationData: PresentationData, openPeer: @escaping (Peer) -> Void) -> ListViewItem { + func item(context: AccountContext, presentationData: PresentationData, openPeer: @escaping (Peer) -> Void, openPeerContextAction: @escaping (Peer, ASDisplayNode, ContextGesture?) -> Void) -> ListViewItem { let peer = self.peer return ItemListPeerItem(presentationData: ItemListPresentationData(presentationData), dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, context: context, peer: self.peer, presence: nil, text: .none, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), switchValue: nil, enabled: true, selectable: true, sectionId: 0, action: { openPeer(peer) }, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in }, contextAction: { node, gesture in - //arguments.contextAction(peer, node, gesture) + openPeerContextAction(peer, node, gesture) }, hasTopStripe: false, noInsets: true) } } -private func preparedTransition(from fromEntries: [GroupsInCommonListEntry], to toEntries: [GroupsInCommonListEntry], context: AccountContext, presentationData: PresentationData, openPeer: @escaping (Peer) -> Void) -> GroupsInCommonListTransaction { +private func preparedTransition(from fromEntries: [GroupsInCommonListEntry], to toEntries: [GroupsInCommonListEntry], context: AccountContext, presentationData: PresentationData, openPeer: @escaping (Peer) -> Void, openPeerContextAction: @escaping (Peer, ASDisplayNode, ContextGesture?) -> Void) -> GroupsInCommonListTransaction { let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries) let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) } - let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, openPeer: openPeer), directionHint: nil) } - let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, openPeer: openPeer), directionHint: nil) } + let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, openPeer: openPeer, openPeerContextAction: openPeerContextAction), directionHint: nil) } + let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, openPeer: openPeer, openPeerContextAction: openPeerContextAction), directionHint: nil) } return GroupsInCommonListTransaction(deletions: deletions, insertions: insertions, updates: updates) } @@ -60,7 +60,8 @@ private func preparedTransition(from fromEntries: [GroupsInCommonListEntry], to final class PeerInfoGroupsInCommonPaneNode: ASDisplayNode, PeerInfoPaneNode { private let context: AccountContext private let peerId: PeerId - private let paneInteraction: PeerInfoPaneInteraction + private let chatControllerInteraction: ChatControllerInteraction + private let openPeerContextAction: (Peer, ASDisplayNode, ContextGesture?) -> Void private let listNode: ListView private var peers: [Peer] = [] @@ -75,10 +76,11 @@ final class PeerInfoGroupsInCommonPaneNode: ASDisplayNode, PeerInfoPaneNode { return self.ready.get() } - init(context: AccountContext, peerId: PeerId, interaction: PeerInfoPaneInteraction, peers: [Peer]) { + init(context: AccountContext, peerId: PeerId, chatControllerInteraction: ChatControllerInteraction, openPeerContextAction: @escaping (Peer, ASDisplayNode, ContextGesture?) -> Void, peers: [Peer]) { self.context = context self.peerId = peerId - self.paneInteraction = interaction + self.chatControllerInteraction = chatControllerInteraction + self.openPeerContextAction = openPeerContextAction self.listNode = ListView() @@ -102,14 +104,14 @@ final class PeerInfoGroupsInCommonPaneNode: ASDisplayNode, PeerInfoPaneNode { } } - func update(size: CGSize, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) { + func update(size: CGSize, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) { let isFirstLayout = self.currentParams == nil self.currentParams = (size, isScrollingLockedAtTop, presentationData) transition.updateFrame(node: self.listNode, frame: CGRect(origin: CGPoint(), size: size)) let (duration, curve) = listViewAnimationDurationAndCurve(transition: transition) - self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: nil, updateSizeAndInsets: ListViewUpdateSizeAndInsets(size: size, insets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0), headerInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0), scrollIndicatorInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0), duration: duration, curve: curve), stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in }) + self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: nil, updateSizeAndInsets: ListViewUpdateSizeAndInsets(size: size, insets: UIEdgeInsets(top: 0.0, left: sideInset, bottom: bottomInset, right: sideInset), duration: duration, curve: curve), stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in }) self.listNode.scrollEnabled = !isScrollingLockedAtTop @@ -124,7 +126,9 @@ final class PeerInfoGroupsInCommonPaneNode: ASDisplayNode, PeerInfoPaneNode { entries.append(GroupsInCommonListEntry(index: entries.count, peer: peer)) } let transaction = preparedTransition(from: self.currentEntries, to: entries, context: self.context, presentationData: presentationData, openPeer: { [weak self] peer in - self?.paneInteraction.openPeer(peer) + self?.chatControllerInteraction.openPeer(peer.id, .default, nil) + }, openPeerContextAction: { [weak self] peer, node, gesture in + self?.openPeerContextAction(peer, node, gesture) }) self.currentEntries = entries self.enqueuedTransactions.append(transaction) @@ -156,13 +160,22 @@ final class PeerInfoGroupsInCommonPaneNode: ASDisplayNode, PeerInfoPaneNode { return nil } + func updateHiddenMedia() { + } + func transferVelocity(_ velocity: CGFloat) { + if velocity > 0.0 { + self.listNode.transferVelocity(velocity) + } } func transitionNodeForGallery(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { return nil } + func addToTransitionSurface(view: UIView) { + } + func updateSelectedMessages(animated: Bool) { } } diff --git a/submodules/TelegramUI/TelegramUI/PeerInfo/Panes/PeerInfoListPaneNode.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/Panes/PeerInfoListPaneNode.swift new file mode 100644 index 0000000000..b021f9542c --- /dev/null +++ b/submodules/TelegramUI/TelegramUI/PeerInfo/Panes/PeerInfoListPaneNode.swift @@ -0,0 +1,125 @@ +import AsyncDisplayKit +import Display +import TelegramCore +import SyncCore +import SwiftSignalKit +import Postbox +import TelegramPresentationData +import AccountContext +import ContextUI +import PhotoResources +import TelegramUIPreferences + +final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode { + private let context: AccountContext + private let peerId: PeerId + private let chatControllerInteraction: ChatControllerInteraction + + private let listNode: ChatHistoryListNode + + private var currentParams: (size: CGSize, isScrollingLockedAtTop: Bool, presentationData: PresentationData)? + + private let ready = Promise() + private var didSetReady: Bool = false + var isReady: Signal { + return self.ready.get() + } + + private let selectedMessagesPromise = Promise?>(nil) + private var selectedMessages: Set? { + didSet { + if self.selectedMessages != oldValue { + self.selectedMessagesPromise.set(.single(self.selectedMessages)) + } + } + } + + private var hiddenMediaDisposable: Disposable? + + init(context: AccountContext, chatControllerInteraction: ChatControllerInteraction, peerId: PeerId, tagMask: MessageTags) { + self.context = context + self.peerId = peerId + self.chatControllerInteraction = chatControllerInteraction + + self.selectedMessages = chatControllerInteraction.selectionState.flatMap { $0.selectedIds } + self.selectedMessagesPromise.set(.single(self.selectedMessages)) + + self.listNode = ChatHistoryListNode(context: context, chatLocation: .peer(peerId), tagMask: tagMask, subject: nil, controllerInteraction: chatControllerInteraction, selectedMessages: self.selectedMessagesPromise.get(), mode: .list(search: false, reversed: false)) + + super.init() + + self.listNode.preloadPages = true + self.addSubnode(self.listNode) + + self.ready.set(self.listNode.historyState.get() + |> take(1) + |> map { _ -> Bool in true }) + } + + deinit { + self.hiddenMediaDisposable?.dispose() + } + + func scrollToTop() -> Bool { + let offset = self.listNode.visibleContentOffset() + switch offset { + case let .known(value) where value <= CGFloat.ulpOfOne: + return false + default: + self.listNode.scrollToEndOfHistory() + return true + } + } + + func update(size: CGSize, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) { + self.currentParams = (size, isScrollingLockedAtTop, presentationData) + + transition.updateFrame(node: self.listNode, frame: CGRect(origin: CGPoint(), size: size)) + let (duration, curve) = listViewAnimationDurationAndCurve(transition: transition) + self.listNode.updateLayout(transition: transition, updateSizeAndInsets: ListViewUpdateSizeAndInsets(size: size, insets: UIEdgeInsets(top: 0.0, left: sideInset, bottom: bottomInset, right: sideInset), duration: duration, curve: curve)) + self.listNode.scrollEnabled = !isScrollingLockedAtTop + } + + func findLoadedMessage(id: MessageId) -> Message? { + self.listNode.messageInCurrentHistoryView(id) + } + + func updateHiddenMedia() { + self.listNode.forEachItemNode { itemNode in + if let itemNode = itemNode as? ListMessageNode { + itemNode.updateHiddenMedia() + } + } + } + + func transferVelocity(_ velocity: CGFloat) { + if velocity > 0.0 { + self.listNode.transferVelocity(velocity) + } + } + + func transitionNodeForGallery(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + var transitionNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? + self.listNode.forEachItemNode { itemNode in + if let itemNode = itemNode as? ListMessageNode { + if let result = itemNode.transitionNode(id: messageId, media: media) { + transitionNode = result + } + } + } + return transitionNode + } + + func addToTransitionSurface(view: UIView) { + self.view.addSubview(view) + } + + func updateSelectedMessages(animated: Bool) { + self.listNode.forEachItemNode { itemNode in + if let itemNode = itemNode as? ChatMessageItemView { + itemNode.updateSelectionState(animated: animated) + } + } + self.selectedMessages = self.chatControllerInteraction.selectionState.flatMap { $0.selectedIds } + } +} diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoVisualMediaPane.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/Panes/PeerInfoVisualMediaPaneNode.swift similarity index 82% rename from submodules/TelegramUI/TelegramUI/PeerInfoVisualMediaPane.swift rename to submodules/TelegramUI/TelegramUI/PeerInfo/Panes/PeerInfoVisualMediaPaneNode.swift index 395b578a67..f374730a20 100644 --- a/submodules/TelegramUI/TelegramUI/PeerInfoVisualMediaPane.swift +++ b/submodules/TelegramUI/TelegramUI/PeerInfo/Panes/PeerInfoVisualMediaPaneNode.swift @@ -16,17 +16,20 @@ private let mediaBadgeBackgroundColor = UIColor(white: 0.0, alpha: 0.6) private let mediaBadgeTextColor = UIColor.white private final class VisualMediaItemInteraction { - let openMessage: (MessageId) -> Void - let toggleSelection: (MessageId) -> Void + let openMessage: (Message) -> Void + let openMessageContextActions: (Message, ASDisplayNode, CGRect, ContextGesture?) -> Void + let toggleSelection: (MessageId, Bool) -> Void var hiddenMedia: [MessageId: [Media]] = [:] var selectedMessageIds: Set? init( - openMessage: @escaping (MessageId) -> Void, - toggleSelection: @escaping (MessageId) -> Void + openMessage: @escaping (Message) -> Void, + openMessageContextActions: @escaping (Message, ASDisplayNode, CGRect, ContextGesture?) -> Void, + toggleSelection: @escaping (MessageId, Bool) -> Void ) { self.openMessage = openMessage + self.openMessageContextActions = openMessageContextActions self.toggleSelection = toggleSelection } } @@ -68,7 +71,12 @@ private final class VisualMediaItemNode: ASDisplayNode { self.containerNode.addSubnode(self.imageNode) self.containerNode.addSubnode(self.mediaBadgeNode) - self.containerNode.isGestureEnabled = false + self.containerNode.activated = { [weak self] gesture in + guard let strongSelf = self, let item = strongSelf.item else { + return + } + strongSelf.interaction.openMessageContextActions(item.0.message, strongSelf.containerNode, strongSelf.containerNode.bounds, gesture) + } } deinit { @@ -79,13 +87,17 @@ private final class VisualMediaItemNode: ASDisplayNode { override func didLoad() { super.didLoad() - self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) + self.view.addGestureRecognizer(TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) } - @objc func tapGesture(_ recognizer: UITapGestureRecognizer) { + @objc func tapGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) { if case .ended = recognizer.state { - if let (item, _, _, _) = self.item { - self.interaction.openMessage(item.message.id) + if let (gesture, _) = recognizer.lastRecognizedGestureAndLocation { + if case .tap = gesture { + if let (item, _, _, _) = self.item { + self.interaction.openMessage(item.message) + } + } } } } @@ -132,8 +144,8 @@ private final class VisualMediaItemNode: ASDisplayNode { let isStreamable = isMediaStreamable(message: item.message, media: file) - let statusState: RadialStatusNodeState - if isStreamable { + let statusState: RadialStatusNodeState = .none + /*if isStreamable { statusState = .none } else { switch status { @@ -145,7 +157,7 @@ private final class VisualMediaItemNode: ASDisplayNode { case .Remote: statusState = .download(.white) } - } + }*/ switch statusState { case .none: @@ -234,7 +246,11 @@ private final class VisualMediaItemNode: ASDisplayNode { } else { let selectionNode = GridMessageSelectionNode(theme: theme, toggle: { [weak self] value in if let strongSelf = self, let messageId = strongSelf.item?.0.message.id { - strongSelf.interaction.toggleSelection(messageId) + var toggledValue = true + if let selectedMessageIds = strongSelf.interaction.selectedMessageIds, selectedMessageIds.contains(messageId) { + toggledValue = false + } + strongSelf.interaction.toggleSelection(messageId, toggledValue) } }) @@ -305,7 +321,7 @@ private final class VisualMediaItem { final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScrollViewDelegate { private let context: AccountContext private let peerId: PeerId - private let interaction: PeerInfoPaneInteraction + private let chatControllerInteraction: ChatControllerInteraction private let scrollNode: ASScrollNode @@ -314,7 +330,7 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro return self._itemInteraction! } - private var currentParams: (size: CGSize, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, presentationData: PresentationData)? + private var currentParams: (size: CGSize, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, presentationData: PresentationData)? private let ready = Promise() private var didSetReady: Bool = false @@ -334,24 +350,27 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro private var decelerationAnimator: ConstantDisplayLinkAnimator? - init(context: AccountContext, openMessage: @escaping (MessageId) -> Bool, peerId: PeerId, interaction: PeerInfoPaneInteraction) { + init(context: AccountContext, chatControllerInteraction: ChatControllerInteraction, peerId: PeerId) { self.context = context self.peerId = peerId - self.interaction = interaction + self.chatControllerInteraction = chatControllerInteraction self.scrollNode = ASScrollNode() super.init() self._itemInteraction = VisualMediaItemInteraction( - openMessage: { id in - openMessage(id) + openMessage: { [weak self] message in + self?.chatControllerInteraction.openMessage(message, .default) }, - toggleSelection: { id in - interaction.toggleMessageSelected(id) + openMessageContextActions: { [weak self] message, sourceNode, sourceRect, gesture in + self?.chatControllerInteraction.openMessageContextActions(message, sourceNode, sourceRect, gesture) + }, + toggleSelection: { [weak self] id, value in + self?.chatControllerInteraction.toggleMessagesSelection([id], value) } ) - self.itemInteraction.selectedMessageIds = self.interaction.selectedMessageIds + self.itemInteraction.selectedMessageIds = chatControllerInteraction.selectionState.flatMap { $0.selectedIds } self.scrollNode.view.showsVerticalScrollIndicator = false if #available(iOS 11.0, *) { @@ -416,8 +435,8 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro let wasFirstHistoryView = self.isFirstHistoryView self.isFirstHistoryView = false - if let (size, visibleHeight, isScrollingLockedAtTop, presentationData) = self.currentParams { - self.update(size: size, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, presentationData: presentationData, synchronous: wasFirstHistoryView, transition: .immediate) + if let (size, sideInset, bottomInset, visibleHeight, isScrollingLockedAtTop, presentationData) = self.currentParams { + self.update(size: size, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, presentationData: presentationData, synchronous: wasFirstHistoryView, transition: .immediate) if !self.didSetReady { self.didSetReady = true self.ready.set(.single(true)) @@ -444,6 +463,12 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro return nil } + func updateHiddenMedia() { + for (_, itemNode) in self.visibleMediaItems { + itemNode.updateHiddenMedia() + } + } + func transferVelocity(_ velocity: CGFloat) { if velocity > 0.0 { //print("transferVelocity \(velocity)") @@ -493,15 +518,19 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro return nil } + func addToTransitionSurface(view: UIView) { + self.scrollNode.view.addSubview(view) + } + func updateSelectedMessages(animated: Bool) { - self.itemInteraction.selectedMessageIds = self.interaction.selectedMessageIds + self.itemInteraction.selectedMessageIds = self.chatControllerInteraction.selectionState.flatMap { $0.selectedIds } for (_, itemNode) in self.visibleMediaItems { itemNode.updateSelectionState(animated: animated) } } - func update(size: CGSize, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) { - self.currentParams = (size, visibleHeight, isScrollingLockedAtTop, presentationData) + func update(size: CGSize, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) { + self.currentParams = (size, sideInset, bottomInset, visibleHeight, isScrollingLockedAtTop, presentationData) transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: size)) @@ -510,10 +539,10 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro let itemSize: CGFloat = floor(size.width / CGFloat(itemsInRow)) let rowCount: Int = self.mediaItems.count / itemsInRow + (self.mediaItems.count % itemsInRow == 0 ? 0 : 1) - let contentHeight = CGFloat(rowCount + 1) * itemSpacing + CGFloat(rowCount) * itemSize + let contentHeight = CGFloat(rowCount + 1) * itemSpacing + CGFloat(rowCount) * itemSize + bottomInset self.scrollNode.view.contentSize = CGSize(width: size.width, height: contentHeight) - self.updateVisibleItems(size: size, visibleHeight: visibleHeight, theme: presentationData.theme, synchronousLoad: synchronous) + self.updateVisibleItems(size: size, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, theme: presentationData.theme, synchronousLoad: synchronous) if isScrollingLockedAtTop { transition.updateBounds(node: self.scrollNode, bounds: CGRect(origin: CGPoint(), size: self.scrollNode.bounds.size)) @@ -527,8 +556,8 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro } func scrollViewDidScroll(_ scrollView: UIScrollView) { - if let (size, visibleHeight, _, presentationData) = self.currentParams { - self.updateVisibleItems(size: size, visibleHeight: visibleHeight, theme: presentationData.theme, synchronousLoad: false) + if let (size, sideInset, bottomInset, visibleHeight, _, presentationData) = self.currentParams { + self.updateVisibleItems(size: size, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, theme: presentationData.theme, synchronousLoad: false) if scrollView.contentOffset.y >= scrollView.contentSize.height - scrollView.bounds.height * 2.0, let currentView = self.currentView, currentView.earlierId != nil { if !self.isRequestingView { @@ -539,10 +568,12 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro } } - private func updateVisibleItems(size: CGSize, visibleHeight: CGFloat, theme: PresentationTheme, synchronousLoad: Bool) { + private func updateVisibleItems(size: CGSize, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, theme: PresentationTheme, synchronousLoad: Bool) { + let availableWidth = size.width - sideInset * 2.0 + let itemSpacing: CGFloat = 1.0 - let itemsInRow: Int = max(3, min(6, Int(size.width / 140.0))) - let itemSize: CGFloat = floor(size.width / CGFloat(itemsInRow)) + let itemsInRow: Int = max(3, min(6, Int(availableWidth / 140.0))) + let itemSize: CGFloat = floor(availableWidth / CGFloat(itemsInRow)) let rowCount: Int = self.mediaItems.count / itemsInRow + (self.mediaItems.count % itemsInRow == 0 ? 0 : 1) @@ -562,8 +593,8 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro validIds.insert(stableId) let rowIndex = i / Int(itemsInRow) let columnIndex = i % Int(itemsInRow) - let itemOrigin = CGPoint(x: CGFloat(columnIndex) * (itemSize + itemSpacing), y: itemSpacing + CGFloat(rowIndex) * (itemSize + itemSpacing)) - let itemFrame = CGRect(origin: itemOrigin, size: CGSize(width: columnIndex == itemsInRow ? (size.width - itemOrigin.x) : itemSize, height: itemSize)) + let itemOrigin = CGPoint(x: sideInset + CGFloat(columnIndex) * (itemSize + itemSpacing), y: itemSpacing + CGFloat(rowIndex) * (itemSize + itemSpacing)) + let itemFrame = CGRect(origin: itemOrigin, size: CGSize(width: columnIndex == itemsInRow ? (availableWidth - itemOrigin.x) : itemSize, height: itemSize)) let itemNode: VisualMediaItemNode if let current = self.visibleMediaItems[stableId] { itemNode = current diff --git a/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoData.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoData.swift new file mode 100644 index 0000000000..feb2c71926 --- /dev/null +++ b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoData.swift @@ -0,0 +1,306 @@ +import Foundation +import UIKit +import Postbox +import SyncCore +import TelegramCore +import SwiftSignalKit +import AccountContext +import PeerPresenceStatusManager +import TelegramStringFormatting +import TelegramPresentationData + +final class PeerInfoState { + let isEditing: Bool + let isSearching: Bool + let selectedMessageIds: Set? + + init( + isEditing: Bool, + isSearching: Bool, + selectedMessageIds: Set? + ) { + self.isEditing = isEditing + self.isSearching = isSearching + self.selectedMessageIds = selectedMessageIds + } + + func withIsEditing(_ isEditing: Bool) -> PeerInfoState { + return PeerInfoState( + isEditing: isEditing, + isSearching: self.isSearching, + selectedMessageIds: self.selectedMessageIds + ) + } + + func withSelectedMessageIds(_ selectedMessageIds: Set?) -> PeerInfoState { + return PeerInfoState( + isEditing: self.isEditing, + isSearching: self.isSearching, + selectedMessageIds: selectedMessageIds + ) + } +} + +final class PeerInfoScreenData { + let peer: Peer? + let cachedData: CachedPeerData? + let status: PeerInfoStatusData? + let notificationSettings: TelegramPeerNotificationSettings? + let globalNotificationSettings: GlobalNotificationSettings? + let isContact: Bool + let availablePanes: [PeerInfoPaneKey] + let groupsInCommon: [Peer]? + + init( + peer: Peer?, + cachedData: CachedPeerData?, + status: PeerInfoStatusData?, + notificationSettings: TelegramPeerNotificationSettings?, + globalNotificationSettings: GlobalNotificationSettings?, + isContact: Bool, + availablePanes: [PeerInfoPaneKey], + groupsInCommon: [Peer]? + ) { + self.peer = peer + self.cachedData = cachedData + self.status = status + self.notificationSettings = notificationSettings + self.globalNotificationSettings = globalNotificationSettings + self.isContact = isContact + self.availablePanes = availablePanes + self.groupsInCommon = groupsInCommon + } +} + +enum PeerInfoScreenInputData: Equatable { + case none + case user(userId: PeerId, secretChatId: PeerId?, isBot: Bool) +} + +func peerInfoAvailableMediaPanes(context: AccountContext, peerId: PeerId) -> Signal<[PeerInfoPaneKey], NoError> { + let tags: [(MessageTags, PeerInfoPaneKey)] = [ + (.photoOrVideo, .media), + (.file, .files), + (.music, .music), + (.voiceOrInstantVideo, .voice), + (.webPage, .links) + ] + return combineLatest(tags.map { tagAndKey -> Signal in + let (tag, key) = tagAndKey + return context.account.viewTracker.aroundMessageHistoryViewForLocation(.peer(peerId), index: .upperBound, anchorIndex: .upperBound, count: 20, clipHoles: false, fixedCombinedReadStates: nil, tagMask: tag) + |> map { (view, _, _) -> PeerInfoPaneKey? in + if view.entries.isEmpty { + return nil + } else { + return key + } + } + }) + |> map { keys -> [PeerInfoPaneKey] in + return keys.compactMap { $0 } + } + |> distinctUntilChanged + /*return context.account.postbox.combinedView(keys: tags.map { (tag, _) -> PostboxViewKey in + return .historyTagInfo(peerId: peerId, tag: tag) + }) + |> map { view -> [PeerInfoPaneKey] in + return tags.compactMap { (tag, key) -> PeerInfoPaneKey? in + if let info = view.views[.historyTagInfo(peerId: peerId, tag: tag)] as? HistoryTagInfoView, !info.isEmpty { + return key + } else { + return nil + } + } + } + |> distinctUntilChanged*/ +} + +struct PeerInfoStatusData: Equatable { + var text: String + var isActivity: Bool +} + +func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat) -> Signal { + return context.account.postbox.combinedView(keys: [.basicPeer(peerId)]) + |> map { view -> PeerInfoScreenInputData in + guard let peer = (view.views[.basicPeer(peerId)] as? BasicPeerView)?.peer else { + return .none + } + if let user = peer as? TelegramUser { + return .user(userId: user.id, secretChatId: nil, isBot: user.botInfo != nil) + } else { + preconditionFailure() + } + } + |> distinctUntilChanged + |> mapToSignal { inputData -> Signal in + switch inputData { + case .none: + return .single(PeerInfoScreenData( + peer: nil, + cachedData: nil, + status: nil, + notificationSettings: nil, + globalNotificationSettings: nil, + isContact: false, + availablePanes: [], + groupsInCommon: nil + )) + case let .user(peerId, secretChatId, isBot): + let groupsInCommonSignal: Signal<[Peer]?, NoError> + if isBot { + groupsInCommonSignal = .single([]) + } else { + groupsInCommonSignal = .single(nil) + |> then( + groupsInCommon(account: context.account, peerId: peerId) + |> map(Optional.init) + ) + } + enum StatusInputData: Equatable { + case none + case presence(TelegramUserPresence) + case bot + } + let status = Signal { subscriber in + class Manager { + var currentValue: TelegramUserPresence? = nil + var updateManager: QueueLocalObject? = nil + } + let manager = Atomic(value: Manager()) + let notify: () -> Void = { + let data = manager.with { manager -> PeerInfoStatusData? in + if let presence = manager.currentValue { + let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 + let (text, isActivity) = stringAndActivityForUserPresence(strings: strings, dateTimeFormat: dateTimeFormat, presence: presence, relativeTo: Int32(timestamp), expanded: true) + return PeerInfoStatusData(text: text, isActivity: isActivity) + } else { + return nil + } + } + subscriber.putNext(data) + } + let disposable = (context.account.viewTracker.peerView(peerId, updateData: false) + |> map { view -> StatusInputData in + guard let user = view.peers[peerId] as? TelegramUser else { + return .none + } + if user.isDeleted { + return .none + } + if user.botInfo != nil { + return .bot + } + if user.flags.contains(.isSupport) { + return .none + } + guard let presence = view.peerPresences[peerId] as? TelegramUserPresence else { + return .none + } + return .presence(presence) + } + |> distinctUntilChanged).start(next: { inputData in + switch inputData { + case .bot: + subscriber.putNext(PeerInfoStatusData(text: strings.Bot_GenericBotStatus, isActivity: false)) + default: + var presence: TelegramUserPresence? + if case let .presence(value) = inputData { + presence = value + } + let _ = manager.with { manager -> Void in + manager.currentValue = presence + if let presence = presence { + let updateManager: QueueLocalObject + if let current = manager.updateManager { + updateManager = current + } else { + updateManager = QueueLocalObject(queue: .mainQueue(), generate: { + return PeerPresenceStatusManager(update: { + notify() + }) + }) + } + updateManager.with { updateManager in + updateManager.reset(presence: presence) + } + } else if let _ = manager.updateManager { + manager.updateManager = nil + } + } + notify() + } + }) + return disposable + } + |> distinctUntilChanged + let globalNotificationsKey: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.globalNotifications])) + var combinedKeys: [PostboxViewKey] = [] + combinedKeys.append(globalNotificationsKey) + if let secretChatId = secretChatId { + combinedKeys.append(.peerChatState(peerId: peerId)) + } + return combineLatest( + context.account.viewTracker.peerView(peerId, updateData: true), + peerInfoAvailableMediaPanes(context: context, peerId: peerId), + context.account.postbox.combinedView(keys: combinedKeys), + status, + groupsInCommonSignal + ) + |> map { peerView, availablePanes, combinedView, status, groupsInCommon -> PeerInfoScreenData in + var globalNotificationSettings: GlobalNotificationSettings = .defaultSettings + if let preferencesView = combinedView.views[globalNotificationsKey] as? PreferencesView { + if let settings = preferencesView.values[PreferencesKeys.globalNotifications] as? GlobalNotificationSettings { + globalNotificationSettings = settings + } + } + + var availablePanes = availablePanes + if let groupsInCommon = groupsInCommon, !groupsInCommon.isEmpty { + availablePanes.append(.groupsInCommon) + } + + return PeerInfoScreenData( + peer: peerView.peers[peerId], + cachedData: peerView.cachedData, + status: status, + notificationSettings: peerView.notificationSettings as? TelegramPeerNotificationSettings, + globalNotificationSettings: globalNotificationSettings, + isContact: peerView.peerIsContact, + availablePanes: availablePanes, + groupsInCommon: groupsInCommon + ) + } + } + } +} + +func peerInfoHeaderButtons(peer: Peer?, cachedData: CachedPeerData?) -> [PeerInfoHeaderButtonKey] { + var result: [PeerInfoHeaderButtonKey] = [] + if let user = peer as? TelegramUser { + result.append(.message) + var callsAvailable = false + if !user.isDeleted, user.botInfo == nil, !user.flags.contains(.isSupport), let cachedUserData = cachedData as? CachedUserData { + callsAvailable = cachedUserData.callsAvailable + } + if callsAvailable { + result.append(.call) + } + result.append(.mute) + + if !user.isDeleted, user.botInfo == nil && !user.flags.contains(.isSupport) { + result.append(.more) + } + } + return result +} + +func peerInfoCanEdit(peer: Peer?, cachedData: CachedPeerData?) -> Bool { + if let user = peer as? TelegramUser { + if user.isDeleted { + return false + } + return true + } + return false +} diff --git a/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoHeaderNode.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoHeaderNode.swift new file mode 100644 index 0000000000..b601a275e4 --- /dev/null +++ b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoHeaderNode.swift @@ -0,0 +1,1497 @@ +import Foundation +import UIKit +import AsyncDisplayKit +import Display +import Postbox +import SyncCore +import TelegramCore +import AvatarNode +import AccountContext +import SwiftSignalKit +import TelegramPresentationData +import PhotoResources +import PeerAvatarGalleryUI +import TelegramStringFormatting + +enum PeerInfoHeaderButtonKey: Hashable { + case message + case call + case mute + case more + case addMember +} + +enum PeerInfoHeaderButtonIcon { + case message + case call + case mute + case unmute + case more + case addMember +} + +final class PeerInfoHeaderButtonNode: HighlightableButtonNode { + let key: PeerInfoHeaderButtonKey + private let action: (PeerInfoHeaderButtonNode) -> Void + let containerNode: ASDisplayNode + private let backgroundNode: ASImageNode + private let textNode: ImmediateTextNode + + private var theme: PresentationTheme? + private var icon: PeerInfoHeaderButtonIcon? + + init(key: PeerInfoHeaderButtonKey, action: @escaping (PeerInfoHeaderButtonNode) -> Void) { + self.key = key + self.action = action + + self.containerNode = ASDisplayNode() + + self.backgroundNode = ASImageNode() + self.backgroundNode.displaysAsynchronously = false + self.backgroundNode.displayWithoutProcessing = true + + self.textNode = ImmediateTextNode() + self.textNode.displaysAsynchronously = false + + super.init() + + self.addSubnode(self.containerNode) + self.containerNode.addSubnode(self.backgroundNode) + self.containerNode.addSubnode(self.textNode) + + self.highligthedChanged = { [weak self] highlighted in + if let strongSelf = self { + if highlighted { + strongSelf.layer.removeAnimation(forKey: "opacity") + strongSelf.alpha = 0.4 + } else { + strongSelf.alpha = 1.0 + strongSelf.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) + } + } + } + + self.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside) + } + + @objc private func buttonPressed() { + self.action(self) + } + + func update(size: CGSize, text: String, icon: PeerInfoHeaderButtonIcon, isExpanded: Bool, presentationData: PresentationData, transition: ContainedViewLayoutTransition) { + if self.theme != presentationData.theme || self.icon != icon { + self.theme = presentationData.theme + self.icon = icon + self.backgroundNode.image = generateImage(CGSize(width: 40.0, height: 40.0), contextGenerator: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + context.setFillColor(presentationData.theme.list.itemAccentColor.cgColor) + context.fillEllipse(in: CGRect(origin: CGPoint(), size: size)) + context.setBlendMode(.normal) + context.setFillColor(presentationData.theme.list.itemCheckColors.foregroundColor.cgColor) + let imageName: String + switch icon { + case .message: + imageName = "Peer Info/ButtonMessage" + case .call: + imageName = "Peer Info/ButtonCall" + case .mute: + imageName = "Peer Info/ButtonMute" + case .unmute: + imageName = "Peer Info/ButtonUnmute" + case .more: + imageName = "Peer Info/ButtonMore" + case .addMember: + imageName = "Peer Info/ButtonAddMember" + } + if let image = UIImage(bundleImageName: imageName) { + let imageRect = CGRect(origin: CGPoint(x: floor((size.width - image.size.width) / 2.0), y: floor((size.height - image.size.height) / 2.0)), size: image.size) + context.clip(to: imageRect, mask: image.cgImage!) + context.fill(imageRect) + } + }) + } + + self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(12.0), textColor: presentationData.theme.list.itemAccentColor) + let titleSize = self.textNode.updateLayout(CGSize(width: 120.0, height: .greatestFiniteMagnitude)) + + transition.updateFrame(node: self.containerNode, frame: CGRect(origin: CGPoint(), size: size)) + transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: size)) + transition.updateFrameAdditiveToCenter(node: self.textNode, frame: CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: size.height + 6.0), size: titleSize)) + transition.updateAlpha(node: self.textNode, alpha: isExpanded ? 0.0 : 1.0) + } +} + +final class PeerInfoHeaderNavigationTransition { + let sourceNavigationBar: NavigationBar + let sourceTitleView: ChatTitleView + let sourceTitleFrame: CGRect + let sourceSubtitleFrame: CGRect + let fraction: CGFloat + + init(sourceNavigationBar: NavigationBar, sourceTitleView: ChatTitleView, sourceTitleFrame: CGRect, sourceSubtitleFrame: CGRect, fraction: CGFloat) { + self.sourceNavigationBar = sourceNavigationBar + self.sourceTitleView = sourceTitleView + self.sourceTitleFrame = sourceTitleFrame + self.sourceSubtitleFrame = sourceSubtitleFrame + self.fraction = fraction + } +} + +enum PeerInfoAvatarListItem: Equatable { + case topImage([ImageRepresentationWithReference]) + case image(TelegramMediaImageReference?, [ImageRepresentationWithReference]) + + var id: WrappedMediaResourceId { + switch self { + case let .topImage(representations): + let representation = largestImageRepresentation(representations.map { $0.representation }) ?? representations[representations.count - 1].representation + return WrappedMediaResourceId(representation.resource.id) + case let .image(_, representations): + let representation = largestImageRepresentation(representations.map { $0.representation }) ?? representations[representations.count - 1].representation + return WrappedMediaResourceId(representation.resource.id) + } + } +} + +final class PeerInfoAvatarListItemNode: ASDisplayNode { + let imageNode: TransformImageNode + + let isReady = Promise() + private var didSetReady: Bool = false + + init(context: AccountContext, item: PeerInfoAvatarListItem) { + self.imageNode = TransformImageNode() + + super.init() + + self.addSubnode(self.imageNode) + let representations: [ImageRepresentationWithReference] + switch item { + case let .topImage(topRepresentations): + representations = topRepresentations + case let .image(_, imageRepresentations): + representations = imageRepresentations + } + self.imageNode.setSignal(chatAvatarGalleryPhoto(account: context.account, representations: representations, autoFetchFullSize: true), dispatchOnDisplayLink: false) + + self.imageNode.imageUpdated = { [weak self] _ in + guard let strongSelf = self else { + return + } + if !strongSelf.didSetReady { + strongSelf.didSetReady = true + strongSelf.isReady.set(.single(true)) + } + } + } + + func update(size: CGSize, transition: ContainedViewLayoutTransition) { + let imageSize = CGSize(width: min(size.width, size.height), height: min(size.width, size.height)) + let makeLayout = self.imageNode.asyncLayout() + let applyLayout = makeLayout(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets())) + let _ = applyLayout() + transition.updateFrame(node: self.imageNode, frame: CGRect(origin: CGPoint(x: floor((size.width - imageSize.width) / 2.0), y: floor((size.height - imageSize.height) / 2.0)), size: imageSize)) + } +} + +final class PeerInfoAvatarListContainerNode: ASDisplayNode { + private let context: AccountContext + + let controlsContainerNode: ASDisplayNode + let controlsContainerTransformNode: ASDisplayNode + let shadowNode: ASDisplayNode + + let contentNode: ASDisplayNode + private(set) var galleryEntries: [AvatarGalleryEntry] = [] + private var items: [PeerInfoAvatarListItem] = [] + private var itemNodes: [WrappedMediaResourceId: PeerInfoAvatarListItemNode] = [:] + private var currentIndex: Int = 0 + private var transitionFraction: CGFloat = 0.0 + + private var validLayout: CGSize? + + private let disposable = MetaDisposable() + private var initializedList = false + + let isReady = Promise() + private var didSetReady = false + + var currentItemNode: PeerInfoAvatarListItemNode? { + if self.currentIndex >= 0 && self.currentIndex < self.items.count { + return self.itemNodes[self.items[self.currentIndex].id] + } else { + return nil + } + } + + init(context: AccountContext) { + self.context = context + + self.contentNode = ASDisplayNode() + + self.controlsContainerNode = ASDisplayNode() + self.controlsContainerNode.isUserInteractionEnabled = false + + self.controlsContainerTransformNode = ASDisplayNode() + self.controlsContainerTransformNode.isUserInteractionEnabled = false + + self.shadowNode = ASDisplayNode() + //self.shadowNode.backgroundColor = .green + + super.init() + + self.backgroundColor = .black + + self.addSubnode(self.contentNode) + + self.controlsContainerNode.addSubnode(self.shadowNode) + self.controlsContainerTransformNode.addSubnode(self.controlsContainerNode) + self.addSubnode(self.controlsContainerTransformNode) + + self.view.disablesInteractiveTransitionGestureRecognizer = true + self.view.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:)))) + } + + deinit { + self.disposable.dispose() + } + + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + return super.hitTest(point, with: event) + } + + func selectFirstItem() { + self.currentIndex = 0 + if let size = self.validLayout { + self.updateItems(size: size, transition: .immediate) + } + } + + @objc private func panGesture(_ recognizer: UIPanGestureRecognizer) { + switch recognizer.state { + case .changed: + let translation = recognizer.translation(in: self.view) + var transitionFraction = translation.x / self.bounds.width + if self.currentIndex <= 0 { + transitionFraction = min(0.0, transitionFraction) + } + if self.currentIndex >= self.items.count - 1 { + transitionFraction = max(0.0, transitionFraction) + } + self.transitionFraction = transitionFraction + if let size = self.validLayout { + self.updateItems(size: size, transition: .animated(duration: 0.3, curve: .spring)) + } + case .cancelled, .ended: + let translation = recognizer.translation(in: self.view) + let velocity = recognizer.velocity(in: self.view) + var directionIsToRight = false + if abs(velocity.x) > 10.0 { + directionIsToRight = velocity.x < 0.0 + } else { + directionIsToRight = translation.x > self.bounds.width / 2.0 + } + var updatedIndex = self.currentIndex + if directionIsToRight { + updatedIndex = min(updatedIndex + 1, self.items.count - 1) + } else { + updatedIndex = max(updatedIndex - 1, 0) + } + self.currentIndex = updatedIndex + self.transitionFraction = 0.0 + if let size = self.validLayout { + self.updateItems(size: size, transition: .animated(duration: 0.3, curve: .spring)) + } + default: + break + } + } + + func update(size: CGSize, peer: Peer?, transition: ContainedViewLayoutTransition) { + self.validLayout = size + if let peer = peer, !self.initializedList { + self.initializedList = true + self.disposable.set((fetchedAvatarGalleryEntries(account: self.context.account, peer: peer) + |> deliverOnMainQueue).start(next: { [weak self] entries in + guard let strongSelf = self else { + return + } + var items: [PeerInfoAvatarListItem] = [] + for entry in entries { + switch entry { + case let .topImage(representations, _): + items.append(.topImage(representations)) + case let .image(reference, representations, _, _, _, _): + items.append(.image(reference, representations)) + } + } + strongSelf.galleryEntries = entries + strongSelf.items = items + if let size = strongSelf.validLayout { + strongSelf.updateItems(size: size, transition: .immediate) + } + if items.isEmpty { + if !strongSelf.didSetReady { + strongSelf.didSetReady = true + strongSelf.isReady.set(.single(true)) + } + } + })) + } + self.updateItems(size: size, transition: transition) + } + + private func updateItems(size: CGSize, transition: ContainedViewLayoutTransition) { + var validIds: [WrappedMediaResourceId] = [] + var addedItemNodesForAdditiveTransition: [PeerInfoAvatarListItemNode] = [] + var additiveTransitionOffset: CGFloat = 0.0 + if self.currentIndex >= 0 && self.currentIndex < self.items.count { + for i in max(0, self.currentIndex - 1) ... min(self.currentIndex + 1, self.items.count - 1) { + validIds.append(self.items[i].id) + let itemNode: PeerInfoAvatarListItemNode + var wasAdded = false + if let current = self.itemNodes[self.items[i].id] { + itemNode = current + } else { + wasAdded = true + itemNode = PeerInfoAvatarListItemNode(context: self.context, item: self.items[i]) + self.itemNodes[self.items[i].id] = itemNode + self.contentNode.addSubnode(itemNode) + } + let indexOffset = CGFloat(i - self.currentIndex) + let itemFrame = CGRect(origin: CGPoint(x: indexOffset * size.width + self.transitionFraction * size.width - size.width / 2.0, y: -size.height / 2.0), size: size) + + if wasAdded { + addedItemNodesForAdditiveTransition.append(itemNode) + itemNode.frame = itemFrame + itemNode.update(size: size, transition: .immediate) + } else { + additiveTransitionOffset = itemNode.frame.minX - itemFrame.minX + transition.updateFrame(node: itemNode, frame: itemFrame) + itemNode.update(size: size, transition: transition) + } + } + } + for itemNode in addedItemNodesForAdditiveTransition { + transition.animatePositionAdditive(node: itemNode, offset: CGPoint(x: additiveTransitionOffset, y: 0.0)) + } + var removeIds: [WrappedMediaResourceId] = [] + for (id, _) in self.itemNodes { + if !validIds.contains(id) { + removeIds.append(id) + } + } + for id in removeIds { + if let itemNode = self.itemNodes.removeValue(forKey: id) { + itemNode.removeFromSupernode() + } + } + + if let item = self.items.first, let itemNode = self.itemNodes[item.id] { + if !self.didSetReady { + self.didSetReady = true + self.isReady.set(itemNode.isReady.get()) + } + } + } +} + +final class PeerInfoAvatarTransformContainerNode: ASDisplayNode { + let context: AccountContext + let avatarNode: AvatarNode + + var tapped: (() -> Void)? + + private var isFirstAvatarLoading = true + + init(context: AccountContext) { + self.context = context + let avatarFont = avatarPlaceholderFont(size: floor(100.0 * 16.0 / 37.0)) + self.avatarNode = AvatarNode(font: avatarFont) + + super.init() + + self.addSubnode(self.avatarNode) + self.avatarNode.frame = CGRect(origin: CGPoint(x: -50.0, y: -50.0), size: CGSize(width: 100.0, height: 100.0)) + + self.avatarNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) + } + + @objc private func tapGesture(_ recognizer: UITapGestureRecognizer) { + if case .ended = recognizer.state { + self.tapped?() + } + } + + func update(peer: Peer?, theme: PresentationTheme) { + if let peer = peer { + var overrideImage: AvatarNodeImageOverride? + if peer.isDeleted { + overrideImage = .deletedIcon + } + self.avatarNode.setPeer(context: self.context, theme: theme, peer: peer, overrideImage: overrideImage, synchronousLoad: self.isFirstAvatarLoading, displayDimensions: CGSize(width: 100.0, height: 100.0)) + self.isFirstAvatarLoading = false + } + } +} + +final class PeerInfoEditingAvatarNode: ASDisplayNode { + let context: AccountContext + let avatarNode: AvatarNode + + var tapped: (() -> Void)? + + init(context: AccountContext) { + self.context = context + let avatarFont = avatarPlaceholderFont(size: floor(100.0 * 16.0 / 37.0)) + self.avatarNode = AvatarNode(font: avatarFont) + + super.init() + + self.addSubnode(self.avatarNode) + self.avatarNode.frame = CGRect(origin: CGPoint(x: -50.0, y: -50.0), size: CGSize(width: 100.0, height: 100.0)) + + self.avatarNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) + } + + @objc private func tapGesture(_ recognizer: UITapGestureRecognizer) { + if case .ended = recognizer.state { + self.tapped?() + } + } + + func update(peer: Peer?, theme: PresentationTheme) { + if let peer = peer { + self.avatarNode.setPeer(context: self.context, theme: theme, peer: peer, synchronousLoad: false, displayDimensions: CGSize(width: 100.0, height: 100.0)) + } + } +} + +final class PeerInfoAvatarListNode: ASDisplayNode { + let avatarContainerNode: PeerInfoAvatarTransformContainerNode + let listContainerTransformNode: ASDisplayNode + let listContainerNode: PeerInfoAvatarListContainerNode + + let isReady = Promise() + + init(context: AccountContext, readyWhenGalleryLoads: Bool) { + self.avatarContainerNode = PeerInfoAvatarTransformContainerNode(context: context) + self.listContainerTransformNode = ASDisplayNode() + self.listContainerNode = PeerInfoAvatarListContainerNode(context: context) + self.listContainerNode.clipsToBounds = true + self.listContainerNode.isHidden = true + + super.init() + + self.addSubnode(self.avatarContainerNode) + self.listContainerTransformNode.addSubnode(self.listContainerNode) + self.addSubnode(self.listContainerTransformNode) + + let avatarReady = self.avatarContainerNode.avatarNode.ready + |> mapToSignal { _ -> Signal in + return .complete() + } + |> then(.single(true)) + + let galleryReady = self.listContainerNode.isReady.get() + |> filter { $0 } + |> take(1) + + let combinedSignal: Signal + if readyWhenGalleryLoads { + combinedSignal = combineLatest(queue: .mainQueue(), + avatarReady, + galleryReady + ) + |> map { lhs, rhs in + return lhs && rhs + } + } else { + combinedSignal = avatarReady + } + + self.isReady.set(combinedSignal + |> filter { $0 } + |> take(1)) + } + + func update(size: CGSize, isExpanded: Bool, peer: Peer?, theme: PresentationTheme, transition: ContainedViewLayoutTransition) { + self.avatarContainerNode.update(peer: peer, theme: theme) + } + + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + if !self.listContainerNode.isHidden { + if let result = self.listContainerNode.view.hitTest(self.view.convert(point, to: self.listContainerNode.view), with: event) { + return result + } + } else { + if let result = self.avatarContainerNode.avatarNode.view.hitTest(self.view.convert(point, to: self.avatarContainerNode.avatarNode.view), with: event) { + return result + } + } + + return super.hitTest(point, with: event) + } + + func animateAvatarCollapse(transition: ContainedViewLayoutTransition) { + if let currentItemNode = self.listContainerNode.currentItemNode, let avatarCopyView = self.avatarContainerNode.avatarNode.view.snapshotContentTree(), case let .animated(duration, curve) = transition { + avatarCopyView.center = currentItemNode.imageNode.position + currentItemNode.view.addSubview(avatarCopyView) + let scale = currentItemNode.imageNode.bounds.height / avatarCopyView.bounds.height + avatarCopyView.layer.transform = CATransform3DMakeScale(scale, scale, scale) + avatarCopyView.alpha = 0.0 + transition.updateAlpha(layer: avatarCopyView.layer, alpha: 1.0, completion: { [weak avatarCopyView] _ in + Queue.mainQueue().after(0.1, { + avatarCopyView?.removeFromSuperview() + }) + }) + } + } +} + +final class PeerInfoHeaderNavigationButton: HighlightableButtonNode { + private let regularTextNode: ImmediateTextNode + private let whiteTextNode: ImmediateTextNode + private let iconNode: ASImageNode + + private var key: PeerInfoHeaderNavigationButtonKey? + private var theme: PresentationTheme? + + var isWhite: Bool = false { + didSet { + if self.isWhite != oldValue { + self.regularTextNode.isHidden = self.isWhite + self.whiteTextNode.isHidden = !self.isWhite + } + } + } + + var action: (() -> Void)? + + override init() { + self.regularTextNode = ImmediateTextNode() + self.whiteTextNode = ImmediateTextNode() + self.whiteTextNode.isHidden = true + + self.iconNode = ASImageNode() + self.iconNode.displaysAsynchronously = false + self.iconNode.displayWithoutProcessing = true + + super.init() + + self.addSubnode(self.regularTextNode) + self.addSubnode(self.whiteTextNode) + self.addSubnode(self.iconNode) + + self.addTarget(self, action: #selector(self.pressed), forControlEvents: .touchUpInside) + } + + @objc private func pressed() { + self.action?() + } + + func update(key: PeerInfoHeaderNavigationButtonKey, presentationData: PresentationData) -> CGSize { + let textSize: CGSize + if self.key != key || self.theme !== presentationData.theme { + self.key = key + self.theme = presentationData.theme + + let text: String + var icon: UIImage? + var isBold = false + switch key { + case .edit: + text = presentationData.strings.Common_Edit + case .done, .cancel, .selectionDone: + text = presentationData.strings.Common_Done + isBold = true + case .select: + text = presentationData.strings.Common_Select + case .search: + text = "" + icon = PresentationResourcesRootController.navigationCompactSearchIcon(presentationData.theme) + } + + let font: UIFont = isBold ? Font.semibold(17.0) : Font.regular(17.0) + + self.regularTextNode.attributedText = NSAttributedString(string: text, font: font, textColor: presentationData.theme.rootController.navigationBar.accentTextColor) + self.whiteTextNode.attributedText = NSAttributedString(string: text, font: font, textColor: .white) + self.iconNode.image = icon + + textSize = self.regularTextNode.updateLayout(CGSize(width: 200.0, height: .greatestFiniteMagnitude)) + let _ = self.whiteTextNode.updateLayout(CGSize(width: 200.0, height: .greatestFiniteMagnitude)) + } else { + textSize = self.regularTextNode.bounds.size + } + + let inset: CGFloat = 0.0 + let height: CGFloat = 44.0 + + let textFrame = CGRect(origin: CGPoint(x: inset, y: floor((height - textSize.height) / 2.0)), size: textSize) + self.regularTextNode.frame = textFrame + self.whiteTextNode.frame = textFrame + + if let image = self.iconNode.image { + self.iconNode.frame = CGRect(origin: CGPoint(x: inset, y: floor((height - image.size.height) / 2.0)), size: image.size) + + return CGSize(width: image.size.width + inset * 2.0, height: height) + } else { + return CGSize(width: textSize.width + inset * 2.0, height: height) + } + } +} + +enum PeerInfoHeaderNavigationButtonKey { + case edit + case done + case cancel + case select + case selectionDone + case search +} + +struct PeerInfoHeaderNavigationButtonSpec: Equatable { + let key: PeerInfoHeaderNavigationButtonKey + let isForExpandedView: Bool +} + +final class PeerInfoHeaderNavigationButtonContainerNode: ASDisplayNode { + private var buttonNodes: [PeerInfoHeaderNavigationButtonKey: PeerInfoHeaderNavigationButton] = [:] + + private var currentButtons: [PeerInfoHeaderNavigationButtonSpec] = [] + + var isWhite: Bool = false { + didSet { + if self.isWhite != oldValue { + for (_, buttonNode) in self.buttonNodes { + buttonNode.isWhite = self.isWhite + } + } + } + } + + var performAction: ((PeerInfoHeaderNavigationButtonKey) -> Void)? + + override init() { + super.init() + } + + func update(size: CGSize, presentationData: PresentationData, buttons: [PeerInfoHeaderNavigationButtonSpec], expandFraction: CGFloat, transition: ContainedViewLayoutTransition) { + let maximumExpandOffset: CGFloat = 14.0 + let expandOffset: CGFloat = -expandFraction * maximumExpandOffset + if self.currentButtons != buttons { + self.currentButtons = buttons + + var nextRegularButtonOrigin = size.width - 16.0 + var nextExpandedButtonOrigin = size.width - 16.0 + for spec in buttons.reversed() { + let buttonNode: PeerInfoHeaderNavigationButton + var wasAdded = false + if let current = self.buttonNodes[spec.key] { + buttonNode = current + } else { + wasAdded = true + buttonNode = PeerInfoHeaderNavigationButton() + self.buttonNodes[spec.key] = buttonNode + self.addSubnode(buttonNode) + buttonNode.isWhite = self.isWhite + buttonNode.action = { [weak self] in + self?.performAction?(spec.key) + } + } + let buttonSize = buttonNode.update(key: spec.key, presentationData: presentationData) + var nextButtonOrigin = spec.isForExpandedView ? nextExpandedButtonOrigin : nextRegularButtonOrigin + let buttonFrame = CGRect(origin: CGPoint(x: nextButtonOrigin - buttonSize.width, y: expandOffset + (spec.isForExpandedView ? maximumExpandOffset : 0.0)), size: buttonSize) + nextButtonOrigin -= buttonSize.width + 4.0 + if spec.isForExpandedView { + nextExpandedButtonOrigin = nextButtonOrigin + } else { + nextRegularButtonOrigin = nextButtonOrigin + } + if wasAdded { + buttonNode.frame = buttonFrame + } else { + transition.updateFrameAdditiveToCenter(node: buttonNode, frame: buttonFrame) + } + let alphaFactor: CGFloat = spec.isForExpandedView ? expandFraction : (1.0 - expandFraction) + transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor) + } + var removeKeys: [PeerInfoHeaderNavigationButtonKey] = [] + for (key, _) in self.buttonNodes { + if !buttons.contains(where: { $0.key == key }) { + removeKeys.append(key) + } + } + for key in removeKeys { + if let buttonNode = self.buttonNodes.removeValue(forKey: key) { + buttonNode.removeFromSupernode() + } + } + } else { + var nextRegularButtonOrigin = size.width - 16.0 + var nextExpandedButtonOrigin = size.width - 16.0 + for spec in buttons.reversed() { + if let buttonNode = self.buttonNodes[spec.key] { + let buttonSize = buttonNode.bounds.size + var nextButtonOrigin = spec.isForExpandedView ? nextExpandedButtonOrigin : nextRegularButtonOrigin + let buttonFrame = CGRect(origin: CGPoint(x: nextButtonOrigin - buttonSize.width, y: expandOffset + (spec.isForExpandedView ? maximumExpandOffset : 0.0)), size: buttonSize) + nextButtonOrigin -= buttonSize.width + 4.0 + if spec.isForExpandedView { + nextExpandedButtonOrigin = nextButtonOrigin + } else { + nextRegularButtonOrigin = nextButtonOrigin + } + transition.updateFrameAdditiveToCenter(node: buttonNode, frame: buttonFrame) + let alphaFactor: CGFloat = spec.isForExpandedView ? expandFraction : (1.0 - expandFraction) + transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor) + } + } + } + } +} + +final class PeerInfoHeaderRegularContentNode: ASDisplayNode { + +} + +enum PeerInfoHeaderTextFieldNodeKey { + case firstName + case lastName + case title + case description +} + +protocol PeerInfoHeaderTextFieldNode: ASDisplayNode { + var text: String { get } + + func update(width: CGFloat, safeInset: CGFloat, hasPrevious: Bool, placeholder: String, isEnabled: Bool, presentationData: PresentationData, updateText: String?) -> CGFloat +} + +final class PeerInfoHeaderSingleLineTextFieldNode: ASDisplayNode, PeerInfoHeaderTextFieldNode { + private let textNode: TextFieldNode + private let topSeparator: ASDisplayNode + + private var theme: PresentationTheme? + + var text: String { + return self.textNode.textField.text ?? "" + } + + override init() { + self.textNode = TextFieldNode() + self.topSeparator = ASDisplayNode() + + super.init() + + self.addSubnode(self.textNode) + self.addSubnode(self.topSeparator) + } + + func update(width: CGFloat, safeInset: CGFloat, hasPrevious: Bool, placeholder: String, isEnabled: Bool, presentationData: PresentationData, updateText: String?) -> CGFloat { + if self.theme !== presentationData.theme { + self.theme = presentationData.theme + self.textNode.textField.textColor = presentationData.theme.list.itemPrimaryTextColor + //self.textNode.textField.keyboardAppearance = presentationData.theme.keyboardAppearance + self.textNode.textField.tintColor = presentationData.theme.list.itemAccentColor + } + + let attributedPlaceholderText = NSAttributedString(string: placeholder, font: Font.regular(17.0), textColor: presentationData.theme.list.itemPlaceholderTextColor) + if self.textNode.textField.attributedPlaceholder == nil || !self.textNode.textField.attributedPlaceholder!.isEqual(to: attributedPlaceholderText) { + self.textNode.textField.attributedPlaceholder = attributedPlaceholderText + self.textNode.textField.accessibilityHint = attributedPlaceholderText.string + } + + if let updateText = updateText { + self.textNode.textField.text = updateText + } + + self.topSeparator.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor + self.topSeparator.frame = CGRect(origin: CGPoint(x: safeInset + (hasPrevious ? 16.0 : 0.0), y: 0.0), size: CGSize(width: width, height: UIScreenPixel)) + + let height: CGFloat = 44.0 + + self.textNode.frame = CGRect(origin: CGPoint(x: safeInset + 16.0, y: floor((height - 40.0) / 2.0)), size: CGSize(width: max(1.0, width - 16.0 * 2.0), height: 40.0)) + + self.textNode.isUserInteractionEnabled = isEnabled + self.textNode.alpha = isEnabled ? 1.0 : 0.6 + + return height + } +} + +/*final class PeerInfoHeaderMultiLineTextFieldNode: ASDisplayNode, PeerInfoHeaderTextFieldNode { + private let textNode: TextFieldNode + private let topSeparator: ASDisplayNode + + override init() { + self.textNode = TextFieldNode() + self.topSeparator = ASDisplayNode() + + super.init() + } + + func update(width: CGFloat, safeInset: CGFloat) -> CGFloat { + return 44.0 + } +}*/ + +final class PeerInfoHeaderEditingContentNode: ASDisplayNode { + private let context: AccountContext + let avatarNode: PeerInfoEditingAvatarNode + + var itemNodes: [PeerInfoHeaderTextFieldNodeKey: PeerInfoHeaderTextFieldNode] = [:] + + init(context: AccountContext) { + self.context = context + self.avatarNode = PeerInfoEditingAvatarNode(context: context) + + super.init() + + self.addSubnode(self.avatarNode) + } + + func editingTextForKey(_ key: PeerInfoHeaderTextFieldNodeKey) -> String? { + return self.itemNodes[key]?.text + } + + func update(width: CGFloat, safeInset: CGFloat, statusBarHeight: CGFloat, navigationHeight: CGFloat, peer: Peer?, isContact: Bool, presentationData: PresentationData, transition: ContainedViewLayoutTransition) -> CGFloat { + let avatarSize: CGFloat = 100.0 + let avatarFrame = CGRect(origin: CGPoint(x: floor((width - avatarSize) / 2.0), y: statusBarHeight + 10.0), size: CGSize(width: avatarSize, height: avatarSize)) + transition.updateFrameAdditiveToCenter(node: self.avatarNode, frame: CGRect(origin: avatarFrame.center, size: CGSize())) + + var contentHeight: CGFloat = statusBarHeight + 10.0 + 100.0 + 20.0 + + var fieldKeys: [PeerInfoHeaderTextFieldNodeKey] = [] + if let user = peer as? TelegramUser { + if !user.isDeleted { + fieldKeys.append(.firstName) + if user.botInfo == nil { + fieldKeys.append(.lastName) + } + } + } + var hasPrevious = false + for key in fieldKeys { + let itemNode: PeerInfoHeaderTextFieldNode + var updateText: String? + if let current = self.itemNodes[key] { + itemNode = current + } else { + switch key { + case .firstName: + updateText = (peer as? TelegramUser)?.firstName ?? "" + case .lastName: + updateText = (peer as? TelegramUser)?.lastName ?? "" + case .title: + updateText = (peer as? TelegramUser)?.debugDisplayTitle ?? "" + case .description: + break + } + itemNode = PeerInfoHeaderSingleLineTextFieldNode() + self.itemNodes[key] = itemNode + self.addSubnode(itemNode) + } + let placeholder: String + var isEnabled = true + switch key { + case .firstName: + placeholder = "First Name" + isEnabled = isContact + case .lastName: + placeholder = "Last Name" + isEnabled = isContact + case .title: + placeholder = "Title" + case .description: + placeholder = "Description" + } + let itemHeight = itemNode.update(width: width, safeInset: safeInset, hasPrevious: hasPrevious, placeholder: placeholder, isEnabled: isEnabled, presentationData: presentationData, updateText: updateText) + transition.updateFrame(node: itemNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: width, height: itemHeight))) + contentHeight += itemHeight + hasPrevious = true + } + var removeKeys: [PeerInfoHeaderTextFieldNodeKey] = [] + for (key, _) in self.itemNodes { + if !fieldKeys.contains(key) { + removeKeys.append(key) + } + } + for key in removeKeys { + if let itemNode = self.itemNodes.removeValue(forKey: key) { + itemNode.removeFromSupernode() + } + } + + return contentHeight + } +} + +final class PeerInfoHeaderNode: ASDisplayNode { + private var context: AccountContext + private var presentationData: PresentationData? + + private(set) var isAvatarExpanded: Bool + + let avatarListNode: PeerInfoAvatarListNode + + let regularContentNode: PeerInfoHeaderRegularContentNode + let editingContentNode: PeerInfoHeaderEditingContentNode + let titleNodeContainer: ASDisplayNode + let titleNodeRawContainer: ASDisplayNode + let titleNode: ImmediateTextNode + let titleCredibilityIconNode: ASImageNode + let subtitleNodeContainer: ASDisplayNode + let subtitleNodeRawContainer: ASDisplayNode + let subtitleNode: ImmediateTextNode + private var buttonNodes: [PeerInfoHeaderButtonKey: PeerInfoHeaderButtonNode] = [:] + private let backgroundNode: ASDisplayNode + private let expandedBackgroundNode: ASDisplayNode + let separatorNode: ASDisplayNode + let navigationButtonContainer: PeerInfoHeaderNavigationButtonContainerNode + + var performButtonAction: ((PeerInfoHeaderButtonKey) -> Void)? + var requestAvatarExpansion: (([AvatarGalleryEntry], (ASDisplayNode, CGRect, () -> (UIView?, UIView?))) -> Void)? + + var navigationTransition: PeerInfoHeaderNavigationTransition? + + init(context: AccountContext, avatarInitiallyExpanded: Bool) { + self.context = context + self.isAvatarExpanded = avatarInitiallyExpanded + + self.avatarListNode = PeerInfoAvatarListNode(context: context, readyWhenGalleryLoads: avatarInitiallyExpanded) + + self.titleNodeContainer = ASDisplayNode() + self.titleNodeRawContainer = ASDisplayNode() + self.titleNode = ImmediateTextNode() + self.titleNode.displaysAsynchronously = false + + self.titleCredibilityIconNode = ASImageNode() + self.titleCredibilityIconNode.displaysAsynchronously = false + self.titleCredibilityIconNode.displayWithoutProcessing = true + self.titleNode.addSubnode(self.titleCredibilityIconNode) + + self.subtitleNodeContainer = ASDisplayNode() + self.subtitleNodeRawContainer = ASDisplayNode() + self.subtitleNode = ImmediateTextNode() + self.subtitleNode.displaysAsynchronously = false + + self.regularContentNode = PeerInfoHeaderRegularContentNode() + self.editingContentNode = PeerInfoHeaderEditingContentNode(context: context) + self.editingContentNode.alpha = 0.0 + + self.navigationButtonContainer = PeerInfoHeaderNavigationButtonContainerNode() + + self.backgroundNode = ASDisplayNode() + self.backgroundNode.isLayerBacked = true + self.expandedBackgroundNode = ASDisplayNode() + self.expandedBackgroundNode.isLayerBacked = true + + self.separatorNode = ASDisplayNode() + self.separatorNode.isLayerBacked = true + + super.init() + + self.addSubnode(self.backgroundNode) + self.addSubnode(self.expandedBackgroundNode) + self.addSubnode(self.separatorNode) + self.titleNodeContainer.addSubnode(self.titleNode) + self.regularContentNode.addSubnode(self.titleNodeContainer) + self.subtitleNodeContainer.addSubnode(self.subtitleNode) + self.regularContentNode.addSubnode(self.subtitleNodeContainer) + self.regularContentNode.addSubnode(self.avatarListNode) + self.addSubnode(self.regularContentNode) + self.addSubnode(self.editingContentNode) + self.addSubnode(self.navigationButtonContainer) + + self.avatarListNode.avatarContainerNode.tapped = { [weak self] in + guard let strongSelf = self else { + return + } + let avatarNode = strongSelf.avatarListNode.avatarContainerNode.avatarNode + strongSelf.requestAvatarExpansion?(strongSelf.avatarListNode.listContainerNode.galleryEntries, (avatarNode, avatarNode.bounds, { [weak avatarNode] in + return (avatarNode?.view.snapshotContentTree(unhide: true), nil) + })) + } + } + + func updateAvatarIsHidden(_ isHidden: Bool) { + self.avatarListNode.avatarContainerNode.avatarNode.isHidden = isHidden + } + + func update(width: CGFloat, containerHeight: CGFloat, containerInset: CGFloat, statusBarHeight: CGFloat, navigationHeight: CGFloat, contentOffset: CGFloat, presentationData: PresentationData, peer: Peer?, cachedData: CachedPeerData?, notificationSettings: TelegramPeerNotificationSettings?, statusData: PeerInfoStatusData?, isContact: Bool, state: PeerInfoState, transition: ContainedViewLayoutTransition, additive: Bool) -> CGFloat { + let themeUpdated = self.presentationData?.theme !== presentationData.theme + self.presentationData = presentationData + + if themeUpdated { + self.titleCredibilityIconNode.image = PresentationResourcesItemList.verifiedPeerIcon(presentationData.theme) + } + + self.regularContentNode.alpha = state.isEditing ? 0.0 : 1.0 + self.editingContentNode.alpha = state.isEditing ? 1.0 : 0.0 + + let editingContentHeight = self.editingContentNode.update(width: width, safeInset: containerInset, statusBarHeight: statusBarHeight, navigationHeight: navigationHeight, peer: state.isEditing ? peer : nil, isContact: isContact, presentationData: presentationData, transition: transition) + transition.updateFrame(node: self.editingContentNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -contentOffset), size: CGSize(width: width, height: editingContentHeight))) + + var transitionSourceHeight: CGFloat = 0.0 + var transitionFraction: CGFloat = 0.0 + var transitionSourceAvatarFrame = CGRect() + var transitionSourceTitleFrame = CGRect() + var transitionSourceSubtitleFrame = CGRect() + + self.backgroundNode.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor + self.expandedBackgroundNode.backgroundColor = presentationData.theme.rootController.navigationBar.backgroundColor + + if let navigationTransition = self.navigationTransition, let sourceAvatarNode = navigationTransition.sourceTitleView.avatarNode?.avatarNode { + transitionSourceHeight = navigationTransition.sourceNavigationBar.bounds.height + transitionFraction = navigationTransition.fraction + transitionSourceAvatarFrame = sourceAvatarNode.view.convert(sourceAvatarNode.view.bounds, to: navigationTransition.sourceNavigationBar.view) + transitionSourceTitleFrame = navigationTransition.sourceTitleFrame + transitionSourceSubtitleFrame = navigationTransition.sourceSubtitleFrame + + transition.updateAlpha(node: self.expandedBackgroundNode, alpha: transitionFraction) + } else { + let backgroundTransitionFraction: CGFloat = max(0.0, min(1.0, contentOffset / (212.0))) + transition.updateAlpha(node: self.expandedBackgroundNode, alpha: backgroundTransitionFraction) + } + + self.separatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor + + let defaultButtonSize: CGFloat = 40.0 + let defaultMaxButtonSpacing: CGFloat = 40.0 + let expandedAvatarListHeight = min(width, containerHeight - 64.0) + let expandedAvatarListSize = CGSize(width: width, height: expandedAvatarListHeight) + + let buttonKeys: [PeerInfoHeaderButtonKey] = peerInfoHeaderButtons(peer: peer, cachedData: cachedData) + + if let peer = peer { + self.titleNode.attributedText = NSAttributedString(string: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), font: Font.medium(24.0), textColor: presentationData.theme.list.itemPrimaryTextColor) + + let subtitleString: NSAttributedString? + if let statusData = statusData { + let subtitleColor: UIColor + if statusData.isActivity { + subtitleColor = presentationData.theme.list.itemAccentColor + } else { + subtitleColor = presentationData.theme.list.itemSecondaryTextColor + } + subtitleString = NSAttributedString(string: statusData.text, font: Font.regular(15.0), textColor: subtitleColor) + } else { + subtitleString = nil + } + self.subtitleNode.attributedText = subtitleString + } + + let textSideInset: CGFloat = 16.0 + let expandedAvatarControlsHeight: CGFloat = 64.0 + let expandedAvatarHeight: CGFloat = expandedAvatarListSize.height + expandedAvatarControlsHeight + + let avatarSize: CGFloat = 100.0 + let avatarFrame = CGRect(origin: CGPoint(x: floor((width - avatarSize) / 2.0), y: statusBarHeight + 10.0), size: CGSize(width: avatarSize, height: avatarSize)) + let avatarCenter = CGPoint(x: (1.0 - transitionFraction) * avatarFrame.midX + transitionFraction * transitionSourceAvatarFrame.midX, y: (1.0 - transitionFraction) * avatarFrame.midY + transitionFraction * transitionSourceAvatarFrame.midY) + + var isVerified = false + if let peer = peer, peer.isVerified { + isVerified = true + } + + let titleSize = self.titleNode.updateLayout(CGSize(width: width - textSideInset * 2.0 - (isVerified ? 16.0 : 0.0), height: .greatestFiniteMagnitude)) + let subtitleSize = self.subtitleNode.updateLayout(CGSize(width: width - textSideInset * 2.0, height: .greatestFiniteMagnitude)) + + if let image = self.titleCredibilityIconNode.image { + transition.updateFrame(node: self.titleCredibilityIconNode, frame: CGRect(origin: CGPoint(x: titleSize.width + 4.0, y: floor((titleSize.height - image.size.height) / 2.0) + 1.0), size: image.size)) + self.titleCredibilityIconNode.isHidden = !isVerified + } + + let titleFrame: CGRect + let subtitleFrame: CGRect + if self.isAvatarExpanded { + titleFrame = CGRect(origin: CGPoint(x: 16.0, y: expandedAvatarHeight - expandedAvatarControlsHeight + 12.0 + (subtitleSize.height.isZero ? 10.0 : 0.0)), size: titleSize) + subtitleFrame = CGRect(origin: CGPoint(x: 16.0, y: titleFrame.maxY - 5.0), size: subtitleSize) + } else { + titleFrame = CGRect(origin: CGPoint(x: floor((width - titleSize.width) / 2.0), y: avatarFrame.maxY + 10.0 + (subtitleSize.height.isZero ? 11.0 : 0.0)), size: titleSize) + subtitleFrame = CGRect(origin: CGPoint(x: floor((width - subtitleSize.width) / 2.0), y: titleFrame.maxY + 1.0), size: subtitleSize) + } + + let titleLockOffset: CGFloat = 7.0 + (subtitleSize.height.isZero ? 8.0 : 0.0) + let titleMaxLockOffset: CGFloat = 7.0 + let titleCollapseOffset = titleFrame.midY - statusBarHeight - titleLockOffset + let titleOffset = -min(titleCollapseOffset, contentOffset) + let titleCollapseFraction = max(0.0, min(1.0, contentOffset / titleCollapseOffset)) + + let titleMinScale: CGFloat = 0.7 + let subtitleMinScale: CGFloat = 0.8 + let avatarMinScale: CGFloat = 0.7 + + let apparentTitleLockOffset = (1.0 - titleCollapseFraction) * 0.0 + titleCollapseFraction * titleMaxLockOffset + + let avatarScale: CGFloat + let avatarOffset: CGFloat + if self.navigationTransition != nil { + avatarScale = ((1.0 - transitionFraction) * avatarFrame.width + transitionFraction * transitionSourceAvatarFrame.width) / avatarFrame.width + avatarOffset = 0.0 + } else { + avatarScale = 1.0 * (1.0 - titleCollapseFraction) + avatarMinScale * titleCollapseFraction + avatarOffset = apparentTitleLockOffset + 0.0 * (1.0 - titleCollapseFraction) + 10.0 * titleCollapseFraction + } + let avatarListFrame = CGRect(origin: CGPoint(), size: expandedAvatarListSize) + + if self.isAvatarExpanded { + self.avatarListNode.listContainerNode.isHidden = false + if !transitionSourceAvatarFrame.width.isZero { + transition.updateCornerRadius(node: self.avatarListNode.listContainerNode, cornerRadius: transitionFraction * transitionSourceAvatarFrame.width / 2.0) + } else { + transition.updateCornerRadius(node: self.avatarListNode.listContainerNode, cornerRadius: 0.0) + } + } else if self.avatarListNode.listContainerNode.cornerRadius != 50.0 { + transition.updateCornerRadius(node: self.avatarListNode.listContainerNode, cornerRadius: 50.0, completion: { [weak self] _ in + guard let strongSelf = self else { + return + } + strongSelf.avatarListNode.listContainerNode.isHidden = true + }) + } + + self.avatarListNode.update(size: CGSize(), isExpanded: self.isAvatarExpanded, peer: peer, theme: presentationData.theme, transition: transition) + self.editingContentNode.avatarNode.update(peer: peer, theme: presentationData.theme) + if additive { + transition.updateSublayerTransformScaleAdditive(node: self.avatarListNode.avatarContainerNode, scale: avatarScale) + } else { + transition.updateSublayerTransformScale(node: self.avatarListNode.avatarContainerNode, scale: avatarScale) + } + let apparentAvatarFrame: CGRect + if self.isAvatarExpanded { + let expandedAvatarCenter = CGPoint(x: expandedAvatarListSize.width / 2.0, y: expandedAvatarListSize.height / 2.0 - contentOffset / 2.0) + apparentAvatarFrame = CGRect(origin: CGPoint(x: expandedAvatarCenter.x * (1.0 - transitionFraction) + transitionFraction * avatarCenter.x, y: expandedAvatarCenter.y * (1.0 - transitionFraction) + transitionFraction * avatarCenter.y), size: CGSize()) + } else { + apparentAvatarFrame = CGRect(origin: CGPoint(x: avatarCenter.x - avatarFrame.width / 2.0, y: -contentOffset + avatarOffset + avatarCenter.y - avatarFrame.height / 2.0), size: avatarFrame.size) + } + if case let .animated(duration, curve) = transition, !transitionSourceAvatarFrame.width.isZero, false { + let previousFrame = self.avatarListNode.frame + self.avatarListNode.frame = CGRect(origin: apparentAvatarFrame.center, size: CGSize()) + let horizontalTransition: ContainedViewLayoutTransition + let verticalTransition: ContainedViewLayoutTransition + if transitionFraction < .ulpOfOne { + horizontalTransition = .animated(duration: duration * 0.85, curve: curve) + verticalTransition = .animated(duration: duration * 1.15, curve: curve) + } else { + horizontalTransition = transition + verticalTransition = .animated(duration: duration * 0.6, curve: curve) + } + horizontalTransition.animatePositionAdditive(node: self.avatarListNode, offset: CGPoint(x: previousFrame.midX - apparentAvatarFrame.midX, y: 0.0)) + verticalTransition.animatePositionAdditive(node: self.avatarListNode, offset: CGPoint(x: 0.0, y: previousFrame.midY - apparentAvatarFrame.midY)) + } else { + transition.updateFrameAdditive(node: self.avatarListNode, frame: CGRect(origin: apparentAvatarFrame.center, size: CGSize())) + } + + let avatarListContainerFrame: CGRect + let avatarListContainerScale: CGFloat + if self.isAvatarExpanded { + if !transitionSourceAvatarFrame.width.isZero { + let neutralAvatarListContainerSize = expandedAvatarListSize + let avatarListContainerSize = CGSize(width: neutralAvatarListContainerSize.width * (1.0 - transitionFraction) + transitionSourceAvatarFrame.width * transitionFraction, height: neutralAvatarListContainerSize.height * (1.0 - transitionFraction) + transitionSourceAvatarFrame.height * transitionFraction) + avatarListContainerFrame = CGRect(origin: CGPoint(x: -avatarListContainerSize.width / 2.0, y: -avatarListContainerSize.height / 2.0), size: avatarListContainerSize) + } else { + avatarListContainerFrame = CGRect(origin: CGPoint(x: -expandedAvatarListSize.width / 2.0, y: -expandedAvatarListSize.height / 2.0), size: expandedAvatarListSize) + } + avatarListContainerScale = 1.0 + max(0.0, -contentOffset / avatarListContainerFrame.height) + } else { + avatarListContainerFrame = CGRect(origin: CGPoint(x: -apparentAvatarFrame.width / 2.0, y: -apparentAvatarFrame.height / 2.0), size: apparentAvatarFrame.size) + avatarListContainerScale = avatarScale + } + transition.updateFrame(node: self.avatarListNode.listContainerNode, frame: avatarListContainerFrame) + let innerScale = avatarListContainerFrame.height / expandedAvatarListSize.height + let innerDeltaX = (avatarListContainerFrame.width - expandedAvatarListSize.width) / 2.0 + let innerDeltaY = (avatarListContainerFrame.height - expandedAvatarListSize.height) / 2.0 + transition.updateSublayerTransformScale(node: self.avatarListNode.listContainerNode, scale: innerScale) + transition.updateFrameAdditive(node: self.avatarListNode.listContainerNode.contentNode, frame: CGRect(origin: CGPoint(x: innerDeltaX + expandedAvatarListSize.width / 2.0, y: innerDeltaY + expandedAvatarListSize.height / 2.0), size: CGSize())) + + transition.updateFrameAdditive(node: self.avatarListNode.listContainerNode.controlsContainerTransformNode, frame: CGRect(origin: CGPoint(x: expandedAvatarListSize.width / 2.0, y: expandedAvatarListSize.height / 2.0 - innerDeltaY), size: CGSize())) + transition.updateSublayerTransformScale(node: self.avatarListNode.listContainerNode.controlsContainerNode, scale: 1.0 / innerScale) + transition.updateSublayerTransformScaleAdditive(node: self.avatarListNode.listContainerNode.controlsContainerTransformNode, scale: 1.0 / avatarListContainerScale) + transition.updateFrameAdditive(node: self.avatarListNode.listContainerNode.shadowNode, frame: CGRect(origin: CGPoint(x: -apparentAvatarFrame.minX, y: -apparentAvatarFrame.minY), size: CGSize(width: expandedAvatarListSize.width, height: navigationHeight))) + + if additive { + transition.updateSublayerTransformScaleAdditive(node: self.avatarListNode.listContainerTransformNode, scale: avatarListContainerScale) + } else { + transition.updateSublayerTransformScale(node: self.avatarListNode.listContainerTransformNode, scale: avatarListContainerScale) + } + + self.avatarListNode.listContainerNode.update(size: expandedAvatarListSize, peer: peer, transition: transition) + + let buttonsCollapseStart = titleCollapseOffset + let buttonsCollapseEnd = 212.0 - (navigationHeight - statusBarHeight) + 10.0 + + let buttonsCollapseFraction = max(0.0, contentOffset - buttonsCollapseStart) / (buttonsCollapseEnd - buttonsCollapseStart) + + let rawHeight: CGFloat + let height: CGFloat + if self.isAvatarExpanded { + rawHeight = expandedAvatarHeight + height = max(navigationHeight, rawHeight - contentOffset) + } else { + rawHeight = navigationHeight + 212.0 + height = navigationHeight + max(0.0, 212.0 - contentOffset) + } + + let apparentHeight = (1.0 - transitionFraction) * height + transitionFraction * transitionSourceHeight + + if !titleSize.width.isZero && !titleSize.height.isZero { + if self.navigationTransition != nil { + var neutralTitleScale: CGFloat = 1.0 + var neutralSubtitleScale: CGFloat = 1.0 + if self.isAvatarExpanded { + neutralTitleScale = 0.7 + neutralSubtitleScale = 1.0 + } + + let titleScale = (transitionFraction * transitionSourceTitleFrame.height + (1.0 - transitionFraction) * titleFrame.height * neutralTitleScale) / (titleFrame.height) + let subtitleScale = max(0.01, min(10.0, (transitionFraction * transitionSourceSubtitleFrame.height + (1.0 - transitionFraction) * subtitleFrame.height * neutralSubtitleScale) / (subtitleFrame.height))) + + let titleOrigin = CGPoint(x: transitionFraction * transitionSourceTitleFrame.minX + (1.0 - transitionFraction) * titleFrame.minX, y: transitionFraction * transitionSourceTitleFrame.minY + (1.0 - transitionFraction) * titleFrame.minY) + let subtitleOrigin = CGPoint(x: transitionFraction * transitionSourceSubtitleFrame.minX + (1.0 - transitionFraction) * subtitleFrame.minX, y: transitionFraction * transitionSourceSubtitleFrame.minY + (1.0 - transitionFraction) * subtitleFrame.minY) + + let rawTitleFrame = CGRect(origin: titleOrigin, size: titleFrame.size) + self.titleNodeRawContainer.frame = rawTitleFrame + transition.updateFrameAdditiveToCenter(node: self.titleNodeContainer, frame: rawTitleFrame.offsetBy(dx: rawTitleFrame.width * 0.5 * (titleScale - 1.0), dy: titleOffset + rawTitleFrame.height * 0.5 * (titleScale - 1.0))) + transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(), size: titleFrame.size)) + let rawSubtitleFrame = CGRect(origin: subtitleOrigin, size: subtitleFrame.size) + self.subtitleNodeRawContainer.frame = rawSubtitleFrame + transition.updateFrameAdditiveToCenter(node: self.subtitleNodeContainer, frame: rawSubtitleFrame.offsetBy(dx: rawSubtitleFrame.width * 0.5 * (subtitleScale - 1.0), dy: titleOffset + rawSubtitleFrame.height * 0.5 * (subtitleScale - 1.0))) + transition.updateFrame(node: self.subtitleNode, frame: CGRect(origin: CGPoint(), size: subtitleFrame.size)) + transition.updateSublayerTransformScale(node: self.titleNodeContainer, scale: titleScale) + transition.updateSublayerTransformScale(node: self.subtitleNodeContainer, scale: subtitleScale) + } else { + let titleScale: CGFloat + let subtitleScale: CGFloat + if self.isAvatarExpanded { + titleScale = 0.7 + subtitleScale = 1.0 + } else { + titleScale = (1.0 - titleCollapseFraction) * 1.0 + titleCollapseFraction * titleMinScale + subtitleScale = (1.0 - titleCollapseFraction) * 1.0 + titleCollapseFraction * subtitleMinScale + } + + let rawTitleFrame = titleFrame + self.titleNodeRawContainer.frame = rawTitleFrame + transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(), size: titleFrame.size)) + let rawSubtitleFrame = subtitleFrame + self.subtitleNodeRawContainer.frame = rawSubtitleFrame + if self.isAvatarExpanded { + transition.updateFrameAdditive(node: self.titleNodeContainer, frame: rawTitleFrame.offsetBy(dx: 0.0, dy: titleOffset + apparentTitleLockOffset).offsetBy(dx: rawTitleFrame.width * 0.5 * (titleScale - 1.0), dy: rawTitleFrame.height * 0.5 * (titleScale - 1.0))) + transition.updateFrameAdditive(node: self.subtitleNodeContainer, frame: rawSubtitleFrame.offsetBy(dx: 0.0, dy: titleOffset).offsetBy(dx: rawSubtitleFrame.width * 0.5 * (subtitleScale - 1.0), dy: rawSubtitleFrame.height * 0.5 * (subtitleScale - 1.0))) + } else { + transition.updateFrameAdditiveToCenter(node: self.titleNodeContainer, frame: rawTitleFrame.offsetBy(dx: 0.0, dy: titleOffset + apparentTitleLockOffset)) + transition.updateFrameAdditiveToCenter(node: self.subtitleNodeContainer, frame: rawSubtitleFrame.offsetBy(dx: 0.0, dy: titleOffset)) + } + transition.updateFrame(node: self.subtitleNode, frame: CGRect(origin: CGPoint(), size: subtitleFrame.size)) + transition.updateSublayerTransformScaleAdditive(node: self.titleNodeContainer, scale: titleScale) + transition.updateSublayerTransformScaleAdditive(node: self.subtitleNodeContainer, scale: subtitleScale) + } + } + + let buttonSpacing: CGFloat + if self.isAvatarExpanded { + buttonSpacing = 16.0 + } else { + buttonSpacing = min(defaultMaxButtonSpacing, width - floor(CGFloat(buttonKeys.count) * defaultButtonSize / CGFloat(buttonKeys.count + 1))) + } + + let expandedButtonSize: CGFloat = 32.0 + let buttonsWidth = buttonSpacing * CGFloat(buttonKeys.count - 1) + CGFloat(buttonKeys.count) * defaultButtonSize + var buttonRightOrigin: CGPoint + if self.isAvatarExpanded { + buttonRightOrigin = CGPoint(x: width - 16.0, y: apparentHeight - 74.0) + } else { + buttonRightOrigin = CGPoint(x: floor((width - buttonsWidth) / 2.0) + buttonsWidth, y: apparentHeight - 74.0) + } + let buttonsScale: CGFloat + let buttonsAlpha: CGFloat + let apparentButtonSize: CGFloat + let buttonsVerticalOffset: CGFloat + if self.navigationTransition != nil { + if self.isAvatarExpanded { + apparentButtonSize = expandedButtonSize + } else { + apparentButtonSize = defaultButtonSize + } + let neutralButtonsScale = apparentButtonSize / defaultButtonSize + buttonsScale = (1.0 - transitionFraction) * neutralButtonsScale + 0.2 * transitionFraction + buttonsAlpha = 1.0 - transitionFraction + + let neutralButtonsOffset: CGFloat + if self.isAvatarExpanded { + neutralButtonsOffset = 74.0 - 15.0 - defaultButtonSize + (defaultButtonSize - apparentButtonSize) / 2.0 + } else { + neutralButtonsOffset = (1.0 - buttonsScale) * apparentButtonSize + } + + buttonsVerticalOffset = (1.0 - transitionFraction) * neutralButtonsOffset + ((1.0 - buttonsScale) * apparentButtonSize) * transitionFraction + } else { + apparentButtonSize = self.isAvatarExpanded ? expandedButtonSize : defaultButtonSize + if self.isAvatarExpanded { + buttonsScale = apparentButtonSize / defaultButtonSize + buttonsVerticalOffset = 74.0 - 15.0 - defaultButtonSize + (defaultButtonSize - apparentButtonSize) / 2.0 + } else { + buttonsScale = (1.0 - buttonsCollapseFraction) * 1.0 + 0.2 * buttonsCollapseFraction + buttonsVerticalOffset = (1.0 - buttonsScale) * apparentButtonSize + } + buttonsAlpha = 1.0 - buttonsCollapseFraction + } + let buttonsScaledOffset = (defaultButtonSize - apparentButtonSize) / 2.0 + for buttonKey in buttonKeys.reversed() { + let buttonNode: PeerInfoHeaderButtonNode + var wasAdded = false + if let current = self.buttonNodes[buttonKey] { + buttonNode = current + } else { + wasAdded = true + buttonNode = PeerInfoHeaderButtonNode(key: buttonKey, action: { [weak self] buttonNode in + self?.buttonPressed(buttonNode) + }) + self.buttonNodes[buttonKey] = buttonNode + self.regularContentNode.addSubnode(buttonNode) + } + + let buttonFrame = CGRect(origin: CGPoint(x: buttonRightOrigin.x - defaultButtonSize + buttonsScaledOffset, y: buttonRightOrigin.y), size: CGSize(width: defaultButtonSize, height: defaultButtonSize)) + let buttonTransition: ContainedViewLayoutTransition = wasAdded ? .immediate : transition + + let apparentButtonFrame = buttonFrame.offsetBy(dx: 0.0, dy: buttonsVerticalOffset) + if additive { + buttonTransition.updateFrameAdditiveToCenter(node: buttonNode, frame: apparentButtonFrame) + } else { + buttonTransition.updateFrame(node: buttonNode, frame: apparentButtonFrame) + } + let buttonText: String + let buttonIcon: PeerInfoHeaderButtonIcon + switch buttonKey { + case .message: + buttonText = "Message" + buttonIcon = .message + case .call: + buttonText = "Call" + buttonIcon = .call + case .mute: + if let notificationSettings = notificationSettings, case .muted = notificationSettings.muteState { + buttonText = "Unmute" + buttonIcon = .unmute + } else { + buttonText = "Mute" + buttonIcon = .mute + } + case .more: + buttonText = "More" + buttonIcon = .more + case .addMember: + buttonText = "Add Member" + buttonIcon = .addMember + } + buttonNode.update(size: buttonFrame.size, text: buttonText, icon: buttonIcon, isExpanded: self.isAvatarExpanded, presentationData: presentationData, transition: buttonTransition) + transition.updateSublayerTransformScaleAdditive(node: buttonNode, scale: buttonsScale) + + transition.updateAlpha(node: buttonNode, alpha: buttonsAlpha) + + let hiddenWhileExpanded: Bool + switch buttonKey { + case .mute: + hiddenWhileExpanded = true + default: + hiddenWhileExpanded = false + } + + if self.isAvatarExpanded, hiddenWhileExpanded { + if case let .animated(duration, curve) = transition { + ContainedViewLayoutTransition.animated(duration: duration * 0.3, curve: curve).updateAlpha(node: buttonNode.containerNode, alpha: 0.0) + } else { + transition.updateAlpha(node: buttonNode.containerNode, alpha: 0.0) + } + } else { + if case .mute = buttonKey, buttonNode.containerNode.alpha.isZero, additive { + if case let .animated(duration, curve) = transition { + ContainedViewLayoutTransition.animated(duration: duration * 0.3, curve: curve).updateAlpha(node: buttonNode.containerNode, alpha: 1.0) + } else { + transition.updateAlpha(node: buttonNode.containerNode, alpha: 1.0) + } + } else { + transition.updateAlpha(node: buttonNode.containerNode, alpha: 1.0) + } + buttonRightOrigin.x -= apparentButtonSize + buttonSpacing + } + } + + for key in self.buttonNodes.keys { + if !buttonKeys.contains(key) { + if let buttonNode = self.buttonNodes[key] { + self.buttonNodes.removeValue(forKey: key) + buttonNode.removeFromSupernode() + } + } + } + + let resolvedRegularHeight: CGFloat + if self.isAvatarExpanded { + resolvedRegularHeight = expandedAvatarListSize.height + expandedAvatarControlsHeight + } else { + resolvedRegularHeight = 212.0 + navigationHeight + } + + let backgroundFrame: CGRect + let separatorFrame: CGRect + + let resolvedHeight: CGFloat + if state.isEditing { + resolvedHeight = editingContentHeight + backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: -2000.0 + resolvedHeight - contentOffset), size: CGSize(width: width, height: 2000.0)) + separatorFrame = CGRect(origin: CGPoint(x: 0.0, y: resolvedHeight - contentOffset), size: CGSize(width: width, height: UIScreenPixel)) + } else { + resolvedHeight = resolvedRegularHeight + backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: -2000.0 + apparentHeight), size: CGSize(width: width, height: 2000.0)) + separatorFrame = CGRect(origin: CGPoint(x: 0.0, y: apparentHeight), size: CGSize(width: width, height: UIScreenPixel)) + } + + transition.updateFrame(node: self.regularContentNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: resolvedHeight))) + + if additive { + transition.updateFrameAdditive(node: self.backgroundNode, frame: backgroundFrame) + transition.updateFrameAdditive(node: self.expandedBackgroundNode, frame: backgroundFrame) + transition.updateFrameAdditive(node: self.separatorNode, frame: separatorFrame) + } else { + transition.updateFrame(node: self.backgroundNode, frame: backgroundFrame) + transition.updateFrame(node: self.expandedBackgroundNode, frame: backgroundFrame) + transition.updateFrame(node: self.separatorNode, frame: separatorFrame) + } + + return resolvedHeight + } + + private func buttonPressed(_ buttonNode: PeerInfoHeaderButtonNode) { + self.performButtonAction?(buttonNode.key) + } + + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + guard let result = super.hitTest(point, with: event) else { + return nil + } + if result.isDescendant(of: self.navigationButtonContainer.view) { + return result + } + if !self.backgroundNode.frame.contains(point) { + return nil + } + if result == self.view || result == self.regularContentNode.view || result == self.editingContentNode.view { + return nil + } + return result + } + + func updateIsAvatarExpanded(_ isAvatarExpanded: Bool, transition: ContainedViewLayoutTransition) { + if self.isAvatarExpanded != isAvatarExpanded { + self.isAvatarExpanded = isAvatarExpanded + if isAvatarExpanded { + self.avatarListNode.listContainerNode.selectFirstItem() + } + if case .animated = transition, !isAvatarExpanded { + self.avatarListNode.animateAvatarCollapse(transition: transition) + } + } + } +} diff --git a/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoPaneContainerNode.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoPaneContainerNode.swift new file mode 100644 index 0000000000..976036603b --- /dev/null +++ b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoPaneContainerNode.swift @@ -0,0 +1,553 @@ +import Foundation +import UIKit +import AsyncDisplayKit +import Display +import SwiftSignalKit +import TelegramPresentationData +import Postbox +import SyncCore +import TelegramCore +import AccountContext +import ContextUI + +protocol PeerInfoPaneNode: ASDisplayNode { + var isReady: Signal { get } + + func update(size: CGSize, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) + func scrollToTop() -> Bool + func transferVelocity(_ velocity: CGFloat) + func findLoadedMessage(id: MessageId) -> Message? + func transitionNodeForGallery(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? + func addToTransitionSurface(view: UIView) + func updateHiddenMedia() + func updateSelectedMessages(animated: Bool) +} + +final class PeerInfoPaneWrapper { + let key: PeerInfoPaneKey + let node: PeerInfoPaneNode + private var appliedParams: (CGSize, CGFloat, CGFloat, CGFloat, Bool, PresentationData)? + + init(key: PeerInfoPaneKey, node: PeerInfoPaneNode) { + self.key = key + self.node = node + } + + func update(size: CGSize, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) { + if let (currentSize, currentSideInset, currentBottomInset, visibleHeight, currentIsScrollingLockedAtTop, currentPresentationData) = self.appliedParams { + if currentSize == size && currentSideInset == sideInset && currentBottomInset == bottomInset, currentIsScrollingLockedAtTop == isScrollingLockedAtTop && currentPresentationData === presentationData { + return + } + } + self.appliedParams = (size, sideInset, bottomInset, visibleHeight, isScrollingLockedAtTop, presentationData) + self.node.update(size: size, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, presentationData: presentationData, synchronous: synchronous, transition: transition) + } +} + +enum PeerInfoPaneKey { + case media + case files + case links + case voice + case music + case groupsInCommon +} + +final class PeerInfoPaneTabsContainerPaneNode: ASDisplayNode { + private let pressed: () -> Void + + private let titleNode: ImmediateTextNode + private let buttonNode: HighlightTrackingButtonNode + + init(pressed: @escaping () -> Void) { + self.pressed = pressed + + self.titleNode = ImmediateTextNode() + self.titleNode.displaysAsynchronously = false + + self.buttonNode = HighlightTrackingButtonNode() + + super.init() + + self.addSubnode(self.titleNode) + self.addSubnode(self.buttonNode) + + self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside) + self.buttonNode.highligthedChanged = { [weak self] highlighted in + if let strongSelf = self { + if highlighted { + strongSelf.titleNode.layer.removeAnimation(forKey: "opacity") + strongSelf.titleNode.alpha = 0.4 + } else { + strongSelf.titleNode.alpha = 1.0 + strongSelf.titleNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) + } + } + } + } + + @objc private func buttonPressed() { + self.pressed() + } + + func updateText(_ title: String, isSelected: Bool, presentationData: PresentationData) { + self.titleNode.attributedText = NSAttributedString(string: title, font: Font.medium(14.0), textColor: isSelected ? presentationData.theme.list.itemAccentColor : presentationData.theme.list.itemSecondaryTextColor) + } + + func updateLayout(height: CGFloat) -> CGFloat { + let titleSize = self.titleNode.updateLayout(CGSize(width: 200.0, height: .greatestFiniteMagnitude)) + self.titleNode.frame = CGRect(origin: CGPoint(x: 0.0, y: floor((height - titleSize.height) / 2.0)), size: titleSize) + return titleSize.width + } + + func updateArea(size: CGSize, sideInset: CGFloat) { + self.buttonNode.frame = CGRect(origin: CGPoint(x: -sideInset, y: 0.0), size: CGSize(width: size.width + sideInset * 2.0, height: size.height)) + } +} + +struct PeerInfoPaneSpecifier: Equatable { + var key: PeerInfoPaneKey + var title: String +} + +final class PeerInfoPaneTabsContainerNode: ASDisplayNode { + private let scrollNode: ASScrollNode + private var paneNodes: [PeerInfoPaneKey: PeerInfoPaneTabsContainerPaneNode] = [:] + private let selectedLineNode: ASImageNode + + private var currentParams: ([PeerInfoPaneSpecifier], PeerInfoPaneKey?, PresentationData)? + + var requestSelectPane: ((PeerInfoPaneKey) -> Void)? + + override init() { + self.scrollNode = ASScrollNode() + + self.selectedLineNode = ASImageNode() + self.selectedLineNode.displaysAsynchronously = false + self.selectedLineNode.displayWithoutProcessing = true + + super.init() + + self.scrollNode.view.disablesInteractiveTransitionGestureRecognizer = true + self.scrollNode.view.showsHorizontalScrollIndicator = false + self.scrollNode.view.scrollsToTop = false + if #available(iOS 11.0, *) { + self.scrollNode.view.contentInsetAdjustmentBehavior = .never + } + + self.addSubnode(self.scrollNode) + self.scrollNode.addSubnode(self.selectedLineNode) + } + + func update(size: CGSize, presentationData: PresentationData, paneList: [PeerInfoPaneSpecifier], selectedPane: PeerInfoPaneKey?, transition: ContainedViewLayoutTransition) { + transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: size)) + + let focusOnSelectedPane = self.currentParams?.1 != selectedPane + + if self.currentParams?.2.theme !== presentationData.theme { + self.selectedLineNode.image = generateImage(CGSize(width: 7.0, height: 4.0), rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + context.setFillColor(presentationData.theme.list.itemAccentColor.cgColor) + context.fillEllipse(in: CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: size.width))) + })?.stretchableImage(withLeftCapWidth: 4, topCapHeight: 1) + } + + if self.currentParams?.0 != paneList || self.currentParams?.1 != selectedPane || self.currentParams?.2 !== presentationData { + self.currentParams = (paneList, selectedPane, presentationData) + for specifier in paneList { + let paneNode: PeerInfoPaneTabsContainerPaneNode + var wasAdded = false + if let current = self.paneNodes[specifier.key] { + paneNode = current + } else { + wasAdded = true + paneNode = PeerInfoPaneTabsContainerPaneNode(pressed: { [weak self] in + self?.paneSelected(specifier.key) + }) + self.paneNodes[specifier.key] = paneNode + self.scrollNode.addSubnode(paneNode) + } + paneNode.updateText(specifier.title, isSelected: selectedPane == specifier.key, presentationData: presentationData) + } + var removeKeys: [PeerInfoPaneKey] = [] + for (key, _) in self.paneNodes { + if !paneList.contains(where: { $0.key == key }) { + removeKeys.append(key) + } + } + for key in removeKeys { + if let paneNode = self.paneNodes.removeValue(forKey: key) { + paneNode.removeFromSupernode() + } + } + } + + var tabSizes: [(CGSize, PeerInfoPaneTabsContainerPaneNode)] = [] + var totalRawTabSize: CGFloat = 0.0 + + var selectedFrame: CGRect? + for specifier in paneList { + guard let paneNode = self.paneNodes[specifier.key] else { + continue + } + let paneNodeWidth = paneNode.updateLayout(height: size.height) + let paneNodeSize = CGSize(width: paneNodeWidth, height: size.height) + tabSizes.append((paneNodeSize, paneNode)) + totalRawTabSize += paneNodeSize.width + } + + let spacing: CGFloat = 32.0 + if tabSizes.count == 1 { + for i in 0 ..< tabSizes.count { + let (paneNodeSize, paneNode) = tabSizes[i] + let leftOffset: CGFloat = 16.0 + + let paneFrame = CGRect(origin: CGPoint(x: leftOffset, y: floor((size.height - paneNodeSize.height) / 2.0)), size: paneNodeSize) + paneNode.frame = paneFrame + let areaSideInset: CGFloat = 16.0 + paneNode.updateArea(size: paneFrame.size, sideInset: areaSideInset) + paneNode.hitTestSlop = UIEdgeInsets(top: 0.0, left: -areaSideInset, bottom: 0.0, right: -areaSideInset) + + if paneList[i].key == selectedPane { + selectedFrame = paneFrame + } + } + self.scrollNode.view.contentSize = CGSize(width: size.width, height: size.height) + } else if totalRawTabSize + CGFloat(tabSizes.count + 1) * spacing <= size.width { + let availableSpace = size.width + let availableSpacing = availableSpace - totalRawTabSize + let perTabSpacing = floor(availableSpacing / CGFloat(tabSizes.count + 1)) + + var leftOffset = perTabSpacing + for i in 0 ..< tabSizes.count { + let (paneNodeSize, paneNode) = tabSizes[i] + + let paneFrame = CGRect(origin: CGPoint(x: leftOffset, y: floor((size.height - paneNodeSize.height) / 2.0)), size: paneNodeSize) + paneNode.frame = paneFrame + let areaSideInset = floor(perTabSpacing / 2.0) + paneNode.updateArea(size: paneFrame.size, sideInset: areaSideInset) + paneNode.hitTestSlop = UIEdgeInsets(top: 0.0, left: -areaSideInset, bottom: 0.0, right: -areaSideInset) + + leftOffset += paneNodeSize.width + perTabSpacing + + if paneList[i].key == selectedPane { + selectedFrame = paneFrame + } + } + self.scrollNode.view.contentSize = CGSize(width: size.width, height: size.height) + } else { + let sideInset: CGFloat = 16.0 + var leftOffset: CGFloat = sideInset + for i in 0 ..< tabSizes.count { + let (paneNodeSize, paneNode) = tabSizes[i] + let paneFrame = CGRect(origin: CGPoint(x: leftOffset, y: floor((size.height - paneNodeSize.height) / 2.0)), size: paneNodeSize) + paneNode.frame = paneFrame + paneNode.updateArea(size: paneFrame.size, sideInset: spacing) + paneNode.hitTestSlop = UIEdgeInsets(top: 0.0, left: -spacing, bottom: 0.0, right: -spacing) + if paneList[i].key == selectedPane { + selectedFrame = paneFrame + } + leftOffset += paneNodeSize.width + spacing + } + self.scrollNode.view.contentSize = CGSize(width: leftOffset + sideInset, height: size.height) + } + + if let selectedFrame = selectedFrame { + self.selectedLineNode.isHidden = false + transition.updateFrame(node: self.selectedLineNode, frame: CGRect(origin: CGPoint(x: selectedFrame.minX, y: size.height - 4.0), size: CGSize(width: selectedFrame.width, height: 4.0))) + if focusOnSelectedPane { + if selectedPane == paneList.first?.key { + transition.updateBounds(node: self.scrollNode, bounds: CGRect(origin: CGPoint(), size: self.scrollNode.bounds.size)) + } else if selectedPane == paneList.last?.key { + transition.updateBounds(node: self.scrollNode, bounds: CGRect(origin: CGPoint(x: self.scrollNode.view.contentSize.width - self.scrollNode.bounds.width, y: 0.0), size: self.scrollNode.bounds.size)) + } else { + let contentOffsetX = max(0.0, min(self.scrollNode.view.contentSize.width - self.scrollNode.bounds.width, floor(selectedFrame.midX - self.scrollNode.bounds.width / 2.0))) + transition.updateBounds(node: self.scrollNode, bounds: CGRect(origin: CGPoint(x: contentOffsetX, y: 0.0), size: self.scrollNode.bounds.size)) + } + } + } else { + self.selectedLineNode.isHidden = true + } + } + + private func paneSelected(_ key: PeerInfoPaneKey) { + self.requestSelectPane?(key) + } +} + +final class PeerInfoPaneContainerNode: ASDisplayNode { + private let context: AccountContext + private let peerId: PeerId + + private let coveringBackgroundNode: ASDisplayNode + private let separatorNode: ASDisplayNode + private let tabsContainerNode: PeerInfoPaneTabsContainerNode + private let tapsSeparatorNode: ASDisplayNode + + let isReady = Promise() + var didSetIsReady = false + + private var currentParams: (size: CGSize, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, expansionFraction: CGFloat, presentationData: PresentationData, data: PeerInfoScreenData?)? + private(set) var currentPaneKey: PeerInfoPaneKey? + private(set) var currentPane: PeerInfoPaneWrapper? + + private var currentCandidatePaneKey: PeerInfoPaneKey? + private var candidatePane: (PeerInfoPaneWrapper, Disposable, Bool)? + + var selectionPanelNode: PeerInfoSelectionPanelNode? + + var chatControllerInteraction: ChatControllerInteraction? + var openPeerContextAction: ((Peer, ASDisplayNode, ContextGesture?) -> Void)? + + var currentPaneUpdated: (() -> Void)? + + private var currentAvailablePanes: [PeerInfoPaneKey]? + + init(context: AccountContext, peerId: PeerId) { + self.context = context + self.peerId = peerId + + self.separatorNode = ASDisplayNode() + self.separatorNode.isLayerBacked = true + + self.coveringBackgroundNode = ASDisplayNode() + self.coveringBackgroundNode.isLayerBacked = true + + self.tabsContainerNode = PeerInfoPaneTabsContainerNode() + + self.tapsSeparatorNode = ASDisplayNode() + self.tapsSeparatorNode.isLayerBacked = true + + super.init() + + self.addSubnode(self.separatorNode) + self.addSubnode(self.coveringBackgroundNode) + self.addSubnode(self.tabsContainerNode) + self.addSubnode(self.tapsSeparatorNode) + + self.tabsContainerNode.requestSelectPane = { [weak self] key in + guard let strongSelf = self else { + return + } + if strongSelf.currentPaneKey == key { + strongSelf.currentPane?.node.scrollToTop() + return + } + if strongSelf.currentCandidatePaneKey == key { + return + } + strongSelf.currentCandidatePaneKey = key + + if let (size, sideInset, bottomInset, visibleHeight, expansionFraction, presentationData, data) = strongSelf.currentParams { + strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: .immediate) + } + } + } + + func scrollToTop() -> Bool { + if let currentPane = self.currentPane { + return currentPane.node.scrollToTop() + } else { + return false + } + } + + func findLoadedMessage(id: MessageId) -> Message? { + return self.currentPane?.node.findLoadedMessage(id: id) + } + + func updateHiddenMedia() { + self.currentPane?.node.updateHiddenMedia() + } + + func transitionNodeForGallery(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + return self.currentPane?.node.transitionNodeForGallery(messageId: messageId, media: media) + } + + func updateSelectedMessageIds(_ selectedMessageIds: Set?, animated: Bool) { + self.currentPane?.node.updateSelectedMessages(animated: animated) + self.candidatePane?.0.node.updateSelectedMessages(animated: animated) + } + + func update(size: CGSize, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, expansionFraction: CGFloat, presentationData: PresentationData, data: PeerInfoScreenData?, transition: ContainedViewLayoutTransition) { + let previousAvailablePanes = self.currentAvailablePanes ?? [] + let availablePanes = data?.availablePanes ?? [] + self.currentAvailablePanes = availablePanes + + if let currentPaneKey = self.currentPaneKey, !availablePanes.contains(currentPaneKey) { + var nextCandidatePaneKey: PeerInfoPaneKey? + if let index = previousAvailablePanes.index(of: currentPaneKey), index != 0 { + for i in (0 ... index - 1).reversed() { + if availablePanes.contains(previousAvailablePanes[i]) { + nextCandidatePaneKey = previousAvailablePanes[i] + } + } + } + if nextCandidatePaneKey == nil { + nextCandidatePaneKey = availablePanes.first + } + + if let nextCandidatePaneKey = nextCandidatePaneKey { + if self.currentCandidatePaneKey != nextCandidatePaneKey { + self.currentCandidatePaneKey = nextCandidatePaneKey + } + } else { + self.currentCandidatePaneKey = nil + if let (_, disposable, _) = self.candidatePane { + disposable.dispose() + self.candidatePane = nil + } + if let currentPane = self.currentPane { + self.currentPane = nil + currentPane.node.removeFromSupernode() + } + } + } else if self.currentPaneKey == nil { + self.currentCandidatePaneKey = availablePanes.first + } + + let previousCurrentPaneKey = self.currentPaneKey + + self.currentParams = (size, sideInset, bottomInset, visibleHeight, expansionFraction, presentationData, data) + + transition.updateAlpha(node: self.coveringBackgroundNode, alpha: expansionFraction) + + self.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor + self.coveringBackgroundNode.backgroundColor = presentationData.theme.rootController.navigationBar.backgroundColor + self.separatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor + self.tapsSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor + + let tabsHeight: CGFloat = 48.0 + + transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: size.width, height: UIScreenPixel))) + transition.updateFrame(node: self.coveringBackgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: size.width, height: tabsHeight + UIScreenPixel))) + + transition.updateFrame(node: self.tapsSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: tabsHeight - UIScreenPixel), size: CGSize(width: size.width, height: UIScreenPixel))) + + let paneFrame = CGRect(origin: CGPoint(x: 0.0, y: tabsHeight), size: CGSize(width: size.width, height: size.height - tabsHeight)) + + if let currentCandidatePaneKey = self.currentCandidatePaneKey { + if self.candidatePane?.0.key != currentCandidatePaneKey { + self.candidatePane?.1.dispose() + + let paneNode: PeerInfoPaneNode + switch currentCandidatePaneKey { + case .media: + paneNode = PeerInfoVisualMediaPaneNode(context: self.context, chatControllerInteraction: self.chatControllerInteraction!, peerId: self.peerId) + case .files: + paneNode = PeerInfoListPaneNode(context: self.context, chatControllerInteraction: self.chatControllerInteraction!, peerId: self.peerId, tagMask: .file) + case .links: + paneNode = PeerInfoListPaneNode(context: self.context, chatControllerInteraction: self.chatControllerInteraction!, peerId: self.peerId, tagMask: .webPage) + case .voice: + paneNode = PeerInfoListPaneNode(context: self.context, chatControllerInteraction: self.chatControllerInteraction!, peerId: self.peerId, tagMask: .voiceOrInstantVideo) + case .music: + paneNode = PeerInfoListPaneNode(context: self.context, chatControllerInteraction: self.chatControllerInteraction!, peerId: self.peerId, tagMask: .music) + case .groupsInCommon: + paneNode = PeerInfoGroupsInCommonPaneNode(context: self.context, peerId: peerId, chatControllerInteraction: self.chatControllerInteraction!, openPeerContextAction: self.openPeerContextAction!, peers: data?.groupsInCommon ?? []) + } + + let disposable = MetaDisposable() + self.candidatePane = (PeerInfoPaneWrapper(key: currentCandidatePaneKey, node: paneNode), disposable, false) + + var shouldReLayout = false + disposable.set((paneNode.isReady + |> take(1) + |> deliverOnMainQueue).start(next: { [weak self] _ in + guard let strongSelf = self else { + return + } + if let (candidatePane, disposable, _) = strongSelf.candidatePane { + strongSelf.candidatePane = (candidatePane, disposable, true) + + if shouldReLayout { + if let (size, sideInset, bottomInset, visibleHeight, expansionFraction, presentationData, data) = strongSelf.currentParams { + strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: strongSelf.currentPane != nil ? .animated(duration: 0.35, curve: .spring) : .immediate) + } + } + } + })) + shouldReLayout = true + } + } + + if let (candidatePane, _, isReady) = self.candidatePane, isReady { + let previousPane = self.currentPane + self.candidatePane = nil + self.currentPaneKey = candidatePane.key + self.currentCandidatePaneKey = nil + self.currentPane = candidatePane + + if let selectionPanelNode = self.selectionPanelNode { + self.insertSubnode(candidatePane.node, belowSubnode: selectionPanelNode) + } else { + self.addSubnode(candidatePane.node) + } + candidatePane.node.frame = paneFrame + candidatePane.update(size: paneFrame.size, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: max(0.0, visibleHeight - paneFrame.minY), isScrollingLockedAtTop: expansionFraction < 1.0 - CGFloat.ulpOfOne, presentationData: presentationData, synchronous: true, transition: .immediate) + + if let previousPane = previousPane { + let directionToRight: Bool + if let previousIndex = availablePanes.index(of: previousPane.key), let updatedIndex = availablePanes.index(of: candidatePane.key) { + directionToRight = previousIndex < updatedIndex + } else { + directionToRight = false + } + + let offset: CGFloat = directionToRight ? previousPane.node.bounds.width : -previousPane.node.bounds.width + + transition.animatePositionAdditive(node: candidatePane.node, offset: CGPoint(x: offset, y: 0.0)) + let previousNode = previousPane.node + transition.updateFrame(node: previousNode, frame: paneFrame.offsetBy(dx: -offset, dy: 0.0), completion: { [weak previousNode] _ in + previousNode?.removeFromSupernode() + }) + } + } else if let currentPane = self.currentPane { + let paneWasAdded = currentPane.node.supernode == nil + if paneWasAdded { + self.addSubnode(currentPane.node) + } + + let paneTransition: ContainedViewLayoutTransition = paneWasAdded ? .immediate : transition + paneTransition.updateFrame(node: currentPane.node, frame: paneFrame) + currentPane.update(size: paneFrame.size, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, isScrollingLockedAtTop: expansionFraction < 1.0 - CGFloat.ulpOfOne, presentationData: presentationData, synchronous: paneWasAdded, transition: paneTransition) + } + + transition.updateFrame(node: self.tabsContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: tabsHeight))) + self.tabsContainerNode.update(size: CGSize(width: size.width, height: tabsHeight), presentationData: presentationData, paneList: availablePanes.map { key in + let title: String + switch key { + case .media: + title = "Media" + case .files: + title = "Files" + case .links: + title = "Links" + case .voice: + title = "Voice Messages" + case .music: + title = "Audio" + case .groupsInCommon: + title = "Groups" + } + return PeerInfoPaneSpecifier(key: key, title: title) + }, selectedPane: self.currentPaneKey, transition: transition) + + if let (candidatePane, _, _) = self.candidatePane { + let paneTransition: ContainedViewLayoutTransition = .immediate + paneTransition.updateFrame(node: candidatePane.node, frame: paneFrame) + candidatePane.update(size: paneFrame.size, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, isScrollingLockedAtTop: expansionFraction < 1.0 - CGFloat.ulpOfOne, presentationData: presentationData, synchronous: true, transition: paneTransition) + } + if !self.didSetIsReady && data != nil { + if let currentPane = self.currentPane { + self.didSetIsReady = true + self.isReady.set(currentPane.node.isReady) + } else if self.candidatePane == nil { + self.didSetIsReady = true + self.isReady.set(.single(true)) + } + } + if let previousCurrentPaneKey = previousCurrentPaneKey, self.currentPaneKey != previousCurrentPaneKey { + self.currentPaneUpdated?() + } + } +} diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoScreen.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoScreen.swift similarity index 51% rename from submodules/TelegramUI/TelegramUI/PeerInfoScreen.swift rename to submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoScreen.swift index 1c4c6b0612..26aa03313d 100644 --- a/submodules/TelegramUI/TelegramUI/PeerInfoScreen.swift +++ b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoScreen.swift @@ -24,1960 +24,10 @@ import TelegramIntents import PeerInfoUI import SearchBarNode import SearchUI - -private enum PeerInfoHeaderButtonKey: Hashable { - case message - case call - case mute - case more - case addMember -} - -private enum PeerInfoHeaderButtonIcon { - case message - case call - case mute - case unmute - case more - case addMember -} - -private final class PeerInfoHeaderButtonNode: HighlightableButtonNode { - let key: PeerInfoHeaderButtonKey - private let action: (PeerInfoHeaderButtonNode) -> Void - let containerNode: ASDisplayNode - private let backgroundNode: ASImageNode - private let textNode: ImmediateTextNode - - private var theme: PresentationTheme? - private var icon: PeerInfoHeaderButtonIcon? - - init(key: PeerInfoHeaderButtonKey, action: @escaping (PeerInfoHeaderButtonNode) -> Void) { - self.key = key - self.action = action - - self.containerNode = ASDisplayNode() - - self.backgroundNode = ASImageNode() - self.backgroundNode.displaysAsynchronously = false - self.backgroundNode.displayWithoutProcessing = true - - self.textNode = ImmediateTextNode() - self.textNode.displaysAsynchronously = false - - super.init() - - self.addSubnode(self.containerNode) - self.containerNode.addSubnode(self.backgroundNode) - self.containerNode.addSubnode(self.textNode) - - self.highligthedChanged = { [weak self] highlighted in - if let strongSelf = self { - if highlighted { - strongSelf.layer.removeAnimation(forKey: "opacity") - strongSelf.alpha = 0.4 - } else { - strongSelf.alpha = 1.0 - strongSelf.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) - } - } - } - - self.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside) - } - - @objc private func buttonPressed() { - self.action(self) - } - - func update(size: CGSize, text: String, icon: PeerInfoHeaderButtonIcon, isExpanded: Bool, presentationData: PresentationData, transition: ContainedViewLayoutTransition) { - if self.theme != presentationData.theme || self.icon != icon { - self.theme = presentationData.theme - self.icon = icon - self.backgroundNode.image = generateImage(CGSize(width: 40.0, height: 40.0), contextGenerator: { size, context in - context.clear(CGRect(origin: CGPoint(), size: size)) - context.setFillColor(presentationData.theme.list.itemAccentColor.cgColor) - context.fillEllipse(in: CGRect(origin: CGPoint(), size: size)) - context.setBlendMode(.normal) - context.setFillColor(presentationData.theme.list.itemCheckColors.foregroundColor.cgColor) - let imageName: String - switch icon { - case .message: - imageName = "Peer Info/ButtonMessage" - case .call: - imageName = "Peer Info/ButtonCall" - case .mute: - imageName = "Peer Info/ButtonMute" - case .unmute: - imageName = "Peer Info/ButtonUnmute" - case .more: - imageName = "Peer Info/ButtonMore" - case .addMember: - imageName = "Peer Info/ButtonAddMember" - } - if let image = UIImage(bundleImageName: imageName) { - let imageRect = CGRect(origin: CGPoint(x: floor((size.width - image.size.width) / 2.0), y: floor((size.height - image.size.height) / 2.0)), size: image.size) - context.clip(to: imageRect, mask: image.cgImage!) - context.fill(imageRect) - } - }) - } - - self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(12.0), textColor: presentationData.theme.list.itemAccentColor) - let titleSize = self.textNode.updateLayout(CGSize(width: 120.0, height: .greatestFiniteMagnitude)) - - transition.updateFrame(node: self.containerNode, frame: CGRect(origin: CGPoint(), size: size)) - transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: size)) - transition.updateFrameAdditiveToCenter(node: self.textNode, frame: CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: size.height + 6.0), size: titleSize)) - transition.updateAlpha(node: self.textNode, alpha: isExpanded ? 0.0 : 1.0) - } -} - -private final class PeerInfoHeaderNavigationTransition { - let sourceNavigationBar: NavigationBar - let sourceTitleView: ChatTitleView - let sourceTitleFrame: CGRect - let sourceSubtitleFrame: CGRect - let fraction: CGFloat - - init(sourceNavigationBar: NavigationBar, sourceTitleView: ChatTitleView, sourceTitleFrame: CGRect, sourceSubtitleFrame: CGRect, fraction: CGFloat) { - self.sourceNavigationBar = sourceNavigationBar - self.sourceTitleView = sourceTitleView - self.sourceTitleFrame = sourceTitleFrame - self.sourceSubtitleFrame = sourceSubtitleFrame - self.fraction = fraction - } -} - -private enum PeerInfoAvatarListItem: Equatable { - case topImage([ImageRepresentationWithReference]) - case image(TelegramMediaImageReference?, [ImageRepresentationWithReference]) - - var id: WrappedMediaResourceId { - switch self { - case let .topImage(representations): - let representation = largestImageRepresentation(representations.map { $0.representation }) ?? representations[representations.count - 1].representation - return WrappedMediaResourceId(representation.resource.id) - case let .image(_, representations): - let representation = largestImageRepresentation(representations.map { $0.representation }) ?? representations[representations.count - 1].representation - return WrappedMediaResourceId(representation.resource.id) - } - } -} - -private final class PeerInfoAvatarListItemNode: ASDisplayNode { - private let imageNode: TransformImageNode - - let isReady = Promise() - private var didSetReady: Bool = false - - init(context: AccountContext, item: PeerInfoAvatarListItem) { - self.imageNode = TransformImageNode() - - super.init() - - self.addSubnode(self.imageNode) - let representations: [ImageRepresentationWithReference] - switch item { - case let .topImage(topRepresentations): - representations = topRepresentations - case let .image(_, imageRepresentations): - representations = imageRepresentations - } - self.imageNode.setSignal(chatAvatarGalleryPhoto(account: context.account, representations: representations, autoFetchFullSize: true), dispatchOnDisplayLink: false) - - self.imageNode.imageUpdated = { [weak self] _ in - guard let strongSelf = self else { - return - } - if !strongSelf.didSetReady { - strongSelf.didSetReady = true - strongSelf.isReady.set(.single(true)) - } - } - } - - func update(size: CGSize, transition: ContainedViewLayoutTransition) { - let imageSize = CGSize(width: min(size.width, size.height), height: min(size.width, size.height)) - let makeLayout = self.imageNode.asyncLayout() - let applyLayout = makeLayout(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets())) - let _ = applyLayout() - transition.updateFrame(node: self.imageNode, frame: CGRect(origin: CGPoint(x: floor((size.width - imageSize.width) / 2.0), y: floor((size.height - imageSize.height) / 2.0)), size: imageSize)) - } -} - -private final class PeerInfoAvatarListContainerNode: ASDisplayNode { - private let context: AccountContext - - let controlsContainerNode: ASDisplayNode - let controlsContainerTransformNode: ASDisplayNode - let shadowNode: ASDisplayNode - - let contentNode: ASDisplayNode - private var items: [PeerInfoAvatarListItem] = [] - private var itemNodes: [WrappedMediaResourceId: PeerInfoAvatarListItemNode] = [:] - private var currentIndex: Int = 0 - private var transitionFraction: CGFloat = 0.0 - - private var validLayout: CGSize? - - private let disposable = MetaDisposable() - private var initializedList = false - - let isReady = Promise() - private var didSetReady = false - - init(context: AccountContext) { - self.context = context - - self.contentNode = ASDisplayNode() - - self.controlsContainerNode = ASDisplayNode() - self.controlsContainerNode.isUserInteractionEnabled = false - - self.controlsContainerTransformNode = ASDisplayNode() - self.controlsContainerTransformNode.isUserInteractionEnabled = false - - self.shadowNode = ASDisplayNode() - //self.shadowNode.backgroundColor = .green - - super.init() - - self.backgroundColor = .black - - self.addSubnode(self.contentNode) - - self.controlsContainerNode.addSubnode(self.shadowNode) - self.controlsContainerTransformNode.addSubnode(self.controlsContainerNode) - self.addSubnode(self.controlsContainerTransformNode) - - self.view.disablesInteractiveTransitionGestureRecognizer = true - self.view.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:)))) - } - - deinit { - self.disposable.dispose() - } - - override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { - return super.hitTest(point, with: event) - } - - @objc private func panGesture(_ recognizer: UIPanGestureRecognizer) { - switch recognizer.state { - case .changed: - let translation = recognizer.translation(in: self.view) - var transitionFraction = translation.x / self.bounds.width - if self.currentIndex <= 0 { - transitionFraction = min(0.0, transitionFraction) - } - if self.currentIndex >= self.items.count - 1 { - transitionFraction = max(0.0, transitionFraction) - } - self.transitionFraction = transitionFraction - if let size = self.validLayout { - self.updateItems(size: size, transition: .animated(duration: 0.3, curve: .spring)) - } - case .cancelled, .ended: - let translation = recognizer.translation(in: self.view) - let velocity = recognizer.velocity(in: self.view) - var directionIsToRight = false - if abs(velocity.x) > 10.0 { - directionIsToRight = velocity.x < 0.0 - } else { - directionIsToRight = translation.x > self.bounds.width / 2.0 - } - var updatedIndex = self.currentIndex - if directionIsToRight { - updatedIndex = min(updatedIndex + 1, self.items.count - 1) - } else { - updatedIndex = max(updatedIndex - 1, 0) - } - self.currentIndex = updatedIndex - self.transitionFraction = 0.0 - if let size = self.validLayout { - self.updateItems(size: size, transition: .animated(duration: 0.3, curve: .spring)) - } - default: - break - } - } - - func update(size: CGSize, peer: Peer?, transition: ContainedViewLayoutTransition) { - self.validLayout = size - if let peer = peer, !self.initializedList { - self.initializedList = true - self.disposable.set((fetchedAvatarGalleryEntries(account: self.context.account, peer: peer) - |> deliverOnMainQueue).start(next: { [weak self] entries in - guard let strongSelf = self else { - return - } - var items: [PeerInfoAvatarListItem] = [] - for entry in entries { - switch entry { - case let .topImage(representations, _): - items.append(.topImage(representations)) - case let .image(reference, representations, _, _, _, _): - items.append(.image(reference, representations)) - } - } - strongSelf.items = items - if let size = strongSelf.validLayout { - strongSelf.updateItems(size: size, transition: .immediate) - } - if items.isEmpty { - if !strongSelf.didSetReady { - strongSelf.didSetReady = true - strongSelf.isReady.set(.single(true)) - } - } - })) - } - self.updateItems(size: size, transition: transition) - } - - private func updateItems(size: CGSize, transition: ContainedViewLayoutTransition) { - var validIds: [WrappedMediaResourceId] = [] - var addedItemNodesForAdditiveTransition: [PeerInfoAvatarListItemNode] = [] - var additiveTransitionOffset: CGFloat = 0.0 - if self.currentIndex >= 0 && self.currentIndex < self.items.count { - for i in max(0, self.currentIndex - 1) ... min(self.currentIndex + 1, self.items.count - 1) { - validIds.append(self.items[i].id) - let itemNode: PeerInfoAvatarListItemNode - var wasAdded = false - if let current = self.itemNodes[self.items[i].id] { - itemNode = current - } else { - wasAdded = true - itemNode = PeerInfoAvatarListItemNode(context: self.context, item: self.items[i]) - self.itemNodes[self.items[i].id] = itemNode - self.contentNode.addSubnode(itemNode) - } - let indexOffset = CGFloat(i - self.currentIndex) - let itemFrame = CGRect(origin: CGPoint(x: indexOffset * size.width + self.transitionFraction * size.width - size.width / 2.0, y: -size.height / 2.0), size: size) - - if wasAdded { - addedItemNodesForAdditiveTransition.append(itemNode) - itemNode.frame = itemFrame - itemNode.update(size: size, transition: .immediate) - } else { - additiveTransitionOffset = itemNode.frame.minX - itemFrame.minX - transition.updateFrame(node: itemNode, frame: itemFrame) - itemNode.update(size: size, transition: transition) - } - } - } - for itemNode in addedItemNodesForAdditiveTransition { - transition.animatePositionAdditive(node: itemNode, offset: CGPoint(x: additiveTransitionOffset, y: 0.0)) - } - var removeIds: [WrappedMediaResourceId] = [] - for (id, _) in self.itemNodes { - if !validIds.contains(id) { - removeIds.append(id) - } - } - for id in removeIds { - if let itemNode = self.itemNodes.removeValue(forKey: id) { - itemNode.removeFromSupernode() - } - } - - if let item = self.items.first, let itemNode = self.itemNodes[item.id] { - if !self.didSetReady { - self.didSetReady = true - self.isReady.set(itemNode.isReady.get()) - } - } - } -} - -private final class PeerInfoAvatarTransformContainerNode: ASDisplayNode { - let context: AccountContext - let avatarNode: AvatarNode - - var tapped: (() -> Void)? - - private var isFirstAvatarLoading = true - - init(context: AccountContext) { - self.context = context - let avatarFont = avatarPlaceholderFont(size: floor(100.0 * 16.0 / 37.0)) - self.avatarNode = AvatarNode(font: avatarFont) - - super.init() - - self.addSubnode(self.avatarNode) - self.avatarNode.frame = CGRect(origin: CGPoint(x: -50.0, y: -50.0), size: CGSize(width: 100.0, height: 100.0)) - - self.avatarNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) - } - - @objc private func tapGesture(_ recognizer: UITapGestureRecognizer) { - if case .ended = recognizer.state { - self.tapped?() - } - } - - func update(peer: Peer?, theme: PresentationTheme) { - if let peer = peer { - self.avatarNode.setPeer(context: self.context, theme: theme, peer: peer, synchronousLoad: self.isFirstAvatarLoading, displayDimensions: CGSize(width: 100.0, height: 100.0)) - self.isFirstAvatarLoading = false - } - } -} - -private final class PeerInfoEditingAvatarNode: ASDisplayNode { - let context: AccountContext - let avatarNode: AvatarNode - - var tapped: (() -> Void)? - - init(context: AccountContext) { - self.context = context - let avatarFont = avatarPlaceholderFont(size: floor(100.0 * 16.0 / 37.0)) - self.avatarNode = AvatarNode(font: avatarFont) - - super.init() - - self.addSubnode(self.avatarNode) - self.avatarNode.frame = CGRect(origin: CGPoint(x: -50.0, y: -50.0), size: CGSize(width: 100.0, height: 100.0)) - - self.avatarNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) - } - - @objc private func tapGesture(_ recognizer: UITapGestureRecognizer) { - if case .ended = recognizer.state { - self.tapped?() - } - } - - func update(peer: Peer?, theme: PresentationTheme) { - if let peer = peer { - self.avatarNode.setPeer(context: self.context, theme: theme, peer: peer, synchronousLoad: false, displayDimensions: CGSize(width: 100.0, height: 100.0)) - } - } -} - -private final class PeerInfoAvatarListNode: ASDisplayNode { - let avatarContainerNode: PeerInfoAvatarTransformContainerNode - let listContainerTransformNode: ASDisplayNode - let listContainerNode: PeerInfoAvatarListContainerNode - - let isReady = Promise() - - init(context: AccountContext, readyWhenGalleryLoads: Bool) { - self.avatarContainerNode = PeerInfoAvatarTransformContainerNode(context: context) - self.listContainerTransformNode = ASDisplayNode() - self.listContainerNode = PeerInfoAvatarListContainerNode(context: context) - self.listContainerNode.clipsToBounds = true - self.listContainerNode.isHidden = true - - super.init() - - self.addSubnode(self.avatarContainerNode) - self.listContainerTransformNode.addSubnode(self.listContainerNode) - self.addSubnode(self.listContainerTransformNode) - - let avatarReady = self.avatarContainerNode.avatarNode.ready - |> mapToSignal { _ -> Signal in - return .complete() - } - |> then(.single(true)) - - let galleryReady = self.listContainerNode.isReady.get() - |> filter { $0 } - |> take(1) - - let combinedSignal: Signal - if readyWhenGalleryLoads { - combinedSignal = combineLatest(queue: .mainQueue(), - avatarReady, - galleryReady - ) - |> map { lhs, rhs in - return lhs && rhs - } - } else { - combinedSignal = avatarReady - } - - self.isReady.set(combinedSignal - |> filter { $0 } - |> take(1)) - } - - func update(size: CGSize, isExpanded: Bool, peer: Peer?, theme: PresentationTheme, transition: ContainedViewLayoutTransition) { - self.avatarContainerNode.update(peer: peer, theme: theme) - } - - override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { - if !self.listContainerNode.isHidden { - if let result = self.listContainerNode.view.hitTest(self.view.convert(point, to: self.listContainerNode.view), with: event) { - return result - } - } else { - if let result = self.avatarContainerNode.avatarNode.view.hitTest(self.view.convert(point, to: self.avatarContainerNode.avatarNode.view), with: event) { - return result - } - } - - return super.hitTest(point, with: event) - } -} - -private final class PeerInfoHeaderNavigationButton: HighlightableButtonNode { - private let regularTextNode: ImmediateTextNode - private let whiteTextNode: ImmediateTextNode - private let iconNode: ASImageNode - - private var key: PeerInfoHeaderNavigationButtonKey? - private var theme: PresentationTheme? - - var isWhite: Bool = false { - didSet { - if self.isWhite != oldValue { - self.regularTextNode.isHidden = self.isWhite - self.whiteTextNode.isHidden = !self.isWhite - } - } - } - - var action: (() -> Void)? - - override init() { - self.regularTextNode = ImmediateTextNode() - self.whiteTextNode = ImmediateTextNode() - self.whiteTextNode.isHidden = true - - self.iconNode = ASImageNode() - self.iconNode.displaysAsynchronously = false - self.iconNode.displayWithoutProcessing = true - - super.init() - - self.addSubnode(self.regularTextNode) - self.addSubnode(self.whiteTextNode) - self.addSubnode(self.iconNode) - - self.addTarget(self, action: #selector(self.pressed), forControlEvents: .touchUpInside) - } - - @objc private func pressed() { - self.action?() - } - - func update(key: PeerInfoHeaderNavigationButtonKey, presentationData: PresentationData) -> CGSize { - let textSize: CGSize - if self.key != key || self.theme !== presentationData.theme { - self.key = key - self.theme = presentationData.theme - - let text: String - var icon: UIImage? - var isBold = false - switch key { - case .edit: - text = presentationData.strings.Common_Edit - case .done, .cancel, .selectionDone: - text = presentationData.strings.Common_Done - isBold = true - case .select: - text = presentationData.strings.Common_Select - case .search: - text = "" - icon = PresentationResourcesRootController.navigationCompactSearchIcon(presentationData.theme) - } - - let font: UIFont = isBold ? Font.semibold(17.0) : Font.regular(17.0) - - self.regularTextNode.attributedText = NSAttributedString(string: text, font: font, textColor: presentationData.theme.rootController.navigationBar.accentTextColor) - self.whiteTextNode.attributedText = NSAttributedString(string: text, font: font, textColor: .white) - self.iconNode.image = icon - - textSize = self.regularTextNode.updateLayout(CGSize(width: 200.0, height: .greatestFiniteMagnitude)) - let _ = self.whiteTextNode.updateLayout(CGSize(width: 200.0, height: .greatestFiniteMagnitude)) - } else { - textSize = self.regularTextNode.bounds.size - } - - let inset: CGFloat = 0.0 - let height: CGFloat = 44.0 - - let textFrame = CGRect(origin: CGPoint(x: inset, y: floor((height - textSize.height) / 2.0)), size: textSize) - self.regularTextNode.frame = textFrame - self.whiteTextNode.frame = textFrame - - if let image = self.iconNode.image { - self.iconNode.frame = CGRect(origin: CGPoint(x: inset, y: floor((height - image.size.height) / 2.0)), size: image.size) - - return CGSize(width: image.size.width + inset * 2.0, height: height) - } else { - return CGSize(width: textSize.width + inset * 2.0, height: height) - } - } -} - -private enum PeerInfoHeaderNavigationButtonKey { - case edit - case done - case cancel - case select - case selectionDone - case search -} - -private struct PeerInfoHeaderNavigationButtonSpec: Equatable { - let key: PeerInfoHeaderNavigationButtonKey - let isForExpandedView: Bool -} - -private final class PeerInfoHeaderNavigationButtonContainerNode: ASDisplayNode { - private var buttonNodes: [PeerInfoHeaderNavigationButtonKey: PeerInfoHeaderNavigationButton] = [:] - - private var currentButtons: [PeerInfoHeaderNavigationButtonSpec] = [] - - var isWhite: Bool = false { - didSet { - if self.isWhite != oldValue { - for (_, buttonNode) in self.buttonNodes { - buttonNode.isWhite = self.isWhite - } - } - } - } - - var performAction: ((PeerInfoHeaderNavigationButtonKey) -> Void)? - - override init() { - super.init() - } - - func update(size: CGSize, presentationData: PresentationData, buttons: [PeerInfoHeaderNavigationButtonSpec], expandFraction: CGFloat, transition: ContainedViewLayoutTransition) { - let maximumExpandOffset: CGFloat = 14.0 - let expandOffset: CGFloat = -expandFraction * maximumExpandOffset - if self.currentButtons != buttons { - self.currentButtons = buttons - - var nextRegularButtonOrigin = size.width - 16.0 - var nextExpandedButtonOrigin = size.width - 16.0 - for spec in buttons.reversed() { - let buttonNode: PeerInfoHeaderNavigationButton - var wasAdded = false - if let current = self.buttonNodes[spec.key] { - buttonNode = current - } else { - wasAdded = true - buttonNode = PeerInfoHeaderNavigationButton() - self.buttonNodes[spec.key] = buttonNode - self.addSubnode(buttonNode) - buttonNode.isWhite = self.isWhite - buttonNode.action = { [weak self] in - self?.performAction?(spec.key) - } - } - let buttonSize = buttonNode.update(key: spec.key, presentationData: presentationData) - var nextButtonOrigin = spec.isForExpandedView ? nextExpandedButtonOrigin : nextRegularButtonOrigin - let buttonFrame = CGRect(origin: CGPoint(x: nextButtonOrigin - buttonSize.width, y: expandOffset + (spec.isForExpandedView ? maximumExpandOffset : 0.0)), size: buttonSize) - nextButtonOrigin -= buttonSize.width + 4.0 - if spec.isForExpandedView { - nextExpandedButtonOrigin = nextButtonOrigin - } else { - nextRegularButtonOrigin = nextButtonOrigin - } - if wasAdded { - buttonNode.frame = buttonFrame - } else { - transition.updateFrameAdditiveToCenter(node: buttonNode, frame: buttonFrame) - } - let alphaFactor: CGFloat = spec.isForExpandedView ? expandFraction : (1.0 - expandFraction) - transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor) - } - var removeKeys: [PeerInfoHeaderNavigationButtonKey] = [] - for (key, _) in self.buttonNodes { - if !buttons.contains(where: { $0.key == key }) { - removeKeys.append(key) - } - } - for key in removeKeys { - if let buttonNode = self.buttonNodes.removeValue(forKey: key) { - buttonNode.removeFromSupernode() - } - } - } else { - var nextRegularButtonOrigin = size.width - 16.0 - var nextExpandedButtonOrigin = size.width - 16.0 - for spec in buttons.reversed() { - if let buttonNode = self.buttonNodes[spec.key] { - let buttonSize = buttonNode.bounds.size - var nextButtonOrigin = spec.isForExpandedView ? nextExpandedButtonOrigin : nextRegularButtonOrigin - let buttonFrame = CGRect(origin: CGPoint(x: nextButtonOrigin - buttonSize.width, y: expandOffset + (spec.isForExpandedView ? maximumExpandOffset : 0.0)), size: buttonSize) - nextButtonOrigin -= buttonSize.width + 4.0 - if spec.isForExpandedView { - nextExpandedButtonOrigin = nextButtonOrigin - } else { - nextRegularButtonOrigin = nextButtonOrigin - } - transition.updateFrameAdditiveToCenter(node: buttonNode, frame: buttonFrame) - let alphaFactor: CGFloat = spec.isForExpandedView ? expandFraction : (1.0 - expandFraction) - transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor) - } - } - } - } -} - -private final class PeerInfoHeaderRegularContentNode: ASDisplayNode { - -} - -private enum PeerInfoHeaderTextFieldNodeKey { - case firstName - case lastName - case title - case description -} - -private protocol PeerInfoHeaderTextFieldNode: ASDisplayNode { - var text: String { get } - - func update(width: CGFloat, safeInset: CGFloat, hasPrevious: Bool, placeholder: String, isEnabled: Bool, presentationData: PresentationData, updateText: String?) -> CGFloat -} - -private final class PeerInfoHeaderSingleLineTextFieldNode: ASDisplayNode, PeerInfoHeaderTextFieldNode { - private let textNode: TextFieldNode - private let topSeparator: ASDisplayNode - - private var theme: PresentationTheme? - - var text: String { - return self.textNode.textField.text ?? "" - } - - override init() { - self.textNode = TextFieldNode() - self.topSeparator = ASDisplayNode() - - super.init() - - self.addSubnode(self.textNode) - self.addSubnode(self.topSeparator) - } - - func update(width: CGFloat, safeInset: CGFloat, hasPrevious: Bool, placeholder: String, isEnabled: Bool, presentationData: PresentationData, updateText: String?) -> CGFloat { - if self.theme !== presentationData.theme { - self.theme = presentationData.theme - self.textNode.textField.textColor = presentationData.theme.list.itemPrimaryTextColor - //self.textNode.textField.keyboardAppearance = presentationData.theme.keyboardAppearance - self.textNode.textField.tintColor = presentationData.theme.list.itemAccentColor - } - - let attributedPlaceholderText = NSAttributedString(string: placeholder, font: Font.regular(17.0), textColor: presentationData.theme.list.itemPlaceholderTextColor) - if self.textNode.textField.attributedPlaceholder == nil || !self.textNode.textField.attributedPlaceholder!.isEqual(to: attributedPlaceholderText) { - self.textNode.textField.attributedPlaceholder = attributedPlaceholderText - self.textNode.textField.accessibilityHint = attributedPlaceholderText.string - } - - if let updateText = updateText { - self.textNode.textField.text = updateText - } - - self.topSeparator.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor - self.topSeparator.frame = CGRect(origin: CGPoint(x: safeInset + (hasPrevious ? 16.0 : 0.0), y: 0.0), size: CGSize(width: width, height: UIScreenPixel)) - - let height: CGFloat = 44.0 - - self.textNode.frame = CGRect(origin: CGPoint(x: safeInset + 16.0, y: floor((height - 40.0) / 2.0)), size: CGSize(width: max(1.0, width - 16.0 * 2.0), height: 40.0)) - - self.textNode.isUserInteractionEnabled = isEnabled - self.textNode.alpha = isEnabled ? 1.0 : 0.6 - - return height - } -} - -/*private final class PeerInfoHeaderMultiLineTextFieldNode: ASDisplayNode, PeerInfoHeaderTextFieldNode { - private let textNode: TextFieldNode - private let topSeparator: ASDisplayNode - - override init() { - self.textNode = TextFieldNode() - self.topSeparator = ASDisplayNode() - - super.init() - } - - func update(width: CGFloat, safeInset: CGFloat) -> CGFloat { - return 44.0 - } -}*/ - -private final class PeerInfoHeaderEditingContentNode: ASDisplayNode { - private let context: AccountContext - let avatarNode: PeerInfoEditingAvatarNode - - var itemNodes: [PeerInfoHeaderTextFieldNodeKey: PeerInfoHeaderTextFieldNode] = [:] - - init(context: AccountContext) { - self.context = context - self.avatarNode = PeerInfoEditingAvatarNode(context: context) - - super.init() - - self.addSubnode(self.avatarNode) - } - - func editingTextForKey(_ key: PeerInfoHeaderTextFieldNodeKey) -> String? { - return self.itemNodes[key]?.text - } - - func update(width: CGFloat, safeInset: CGFloat, statusBarHeight: CGFloat, navigationHeight: CGFloat, peer: Peer?, isContact: Bool, presentationData: PresentationData, transition: ContainedViewLayoutTransition) -> CGFloat { - let avatarSize: CGFloat = 100.0 - let avatarFrame = CGRect(origin: CGPoint(x: floor((width - avatarSize) / 2.0), y: statusBarHeight + 10.0), size: CGSize(width: avatarSize, height: avatarSize)) - transition.updateFrameAdditiveToCenter(node: self.avatarNode, frame: CGRect(origin: avatarFrame.center, size: CGSize())) - - var contentHeight: CGFloat = statusBarHeight + 10.0 + 100.0 + 20.0 - - var fieldKeys: [PeerInfoHeaderTextFieldNodeKey] = [] - if let _ = peer as? TelegramUser { - fieldKeys.append(.firstName) - fieldKeys.append(.lastName) - } - var hasPrevious = false - for key in fieldKeys { - let itemNode: PeerInfoHeaderTextFieldNode - var updateText: String? - if let current = self.itemNodes[key] { - itemNode = current - } else { - switch key { - case .firstName: - updateText = (peer as? TelegramUser)?.firstName ?? "" - case .lastName: - updateText = (peer as? TelegramUser)?.lastName ?? "" - case .title: - updateText = (peer as? TelegramUser)?.debugDisplayTitle ?? "" - case .description: - break - } - itemNode = PeerInfoHeaderSingleLineTextFieldNode() - self.itemNodes[key] = itemNode - self.addSubnode(itemNode) - } - let placeholder: String - var isEnabled = true - switch key { - case .firstName: - placeholder = "First Name" - isEnabled = isContact - case .lastName: - placeholder = "Last Name" - isEnabled = isContact - case .title: - placeholder = "Title" - case .description: - placeholder = "Description" - } - let itemHeight = itemNode.update(width: width, safeInset: safeInset, hasPrevious: hasPrevious, placeholder: placeholder, isEnabled: isEnabled, presentationData: presentationData, updateText: updateText) - transition.updateFrame(node: itemNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: width, height: itemHeight))) - contentHeight += itemHeight - hasPrevious = true - } - var removeKeys: [PeerInfoHeaderTextFieldNodeKey] = [] - for (key, _) in self.itemNodes { - if !fieldKeys.contains(key) { - removeKeys.append(key) - } - } - for key in removeKeys { - if let itemNode = self.itemNodes.removeValue(forKey: key) { - itemNode.removeFromSupernode() - } - } - - return contentHeight - } -} - -private final class PeerInfoHeaderNode: ASDisplayNode { - private var context: AccountContext - private var presentationData: PresentationData? - - private(set) var isAvatarExpanded: Bool - - let avatarListNode: PeerInfoAvatarListNode - - let regularContentNode: PeerInfoHeaderRegularContentNode - let editingContentNode: PeerInfoHeaderEditingContentNode - let titleNodeContainer: ASDisplayNode - let titleNodeRawContainer: ASDisplayNode - let titleNode: ImmediateTextNode - let subtitleNodeContainer: ASDisplayNode - let subtitleNodeRawContainer: ASDisplayNode - let subtitleNode: ImmediateTextNode - private var buttonNodes: [PeerInfoHeaderButtonKey: PeerInfoHeaderButtonNode] = [:] - private let backgroundNode: ASDisplayNode - private let expandedBackgroundNode: ASDisplayNode - let separatorNode: ASDisplayNode - let navigationButtonContainer: PeerInfoHeaderNavigationButtonContainerNode - - var performButtonAction: ((PeerInfoHeaderButtonKey) -> Void)? - var requestAvatarExpansion: (() -> Void)? - - var navigationTransition: PeerInfoHeaderNavigationTransition? - - init(context: AccountContext, avatarInitiallyExpanded: Bool) { - self.context = context - self.isAvatarExpanded = avatarInitiallyExpanded - - self.avatarListNode = PeerInfoAvatarListNode(context: context, readyWhenGalleryLoads: avatarInitiallyExpanded) - - self.titleNodeContainer = ASDisplayNode() - self.titleNodeRawContainer = ASDisplayNode() - self.titleNode = ImmediateTextNode() - self.titleNode.displaysAsynchronously = false - - self.subtitleNodeContainer = ASDisplayNode() - self.subtitleNodeRawContainer = ASDisplayNode() - self.subtitleNode = ImmediateTextNode() - self.subtitleNode.displaysAsynchronously = false - - self.regularContentNode = PeerInfoHeaderRegularContentNode() - self.editingContentNode = PeerInfoHeaderEditingContentNode(context: context) - self.editingContentNode.alpha = 0.0 - - self.navigationButtonContainer = PeerInfoHeaderNavigationButtonContainerNode() - - self.backgroundNode = ASDisplayNode() - self.backgroundNode.isLayerBacked = true - self.expandedBackgroundNode = ASDisplayNode() - self.expandedBackgroundNode.isLayerBacked = true - - self.separatorNode = ASDisplayNode() - self.separatorNode.isLayerBacked = true - - super.init() - - self.addSubnode(self.backgroundNode) - self.addSubnode(self.expandedBackgroundNode) - self.addSubnode(self.separatorNode) - self.titleNodeContainer.addSubnode(self.titleNode) - self.regularContentNode.addSubnode(self.titleNodeContainer) - self.subtitleNodeContainer.addSubnode(self.subtitleNode) - self.regularContentNode.addSubnode(self.subtitleNodeContainer) - self.regularContentNode.addSubnode(self.avatarListNode) - self.addSubnode(self.regularContentNode) - self.addSubnode(self.editingContentNode) - self.addSubnode(self.navigationButtonContainer) - - self.avatarListNode.avatarContainerNode.tapped = { [weak self] in - guard let strongSelf = self else { - return - } - if !strongSelf.isAvatarExpanded { - strongSelf.requestAvatarExpansion?() - } - } - } - - func update(width: CGFloat, containerHeight: CGFloat, containerInset: CGFloat, statusBarHeight: CGFloat, navigationHeight: CGFloat, contentOffset: CGFloat, presentationData: PresentationData, peer: Peer?, cachedData: CachedPeerData?, notificationSettings: TelegramPeerNotificationSettings?, presence: TelegramUserPresence?, isContact: Bool, state: PeerInfoState, transition: ContainedViewLayoutTransition, additive: Bool) -> CGFloat { - self.presentationData = presentationData - - self.regularContentNode.alpha = state.isEditing ? 0.0 : 1.0 - self.editingContentNode.alpha = state.isEditing ? 1.0 : 0.0 - - let editingContentHeight = self.editingContentNode.update(width: width, safeInset: containerInset, statusBarHeight: statusBarHeight, navigationHeight: navigationHeight, peer: state.isEditing ? peer : nil, isContact: isContact, presentationData: presentationData, transition: transition) - transition.updateFrame(node: self.editingContentNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -contentOffset), size: CGSize(width: width, height: editingContentHeight))) - - var transitionSourceHeight: CGFloat = 0.0 - var transitionFraction: CGFloat = 0.0 - var transitionSourceAvatarFrame = CGRect() - var transitionSourceTitleFrame = CGRect() - var transitionSourceSubtitleFrame = CGRect() - - self.backgroundNode.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor - self.expandedBackgroundNode.backgroundColor = presentationData.theme.rootController.navigationBar.backgroundColor - - if let navigationTransition = self.navigationTransition, let sourceAvatarNode = navigationTransition.sourceTitleView.avatarNode?.avatarNode { - transitionSourceHeight = navigationTransition.sourceNavigationBar.bounds.height - transitionFraction = navigationTransition.fraction - transitionSourceAvatarFrame = sourceAvatarNode.view.convert(sourceAvatarNode.view.bounds, to: navigationTransition.sourceNavigationBar.view) - transitionSourceTitleFrame = navigationTransition.sourceTitleFrame - transitionSourceSubtitleFrame = navigationTransition.sourceSubtitleFrame - - //transition.updateBackgroundColor(node: self.backgroundNode, color: presentationData.theme.list.itemBlocksBackgroundColor.interpolateTo(presentationData.theme.rootController.navigationBar.backgroundColor, fraction: transitionFraction)!) - transition.updateAlpha(node: self.expandedBackgroundNode, alpha: transitionFraction) - } else { - let backgroundTransitionFraction: CGFloat = max(0.0, min(1.0, contentOffset / (212.0))) - transition.updateAlpha(node: self.expandedBackgroundNode, alpha: backgroundTransitionFraction) - //transition.updateBackgroundColor(node: self.backgroundNode, color: presentationData.theme.list.itemBlocksBackgroundColor.interpolateTo(presentationData.theme.rootController.navigationBar.backgroundColor, fraction: backgroundTransitionFraction)!) - } - - self.separatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor - - let defaultButtonSize: CGFloat = 40.0 - let defaultMaxButtonSpacing: CGFloat = 40.0 - let expandedAvatarListHeight = min(width, containerHeight - 64.0) - let expandedAvatarListSize = CGSize(width: width, height: expandedAvatarListHeight) - - var buttonKeys: [PeerInfoHeaderButtonKey] = [] - - if let peer = peer { - buttonKeys.append(.message) - buttonKeys.append(.call) - buttonKeys.append(.mute) - buttonKeys.append(.more) - - self.titleNode.attributedText = NSAttributedString(string: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), font: Font.medium(24.0), textColor: presentationData.theme.list.itemPrimaryTextColor) - - let presence = presence ?? TelegramUserPresence(status: .none, lastActivity: 0) - let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 - let (subtitleString, activity) = stringAndActivityForUserPresence(strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, presence: presence, relativeTo: Int32(timestamp), expanded: true) - let subtitleColor: UIColor - if activity { - subtitleColor = presentationData.theme.list.itemAccentColor - } else { - subtitleColor = presentationData.theme.list.itemSecondaryTextColor - } - self.subtitleNode.attributedText = NSAttributedString(string: subtitleString, font: Font.regular(15.0), textColor: subtitleColor) - } - - let textSideInset: CGFloat = 16.0 - let expandedAvatarControlsHeight: CGFloat = 64.0 - let expandedAvatarHeight: CGFloat = expandedAvatarListSize.height + expandedAvatarControlsHeight - - let avatarSize: CGFloat = 100.0 - let avatarFrame = CGRect(origin: CGPoint(x: floor((width - avatarSize) / 2.0), y: statusBarHeight + 10.0), size: CGSize(width: avatarSize, height: avatarSize)) - let avatarCenter = CGPoint(x: (1.0 - transitionFraction) * avatarFrame.midX + transitionFraction * transitionSourceAvatarFrame.midX, y: (1.0 - transitionFraction) * avatarFrame.midY + transitionFraction * transitionSourceAvatarFrame.midY) - - let titleSize = self.titleNode.updateLayout(CGSize(width: width - textSideInset * 2.0, height: .greatestFiniteMagnitude)) - let subtitleSize = self.subtitleNode.updateLayout(CGSize(width: width - textSideInset * 2.0, height: .greatestFiniteMagnitude)) - - let titleFrame: CGRect - let subtitleFrame: CGRect - if self.isAvatarExpanded { - titleFrame = CGRect(origin: CGPoint(x: 16.0, y: expandedAvatarHeight - expandedAvatarControlsHeight + 12.0), size: titleSize) - subtitleFrame = CGRect(origin: CGPoint(x: 16.0, y: titleFrame.maxY - 5.0), size: subtitleSize) - } else { - titleFrame = CGRect(origin: CGPoint(x: floor((width - titleSize.width) / 2.0), y: avatarFrame.maxY + 10.0), size: titleSize) - subtitleFrame = CGRect(origin: CGPoint(x: floor((width - subtitleSize.width) / 2.0), y: titleFrame.maxY + 1.0), size: subtitleSize) - } - - let titleLockOffset: CGFloat = 7.0 - let titleMaxLockOffset: CGFloat = 7.0 - let titleCollapseOffset = titleFrame.midY - statusBarHeight - titleLockOffset - let titleOffset = -min(titleCollapseOffset, contentOffset) - let titleCollapseFraction = max(0.0, min(1.0, contentOffset / titleCollapseOffset)) - - let titleMinScale: CGFloat = 0.7 - let subtitleMinScale: CGFloat = 0.8 - let avatarMinScale: CGFloat = 0.7 - - let apparentTitleLockOffset = (1.0 - titleCollapseFraction) * 0.0 + titleCollapseFraction * titleMaxLockOffset - - let avatarScale: CGFloat - let avatarOffset: CGFloat - if self.navigationTransition != nil { - avatarScale = ((1.0 - transitionFraction) * avatarFrame.width + transitionFraction * transitionSourceAvatarFrame.width) / avatarFrame.width - avatarOffset = 0.0 - } else { - avatarScale = 1.0 * (1.0 - titleCollapseFraction) + avatarMinScale * titleCollapseFraction - avatarOffset = apparentTitleLockOffset + 0.0 * (1.0 - titleCollapseFraction) + 10.0 * titleCollapseFraction - } - let avatarListFrame = CGRect(origin: CGPoint(), size: expandedAvatarListSize) - - if self.isAvatarExpanded { - self.avatarListNode.listContainerNode.isHidden = false - if !transitionSourceAvatarFrame.width.isZero { - transition.updateCornerRadius(node: self.avatarListNode.listContainerNode, cornerRadius: transitionFraction * transitionSourceAvatarFrame.width / 2.0) - } else { - transition.updateCornerRadius(node: self.avatarListNode.listContainerNode, cornerRadius: 0.0) - } - } else if self.avatarListNode.listContainerNode.cornerRadius != 50.0 { - transition.updateCornerRadius(node: self.avatarListNode.listContainerNode, cornerRadius: 50.0, completion: { [weak self] _ in - guard let strongSelf = self else { - return - } - strongSelf.avatarListNode.listContainerNode.isHidden = true - }) - } - - self.avatarListNode.update(size: CGSize(), isExpanded: self.isAvatarExpanded, peer: peer, theme: presentationData.theme, transition: transition) - self.editingContentNode.avatarNode.update(peer: peer, theme: presentationData.theme) - if additive { - transition.updateSublayerTransformScaleAdditive(node: self.avatarListNode.avatarContainerNode, scale: avatarScale) - } else { - transition.updateSublayerTransformScale(node: self.avatarListNode.avatarContainerNode, scale: avatarScale) - } - let apparentAvatarFrame: CGRect - if self.isAvatarExpanded { - let expandedAvatarCenter = CGPoint(x: expandedAvatarListSize.width / 2.0, y: expandedAvatarListSize.height / 2.0 - contentOffset / 2.0) - apparentAvatarFrame = CGRect(origin: CGPoint(x: expandedAvatarCenter.x * (1.0 - transitionFraction) + transitionFraction * avatarCenter.x, y: expandedAvatarCenter.y * (1.0 - transitionFraction) + transitionFraction * avatarCenter.y), size: CGSize()) - } else { - apparentAvatarFrame = CGRect(origin: CGPoint(x: avatarCenter.x - avatarFrame.width / 2.0, y: -contentOffset + avatarOffset + avatarCenter.y - avatarFrame.height / 2.0), size: avatarFrame.size) - } - if case let .animated(duration, curve) = transition, !transitionSourceAvatarFrame.width.isZero, false { - let previousFrame = self.avatarListNode.frame - self.avatarListNode.frame = CGRect(origin: apparentAvatarFrame.center, size: CGSize()) - let horizontalTransition: ContainedViewLayoutTransition - let verticalTransition: ContainedViewLayoutTransition - if transitionFraction < .ulpOfOne { - horizontalTransition = .animated(duration: duration * 0.85, curve: curve) - verticalTransition = .animated(duration: duration * 1.15, curve: curve) - } else { - horizontalTransition = transition - verticalTransition = .animated(duration: duration * 0.6, curve: curve) - } - horizontalTransition.animatePositionAdditive(node: self.avatarListNode, offset: CGPoint(x: previousFrame.midX - apparentAvatarFrame.midX, y: 0.0)) - verticalTransition.animatePositionAdditive(node: self.avatarListNode, offset: CGPoint(x: 0.0, y: previousFrame.midY - apparentAvatarFrame.midY)) - } else { - transition.updateFrameAdditive(node: self.avatarListNode, frame: CGRect(origin: apparentAvatarFrame.center, size: CGSize())) - } - - let avatarListContainerFrame: CGRect - let avatarListContainerScale: CGFloat - if self.isAvatarExpanded { - if !transitionSourceAvatarFrame.width.isZero { - let neutralAvatarListContainerSize = expandedAvatarListSize - let avatarListContainerSize = CGSize(width: neutralAvatarListContainerSize.width * (1.0 - transitionFraction) + transitionSourceAvatarFrame.width * transitionFraction, height: neutralAvatarListContainerSize.height * (1.0 - transitionFraction) + transitionSourceAvatarFrame.height * transitionFraction) - avatarListContainerFrame = CGRect(origin: CGPoint(x: -avatarListContainerSize.width / 2.0, y: -avatarListContainerSize.height / 2.0), size: avatarListContainerSize) - } else { - avatarListContainerFrame = CGRect(origin: CGPoint(x: -expandedAvatarListSize.width / 2.0, y: -expandedAvatarListSize.height / 2.0), size: expandedAvatarListSize) - } - avatarListContainerScale = 1.0 + max(0.0, -contentOffset / avatarListContainerFrame.height) - } else { - avatarListContainerFrame = CGRect(origin: CGPoint(x: -apparentAvatarFrame.width / 2.0, y: -apparentAvatarFrame.height / 2.0), size: apparentAvatarFrame.size) - avatarListContainerScale = avatarScale - } - transition.updateFrame(node: self.avatarListNode.listContainerNode, frame: avatarListContainerFrame) - let innerScale = avatarListContainerFrame.height / expandedAvatarListSize.height - let innerDeltaX = (avatarListContainerFrame.width - expandedAvatarListSize.width) / 2.0 - let innerDeltaY = (avatarListContainerFrame.height - expandedAvatarListSize.height) / 2.0 - transition.updateSublayerTransformScale(node: self.avatarListNode.listContainerNode, scale: innerScale) - transition.updateFrameAdditive(node: self.avatarListNode.listContainerNode.contentNode, frame: CGRect(origin: CGPoint(x: innerDeltaX + expandedAvatarListSize.width / 2.0, y: innerDeltaY + expandedAvatarListSize.height / 2.0), size: CGSize())) - - transition.updateFrameAdditive(node: self.avatarListNode.listContainerNode.controlsContainerTransformNode, frame: CGRect(origin: CGPoint(x: expandedAvatarListSize.width / 2.0, y: expandedAvatarListSize.height / 2.0 - innerDeltaY), size: CGSize())) - transition.updateSublayerTransformScale(node: self.avatarListNode.listContainerNode.controlsContainerNode, scale: 1.0 / innerScale) - transition.updateSublayerTransformScaleAdditive(node: self.avatarListNode.listContainerNode.controlsContainerTransformNode, scale: 1.0 / avatarListContainerScale) - transition.updateFrameAdditive(node: self.avatarListNode.listContainerNode.shadowNode, frame: CGRect(origin: CGPoint(x: -apparentAvatarFrame.minX, y: -apparentAvatarFrame.minY), size: CGSize(width: expandedAvatarListSize.width, height: navigationHeight))) - - if additive { - transition.updateSublayerTransformScaleAdditive(node: self.avatarListNode.listContainerTransformNode, scale: avatarListContainerScale) - } else { - transition.updateSublayerTransformScale(node: self.avatarListNode.listContainerTransformNode, scale: avatarListContainerScale) - } - - self.avatarListNode.listContainerNode.update(size: expandedAvatarListSize, peer: peer, transition: transition) - - let buttonsCollapseStart = titleCollapseOffset - let buttonsCollapseEnd = 212.0 - (navigationHeight - statusBarHeight) + 10.0 - - let buttonsCollapseFraction = max(0.0, contentOffset - buttonsCollapseStart) / (buttonsCollapseEnd - buttonsCollapseStart) - - let rawHeight: CGFloat - let height: CGFloat - if self.isAvatarExpanded { - rawHeight = expandedAvatarHeight - height = max(navigationHeight, rawHeight - contentOffset) - } else { - rawHeight = navigationHeight + 212.0 - height = navigationHeight + max(0.0, 212.0 - contentOffset) - } - - let apparentHeight = (1.0 - transitionFraction) * height + transitionFraction * transitionSourceHeight - - if !titleSize.width.isZero && !titleSize.height.isZero { - if self.navigationTransition != nil { - var neutralTitleScale: CGFloat = 1.0 - var neutralSubtitleScale: CGFloat = 1.0 - if self.isAvatarExpanded { - neutralTitleScale = 0.7 - neutralSubtitleScale = 1.0 - } - - let titleScale = (transitionFraction * transitionSourceTitleFrame.height + (1.0 - transitionFraction) * titleFrame.height * neutralTitleScale) / (titleFrame.height) - let subtitleScale = max(0.01, min(10.0, (transitionFraction * transitionSourceSubtitleFrame.height + (1.0 - transitionFraction) * subtitleFrame.height * neutralSubtitleScale) / (subtitleFrame.height))) - - let titleOrigin = CGPoint(x: transitionFraction * transitionSourceTitleFrame.minX + (1.0 - transitionFraction) * titleFrame.minX, y: transitionFraction * transitionSourceTitleFrame.minY + (1.0 - transitionFraction) * titleFrame.minY) - let subtitleOrigin = CGPoint(x: transitionFraction * transitionSourceSubtitleFrame.minX + (1.0 - transitionFraction) * subtitleFrame.minX, y: transitionFraction * transitionSourceSubtitleFrame.minY + (1.0 - transitionFraction) * subtitleFrame.minY) - - let rawTitleFrame = CGRect(origin: titleOrigin, size: titleFrame.size) - self.titleNodeRawContainer.frame = rawTitleFrame - transition.updateFrameAdditiveToCenter(node: self.titleNodeContainer, frame: rawTitleFrame.offsetBy(dx: rawTitleFrame.width * 0.5 * (titleScale - 1.0), dy: titleOffset + rawTitleFrame.height * 0.5 * (titleScale - 1.0))) - transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(), size: titleFrame.size)) - let rawSubtitleFrame = CGRect(origin: subtitleOrigin, size: subtitleFrame.size) - self.subtitleNodeRawContainer.frame = rawSubtitleFrame - transition.updateFrameAdditiveToCenter(node: self.subtitleNodeContainer, frame: rawSubtitleFrame.offsetBy(dx: rawSubtitleFrame.width * 0.5 * (subtitleScale - 1.0), dy: titleOffset + rawSubtitleFrame.height * 0.5 * (subtitleScale - 1.0))) - transition.updateFrame(node: self.subtitleNode, frame: CGRect(origin: CGPoint(), size: subtitleFrame.size)) - transition.updateSublayerTransformScale(node: self.titleNodeContainer, scale: titleScale) - transition.updateSublayerTransformScale(node: self.subtitleNodeContainer, scale: subtitleScale) - } else { - let titleScale: CGFloat - let subtitleScale: CGFloat - if self.isAvatarExpanded { - titleScale = 0.7 - subtitleScale = 1.0 - } else { - titleScale = (1.0 - titleCollapseFraction) * 1.0 + titleCollapseFraction * titleMinScale - subtitleScale = (1.0 - titleCollapseFraction) * 1.0 + titleCollapseFraction * subtitleMinScale - } - - let rawTitleFrame = titleFrame - self.titleNodeRawContainer.frame = rawTitleFrame - transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(), size: titleFrame.size)) - let rawSubtitleFrame = subtitleFrame - self.subtitleNodeRawContainer.frame = rawSubtitleFrame - if self.isAvatarExpanded { - transition.updateFrameAdditive(node: self.titleNodeContainer, frame: rawTitleFrame.offsetBy(dx: 0.0, dy: titleOffset + apparentTitleLockOffset).offsetBy(dx: rawTitleFrame.width * 0.5 * (titleScale - 1.0), dy: rawTitleFrame.height * 0.5 * (titleScale - 1.0))) - transition.updateFrameAdditive(node: self.subtitleNodeContainer, frame: rawSubtitleFrame.offsetBy(dx: 0.0, dy: titleOffset).offsetBy(dx: rawSubtitleFrame.width * 0.5 * (subtitleScale - 1.0), dy: rawSubtitleFrame.height * 0.5 * (subtitleScale - 1.0))) - } else { - transition.updateFrameAdditiveToCenter(node: self.titleNodeContainer, frame: rawTitleFrame.offsetBy(dx: 0.0, dy: titleOffset + apparentTitleLockOffset)) - transition.updateFrameAdditiveToCenter(node: self.subtitleNodeContainer, frame: rawSubtitleFrame.offsetBy(dx: 0.0, dy: titleOffset)) - } - transition.updateFrame(node: self.subtitleNode, frame: CGRect(origin: CGPoint(), size: subtitleFrame.size)) - transition.updateSublayerTransformScaleAdditive(node: self.titleNodeContainer, scale: titleScale) - transition.updateSublayerTransformScaleAdditive(node: self.subtitleNodeContainer, scale: subtitleScale) - } - } - - let buttonSpacing: CGFloat - if self.isAvatarExpanded { - buttonSpacing = 16.0 - } else { - buttonSpacing = min(defaultMaxButtonSpacing, width - floor(CGFloat(buttonKeys.count) * defaultButtonSize / CGFloat(buttonKeys.count + 1))) - } - - let expandedButtonSize: CGFloat = 32.0 - let buttonsWidth = buttonSpacing * CGFloat(buttonKeys.count - 1) + CGFloat(buttonKeys.count) * defaultButtonSize - var buttonRightOrigin: CGPoint - if self.isAvatarExpanded { - buttonRightOrigin = CGPoint(x: width - 16.0, y: apparentHeight - 74.0) - } else { - buttonRightOrigin = CGPoint(x: floor((width - buttonsWidth) / 2.0) + buttonsWidth, y: apparentHeight - 74.0) - } - let buttonsScale: CGFloat - let buttonsAlpha: CGFloat - let apparentButtonSize: CGFloat - let buttonsVerticalOffset: CGFloat - if self.navigationTransition != nil { - if self.isAvatarExpanded { - apparentButtonSize = expandedButtonSize - } else { - apparentButtonSize = defaultButtonSize - } - let neutralButtonsScale = apparentButtonSize / defaultButtonSize - buttonsScale = (1.0 - transitionFraction) * neutralButtonsScale + 0.2 * transitionFraction - buttonsAlpha = 1.0 - transitionFraction - - let neutralButtonsOffset: CGFloat - if self.isAvatarExpanded { - neutralButtonsOffset = 74.0 - 15.0 - defaultButtonSize + (defaultButtonSize - apparentButtonSize) / 2.0 - } else { - neutralButtonsOffset = (1.0 - buttonsScale) * apparentButtonSize - } - - buttonsVerticalOffset = (1.0 - transitionFraction) * neutralButtonsOffset + ((1.0 - buttonsScale) * apparentButtonSize) * transitionFraction - } else { - apparentButtonSize = self.isAvatarExpanded ? expandedButtonSize : defaultButtonSize - if self.isAvatarExpanded { - buttonsScale = apparentButtonSize / defaultButtonSize - buttonsVerticalOffset = 74.0 - 15.0 - defaultButtonSize + (defaultButtonSize - apparentButtonSize) / 2.0 - } else { - buttonsScale = (1.0 - buttonsCollapseFraction) * 1.0 + 0.2 * buttonsCollapseFraction - buttonsVerticalOffset = (1.0 - buttonsScale) * apparentButtonSize - } - buttonsAlpha = 1.0 - buttonsCollapseFraction - } - let buttonsScaledOffset = (defaultButtonSize - apparentButtonSize) / 2.0 - for buttonKey in buttonKeys.reversed() { - let buttonNode: PeerInfoHeaderButtonNode - var wasAdded = false - if let current = self.buttonNodes[buttonKey] { - buttonNode = current - } else { - wasAdded = true - buttonNode = PeerInfoHeaderButtonNode(key: buttonKey, action: { [weak self] buttonNode in - self?.buttonPressed(buttonNode) - }) - self.buttonNodes[buttonKey] = buttonNode - self.regularContentNode.addSubnode(buttonNode) - } - - let buttonFrame = CGRect(origin: CGPoint(x: buttonRightOrigin.x - defaultButtonSize + buttonsScaledOffset, y: buttonRightOrigin.y), size: CGSize(width: defaultButtonSize, height: defaultButtonSize)) - let buttonTransition: ContainedViewLayoutTransition = wasAdded ? .immediate : transition - - let apparentButtonFrame = buttonFrame.offsetBy(dx: 0.0, dy: buttonsVerticalOffset) - if additive { - buttonTransition.updateFrameAdditiveToCenter(node: buttonNode, frame: apparentButtonFrame) - } else { - buttonTransition.updateFrame(node: buttonNode, frame: apparentButtonFrame) - } - let buttonText: String - let buttonIcon: PeerInfoHeaderButtonIcon - switch buttonKey { - case .message: - buttonText = "Message" - buttonIcon = .message - case .call: - buttonText = "Call" - buttonIcon = .call - case .mute: - if let notificationSettings = notificationSettings, case .muted = notificationSettings.muteState { - buttonText = "Unmute" - buttonIcon = .unmute - } else { - buttonText = "Mute" - buttonIcon = .mute - } - case .more: - buttonText = "More" - buttonIcon = .more - case .addMember: - buttonText = "Add Member" - buttonIcon = .addMember - } - buttonNode.update(size: buttonFrame.size, text: buttonText, icon: buttonIcon, isExpanded: self.isAvatarExpanded, presentationData: presentationData, transition: buttonTransition) - transition.updateSublayerTransformScaleAdditive(node: buttonNode, scale: buttonsScale) - - transition.updateAlpha(node: buttonNode, alpha: buttonsAlpha) - - let hiddenWhileExpanded: Bool - switch buttonKey { - case .more: - hiddenWhileExpanded = false - default: - hiddenWhileExpanded = true - } - - if self.isAvatarExpanded, hiddenWhileExpanded { - if case let .animated(duration, curve) = transition { - ContainedViewLayoutTransition.animated(duration: duration * 0.3, curve: curve).updateAlpha(node: buttonNode.containerNode, alpha: 0.0) - } else { - transition.updateAlpha(node: buttonNode.containerNode, alpha: 0.0) - } - } else { - if case .mute = buttonKey, buttonNode.containerNode.alpha.isZero, additive { - if case let .animated(duration, curve) = transition { - ContainedViewLayoutTransition.animated(duration: duration * 0.3, curve: curve).updateAlpha(node: buttonNode.containerNode, alpha: 1.0) - } else { - transition.updateAlpha(node: buttonNode.containerNode, alpha: 1.0) - } - } else { - transition.updateAlpha(node: buttonNode.containerNode, alpha: 1.0) - } - buttonRightOrigin.x -= apparentButtonSize + buttonSpacing - } - } - - for key in self.buttonNodes.keys { - if !buttonKeys.contains(key) { - if let buttonNode = self.buttonNodes[key] { - self.buttonNodes.removeValue(forKey: key) - buttonNode.removeFromSupernode() - } - } - } - - let resolvedRegularHeight: CGFloat - if self.isAvatarExpanded { - resolvedRegularHeight = expandedAvatarListSize.height + expandedAvatarControlsHeight - } else { - resolvedRegularHeight = 212.0 + navigationHeight - } - - let backgroundFrame: CGRect - let separatorFrame: CGRect - - let resolvedHeight: CGFloat - if state.isEditing { - resolvedHeight = editingContentHeight - backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: -2000.0 + resolvedHeight - contentOffset), size: CGSize(width: width, height: 2000.0)) - separatorFrame = CGRect(origin: CGPoint(x: 0.0, y: resolvedHeight - contentOffset), size: CGSize(width: width, height: UIScreenPixel)) - } else { - resolvedHeight = resolvedRegularHeight - backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: -2000.0 + apparentHeight), size: CGSize(width: width, height: 2000.0)) - separatorFrame = CGRect(origin: CGPoint(x: 0.0, y: apparentHeight), size: CGSize(width: width, height: UIScreenPixel)) - } - - transition.updateFrame(node: self.regularContentNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: resolvedHeight))) - - if additive { - transition.updateFrameAdditive(node: self.backgroundNode, frame: backgroundFrame) - transition.updateFrameAdditive(node: self.expandedBackgroundNode, frame: backgroundFrame) - transition.updateFrameAdditive(node: self.separatorNode, frame: separatorFrame) - } else { - transition.updateFrame(node: self.backgroundNode, frame: backgroundFrame) - transition.updateFrame(node: self.expandedBackgroundNode, frame: backgroundFrame) - transition.updateFrame(node: self.separatorNode, frame: separatorFrame) - } - - return resolvedHeight - } - - private func buttonPressed(_ buttonNode: PeerInfoHeaderButtonNode) { - self.performButtonAction?(buttonNode.key) - } - - override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { - guard let result = super.hitTest(point, with: event) else { - return nil - } - if result.isDescendant(of: self.navigationButtonContainer.view) { - return result - } - if !self.backgroundNode.frame.contains(point) { - return nil - } - if result == self.view || result == self.regularContentNode.view || result == self.editingContentNode.view { - return nil - } - return result - } - - func updateIsAvatarExpanded(_ isAvatarExpanded: Bool) { - self.isAvatarExpanded = isAvatarExpanded - } -} - -protocol PeerInfoPaneNode: ASDisplayNode { - var isReady: Signal { get } - - func update(size: CGSize, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) - func scrollToTop() -> Bool - func transferVelocity(_ velocity: CGFloat) - func findLoadedMessage(id: MessageId) -> Message? - func transitionNodeForGallery(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? - func updateSelectedMessages(animated: Bool) -} - -final class PeerInfoPaneInteraction { - var selectedMessageIds: Set? - - let toggleMessageSelected: (MessageId) -> Void - let openPeer: (Peer) -> Void - - init( - toggleMessageSelected: @escaping (MessageId) -> Void, - openPeer: @escaping (Peer) -> Void - ) { - self.toggleMessageSelected = toggleMessageSelected - self.openPeer = openPeer - } -} - -private final class PeerInfoPaneWrapper { - let key: PeerInfoPaneKey - let node: PeerInfoPaneNode - private var appliedParams: (CGSize, CGFloat, Bool, PresentationData)? - - init(key: PeerInfoPaneKey, node: PeerInfoPaneNode) { - self.key = key - self.node = node - } - - func update(size: CGSize, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) { - if let (currentSize, visibleHeight, currentIsScrollingLockedAtTop, currentPresentationData) = self.appliedParams { - if currentSize == size && currentIsScrollingLockedAtTop == isScrollingLockedAtTop && currentPresentationData === presentationData { - return - } - } - self.appliedParams = (size, visibleHeight, isScrollingLockedAtTop, presentationData) - self.node.update(size: size, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, presentationData: presentationData, synchronous: synchronous, transition: transition) - } -} - -private enum PeerInfoPaneKey { - case media - case files - case links - case voice - case music - case groupsInCommon -} - -private final class PeerInfoPaneTabsContainerPaneNode: ASDisplayNode { - private let pressed: () -> Void - - private let titleNode: ImmediateTextNode - private let buttonNode: HighlightTrackingButtonNode - - init(pressed: @escaping () -> Void) { - self.pressed = pressed - - self.titleNode = ImmediateTextNode() - self.titleNode.displaysAsynchronously = false - - self.buttonNode = HighlightTrackingButtonNode() - - super.init() - - self.addSubnode(self.titleNode) - self.addSubnode(self.buttonNode) - - self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside) - self.buttonNode.highligthedChanged = { [weak self] highlighted in - if let strongSelf = self { - if highlighted { - strongSelf.titleNode.layer.removeAnimation(forKey: "opacity") - strongSelf.titleNode.alpha = 0.4 - } else { - strongSelf.titleNode.alpha = 1.0 - strongSelf.titleNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) - } - } - } - } - - @objc private func buttonPressed() { - self.pressed() - } - - func updateText(_ title: String, isSelected: Bool, presentationData: PresentationData) { - self.titleNode.attributedText = NSAttributedString(string: title, font: Font.medium(14.0), textColor: isSelected ? presentationData.theme.list.itemAccentColor : presentationData.theme.list.itemSecondaryTextColor) - } - - func updateLayout(height: CGFloat) -> CGFloat { - let titleSize = self.titleNode.updateLayout(CGSize(width: 200.0, height: .greatestFiniteMagnitude)) - self.titleNode.frame = CGRect(origin: CGPoint(x: 0.0, y: floor((height - titleSize.height) / 2.0)), size: titleSize) - return titleSize.width - } - - func updateArea(size: CGSize, sideInset: CGFloat) { - self.buttonNode.frame = CGRect(origin: CGPoint(x: -sideInset, y: 0.0), size: CGSize(width: size.width + sideInset * 2.0, height: size.height)) - } -} - -private struct PeerInfoPaneSpecifier: Equatable { - var key: PeerInfoPaneKey - var title: String -} - -private final class PeerInfoPaneTabsContainerNode: ASDisplayNode { - private let scrollNode: ASScrollNode - private var paneNodes: [PeerInfoPaneKey: PeerInfoPaneTabsContainerPaneNode] = [:] - private let selectedLineNode: ASImageNode - - private var currentParams: ([PeerInfoPaneSpecifier], PeerInfoPaneKey?, PresentationData)? - - var requestSelectPane: ((PeerInfoPaneKey) -> Void)? - - override init() { - self.scrollNode = ASScrollNode() - - self.selectedLineNode = ASImageNode() - self.selectedLineNode.displaysAsynchronously = false - self.selectedLineNode.displayWithoutProcessing = true - - super.init() - - self.scrollNode.view.disablesInteractiveTransitionGestureRecognizer = true - self.scrollNode.view.showsHorizontalScrollIndicator = false - self.scrollNode.view.scrollsToTop = false - if #available(iOS 11.0, *) { - self.scrollNode.view.contentInsetAdjustmentBehavior = .never - } - - self.addSubnode(self.scrollNode) - self.scrollNode.addSubnode(self.selectedLineNode) - } - - func update(size: CGSize, presentationData: PresentationData, paneList: [PeerInfoPaneSpecifier], selectedPane: PeerInfoPaneKey?, transition: ContainedViewLayoutTransition) { - transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: size)) - - let focusOnSelectedPane = self.currentParams?.1 != selectedPane - - if self.currentParams?.2.theme !== presentationData.theme { - self.selectedLineNode.image = generateImage(CGSize(width: 7.0, height: 4.0), rotatedContext: { size, context in - context.clear(CGRect(origin: CGPoint(), size: size)) - context.setFillColor(presentationData.theme.list.itemAccentColor.cgColor) - context.fillEllipse(in: CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: size.width))) - })?.stretchableImage(withLeftCapWidth: 4, topCapHeight: 1) - } - - if self.currentParams?.0 != paneList || self.currentParams?.1 != selectedPane || self.currentParams?.2 !== presentationData { - self.currentParams = (paneList, selectedPane, presentationData) - for specifier in paneList { - let paneNode: PeerInfoPaneTabsContainerPaneNode - var wasAdded = false - if let current = self.paneNodes[specifier.key] { - paneNode = current - } else { - wasAdded = true - paneNode = PeerInfoPaneTabsContainerPaneNode(pressed: { [weak self] in - self?.paneSelected(specifier.key) - }) - self.paneNodes[specifier.key] = paneNode - self.scrollNode.addSubnode(paneNode) - } - paneNode.updateText(specifier.title, isSelected: selectedPane == specifier.key, presentationData: presentationData) - } - var removeKeys: [PeerInfoPaneKey] = [] - for (key, _) in self.paneNodes { - if !paneList.contains(where: { $0.key == key }) { - removeKeys.append(key) - } - } - for key in removeKeys { - if let paneNode = self.paneNodes.removeValue(forKey: key) { - paneNode.removeFromSupernode() - } - } - } - - var tabSizes: [(CGSize, PeerInfoPaneTabsContainerPaneNode)] = [] - var totalRawTabSize: CGFloat = 0.0 - - var selectedFrame: CGRect? - for specifier in paneList { - guard let paneNode = self.paneNodes[specifier.key] else { - continue - } - let paneNodeWidth = paneNode.updateLayout(height: size.height) - let paneNodeSize = CGSize(width: paneNodeWidth, height: size.height) - tabSizes.append((paneNodeSize, paneNode)) - totalRawTabSize += paneNodeSize.width - } - - let spacing: CGFloat = 32.0 - if totalRawTabSize + CGFloat(tabSizes.count + 1) * spacing <= size.width { - let singleTabSpace = floor((size.width - spacing * 2.0) / CGFloat(tabSizes.count)) - - for i in 0 ..< tabSizes.count { - let (paneNodeSize, paneNode) = tabSizes[i] - let leftOffset = spacing + CGFloat(i) * singleTabSpace + floor((singleTabSpace - paneNodeSize.width) / 2.0) - - let paneFrame = CGRect(origin: CGPoint(x: leftOffset, y: floor((size.height - paneNodeSize.height) / 2.0)), size: paneNodeSize) - paneNode.frame = paneFrame - let areaSideInset = floor((singleTabSpace - paneFrame.size.width) / 2.0) - paneNode.updateArea(size: paneFrame.size, sideInset: areaSideInset) - paneNode.hitTestSlop = UIEdgeInsets(top: 0.0, left: -areaSideInset, bottom: 0.0, right: -areaSideInset) - - if paneList[i].key == selectedPane { - selectedFrame = paneFrame - } - } - self.scrollNode.view.contentSize = CGSize(width: size.width, height: size.height) - } else { - let sideInset: CGFloat = 16.0 - var leftOffset: CGFloat = sideInset - for i in 0 ..< tabSizes.count { - let (paneNodeSize, paneNode) = tabSizes[i] - let paneFrame = CGRect(origin: CGPoint(x: leftOffset, y: floor((size.height - paneNodeSize.height) / 2.0)), size: paneNodeSize) - paneNode.frame = paneFrame - paneNode.updateArea(size: paneFrame.size, sideInset: spacing) - paneNode.hitTestSlop = UIEdgeInsets(top: 0.0, left: -spacing, bottom: 0.0, right: -spacing) - if paneList[i].key == selectedPane { - selectedFrame = paneFrame - } - leftOffset += paneNodeSize.width + spacing - } - self.scrollNode.view.contentSize = CGSize(width: leftOffset + sideInset, height: size.height) - } - - if let selectedFrame = selectedFrame { - self.selectedLineNode.isHidden = false - transition.updateFrame(node: self.selectedLineNode, frame: CGRect(origin: CGPoint(x: selectedFrame.minX, y: size.height - 4.0), size: CGSize(width: selectedFrame.width, height: 4.0))) - if focusOnSelectedPane { - if selectedPane == paneList.first?.key { - transition.updateBounds(node: self.scrollNode, bounds: CGRect(origin: CGPoint(), size: self.scrollNode.bounds.size)) - } else if selectedPane == paneList.last?.key { - transition.updateBounds(node: self.scrollNode, bounds: CGRect(origin: CGPoint(x: self.scrollNode.view.contentSize.width - self.scrollNode.bounds.width, y: 0.0), size: self.scrollNode.bounds.size)) - } else { - let contentOffsetX = max(0.0, min(self.scrollNode.view.contentSize.width - self.scrollNode.bounds.width, floor(selectedFrame.midX - self.scrollNode.bounds.width / 2.0))) - transition.updateBounds(node: self.scrollNode, bounds: CGRect(origin: CGPoint(x: contentOffsetX, y: 0.0), size: self.scrollNode.bounds.size)) - } - } - } else { - self.selectedLineNode.isHidden = true - } - } - - private func paneSelected(_ key: PeerInfoPaneKey) { - self.requestSelectPane?(key) - } -} - -private final class PeerInfoPaneContainerNode: ASDisplayNode { - private let context: AccountContext - private let peerId: PeerId - - private let coveringBackgroundNode: ASDisplayNode - private let separatorNode: ASDisplayNode - private let tabsContainerNode: PeerInfoPaneTabsContainerNode - private let tapsSeparatorNode: ASDisplayNode - - let isReady = Promise() - var didSetIsReady = false - - private var currentParams: (size: CGSize, visibleHeight: CGFloat, expansionFraction: CGFloat, presentationData: PresentationData, data: PeerInfoScreenData?)? - private(set) var currentPaneKey: PeerInfoPaneKey? - private(set) var currentPane: PeerInfoPaneWrapper? - - private var currentCandidatePaneKey: PeerInfoPaneKey? - private var candidatePane: (PeerInfoPaneWrapper, Disposable, Bool)? - - var selectionPanelNode: PeerInfoSelectionPanelNode? - - var _paneInteraction: PeerInfoPaneInteraction? - var paneInteraction: PeerInfoPaneInteraction { - return self._paneInteraction! - } - - var openMessage: ((MessageId) -> Bool)? - var toggleMessageSelected: ((MessageId) -> Void)? - var openPeer: ((Peer) -> Void)? - var currentPaneUpdated: (() -> Void)? - - init(context: AccountContext, peerId: PeerId) { - self.context = context - self.peerId = peerId - - self.separatorNode = ASDisplayNode() - self.separatorNode.isLayerBacked = true - - self.coveringBackgroundNode = ASDisplayNode() - self.coveringBackgroundNode.isLayerBacked = true - - self.tabsContainerNode = PeerInfoPaneTabsContainerNode() - - self.tapsSeparatorNode = ASDisplayNode() - self.tapsSeparatorNode.isLayerBacked = true - - super.init() - - self._paneInteraction = PeerInfoPaneInteraction( - toggleMessageSelected: { [weak self] id in - guard let strongSelf = self else { - return - } - strongSelf.toggleMessageSelected?(id) - }, - openPeer: { [weak self] peer in - guard let strongSelf = self else { - return - } - strongSelf.openPeer?(peer) - } - ) - - self.addSubnode(self.separatorNode) - self.addSubnode(self.coveringBackgroundNode) - self.addSubnode(self.tabsContainerNode) - self.addSubnode(self.tapsSeparatorNode) - - self.tabsContainerNode.requestSelectPane = { [weak self] key in - guard let strongSelf = self else { - return - } - if strongSelf.currentPaneKey == key { - return - } - if strongSelf.currentCandidatePaneKey == key { - return - } - strongSelf.currentCandidatePaneKey = key - - if let (size, visibleHeight, expansionFraction, presentationData, data) = strongSelf.currentParams { - strongSelf.update(size: size, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: .immediate) - } - } - } - - func scrollToTop() -> Bool { - if let currentPane = self.currentPane { - return currentPane.node.scrollToTop() - } else { - return false - } - } - - func findLoadedMessage(id: MessageId) -> Message? { - return self.currentPane?.node.findLoadedMessage(id: id) - } - - func transitionNodeForGallery(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { - return self.currentPane?.node.transitionNodeForGallery(messageId: messageId, media: media) - } - - func updateSelectedMessageIds(_ selectedMessageIds: Set?, animated: Bool) { - if self.paneInteraction.selectedMessageIds != selectedMessageIds { - self.paneInteraction.selectedMessageIds = selectedMessageIds - self.currentPane?.node.updateSelectedMessages(animated: animated) - self.candidatePane?.0.node.updateSelectedMessages(animated: animated) - } - } - - func update(size: CGSize, visibleHeight: CGFloat, expansionFraction: CGFloat, presentationData: PresentationData, data: PeerInfoScreenData?, transition: ContainedViewLayoutTransition) { - let availablePanes = data?.availablePanes ?? [] - - let previousCurrentPaneKey = self.currentPaneKey - if availablePanes.isEmpty { - self.currentPaneKey = nil - self.currentCandidatePaneKey = nil - if let (_, disposable, _) = self.candidatePane { - disposable.dispose() - self.candidatePane = nil - } - if let currentPane = self.currentPane { - self.currentPane = nil - currentPane.node.removeFromSupernode() - } - } else if (self.currentParams?.data?.availablePanes ?? []).isEmpty { - self.currentCandidatePaneKey = availablePanes.first - } - - self.currentParams = (size, visibleHeight, expansionFraction, presentationData, data) - - transition.updateAlpha(node: self.coveringBackgroundNode, alpha: expansionFraction) - - self.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor - self.coveringBackgroundNode.backgroundColor = presentationData.theme.rootController.navigationBar.backgroundColor - self.separatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor - self.tapsSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor - - let tabsHeight: CGFloat = 48.0 - - transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: size.width, height: UIScreenPixel))) - transition.updateFrame(node: self.coveringBackgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: size.width, height: tabsHeight + UIScreenPixel))) - - transition.updateFrame(node: self.tapsSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: tabsHeight - UIScreenPixel), size: CGSize(width: size.width, height: UIScreenPixel))) - - let paneFrame = CGRect(origin: CGPoint(x: 0.0, y: tabsHeight), size: CGSize(width: size.width, height: size.height - tabsHeight)) - - if let currentCandidatePaneKey = self.currentCandidatePaneKey { - if self.candidatePane?.0.key != currentCandidatePaneKey { - self.candidatePane?.1.dispose() - - let paneNode: PeerInfoPaneNode - switch currentCandidatePaneKey { - case .media: - paneNode = PeerInfoVisualMediaPaneNode(context: self.context, openMessage: { [weak self] id in - return self?.openMessage?(id) ?? false - }, peerId: self.peerId, interaction: self.paneInteraction) - case .files: - paneNode = PeerInfoListPaneNode(context: self.context, openMessage: { [weak self] id in - return self?.openMessage?(id) ?? false - }, peerId: self.peerId, tagMask: .file, interaction: self.paneInteraction) - case .links: - paneNode = PeerInfoListPaneNode(context: self.context, openMessage: { [weak self] id in - return self?.openMessage?(id) ?? false - }, peerId: self.peerId, tagMask: .webPage, interaction: self.paneInteraction) - case .voice: - paneNode = PeerInfoListPaneNode(context: self.context, openMessage: { [weak self] id in - return self?.openMessage?(id) ?? false - }, peerId: self.peerId, tagMask: .voiceOrInstantVideo, interaction: self.paneInteraction) - case .music: - paneNode = PeerInfoListPaneNode(context: self.context, openMessage: { [weak self] id in - return self?.openMessage?(id) ?? false - }, peerId: self.peerId, tagMask: .music, interaction: self.paneInteraction) - case .groupsInCommon: - paneNode = PeerInfoGroupsInCommonPaneNode(context: self.context, peerId: peerId, interaction: self.paneInteraction, peers: data?.groupsInCommon ?? []) - } - - let disposable = MetaDisposable() - self.candidatePane = (PeerInfoPaneWrapper(key: currentCandidatePaneKey, node: paneNode), disposable, false) - - var shouldReLayout = false - disposable.set((paneNode.isReady - |> take(1) - |> deliverOnMainQueue).start(next: { [weak self] _ in - guard let strongSelf = self else { - return - } - if let (candidatePane, disposable, _) = strongSelf.candidatePane { - strongSelf.candidatePane = (candidatePane, disposable, true) - - if shouldReLayout { - if let (size, visibleHeight, expansionFraction, presentationData, data) = strongSelf.currentParams { - strongSelf.update(size: size, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: strongSelf.currentPane != nil ? .animated(duration: 0.35, curve: .spring) : .immediate) - } - } - } - })) - shouldReLayout = true - } - } - - if let (candidatePane, _, isReady) = self.candidatePane, isReady { - let previousPane = self.currentPane - self.candidatePane = nil - self.currentPaneKey = candidatePane.key - self.currentCandidatePaneKey = nil - self.currentPane = candidatePane - - if let selectionPanelNode = self.selectionPanelNode { - self.insertSubnode(candidatePane.node, belowSubnode: selectionPanelNode) - } else { - self.addSubnode(candidatePane.node) - } - candidatePane.node.frame = paneFrame - candidatePane.update(size: paneFrame.size, visibleHeight: max(0.0, visibleHeight - paneFrame.minY), isScrollingLockedAtTop: expansionFraction < 1.0 - CGFloat.ulpOfOne, presentationData: presentationData, synchronous: true, transition: .immediate) - - if let previousPane = previousPane { - let directionToRight: Bool - if let previousIndex = availablePanes.index(of: previousPane.key), let updatedIndex = availablePanes.index(of: candidatePane.key) { - directionToRight = previousIndex < updatedIndex - } else { - directionToRight = false - } - - let offset: CGFloat = directionToRight ? previousPane.node.bounds.width : -previousPane.node.bounds.width - - transition.animatePositionAdditive(node: candidatePane.node, offset: CGPoint(x: offset, y: 0.0)) - let previousNode = previousPane.node - transition.updateFrame(node: previousNode, frame: paneFrame.offsetBy(dx: -offset, dy: 0.0), completion: { [weak previousNode] _ in - previousNode?.removeFromSupernode() - }) - } - } else if let currentPane = self.currentPane { - let paneWasAdded = currentPane.node.supernode == nil - if paneWasAdded { - self.addSubnode(currentPane.node) - } - - let paneTransition: ContainedViewLayoutTransition = paneWasAdded ? .immediate : transition - paneTransition.updateFrame(node: currentPane.node, frame: paneFrame) - currentPane.update(size: paneFrame.size, visibleHeight: visibleHeight, isScrollingLockedAtTop: expansionFraction < 1.0 - CGFloat.ulpOfOne, presentationData: presentationData, synchronous: paneWasAdded, transition: paneTransition) - } - - transition.updateFrame(node: self.tabsContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: tabsHeight))) - self.tabsContainerNode.update(size: CGSize(width: size.width, height: tabsHeight), presentationData: presentationData, paneList: availablePanes.map { key in - let title: String - switch key { - case .media: - title = "Media" - case .files: - title = "Files" - case .links: - title = "Links" - case .voice: - title = "Voice Messages" - case .music: - title = "Audio" - case .groupsInCommon: - title = "Groups" - } - return PeerInfoPaneSpecifier(key: key, title: title) - }, selectedPane: self.currentPaneKey, transition: transition) - - if let (candidatePane, _, _) = self.candidatePane { - let paneTransition: ContainedViewLayoutTransition = .immediate - paneTransition.updateFrame(node: candidatePane.node, frame: paneFrame) - candidatePane.update(size: paneFrame.size, visibleHeight: visibleHeight, isScrollingLockedAtTop: expansionFraction < 1.0 - CGFloat.ulpOfOne, presentationData: presentationData, synchronous: true, transition: paneTransition) - } - if !self.didSetIsReady && data != nil { - if let currentPane = self.currentPane { - self.didSetIsReady = true - self.isReady.set(currentPane.node.isReady) - } else if self.candidatePane == nil { - self.didSetIsReady = true - self.isReady.set(.single(true)) - } - } - if let previousCurrentPaneKey = previousCurrentPaneKey, self.currentPaneKey != previousCurrentPaneKey { - self.currentPaneUpdated?() - } - } -} +import ContextUI +import OpenInExternalAppUI +import SafariServices +import GalleryUI protocol PeerInfoScreenItem: class { var id: AnyHashable { get } @@ -2090,7 +140,7 @@ private final class PeerInfoScreenItemSectionContainerNode: ASDisplayNode { } } -private final class PeerInfoSelectionPanelNode: ASDisplayNode { +final class PeerInfoSelectionPanelNode: ASDisplayNode { private let context: AccountContext private let peerId: PeerId @@ -2197,7 +247,7 @@ private final class PeerInfoSelectionPanelNode: ASDisplayNode { }, displaySearchResultsTooltip: { _, _ in }, statuses: nil) - selectionPanel.interfaceInteraction = interfaceInteraction + self.selectionPanel.interfaceInteraction = interfaceInteraction super.init() @@ -2206,192 +256,28 @@ private final class PeerInfoSelectionPanelNode: ASDisplayNode { self.addSubnode(self.selectionPanel) } - func update(width: CGFloat, safeInset: CGFloat, metrics: LayoutMetrics, presentationData: PresentationData, transition: ContainedViewLayoutTransition) -> CGFloat { + func update(layout: ContainerViewLayout, presentationData: PresentationData, transition: ContainedViewLayoutTransition) -> CGFloat { self.backgroundNode.backgroundColor = presentationData.theme.rootController.navigationBar.backgroundColor self.separatorNode.backgroundColor = presentationData.theme.rootController.navigationBar.separatorColor let interfaceState = ChatPresentationInterfaceState(chatWallpaper: .color(0), theme: presentationData.theme, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, limitsConfiguration: .defaultValue, fontSize: .regular, bubbleCorners: PresentationChatBubbleCorners(mainRadius: 16.0, auxiliaryRadius: 8.0, mergeBubbleCorners: true), accountPeerId: self.context.account.peerId, mode: .standard(previewing: false), chatLocation: .peer(self.peerId), isScheduledMessages: false) - let panelHeight = self.selectionPanel.updateLayout(width: width, leftInset: safeInset, rightInset: safeInset, maxHeight: 0.0, isSecondary: false, transition: transition, interfaceState: interfaceState, metrics: metrics) + let panelHeight = self.selectionPanel.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, maxHeight: 0.0, isSecondary: false, transition: transition, interfaceState: interfaceState, metrics: layout.metrics) - transition.updateFrame(node: self.selectionPanel, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: panelHeight))) - transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: panelHeight))) - transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: width, height: UIScreenPixel))) + transition.updateFrame(node: self.selectionPanel, frame: CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: panelHeight))) - return panelHeight + let panelHeightWithInset = panelHeight + layout.intrinsicInsets.bottom + + transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: panelHeightWithInset))) + transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: layout.size.width, height: UIScreenPixel))) + + return panelHeightWithInset } } -private final class PeerInfoState { - let isEditing: Bool - let isSearching: Bool - let selectedMessageIds: Set? - - init( - isEditing: Bool, - isSearching: Bool, - selectedMessageIds: Set? - ) { - self.isEditing = isEditing - self.isSearching = isSearching - self.selectedMessageIds = selectedMessageIds - } - - func withIsEditing(_ isEditing: Bool) -> PeerInfoState { - return PeerInfoState( - isEditing: isEditing, - isSearching: self.isSearching, - selectedMessageIds: self.selectedMessageIds - ) - } - - func withSelectedMessageIds(_ selectedMessageIds: Set?) -> PeerInfoState { - return PeerInfoState( - isEditing: self.isEditing, - isSearching: self.isSearching, - selectedMessageIds: selectedMessageIds - ) - } -} - -private final class PeerInfoScreenData { - let peer: Peer? - let cachedData: CachedPeerData? - let presence: TelegramUserPresence? - let notificationSettings: TelegramPeerNotificationSettings? - let globalNotificationSettings: GlobalNotificationSettings? - let isContact: Bool - let availablePanes: [PeerInfoPaneKey] - let groupsInCommon: [Peer]? - - init( - peer: Peer?, - cachedData: CachedPeerData?, - presence: TelegramUserPresence?, - notificationSettings: TelegramPeerNotificationSettings?, - globalNotificationSettings: GlobalNotificationSettings?, - isContact: Bool, - availablePanes: [PeerInfoPaneKey], - groupsInCommon: [Peer]? - ) { - self.peer = peer - self.cachedData = cachedData - self.presence = presence - self.notificationSettings = notificationSettings - self.globalNotificationSettings = globalNotificationSettings - self.isContact = isContact - self.availablePanes = availablePanes - self.groupsInCommon = groupsInCommon - } -} - -private enum PeerInfoScreenInputData: Equatable { - case none - case user -} - -private func peerInfoAvailableMediaPanes(context: AccountContext, peerId: PeerId) -> Signal<[PeerInfoPaneKey], NoError> { - let tags: [(MessageTags, PeerInfoPaneKey)] = [ - (.photoOrVideo, .media), - (.file, .files), - (.music, .music), - (.voiceOrInstantVideo, .voice), - (.webPage, .links) - ] - return combineLatest(tags.map { tagAndKey -> Signal in - let (tag, key) = tagAndKey - return context.account.viewTracker.aroundMessageHistoryViewForLocation(.peer(peerId), index: .upperBound, anchorIndex: .upperBound, count: 2, clipHoles: false, fixedCombinedReadStates: nil, tagMask: tag) - |> map { (view, _, _) -> PeerInfoPaneKey? in - if view.entries.isEmpty { - return nil - } else { - return key - } - } - }) - |> map { keys -> [PeerInfoPaneKey] in - return keys.compactMap { $0 } - } - |> distinctUntilChanged - /*return context.account.postbox.combinedView(keys: tags.map { (tag, _) -> PostboxViewKey in - return .historyTagInfo(peerId: peerId, tag: tag) - }) - |> map { view -> [PeerInfoPaneKey] in - return tags.compactMap { (tag, key) -> PeerInfoPaneKey? in - if let info = view.views[.historyTagInfo(peerId: peerId, tag: tag)] as? HistoryTagInfoView, !info.isEmpty { - return key - } else { - return nil - } - } - } - |> distinctUntilChanged*/ -} - -private func peerInfoScreenData(context: AccountContext, peerId: PeerId) -> Signal { - return context.account.postbox.combinedView(keys: [.basicPeer(peerId)]) - |> map { view -> PeerInfoScreenInputData in - guard let peer = (view.views[.basicPeer(peerId)] as? BasicPeerView)?.peer else { - return .none - } - if let _ = peer as? TelegramUser { - return .user - } else { - preconditionFailure() - } - } - |> distinctUntilChanged - |> mapToSignal { inputData -> Signal in - switch inputData { - case .none: - return .single(PeerInfoScreenData( - peer: nil, - cachedData: nil, - presence: nil, - notificationSettings: nil, - globalNotificationSettings: nil, - isContact: false, - availablePanes: [], - groupsInCommon: nil - )) - case .user: - let groupsInCommonSignal: Signal<[Peer]?, NoError> = .single(nil) - |> then( - groupsInCommon(account: context.account, peerId: peerId) - |> map(Optional.init) - ) - let globalNotificationsKey: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.globalNotifications])) - return combineLatest( - context.account.viewTracker.peerView(peerId, updateData: true), - peerInfoAvailableMediaPanes(context: context, peerId: peerId), - context.account.postbox.combinedView(keys: [.peerChatState(peerId: peerId), globalNotificationsKey]), - groupsInCommonSignal - ) - |> map { peerView, availablePanes, combinedView, groupsInCommon -> PeerInfoScreenData in - var globalNotificationSettings: GlobalNotificationSettings = .defaultSettings - if let preferencesView = combinedView.views[globalNotificationsKey] as? PreferencesView { - if let settings = preferencesView.values[PreferencesKeys.globalNotifications] as? GlobalNotificationSettings { - globalNotificationSettings = settings - } - } - - var availablePanes = availablePanes - if let groupsInCommon = groupsInCommon, !groupsInCommon.isEmpty { - availablePanes.append(.groupsInCommon) - } - - return PeerInfoScreenData( - peer: peerView.peers[peerId], - cachedData: peerView.cachedData, - presence: peerView.peerPresences[peerId] as? TelegramUserPresence, - notificationSettings: peerView.notificationSettings as? TelegramPeerNotificationSettings, - globalNotificationSettings: globalNotificationSettings, - isContact: peerView.peerIsContact, - availablePanes: availablePanes, - groupsInCommon: groupsInCommon - ) - } - } - } +private enum PeerInfoBotCommand { + case settings + case help + case privacy } private final class PeerInfoInteraction { @@ -2403,6 +289,10 @@ private final class PeerInfoInteraction { let requestDeleteContact: () -> Void let openAddContact: () -> Void let updateBlocked: (Bool) -> Void + let openReport: () -> Void + let openShareBot: () -> Void + let openAddBotToGroup: () -> Void + let performBotCommand: (PeerInfoBotCommand) -> Void init( openUsername: @escaping (String) -> Void, @@ -2412,7 +302,11 @@ private final class PeerInfoInteraction { editingToggleShowMessageText: @escaping (Bool) -> Void, requestDeleteContact: @escaping () -> Void, openAddContact: @escaping () -> Void, - updateBlocked: @escaping (Bool) -> Void + updateBlocked: @escaping (Bool) -> Void, + openReport: @escaping () -> Void, + openShareBot: @escaping () -> Void, + openAddBotToGroup: @escaping () -> Void, + performBotCommand: @escaping (PeerInfoBotCommand) -> Void ) { self.openUsername = openUsername self.openPhone = openPhone @@ -2422,6 +316,10 @@ private final class PeerInfoInteraction { self.requestDeleteContact = requestDeleteContact self.openAddContact = openAddContact self.updateBlocked = updateBlocked + self.openReport = openReport + self.openShareBot = openShareBot + self.openAddBotToGroup = openAddBotToGroup + self.performBotCommand = performBotCommand } } @@ -2447,23 +345,57 @@ private func peerInfoSectionItems(data: PeerInfoScreenData?, presentationData: P } } if !data.isContact { - items.append(PeerInfoScreenActionItem(id: 3, text: "Add Contact", action: { - interaction.openAddContact() - })) + if let botInfo = user.botInfo { + if botInfo.flags.contains(.worksWithGroups) { + items.append(PeerInfoScreenActionItem(id: 6, text: presentationData.strings.UserInfo_InviteBotToGroup, action: { + interaction.openAddBotToGroup() + })) + } + items.append(PeerInfoScreenActionItem(id: 7, text: presentationData.strings.UserInfo_ShareBot, action: { + interaction.openShareBot() + })) + + if let cachedData = data.cachedData as? CachedUserData, let botInfo = cachedData.botInfo { + for command in botInfo.commands { + if command.text == "settings" { + items.append(PeerInfoScreenActionItem(id: 8, text: presentationData.strings.UserInfo_BotSettings, action: { + interaction.performBotCommand(.settings) + })) + } else if command.text == "help" { + items.append(PeerInfoScreenActionItem(id: 9, text: presentationData.strings.UserInfo_BotHelp, action: { + interaction.performBotCommand(.help) + })) + } else if command.text == "privacy" { + items.append(PeerInfoScreenActionItem(id: 10, text: presentationData.strings.UserInfo_BotPrivacy, action: { + interaction.performBotCommand(.privacy) + })) + } + } + } + } else { + items.append(PeerInfoScreenActionItem(id: 3, text: "Add Contact", action: { + interaction.openAddContact() + })) + } if let cachedData = data.cachedData as? CachedUserData { if cachedData.isBlocked { - items.append(PeerInfoScreenActionItem(id: 4, text: "Unblock", action: { + items.append(PeerInfoScreenActionItem(id: 4, text: user.botInfo != nil ? "Restart Bot" : "Unblock", action: { interaction.updateBlocked(false) })) } else { if user.flags.contains(.isSupport) { } else { - items.append(PeerInfoScreenActionItem(id: 4, text: "Block User", color: .destructive, action: { + items.append(PeerInfoScreenActionItem(id: 4, text: user.botInfo != nil ? "Stop Bot" : "Block User", color: .destructive, action: { interaction.updateBlocked(true) })) } } } + if user.botInfo != nil, !user.isVerified { + items.append(PeerInfoScreenActionItem(id: 5, text: presentationData.strings.ReportPeer_Report, action: { + interaction.openReport() + })) + } } } return items @@ -2547,6 +479,8 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD private var chatInterfaceInteraction: ChatControllerInteraction { return self._chatInterfaceInteraction! } + private var hiddenMediaDisposable: Disposable? + private let hiddenAvatarRepresentationDisposable = MetaDisposable() private(set) var validLayout: (ContainerViewLayout, CGFloat)? private(set) var data: PeerInfoScreenData? @@ -2558,6 +492,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD private var dataDisposable: Disposable? private let activeActionDisposable = MetaDisposable() + private let resolveUrlDisposable = MetaDisposable() private let _ready = Promise() var ready: Promise { @@ -2605,56 +540,33 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD }, updateBlocked: { [weak self] block in self?.updateBlocked(block: block) + }, + openReport: { [weak self] in + self?.openReport() + }, + openShareBot: { [weak self] in + self?.openShareBot() + }, + openAddBotToGroup: { [weak self] in + self?.openAddBotToGroup() + }, + performBotCommand: { [weak self] command in + self?.performBotCommand(command: command) } ) - self._chatInterfaceInteraction = ChatControllerInteraction(openMessage: { message, mode in - /*if let strongSelf = self, strongSelf.isNodeLoaded, let galleryMessage = strongSelf.mediaCollectionDisplayNode.messageForGallery(message.id) { - guard let navigationController = strongSelf.navigationController as? NavigationController else { - return false - } - strongSelf.mediaCollectionDisplayNode.view.endEditing(true) - return context.sharedContext.openChatMessage(OpenChatMessageParams(context: context, message: galleryMessage.message, standalone: false, reverseMessageGalleryOrder: true, navigationController: navigationController, dismissInput: { - self?.mediaCollectionDisplayNode.view.endEditing(true) - }, present: { c, a in - self?.present(c, in: .window(.root), with: a, blockInteraction: true) - }, transitionNode: { messageId, media in - if let strongSelf = self { - return strongSelf.mediaCollectionDisplayNode.transitionNodeForGallery(messageId: messageId, media: media) - } - return nil - }, addToTransitionSurface: { view in - if let strongSelf = self { - var belowSubview: UIView? - if let historyNode = strongSelf.mediaCollectionDisplayNode.historyNode as? ChatHistoryGridNode { - if let lowestSectionNode = historyNode.lowestSectionNode() { - belowSubview = lowestSectionNode.view - } - } - strongSelf.mediaCollectionDisplayNode.historyNode - if let belowSubview = belowSubview { - strongSelf.mediaCollectionDisplayNode.historyNode.view.insertSubview(view, belowSubview: belowSubview) - } else { - strongSelf.mediaCollectionDisplayNode.historyNode.view.addSubview(view) - } - } - }, openUrl: { url in - self?.openUrl(url) - }, openPeer: { peer, navigation in - self?.controllerInteraction?.openPeer(peer.id, navigation, nil) - }, callPeer: { peerId in - self?.controllerInteraction?.callPeer(peerId) - }, enqueueMessage: { _ in - }, sendSticker: nil, setupTemporaryHiddenMedia: { _, _, _ in }, chatAvatarHiddenMedia: { _, _ in })) - }*/ - return false - }, openPeer: { id, navigation, _ in - /*if let strongSelf = self, let id = id, let navigationController = strongSelf.navigationController as? NavigationController { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id))) - }*/ + self._chatInterfaceInteraction = ChatControllerInteraction(openMessage: { [weak self] message, mode in + guard let strongSelf = self else { + return false + } + return strongSelf.openMessage(id: message.id) + }, openPeer: { [weak self] id, navigation, _ in + if let id = id { + self?.openPeer(peerId: id, navigation: navigation) + } }, openPeerMention: { _ in - }, openMessageContextMenu: { message, _, _, _, _ in - /*guard let strongSelf = self else { + }, openMessageContextMenu: { [weak self] message, _, _, _, _ in + guard let strongSelf = self else { return } let items = (chatAvailableMessageActionsImpl(postbox: strongSelf.context.account.postbox, accountPeerId: strongSelf.context.account.peerId, messageIds: [message.id]) @@ -2662,28 +574,28 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD var messageIds = Set() messageIds.insert(message.id) - if let strongSelf = self, strongSelf.isNodeLoaded { - if let message = strongSelf.mediaCollectionDisplayNode.messageForGallery(message.id)?.message { + if let strongSelf = self { + if let message = strongSelf.paneContainerNode.findLoadedMessage(id: message.id) { let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData) var items: [ActionSheetButtonItem] = [] items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.SharedMedia_ViewInChat, color: .accent, action: { [weak actionSheet] in actionSheet?.dismissAnimated() - if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController { + if let strongSelf = self, let navigationController = strongSelf.controller?.navigationController as? NavigationController { strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(strongSelf.peerId), subject: .message(message.id))) } })) items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_ContextMenuForward, color: .accent, action: { [weak actionSheet] in actionSheet?.dismissAnimated() if let strongSelf = self { - strongSelf.forwardMessages(messageIds) + strongSelf.forwardMessages(messageIds: messageIds) } })) if actions.options.contains(.deleteLocally) || actions.options.contains(.deleteGlobally) { items.append( ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_ContextMenuDelete, color: .destructive, action: { [weak actionSheet] in actionSheet?.dismissAnimated() if let strongSelf = self { - strongSelf.deleteMessages(messageIds) + strongSelf.deleteMessages(messageIds: Set(messageIds)) } })) } @@ -2692,18 +604,18 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD actionSheet?.dismissAnimated() }) ])]) - strongSelf.mediaCollectionDisplayNode.view.endEditing(true) - strongSelf.present(actionSheet, in: .window(.root)) + strongSelf.view.endEditing(true) + strongSelf.controller?.present(actionSheet, in: .window(.root)) } } - })*/ - }, openMessageContextActions: { message, node, rect, gesture in - /*guard let strongSelf = self else { + }) + }, openMessageContextActions: { [weak self] message, node, rect, gesture in + guard let strongSelf = self else { gesture?.cancel() return } - let _ = (chatMediaListPreviewControllerData(context: strongSelf.context, message: message, standalone: false, reverseMessageGalleryOrder: false, navigationController: strongSelf.navigationController as? NavigationController) + let _ = (chatMediaListPreviewControllerData(context: strongSelf.context, message: message, standalone: false, reverseMessageGalleryOrder: false, navigationController: strongSelf.controller?.navigationController as? NavigationController) |> deliverOnMainQueue).start(next: { previewData in guard let strongSelf = self else { gesture?.cancel() @@ -2718,7 +630,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD items.append(.action(ContextMenuActionItem(text: strings.SharedMedia_ViewInChat, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/GoToMessage"), color: theme.contextMenu.primaryColor) }, action: { c, f in c.dismiss(completion: { - if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController { + if let strongSelf = self, let navigationController = strongSelf.controller?.navigationController as? NavigationController { strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(strongSelf.peerId), subject: .message(message.id))) } }) @@ -2727,7 +639,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD items.append(.action(ContextMenuActionItem(text: strings.Conversation_ContextMenuForward, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.contextMenu.primaryColor) }, action: { c, f in c.dismiss(completion: { if let strongSelf = self { - strongSelf.forwardMessages([message.id]) + strongSelf.forwardMessages(messageIds: [message.id]) } }) }))) @@ -2759,7 +671,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD items.append(.action(ContextMenuActionItem(text: globalTitle, textColor: .destructive, icon: { _ in nil }, action: { c, f in c.dismiss(completion: { if let strongSelf = self { - strongSelf.updateInterfaceState(animated: true, { $0.withoutSelectionState() }) + strongSelf.headerNode.navigationButtonContainer.performAction?(.selectionDone) let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: .forEveryone).start() } }) @@ -2778,7 +690,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD items.append(.action(ContextMenuActionItem(text: localOptionText, textColor: .destructive, icon: { _ in nil }, action: { c, f in c.dismiss(completion: { if let strongSelf = self { - strongSelf.updateInterfaceState(animated: true, { $0.withoutSelectionState() }) + strongSelf.headerNode.navigationButtonContainer.performAction?(.selectionDone) let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: .forLocalPeer).start() } }) @@ -2798,30 +710,35 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD case let .gallery(gallery): gallery.setHintWillBePresentedInPreviewingContext(true) let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: gallery, sourceNode: node)), items: items, reactionItems: [], gesture: gesture) - strongSelf.presentInGlobalOverlay(contextController) + strongSelf.controller?.presentInGlobalOverlay(contextController) case .instantPage: break } } - })*/ + }) }, navigateToMessage: { fromId, id in - /*if let strongSelf = self, strongSelf.isNodeLoaded { - if id.peerId == strongSelf.peerId { - var fromIndex: MessageIndex? - - if let message = strongSelf.mediaCollectionDisplayNode.historyNode.messageInCurrentHistoryView(fromId) { - fromIndex = message.index - } - } else { - (strongSelf.navigationController as? NavigationController)?.pushViewController(ChatControllerImpl(context: strongSelf.context, chatLocation: .peer(id.peerId), subject: .message(id))) - } - }*/ }, tapMessage: nil, clickThroughMessage: { - //self?.view.endEditing(true) - }, toggleMessagesSelection: { ids, value in - /*if let strongSelf = self, strongSelf.isNodeLoaded { - strongSelf.updateInterfaceState(animated: true, { $0.withToggledSelectedMessages(ids, value: value) }) - }*/ + }, toggleMessagesSelection: { [weak self] ids, value in + guard let strongSelf = self else { + return + } + if var selectedMessageIds = strongSelf.state.selectedMessageIds { + for id in ids { + if value { + selectedMessageIds.insert(id) + } else { + selectedMessageIds.remove(id) + } + } + strongSelf.state = strongSelf.state.withSelectedMessageIds(selectedMessageIds) + } else { + strongSelf.state = strongSelf.state.withSelectedMessageIds(value ? Set(ids) : Set()) + } + strongSelf.chatInterfaceInteraction.selectionState = strongSelf.state.selectedMessageIds.flatMap { ChatInterfaceSelectionState(selectedIds: $0) } + if let (layout, navigationHeight) = strongSelf.validLayout { + strongSelf.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .animated(duration: 0.4, curve: .spring), additive: false) + } + strongSelf.paneContainerNode.updateSelectedMessageIds(strongSelf.state.selectedMessageIds, animated: true) }, sendCurrentMessage: { _ in }, sendMessage: { _ in }, sendSticker: { _, _, _, _ in @@ -2831,21 +748,37 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD }, requestMessageActionCallback: { _, _, _ in }, requestMessageActionUrlAuth: { _, _, _ in }, activateSwitchInline: { _, _ in - }, openUrl: { url, _, external, _ in - //self?.openUrl(url, external: external ?? false) + }, openUrl: { [weak self] url, _, external, _ in + guard let strongSelf = self else { + return + } + strongSelf.openUrl(url: url, external: external ?? false) }, shareCurrentLocation: { }, shareAccountContact: { }, sendBotCommand: { _, _ in - }, openInstantPage: { message, associatedData in - /*if let strongSelf = self, strongSelf.isNodeLoaded, let navigationController = strongSelf.navigationController as? NavigationController, let message = strongSelf.mediaCollectionDisplayNode.messageForGallery(message.id)?.message { - openChatInstantPage(context: strongSelf.context, message: message, sourcePeerType: associatedData?.automaticDownloadPeerType, navigationController: navigationController) - }*/ - }, openWallpaper: { message in - /*if let strongSelf = self, strongSelf.isNodeLoaded, let message = strongSelf.mediaCollectionDisplayNode.messageForGallery(message.id)?.message { - openChatWallpaper(context: strongSelf.context, message: message, present: { [weak self] c, a in - self?.present(c, in: .window(.root), with: a, blockInteraction: true) - }) - }*/ + }, openInstantPage: { [weak self] message, associatedData in + guard let strongSelf = self, let navigationController = strongSelf.controller?.navigationController as? NavigationController else { + return + } + var foundGalleryMessage: Message? + if let searchContentNode = strongSelf.searchDisplayController?.contentNode as? ChatHistorySearchContainerNode { + if let galleryMessage = searchContentNode.messageForGallery(message.id) { + let _ = (strongSelf.context.account.postbox.transaction { transaction -> Void in + if transaction.getMessage(galleryMessage.id) == nil { + storeMessageFromSearch(transaction: transaction, message: galleryMessage) + } + }).start() + foundGalleryMessage = galleryMessage + } + } + if foundGalleryMessage == nil, let galleryMessage = strongSelf.paneContainerNode.findLoadedMessage(id: message.id) { + foundGalleryMessage = galleryMessage + } + + if let foundGalleryMessage = foundGalleryMessage { + openChatInstantPage(context: strongSelf.context, message: foundGalleryMessage, sourcePeerType: associatedData?.automaticDownloadPeerType, navigationController: navigationController) + } + }, openWallpaper: { _ in }, openTheme: { _ in }, openHashtag: { _, _ in }, updateInputState: { _ in @@ -2859,55 +792,55 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD }, reactionContainerNode: { return nil }, presentGlobalOverlayController: { _, _ in }, callPeer: { _ in - }, longTap: { content, _ in - /*if let strongSelf = self { - strongSelf.view.endEditing(true) - switch content { - case let .url(url): - let canOpenIn = availableOpenInOptions(context: strongSelf.context, item: .url(url: url)).count > 1 - let openText = canOpenIn ? strongSelf.presentationData.strings.Conversation_FileOpenIn : strongSelf.presentationData.strings.Conversation_LinkDialogOpen - let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData) - actionSheet.setItemGroups([ActionSheetItemGroup(items: [ - ActionSheetTextItem(title: url), - ActionSheetButtonItem(title: openText, color: .accent, action: { [weak actionSheet] in - actionSheet?.dismissAnimated() - if let strongSelf = self { - if canOpenIn { - let actionSheet = OpenInActionSheetController(context: strongSelf.context, item: .url(url: url), openUrl: { [weak self] url in - if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController { - strongSelf.context.sharedContext.openExternalUrl(context: strongSelf.context, urlContext: .generic, url: url, forceExternal: true, presentationData: strongSelf.presentationData, navigationController: navigationController, dismissInput: { - }) - } + }, longTap: { [weak self] content, _ in + guard let strongSelf = self else { + return + } + strongSelf.view.endEditing(true) + switch content { + case let .url(url): + let canOpenIn = availableOpenInOptions(context: strongSelf.context, item: .url(url: url)).count > 1 + let openText = canOpenIn ? strongSelf.presentationData.strings.Conversation_FileOpenIn : strongSelf.presentationData.strings.Conversation_LinkDialogOpen + let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData) + actionSheet.setItemGroups([ActionSheetItemGroup(items: [ + ActionSheetTextItem(title: url), + ActionSheetButtonItem(title: openText, color: .accent, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + if let strongSelf = self { + if canOpenIn { + let actionSheet = OpenInActionSheetController(context: strongSelf.context, item: .url(url: url), openUrl: { [weak self] url in + if let strongSelf = self, let navigationController = strongSelf.controller?.navigationController as? NavigationController { + strongSelf.context.sharedContext.openExternalUrl(context: strongSelf.context, urlContext: .generic, url: url, forceExternal: true, presentationData: strongSelf.presentationData, navigationController: navigationController, dismissInput: { }) - strongSelf.present(actionSheet, in: .window(.root)) - } else { - strongSelf.context.sharedContext.applicationBindings.openUrl(url) } - } - }), - ActionSheetButtonItem(title: strongSelf.presentationData.strings.ShareMenu_CopyShareLink, color: .accent, action: { [weak actionSheet] in - actionSheet?.dismissAnimated() - UIPasteboard.general.string = url - }), - ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_AddToReadingList, color: .accent, action: { [weak actionSheet] in - actionSheet?.dismissAnimated() - if let link = URL(string: url) { - let _ = try? SSReadingList.default()?.addItem(with: link, title: nil, previewText: nil) - } - }) - ]), ActionSheetItemGroup(items: [ - ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in - actionSheet?.dismissAnimated() - }) - ])]) - strongSelf.present(actionSheet, in: .window(.root)) - default: - break - } - }*/ + }) + strongSelf.controller?.present(actionSheet, in: .window(.root)) + } else { + strongSelf.context.sharedContext.applicationBindings.openUrl(url) + } + } + }), + ActionSheetButtonItem(title: strongSelf.presentationData.strings.ShareMenu_CopyShareLink, color: .accent, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + UIPasteboard.general.string = url + }), + ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_AddToReadingList, color: .accent, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + if let link = URL(string: url) { + let _ = try? SSReadingList.default()?.addItem(with: link, title: nil, previewText: nil) + } + }) + ]), ActionSheetItemGroup(items: [ + ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + }) + ])]) + strongSelf.controller?.present(actionSheet, in: .window(.root)) + default: + break + } }, openCheckoutOrReceipt: { _ in }, openSearch: { - //self?.activateSearch() }, setupReply: { _ in }, canSetupReply: { _ in return false @@ -2934,6 +867,19 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD }, cancelInteractiveKeyboardGestures: { }, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: false)) + self.hiddenMediaDisposable = context.sharedContext.mediaManager.galleryHiddenMediaManager.hiddenIds().start(next: { [weak self] ids in + guard let strongSelf = self else { + return + } + var hiddenMedia: [MessageId: [Media]] = [:] + for id in ids { + if case let .chat(accountId, messageId, media) = id, accountId == strongSelf.context.account.id { + hiddenMedia[messageId] = [media] + } + } + strongSelf.chatInterfaceInteraction.hiddenMedia = hiddenMedia + strongSelf.paneContainerNode.updateHiddenMedia() + }) self.backgroundColor = self.presentationData.theme.list.blocksBackgroundColor @@ -2951,35 +897,22 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD self.scrollNode.addSubnode(self.paneContainerNode) self.addSubnode(self.headerNode) - self.paneContainerNode.openMessage = { [weak self] id in - return self?.openMessage(id: id) ?? false - } - - self.paneContainerNode.toggleMessageSelected = { [weak self] id in - guard let strongSelf = self else { + self.paneContainerNode.chatControllerInteraction = self.chatInterfaceInteraction + self.paneContainerNode.openPeerContextAction = { [weak self] peer, node, gesture in + guard let strongSelf = self, let controller = strongSelf.controller else { return } - if var selectedMessageIds = strongSelf.state.selectedMessageIds { - if selectedMessageIds.contains(id) { - selectedMessageIds.remove(id) - } else { - selectedMessageIds.insert(id) - } - strongSelf.state = strongSelf.state.withSelectedMessageIds(selectedMessageIds) - strongSelf.paneContainerNode.updateSelectedMessageIds(strongSelf.state.selectedMessageIds, animated: true) - if let (layout, navigationHeight) = strongSelf.validLayout { - strongSelf.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .animated(duration: 0.4, curve: .spring), additive: false) - } - } - } - - self.paneContainerNode.openPeer = { [weak self] peer in - guard let strongSelf = self else { - return - } - if let navigationController = strongSelf.controller?.navigationController as? NavigationController { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), keepStack: .always)) - } + let presentationData = strongSelf.presentationData + let chatController = strongSelf.context.sharedContext.makeChatController(context: context, chatLocation: .peer(peer.id), subject: nil, botStart: nil, mode: .standard(previewing: true)) + chatController.canReadHistory.set(false) + let items: [ContextMenuItem] = [ + .action(ContextMenuActionItem(text: presentationData.strings.Conversation_LinkDialogOpen, icon: { _ in nil }, action: { _, f in + f(.dismissWithoutContent) + self?.chatInterfaceInteraction.openPeer(peer.id, .default, nil) + })) + ] + let contextController = ContextController(account: strongSelf.context.account, presentationData: presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node)), items: .single(items), reactionItems: [], gesture: gesture) + controller.presentInGlobalOverlay(contextController) } self.paneContainerNode.currentPaneUpdated = { [weak self] in @@ -2996,19 +929,25 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD self?.performButtonAction(key: key) } - self.headerNode.requestAvatarExpansion = { [weak self] in + self.headerNode.requestAvatarExpansion = { [weak self] entries, transitionNode in guard let strongSelf = self, let peer = strongSelf.data?.peer, peer.smallProfileImage != nil else { return } - let transition: ContainedViewLayoutTransition = .animated(duration: 0.35, curve: .spring) - - strongSelf.headerNode.updateIsAvatarExpanded(true) - strongSelf.updateNavigationExpansionPresentation(isExpanded: true, animated: true) - - if let (layout, navigationHeight) = strongSelf.validLayout { - strongSelf.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: transition, additive: true) - } + let entriesPromise = Promise<[AvatarGalleryEntry]>(entries) + let galleryController = AvatarGalleryController(context: strongSelf.context, peer: peer, remoteEntries: entriesPromise, replaceRootController: { controller, ready in + }) + strongSelf.hiddenAvatarRepresentationDisposable.set((galleryController.hiddenMedia |> deliverOnMainQueue).start(next: { entry in + if entry == entries.first { + self?.headerNode.updateAvatarIsHidden(true) + } else { + self?.headerNode.updateAvatarIsHidden(false) + } + })) + strongSelf.controller?.present(galleryController, in: .window(.root), with: AvatarGalleryControllerPresentationArguments(transitionArguments: { _ in + return GalleryTransitionArguments(transitionNode: transitionNode, addToTransitionSurface: { _ in + }) + })) } self.headerNode.navigationButtonContainer.performAction = { [weak self] key in @@ -3019,7 +958,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD case .edit: strongSelf.state = strongSelf.state.withIsEditing(true) if strongSelf.headerNode.isAvatarExpanded { - strongSelf.headerNode.updateIsAvatarExpanded(false) + strongSelf.headerNode.updateIsAvatarExpanded(false, transition: .immediate) strongSelf.updateNavigationExpansionPresentation(isExpanded: false, animated: true) } if let (layout, navigationHeight) = strongSelf.validLayout { @@ -3092,19 +1031,21 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD if let (layout, navigationHeight) = strongSelf.validLayout { strongSelf.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .animated(duration: 0.4, curve: .spring), additive: false) } + strongSelf.chatInterfaceInteraction.selectionState = strongSelf.state.selectedMessageIds.flatMap { ChatInterfaceSelectionState(selectedIds: $0) } strongSelf.paneContainerNode.updateSelectedMessageIds(strongSelf.state.selectedMessageIds, animated: true) case .selectionDone: strongSelf.state = strongSelf.state.withSelectedMessageIds(nil) if let (layout, navigationHeight) = strongSelf.validLayout { strongSelf.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .animated(duration: 0.4, curve: .spring), additive: false) } + strongSelf.chatInterfaceInteraction.selectionState = strongSelf.state.selectedMessageIds.flatMap { ChatInterfaceSelectionState(selectedIds: $0) } strongSelf.paneContainerNode.updateSelectedMessageIds(strongSelf.state.selectedMessageIds, animated: true) case .search: strongSelf.activateSearch() } } - self.dataDisposable = (peerInfoScreenData(context: context, peerId: peerId) + self.dataDisposable = (peerInfoScreenData(context: context, peerId: peerId, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat) |> deliverOnMainQueue).start(next: { [weak self] data in guard let strongSelf = self else { return @@ -3115,7 +1056,10 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD deinit { self.dataDisposable?.dispose() + self.hiddenMediaDisposable?.dispose() self.activeActionDisposable.dispose() + self.resolveUrlDisposable.dispose() + self.hiddenAvatarRepresentationDisposable.dispose() } override func didLoad() { @@ -3130,7 +1074,9 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } func scrollToTop() { - self.scrollNode.view.setContentOffset(CGPoint(), animated: true) + if !self.paneContainerNode.scrollToTop() { + self.scrollNode.view.setContentOffset(CGPoint(), animated: true) + } } @objc private func editingCancelPressed() { @@ -3138,7 +1084,25 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } private func openMessage(id: MessageId) -> Bool { - guard let galleryMessage = self.paneContainerNode.findLoadedMessage(id: id), let controller = self.controller, let navigationController = controller.navigationController as? NavigationController else { + guard let controller = self.controller, let navigationController = controller.navigationController as? NavigationController else { + return false + } + var foundGalleryMessage: Message? + if let searchContentNode = self.searchDisplayController?.contentNode as? ChatHistorySearchContainerNode { + if let galleryMessage = searchContentNode.messageForGallery(id) { + let _ = (self.context.account.postbox.transaction { transaction -> Void in + if transaction.getMessage(galleryMessage.id) == nil { + storeMessageFromSearch(transaction: transaction, message: galleryMessage) + } + }).start() + foundGalleryMessage = galleryMessage + } + } + if foundGalleryMessage == nil, let galleryMessage = self.paneContainerNode.findLoadedMessage(id: id) { + foundGalleryMessage = galleryMessage + } + + guard let galleryMessage = foundGalleryMessage else { return false } self.view.endEditing(true) @@ -3156,17 +1120,73 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD guard let strongSelf = self else { return } - strongSelf.view.addSubview(view) - }, openUrl: { url in - //self?.openUrl(url) - }, openPeer: { peer, navigation in - //self?.controllerInteraction?.openPeer(peer.id, navigation, nil) + strongSelf.paneContainerNode.currentPane?.node.addToTransitionSurface(view: view) + }, openUrl: { [weak self] url in + self?.openUrl(url: url, external: false) + }, openPeer: { [weak self] peer, navigation in + self?.openPeer(peerId: peer.id, navigation: navigation) }, callPeer: { peerId in //self?.controllerInteraction?.callPeer(peerId) }, enqueueMessage: { _ in }, sendSticker: nil, setupTemporaryHiddenMedia: { _, _, _ in }, chatAvatarHiddenMedia: { _, _ in })) } + private func openUrl(url: String, external: Bool) { + let disposable = self.resolveUrlDisposable + + let resolvedUrl: Signal + if external { + resolvedUrl = .single(.externalUrl(url)) + } else { + resolvedUrl = self.context.sharedContext.resolveUrl(account: self.context.account, url: url) + } + + disposable.set((resolvedUrl + |> deliverOnMainQueue).start(next: { [weak self] result in + guard let strongSelf = self else { + return + } + strongSelf.context.sharedContext.openResolvedUrl(result, context: strongSelf.context, urlContext: .generic, navigationController: strongSelf.controller?.navigationController as? NavigationController, openPeer: { peerId, navigation in + self?.openPeer(peerId: peerId, navigation: navigation) + }, sendFile: nil, + sendSticker: nil, + present: { c, a in + self?.controller?.present(c, in: .window(.root), with: a) + }, dismissInput: { + self?.view.endEditing(true) + }, contentContext: nil) + })) + } + + private func openPeer(peerId: PeerId, navigation: ChatControllerInteractionNavigateToPeer) { + switch navigation { + case .default: + if let navigationController = self.controller?.navigationController as? NavigationController { + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peerId), keepStack: .always)) + } + case let .chat(_, subject): + if let navigationController = self.controller?.navigationController as? NavigationController { + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peerId), subject: subject, keepStack: .always)) + } + case .info: + self.resolveUrlDisposable.set((self.context.account.postbox.loadedPeerWithId(peerId) + |> take(1) + |> deliverOnMainQueue).start(next: { [weak self] peer in + if let strongSelf = self, peer.restrictionText(platform: "ios", contentSettings: strongSelf.context.currentContentSettings.with { $0 }) == nil { + if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic, avatarInitiallyExpanded: false) { + (strongSelf.controller?.navigationController as? NavigationController)?.pushViewController(infoController) + } + } + })) + case let .withBotStartPayload(startPayload): + if let navigationController = self.controller?.navigationController as? NavigationController { + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peerId), botStart: startPayload)) + } + default: + break + } + } + private func performButtonAction(key: PeerInfoHeaderButtonKey) { guard let controller = self.controller else { return @@ -3215,6 +1235,9 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD strongSelf.controller?.present(muteSettingsController, in: .window(.root)) }) case .more: + guard let data = self.data, let peer = data.peer else { + return + } let actionSheet = ActionSheetController(presentationData: self.presentationData) let dismissAction: () -> Void = { [weak actionSheet] in actionSheet?.dismissAnimated() @@ -3222,24 +1245,14 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD var reportSpam = false var deleteChat = false var items: [ActionSheetItem] = [] - if self.headerNode.isAvatarExpanded { - items.append(ActionSheetButtonItem(title: "Message", color: .accent, action: { [weak self] in - dismissAction() - self?.performButtonAction(key: .message) - })) - items.append(ActionSheetButtonItem(title: "Call", color: .accent, action: { [weak self] in - dismissAction() - self?.performButtonAction(key: .call) - })) - items.append(ActionSheetButtonItem(title: "Mute", color: .accent, action: { [weak self] in - dismissAction() - self?.performButtonAction(key: .mute) - })) + if let user = peer as? TelegramUser { + if user.botInfo == nil && !user.flags.contains(.isSupport) { + items.append(ActionSheetButtonItem(title: presentationData.strings.UserInfo_StartSecretChat, color: .accent, action: { [weak self] in + dismissAction() + self?.openStartSecretChat() + })) + } } - items.append(ActionSheetButtonItem(title: presentationData.strings.UserInfo_StartSecretChat, color: .accent, action: { [weak self] in - dismissAction() - self?.openStartSecretChat() - })) actionSheet.setItemGroups([ ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ActionSheetButtonItem(title: self.presentationData.strings.Common_Cancel, action: { dismissAction() })]) @@ -3297,9 +1310,9 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD cancelImpl?() })) strongSelf.controller?.present(statusController, in: .window(.root)) - return ActionDisposable { [weak controller] in + return ActionDisposable { [weak statusController] in Queue.mainQueue().async() { - controller?.dismiss() + statusController?.dismiss() } } } else { @@ -3327,7 +1340,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD return } if let navigationController = (strongSelf.controller?.navigationController as? NavigationController) { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(strongSelf.peerId))) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId))) } }, error: { _ in guard let strongSelf = self else { @@ -3636,8 +1649,69 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD }) } - func deleteMessages() { - if let messageIds = self.state.selectedMessageIds, !messageIds.isEmpty { + private func openReport() { + guard let controller = self.controller else { + return + } + controller.present(peerReportOptionsController(context: self.context, subject: .peer(self.peerId), present: { [weak controller] c, a in + controller?.present(c, in: .window(.root), with: a) + }, push: { [weak controller] c in + controller?.push(c) + }, completion: { _ in }), in: .window(.root)) + } + + private func openShareBot() { + let _ = (getUserPeer(postbox: self.context.account.postbox, peerId: self.peerId) + |> deliverOnMainQueue).start(next: { [weak self] peer, _ in + guard let strongSelf = self else { + return + } + if let peer = peer as? TelegramUser, let username = peer.username { + let shareController = ShareController(context: strongSelf.context, subject: .url("https://t.me/\(username)")) + strongSelf.controller?.present(shareController, in: .window(.root)) + } + }) + } + + private func openAddBotToGroup() { + guard let controller = self.controller else { + return + } + context.sharedContext.openResolvedUrl(.groupBotStart(peerId: peerId, payload: ""), context: self.context, urlContext: .generic, navigationController: controller.navigationController as? NavigationController, openPeer: { id, navigation in + }, sendFile: nil, + sendSticker: nil, + present: { [weak controller] c, a in + controller?.present(c, in: .window(.root), with: a) + }, dismissInput: { [weak controller] in + controller?.view.endEditing(true) + }, contentContext: nil) + } + + private func performBotCommand(command: PeerInfoBotCommand) { + let _ = (self.context.account.postbox.loadedPeerWithId(peerId) + |> deliverOnMainQueue).start(next: { [weak self] peer in + guard let strongSelf = self else { + return + } + let text: String + switch command { + case .settings: + text = "/settings" + case .privacy: + text = "/privacy" + case .help: + text = "/help" + } + let _ = enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil)]).start() + + if let navigationController = strongSelf.controller?.navigationController as? NavigationController { + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(strongSelf.peerId))) + } + }) + } + + func deleteMessages(messageIds: Set?) { + if let messageIds = messageIds ?? self.state.selectedMessageIds, !messageIds.isEmpty { self.activeActionDisposable.set((self.context.sharedContext.chatAvailableMessageActions(postbox: self.context.account.postbox, accountPeerId: self.context.account.peerId, messageIds: messageIds) |> deliverOnMainQueue).start(next: { [weak self] actions in if let strongSelf = self, let peer = strongSelf.data?.peer, !actions.options.isEmpty { @@ -3696,8 +1770,8 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } } - func forwardMessages() { - if let messageIds = self.state.selectedMessageIds, !messageIds.isEmpty { + func forwardMessages(messageIds: Set?) { + if let messageIds = messageIds ?? self.state.selectedMessageIds, !messageIds.isEmpty { let peerSelectionController = self.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: self.context, filter: [.onlyWriteable, .excludeDisabled])) peerSelectionController.peerSelected = { [weak self, weak peerSelectionController] peerId in if let strongSelf = self, let _ = peerSelectionController { @@ -3770,15 +1844,6 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD return } - var maybePlaceholderNode: SearchBarPlaceholderNode? - /*if let listNode = historyNode as? ListView { - listNode.forEachItemNode { node in - if let node = node as? ChatListSearchItemNode { - maybePlaceholderNode = node.searchBarNode - } - } - }*/ - if let _ = self.searchDisplayController { return } @@ -3795,7 +1860,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } } - self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, mode: .list, contentNode: ChatHistorySearchContainerNode(context: self.context, peerId: self.peerId, tagMask: tagMask, interfaceInteraction: self.chatInterfaceInteraction), cancel: { [weak self] in + self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, mode: .list, placeholder: self.presentationData.strings.Common_Search, contentNode: ChatHistorySearchContainerNode(context: self.context, peerId: self.peerId, tagMask: tagMask, interfaceInteraction: self.chatInterfaceInteraction), cancel: { [weak self] in self?.deactivateSearch() }) let transition: ContainedViewLayoutTransition = .animated(duration: 0.2, curve: .easeInOut) @@ -3828,6 +1893,18 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } } + func updatePresentationData(_ presentationData: PresentationData) { + self.presentationData = presentationData + + self.backgroundColor = self.presentationData.theme.list.blocksBackgroundColor + + self.updateNavigationExpansionPresentation(isExpanded: self.headerNode.isAvatarExpanded, animated: false) + + if let (layout, navigationHeight) = self.validLayout { + self.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate) + } + } + func containerLayoutUpdated(layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition, additive: Bool = false) { self.validLayout = (layout, navigationHeight) @@ -3846,7 +1923,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD var contentHeight: CGFloat = 0.0 - let headerHeight = self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: layout.safeInsets.left, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, contentOffset: self.scrollNode.view.contentOffset.y, presentationData: self.presentationData, peer: self.data?.peer, cachedData: self.data?.cachedData, notificationSettings: self.data?.notificationSettings, presence: self.data?.presence, isContact: self.data?.isContact ?? false, state: self.state, transition: transition, additive: additive) + let headerHeight = self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: layout.safeInsets.left, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, contentOffset: self.scrollNode.view.contentOffset.y, presentationData: self.presentationData, peer: self.data?.peer, cachedData: self.data?.cachedData, notificationSettings: self.data?.notificationSettings, statusData: self.data?.status, isContact: self.data?.isContact ?? false, state: self.state, transition: transition, additive: additive) let headerFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: layout.size.width, height: headerHeight)) if additive { transition.updateFrameAdditive(node: self.headerNode, frame: headerFrame) @@ -3930,7 +2007,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD guard let strongSelf = self else { return } - strongSelf.deleteMessages() + strongSelf.deleteMessages(messageIds: nil) }, shareMessages: { [weak self] in guard let strongSelf = self, let messageIds = strongSelf.state.selectedMessageIds, !messageIds.isEmpty else { return @@ -3958,7 +2035,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD guard let strongSelf = self else { return } - strongSelf.forwardMessages() + strongSelf.forwardMessages(messageIds: nil) }, reportMessages: { [weak self] in guard let strongSelf = self, let messageIds = strongSelf.state.selectedMessageIds, !messageIds.isEmpty else { return @@ -3973,7 +2050,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD self.paneContainerNode.addSubnode(selectionPanelNode) } selectionPanelNode.selectionPanel.selectedMessages = selectedMessageIds - let panelHeight = selectionPanelNode.update(width: layout.size.width, safeInset: layout.safeInsets.left, metrics: layout.metrics, presentationData: self.presentationData, transition: wasAdded ? .immediate : transition) + let panelHeight = selectionPanelNode.update(layout: layout, presentationData: self.presentationData, transition: wasAdded ? .immediate : transition) let panelFrame = CGRect(origin: CGPoint(x: 0.0, y: paneContainerSize.height - panelHeight), size: CGSize(width: layout.size.width, height: panelHeight)) if wasAdded { selectionPanelNode.frame = panelFrame @@ -4022,16 +2099,20 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD let offsetY = self.scrollNode.view.contentOffset.y if self.state.isEditing || offsetY <= 50.0 { - self.scrollNode.view.bounces = true - self.scrollNode.view.alwaysBounceVertical = true + if !self.scrollNode.view.bounces { + self.scrollNode.view.bounces = true + self.scrollNode.view.alwaysBounceVertical = true + } } else { - self.scrollNode.view.bounces = false - self.scrollNode.view.alwaysBounceVertical = false + if self.scrollNode.view.bounces { + self.scrollNode.view.bounces = false + self.scrollNode.view.alwaysBounceVertical = false + } } if let (layout, navigationHeight) = self.validLayout { if !additive { - self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: layout.safeInsets.left, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, contentOffset: offsetY, presentationData: self.presentationData, peer: self.data?.peer, cachedData: self.data?.cachedData, notificationSettings: self.data?.notificationSettings, presence: self.data?.presence, isContact: self.data?.isContact ?? false, state: self.state, transition: transition, additive: additive) + self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: layout.safeInsets.left, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, contentOffset: offsetY, presentationData: self.presentationData, peer: self.data?.peer, cachedData: self.data?.cachedData, notificationSettings: self.data?.notificationSettings, statusData: self.data?.status, isContact: self.data?.isContact ?? false, state: self.state, transition: transition, additive: additive) } let paneAreaExpansionDistance: CGFloat = 32.0 @@ -4051,7 +2132,12 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD let visibleHeight = self.scrollNode.view.contentOffset.y + self.scrollNode.view.bounds.height - self.paneContainerNode.frame.minY - self.paneContainerNode.update(size: self.paneContainerNode.bounds.size, visibleHeight: visibleHeight, expansionFraction: paneAreaExpansionFraction, presentationData: self.presentationData, data: self.data, transition: transition) + var bottomInset = layout.intrinsicInsets.bottom + if let selectionPanelNode = self.paneContainerNode.selectionPanelNode { + bottomInset = max(bottomInset, selectionPanelNode.bounds.height) + } + + self.paneContainerNode.update(size: self.paneContainerNode.bounds.size, sideInset: layout.safeInsets.left, bottomInset: bottomInset, visibleHeight: visibleHeight, expansionFraction: paneAreaExpansionFraction, presentationData: self.presentationData, data: self.data, transition: transition) self.headerNode.navigationButtonContainer.frame = CGRect(origin: CGPoint(x: layout.safeInsets.left, y: layout.statusBarHeight ?? 0.0), size: CGSize(width: layout.size.width - layout.safeInsets.left * 2.0, height: 44.0)) self.headerNode.navigationButtonContainer.isWhite = self.headerNode.isAvatarExpanded @@ -4059,7 +2145,9 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD if self.state.isEditing { navigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .done, isForExpandedView: false)) } else { - navigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .edit, isForExpandedView: false)) + if peerInfoCanEdit(peer: self.data?.peer, cachedData: self.data?.cachedData) { + navigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .edit, isForExpandedView: false)) + } if self.state.selectedMessageIds == nil { if let currentPaneKey = self.paneContainerNode.currentPaneKey { switch currentPaneKey { @@ -4068,8 +2156,13 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD default: break } + switch currentPaneKey { + case .media, .files, .music, .links, .voice: + navigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .select, isForExpandedView: true)) + default: + break + } } - navigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .select, isForExpandedView: true)) } else { navigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .selectionDone, isForExpandedView: true)) } @@ -4123,7 +2216,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD self.hapticFeedback?.tap() } - self.headerNode.updateIsAvatarExpanded(shouldBeExpanded) + self.headerNode.updateIsAvatarExpanded(shouldBeExpanded, transition: transition) self.updateNavigationExpansionPresentation(isExpanded: shouldBeExpanded, animated: true) if let (layout, navigationHeight) = self.validLayout { @@ -4230,6 +2323,7 @@ public final class PeerInfoScreen: ViewController { private let avatarInitiallyExpanded: Bool private var presentationData: PresentationData + private var presentationDataDisposable: Disposable? fileprivate var controllerNode: PeerInfoScreenNode { return self.displayNode as! PeerInfoScreenNode @@ -4269,6 +2363,9 @@ public final class PeerInfoScreen: ViewController { if strongSelf.controllerNode.scrollNode.view.contentOffset.y > .ulpOfOne { return nil } + if strongSelf.controllerNode.headerNode.isAvatarExpanded { + return nil + } if let tag = other.userInfo as? PeerInfoNavigationSourceTag, tag.peerId == peerId { return PeerInfoNavigationTransitionNode(screenNode: strongSelf.controllerNode, presentationData: strongSelf.presentationData, headerNode: strongSelf.controllerNode.headerNode) } @@ -4280,12 +2377,30 @@ public final class PeerInfoScreen: ViewController { self.scrollToTop = { [weak self] in self?.controllerNode.scrollToTop() } + + self.presentationDataDisposable = (context.sharedContext.presentationData + |> deliverOnMainQueue).start(next: { [weak self] presentationData in + if let strongSelf = self { + let previousTheme = strongSelf.presentationData.theme + let previousStrings = strongSelf.presentationData.strings + + strongSelf.presentationData = presentationData + + if previousTheme !== presentationData.theme || previousStrings !== presentationData.strings { + strongSelf.controllerNode.updatePresentationData(strongSelf.presentationData) + } + } + }) } required init(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } + deinit { + self.presentationDataDisposable?.dispose() + } + override public func loadDisplayNode() { self.displayNode = PeerInfoScreenNode(controller: self, context: self.context, peerId: self.peerId, avatarInitiallyExpanded: self.avatarInitiallyExpanded) @@ -4457,7 +2572,7 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig self.headerNode.navigationTransition = PeerInfoHeaderNavigationTransition(sourceNavigationBar: bottomNavigationBar, sourceTitleView: previousTitleView, sourceTitleFrame: previousTitleFrame, sourceSubtitleFrame: previousStatusFrame, fraction: fraction) if let (layout, navigationHeight) = self.screenNode.validLayout { - self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: layout.safeInsets.left, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: topNavigationBar.bounds.height, contentOffset: 0.0, presentationData: self.presentationData, peer: self.screenNode.data?.peer, cachedData: self.screenNode.data?.cachedData, notificationSettings: self.screenNode.data?.notificationSettings, presence: self.screenNode.data?.presence, isContact: self.screenNode.data?.isContact ?? false, state: self.screenNode.state, transition: transition, additive: false) + self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: layout.safeInsets.left, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: topNavigationBar.bounds.height, contentOffset: 0.0, presentationData: self.presentationData, peer: self.screenNode.data?.peer, cachedData: self.screenNode.data?.cachedData, notificationSettings: self.screenNode.data?.notificationSettings, statusData: self.screenNode.data?.status, isContact: self.screenNode.data?.isContact ?? false, state: self.screenNode.state, transition: transition, additive: false) } let titleScale = (fraction * previousTitleNode.bounds.height + (1.0 - fraction) * self.headerNode.titleNode.bounds.height) / previousTitleNode.bounds.height @@ -4499,3 +2614,32 @@ private func encodeText(_ string: String, _ key: Int) -> String { } return result } + +private final class ContextControllerContentSourceImpl: ContextControllerContentSource { + let controller: ViewController + weak var sourceNode: ASDisplayNode? + + let navigationController: NavigationController? = nil + + let passthroughTouches: Bool = false + + init(controller: ViewController, sourceNode: ASDisplayNode?) { + self.controller = controller + self.sourceNode = sourceNode + } + + func transitionInfo() -> ContextControllerTakeControllerInfo? { + let sourceNode = self.sourceNode + return ContextControllerTakeControllerInfo(contentAreaInScreenSpace: CGRect(origin: CGPoint(), size: CGSize(width: 10.0, height: 10.0)), sourceNode: { [weak sourceNode] in + if let sourceNode = sourceNode { + return (sourceNode, sourceNode.bounds) + } else { + return nil + } + }) + } + + func animatedIn() { + self.controller.didAppearInContextPreview() + } +} diff --git a/submodules/TelegramUI/TelegramUI/PeerInfoFilesPane.swift b/submodules/TelegramUI/TelegramUI/PeerInfoFilesPane.swift deleted file mode 100644 index 1a2b77ee30..0000000000 --- a/submodules/TelegramUI/TelegramUI/PeerInfoFilesPane.swift +++ /dev/null @@ -1,217 +0,0 @@ -import AsyncDisplayKit -import Display -import TelegramCore -import SyncCore -import SwiftSignalKit -import Postbox -import TelegramPresentationData -import AccountContext -import ContextUI -import PhotoResources -import TelegramUIPreferences - -final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode { - private let context: AccountContext - private let peerId: PeerId - private let paneInteraction: PeerInfoPaneInteraction - private let controllerInteraction: ChatControllerInteraction - - private let listNode: ChatHistoryListNode - - private var currentParams: (size: CGSize, isScrollingLockedAtTop: Bool, presentationData: PresentationData)? - - private let ready = Promise() - private var didSetReady: Bool = false - var isReady: Signal { - return self.ready.get() - } - - private let selectedMessagesPromise = Promise?>(nil) - private var selectedMessages: Set? { - didSet { - if self.selectedMessages != oldValue { - self.selectedMessagesPromise.set(.single(self.selectedMessages)) - } - } - } - - private var hiddenMediaDisposable: Disposable? - - init(context: AccountContext, openMessage: @escaping (MessageId) -> Bool, peerId: PeerId, tagMask: MessageTags, interaction: PeerInfoPaneInteraction) { - self.context = context - self.peerId = peerId - self.paneInteraction = interaction - - var openMessageImpl: ((MessageId) -> Bool)? - var toggleMessageSelectionImpl: (([MessageId]) -> Void)? - self.controllerInteraction = ChatControllerInteraction(openMessage: { message, _ in - return openMessageImpl?(message.id) ?? false - }, openPeer: { _, _, _ in - }, openPeerMention: { _ in - }, openMessageContextMenu: { _, _, _, _, _ in - }, openMessageContextActions: { _, _, _, _ in - }, navigateToMessage: { _, _ in - }, tapMessage: nil, clickThroughMessage: { - }, toggleMessagesSelection: { ids, _ in - toggleMessageSelectionImpl?(ids) - }, sendCurrentMessage: { _ in - }, sendMessage: { _ in - }, sendSticker: { _, _, _, _ in - return false - }, sendGif: { _, _, _ in - return false - }, requestMessageActionCallback: { _, _, _ in - }, requestMessageActionUrlAuth: { _, _, _ in - }, activateSwitchInline: { _, _ in - }, openUrl: { _, _, _, _ in - }, shareCurrentLocation: { - }, shareAccountContact: { - }, sendBotCommand: { _, _ in - }, openInstantPage: { _, _ in - }, openWallpaper: { _ in - }, openTheme: {_ in - }, openHashtag: { _, _ in - }, updateInputState: { _ in - }, updateInputMode: { _ in - }, openMessageShareMenu: { _ in - }, presentController: { _, _ in - }, navigationController: { - return nil - }, chatControllerNode: { - return nil - }, reactionContainerNode: { - return nil - }, presentGlobalOverlayController: { _, _ in - }, callPeer: { _ in - }, longTap: { _, _ in - }, openCheckoutOrReceipt: { _ in - }, openSearch: { - }, setupReply: { _ in - }, canSetupReply: { _ in - return false - }, navigateToFirstDateMessage: { _ in - }, requestRedeliveryOfFailedMessages: { _ in - }, addContact: { _ in - }, rateCall: { _, _ in - }, requestSelectMessagePollOptions: { _, _ in - }, requestOpenMessagePollResults: { _, _ in - }, openAppStorePage: { - }, displayMessageTooltip: { _, _, _, _ in - }, seekToTimecode: { _, _, _ in - }, scheduleCurrentMessage: { - }, sendScheduledMessagesNow: { _ in - }, editScheduledMessagesTime: { _ in - }, performTextSelectionAction: { _, _, _ in - }, updateMessageReaction: { _, _ in - }, openMessageReactions: { _ in - }, displaySwipeToReplyHint: { - }, dismissReplyMarkupMessage: { _ in - }, openMessagePollResults: { _, _ in - }, openPollCreation: { _ in - }, requestMessageUpdate: { _ in - }, cancelInteractiveKeyboardGestures: { - }, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: false)) - self.controllerInteraction.selectionState = self.paneInteraction.selectedMessageIds.flatMap { ids in - return ChatInterfaceSelectionState(selectedIds: ids) - } - self.selectedMessages = self.paneInteraction.selectedMessageIds - self.selectedMessagesPromise.set(.single(self.selectedMessages)) - - self.listNode = ChatHistoryListNode(context: context, chatLocation: .peer(peerId), tagMask: tagMask, subject: nil, controllerInteraction: controllerInteraction, selectedMessages: self.selectedMessagesPromise.get(), mode: .list(search: false, reversed: false)) - - super.init() - - openMessageImpl = { id in - return openMessage(id) - } - - toggleMessageSelectionImpl = { [weak self] ids in - for id in ids { - self?.paneInteraction.toggleMessageSelected(id) - } - } - - self.hiddenMediaDisposable = context.sharedContext.mediaManager.galleryHiddenMediaManager.hiddenIds().start(next: { [weak self] ids in - guard let strongSelf = self else { - return - } - var hiddenMedia: [MessageId: [Media]] = [:] - for id in ids { - if case let .chat(accountId, messageId, media) = id, accountId == strongSelf.context.account.id { - hiddenMedia[messageId] = [media] - } - } - strongSelf.controllerInteraction.hiddenMedia = hiddenMedia - strongSelf.listNode.forEachItemNode { itemNode in - if let itemNode = itemNode as? ListMessageNode { - itemNode.updateHiddenMedia() - } - } - }) - - self.listNode.preloadPages = true - self.addSubnode(self.listNode) - - self.ready.set(self.listNode.historyState.get() - |> take(1) - |> map { _ -> Bool in true }) - } - - deinit { - self.hiddenMediaDisposable?.dispose() - } - - func scrollToTop() -> Bool { - let offset = self.listNode.visibleContentOffset() - switch offset { - case let .known(value) where value <= CGFloat.ulpOfOne: - return false - default: - self.listNode.scrollToEndOfHistory() - return true - } - } - - func update(size: CGSize, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) { - self.currentParams = (size, isScrollingLockedAtTop, presentationData) - - transition.updateFrame(node: self.listNode, frame: CGRect(origin: CGPoint(), size: size)) - let (duration, curve) = listViewAnimationDurationAndCurve(transition: transition) - self.listNode.updateLayout(transition: transition, updateSizeAndInsets: ListViewUpdateSizeAndInsets(size: size, insets: UIEdgeInsets(), duration: duration, curve: curve)) - self.listNode.scrollEnabled = !isScrollingLockedAtTop - } - - func findLoadedMessage(id: MessageId) -> Message? { - self.listNode.messageInCurrentHistoryView(id) - } - - func transferVelocity(_ velocity: CGFloat) { - if velocity > 0.0 { - self.listNode.transferVelocity(velocity) - } - } - - func transitionNodeForGallery(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { - var transitionNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? - self.listNode.forEachItemNode { itemNode in - if let itemNode = itemNode as? ListMessageNode { - if let result = itemNode.transitionNode(id: messageId, media: media) { - transitionNode = result - } - } - } - return transitionNode - } - - func updateSelectedMessages(animated: Bool) { - self.controllerInteraction.selectionState = self.paneInteraction.selectedMessageIds.flatMap { ids in - return ChatInterfaceSelectionState(selectedIds: ids) - } - self.listNode.forEachItemNode { itemNode in - if let itemNode = itemNode as? ChatMessageItemView { - itemNode.updateSelectionState(animated: animated) - } - } - self.selectedMessages = self.paneInteraction.selectedMessageIds - } -} From d6188e21240f2818f903e3c16e326b5a6d01ac40 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Mon, 10 Feb 2020 18:03:13 +0100 Subject: [PATCH 47/50] Temporary --- SiriIntents/IntentHandler.swift | 4 +- buildbox/deploy-appcenter.sh | 83 +++ buildbox/deploy-telegram.sh | 7 +- .../Sources/AccountContext.swift | 4 +- .../AvatarNode/Sources/AvatarNode.swift | 15 +- .../AvatarNode/Sources/PeerAvatar.swift | 44 +- ...teractiveTransitionGestureRecognizer.swift | 3 + .../Navigation/NavigationContainer.swift | 25 +- .../Display/Display/NavigationBar.swift | 2 +- .../Display/NavigationButtonNode.swift | 7 + .../NavigationTransitionCoordinator.swift | 21 +- ...pLongTapOrDoubleTapGestureRecognizer.swift | 5 +- .../Sources/PhotoResources.swift | 12 +- .../Sources/SettingsController.swift | 3 +- .../Sources/TelegramIntents.swift | 3 +- .../TelegramUI/ChatAvatarNavigationNode.swift | 12 +- .../TelegramUI/ChatController.swift | 116 +++- .../ChatMessagePollBubbleContentNode.swift | 3 +- .../TelegramUI/TelegramUI/ChatTitleView.swift | 118 ++-- .../TelegramUI/MultiScaleTextNode.swift | 75 ++ .../TelegramUI/NavigateToChatController.swift | 7 + .../ListItems/PeerInfoScreenCommentItem.swift | 57 ++ .../Panes/PeerInfoVisualMediaPaneNode.swift | 1 + .../TelegramUI/PeerInfo/PeerInfoData.swift | 258 ++++++- .../PeerInfo/PeerInfoHeaderNode.swift | 396 +++++++++-- .../PeerInfo/PeerInfoPaneContainerNode.swift | 9 +- .../TelegramUI/PeerInfo/PeerInfoScreen.swift | 644 +++++++++++++++--- .../TelegramUI/SharedAccountContext.swift | 6 +- 28 files changed, 1650 insertions(+), 290 deletions(-) create mode 100644 buildbox/deploy-appcenter.sh create mode 100644 submodules/TelegramUI/TelegramUI/MultiScaleTextNode.swift create mode 100644 submodules/TelegramUI/TelegramUI/PeerInfo/ListItems/PeerInfoScreenCommentItem.swift diff --git a/SiriIntents/IntentHandler.swift b/SiriIntents/IntentHandler.swift index e0d00c1ea1..efc0b4076a 100644 --- a/SiriIntents/IntentHandler.swift +++ b/SiriIntents/IntentHandler.swift @@ -567,9 +567,9 @@ public class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchFo completion(.success(with: .missed)) } - public func resolveCallType(for intent: INSearchCallHistoryIntent, with completion: @escaping (INCallRecordTypeResolutionResult) -> Void) { + /*public func resolveCallType(for intent: INSearchCallHistoryIntent, with completion: @escaping (INCallRecordTypeResolutionResult) -> Void) { completion(.success(with: .missed)) - } + }*/ public func handle(intent: INSearchCallHistoryIntent, completion: @escaping (INSearchCallHistoryIntentResponse) -> Void) { self.actionDisposable.set((self.accountPromise.get() diff --git a/buildbox/deploy-appcenter.sh b/buildbox/deploy-appcenter.sh new file mode 100644 index 0000000000..f738d21718 --- /dev/null +++ b/buildbox/deploy-appcenter.sh @@ -0,0 +1,83 @@ +#!/bin/bash + +set -e +set -x + +API_HOST="https://api.appcenter.ms" +IPA_PATH="build/Telegram_Signed.ipa" +DSYM_PATH="build/DSYM.zip" + +upload_ipa() { + GROUP_DATA=$(curl \ + -X GET \ + --header "X-API-Token: $API_TOKEN" \ + "$API_HOST/v0.1/apps/$API_USER_NAME/$API_APP_NAME/distribution_groups/Internal" \ + ) + + GROUP_ID=$(echo "$GROUP_DATA" | python -c 'import json,sys; obj=json.load(sys.stdin); print obj["id"];') + + UPLOAD_TOKEN=$(curl \ + -X POST \ + --header "Content-Type: application/json" \ + --header "Accept: application/json" \ + --header "X-API-Token: $API_TOKEN" \ + "$API_HOST/v0.1/apps/$API_USER_NAME/$API_APP_NAME/release_uploads" \ + ) + + + UPLOAD_URL=$(echo "$UPLOAD_TOKEN" | python -c 'import json,sys; obj=json.load(sys.stdin); print obj["upload_url"];') + UPLOAD_ID=$(echo "$UPLOAD_TOKEN" | python -c 'import json,sys; obj=json.load(sys.stdin); print obj["upload_id"];') + + curl --progress-bar -F "ipa=@${IPA_PATH}" "$UPLOAD_URL" + + RELEASE_TOKEN=$(curl \ + -X PATCH \ + --header "Content-Type: application/json" \ + --header "Accept: application/json" \ + --header "X-API-Token: $API_TOKEN" \ + -d '{ "status": "committed" }' \ + "$API_HOST/v0.1/apps/$API_USER_NAME/$API_APP_NAME/release_uploads/$UPLOAD_ID" \ + ) + + + RELEASE_URL=$(echo "$RELEASE_TOKEN" | python -c 'import json,sys; obj=json.load(sys.stdin); print obj["release_url"];') + RELEASE_ID=$(echo "$RELEASE_TOKEN" | python -c 'import json,sys; obj=json.load(sys.stdin); print obj["release_id"];') + + curl \ + -X POST \ + --header "Content-Type: application/json" \ + --header "Accept: application/json" \ + --header "X-API-Token: $API_TOKEN" \ + -d "{ \"id\": \"$GROUP_ID\", \"mandatory_update\": false, \"notify_testers\": false }" \ + "$API_HOST/$RELEASE_URL/groups" +} + +upload_dsym() { + UPLOAD_DSYM_DATA=$(curl \ + -X POST \ + --header "Content-Type: application/json" \ + --header "Accept: application/json" \ + --header "X-API-Token: $API_TOKEN" \ + -d "{ \"symbol_type\": \"Apple\"}" \ + "$API_HOST/v0.1/apps/$API_USER_NAME/$API_APP_NAME/symbol_uploads" \ + ) + + DSYM_UPLOAD_URL=$(echo "$UPLOAD_DSYM_DATA" | python -c 'import json,sys; obj=json.load(sys.stdin); print obj["upload_url"];') + DSYM_UPLOAD_ID=$(echo "$UPLOAD_DSYM_DATA" | python -c 'import json,sys; obj=json.load(sys.stdin); print obj["symbol_upload_id"];') + + curl \ + --progress-bar \ + --header "x-ms-blob-type: BlockBlob" \ + --upload-file "${DSYM_PATH}" \ + "$DSYM_UPLOAD_URL" + + curl \ + -X PATCH \ + --header "Content-Type: application/json" \ + --header "Accept: application/json" \ + --header "X-API-Token: $API_TOKEN" \ + -d '{ "status": "committed" }' \ + "$API_HOST/v0.1/apps/$API_USER_NAME/$API_APP_NAME/symbol_uploads/$DSYM_UPLOAD_ID" +} + +upload_ipa diff --git a/buildbox/deploy-telegram.sh b/buildbox/deploy-telegram.sh index 85374f2d68..d76f0a292d 100644 --- a/buildbox/deploy-telegram.sh +++ b/buildbox/deploy-telegram.sh @@ -34,12 +34,10 @@ fi if [ "$CONFIGURATION" == "hockeyapp" ]; then FASTLANE_PASSWORD="" FASTLANE_ITC_TEAM_NAME="" - FASTLANE_BUILD_CONFIGURATION="internalhockeyapp" elif [ "$CONFIGURATION" == "appstore" ]; then FASTLANE_PASSWORD="$TELEGRAM_BUILD_APPSTORE_PASSWORD" FASTLANE_ITC_TEAM_NAME="$TELEGRAM_BUILD_APPSTORE_TEAM_NAME" FASTLANE_ITC_USERNAME="$TELEGRAM_BUILD_APPSTORE_USERNAME" - FASTLANE_BUILD_CONFIGURATION="testflight_llc" else echo "Unknown configuration $CONFIGURATION" exit 1 @@ -62,7 +60,6 @@ fi if [ "$1" == "appstore" ]; then export DELIVER_ITMSTRANSPORTER_ADDITIONAL_UPLOAD_PARAMETERS="-t DAV" FASTLANE_PASSWORD="$FASTLANE_PASSWORD" xcrun altool --upload-app --type ios --file "$IPA_PATH" --username "$FASTLANE_ITC_USERNAME" --password "@env:FASTLANE_PASSWORD" - #FASTLANE_PASSWORD="$FASTLANE_PASSWORD" FASTLANE_ITC_TEAM_NAME="$FASTLANE_ITC_TEAM_NAME" fastlane "$FASTLANE_BUILD_CONFIGURATION" build_number:"$BUILD_NUMBER" commit_hash:"$COMMIT_ID" commit_author:"$COMMIT_AUTHOR" skip_build:1 skip_pilot:1 -else - FASTLANE_PASSWORD="$FASTLANE_PASSWORD" FASTLANE_ITC_TEAM_NAME="$FASTLANE_ITC_TEAM_NAME" fastlane "$FASTLANE_BUILD_CONFIGURATION" build_number:"$BUILD_NUMBER" commit_hash:"$COMMIT_ID" commit_author:"$COMMIT_AUTHOR" skip_build:1 +else if [ "$1" == "hockeyapp" ]; then + API_USER_NAME="$API_USER_NAME" API_APP_NAME="$API_APP_NAME" API_TOKEN="$API_TOKEN" sh buildbox/deploy-appcenter.sh fi diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index 966bb8418a..56df2567ab 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -197,12 +197,13 @@ public final class NavigateToChatControllerParams { public let keepStack: NavigateToChatKeepStack public let purposefulAction: (() -> Void)? public let scrollToEndIfExists: Bool + public let activateMessageSearch: Bool public let animated: Bool public let options: NavigationAnimationOptions public let parentGroupId: PeerGroupId? public let completion: () -> Void - public init(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, updateTextInputState: ChatTextInputState? = nil, activateInput: Bool = false, keepStack: NavigateToChatKeepStack = .default, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, completion: @escaping () -> Void = {}) { + public init(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, updateTextInputState: ChatTextInputState? = nil, activateInput: Bool = false, keepStack: NavigateToChatKeepStack = .default, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, activateMessageSearch: Bool = false, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, completion: @escaping () -> Void = {}) { self.navigationController = navigationController self.chatController = chatController self.context = context @@ -214,6 +215,7 @@ public final class NavigateToChatControllerParams { self.keepStack = keepStack self.purposefulAction = purposefulAction self.scrollToEndIfExists = scrollToEndIfExists + self.activateMessageSearch = activateMessageSearch self.animated = animated self.options = options self.parentGroupId = parentGroupId diff --git a/submodules/AvatarNode/Sources/AvatarNode.swift b/submodules/AvatarNode/Sources/AvatarNode.swift index 18f61800f6..b871681a0a 100644 --- a/submodules/AvatarNode/Sources/AvatarNode.swift +++ b/submodules/AvatarNode/Sources/AvatarNode.swift @@ -191,6 +191,8 @@ public final class AvatarNode: ASDisplayNode { private let imageReadyDisposable = MetaDisposable() private var state: AvatarNodeState = .empty + public var unroundedImage: UIImage? + private let imageReady = Promise(false) public var ready: Signal { let imageReady = self.imageReady @@ -283,7 +285,7 @@ public final class AvatarNode: ASDisplayNode { self.imageNode.isHidden = true } - public func setPeer(context: AccountContext, theme: PresentationTheme, peer: Peer?, authorOfMessage: MessageReference? = nil, overrideImage: AvatarNodeImageOverride? = nil, emptyColor: UIColor? = nil, clipStyle: AvatarNodeClipStyle = .round, synchronousLoad: Bool = false, displayDimensions: CGSize = CGSize(width: 60.0, height: 60.0)) { + public func setPeer(context: AccountContext, theme: PresentationTheme, peer: Peer?, authorOfMessage: MessageReference? = nil, overrideImage: AvatarNodeImageOverride? = nil, emptyColor: UIColor? = nil, clipStyle: AvatarNodeClipStyle = .round, synchronousLoad: Bool = false, displayDimensions: CGSize = CGSize(width: 60.0, height: 60.0), storeUnrounded: Bool = false) { var synchronousLoad = synchronousLoad var representation: TelegramMediaImageRepresentation? var icon = AvatarNodeIcon.none @@ -318,11 +320,18 @@ public final class AvatarNode: ASDisplayNode { let parameters: AvatarNodeParameters - if let peer = peer, let signal = peerAvatarImage(account: context.account, peerReference: PeerReference(peer), authorOfMessage: authorOfMessage, representation: representation, displayDimensions: displayDimensions, emptyColor: emptyColor, synchronousLoad: synchronousLoad) { + if let peer = peer, let signal = peerAvatarImage(account: context.account, peerReference: PeerReference(peer), authorOfMessage: authorOfMessage, representation: representation, displayDimensions: displayDimensions, emptyColor: emptyColor, synchronousLoad: synchronousLoad, provideUnrounded: storeUnrounded) { self.contents = nil self.displaySuspended = true self.imageReady.set(self.imageNode.ready) - self.imageNode.setSignal(signal) + self.imageNode.setSignal(signal |> beforeNext { [weak self] next in + Queue.mainQueue().async { + self?.unroundedImage = next?.1 + } + } + |> map { next -> UIImage? in + return next?.0 + }) if case .editAvatarIcon = icon { if self.editOverlayNode == nil { diff --git a/submodules/AvatarNode/Sources/PeerAvatar.swift b/submodules/AvatarNode/Sources/PeerAvatar.swift index f9dee458bd..5419985f9f 100644 --- a/submodules/AvatarNode/Sources/PeerAvatar.swift +++ b/submodules/AvatarNode/Sources/PeerAvatar.swift @@ -64,15 +64,15 @@ public func peerAvatarImageData(account: Account, peerReference: PeerReference?, } } -public func peerAvatarImage(account: Account, peerReference: PeerReference?, authorOfMessage: MessageReference?, representation: TelegramMediaImageRepresentation?, displayDimensions: CGSize = CGSize(width: 60.0, height: 60.0), round: Bool = true, inset: CGFloat = 0.0, emptyColor: UIColor? = nil, synchronousLoad: Bool = false) -> Signal? { +public func peerAvatarImage(account: Account, peerReference: PeerReference?, authorOfMessage: MessageReference?, representation: TelegramMediaImageRepresentation?, displayDimensions: CGSize = CGSize(width: 60.0, height: 60.0), round: Bool = true, inset: CGFloat = 0.0, emptyColor: UIColor? = nil, synchronousLoad: Bool = false, provideUnrounded: Bool = false) -> Signal<(UIImage, UIImage)?, NoError>? { if let imageData = peerAvatarImageData(account: account, peerReference: peerReference, authorOfMessage: authorOfMessage, representation: representation, synchronousLoad: synchronousLoad) { return imageData - |> mapToSignal { data -> Signal in - let generate = deferred { () -> Signal in + |> mapToSignal { data -> Signal<(UIImage, UIImage)?, NoError> in + let generate = deferred { () -> Signal<(UIImage, UIImage)?, NoError> in if emptyColor == nil && data == nil { return .single(nil) } - return .single(generateImage(displayDimensions, contextGenerator: { size, context -> Void in + let roundedImage = generateImage(displayDimensions, contextGenerator: { size, context -> Void in if let data = data { if let imageSource = CGImageSourceCreateWithData(data as CFData, nil), let dataImage = CGImageSourceCreateImageAtIndex(imageSource, 0, nil) { context.clear(CGRect(origin: CGPoint(), size: displayDimensions)) @@ -110,7 +110,41 @@ public func peerAvatarImage(account: Account, peerReference: PeerReference?, aut context.fill(CGRect(origin: CGPoint(), size: displayDimensions).insetBy(dx: inset, dy: inset)) } } - })) + }) + let unroundedImage: UIImage? + if provideUnrounded { + unroundedImage = generateImage(displayDimensions, contextGenerator: { size, context -> Void in + if let data = data { + if let imageSource = CGImageSourceCreateWithData(data as CFData, nil), let dataImage = CGImageSourceCreateImageAtIndex(imageSource, 0, nil) { + context.clear(CGRect(origin: CGPoint(), size: displayDimensions)) + context.setBlendMode(.copy) + + context.draw(dataImage, in: CGRect(origin: CGPoint(), size: displayDimensions).insetBy(dx: inset, dy: inset)) + } else { + if let emptyColor = emptyColor { + context.clear(CGRect(origin: CGPoint(), size: displayDimensions)) + context.setFillColor(emptyColor.cgColor) + context.fill(CGRect(origin: CGPoint(), size: displayDimensions).insetBy(dx: inset, dy: inset)) + } + } + } else if let emptyColor = emptyColor { + context.clear(CGRect(origin: CGPoint(), size: displayDimensions)) + context.setFillColor(emptyColor.cgColor) + if round { + context.fillEllipse(in: CGRect(origin: CGPoint(), size: displayDimensions).insetBy(dx: inset, dy: inset)) + } else { + context.fill(CGRect(origin: CGPoint(), size: displayDimensions).insetBy(dx: inset, dy: inset)) + } + } + }) + } else { + unroundedImage = roundedImage + } + if let roundedImage = roundedImage, let unroundedImage = unroundedImage { + return .single((roundedImage, unroundedImage)) + } else { + return .single(nil) + } } if synchronousLoad { return generate diff --git a/submodules/Display/Display/InteractiveTransitionGestureRecognizer.swift b/submodules/Display/Display/InteractiveTransitionGestureRecognizer.swift index 25b3a4db81..507899560a 100644 --- a/submodules/Display/Display/InteractiveTransitionGestureRecognizer.swift +++ b/submodules/Display/Display/InteractiveTransitionGestureRecognizer.swift @@ -5,6 +5,9 @@ private func hasHorizontalGestures(_ view: UIView, point: CGPoint?) -> Bool { if view.disablesInteractiveTransitionGestureRecognizer { return true } + if let disablesInteractiveTransitionGestureRecognizerNow = view.disablesInteractiveTransitionGestureRecognizerNow, disablesInteractiveTransitionGestureRecognizerNow() { + return true + } if let point = point, let test = view.interactiveTransitionGestureRecognizerTest, test(point) { return true diff --git a/submodules/Display/Display/Navigation/NavigationContainer.swift b/submodules/Display/Display/Navigation/NavigationContainer.swift index fe79956916..282101e452 100644 --- a/submodules/Display/Display/Navigation/NavigationContainer.swift +++ b/submodules/Display/Display/Navigation/NavigationContainer.swift @@ -188,14 +188,14 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate { bottomController.viewWillAppear(true) let bottomNode = bottomController.displayNode - let navigationTransitionCoordinator = NavigationTransitionCoordinator(transition: .Pop, container: self, topNode: topNode, topNavigationBar: topController.navigationBar, bottomNode: bottomNode, bottomNavigationBar: bottomController.navigationBar, didUpdateProgress: { [weak self] progress, transition, topFrame, bottomFrame in + let navigationTransitionCoordinator = NavigationTransitionCoordinator(transition: .Pop, isInteractive: true, container: self, topNode: topNode, topNavigationBar: topController.navigationBar, bottomNode: bottomNode, bottomNavigationBar: bottomController.navigationBar, didUpdateProgress: { [weak self, weak bottomController] progress, transition, topFrame, bottomFrame in if let strongSelf = self { if let top = strongSelf.state.top { strongSelf.syncKeyboard(leftEdge: top.value.displayNode.frame.minX, transition: transition) var updatedStatusBarStyle = strongSelf.statusBarStyle - if let childTransition = strongSelf.state.transition, childTransition.coordinator.progress >= 0.3 { - updatedStatusBarStyle = childTransition.previous.value.statusBar.statusBarStyle + if let bottomController = bottomController, progress >= 0.3 { + updatedStatusBarStyle = bottomController.statusBar.statusBarStyle } else { updatedStatusBarStyle = top.value.statusBar.statusBarStyle } @@ -355,8 +355,21 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate { } } self.applyLayout(layout: updatedLayout, to: top, isMaster: true, transition: transition) - if let childTransition = self.state.transition, childTransition.coordinator.progress >= 0.3 { - updatedStatusBarStyle = childTransition.previous.value.statusBar.statusBarStyle + if let childTransition = self.state.transition, childTransition.coordinator.isInteractive { + switch childTransition.type { + case .push: + if childTransition.coordinator.progress >= 0.3 { + updatedStatusBarStyle = top.value.statusBar.statusBarStyle + } else { + updatedStatusBarStyle = childTransition.previous.value.statusBar.statusBarStyle + } + case .pop: + if childTransition.coordinator.progress >= 0.3 { + updatedStatusBarStyle = childTransition.previous.value.statusBar.statusBarStyle + } else { + updatedStatusBarStyle = top.value.statusBar.statusBarStyle + } + } } else { updatedStatusBarStyle = top.value.statusBar.statusBarStyle } @@ -399,7 +412,7 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate { } toValue.value.setIgnoreAppearanceMethodInvocations(false) - let topTransition = TopTransition(type: transitionType, previous: fromValue, coordinator: NavigationTransitionCoordinator(transition: mappedTransitionType, container: self, topNode: topController.displayNode, topNavigationBar: topController.navigationBar, bottomNode: bottomController.displayNode, bottomNavigationBar: bottomController.navigationBar, didUpdateProgress: { [weak self] _, transition, topFrame, bottomFrame in + let topTransition = TopTransition(type: transitionType, previous: fromValue, coordinator: NavigationTransitionCoordinator(transition: mappedTransitionType, isInteractive: false, container: self, topNode: topController.displayNode, topNavigationBar: topController.navigationBar, bottomNode: bottomController.displayNode, bottomNavigationBar: bottomController.navigationBar, didUpdateProgress: { [weak self] _, transition, topFrame, bottomFrame in guard let strongSelf = self else { return } diff --git a/submodules/Display/Display/NavigationBar.swift b/submodules/Display/Display/NavigationBar.swift index 2bd04661cd..ff66977045 100644 --- a/submodules/Display/Display/NavigationBar.swift +++ b/submodules/Display/Display/NavigationBar.swift @@ -112,7 +112,7 @@ open class NavigationBar: ASDisplayNode { public var backPressed: () -> () = { } public var userInfo: Any? - public var makeCustomTransitionNode: ((NavigationBar) -> CustomNavigationTransitionNode?)? + public var makeCustomTransitionNode: ((NavigationBar, Bool) -> CustomNavigationTransitionNode?)? private var collapsed: Bool { get { diff --git a/submodules/Display/Display/NavigationButtonNode.swift b/submodules/Display/Display/NavigationButtonNode.swift index b237e14361..a21f37823f 100644 --- a/submodules/Display/Display/NavigationButtonNode.swift +++ b/submodules/Display/Display/NavigationButtonNode.swift @@ -306,6 +306,13 @@ private final class NavigationButtonItemNode: ASTextNode { public final class NavigationButtonNode: ASDisplayNode { private var nodes: [NavigationButtonItemNode] = [] + public var singleCustomNode: ASDisplayNode? { + for node in self.nodes { + return node.node + } + return nil + } + public var pressed: (Int) -> () = { _ in } public var highlightChanged: (Int, Bool) -> () = { _, _ in } diff --git a/submodules/Display/Display/NavigationTransitionCoordinator.swift b/submodules/Display/Display/NavigationTransitionCoordinator.swift index f439a5bc64..48aec470c2 100644 --- a/submodules/Display/Display/NavigationTransitionCoordinator.swift +++ b/submodules/Display/Display/NavigationTransitionCoordinator.swift @@ -35,6 +35,7 @@ final class NavigationTransitionCoordinator { private let container: ASDisplayNode private let transition: NavigationTransition + let isInteractive: Bool let topNode: ASDisplayNode let bottomNode: ASDisplayNode private let topNavigationBar: NavigationBar? @@ -49,8 +50,9 @@ final class NavigationTransitionCoordinator { private var currentCompletion: (() -> Void)? private var didUpdateProgress: ((CGFloat, ContainedViewLayoutTransition, CGRect, CGRect) -> Void)? - init(transition: NavigationTransition, container: ASDisplayNode, topNode: ASDisplayNode, topNavigationBar: NavigationBar?, bottomNode: ASDisplayNode, bottomNavigationBar: NavigationBar?, didUpdateProgress: ((CGFloat, ContainedViewLayoutTransition, CGRect, CGRect) -> Void)? = nil) { + init(transition: NavigationTransition, isInteractive: Bool, container: ASDisplayNode, topNode: ASDisplayNode, topNavigationBar: NavigationBar?, bottomNode: ASDisplayNode, bottomNavigationBar: NavigationBar?, didUpdateProgress: ((CGFloat, ContainedViewLayoutTransition, CGRect, CGRect) -> Void)? = nil) { self.transition = transition + self.isInteractive = isInteractive self.container = container self.didUpdateProgress = didUpdateProgress self.topNode = topNode @@ -65,11 +67,11 @@ final class NavigationTransitionCoordinator { self.shadowNode.image = shadowImage if let topNavigationBar = topNavigationBar, let bottomNavigationBar = bottomNavigationBar { - if let customTransitionNode = topNavigationBar.makeCustomTransitionNode?(bottomNavigationBar) { + if let customTransitionNode = topNavigationBar.makeCustomTransitionNode?(bottomNavigationBar, isInteractive) { self.inlineNavigationBarTransition = false customTransitionNode.setup(topNavigationBar: topNavigationBar, bottomNavigationBar: bottomNavigationBar) self.customTransitionNode = customTransitionNode - } else if let customTransitionNode = bottomNavigationBar.makeCustomTransitionNode?(topNavigationBar) { + } else if let customTransitionNode = bottomNavigationBar.makeCustomTransitionNode?(topNavigationBar, isInteractive) { self.inlineNavigationBarTransition = false customTransitionNode.setup(topNavigationBar: topNavigationBar, bottomNavigationBar: bottomNavigationBar) self.customTransitionNode = customTransitionNode @@ -131,9 +133,16 @@ final class NavigationTransitionCoordinator { let topFrame = CGRect(origin: CGPoint(x: floorToScreenPixels(position * containerSize.width), y: 0.0), size: containerSize) let bottomFrame = CGRect(origin: CGPoint(x: ((position - 1.0) * containerSize.width * 0.3), y: 0.0), size: containerSize) + var canInvokeCompletion = false + var hadEarlyCompletion = false transition.updateFrame(node: self.topNode, frame: topFrame, completion: { _ in - completion() + if canInvokeCompletion { + completion() + } else { + hadEarlyCompletion = true + } }) + canInvokeCompletion = true transition.updateFrame(node: self.dimNode, frame: CGRect(origin: CGPoint(x: 0.0, y: dimInset), size: CGSize(width: max(0.0, topFrame.minX), height: self.container.bounds.size.height - dimInset))) transition.updateFrame(node: self.shadowNode, frame: CGRect(origin: CGPoint(x: self.dimNode.frame.maxX - shadowWidth, y: dimInset), size: CGSize(width: shadowWidth, height: containerSize.height - dimInset))) transition.updateAlpha(node: self.dimNode, alpha: (1.0 - position) * 0.15) @@ -149,6 +158,10 @@ final class NavigationTransitionCoordinator { } self.didUpdateProgress?(self.progress, transition, topFrame, bottomFrame) + + if hadEarlyCompletion { + completion() + } } private func updateNavigationBarTransition(transition: ContainedViewLayoutTransition) { diff --git a/submodules/Display/Display/TapLongTapOrDoubleTapGestureRecognizer.swift b/submodules/Display/Display/TapLongTapOrDoubleTapGestureRecognizer.swift index 62107686ed..35d1372542 100644 --- a/submodules/Display/Display/TapLongTapOrDoubleTapGestureRecognizer.swift +++ b/submodules/Display/Display/TapLongTapOrDoubleTapGestureRecognizer.swift @@ -68,6 +68,7 @@ public enum TapLongTapOrDoubleTapGestureRecognizerAction { case waitForSingleTap case waitForHold(timeout: Double, acceptTap: Bool) case fail + case keepWithSingleTap } public final class TapLongTapOrDoubleTapGestureRecognizer: UIGestureRecognizer, UIGestureRecognizerDelegate { @@ -206,6 +207,8 @@ public final class TapLongTapOrDoubleTapGestureRecognizer: UIGestureRecognizer, } switch tapAction { + case .keepWithSingleTap: + break case .waitForSingleTap, .waitForDoubleTap: self.timer?.invalidate() let timer = Timer(timeInterval: 0.3, target: TapLongTapOrDoubleTapGestureRecognizerTimerTarget(target: self), selector: #selector(TapLongTapOrDoubleTapGestureRecognizerTimerTarget.longTapEvent), userInfo: nil, repeats: false) @@ -284,7 +287,7 @@ public final class TapLongTapOrDoubleTapGestureRecognizer: UIGestureRecognizer, } switch tapAction { - case .waitForSingleTap: + case .waitForSingleTap, .keepWithSingleTap: if let (touchLocation, _) = self.touchLocationAndTimestamp { self.lastRecognizedGestureAndLocation = (.tap, touchLocation) } diff --git a/submodules/PhotoResources/Sources/PhotoResources.swift b/submodules/PhotoResources/Sources/PhotoResources.swift index f7e0f13037..5aa2304795 100644 --- a/submodules/PhotoResources/Sources/PhotoResources.swift +++ b/submodules/PhotoResources/Sources/PhotoResources.swift @@ -2020,10 +2020,10 @@ public func instantPageImageFile(account: Account, fileReference: FileMediaRefer } } -private func avatarGalleryPhotoDatas(account: Account, fileReference: FileMediaReference? = nil, representations: [ImageRepresentationWithReference], autoFetchFullSize: Bool = false) -> Signal, NoError> { +private func avatarGalleryPhotoDatas(account: Account, fileReference: FileMediaReference? = nil, representations: [ImageRepresentationWithReference], autoFetchFullSize: Bool = false, attemptSynchronously: Bool = false) -> Signal, NoError> { if let smallestRepresentation = smallestImageRepresentation(representations.map({ $0.representation })), let largestRepresentation = largestImageRepresentation(representations.map({ $0.representation })), let smallestIndex = representations.firstIndex(where: { $0.representation == smallestRepresentation }), let largestIndex = representations.firstIndex(where: { $0.representation == largestRepresentation }) { - let maybeFullSize = account.postbox.mediaBox.resourceData(largestRepresentation.resource) + let maybeFullSize = account.postbox.mediaBox.resourceData(largestRepresentation.resource, attemptSynchronously: attemptSynchronously) let signal = maybeFullSize |> take(1) @@ -2037,7 +2037,7 @@ private func avatarGalleryPhotoDatas(account: Account, fileReference: FileMediaR let thumbnail = Signal { subscriber in let fetchedDisposable = fetchedThumbnail.start() - let thumbnailDisposable = account.postbox.mediaBox.resourceData(smallestRepresentation.resource).start(next: { next in + let thumbnailDisposable = account.postbox.mediaBox.resourceData(smallestRepresentation.resource, attemptSynchronously: attemptSynchronously).start(next: { next in subscriber.putNext(next.size == 0 ? nil : try? Data(contentsOf: URL(fileURLWithPath: next.path), options: [])) }, error: subscriber.putError, completed: subscriber.putCompletion) @@ -2052,7 +2052,7 @@ private func avatarGalleryPhotoDatas(account: Account, fileReference: FileMediaR if autoFetchFullSize { fullSizeData = Signal, NoError> { subscriber in let fetchedFullSizeDisposable = fetchedFullSize.start() - let fullSizeDisposable = account.postbox.mediaBox.resourceData(largestRepresentation.resource).start(next: { next in + let fullSizeDisposable = account.postbox.mediaBox.resourceData(largestRepresentation.resource, attemptSynchronously: attemptSynchronously).start(next: { next in subscriber.putNext(Tuple(next.size == 0 ? nil : try? Data(contentsOf: URL(fileURLWithPath: next.path), options: []), next.complete)) }, error: subscriber.putError, completed: subscriber.putCompletion) @@ -2082,8 +2082,8 @@ private func avatarGalleryPhotoDatas(account: Account, fileReference: FileMediaR } } -public func chatAvatarGalleryPhoto(account: Account, representations: [ImageRepresentationWithReference], autoFetchFullSize: Bool = false) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { - let signal = avatarGalleryPhotoDatas(account: account, representations: representations, autoFetchFullSize: autoFetchFullSize) +public func chatAvatarGalleryPhoto(account: Account, representations: [ImageRepresentationWithReference], autoFetchFullSize: Bool = false, attemptSynchronously: Bool = false) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { + let signal = avatarGalleryPhotoDatas(account: account, representations: representations, autoFetchFullSize: autoFetchFullSize, attemptSynchronously: attemptSynchronously) return signal |> map { value in diff --git a/submodules/SettingsUI/Sources/SettingsController.swift b/submodules/SettingsUI/Sources/SettingsController.swift index 280b6055f8..1a1e15ec0d 100644 --- a/submodules/SettingsUI/Sources/SettingsController.swift +++ b/submodules/SettingsUI/Sources/SettingsController.swift @@ -1476,7 +1476,8 @@ public func settingsController(context: AccountContext, accountManager: AccountM let inset: CGFloat = 3.0 if let signal = peerAvatarImage(account: primary.0, peerReference: PeerReference(primary.1), authorOfMessage: nil, representation: primary.1.profileImageRepresentations.first, displayDimensions: size, inset: 3.0, emptyColor: nil, synchronousLoad: false) { return signal - |> map { image -> (UIImage, UIImage)? in + |> map { imageVersions -> (UIImage, UIImage)? in + let image = imageVersions?.0 if let image = image, let selectedImage = generateImage(size, rotatedContext: { size, context in context.clear(CGRect(origin: CGPoint(), size: size)) context.translateBy(x: size.width / 2.0, y: size.height / 2.0) diff --git a/submodules/TelegramIntents/Sources/TelegramIntents.swift b/submodules/TelegramIntents/Sources/TelegramIntents.swift index 3cf79eb5d8..a06109c8d2 100644 --- a/submodules/TelegramIntents/Sources/TelegramIntents.swift +++ b/submodules/TelegramIntents/Sources/TelegramIntents.swift @@ -135,7 +135,8 @@ public func donateSendMessageIntent(account: Account, sharedContext: SharedAccou signals.append(.single((peer, subject, savedMessagesAvatar))) } else { let peerAndAvatar = (peerAvatarImage(account: account, peerReference: PeerReference(peer), authorOfMessage: nil, representation: peer.smallProfileImage, round: false) ?? .single(nil)) - |> map { avatarImage in + |> map { imageVersions -> (Peer, SendMessageIntentSubject, UIImage?) in + let avatarImage = imageVersions?.0 return (peer, subject, avatarImage) } signals.append(peerAndAvatar) diff --git a/submodules/TelegramUI/TelegramUI/ChatAvatarNavigationNode.swift b/submodules/TelegramUI/TelegramUI/ChatAvatarNavigationNode.swift index 4e63ec7863..1ba556629e 100644 --- a/submodules/TelegramUI/TelegramUI/ChatAvatarNavigationNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatAvatarNavigationNode.swift @@ -70,8 +70,8 @@ final class ChatAvatarNavigationNode: ASDisplayNode { strongSelf.contextAction?(strongSelf.containerNode, gesture) } - self.containerNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 37.0, height: 37.0)) - self.avatarNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 37.0, height: 37.0)) + /*self.containerNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 37.0, height: 37.0)) + self.avatarNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 37.0, height: 37.0))*/ } override func didLoad() { @@ -80,8 +80,8 @@ final class ChatAvatarNavigationNode: ASDisplayNode { (self.view as? ChatAvatarNavigationNodeView)?.targetNode = self (self.view as? ChatAvatarNavigationNodeView)?.chatController = self.chatController - let tapRecognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.avatarTapGesture(_:))) - self.avatarNode.view.addGestureRecognizer(tapRecognizer) + /*let tapRecognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.avatarTapGesture(_:))) + self.avatarNode.view.addGestureRecognizer(tapRecognizer)*/ } @objc private func avatarTapGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) { @@ -106,7 +106,7 @@ final class ChatAvatarNavigationNode: ASDisplayNode { } func onLayout() { - /*let bounds = self.bounds + let bounds = self.bounds if self.bounds.size.height.isLessThanOrEqualTo(26.0) { if !self.avatarNode.bounds.size.equalTo(bounds.size) { self.avatarNode.font = smallFont @@ -119,6 +119,6 @@ final class ChatAvatarNavigationNode: ASDisplayNode { } self.containerNode.frame = bounds.offsetBy(dx: 10.0, dy: 1.0) self.avatarNode.frame = bounds - }*/ + } } } diff --git a/submodules/TelegramUI/TelegramUI/ChatController.swift b/submodules/TelegramUI/TelegramUI/ChatController.swift index b2fa3154bc..968e201390 100644 --- a/submodules/TelegramUI/TelegramUI/ChatController.swift +++ b/submodules/TelegramUI/TelegramUI/ChatController.swift @@ -307,6 +307,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G private var updateSlowmodeStatusTimerValue: Int32? private var isDismissed = false + + private var focusOnSearchAfterAppearance: Bool = false public override var customData: Any? { return self.chatLocation @@ -1869,46 +1871,72 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if case let .peer(peerId) = chatLocation, peerId != context.account.peerId, subject != .scheduledMessages { self.navigationBar?.userInfo = PeerInfoNavigationSourceTag(peerId: peerId) } - self.chatTitleView = ChatTitleView(account: self.context.account, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, displayAvatar: true) - if let avatarNode = self.chatTitleView?.avatarNode { - avatarNode.chatController = self - avatarNode.contextAction = { [weak self] node, gesture in - guard let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.chatMainPeer, peer.smallProfileImage != nil else { - return + + self.chatTitleView = ChatTitleView(account: self.context.account, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder) + self.navigationItem.titleView = self.chatTitleView + self.chatTitleView?.pressed = { [weak self] in + if let strongSelf = self { + if strongSelf.chatLocation == .peer(strongSelf.context.account.peerId) { + strongSelf.effectiveNavigationController?.pushViewController(PeerMediaCollectionController(context: strongSelf.context, peerId: strongSelf.context.account.peerId)) + } else { + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { + return $0.updatedTitlePanelContext { + if let index = $0.firstIndex(where: { + switch $0 { + case .chatInfo: + return true + default: + return false + } + }) { + var updatedContexts = $0 + updatedContexts.remove(at: index) + return updatedContexts + } else { + var updatedContexts = $0 + updatedContexts.append(.chatInfo) + return updatedContexts.sorted() + } + } + }) } - let galleryController = AvatarGalleryController(context: strongSelf.context, peer: peer, remoteEntries: nil, replaceRootController: { controller, ready in - }, synchronousLoad: true) - galleryController.setHintWillBePresentedInPreviewingContext(true) - - let items: [ContextMenuItem] = [ - .action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Conversation_LinkDialogOpen, icon: { _ in nil }, action: { _, f in - f(.dismissWithoutContent) - self?.navigationButtonAction(.openChatInfo(expandAvatar: false)) - })) - ] - let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: galleryController, sourceNode: node)), items: .single(items), reactionItems: [], gesture: gesture) - strongSelf.presentInGlobalOverlay(contextController) - } - avatarNode.tapped = { [weak self] in - guard let strongSelf = self else { - return - } - var expandAvatar = false - if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer, peer.smallProfileImage != nil { - expandAvatar = true - } - strongSelf.navigationButtonAction(.openChatInfo(expandAvatar: expandAvatar)) } } + + let chatInfoButtonItem: UIBarButtonItem + switch chatLocation { + case .peer: + let avatarNode = ChatAvatarNavigationNode() + avatarNode.chatController = self + avatarNode.contextAction = { [weak self] node, gesture in + guard let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.chatMainPeer, peer.smallProfileImage != nil else { + return + } + let galleryController = AvatarGalleryController(context: strongSelf.context, peer: peer, remoteEntries: nil, replaceRootController: { controller, ready in + }, synchronousLoad: true) + galleryController.setHintWillBePresentedInPreviewingContext(true) + + let items: [ContextMenuItem] = [ + .action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Conversation_LinkDialogOpen, icon: { _ in nil }, action: { _, f in + f(.dismissWithoutContent) + self?.navigationButtonAction(.openChatInfo(expandAvatar: true)) + })) + ] + let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: galleryController, sourceNode: node)), items: .single(items), reactionItems: [], gesture: gesture) + strongSelf.presentInGlobalOverlay(contextController) + } + chatInfoButtonItem = UIBarButtonItem(customDisplayNode: avatarNode)! + } + chatInfoButtonItem.target = self + chatInfoButtonItem.action = #selector(self.rightNavigationButtonAction) + chatInfoButtonItem.accessibilityLabel = self.presentationData.strings.Conversation_Info + self.chatInfoNavigationButton = ChatNavigationButton(action: .openChatInfo(expandAvatar: true), buttonItem: chatInfoButtonItem) + self.navigationItem.titleView = self.chatTitleView self.chatTitleView?.pressed = { [weak self] in self?.navigationButtonAction(.openChatInfo(expandAvatar: false)) } - let buttonItem = UIBarButtonItem(image: PresentationResourcesRootController.navigationMoreIcon(presentationInterfaceState.theme), style: .plain, target: self, action: #selector(self.rightNavigationButtonAction)) - //buttonItem.accessibilityLabel = strings.Conversation_Search - chatInfoNavigationButton = ChatNavigationButton(action: .toggleInfoPanel, buttonItem: buttonItem) - self.updateChatPresentationInterfaceState(animated: false, interactive: false, { state in if let botStart = botStart, case .interactive = botStart.behavior { return state.updatedBotStartPayload(botStart.payload) @@ -1994,8 +2022,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } else { imageOverride = nil } - strongSelf.chatTitleView?.avatarNode?.avatarNode.setPeer(context: strongSelf.context, theme: strongSelf.presentationData.theme, peer: peer, overrideImage: imageOverride) - strongSelf.chatTitleView?.avatarNode?.contextActionIsEnabled = peer.restrictionText(platform: "ios", contentSettings: strongSelf.context.currentContentSettings.with { $0 }) == nil && imageOverride == nil && peer.smallProfileImage != nil + (strongSelf.chatInfoNavigationButton?.buttonItem.customDisplayNode as? ChatAvatarNavigationNode)?.avatarNode.setPeer(context: strongSelf.context, theme: strongSelf.presentationData.theme, peer: peer, overrideImage: imageOverride) + (strongSelf.chatInfoNavigationButton?.buttonItem.customDisplayNode as? ChatAvatarNavigationNode)?.contextActionIsEnabled = peer.restrictionText(platform: "ios", contentSettings: strongSelf.context.currentContentSettings.with { $0 }) == nil } if strongSelf.peerView === peerView && strongSelf.reportIrrelvantGeoNotice == peerReportNotice && strongSelf.hasScheduledMessages == hasScheduledMessages { @@ -4443,6 +4471,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } self.interfaceInteraction = interfaceInteraction + + if self.focusOnSearchAfterAppearance { + self.focusOnSearchAfterAppearance = false + self.interfaceInteraction?.beginMessageSearch(.everything, "") + } + self.chatDisplayNode.interfaceInteraction = interfaceInteraction self.context.sharedContext.mediaManager.galleryHiddenMediaManager.addTarget(self) @@ -4700,6 +4734,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G })]), in: .window(.root)) })) } + + if self.focusOnSearchAfterAppearance { + self.focusOnSearchAfterAppearance = false + if let searchNode = self.navigationBar?.contentNode as? ChatSearchNavigationContentNode { + searchNode.activate() + } + } } override public func viewWillDisappear(_ animated: Bool) { @@ -5081,8 +5122,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.leftNavigationButton = nil } - self.chatTitleView?.displayAvatar = updatedChatPresentationInterfaceState.interfaceState.selectionState == nil - if let button = rightNavigationButtonForChatInterfaceState(updatedChatPresentationInterfaceState, strings: updatedChatPresentationInterfaceState.strings, currentButton: self.rightNavigationButton, target: self, selector: #selector(self.rightNavigationButtonAction), chatInfoNavigationButton: self.chatInfoNavigationButton) { if self.rightNavigationButton != button { var animated = transition.isAnimated @@ -8456,6 +8495,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return nil } } + + func activateSearch() { + self.focusOnSearchAfterAppearance = true + self.interfaceInteraction?.beginMessageSearch(.everything, "") + } } private final class ContextControllerContentSourceImpl: ContextControllerContentSource { diff --git a/submodules/TelegramUI/TelegramUI/ChatMessagePollBubbleContentNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessagePollBubbleContentNode.swift index c1ba412885..8a812fe3e0 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessagePollBubbleContentNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessagePollBubbleContentNode.swift @@ -1628,10 +1628,11 @@ private final class MergedAvatarsNode: ASDisplayNode { if self.disposables[peer.peerId] == nil { if let signal = peerAvatarImage(account: context.account, peerReference: peerReference, authorOfMessage: nil, representation: representation, displayDimensions: CGSize(width: mergedImageSize, height: mergedImageSize), synchronousLoad: synchronousLoad) { let disposable = (signal - |> deliverOnMainQueue).start(next: { [weak self] image in + |> deliverOnMainQueue).start(next: { [weak self] imageVersions in guard let strongSelf = self else { return } + let image = imageVersions?.0 if let image = image { strongSelf.images[peer.peerId] = image strongSelf.setNeedsDisplay() diff --git a/submodules/TelegramUI/TelegramUI/ChatTitleView.swift b/submodules/TelegramUI/TelegramUI/ChatTitleView.swift index d399138c28..e429d1315e 100644 --- a/submodules/TelegramUI/TelegramUI/ChatTitleView.swift +++ b/submodules/TelegramUI/TelegramUI/ChatTitleView.swift @@ -101,8 +101,6 @@ final class ChatTitleView: UIView, NavigationBarTitleView { private let button: HighlightTrackingButtonNode - let avatarNode: ChatAvatarNavigationNode? - private var validLayout: (CGSize, CGRect)? private var titleLeftIcon: ChatTitleIcon = .none @@ -179,15 +177,6 @@ final class ChatTitleView: UIView, NavigationBarTitleView { var pressed: (() -> Void)? - var displayAvatar: Bool = true { - didSet { - if self.displayAvatar != oldValue { - self.avatarNode?.isHidden = !self.displayAvatar - self.setNeedsLayout() - } - } - } - var titleContent: ChatTitleContent? { didSet { if let titleContent = self.titleContent { @@ -480,7 +469,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView { } } - init(account: Account, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, displayAvatar: Bool) { + init(account: Account, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder) { self.account = account self.theme = theme self.strings = strings @@ -511,11 +500,6 @@ final class ChatTitleView: UIView, NavigationBarTitleView { self.activityNode = ChatTitleActivityNode() self.button = HighlightTrackingButtonNode() - if displayAvatar { - self.avatarNode = ChatAvatarNavigationNode() - } else { - self.avatarNode = nil - } super.init(frame: CGRect()) @@ -526,7 +510,6 @@ final class ChatTitleView: UIView, NavigationBarTitleView { self.contentContainer.addSubnode(self.titleNode) self.contentContainer.addSubnode(self.activityNode) self.addSubnode(self.button) - self.avatarNode.flatMap(self.contentContainer.addSubnode) self.presenceManager = PeerPresenceStatusManager(update: { [weak self] in self?.updateStatus() @@ -541,16 +524,12 @@ final class ChatTitleView: UIView, NavigationBarTitleView { strongSelf.titleCredibilityIconNode.layer.removeAnimation(forKey: "opacity") strongSelf.titleNode.alpha = 0.4 strongSelf.activityNode.alpha = 0.4 - strongSelf.titleCredibilityIconNode.alpha = 0.4 } else { strongSelf.titleNode.alpha = 1.0 strongSelf.activityNode.alpha = 1.0 strongSelf.titleCredibilityIconNode.alpha = 1.0 strongSelf.titleNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) strongSelf.activityNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) - strongSelf.titleLeftIconNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) - strongSelf.titleRightIconNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) - strongSelf.titleCredibilityIconNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) } } } @@ -587,6 +566,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView { let transition: ContainedViewLayoutTransition = .immediate + self.button.frame = clearBounds self.contentContainer.frame = clearBounds var leftIconWidth: CGFloat = 0.0 @@ -604,7 +584,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView { if let image = self.titleCredibilityIconNode.image { if self.titleCredibilityIconNode.supernode == nil { - self.contentContainer.addSubnode(self.titleCredibilityIconNode) + self.titleNode.addSubnode(self.titleCredibilityIconNode) } credibilityIconWidth = image.size.width + 3.0 } else if self.titleCredibilityIconNode.supernode != nil { @@ -620,47 +600,67 @@ final class ChatTitleView: UIView, NavigationBarTitleView { self.titleRightIconNode.removeFromSupernode() } - var leftInset: CGFloat = 12.0 - if let avatarNode = self.avatarNode { - let avatarSize = CGSize(width: 37.0, height: 37.0) - let avatarFrame = CGRect(origin: CGPoint(x: leftInset + 10.0, y: floor((size.height - avatarSize.height) / 2.0)), size: avatarSize) - avatarNode.frame = avatarFrame - if self.displayAvatar { - leftInset += avatarSize.width + 10.0 + 8.0 - } - } - - self.button.frame = CGRect(origin: CGPoint(x: leftInset - 20.0, y: 0.0), size: CGSize(width: clearBounds.width - leftInset, height: size.height)) - let titleSideInset: CGFloat = 3.0 - var titleSize = self.titleNode.updateLayout(CGSize(width: clearBounds.width - leftIconWidth - credibilityIconWidth - rightIconWidth - titleSideInset * 2.0 - leftInset, height: size.height)) - titleSize.width += credibilityIconWidth - let activitySize = self.activityNode.updateLayout(clearBounds.size, alignment: .left) - let titleInfoSpacing: CGFloat = 0.0 - - var titleFrame: CGRect - - if activitySize.height.isZero { - titleFrame = CGRect(origin: CGPoint(x: leftInset + leftIconWidth, y: floor((size.height - titleSize.height) / 2.0)), size: titleSize) - self.titleNode.frame = titleFrame + if size.height > 40.0 { + var titleSize = self.titleNode.updateLayout(CGSize(width: clearBounds.width - leftIconWidth - credibilityIconWidth - rightIconWidth - titleSideInset * 2.0, height: size.height)) + titleSize.width += credibilityIconWidth + let activitySize = self.activityNode.updateLayout(clearBounds.size, alignment: .center) + let titleInfoSpacing: CGFloat = 0.0 + + var titleFrame: CGRect + + if activitySize.height.isZero { + titleFrame = CGRect(origin: CGPoint(x: floor((clearBounds.width - titleSize.width) / 2.0), y: floor((size.height - titleSize.height) / 2.0)), size: titleSize) + if titleFrame.size.width < size.width { + titleFrame.origin.x = -clearBounds.minX + floor((size.width - titleFrame.width) / 2.0) + } + self.titleNode.frame = titleFrame + } else { + let combinedHeight = titleSize.height + activitySize.height + titleInfoSpacing + + titleFrame = CGRect(origin: CGPoint(x: floor((clearBounds.width - titleSize.width) / 2.0), y: floor((size.height - combinedHeight) / 2.0)), size: titleSize) + if titleFrame.size.width < size.width { + titleFrame.origin.x = -clearBounds.minX + floor((size.width - titleFrame.width) / 2.0) + } + titleFrame.origin.x = max(titleFrame.origin.x, clearBounds.minX + leftIconWidth) + self.titleNode.frame = titleFrame + + var activityFrame = CGRect(origin: CGPoint(x: floor((clearBounds.width - activitySize.width) / 2.0), y: floor((size.height - combinedHeight) / 2.0) + titleSize.height + titleInfoSpacing), size: activitySize) + if activitySize.width < size.width { + activityFrame.origin.x = -clearBounds.minX + floor((size.width - activityFrame.width) / 2.0) + } + self.activityNode.frame = activityFrame + } + + if let image = self.titleLeftIconNode.image { + self.titleLeftIconNode.frame = CGRect(origin: CGPoint(x: -image.size.width - 3.0 - UIScreenPixel, y: 4.0), size: image.size) + } + if let image = self.titleCredibilityIconNode.image { + self.titleCredibilityIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.width - image.size.width - 1.0, y: 2.0), size: image.size) + } + if let image = self.titleRightIconNode.image { + self.titleRightIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.width + 3.0, y: 6.0), size: image.size) + } } else { - let combinedHeight = titleSize.height + activitySize.height + titleInfoSpacing + let titleSize = self.titleNode.updateLayout(CGSize(width: floor(clearBounds.width / 2.0 - leftIconWidth - credibilityIconWidth - rightIconWidth - titleSideInset * 2.0), height: size.height)) + let activitySize = self.activityNode.updateLayout(CGSize(width: floor(clearBounds.width / 2.0), height: size.height), alignment: .center) - titleFrame = CGRect(origin: CGPoint(x: leftInset + leftIconWidth, y: floor((size.height - combinedHeight) / 2.0)), size: titleSize) + let titleInfoSpacing: CGFloat = 8.0 + let combinedWidth = titleSize.width + leftIconWidth + credibilityIconWidth + rightIconWidth + activitySize.width + titleInfoSpacing + + let titleFrame = CGRect(origin: CGPoint(x: leftIconWidth + floor((clearBounds.width - combinedWidth) / 2.0), y: floor((size.height - titleSize.height) / 2.0)), size: titleSize) self.titleNode.frame = titleFrame + self.activityNode.frame = CGRect(origin: CGPoint(x: floor((clearBounds.width - combinedWidth) / 2.0 + titleSize.width + leftIconWidth + credibilityIconWidth + rightIconWidth + titleInfoSpacing), y: floor((size.height - activitySize.height) / 2.0)), size: activitySize) - var activityFrame = CGRect(origin: CGPoint(x: leftInset, y: floor((size.height - combinedHeight) / 2.0) + titleSize.height + titleInfoSpacing), size: activitySize) - self.activityNode.frame = activityFrame - } - - if let image = self.titleLeftIconNode.image { - self.titleLeftIconNode.frame = CGRect(origin: CGPoint(x: -image.size.width - 3.0 - UIScreenPixel, y: 4.0), size: image.size) - } - if let image = self.titleCredibilityIconNode.image { - self.titleCredibilityIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.maxX - image.size.width - 1.0, y: titleFrame.minY + 2.0), size: image.size) - } - if let image = self.titleRightIconNode.image { - self.titleRightIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.width + 3.0, y: 6.0), size: image.size) + if let image = self.titleLeftIconNode.image { + self.titleLeftIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.minX, y: titleFrame.minY + 4.0), size: image.size) + } + if let image = self.titleCredibilityIconNode.image { + self.titleCredibilityIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.maxX - image.size.width - 1.0, y: titleFrame.minY + 6.0), size: image.size) + } + if let image = self.titleRightIconNode.image { + self.titleRightIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.maxX - image.size.width - 1.0, y: titleFrame.minY + 6.0), size: image.size) + } } } diff --git a/submodules/TelegramUI/TelegramUI/MultiScaleTextNode.swift b/submodules/TelegramUI/TelegramUI/MultiScaleTextNode.swift new file mode 100644 index 0000000000..9eec9f4aa9 --- /dev/null +++ b/submodules/TelegramUI/TelegramUI/MultiScaleTextNode.swift @@ -0,0 +1,75 @@ +import Foundation +import UIKit +import AsyncDisplayKit +import Display + +private final class MultiScaleTextStateNode: ASDisplayNode { + let textNode: ImmediateTextNode + + var currentLayout: MultiScaleTextLayout? + + override init() { + self.textNode = ImmediateTextNode() + + super.init() + + self.addSubnode(self.textNode) + } +} + +final class MultiScaleTextState { + let attributedText: NSAttributedString + let constrainedSize: CGSize + + init(attributedText: NSAttributedString, constrainedSize: CGSize) { + self.attributedText = attributedText + self.constrainedSize = constrainedSize + } +} + +struct MultiScaleTextLayout { + var size: CGSize +} + +final class MultiScaleTextNode: ASDisplayNode { + private let stateNodes: [AnyHashable: MultiScaleTextStateNode] + + init(stateKeys: [AnyHashable]) { + self.stateNodes = Dictionary(stateKeys.map { ($0, MultiScaleTextStateNode()) }, uniquingKeysWith: { lhs, _ in lhs }) + + super.init() + + for (_, node) in self.stateNodes { + self.addSubnode(node) + } + } + + func updateLayout(states: [AnyHashable: MultiScaleTextState]) -> [AnyHashable: MultiScaleTextLayout] { + assert(Set(states.keys) == Set(self.stateNodes.keys)) + + var result: [AnyHashable: MultiScaleTextLayout] = [:] + for (key, state) in states { + if let node = self.stateNodes[key] { + node.textNode.attributedText = state.attributedText + let nodeSize = node.textNode.updateLayout(state.constrainedSize) + let nodeLayout = MultiScaleTextLayout(size: nodeSize) + node.currentLayout = nodeLayout + node.textNode.frame = CGRect(origin: CGPoint(x: -nodeSize.width / 2.0, y: -nodeSize.height / 2.0), size: nodeSize) + result[key] = nodeLayout + } + } + return result + } + + func update(stateFractions: [AnyHashable: CGFloat], transition: ContainedViewLayoutTransition) { + var fractionSum: CGFloat = 0.0 + for (_, fraction) in stateFractions { + fractionSum += fraction + } + for (key, fraction) in stateFractions { + if let node = self.stateNodes[key], let nodeLayout = node.currentLayout { + transition.updateAlpha(node: node, alpha: fraction / fractionSum) + } + } + } +} diff --git a/submodules/TelegramUI/TelegramUI/NavigateToChatController.swift b/submodules/TelegramUI/TelegramUI/NavigateToChatController.swift index 5b05789afd..9d7591e00c 100644 --- a/submodules/TelegramUI/TelegramUI/NavigateToChatController.swift +++ b/submodules/TelegramUI/TelegramUI/NavigateToChatController.swift @@ -33,6 +33,10 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam controller.scrollToEndOfHistory() let _ = params.navigationController.popToViewController(controller, animated: params.animated) params.completion() + } else if params.activateMessageSearch { + controller.activateSearch() + let _ = params.navigationController.popToViewController(controller, animated: params.animated) + params.completion() } else { let _ = params.navigationController.popToViewController(controller, animated: params.animated) params.completion() @@ -65,6 +69,9 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam controller = ChatControllerImpl(context: params.context, chatLocation: params.chatLocation, subject: params.subject, botStart: params.botStart) } controller.purposefulAction = params.purposefulAction + if params.activateMessageSearch { + controller.activateSearch() + } let resolvedKeepStack: Bool switch params.keepStack { case .default: diff --git a/submodules/TelegramUI/TelegramUI/PeerInfo/ListItems/PeerInfoScreenCommentItem.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/ListItems/PeerInfoScreenCommentItem.swift new file mode 100644 index 0000000000..19937b5c92 --- /dev/null +++ b/submodules/TelegramUI/TelegramUI/PeerInfo/ListItems/PeerInfoScreenCommentItem.swift @@ -0,0 +1,57 @@ +import AsyncDisplayKit +import Display +import TelegramPresentationData + +final class PeerInfoScreenCommentItem: PeerInfoScreenItem { + let id: AnyHashable + let text: String + + init(id: AnyHashable, text: String) { + self.id = id + self.text = text + } + + func node() -> PeerInfoScreenItemNode { + return PeerInfoScreenCommentItemNode() + } +} + +private final class PeerInfoScreenCommentItemNode: PeerInfoScreenItemNode { + private let textNode: ImmediateTextNode + + private var item: PeerInfoScreenCommentItem? + + override init() { + self.textNode = ImmediateTextNode() + self.textNode.displaysAsynchronously = false + self.textNode.isUserInteractionEnabled = false + + super.init() + + self.addSubnode(self.textNode) + } + + override func update(width: CGFloat, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, transition: ContainedViewLayoutTransition) -> CGFloat { + guard let item = item as? PeerInfoScreenCommentItem else { + return 10.0 + } + + self.item = item + + let sideInset: CGFloat = 16.0 + let verticalInset: CGFloat = 7.0 + + self.textNode.maximumNumberOfLines = 0 + self.textNode.attributedText = NSAttributedString(string: item.text, font: Font.regular(14.0), textColor: presentationData.theme.list.freeTextColor) + + let textSize = self.textNode.updateLayout(CGSize(width: width - sideInset * 2.0, height: .greatestFiniteMagnitude)) + + let textFrame = CGRect(origin: CGPoint(x: sideInset, y: verticalInset), size: textSize) + + let height = textSize.height + verticalInset * 2.0 + + transition.updateFrame(node: self.textNode, frame: textFrame) + + return height + } +} diff --git a/submodules/TelegramUI/TelegramUI/PeerInfo/Panes/PeerInfoVisualMediaPaneNode.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/Panes/PeerInfoVisualMediaPaneNode.swift index f374730a20..34e7e78ef9 100644 --- a/submodules/TelegramUI/TelegramUI/PeerInfo/Panes/PeerInfoVisualMediaPaneNode.swift +++ b/submodules/TelegramUI/TelegramUI/PeerInfo/Panes/PeerInfoVisualMediaPaneNode.swift @@ -372,6 +372,7 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro ) self.itemInteraction.selectedMessageIds = chatControllerInteraction.selectionState.flatMap { $0.selectedIds } + self.scrollNode.view.delaysContentTouches = false self.scrollNode.view.showsVerticalScrollIndicator = false if #available(iOS 11.0, *) { self.scrollNode.view.contentInsetAdjustmentBehavior = .never diff --git a/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoData.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoData.swift index feb2c71926..a68b93dc2c 100644 --- a/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoData.swift +++ b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoData.swift @@ -9,34 +9,47 @@ import PeerPresenceStatusManager import TelegramStringFormatting import TelegramPresentationData +enum PeerInfoUpdatingAvatar { + case none + case image(TelegramMediaImageRepresentation) +} + final class PeerInfoState { let isEditing: Bool - let isSearching: Bool let selectedMessageIds: Set? + let updatingAvatar: PeerInfoUpdatingAvatar? init( isEditing: Bool, - isSearching: Bool, - selectedMessageIds: Set? + selectedMessageIds: Set?, + updatingAvatar: PeerInfoUpdatingAvatar? ) { self.isEditing = isEditing - self.isSearching = isSearching self.selectedMessageIds = selectedMessageIds + self.updatingAvatar = updatingAvatar } func withIsEditing(_ isEditing: Bool) -> PeerInfoState { return PeerInfoState( isEditing: isEditing, - isSearching: self.isSearching, - selectedMessageIds: self.selectedMessageIds + selectedMessageIds: self.selectedMessageIds, + updatingAvatar: self.updatingAvatar ) } func withSelectedMessageIds(_ selectedMessageIds: Set?) -> PeerInfoState { return PeerInfoState( isEditing: self.isEditing, - isSearching: self.isSearching, - selectedMessageIds: selectedMessageIds + selectedMessageIds: selectedMessageIds, + updatingAvatar: self.updatingAvatar + ) + } + + func withUpdatingAvatar(_ updatingAvatar: PeerInfoUpdatingAvatar?) -> PeerInfoState { + return PeerInfoState( + isEditing: self.isEditing, + selectedMessageIds: self.selectedMessageIds, + updatingAvatar: updatingAvatar ) } } @@ -50,6 +63,7 @@ final class PeerInfoScreenData { let isContact: Bool let availablePanes: [PeerInfoPaneKey] let groupsInCommon: [Peer]? + let linkedDiscussionPeer: Peer? init( peer: Peer?, @@ -59,7 +73,8 @@ final class PeerInfoScreenData { globalNotificationSettings: GlobalNotificationSettings?, isContact: Bool, availablePanes: [PeerInfoPaneKey], - groupsInCommon: [Peer]? + groupsInCommon: [Peer]?, + linkedDiscussionPeer: Peer? ) { self.peer = peer self.cachedData = cachedData @@ -69,12 +84,21 @@ final class PeerInfoScreenData { self.isContact = isContact self.availablePanes = availablePanes self.groupsInCommon = groupsInCommon + self.linkedDiscussionPeer = linkedDiscussionPeer } } +enum PeerInfoScreenInputUserKind { + case user + case bot + case support +} + enum PeerInfoScreenInputData: Equatable { case none - case user(userId: PeerId, secretChatId: PeerId?, isBot: Bool) + case user(userId: PeerId, secretChatId: PeerId?, kind: PeerInfoScreenInputUserKind) + case channel + case group(isSupergroup: Bool) } func peerInfoAvailableMediaPanes(context: AccountContext, peerId: PeerId) -> Signal<[PeerInfoPaneKey], NoError> { @@ -82,7 +106,7 @@ func peerInfoAvailableMediaPanes(context: AccountContext, peerId: PeerId) -> Sig (.photoOrVideo, .media), (.file, .files), (.music, .music), - (.voiceOrInstantVideo, .voice), + //(.voiceOrInstantVideo, .voice), (.webPage, .links) ] return combineLatest(tags.map { tagAndKey -> Signal in @@ -127,9 +151,25 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen return .none } if let user = peer as? TelegramUser { - return .user(userId: user.id, secretChatId: nil, isBot: user.botInfo != nil) + let kind: PeerInfoScreenInputUserKind + if user.flags.contains(.isSupport) { + kind = .support + } else if user.botInfo != nil { + kind = .bot + } else { + kind = .user + } + return .user(userId: user.id, secretChatId: nil, kind: kind) + } else if let channel = peer as? TelegramChannel { + if case .group = channel.info { + return .group(isSupergroup: true) + } else { + return .channel + } + } else if let _ = peer as? TelegramGroup { + return .group(isSupergroup: false) } else { - preconditionFailure() + return .none } } |> distinctUntilChanged @@ -144,23 +184,26 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen globalNotificationSettings: nil, isContact: false, availablePanes: [], - groupsInCommon: nil + groupsInCommon: nil, + linkedDiscussionPeer: nil )) - case let .user(peerId, secretChatId, isBot): + case let .user(peerId, secretChatId, kind): let groupsInCommonSignal: Signal<[Peer]?, NoError> - if isBot { - groupsInCommonSignal = .single([]) - } else { + switch kind { + case .user: groupsInCommonSignal = .single(nil) |> then( groupsInCommon(account: context.account, peerId: peerId) |> map(Optional.init) ) + default: + groupsInCommonSignal = .single([]) } enum StatusInputData: Equatable { case none case presence(TelegramUserPresence) case bot + case support } let status = Signal { subscriber in class Manager { @@ -188,12 +231,12 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen if user.isDeleted { return .none } + if user.flags.contains(.isSupport) { + return .support + } if user.botInfo != nil { return .bot } - if user.flags.contains(.isSupport) { - return .none - } guard let presence = view.peerPresences[peerId] as? TelegramUserPresence else { return .none } @@ -203,6 +246,8 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen switch inputData { case .bot: subscriber.putNext(PeerInfoStatusData(text: strings.Bot_GenericBotStatus, isActivity: false)) + case .support: + subscriber.putNext(PeerInfoStatusData(text: strings.Bot_GenericSupportStatus, isActivity: false)) default: var presence: TelegramUserPresence? if case let .presence(value) = inputData { @@ -268,13 +313,124 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen globalNotificationSettings: globalNotificationSettings, isContact: peerView.peerIsContact, availablePanes: availablePanes, - groupsInCommon: groupsInCommon + groupsInCommon: groupsInCommon, + linkedDiscussionPeer: nil + ) + } + case .channel: + let status = context.account.viewTracker.peerView(peerId, updateData: false) + |> map { peerView -> PeerInfoStatusData? in + guard let channel = peerView.peers[peerId] as? TelegramChannel else { + return PeerInfoStatusData(text: strings.Channel_Status, isActivity: false) + } + if let cachedChannelData = peerView.cachedData as? CachedChannelData, let memberCount = cachedChannelData.participantsSummary.memberCount, memberCount != 0 { + return PeerInfoStatusData(text: strings.Conversation_StatusSubscribers(memberCount), isActivity: false) + } else { + return PeerInfoStatusData(text: strings.Channel_Status, isActivity: false) + } + } + |> distinctUntilChanged + + let globalNotificationsKey: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.globalNotifications])) + var combinedKeys: [PostboxViewKey] = [] + combinedKeys.append(globalNotificationsKey) + return combineLatest( + context.account.viewTracker.peerView(peerId, updateData: true), + peerInfoAvailableMediaPanes(context: context, peerId: peerId), + context.account.postbox.combinedView(keys: combinedKeys), + status + ) + |> map { peerView, availablePanes, combinedView, status -> PeerInfoScreenData in + var globalNotificationSettings: GlobalNotificationSettings = .defaultSettings + if let preferencesView = combinedView.views[globalNotificationsKey] as? PreferencesView { + if let settings = preferencesView.values[PreferencesKeys.globalNotifications] as? GlobalNotificationSettings { + globalNotificationSettings = settings + } + } + + var discussionPeer: Peer? + if let linkedDiscussionPeerId = (peerView.cachedData as? CachedChannelData)?.linkedDiscussionPeerId, let peer = peerView.peers[linkedDiscussionPeerId] { + discussionPeer = peer + } + + return PeerInfoScreenData( + peer: peerView.peers[peerId], + cachedData: peerView.cachedData, + status: status, + notificationSettings: peerView.notificationSettings as? TelegramPeerNotificationSettings, + globalNotificationSettings: globalNotificationSettings, + isContact: peerView.peerIsContact, + availablePanes: availablePanes, + groupsInCommon: [], + linkedDiscussionPeer: discussionPeer + ) + } + case .group: + let status = context.account.viewTracker.peerView(peerId, updateData: false) + |> map { peerView -> PeerInfoStatusData? in + guard let channel = peerView.peers[peerId] as? TelegramChannel else { + return PeerInfoStatusData(text: strings.Channel_Status, isActivity: false) + } + if let cachedChannelData = peerView.cachedData as? CachedChannelData, let memberCount = cachedChannelData.participantsSummary.memberCount, memberCount != 0 { + return PeerInfoStatusData(text: strings.Conversation_StatusMembers(memberCount), isActivity: false) + } else { + return PeerInfoStatusData(text: strings.Group_Status, isActivity: false) + } + } + |> distinctUntilChanged + + let globalNotificationsKey: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.globalNotifications])) + var combinedKeys: [PostboxViewKey] = [] + combinedKeys.append(globalNotificationsKey) + return combineLatest( + context.account.viewTracker.peerView(peerId, updateData: true), + peerInfoAvailableMediaPanes(context: context, peerId: peerId), + context.account.postbox.combinedView(keys: combinedKeys), + status + ) + |> map { peerView, availablePanes, combinedView, status -> PeerInfoScreenData in + var globalNotificationSettings: GlobalNotificationSettings = .defaultSettings + if let preferencesView = combinedView.views[globalNotificationsKey] as? PreferencesView { + if let settings = preferencesView.values[PreferencesKeys.globalNotifications] as? GlobalNotificationSettings { + globalNotificationSettings = settings + } + } + + return PeerInfoScreenData( + peer: peerView.peers[peerId], + cachedData: peerView.cachedData, + status: status, + notificationSettings: peerView.notificationSettings as? TelegramPeerNotificationSettings, + globalNotificationSettings: globalNotificationSettings, + isContact: peerView.peerIsContact, + availablePanes: availablePanes, + groupsInCommon: [], + linkedDiscussionPeer: nil ) } } } } +func canEditPeerInfo(peer: Peer?) -> Bool { + if let channel = peer as? TelegramChannel { + if channel.hasPermission(.changeInfo) { + return true + } + } else if let group = peer as? TelegramGroup { + switch group.role { + case .admin, .creator: + return true + case .member: + break + } + if !group.hasBannedPermission(.banChangeInfo) { + return true + } + } + return false +} + func peerInfoHeaderButtons(peer: Peer?, cachedData: CachedPeerData?) -> [PeerInfoHeaderButtonKey] { var result: [PeerInfoHeaderButtonKey] = [] if let user = peer as? TelegramUser { @@ -291,6 +447,62 @@ func peerInfoHeaderButtons(peer: Peer?, cachedData: CachedPeerData?) -> [PeerInf if !user.isDeleted, user.botInfo == nil && !user.flags.contains(.isSupport) { result.append(.more) } + } else if let channel = peer as? TelegramChannel { + var canEditGroupInfo = false + var canEditMembers = false + var canAddMembers = false + var isPublic = false + var isCreator = false + + isPublic = channel.username != nil + if !isPublic, let cachedChannelData = cachedData as? CachedChannelData, cachedChannelData.peerGeoLocation != nil { + isPublic = true + } + + isCreator = channel.flags.contains(.isCreator) + if channel.hasPermission(.changeInfo) { + canEditGroupInfo = true + } + if channel.hasPermission(.banMembers) { + canEditMembers = true + } + if channel.hasPermission(.inviteMembers) { + canAddMembers = true + } + + result.append(.mute) + result.append(.more) + } else if let group = peer as? TelegramGroup { + var canEditGroupInfo = false + var canEditMembers = false + var canAddMembers = false + var isPublic = false + var isCreator = false + + if case .creator = group.role { + isCreator = true + } + switch group.role { + case .admin, .creator: + canEditGroupInfo = true + canEditMembers = true + canAddMembers = true + case .member: + break + } + if !group.hasBannedPermission(.banChangeInfo) { + canEditGroupInfo = true + } + if !group.hasBannedPermission(.banAddMembers) { + canAddMembers = true + } + + if canAddMembers { + result.append(.addMember) + } + + result.append(.mute) + result.append(.more) } return result } @@ -301,6 +513,8 @@ func peerInfoCanEdit(peer: Peer?, cachedData: CachedPeerData?) -> Bool { return false } return true + } else if peer is TelegramChannel || peer is TelegramGroup { + return true } return false } diff --git a/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoHeaderNode.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoHeaderNode.swift index b601a275e4..b44399c74e 100644 --- a/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoHeaderNode.swift +++ b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoHeaderNode.swift @@ -12,6 +12,7 @@ import TelegramPresentationData import PhotoResources import PeerAvatarGalleryUI import TelegramStringFormatting +import ActivityIndicator enum PeerInfoHeaderButtonKey: Hashable { case message @@ -154,25 +155,19 @@ enum PeerInfoAvatarListItem: Equatable { } final class PeerInfoAvatarListItemNode: ASDisplayNode { + private let context: AccountContext let imageNode: TransformImageNode let isReady = Promise() private var didSetReady: Bool = false - init(context: AccountContext, item: PeerInfoAvatarListItem) { + init(context: AccountContext) { + self.context = context self.imageNode = TransformImageNode() super.init() self.addSubnode(self.imageNode) - let representations: [ImageRepresentationWithReference] - switch item { - case let .topImage(topRepresentations): - representations = topRepresentations - case let .image(_, imageRepresentations): - representations = imageRepresentations - } - self.imageNode.setSignal(chatAvatarGalleryPhoto(account: context.account, representations: representations, autoFetchFullSize: true), dispatchOnDisplayLink: false) self.imageNode.imageUpdated = { [weak self] _ in guard let strongSelf = self else { @@ -185,6 +180,17 @@ final class PeerInfoAvatarListItemNode: ASDisplayNode { } } + func setup(item: PeerInfoAvatarListItem, synchronous: Bool) { + let representations: [ImageRepresentationWithReference] + switch item { + case let .topImage(topRepresentations): + representations = topRepresentations + case let .image(_, imageRepresentations): + representations = imageRepresentations + } + self.imageNode.setSignal(chatAvatarGalleryPhoto(account: self.context.account, representations: representations, autoFetchFullSize: true, attemptSynchronously: synchronous), attemptSynchronously: synchronous, dispatchOnDisplayLink: false) + } + func update(size: CGSize, transition: ContainedViewLayoutTransition) { let imageSize = CGSize(width: min(size.width, size.height), height: min(size.width, size.height)) let makeLayout = self.imageNode.asyncLayout() @@ -198,13 +204,23 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode { private let context: AccountContext let controlsContainerNode: ASDisplayNode - let controlsContainerTransformNode: ASDisplayNode - let shadowNode: ASDisplayNode + let controlsClippingNode: ASDisplayNode + let controlsClippingOffsetNode: ASDisplayNode + let shadowNode: ASImageNode let contentNode: ASDisplayNode + let leftHighlightNode: ASImageNode + let rightHighlightNode: ASImageNode + var highlightedSide: Bool? + let stripContainerNode: ASDisplayNode + let highlightContainerNode: ASDisplayNode private(set) var galleryEntries: [AvatarGalleryEntry] = [] private var items: [PeerInfoAvatarListItem] = [] private var itemNodes: [WrappedMediaResourceId: PeerInfoAvatarListItemNode] = [:] + private var stripNodes: [ASImageNode] = [] + private let inactiveStripImage: UIImage + private let activeStripImage: UIImage + private var appliedStripNodeCurrentIndex: Int? private var currentIndex: Int = 0 private var transitionFraction: CGFloat = 0.0 @@ -229,14 +245,99 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode { self.contentNode = ASDisplayNode() + self.leftHighlightNode = ASImageNode() + self.leftHighlightNode.displaysAsynchronously = false + self.leftHighlightNode.displayWithoutProcessing = true + self.leftHighlightNode.contentMode = .scaleToFill + self.leftHighlightNode.image = generateImage(CGSize(width: 88.0, height: 1.0), contextGenerator: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + + let topColor = UIColor(rgb: 0x000000, alpha: 0.5) + let bottomColor = UIColor(rgb: 0x000000, alpha: 0.0) + + var locations: [CGFloat] = [0.0, 1.0] + let colors: [CGColor] = [topColor.cgColor, bottomColor.cgColor] + + let colorSpace = CGColorSpaceCreateDeviceRGB() + let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &locations)! + + context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: size.width, y: 0.0), options: [.drawsBeforeStartLocation, .drawsAfterEndLocation]) + }) + self.leftHighlightNode.isHidden = true + + self.rightHighlightNode = ASImageNode() + self.rightHighlightNode.displaysAsynchronously = false + self.rightHighlightNode.displayWithoutProcessing = true + self.rightHighlightNode.contentMode = .scaleToFill + self.rightHighlightNode.image = generateImage(CGSize(width: 88.0, height: 1.0), contextGenerator: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + + let topColor = UIColor(rgb: 0x000000, alpha: 0.5) + let bottomColor = UIColor(rgb: 0x000000, alpha: 0.0) + + var locations: [CGFloat] = [0.0, 1.0] + let colors: [CGColor] = [topColor.cgColor, bottomColor.cgColor] + + let colorSpace = CGColorSpaceCreateDeviceRGB() + let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &locations)! + + context.drawLinearGradient(gradient, start: CGPoint(x: size.width, y: 0.0), end: CGPoint(x: 0.0, y: 0.0), options: [.drawsBeforeStartLocation, .drawsAfterEndLocation]) + }) + self.rightHighlightNode.isHidden = true + + self.stripContainerNode = ASDisplayNode() + self.contentNode.addSubnode(self.stripContainerNode) + self.inactiveStripImage = generateStretchableFilledCircleImage(diameter: 3.0, color: UIColor(white: 1.0, alpha: 0.2))! + self.activeStripImage = generateStretchableFilledCircleImage(diameter: 3.0, color: .white)! + + self.highlightContainerNode = ASDisplayNode() + self.highlightContainerNode.addSubnode(self.leftHighlightNode) + self.highlightContainerNode.addSubnode(self.rightHighlightNode) + self.controlsContainerNode = ASDisplayNode() self.controlsContainerNode.isUserInteractionEnabled = false - self.controlsContainerTransformNode = ASDisplayNode() - self.controlsContainerTransformNode.isUserInteractionEnabled = false + self.controlsClippingOffsetNode = ASDisplayNode() - self.shadowNode = ASDisplayNode() - //self.shadowNode.backgroundColor = .green + self.controlsClippingNode = ASDisplayNode() + self.controlsClippingNode.isUserInteractionEnabled = false + self.controlsClippingNode.clipsToBounds = true + + self.shadowNode = ASImageNode() + self.shadowNode.displaysAsynchronously = false + self.shadowNode.displayWithoutProcessing = true + self.shadowNode.contentMode = .scaleToFill + + do { + let size = CGSize(width: 88.0, height: 88.0) + UIGraphicsBeginImageContextWithOptions(size, false, 0.0) + if let context = UIGraphicsGetCurrentContext() { + context.clip(to: CGRect(origin: CGPoint(), size: size)) + + let topColor = UIColor(rgb: 0x000000, alpha: 0.4) + let bottomColor = UIColor(rgb: 0x000000, alpha: 0.0) + + var locations: [CGFloat] = [0.0, 1.0] + let colors: [CGColor] = [topColor.cgColor, bottomColor.cgColor] + + let colorSpace = CGColorSpaceCreateDeviceRGB() + let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &locations)! + + context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: size.width, y: 0.0), options: [.drawsBeforeStartLocation, .drawsAfterEndLocation]) + + let image = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + if let image = image { + self.shadowNode.image = generateImage(image.size, contextGenerator: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + context.translateBy(x: size.width / 2.0, y: size.height / 2.0) + context.rotate(by: -CGFloat.pi / 2.0) + context.translateBy(x: -size.width / 2.0, y: -size.height / 2.0) + context.draw(image.cgImage!, in: CGRect(origin: CGPoint(), size: size)) + }) + } + } + } super.init() @@ -244,12 +345,52 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode { self.addSubnode(self.contentNode) + self.controlsContainerNode.addSubnode(self.highlightContainerNode) self.controlsContainerNode.addSubnode(self.shadowNode) - self.controlsContainerTransformNode.addSubnode(self.controlsContainerNode) - self.addSubnode(self.controlsContainerTransformNode) + self.controlsContainerNode.addSubnode(self.stripContainerNode) + self.controlsClippingNode.addSubnode(self.controlsContainerNode) + self.controlsClippingOffsetNode.addSubnode(self.controlsClippingNode) - self.view.disablesInteractiveTransitionGestureRecognizer = true + self.view.disablesInteractiveTransitionGestureRecognizerNow = { [weak self] in + guard let strongSelf = self else { + return false + } + return strongSelf.currentIndex != 0 + } self.view.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:)))) + + let recognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapLongTapOrDoubleTapGesture(_:))) + recognizer.tapActionAtPoint = { _ in + return .keepWithSingleTap + } + recognizer.highlight = { [weak self] point in + guard let strongSelf = self, let size = strongSelf.validLayout else { + return + } + var highlightedSide: Bool? + if let point = point { + if point.x < size.width * 1.0 / 5.0 { + if strongSelf.currentIndex != 0 { + highlightedSide = false + } + } else if point.x > size.width * 4.0 / 5.0 { + if strongSelf.currentIndex < strongSelf.items.count - 1 || strongSelf.items.count > 1 { + highlightedSide = true + } + } + } + if strongSelf.highlightedSide != highlightedSide { + strongSelf.highlightedSide = highlightedSide + if let highlightedSide = highlightedSide { + strongSelf.leftHighlightNode.isHidden = highlightedSide + strongSelf.rightHighlightNode.isHidden = !highlightedSide + } else { + strongSelf.leftHighlightNode.isHidden = true + strongSelf.rightHighlightNode.isHidden = true + } + } + } + self.view.addGestureRecognizer(recognizer) } deinit { @@ -267,6 +408,32 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode { } } + @objc private func tapLongTapOrDoubleTapGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) { + switch recognizer.state { + case .ended: + if let (gesture, location) = recognizer.lastRecognizedGestureAndLocation { + if let size = self.validLayout, case .tap = gesture { + if location.x < size.width * 1.0 / 5.0 { + if self.currentIndex != 0 { + self.currentIndex -= 1 + self.updateItems(size: size, transition: .immediate) + } + } else if location.x > size.width * 4.0 / 5.0 { + if self.currentIndex < self.items.count - 1 { + self.currentIndex += 1 + self.updateItems(size: size, transition: .immediate) + } else if self.items.count > 1 { + self.currentIndex = 0 + self.updateItems(size: size, transition: .immediate, synchronous: true) + } + } + } + } + default: + break + } + } + @objc private func panGesture(_ recognizer: UIPanGestureRecognizer) { switch recognizer.state { case .changed: @@ -309,6 +476,10 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode { func update(size: CGSize, peer: Peer?, transition: ContainedViewLayoutTransition) { self.validLayout = size + + self.leftHighlightNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: floor(size.width * 1.0 / 5.0), height: size.height)) + self.rightHighlightNode.frame = CGRect(origin: CGPoint(x: size.width - floor(size.width * 1.0 / 5.0), y: 0.0), size: CGSize(width: floor(size.width * 1.0 / 5.0), height: size.height)) + if let peer = peer, !self.initializedList { self.initializedList = true self.disposable.set((fetchedAvatarGalleryEntries(account: self.context.account, peer: peer) @@ -341,7 +512,7 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode { self.updateItems(size: size, transition: transition) } - private func updateItems(size: CGSize, transition: ContainedViewLayoutTransition) { + private func updateItems(size: CGSize, transition: ContainedViewLayoutTransition, synchronous: Bool = false) { var validIds: [WrappedMediaResourceId] = [] var addedItemNodesForAdditiveTransition: [PeerInfoAvatarListItemNode] = [] var additiveTransitionOffset: CGFloat = 0.0 @@ -354,7 +525,8 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode { itemNode = current } else { wasAdded = true - itemNode = PeerInfoAvatarListItemNode(context: self.context, item: self.items[i]) + itemNode = PeerInfoAvatarListItemNode(context: self.context) + itemNode.setup(item: self.items[i], synchronous: synchronous && i == self.currentIndex) self.itemNodes[self.items[i].id] = itemNode self.contentNode.addSubnode(itemNode) } @@ -387,6 +559,52 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode { } } + if self.stripNodes.count != self.items.count { + if self.stripNodes.count < self.items.count { + for _ in 0 ..< self.items.count - self.stripNodes.count { + let stripNode = ASImageNode() + stripNode.displaysAsynchronously = false + stripNode.displayWithoutProcessing = true + if stripNodes.count == self.currentIndex { + stripNode.image = self.activeStripImage + } else { + stripNode.image = self.inactiveStripImage + } + self.stripNodes.append(stripNode) + self.stripContainerNode.addSubnode(stripNode) + } + } else { + for i in (self.items.count ..< self.stripNodes.count).reversed() { + self.stripNodes[i].removeFromSupernode() + self.stripNodes.remove(at: i) + } + } + } + if self.appliedStripNodeCurrentIndex != self.currentIndex { + if let appliedStripNodeCurrentIndex = self.appliedStripNodeCurrentIndex { + if appliedStripNodeCurrentIndex >= 0 && appliedStripNodeCurrentIndex < self.stripNodes.count { + self.stripNodes[appliedStripNodeCurrentIndex].image = self.inactiveStripImage + } + } + self.appliedStripNodeCurrentIndex = self.currentIndex + if self.currentIndex >= 0 && self.currentIndex < self.stripNodes.count { + self.stripNodes[self.currentIndex].image = self.activeStripImage + } + } + let stripInset: CGFloat = 5.0 + let stripSpacing: CGFloat = 4.0 + let stripWidth: CGFloat = floor((size.width - stripInset * 2.0 - stripSpacing * CGFloat(self.stripNodes.count - 1)) / CGFloat(self.stripNodes.count)) + var stripX: CGFloat = stripInset + for i in 0 ..< self.stripNodes.count { + if i == 0 && self.stripNodes.count == 1 { + self.stripNodes[i].isHidden = true + } else { + self.stripNodes[i].isHidden = false + } + self.stripNodes[i].frame = CGRect(origin: CGPoint(x: stripX, y: 0.0), size: CGSize(width: stripWidth, height: 3.0)) + stripX += stripWidth + stripSpacing + } + if let item = self.items.first, let itemNode = self.itemNodes[item.id] { if !self.didSetReady { self.didSetReady = true @@ -429,7 +647,7 @@ final class PeerInfoAvatarTransformContainerNode: ASDisplayNode { if peer.isDeleted { overrideImage = .deletedIcon } - self.avatarNode.setPeer(context: self.context, theme: theme, peer: peer, overrideImage: overrideImage, synchronousLoad: self.isFirstAvatarLoading, displayDimensions: CGSize(width: 100.0, height: 100.0)) + self.avatarNode.setPeer(context: self.context, theme: theme, peer: peer, overrideImage: overrideImage, synchronousLoad: self.isFirstAvatarLoading, displayDimensions: CGSize(width: 100.0, height: 100.0), storeUnrounded: true) self.isFirstAvatarLoading = false } } @@ -439,6 +657,9 @@ final class PeerInfoEditingAvatarNode: ASDisplayNode { let context: AccountContext let avatarNode: AvatarNode + private let updatingAvatarOverlay: ASImageNode + private let activityIndicator: ActivityIndicator + var tapped: (() -> Void)? init(context: AccountContext) { @@ -446,10 +667,24 @@ final class PeerInfoEditingAvatarNode: ASDisplayNode { let avatarFont = avatarPlaceholderFont(size: floor(100.0 * 16.0 / 37.0)) self.avatarNode = AvatarNode(font: avatarFont) + self.updatingAvatarOverlay = ASImageNode() + self.updatingAvatarOverlay.displayWithoutProcessing = true + self.updatingAvatarOverlay.displaysAsynchronously = false + self.updatingAvatarOverlay.isHidden = true + + self.activityIndicator = ActivityIndicator(type: .custom(.white, 22.0, 1.0, false)) + self.activityIndicator.isHidden = true + super.init() self.addSubnode(self.avatarNode) self.avatarNode.frame = CGRect(origin: CGPoint(x: -50.0, y: -50.0), size: CGSize(width: 100.0, height: 100.0)) + self.updatingAvatarOverlay.frame = self.avatarNode.frame + let indicatorSize = self.activityIndicator.measure(CGSize(width: 100.0, height: 100.0)) + self.activityIndicator.frame = CGRect(origin: CGPoint(x: floorToScreenPixels(self.avatarNode.frame.midX - indicatorSize.width / 2.0), y: floorToScreenPixels(self.avatarNode.frame.midY - indicatorSize.height / 2.0)), size: indicatorSize) + + self.addSubnode(self.updatingAvatarOverlay) + self.addSubnode(self.activityIndicator) self.avatarNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) } @@ -460,11 +695,42 @@ final class PeerInfoEditingAvatarNode: ASDisplayNode { } } - func update(peer: Peer?, theme: PresentationTheme) { + func update(peer: Peer?, updatingAvatar: PeerInfoUpdatingAvatar?, theme: PresentationTheme) { if let peer = peer { - self.avatarNode.setPeer(context: self.context, theme: theme, peer: peer, synchronousLoad: false, displayDimensions: CGSize(width: 100.0, height: 100.0)) + let overrideImage: AvatarNodeImageOverride? + if canEditPeerInfo(peer: peer) { + if let updatingAvatar = updatingAvatar { + switch updatingAvatar { + case let .image(representation): + overrideImage = .image(representation) + case .none: + overrideImage = .none + } + self.activityIndicator.isHidden = false + self.updatingAvatarOverlay.isHidden = false + if self.updatingAvatarOverlay.image == nil { + self.updatingAvatarOverlay.image = generateFilledCircleImage(diameter: 100.0, color: UIColor(white: 0.0, alpha: 0.4), backgroundColor: nil) + } + } else { + overrideImage = .editAvatarIcon + self.activityIndicator.isHidden = true + self.updatingAvatarOverlay.isHidden = true + } + } else { + overrideImage = nil + self.activityIndicator.isHidden = true + self.updatingAvatarOverlay.isHidden = true + } + self.avatarNode.setPeer(context: self.context, theme: theme, peer: peer, overrideImage: overrideImage, synchronousLoad: false, displayDimensions: CGSize(width: 100.0, height: 100.0)) } } + + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + if self.avatarNode.frame.contains(point) { + return self.avatarNode.view + } + return super.hitTest(point, with: event) + } } final class PeerInfoAvatarListNode: ASDisplayNode { @@ -534,7 +800,10 @@ final class PeerInfoAvatarListNode: ASDisplayNode { } func animateAvatarCollapse(transition: ContainedViewLayoutTransition) { - if let currentItemNode = self.listContainerNode.currentItemNode, let avatarCopyView = self.avatarContainerNode.avatarNode.view.snapshotContentTree(), case let .animated(duration, curve) = transition { + if let currentItemNode = self.listContainerNode.currentItemNode, let unroundedImage = self.avatarContainerNode.avatarNode.unroundedImage, case let .animated(duration, curve) = transition { + let avatarCopyView = UIImageView() + avatarCopyView.image = unroundedImage + avatarCopyView.frame = self.avatarContainerNode.avatarNode.frame avatarCopyView.center = currentItemNode.imageNode.position currentItemNode.view.addSubview(avatarCopyView) let scale = currentItemNode.imageNode.bounds.height / avatarCopyView.bounds.height @@ -854,7 +1123,7 @@ final class PeerInfoHeaderEditingContentNode: ASDisplayNode { return self.itemNodes[key]?.text } - func update(width: CGFloat, safeInset: CGFloat, statusBarHeight: CGFloat, navigationHeight: CGFloat, peer: Peer?, isContact: Bool, presentationData: PresentationData, transition: ContainedViewLayoutTransition) -> CGFloat { + func update(width: CGFloat, safeInset: CGFloat, statusBarHeight: CGFloat, navigationHeight: CGFloat, peer: Peer?, cachedData: CachedPeerData?, isContact: Bool, presentationData: PresentationData, transition: ContainedViewLayoutTransition) -> CGFloat { let avatarSize: CGFloat = 100.0 let avatarFrame = CGRect(origin: CGPoint(x: floor((width - avatarSize) / 2.0), y: statusBarHeight + 10.0), size: CGSize(width: avatarSize, height: avatarSize)) transition.updateFrameAdditiveToCenter(node: self.avatarNode, frame: CGRect(origin: avatarFrame.center, size: CGSize())) @@ -869,6 +1138,16 @@ final class PeerInfoHeaderEditingContentNode: ASDisplayNode { fieldKeys.append(.lastName) } } + } else if let _ = peer as? TelegramGroup { + fieldKeys.append(.title) + if canEditPeerInfo(peer: peer) { + fieldKeys.append(.description) + } + } else if let _ = peer as? TelegramChannel { + fieldKeys.append(.title) + if canEditPeerInfo(peer: peer) { + fieldKeys.append(.description) + } } var hasPrevious = false for key in fieldKeys { @@ -883,9 +1162,15 @@ final class PeerInfoHeaderEditingContentNode: ASDisplayNode { case .lastName: updateText = (peer as? TelegramUser)?.lastName ?? "" case .title: - updateText = (peer as? TelegramUser)?.debugDisplayTitle ?? "" + updateText = peer?.debugDisplayTitle ?? "" case .description: - break + if let cachedData = cachedData as? CachedChannelData { + updateText = cachedData.about ?? "" + } else if let cachedData = cachedData as? CachedGroupData { + updateText = cachedData.about ?? "" + } else { + updateText = "" + } } itemNode = PeerInfoHeaderSingleLineTextFieldNode() self.itemNodes[key] = itemNode @@ -902,8 +1187,10 @@ final class PeerInfoHeaderEditingContentNode: ASDisplayNode { isEnabled = isContact case .title: placeholder = "Title" + isEnabled = canEditPeerInfo(peer: peer) case .description: placeholder = "Description" + isEnabled = canEditPeerInfo(peer: peer) } let itemHeight = itemNode.update(width: width, safeInset: safeInset, hasPrevious: hasPrevious, placeholder: placeholder, isEnabled: isEnabled, presentationData: presentationData, updateText: updateText) transition.updateFrame(node: itemNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: width, height: itemHeight))) @@ -951,6 +1238,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { var performButtonAction: ((PeerInfoHeaderButtonKey) -> Void)? var requestAvatarExpansion: (([AvatarGalleryEntry], (ASDisplayNode, CGRect, () -> (UIView?, UIView?))) -> Void)? + var requestOpenAvatarForEditing: (() -> Void)? var navigationTransition: PeerInfoHeaderNavigationTransition? @@ -999,6 +1287,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { self.subtitleNodeContainer.addSubnode(self.subtitleNode) self.regularContentNode.addSubnode(self.subtitleNodeContainer) self.regularContentNode.addSubnode(self.avatarListNode) + self.regularContentNode.addSubnode(self.avatarListNode.listContainerNode.controlsClippingOffsetNode) self.addSubnode(self.regularContentNode) self.addSubnode(self.editingContentNode) self.addSubnode(self.navigationButtonContainer) @@ -1012,6 +1301,12 @@ final class PeerInfoHeaderNode: ASDisplayNode { return (avatarNode?.view.snapshotContentTree(unhide: true), nil) })) } + self.editingContentNode.avatarNode.tapped = { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.requestOpenAvatarForEditing?() + } } func updateAvatarIsHidden(_ isHidden: Bool) { @@ -1029,7 +1324,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { self.regularContentNode.alpha = state.isEditing ? 0.0 : 1.0 self.editingContentNode.alpha = state.isEditing ? 1.0 : 0.0 - let editingContentHeight = self.editingContentNode.update(width: width, safeInset: containerInset, statusBarHeight: statusBarHeight, navigationHeight: navigationHeight, peer: state.isEditing ? peer : nil, isContact: isContact, presentationData: presentationData, transition: transition) + let editingContentHeight = self.editingContentNode.update(width: width, safeInset: containerInset, statusBarHeight: statusBarHeight, navigationHeight: navigationHeight, peer: state.isEditing ? peer : nil, cachedData: cachedData, isContact: isContact, presentationData: presentationData, transition: transition) transition.updateFrame(node: self.editingContentNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -contentOffset), size: CGSize(width: width, height: editingContentHeight))) var transitionSourceHeight: CGFloat = 0.0 @@ -1041,7 +1336,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { self.backgroundNode.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor self.expandedBackgroundNode.backgroundColor = presentationData.theme.rootController.navigationBar.backgroundColor - if let navigationTransition = self.navigationTransition, let sourceAvatarNode = navigationTransition.sourceTitleView.avatarNode?.avatarNode { + if let navigationTransition = self.navigationTransition, let sourceAvatarNode = (navigationTransition.sourceNavigationBar.rightButtonNode.singleCustomNode as? ChatAvatarNavigationNode)?.avatarNode { transitionSourceHeight = navigationTransition.sourceNavigationBar.bounds.height transitionFraction = navigationTransition.fraction transitionSourceAvatarFrame = sourceAvatarNode.view.convert(sourceAvatarNode.view.bounds, to: navigationTransition.sourceNavigationBar.view) @@ -1049,6 +1344,10 @@ final class PeerInfoHeaderNode: ASDisplayNode { transitionSourceSubtitleFrame = navigationTransition.sourceSubtitleFrame transition.updateAlpha(node: self.expandedBackgroundNode, alpha: transitionFraction) + + if self.isAvatarExpanded, case .animated = transition, transitionFraction == 1.0 { + self.avatarListNode.animateAvatarCollapse(transition: transition) + } } else { let backgroundTransitionFraction: CGFloat = max(0.0, min(1.0, contentOffset / (212.0))) transition.updateAlpha(node: self.expandedBackgroundNode, alpha: backgroundTransitionFraction) @@ -1139,10 +1438,13 @@ final class PeerInfoHeaderNode: ASDisplayNode { self.avatarListNode.listContainerNode.isHidden = false if !transitionSourceAvatarFrame.width.isZero { transition.updateCornerRadius(node: self.avatarListNode.listContainerNode, cornerRadius: transitionFraction * transitionSourceAvatarFrame.width / 2.0) + transition.updateCornerRadius(node: self.avatarListNode.listContainerNode.controlsClippingNode, cornerRadius: transitionFraction * transitionSourceAvatarFrame.width / 2.0) } else { transition.updateCornerRadius(node: self.avatarListNode.listContainerNode, cornerRadius: 0.0) + transition.updateCornerRadius(node: self.avatarListNode.listContainerNode.controlsClippingNode, cornerRadius: 0.0) } } else if self.avatarListNode.listContainerNode.cornerRadius != 50.0 { + transition.updateCornerRadius(node: self.avatarListNode.listContainerNode.controlsClippingNode, cornerRadius: 50.0) transition.updateCornerRadius(node: self.avatarListNode.listContainerNode, cornerRadius: 50.0, completion: { [weak self] _ in guard let strongSelf = self else { return @@ -1152,18 +1454,26 @@ final class PeerInfoHeaderNode: ASDisplayNode { } self.avatarListNode.update(size: CGSize(), isExpanded: self.isAvatarExpanded, peer: peer, theme: presentationData.theme, transition: transition) - self.editingContentNode.avatarNode.update(peer: peer, theme: presentationData.theme) + self.editingContentNode.avatarNode.update(peer: peer, updatingAvatar: state.updatingAvatar, theme: presentationData.theme) if additive { transition.updateSublayerTransformScaleAdditive(node: self.avatarListNode.avatarContainerNode, scale: avatarScale) } else { transition.updateSublayerTransformScale(node: self.avatarListNode.avatarContainerNode, scale: avatarScale) } let apparentAvatarFrame: CGRect + let controlsClippingFrame: CGRect if self.isAvatarExpanded { let expandedAvatarCenter = CGPoint(x: expandedAvatarListSize.width / 2.0, y: expandedAvatarListSize.height / 2.0 - contentOffset / 2.0) apparentAvatarFrame = CGRect(origin: CGPoint(x: expandedAvatarCenter.x * (1.0 - transitionFraction) + transitionFraction * avatarCenter.x, y: expandedAvatarCenter.y * (1.0 - transitionFraction) + transitionFraction * avatarCenter.y), size: CGSize()) + if !transitionSourceAvatarFrame.width.isZero { + let expandedFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: expandedAvatarListSize) + controlsClippingFrame = CGRect(origin: CGPoint(x: transitionFraction * transitionSourceAvatarFrame.minX + (1.0 - transitionFraction) * expandedFrame.minX, y: transitionFraction * transitionSourceAvatarFrame.minY + (1.0 - transitionFraction) * expandedFrame.minY), size: CGSize(width: transitionFraction * transitionSourceAvatarFrame.width + (1.0 - transitionFraction) * expandedFrame.width, height: transitionFraction * transitionSourceAvatarFrame.height + (1.0 - transitionFraction) * expandedFrame.height)) + } else { + controlsClippingFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: expandedAvatarListSize) + } } else { apparentAvatarFrame = CGRect(origin: CGPoint(x: avatarCenter.x - avatarFrame.width / 2.0, y: -contentOffset + avatarOffset + avatarCenter.y - avatarFrame.height / 2.0), size: avatarFrame.size) + controlsClippingFrame = apparentAvatarFrame } if case let .animated(duration, curve) = transition, !transitionSourceAvatarFrame.width.isZero, false { let previousFrame = self.avatarListNode.frame @@ -1205,10 +1515,14 @@ final class PeerInfoHeaderNode: ASDisplayNode { transition.updateSublayerTransformScale(node: self.avatarListNode.listContainerNode, scale: innerScale) transition.updateFrameAdditive(node: self.avatarListNode.listContainerNode.contentNode, frame: CGRect(origin: CGPoint(x: innerDeltaX + expandedAvatarListSize.width / 2.0, y: innerDeltaY + expandedAvatarListSize.height / 2.0), size: CGSize())) - transition.updateFrameAdditive(node: self.avatarListNode.listContainerNode.controlsContainerTransformNode, frame: CGRect(origin: CGPoint(x: expandedAvatarListSize.width / 2.0, y: expandedAvatarListSize.height / 2.0 - innerDeltaY), size: CGSize())) - transition.updateSublayerTransformScale(node: self.avatarListNode.listContainerNode.controlsContainerNode, scale: 1.0 / innerScale) - transition.updateSublayerTransformScaleAdditive(node: self.avatarListNode.listContainerNode.controlsContainerTransformNode, scale: 1.0 / avatarListContainerScale) - transition.updateFrameAdditive(node: self.avatarListNode.listContainerNode.shadowNode, frame: CGRect(origin: CGPoint(x: -apparentAvatarFrame.minX, y: -apparentAvatarFrame.minY), size: CGSize(width: expandedAvatarListSize.width, height: navigationHeight))) + transition.updateFrameAdditive(node: self.avatarListNode.listContainerNode.controlsClippingOffsetNode, frame: CGRect(origin: controlsClippingFrame.center, size: CGSize())) + transition.updateFrame(node: self.avatarListNode.listContainerNode.controlsClippingNode, frame: CGRect(origin: CGPoint(x: -controlsClippingFrame.width / 2.0, y: -controlsClippingFrame.height / 2.0), size: controlsClippingFrame.size)) + transition.updateFrameAdditive(node: self.avatarListNode.listContainerNode.controlsContainerNode, frame: CGRect(origin: CGPoint(x: -controlsClippingFrame.minX, y: -controlsClippingFrame.minY), size: CGSize(width: expandedAvatarListSize.width, height: expandedAvatarListSize.height))) + + transition.updateFrame(node: self.avatarListNode.listContainerNode.shadowNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: expandedAvatarListSize.width, height: navigationHeight + 20.0))) + transition.updateFrame(node: self.avatarListNode.listContainerNode.stripContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: statusBarHeight + 2.0), size: CGSize(width: expandedAvatarListSize.width, height: 3.0))) + transition.updateFrame(node: self.avatarListNode.listContainerNode.highlightContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: expandedAvatarListSize.width, height: expandedAvatarListSize.height))) + transition.updateAlpha(node: self.avatarListNode.listContainerNode.controlsContainerNode, alpha: self.isAvatarExpanded ? (1.0 - transitionFraction) : 0.0) if additive { transition.updateSublayerTransformScaleAdditive(node: self.avatarListNode.listContainerTransformNode, scale: avatarListContainerScale) @@ -1247,16 +1561,16 @@ final class PeerInfoHeaderNode: ASDisplayNode { let titleScale = (transitionFraction * transitionSourceTitleFrame.height + (1.0 - transitionFraction) * titleFrame.height * neutralTitleScale) / (titleFrame.height) let subtitleScale = max(0.01, min(10.0, (transitionFraction * transitionSourceSubtitleFrame.height + (1.0 - transitionFraction) * subtitleFrame.height * neutralSubtitleScale) / (subtitleFrame.height))) - let titleOrigin = CGPoint(x: transitionFraction * transitionSourceTitleFrame.minX + (1.0 - transitionFraction) * titleFrame.minX, y: transitionFraction * transitionSourceTitleFrame.minY + (1.0 - transitionFraction) * titleFrame.minY) - let subtitleOrigin = CGPoint(x: transitionFraction * transitionSourceSubtitleFrame.minX + (1.0 - transitionFraction) * subtitleFrame.minX, y: transitionFraction * transitionSourceSubtitleFrame.minY + (1.0 - transitionFraction) * subtitleFrame.minY) + let titleCenter = CGPoint(x: transitionFraction * transitionSourceTitleFrame.midX + (1.0 - transitionFraction) * titleFrame.midX, y: transitionFraction * transitionSourceTitleFrame.midY + (1.0 - transitionFraction) * titleFrame.midY) + let subtitleCenter = CGPoint(x: transitionFraction * transitionSourceSubtitleFrame.midX + (1.0 - transitionFraction) * subtitleFrame.midX, y: transitionFraction * transitionSourceSubtitleFrame.midY + (1.0 - transitionFraction) * subtitleFrame.midY) - let rawTitleFrame = CGRect(origin: titleOrigin, size: titleFrame.size) + let rawTitleFrame = CGRect(origin: CGPoint(x: titleCenter.x - titleFrame.size.width * titleScale / 2.0, y: titleCenter.y - titleFrame.size.height * titleScale / 2.0), size: CGSize(width: titleFrame.size.width * titleScale, height: titleFrame.size.height * titleScale)) self.titleNodeRawContainer.frame = rawTitleFrame - transition.updateFrameAdditiveToCenter(node: self.titleNodeContainer, frame: rawTitleFrame.offsetBy(dx: rawTitleFrame.width * 0.5 * (titleScale - 1.0), dy: titleOffset + rawTitleFrame.height * 0.5 * (titleScale - 1.0))) - transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(), size: titleFrame.size)) - let rawSubtitleFrame = CGRect(origin: subtitleOrigin, size: subtitleFrame.size) + transition.updateFrameAdditiveToCenter(node: self.titleNodeContainer, frame: CGRect(origin: rawTitleFrame.center, size: CGSize())) + transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: -titleFrame.size.width * 1.0 / titleScale / 2.0, y: -titleFrame.size.height * 1.0 / titleScale / 2.0), size: titleFrame.size)) + let rawSubtitleFrame = CGRect(origin: CGPoint(x: subtitleCenter.x - subtitleFrame.size.width / 2.0, y: subtitleCenter.y - subtitleFrame.size.height / 2.0), size: subtitleFrame.size) self.subtitleNodeRawContainer.frame = rawSubtitleFrame - transition.updateFrameAdditiveToCenter(node: self.subtitleNodeContainer, frame: rawSubtitleFrame.offsetBy(dx: rawSubtitleFrame.width * 0.5 * (subtitleScale - 1.0), dy: titleOffset + rawSubtitleFrame.height * 0.5 * (subtitleScale - 1.0))) + transition.updateFrameAdditiveToCenter(node: self.subtitleNodeContainer, frame: rawSubtitleFrame) transition.updateFrame(node: self.subtitleNode, frame: CGRect(origin: CGPoint(), size: subtitleFrame.size)) transition.updateSublayerTransformScale(node: self.titleNodeContainer, scale: titleScale) transition.updateSublayerTransformScale(node: self.subtitleNodeContainer, scale: subtitleScale) diff --git a/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoPaneContainerNode.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoPaneContainerNode.swift index 976036603b..4efc5d5bcd 100644 --- a/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoPaneContainerNode.swift +++ b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoPaneContainerNode.swift @@ -128,7 +128,12 @@ final class PeerInfoPaneTabsContainerNode: ASDisplayNode { super.init() - self.scrollNode.view.disablesInteractiveTransitionGestureRecognizer = true + self.scrollNode.view.disablesInteractiveTransitionGestureRecognizerNow = { [weak self] in + guard let strongSelf = self else { + return false + } + return strongSelf.scrollNode.view.contentOffset.x > .ulpOfOne + } self.scrollNode.view.showsHorizontalScrollIndicator = false self.scrollNode.view.scrollsToTop = false if #available(iOS 11.0, *) { @@ -249,7 +254,7 @@ final class PeerInfoPaneTabsContainerNode: ASDisplayNode { } leftOffset += paneNodeSize.width + spacing } - self.scrollNode.view.contentSize = CGSize(width: leftOffset + sideInset, height: size.height) + self.scrollNode.view.contentSize = CGSize(width: leftOffset - spacing + sideInset, height: size.height) } if let selectedFrame = selectedFrame { diff --git a/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoScreen.swift index 26aa03313d..5466014007 100644 --- a/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoScreen.swift @@ -28,6 +28,10 @@ import ContextUI import OpenInExternalAppUI import SafariServices import GalleryUI +import LegacyUI +import MapResourceToAvatarSizes +import LegacyComponents +import WebSearchUI protocol PeerInfoScreenItem: class { var id: AnyHashable { get } @@ -77,6 +81,7 @@ private final class PeerInfoScreenItemSectionContainerNode: ASDisplayNode { self.bottomSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor var contentHeight: CGFloat = 0.0 + var contentWithBackgroundHeight: CGFloat = 0.0 for i in 0 ..< items.count { let item = items[i] @@ -100,13 +105,28 @@ private final class PeerInfoScreenItemSectionContainerNode: ASDisplayNode { let itemTransition: ContainedViewLayoutTransition = wasAdded ? .immediate : transition - let itemHeight = itemNode.update(width: width, presentationData: presentationData, item: item, topItem: i == 0 ? nil : items[i - 1], bottomItem: (i == items.count - 1) ? nil : items[i + 1], transition: itemTransition) + let bottomItem: PeerInfoScreenItem? + if i == items.count - 1 { + bottomItem = nil + } else if items[i + 1] is PeerInfoScreenCommentItem { + bottomItem = nil + } else { + bottomItem = items[i + 1] + } + + let itemHeight = itemNode.update(width: width, presentationData: presentationData, item: item, topItem: i == 0 ? nil : items[i - 1], bottomItem: bottomItem, transition: itemTransition) let itemFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: width, height: itemHeight)) itemTransition.updateFrame(node: itemNode, frame: itemFrame) if wasAdded { itemNode.alpha = 0.0 transition.updateAlpha(node: itemNode, alpha: 1.0) } + + if item is PeerInfoScreenCommentItem { + + } else { + contentWithBackgroundHeight += itemHeight + } contentHeight += itemHeight } @@ -124,9 +144,9 @@ private final class PeerInfoScreenItemSectionContainerNode: ASDisplayNode { } } - transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: contentHeight))) + transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: contentWithBackgroundHeight))) transition.updateFrame(node: self.topSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: width, height: UIScreenPixel))) - transition.updateFrame(node: self.bottomSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: width, height: UIScreenPixel))) + transition.updateFrame(node: self.bottomSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentWithBackgroundHeight), size: CGSize(width: width, height: UIScreenPixel))) if contentHeight.isZero { transition.updateAlpha(node: self.topSeparatorNode, alpha: 0.0) @@ -280,6 +300,12 @@ private enum PeerInfoBotCommand { case privacy } +private enum PeerInfoParticipantsSection { + case members + case admins + case banned +} + private final class PeerInfoInteraction { let openUsername: (String) -> Void let openPhone: (String) -> Void @@ -293,6 +319,10 @@ private final class PeerInfoInteraction { let openShareBot: () -> Void let openAddBotToGroup: () -> Void let performBotCommand: (PeerInfoBotCommand) -> Void + let editingOpenPublicLinkSetup: () -> Void + let editingOpenDiscussionGroupSetup: () -> Void + let editingToggleMessageSignatures: (Bool) -> Void + let openParticipantsSection: (PeerInfoParticipantsSection) -> Void init( openUsername: @escaping (String) -> Void, @@ -306,7 +336,11 @@ private final class PeerInfoInteraction { openReport: @escaping () -> Void, openShareBot: @escaping () -> Void, openAddBotToGroup: @escaping () -> Void, - performBotCommand: @escaping (PeerInfoBotCommand) -> Void + performBotCommand: @escaping (PeerInfoBotCommand) -> Void, + editingOpenPublicLinkSetup: @escaping () -> Void, + editingOpenDiscussionGroupSetup: @escaping () -> Void, + editingToggleMessageSignatures: @escaping (Bool) -> Void, + openParticipantsSection: @escaping (PeerInfoParticipantsSection) -> Void ) { self.openUsername = openUsername self.openPhone = openPhone @@ -320,6 +354,10 @@ private final class PeerInfoInteraction { self.openShareBot = openShareBot self.openAddBotToGroup = openAddBotToGroup self.performBotCommand = performBotCommand + self.editingOpenPublicLinkSetup = editingOpenPublicLinkSetup + self.editingOpenDiscussionGroupSetup = editingOpenDiscussionGroupSetup + self.editingToggleMessageSignatures = editingToggleMessageSignatures + self.openParticipantsSection = openParticipantsSection } } @@ -341,38 +379,11 @@ private func peerInfoSectionItems(data: PeerInfoScreenData?, presentationData: P } if let cachedData = data.cachedData as? CachedUserData { if let about = cachedData.about { - items.append(PeerInfoScreenLabeledValueItem(id: 0, label: "bio", text: about, textColor: .primary, textBehavior: .multiLine(maxLines: 10), action: nil)) + items.append(PeerInfoScreenLabeledValueItem(id: 0, label: presentationData.strings.Profile_About, text: about, textColor: .primary, textBehavior: .multiLine(maxLines: 10), action: nil)) } } if !data.isContact { - if let botInfo = user.botInfo { - if botInfo.flags.contains(.worksWithGroups) { - items.append(PeerInfoScreenActionItem(id: 6, text: presentationData.strings.UserInfo_InviteBotToGroup, action: { - interaction.openAddBotToGroup() - })) - } - items.append(PeerInfoScreenActionItem(id: 7, text: presentationData.strings.UserInfo_ShareBot, action: { - interaction.openShareBot() - })) - - if let cachedData = data.cachedData as? CachedUserData, let botInfo = cachedData.botInfo { - for command in botInfo.commands { - if command.text == "settings" { - items.append(PeerInfoScreenActionItem(id: 8, text: presentationData.strings.UserInfo_BotSettings, action: { - interaction.performBotCommand(.settings) - })) - } else if command.text == "help" { - items.append(PeerInfoScreenActionItem(id: 9, text: presentationData.strings.UserInfo_BotHelp, action: { - interaction.performBotCommand(.help) - })) - } else if command.text == "privacy" { - items.append(PeerInfoScreenActionItem(id: 10, text: presentationData.strings.UserInfo_BotPrivacy, action: { - interaction.performBotCommand(.privacy) - })) - } - } - } - } else { + if user.botInfo == nil { items.append(PeerInfoScreenActionItem(id: 3, text: "Add Contact", action: { interaction.openAddContact() })) @@ -397,6 +408,54 @@ private func peerInfoSectionItems(data: PeerInfoScreenData?, presentationData: P })) } } + } else if let channel = data.peer as? TelegramChannel { + let ItemUsername = 1 + let ItemAbout = 2 + let ItemAdmins = 3 + let ItemMembers = 4 + let ItemBanned = 5 + let ItemReport = 6 + + if let username = channel.username { + items.append(PeerInfoScreenLabeledValueItem(id: ItemUsername, label: presentationData.strings.Channel_LinkItem, text: "https://t.me/\(username)", textColor: .accent, action: { + interaction.openUsername(username) + })) + } + if let cachedData = data.cachedData as? CachedChannelData { + if let about = cachedData.about { + items.append(PeerInfoScreenLabeledValueItem(id: ItemAbout, label: presentationData.strings.Profile_About, text: about, textColor: .primary, textBehavior: .multiLine(maxLines: 10), action: nil)) + } + + if case .broadcast = channel.info { + var canEditMembers = false + if channel.hasPermission(.banMembers) { + canEditMembers = true + } + if canEditMembers { + if channel.adminRights != nil || channel.flags.contains(.isCreator) { + let adminCount = cachedData.participantsSummary.adminCount ?? 0 + let memberCount = cachedData.participantsSummary.memberCount ?? 0 + let bannedCount = cachedData.participantsSummary.kickedCount ?? 0 + + items.append(PeerInfoScreenDisclosureItem(id: ItemAdmins, label: "\(adminCount == 0 ? "" : "\(presentationStringsFormattedNumber(adminCount, presentationData.dateTimeFormat.groupingSeparator))")", text: presentationData.strings.GroupInfo_Administrators, action: { + interaction.openParticipantsSection(.admins) + })) + items.append(PeerInfoScreenDisclosureItem(id: ItemMembers, label: "\(memberCount == 0 ? "" : "\(presentationStringsFormattedNumber(memberCount, presentationData.dateTimeFormat.groupingSeparator))")", text: presentationData.strings.Channel_Info_Subscribers, action: { + interaction.openParticipantsSection(.members) + })) + items.append(PeerInfoScreenDisclosureItem(id: ItemBanned, label: "\(bannedCount == 0 ? "" : "\(presentationStringsFormattedNumber(bannedCount, presentationData.dateTimeFormat.groupingSeparator))")", text: presentationData.strings.GroupInfo_Permissions_Removed, action: { + interaction.openParticipantsSection(.banned) + })) + } + } + } + } + } else if let group = data.peer as? TelegramGroup { + if let cachedData = data.cachedData as? CachedGroupData { + if let about = cachedData.about { + items.append(PeerInfoScreenLabeledValueItem(id: 0, label: presentationData.strings.Profile_About, text: about, textColor: .primary, textBehavior: .multiLine(maxLines: 10), action: nil)) + } + } } return items } @@ -407,34 +466,32 @@ private func editingInfoSectionItems(data: PeerInfoScreenData?, presentationData } var items: [PeerInfoScreenItem] = [] - if let _ = data.peer as? TelegramUser { - if let notificationSettings = data.notificationSettings { - let notificationsLabel: String - let soundLabel: String - let notificationSettings = notificationSettings as? TelegramPeerNotificationSettings ?? TelegramPeerNotificationSettings.defaultSettings - if case let .muted(until) = notificationSettings.muteState, until >= Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970) { - if until < Int32.max - 1 { - notificationsLabel = stringForRemainingMuteInterval(strings: presentationData.strings, muteInterval: until) - } else { - notificationsLabel = presentationData.strings.UserInfo_NotificationsDisabled - } + if let notificationSettings = data.notificationSettings { + let notificationsLabel: String + let soundLabel: String + let notificationSettings = notificationSettings as? TelegramPeerNotificationSettings ?? TelegramPeerNotificationSettings.defaultSettings + if case let .muted(until) = notificationSettings.muteState, until >= Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970) { + if until < Int32.max - 1 { + notificationsLabel = stringForRemainingMuteInterval(strings: presentationData.strings, muteInterval: until) } else { - notificationsLabel = presentationData.strings.UserInfo_NotificationsEnabled + notificationsLabel = presentationData.strings.UserInfo_NotificationsDisabled } - - let globalNotificationSettings: GlobalNotificationSettings = data.globalNotificationSettings ?? GlobalNotificationSettings.defaultSettings - soundLabel = localizedPeerNotificationSoundString(strings: presentationData.strings, sound: notificationSettings.messageSound, default: globalNotificationSettings.effective.privateChats.sound) - - items.append(PeerInfoScreenDisclosureItem(id: 0, label: notificationsLabel, text: "Notifications", action: { - interaction.editingOpenNotificationSettings() - })) - items.append(PeerInfoScreenDisclosureItem(id: 1, label: soundLabel, text: "Sound", action: { - interaction.editingOpenSoundSettings() - })) - items.append(PeerInfoScreenSwitchItem(id: 2, text: "Show Message Text", value: notificationSettings.displayPreviews != .hide, toggled: { value in - interaction.editingToggleShowMessageText(value) - })) + } else { + notificationsLabel = presentationData.strings.UserInfo_NotificationsEnabled } + + let globalNotificationSettings: GlobalNotificationSettings = data.globalNotificationSettings ?? GlobalNotificationSettings.defaultSettings + soundLabel = localizedPeerNotificationSoundString(strings: presentationData.strings, sound: notificationSettings.messageSound, default: globalNotificationSettings.effective.privateChats.sound) + + items.append(PeerInfoScreenDisclosureItem(id: 0, label: notificationsLabel, text: "Notifications", action: { + interaction.editingOpenNotificationSettings() + })) + items.append(PeerInfoScreenDisclosureItem(id: 1, label: soundLabel, text: "Sound", action: { + interaction.editingOpenSoundSettings() + })) + items.append(PeerInfoScreenSwitchItem(id: 2, text: "Show Message Text", value: notificationSettings.displayPreviews != .hide, toggled: { value in + interaction.editingToggleShowMessageText(value) + })) } return items @@ -443,10 +500,62 @@ private func editingInfoSectionItems(data: PeerInfoScreenData?, presentationData private func editingActionsSectionItems(data: PeerInfoScreenData?, presentationData: PresentationData, interaction: PeerInfoInteraction) -> [PeerInfoScreenItem] { var items: [PeerInfoScreenItem] = [] if let data = data { - if data.isContact { - items.append(PeerInfoScreenActionItem(id: 0, text: "Delete Contact", color: .destructive, action: { - interaction.requestDeleteContact() - })) + if let user = data.peer as? TelegramUser { + if data.isContact { + items.append(PeerInfoScreenActionItem(id: 0, text: presentationData.strings.UserInfo_DeleteContact, color: .destructive, action: { + interaction.requestDeleteContact() + })) + } + } else if let channel = data.peer as? TelegramChannel { + if channel.flags.contains(.isCreator) { + let linkText: String + if let username = channel.username { + linkText = "@\(username)" + } else { + linkText = presentationData.strings.Channel_Setup_TypePrivate + } + items.append(PeerInfoScreenDisclosureItem(id: 1, label: linkText, text: presentationData.strings.Channel_TypeSetup_Title, action: { + interaction.editingOpenPublicLinkSetup() + })) + + let discussionGroupTitle: String + if let cachedData = data.cachedData as? CachedChannelData { + if let peer = data.linkedDiscussionPeer { + if let addressName = peer.addressName, !addressName.isEmpty { + discussionGroupTitle = "@\(addressName)" + } else { + discussionGroupTitle = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + } + } else { + discussionGroupTitle = presentationData.strings.Channel_DiscussionGroupAdd + } + } else { + discussionGroupTitle = "..." + } + + items.append(PeerInfoScreenDisclosureItem(id: 2, label: discussionGroupTitle, text: presentationData.strings.Channel_DiscussionGroup, action: { + interaction.editingOpenDiscussionGroupSetup() + })) + //items.append(PeerInfoScreenCommentItem(id: 3, text: presentationData.strings.Channel_DiscussionGroupInfo)) + + let messagesShouldHaveSignatures: Bool + switch channel.info { + case let .broadcast(info): + messagesShouldHaveSignatures = info.flags.contains(.messagesShouldHaveSignatures) + default: + messagesShouldHaveSignatures = false + } + items.append(PeerInfoScreenSwitchItem(id: 4, text: presentationData.strings.Channel_SignMessages, value: messagesShouldHaveSignatures, toggled: { value in + interaction.editingToggleMessageSignatures(value) + })) + items.append(PeerInfoScreenCommentItem(id: 5, text: presentationData.strings.Channel_SignMessages_Help)) + } + } else if let group = data.peer as? TelegramGroup { + if case .creator = group.role { + items.append(PeerInfoScreenDisclosureItem(id: 1, label: presentationData.strings.Group_Setup_TypePrivate, text: presentationData.strings.Channel_TypeSetup_Title, action: { + interaction.editingOpenPublicLinkSetup() + })) + } } } return items @@ -486,13 +595,17 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD private(set) var data: PeerInfoScreenData? private(set) var state = PeerInfoState( isEditing: false, - isSearching: false, - selectedMessageIds: nil + selectedMessageIds: nil, + updatingAvatar: nil ) private var dataDisposable: Disposable? private let activeActionDisposable = MetaDisposable() private let resolveUrlDisposable = MetaDisposable() + private let toggleShouldChannelMessagesSignaturesDisposable = MetaDisposable() + + private let updateAvatarDisposable = MetaDisposable() + private let currentAvatarMixin = Atomic(value: nil) private let _ready = Promise() var ready: Promise { @@ -507,6 +620,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD self.presentationData = context.sharedContext.currentPresentationData.with { $0 } self.scrollNode = ASScrollNode() + self.scrollNode.view.delaysContentTouches = false self.headerNode = PeerInfoHeaderNode(context: context, avatarInitiallyExpanded: avatarInitiallyExpanded) self.infoSection = PeerInfoScreenItemSectionContainerNode(id: 0) @@ -552,6 +666,18 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD }, performBotCommand: { [weak self] command in self?.performBotCommand(command: command) + }, + editingOpenPublicLinkSetup: { [weak self] in + self?.editingOpenPublicLinkSetup() + }, + editingOpenDiscussionGroupSetup: { [weak self] in + self?.editingOpenDiscussionGroupSetup() + }, + editingToggleMessageSignatures: { [weak self] value in + self?.editingToggleMessageSignatures(value: value) + }, + openParticipantsSection: { [weak self] section in + self?.openParticipantsSection(section: section) } ) @@ -950,6 +1076,10 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD })) } + self.headerNode.requestOpenAvatarForEditing = { [weak self] in + self?.openAvatarForEditing() + } + self.headerNode.navigationButtonContainer.performAction = { [weak self] key in guard let strongSelf = self else { return @@ -970,8 +1100,12 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD strongSelf.controller?.navigationItem.setLeftBarButton(UIBarButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, style: .plain, target: strongSelf, action: #selector(strongSelf.editingCancelPressed)), animated: true) case .done, .cancel: if case .done = key { - if let data = strongSelf.data, data.isContact { - if let peer = data.peer as? TelegramUser { + guard let data = strongSelf.data else { + strongSelf.headerNode.navigationButtonContainer.performAction?(.cancel) + return + } + if let peer = data.peer as? TelegramUser { + if data.isContact { let firstName = strongSelf.headerNode.editingContentNode.editingTextForKey(.firstName) ?? "" let lastName = strongSelf.headerNode.editingContentNode.editingTextForKey(.lastName) ?? "" @@ -1012,7 +1146,44 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } else { strongSelf.headerNode.navigationButtonContainer.performAction?(.cancel) } + } else { + strongSelf.headerNode.navigationButtonContainer.performAction?(.cancel) } + } else if let group = data.peer as? TelegramGroup, canEditPeerInfo(peer: group) { + let title = strongSelf.headerNode.editingContentNode.editingTextForKey(.title) ?? "" + + } else if let channel = data.peer as? TelegramChannel, canEditPeerInfo(peer: channel) { + let title = strongSelf.headerNode.editingContentNode.editingTextForKey(.title) ?? "" + let description = strongSelf.headerNode.editingContentNode.editingTextForKey(.description) ?? "" + + var updateDataSignals: [Signal] = [] + + if title != channel.title { + updateDataSignals.append( + updatePeerTitle(account: strongSelf.context.account, peerId: channel.id, title: title) + |> ignoreValues + |> mapError { _ in return Void() } + ) + } + if description != (data.cachedData as? CachedChannelData)?.about { + updateDataSignals.append( + updatePeerDescription(account: strongSelf.context.account, peerId: channel.id, description: description.isEmpty ? nil : description) + |> ignoreValues + |> mapError { _ in return Void() } + ) + } + strongSelf.activeActionDisposable.set((combineLatest(updateDataSignals) + |> deliverOnMainQueue).start(error: { _ in + guard let strongSelf = self else { + return + } + strongSelf.headerNode.navigationButtonContainer.performAction?(.cancel) + }, completed: { + guard let strongSelf = self else { + return + } + strongSelf.headerNode.navigationButtonContainer.performAction?(.cancel) + })) } else { strongSelf.headerNode.navigationButtonContainer.performAction?(.cancel) } @@ -1060,6 +1231,8 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD self.activeActionDisposable.dispose() self.resolveUrlDisposable.dispose() self.hiddenAvatarRepresentationDisposable.dispose() + self.toggleShouldChannelMessagesSignaturesDisposable.dispose() + self.updateAvatarDisposable.dispose() } override func didLoad() { @@ -1242,16 +1415,86 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD let dismissAction: () -> Void = { [weak actionSheet] in actionSheet?.dismissAnimated() } - var reportSpam = false - var deleteChat = false var items: [ActionSheetItem] = [] + items.append(ActionSheetButtonItem(title: presentationData.strings.ChatSearch_SearchPlaceholder, color: .accent, action: { [weak self] in + dismissAction() + self?.openChatWithMessageSearch() + })) if let user = peer as? TelegramUser { + if let botInfo = user.botInfo { + if botInfo.flags.contains(.worksWithGroups) { + items.append(ActionSheetButtonItem(title: presentationData.strings.UserInfo_InviteBotToGroup, color: .accent, action: { [weak self] in + dismissAction() + self?.openAddBotToGroup() + })) + } + if user.username != nil { + items.append(ActionSheetButtonItem(title: presentationData.strings.UserInfo_ShareBot, color: .accent, action: { [weak self] in + dismissAction() + self?.openShareBot() + })) + } + + if let cachedData = data.cachedData as? CachedUserData, let botInfo = cachedData.botInfo { + for command in botInfo.commands { + if command.text == "settings" { + items.append(ActionSheetButtonItem(title: presentationData.strings.UserInfo_BotSettings, color: .accent, action: { [weak self] in + dismissAction() + self?.performBotCommand(command: .settings) + })) + } else if command.text == "help" { + items.append(ActionSheetButtonItem(title: presentationData.strings.UserInfo_BotHelp, color: .accent, action: { [weak self] in + dismissAction() + self?.performBotCommand(command: .help) + })) + } else if command.text == "privacy" { + items.append(ActionSheetButtonItem(title: presentationData.strings.UserInfo_BotPrivacy, color: .accent, action: { [weak self] in + dismissAction() + self?.performBotCommand(command: .privacy) + })) + } + } + } + } + if user.botInfo == nil && !user.flags.contains(.isSupport) { items.append(ActionSheetButtonItem(title: presentationData.strings.UserInfo_StartSecretChat, color: .accent, action: { [weak self] in dismissAction() self?.openStartSecretChat() })) } + } else if let channel = peer as? TelegramChannel { + var canReport = true + if channel.isVerified { + canReport = false + } + if channel.adminRights != nil { + canReport = false + } + if channel.flags.contains(.isCreator) { + canReport = false + } + if canReport { + items.append(ActionSheetButtonItem(title: presentationData.strings.ReportPeer_Report, color: .destructive, action: { [weak self] in + dismissAction() + self?.openReport() + })) + } + if channel.flags.contains(.isCreator) { + items.append(ActionSheetButtonItem(title: presentationData.strings.ChannelInfo_DeleteChannel, color: .destructive, action: { [weak self] in + dismissAction() + self?.openDeleteChannel() + })) + } else { + if case .member = channel.participationStatus { + items.append(ActionSheetButtonItem(title: presentationData.strings.Channel_LeaveChannel, color: .destructive, action: { [weak self] in + dismissAction() + self?.openLeaveChannel() + })) + } + } + } else if let group = peer as? TelegramGroup { + } actionSheet.setItemGroups([ ActionSheetItemGroup(items: items), @@ -1263,6 +1506,12 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } } + private func openChatWithMessageSearch() { + if let navigationController = (self.controller?.navigationController as? NavigationController) { + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(self.peerId), activateMessageSearch: true)) + } + } + private func openStartSecretChat() { let peerId = self.peerId let _ = (self.context.account.postbox.transaction { transaction -> (Peer?, PeerId?) in @@ -1710,6 +1959,235 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD }) } + private func editingOpenPublicLinkSetup() { + self.controller?.push(channelVisibilityController(context: self.context, peerId: self.peerId, mode: .generic, upgradedToSupergroup: { _, f in f() })) + } + + private func editingOpenDiscussionGroupSetup() { + self.controller?.push(channelDiscussionGroupSetupController(context: self.context, peerId: self.peerId)) + } + + private func editingToggleMessageSignatures(value: Bool) { + self.toggleShouldChannelMessagesSignaturesDisposable.set(toggleShouldChannelMessagesSignatures(account: self.context.account, peerId: self.peerId, enabled: value).start()) + } + + private func openParticipantsSection(section: PeerInfoParticipantsSection) { + switch section { + case .members: + self.controller?.push(channelMembersController(context: self.context, peerId: self.peerId)) + case .admins: + self.controller?.push(channelAdminsController(context: self.context, peerId: self.peerId)) + case .banned: + self.controller?.push(channelBlacklistController(context: self.context, peerId: self.peerId)) + } + } + + private func openDeleteChannel() { + let peerId = self.peerId + let _ = (self.context.account.postbox.transaction { transaction -> Peer? in + return transaction.getPeer(peerId) + } + |> deliverOnMainQueue).start(next: { [weak self] peer in + guard let strongSelf = self, let peer = peer else { + return + } + let presentationData = strongSelf.presentationData + let actionSheet = ActionSheetController(presentationData: presentationData) + let dismissAction: () -> Void = { [weak actionSheet] in + actionSheet?.dismissAnimated() + } + actionSheet.setItemGroups([ + ActionSheetItemGroup(items: [ + ActionSheetTextItem(title: presentationData.strings.ChannelInfo_DeleteChannelConfirmation), + ActionSheetButtonItem(title: presentationData.strings.ChannelInfo_DeleteChannel, color: .destructive, action: { + dismissAction() + self?.deletePeerChat(peer: peer, globally: true) + }), + ]), + ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })]) + ]) + strongSelf.controller?.present(actionSheet, in: .window(.root)) + }) + } + + private func openLeaveChannel() { + let peerId = self.peerId + let _ = (self.context.account.postbox.transaction { transaction -> Peer? in + return transaction.getPeer(peerId) + } + |> deliverOnMainQueue).start(next: { [weak self] peer in + guard let strongSelf = self, let peer = peer else { + return + } + let presentationData = strongSelf.presentationData + let actionSheet = ActionSheetController(presentationData: presentationData) + let dismissAction: () -> Void = { [weak actionSheet] in + actionSheet?.dismissAnimated() + } + actionSheet.setItemGroups([ + ActionSheetItemGroup(items: [ + ActionSheetButtonItem(title: presentationData.strings.Channel_LeaveChannel, color: .destructive, action: { + dismissAction() + self?.deletePeerChat(peer: peer, globally: false) + }), + ]), + ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })]) + ]) + strongSelf.controller?.present(actionSheet, in: .window(.root)) + }) + } + + private func deletePeerChat(peer: Peer, globally: Bool) { + guard let controller = self.controller, let navigationController = controller.navigationController as? NavigationController else { + return + } + guard let tabController = navigationController.viewControllers.first as? TabBarController else { + return + } + for childController in tabController.controllers { + if let chatListController = childController as? ChatListController { + chatListController.maybeAskForPeerChatRemoval(peer: RenderedPeer(peer: peer), deleteGloballyIfPossible: globally, completion: { [weak navigationController] deleted in + if deleted { + navigationController?.popToRoot(animated: true) + } + }, removed: { + }) + break + } + } + } + + private func openAvatarForEditing() { + guard let peer = self.data?.peer, canEditPeerInfo(peer: peer) else { + return + } + + let peerId = self.peerId + let _ = (self.context.account.postbox.transaction { transaction -> (Peer?, SearchBotsConfiguration) in + return (transaction.getPeer(peerId), currentSearchBotsConfiguration(transaction: transaction)) + } + |> deliverOnMainQueue).start(next: { [weak self] peer, searchBotsConfiguration in + guard let strongSelf = self, let peer = peer else { + return + } + + let presentationData = strongSelf.presentationData + + let legacyController = LegacyController(presentation: .custom, theme: presentationData.theme) + legacyController.statusBar.statusBarStyle = .Ignore + + let emptyController = LegacyEmptyController(context: legacyController.context)! + let navigationController = makeLegacyNavigationController(rootController: emptyController) + navigationController.setNavigationBarHidden(true, animated: false) + navigationController.navigationBar.transform = CGAffineTransform(translationX: -1000.0, y: 0.0) + + legacyController.bind(controller: navigationController) + + strongSelf.controller?.present(legacyController, in: .window(.root)) + + var hasPhotos = false + if !peer.profileImageRepresentations.isEmpty { + hasPhotos = true + } + + let completedImpl: (UIImage) -> Void = { image in + guard let strongSelf = self, let data = image.jpegData(compressionQuality: 0.6) else { + return + } + + let resource = LocalFileMediaResource(fileId: arc4random64()) + strongSelf.context.account.postbox.mediaBox.storeResourceData(resource.id, data: data) + let representation = TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 640, height: 640), resource: resource) + + strongSelf.state = strongSelf.state.withUpdatingAvatar(.image(representation)) + if let (layout, navigationHeight) = strongSelf.validLayout { + strongSelf.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate, additive: false) + } + + let postbox = strongSelf.context.account.postbox + strongSelf.updateAvatarDisposable.set((updatePeerPhoto(postbox: strongSelf.context.account.postbox, network: strongSelf.context.account.network, stateManager: strongSelf.context.account.stateManager, accountPeerId: strongSelf.context.account.peerId, peerId: strongSelf.peerId, photo: uploadedPeerPhoto(postbox: strongSelf.context.account.postbox, network: strongSelf.context.account.network, resource: resource), mapResourceToAvatarSizes: { resource, representations in + return mapResourceToAvatarSizes(postbox: postbox, resource: resource, representations: representations) + }) + |> deliverOnMainQueue).start(next: { result in + guard let strongSelf = self else { + return + } + switch result { + case .complete: + strongSelf.state = strongSelf.state.withUpdatingAvatar(nil) + if let (layout, navigationHeight) = strongSelf.validLayout { + strongSelf.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate, additive: false) + } + case .progress: + break + } + })) + } + + let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: hasPhotos, hasViewButton: false, personalPhoto: false, saveEditedPhotos: false, saveCapturedMedia: false, signup: false)! + let _ = strongSelf.currentAvatarMixin.swap(mixin) + mixin.requestSearchController = { assetsController in + guard let strongSelf = self else { + return + } + let controller = WebSearchController(context: strongSelf.context, peer: peer, configuration: searchBotsConfiguration, mode: .avatar(initialQuery: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), completion: { result in + assetsController?.dismiss() + completedImpl(result) + })) + strongSelf.controller?.present(controller, in: .window(.root)) + } + mixin.didFinishWithImage = { image in + if let image = image { + completedImpl(image) + } + } + mixin.didFinishWithDelete = { + guard let strongSelf = self else { + return + } + + let _ = strongSelf.currentAvatarMixin.swap(nil) + if let profileImage = peer.smallProfileImage { + strongSelf.state = strongSelf.state.withUpdatingAvatar(.none) + if let (layout, navigationHeight) = strongSelf.validLayout { + strongSelf.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate, additive: false) + } + } + let postbox = strongSelf.context.account.postbox + strongSelf.updateAvatarDisposable.set((updatePeerPhoto(postbox: strongSelf.context.account.postbox, network: strongSelf.context.account.network, stateManager: strongSelf.context.account.stateManager, accountPeerId: strongSelf.context.account.peerId, peerId: strongSelf.peerId, photo: nil, mapResourceToAvatarSizes: { resource, representations in + return mapResourceToAvatarSizes(postbox: postbox, resource: resource, representations: representations) + }) + |> deliverOnMainQueue).start(next: { result in + guard let strongSelf = self else { + return + } + switch result { + case .complete: + strongSelf.state = strongSelf.state.withUpdatingAvatar(nil) + if let (layout, navigationHeight) = strongSelf.validLayout { + strongSelf.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate, additive: false) + } + case .progress: + break + } + })) + } + mixin.didDismiss = { [weak legacyController] in + guard let strongSelf = self else { + return + } + let _ = strongSelf.currentAvatarMixin.swap(nil) + legacyController?.dismiss() + } + let menuController = mixin.present() + if let menuController = menuController { + menuController.customRemoveFromParentViewController = { [weak legacyController] in + legacyController?.dismiss() + } + } + }) + } + func deleteMessages(messageIds: Set?) { if let messageIds = messageIds ?? self.state.selectedMessageIds, !messageIds.isEmpty { self.activeActionDisposable.set((self.context.sharedContext.chatAvailableMessageActions(postbox: self.context.account.postbox, accountPeerId: self.context.account.peerId, messageIds: messageIds) @@ -2353,7 +2831,7 @@ public final class PeerInfoScreen: ViewController { badgeStrokeColor: baseNavigationBarPresentationData.theme.badgeStrokeColor, badgeTextColor: baseNavigationBarPresentationData.theme.badgeTextColor ), strings: baseNavigationBarPresentationData.strings)) - self.navigationBar?.makeCustomTransitionNode = { [weak self] other in + self.navigationBar?.makeCustomTransitionNode = { [weak self] other, isInteractive in guard let strongSelf = self else { return nil } @@ -2363,7 +2841,10 @@ public final class PeerInfoScreen: ViewController { if strongSelf.controllerNode.scrollNode.view.contentOffset.y > .ulpOfOne { return nil } - if strongSelf.controllerNode.headerNode.isAvatarExpanded { + if isInteractive && strongSelf.controllerNode.headerNode.isAvatarExpanded { + return nil + } + if other.contentNode != nil { return nil } if let tag = other.userInfo as? PeerInfoNavigationSourceTag, tag.peerId == peerId { @@ -2456,7 +2937,6 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig private var previousBackButtonArrow: ASDisplayNode? private var currentBackButtonArrow: ASDisplayNode? private var previousBackButtonBadge: ASDisplayNode? - private var previousRightButton: ASDisplayNode? private var currentBackButton: ASDisplayNode? private var previousTitleNode: (ASDisplayNode, TextNode)? @@ -2500,10 +2980,6 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig self.previousBackButtonBadge = previousBackButtonBadge self.addSubnode(previousBackButtonBadge) } - if let previousRightButton = bottomNavigationBar.makeTransitionRightButtonNode(accentColor: self.presentationData.theme.rootController.navigationBar.accentTextColor) { - self.previousRightButton = previousRightButton - self.addSubnode(previousRightButton) - } if let currentBackButton = topNavigationBar.makeTransitionBackButtonNode(accentColor: self.screenNode.headerNode.isAvatarExpanded ? .white : self.presentationData.theme.rootController.navigationBar.accentTextColor) { self.currentBackButton = currentBackButton self.addSubnode(currentBackButton) @@ -2512,12 +2988,14 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig let previousTitleNode = previousTitleView.titleNode.makeCopy() let previousTitleContainerNode = ASDisplayNode() previousTitleContainerNode.addSubnode(previousTitleNode) + previousTitleNode.frame = previousTitleNode.frame.offsetBy(dx: -previousTitleNode.frame.width / 2.0, dy: -previousTitleNode.frame.height / 2.0) self.previousTitleNode = (previousTitleContainerNode, previousTitleNode) self.addSubnode(previousTitleContainerNode) let previousStatusNode = previousTitleView.activityNode.makeCopy() let previousStatusContainerNode = ASDisplayNode() previousStatusContainerNode.addSubnode(previousStatusNode) + previousStatusNode.frame = previousStatusNode.frame.offsetBy(dx: -previousStatusNode.frame.width / 2.0, dy: -previousStatusNode.frame.height / 2.0) self.previousStatusNode = (previousStatusContainerNode, previousStatusNode) self.addSubnode(previousStatusContainerNode) } @@ -2553,12 +3031,6 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig transition.updateAlpha(node: previousBackButtonBadge, alpha: fraction) } - if let previousRightButton = self.previousRightButton { - let previousRightButtonFrame = bottomNavigationBar.rightButtonNode.view.convert(bottomNavigationBar.rightButtonNode.view.bounds, to: bottomNavigationBar.view) - previousRightButton.frame = previousRightButtonFrame - transition.updateAlpha(node: previousRightButton, alpha: fraction) - } - if let currentBackButton = self.currentBackButton { let currentBackButtonFrame = topNavigationBar.backButtonNode.view.convert(topNavigationBar.backButtonNode.view.bounds, to: topNavigationBar.view) transition.updateFrame(node: currentBackButton, frame: currentBackButtonFrame.offsetBy(dx: fraction * 12.0, dy: 0.0)) @@ -2566,7 +3038,7 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig transition.updateAlpha(node: currentBackButton, alpha: (1.0 - fraction)) } - if let previousTitleView = bottomNavigationBar.titleView as? ChatTitleView, let avatarNode = previousTitleView.avatarNode, let (previousTitleContainerNode, previousTitleNode) = self.previousTitleNode, let (previousStatusContainerNode, previousStatusNode) = self.previousStatusNode { + if let previousTitleView = bottomNavigationBar.titleView as? ChatTitleView, let _ = (bottomNavigationBar.rightButtonNode.singleCustomNode as? ChatAvatarNavigationNode)?.avatarNode, let (previousTitleContainerNode, previousTitleNode) = self.previousTitleNode, let (previousStatusContainerNode, previousStatusNode) = self.previousStatusNode { let previousTitleFrame = previousTitleView.titleNode.view.convert(previousTitleView.titleNode.bounds, to: bottomNavigationBar.view) let previousStatusFrame = previousTitleView.activityNode.view.convert(previousTitleView.activityNode.bounds, to: bottomNavigationBar.view) @@ -2578,10 +3050,10 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig let titleScale = (fraction * previousTitleNode.bounds.height + (1.0 - fraction) * self.headerNode.titleNode.bounds.height) / previousTitleNode.bounds.height let subtitleScale = max(0.01, min(10.0, (fraction * previousStatusNode.bounds.height + (1.0 - fraction) * self.headerNode.subtitleNode.bounds.height) / previousStatusNode.bounds.height)) - transition.updateFrame(node: previousTitleContainerNode, frame: CGRect(origin: self.headerNode.titleNodeRawContainer.frame.origin.offsetBy(dx: previousTitleFrame.size.width * 0.5 * (titleScale - 1.0), dy: previousTitleFrame.size.height * 0.5 * (titleScale - 1.0)), size: previousTitleFrame.size)) - transition.updateFrame(node: previousTitleNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: previousTitleFrame.size)) - transition.updateFrame(node: previousStatusContainerNode, frame: CGRect(origin: self.headerNode.subtitleNodeRawContainer.frame.origin.offsetBy(dx: previousStatusFrame.size.width * 0.5 * (subtitleScale - 1.0), dy: previousStatusFrame.size.height * 0.5 * (subtitleScale - 1.0)), size: previousStatusFrame.size)) - transition.updateFrame(node: previousStatusNode, frame: CGRect(origin: CGPoint(), size: previousStatusFrame.size)) + transition.updateFrame(node: previousTitleContainerNode, frame: CGRect(origin: self.headerNode.titleNodeRawContainer.frame.center, size: CGSize())) + transition.updateFrame(node: previousTitleNode, frame: CGRect(origin: CGPoint(x: -previousTitleFrame.width / 2.0, y: -previousTitleFrame.height / 2.0), size: previousTitleFrame.size)) + transition.updateFrame(node: previousStatusContainerNode, frame: CGRect(origin: self.headerNode.subtitleNodeRawContainer.frame.center, size: CGSize())) + transition.updateFrame(node: previousStatusNode, frame: CGRect(origin: CGPoint(x: -previousStatusFrame.size.width / 2.0, y: -previousStatusFrame.size.height / 2.0), size: previousStatusFrame.size)) transition.updateSublayerTransformScale(node: previousTitleContainerNode, scale: titleScale) transition.updateSublayerTransformScale(node: previousStatusContainerNode, scale: subtitleScale) diff --git a/submodules/TelegramUI/TelegramUI/SharedAccountContext.swift b/submodules/TelegramUI/TelegramUI/SharedAccountContext.swift index 50cdd8a69d..8a475cb359 100644 --- a/submodules/TelegramUI/TelegramUI/SharedAccountContext.swift +++ b/submodules/TelegramUI/TelegramUI/SharedAccountContext.swift @@ -1246,9 +1246,13 @@ public final class SharedAccountContextImpl: SharedAccountContext { private let defaultChatControllerInteraction = ChatControllerInteraction.default private func peerInfoControllerImpl(context: AccountContext, peer: Peer, mode: PeerInfoControllerMode, avatarInitiallyExpanded: Bool) -> ViewController? { - if let _ = peer as? TelegramGroup { + if let _ = peer as? TelegramGroup { + return PeerInfoScreen(context: context, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded) + return groupInfoController(context: context, peerId: peer.id) } else if let channel = peer as? TelegramChannel { + return PeerInfoScreen(context: context, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded) + if case .group = channel.info { return groupInfoController(context: context, peerId: peer.id) } else { From 0f0bb05cc547adff24f4b0177583e6cd5a7b2886 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Mon, 10 Feb 2020 18:35:38 +0100 Subject: [PATCH 48/50] Fix typo --- buildbox/deploy-telegram.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildbox/deploy-telegram.sh b/buildbox/deploy-telegram.sh index d76f0a292d..744c99ea44 100644 --- a/buildbox/deploy-telegram.sh +++ b/buildbox/deploy-telegram.sh @@ -60,6 +60,6 @@ fi if [ "$1" == "appstore" ]; then export DELIVER_ITMSTRANSPORTER_ADDITIONAL_UPLOAD_PARAMETERS="-t DAV" FASTLANE_PASSWORD="$FASTLANE_PASSWORD" xcrun altool --upload-app --type ios --file "$IPA_PATH" --username "$FASTLANE_ITC_USERNAME" --password "@env:FASTLANE_PASSWORD" -else if [ "$1" == "hockeyapp" ]; then +elif [ "$1" == "hockeyapp" ]; then API_USER_NAME="$API_USER_NAME" API_APP_NAME="$API_APP_NAME" API_TOKEN="$API_TOKEN" sh buildbox/deploy-appcenter.sh fi From fd9be238d2500d61d673cce63498f2a32f4c3e28 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Mon, 10 Feb 2020 18:41:06 +0100 Subject: [PATCH 49/50] Fix script --- buildbox/deploy-appcenter.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/buildbox/deploy-appcenter.sh b/buildbox/deploy-appcenter.sh index f738d21718..58376b2c20 100644 --- a/buildbox/deploy-appcenter.sh +++ b/buildbox/deploy-appcenter.sh @@ -4,8 +4,8 @@ set -e set -x API_HOST="https://api.appcenter.ms" -IPA_PATH="build/Telegram_Signed.ipa" -DSYM_PATH="build/DSYM.zip" +IPA_PATH="build/artifacts/Telegram.ipa" +DSYM_PATH="build/artifacts/Telegram.DSYMs.zip" upload_ipa() { GROUP_DATA=$(curl \ From 76893115f6cbdce49956499fb0549a91edbe9348 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Tue, 11 Feb 2020 01:53:12 +0100 Subject: [PATCH 50/50] Temp --- .../AvatarNode/Sources/AvatarNode.swift | 14 +- .../Display/Display/GenerateImage.swift | 31 + .../Sources/ItemListAddressItem.swift | 17 +- .../Sources/ItemListPeerItem.swift | 11 +- .../ChannelPermissionsController.swift | 2 +- .../Contents.json | 12 + .../ic_camera.pdf | Bin 0 -> 4149 bytes .../TelegramUI/ChatController.swift | 6 +- .../ListItems/PeerInfoScreenAddressItem.swift | 122 +++ .../ListItems/PeerInfoScreenHeaderItem.swift | 57 ++ .../ListItems/PeerInfoScreenMemberItem.swift | 124 +++ .../PeerInfo/Panes/PeerInfoMembersPane.swift | 196 ++++ .../TelegramUI/PeerInfo/PeerInfoData.swift | 103 ++- .../PeerInfo/PeerInfoHeaderNode.swift | 29 +- .../TelegramUI/PeerInfo/PeerInfoMembers.swift | 153 ++++ .../PeerInfo/PeerInfoPaneContainerNode.swift | 9 + .../TelegramUI/PeerInfo/PeerInfoScreen.swift | 863 +++++++++++++++--- 17 files changed, 1542 insertions(+), 207 deletions(-) create mode 100644 submodules/TelegramUI/Images.xcassets/Avatar/EditAvatarIconLarge.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Avatar/EditAvatarIconLarge.imageset/ic_camera.pdf create mode 100644 submodules/TelegramUI/TelegramUI/PeerInfo/ListItems/PeerInfoScreenAddressItem.swift create mode 100644 submodules/TelegramUI/TelegramUI/PeerInfo/ListItems/PeerInfoScreenHeaderItem.swift create mode 100644 submodules/TelegramUI/TelegramUI/PeerInfo/ListItems/PeerInfoScreenMemberItem.swift create mode 100644 submodules/TelegramUI/TelegramUI/PeerInfo/Panes/PeerInfoMembersPane.swift create mode 100644 submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoMembers.swift diff --git a/submodules/AvatarNode/Sources/AvatarNode.swift b/submodules/AvatarNode/Sources/AvatarNode.swift index b871681a0a..2f4e502e6a 100644 --- a/submodules/AvatarNode/Sources/AvatarNode.swift +++ b/submodules/AvatarNode/Sources/AvatarNode.swift @@ -150,8 +150,14 @@ public final class AvatarEditOverlayNode: ASDisplayNode { context.setBlendMode(.normal) - if let editAvatarIcon = generateTintedImage(image: UIImage(bundleImageName: "Avatar/EditAvatarIcon"), color: .white) { - context.draw(editAvatarIcon.cgImage!, in: CGRect(origin: CGPoint(x: floor((bounds.size.width - editAvatarIcon.size.width) / 2.0) + 0.5, y: floor((bounds.size.height - editAvatarIcon.size.height) / 2.0) + 1.0), size: editAvatarIcon.size)) + if bounds.width > 90.0 { + if let editAvatarIcon = generateTintedImage(image: UIImage(bundleImageName: "Avatar/EditAvatarIconLarge"), color: .white) { + context.draw(editAvatarIcon.cgImage!, in: CGRect(origin: CGPoint(x: floor((bounds.size.width - editAvatarIcon.size.width) / 2.0) + 0.5, y: floor((bounds.size.height - editAvatarIcon.size.height) / 2.0) + 1.0), size: editAvatarIcon.size)) + } + } else { + if let editAvatarIcon = generateTintedImage(image: UIImage(bundleImageName: "Avatar/EditAvatarIcon"), color: .white) { + context.draw(editAvatarIcon.cgImage!, in: CGRect(origin: CGPoint(x: floor((bounds.size.width - editAvatarIcon.size.width) / 2.0) + 0.5, y: floor((bounds.size.height - editAvatarIcon.size.height) / 2.0) + 1.0), size: editAvatarIcon.size)) + } } } } @@ -501,7 +507,9 @@ public final class AvatarNode: ASDisplayNode { context.scaleBy(x: 1.0, y: -1.0) context.translateBy(x: -bounds.size.width / 2.0, y: -bounds.size.height / 2.0) - if let editAvatarIcon = generateTintedImage(image: UIImage(bundleImageName: "Avatar/EditAvatarIcon"), color: theme.list.itemAccentColor) { + if bounds.width > 90.0, let editAvatarIcon = generateTintedImage(image: UIImage(bundleImageName: "Avatar/EditAvatarIconLarge"), color: theme.list.itemAccentColor) { + context.draw(editAvatarIcon.cgImage!, in: CGRect(origin: CGPoint(x: floor((bounds.size.width - editAvatarIcon.size.width) / 2.0) + 0.5, y: floor((bounds.size.height - editAvatarIcon.size.height) / 2.0) + 1.0), size: editAvatarIcon.size)) + } else if let editAvatarIcon = generateTintedImage(image: UIImage(bundleImageName: "Avatar/EditAvatarIcon"), color: theme.list.itemAccentColor) { context.draw(editAvatarIcon.cgImage!, in: CGRect(origin: CGPoint(x: floor((bounds.size.width - editAvatarIcon.size.width) / 2.0) + 0.5, y: floor((bounds.size.height - editAvatarIcon.size.height) / 2.0) + 1.0), size: editAvatarIcon.size)) } } else if case .archivedChatsIcon = parameters.icon { diff --git a/submodules/Display/Display/GenerateImage.swift b/submodules/Display/Display/GenerateImage.swift index cabf6f5c54..4b7f38fbe9 100644 --- a/submodules/Display/Display/GenerateImage.swift +++ b/submodules/Display/Display/GenerateImage.swift @@ -238,6 +238,8 @@ public func generateStretchableFilledCircleImage(diameter: CGFloat, color: UICol let cap: Int if intDiameter == 3 { cap = 1 + } else if intDiameter == 2 { + cap = 3 } else if intRadius == 1 { cap = 2 } else { @@ -266,6 +268,35 @@ public func generateVerticallyStretchableFilledCircleImage(radius: CGFloat, colo })?.stretchableImage(withLeftCapWidth: Int(radius), topCapHeight: Int(radius)) } +public func generateSmallHorizontalStretchableFilledCircleImage(diameter: CGFloat, color: UIColor?, backgroundColor: UIColor? = nil) -> UIImage? { + return generateImage(CGSize(width: diameter + 1.0, height: diameter), contextGenerator: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + + if let subImage = generateImage(CGSize(width: diameter + 1.0, height: diameter), contextGenerator: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + context.setFillColor(UIColor.black.cgColor) + context.fillEllipse(in: CGRect(origin: CGPoint(), size: CGSize(width: diameter, height: diameter))) + context.fill(CGRect(origin: CGPoint(x: diameter / 2.0, y: 0.0), size: CGSize(width: 1.0, height: diameter))) + context.fillEllipse(in: CGRect(origin: CGPoint(x: 1.0, y: 0.0), size: CGSize(width: diameter, height: diameter))) + }) { + if let backgroundColor = backgroundColor { + context.setFillColor(backgroundColor.cgColor) + context.fill(CGRect(origin: CGPoint(), size: size)) + } + + if let color = color { + context.setFillColor(color.cgColor) + } else { + context.setFillColor(UIColor.clear.cgColor) + context.setBlendMode(.copy) + } + + context.clip(to: CGRect(origin: CGPoint(), size: size), mask: subImage.cgImage!) + context.fill(CGRect(origin: CGPoint(), size: size)) + } + })?.stretchableImage(withLeftCapWidth: Int(diameter / 2), topCapHeight: Int(diameter / 2)) +} + public func generateTintedImage(image: UIImage?, color: UIColor, backgroundColor: UIColor? = nil) -> UIImage? { guard let image = image else { return nil diff --git a/submodules/ItemListAddressItem/Sources/ItemListAddressItem.swift b/submodules/ItemListAddressItem/Sources/ItemListAddressItem.swift index 9ad3ec1d6d..929a0d82ca 100644 --- a/submodules/ItemListAddressItem/Sources/ItemListAddressItem.swift +++ b/submodules/ItemListAddressItem/Sources/ItemListAddressItem.swift @@ -18,13 +18,14 @@ public final class ItemListAddressItem: ListViewItem, ItemListItem { let selected: Bool? public let sectionId: ItemListSectionId let style: ItemListStyle + let displayDecorations: Bool let action: (() -> Void)? let longTapAction: (() -> Void)? let linkItemAction: ((TextLinkItemActionType, TextLinkItem) -> Void)? public let tag: Any? - public init(theme: PresentationTheme, label: String, text: String, imageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>?, selected: Bool? = nil, sectionId: ItemListSectionId, style: ItemListStyle, action: (() -> Void)?, longTapAction: (() -> Void)? = nil, linkItemAction: ((TextLinkItemActionType, TextLinkItem) -> Void)? = nil, tag: Any? = nil) { + public init(theme: PresentationTheme, label: String, text: String, imageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>?, selected: Bool? = nil, sectionId: ItemListSectionId, style: ItemListStyle, displayDecorations: Bool = true, action: (() -> Void)?, longTapAction: (() -> Void)? = nil, linkItemAction: ((TextLinkItemActionType, TextLinkItem) -> Void)? = nil, tag: Any? = nil) { self.theme = theme self.label = label self.text = text @@ -32,6 +33,7 @@ public final class ItemListAddressItem: ListViewItem, ItemListItem { self.selected = selected self.sectionId = sectionId self.style = style + self.displayDecorations = displayDecorations self.action = action self.longTapAction = longTapAction self.linkItemAction = linkItemAction @@ -157,7 +159,7 @@ public class ItemListAddressItemNode: ListViewItemNode { updatedTheme = item.theme } - let insets: UIEdgeInsets + var insets: UIEdgeInsets let leftInset: CGFloat = 16.0 + params.leftInset let rightInset: CGFloat = 8.0 + params.rightInset let separatorHeight = UIScreenPixel @@ -175,6 +177,10 @@ public class ItemListAddressItemNode: ListViewItemNode { insets = itemListNeighborsGroupedInsets(neighbors) } + if !item.displayDecorations { + insets = UIEdgeInsets() + } + var leftOffset: CGFloat = 0.0 var selectionNodeWidthAndApply: (CGFloat, (CGSize, Bool) -> ItemListSelectableControlNode)? if let selected = item.selected { @@ -226,6 +232,11 @@ public class ItemListAddressItemNode: ListViewItemNode { strongSelf.highlightedBackgroundNode.backgroundColor = item.theme.list.itemHighlightedBackgroundColor } + strongSelf.topStripeNode.isHidden = !item.displayDecorations + strongSelf.bottomStripeNode.isHidden = !item.displayDecorations + strongSelf.backgroundNode.isHidden = !item.displayDecorations + strongSelf.highlightedBackgroundNode.isHidden = !item.displayDecorations + let _ = labelApply() let _ = textApply() let _ = imageApply() @@ -293,7 +304,7 @@ public class ItemListAddressItemNode: ListViewItemNode { case .sameSection(false): strongSelf.topStripeNode.isHidden = true default: - strongSelf.topStripeNode.isHidden = false + strongSelf.topStripeNode.isHidden = !item.displayDecorations } let bottomStripeInset: CGFloat let bottomStripeOffset: CGFloat diff --git a/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift b/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift index 59d93c72ca..ce2f1c397a 100644 --- a/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift +++ b/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift @@ -334,8 +334,9 @@ public final class ItemListPeerItem: ListViewItem, ItemListItem { public let tag: ItemListItemTag? let header: ListViewItemHeader? let shimmering: ItemListPeerItemShimmering? + let displayDecorations: Bool - public init(presentationData: ItemListPresentationData, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, context: AccountContext, peer: Peer, height: ItemListPeerItemHeight = .peerList, aliasHandling: ItemListPeerItemAliasHandling = .standard, nameColor: ItemListPeerItemNameColor = .primary, nameStyle: ItemListPeerItemNameStyle = .distinctBold, presence: PeerPresence?, text: ItemListPeerItemText, label: ItemListPeerItemLabel, editing: ItemListPeerItemEditing, revealOptions: ItemListPeerItemRevealOptions? = nil, switchValue: ItemListPeerItemSwitch?, enabled: Bool, selectable: Bool, sectionId: ItemListSectionId, action: (() -> Void)?, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, removePeer: @escaping (PeerId) -> Void, toggleUpdated: ((Bool) -> Void)? = nil, contextAction: ((ASDisplayNode, ContextGesture?) -> Void)? = nil, hasTopStripe: Bool = true, hasTopGroupInset: Bool = true, noInsets: Bool = false, tag: ItemListItemTag? = nil, header: ListViewItemHeader? = nil, shimmering: ItemListPeerItemShimmering? = nil) { + public init(presentationData: ItemListPresentationData, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, context: AccountContext, peer: Peer, height: ItemListPeerItemHeight = .peerList, aliasHandling: ItemListPeerItemAliasHandling = .standard, nameColor: ItemListPeerItemNameColor = .primary, nameStyle: ItemListPeerItemNameStyle = .distinctBold, presence: PeerPresence?, text: ItemListPeerItemText, label: ItemListPeerItemLabel, editing: ItemListPeerItemEditing, revealOptions: ItemListPeerItemRevealOptions? = nil, switchValue: ItemListPeerItemSwitch?, enabled: Bool, selectable: Bool, sectionId: ItemListSectionId, action: (() -> Void)?, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, removePeer: @escaping (PeerId) -> Void, toggleUpdated: ((Bool) -> Void)? = nil, contextAction: ((ASDisplayNode, ContextGesture?) -> Void)? = nil, hasTopStripe: Bool = true, hasTopGroupInset: Bool = true, noInsets: Bool = false, tag: ItemListItemTag? = nil, header: ListViewItemHeader? = nil, shimmering: ItemListPeerItemShimmering? = nil, displayDecorations: Bool = true) { self.presentationData = presentationData self.dateTimeFormat = dateTimeFormat self.nameDisplayOrder = nameDisplayOrder @@ -365,6 +366,7 @@ public final class ItemListPeerItem: ListViewItem, ItemListItem { self.tag = tag self.header = header self.shimmering = shimmering + self.displayDecorations = displayDecorations } public func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal?, (ListViewItemApply) -> Void)) -> Void) { @@ -932,7 +934,7 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo strongSelf.topStripeNode.isHidden = true default: hasTopCorners = true - strongSelf.topStripeNode.isHidden = hasCorners || !item.hasTopStripe + strongSelf.topStripeNode.isHidden = !item.displayDecorations || hasCorners || !item.hasTopStripe } let bottomStripeInset: CGFloat let bottomStripeOffset: CGFloat @@ -944,7 +946,7 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo bottomStripeInset = 0.0 bottomStripeOffset = 0.0 hasBottomCorners = true - strongSelf.bottomStripeNode.isHidden = hasCorners + strongSelf.bottomStripeNode.isHidden = hasCorners || !item.displayDecorations } strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil @@ -1087,6 +1089,9 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo shimmerNode.removeFromSupernode() } + strongSelf.backgroundNode.isHidden = !item.displayDecorations + strongSelf.highlightedBackgroundNode.isHidden = !item.displayDecorations + strongSelf.updateLayout(size: layout.contentSize, leftInset: params.leftInset, rightInset: params.rightInset) strongSelf.setRevealOptions((left: [], right: peerRevealOptions)) diff --git a/submodules/PeerInfoUI/Sources/ChannelPermissionsController.swift b/submodules/PeerInfoUI/Sources/ChannelPermissionsController.swift index 05e6b55824..85d9837112 100644 --- a/submodules/PeerInfoUI/Sources/ChannelPermissionsController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelPermissionsController.swift @@ -335,7 +335,7 @@ func compactStringForGroupPermission(strings: PresentationStrings, right: Telegr } } -let allGroupPermissionList: [(TelegramChatBannedRightsFlags, TelegramChannelPermission)] = [ +public let allGroupPermissionList: [(TelegramChatBannedRightsFlags, TelegramChannelPermission)] = [ (.banSendMessages, .sendMessages), (.banSendMedia, .sendMessages), (.banSendGifs, .sendMessages), diff --git a/submodules/TelegramUI/Images.xcassets/Avatar/EditAvatarIconLarge.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Avatar/EditAvatarIconLarge.imageset/Contents.json new file mode 100644 index 0000000000..868e9f5048 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Avatar/EditAvatarIconLarge.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "ic_camera.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Avatar/EditAvatarIconLarge.imageset/ic_camera.pdf b/submodules/TelegramUI/Images.xcassets/Avatar/EditAvatarIconLarge.imageset/ic_camera.pdf new file mode 100644 index 0000000000000000000000000000000000000000..6b39b47bbb0836616233b848db889f51e3b47534 GIT binary patch literal 4149 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 igjYaeFsk7HF8LWC5}Dr19~%u DrawingContext?, NoError>? + let action: (() -> Void)? + let longTapAction: (() -> Void)? + let linkItemAction: ((TextLinkItemActionType, TextLinkItem) -> Void)? + + init( + id: AnyHashable, + label: String, + text: String, + imageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>?, + action: (() -> Void)?, + longTapAction: (() -> Void)? = nil, + linkItemAction: ((TextLinkItemActionType, TextLinkItem) -> Void)? = nil + ) { + self.id = id + self.label = label + self.text = text + self.imageSignal = imageSignal + self.action = action + self.longTapAction = longTapAction + self.linkItemAction = linkItemAction + } + + func node() -> PeerInfoScreenItemNode { + return PeerInfoScreenAddressItemNode() + } +} + +private final class PeerInfoScreenAddressItemNode: PeerInfoScreenItemNode { + private let selectionNode: PeerInfoScreenSelectableBackgroundNode + private let bottomSeparatorNode: ASDisplayNode + + private var item: PeerInfoScreenAddressItem? + private var itemNode: ItemListAddressItemNode? + + override init() { + var bringToFrontForHighlightImpl: (() -> Void)? + self.selectionNode = PeerInfoScreenSelectableBackgroundNode(bringToFrontForHighlight: { bringToFrontForHighlightImpl?() }) + + self.bottomSeparatorNode = ASDisplayNode() + self.bottomSeparatorNode.isLayerBacked = true + + super.init() + + bringToFrontForHighlightImpl = { [weak self] in + self?.bringToFrontForHighlight?() + } + + self.addSubnode(self.bottomSeparatorNode) + self.addSubnode(self.selectionNode) + } + + override func update(width: CGFloat, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, transition: ContainedViewLayoutTransition) -> CGFloat { + guard let item = item as? PeerInfoScreenAddressItem else { + return 10.0 + } + + self.item = item + + self.selectionNode.pressed = item.action + + let sideInset: CGFloat = 16.0 + + self.bottomSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor + + let addressItem = ItemListAddressItem(theme: presentationData.theme, label: item.label, text: item.text, imageSignal: item.imageSignal, sectionId: 0, style: .blocks, displayDecorations: false, action: nil, longTapAction: item.longTapAction, linkItemAction: item.linkItemAction) + + let params = ListViewItemLayoutParams(width: width, leftInset: 0.0, rightInset: 0.0, availableHeight: 1000.0) + + let itemNode: ItemListAddressItemNode + if let current = self.itemNode { + itemNode = current + addressItem.updateNode(async: { $0() }, node: { + return itemNode + }, params: params, previousItem: nil, nextItem: nil, animation: .None, completion: { (layout, apply) in + let nodeFrame = CGRect(origin: CGPoint(), size: CGSize(width: width, height: layout.size.height)) + + itemNode.contentSize = layout.contentSize + itemNode.insets = layout.insets + itemNode.frame = nodeFrame + + apply(ListViewItemApply(isOnScreen: true)) + }) + } else { + var itemNodeValue: ListViewItemNode? + addressItem.nodeConfiguredForParams(async: { $0() }, params: params, synchronousLoads: false, previousItem: nil, nextItem: nil, completion: { node, apply in + itemNodeValue = node + apply().1(ListViewItemApply(isOnScreen: true)) + }) + itemNode = itemNodeValue as! ItemListAddressItemNode + itemNode.isUserInteractionEnabled = false + self.itemNode = itemNode + self.addSubnode(itemNode) + } + + let height = itemNode.contentSize.height + + transition.updateFrame(node: itemNode, frame: CGRect(origin: CGPoint(), size: itemNode.bounds.size)) + + let highlightNodeOffset: CGFloat = topItem == nil ? 0.0 : UIScreenPixel + self.selectionNode.update(size: CGSize(width: width, height: height + highlightNodeOffset), theme: presentationData.theme, transition: transition) + transition.updateFrame(node: self.selectionNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -highlightNodeOffset), size: CGSize(width: width, height: height + highlightNodeOffset))) + + transition.updateFrame(node: self.bottomSeparatorNode, frame: CGRect(origin: CGPoint(x: sideInset, y: height - UIScreenPixel), size: CGSize(width: width - sideInset, height: UIScreenPixel))) + transition.updateAlpha(node: self.bottomSeparatorNode, alpha: bottomItem == nil ? 0.0 : 1.0) + + return height + } +} diff --git a/submodules/TelegramUI/TelegramUI/PeerInfo/ListItems/PeerInfoScreenHeaderItem.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/ListItems/PeerInfoScreenHeaderItem.swift new file mode 100644 index 0000000000..6ab8aab21e --- /dev/null +++ b/submodules/TelegramUI/TelegramUI/PeerInfo/ListItems/PeerInfoScreenHeaderItem.swift @@ -0,0 +1,57 @@ +import AsyncDisplayKit +import Display +import TelegramPresentationData + +final class PeerInfoScreenHeaderItem: PeerInfoScreenItem { + let id: AnyHashable + let text: String + + init(id: AnyHashable, text: String) { + self.id = id + self.text = text + } + + func node() -> PeerInfoScreenItemNode { + return PeerInfoScreenHeaderItemNode() + } +} + +private final class PeerInfoScreenHeaderItemNode: PeerInfoScreenItemNode { + private let textNode: ImmediateTextNode + + private var item: PeerInfoScreenHeaderItem? + + override init() { + self.textNode = ImmediateTextNode() + self.textNode.displaysAsynchronously = false + self.textNode.isUserInteractionEnabled = false + + super.init() + + self.addSubnode(self.textNode) + } + + override func update(width: CGFloat, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, transition: ContainedViewLayoutTransition) -> CGFloat { + guard let item = item as? PeerInfoScreenHeaderItem else { + return 10.0 + } + + self.item = item + + let sideInset: CGFloat = 16.0 + let verticalInset: CGFloat = 7.0 + + self.textNode.maximumNumberOfLines = 0 + self.textNode.attributedText = NSAttributedString(string: item.text, font: Font.regular(13.0), textColor: presentationData.theme.list.freeTextColor) + + let textSize = self.textNode.updateLayout(CGSize(width: width - sideInset * 2.0, height: .greatestFiniteMagnitude)) + + let textFrame = CGRect(origin: CGPoint(x: sideInset, y: verticalInset), size: textSize) + + let height = textSize.height + verticalInset * 2.0 + + transition.updateFrame(node: self.textNode, frame: textFrame) + + return height + } +} diff --git a/submodules/TelegramUI/TelegramUI/PeerInfo/ListItems/PeerInfoScreenMemberItem.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/ListItems/PeerInfoScreenMemberItem.swift new file mode 100644 index 0000000000..246861f33d --- /dev/null +++ b/submodules/TelegramUI/TelegramUI/PeerInfo/ListItems/PeerInfoScreenMemberItem.swift @@ -0,0 +1,124 @@ +import Foundation +import UIKit +import AsyncDisplayKit +import Display +import TelegramPresentationData +import ItemListPeerItem +import SwiftSignalKit +import AccountContext +import Postbox +import SyncCore +import TelegramCore +import ItemListUI + +final class PeerInfoScreenMemberItem: PeerInfoScreenItem { + let id: AnyHashable + let context: AccountContext + let peer: Peer + let presence: TelegramUserPresence? + let action: (() -> Void)? + + init( + id: AnyHashable, + context: AccountContext, + peer: Peer, + presence: TelegramUserPresence?, + action: (() -> Void)? + ) { + self.id = id + self.context = context + self.peer = peer + self.presence = presence + self.action = action + } + + func node() -> PeerInfoScreenItemNode { + return PeerInfoScreenMemberItemNode() + } +} + +private final class PeerInfoScreenMemberItemNode: PeerInfoScreenItemNode { + private let selectionNode: PeerInfoScreenSelectableBackgroundNode + private let bottomSeparatorNode: ASDisplayNode + + private var item: PeerInfoScreenMemberItem? + private var itemNode: ItemListPeerItemNode? + + override init() { + var bringToFrontForHighlightImpl: (() -> Void)? + self.selectionNode = PeerInfoScreenSelectableBackgroundNode(bringToFrontForHighlight: { bringToFrontForHighlightImpl?() }) + + self.bottomSeparatorNode = ASDisplayNode() + self.bottomSeparatorNode.isLayerBacked = true + + super.init() + + bringToFrontForHighlightImpl = { [weak self] in + self?.bringToFrontForHighlight?() + } + + self.addSubnode(self.bottomSeparatorNode) + self.addSubnode(self.selectionNode) + } + + override func update(width: CGFloat, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, transition: ContainedViewLayoutTransition) -> CGFloat { + guard let item = item as? PeerInfoScreenMemberItem else { + return 10.0 + } + + self.item = item + + self.selectionNode.pressed = item.action + + let sideInset: CGFloat = 16.0 + + self.bottomSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor + + let peerItem = ItemListPeerItem(presentationData: ItemListPresentationData(presentationData), dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, context: item.context, peer: item.peer, height: .peerList, presence: item.presence, text: .presence, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, selectable: false, sectionId: 0, action: nil, setPeerIdWithRevealedOptions: { lhs, rhs in + + }, removePeer: { _ in + + }, contextAction: nil, hasTopStripe: false, hasTopGroupInset: false, noInsets: true, displayDecorations: false) + + let params = ListViewItemLayoutParams(width: width, leftInset: 0.0, rightInset: 0.0, availableHeight: 1000.0) + + let itemNode: ItemListPeerItemNode + if let current = self.itemNode { + itemNode = current + peerItem.updateNode(async: { $0() }, node: { + return itemNode + }, params: params, previousItem: nil, nextItem: nil, animation: .None, completion: { (layout, apply) in + let nodeFrame = CGRect(origin: CGPoint(), size: CGSize(width: width, height: layout.size.height)) + + itemNode.contentSize = layout.contentSize + itemNode.insets = layout.insets + itemNode.frame = nodeFrame + + apply(ListViewItemApply(isOnScreen: true)) + }) + } else { + var itemNodeValue: ListViewItemNode? + peerItem.nodeConfiguredForParams(async: { $0() }, params: params, synchronousLoads: false, previousItem: nil, nextItem: nil, completion: { node, apply in + itemNodeValue = node + apply().1(ListViewItemApply(isOnScreen: true)) + }) + itemNode = itemNodeValue as! ItemListPeerItemNode + itemNode.isUserInteractionEnabled = false + self.itemNode = itemNode + self.addSubnode(itemNode) + } + + let height = itemNode.contentSize.height + + transition.updateFrame(node: itemNode, frame: CGRect(origin: CGPoint(), size: itemNode.bounds.size)) + + let highlightNodeOffset: CGFloat = topItem == nil ? 0.0 : UIScreenPixel + self.selectionNode.update(size: CGSize(width: width, height: height + highlightNodeOffset), theme: presentationData.theme, transition: transition) + transition.updateFrame(node: self.selectionNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -highlightNodeOffset), size: CGSize(width: width, height: height + highlightNodeOffset))) + + transition.updateFrame(node: self.bottomSeparatorNode, frame: CGRect(origin: CGPoint(x: sideInset, y: height - UIScreenPixel), size: CGSize(width: width - sideInset, height: UIScreenPixel))) + transition.updateAlpha(node: self.bottomSeparatorNode, alpha: bottomItem == nil ? 0.0 : 1.0) + + return height + } +} diff --git a/submodules/TelegramUI/TelegramUI/PeerInfo/Panes/PeerInfoMembersPane.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/Panes/PeerInfoMembersPane.swift new file mode 100644 index 0000000000..243a95f6a9 --- /dev/null +++ b/submodules/TelegramUI/TelegramUI/PeerInfo/Panes/PeerInfoMembersPane.swift @@ -0,0 +1,196 @@ +import AsyncDisplayKit +import Display +import TelegramCore +import SyncCore +import SwiftSignalKit +import Postbox +import TelegramPresentationData +import AccountContext +import ContextUI +import PhotoResources +import TelegramUIPreferences +import ItemListPeerItem +import MergeLists +import ItemListUI + +private struct PeerMembersListTransaction { + let deletions: [ListViewDeleteItem] + let insertions: [ListViewInsertItem] + let updates: [ListViewUpdateItem] +} + +private struct PeerMembersListEntry: Comparable, Identifiable { + var index: Int + var member: PeerInfoMember + + var stableId: PeerId { + return self.member.id + } + + static func ==(lhs: PeerMembersListEntry, rhs: PeerMembersListEntry) -> Bool { + return lhs.member == rhs.member + } + + static func <(lhs: PeerMembersListEntry, rhs: PeerMembersListEntry) -> Bool { + return lhs.index < rhs.index + } + + func item(context: AccountContext, presentationData: PresentationData, openPeer: @escaping (Peer) -> Void) -> ListViewItem { + let member = self.member + return ItemListPeerItem(presentationData: ItemListPresentationData(presentationData), dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, context: context, peer: member.peer, presence: nil, text: .none, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), switchValue: nil, enabled: true, selectable: true, sectionId: 0, action: { + openPeer(member.peer) + }, setPeerIdWithRevealedOptions: { _, _ in + }, removePeer: { _ in + }, contextAction: nil/*{ node, gesture in + openPeerContextAction(peer, node, gesture) + }*/, hasTopStripe: false, noInsets: true) + } +} + +private func preparedTransition(from fromEntries: [PeerMembersListEntry], to toEntries: [PeerMembersListEntry], context: AccountContext, presentationData: PresentationData, openPeer: @escaping (Peer) -> Void) -> PeerMembersListTransaction { + let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries) + + let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) } + let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, openPeer: openPeer), directionHint: nil) } + let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, openPeer: openPeer), directionHint: nil) } + + return PeerMembersListTransaction(deletions: deletions, insertions: insertions, updates: updates) +} + +final class PeerInfoMembersPaneNode: ASDisplayNode, PeerInfoPaneNode { + private let context: AccountContext + private let membersContext: PeerInfoMembersContext + + private let listNode: ListView + private var currentEntries: [PeerMembersListEntry] = [] + private var currentState: PeerInfoMembersState? + private var canLoadMore: Bool = false + private var enqueuedTransactions: [PeerMembersListTransaction] = [] + + private var currentParams: (size: CGSize, isScrollingLockedAtTop: Bool, presentationData: PresentationData)? + + private let ready = Promise() + private var didSetReady: Bool = false + var isReady: Signal { + return self.ready.get() + } + + private var disposable: Disposable? + + init(context: AccountContext, membersContext: PeerInfoMembersContext) { + self.context = context + self.membersContext = membersContext + + self.listNode = ListView() + + super.init() + + self.listNode.preloadPages = true + self.addSubnode(self.listNode) + + self.disposable = (membersContext.state + |> deliverOnMainQueue).start(next: { [weak self] state in + guard let strongSelf = self else { + return + } + strongSelf.currentState = state + if let (_, _, presentationData) = strongSelf.currentParams { + strongSelf.updateState(state: state, presentationData: presentationData) + } + }) + + self.listNode.visibleBottomContentOffsetChanged = { [weak self] offset in + guard let strongSelf = self, let state = strongSelf.currentState, case .ready(true) = state.dataState else { + return + } + if case let .known(value) = offset, value < 100.0 { + strongSelf.membersContext.loadMore() + } + } + } + + deinit { + } + + func scrollToTop() -> Bool { + if !self.listNode.scrollToOffsetFromTop(0.0) { + self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: .Spring(duration: 0.4), directionHint: .Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in }) + return true + } else { + return false + } + } + + func update(size: CGSize, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) { + let isFirstLayout = self.currentParams == nil + self.currentParams = (size, isScrollingLockedAtTop, presentationData) + + transition.updateFrame(node: self.listNode, frame: CGRect(origin: CGPoint(), size: size)) + let (duration, curve) = listViewAnimationDurationAndCurve(transition: transition) + + self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: nil, updateSizeAndInsets: ListViewUpdateSizeAndInsets(size: size, insets: UIEdgeInsets(top: 0.0, left: sideInset, bottom: bottomInset, right: sideInset), duration: duration, curve: curve), stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in }) + + self.listNode.scrollEnabled = !isScrollingLockedAtTop + + if isFirstLayout, let state = self.currentState { + self.updateState(state: state, presentationData: presentationData) + } + } + + private func updateState(state: PeerInfoMembersState, presentationData: PresentationData) { + var entries: [PeerMembersListEntry] = [] + for member in state.members { + entries.append(PeerMembersListEntry(index: entries.count, member: member)) + } + let transaction = preparedTransition(from: self.currentEntries, to: entries, context: self.context, presentationData: presentationData, openPeer: { [weak self] peer in + + }) + self.currentEntries = entries + self.enqueuedTransactions.append(transaction) + self.dequeueTransaction() + } + + private func dequeueTransaction() { + guard let (layout, _, _) = self.currentParams, let transaction = self.enqueuedTransactions.first else { + return + } + + self.enqueuedTransactions.remove(at: 0) + + var options = ListViewDeleteAndInsertOptions() + options.insert(.Synchronous) + + self.listNode.transaction(deleteIndices: transaction.deletions, insertIndicesAndItems: transaction.insertions, updateIndicesAndItems: transaction.updates, options: options, updateSizeAndInsets: nil, updateOpaqueState: nil, completion: { [weak self] _ in + guard let strongSelf = self else { + return + } + if !strongSelf.didSetReady { + strongSelf.didSetReady = true + strongSelf.ready.set(.single(true)) + } + }) + } + + func findLoadedMessage(id: MessageId) -> Message? { + return nil + } + + func updateHiddenMedia() { + } + + func transferVelocity(_ velocity: CGFloat) { + if velocity > 0.0 { + self.listNode.transferVelocity(velocity) + } + } + + func transitionNodeForGallery(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + return nil + } + + func addToTransitionSurface(view: UIView) { + } + + func updateSelectedMessages(animated: Bool) { + } +} diff --git a/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoData.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoData.swift index a68b93dc2c..09bbdafd90 100644 --- a/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoData.swift +++ b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoData.swift @@ -64,6 +64,7 @@ final class PeerInfoScreenData { let availablePanes: [PeerInfoPaneKey] let groupsInCommon: [Peer]? let linkedDiscussionPeer: Peer? + let members: PeerInfoMembersData? init( peer: Peer?, @@ -74,7 +75,8 @@ final class PeerInfoScreenData { isContact: Bool, availablePanes: [PeerInfoPaneKey], groupsInCommon: [Peer]?, - linkedDiscussionPeer: Peer? + linkedDiscussionPeer: Peer?, + members: PeerInfoMembersData? ) { self.peer = peer self.cachedData = cachedData @@ -85,6 +87,7 @@ final class PeerInfoScreenData { self.availablePanes = availablePanes self.groupsInCommon = groupsInCommon self.linkedDiscussionPeer = linkedDiscussionPeer + self.members = members } } @@ -98,7 +101,7 @@ enum PeerInfoScreenInputData: Equatable { case none case user(userId: PeerId, secretChatId: PeerId?, kind: PeerInfoScreenInputUserKind) case channel - case group(isSupergroup: Bool) + case group(isSupergroup: Bool, membersContext: PeerInfoMembersContext) } func peerInfoAvailableMediaPanes(context: AccountContext, peerId: PeerId) -> Signal<[PeerInfoPaneKey], NoError> { @@ -144,6 +147,11 @@ struct PeerInfoStatusData: Equatable { var isActivity: Bool } +enum PeerInfoMembersData: Equatable { + case shortList([PeerInfoMember]) + case longList(PeerInfoMembersContext) +} + func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat) -> Signal { return context.account.postbox.combinedView(keys: [.basicPeer(peerId)]) |> map { view -> PeerInfoScreenInputData in @@ -162,12 +170,12 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen return .user(userId: user.id, secretChatId: nil, kind: kind) } else if let channel = peer as? TelegramChannel { if case .group = channel.info { - return .group(isSupergroup: true) + return .group(isSupergroup: true, membersContext: PeerInfoMembersContext(context: context, peerId: channel.id)) } else { return .channel } - } else if let _ = peer as? TelegramGroup { - return .group(isSupergroup: false) + } else if let group = peer as? TelegramGroup { + return .group(isSupergroup: false, membersContext: PeerInfoMembersContext(context: context, peerId: group.id)) } else { return .none } @@ -185,7 +193,8 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen isContact: false, availablePanes: [], groupsInCommon: nil, - linkedDiscussionPeer: nil + linkedDiscussionPeer: nil, + members: nil )) case let .user(peerId, secretChatId, kind): let groupsInCommonSignal: Signal<[Peer]?, NoError> @@ -301,8 +310,14 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen } var availablePanes = availablePanes - if let groupsInCommon = groupsInCommon, !groupsInCommon.isEmpty { - availablePanes.append(.groupsInCommon) + if let groupsInCommon = groupsInCommon { + if !groupsInCommon.isEmpty { + availablePanes.append(.groupsInCommon) + } + } else if let cachedData = peerView.cachedData as? CachedUserData { + if cachedData.commonGroupCount != 0 { + availablePanes.append(.groupsInCommon) + } } return PeerInfoScreenData( @@ -314,7 +329,8 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen isContact: peerView.peerIsContact, availablePanes: availablePanes, groupsInCommon: groupsInCommon, - linkedDiscussionPeer: nil + linkedDiscussionPeer: nil, + members: nil ) } case .channel: @@ -362,10 +378,11 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen isContact: peerView.peerIsContact, availablePanes: availablePanes, groupsInCommon: [], - linkedDiscussionPeer: discussionPeer + linkedDiscussionPeer: discussionPeer, + members: nil ) } - case .group: + case let .group(_, membersContext): let status = context.account.viewTracker.peerView(peerId, updateData: false) |> map { peerView -> PeerInfoStatusData? in guard let channel = peerView.peers[peerId] as? TelegramChannel else { @@ -379,6 +396,16 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen } |> distinctUntilChanged + let membersData: Signal = membersContext.state + |> map { state -> PeerInfoMembersData? in + if state.members.count > 5 { + return .longList(membersContext) + } else { + return .shortList(state.members) + } + } + |> distinctUntilChanged + let globalNotificationsKey: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.globalNotifications])) var combinedKeys: [PostboxViewKey] = [] combinedKeys.append(globalNotificationsKey) @@ -386,9 +413,10 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen context.account.viewTracker.peerView(peerId, updateData: true), peerInfoAvailableMediaPanes(context: context, peerId: peerId), context.account.postbox.combinedView(keys: combinedKeys), - status + status, + membersData ) - |> map { peerView, availablePanes, combinedView, status -> PeerInfoScreenData in + |> map { peerView, availablePanes, combinedView, status, membersData -> PeerInfoScreenData in var globalNotificationSettings: GlobalNotificationSettings = .defaultSettings if let preferencesView = combinedView.views[globalNotificationsKey] as? PreferencesView { if let settings = preferencesView.values[PreferencesKeys.globalNotifications] as? GlobalNotificationSettings { @@ -396,6 +424,16 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen } } + var discussionPeer: Peer? + if let linkedDiscussionPeerId = (peerView.cachedData as? CachedChannelData)?.linkedDiscussionPeerId, let peer = peerView.peers[linkedDiscussionPeerId] { + discussionPeer = peer + } + + var availablePanes = availablePanes + if let membersData = membersData, case .longList = membersData { + availablePanes.insert(.members, at: 0) + } + return PeerInfoScreenData( peer: peerView.peers[peerId], cachedData: peerView.cachedData, @@ -405,7 +443,8 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen isContact: peerView.peerIsContact, availablePanes: availablePanes, groupsInCommon: [], - linkedDiscussionPeer: nil + linkedDiscussionPeer: discussionPeer, + members: membersData ) } } @@ -443,31 +482,19 @@ func peerInfoHeaderButtons(peer: Peer?, cachedData: CachedPeerData?) -> [PeerInf result.append(.call) } result.append(.mute) - - if !user.isDeleted, user.botInfo == nil && !user.flags.contains(.isSupport) { - result.append(.more) - } + result.append(.more) } else if let channel = peer as? TelegramChannel { - var canEditGroupInfo = false - var canEditMembers = false - var canAddMembers = false - var isPublic = false - var isCreator = false - - isPublic = channel.username != nil - if !isPublic, let cachedChannelData = cachedData as? CachedChannelData, cachedChannelData.peerGeoLocation != nil { - isPublic = true - } - - isCreator = channel.flags.contains(.isCreator) - if channel.hasPermission(.changeInfo) { - canEditGroupInfo = true - } - if channel.hasPermission(.banMembers) { - canEditMembers = true - } - if channel.hasPermission(.inviteMembers) { - canAddMembers = true + switch channel.info { + case .broadcast: + if let cachedData = cachedData as? CachedChannelData { + if cachedData.linkedDiscussionPeerId != nil { + result.append(.discussion) + } + } + case .group: + if channel.flags.contains(.isCreator) || channel.hasPermission(.inviteMembers) { + result.append(.addMember) + } } result.append(.mute) diff --git a/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoHeaderNode.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoHeaderNode.swift index b44399c74e..606947df54 100644 --- a/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoHeaderNode.swift +++ b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoHeaderNode.swift @@ -16,6 +16,7 @@ import ActivityIndicator enum PeerInfoHeaderButtonKey: Hashable { case message + case discussion case call case mute case more @@ -252,7 +253,7 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode { self.leftHighlightNode.image = generateImage(CGSize(width: 88.0, height: 1.0), contextGenerator: { size, context in context.clear(CGRect(origin: CGPoint(), size: size)) - let topColor = UIColor(rgb: 0x000000, alpha: 0.5) + let topColor = UIColor(rgb: 0x000000, alpha: 0.1) let bottomColor = UIColor(rgb: 0x000000, alpha: 0.0) var locations: [CGFloat] = [0.0, 1.0] @@ -272,7 +273,7 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode { self.rightHighlightNode.image = generateImage(CGSize(width: 88.0, height: 1.0), contextGenerator: { size, context in context.clear(CGRect(origin: CGPoint(), size: size)) - let topColor = UIColor(rgb: 0x000000, alpha: 0.5) + let topColor = UIColor(rgb: 0x000000, alpha: 0.1) let bottomColor = UIColor(rgb: 0x000000, alpha: 0.0) var locations: [CGFloat] = [0.0, 1.0] @@ -287,8 +288,8 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode { self.stripContainerNode = ASDisplayNode() self.contentNode.addSubnode(self.stripContainerNode) - self.inactiveStripImage = generateStretchableFilledCircleImage(diameter: 3.0, color: UIColor(white: 1.0, alpha: 0.2))! - self.activeStripImage = generateStretchableFilledCircleImage(diameter: 3.0, color: .white)! + self.inactiveStripImage = generateSmallHorizontalStretchableFilledCircleImage(diameter: 2.0, color: UIColor(white: 1.0, alpha: 0.2))! + self.activeStripImage = generateSmallHorizontalStretchableFilledCircleImage(diameter: 2.0, color: .white)! self.highlightContainerNode = ASDisplayNode() self.highlightContainerNode.addSubnode(self.leftHighlightNode) @@ -370,11 +371,11 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode { var highlightedSide: Bool? if let point = point { if point.x < size.width * 1.0 / 5.0 { - if strongSelf.currentIndex != 0 { + if strongSelf.items.count > 1 { highlightedSide = false } } else if point.x > size.width * 4.0 / 5.0 { - if strongSelf.currentIndex < strongSelf.items.count - 1 || strongSelf.items.count > 1 { + if strongSelf.items.count > 1 { highlightedSide = true } } @@ -417,6 +418,9 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode { if self.currentIndex != 0 { self.currentIndex -= 1 self.updateItems(size: size, transition: .immediate) + } else if self.items.count > 1 { + self.currentIndex = self.items.count - 1 + self.updateItems(size: size, transition: .immediate) } } else if location.x > size.width * 4.0 / 5.0 { if self.currentIndex < self.items.count - 1 { @@ -559,6 +563,7 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode { } } + let hadOneStripNode = self.stripNodes.count == 1 if self.stripNodes.count != self.items.count { if self.stripNodes.count < self.items.count { for _ in 0 ..< self.items.count - self.stripNodes.count { @@ -591,9 +596,12 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode { self.stripNodes[self.currentIndex].image = self.activeStripImage } } + if hadOneStripNode && self.stripNodes.count > 1 { + self.stripContainerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25) + } let stripInset: CGFloat = 5.0 let stripSpacing: CGFloat = 4.0 - let stripWidth: CGFloat = floor((size.width - stripInset * 2.0 - stripSpacing * CGFloat(self.stripNodes.count - 1)) / CGFloat(self.stripNodes.count)) + let stripWidth: CGFloat = max(5.0, floor((size.width - stripInset * 2.0 - stripSpacing * CGFloat(self.stripNodes.count - 1)) / CGFloat(self.stripNodes.count))) var stripX: CGFloat = stripInset for i in 0 ..< self.stripNodes.count { if i == 0 && self.stripNodes.count == 1 { @@ -601,7 +609,7 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode { } else { self.stripNodes[i].isHidden = false } - self.stripNodes[i].frame = CGRect(origin: CGPoint(x: stripX, y: 0.0), size: CGSize(width: stripWidth, height: 3.0)) + self.stripNodes[i].frame = CGRect(origin: CGPoint(x: stripX, y: 0.0), size: CGSize(width: stripWidth, height: 2.0)) stripX += stripWidth + stripSpacing } @@ -1520,7 +1528,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { transition.updateFrameAdditive(node: self.avatarListNode.listContainerNode.controlsContainerNode, frame: CGRect(origin: CGPoint(x: -controlsClippingFrame.minX, y: -controlsClippingFrame.minY), size: CGSize(width: expandedAvatarListSize.width, height: expandedAvatarListSize.height))) transition.updateFrame(node: self.avatarListNode.listContainerNode.shadowNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: expandedAvatarListSize.width, height: navigationHeight + 20.0))) - transition.updateFrame(node: self.avatarListNode.listContainerNode.stripContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: statusBarHeight + 2.0), size: CGSize(width: expandedAvatarListSize.width, height: 3.0))) + transition.updateFrame(node: self.avatarListNode.listContainerNode.stripContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: statusBarHeight + 2.0), size: CGSize(width: expandedAvatarListSize.width, height: 2.0))) transition.updateFrame(node: self.avatarListNode.listContainerNode.highlightContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: expandedAvatarListSize.width, height: expandedAvatarListSize.height))) transition.updateAlpha(node: self.avatarListNode.listContainerNode.controlsContainerNode, alpha: self.isAvatarExpanded ? (1.0 - transitionFraction) : 0.0) @@ -1681,6 +1689,9 @@ final class PeerInfoHeaderNode: ASDisplayNode { case .message: buttonText = "Message" buttonIcon = .message + case .discussion: + buttonText = "Discussion" + buttonIcon = .message case .call: buttonText = "Call" buttonIcon = .call diff --git a/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoMembers.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoMembers.swift new file mode 100644 index 0000000000..ecc921a2c0 --- /dev/null +++ b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoMembers.swift @@ -0,0 +1,153 @@ +import Foundation +import SwiftSignalKit +import Postbox +import SyncCore +import TelegramCore +import AccountContext +import TemporaryCachedPeerDataManager + +enum PeerInfoMember: Equatable { + case channelMember(RenderedChannelParticipant) + + var id: PeerId { + switch self { + case let .channelMember(channelMember): + return channelMember.peer.id + } + } + + var peer: Peer { + switch self { + case let .channelMember(channelMember): + return channelMember.peer + } + } + + var presence: TelegramUserPresence? { + switch self { + case let .channelMember(channelMember): + return channelMember.presences[channelMember.peer.id] as? TelegramUserPresence + } + } +} + +enum PeerInfoMembersDataState: Equatable { + case loading(isInitial: Bool) + case ready(canLoadMore: Bool) +} + +struct PeerInfoMembersState: Equatable { + var members: [PeerInfoMember] + var dataState: PeerInfoMembersDataState +} + +private final class PeerInfoMembersContextImpl { + private let queue: Queue + private let context: AccountContext + private let peerId: PeerId + + private var members: [PeerInfoMember] = [] + private var dataState: PeerInfoMembersDataState = .loading(isInitial: true) + + private let stateValue = Promise() + var state: Signal { + return self.stateValue.get() + } + private let disposable = MetaDisposable() + + private var channelMembersControl: PeerChannelMemberCategoryControl? + + init(queue: Queue, context: AccountContext, peerId: PeerId) { + self.queue = queue + self.context = context + self.peerId = peerId + + self.pushState() + + if peerId.namespace == Namespaces.Peer.CloudChannel { + let (disposable, control) = context.peerChannelMemberCategoriesContextsManager.recent(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, updated: { [weak self] state in + queue.async { + guard let strongSelf = self else { + return + } + strongSelf.members = state.list.map(PeerInfoMember.channelMember) + switch state.loadingState { + case let .loading(initial): + strongSelf.dataState = .loading(isInitial: initial) + case let .ready(hasMore): + strongSelf.dataState = .ready(canLoadMore: hasMore) + } + strongSelf.pushState() + } + }) + self.disposable.set(disposable) + self.channelMembersControl = control + } else if peerId.namespace == Namespaces.Peer.CloudGroup { + disposable.set((context.account.postbox.peerView(id: peerId) + |> deliverOn(self.queue)).start(next: { [weak self] view in + guard let strongSelf = self, let cachedData = view.cachedData as? CachedGroupData, let participantsData = cachedData.participants else { + return + } + var members: [PeerInfoMember] = [] + for participant in participantsData.participants { + if let peer = view.peers[participant.peerId] { + + } + } + strongSelf.dataState = .ready(canLoadMore: false) + strongSelf.pushState() + })) + } else { + self.dataState = .ready(canLoadMore: false) + self.pushState() + } + } + + deinit { + self.disposable.dispose() + } + + private func pushState() { + self.stateValue.set(.single(PeerInfoMembersState(members: self.members, dataState: self.dataState))) + } + + func loadMore() { + if case .ready(true) = self.dataState, let channelMembersControl = self.channelMembersControl { + self.context.peerChannelMemberCategoriesContextsManager.loadMore(peerId: self.peerId, control: channelMembersControl) + } + } +} + +final class PeerInfoMembersContext: Equatable { + private let queue = Queue.mainQueue() + private let impl: QueueLocalObject + + var state: Signal { + return Signal { subscriber in + let disposable = MetaDisposable() + self.impl.with { impl in + disposable.set(impl.state.start(next: { value in + subscriber.putNext(value) + })) + } + return disposable + } + } + + init(context: AccountContext, peerId: PeerId) { + let queue = self.queue + self.impl = QueueLocalObject(queue: queue, generate: { + return PeerInfoMembersContextImpl(queue: queue, context: context, peerId: peerId) + }) + } + + func loadMore() { + self.impl.with { impl in + impl.loadMore() + } + } + + static func ==(lhs: PeerInfoMembersContext, rhs: PeerInfoMembersContext) -> Bool { + return lhs === rhs + } +} diff --git a/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoPaneContainerNode.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoPaneContainerNode.swift index 4efc5d5bcd..9eb080c548 100644 --- a/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoPaneContainerNode.swift +++ b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoPaneContainerNode.swift @@ -51,6 +51,7 @@ enum PeerInfoPaneKey { case voice case music case groupsInCommon + case members } final class PeerInfoPaneTabsContainerPaneNode: ASDisplayNode { @@ -449,6 +450,12 @@ final class PeerInfoPaneContainerNode: ASDisplayNode { paneNode = PeerInfoListPaneNode(context: self.context, chatControllerInteraction: self.chatControllerInteraction!, peerId: self.peerId, tagMask: .music) case .groupsInCommon: paneNode = PeerInfoGroupsInCommonPaneNode(context: self.context, peerId: peerId, chatControllerInteraction: self.chatControllerInteraction!, openPeerContextAction: self.openPeerContextAction!, peers: data?.groupsInCommon ?? []) + case .members: + if case let .longList(membersContext) = data?.members { + paneNode = PeerInfoMembersPaneNode(context: self.context, membersContext: membersContext) + } else { + preconditionFailure() + } } let disposable = MetaDisposable() @@ -533,6 +540,8 @@ final class PeerInfoPaneContainerNode: ASDisplayNode { title = "Audio" case .groupsInCommon: title = "Groups" + case .members: + title = "Members" } return PeerInfoPaneSpecifier(key: key, title: title) }, selectedPane: self.currentPaneKey, transition: transition) diff --git a/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoScreen.swift index 5466014007..346f706c01 100644 --- a/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoScreen.swift @@ -32,6 +32,9 @@ import LegacyUI import MapResourceToAvatarSizes import LegacyComponents import WebSearchUI +import LocationResources +import LocationUI +import Geocoding protocol PeerInfoScreenItem: class { var id: AnyHashable { get } @@ -47,8 +50,6 @@ class PeerInfoScreenItemNode: ASDisplayNode { } private final class PeerInfoScreenItemSectionContainerNode: ASDisplayNode { - let id: AnyHashable - private let backgroundNode: ASDisplayNode private let topSeparatorNode: ASDisplayNode private let bottomSeparatorNode: ASDisplayNode @@ -56,9 +57,7 @@ private final class PeerInfoScreenItemSectionContainerNode: ASDisplayNode { private var currentItems: [PeerInfoScreenItem] = [] private var itemNodes: [AnyHashable: PeerInfoScreenItemNode] = [:] - init(id: AnyHashable) { - self.id = id - + override init() { self.backgroundNode = ASDisplayNode() self.backgroundNode.isLayerBacked = true @@ -82,6 +81,7 @@ private final class PeerInfoScreenItemSectionContainerNode: ASDisplayNode { var contentHeight: CGFloat = 0.0 var contentWithBackgroundHeight: CGFloat = 0.0 + var contentWithBackgroundOffset: CGFloat = 0.0 for i in 0 ..< items.count { let item = items[i] @@ -105,6 +105,15 @@ private final class PeerInfoScreenItemSectionContainerNode: ASDisplayNode { let itemTransition: ContainedViewLayoutTransition = wasAdded ? .immediate : transition + let topItem: PeerInfoScreenItem? + if i == 0 { + topItem = nil + } else if items[i - 1] is PeerInfoScreenHeaderItem { + topItem = nil + } else { + topItem = items[i - 1] + } + let bottomItem: PeerInfoScreenItem? if i == items.count - 1 { bottomItem = nil @@ -114,7 +123,7 @@ private final class PeerInfoScreenItemSectionContainerNode: ASDisplayNode { bottomItem = items[i + 1] } - let itemHeight = itemNode.update(width: width, presentationData: presentationData, item: item, topItem: i == 0 ? nil : items[i - 1], bottomItem: bottomItem, transition: itemTransition) + let itemHeight = itemNode.update(width: width, presentationData: presentationData, item: item, topItem: topItem, bottomItem: bottomItem, transition: itemTransition) let itemFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: width, height: itemHeight)) itemTransition.updateFrame(node: itemNode, frame: itemFrame) if wasAdded { @@ -123,11 +132,14 @@ private final class PeerInfoScreenItemSectionContainerNode: ASDisplayNode { } if item is PeerInfoScreenCommentItem { - } else { contentWithBackgroundHeight += itemHeight } contentHeight += itemHeight + + if item is PeerInfoScreenHeaderItem { + contentWithBackgroundOffset = contentHeight + } } var removeIds: [AnyHashable] = [] @@ -144,8 +156,8 @@ private final class PeerInfoScreenItemSectionContainerNode: ASDisplayNode { } } - transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: contentWithBackgroundHeight))) - transition.updateFrame(node: self.topSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: width, height: UIScreenPixel))) + transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentWithBackgroundOffset), size: CGSize(width: width, height: max(0.0, contentWithBackgroundHeight - contentWithBackgroundOffset)))) + transition.updateFrame(node: self.topSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentWithBackgroundOffset - UIScreenPixel), size: CGSize(width: width, height: UIScreenPixel))) transition.updateFrame(node: self.bottomSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentWithBackgroundHeight), size: CGSize(width: width, height: UIScreenPixel))) if contentHeight.isZero { @@ -160,6 +172,133 @@ private final class PeerInfoScreenItemSectionContainerNode: ASDisplayNode { } } +private final class PeerInfoScreenDynamicItemSectionContainerNode: ASDisplayNode { + private let backgroundNode: ASDisplayNode + private let topSeparatorNode: ASDisplayNode + private let bottomSeparatorNode: ASDisplayNode + + private var currentItems: [PeerInfoScreenItem] = [] + private var itemNodes: [AnyHashable: PeerInfoScreenItemNode] = [:] + + override init() { + self.backgroundNode = ASDisplayNode() + self.backgroundNode.isLayerBacked = true + + self.topSeparatorNode = ASDisplayNode() + self.topSeparatorNode.isLayerBacked = true + + self.bottomSeparatorNode = ASDisplayNode() + self.bottomSeparatorNode.isLayerBacked = true + + super.init() + + self.addSubnode(self.backgroundNode) + self.addSubnode(self.topSeparatorNode) + self.addSubnode(self.bottomSeparatorNode) + } + + func update(width: CGFloat, presentationData: PresentationData, items: [PeerInfoScreenItem], transition: ContainedViewLayoutTransition) -> CGFloat { + self.backgroundNode.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor + self.topSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor + self.bottomSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor + + var contentHeight: CGFloat = 0.0 + var contentWithBackgroundHeight: CGFloat = 0.0 + var contentWithBackgroundOffset: CGFloat = 0.0 + + for i in 0 ..< items.count { + let item = items[i] + + let itemNode: PeerInfoScreenItemNode + var wasAdded = false + if let current = self.itemNodes[item.id] { + itemNode = current + } else { + wasAdded = true + itemNode = item.node() + self.itemNodes[item.id] = itemNode + self.addSubnode(itemNode) + itemNode.bringToFrontForHighlight = { [weak self, weak itemNode] in + guard let strongSelf = self, let itemNode = itemNode else { + return + } + strongSelf.view.bringSubviewToFront(itemNode.view) + } + } + + let itemTransition: ContainedViewLayoutTransition = wasAdded ? .immediate : transition + + let topItem: PeerInfoScreenItem? + if i == 0 { + topItem = nil + } else if items[i - 1] is PeerInfoScreenHeaderItem { + topItem = nil + } else { + topItem = items[i - 1] + } + + let bottomItem: PeerInfoScreenItem? + if i == items.count - 1 { + bottomItem = nil + } else if items[i + 1] is PeerInfoScreenCommentItem { + bottomItem = nil + } else { + bottomItem = items[i + 1] + } + + let itemHeight = itemNode.update(width: width, presentationData: presentationData, item: item, topItem: topItem, bottomItem: bottomItem, transition: itemTransition) + let itemFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: width, height: itemHeight)) + itemTransition.updateFrame(node: itemNode, frame: itemFrame) + if wasAdded { + itemNode.alpha = 0.0 + transition.updateAlpha(node: itemNode, alpha: 1.0) + } + + if item is PeerInfoScreenCommentItem { + } else { + contentWithBackgroundHeight += itemHeight + } + contentHeight += itemHeight + + if item is PeerInfoScreenHeaderItem { + contentWithBackgroundOffset = contentHeight + } + } + + var removeIds: [AnyHashable] = [] + for (id, _) in self.itemNodes { + if !items.contains(where: { $0.id == id }) { + removeIds.append(id) + } + } + for id in removeIds { + if let itemNode = self.itemNodes.removeValue(forKey: id) { + transition.updateAlpha(node: itemNode, alpha: 0.0, completion: { [weak itemNode] _ in + itemNode?.removeFromSupernode() + }) + } + } + + transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentWithBackgroundOffset), size: CGSize(width: width, height: max(0.0, contentWithBackgroundHeight - contentWithBackgroundOffset)))) + transition.updateFrame(node: self.topSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentWithBackgroundOffset - UIScreenPixel), size: CGSize(width: width, height: UIScreenPixel))) + transition.updateFrame(node: self.bottomSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentWithBackgroundHeight), size: CGSize(width: width, height: UIScreenPixel))) + + if contentHeight.isZero { + transition.updateAlpha(node: self.topSeparatorNode, alpha: 0.0) + transition.updateAlpha(node: self.bottomSeparatorNode, alpha: 0.0) + } else { + transition.updateAlpha(node: self.topSeparatorNode, alpha: 1.0) + transition.updateAlpha(node: self.bottomSeparatorNode, alpha: 1.0) + } + + return contentHeight + } + + func updateVisibleItems(in rect: CGRect) { + + } +} + final class PeerInfoSelectionPanelNode: ASDisplayNode { private let context: AccountContext private let peerId: PeerId @@ -323,6 +462,12 @@ private final class PeerInfoInteraction { let editingOpenDiscussionGroupSetup: () -> Void let editingToggleMessageSignatures: (Bool) -> Void let openParticipantsSection: (PeerInfoParticipantsSection) -> Void + let editingOpenPreHistorySetup: () -> Void + let openPermissions: () -> Void + let editingOpenStickerPackSetup: () -> Void + let openLocation: () -> Void + let editingOpenSetupLocation: () -> Void + let openPeerInfo: (Peer) -> Void init( openUsername: @escaping (String) -> Void, @@ -340,7 +485,13 @@ private final class PeerInfoInteraction { editingOpenPublicLinkSetup: @escaping () -> Void, editingOpenDiscussionGroupSetup: @escaping () -> Void, editingToggleMessageSignatures: @escaping (Bool) -> Void, - openParticipantsSection: @escaping (PeerInfoParticipantsSection) -> Void + openParticipantsSection: @escaping (PeerInfoParticipantsSection) -> Void, + editingOpenPreHistorySetup: @escaping () -> Void, + openPermissions: @escaping () -> Void, + editingOpenStickerPackSetup: @escaping () -> Void, + openLocation: @escaping () -> Void, + editingOpenSetupLocation: @escaping () -> Void, + openPeerInfo: @escaping (Peer) -> Void ) { self.openUsername = openUsername self.openPhone = openPhone @@ -358,52 +509,71 @@ private final class PeerInfoInteraction { self.editingOpenDiscussionGroupSetup = editingOpenDiscussionGroupSetup self.editingToggleMessageSignatures = editingToggleMessageSignatures self.openParticipantsSection = openParticipantsSection + self.editingOpenPreHistorySetup = editingOpenPreHistorySetup + self.openPermissions = openPermissions + self.editingOpenStickerPackSetup = editingOpenStickerPackSetup + self.openLocation = openLocation + self.editingOpenSetupLocation = editingOpenSetupLocation + self.openPeerInfo = openPeerInfo } } -private func peerInfoSectionItems(data: PeerInfoScreenData?, presentationData: PresentationData, interaction: PeerInfoInteraction) -> [PeerInfoScreenItem] { +private func infoItems(data: PeerInfoScreenData?, context: AccountContext, presentationData: PresentationData, interaction: PeerInfoInteraction) -> [(AnyHashable, [PeerInfoScreenItem])] { guard let data = data else { return [] } - var items: [PeerInfoScreenItem] = [] + + enum Section: Int, CaseIterable { + case groupLocation + case peerInfo + case peerMembers + } + + var items: [Section: [PeerInfoScreenItem]] = [:] + for section in Section.allCases { + items[section] = [] + } + if let user = data.peer as? TelegramUser { if let phone = user.phone { - items.append(PeerInfoScreenLabeledValueItem(id: 2, label: "mobile", text: "\(formatPhoneNumber(phone))", textColor: .accent, action: { + items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: 2, label: "mobile", text: "\(formatPhoneNumber(phone))", textColor: .accent, action: { interaction.openPhone(phone) })) } if let username = user.username { - items.append(PeerInfoScreenLabeledValueItem(id: 1, label: "username", text: "@\(username)", textColor: .accent, action: { + items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: 1, label: "username", text: "@\(username)", textColor: .accent, action: { interaction.openUsername(username) })) } if let cachedData = data.cachedData as? CachedUserData { - if let about = cachedData.about { - items.append(PeerInfoScreenLabeledValueItem(id: 0, label: presentationData.strings.Profile_About, text: about, textColor: .primary, textBehavior: .multiLine(maxLines: 10), action: nil)) + if user.isScam { + items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: presentationData.strings.Profile_About, text: user.botInfo != nil ? presentationData.strings.UserInfo_ScamBotWarning : presentationData.strings.UserInfo_ScamUserWarning, textColor: .primary, textBehavior: .multiLine(maxLines: 10), action: nil)) + } else if let about = cachedData.about, !about.isEmpty { + items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: presentationData.strings.Profile_About, text: about, textColor: .primary, textBehavior: .multiLine(maxLines: 10), action: nil)) } } if !data.isContact { if user.botInfo == nil { - items.append(PeerInfoScreenActionItem(id: 3, text: "Add Contact", action: { + items[.peerInfo]!.append(PeerInfoScreenActionItem(id: 3, text: "Add Contact", action: { interaction.openAddContact() })) } if let cachedData = data.cachedData as? CachedUserData { if cachedData.isBlocked { - items.append(PeerInfoScreenActionItem(id: 4, text: user.botInfo != nil ? "Restart Bot" : "Unblock", action: { + items[.peerInfo]!.append(PeerInfoScreenActionItem(id: 4, text: user.botInfo != nil ? "Restart Bot" : "Unblock", action: { interaction.updateBlocked(false) })) } else { if user.flags.contains(.isSupport) { } else { - items.append(PeerInfoScreenActionItem(id: 4, text: user.botInfo != nil ? "Stop Bot" : "Block User", color: .destructive, action: { + items[.peerInfo]!.append(PeerInfoScreenActionItem(id: 4, text: user.botInfo != nil ? "Stop Bot" : "Block User", color: .destructive, action: { interaction.updateBlocked(true) })) } } } if user.botInfo != nil, !user.isVerified { - items.append(PeerInfoScreenActionItem(id: 5, text: presentationData.strings.ReportPeer_Report, action: { + items[.peerInfo]!.append(PeerInfoScreenActionItem(id: 5, text: presentationData.strings.ReportPeer_Report, action: { interaction.openReport() })) } @@ -415,15 +585,34 @@ private func peerInfoSectionItems(data: PeerInfoScreenData?, presentationData: P let ItemMembers = 4 let ItemBanned = 5 let ItemReport = 6 + let ItemLocationHeader = 7 + let ItemLocation = 8 + + if let location = (data.cachedData as? CachedChannelData)?.peerGeoLocation { + items[.groupLocation]!.append(PeerInfoScreenHeaderItem(id: ItemLocationHeader, text: presentationData.strings.GroupInfo_Location.uppercased())) + + let imageSignal = chatMapSnapshotImage(account: context.account, resource: MapSnapshotMediaResource(latitude: location.latitude, longitude: location.longitude, width: 90, height: 90)) + items[.groupLocation]!.append(PeerInfoScreenAddressItem( + id: ItemLocation, + label: "", + text: location.address.replacingOccurrences(of: ", ", with: "\n"), + imageSignal: imageSignal, + action: { + interaction.openLocation() + } + )) + } if let username = channel.username { - items.append(PeerInfoScreenLabeledValueItem(id: ItemUsername, label: presentationData.strings.Channel_LinkItem, text: "https://t.me/\(username)", textColor: .accent, action: { + items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: ItemUsername, label: presentationData.strings.Channel_LinkItem, text: "https://t.me/\(username)", textColor: .accent, action: { interaction.openUsername(username) })) } if let cachedData = data.cachedData as? CachedChannelData { - if let about = cachedData.about { - items.append(PeerInfoScreenLabeledValueItem(id: ItemAbout, label: presentationData.strings.Profile_About, text: about, textColor: .primary, textBehavior: .multiLine(maxLines: 10), action: nil)) + if channel.isScam { + items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: ItemAbout, label: presentationData.strings.Profile_About, text: presentationData.strings.GroupInfo_ScamGroupWarning, textColor: .primary, textBehavior: .multiLine(maxLines: 10), action: nil)) + } else if let about = cachedData.about, !about.isEmpty { + items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: ItemAbout, label: presentationData.strings.Profile_About, text: about, textColor: .primary, textBehavior: .multiLine(maxLines: 10), action: nil)) } if case .broadcast = channel.info { @@ -437,13 +626,13 @@ private func peerInfoSectionItems(data: PeerInfoScreenData?, presentationData: P let memberCount = cachedData.participantsSummary.memberCount ?? 0 let bannedCount = cachedData.participantsSummary.kickedCount ?? 0 - items.append(PeerInfoScreenDisclosureItem(id: ItemAdmins, label: "\(adminCount == 0 ? "" : "\(presentationStringsFormattedNumber(adminCount, presentationData.dateTimeFormat.groupingSeparator))")", text: presentationData.strings.GroupInfo_Administrators, action: { + items[.peerInfo]!.append(PeerInfoScreenDisclosureItem(id: ItemAdmins, label: "\(adminCount == 0 ? "" : "\(presentationStringsFormattedNumber(adminCount, presentationData.dateTimeFormat.groupingSeparator))")", text: presentationData.strings.GroupInfo_Administrators, action: { interaction.openParticipantsSection(.admins) })) - items.append(PeerInfoScreenDisclosureItem(id: ItemMembers, label: "\(memberCount == 0 ? "" : "\(presentationStringsFormattedNumber(memberCount, presentationData.dateTimeFormat.groupingSeparator))")", text: presentationData.strings.Channel_Info_Subscribers, action: { + items[.peerInfo]!.append(PeerInfoScreenDisclosureItem(id: ItemMembers, label: "\(memberCount == 0 ? "" : "\(presentationStringsFormattedNumber(memberCount, presentationData.dateTimeFormat.groupingSeparator))")", text: presentationData.strings.Channel_Info_Subscribers, action: { interaction.openParticipantsSection(.members) })) - items.append(PeerInfoScreenDisclosureItem(id: ItemBanned, label: "\(bannedCount == 0 ? "" : "\(presentationStringsFormattedNumber(bannedCount, presentationData.dateTimeFormat.groupingSeparator))")", text: presentationData.strings.GroupInfo_Permissions_Removed, action: { + items[.peerInfo]!.append(PeerInfoScreenDisclosureItem(id: ItemBanned, label: "\(bannedCount == 0 ? "" : "\(presentationStringsFormattedNumber(bannedCount, presentationData.dateTimeFormat.groupingSeparator))")", text: presentationData.strings.GroupInfo_Permissions_Removed, action: { interaction.openParticipantsSection(.banned) })) } @@ -452,21 +641,49 @@ private func peerInfoSectionItems(data: PeerInfoScreenData?, presentationData: P } } else if let group = data.peer as? TelegramGroup { if let cachedData = data.cachedData as? CachedGroupData { - if let about = cachedData.about { - items.append(PeerInfoScreenLabeledValueItem(id: 0, label: presentationData.strings.Profile_About, text: about, textColor: .primary, textBehavior: .multiLine(maxLines: 10), action: nil)) + if group.isScam { + items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: presentationData.strings.Profile_About, text: presentationData.strings.GroupInfo_ScamGroupWarning, textColor: .primary, textBehavior: .multiLine(maxLines: 10), action: nil)) + } else if let about = cachedData.about, !about.isEmpty { + items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: presentationData.strings.Profile_About, text: about, textColor: .primary, textBehavior: .multiLine(maxLines: 10), action: nil)) } } } - return items + + if let members = data.members, case let .shortList(memberList) = members { + for member in memberList { + var presence = member.presence + if member.id == context.account.peerId { + presence = TelegramUserPresence(status: .present(until: Int32.max - 1), lastActivity: 0) + } + items[.peerMembers]!.append(PeerInfoScreenMemberItem(id: member.id, context: context, peer: member.peer, presence: presence, action: { + interaction.openPeerInfo(member.peer) + })) + } + } + + var result: [(AnyHashable, [PeerInfoScreenItem])] = [] + for section in Section.allCases { + if let sectionItems = items[section], !sectionItems.isEmpty { + result.append((section, sectionItems)) + } + } + return result } -private func editingInfoSectionItems(data: PeerInfoScreenData?, presentationData: PresentationData, interaction: PeerInfoInteraction) -> [PeerInfoScreenItem] { - guard let data = data else { - return [] +private func editingItems(data: PeerInfoScreenData?, context: AccountContext, presentationData: PresentationData, interaction: PeerInfoInteraction) -> [(AnyHashable, [PeerInfoScreenItem])] { + enum Section: Int, CaseIterable { + case notifications + case groupLocation + case peerPublicSettings + case peerSettings } - var items: [PeerInfoScreenItem] = [] - if let notificationSettings = data.notificationSettings { + var items: [Section: [PeerInfoScreenItem]] = [:] + for section in Section.allCases { + items[section] = [] + } + + if let data = data, let notificationSettings = data.notificationSettings { let notificationsLabel: String let soundLabel: String let notificationSettings = notificationSettings as? TelegramPeerNotificationSettings ?? TelegramPeerNotificationSettings.defaultSettings @@ -483,82 +700,230 @@ private func editingInfoSectionItems(data: PeerInfoScreenData?, presentationData let globalNotificationSettings: GlobalNotificationSettings = data.globalNotificationSettings ?? GlobalNotificationSettings.defaultSettings soundLabel = localizedPeerNotificationSoundString(strings: presentationData.strings, sound: notificationSettings.messageSound, default: globalNotificationSettings.effective.privateChats.sound) - items.append(PeerInfoScreenDisclosureItem(id: 0, label: notificationsLabel, text: "Notifications", action: { + items[.notifications]!.append(PeerInfoScreenDisclosureItem(id: 0, label: notificationsLabel, text: "Notifications", action: { interaction.editingOpenNotificationSettings() })) - items.append(PeerInfoScreenDisclosureItem(id: 1, label: soundLabel, text: "Sound", action: { + items[.notifications]!.append(PeerInfoScreenDisclosureItem(id: 1, label: soundLabel, text: "Sound", action: { interaction.editingOpenSoundSettings() })) - items.append(PeerInfoScreenSwitchItem(id: 2, text: "Show Message Text", value: notificationSettings.displayPreviews != .hide, toggled: { value in + items[.notifications]!.append(PeerInfoScreenSwitchItem(id: 2, text: "Show Message Text", value: notificationSettings.displayPreviews != .hide, toggled: { value in interaction.editingToggleShowMessageText(value) })) } - return items -} - -private func editingActionsSectionItems(data: PeerInfoScreenData?, presentationData: PresentationData, interaction: PeerInfoInteraction) -> [PeerInfoScreenItem] { - var items: [PeerInfoScreenItem] = [] if let data = data { if let user = data.peer as? TelegramUser { + let ItemDelete = 0 if data.isContact { - items.append(PeerInfoScreenActionItem(id: 0, text: presentationData.strings.UserInfo_DeleteContact, color: .destructive, action: { + items[.peerSettings]!.append(PeerInfoScreenActionItem(id: ItemDelete, text: presentationData.strings.UserInfo_DeleteContact, color: .destructive, action: { interaction.requestDeleteContact() })) } } else if let channel = data.peer as? TelegramChannel { - if channel.flags.contains(.isCreator) { - let linkText: String - if let username = channel.username { - linkText = "@\(username)" - } else { - linkText = presentationData.strings.Channel_Setup_TypePrivate - } - items.append(PeerInfoScreenDisclosureItem(id: 1, label: linkText, text: presentationData.strings.Channel_TypeSetup_Title, action: { - interaction.editingOpenPublicLinkSetup() - })) - - let discussionGroupTitle: String - if let cachedData = data.cachedData as? CachedChannelData { - if let peer = data.linkedDiscussionPeer { - if let addressName = peer.addressName, !addressName.isEmpty { - discussionGroupTitle = "@\(addressName)" + let ItemUsername = 1 + let ItemDiscussionGroup = 2 + let ItemSignMessages = 3 + let ItemSignMessagesHelp = 4 + + switch channel.info { + case .broadcast: + if channel.flags.contains(.isCreator) { + let linkText: String + if let username = channel.username { + linkText = "@\(username)" + } else { + linkText = presentationData.strings.Channel_Setup_TypePrivate + } + items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemUsername, label: linkText, text: presentationData.strings.Channel_TypeSetup_Title, action: { + interaction.editingOpenPublicLinkSetup() + })) + + let discussionGroupTitle: String + if let cachedData = data.cachedData as? CachedChannelData { + if let peer = data.linkedDiscussionPeer { + if let addressName = peer.addressName, !addressName.isEmpty { + discussionGroupTitle = "@\(addressName)" + } else { + discussionGroupTitle = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + } } else { - discussionGroupTitle = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + discussionGroupTitle = presentationData.strings.Channel_DiscussionGroupAdd } } else { - discussionGroupTitle = presentationData.strings.Channel_DiscussionGroupAdd + discussionGroupTitle = "..." } - } else { - discussionGroupTitle = "..." + + items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemDiscussionGroup, label: discussionGroupTitle, text: presentationData.strings.Channel_DiscussionGroup, action: { + interaction.editingOpenDiscussionGroupSetup() + })) + + let messagesShouldHaveSignatures: Bool + switch channel.info { + case let .broadcast(info): + messagesShouldHaveSignatures = info.flags.contains(.messagesShouldHaveSignatures) + default: + messagesShouldHaveSignatures = false + } + items[.peerSettings]!.append(PeerInfoScreenSwitchItem(id: ItemSignMessages, text: presentationData.strings.Channel_SignMessages, value: messagesShouldHaveSignatures, toggled: { value in + interaction.editingToggleMessageSignatures(value) + })) + items[.peerSettings]!.append(PeerInfoScreenCommentItem(id: ItemSignMessagesHelp, text: presentationData.strings.Channel_SignMessages_Help)) } + case .group: + let ItemUsername = 1 + let ItemLinkedChannel = 2 + let ItemPreHistory = 3 + let ItemStickerPack = 4 + let ItemPermissions = 5 + let ItemAdmins = 6 + let ItemLocationHeader = 7 + let ItemLocation = 8 + let ItemLocationSetup = 9 - items.append(PeerInfoScreenDisclosureItem(id: 2, label: discussionGroupTitle, text: presentationData.strings.Channel_DiscussionGroup, action: { - interaction.editingOpenDiscussionGroupSetup() - })) - //items.append(PeerInfoScreenCommentItem(id: 3, text: presentationData.strings.Channel_DiscussionGroupInfo)) + let isCreator = channel.flags.contains(.isCreator) + let isPublic = channel.username != nil - let messagesShouldHaveSignatures: Bool - switch channel.info { - case let .broadcast(info): - messagesShouldHaveSignatures = info.flags.contains(.messagesShouldHaveSignatures) - default: - messagesShouldHaveSignatures = false + if let cachedData = data.cachedData as? CachedChannelData { + if isCreator, let location = cachedData.peerGeoLocation { + items[.groupLocation]!.append(PeerInfoScreenHeaderItem(id: ItemLocationHeader, text: presentationData.strings.GroupInfo_Location.uppercased())) + + let imageSignal = chatMapSnapshotImage(account: context.account, resource: MapSnapshotMediaResource(latitude: location.latitude, longitude: location.longitude, width: 90, height: 90)) + items[.groupLocation]!.append(PeerInfoScreenAddressItem( + id: ItemLocation, + label: "", + text: location.address.replacingOccurrences(of: ", ", with: "\n"), + imageSignal: imageSignal, + action: { + interaction.openLocation() + } + )) + if cachedData.flags.contains(.canChangePeerGeoLocation) { + items[.groupLocation]!.append(PeerInfoScreenActionItem(id: ItemLocationSetup, text: presentationData.strings.Group_Location_ChangeLocation, action: { + interaction.editingOpenSetupLocation() + })) + } + } + + if isCreator || (channel.adminRights != nil && channel.hasPermission(.pinMessages)) { + if cachedData.peerGeoLocation != nil { + if isCreator { + let linkText: String + if let username = channel.username { + linkText = "@\(username)" + } else { + linkText = presentationData.strings.GroupInfo_PublicLinkAdd + } + items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemUsername, label: linkText, text: presentationData.strings.GroupInfo_PublicLink, action: { + interaction.editingOpenPublicLinkSetup() + })) + } + } else { + if cachedData.flags.contains(.canChangeUsername) { + items[.peerPublicSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemUsername, label: isPublic ? presentationData.strings.Channel_Setup_TypePublic : presentationData.strings.Channel_Setup_TypePrivate, text: presentationData.strings.GroupInfo_GroupType, action: { + interaction.editingOpenPublicLinkSetup() + })) + + if let linkedDiscussionPeer = data.linkedDiscussionPeer { + let peerTitle: String + if let addressName = linkedDiscussionPeer.addressName, !addressName.isEmpty { + peerTitle = "@\(addressName)" + } else { + peerTitle = linkedDiscussionPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + } + items[.peerPublicSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemLinkedChannel, label: peerTitle, text: presentationData.strings.Group_LinkedChannel, action: { + interaction.editingOpenDiscussionGroupSetup() + })) + } + } + if !isPublic && cachedData.linkedDiscussionPeerId == nil { + items[.peerPublicSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemPreHistory, label: cachedData.flags.contains(.preHistoryEnabled) ? presentationData.strings.GroupInfo_GroupHistoryVisible : presentationData.strings.GroupInfo_GroupHistoryHidden, text: presentationData.strings.GroupInfo_GroupHistory, action: { + interaction.editingOpenPreHistorySetup() + })) + } + } + } + + if cachedData.flags.contains(.canSetStickerSet) && canEditPeerInfo(peer: channel) { + items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemStickerPack, label: cachedData.stickerPack?.title ?? presentationData.strings.GroupInfo_SharedMediaNone, text: presentationData.strings.Stickers_GroupStickers, action: { + interaction.editingOpenStickerPackSetup() + })) + } + + var canViewAdminsAndBanned = false + if let adminRights = channel.adminRights, !adminRights.isEmpty { + canViewAdminsAndBanned = true + } else if channel.flags.contains(.isCreator) { + canViewAdminsAndBanned = true + } + + if canViewAdminsAndBanned { + var activePermissionCount: Int? + if let defaultBannedRights = channel.defaultBannedRights { + var count = 0 + for (right, _) in allGroupPermissionList { + if !defaultBannedRights.flags.contains(right) { + count += 1 + } + } + activePermissionCount = count + } + + items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemPermissions, label: activePermissionCount.flatMap({ "\($0)/\(allGroupPermissionList.count)" }) ?? "", text: presentationData.strings.GroupInfo_Permissions, action: { + interaction.openPermissions() + })) + + items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemAdmins, label: cachedData.participantsSummary.adminCount.flatMap { "\(presentationStringsFormattedNumber($0, presentationData.dateTimeFormat.groupingSeparator))" } ?? "", text: presentationData.strings.GroupInfo_Administrators, action: { + interaction.openParticipantsSection(.admins) + })) + } } - items.append(PeerInfoScreenSwitchItem(id: 4, text: presentationData.strings.Channel_SignMessages, value: messagesShouldHaveSignatures, toggled: { value in - interaction.editingToggleMessageSignatures(value) - })) - items.append(PeerInfoScreenCommentItem(id: 5, text: presentationData.strings.Channel_SignMessages_Help)) } } else if let group = data.peer as? TelegramGroup { + let ItemUsername = 1 + let ItemPreHistory = 2 + let ItemPermissions = 3 + let ItemAdmins = 4 + if case .creator = group.role { - items.append(PeerInfoScreenDisclosureItem(id: 1, label: presentationData.strings.Group_Setup_TypePrivate, text: presentationData.strings.Channel_TypeSetup_Title, action: { - interaction.editingOpenPublicLinkSetup() + if let cachedData = data.cachedData as? CachedGroupData { + if cachedData.flags.contains(.canChangeUsername) { + items[.peerPublicSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemUsername, label: presentationData.strings.Group_Setup_TypePrivate, text: presentationData.strings.GroupInfo_GroupType, action: { + interaction.editingOpenPublicLinkSetup() + })) + } + } + items[.peerPublicSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemPreHistory, label: presentationData.strings.GroupInfo_GroupHistoryHidden, text: presentationData.strings.GroupInfo_GroupHistory, action: { + interaction.editingOpenPreHistorySetup() + })) + var activePermissionCount: Int? + if let defaultBannedRights = group.defaultBannedRights { + var count = 0 + for (right, _) in allGroupPermissionList { + if !defaultBannedRights.flags.contains(right) { + count += 1 + } + } + activePermissionCount = count + } + + items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemPermissions, label: activePermissionCount.flatMap({ "\($0)/\(allGroupPermissionList.count)" }) ?? "", text: presentationData.strings.GroupInfo_Permissions, action: { + interaction.openPermissions() + })) + + items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemAdmins, label: "", text: presentationData.strings.GroupInfo_Administrators, action: { + interaction.openParticipantsSection(.admins) })) } } } - return items + + var result: [(AnyHashable, [PeerInfoScreenItem])] = [] + for section in Section.allCases { + if let sectionItems = items[section], !sectionItems.isEmpty { + result.append((section, sectionItems)) + } + } + return result } private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate { @@ -570,9 +935,8 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD let scrollNode: ASScrollNode let headerNode: PeerInfoHeaderNode - private let infoSection: PeerInfoScreenItemSectionContainerNode - private let editingInfoSection: PeerInfoScreenItemSectionContainerNode - private let editingActionsSection: PeerInfoScreenItemSectionContainerNode + private var regularSections: [AnyHashable: PeerInfoScreenItemSectionContainerNode] = [:] + private var editingSections: [AnyHashable: PeerInfoScreenItemSectionContainerNode] = [:] private let paneContainerNode: PeerInfoPaneContainerNode private var ignoreScrolling: Bool = false private var hapticFeedback: HapticFeedback? @@ -623,9 +987,6 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD self.scrollNode.view.delaysContentTouches = false self.headerNode = PeerInfoHeaderNode(context: context, avatarInitiallyExpanded: avatarInitiallyExpanded) - self.infoSection = PeerInfoScreenItemSectionContainerNode(id: 0) - self.editingInfoSection = PeerInfoScreenItemSectionContainerNode(id: 1) - self.editingActionsSection = PeerInfoScreenItemSectionContainerNode(id: 2) self.paneContainerNode = PeerInfoPaneContainerNode(context: context, peerId: peerId) super.init() @@ -678,6 +1039,24 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD }, openParticipantsSection: { [weak self] section in self?.openParticipantsSection(section: section) + }, + editingOpenPreHistorySetup: { [weak self] in + self?.editingOpenPreHistorySetup() + }, + openPermissions: { [weak self] in + self?.openPermissions() + }, + editingOpenStickerPackSetup: { [weak self] in + self?.editingOpenStickerPackSetup() + }, + openLocation: { [weak self] in + self?.openLocation() + }, + editingOpenSetupLocation: { [weak self] in + self?.editingOpenSetupLocation() + }, + openPeerInfo: { [weak self] peer in + self?.openPeerInfo(peer: peer) } ) @@ -940,6 +1319,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD }) } }) + strongSelf.view.endEditing(true) strongSelf.controller?.present(actionSheet, in: .window(.root)) } else { strongSelf.context.sharedContext.applicationBindings.openUrl(url) @@ -961,6 +1341,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD actionSheet?.dismissAnimated() }) ])]) + strongSelf.view.endEditing(true) strongSelf.controller?.present(actionSheet, in: .window(.root)) default: break @@ -1017,9 +1398,6 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD self.scrollNode.view.scrollsToTop = false self.scrollNode.view.delegate = self self.addSubnode(self.scrollNode) - self.scrollNode.addSubnode(self.infoSection) - self.scrollNode.addSubnode(self.editingInfoSection) - self.scrollNode.addSubnode(self.editingActionsSection) self.scrollNode.addSubnode(self.paneContainerNode) self.addSubnode(self.headerNode) @@ -1070,6 +1448,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD self?.headerNode.updateAvatarIsHidden(false) } })) + strongSelf.view.endEditing(true) strongSelf.controller?.present(galleryController, in: .window(.root), with: AvatarGalleryControllerPresentationArguments(transitionArguments: { _ in return GalleryTransitionArguments(transitionNode: transitionNode, addToTransitionSurface: { _ in }) @@ -1369,6 +1748,12 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD if let navigationController = controller.navigationController as? NavigationController { self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(self.peerId))) } + case .discussion: + if let cachedData = self.data?.cachedData as? CachedChannelData, let linkedDiscussionPeerId = cachedData.linkedDiscussionPeerId { + if let navigationController = controller.navigationController as? NavigationController { + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(linkedDiscussionPeerId))) + } + } case .call: self.requestCall() case .mute: @@ -1480,26 +1865,50 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD self?.openReport() })) } - if channel.flags.contains(.isCreator) { - items.append(ActionSheetButtonItem(title: presentationData.strings.ChannelInfo_DeleteChannel, color: .destructive, action: { [weak self] in - dismissAction() - self?.openDeleteChannel() - })) - } else { - if case .member = channel.participationStatus { - items.append(ActionSheetButtonItem(title: presentationData.strings.Channel_LeaveChannel, color: .destructive, action: { [weak self] in + + switch channel.info { + case .broadcast: + if channel.flags.contains(.isCreator) { + items.append(ActionSheetButtonItem(title: presentationData.strings.ChannelInfo_DeleteChannel, color: .destructive, action: { [weak self] in dismissAction() - self?.openLeaveChannel() + self?.openDeletePeer() })) + } else { + if case .member = channel.participationStatus { + items.append(ActionSheetButtonItem(title: presentationData.strings.Channel_LeaveChannel, color: .destructive, action: { [weak self] in + dismissAction() + self?.openLeavePeer() + })) + } + } + case .group: + if channel.flags.contains(.isCreator) { + items.append(ActionSheetButtonItem(title: presentationData.strings.ChannelInfo_DeleteGroup, color: .destructive, action: { [weak self] in + dismissAction() + self?.openDeletePeer() + })) + } else { + if case .member = channel.participationStatus { + items.append(ActionSheetButtonItem(title: presentationData.strings.Group_LeaveGroup, color: .destructive, action: { [weak self] in + dismissAction() + self?.openLeavePeer() + })) + } } } } else if let group = peer as? TelegramGroup { - + if case .Member = group.membership { + items.append(ActionSheetButtonItem(title: presentationData.strings.Group_LeaveGroup, color: .destructive, action: { [weak self] in + dismissAction() + self?.openLeavePeer() + })) + } } actionSheet.setItemGroups([ ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ActionSheetButtonItem(title: self.presentationData.strings.Common_Cancel, action: { dismissAction() })]) ]) + self.view.endEditing(true) controller.present(actionSheet, in: .window(.root)) case .addMember: break @@ -1604,6 +2013,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD private func openUsername(value: String) { let shareController = ShareController(context: context, subject: .url("\(value)")) + self.view.endEditing(true) self.controller?.present(shareController, in: .window(.root)) } @@ -1669,6 +2079,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD ]), ActionSheetItemGroup(items: [ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, action: { dismissAction() })]) ]) + strongSelf.view.endEditing(true) strongSelf.controller?.present(actionSheet, in: .window(.root)) } else { strongSelf.context.sharedContext.applicationBindings.openUrl("tel:\(formatPhoneNumber(value).replacingOccurrences(of: " ", with: ""))") @@ -1710,6 +2121,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } let _ = updatePeerMuteSetting(account: strongSelf.context.account, peerId: strongSelf.peerId, muteInterval: value).start() }) + strongSelf.view.endEditing(true) strongSelf.controller?.present(muteSettingsController, in: .window(.root)) }) } @@ -1814,6 +2226,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD ]), ActionSheetItemGroup(items: [ActionSheetButtonItem(title: self.presentationData.strings.Common_Cancel, action: { dismissAction() })]) ]) + self.view.endEditing(true) self.controller?.present(actionSheet, in: .window(.root)) } @@ -1879,6 +2292,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD ]), ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })]) ]) + strongSelf.view.endEditing(true) strongSelf.controller?.present(actionSheet, in: .window(.root)) } else { let text: String @@ -1902,6 +2316,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD guard let controller = self.controller else { return } + self.view.endEditing(true) controller.present(peerReportOptionsController(context: self.context, subject: .peer(self.peerId), present: { [weak controller] c, a in controller?.present(c, in: .window(.root), with: a) }, push: { [weak controller] c in @@ -1917,6 +2332,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } if let peer = peer as? TelegramUser, let username = peer.username { let shareController = ShareController(context: strongSelf.context, subject: .url("https://t.me/\(username)")) + strongSelf.view.endEditing(true) strongSelf.controller?.present(shareController, in: .window(.root)) } }) @@ -1964,7 +2380,10 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } private func editingOpenDiscussionGroupSetup() { - self.controller?.push(channelDiscussionGroupSetupController(context: self.context, peerId: self.peerId)) + guard let data = self.data, let peer = data.peer else { + return + } + self.controller?.push(channelDiscussionGroupSetupController(context: self.context, peerId: peer.id)) } private func editingToggleMessageSignatures(value: Bool) { @@ -1972,17 +2391,103 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } private func openParticipantsSection(section: PeerInfoParticipantsSection) { + guard let data = self.data, let peer = data.peer else { + return + } switch section { case .members: self.controller?.push(channelMembersController(context: self.context, peerId: self.peerId)) case .admins: - self.controller?.push(channelAdminsController(context: self.context, peerId: self.peerId)) + if peer is TelegramGroup { + self.controller?.push(channelAdminsController(context: self.context, peerId: self.peerId)) + } else if peer is TelegramChannel { + self.controller?.push(channelAdminsController(context: self.context, peerId: self.peerId)) + } case .banned: self.controller?.push(channelBlacklistController(context: self.context, peerId: self.peerId)) } } - private func openDeleteChannel() { + private func editingOpenPreHistorySetup() { + guard let data = self.data, let peer = data.peer else { + return + } + self.controller?.push(groupPreHistorySetupController(context: self.context, peerId: peer.id, upgradedToSupergroup: { _, f in f() })) + } + + private func openPermissions() { + guard let data = self.data, let peer = data.peer else { + return + } + self.controller?.push(channelPermissionsController(context: self.context, peerId: peer.id)) + } + + private func editingOpenStickerPackSetup() { + guard let data = self.data, let peer = data.peer, let cachedData = data.cachedData as? CachedChannelData else { + return + } + self.controller?.push(groupStickerPackSetupController(context: self.context, peerId: peer.id, currentPackInfo: cachedData.stickerPack)) + } + + private func openLocation() { + guard let data = self.data, let peer = data.peer, let cachedData = data.cachedData as? CachedChannelData, let location = cachedData.peerGeoLocation else { + return + } + let context = self.context + let presentationData = self.presentationData + let mapMedia = TelegramMediaMap(latitude: location.latitude, longitude: location.longitude, geoPlace: nil, venue: MapVenue(title: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), address: location.address, provider: nil, id: nil, type: nil), liveBroadcastingTimeout: nil) + let locationController = legacyLocationController(message: nil, mapMedia: mapMedia, context: context, openPeer: { _ in }, sendLiveLocation: { _, _ in }, stopLiveLocation: {}, openUrl: { url in + context.sharedContext.applicationBindings.openUrl(url) + }) + self.controller?.push(locationController) + } + + private func editingOpenSetupLocation() { + guard let data = self.data, let peer = data.peer else { + return + } + let presentationData = self.presentationData + let locationController = legacyLocationPickerController(context: self.context, selfPeer: peer, peer: peer, sendLocation: { [weak self] coordinate, _, address in + guard let strongSelf = self else { + return + } + let addressSignal: Signal + if let address = address { + addressSignal = .single(address) + } else { + addressSignal = reverseGeocodeLocation(latitude: coordinate.latitude, longitude: coordinate.longitude) + |> map { placemark in + if let placemark = placemark { + return placemark.fullAddress + } else { + return "\(coordinate.latitude), \(coordinate.longitude)" + } + } + } + + let context = strongSelf.context + let _ = (addressSignal + |> mapToSignal { address -> Signal in + return updateChannelGeoLocation(postbox: context.account.postbox, network: context.account.network, channelId: peer.id, coordinate: (coordinate.latitude, coordinate.longitude), address: address) + } + |> deliverOnMainQueue).start(error: { errror in + guard let strongSelf = self else { + return + } + strongSelf.controller?.present(textAlertController(context: context, title: nil, text: strongSelf.presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root)) + }) + }, sendLiveLocation: { _, _ in }, theme: presentationData.theme, customLocationPicker: true, presentationCompleted: { + }) + self.controller?.push(locationController) + } + + private func openPeerInfo(peer: Peer) { + if let infoController = self.context.sharedContext.makePeerInfoController(context: self.context, peer: peer, mode: .generic, avatarInitiallyExpanded: false) { + (self.controller?.navigationController as? NavigationController)?.pushViewController(infoController) + } + } + + private func openDeletePeer() { let peerId = self.peerId let _ = (self.context.account.postbox.transaction { transaction -> Peer? in return transaction.getPeer(peerId) @@ -1991,6 +2496,14 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD guard let strongSelf = self, let peer = peer else { return } + var isGroup = false + if let channel = peer as? TelegramChannel { + if case .group = channel.info { + isGroup = true + } + } else if peer is TelegramGroup { + isGroup = true + } let presentationData = strongSelf.presentationData let actionSheet = ActionSheetController(presentationData: presentationData) let dismissAction: () -> Void = { [weak actionSheet] in @@ -1998,19 +2511,20 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } actionSheet.setItemGroups([ ActionSheetItemGroup(items: [ - ActionSheetTextItem(title: presentationData.strings.ChannelInfo_DeleteChannelConfirmation), - ActionSheetButtonItem(title: presentationData.strings.ChannelInfo_DeleteChannel, color: .destructive, action: { + ActionSheetTextItem(title: isGroup ? presentationData.strings.ChannelInfo_DeleteGroupConfirmation : presentationData.strings.ChannelInfo_DeleteChannelConfirmation), + ActionSheetButtonItem(title: isGroup ? presentationData.strings.ChannelInfo_DeleteGroup : presentationData.strings.ChannelInfo_DeleteChannel, color: .destructive, action: { dismissAction() self?.deletePeerChat(peer: peer, globally: true) }), ]), ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })]) ]) + strongSelf.view.endEditing(true) strongSelf.controller?.present(actionSheet, in: .window(.root)) }) } - private func openLeaveChannel() { + private func openLeavePeer() { let peerId = self.peerId let _ = (self.context.account.postbox.transaction { transaction -> Peer? in return transaction.getPeer(peerId) @@ -2019,6 +2533,14 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD guard let strongSelf = self, let peer = peer else { return } + var isGroup = false + if let channel = peer as? TelegramChannel { + if case .group = channel.info { + isGroup = true + } + } else if peer is TelegramGroup { + isGroup = true + } let presentationData = strongSelf.presentationData let actionSheet = ActionSheetController(presentationData: presentationData) let dismissAction: () -> Void = { [weak actionSheet] in @@ -2026,13 +2548,14 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } actionSheet.setItemGroups([ ActionSheetItemGroup(items: [ - ActionSheetButtonItem(title: presentationData.strings.Channel_LeaveChannel, color: .destructive, action: { + ActionSheetButtonItem(title: isGroup ? presentationData.strings.Group_LeaveGroup : presentationData.strings.Channel_LeaveChannel, color: .destructive, action: { dismissAction() self?.deletePeerChat(peer: peer, globally: false) }), ]), ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })]) ]) + strongSelf.view.endEditing(true) strongSelf.controller?.present(actionSheet, in: .window(.root)) }) } @@ -2083,6 +2606,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD legacyController.bind(controller: navigationController) + strongSelf.view.endEditing(true) strongSelf.controller?.present(legacyController, in: .window(.root)) var hasPhotos = false @@ -2242,6 +2766,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD actionSheet?.dismissAnimated() }) ])]) + strongSelf.view.endEditing(true) strongSelf.controller?.present(actionSheet, in: .window(.root)) } })) @@ -2411,54 +2936,83 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD contentHeight += headerHeight contentHeight += sectionSpacing - let infoSectionHeight = self.infoSection.update(width: layout.size.width, presentationData: self.presentationData, items: peerInfoSectionItems(data: self.data, presentationData: self.presentationData, interaction: self.interaction), transition: transition) - let infoSectionFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: layout.size.width, height: infoSectionHeight)) - if additive { - transition.updateFrameAdditive(node: self.infoSection, frame: infoSectionFrame) - } else { - transition.updateFrame(node: self.infoSection, frame: infoSectionFrame) - } - - let editingInfoSectionHeight = self.editingInfoSection.update(width: layout.size.width, presentationData: self.presentationData, items: editingInfoSectionItems(data: self.data, presentationData: self.presentationData, interaction: self.interaction), transition: transition) - let editingInfoSectionFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: layout.size.width, height: infoSectionHeight)) - if additive { - transition.updateFrameAdditive(node: self.editingInfoSection, frame: editingInfoSectionFrame) - } else { - transition.updateFrame(node: self.editingInfoSection, frame: editingInfoSectionFrame) - } - - if self.state.isEditing { - transition.updateAlpha(node: self.infoSection, alpha: 0.0) - transition.updateAlpha(node: self.editingInfoSection, alpha: 1.0) - transition.updateAlpha(node: self.editingActionsSection, alpha: 1.0) - if !editingInfoSectionHeight.isZero { - contentHeight += editingInfoSectionHeight - contentHeight += sectionSpacing + var validRegularSections: [AnyHashable] = [] + for (sectionId, sectionItems) in infoItems(data: self.data, context: self.context, presentationData: self.presentationData, interaction: self.interaction) { + validRegularSections.append(sectionId) + + let sectionNode: PeerInfoScreenItemSectionContainerNode + if let current = self.regularSections[sectionId] { + sectionNode = current + } else { + sectionNode = PeerInfoScreenItemSectionContainerNode() + self.regularSections[sectionId] = sectionNode + self.scrollNode.addSubnode(sectionNode) } - } else { - transition.updateAlpha(node: self.infoSection, alpha: 1.0) - transition.updateAlpha(node: self.editingInfoSection, alpha: 0.0) - transition.updateAlpha(node: self.editingActionsSection, alpha: 0.0) - if !infoSectionHeight.isZero { - contentHeight += infoSectionHeight + + let sectionHeight = sectionNode.update(width: layout.size.width, presentationData: self.presentationData, items: sectionItems, transition: transition) + let sectionFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: layout.size.width, height: sectionHeight)) + if additive { + transition.updateFrameAdditive(node: sectionNode, frame: sectionFrame) + } else { + transition.updateFrame(node: sectionNode, frame: sectionFrame) + } + + transition.updateAlpha(node: sectionNode, alpha: self.state.isEditing ? 0.0 : 1.0) + if !sectionHeight.isZero && !self.state.isEditing { + contentHeight += sectionHeight contentHeight += sectionSpacing } } - - let editingActionsSectionHeight = self.editingActionsSection.update(width: layout.size.width, presentationData: self.presentationData, items: editingActionsSectionItems(data: self.data, presentationData: self.presentationData, interaction: self.interaction), transition: transition) - let editingActionsSectionFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: layout.size.width, height: editingActionsSectionHeight)) - if additive { - transition.updateFrameAdditive(node: self.editingActionsSection, frame: editingActionsSectionFrame) - } else { - transition.updateFrame(node: self.editingActionsSection, frame: editingActionsSectionFrame) + var removeRegularSections: [AnyHashable] = [] + for (sectionId, sectionNode) in self.regularSections { + if !validRegularSections.contains(sectionId) { + removeRegularSections.append(sectionId) + } + } + for sectionId in removeRegularSections { + if let sectionNode = self.regularSections.removeValue(forKey: sectionId) { + sectionNode.removeFromSupernode() + } } - if self.state.isEditing { - if !editingActionsSectionHeight.isZero { - contentHeight += editingActionsSectionHeight + var validEditingSections: [AnyHashable] = [] + for (sectionId, sectionItems) in editingItems(data: self.data, context: self.context, presentationData: self.presentationData, interaction: self.interaction) { + validEditingSections.append(sectionId) + + let sectionNode: PeerInfoScreenItemSectionContainerNode + if let current = self.editingSections[sectionId] { + sectionNode = current + } else { + sectionNode = PeerInfoScreenItemSectionContainerNode() + self.editingSections[sectionId] = sectionNode + self.scrollNode.addSubnode(sectionNode) + } + + let sectionHeight = sectionNode.update(width: layout.size.width, presentationData: self.presentationData, items: sectionItems, transition: transition) + let sectionFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: layout.size.width, height: sectionHeight)) + if additive { + transition.updateFrameAdditive(node: sectionNode, frame: sectionFrame) + } else { + transition.updateFrame(node: sectionNode, frame: sectionFrame) + } + + transition.updateAlpha(node: sectionNode, alpha: self.state.isEditing ? 1.0 : 0.0) + if !sectionHeight.isZero && self.state.isEditing { + contentHeight += sectionHeight contentHeight += sectionSpacing } } + var removeEditingSections: [AnyHashable] = [] + for (sectionId, sectionNode) in self.editingSections { + if !validEditingSections.contains(sectionId) { + removeEditingSections.append(sectionId) + } + } + for sectionId in removeEditingSections { + if let sectionNode = self.editingSections.removeValue(forKey: sectionId) { + sectionNode.removeFromSupernode() + } + } let paneContainerSize = CGSize(width: layout.size.width, height: layout.size.height - navigationHeight) var restoreContentOffset: CGPoint? @@ -2506,6 +3060,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD let shareController = ShareController(context: strongSelf.context, subject: .messages(messages.sorted(by: { lhs, rhs in return lhs.index < rhs.index })), externalShare: true, immediateExternalShare: true) + strongSelf.view.endEditing(true) strongSelf.controller?.present(shareController, in: .window(.root)) } }) @@ -2518,6 +3073,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD guard let strongSelf = self, let messageIds = strongSelf.state.selectedMessageIds, !messageIds.isEmpty else { return } + strongSelf.view.endEditing(true) strongSelf.controller?.present(peerReportOptionsController(context: strongSelf.context, subject: .messages(Array(messageIds).sorted()), present: { c, a in self?.controller?.present(c, in: .window(.root), with: a) }, push: { c in @@ -2576,7 +3132,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD private func updateNavigation(transition: ContainedViewLayoutTransition, additive: Bool) { let offsetY = self.scrollNode.view.contentOffset.y - if self.state.isEditing || offsetY <= 50.0 { + if self.state.isEditing || offsetY <= 50.0 || self.paneContainerNode.alpha.isZero { if !self.scrollNode.view.bounces { self.scrollNode.view.bounces = true self.scrollNode.view.alwaysBounceVertical = true @@ -2682,7 +3238,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } else if offsetY >= 1.0 { shouldBeExpanded = false } - if let shouldBeExpanded = shouldBeExpanded, self.canUpdateAvatarExpansion, shouldBeExpanded != self.headerNode.isAvatarExpanded { + if let shouldBeExpanded = shouldBeExpanded, shouldBeExpanded != self.headerNode.isAvatarExpanded { let transition: ContainedViewLayoutTransition = .animated(duration: 0.35, curve: .spring) if self.hapticFeedback == nil { @@ -2935,6 +3491,7 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig private let headerNode: PeerInfoHeaderNode private var previousBackButtonArrow: ASDisplayNode? + private var previousBackButton: ASDisplayNode? private var currentBackButtonArrow: ASDisplayNode? private var previousBackButtonBadge: ASDisplayNode? private var currentBackButton: ASDisplayNode? @@ -2972,6 +3529,10 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig self.previousBackButtonArrow = previousBackButtonArrow self.addSubnode(previousBackButtonArrow) } + if let previousBackButton = bottomNavigationBar.makeTransitionBackButtonNode(accentColor: self.presentationData.theme.rootController.navigationBar.accentTextColor) { + self.previousBackButton = previousBackButton + self.addSubnode(previousBackButton) + } if self.screenNode.headerNode.isAvatarExpanded, let currentBackButtonArrow = topNavigationBar.makeTransitionBackArrowNode(accentColor: self.screenNode.headerNode.isAvatarExpanded ? .white : self.presentationData.theme.rootController.navigationBar.accentTextColor) { self.currentBackButtonArrow = currentBackButtonArrow self.addSubnode(currentBackButtonArrow) @@ -3014,6 +3575,12 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig previousBackButtonArrow.frame = previousBackButtonArrowFrame } + if let previousBackButton = self.previousBackButton { + let previousBackButtonFrame = bottomNavigationBar.backButtonNode.view.convert(bottomNavigationBar.backButtonNode.view.bounds, to: bottomNavigationBar.view) + previousBackButton.frame = previousBackButtonFrame + transition.updateAlpha(node: previousBackButton, alpha: fraction) + } + if let currentBackButtonArrow = self.currentBackButtonArrow { let currentBackButtonArrowFrame = topNavigationBar.backButtonArrow.view.convert(topNavigationBar.backButtonArrow.view.bounds, to: topNavigationBar.view) currentBackButtonArrow.frame = currentBackButtonArrowFrame @@ -3033,7 +3600,7 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig if let currentBackButton = self.currentBackButton { let currentBackButtonFrame = topNavigationBar.backButtonNode.view.convert(topNavigationBar.backButtonNode.view.bounds, to: topNavigationBar.view) - transition.updateFrame(node: currentBackButton, frame: currentBackButtonFrame.offsetBy(dx: fraction * 12.0, dy: 0.0)) + //transition.updateFrame(node: currentBackButton, frame: currentBackButtonFrame.offsetBy(dx: fraction * 12.0, dy: 0.0)) transition.updateAlpha(node: currentBackButton, alpha: (1.0 - fraction)) }