diff --git a/Telegram-iOS/en.lproj/Localizable.strings b/Telegram-iOS/en.lproj/Localizable.strings index 1aceb55efb..e6d484e908 100644 --- a/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram-iOS/en.lproj/Localizable.strings @@ -5240,3 +5240,5 @@ Any member of this group will be able to see messages in the channel."; "StickerPackActionInfo.RemovedTitle" = "Stickers Removed"; "StickerPackActionInfo.ArchivedTitle" = "Stickers Archived"; "StickerPackActionInfo.RemovedText" = "%@ is no longer in your stickers."; + +"Conversation.ContextMenuCancelEditing" = "Cancel Editing"; diff --git a/submodules/LegacyComponents/LegacyComponents/TGPhotoVideoEditor.h b/submodules/LegacyComponents/LegacyComponents/TGPhotoVideoEditor.h index ff8cfd650c..666a17ec58 100644 --- a/submodules/LegacyComponents/LegacyComponents/TGPhotoVideoEditor.h +++ b/submodules/LegacyComponents/LegacyComponents/TGPhotoVideoEditor.h @@ -2,6 +2,6 @@ @interface TGPhotoVideoEditor : NSObject -+ (void)presentWithContext:(id)context controller:(TGViewController *)controller caption:(NSString *)caption entities:(NSArray *)entities withItem:(id)item recipientName:(NSString *)recipientName completion:(void (^)(id, TGMediaEditingContext *))completion; ++ (void)presentWithContext:(id)context controller:(TGViewController *)controller caption:(NSString *)caption entities:(NSArray *)entities withItem:(id)item recipientName:(NSString *)recipientName completion:(void (^)(id, TGMediaEditingContext *))completion dismissed:(void (^)())dismissed; @end diff --git a/submodules/LegacyComponents/LegacyComponents/TGPhotoVideoEditor.m b/submodules/LegacyComponents/LegacyComponents/TGPhotoVideoEditor.m index ee6a2bc03d..666333a543 100644 --- a/submodules/LegacyComponents/LegacyComponents/TGPhotoVideoEditor.m +++ b/submodules/LegacyComponents/LegacyComponents/TGPhotoVideoEditor.m @@ -10,7 +10,7 @@ @implementation TGPhotoVideoEditor -+ (void)presentWithContext:(id)context controller:(TGViewController *)controller caption:(NSString *)caption entities:(NSArray *)entities withItem:(id)item recipientName:(NSString *)recipientName completion:(void (^)(id, TGMediaEditingContext *))completion ++ (void)presentWithContext:(id)context controller:(TGViewController *)controller caption:(NSString *)caption entities:(NSArray *)entities withItem:(id)item recipientName:(NSString *)recipientName completion:(void (^)(id, TGMediaEditingContext *))completion dismissed:(void (^)())dismissed { id windowManager = [context makeOverlayWindowManager]; id windowContext = [windowManager context]; @@ -78,13 +78,15 @@ if (completion != nil) completion(item.asset, editingContext); - [UIView animateWithDuration:0.3f delay:0.0f options:(7 << 16) animations:^ + [strongController dismissWhenReadyAnimated:true]; + + /*[UIView animateWithDuration:0.3f delay:0.0f options:(7 << 16) animations:^ { strongController.view.frame = CGRectOffset(strongController.view.frame, 0, strongController.view.frame.size.height); } completion:^(__unused BOOL finished) { [strongController dismiss]; - }]; + }];*/ }; galleryController.beginTransitionIn = ^UIView *(__unused TGMediaPickerGalleryItem *item, __unused TGModernGalleryItemView *itemView) @@ -107,6 +109,9 @@ if ([window isKindOfClass:[TGOverlayControllerWindow class]]) [window dismiss]; } + if (dismissed) { + dismissed(); + } }; TGOverlayControllerWindow *controllerWindow = [[TGOverlayControllerWindow alloc] initWithManager:windowManager parentController:controller contentController:galleryController]; diff --git a/submodules/LegacyMediaPickerUI/BUCK b/submodules/LegacyMediaPickerUI/BUCK index a740c095be..85dce0dcfa 100644 --- a/submodules/LegacyMediaPickerUI/BUCK +++ b/submodules/LegacyMediaPickerUI/BUCK @@ -26,6 +26,7 @@ static_library( "//submodules/MimeTypes:MimeTypes", "//submodules/LocalMediaResources:LocalMediaResources", "//submodules/SearchPeerMembers:SearchPeerMembers", + "//submodules/SaveToCameraRoll:SaveToCameraRoll", ], frameworks = [ "$SDKROOT/System/Library/Frameworks/Foundation.framework", diff --git a/submodules/LegacyMediaPickerUI/Sources/LegacyAttachmentMenu.swift b/submodules/LegacyMediaPickerUI/Sources/LegacyAttachmentMenu.swift index ff3580f511..3b87eaecea 100644 --- a/submodules/LegacyMediaPickerUI/Sources/LegacyAttachmentMenu.swift +++ b/submodules/LegacyMediaPickerUI/Sources/LegacyAttachmentMenu.swift @@ -10,6 +10,7 @@ import TelegramPresentationData import DeviceAccess import AccountContext import LegacyUI +import SaveToCameraRoll public func defaultVideoPresetForContext(_ context: AccountContext) -> TGMediaVideoConversionPreset { var networkType: NetworkType = .wifi @@ -52,17 +53,13 @@ public func defaultVideoPresetForContext(_ context: AccountContext) -> TGMediaVi } } -public struct LegacyAttachmentMenuMediaEditing: OptionSet { - public var rawValue: Int32 - - public init(rawValue: Int32) { - self.rawValue = rawValue - } - - public static let imageOrVideo = LegacyAttachmentMenuMediaEditing(rawValue: 1 << 0) +public enum LegacyAttachmentMenuMediaEditing { + case none + case imageOrVideo(AnyMediaReference?) + case file } -public func legacyAttachmentMenu(context: AccountContext, peer: Peer, editMediaOptions: LegacyAttachmentMenuMediaEditing?, saveEditedPhotos: Bool, allowGrouping: Bool, hasSchedule: Bool, canSendPolls: Bool, presentationData: PresentationData, parentController: LegacyController, recentlyUsedInlineBots: [Peer], initialCaption: String, openGallery: @escaping () -> Void, openCamera: @escaping (TGAttachmentCameraView?, TGMenuSheetController?) -> Void, openFileGallery: @escaping () -> Void, openWebSearch: @escaping () -> Void, openMap: @escaping () -> Void, openContacts: @escaping () -> Void, openPoll: @escaping () -> Void, presentSelectionLimitExceeded: @escaping () -> Void, presentCantSendMultipleFiles: @escaping () -> Void, presentSchedulePicker: @escaping (@escaping (Int32) -> Void) -> Void, sendMessagesWithSignals: @escaping ([Any]?, Bool, Int32) -> Void, selectRecentlyUsedInlineBot: @escaping (Peer) -> Void) -> TGMenuSheetController { +public func legacyAttachmentMenu(context: AccountContext, peer: Peer, editMediaOptions: LegacyAttachmentMenuMediaEditing?, saveEditedPhotos: Bool, allowGrouping: Bool, hasSchedule: Bool, canSendPolls: Bool, presentationData: PresentationData, parentController: LegacyController, recentlyUsedInlineBots: [Peer], initialCaption: String, openGallery: @escaping () -> Void, openCamera: @escaping (TGAttachmentCameraView?, TGMenuSheetController?) -> Void, openFileGallery: @escaping () -> Void, openWebSearch: @escaping () -> Void, openMap: @escaping () -> Void, openContacts: @escaping () -> Void, openPoll: @escaping () -> Void, presentSelectionLimitExceeded: @escaping () -> Void, presentCantSendMultipleFiles: @escaping () -> Void, presentSchedulePicker: @escaping (@escaping (Int32) -> Void) -> Void, sendMessagesWithSignals: @escaping ([Any]?, Bool, Int32) -> Void, selectRecentlyUsedInlineBot: @escaping (Peer) -> Void, present: @escaping (ViewController, Any?) -> Void) -> TGMenuSheetController { let defaultVideoPreset = defaultVideoPresetForContext(context) UserDefaults.standard.set(defaultVideoPreset.rawValue as NSNumber, forKey: "TG_preferredVideoPreset_v0") @@ -81,11 +78,19 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, editMediaO var editing = false var canSendImageOrVideo = false - var canEditCurrent = false - if let editMediaOptions = editMediaOptions, editMediaOptions.contains(.imageOrVideo) { + var canEditFile = false + var editCurrentMedia: AnyMediaReference? + if let editMediaOptions = editMediaOptions { + switch editMediaOptions { + case .none: + break + case let .imageOrVideo(anyReference): + editCurrentMedia = anyReference + case .file: + canEditFile = true + } canSendImageOrVideo = true editing = true - canEditCurrent = true } else { canSendImageOrVideo = true } @@ -165,7 +170,7 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, editMediaO } if !editing { - let fileItem = TGMenuSheetButtonItemView(title: presentationData.strings.AttachmentMenu_File, type: TGMenuSheetButtonTypeDefault, fontSize: fontSize, action: {[weak controller] in + let fileItem = TGMenuSheetButtonItemView(title: presentationData.strings.AttachmentMenu_File, type: TGMenuSheetButtonTypeDefault, fontSize: fontSize, action: { [weak controller] in controller?.dismiss(animated: true) openFileGallery() })! @@ -173,14 +178,113 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, editMediaO underlyingViews.append(fileItem) } - if canEditCurrent { - let fileItem = TGMenuSheetButtonItemView(title: presentationData.strings.AttachmentMenu_File, type: TGMenuSheetButtonTypeDefault, fontSize: fontSize, action: {[weak controller] in + if canEditFile { + let fileItem = TGMenuSheetButtonItemView(title: presentationData.strings.AttachmentMenu_File, type: TGMenuSheetButtonTypeDefault, fontSize: fontSize, action: { [weak controller] in controller?.dismiss(animated: true) openFileGallery() })! itemViews.append(fileItem) } + if let editCurrentMedia = editCurrentMedia { + let title: String + if editCurrentMedia.media is TelegramMediaImage { + title = presentationData.strings.Conversation_EditingMessageMediaEditCurrentPhoto + } else { + title = presentationData.strings.Conversation_EditingMessageMediaEditCurrentVideo + } + let editCurrentItem = TGMenuSheetButtonItemView(title: title, type: TGMenuSheetButtonTypeDefault, fontSize: fontSize, action: { [weak controller] in + controller?.dismiss(animated: true) + + let _ = (fetchMediaData(context: context, postbox: context.account.postbox, mediaReference: editCurrentMedia) + |> deliverOnMainQueue).start(next: { (value, isImage) in + guard case let .data(data) = value, data.complete else { + return + } + + let item: TGMediaEditableItem & TGMediaSelectableItem + if let image = UIImage(contentsOfFile: data.path) { + item = TGCameraCapturedPhoto(existing: image) + } else { + item = TGCameraCapturedVideo(url: URL(fileURLWithPath: data.path)) + } + + let legacyController = LegacyController(presentation: .custom, theme: presentationData.theme, initialLayout: nil) + legacyController.statusBar.statusBarStyle = .Ignore + legacyController.controllerLoaded = { [weak legacyController] in + legacyController?.view.disablesInteractiveTransitionGestureRecognizer = true + } + + let emptyController = LegacyEmptyController(context: legacyController.context)! + emptyController.navigationBarShouldBeHidden = true + let navigationController = makeLegacyNavigationController(rootController: emptyController) + navigationController.setNavigationBarHidden(true, animated: false) + legacyController.bind(controller: navigationController) + + var hasTimer = false + var hasSilentPosting = false + if peer.id != context.account.peerId { + if peer is TelegramUser { + hasTimer = true + } + hasSilentPosting = true + } + let recipientName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + + legacyController.enableSizeClassSignal = true + + let presentationDisposable = context.sharedContext.presentationData.start(next: { [weak legacyController] presentationData in + if let legacyController = legacyController, let controller = legacyController.legacyController as? TGMenuSheetController { + controller.pallete = legacyMenuPaletteFromTheme(presentationData.theme) + } + }) + legacyController.disposables.add(presentationDisposable) + + present(legacyController, nil) + + TGPhotoVideoEditor.present(with: legacyController.context, controller: emptyController, caption: "", entities: [], withItem: item, recipientName: recipientName, completion: { result, editingContext in + let intent: TGMediaAssetsControllerIntent = TGMediaAssetsControllerSendMediaIntent + let signals = TGCameraController.resultSignals(for: nil, editingContext: editingContext, currentItem: result as! TGMediaSelectableItem, storeAssets: false, saveEditedPhotos: false, descriptionGenerator: legacyAssetPickerItemGenerator()) + sendMessagesWithSignals(signals, false, 0) + /* + [TGCameraController resultSignalsForSelectionContext:nil editingContext:editingContext currentItem:result storeAssets:false saveEditedPhotos:false descriptionGenerator:^id(id result, NSString *caption, NSArray *entities, NSString *hash) + { + __strong TGModernConversationController *strongSelf = weakSelf; + if (strongSelf == nil) + return nil; + + NSDictionary *desc = [strongSelf _descriptionForItem:result caption:caption entities:entities hash:hash allowRemoteCache:allowRemoteCache]; + return [strongSelf _descriptionForReplacingMedia:desc message:message]; + }]] + */ + //let signals = TGMediaAssetsController.resultSignals(for: nil, editingContext: editingContext, intent: intent, currentItem: result, storeAssets: true, useMediaCache: false, descriptionGenerator: legacyAssetPickerItemGenerator(), saveEditedPhotos: saveEditedPhotos) + //sendMessagesWithSignals(signals, silentPosting, scheduleTime) + }, dismissed: { [weak legacyController] in + legacyController?.dismiss() + }) + }) + /* + + + bool allowRemoteCache = [strongSelf->_companion controllerShouldCacheServerAssets]; + [TGPhotoVideoEditor presentWithContext:[TGLegacyComponentsContext shared] controller:strongSelf caption:text entities:entities withItem:item recipientName:[strongSelf->_companion title] completion:^(id result, TGMediaEditingContext *editingContext) + { + [strongSelf _asyncProcessMediaAssetSignals:[TGCameraController resultSignalsForSelectionContext:nil editingContext:editingContext currentItem:result storeAssets:false saveEditedPhotos:false descriptionGenerator:^id(id result, NSString *caption, NSArray *entities, NSString *hash) + { + __strong TGModernConversationController *strongSelf = weakSelf; + if (strongSelf == nil) + return nil; + + NSDictionary *desc = [strongSelf _descriptionForItem:result caption:caption entities:entities hash:hash allowRemoteCache:allowRemoteCache]; + return [strongSelf _descriptionForReplacingMedia:desc message:message]; + }]]; + [strongSelf endMessageEditing:true]; + }]; + */ + })! + itemViews.append(editCurrentItem) + } + if editMediaOptions == nil { let locationItem = TGMenuSheetButtonItemView(title: presentationData.strings.Conversation_Location, type: TGMenuSheetButtonTypeDefault, fontSize: fontSize, action: { [weak controller] in controller?.dismiss(animated: true) diff --git a/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift b/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift index e9d234debf..24be4f12b1 100644 --- a/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift +++ b/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift @@ -219,7 +219,7 @@ public func legacyAssetPickerItemGenerator() -> ((Any?, String?, [Any]?, String? asFile = true } - let url: String? = (dict["url"] as? String) ?? (dict["url"] as? URL)?.absoluteString + let url: String? = (dict["url"] as? String) ?? (dict["url"] as? URL)?.path if let url = url, let previewImage = dict["previewImage"] as? UIImage { let dimensions = previewImage.pixelSize() diff --git a/submodules/SaveToCameraRoll/Sources/SaveToCameraRoll.swift b/submodules/SaveToCameraRoll/Sources/SaveToCameraRoll.swift index a5c381ade1..6580e6ee46 100644 --- a/submodules/SaveToCameraRoll/Sources/SaveToCameraRoll.swift +++ b/submodules/SaveToCameraRoll/Sources/SaveToCameraRoll.swift @@ -10,12 +10,12 @@ import MobileCoreServices import DeviceAccess import AccountContext -private enum SaveToCameraRollState { +public enum FetchMediaDataState { case progress(Float) case data(MediaResourceData) } -private func fetchMediaData(context: AccountContext, postbox: Postbox, mediaReference: AnyMediaReference) -> Signal<(SaveToCameraRollState, Bool), NoError> { +public func fetchMediaData(context: AccountContext, postbox: Postbox, mediaReference: AnyMediaReference) -> Signal<(FetchMediaDataState, Bool), NoError> { var resource: MediaResource? var isImage = true var fileExtension: String? @@ -46,7 +46,7 @@ private func fetchMediaData(context: AccountContext, postbox: Postbox, mediaRefe } if let resource = resource { - let fetchedData: Signal = Signal { subscriber in + let fetchedData: Signal = Signal { subscriber in let fetched = fetchedMediaResource(mediaBox: postbox.mediaBox, reference: mediaReference.resourceReference(resource)).start() let status = postbox.mediaBox.resourceStatus(resource).start(next: { status in switch status { diff --git a/submodules/TelegramCore/Sources/Account.swift b/submodules/TelegramCore/Sources/Account.swift index 55c03cea20..c48c044ca6 100644 --- a/submodules/TelegramCore/Sources/Account.swift +++ b/submodules/TelegramCore/Sources/Account.swift @@ -834,6 +834,7 @@ public class Account { public private(set) var callSessionManager: CallSessionManager! public private(set) var viewTracker: AccountViewTracker! public private(set) var pendingMessageManager: PendingMessageManager! + public private(set) var pendingUpdateMessageManager: PendingUpdateMessageManager! public private(set) var messageMediaPreuploadManager: MessageMediaPreuploadManager! private(set) var mediaReferenceRevalidationContext: MediaReferenceRevalidationContext! private var peerInputActivityManager: PeerInputActivityManager! @@ -918,6 +919,7 @@ public class Account { self.messageMediaPreuploadManager = MessageMediaPreuploadManager() self.mediaReferenceRevalidationContext = MediaReferenceRevalidationContext() self.pendingMessageManager = PendingMessageManager(network: network, postbox: postbox, accountPeerId: peerId, auxiliaryMethods: auxiliaryMethods, stateManager: self.stateManager, localInputActivityManager: self.localInputActivityManager, messageMediaPreuploadManager: self.messageMediaPreuploadManager, revalidationContext: self.mediaReferenceRevalidationContext) + self.pendingUpdateMessageManager = PendingUpdateMessageManager(postbox: postbox, network: network, stateManager: self.stateManager, messageMediaPreuploadManager: self.messageMediaPreuploadManager, mediaReferenceRevalidationContext: self.mediaReferenceRevalidationContext) self.network.loggedOut = { [weak self] in Logger.shared.log("Account", "network logged out") @@ -1246,4 +1248,5 @@ public func setupAccount(_ account: Account, fetchCachedResourceRepresentation: account.transformOutgoingMessageMedia = transformOutgoingMessageMedia account.pendingMessageManager.transformOutgoingMessageMedia = transformOutgoingMessageMedia + account.pendingUpdateMessageManager.transformOutgoingMessageMedia = transformOutgoingMessageMedia } diff --git a/submodules/TelegramCore/Sources/AccountStateManager.swift b/submodules/TelegramCore/Sources/AccountStateManager.swift index f67969c91f..3a7a952951 100644 --- a/submodules/TelegramCore/Sources/AccountStateManager.swift +++ b/submodules/TelegramCore/Sources/AccountStateManager.swift @@ -57,7 +57,8 @@ public final class AccountStateManager { private let shouldKeepOnlinePresence: Signal private let peerInputActivityManager: PeerInputActivityManager - private let auxiliaryMethods: AccountAuxiliaryMethods + let auxiliaryMethods: AccountAuxiliaryMethods + var transformOutgoingMessageMedia: TransformOutgoingMessageMedia? private var updateService: UpdateMessageService? private let updateServiceDisposable = MetaDisposable() diff --git a/submodules/TelegramCore/Sources/ApplyUpdateMessage.swift b/submodules/TelegramCore/Sources/ApplyUpdateMessage.swift index e399aa60cd..10e51ef71a 100644 --- a/submodules/TelegramCore/Sources/ApplyUpdateMessage.swift +++ b/submodules/TelegramCore/Sources/ApplyUpdateMessage.swift @@ -5,7 +5,7 @@ import SwiftSignalKit import SyncCore -func applyMediaResourceChanges(from: Media, to: Media, postbox: Postbox) { +func applyMediaResourceChanges(from: Media, to: Media, postbox: Postbox, force: Bool) { if let fromImage = from as? TelegramMediaImage, let toImage = to as? TelegramMediaImage { let fromSmallestRepresentation = smallestImageRepresentation(fromImage.representations) if let fromSmallestRepresentation = fromSmallestRepresentation, let toSmallestRepresentation = smallestImageRepresentation(toImage.representations) { @@ -23,7 +23,7 @@ func applyMediaResourceChanges(from: Media, to: Media, postbox: Postbox) { if let fromPreview = smallestImageRepresentation(fromFile.previewRepresentations), let toPreview = smallestImageRepresentation(toFile.previewRepresentations) { postbox.mediaBox.moveResourceData(from: fromPreview.resource.id, to: toPreview.resource.id) } - if (fromFile.size == toFile.size || fromFile.resource.size == toFile.resource.size) && fromFile.mimeType == toFile.mimeType { + if (force || fromFile.size == toFile.size || fromFile.resource.size == toFile.resource.size) && fromFile.mimeType == toFile.mimeType { postbox.mediaBox.moveResourceData(from: fromFile.resource.id, to: toFile.resource.id) } } @@ -152,7 +152,7 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes } if let fromMedia = currentMessage.media.first, let toMedia = media.first { - applyMediaResourceChanges(from: fromMedia, to: toMedia, postbox: postbox) + applyMediaResourceChanges(from: fromMedia, to: toMedia, postbox: postbox, force: false) } if forwardInfo == nil { @@ -311,7 +311,7 @@ func applyUpdateGroupMessages(postbox: Postbox, stateManager: AccountStateManage } if let fromMedia = currentMessage.media.first, let toMedia = media.first { - applyMediaResourceChanges(from: fromMedia, to: toMedia, postbox: postbox) + applyMediaResourceChanges(from: fromMedia, to: toMedia, postbox: postbox, force: false) } if storeForwardInfo == nil { diff --git a/submodules/TelegramUI/TelegramUI/ChatUpdatingMessageMedia.swift b/submodules/TelegramCore/Sources/ChatUpdatingMessageMedia.swift similarity index 82% rename from submodules/TelegramUI/TelegramUI/ChatUpdatingMessageMedia.swift rename to submodules/TelegramCore/Sources/ChatUpdatingMessageMedia.swift index 20bcad8fea..f3fa1baf1a 100644 --- a/submodules/TelegramUI/TelegramUI/ChatUpdatingMessageMedia.swift +++ b/submodules/TelegramCore/Sources/ChatUpdatingMessageMedia.swift @@ -36,4 +36,8 @@ public final class ChatUpdatingMessageMedia: Equatable { } return true } + + func withProgress(_ progress: Float) -> ChatUpdatingMessageMedia { + return ChatUpdatingMessageMedia(text: self.text, entities: self.entities, disableUrlPreview: self.disableUrlPreview, media: self.media, progress: progress) + } } diff --git a/submodules/TelegramCore/Sources/ManagedSecretChatOutgoingOperations.swift b/submodules/TelegramCore/Sources/ManagedSecretChatOutgoingOperations.swift index 6ee05fe6e0..7754b00b97 100644 --- a/submodules/TelegramCore/Sources/ManagedSecretChatOutgoingOperations.swift +++ b/submodules/TelegramCore/Sources/ManagedSecretChatOutgoingOperations.swift @@ -1415,7 +1415,7 @@ private func sendMessage(auxiliaryMethods: AccountAuxiliaryMethods, postbox: Pos } if let toMedia = toMedia { - applyMediaResourceChanges(from: fromMedia, to: toMedia, postbox: postbox) + applyMediaResourceChanges(from: fromMedia, to: toMedia, postbox: postbox, force: false) } } diff --git a/submodules/TelegramCore/Sources/PendingUpdateMessageManager.swift b/submodules/TelegramCore/Sources/PendingUpdateMessageManager.swift new file mode 100644 index 0000000000..f4e6adbe11 --- /dev/null +++ b/submodules/TelegramCore/Sources/PendingUpdateMessageManager.swift @@ -0,0 +1,178 @@ +import Foundation +import SwiftSignalKit +import SyncCore +import Postbox + +private final class PendingUpdateMessageContext { + var value: ChatUpdatingMessageMedia + let disposable: Disposable + + init(value: ChatUpdatingMessageMedia, disposable: Disposable) { + self.value = value + self.disposable = disposable + } +} + +private final class PendingUpdateMessageManagerImpl { + let queue: Queue + let postbox: Postbox + let network: Network + let stateManager: AccountStateManager + let messageMediaPreuploadManager: MessageMediaPreuploadManager + let mediaReferenceRevalidationContext: MediaReferenceRevalidationContext + + var transformOutgoingMessageMedia: TransformOutgoingMessageMedia? + + private var updatingMessageMediaValue: [MessageId: ChatUpdatingMessageMedia] = [:] { + didSet { + if self.updatingMessageMediaValue != oldValue { + self.updatingMessageMediaPromise.set(.single(self.updatingMessageMediaValue)) + } + } + } + private let updatingMessageMediaPromise = Promise<[MessageId: ChatUpdatingMessageMedia]>() + var updatingMessageMedia: Signal<[MessageId: ChatUpdatingMessageMedia], NoError> { + return self.updatingMessageMediaPromise.get() + } + + private var contexts: [MessageId: PendingUpdateMessageContext] = [:] + + private let errorsPipe = ValuePipe<(MessageId, RequestEditMessageError)>() + var errors: Signal<(MessageId, RequestEditMessageError), NoError> { + return self.errorsPipe.signal() + } + + init(queue: Queue, postbox: Postbox, network: Network, stateManager: AccountStateManager, messageMediaPreuploadManager: MessageMediaPreuploadManager, mediaReferenceRevalidationContext: MediaReferenceRevalidationContext) { + self.queue = queue + self.postbox = postbox + self.network = network + self.stateManager = stateManager + self.messageMediaPreuploadManager = messageMediaPreuploadManager + self.mediaReferenceRevalidationContext = mediaReferenceRevalidationContext + + self.updatingMessageMediaPromise.set(.single(self.updatingMessageMediaValue)) + } + + deinit { + for (_, context) in self.contexts { + context.disposable.dispose() + } + } + + private func updateValues() { + self.updatingMessageMediaValue = self.contexts.mapValues { context in + return context.value + } + } + + func add(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, disableUrlPreview: Bool) { + if let context = self.contexts[messageId] { + self.contexts.removeValue(forKey: messageId) + context.disposable.dispose() + } + + let disposable = MetaDisposable() + let context = PendingUpdateMessageContext(value: ChatUpdatingMessageMedia(text: text, entities: entities, disableUrlPreview: disableUrlPreview, media: media, progress: 0.0), disposable: disposable) + self.contexts[messageId] = context + + let queue = self.queue + disposable.set((requestEditMessage(postbox: self.postbox, network: self.network, stateManager: self.stateManager, transformOutgoingMessageMedia: self.transformOutgoingMessageMedia, messageMediaPreuploadManager: self.messageMediaPreuploadManager, mediaReferenceRevalidationContext: self.mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, disableUrlPreview: disableUrlPreview, scheduleTime: nil) + |> deliverOn(self.queue)).start(next: { [weak self, weak context] value in + queue.async { + guard let strongSelf = self, let initialContext = context else { + return + } + if let context = strongSelf.contexts[messageId], context === initialContext { + switch value { + case .done: + strongSelf.contexts.removeValue(forKey: messageId) + context.disposable.dispose() + strongSelf.updateValues() + case let .progress(progress): + context.value = context.value.withProgress(progress) + strongSelf.updateValues() + } + } + } + }, error: { [weak self, weak context] error in + queue.async { + guard let strongSelf = self, let initialContext = context else { + return + } + if let context = strongSelf.contexts[messageId], context === initialContext { + strongSelf.contexts.removeValue(forKey: messageId) + context.disposable.dispose() + strongSelf.updateValues() + } + + strongSelf.errorsPipe.putNext((messageId, error)) + } + })) + } + + func cancel(messageId: MessageId) { + if let context = self.contexts[messageId] { + self.contexts.removeValue(forKey: messageId) + context.disposable.dispose() + + self.updateValues() + } + } +} + +public final class PendingUpdateMessageManager { + private let queue = Queue() + private let impl: QueueLocalObject + + var transformOutgoingMessageMedia: TransformOutgoingMessageMedia? { + didSet { + let transformOutgoingMessageMedia = self.transformOutgoingMessageMedia + self.impl.with { impl in + impl.transformOutgoingMessageMedia = transformOutgoingMessageMedia + } + } + } + + public var updatingMessageMedia: Signal<[MessageId: ChatUpdatingMessageMedia], NoError> { + return Signal { subscriber in + let disposable = MetaDisposable() + self.impl.with { impl in + disposable.set(impl.updatingMessageMedia.start(next: { value in + subscriber.putNext(value) + })) + } + return disposable + } + } + + public var errors: Signal<(MessageId, RequestEditMessageError), NoError> { + return Signal { subscriber in + let disposable = MetaDisposable() + self.impl.with { impl in + disposable.set(impl.errors.start(next: { value in + subscriber.putNext(value) + })) + } + return disposable + } + } + + init(postbox: Postbox, network: Network, stateManager: AccountStateManager, messageMediaPreuploadManager: MessageMediaPreuploadManager, mediaReferenceRevalidationContext: MediaReferenceRevalidationContext) { + let queue = self.queue + self.impl = QueueLocalObject(queue: queue, generate: { + return PendingUpdateMessageManagerImpl(queue: queue, postbox: postbox, network: network, stateManager: stateManager, messageMediaPreuploadManager: messageMediaPreuploadManager, mediaReferenceRevalidationContext: mediaReferenceRevalidationContext) + }) + } + + public func add(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute? = nil, disableUrlPreview: Bool = false) { + self.impl.with { impl in + impl.add(messageId: messageId, text: text, media: media, entities: entities, disableUrlPreview: disableUrlPreview) + } + } + + public func cancel(messageId: MessageId) { + self.impl.with { impl in + impl.cancel(messageId: messageId) + } + } +} diff --git a/submodules/TelegramCore/Sources/RequestEditMessage.swift b/submodules/TelegramCore/Sources/RequestEditMessage.swift index 94d775b546..0050505c1e 100644 --- a/submodules/TelegramCore/Sources/RequestEditMessage.swift +++ b/submodules/TelegramCore/Sources/RequestEditMessage.swift @@ -27,10 +27,14 @@ public enum RequestEditMessageError { } public func requestEditMessage(account: Account, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute? = nil, disableUrlPreview: Bool = false, scheduleTime: Int32? = nil) -> Signal { - return requestEditMessageInternal(account: account, messageId: messageId, text: text, media: media, entities: entities, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime, forceReupload: false) + return requestEditMessage(postbox: account.postbox, network: account.network, stateManager: account.stateManager, transformOutgoingMessageMedia: account.transformOutgoingMessageMedia, messageMediaPreuploadManager: account.messageMediaPreuploadManager, mediaReferenceRevalidationContext: account.mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime) +} + +func requestEditMessage(postbox: Postbox, network: Network, stateManager: AccountStateManager, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, messageMediaPreuploadManager: MessageMediaPreuploadManager, mediaReferenceRevalidationContext: MediaReferenceRevalidationContext, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, disableUrlPreview: Bool, scheduleTime: Int32?) -> Signal { + return requestEditMessageInternal(postbox: postbox, network: network, stateManager: stateManager, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, mediaReferenceRevalidationContext: mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime, forceReupload: false) |> `catch` { error -> Signal in if case .invalidReference = error { - return requestEditMessageInternal(account: account, messageId: messageId, text: text, media: media, entities: entities, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime, forceReupload: true) + return requestEditMessageInternal(postbox: postbox, network: network, stateManager: stateManager, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, mediaReferenceRevalidationContext: mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime, forceReupload: true) } else { return .fail(error) } @@ -45,34 +49,34 @@ public func requestEditMessage(account: Account, messageId: MessageId, text: Str } } -private func requestEditMessageInternal(account: Account, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, disableUrlPreview: Bool, scheduleTime: Int32?, forceReupload: Bool) -> Signal { +private func requestEditMessageInternal(postbox: Postbox, network: Network, stateManager: AccountStateManager, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, messageMediaPreuploadManager: MessageMediaPreuploadManager, mediaReferenceRevalidationContext: MediaReferenceRevalidationContext, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, disableUrlPreview: Bool, scheduleTime: Int32?, forceReupload: Bool) -> Signal { let uploadedMedia: Signal switch media { - case .keep: - uploadedMedia = .single(.progress(0.0)) - |> then(.single(nil)) - case let .update(media): - let generateUploadSignal: (Bool) -> Signal? = { forceReupload in - let augmentedMedia = augmentMediaWithReference(media) - return mediaContentToUpload(network: account.network, postbox: account.postbox, auxiliaryMethods: account.auxiliaryMethods, transformOutgoingMessageMedia: account.transformOutgoingMessageMedia, messageMediaPreuploadManager: account.messageMediaPreuploadManager, revalidationContext: account.mediaReferenceRevalidationContext, forceReupload: forceReupload, isGrouped: false, peerId: messageId.peerId, media: augmentedMedia, text: "", autoremoveAttribute: nil, messageId: nil, attributes: []) - } - if let uploadSignal = generateUploadSignal(forceReupload) { - uploadedMedia = .single(.progress(0.027)) - |> then(uploadSignal) - |> map { result -> PendingMessageUploadedContentResult? in - switch result { - case let .progress(value): - return .progress(max(value, 0.027)) - case let .content(content): - return .content(content) - } + case .keep: + uploadedMedia = .single(.progress(0.0)) + |> then(.single(nil)) + case let .update(media): + let generateUploadSignal: (Bool) -> Signal? = { forceReupload in + let augmentedMedia = augmentMediaWithReference(media) + return mediaContentToUpload(network: network, postbox: postbox, auxiliaryMethods: stateManager.auxiliaryMethods, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, revalidationContext: mediaReferenceRevalidationContext, forceReupload: forceReupload, isGrouped: false, peerId: messageId.peerId, media: augmentedMedia, text: "", autoremoveAttribute: nil, messageId: nil, attributes: []) + } + if let uploadSignal = generateUploadSignal(forceReupload) { + uploadedMedia = .single(.progress(0.027)) + |> then(uploadSignal) + |> map { result -> PendingMessageUploadedContentResult? in + switch result { + case let .progress(value): + return .progress(max(value, 0.027)) + case let .content(content): + return .content(content) } - |> `catch` { _ -> Signal in - return .single(nil) - } - } else { - uploadedMedia = .single(nil) } + |> `catch` { _ -> Signal in + return .single(nil) + } + } else { + uploadedMedia = .single(nil) + } } return uploadedMedia |> mapError { _ -> RequestEditMessageInternalError in return .error(.generic) } @@ -86,7 +90,7 @@ private func requestEditMessageInternal(account: Account, messageId: MessageId, pendingMediaContent = content.content } } - return account.postbox.transaction { transaction -> (Peer?, Message?, SimpleDictionary) in + return postbox.transaction { transaction -> (Peer?, Message?, SimpleDictionary) in guard let message = transaction.getMessage(messageId) else { return (nil, nil, SimpleDictionary()) } @@ -155,7 +159,7 @@ private func requestEditMessageInternal(account: Account, messageId: MessageId, flags |= Int32(1 << 15) } - return account.network.request(Api.functions.messages.editMessage(flags: flags, peer: inputPeer, id: messageId.id, message: text, media: inputMedia, replyMarkup: nil, entities: apiEntities, scheduleDate: effectiveScheduleTime)) + return network.request(Api.functions.messages.editMessage(flags: flags, peer: inputPeer, id: messageId.id, message: text, media: inputMedia, replyMarkup: nil, entities: apiEntities, scheduleDate: effectiveScheduleTime)) |> map { result -> Api.Updates? in return result } @@ -176,16 +180,58 @@ private func requestEditMessageInternal(account: Account, messageId: MessageId, } |> mapToSignal { result -> Signal in if let result = result { - return account.postbox.transaction { transaction -> RequestEditMessageResult in + return postbox.transaction { transaction -> RequestEditMessageResult in var toMedia: Media? if let message = result.messages.first.flatMap({ StoreMessage(apiMessage: $0) }) { toMedia = message.media.first } if case let .update(fromMedia) = media, let toMedia = toMedia { - applyMediaResourceChanges(from: fromMedia.media, to: toMedia, postbox: account.postbox) + applyMediaResourceChanges(from: fromMedia.media, to: toMedia, postbox: postbox, force: true) } - account.stateManager.addUpdates(result) + + switch result { + case let .updates(updates, users, chats, _, _): + for update in updates { + switch update { + case .updateEditMessage(let message, _, _), .updateNewMessage(let message, _, _), .updateEditChannelMessage(let message, _, _), .updateNewChannelMessage(let message, _, _): + var peers: [Peer] = [] + for chat in chats { + if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) { + peers.append(groupOrChannel) + } + } + for user in users { + let telegramUser = TelegramUser(user: user) + peers.append(telegramUser) + } + + updatePeers(transaction: transaction, peers: peers, update: { _, updated in updated }) + + if let message = StoreMessage(apiMessage: message), case let .Id(id) = message.id { + transaction.updateMessage(id, update: { previousMessage in + var updatedFlags = message.flags + var updatedLocalTags = message.localTags + if previousMessage.localTags.contains(.OutgoingLiveLocation) { + updatedLocalTags.insert(.OutgoingLiveLocation) + } + if previousMessage.flags.contains(.Incoming) { + updatedFlags.insert(.Incoming) + } else { + updatedFlags.remove(.Incoming) + } + return .update(message.withUpdatedLocalTags(updatedLocalTags).withUpdatedFlags(updatedFlags)) + }) + } + default: + break + } + } + default: + break + } + + stateManager.addUpdates(result) return .done(true) } diff --git a/submodules/TelegramPresentationData/Sources/PresentationStrings.swift b/submodules/TelegramPresentationData/Sources/PresentationStrings.swift index 1af3815ddd..b01e8d904d 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationStrings.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationStrings.swift @@ -3617,1146 +3617,1146 @@ public final class PresentationStrings: Equatable { } public var Notification_Exceptions_AlwaysOn: String { return self._s[3178]! } public var UserInfo_NotificationsDisable: String { return self._s[3179]! } - public var Paint_Outlined: String { return self._s[3180]! } - public var Activity_PlayingGame: String { return self._s[3181]! } - public var SearchImages_NoImagesFound: String { return self._s[3182]! } - public var SocksProxySetup_ProxyType: String { return self._s[3183]! } - public var AppleWatch_ReplyPresetsHelp: String { return self._s[3185]! } - public var Conversation_ContextMenuCancelSending: String { return self._s[3186]! } - public var Settings_AppLanguage: String { return self._s[3187]! } - public var TwoStepAuth_ResetAccountHelp: String { return self._s[3188]! } - public var Common_ChoosePhoto: String { return self._s[3189]! } - public var AuthSessions_AddDevice_InvalidQRCode: String { return self._s[3190]! } - public var CallFeedback_ReasonEcho: String { return self._s[3191]! } + public var Conversation_ContextMenuCancelEditing: String { return self._s[3180]! } + public var Paint_Outlined: String { return self._s[3181]! } + public var Activity_PlayingGame: String { return self._s[3182]! } + public var SearchImages_NoImagesFound: String { return self._s[3183]! } + public var SocksProxySetup_ProxyType: String { return self._s[3184]! } + public var AppleWatch_ReplyPresetsHelp: String { return self._s[3186]! } + public var Conversation_ContextMenuCancelSending: String { return self._s[3187]! } + public var Settings_AppLanguage: String { return self._s[3188]! } + public var TwoStepAuth_ResetAccountHelp: String { return self._s[3189]! } + public var Common_ChoosePhoto: String { return self._s[3190]! } + public var AuthSessions_AddDevice_InvalidQRCode: String { return self._s[3191]! } + public var CallFeedback_ReasonEcho: String { return self._s[3192]! } public func PUSH_PINNED_AUDIO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3192]!, self._r[3192]!, [_1]) + return formatWithArgumentRanges(self._s[3193]!, self._r[3193]!, [_1]) } - public var Privacy_Calls_AlwaysAllow: String { return self._s[3193]! } - public var Activity_UploadingVideo: String { return self._s[3194]! } - public var Conversation_WalletRequiredNotNow: String { return self._s[3195]! } - public var ChannelInfo_DeleteChannelConfirmation: String { return self._s[3196]! } - public var NetworkUsageSettings_Wifi: String { return self._s[3197]! } - public var VoiceOver_Editing_ClearText: String { return self._s[3198]! } - public var PUSH_SENDER_YOU: String { return self._s[3199]! } - public var Channel_BanUser_PermissionReadMessages: String { return self._s[3200]! } - public var Checkout_PayWithTouchId: String { return self._s[3201]! } - public var Wallpaper_ResetWallpapersConfirmation: String { return self._s[3202]! } + public var Privacy_Calls_AlwaysAllow: String { return self._s[3194]! } + public var Activity_UploadingVideo: String { return self._s[3195]! } + public var Conversation_WalletRequiredNotNow: String { return self._s[3196]! } + public var ChannelInfo_DeleteChannelConfirmation: String { return self._s[3197]! } + public var NetworkUsageSettings_Wifi: String { return self._s[3198]! } + public var VoiceOver_Editing_ClearText: String { return self._s[3199]! } + public var PUSH_SENDER_YOU: String { return self._s[3200]! } + public var Channel_BanUser_PermissionReadMessages: String { return self._s[3201]! } + public var Checkout_PayWithTouchId: String { return self._s[3202]! } + public var Wallpaper_ResetWallpapersConfirmation: String { return self._s[3203]! } public func PUSH_LOCKED_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3204]!, self._r[3204]!, [_1]) + return formatWithArgumentRanges(self._s[3205]!, self._r[3205]!, [_1]) } - public var Notifications_ExceptionsNone: String { return self._s[3205]! } + public var Notifications_ExceptionsNone: String { return self._s[3206]! } public func Message_ForwardedMessageShort(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3206]!, self._r[3206]!, [_0]) + return formatWithArgumentRanges(self._s[3207]!, self._r[3207]!, [_0]) } public func PUSH_PINNED_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3207]!, self._r[3207]!, [_1]) + return formatWithArgumentRanges(self._s[3208]!, self._r[3208]!, [_1]) } - public var AuthSessions_IncompleteAttempts: String { return self._s[3209]! } - public var Passport_Address_Region: String { return self._s[3212]! } - public var ChatList_DeleteChat: String { return self._s[3213]! } - public var LogoutOptions_ClearCacheTitle: String { return self._s[3214]! } - public var PhotoEditor_TiltShift: String { return self._s[3215]! } - public var Settings_FAQ_URL: String { return self._s[3216]! } - public var TwoFactorSetup_EmailVerification_ChangeAction: String { return self._s[3217]! } - public var Passport_Language_sl: String { return self._s[3218]! } - public var Settings_PrivacySettings: String { return self._s[3220]! } - public var SharedMedia_TitleLink: String { return self._s[3221]! } - public var Passport_Identity_TypePassportUploadScan: String { return self._s[3222]! } - public var Settings_SetProfilePhoto: String { return self._s[3223]! } - public var Channel_About_Help: String { return self._s[3224]! } - public var Contacts_PermissionsEnable: String { return self._s[3225]! } - public var Wallet_Sending_Title: String { return self._s[3226]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsAlert: String { return self._s[3227]! } - public var AttachmentMenu_SendAsFiles: String { return self._s[3228]! } - public var CallFeedback_ReasonInterruption: String { return self._s[3230]! } - public var Passport_Address_AddTemporaryRegistration: String { return self._s[3231]! } - public var AutoDownloadSettings_AutodownloadVideos: String { return self._s[3232]! } - public var ChatSettings_AutoDownloadSettings_Delimeter: String { return self._s[3233]! } - public var OldChannels_Title: String { return self._s[3234]! } - public var PrivacySettings_DeleteAccountTitle: String { return self._s[3235]! } - public var AccessDenied_VideoMessageCamera: String { return self._s[3237]! } - public var Map_OpenInYandexMaps: String { return self._s[3239]! } - public var CreateGroup_ErrorLocatedGroupsTooMuch: String { return self._s[3240]! } - public var VoiceOver_MessageContextReply: String { return self._s[3241]! } - public var PhotoEditor_SaturationTool: String { return self._s[3243]! } + public var AuthSessions_IncompleteAttempts: String { return self._s[3210]! } + public var Passport_Address_Region: String { return self._s[3213]! } + public var ChatList_DeleteChat: String { return self._s[3214]! } + public var LogoutOptions_ClearCacheTitle: String { return self._s[3215]! } + public var PhotoEditor_TiltShift: String { return self._s[3216]! } + public var Settings_FAQ_URL: String { return self._s[3217]! } + public var TwoFactorSetup_EmailVerification_ChangeAction: String { return self._s[3218]! } + public var Passport_Language_sl: String { return self._s[3219]! } + public var Settings_PrivacySettings: String { return self._s[3221]! } + public var SharedMedia_TitleLink: String { return self._s[3222]! } + public var Passport_Identity_TypePassportUploadScan: String { return self._s[3223]! } + public var Settings_SetProfilePhoto: String { return self._s[3224]! } + public var Channel_About_Help: String { return self._s[3225]! } + public var Contacts_PermissionsEnable: String { return self._s[3226]! } + public var Wallet_Sending_Title: String { return self._s[3227]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsAlert: String { return self._s[3228]! } + public var AttachmentMenu_SendAsFiles: String { return self._s[3229]! } + public var CallFeedback_ReasonInterruption: String { return self._s[3231]! } + public var Passport_Address_AddTemporaryRegistration: String { return self._s[3232]! } + public var AutoDownloadSettings_AutodownloadVideos: String { return self._s[3233]! } + public var ChatSettings_AutoDownloadSettings_Delimeter: String { return self._s[3234]! } + public var OldChannels_Title: String { return self._s[3235]! } + public var PrivacySettings_DeleteAccountTitle: String { return self._s[3236]! } + public var AccessDenied_VideoMessageCamera: String { return self._s[3238]! } + public var Map_OpenInYandexMaps: String { return self._s[3240]! } + public var CreateGroup_ErrorLocatedGroupsTooMuch: String { return self._s[3241]! } + public var VoiceOver_MessageContextReply: String { return self._s[3242]! } + public var PhotoEditor_SaturationTool: String { return self._s[3244]! } public func PUSH_MESSAGE_STICKER(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3244]!, self._r[3244]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3245]!, self._r[3245]!, [_1, _2]) } - public var PrivacyPhoneNumberSettings_CustomHelp: String { return self._s[3245]! } - public var Notification_Exceptions_NewException_NotificationHeader: String { return self._s[3246]! } - public var Group_OwnershipTransfer_ErrorLocatedGroupsTooMuch: String { return self._s[3247]! } + public var PrivacyPhoneNumberSettings_CustomHelp: String { return self._s[3246]! } + public var Notification_Exceptions_NewException_NotificationHeader: String { return self._s[3247]! } + public var Group_OwnershipTransfer_ErrorLocatedGroupsTooMuch: String { return self._s[3248]! } public func LOCAL_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3248]!, self._r[3248]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[3249]!, self._r[3249]!, [_1, "\(_2)"]) } - public var Appearance_ThemePreview_ChatList_2_Text: String { return self._s[3249]! } - public var Channel_Username_InvalidTooShort: String { return self._s[3251]! } - public var SettingsSearch_Synonyms_Wallet: String { return self._s[3252]! } + public var Appearance_ThemePreview_ChatList_2_Text: String { return self._s[3250]! } + public var Channel_Username_InvalidTooShort: String { return self._s[3252]! } + public var SettingsSearch_Synonyms_Wallet: String { return self._s[3253]! } public func Group_OwnershipTransfer_DescriptionInfo(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3253]!, self._r[3253]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3254]!, self._r[3254]!, [_1, _2]) } public func PUSH_CHAT_MESSAGE_GAME(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3254]!, self._r[3254]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3255]!, self._r[3255]!, [_1, _2, _3]) } - public var WallpaperPreview_PatternTitle: String { return self._s[3255]! } - public var GroupInfo_PublicLinkAdd: String { return self._s[3256]! } - public var Passport_PassportInformation: String { return self._s[3259]! } - public var Theme_Unsupported: String { return self._s[3260]! } - public var WatchRemote_AlertTitle: String { return self._s[3261]! } - public var Privacy_GroupsAndChannels_NeverAllow: String { return self._s[3262]! } - public var ConvertToSupergroup_HelpText: String { return self._s[3264]! } + public var WallpaperPreview_PatternTitle: String { return self._s[3256]! } + public var GroupInfo_PublicLinkAdd: String { return self._s[3257]! } + public var Passport_PassportInformation: String { return self._s[3260]! } + public var Theme_Unsupported: String { return self._s[3261]! } + public var WatchRemote_AlertTitle: String { return self._s[3262]! } + public var Privacy_GroupsAndChannels_NeverAllow: String { return self._s[3263]! } + public var ConvertToSupergroup_HelpText: String { return self._s[3265]! } public func Time_MonthOfYear_m7(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3265]!, self._r[3265]!, [_0]) + return formatWithArgumentRanges(self._s[3266]!, self._r[3266]!, [_0]) } public func PUSH_PHONE_CALL_REQUEST(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3266]!, self._r[3266]!, [_1]) + return formatWithArgumentRanges(self._s[3267]!, self._r[3267]!, [_1]) } - public var Privacy_GroupsAndChannels_CustomHelp: String { return self._s[3267]! } - public var Wallet_Navigation_Done: String { return self._s[3269]! } - public var TwoStepAuth_RecoveryCodeInvalid: String { return self._s[3270]! } - public var AccessDenied_CameraDisabled: String { return self._s[3271]! } + public var Privacy_GroupsAndChannels_CustomHelp: String { return self._s[3268]! } + public var Wallet_Navigation_Done: String { return self._s[3270]! } + public var TwoStepAuth_RecoveryCodeInvalid: String { return self._s[3271]! } + public var AccessDenied_CameraDisabled: String { return self._s[3272]! } public func Channel_Username_UsernameIsAvailable(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3272]!, self._r[3272]!, [_0]) + return formatWithArgumentRanges(self._s[3273]!, self._r[3273]!, [_0]) } - public var ClearCache_Forever: String { return self._s[3273]! } - public var AuthSessions_AddDeviceIntro_Title: String { return self._s[3274]! } - public var PhotoEditor_ContrastTool: String { return self._s[3277]! } + public var ClearCache_Forever: String { return self._s[3274]! } + public var AuthSessions_AddDeviceIntro_Title: String { return self._s[3275]! } + public var PhotoEditor_ContrastTool: String { return self._s[3278]! } public func PUSH_PINNED_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3278]!, self._r[3278]!, [_1]) + return formatWithArgumentRanges(self._s[3279]!, self._r[3279]!, [_1]) } - public var DialogList_Draft: String { return self._s[3279]! } - public var Wallet_Configuration_BlockchainIdInfo: String { return self._s[3280]! } - public var Privacy_TopPeersDelete: String { return self._s[3282]! } - public var LoginPassword_PasswordPlaceholder: String { return self._s[3283]! } - public var Passport_Identity_TypeIdentityCardUploadScan: String { return self._s[3284]! } - public var WebSearch_RecentSectionClear: String { return self._s[3285]! } - public var EditTheme_ErrorInvalidCharacters: String { return self._s[3286]! } - public var Watch_ChatList_NoConversationsTitle: String { return self._s[3288]! } - public var Common_Done: String { return self._s[3290]! } - public var Shortcut_SwitchAccount: String { return self._s[3291]! } - public var AuthSessions_EmptyText: String { return self._s[3292]! } - public var Wallet_Configuration_BlockchainNameChangedTitle: String { return self._s[3293]! } - public var Conversation_ShareBotContactConfirmation: String { return self._s[3294]! } - public var Tour_Title5: String { return self._s[3295]! } - public var Wallet_Settings_Title: String { return self._s[3296]! } + public var DialogList_Draft: String { return self._s[3280]! } + public var Wallet_Configuration_BlockchainIdInfo: String { return self._s[3281]! } + public var Privacy_TopPeersDelete: String { return self._s[3283]! } + public var LoginPassword_PasswordPlaceholder: String { return self._s[3284]! } + public var Passport_Identity_TypeIdentityCardUploadScan: String { return self._s[3285]! } + public var WebSearch_RecentSectionClear: String { return self._s[3286]! } + public var EditTheme_ErrorInvalidCharacters: String { return self._s[3287]! } + public var Watch_ChatList_NoConversationsTitle: String { return self._s[3289]! } + public var Common_Done: String { return self._s[3291]! } + public var Shortcut_SwitchAccount: String { return self._s[3292]! } + public var AuthSessions_EmptyText: String { return self._s[3293]! } + public var Wallet_Configuration_BlockchainNameChangedTitle: String { return self._s[3294]! } + public var Conversation_ShareBotContactConfirmation: String { return self._s[3295]! } + public var Tour_Title5: String { return self._s[3296]! } + public var Wallet_Settings_Title: String { return self._s[3297]! } public func Map_DirectionsDriveEta(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3297]!, self._r[3297]!, [_0]) + return formatWithArgumentRanges(self._s[3298]!, self._r[3298]!, [_0]) } - public var ApplyLanguage_UnsufficientDataTitle: String { return self._s[3298]! } - public var Conversation_LinkDialogSave: String { return self._s[3299]! } - public var GroupInfo_ActionRestrict: String { return self._s[3300]! } - public var Checkout_Title: String { return self._s[3301]! } - public var Channel_DiscussionGroup_HeaderLabel: String { return self._s[3303]! } - public var Channel_AdminLog_CanChangeInfo: String { return self._s[3305]! } - public var Notification_RenamedGroup: String { return self._s[3306]! } - public var PeopleNearby_Groups: String { return self._s[3307]! } - public var Checkout_PayWithFaceId: String { return self._s[3308]! } - public var Channel_BanList_BlockedTitle: String { return self._s[3309]! } - public var SettingsSearch_Synonyms_Notifications_InAppNotificationsSound: String { return self._s[3311]! } - public var Checkout_WebConfirmation_Title: String { return self._s[3312]! } - public var Notifications_MessageNotificationsAlert: String { return self._s[3313]! } + public var ApplyLanguage_UnsufficientDataTitle: String { return self._s[3299]! } + public var Conversation_LinkDialogSave: String { return self._s[3300]! } + public var GroupInfo_ActionRestrict: String { return self._s[3301]! } + public var Checkout_Title: String { return self._s[3302]! } + public var Channel_DiscussionGroup_HeaderLabel: String { return self._s[3304]! } + public var Channel_AdminLog_CanChangeInfo: String { return self._s[3306]! } + public var Notification_RenamedGroup: String { return self._s[3307]! } + public var PeopleNearby_Groups: String { return self._s[3308]! } + public var Checkout_PayWithFaceId: String { return self._s[3309]! } + public var Channel_BanList_BlockedTitle: String { return self._s[3310]! } + public var SettingsSearch_Synonyms_Notifications_InAppNotificationsSound: String { return self._s[3312]! } + public var Checkout_WebConfirmation_Title: String { return self._s[3313]! } + public var Notifications_MessageNotificationsAlert: String { return self._s[3314]! } public func Activity_RemindAboutGroup(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3314]!, self._r[3314]!, [_0]) + return formatWithArgumentRanges(self._s[3315]!, self._r[3315]!, [_0]) } - public var Profile_AddToExisting: String { return self._s[3316]! } + public var Profile_AddToExisting: String { return self._s[3317]! } public func Profile_CreateEncryptedChatOutdatedError(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3317]!, self._r[3317]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3318]!, self._r[3318]!, [_0, _1]) } - public var Cache_Files: String { return self._s[3319]! } - public var Permissions_PrivacyPolicy: String { return self._s[3320]! } - public var SocksProxySetup_ConnectAndSave: String { return self._s[3321]! } - public var UserInfo_NotificationsDefaultDisabled: String { return self._s[3322]! } - public var AutoDownloadSettings_TypeContacts: String { return self._s[3324]! } - public var Appearance_ThemePreview_ChatList_1_Text: String { return self._s[3326]! } - public var Calls_NoCallsPlaceholder: String { return self._s[3327]! } + public var Cache_Files: String { return self._s[3320]! } + public var Permissions_PrivacyPolicy: String { return self._s[3321]! } + public var SocksProxySetup_ConnectAndSave: String { return self._s[3322]! } + public var UserInfo_NotificationsDefaultDisabled: String { return self._s[3323]! } + public var AutoDownloadSettings_TypeContacts: String { return self._s[3325]! } + public var Appearance_ThemePreview_ChatList_1_Text: String { return self._s[3327]! } + public var Calls_NoCallsPlaceholder: String { return self._s[3328]! } public func Wallet_Receive_ShareInvoiceUrlInfo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3328]!, self._r[3328]!, [_0]) + return formatWithArgumentRanges(self._s[3329]!, self._r[3329]!, [_0]) } - public var Channel_Username_RevokeExistingUsernamesInfo: String { return self._s[3329]! } - public var VoiceOver_AttachMedia: String { return self._s[3332]! } - public var Notifications_ExceptionsGroupPlaceholder: String { return self._s[3333]! } + public var Channel_Username_RevokeExistingUsernamesInfo: String { return self._s[3330]! } + public var VoiceOver_AttachMedia: String { return self._s[3333]! } + public var Notifications_ExceptionsGroupPlaceholder: String { return self._s[3334]! } public func PUSH_CHAT_MESSAGE_INVOICE(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3334]!, self._r[3334]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3335]!, self._r[3335]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsSound: String { return self._s[3335]! } - public var Conversation_SetReminder_Title: String { return self._s[3336]! } - public var Passport_FieldAddressHelp: String { return self._s[3337]! } - public var Privacy_GroupsAndChannels_InviteToChannelMultipleError: String { return self._s[3338]! } - public var PUSH_REMINDER_TITLE: String { return self._s[3339]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsSound: String { return self._s[3336]! } + public var Conversation_SetReminder_Title: String { return self._s[3337]! } + public var Passport_FieldAddressHelp: String { return self._s[3338]! } + public var Privacy_GroupsAndChannels_InviteToChannelMultipleError: String { return self._s[3339]! } + public var PUSH_REMINDER_TITLE: String { return self._s[3340]! } public func Login_TermsOfService_ProceedBot(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3340]!, self._r[3340]!, [_0]) + return formatWithArgumentRanges(self._s[3341]!, self._r[3341]!, [_0]) } - public var Channel_AdminLog_EmptyTitle: String { return self._s[3341]! } - public var Privacy_Calls_NeverAllow_Title: String { return self._s[3342]! } - public var Login_UnknownError: String { return self._s[3343]! } - public var Group_UpgradeNoticeText2: String { return self._s[3346]! } - public var Watch_Compose_AddContact: String { return self._s[3347]! } - public var ClearCache_StorageServiceFiles: String { return self._s[3348]! } - public var Web_Error: String { return self._s[3349]! } - public var Gif_Search: String { return self._s[3350]! } - public var Profile_MessageLifetime1h: String { return self._s[3351]! } - public var CheckoutInfo_ReceiverInfoEmailPlaceholder: String { return self._s[3352]! } - public var Channel_Username_CheckingUsername: String { return self._s[3353]! } - public var CallFeedback_ReasonSilentRemote: String { return self._s[3354]! } - public var AutoDownloadSettings_TypeChannels: String { return self._s[3355]! } - public var Channel_AboutItem: String { return self._s[3356]! } - public var Privacy_GroupsAndChannels_AlwaysAllow_Placeholder: String { return self._s[3358]! } - public var VoiceOver_Chat_VoiceMessage: String { return self._s[3359]! } - public var GroupInfo_SharedMedia: String { return self._s[3360]! } + public var Channel_AdminLog_EmptyTitle: String { return self._s[3342]! } + public var Privacy_Calls_NeverAllow_Title: String { return self._s[3343]! } + public var Login_UnknownError: String { return self._s[3344]! } + public var Group_UpgradeNoticeText2: String { return self._s[3347]! } + public var Watch_Compose_AddContact: String { return self._s[3348]! } + public var ClearCache_StorageServiceFiles: String { return self._s[3349]! } + public var Web_Error: String { return self._s[3350]! } + public var Gif_Search: String { return self._s[3351]! } + public var Profile_MessageLifetime1h: String { return self._s[3352]! } + public var CheckoutInfo_ReceiverInfoEmailPlaceholder: String { return self._s[3353]! } + public var Channel_Username_CheckingUsername: String { return self._s[3354]! } + public var CallFeedback_ReasonSilentRemote: String { return self._s[3355]! } + public var AutoDownloadSettings_TypeChannels: String { return self._s[3356]! } + public var Channel_AboutItem: String { return self._s[3357]! } + public var Privacy_GroupsAndChannels_AlwaysAllow_Placeholder: String { return self._s[3359]! } + public var VoiceOver_Chat_VoiceMessage: String { return self._s[3360]! } + public var GroupInfo_SharedMedia: String { return self._s[3361]! } public func Channel_AdminLog_MessagePromotedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3361]!, self._r[3361]!, [_1]) + return formatWithArgumentRanges(self._s[3362]!, self._r[3362]!, [_1]) } - public var Call_PhoneCallInProgressMessage: String { return self._s[3362]! } + public var Call_PhoneCallInProgressMessage: String { return self._s[3363]! } public func PUSH_CHANNEL_ALBUM(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3363]!, self._r[3363]!, [_1]) + return formatWithArgumentRanges(self._s[3364]!, self._r[3364]!, [_1]) } - public var ChatList_UndoArchiveRevealedText: String { return self._s[3364]! } - public var GroupInfo_InviteLink_RevokeAlert_Text: String { return self._s[3365]! } - public var Conversation_SearchByName_Placeholder: String { return self._s[3366]! } - public var CreatePoll_AddOption: String { return self._s[3367]! } - public var GroupInfo_Permissions_SearchPlaceholder: String { return self._s[3368]! } - public var Group_UpgradeNoticeHeader: String { return self._s[3369]! } - public var Channel_Management_AddModerator: String { return self._s[3370]! } - public var AutoDownloadSettings_MaxFileSize: String { return self._s[3371]! } - public var StickerPacksSettings_ShowStickersButton: String { return self._s[3372]! } - public var Wallet_Info_RefreshErrorNetworkText: String { return self._s[3373]! } - public var Theme_Colors_Background: String { return self._s[3374]! } - public var NotificationsSound_Hello: String { return self._s[3376]! } - public var SocksProxySetup_SavedProxies: String { return self._s[3377]! } - public var Channel_Stickers_Placeholder: String { return self._s[3379]! } + public var ChatList_UndoArchiveRevealedText: String { return self._s[3365]! } + public var GroupInfo_InviteLink_RevokeAlert_Text: String { return self._s[3366]! } + public var Conversation_SearchByName_Placeholder: String { return self._s[3367]! } + public var CreatePoll_AddOption: String { return self._s[3368]! } + public var GroupInfo_Permissions_SearchPlaceholder: String { return self._s[3369]! } + public var Group_UpgradeNoticeHeader: String { return self._s[3370]! } + public var Channel_Management_AddModerator: String { return self._s[3371]! } + public var AutoDownloadSettings_MaxFileSize: String { return self._s[3372]! } + public var StickerPacksSettings_ShowStickersButton: String { return self._s[3373]! } + public var Wallet_Info_RefreshErrorNetworkText: String { return self._s[3374]! } + public var Theme_Colors_Background: String { return self._s[3375]! } + public var NotificationsSound_Hello: String { return self._s[3377]! } + public var SocksProxySetup_SavedProxies: String { return self._s[3378]! } + public var Channel_Stickers_Placeholder: String { return self._s[3380]! } public func Login_EmailCodeBody(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3380]!, self._r[3380]!, [_0]) + return formatWithArgumentRanges(self._s[3381]!, self._r[3381]!, [_0]) } - public var PrivacyPolicy_DeclineDeclineAndDelete: String { return self._s[3381]! } - public var Channel_Management_AddModeratorHelp: String { return self._s[3382]! } - public var ContactInfo_BirthdayLabel: String { return self._s[3383]! } - public var ChangePhoneNumberCode_RequestingACall: String { return self._s[3384]! } - public var AutoDownloadSettings_Channels: String { return self._s[3385]! } - public var Passport_Language_mn: String { return self._s[3386]! } - public var Notifications_ResetAllNotificationsHelp: String { return self._s[3389]! } - public var GroupInfo_Permissions_SlowmodeValue_Off: String { return self._s[3390]! } - public var Passport_Language_ja: String { return self._s[3392]! } - public var Settings_About_Title: String { return self._s[3393]! } - public var Settings_NotificationsAndSounds: String { return self._s[3394]! } - public var ChannelInfo_DeleteGroup: String { return self._s[3395]! } - public var Settings_BlockedUsers: String { return self._s[3396]! } + public var PrivacyPolicy_DeclineDeclineAndDelete: String { return self._s[3382]! } + public var Channel_Management_AddModeratorHelp: String { return self._s[3383]! } + public var ContactInfo_BirthdayLabel: String { return self._s[3384]! } + public var ChangePhoneNumberCode_RequestingACall: String { return self._s[3385]! } + public var AutoDownloadSettings_Channels: String { return self._s[3386]! } + public var Passport_Language_mn: String { return self._s[3387]! } + public var Notifications_ResetAllNotificationsHelp: String { return self._s[3390]! } + public var GroupInfo_Permissions_SlowmodeValue_Off: String { return self._s[3391]! } + public var Passport_Language_ja: String { return self._s[3393]! } + public var Settings_About_Title: String { return self._s[3394]! } + public var Settings_NotificationsAndSounds: String { return self._s[3395]! } + public var ChannelInfo_DeleteGroup: String { return self._s[3396]! } + public var Settings_BlockedUsers: String { return self._s[3397]! } public func Time_MonthOfYear_m4(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3397]!, self._r[3397]!, [_0]) + return formatWithArgumentRanges(self._s[3398]!, self._r[3398]!, [_0]) } - public var EditTheme_Create_Preview_OutgoingText: String { return self._s[3398]! } - public var Wallet_Weekday_Today: String { return self._s[3399]! } - public var AutoDownloadSettings_PreloadVideo: String { return self._s[3400]! } - public var Widget_ApplicationLocked: String { return self._s[3401]! } - public var Passport_Address_AddResidentialAddress: String { return self._s[3402]! } - public var Channel_Username_Title: String { return self._s[3403]! } + public var EditTheme_Create_Preview_OutgoingText: String { return self._s[3399]! } + public var Wallet_Weekday_Today: String { return self._s[3400]! } + public var AutoDownloadSettings_PreloadVideo: String { return self._s[3401]! } + public var Widget_ApplicationLocked: String { return self._s[3402]! } + public var Passport_Address_AddResidentialAddress: String { return self._s[3403]! } + public var Channel_Username_Title: String { return self._s[3404]! } public func Notification_RemovedGroupPhoto(_ _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 AttachmentMenu_File: String { return self._s[3406]! } - public var AppleWatch_Title: String { return self._s[3407]! } - public var Activity_RecordingVideoMessage: String { return self._s[3408]! } + public var AttachmentMenu_File: String { return self._s[3407]! } + public var AppleWatch_Title: String { return self._s[3408]! } + public var Activity_RecordingVideoMessage: String { return self._s[3409]! } public func Channel_DiscussionGroup_PublicChannelLink(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3409]!, self._r[3409]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3410]!, self._r[3410]!, [_1, _2]) } - public var Theme_Colors_Messages: String { return self._s[3410]! } - public var Weekday_Saturday: String { return self._s[3411]! } - public var WallpaperPreview_SwipeColorsTopText: String { return self._s[3412]! } - public var Profile_CreateEncryptedChatError: String { return self._s[3413]! } - public var Common_Next: String { return self._s[3415]! } - public var Channel_Stickers_YourStickers: String { return self._s[3417]! } - public var Message_Theme: String { return self._s[3418]! } - public var Call_AudioRouteHeadphones: String { return self._s[3419]! } - public var TwoStepAuth_EnterPasswordForgot: String { return self._s[3421]! } - public var Watch_Contacts_NoResults: String { return self._s[3423]! } - public var PhotoEditor_TintTool: String { return self._s[3426]! } - public var LoginPassword_ResetAccount: String { return self._s[3428]! } - public var Settings_SavedMessages: String { return self._s[3429]! } - public var SettingsSearch_Synonyms_Appearance_Animations: String { return self._s[3430]! } - public var Bot_GenericSupportStatus: String { return self._s[3431]! } - public var StickerPack_Add: String { return self._s[3432]! } - public var Checkout_TotalAmount: String { return self._s[3433]! } - public var Your_cards_number_is_invalid: String { return self._s[3434]! } - public var SettingsSearch_Synonyms_Appearance_AutoNightTheme: String { return self._s[3435]! } - public var VoiceOver_Chat_VideoMessage: String { return self._s[3436]! } + public var Theme_Colors_Messages: String { return self._s[3411]! } + public var Weekday_Saturday: String { return self._s[3412]! } + public var WallpaperPreview_SwipeColorsTopText: String { return self._s[3413]! } + public var Profile_CreateEncryptedChatError: String { return self._s[3414]! } + public var Common_Next: String { return self._s[3416]! } + public var Channel_Stickers_YourStickers: String { return self._s[3418]! } + public var Message_Theme: String { return self._s[3419]! } + public var Call_AudioRouteHeadphones: String { return self._s[3420]! } + public var TwoStepAuth_EnterPasswordForgot: String { return self._s[3422]! } + public var Watch_Contacts_NoResults: String { return self._s[3424]! } + public var PhotoEditor_TintTool: String { return self._s[3427]! } + public var LoginPassword_ResetAccount: String { return self._s[3429]! } + public var Settings_SavedMessages: String { return self._s[3430]! } + public var SettingsSearch_Synonyms_Appearance_Animations: String { return self._s[3431]! } + public var Bot_GenericSupportStatus: String { return self._s[3432]! } + public var StickerPack_Add: String { return self._s[3433]! } + public var Checkout_TotalAmount: String { return self._s[3434]! } + public var Your_cards_number_is_invalid: String { return self._s[3435]! } + public var SettingsSearch_Synonyms_Appearance_AutoNightTheme: String { return self._s[3436]! } + public var VoiceOver_Chat_VideoMessage: String { return self._s[3437]! } public func ChangePhoneNumberCode_CallTimer(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3437]!, self._r[3437]!, [_0]) + return formatWithArgumentRanges(self._s[3438]!, self._r[3438]!, [_0]) } public func GroupPermission_AddedInfo(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3438]!, self._r[3438]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3439]!, self._r[3439]!, [_1, _2]) } - public var ChatSettings_ConnectionType_UseSocks5: String { return self._s[3439]! } + public var ChatSettings_ConnectionType_UseSocks5: String { return self._s[3440]! } public func PUSH_CHAT_PHOTO_EDITED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3441]!, self._r[3441]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3442]!, self._r[3442]!, [_1, _2]) } public func Conversation_RestrictedTextTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3442]!, self._r[3442]!, [_0]) + return formatWithArgumentRanges(self._s[3443]!, self._r[3443]!, [_0]) } - public var GroupInfo_InviteLink_ShareLink: String { return self._s[3443]! } - public var StickerPack_Share: String { return self._s[3444]! } - public var Passport_DeleteAddress: String { return self._s[3445]! } - public var Settings_Passport: String { return self._s[3446]! } - public var SharedMedia_EmptyFilesText: String { return self._s[3447]! } - public var Conversation_DeleteMessagesForMe: String { return self._s[3448]! } - public var PasscodeSettings_AutoLock_IfAwayFor_1hour: String { return self._s[3449]! } - public var Contacts_PermissionsText: String { return self._s[3450]! } - public var Group_Setup_HistoryVisible: String { return self._s[3451]! } - public var Wallet_Month_ShortDecember: String { return self._s[3453]! } - public var Channel_EditAdmin_PermissionEnabledByDefault: String { return self._s[3454]! } - public var Passport_Address_AddRentalAgreement: String { return self._s[3455]! } - public var SocksProxySetup_Title: String { return self._s[3456]! } - public var Notification_Mute1h: String { return self._s[3457]! } + public var GroupInfo_InviteLink_ShareLink: String { return self._s[3444]! } + public var StickerPack_Share: String { return self._s[3445]! } + public var Passport_DeleteAddress: String { return self._s[3446]! } + public var Settings_Passport: String { return self._s[3447]! } + public var SharedMedia_EmptyFilesText: String { return self._s[3448]! } + public var Conversation_DeleteMessagesForMe: String { return self._s[3449]! } + public var PasscodeSettings_AutoLock_IfAwayFor_1hour: String { return self._s[3450]! } + public var Contacts_PermissionsText: String { return self._s[3451]! } + public var Group_Setup_HistoryVisible: String { return self._s[3452]! } + public var Wallet_Month_ShortDecember: String { return self._s[3454]! } + public var Channel_EditAdmin_PermissionEnabledByDefault: String { return self._s[3455]! } + public var Passport_Address_AddRentalAgreement: String { return self._s[3456]! } + public var SocksProxySetup_Title: String { return self._s[3457]! } + public var Notification_Mute1h: String { return self._s[3458]! } public func Passport_Email_CodeHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3458]!, self._r[3458]!, [_0]) + return formatWithArgumentRanges(self._s[3459]!, self._r[3459]!, [_0]) } - public var NotificationSettings_ShowNotificationsAllAccountsInfoOff: String { return self._s[3459]! } + public var NotificationSettings_ShowNotificationsAllAccountsInfoOff: String { return self._s[3460]! } public func PUSH_PINNED_GEOLIVE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3460]!, self._r[3460]!, [_1]) + return formatWithArgumentRanges(self._s[3461]!, self._r[3461]!, [_1]) } - public var FastTwoStepSetup_PasswordSection: String { return self._s[3461]! } - public var NetworkUsageSettings_ResetStatsConfirmation: String { return self._s[3464]! } - public var InfoPlist_NSFaceIDUsageDescription: String { return self._s[3466]! } - public var DialogList_NoMessagesText: String { return self._s[3467]! } - public var Privacy_ContactsResetConfirmation: String { return self._s[3468]! } - public var Privacy_Calls_P2PHelp: String { return self._s[3469]! } - public var Channel_DiscussionGroup_SearchPlaceholder: String { return self._s[3471]! } - public var Your_cards_expiration_year_is_invalid: String { return self._s[3472]! } - public var Common_TakePhotoOrVideo: String { return self._s[3473]! } - public var Wallet_Words_Text: String { return self._s[3474]! } - public var Call_StatusBusy: String { return self._s[3475]! } - public var Conversation_PinnedMessage: String { return self._s[3476]! } - public var AutoDownloadSettings_VoiceMessagesTitle: String { return self._s[3477]! } - public var Wallet_Configuration_BlockchainNameChangedProceed: String { return self._s[3478]! } - public var TwoStepAuth_SetupPasswordConfirmFailed: String { return self._s[3479]! } - public var Undo_ChatCleared: String { return self._s[3480]! } - public var AppleWatch_ReplyPresets: String { return self._s[3481]! } - public var Passport_DiscardMessageDescription: String { return self._s[3483]! } - public var Login_NetworkError: String { return self._s[3484]! } + public var FastTwoStepSetup_PasswordSection: String { return self._s[3462]! } + public var NetworkUsageSettings_ResetStatsConfirmation: String { return self._s[3465]! } + public var InfoPlist_NSFaceIDUsageDescription: String { return self._s[3467]! } + public var DialogList_NoMessagesText: String { return self._s[3468]! } + public var Privacy_ContactsResetConfirmation: String { return self._s[3469]! } + public var Privacy_Calls_P2PHelp: String { return self._s[3470]! } + public var Channel_DiscussionGroup_SearchPlaceholder: String { return self._s[3472]! } + public var Your_cards_expiration_year_is_invalid: String { return self._s[3473]! } + public var Common_TakePhotoOrVideo: String { return self._s[3474]! } + public var Wallet_Words_Text: String { return self._s[3475]! } + public var Call_StatusBusy: String { return self._s[3476]! } + public var Conversation_PinnedMessage: String { return self._s[3477]! } + public var AutoDownloadSettings_VoiceMessagesTitle: String { return self._s[3478]! } + public var Wallet_Configuration_BlockchainNameChangedProceed: String { return self._s[3479]! } + public var TwoStepAuth_SetupPasswordConfirmFailed: String { return self._s[3480]! } + public var Undo_ChatCleared: String { return self._s[3481]! } + public var AppleWatch_ReplyPresets: String { return self._s[3482]! } + public var Passport_DiscardMessageDescription: String { return self._s[3484]! } + public var Login_NetworkError: String { return self._s[3485]! } public func Notification_PinnedRoundMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3485]!, self._r[3485]!, [_0]) - } - public func Channel_AdminLog_MessageRemovedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3486]!, self._r[3486]!, [_0]) } - public var SocksProxySetup_PasswordPlaceholder: String { return self._s[3487]! } - public var Wallet_WordCheck_ViewWords: String { return self._s[3489]! } - public var Login_ResetAccountProtected_LimitExceeded: String { return self._s[3490]! } + public func Channel_AdminLog_MessageRemovedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3487]!, self._r[3487]!, [_0]) + } + public var SocksProxySetup_PasswordPlaceholder: String { return self._s[3488]! } + public var Wallet_WordCheck_ViewWords: String { return self._s[3490]! } + public var Login_ResetAccountProtected_LimitExceeded: String { return self._s[3491]! } public func Watch_LastSeen_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3492]!, self._r[3492]!, [_0]) + return formatWithArgumentRanges(self._s[3493]!, self._r[3493]!, [_0]) } - public var Call_ConnectionErrorMessage: String { return self._s[3493]! } - public var VoiceOver_Chat_Music: String { return self._s[3494]! } - public var SettingsSearch_Synonyms_Notifications_MessageNotificationsSound: String { return self._s[3495]! } - public var Compose_GroupTokenListPlaceholder: String { return self._s[3497]! } - public var ConversationMedia_Title: String { return self._s[3498]! } - public var EncryptionKey_Title: String { return self._s[3500]! } - public var TwoStepAuth_EnterPasswordTitle: String { return self._s[3501]! } - public var Notification_Exceptions_AddException: String { return self._s[3502]! } - public var PrivacySettings_BlockedPeersEmpty: String { return self._s[3503]! } - public var Profile_MessageLifetime1m: String { return self._s[3504]! } + public var Call_ConnectionErrorMessage: String { return self._s[3494]! } + public var VoiceOver_Chat_Music: String { return self._s[3495]! } + public var SettingsSearch_Synonyms_Notifications_MessageNotificationsSound: String { return self._s[3496]! } + public var Compose_GroupTokenListPlaceholder: String { return self._s[3498]! } + public var ConversationMedia_Title: String { return self._s[3499]! } + public var EncryptionKey_Title: String { return self._s[3501]! } + public var TwoStepAuth_EnterPasswordTitle: String { return self._s[3502]! } + public var Notification_Exceptions_AddException: String { return self._s[3503]! } + public var PrivacySettings_BlockedPeersEmpty: String { return self._s[3504]! } + public var Profile_MessageLifetime1m: String { return self._s[3505]! } public func Channel_AdminLog_MessageUnkickedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3505]!, self._r[3505]!, [_1]) + return formatWithArgumentRanges(self._s[3506]!, self._r[3506]!, [_1]) } - public var Month_GenMay: String { return self._s[3506]! } + public var Month_GenMay: String { return self._s[3507]! } public func LiveLocationUpdated_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3507]!, self._r[3507]!, [_0]) + return formatWithArgumentRanges(self._s[3508]!, self._r[3508]!, [_0]) } - public var PeopleNearby_Users: String { return self._s[3508]! } - public var Wallet_Send_AddressInfo: String { return self._s[3509]! } - public var ChannelMembers_WhoCanAddMembersAllHelp: String { return self._s[3510]! } - public var AutoDownloadSettings_ResetSettings: String { return self._s[3511]! } + public var PeopleNearby_Users: String { return self._s[3509]! } + public var Wallet_Send_AddressInfo: String { return self._s[3510]! } + public var ChannelMembers_WhoCanAddMembersAllHelp: String { return self._s[3511]! } + public var AutoDownloadSettings_ResetSettings: String { return self._s[3512]! } public func Wallet_Updated_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3513]!, self._r[3513]!, [_0]) + return formatWithArgumentRanges(self._s[3514]!, self._r[3514]!, [_0]) } - public var Conversation_EmptyPlaceholder: String { return self._s[3514]! } - public var Passport_Address_AddPassportRegistration: String { return self._s[3515]! } - public var Notifications_ChannelNotificationsAlert: String { return self._s[3516]! } - public var ChatSettings_AutoDownloadUsingCellular: String { return self._s[3517]! } - public var Camera_TapAndHoldForVideo: String { return self._s[3518]! } - public var Channel_JoinChannel: String { return self._s[3520]! } - public var Appearance_Animations: String { return self._s[3523]! } + public var Conversation_EmptyPlaceholder: String { return self._s[3515]! } + public var Passport_Address_AddPassportRegistration: String { return self._s[3516]! } + public var Notifications_ChannelNotificationsAlert: String { return self._s[3517]! } + public var ChatSettings_AutoDownloadUsingCellular: String { return self._s[3518]! } + public var Camera_TapAndHoldForVideo: String { return self._s[3519]! } + public var Channel_JoinChannel: String { return self._s[3521]! } + public var Appearance_Animations: String { return self._s[3524]! } public func Notification_MessageLifetimeChanged(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3524]!, self._r[3524]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3525]!, self._r[3525]!, [_1, _2]) } - public var Stickers_GroupStickers: String { return self._s[3526]! } - public var Appearance_ShareTheme: String { return self._s[3527]! } - public var TwoFactorSetup_Hint_Placeholder: String { return self._s[3528]! } - public var ConvertToSupergroup_HelpTitle: String { return self._s[3530]! } - public var StickerPackActionInfo_RemovedTitle: String { return self._s[3531]! } - public var Passport_Address_Street: String { return self._s[3532]! } - public var Conversation_AddContact: String { return self._s[3533]! } - public var Login_PhonePlaceholder: String { return self._s[3534]! } - public var Channel_Members_InviteLink: String { return self._s[3536]! } - public var Bot_Stop: String { return self._s[3537]! } - public var SettingsSearch_Synonyms_Proxy_UseForCalls: String { return self._s[3539]! } - public var Notification_PassportValueAddress: String { return self._s[3540]! } - public var Month_ShortJuly: String { return self._s[3541]! } - public var Passport_Address_TypeTemporaryRegistrationUploadScan: String { return self._s[3542]! } - public var Channel_AdminLog_BanSendMedia: String { return self._s[3543]! } - public var Passport_Identity_ReverseSide: String { return self._s[3544]! } - public var Watch_Stickers_Recents: String { return self._s[3547]! } - public var PrivacyLastSeenSettings_EmpryUsersPlaceholder: String { return self._s[3549]! } - public var Map_SendThisLocation: String { return self._s[3550]! } + public var Stickers_GroupStickers: String { return self._s[3527]! } + public var Appearance_ShareTheme: String { return self._s[3528]! } + public var TwoFactorSetup_Hint_Placeholder: String { return self._s[3529]! } + public var ConvertToSupergroup_HelpTitle: String { return self._s[3531]! } + public var StickerPackActionInfo_RemovedTitle: String { return self._s[3532]! } + public var Passport_Address_Street: String { return self._s[3533]! } + public var Conversation_AddContact: String { return self._s[3534]! } + public var Login_PhonePlaceholder: String { return self._s[3535]! } + public var Channel_Members_InviteLink: String { return self._s[3537]! } + public var Bot_Stop: String { return self._s[3538]! } + public var SettingsSearch_Synonyms_Proxy_UseForCalls: String { return self._s[3540]! } + public var Notification_PassportValueAddress: String { return self._s[3541]! } + public var Month_ShortJuly: String { return self._s[3542]! } + public var Passport_Address_TypeTemporaryRegistrationUploadScan: String { return self._s[3543]! } + public var Channel_AdminLog_BanSendMedia: String { return self._s[3544]! } + public var Passport_Identity_ReverseSide: String { return self._s[3545]! } + public var Watch_Stickers_Recents: String { return self._s[3548]! } + public var PrivacyLastSeenSettings_EmpryUsersPlaceholder: String { return self._s[3550]! } + public var Map_SendThisLocation: String { return self._s[3551]! } public func Time_MonthOfYear_m1(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3551]!, self._r[3551]!, [_0]) - } - public func InviteText_SingleContact(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3552]!, self._r[3552]!, [_0]) } - public var ConvertToSupergroup_Note: String { return self._s[3553]! } - public var Wallet_Intro_NotNow: String { return self._s[3554]! } + public func InviteText_SingleContact(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3553]!, self._r[3553]!, [_0]) + } + public var ConvertToSupergroup_Note: String { return self._s[3554]! } + public var Wallet_Intro_NotNow: String { return self._s[3555]! } public func FileSize_MB(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3555]!, self._r[3555]!, [_0]) + return formatWithArgumentRanges(self._s[3556]!, self._r[3556]!, [_0]) } - public var NetworkUsageSettings_GeneralDataSection: String { return self._s[3556]! } + public var NetworkUsageSettings_GeneralDataSection: String { return self._s[3557]! } public func Compatibility_SecretMediaVersionTooLow(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3557]!, self._r[3557]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3558]!, self._r[3558]!, [_0, _1]) } - public var Login_CallRequestState3: String { return self._s[3559]! } - public var Wallpaper_SearchShort: String { return self._s[3560]! } - public var SettingsSearch_Synonyms_Appearance_ColorTheme: String { return self._s[3562]! } - public var PasscodeSettings_UnlockWithFaceId: String { return self._s[3563]! } - public var Channel_BotDoesntSupportGroups: String { return self._s[3564]! } + public var Login_CallRequestState3: String { return self._s[3560]! } + public var Wallpaper_SearchShort: String { return self._s[3561]! } + public var SettingsSearch_Synonyms_Appearance_ColorTheme: String { return self._s[3563]! } + public var PasscodeSettings_UnlockWithFaceId: String { return self._s[3564]! } + public var Channel_BotDoesntSupportGroups: String { return self._s[3565]! } public func PUSH_CHAT_MESSAGE_GEOLIVE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3565]!, self._r[3565]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3566]!, self._r[3566]!, [_1, _2]) } - public var Channel_AdminLogFilter_Title: String { return self._s[3566]! } - public var Appearance_ThemePreview_Chat_4_Text: String { return self._s[3568]! } - public var Notifications_GroupNotificationsExceptions: String { return self._s[3571]! } + public var Channel_AdminLogFilter_Title: String { return self._s[3567]! } + public var Appearance_ThemePreview_Chat_4_Text: String { return self._s[3569]! } + public var Notifications_GroupNotificationsExceptions: String { return self._s[3572]! } public func FileSize_B(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3572]!, self._r[3572]!, [_0]) + return formatWithArgumentRanges(self._s[3573]!, self._r[3573]!, [_0]) } - public var Passport_CorrectErrors: String { return self._s[3573]! } - public var VoiceOver_Chat_YourAnonymousPoll: String { return self._s[3574]! } + public var Passport_CorrectErrors: String { return self._s[3574]! } + public var VoiceOver_Chat_YourAnonymousPoll: String { return self._s[3575]! } public func Channel_MessageTitleUpdated(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3575]!, self._r[3575]!, [_0]) + return formatWithArgumentRanges(self._s[3576]!, self._r[3576]!, [_0]) } - public var Map_SendMyCurrentLocation: String { return self._s[3576]! } - public var Channel_DiscussionGroup: String { return self._s[3577]! } - public var TwoFactorSetup_Email_SkipConfirmationSkip: String { return self._s[3578]! } + public var Map_SendMyCurrentLocation: String { return self._s[3577]! } + public var Channel_DiscussionGroup: String { return self._s[3578]! } + public var TwoFactorSetup_Email_SkipConfirmationSkip: String { return self._s[3579]! } public func PUSH_PINNED_CONTACT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3579]!, self._r[3579]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3580]!, self._r[3580]!, [_1, _2]) } - public var SharedMedia_SearchNoResults: String { return self._s[3580]! } - public var Permissions_NotificationsText_v0: String { return self._s[3581]! } - public var Channel_EditAdmin_PermissionDeleteMessagesOfOthers: String { return self._s[3582]! } - public var Appearance_AppIcon: String { return self._s[3583]! } - public var Appearance_ThemePreview_ChatList_3_AuthorName: String { return self._s[3584]! } - public var LoginPassword_FloodError: String { return self._s[3585]! } - public var Wallet_Send_OwnAddressAlertProceed: String { return self._s[3587]! } - public var Group_Setup_HistoryHiddenHelp: String { return self._s[3588]! } + public var SharedMedia_SearchNoResults: String { return self._s[3581]! } + public var Permissions_NotificationsText_v0: String { return self._s[3582]! } + public var Channel_EditAdmin_PermissionDeleteMessagesOfOthers: String { return self._s[3583]! } + public var Appearance_AppIcon: String { return self._s[3584]! } + public var Appearance_ThemePreview_ChatList_3_AuthorName: String { return self._s[3585]! } + public var LoginPassword_FloodError: String { return self._s[3586]! } + public var Wallet_Send_OwnAddressAlertProceed: String { return self._s[3588]! } + public var Group_Setup_HistoryHiddenHelp: String { return self._s[3589]! } public func TwoStepAuth_PendingEmailHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3589]!, self._r[3589]!, [_0]) + return formatWithArgumentRanges(self._s[3590]!, self._r[3590]!, [_0]) } - public var Passport_Language_bn: String { return self._s[3590]! } + public var Passport_Language_bn: String { return self._s[3591]! } public func DialogList_SingleUploadingPhotoSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3591]!, self._r[3591]!, [_0]) + return formatWithArgumentRanges(self._s[3592]!, self._r[3592]!, [_0]) } - public var ChatList_Context_Pin: String { return self._s[3592]! } + public var ChatList_Context_Pin: String { return self._s[3593]! } public func Notification_PinnedAudioMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3593]!, self._r[3593]!, [_0]) - } - public func Channel_AdminLog_MessageChangedGroupStickerPack(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3594]!, self._r[3594]!, [_0]) } - public var Wallet_Navigation_Close: String { return self._s[3595]! } - public var GroupInfo_InvitationLinkGroupFull: String { return self._s[3599]! } - public var Group_EditAdmin_PermissionChangeInfo: String { return self._s[3601]! } - public var Wallet_Month_GenDecember: String { return self._s[3602]! } - public var Contacts_PermissionsAllow: String { return self._s[3603]! } - public var ReportPeer_ReasonCopyright: String { return self._s[3604]! } - public var Channel_EditAdmin_PermissinAddAdminOn: String { return self._s[3605]! } - public var WallpaperPreview_Pattern: String { return self._s[3606]! } - public var Paint_Duplicate: String { return self._s[3607]! } - public var Passport_Address_Country: String { return self._s[3608]! } - public var Notification_RenamedChannel: String { return self._s[3610]! } - public var ChatList_Context_Unmute: String { return self._s[3611]! } - public var CheckoutInfo_ErrorPostcodeInvalid: String { return self._s[3612]! } - public var Group_MessagePhotoUpdated: String { return self._s[3613]! } - public var Channel_BanUser_PermissionSendMedia: String { return self._s[3614]! } - public var Conversation_ContextMenuBan: String { return self._s[3615]! } - public var TwoStepAuth_EmailSent: String { return self._s[3616]! } - public var MessagePoll_NoVotes: String { return self._s[3617]! } - public var Wallet_Send_ErrorNotEnoughFundsTitle: String { return self._s[3618]! } - public var Passport_Language_is: String { return self._s[3619]! } - public var PeopleNearby_UsersEmpty: String { return self._s[3621]! } - public var Tour_Text5: String { return self._s[3622]! } + public func Channel_AdminLog_MessageChangedGroupStickerPack(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3595]!, self._r[3595]!, [_0]) + } + public var Wallet_Navigation_Close: String { return self._s[3596]! } + public var GroupInfo_InvitationLinkGroupFull: String { return self._s[3600]! } + public var Group_EditAdmin_PermissionChangeInfo: String { return self._s[3602]! } + public var Wallet_Month_GenDecember: String { return self._s[3603]! } + public var Contacts_PermissionsAllow: String { return self._s[3604]! } + public var ReportPeer_ReasonCopyright: String { return self._s[3605]! } + public var Channel_EditAdmin_PermissinAddAdminOn: String { return self._s[3606]! } + public var WallpaperPreview_Pattern: String { return self._s[3607]! } + public var Paint_Duplicate: String { return self._s[3608]! } + public var Passport_Address_Country: String { return self._s[3609]! } + public var Notification_RenamedChannel: String { return self._s[3611]! } + public var ChatList_Context_Unmute: String { return self._s[3612]! } + public var CheckoutInfo_ErrorPostcodeInvalid: String { return self._s[3613]! } + public var Group_MessagePhotoUpdated: String { return self._s[3614]! } + public var Channel_BanUser_PermissionSendMedia: String { return self._s[3615]! } + public var Conversation_ContextMenuBan: String { return self._s[3616]! } + public var TwoStepAuth_EmailSent: String { return self._s[3617]! } + public var MessagePoll_NoVotes: String { return self._s[3618]! } + public var Wallet_Send_ErrorNotEnoughFundsTitle: String { return self._s[3619]! } + public var Passport_Language_is: String { return self._s[3620]! } + public var PeopleNearby_UsersEmpty: String { return self._s[3622]! } + public var Tour_Text5: String { return self._s[3623]! } public func Call_GroupFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3624]!, self._r[3624]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3625]!, self._r[3625]!, [_1, _2]) } - public var Undo_SecretChatDeleted: String { return self._s[3625]! } - public var SocksProxySetup_ShareQRCode: String { return self._s[3626]! } + public var Undo_SecretChatDeleted: String { return self._s[3626]! } + public var SocksProxySetup_ShareQRCode: String { return self._s[3627]! } public func VoiceOver_Chat_Size(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3627]!, self._r[3627]!, [_0]) + return formatWithArgumentRanges(self._s[3628]!, self._r[3628]!, [_0]) } - public var LogoutOptions_ChangePhoneNumberText: String { return self._s[3628]! } - public var Paint_Edit: String { return self._s[3630]! } - public var ScheduledMessages_ReminderNotification: String { return self._s[3632]! } - public var Undo_DeletedGroup: String { return self._s[3634]! } - public var LoginPassword_ForgotPassword: String { return self._s[3635]! } - public var Wallet_WordImport_IncorrectTitle: String { return self._s[3636]! } - public var GroupInfo_GroupNamePlaceholder: String { return self._s[3637]! } + public var LogoutOptions_ChangePhoneNumberText: String { return self._s[3629]! } + public var Paint_Edit: String { return self._s[3631]! } + public var ScheduledMessages_ReminderNotification: String { return self._s[3633]! } + public var Undo_DeletedGroup: String { return self._s[3635]! } + public var LoginPassword_ForgotPassword: String { return self._s[3636]! } + public var Wallet_WordImport_IncorrectTitle: String { return self._s[3637]! } + public var GroupInfo_GroupNamePlaceholder: String { return self._s[3638]! } public func Notification_Kicked(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3638]!, self._r[3638]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3639]!, self._r[3639]!, [_0, _1]) } - public var AppWallet_TransactionInfo_FeeInfoURL: String { return self._s[3639]! } - public var Conversation_InputTextCaptionPlaceholder: String { return self._s[3640]! } - public var AutoDownloadSettings_VideoMessagesTitle: String { return self._s[3641]! } - public var Passport_Language_uz: String { return self._s[3642]! } - public var Conversation_PinMessageAlertGroup: String { return self._s[3643]! } - public var SettingsSearch_Synonyms_Privacy_GroupsAndChannels: String { return self._s[3644]! } - public var Map_StopLiveLocation: String { return self._s[3646]! } - public var VoiceOver_MessageContextSend: String { return self._s[3648]! } - public var PasscodeSettings_Help: String { return self._s[3649]! } - public var NotificationsSound_Input: String { return self._s[3650]! } - public var Share_Title: String { return self._s[3653]! } - public var LogoutOptions_Title: String { return self._s[3654]! } - public var Wallet_Send_AddressText: String { return self._s[3655]! } - public var Login_TermsOfServiceAgree: String { return self._s[3656]! } - public var Compose_NewEncryptedChatTitle: String { return self._s[3657]! } - public var Channel_AdminLog_TitleSelectedEvents: String { return self._s[3658]! } - public var Channel_EditAdmin_PermissionEditMessages: String { return self._s[3659]! } - public var EnterPasscode_EnterTitle: String { return self._s[3660]! } + public var AppWallet_TransactionInfo_FeeInfoURL: String { return self._s[3640]! } + public var Conversation_InputTextCaptionPlaceholder: String { return self._s[3641]! } + public var AutoDownloadSettings_VideoMessagesTitle: String { return self._s[3642]! } + public var Passport_Language_uz: String { return self._s[3643]! } + public var Conversation_PinMessageAlertGroup: String { return self._s[3644]! } + public var SettingsSearch_Synonyms_Privacy_GroupsAndChannels: String { return self._s[3645]! } + public var Map_StopLiveLocation: String { return self._s[3647]! } + public var VoiceOver_MessageContextSend: String { return self._s[3649]! } + public var PasscodeSettings_Help: String { return self._s[3650]! } + public var NotificationsSound_Input: String { return self._s[3651]! } + public var Share_Title: String { return self._s[3654]! } + public var LogoutOptions_Title: String { return self._s[3655]! } + public var Wallet_Send_AddressText: String { return self._s[3656]! } + public var Login_TermsOfServiceAgree: String { return self._s[3657]! } + public var Compose_NewEncryptedChatTitle: String { return self._s[3658]! } + public var Channel_AdminLog_TitleSelectedEvents: String { return self._s[3659]! } + public var Channel_EditAdmin_PermissionEditMessages: String { return self._s[3660]! } + public var EnterPasscode_EnterTitle: String { return self._s[3661]! } public func Call_PrivacyErrorMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3661]!, self._r[3661]!, [_0]) + return formatWithArgumentRanges(self._s[3662]!, self._r[3662]!, [_0]) } - public var Settings_CopyPhoneNumber: String { return self._s[3662]! } - public var Conversation_AddToContacts: String { return self._s[3663]! } + public var Settings_CopyPhoneNumber: String { return self._s[3663]! } + public var Conversation_AddToContacts: String { return self._s[3664]! } public func VoiceOver_Chat_ReplyFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3664]!, self._r[3664]!, [_0]) + return formatWithArgumentRanges(self._s[3665]!, self._r[3665]!, [_0]) } - public var NotificationsSound_Keys: String { return self._s[3665]! } + public var NotificationsSound_Keys: String { return self._s[3666]! } public func Call_ParticipantVersionOutdatedError(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3666]!, self._r[3666]!, [_0]) + return formatWithArgumentRanges(self._s[3667]!, self._r[3667]!, [_0]) } - public var Notification_MessageLifetime1w: String { return self._s[3667]! } - public var Message_Video: String { return self._s[3668]! } - public var AutoDownloadSettings_CellularTitle: String { return self._s[3669]! } + public var Notification_MessageLifetime1w: String { return self._s[3668]! } + public var Message_Video: String { return self._s[3669]! } + public var AutoDownloadSettings_CellularTitle: String { return self._s[3670]! } public func PUSH_CHANNEL_MESSAGE_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3670]!, self._r[3670]!, [_1]) + return formatWithArgumentRanges(self._s[3671]!, self._r[3671]!, [_1]) } - public var Wallet_Receive_AmountInfo: String { return self._s[3673]! } + public var Wallet_Receive_AmountInfo: String { return self._s[3674]! } public func Notification_JoinedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3674]!, self._r[3674]!, [_0]) - } - public func PrivacySettings_LastSeenContactsPlus(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3675]!, self._r[3675]!, [_0]) } - public var Passport_Language_mk: String { return self._s[3676]! } - public func Wallet_Time_PreciseDate_m2(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3677]!, self._r[3677]!, [_1, _2, _3]) + public func PrivacySettings_LastSeenContactsPlus(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3676]!, self._r[3676]!, [_0]) } - public var CreatePoll_CancelConfirmation: String { return self._s[3678]! } - public var Conversation_SilentBroadcastTooltipOn: String { return self._s[3680]! } - public var PrivacyPolicy_Decline: String { return self._s[3681]! } - public var Passport_Identity_DoesNotExpire: String { return self._s[3682]! } - public var Channel_AdminLogFilter_EventsRestrictions: String { return self._s[3683]! } - public var AuthSessions_AddDeviceIntro_Action: String { return self._s[3684]! } - public var Permissions_SiriAllow_v0: String { return self._s[3686]! } - public var Wallet_Month_ShortAugust: String { return self._s[3687]! } - public var Appearance_ThemeCarouselNight: String { return self._s[3688]! } + public var Passport_Language_mk: String { return self._s[3677]! } + public func Wallet_Time_PreciseDate_m2(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3678]!, self._r[3678]!, [_1, _2, _3]) + } + public var CreatePoll_CancelConfirmation: String { return self._s[3679]! } + public var Conversation_SilentBroadcastTooltipOn: String { return self._s[3681]! } + public var PrivacyPolicy_Decline: String { return self._s[3682]! } + public var Passport_Identity_DoesNotExpire: String { return self._s[3683]! } + public var Channel_AdminLogFilter_EventsRestrictions: String { return self._s[3684]! } + public var AuthSessions_AddDeviceIntro_Action: String { return self._s[3685]! } + public var Permissions_SiriAllow_v0: String { return self._s[3687]! } + public var Wallet_Month_ShortAugust: String { return self._s[3688]! } + public var Appearance_ThemeCarouselNight: String { return self._s[3689]! } public func LOCAL_CHAT_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3689]!, self._r[3689]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[3690]!, self._r[3690]!, [_1, "\(_2)"]) } public func Notification_RenamedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3690]!, self._r[3690]!, [_0]) + return formatWithArgumentRanges(self._s[3691]!, self._r[3691]!, [_0]) } - public var Paint_Regular: String { return self._s[3691]! } - public var ChatSettings_AutoDownloadReset: String { return self._s[3692]! } - public var SocksProxySetup_ShareLink: String { return self._s[3693]! } - public var Wallet_Qr_Title: String { return self._s[3694]! } - public var BlockedUsers_SelectUserTitle: String { return self._s[3695]! } - public var VoiceOver_Chat_RecordModeVoiceMessage: String { return self._s[3697]! } - public var Wallet_Settings_Configuration: String { return self._s[3698]! } - public var GroupInfo_InviteByLink: String { return self._s[3699]! } - public var MessageTimer_Custom: String { return self._s[3700]! } - public var UserInfo_NotificationsDefaultEnabled: String { return self._s[3701]! } - public var Passport_Address_TypeTemporaryRegistration: String { return self._s[3703]! } - public var Conversation_SendMessage_SetReminder: String { return self._s[3704]! } - public var VoiceOver_Chat_Selected: String { return self._s[3705]! } - public var ChatSettings_AutoDownloadUsingWiFi: String { return self._s[3706]! } - public var Channel_Username_InvalidTaken: String { return self._s[3707]! } - public var Conversation_ClousStorageInfo_Description3: String { return self._s[3708]! } - public var Wallet_WordCheck_TryAgain: String { return self._s[3709]! } - public var Wallet_Info_TransactionPendingHeader: String { return self._s[3710]! } - public var Settings_ChatBackground: String { return self._s[3711]! } - public var Channel_Subscribers_Title: String { return self._s[3712]! } - public var Wallet_Receive_InvoiceUrlHeader: String { return self._s[3713]! } - public var ApplyLanguage_ChangeLanguageTitle: String { return self._s[3714]! } - public var Watch_ConnectionDescription: String { return self._s[3715]! } - public var OldChannels_NoticeText: String { return self._s[3718]! } - public var Wallet_Configuration_ApplyErrorTitle: String { return self._s[3719]! } - public var IntentsSettings_SuggestBy: String { return self._s[3721]! } - public var Theme_ThemeChangedText: String { return self._s[3722]! } - public var ChatList_ArchivedChatsTitle: String { return self._s[3723]! } - public var Wallpaper_ResetWallpapers: String { return self._s[3724]! } - public var Wallet_Send_TransactionInProgress: String { return self._s[3725]! } - public var EditProfile_Title: String { return self._s[3726]! } - public var NotificationsSound_Bamboo: String { return self._s[3728]! } - public var Channel_AdminLog_MessagePreviousMessage: String { return self._s[3730]! } - public var Login_SmsRequestState2: String { return self._s[3731]! } - public var Passport_Language_ar: String { return self._s[3732]! } + public var Paint_Regular: String { return self._s[3692]! } + public var ChatSettings_AutoDownloadReset: String { return self._s[3693]! } + public var SocksProxySetup_ShareLink: String { return self._s[3694]! } + public var Wallet_Qr_Title: String { return self._s[3695]! } + public var BlockedUsers_SelectUserTitle: String { return self._s[3696]! } + public var VoiceOver_Chat_RecordModeVoiceMessage: String { return self._s[3698]! } + public var Wallet_Settings_Configuration: String { return self._s[3699]! } + public var GroupInfo_InviteByLink: String { return self._s[3700]! } + public var MessageTimer_Custom: String { return self._s[3701]! } + public var UserInfo_NotificationsDefaultEnabled: String { return self._s[3702]! } + public var Passport_Address_TypeTemporaryRegistration: String { return self._s[3704]! } + public var Conversation_SendMessage_SetReminder: String { return self._s[3705]! } + public var VoiceOver_Chat_Selected: String { return self._s[3706]! } + public var ChatSettings_AutoDownloadUsingWiFi: String { return self._s[3707]! } + public var Channel_Username_InvalidTaken: String { return self._s[3708]! } + public var Conversation_ClousStorageInfo_Description3: String { return self._s[3709]! } + public var Wallet_WordCheck_TryAgain: String { return self._s[3710]! } + public var Wallet_Info_TransactionPendingHeader: String { return self._s[3711]! } + public var Settings_ChatBackground: String { return self._s[3712]! } + public var Channel_Subscribers_Title: String { return self._s[3713]! } + public var Wallet_Receive_InvoiceUrlHeader: String { return self._s[3714]! } + public var ApplyLanguage_ChangeLanguageTitle: String { return self._s[3715]! } + public var Watch_ConnectionDescription: String { return self._s[3716]! } + public var OldChannels_NoticeText: String { return self._s[3719]! } + public var Wallet_Configuration_ApplyErrorTitle: String { return self._s[3720]! } + public var IntentsSettings_SuggestBy: String { return self._s[3722]! } + public var Theme_ThemeChangedText: String { return self._s[3723]! } + public var ChatList_ArchivedChatsTitle: String { return self._s[3724]! } + public var Wallpaper_ResetWallpapers: String { return self._s[3725]! } + public var Wallet_Send_TransactionInProgress: String { return self._s[3726]! } + public var EditProfile_Title: String { return self._s[3727]! } + public var NotificationsSound_Bamboo: String { return self._s[3729]! } + public var Channel_AdminLog_MessagePreviousMessage: String { return self._s[3731]! } + public var Login_SmsRequestState2: String { return self._s[3732]! } + public var Passport_Language_ar: String { return self._s[3733]! } public func Message_AuthorPinnedGame(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3733]!, self._r[3733]!, [_0]) + return formatWithArgumentRanges(self._s[3734]!, self._r[3734]!, [_0]) } - public var SettingsSearch_Synonyms_EditProfile_Title: String { return self._s[3734]! } - public var Wallet_Created_Text: String { return self._s[3735]! } - public var Conversation_MessageDialogEdit: String { return self._s[3737]! } - public var Wallet_Created_Proceed: String { return self._s[3738]! } - public var Wallet_Words_Done: String { return self._s[3739]! } - public var VoiceOver_Media_PlaybackPause: String { return self._s[3740]! } + public var SettingsSearch_Synonyms_EditProfile_Title: String { return self._s[3735]! } + public var Wallet_Created_Text: String { return self._s[3736]! } + public var Conversation_MessageDialogEdit: String { return self._s[3738]! } + public var Wallet_Created_Proceed: String { return self._s[3739]! } + public var Wallet_Words_Done: String { return self._s[3740]! } + public var VoiceOver_Media_PlaybackPause: String { return self._s[3741]! } public func PUSH_AUTH_UNKNOWN(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3741]!, self._r[3741]!, [_1]) + return formatWithArgumentRanges(self._s[3742]!, self._r[3742]!, [_1]) } - public var Common_Close: String { return self._s[3742]! } - public var GroupInfo_PublicLink: String { return self._s[3743]! } - public var Channel_OwnershipTransfer_ErrorPrivacyRestricted: String { return self._s[3744]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsPreview: String { return self._s[3745]! } + public var Common_Close: String { return self._s[3743]! } + public var GroupInfo_PublicLink: String { return self._s[3744]! } + public var Channel_OwnershipTransfer_ErrorPrivacyRestricted: String { return self._s[3745]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsPreview: String { return self._s[3746]! } public func Channel_AdminLog_MessageToggleInvitesOff(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3749]!, self._r[3749]!, [_0]) + return formatWithArgumentRanges(self._s[3750]!, self._r[3750]!, [_0]) } - public var UserInfo_About_Placeholder: String { return self._s[3750]! } + public var UserInfo_About_Placeholder: String { return self._s[3751]! } public func Conversation_FileHowToText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3751]!, self._r[3751]!, [_0]) + return formatWithArgumentRanges(self._s[3752]!, self._r[3752]!, [_0]) } - public var GroupInfo_Permissions_SectionTitle: String { return self._s[3752]! } - public var Channel_Info_Banned: String { return self._s[3754]! } + public var GroupInfo_Permissions_SectionTitle: String { return self._s[3753]! } + public var Channel_Info_Banned: String { return self._s[3755]! } public func Time_MonthOfYear_m11(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3755]!, self._r[3755]!, [_0]) + return formatWithArgumentRanges(self._s[3756]!, self._r[3756]!, [_0]) } - public var Appearance_Other: String { return self._s[3756]! } - public var Passport_Language_my: String { return self._s[3757]! } - public var Group_Setup_BasicHistoryHiddenHelp: String { return self._s[3758]! } + public var Appearance_Other: String { return self._s[3757]! } + public var Passport_Language_my: String { return self._s[3758]! } + public var Group_Setup_BasicHistoryHiddenHelp: String { return self._s[3759]! } public func Time_PreciseDate_m9(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3759]!, self._r[3759]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3760]!, self._r[3760]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_Privacy_PasscodeAndFaceId: String { return self._s[3760]! } - public var Preview_CopyAddress: String { return self._s[3761]! } + public var SettingsSearch_Synonyms_Privacy_PasscodeAndFaceId: String { return self._s[3761]! } + public var Preview_CopyAddress: String { return self._s[3762]! } public func DialogList_SinglePlayingGameSuffix(_ _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 KeyCommand_JumpToPreviousChat: String { return self._s[3763]! } - public var UserInfo_BotSettings: String { return self._s[3764]! } - public var LiveLocation_MenuStopAll: String { return self._s[3766]! } - public var Passport_PasswordCreate: String { return self._s[3767]! } - public var StickerSettings_MaskContextInfo: String { return self._s[3768]! } - public var Message_PinnedLocationMessage: String { return self._s[3769]! } - public var Map_Satellite: String { return self._s[3770]! } - public var Watch_Message_Unsupported: String { return self._s[3771]! } - public var Username_TooManyPublicUsernamesError: String { return self._s[3772]! } - public var TwoStepAuth_EnterPasswordInvalid: String { return self._s[3773]! } + public var KeyCommand_JumpToPreviousChat: String { return self._s[3764]! } + public var UserInfo_BotSettings: String { return self._s[3765]! } + public var LiveLocation_MenuStopAll: String { return self._s[3767]! } + public var Passport_PasswordCreate: String { return self._s[3768]! } + public var StickerSettings_MaskContextInfo: String { return self._s[3769]! } + public var Message_PinnedLocationMessage: String { return self._s[3770]! } + public var Map_Satellite: String { return self._s[3771]! } + public var Watch_Message_Unsupported: String { return self._s[3772]! } + public var Username_TooManyPublicUsernamesError: String { return self._s[3773]! } + public var TwoStepAuth_EnterPasswordInvalid: String { return self._s[3774]! } public func Notification_PinnedTextMessage(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3774]!, self._r[3774]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3775]!, self._r[3775]!, [_0, _1]) } public func Conversation_OpenBotLinkText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3775]!, self._r[3775]!, [_0]) + return formatWithArgumentRanges(self._s[3776]!, self._r[3776]!, [_0]) } - public var Wallet_WordImport_Continue: String { return self._s[3776]! } + public var Wallet_WordImport_Continue: String { return self._s[3777]! } public func TwoFactorSetup_EmailVerification_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3777]!, self._r[3777]!, [_0]) + return formatWithArgumentRanges(self._s[3778]!, self._r[3778]!, [_0]) } - public var Notifications_ChannelNotificationsHelp: String { return self._s[3778]! } - public var Privacy_Calls_P2PContacts: String { return self._s[3779]! } - public var NotificationsSound_None: String { return self._s[3780]! } - public var Wallet_TransactionInfo_StorageFeeHeader: String { return self._s[3781]! } - public var Channel_DiscussionGroup_UnlinkGroup: String { return self._s[3783]! } - public var AccessDenied_VoiceMicrophone: String { return self._s[3784]! } + public var Notifications_ChannelNotificationsHelp: String { return self._s[3779]! } + public var Privacy_Calls_P2PContacts: String { return self._s[3780]! } + public var NotificationsSound_None: String { return self._s[3781]! } + public var Wallet_TransactionInfo_StorageFeeHeader: String { return self._s[3782]! } + public var Channel_DiscussionGroup_UnlinkGroup: String { return self._s[3784]! } + public var AccessDenied_VoiceMicrophone: String { return self._s[3785]! } public func ApplyLanguage_ChangeLanguageAlreadyActive(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3785]!, self._r[3785]!, [_1]) + return formatWithArgumentRanges(self._s[3786]!, self._r[3786]!, [_1]) } - public var Cache_Indexing: String { return self._s[3786]! } - public var DialogList_RecentTitlePeople: String { return self._s[3788]! } - public var DialogList_EncryptionRejected: String { return self._s[3789]! } - public var GroupInfo_Administrators: String { return self._s[3790]! } - public var Passport_ScanPassportHelp: String { return self._s[3791]! } - public var Application_Name: String { return self._s[3792]! } - public var Channel_AdminLogFilter_ChannelEventsInfo: String { return self._s[3793]! } - public var Appearance_ThemeCarouselDay: String { return self._s[3795]! } - public var Passport_Identity_TranslationHelp: String { return self._s[3796]! } + public var Cache_Indexing: String { return self._s[3787]! } + public var DialogList_RecentTitlePeople: String { return self._s[3789]! } + public var DialogList_EncryptionRejected: String { return self._s[3790]! } + public var GroupInfo_Administrators: String { return self._s[3791]! } + public var Passport_ScanPassportHelp: String { return self._s[3792]! } + public var Application_Name: String { return self._s[3793]! } + public var Channel_AdminLogFilter_ChannelEventsInfo: String { return self._s[3794]! } + public var Appearance_ThemeCarouselDay: String { return self._s[3796]! } + public var Passport_Identity_TranslationHelp: String { return self._s[3797]! } public func VoiceOver_Chat_VideoMessageFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3797]!, self._r[3797]!, [_0]) - } - public func Notification_JoinedGroupByLink(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3798]!, self._r[3798]!, [_0]) } - public func DialogList_EncryptedChatStartedOutgoing(_ _0: String) -> (String, [(Int, NSRange)]) { + public func Notification_JoinedGroupByLink(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3799]!, self._r[3799]!, [_0]) } - public var Channel_EditAdmin_PermissionDeleteMessages: String { return self._s[3800]! } - public var Privacy_ChatsTitle: String { return self._s[3801]! } - public var DialogList_ClearHistoryConfirmation: String { return self._s[3802]! } - public var SettingsSearch_Synonyms_Data_Storage_ClearCache: String { return self._s[3803]! } - public var Watch_Suggestion_HoldOn: String { return self._s[3804]! } - public var Group_EditAdmin_TransferOwnership: String { return self._s[3805]! } - public var WebBrowser_Title: String { return self._s[3806]! } - public var Group_LinkedChannel: String { return self._s[3807]! } - public var VoiceOver_Chat_SeenByRecipient: String { return self._s[3808]! } - public var SocksProxySetup_RequiredCredentials: String { return self._s[3809]! } - public var Passport_Address_TypeRentalAgreementUploadScan: String { return self._s[3810]! } - public var Appearance_TextSize_UseSystem: String { return self._s[3811]! } - public var TwoStepAuth_EmailSkipAlert: String { return self._s[3812]! } - public var ScheduledMessages_RemindersTitle: String { return self._s[3814]! } - public var Channel_Setup_TypePublic: String { return self._s[3816]! } + public func DialogList_EncryptedChatStartedOutgoing(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3800]!, self._r[3800]!, [_0]) + } + public var Channel_EditAdmin_PermissionDeleteMessages: String { return self._s[3801]! } + public var Privacy_ChatsTitle: String { return self._s[3802]! } + public var DialogList_ClearHistoryConfirmation: String { return self._s[3803]! } + public var SettingsSearch_Synonyms_Data_Storage_ClearCache: String { return self._s[3804]! } + public var Watch_Suggestion_HoldOn: String { return self._s[3805]! } + public var Group_EditAdmin_TransferOwnership: String { return self._s[3806]! } + public var WebBrowser_Title: String { return self._s[3807]! } + public var Group_LinkedChannel: String { return self._s[3808]! } + public var VoiceOver_Chat_SeenByRecipient: String { return self._s[3809]! } + public var SocksProxySetup_RequiredCredentials: String { return self._s[3810]! } + public var Passport_Address_TypeRentalAgreementUploadScan: String { return self._s[3811]! } + public var Appearance_TextSize_UseSystem: String { return self._s[3812]! } + public var TwoStepAuth_EmailSkipAlert: String { return self._s[3813]! } + public var ScheduledMessages_RemindersTitle: String { return self._s[3815]! } + public var Channel_Setup_TypePublic: String { return self._s[3817]! } public func Channel_AdminLog_MessageToggleInvitesOn(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3817]!, self._r[3817]!, [_0]) + return formatWithArgumentRanges(self._s[3818]!, self._r[3818]!, [_0]) } - public var Channel_TypeSetup_Title: String { return self._s[3819]! } - public var Map_OpenInMaps: String { return self._s[3821]! } + public var Channel_TypeSetup_Title: String { return self._s[3820]! } + public var Map_OpenInMaps: String { return self._s[3822]! } public func PUSH_PINNED_NOTEXT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3822]!, self._r[3822]!, [_1]) + return formatWithArgumentRanges(self._s[3823]!, self._r[3823]!, [_1]) } - public var NotificationsSound_Tremolo: String { return self._s[3824]! } + public var NotificationsSound_Tremolo: String { return self._s[3825]! } public func Date_ChatDateHeaderYear(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3825]!, self._r[3825]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3826]!, self._r[3826]!, [_1, _2, _3]) } - public var ConversationProfile_UnknownAddMemberError: String { return self._s[3826]! } - public var Channel_OwnershipTransfer_PasswordPlaceholder: String { return self._s[3827]! } - public var Passport_PasswordHelp: String { return self._s[3828]! } - public var Login_CodeExpiredError: String { return self._s[3829]! } - public var Channel_EditAdmin_PermissionChangeInfo: String { return self._s[3830]! } - public var Conversation_TitleUnmute: String { return self._s[3831]! } - public var Passport_Identity_ScansHelp: String { return self._s[3832]! } - public var Passport_Language_lo: String { return self._s[3833]! } - public var Camera_FlashAuto: String { return self._s[3834]! } - public var Conversation_OpenBotLinkOpen: String { return self._s[3835]! } - public var Common_Cancel: String { return self._s[3836]! } - public var DialogList_SavedMessagesTooltip: String { return self._s[3837]! } - public var TwoStepAuth_SetupPasswordTitle: String { return self._s[3838]! } - public var Appearance_TintAllColors: String { return self._s[3839]! } + public var ConversationProfile_UnknownAddMemberError: String { return self._s[3827]! } + public var Channel_OwnershipTransfer_PasswordPlaceholder: String { return self._s[3828]! } + public var Passport_PasswordHelp: String { return self._s[3829]! } + public var Login_CodeExpiredError: String { return self._s[3830]! } + public var Channel_EditAdmin_PermissionChangeInfo: String { return self._s[3831]! } + public var Conversation_TitleUnmute: String { return self._s[3832]! } + public var Passport_Identity_ScansHelp: String { return self._s[3833]! } + public var Passport_Language_lo: String { return self._s[3834]! } + public var Camera_FlashAuto: String { return self._s[3835]! } + public var Conversation_OpenBotLinkOpen: String { return self._s[3836]! } + public var Common_Cancel: String { return self._s[3837]! } + public var DialogList_SavedMessagesTooltip: String { return self._s[3838]! } + public var TwoStepAuth_SetupPasswordTitle: String { return self._s[3839]! } + public var Appearance_TintAllColors: String { return self._s[3840]! } public func PUSH_MESSAGE_FWD(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3840]!, self._r[3840]!, [_1]) + return formatWithArgumentRanges(self._s[3841]!, self._r[3841]!, [_1]) } - public var Conversation_ReportSpamConfirmation: String { return self._s[3841]! } - public var ChatSettings_Title: String { return self._s[3843]! } - public var Passport_PasswordReset: String { return self._s[3844]! } - public var SocksProxySetup_TypeNone: String { return self._s[3845]! } - public var EditTheme_Title: String { return self._s[3847]! } - public var PhoneNumberHelp_Help: String { return self._s[3848]! } - public var Checkout_EnterPassword: String { return self._s[3849]! } - public var Share_AuthTitle: String { return self._s[3851]! } - public var Activity_UploadingDocument: String { return self._s[3852]! } - public var State_Connecting: String { return self._s[3853]! } - public var Profile_MessageLifetime1w: String { return self._s[3854]! } - public var Conversation_ContextMenuReport: String { return self._s[3855]! } - public var CheckoutInfo_ReceiverInfoPhone: String { return self._s[3856]! } - public var AutoNightTheme_ScheduledTo: String { return self._s[3857]! } + public var Conversation_ReportSpamConfirmation: String { return self._s[3842]! } + public var ChatSettings_Title: String { return self._s[3844]! } + public var Passport_PasswordReset: String { return self._s[3845]! } + public var SocksProxySetup_TypeNone: String { return self._s[3846]! } + public var EditTheme_Title: String { return self._s[3848]! } + public var PhoneNumberHelp_Help: String { return self._s[3849]! } + public var Checkout_EnterPassword: String { return self._s[3850]! } + public var Share_AuthTitle: String { return self._s[3852]! } + public var Activity_UploadingDocument: String { return self._s[3853]! } + public var State_Connecting: String { return self._s[3854]! } + public var Profile_MessageLifetime1w: String { return self._s[3855]! } + public var Conversation_ContextMenuReport: String { return self._s[3856]! } + public var CheckoutInfo_ReceiverInfoPhone: String { return self._s[3857]! } + public var AutoNightTheme_ScheduledTo: String { return self._s[3858]! } public func VoiceOver_Chat_AnonymousPollFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3858]!, self._r[3858]!, [_0]) + return formatWithArgumentRanges(self._s[3859]!, self._r[3859]!, [_0]) } - public var AuthSessions_Terminate: String { return self._s[3859]! } - public var Wallet_WordImport_CanNotRemember: String { return self._s[3860]! } - public var Checkout_NewCard_CardholderNamePlaceholder: String { return self._s[3862]! } - public var KeyCommand_JumpToPreviousUnreadChat: String { return self._s[3863]! } - public var PhotoEditor_Set: String { return self._s[3864]! } - public var EmptyGroupInfo_Title: String { return self._s[3865]! } - public var Login_PadPhoneHelp: String { return self._s[3866]! } - public var AutoDownloadSettings_TypeGroupChats: String { return self._s[3868]! } - public var PrivacyPolicy_DeclineLastWarning: String { return self._s[3870]! } - public var NotificationsSound_Complete: String { return self._s[3871]! } - public var SettingsSearch_Synonyms_Privacy_Data_Title: String { return self._s[3872]! } - public var Group_Info_AdminLog: String { return self._s[3873]! } - public var GroupPermission_NotAvailableInPublicGroups: String { return self._s[3874]! } + public var AuthSessions_Terminate: String { return self._s[3860]! } + public var Wallet_WordImport_CanNotRemember: String { return self._s[3861]! } + public var Checkout_NewCard_CardholderNamePlaceholder: String { return self._s[3863]! } + public var KeyCommand_JumpToPreviousUnreadChat: String { return self._s[3864]! } + public var PhotoEditor_Set: String { return self._s[3865]! } + public var EmptyGroupInfo_Title: String { return self._s[3866]! } + public var Login_PadPhoneHelp: String { return self._s[3867]! } + public var AutoDownloadSettings_TypeGroupChats: String { return self._s[3869]! } + public var PrivacyPolicy_DeclineLastWarning: String { return self._s[3871]! } + public var NotificationsSound_Complete: String { return self._s[3872]! } + public var SettingsSearch_Synonyms_Privacy_Data_Title: String { return self._s[3873]! } + public var Group_Info_AdminLog: String { return self._s[3874]! } + public var GroupPermission_NotAvailableInPublicGroups: String { return self._s[3875]! } public func Wallet_Time_PreciseDate_m11(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3875]!, self._r[3875]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3876]!, self._r[3876]!, [_1, _2, _3]) } - public var Channel_AdminLog_InfoPanelAlertText: String { return self._s[3876]! } - public var Group_Location_CreateInThisPlace: String { return self._s[3878]! } - public var Conversation_Admin: String { return self._s[3879]! } - public var Conversation_GifTooltip: String { return self._s[3880]! } - public var Passport_NotLoggedInMessage: String { return self._s[3881]! } + public var Channel_AdminLog_InfoPanelAlertText: String { return self._s[3877]! } + public var Group_Location_CreateInThisPlace: String { return self._s[3879]! } + public var Conversation_Admin: String { return self._s[3880]! } + public var Conversation_GifTooltip: String { return self._s[3881]! } + public var Passport_NotLoggedInMessage: String { return self._s[3882]! } public func AutoDownloadSettings_OnFor(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3883]!, self._r[3883]!, [_0]) + return formatWithArgumentRanges(self._s[3884]!, self._r[3884]!, [_0]) } - public var Profile_MessageLifetimeForever: String { return self._s[3884]! } - public var SharedMedia_EmptyTitle: String { return self._s[3886]! } - public var Channel_Edit_PrivatePublicLinkAlert: String { return self._s[3888]! } - public var Username_Help: String { return self._s[3889]! } - public var DialogList_LanguageTooltip: String { return self._s[3891]! } - public var Map_LoadError: String { return self._s[3892]! } - public var Login_PhoneNumberAlreadyAuthorized: String { return self._s[3893]! } - public var Channel_AdminLog_AddMembers: String { return self._s[3894]! } - public var ArchivedChats_IntroTitle2: String { return self._s[3895]! } - public var Notification_Exceptions_NewException: String { return self._s[3896]! } - public var TwoStepAuth_EmailTitle: String { return self._s[3897]! } - public var WatchRemote_AlertText: String { return self._s[3898]! } + public var Profile_MessageLifetimeForever: String { return self._s[3885]! } + public var SharedMedia_EmptyTitle: String { return self._s[3887]! } + public var Channel_Edit_PrivatePublicLinkAlert: String { return self._s[3889]! } + public var Username_Help: String { return self._s[3890]! } + public var DialogList_LanguageTooltip: String { return self._s[3892]! } + public var Map_LoadError: String { return self._s[3893]! } + public var Login_PhoneNumberAlreadyAuthorized: String { return self._s[3894]! } + public var Channel_AdminLog_AddMembers: String { return self._s[3895]! } + public var ArchivedChats_IntroTitle2: String { return self._s[3896]! } + public var Notification_Exceptions_NewException: String { return self._s[3897]! } + public var TwoStepAuth_EmailTitle: String { return self._s[3898]! } + public var WatchRemote_AlertText: String { return self._s[3899]! } public func Wallet_Send_ConfirmationText(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3899]!, self._r[3899]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3900]!, self._r[3900]!, [_1, _2, _3]) } - public var ChatSettings_ConnectionType_Title: String { return self._s[3903]! } - public var WebBrowser_DefaultBrowser: String { return self._s[3904]! } + public var ChatSettings_ConnectionType_Title: String { return self._s[3904]! } + public var WebBrowser_DefaultBrowser: String { return self._s[3905]! } public func Settings_CheckPhoneNumberTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3905]!, self._r[3905]!, [_0]) + return formatWithArgumentRanges(self._s[3906]!, self._r[3906]!, [_0]) } - public var SettingsSearch_Synonyms_Calls_CallTab: String { return self._s[3906]! } - public var Passport_Address_CountryPlaceholder: String { return self._s[3907]! } + public var SettingsSearch_Synonyms_Calls_CallTab: String { return self._s[3907]! } + public var Passport_Address_CountryPlaceholder: String { return self._s[3908]! } public func DialogList_AwaitingEncryption(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3908]!, self._r[3908]!, [_0]) + return formatWithArgumentRanges(self._s[3909]!, self._r[3909]!, [_0]) } public func Time_PreciseDate_m6(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3909]!, self._r[3909]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3910]!, self._r[3910]!, [_1, _2, _3]) } - public var Group_AdminLog_EmptyText: String { return self._s[3910]! } - public var SettingsSearch_Synonyms_Appearance_Title: String { return self._s[3911]! } - public var Conversation_PrivateChannelTooltip: String { return self._s[3913]! } - public var Wallet_Created_ExportErrorText: String { return self._s[3914]! } - public var ChatList_UndoArchiveText1: String { return self._s[3915]! } - public var AccessDenied_VideoMicrophone: String { return self._s[3916]! } - public var Conversation_ContextMenuStickerPackAdd: String { return self._s[3917]! } - public var Cache_ClearNone: String { return self._s[3918]! } - public var SocksProxySetup_FailedToConnect: String { return self._s[3919]! } - public var Permissions_NotificationsTitle_v0: String { return self._s[3920]! } + public var Group_AdminLog_EmptyText: String { return self._s[3911]! } + public var SettingsSearch_Synonyms_Appearance_Title: String { return self._s[3912]! } + public var Conversation_PrivateChannelTooltip: String { return self._s[3914]! } + public var Wallet_Created_ExportErrorText: String { return self._s[3915]! } + public var ChatList_UndoArchiveText1: String { return self._s[3916]! } + public var AccessDenied_VideoMicrophone: String { return self._s[3917]! } + public var Conversation_ContextMenuStickerPackAdd: String { return self._s[3918]! } + public var Cache_ClearNone: String { return self._s[3919]! } + public var SocksProxySetup_FailedToConnect: String { return self._s[3920]! } + public var Permissions_NotificationsTitle_v0: String { return self._s[3921]! } public func Channel_AdminLog_MessageEdited(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3921]!, self._r[3921]!, [_0]) + return formatWithArgumentRanges(self._s[3922]!, self._r[3922]!, [_0]) } - public var Passport_Identity_Country: String { return self._s[3922]! } + public var Passport_Identity_Country: String { return self._s[3923]! } public func ChatSettings_AutoDownloadSettings_TypeFile(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3923]!, self._r[3923]!, [_0]) - } - public func Notification_CreatedChat(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3924]!, self._r[3924]!, [_0]) } - public var Exceptions_AddToExceptions: String { return self._s[3925]! } - public var AccessDenied_Settings: String { return self._s[3926]! } - public var Passport_Address_TypeUtilityBillUploadScan: String { return self._s[3927]! } - public var Month_ShortMay: String { return self._s[3928]! } - public var Compose_NewGroup: String { return self._s[3930]! } - public var Group_Setup_TypePrivate: String { return self._s[3932]! } - public var Login_PadPhoneHelpTitle: String { return self._s[3934]! } - public var Appearance_ThemeDayClassic: String { return self._s[3935]! } - public var Channel_AdminLog_MessagePreviousCaption: String { return self._s[3936]! } - public var AutoDownloadSettings_OffForAll: String { return self._s[3937]! } - public var Privacy_GroupsAndChannels_WhoCanAddMe: String { return self._s[3938]! } - public var Conversation_typing: String { return self._s[3940]! } - public var Undo_ScheduledMessagesCleared: String { return self._s[3941]! } - public var Paint_Masks: String { return self._s[3942]! } - public var Contacts_DeselectAll: String { return self._s[3943]! } - public func Wallet_Updated_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3944]!, self._r[3944]!, [_0]) + public func Notification_CreatedChat(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3925]!, self._r[3925]!, [_0]) } - public var Username_InvalidTaken: String { return self._s[3945]! } - public var Call_StatusNoAnswer: String { return self._s[3946]! } - public var TwoStepAuth_EmailAddSuccess: String { return self._s[3947]! } - public var SettingsSearch_Synonyms_Privacy_BlockedUsers: String { return self._s[3948]! } - public var Passport_Identity_Selfie: String { return self._s[3949]! } - public var Login_InfoLastNamePlaceholder: String { return self._s[3950]! } - public var Privacy_SecretChatsLinkPreviewsHelp: String { return self._s[3951]! } - public var Conversation_ClearSecretHistory: String { return self._s[3952]! } - public var PeopleNearby_Description: String { return self._s[3954]! } - public var NetworkUsageSettings_Title: String { return self._s[3955]! } - public var Your_cards_security_code_is_invalid: String { return self._s[3957]! } + public var Exceptions_AddToExceptions: String { return self._s[3926]! } + public var AccessDenied_Settings: String { return self._s[3927]! } + public var Passport_Address_TypeUtilityBillUploadScan: String { return self._s[3928]! } + public var Month_ShortMay: String { return self._s[3929]! } + public var Compose_NewGroup: String { return self._s[3931]! } + public var Group_Setup_TypePrivate: String { return self._s[3933]! } + public var Login_PadPhoneHelpTitle: String { return self._s[3935]! } + public var Appearance_ThemeDayClassic: String { return self._s[3936]! } + public var Channel_AdminLog_MessagePreviousCaption: String { return self._s[3937]! } + public var AutoDownloadSettings_OffForAll: String { return self._s[3938]! } + public var Privacy_GroupsAndChannels_WhoCanAddMe: String { return self._s[3939]! } + public var Conversation_typing: String { return self._s[3941]! } + public var Undo_ScheduledMessagesCleared: String { return self._s[3942]! } + public var Paint_Masks: String { return self._s[3943]! } + public var Contacts_DeselectAll: String { return self._s[3944]! } + public func Wallet_Updated_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3945]!, self._r[3945]!, [_0]) + } + public var Username_InvalidTaken: String { return self._s[3946]! } + public var Call_StatusNoAnswer: String { return self._s[3947]! } + public var TwoStepAuth_EmailAddSuccess: String { return self._s[3948]! } + public var SettingsSearch_Synonyms_Privacy_BlockedUsers: String { return self._s[3949]! } + public var Passport_Identity_Selfie: String { return self._s[3950]! } + public var Login_InfoLastNamePlaceholder: String { return self._s[3951]! } + public var Privacy_SecretChatsLinkPreviewsHelp: String { return self._s[3952]! } + public var Conversation_ClearSecretHistory: String { return self._s[3953]! } + public var PeopleNearby_Description: String { return self._s[3955]! } + public var NetworkUsageSettings_Title: String { return self._s[3956]! } + public var Your_cards_security_code_is_invalid: String { return self._s[3958]! } public func Notification_LeftChannel(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3959]!, self._r[3959]!, [_0]) + return formatWithArgumentRanges(self._s[3960]!, self._r[3960]!, [_0]) } public func Call_CallInProgressMessage(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3960]!, self._r[3960]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3961]!, self._r[3961]!, [_1, _2]) } - public var SaveIncomingPhotosSettings_From: String { return self._s[3962]! } - public var VoiceOver_Navigation_Search: String { return self._s[3963]! } - public var Map_LiveLocationTitle: String { return self._s[3964]! } - public var Login_InfoAvatarAdd: String { return self._s[3965]! } - public var Passport_Identity_FilesView: String { return self._s[3966]! } - public var UserInfo_GenericPhoneLabel: String { return self._s[3967]! } - public var Privacy_Calls_NeverAllow: String { return self._s[3968]! } - public var VoiceOver_Chat_File: String { return self._s[3969]! } - public var Wallet_Settings_DeleteWalletInfo: String { return self._s[3970]! } + public var SaveIncomingPhotosSettings_From: String { return self._s[3963]! } + public var VoiceOver_Navigation_Search: String { return self._s[3964]! } + public var Map_LiveLocationTitle: String { return self._s[3965]! } + public var Login_InfoAvatarAdd: String { return self._s[3966]! } + public var Passport_Identity_FilesView: String { return self._s[3967]! } + public var UserInfo_GenericPhoneLabel: String { return self._s[3968]! } + public var Privacy_Calls_NeverAllow: String { return self._s[3969]! } + public var VoiceOver_Chat_File: String { return self._s[3970]! } + public var Wallet_Settings_DeleteWalletInfo: String { return self._s[3971]! } public func Contacts_AddPhoneNumber(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3971]!, self._r[3971]!, [_0]) + return formatWithArgumentRanges(self._s[3972]!, self._r[3972]!, [_0]) } - public var ContactInfo_PhoneNumberHidden: String { return self._s[3972]! } - public var TwoStepAuth_ConfirmationText: String { return self._s[3973]! } - public var ChatSettings_AutomaticVideoMessageDownload: String { return self._s[3974]! } + public var ContactInfo_PhoneNumberHidden: String { return self._s[3973]! } + public var TwoStepAuth_ConfirmationText: String { return self._s[3974]! } + public var ChatSettings_AutomaticVideoMessageDownload: String { return self._s[3975]! } public func PUSH_CHAT_MESSAGE_VIDEOS(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3975]!, self._r[3975]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3976]!, self._r[3976]!, [_1, _2, _3]) } - public var Channel_AdminLogFilter_AdminsAll: String { return self._s[3976]! } - public var Wallet_Intro_CreateErrorText: String { return self._s[3977]! } - public var Tour_Title2: String { return self._s[3978]! } - public var Wallet_Sent_ViewWallet: String { return self._s[3979]! } - public var Conversation_FileOpenIn: String { return self._s[3980]! } - public var Checkout_ErrorPrecheckoutFailed: String { return self._s[3981]! } - public var Wallet_Send_ErrorInvalidAddress: String { return self._s[3982]! } - public var Wallpaper_Set: String { return self._s[3983]! } - public var Passport_Identity_Translations: String { return self._s[3985]! } + public var Channel_AdminLogFilter_AdminsAll: String { return self._s[3977]! } + public var Wallet_Intro_CreateErrorText: String { return self._s[3978]! } + public var Tour_Title2: String { return self._s[3979]! } + public var Wallet_Sent_ViewWallet: String { return self._s[3980]! } + public var Conversation_FileOpenIn: String { return self._s[3981]! } + public var Checkout_ErrorPrecheckoutFailed: String { return self._s[3982]! } + public var Wallet_Send_ErrorInvalidAddress: String { return self._s[3983]! } + public var Wallpaper_Set: String { return self._s[3984]! } + public var Passport_Identity_Translations: String { return self._s[3986]! } public func Channel_AdminLog_MessageChangedChannelAbout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3986]!, self._r[3986]!, [_0]) + return formatWithArgumentRanges(self._s[3987]!, self._r[3987]!, [_0]) } - public var Channel_LeaveChannel: String { return self._s[3987]! } + public var Channel_LeaveChannel: String { return self._s[3988]! } public func PINNED_INVOICE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3988]!, self._r[3988]!, [_1]) + return formatWithArgumentRanges(self._s[3989]!, self._r[3989]!, [_1]) } - public var SettingsSearch_Synonyms_Proxy_AddProxy: String { return self._s[3990]! } - public var PhotoEditor_HighlightsTint: String { return self._s[3991]! } - public var Passport_Email_Delete: String { return self._s[3992]! } - public var Conversation_Mute: String { return self._s[3994]! } - public var Channel_AddBotAsAdmin: String { return self._s[3995]! } - public var Channel_AdminLog_CanSendMessages: String { return self._s[3997]! } - public var Wallet_Configuration_BlockchainNameChangedText: String { return self._s[3998]! } - public var ChatSettings_IntentsSettings: String { return self._s[4000]! } - public var Channel_Management_LabelOwner: String { return self._s[4001]! } + public var SettingsSearch_Synonyms_Proxy_AddProxy: String { return self._s[3991]! } + public var PhotoEditor_HighlightsTint: String { return self._s[3992]! } + public var Passport_Email_Delete: String { return self._s[3993]! } + public var Conversation_Mute: String { return self._s[3995]! } + public var Channel_AddBotAsAdmin: String { return self._s[3996]! } + public var Channel_AdminLog_CanSendMessages: String { return self._s[3998]! } + public var Wallet_Configuration_BlockchainNameChangedText: String { return self._s[3999]! } + public var ChatSettings_IntentsSettings: String { return self._s[4001]! } + public var Channel_Management_LabelOwner: String { return self._s[4002]! } public func Notification_PassportValuesSentMessage(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4002]!, self._r[4002]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4003]!, self._r[4003]!, [_1, _2]) } - public var Calls_CallTabDescription: String { return self._s[4003]! } - public var Passport_Identity_NativeNameHelp: String { return self._s[4004]! } - public var Common_No: String { return self._s[4005]! } - public var Weekday_Sunday: String { return self._s[4006]! } - public var Notification_Reply: String { return self._s[4007]! } - public var Conversation_ViewMessage: String { return self._s[4008]! } + public var Calls_CallTabDescription: String { return self._s[4004]! } + public var Passport_Identity_NativeNameHelp: String { return self._s[4005]! } + public var Common_No: String { return self._s[4006]! } + public var Weekday_Sunday: String { return self._s[4007]! } + public var Notification_Reply: String { return self._s[4008]! } + public var Conversation_ViewMessage: String { return self._s[4009]! } public func Checkout_SavePasswordTimeoutAndFaceId(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4009]!, self._r[4009]!, [_0]) - } - public func Map_LiveLocationPrivateDescription(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[4010]!, self._r[4010]!, [_0]) } + public func Map_LiveLocationPrivateDescription(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[4011]!, self._r[4011]!, [_0]) + } public func Wallet_Time_PreciseDate_m7(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4011]!, self._r[4011]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[4012]!, self._r[4012]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_EditProfile_AddAccount: String { return self._s[4012]! } - public var Wallet_Send_Title: String { return self._s[4013]! } - public var Message_PinnedDocumentMessage: String { return self._s[4014]! } - public var Wallet_Info_RefreshErrorText: String { return self._s[4015]! } - public var DialogList_TabTitle: String { return self._s[4017]! } - public var ChatSettings_AutoPlayTitle: String { return self._s[4018]! } - public var Passport_FieldEmail: String { return self._s[4019]! } - public var Conversation_UnpinMessageAlert: String { return self._s[4020]! } - public var Passport_Address_TypeBankStatement: String { return self._s[4021]! } - public var Wallet_SecureStorageReset_Title: String { return self._s[4022]! } - public var Passport_Identity_ExpiryDate: String { return self._s[4023]! } - public var Privacy_Calls_P2P: String { return self._s[4024]! } + public var SettingsSearch_Synonyms_EditProfile_AddAccount: String { return self._s[4013]! } + public var Wallet_Send_Title: String { return self._s[4014]! } + public var Message_PinnedDocumentMessage: String { return self._s[4015]! } + public var Wallet_Info_RefreshErrorText: String { return self._s[4016]! } + public var DialogList_TabTitle: String { return self._s[4018]! } + public var ChatSettings_AutoPlayTitle: String { return self._s[4019]! } + public var Passport_FieldEmail: String { return self._s[4020]! } + public var Conversation_UnpinMessageAlert: String { return self._s[4021]! } + public var Passport_Address_TypeBankStatement: String { return self._s[4022]! } + public var Wallet_SecureStorageReset_Title: String { return self._s[4023]! } + public var Passport_Identity_ExpiryDate: String { return self._s[4024]! } + public var Privacy_Calls_P2P: String { return self._s[4025]! } public func CancelResetAccount_Success(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4026]!, self._r[4026]!, [_0]) + return formatWithArgumentRanges(self._s[4027]!, self._r[4027]!, [_0]) } - public var SocksProxySetup_UseForCallsHelp: String { return self._s[4027]! } + public var SocksProxySetup_UseForCallsHelp: String { return self._s[4028]! } public func PUSH_CHAT_ALBUM(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4028]!, self._r[4028]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4029]!, self._r[4029]!, [_1, _2]) } - public var Stickers_ClearRecent: String { return self._s[4029]! } - public var EnterPasscode_ChangeTitle: String { return self._s[4030]! } - public var TwoFactorSetup_Email_Title: String { return self._s[4031]! } - public var Passport_InfoText: String { return self._s[4032]! } - public var Checkout_NewCard_SaveInfoEnableHelp: String { return self._s[4033]! } + public var Stickers_ClearRecent: String { return self._s[4030]! } + public var EnterPasscode_ChangeTitle: String { return self._s[4031]! } + public var TwoFactorSetup_Email_Title: String { return self._s[4032]! } + public var Passport_InfoText: String { return self._s[4033]! } + public var Checkout_NewCard_SaveInfoEnableHelp: String { return self._s[4034]! } public func Login_InvalidPhoneEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4034]!, self._r[4034]!, [_0]) + return formatWithArgumentRanges(self._s[4035]!, self._r[4035]!, [_0]) } public func Time_PreciseDate_m3(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4035]!, self._r[4035]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[4036]!, self._r[4036]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChannels: String { return self._s[4036]! } - public var ScheduledMessages_PollUnavailable: String { return self._s[4037]! } - public var VoiceOver_Navigation_Compose: String { return self._s[4038]! } - public var Passport_Identity_EditDriversLicense: String { return self._s[4039]! } - public var Conversation_TapAndHoldToRecord: String { return self._s[4041]! } - public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChats: String { return self._s[4042]! } + public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChannels: String { return self._s[4037]! } + public var ScheduledMessages_PollUnavailable: String { return self._s[4038]! } + public var VoiceOver_Navigation_Compose: String { return self._s[4039]! } + public var Passport_Identity_EditDriversLicense: String { return self._s[4040]! } + public var Conversation_TapAndHoldToRecord: String { return self._s[4042]! } + public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChats: String { return self._s[4043]! } public func Notification_CallTimeFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4043]!, self._r[4043]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4044]!, self._r[4044]!, [_1, _2]) } - public var Channel_EditAdmin_PermissionInviteViaLink: String { return self._s[4045]! } - public var ChatSettings_OpenLinksIn: String { return self._s[4046]! } - public var Map_HomeAndWorkTitle: String { return self._s[4047]! } + public var Channel_EditAdmin_PermissionInviteViaLink: String { return self._s[4046]! } + public var ChatSettings_OpenLinksIn: String { return self._s[4047]! } + public var Map_HomeAndWorkTitle: String { return self._s[4048]! } public func Generic_OpenHiddenLinkAlert(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4049]!, self._r[4049]!, [_0]) + return formatWithArgumentRanges(self._s[4050]!, self._r[4050]!, [_0]) } - public var DialogList_Unread: String { return self._s[4050]! } + public var DialogList_Unread: String { return self._s[4051]! } public func PUSH_CHAT_MESSAGE_GIF(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4051]!, self._r[4051]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4052]!, self._r[4052]!, [_1, _2]) } - public var User_DeletedAccount: String { return self._s[4052]! } - public var OwnershipTransfer_SetupTwoStepAuth: String { return self._s[4053]! } + public var User_DeletedAccount: String { return self._s[4053]! } + public var OwnershipTransfer_SetupTwoStepAuth: String { return self._s[4054]! } public func Watch_Time_ShortYesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4054]!, self._r[4054]!, [_0]) + return formatWithArgumentRanges(self._s[4055]!, self._r[4055]!, [_0]) } - public var UserInfo_NotificationsDefault: String { return self._s[4055]! } - public var SharedMedia_CategoryMedia: String { return self._s[4056]! } - public var SocksProxySetup_ProxyStatusUnavailable: String { return self._s[4057]! } - public var Channel_AdminLog_MessageRestrictedForever: String { return self._s[4058]! } - public var Watch_ChatList_Compose: String { return self._s[4059]! } - public var Notifications_MessageNotificationsExceptionsHelp: String { return self._s[4060]! } - public var AutoDownloadSettings_Delimeter: String { return self._s[4061]! } - public var Watch_Microphone_Access: String { return self._s[4062]! } - public var Group_Setup_HistoryHeader: String { return self._s[4063]! } - public var Map_SetThisLocation: String { return self._s[4064]! } - public var Appearance_ThemePreview_Chat_2_ReplyName: String { return self._s[4065]! } - public var Activity_UploadingPhoto: String { return self._s[4066]! } - public var Conversation_Edit: String { return self._s[4068]! } - public var Group_ErrorSendRestrictedMedia: String { return self._s[4069]! } - public var Login_TermsOfServiceDecline: String { return self._s[4070]! } - public var Message_PinnedContactMessage: String { return self._s[4071]! } + public var UserInfo_NotificationsDefault: String { return self._s[4056]! } + public var SharedMedia_CategoryMedia: String { return self._s[4057]! } + public var SocksProxySetup_ProxyStatusUnavailable: String { return self._s[4058]! } + public var Channel_AdminLog_MessageRestrictedForever: String { return self._s[4059]! } + public var Watch_ChatList_Compose: String { return self._s[4060]! } + public var Notifications_MessageNotificationsExceptionsHelp: String { return self._s[4061]! } + public var AutoDownloadSettings_Delimeter: String { return self._s[4062]! } + public var Watch_Microphone_Access: String { return self._s[4063]! } + public var Group_Setup_HistoryHeader: String { return self._s[4064]! } + public var Map_SetThisLocation: String { return self._s[4065]! } + public var Appearance_ThemePreview_Chat_2_ReplyName: String { return self._s[4066]! } + public var Activity_UploadingPhoto: String { return self._s[4067]! } + public var Conversation_Edit: String { return self._s[4069]! } + public var Group_ErrorSendRestrictedMedia: String { return self._s[4070]! } + public var Login_TermsOfServiceDecline: String { return self._s[4071]! } + public var Message_PinnedContactMessage: String { return self._s[4072]! } public func Channel_AdminLog_MessageRestrictedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4072]!, self._r[4072]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4073]!, self._r[4073]!, [_1, _2]) } public func Login_PhoneBannedEmailBody(_ _1: String, _ _2: String, _ _3: String, _ _4: String, _ _5: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4073]!, self._r[4073]!, [_1, _2, _3, _4, _5]) + return formatWithArgumentRanges(self._s[4074]!, self._r[4074]!, [_1, _2, _3, _4, _5]) } - public var Appearance_LargeEmoji: String { return self._s[4074]! } - public var TwoStepAuth_AdditionalPassword: String { return self._s[4076]! } - public var EditTheme_Edit_Preview_IncomingReplyText: String { return self._s[4077]! } + public var Appearance_LargeEmoji: String { return self._s[4075]! } + public var TwoStepAuth_AdditionalPassword: String { return self._s[4077]! } + public var EditTheme_Edit_Preview_IncomingReplyText: String { return self._s[4078]! } public func PUSH_CHAT_DELETE_YOU(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4078]!, self._r[4078]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4079]!, self._r[4079]!, [_1, _2]) } - public var Passport_Phone_EnterOtherNumber: String { return self._s[4079]! } - public var Message_PinnedPhotoMessage: String { return self._s[4080]! } - public var Passport_FieldPhone: String { return self._s[4081]! } - public var TwoStepAuth_RecoveryEmailAddDescription: String { return self._s[4082]! } - public var ChatSettings_AutoPlayGifs: String { return self._s[4083]! } - public var InfoPlist_NSCameraUsageDescription: String { return self._s[4085]! } - public var Conversation_Call: String { return self._s[4086]! } - public var Common_TakePhoto: String { return self._s[4088]! } - public var Group_EditAdmin_RankTitle: String { return self._s[4089]! } - public var Wallet_Receive_CommentHeader: String { return self._s[4090]! } - public var Channel_NotificationLoading: String { return self._s[4091]! } + public var Passport_Phone_EnterOtherNumber: String { return self._s[4080]! } + public var Message_PinnedPhotoMessage: String { return self._s[4081]! } + public var Passport_FieldPhone: String { return self._s[4082]! } + public var TwoStepAuth_RecoveryEmailAddDescription: String { return self._s[4083]! } + public var ChatSettings_AutoPlayGifs: String { return self._s[4084]! } + public var InfoPlist_NSCameraUsageDescription: String { return self._s[4086]! } + public var Conversation_Call: String { return self._s[4087]! } + public var Common_TakePhoto: String { return self._s[4089]! } + public var Group_EditAdmin_RankTitle: String { return self._s[4090]! } + public var Wallet_Receive_CommentHeader: String { return self._s[4091]! } + public var Channel_NotificationLoading: String { return self._s[4092]! } public func Notification_Exceptions_Sound(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4092]!, self._r[4092]!, [_0]) - } - public func ScheduledMessages_ScheduledDate(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[4093]!, self._r[4093]!, [_0]) } + public func ScheduledMessages_ScheduledDate(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[4094]!, self._r[4094]!, [_0]) + } public func PUSH_CHANNEL_MESSAGE_VIDEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4094]!, self._r[4094]!, [_1]) + return formatWithArgumentRanges(self._s[4095]!, self._r[4095]!, [_1]) } - public var Permissions_SiriTitle_v0: String { return self._s[4095]! } + public var Permissions_SiriTitle_v0: String { return self._s[4096]! } public func VoiceOver_Chat_VoiceMessageFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4096]!, self._r[4096]!, [_0]) - } - public func Login_ResetAccountProtected_Text(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[4097]!, self._r[4097]!, [_0]) } - public var Channel_MessagePhotoRemoved: String { return self._s[4098]! } - public var Wallet_Info_ReceiveGrams: String { return self._s[4099]! } - public var ClearCache_FreeSpace: String { return self._s[4100]! } - public var Common_edit: String { return self._s[4101]! } - public var PrivacySettings_AuthSessions: String { return self._s[4102]! } - public var Month_ShortJune: String { return self._s[4103]! } - public var PrivacyLastSeenSettings_AlwaysShareWith_Placeholder: String { return self._s[4104]! } - public var Call_ReportSend: String { return self._s[4105]! } - public var Watch_LastSeen_JustNow: String { return self._s[4106]! } - public var Notifications_MessageNotifications: String { return self._s[4107]! } - public var WallpaperSearch_ColorGreen: String { return self._s[4108]! } - public var BroadcastListInfo_AddRecipient: String { return self._s[4110]! } - public var Group_Status: String { return self._s[4111]! } + public func Login_ResetAccountProtected_Text(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[4098]!, self._r[4098]!, [_0]) + } + public var Channel_MessagePhotoRemoved: String { return self._s[4099]! } + public var Wallet_Info_ReceiveGrams: String { return self._s[4100]! } + public var ClearCache_FreeSpace: String { return self._s[4101]! } + public var Common_edit: String { return self._s[4102]! } + public var PrivacySettings_AuthSessions: String { return self._s[4103]! } + public var Month_ShortJune: String { return self._s[4104]! } + public var PrivacyLastSeenSettings_AlwaysShareWith_Placeholder: String { return self._s[4105]! } + public var Call_ReportSend: String { return self._s[4106]! } + public var Watch_LastSeen_JustNow: String { return self._s[4107]! } + public var Notifications_MessageNotifications: String { return self._s[4108]! } + public var WallpaperSearch_ColorGreen: String { return self._s[4109]! } + public var BroadcastListInfo_AddRecipient: String { return self._s[4111]! } + public var Group_Status: String { return self._s[4112]! } public func AutoNightTheme_LocationHelp(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4112]!, self._r[4112]!, [_0, _1]) + return formatWithArgumentRanges(self._s[4113]!, self._r[4113]!, [_0, _1]) } - public var TextFormat_AddLinkTitle: String { return self._s[4113]! } - public var ShareMenu_ShareTo: String { return self._s[4114]! } - public var Conversation_Moderate_Ban: String { return self._s[4115]! } + public var TextFormat_AddLinkTitle: String { return self._s[4114]! } + public var ShareMenu_ShareTo: String { return self._s[4115]! } + public var Conversation_Moderate_Ban: String { return self._s[4116]! } public func Conversation_DeleteMessagesFor(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4116]!, self._r[4116]!, [_0]) + return formatWithArgumentRanges(self._s[4117]!, self._r[4117]!, [_0]) } - public var SharedMedia_ViewInChat: String { return self._s[4117]! } - public var Map_LiveLocationFor8Hours: String { return self._s[4118]! } + public var SharedMedia_ViewInChat: String { return self._s[4118]! } + public var Map_LiveLocationFor8Hours: String { return self._s[4119]! } public func PUSH_PINNED_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4119]!, self._r[4119]!, [_1]) + return formatWithArgumentRanges(self._s[4120]!, self._r[4120]!, [_1]) } public func PUSH_PINNED_POLL(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4120]!, self._r[4120]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4121]!, self._r[4121]!, [_1, _2]) } public func Map_AccurateTo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4122]!, self._r[4122]!, [_0]) + return formatWithArgumentRanges(self._s[4123]!, self._r[4123]!, [_0]) } - public var Map_OpenInHereMaps: String { return self._s[4123]! } - public var Appearance_ReduceMotion: String { return self._s[4124]! } + public var Map_OpenInHereMaps: String { return self._s[4124]! } + public var Appearance_ReduceMotion: String { return self._s[4125]! } public func PUSH_MESSAGE_TEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4125]!, self._r[4125]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4126]!, self._r[4126]!, [_1, _2]) } - public var Channel_Setup_TypePublicHelp: String { return self._s[4126]! } - public var Passport_Identity_EditInternalPassport: String { return self._s[4127]! } - public var PhotoEditor_Skip: String { return self._s[4128]! } - public func Conversation_StatusMembers(_ value: Int32) -> String { + public var Channel_Setup_TypePublicHelp: String { return self._s[4127]! } + public var Passport_Identity_EditInternalPassport: String { return self._s[4128]! } + public var PhotoEditor_Skip: String { return self._s[4129]! } + public func StickerPack_AddMaskCount(_ 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 PUSH_CHAT_MESSAGES(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, _2, _1, _3) + public func ForwardedVideos(_ 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 MessageTimer_ShortHours(_ value: Int32) -> String { + public func Media_SharePhoto(_ 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_Seconds(_ 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[3 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_ShortDays(_ 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[4 * 6 + Int(form.rawValue)]!, stringValue) } - public func MuteExpires_Hours(_ value: Int32) -> String { + public func SharedMedia_Generic(_ 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 Contacts_ImportersCount(_ 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_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[6 * 6 + Int(form.rawValue)]!, _1, _2) } - public func SharedMedia_DeleteItemsConfirmation(_ 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[7 * 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[8 * 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[8 * 6 + Int(form.rawValue)]!, _1, _2) } - public func Forward_ConfirmMultipleFiles(_ 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[9 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedGifs(_ 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[10 * 6 + Int(form.rawValue)]!, stringValue) } - public func Notification_GameScoreExtended(_ 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[11 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_Weeks(_ 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[12 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_Hours(_ 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[13 * 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[14 * 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 Notification_GameScoreSimple(_ 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[15 * 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[16 * 6 + Int(form.rawValue)]!, _2, _1, _3) + public func OldChannels_Leave(_ 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 PUSH_CHANNEL_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + public func PUSH_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { let form = getPluralizationForm(self.lc, selector) return String(format: self._ps[17 * 6 + Int(form.rawValue)]!, _1, _2) } - public func MuteFor_Hours(_ 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[18 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_ShortSeconds(_ 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[19 * 6 + Int(form.rawValue)]!, stringValue) } - public func AttachmentMenu_SendItem(_ value: Int32) -> String { + public func LiveLocation_MenuChatsCount(_ 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) @@ -4766,382 +4766,382 @@ public final class PresentationStrings: Equatable { let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[21 * 6 + Int(form.rawValue)]!, stringValue) } - public func AttachmentMenu_SendPhoto(_ 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[22 * 6 + Int(form.rawValue)]!, stringValue) } - public func PUSH_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + public func PUSH_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { let form = getPluralizationForm(self.lc, selector) return String(format: self._ps[23 * 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[24 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + public func PUSH_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[25 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func ServiceMessage_GameScoreExtended(_ 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 SharedMedia_Generic(_ 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 ServiceMessage_GameScoreSimple(_ 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 StickerPack_StickerCount(_ 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 LastSeen_MinutesAgo(_ 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 GroupInfo_ShowMoreMembers(_ 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 PUSH_CHANNEL_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[33 * 6 + Int(form.rawValue)]!, _1, _2) - } - 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[34 * 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[35 * 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[36 * 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[37 * 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[38 * 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[39 * 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[40 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[24 * 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[41 * 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[42 * 6 + Int(form.rawValue)]!, _0, _1) - } - public func QuickSend_Photos(_ 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 Watch_LastSeen_HoursAgo(_ 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_LastSeen_MinutesAgo(_ 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_SharePhoto(_ 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 ServiceMessage_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 PrivacyLastSeenSettings_AddUsers(_ 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 ChatList_DeletedChats(_ 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 AttachmentMenu_SendGif(_ 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 ForwardedPolls(_ 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 PUSH_CHAT_MESSAGE_VIDEOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[52 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func MessagePoll_VotedCount(_ 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 PUSH_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[54 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func ForwardedLocations(_ 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 Conversation_StatusSubscribers(_ 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_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[57 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func LiveLocationUpdated_MinutesAgo(_ 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 Invitation_Members(_ 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 Conversation_SelectedMessages(_ 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 MessageTimer_Minutes(_ 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 Wallpaper_DeleteConfirmation(_ 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 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 SharedMedia_Link(_ 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 SharedMedia_Video(_ 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 ForwardedAudios(_ 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 Watch_UserInfo_Mute(_ 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 ForwardedMessages(_ 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 ForwardedVideos(_ 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_CHANNEL_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[70 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func Call_Seconds(_ 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 Contacts_InviteContacts(_ 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_SelectedChats(_ 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 MuteExpires_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 Call_Minutes(_ 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_Months(_ 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_Years(_ 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 MuteFor_Days(_ 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 CreatePoll_AddMoreOptions(_ 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 LastSeen_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 OldChannels_InactiveYear(_ 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 Map_ETAMinutes(_ 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_CHANNEL_MESSAGES(_ 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 OldChannels_InactiveMonth(_ 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 PUSH_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[85 * 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[86 * 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[87 * 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[88 * 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[89 * 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[90 * 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[91 * 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[92 * 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[93 * 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[94 * 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[95 * 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[96 * 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[97 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[25 * 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[26 * 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[27 * 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[28 * 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[29 * 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[30 * 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[31 * 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[32 * 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[33 * 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[34 * 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[35 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func MuteFor_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 AttachmentMenu_SendPhoto(_ 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_Photo(_ 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 Invitation_Members(_ 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 Conversation_StatusSubscribers(_ 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 ForwardedGifs(_ 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 CreatePoll_AddMoreOptions(_ 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 MessageTimer_ShortSeconds(_ 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 PUSH_CHANNEL_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[44 * 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[45 * 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[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 PUSH_CHAT_MESSAGES(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[48 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func StickerPack_StickerCount(_ 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_CHAT_MESSAGE_FWDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[50 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func MessageTimer_Years(_ 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 ForwardedFiles(_ 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 Watch_LastSeen_MinutesAgo(_ 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 Map_ETAHours(_ 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 MessageTimer_ShortHours(_ 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[56 * 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[57 * 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[58 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func GroupInfo_ShowMoreMembers(_ 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 Notifications_Exceptions(_ 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 Passport_Scans(_ 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 LastSeen_HoursAgo(_ 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_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[63 * 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[64 * 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[65 * 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[66 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func UserCount(_ 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 LastSeen_MinutesAgo(_ 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 MuteExpires_Days(_ 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 ServiceMessage_GameScoreSelfSimple(_ 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 Media_ShareItem(_ 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 ForwardedPhotos(_ 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 Conversation_LiveLocationMembersCount(_ 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 VoiceOver_Chat_PollOptionCount(_ 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 Conversation_StatusMembers(_ 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 ForwardedContacts(_ 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 ServiceMessage_GameScoreSimple(_ 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 MessageTimer_Seconds(_ 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 LiveLocationUpdated_MinutesAgo(_ 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_ROUNDS(_ 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 DialogList_LiveLocationChatsCount(_ 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 OldChannels_GroupFormat(_ 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 Contacts_ImportersCount(_ 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 StickerPack_AddStickerCount(_ 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 VoiceOver_Chat_ContactEmailCount(_ 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 Notifications_ExceptionMuteExpires_Minutes(_ 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 ForwardedMessages(_ 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 ForwardedLocations(_ 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 PasscodeSettings_FailedAttempts(_ 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 MuteExpires_Minutes(_ 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 Call_ShortSeconds(_ 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 GroupInfo_ParticipantCount(_ 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 Media_ShareVideo(_ 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 Watch_UserInfo_Mute(_ 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 SharedMedia_DeleteItemsConfirmation(_ 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_Days(_ 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 OldChannels_Leave(_ 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[99 * 6 + Int(form.rawValue)]!, stringValue) @@ -5151,42 +5151,42 @@ public final class PresentationStrings: Equatable { let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[100 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_ShortMinutes(_ 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[101 * 6 + Int(form.rawValue)]!, stringValue) } - public func Theme_UsersCount(_ 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[102 * 6 + Int(form.rawValue)]!, stringValue) } - public func Notification_GameScoreSelfSimple(_ 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[103 * 6 + Int(form.rawValue)]!, stringValue) } - public func Media_ShareItem(_ 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[104 * 6 + Int(form.rawValue)]!, stringValue) } - public func StickerPack_RemoveStickerCount(_ value: Int32) -> String { + public func QuickSend_Photos(_ 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 Call_ShortMinutes(_ value: Int32) -> String { + public func Conversation_SelectedMessages(_ 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 MessageTimer_Days(_ value: Int32) -> String { + public func PrivacyLastSeenSettings_AddUsers(_ 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 ForwardedPhotos(_ 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[108 * 6 + Int(form.rawValue)]!, stringValue) @@ -5201,67 +5201,68 @@ public final class PresentationStrings: Equatable { let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[110 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedVideoMessages(_ value: Int32) -> String { + public func OldChannels_InactiveMonth(_ 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 Passport_Scans(_ value: Int32) -> String { + public func MessageTimer_ShortMinutes(_ 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_StatusOnline(_ 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[113 * 6 + Int(form.rawValue)]!, stringValue) } - public func PUSH_CHANNEL_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + public func PUSH_CHANNEL_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { let form = getPluralizationForm(self.lc, selector) return String(format: self._ps[114 * 6 + Int(form.rawValue)]!, _1, _2) } - public func StickerPack_RemoveMaskCount(_ 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[115 * 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[116 * 6 + Int(form.rawValue)]!, _2, _1, _3) + 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[116 * 6 + Int(form.rawValue)]!, stringValue) } - public func GroupInfo_ParticipantCount(_ 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[117 * 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[118 * 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[118 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_ShortWeeks(_ value: Int32) -> String { + public func SharedMedia_File(_ 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 Notifications_ExceptionMuteExpires_Minutes(_ 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[120 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedContacts(_ value: Int32) -> String { + public func MessageTimer_ShortWeeks(_ 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 ForwardedStickers(_ value: Int32) -> String { + public func MessageTimer_Hours(_ 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 UserCount(_ 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 ForwardedAuthorsOthers(_ selector: Int32, _ _0: String, _ _1: String) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[123 * 6 + Int(form.rawValue)]!, _0, _1) } public init(primaryComponent: PresentationStringsComponent, secondaryComponent: PresentationStringsComponent?, groupingSeparator: String) { diff --git a/submodules/TelegramUI/TelegramUI/ChatController.swift b/submodules/TelegramUI/TelegramUI/ChatController.swift index ca49e32fbf..06769b7d7f 100644 --- a/submodules/TelegramUI/TelegramUI/ChatController.swift +++ b/submodules/TelegramUI/TelegramUI/ChatController.swift @@ -186,6 +186,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G private let messageActionCallbackDisposable = MetaDisposable() private let messageActionUrlAuthDisposable = MetaDisposable() private let editMessageDisposable = MetaDisposable() + private let editMessageErrorsDisposable = MetaDisposable() private let enqueueMediaMessageDisposable = MetaDisposable() private var resolvePeerByNameDisposable: MetaDisposable? private var shareStatusDisposable: MetaDisposable? @@ -2349,6 +2350,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.messageActionCallbackDisposable.dispose() self.messageActionUrlAuthDisposable.dispose() self.editMessageDisposable.dispose() + self.editMessageErrorsDisposable.dispose() self.enqueueMediaMessageDisposable.dispose() self.resolvePeerByNameDisposable?.dispose() self.shareStatusDisposable?.dispose() @@ -2873,10 +2875,22 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G guard let strongSelf = self, let editMessageState = strongSelf.presentationInterfaceState.editMessageState, case let .media(options) = editMessageState.content else { return } - strongSelf.presentAttachmentMenu(editMediaOptions: options) + var originalMediaReference: AnyMediaReference? + if let message = message { + for media in message.media { + if let image = media as? TelegramMediaImage { + originalMediaReference = .message(message: MessageReference(message), media: image) + } else if let file = media as? TelegramMediaFile { + if file.isVideo || file.isAnimated { + originalMediaReference = .message(message: MessageReference(message), media: file) + } + } + } + } + strongSelf.presentAttachmentMenu(editMediaOptions: options, editMediaReference: originalMediaReference) }) } else { - strongSelf.presentAttachmentMenu(editMediaOptions: nil) + strongSelf.presentAttachmentMenu(editMediaOptions: nil, editMediaReference: nil) } } self.chatDisplayNode.paste = { [weak self] data in @@ -3004,7 +3018,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G state = state.updatedEditMessageState(nil) return state }, completion: completion) - strongSelf.editMessageDisposable.set(nil) return } @@ -3217,41 +3230,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G media = .keep } - strongSelf.editMessageDisposable.set((requestEditMessage(account: strongSelf.context.account, messageId: editMessage.messageId, text: text.string, media: media, entities: entitiesAttribute, disableUrlPreview: disableUrlPreview) |> deliverOnMainQueue |> afterDisposed({ - editingMessage.set(nil) - })).start(next: { result in - guard let strongSelf = self else { - return - } - switch result { - case let .progress(value): - editingMessage.set(value) - case .done: - editingMessage.set(nil) - strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { state in - var state = state - state = state.updatedInterfaceState({ $0.withUpdatedEditMessage(nil) }) - state = state.updatedEditMessageState(nil) - return state - }) - } - }, error: { error in - guard let strongSelf = self else { - return - } - - editingMessage.set(nil) - - let text: String - switch error { - case .generic: - text = strongSelf.presentationData.strings.Channel_EditMessageErrorGeneric - case .restricted: - text = strongSelf.presentationData.strings.Group_ErrorSendRestrictedMedia - } - strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: { - })]), in: .window(.root)) - })) + strongSelf.context.account.pendingUpdateMessageManager.add(messageId: editMessage.messageId, text: text.string, media: media, entities: entitiesAttribute, disableUrlPreview: disableUrlPreview) + + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { state in + var state = state + state = state.updatedInterfaceState({ $0.withUpdatedEditMessage(nil) }) + state = state.updatedEditMessageState(nil) + return state + }) } }, beginMessageSearch: { [weak self] domain, query in guard let strongSelf = self else { @@ -4569,6 +4555,23 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } } + + self.editMessageErrorsDisposable.set((self.context.account.pendingUpdateMessageManager.errors + |> deliverOnMainQueue).start(next: { [weak self] (_, error) in + guard let strongSelf = self else { + return + } + + let text: String + switch error { + case .generic: + text = strongSelf.presentationData.strings.Channel_EditMessageErrorGeneric + case .restricted: + text = strongSelf.presentationData.strings.Group_ErrorSendRestrictedMedia + } + strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: { + })]), in: .window(.root)) + })) } } @@ -5426,7 +5429,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) } - private func presentAttachmentMenu(editMediaOptions: MessageMediaEditingOptions?) { + private func presentAttachmentMenu(editMediaOptions: MessageMediaEditingOptions?, editMediaReference: AnyMediaReference?) { let _ = (self.context.sharedContext.accountManager.transaction { transaction -> GeneratedMediaStoreSettings in let entry = transaction.getSharedData(ApplicationSpecificSharedDataKeys.generatedMediaStoreSettings) as? GeneratedMediaStoreSettings return entry ?? GeneratedMediaStoreSettings.defaultSettings @@ -5508,9 +5511,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let inputText = strongSelf.presentationInterfaceState.interfaceState.effectiveInputState.inputText let menuEditMediaOptions = editMediaOptions.flatMap { options -> LegacyAttachmentMenuMediaEditing in - var result: LegacyAttachmentMenuMediaEditing = [] + var result: LegacyAttachmentMenuMediaEditing = .none if options.contains(.imageOrVideo) { - result.insert(.imageOrVideo) + result = .imageOrVideo(editMediaReference) } return result } @@ -5619,6 +5622,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) }) } + }, present: { [weak self] c, a in + self?.present(c, in: .window(.root), with: a) }) controller.didDismiss = { [weak legacyController] _ in legacyController?.dismiss() diff --git a/submodules/TelegramUI/TelegramUI/ChatControllerNode.swift b/submodules/TelegramUI/TelegramUI/ChatControllerNode.swift index bb25c30d65..d45d867ebe 100644 --- a/submodules/TelegramUI/TelegramUI/ChatControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatControllerNode.swift @@ -217,7 +217,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.inputContextPanelContainer = ChatControllerTitlePanelNodeContainer() - self.historyNode = ChatHistoryListNode(context: context, chatLocation: chatLocation, tagMask: nil, subject: subject, controllerInteraction: controllerInteraction, selectedMessages: self.selectedMessagesPromise.get(), updatingMedia: .single([:])) + self.historyNode = ChatHistoryListNode(context: context, chatLocation: chatLocation, tagMask: nil, subject: subject, controllerInteraction: controllerInteraction, selectedMessages: self.selectedMessagesPromise.get()) self.historyNode.rotated = true self.historyNodeContainer = ASDisplayNode() self.historyNodeContainer.addSubnode(self.historyNode) diff --git a/submodules/TelegramUI/TelegramUI/ChatHistoryEntriesForView.swift b/submodules/TelegramUI/TelegramUI/ChatHistoryEntriesForView.swift index bca596e929..6b210fbb21 100644 --- a/submodules/TelegramUI/TelegramUI/ChatHistoryEntriesForView.swift +++ b/submodules/TelegramUI/TelegramUI/ChatHistoryEntriesForView.swift @@ -5,7 +5,7 @@ import SyncCore import TemporaryCachedPeerDataManager import Emoji -func chatHistoryEntriesForView(location: ChatLocation, view: MessageHistoryView, includeUnreadEntry: Bool, includeEmptyEntry: Bool, includeChatInfoEntry: Bool, includeSearchEntry: Bool, reverse: Bool, groupMessages: Bool, selectedMessages: Set?, presentationData: ChatPresentationData, historyAppearsCleared: Bool, associatedData: ChatMessageItemAssociatedData) -> [ChatHistoryEntry] { +func chatHistoryEntriesForView(location: ChatLocation, view: MessageHistoryView, includeUnreadEntry: Bool, includeEmptyEntry: Bool, includeChatInfoEntry: Bool, includeSearchEntry: Bool, reverse: Bool, groupMessages: Bool, selectedMessages: Set?, presentationData: ChatPresentationData, historyAppearsCleared: Bool, associatedData: ChatMessageItemAssociatedData, updatingMedia: [MessageId: ChatUpdatingMessageMedia]) -> [ChatHistoryEntry] { if historyAppearsCleared { return [] } @@ -65,7 +65,7 @@ func chatHistoryEntriesForView(location: ChatLocation, view: MessageHistoryView, } else { selection = .none } - groupBucket.append((entry.message, entry.isRead, selection, ChatMessageEntryAttributes(rank: adminRank, isContact: entry.attributes.authorIsContact, contentTypeHint: contentTypeHint))) + groupBucket.append((entry.message, entry.isRead, selection, ChatMessageEntryAttributes(rank: adminRank, isContact: entry.attributes.authorIsContact, contentTypeHint: contentTypeHint, updatingMedia: updatingMedia[entry.message.id]))) } else { let selection: ChatHistoryMessageSelection if let selectedMessages = selectedMessages { @@ -73,7 +73,7 @@ func chatHistoryEntriesForView(location: ChatLocation, view: MessageHistoryView, } else { selection = .none } - entries.append(.MessageEntry(entry.message, presentationData, entry.isRead, entry.monthLocation, selection, ChatMessageEntryAttributes(rank: adminRank, isContact: entry.attributes.authorIsContact, contentTypeHint: contentTypeHint))) + entries.append(.MessageEntry(entry.message, presentationData, entry.isRead, entry.monthLocation, selection, ChatMessageEntryAttributes(rank: adminRank, isContact: entry.attributes.authorIsContact, contentTypeHint: contentTypeHint, updatingMedia: updatingMedia[entry.message.id]))) } } else { let selection: ChatHistoryMessageSelection @@ -82,7 +82,7 @@ func chatHistoryEntriesForView(location: ChatLocation, view: MessageHistoryView, } else { selection = .none } - entries.append(.MessageEntry(entry.message, presentationData, entry.isRead, entry.monthLocation, selection, ChatMessageEntryAttributes(rank: adminRank, isContact: entry.attributes.authorIsContact, contentTypeHint: contentTypeHint))) + entries.append(.MessageEntry(entry.message, presentationData, entry.isRead, entry.monthLocation, selection, ChatMessageEntryAttributes(rank: adminRank, isContact: entry.attributes.authorIsContact, contentTypeHint: contentTypeHint, updatingMedia: updatingMedia[entry.message.id]))) } } diff --git a/submodules/TelegramUI/TelegramUI/ChatHistoryEntry.swift b/submodules/TelegramUI/TelegramUI/ChatHistoryEntry.swift index 89a6fb2242..05488d9409 100644 --- a/submodules/TelegramUI/TelegramUI/ChatHistoryEntry.swift +++ b/submodules/TelegramUI/TelegramUI/ChatHistoryEntry.swift @@ -37,17 +37,20 @@ public struct ChatMessageEntryAttributes: Equatable { let rank: CachedChannelAdminRank? let isContact: Bool let contentTypeHint: ChatMessageEntryContentType + let updatingMedia: ChatUpdatingMessageMedia? - init(rank: CachedChannelAdminRank?, isContact: Bool, contentTypeHint: ChatMessageEntryContentType) { + init(rank: CachedChannelAdminRank?, isContact: Bool, contentTypeHint: ChatMessageEntryContentType, updatingMedia: ChatUpdatingMessageMedia?) { self.rank = rank self.isContact = isContact self.contentTypeHint = contentTypeHint + self.updatingMedia = updatingMedia } public init() { self.rank = nil self.isContact = false self.contentTypeHint = .generic + self.updatingMedia = nil } } diff --git a/submodules/TelegramUI/TelegramUI/ChatHistoryGridNode.swift b/submodules/TelegramUI/TelegramUI/ChatHistoryGridNode.swift index 747ef6ada8..42b2a10878 100644 --- a/submodules/TelegramUI/TelegramUI/ChatHistoryGridNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatHistoryGridNode.swift @@ -305,7 +305,7 @@ public final class ChatHistoryGridNode: GridNode, ChatHistoryNode { } let associatedData = ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: false) - let processedView = ChatHistoryView(originalView: view, filteredEntries: chatHistoryEntriesForView(location: .peer(peerId), view: view, includeUnreadEntry: false, includeEmptyEntry: false, includeChatInfoEntry: false, includeSearchEntry: false, reverse: false, groupMessages: false, selectedMessages: nil, presentationData: chatPresentationData, historyAppearsCleared: false, associatedData: associatedData), associatedData: associatedData, id: id) + let processedView = ChatHistoryView(originalView: view, filteredEntries: chatHistoryEntriesForView(location: .peer(peerId), view: view, includeUnreadEntry: false, includeEmptyEntry: false, includeChatInfoEntry: false, includeSearchEntry: false, reverse: false, groupMessages: false, selectedMessages: nil, presentationData: chatPresentationData, historyAppearsCleared: false, associatedData: associatedData, updatingMedia: [:]), associatedData: associatedData, id: id) let previous = previousView.swap(processedView) let rawTransition = preparedChatHistoryViewTransition(from: previous, to: processedView, reason: reason, reverse: false, chatLocation: .peer(peerId), controllerInteraction: controllerInteraction, scrollPosition: scrollPosition, initialData: nil, keyboardButtonsMessage: nil, cachedData: nil, cachedDataMessages: nil, readStateData: nil, flashIndicators: flashIndicators, updatedMessageSelection: false) diff --git a/submodules/TelegramUI/TelegramUI/ChatHistoryListNode.swift b/submodules/TelegramUI/TelegramUI/ChatHistoryListNode.swift index f0205a0cda..53118f4c11 100644 --- a/submodules/TelegramUI/TelegramUI/ChatHistoryListNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatHistoryListNode.swift @@ -496,7 +496,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { private var loadedMessagesFromCachedDataDisposable: Disposable? - public init(context: AccountContext, chatLocation: ChatLocation, tagMask: MessageTags?, subject: ChatControllerSubject?, controllerInteraction: ChatControllerInteraction, selectedMessages: Signal?, NoError>, updatingMedia: Signal<[MessageId: ChatUpdatingMessageMedia], NoError>, mode: ChatHistoryListMode = .bubbles) { + public init(context: AccountContext, chatLocation: ChatLocation, tagMask: MessageTags?, subject: ChatControllerSubject?, controllerInteraction: ChatControllerInteraction, selectedMessages: Signal?, NoError>, mode: ChatHistoryListMode = .bubbles) { self.context = context self.chatLocation = chatLocation self.subject = subject @@ -624,6 +624,22 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { let nextTransitionVersion = Atomic(value: 0) + let updatingMedia = context.account.pendingUpdateMessageManager.updatingMessageMedia + |> map { value -> [MessageId: ChatUpdatingMessageMedia] in + var result = value + for id in value.keys { + if case let .peer(peerId) = chatLocation { + if id.peerId != peerId { + result.removeValue(forKey: id) + } + } else { + result.removeValue(forKey: id) + } + } + return result + } + |> distinctUntilChanged + let historyViewTransitionDisposable = combineLatest(queue: messageViewQueue, historyViewUpdate, self.chatPresentationDataPromise.get(), @@ -710,7 +726,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { let associatedData = extractAssociatedData(chatLocation: chatLocation, view: view, automaticDownloadNetworkType: networkType, animatedEmojiStickers: animatedEmojiStickers, isScheduledMessages: isScheduledMessages) - let processedView = ChatHistoryView(originalView: view, filteredEntries: chatHistoryEntriesForView(location: chatLocation, view: view, includeUnreadEntry: mode == .bubbles, includeEmptyEntry: mode == .bubbles && tagMask == nil, includeChatInfoEntry: mode == .bubbles, includeSearchEntry: includeSearchEntry && tagMask != nil, reverse: reverse, groupMessages: mode == .bubbles, selectedMessages: selectedMessages, presentationData: chatPresentationData, historyAppearsCleared: historyAppearsCleared, associatedData: associatedData), associatedData: associatedData, id: id) + let processedView = ChatHistoryView(originalView: view, filteredEntries: chatHistoryEntriesForView(location: chatLocation, view: view, includeUnreadEntry: mode == .bubbles, includeEmptyEntry: mode == .bubbles && tagMask == nil, includeChatInfoEntry: mode == .bubbles, includeSearchEntry: includeSearchEntry && tagMask != nil, reverse: reverse, groupMessages: mode == .bubbles, selectedMessages: selectedMessages, presentationData: chatPresentationData, historyAppearsCleared: historyAppearsCleared, associatedData: associatedData, updatingMedia: updatingMedia), associatedData: associatedData, id: id) let previousValueAndVersion = previousView.swap((processedView, update.1, selectedMessages)) let previous = previousValueAndVersion?.0 let previousSelectedMessages = previousValueAndVersion?.2 @@ -1235,7 +1251,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { public func isMessageVisibleOnScreen(_ id: MessageId) -> Bool { var result = false self.forEachItemNode({ itemNode in - if let itemNode = itemNode as? ChatMessageItemView, let item = itemNode.item, item.content.contains(where: { $0.id == id }) { + if let itemNode = itemNode as? ChatMessageItemView, let item = itemNode.item, item.content.contains(where: { $0.0.id == id }) { if self.itemNodeVisibleInsideInsets(itemNode) { result = true } @@ -1612,7 +1628,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { var messageItem: ChatMessageItem? self.forEachItemNode({ itemNode in if let itemNode = itemNode as? ChatMessageItemView, let item = itemNode.item { - for message in item.content { + for (message, _) in item.content { if message.id == id { messageItem = item break diff --git a/submodules/TelegramUI/TelegramUI/ChatInterfaceStateContextMenus.swift b/submodules/TelegramUI/TelegramUI/ChatInterfaceStateContextMenus.swift index 44c044b870..af37f08b4d 100644 --- a/submodules/TelegramUI/TelegramUI/ChatInterfaceStateContextMenus.swift +++ b/submodules/TelegramUI/TelegramUI/ChatInterfaceStateContextMenus.swift @@ -253,8 +253,6 @@ func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState: return .single([]) } - let dataSignal: Signal - var loadStickerSaveStatus: MediaId? var loadCopyMediaResource: MediaResource? var isAction = false @@ -346,20 +344,27 @@ func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState: return transaction.getPreferencesEntry(key: PreferencesKeys.limitsConfiguration) as? LimitsConfiguration ?? LimitsConfiguration.defaultValue } - dataSignal = combineLatest(loadLimits, loadStickerSaveStatusSignal, loadResourceStatusSignal, context.sharedContext.chatAvailableMessageActions(postbox: context.account.postbox, accountPeerId: context.account.peerId, messageIds: Set(messages.map { $0.id }))) - |> map { limitsConfiguration, stickerSaveStatus, resourceStatus, messageActions -> MessageContextMenuData in + let dataSignal: Signal<(MessageContextMenuData, [MessageId: ChatUpdatingMessageMedia]), NoError> = combineLatest( + loadLimits, + loadStickerSaveStatusSignal, + loadResourceStatusSignal, + context.sharedContext.chatAvailableMessageActions(postbox: context.account.postbox, accountPeerId: context.account.peerId, messageIds: Set(messages.map { $0.id })), + context.account.pendingUpdateMessageManager.updatingMessageMedia + |> take(1) + ) + |> map { limitsConfiguration, stickerSaveStatus, resourceStatus, messageActions, updatingMessageMedia -> (MessageContextMenuData, [MessageId: ChatUpdatingMessageMedia]) in var canEdit = false if !isAction { let message = messages[0] canEdit = canEditMessage(context: context, limitsConfiguration: limitsConfiguration, message: message) } - return MessageContextMenuData(starStatus: stickerSaveStatus, canReply: canReply, canPin: canPin, canEdit: canEdit, canSelect: canSelect, resourceStatus: resourceStatus, messageActions: messageActions) + return (MessageContextMenuData(starStatus: stickerSaveStatus, canReply: canReply, canPin: canPin, canEdit: canEdit, canSelect: canSelect, resourceStatus: resourceStatus, messageActions: messageActions), updatingMessageMedia) } return dataSignal |> deliverOnMainQueue - |> map { data -> [ContextMenuItem] in + |> map { data, updatingMessageMedia -> [ContextMenuItem] in var actions: [ContextMenuItem] = [] if let starStatus = data.starStatus { @@ -688,11 +693,28 @@ func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState: clearCacheAsDelete = true } if (!data.messageActions.options.intersection([.deleteLocally, .deleteGlobally]).isEmpty || clearCacheAsDelete) && !isAction { - let title = message.flags.isSending ? chatPresentationInterfaceState.strings.Conversation_ContextMenuCancelSending : chatPresentationInterfaceState.strings.Conversation_ContextMenuDelete + let title: String + var isSending = false + var isEditing = false + if updatingMessageMedia[message.id] != nil { + isSending = true + isEditing = true + title = chatPresentationInterfaceState.strings.Conversation_ContextMenuCancelEditing + } else if message.flags.isSending { + isSending = true + title = chatPresentationInterfaceState.strings.Conversation_ContextMenuCancelSending + } else { + title = chatPresentationInterfaceState.strings.Conversation_ContextMenuDelete + } actions.append(.action(ContextMenuActionItem(text: title, textColor: .destructive, icon: { theme in - return generateTintedImage(image: UIImage(bundleImageName: message.flags.isSending ? "Chat/Context Menu/Clear" : "Chat/Context Menu/Delete"), color: theme.actionSheet.destructiveActionTextColor) + return generateTintedImage(image: UIImage(bundleImageName: isSending ? "Chat/Context Menu/Clear" : "Chat/Context Menu/Delete"), color: theme.actionSheet.destructiveActionTextColor) }, action: { controller, f in - interfaceInteraction.deleteMessages(selectAll ? messages : [message], controller, f) + if isEditing { + context.account.pendingUpdateMessageManager.cancel(messageId: message.id) + f(.default) + } else { + interfaceInteraction.deleteMessages(selectAll ? messages : [message], controller, f) + } }))) } diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageAttachedContentNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageAttachedContentNode.swift index 907ee9dee2..1cb26d13db 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageAttachedContentNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageAttachedContentNode.swift @@ -268,7 +268,7 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { self.addSubnode(self.statusNode) } - func asyncLayout() -> (_ presentationData: ChatPresentationData, _ automaticDownloadSettings: MediaAutoDownloadSettings, _ associatedData: ChatMessageItemAssociatedData, _ context: AccountContext, _ controllerInteraction: ChatControllerInteraction, _ message: Message, _ messageRead: Bool, _ title: String?, _ subtitle: NSAttributedString?, _ text: String?, _ entities: [MessageTextEntity]?, _ media: (Media, ChatMessageAttachedContentNodeMediaFlags)?, _ mediaBadge: String?, _ actionIcon: ChatMessageAttachedContentActionIcon?, _ actionTitle: String?, _ displayLine: Bool, _ layoutConstants: ChatMessageItemLayoutConstants, _ constrainedSize: CGSize) -> (CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool) -> Void))) { + func asyncLayout() -> (_ presentationData: ChatPresentationData, _ automaticDownloadSettings: MediaAutoDownloadSettings, _ associatedData: ChatMessageItemAssociatedData, _ attributes: ChatMessageEntryAttributes, _ context: AccountContext, _ controllerInteraction: ChatControllerInteraction, _ message: Message, _ messageRead: Bool, _ title: String?, _ subtitle: NSAttributedString?, _ text: String?, _ entities: [MessageTextEntity]?, _ media: (Media, ChatMessageAttachedContentNodeMediaFlags)?, _ mediaBadge: String?, _ actionIcon: ChatMessageAttachedContentActionIcon?, _ actionTitle: String?, _ displayLine: Bool, _ layoutConstants: ChatMessageItemLayoutConstants, _ constrainedSize: CGSize) -> (CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool) -> Void))) { let textAsyncLayout = TextNode.asyncLayout(self.textNode) let currentImage = self.media as? TelegramMediaImage let imageLayout = self.inlineImageNode.asyncLayout() @@ -281,7 +281,7 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { let currentAdditionalImageBadgeNode = self.additionalImageBadgeNode - return { presentationData, automaticDownloadSettings, associatedData, context, controllerInteraction, message, messageRead, title, subtitle, text, entities, mediaAndFlags, mediaBadge, actionIcon, actionTitle, displayLine, layoutConstants, constrainedSize in + return { presentationData, automaticDownloadSettings, associatedData, attributes, context, controllerInteraction, message, messageRead, title, subtitle, text, entities, mediaAndFlags, mediaBadge, actionIcon, actionTitle, displayLine, layoutConstants, constrainedSize in let fontSize: CGFloat = floor(presentationData.fontSize.baseDisplaySize * 15.0 / 17.0) let titleFont = Font.semibold(fontSize) @@ -309,6 +309,9 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { var contentMode: InteractiveMediaNodeContentMode = preferMediaAspectFilled ? .aspectFill : .aspectFit var edited = false + if attributes.updatingMedia != nil { + edited = true + } var viewCount: Int? for attribute in message.attributes { if let attribute = attribute as? EditedMessageAttribute { @@ -407,12 +410,12 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { if let (media, flags) = mediaAndFlags { if let file = media as? TelegramMediaFile { if file.mimeType == "application/x-tgtheme-ios", let size = file.size, size < 16 * 1024 { - let (_, initialImageWidth, refineLayout) = contentImageLayout(context, presentationData.theme.theme, presentationData.strings, presentationData.dateTimeFormat, message, file, .full, associatedData.automaticDownloadPeerType, .constrained(CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)), layoutConstants, contentMode) + let (_, initialImageWidth, refineLayout) = contentImageLayout(context, presentationData.theme.theme, presentationData.strings, presentationData.dateTimeFormat, message, attributes, file, .full, associatedData.automaticDownloadPeerType, .constrained(CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)), layoutConstants, contentMode) initialWidth = initialImageWidth + horizontalInsets.left + horizontalInsets.right refineContentImageLayout = refineLayout } else if file.isInstantVideo { let automaticDownload = shouldDownloadMediaAutomatically(settings: automaticDownloadSettings, peerType: associatedData.automaticDownloadPeerType, networkType: associatedData.automaticDownloadNetworkType, authorPeerId: message.author?.id, contactsPeerIds: associatedData.contactsPeerIds, media: file) - let (videoLayout, apply) = contentInstantVideoLayout(ChatMessageBubbleContentItem(context: context, controllerInteraction: controllerInteraction, message: message, read: messageRead, presentationData: presentationData, associatedData: associatedData), constrainedSize.width - horizontalInsets.left - horizontalInsets.right, CGSize(width: 212.0, height: 212.0), .bubble, automaticDownload) + let (videoLayout, apply) = contentInstantVideoLayout(ChatMessageBubbleContentItem(context: context, controllerInteraction: controllerInteraction, message: message, read: messageRead, presentationData: presentationData, associatedData: associatedData, attributes: attributes), constrainedSize.width - horizontalInsets.left - horizontalInsets.right, CGSize(width: 212.0, height: 212.0), .bubble, automaticDownload) initialWidth = videoLayout.contentSize.width + videoLayout.overflowLeft + videoLayout.overflowRight contentInstantVideoSizeAndApply = (videoLayout, apply) } else if file.isVideo { @@ -438,12 +441,12 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { } } - let (_, initialImageWidth, refineLayout) = contentImageLayout(context, presentationData.theme.theme, presentationData.strings, presentationData.dateTimeFormat, message, file, automaticDownload, associatedData.automaticDownloadPeerType, .constrained(CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)), layoutConstants, contentMode) + let (_, initialImageWidth, refineLayout) = contentImageLayout(context, presentationData.theme.theme, presentationData.strings, presentationData.dateTimeFormat, message, attributes, file, automaticDownload, associatedData.automaticDownloadPeerType, .constrained(CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)), layoutConstants, contentMode) initialWidth = initialImageWidth + horizontalInsets.left + horizontalInsets.right refineContentImageLayout = refineLayout } else if file.isSticker || file.isAnimatedSticker { let automaticDownload = shouldDownloadMediaAutomatically(settings: automaticDownloadSettings, peerType: associatedData.automaticDownloadPeerType, networkType: associatedData.automaticDownloadNetworkType, authorPeerId: message.author?.id, contactsPeerIds: associatedData.contactsPeerIds, media: file) - let (_, initialImageWidth, refineLayout) = contentImageLayout(context, presentationData.theme.theme, presentationData.strings, presentationData.dateTimeFormat, message, file, automaticDownload ? .full : .none, associatedData.automaticDownloadPeerType, .constrained(CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)), layoutConstants, contentMode) + let (_, initialImageWidth, refineLayout) = contentImageLayout(context, presentationData.theme.theme, presentationData.strings, presentationData.dateTimeFormat, message, attributes, file, automaticDownload ? .full : .none, associatedData.automaticDownloadPeerType, .constrained(CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)), layoutConstants, contentMode) initialWidth = initialImageWidth + horizontalInsets.left + horizontalInsets.right refineContentImageLayout = refineLayout } else { @@ -455,20 +458,20 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { } else { if message.flags.contains(.Failed) { statusType = .BubbleOutgoing(.Failed) - } else if message.flags.isSending && !message.isSentOrAcknowledged { + } else if (message.flags.isSending && !message.isSentOrAcknowledged) || attributes.updatingMedia != nil { statusType = .BubbleOutgoing(.Sending) } else { statusType = .BubbleOutgoing(.Sent(read: messageRead)) } } - let (_, refineLayout) = contentFileLayout(context, presentationData, message, file, automaticDownload, message.effectivelyIncoming(context.account.peerId), false, associatedData.forcedResourceStatus, statusType, CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)) + let (_, refineLayout) = contentFileLayout(context, presentationData, message, attributes, file, automaticDownload, message.effectivelyIncoming(context.account.peerId), false, associatedData.forcedResourceStatus, statusType, CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)) refineContentFileLayout = refineLayout } } else if let image = media as? TelegramMediaImage { if !flags.contains(.preferMediaInline) { let automaticDownload = shouldDownloadMediaAutomatically(settings: automaticDownloadSettings, peerType: associatedData.automaticDownloadPeerType, networkType: associatedData.automaticDownloadNetworkType, authorPeerId: message.author?.id, contactsPeerIds: associatedData.contactsPeerIds, media: image) - let (_, initialImageWidth, refineLayout) = contentImageLayout(context, presentationData.theme.theme, presentationData.strings, presentationData.dateTimeFormat, message, image, automaticDownload ? .full : .none, associatedData.automaticDownloadPeerType, .constrained(CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)), layoutConstants, contentMode) + let (_, initialImageWidth, refineLayout) = contentImageLayout(context, presentationData.theme.theme, presentationData.strings, presentationData.dateTimeFormat, message, attributes, image, automaticDownload ? .full : .none, associatedData.automaticDownloadPeerType, .constrained(CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)), layoutConstants, contentMode) initialWidth = initialImageWidth + horizontalInsets.left + horizontalInsets.right refineContentImageLayout = refineLayout } else if let dimensions = largestImageRepresentation(image.representations)?.dimensions { @@ -480,11 +483,11 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { } } else if let image = media as? TelegramMediaWebFile { let automaticDownload = shouldDownloadMediaAutomatically(settings: automaticDownloadSettings, peerType: associatedData.automaticDownloadPeerType, networkType: associatedData.automaticDownloadNetworkType, authorPeerId: message.author?.id, contactsPeerIds: associatedData.contactsPeerIds, media: image) - let (_, initialImageWidth, refineLayout) = contentImageLayout(context, presentationData.theme.theme, presentationData.strings, presentationData.dateTimeFormat, message, image, automaticDownload ? .full : .none, associatedData.automaticDownloadPeerType, .constrained(CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)), layoutConstants, contentMode) + let (_, initialImageWidth, refineLayout) = contentImageLayout(context, presentationData.theme.theme, presentationData.strings, presentationData.dateTimeFormat, message, attributes, image, automaticDownload ? .full : .none, associatedData.automaticDownloadPeerType, .constrained(CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)), layoutConstants, contentMode) initialWidth = initialImageWidth + horizontalInsets.left + horizontalInsets.right refineContentImageLayout = refineLayout } else if let wallpaper = media as? WallpaperPreviewMedia { - let (_, initialImageWidth, refineLayout) = contentImageLayout(context, presentationData.theme.theme, presentationData.strings, presentationData.dateTimeFormat, message, wallpaper, .full, associatedData.automaticDownloadPeerType, .constrained(CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)), layoutConstants, contentMode) + let (_, initialImageWidth, refineLayout) = contentImageLayout(context, presentationData.theme.theme, presentationData.strings, presentationData.dateTimeFormat, message, attributes, wallpaper, .full, associatedData.automaticDownloadPeerType, .constrained(CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)), layoutConstants, contentMode) initialWidth = initialImageWidth + horizontalInsets.left + horizontalInsets.right refineContentImageLayout = refineLayout if case let .file(_, _, _, _, isTheme, _) = wallpaper.content, isTheme { @@ -546,7 +549,7 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { } else { statusType = .BubbleOutgoing(.Failed) } - } else if message.flags.isSending && !message.isSentOrAcknowledged { + } else if (message.flags.isSending && !message.isSentOrAcknowledged) || attributes.updatingMedia != nil { if imageMode { statusType = .ImageOutgoing(.Sending) } else { diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleContentNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleContentNode.swift index f13a99335d..8a7925daf6 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleContentNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleContentNode.swift @@ -90,14 +90,16 @@ final class ChatMessageBubbleContentItem { let read: Bool let presentationData: ChatPresentationData let associatedData: ChatMessageItemAssociatedData + let attributes: ChatMessageEntryAttributes - init(context: AccountContext, controllerInteraction: ChatControllerInteraction, message: Message, read: Bool, presentationData: ChatPresentationData, associatedData: ChatMessageItemAssociatedData) { + init(context: AccountContext, controllerInteraction: ChatControllerInteraction, message: Message, read: Bool, presentationData: ChatPresentationData, associatedData: ChatMessageItemAssociatedData, attributes: ChatMessageEntryAttributes) { self.context = context self.controllerInteraction = controllerInteraction self.message = message self.read = read self.presentationData = presentationData self.associatedData = associatedData + self.attributes = attributes } } diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift index f59cece08d..90efe7d024 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift @@ -23,54 +23,54 @@ import GridMessageSelectionNode import AppBundle import Markdown -private func contentNodeMessagesAndClassesForItem(_ item: ChatMessageItem) -> [(Message, AnyClass)] { - var result: [(Message, AnyClass)] = [] +private func contentNodeMessagesAndClassesForItem(_ item: ChatMessageItem) -> [(Message, AnyClass, ChatMessageEntryAttributes)] { + var result: [(Message, AnyClass, ChatMessageEntryAttributes)] = [] var skipText = false - var messageWithCaptionToAdd: Message? + var messageWithCaptionToAdd: (Message, ChatMessageEntryAttributes)? var isUnsupportedMedia = false - outer: for message in item.content { + outer: for (message, itemAttributes) in item.content { for attribute in message.attributes { if let attribute = attribute as? RestrictedContentMessageAttribute, attribute.platformText(platform: "ios", contentSettings: item.context.currentContentSettings.with { $0 }) != nil { - result.append((message, ChatMessageRestrictedBubbleContentNode.self)) + result.append((message, ChatMessageRestrictedBubbleContentNode.self, itemAttributes)) break outer } } inner: for media in message.media { if let _ = media as? TelegramMediaImage { - result.append((message, ChatMessageMediaBubbleContentNode.self)) + result.append((message, ChatMessageMediaBubbleContentNode.self, itemAttributes)) } else if let file = media as? TelegramMediaFile { var isVideo = file.isVideo || (file.isAnimated && file.dimensions != nil) if isVideo { - result.append((message, ChatMessageMediaBubbleContentNode.self)) + result.append((message, ChatMessageMediaBubbleContentNode.self, itemAttributes)) } else { - result.append((message, ChatMessageFileBubbleContentNode.self)) + result.append((message, ChatMessageFileBubbleContentNode.self, itemAttributes)) } } else if let action = media as? TelegramMediaAction { if case .phoneCall = action.action { - result.append((message, ChatMessageCallBubbleContentNode.self)) + result.append((message, ChatMessageCallBubbleContentNode.self, itemAttributes)) } else { - result.append((message, ChatMessageActionBubbleContentNode.self)) + result.append((message, ChatMessageActionBubbleContentNode.self, itemAttributes)) } } else if let _ = media as? TelegramMediaMap { - result.append((message, ChatMessageMapBubbleContentNode.self)) + result.append((message, ChatMessageMapBubbleContentNode.self, itemAttributes)) } else if let _ = media as? TelegramMediaGame { skipText = true - result.append((message, ChatMessageGameBubbleContentNode.self)) + result.append((message, ChatMessageGameBubbleContentNode.self, itemAttributes)) break inner } else if let _ = media as? TelegramMediaInvoice { skipText = true - result.append((message, ChatMessageInvoiceBubbleContentNode.self)) + result.append((message, ChatMessageInvoiceBubbleContentNode.self, itemAttributes)) break inner } else if let _ = media as? TelegramMediaContact { - result.append((message, ChatMessageContactBubbleContentNode.self)) + result.append((message, ChatMessageContactBubbleContentNode.self, itemAttributes)) } else if let _ = media as? TelegramMediaExpiredContent { result.removeAll() - result.append((message, ChatMessageActionBubbleContentNode.self)) + result.append((message, ChatMessageActionBubbleContentNode.self, itemAttributes)) return result } else if let _ = media as? TelegramMediaPoll { - result.append((message, ChatMessagePollBubbleContentNode.self)) + result.append((message, ChatMessagePollBubbleContentNode.self, itemAttributes)) } else if let _ = media as? TelegramMediaUnsupported { isUnsupportedMedia = true } @@ -79,10 +79,10 @@ private func contentNodeMessagesAndClassesForItem(_ item: ChatMessageItem) -> [( if !message.text.isEmpty || isUnsupportedMedia { if !skipText { if case .group = item.content { - messageWithCaptionToAdd = message + messageWithCaptionToAdd = (message, itemAttributes) skipText = true } else { - result.append((message, ChatMessageTextBubbleContentNode.self)) + result.append((message, ChatMessageTextBubbleContentNode.self, itemAttributes)) } } else { if case .group = item.content { @@ -94,29 +94,29 @@ private func contentNodeMessagesAndClassesForItem(_ item: ChatMessageItem) -> [( inner: for media in message.media { if let webpage = media as? TelegramMediaWebpage { if case .Loaded = webpage.content { - result.append((message, ChatMessageWebpageBubbleContentNode.self)) + result.append((message, ChatMessageWebpageBubbleContentNode.self, itemAttributes)) } break inner } } if isUnsupportedMedia { - result.append((message, ChatMessageUnsupportedBubbleContentNode.self)) + result.append((message, ChatMessageUnsupportedBubbleContentNode.self, itemAttributes)) } } - if let messageWithCaptionToAdd = messageWithCaptionToAdd { - result.append((messageWithCaptionToAdd, ChatMessageTextBubbleContentNode.self)) + if let (messageWithCaptionToAdd, itemAttributes) = messageWithCaptionToAdd { + result.append((messageWithCaptionToAdd, ChatMessageTextBubbleContentNode.self, itemAttributes)) } if let additionalContent = item.additionalContent { switch additionalContent { case let .eventLogPreviousMessage(previousMessage): - result.append((previousMessage, ChatMessageEventLogPreviousMessageContentNode.self)) + result.append((previousMessage, ChatMessageEventLogPreviousMessageContentNode.self, ChatMessageEntryAttributes())) case let .eventLogPreviousDescription(previousMessage): - result.append((previousMessage, ChatMessageEventLogPreviousDescriptionContentNode.self)) + result.append((previousMessage, ChatMessageEventLogPreviousDescriptionContentNode.self, ChatMessageEntryAttributes())) case let .eventLogPreviousLink(previousMessage): - result.append((previousMessage, ChatMessageEventLogPreviousLinkContentNode.self)) + result.append((previousMessage, ChatMessageEventLogPreviousLinkContentNode.self, ChatMessageEntryAttributes())) } } @@ -806,22 +806,22 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode let maximumContentWidth = floor(tmpWidth - layoutConstants.bubble.edgeInset - layoutConstants.bubble.edgeInset - layoutConstants.bubble.contentInsets.left - layoutConstants.bubble.contentInsets.right - avatarInset) - var contentPropertiesAndPrepareLayouts: [(Message, Bool, (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool) -> Void))))] = [] + var contentPropertiesAndPrepareLayouts: [(Message, Bool, ChatMessageEntryAttributes, (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool) -> Void))))] = [] var addedContentNodes: [(Message, ChatMessageBubbleContentNode)]? let contentNodeMessagesAndClasses = contentNodeMessagesAndClassesForItem(item) - for (contentNodeMessage, contentNodeClass) in contentNodeMessagesAndClasses { + for (contentNodeMessage, contentNodeClass, attributes) in contentNodeMessagesAndClasses { var found = false for (currentMessage, currentClass, supportsMosaic, currentLayout) in currentContentClassesPropertiesAndLayouts { if currentClass == contentNodeClass && currentMessage.stableId == contentNodeMessage.stableId { - contentPropertiesAndPrepareLayouts.append((contentNodeMessage, supportsMosaic, currentLayout)) + contentPropertiesAndPrepareLayouts.append((contentNodeMessage, supportsMosaic, attributes, currentLayout)) found = true break } } if !found { let contentNode = (contentNodeClass as! ChatMessageBubbleContentNode.Type).init() - contentPropertiesAndPrepareLayouts.append((contentNodeMessage, contentNode.supportsMosaic, contentNode.asyncLayoutContent())) + contentPropertiesAndPrepareLayouts.append((contentNodeMessage, contentNode.supportsMosaic, attributes, contentNode.asyncLayoutContent())) if addedContentNodes == nil { addedContentNodes = [] } @@ -918,7 +918,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode } var index = 0 - for (message, _, prepareLayout) in contentPropertiesAndPrepareLayouts { + for (message, _, attributes, prepareLayout) in contentPropertiesAndPrepareLayouts { let topPosition: ChatMessageBubbleRelativePosition let bottomPosition: ChatMessageBubbleRelativePosition @@ -938,7 +938,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode prepareContentPosition = .linear(top: topPosition, bottom: refinedBottomPosition) } - let contentItem = ChatMessageBubbleContentItem(context: item.context, controllerInteraction: item.controllerInteraction, message: message, read: read, presentationData: item.presentationData, associatedData: item.associatedData) + let contentItem = ChatMessageBubbleContentItem(context: item.context, controllerInteraction: item.controllerInteraction, message: message, read: read, presentationData: item.presentationData, associatedData: item.associatedData, attributes: attributes) var itemSelection: Bool? if case .mosaic = prepareContentPosition { @@ -1074,6 +1074,9 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode let message = item.content.firstMessage var edited = false + if item.content.firstMessageAttributes.updatingMedia != nil { + edited = true + } var viewCount: Int? for attribute in message.attributes { if let attribute = attribute as? EditedMessageAttribute { @@ -1104,7 +1107,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode } else { if isFailed { statusType = .ImageOutgoing(.Failed) - } else if message.flags.isSending && !message.isSentOrAcknowledged { + } else if (message.flags.isSending && !message.isSentOrAcknowledged) || item.content.firstMessageAttributes.updatingMedia != nil { statusType = .ImageOutgoing(.Sending) } else { statusType = .ImageOutgoing(.Sent(read: item.read)) @@ -1258,7 +1261,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode findRemoved: for i in 0 ..< currentContentClassesPropertiesAndLayouts.count { let currentMessage = currentContentClassesPropertiesAndLayouts[i].0 let currentClass: AnyClass = currentContentClassesPropertiesAndLayouts[i].1 - for (contentNodeMessage, contentNodeClass) in contentNodeMessagesAndClasses { + for (contentNodeMessage, contentNodeClass, _) in contentNodeMessagesAndClasses { if currentClass == contentNodeClass && currentMessage.stableId == contentNodeMessage.stableId { continue findRemoved } @@ -1614,7 +1617,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode replyInfoOriginY: CGFloat, removedContentNodeIndices: [Int]?, addedContentNodes: [(Message, ChatMessageBubbleContentNode)]?, - contentNodeMessagesAndClasses: [(Message, AnyClass)], + contentNodeMessagesAndClasses: [(Message, AnyClass, ChatMessageEntryAttributes)], contentNodeFramesPropertiesAndApply: [(CGRect, ChatMessageBubbleContentProperties, (ListViewItemUpdateAnimation, Bool) -> Void)], mosaicStatusOrigin: CGPoint?, mosaicStatusSizeAndApply: (CGSize, (Bool) -> ChatMessageDateAndStatusNode)?, @@ -1812,7 +1815,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode } var sortedContentNodes: [ChatMessageBubbleContentNode] = [] - outer: for (message, nodeClass) in contentNodeMessagesAndClasses { + outer: for (message, nodeClass, _) in contentNodeMessagesAndClasses { if let addedContentNodes = addedContentNodes { for (contentNodeMessage, contentNode) in addedContentNodes { if type(of: contentNode) == nodeClass && contentNodeMessage.stableId == message.stableId { @@ -2743,7 +2746,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode } if let highlightedState = item.controllerInteraction.highlightedState { - for message in item.content { + for (message, _) in item.content { if highlightedState.messageStableId == message.stableId { highlighted = true break diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageContactBubbleContentNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageContactBubbleContentNode.swift index 3bd246e9f0..4d5cbe76e5 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageContactBubbleContentNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageContactBubbleContentNode.swift @@ -142,6 +142,9 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode { let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: textString, backgroundColor: nil, maximumNumberOfLines: 5, truncationType: .end, constrainedSize: CGSize(width: maxTextWidth, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) var edited = false + if item.attributes.updatingMedia != nil { + edited = true + } var viewCount: Int? for attribute in item.message.attributes { if let attribute = attribute as? EditedMessageAttribute { @@ -174,7 +177,7 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode { } else { if item.message.flags.contains(.Failed) { statusType = .BubbleOutgoing(.Failed) - } else if item.message.flags.isSending && !item.message.isSentOrAcknowledged { + } else if (item.message.flags.isSending && !item.message.isSentOrAcknowledged) || item.attributes.updatingMedia != nil { statusType = .BubbleOutgoing(.Sending) } else { statusType = .BubbleOutgoing(.Sent(read: item.read)) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageContextControllerContentSource.swift b/submodules/TelegramUI/TelegramUI/ChatMessageContextControllerContentSource.swift index 93050d570f..ac481544af 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageContextControllerContentSource.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageContextControllerContentSource.swift @@ -26,7 +26,7 @@ final class ChatMessageContextExtractedContentSource: ContextExtractedContentSou guard let item = itemNode.item else { return } - if item.content.contains(where: { $0.stableId == self.message.stableId }), let contentNode = itemNode.getMessageContextSourceNode() { + if item.content.contains(where: { $0.0.stableId == self.message.stableId }), let contentNode = itemNode.getMessageContextSourceNode() { result = ContextControllerTakeViewInfo(contentContainingNode: contentNode, contentAreaInScreenSpace: chatNode.convert(chatNode.frameForVisibleArea(), to: nil)) } } @@ -46,7 +46,7 @@ final class ChatMessageContextExtractedContentSource: ContextExtractedContentSou guard let item = itemNode.item else { return } - if item.content.contains(where: { $0.stableId == self.message.stableId }) { + if item.content.contains(where: { $0.0.stableId == self.message.stableId }) { result = ContextControllerPutBackViewInfo(contentAreaInScreenSpace: chatNode.convert(chatNode.frameForVisibleArea(), to: nil)) } } diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageEventLogPreviousDescriptionContentNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageEventLogPreviousDescriptionContentNode.swift index ae9077c843..f540c74239 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageEventLogPreviousDescriptionContentNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageEventLogPreviousDescriptionContentNode.swift @@ -44,7 +44,7 @@ final class ChatMessageEventLogPreviousDescriptionContentNode: ChatMessageBubble } let mediaAndFlags: (Media, ChatMessageAttachedContentNodeMediaFlags)? = nil - let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.context, item.controllerInteraction, item.message, true, title, nil, text, messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, constrainedSize) + let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, true, title, nil, text, messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, constrainedSize) let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 8.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageEventLogPreviousLinkContentNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageEventLogPreviousLinkContentNode.swift index 5f788aa00c..9c76292417 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageEventLogPreviousLinkContentNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageEventLogPreviousLinkContentNode.swift @@ -39,7 +39,7 @@ final class ChatMessageEventLogPreviousLinkContentNode: ChatMessageBubbleContent let text: String = item.message.text let mediaAndFlags: (Media, ChatMessageAttachedContentNodeMediaFlags)? = nil - let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.context, item.controllerInteraction, item.message, true, title, nil, text, messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, constrainedSize) + let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, true, title, nil, text, messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, constrainedSize) let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 8.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageEventLogPreviousMessageContentNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageEventLogPreviousMessageContentNode.swift index 7058604a8c..9d05694c53 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageEventLogPreviousMessageContentNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageEventLogPreviousMessageContentNode.swift @@ -44,7 +44,7 @@ final class ChatMessageEventLogPreviousMessageContentNode: ChatMessageBubbleCont } let mediaAndFlags: (Media, ChatMessageAttachedContentNodeMediaFlags)? = nil - let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.context, item.controllerInteraction, item.message, true, title, nil, text, messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, constrainedSize) + let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, true, title, nil, text, messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, constrainedSize) let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 8.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageFileBubbleContentNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageFileBubbleContentNode.swift index 24366c0374..701b5ce552 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageFileBubbleContentNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageFileBubbleContentNode.swift @@ -59,7 +59,7 @@ class ChatMessageFileBubbleContentNode: ChatMessageBubbleContentNode { } else { if item.message.flags.contains(.Failed) { statusType = .BubbleOutgoing(.Failed) - } else if item.message.flags.isSending && !item.message.isSentOrAcknowledged { + } else if (item.message.flags.isSending && !item.message.isSentOrAcknowledged) || item.attributes.updatingMedia != nil { statusType = .BubbleOutgoing(.Sending) } else { statusType = .BubbleOutgoing(.Sent(read: item.read)) @@ -71,7 +71,7 @@ class ChatMessageFileBubbleContentNode: ChatMessageBubbleContentNode { let automaticDownload = shouldDownloadMediaAutomatically(settings: item.controllerInteraction.automaticMediaDownloadSettings, peerType: item.associatedData.automaticDownloadPeerType, networkType: item.associatedData.automaticDownloadNetworkType, authorPeerId: item.message.author?.id, contactsPeerIds: item.associatedData.contactsPeerIds, media: selectedFile!) - let (initialWidth, refineLayout) = interactiveFileLayout(item.context, item.presentationData, item.message, selectedFile!, automaticDownload, item.message.effectivelyIncoming(item.context.account.peerId), item.associatedData.isRecentActions, item.associatedData.forcedResourceStatus, statusType, CGSize(width: constrainedSize.width - layoutConstants.file.bubbleInsets.left - layoutConstants.file.bubbleInsets.right, height: constrainedSize.height)) + let (initialWidth, refineLayout) = interactiveFileLayout(item.context, item.presentationData, item.message, item.attributes, selectedFile!, automaticDownload, item.message.effectivelyIncoming(item.context.account.peerId), item.associatedData.isRecentActions, item.associatedData.forcedResourceStatus, statusType, CGSize(width: constrainedSize.width - layoutConstants.file.bubbleInsets.left - layoutConstants.file.bubbleInsets.right, height: constrainedSize.height)) let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 0.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageGameBubbleContentNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageGameBubbleContentNode.swift index 4b2c542f75..04be9ee3d9 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageGameBubbleContentNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageGameBubbleContentNode.swift @@ -71,7 +71,7 @@ final class ChatMessageGameBubbleContentNode: ChatMessageBubbleContentNode { } } - let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.context, item.controllerInteraction, item.message, item.read, title, nil, item.message.text.isEmpty ? text : item.message.text, item.message.text.isEmpty ? nil : messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, constrainedSize) + let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, item.read, title, nil, item.message.text.isEmpty ? text : item.message.text, item.message.text.isEmpty ? nil : messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, constrainedSize) let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 8.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageInstantVideoItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageInstantVideoItemNode.swift index c2136f81d2..77dbaa3cbe 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageInstantVideoItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageInstantVideoItemNode.swift @@ -210,7 +210,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView { } } - let (videoLayout, videoApply) = makeVideoLayout(ChatMessageBubbleContentItem(context: item.context, controllerInteraction: item.controllerInteraction, message: item.message, read: item.read, presentationData: item.presentationData, associatedData: item.associatedData), params.width - params.leftInset - params.rightInset - avatarInset, displaySize, .free, automaticDownload) + let (videoLayout, videoApply) = makeVideoLayout(ChatMessageBubbleContentItem(context: item.context, controllerInteraction: item.controllerInteraction, message: item.message, read: item.read, presentationData: item.presentationData, associatedData: item.associatedData, attributes: item.content.firstMessageAttributes), params.width - params.leftInset - params.rightInset - avatarInset, displaySize, .free, automaticDownload) let videoFrame = CGRect(origin: CGPoint(x: (incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + avatarInset + layoutConstants.bubble.contentInsets.left) : (params.width - params.rightInset - videoLayout.contentSize.width - layoutConstants.bubble.edgeInset - layoutConstants.bubble.contentInsets.left - deliveryFailedInset)), y: 0.0), size: videoLayout.contentSize) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveFileNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveFileNode.swift index 938b34cd74..758b2a4aa4 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveFileNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveFileNode.swift @@ -186,7 +186,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { } } - func asyncLayout() -> (_ context: AccountContext, _ presentationData: ChatPresentationData, _ message: Message, _ file: TelegramMediaFile, _ automaticDownload: Bool, _ incoming: Bool, _ isRecentActions: Bool, _ forcedResourceStatus: FileMediaResourceStatus?, _ dateAndStatusType: ChatMessageDateAndStatusType?, _ constrainedSize: CGSize) -> (CGFloat, (CGSize) -> (CGFloat, (CGFloat) -> (CGSize, (Bool) -> Void))) { + func asyncLayout() -> (_ context: AccountContext, _ presentationData: ChatPresentationData, _ message: Message, _ attributes: ChatMessageEntryAttributes, _ file: TelegramMediaFile, _ automaticDownload: Bool, _ incoming: Bool, _ isRecentActions: Bool, _ forcedResourceStatus: FileMediaResourceStatus?, _ dateAndStatusType: ChatMessageDateAndStatusType?, _ constrainedSize: CGSize) -> (CGFloat, (CGSize) -> (CGFloat, (CGFloat) -> (CGSize, (Bool) -> Void))) { let currentFile = self.file let titleAsyncLayout = TextNode.asyncLayout(self.titleNode) @@ -196,7 +196,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { let currentMessage = self.message - return { context, presentationData, message, file, automaticDownload, incoming, isRecentActions, forcedResourceStatus, dateAndStatusType, constrainedSize in + return { context, presentationData, message, attributes, file, automaticDownload, incoming, isRecentActions, forcedResourceStatus, dateAndStatusType, constrainedSize in return (CGFloat.greatestFiniteMagnitude, { constrainedSize in let titleFont = Font.regular(floor(presentationData.fontSize.baseDisplaySize * 16.0 / 17.0)) let descriptionFont = Font.regular(floor(presentationData.fontSize.baseDisplaySize * 13.0 / 17.0)) @@ -269,6 +269,9 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { if let statusType = dateAndStatusType { var edited = false + if attributes.updatingMedia != nil { + edited = true + } var viewCount: Int? for attribute in message.attributes { if let attribute = attribute as? EditedMessageAttribute { @@ -880,12 +883,12 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { self.fetchingCompactTextNode.frame = CGRect(origin: self.descriptionNode.frame.origin, size: fetchingCompactSize) } - static func asyncLayout(_ node: ChatMessageInteractiveFileNode?) -> (_ context: AccountContext, _ presentationData: ChatPresentationData, _ message: Message, _ file: TelegramMediaFile, _ automaticDownload: Bool, _ incoming: Bool, _ isRecentActions: Bool, _ forcedResourceStatus: FileMediaResourceStatus?, _ dateAndStatusType: ChatMessageDateAndStatusType?, _ constrainedSize: CGSize) -> (CGFloat, (CGSize) -> (CGFloat, (CGFloat) -> (CGSize, (Bool) -> ChatMessageInteractiveFileNode))) { + static func asyncLayout(_ node: ChatMessageInteractiveFileNode?) -> (_ context: AccountContext, _ presentationData: ChatPresentationData, _ message: Message, _ attributes: ChatMessageEntryAttributes, _ file: TelegramMediaFile, _ automaticDownload: Bool, _ incoming: Bool, _ isRecentActions: Bool, _ forcedResourceStatus: FileMediaResourceStatus?, _ dateAndStatusType: ChatMessageDateAndStatusType?, _ constrainedSize: CGSize) -> (CGFloat, (CGSize) -> (CGFloat, (CGFloat) -> (CGSize, (Bool) -> ChatMessageInteractiveFileNode))) { let currentAsyncLayout = node?.asyncLayout() - return { context, presentationData, message, file, automaticDownload, incoming, isRecentActions, forcedResourceStatus, dateAndStatusType, constrainedSize in + return { context, presentationData, message, attributes, file, automaticDownload, incoming, isRecentActions, forcedResourceStatus, dateAndStatusType, constrainedSize in var fileNode: ChatMessageInteractiveFileNode - var fileLayout: (_ context: AccountContext, _ presentationData: ChatPresentationData, _ message: Message, _ file: TelegramMediaFile, _ automaticDownload: Bool, _ incoming: Bool, _ isRecentActions: Bool, _ forcedResourceStatus: FileMediaResourceStatus?, _ dateAndStatusType: ChatMessageDateAndStatusType?, _ constrainedSize: CGSize) -> (CGFloat, (CGSize) -> (CGFloat, (CGFloat) -> (CGSize, (Bool) -> Void))) + var fileLayout: (_ context: AccountContext, _ presentationData: ChatPresentationData, _ message: Message, _ attributes: ChatMessageEntryAttributes, _ file: TelegramMediaFile, _ automaticDownload: Bool, _ incoming: Bool, _ isRecentActions: Bool, _ forcedResourceStatus: FileMediaResourceStatus?, _ dateAndStatusType: ChatMessageDateAndStatusType?, _ constrainedSize: CGSize) -> (CGFloat, (CGSize) -> (CGFloat, (CGFloat) -> (CGSize, (Bool) -> Void))) if let node = node, let currentAsyncLayout = currentAsyncLayout { fileNode = node @@ -895,7 +898,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { fileLayout = fileNode.asyncLayout() } - let (initialWidth, continueLayout) = fileLayout(context, presentationData, message, file, automaticDownload, incoming, isRecentActions, forcedResourceStatus, dateAndStatusType, constrainedSize) + let (initialWidth, continueLayout) = fileLayout(context, presentationData, message, attributes, file, automaticDownload, incoming, isRecentActions, forcedResourceStatus, dateAndStatusType, constrainedSize) return (initialWidth, { constrainedSize in let (finalWidth, finalLayout) = continueLayout(constrainedSize) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveInstantVideoNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveInstantVideoNode.swift index 8791948699..8a35e620dc 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveInstantVideoNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveInstantVideoNode.swift @@ -239,7 +239,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { case .bubble: if item.message.flags.contains(.Failed) { statusType = .BubbleOutgoing(.Failed) - } else if item.message.flags.isSending && !item.message.isSentOrAcknowledged { + } else if (item.message.flags.isSending && !item.message.isSentOrAcknowledged) || item.attributes.updatingMedia != nil { statusType = .BubbleOutgoing(.Sending) } else { statusType = .BubbleOutgoing(.Sent(read: item.read)) @@ -248,6 +248,9 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { } var edited = false + if item.attributes.updatingMedia != nil { + edited = true + } let sentViaBot = false var viewCount: Int? = nil for attribute in item.message.attributes { diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveMediaNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveMediaNode.swift index fd2bea92cf..90aaeaa6e8 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveMediaNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveMediaNode.swift @@ -79,6 +79,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio private var context: AccountContext? private var message: Message? + private var attributes: ChatMessageEntryAttributes? private var media: Media? private var themeAndStrings: (PresentationTheme, PresentationStrings, String)? private var sizeCalculation: InteractiveMediaNodeSizeCalculation? @@ -168,7 +169,11 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio } private func progressPressed(canActivate: Bool) { - if let fetchStatus = self.fetchStatus { + if let _ = self.attributes?.updatingMedia { + if let message = self.message { + self.context?.account.pendingUpdateMessageManager.cancel(messageId: message.id) + } + } else if let fetchStatus = self.fetchStatus { var activateContent = false if let state = self.statusNode?.state, case .play = state { activateContent = true @@ -214,7 +219,11 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio @objc func imageTap(_ recognizer: UITapGestureRecognizer) { if case .ended = recognizer.state { let point = recognizer.location(in: self.imageNode.view) - if let fetchStatus = self.fetchStatus, case .Local = fetchStatus { + if let _ = self.attributes?.updatingMedia { + if let statusNode = self.statusNode, statusNode.frame.contains(point) { + self.progressPressed(canActivate: true) + } + } else if let fetchStatus = self.fetchStatus, case .Local = fetchStatus { var videoContentMatch = true if let content = self.videoContent, case let .message(stableId, mediaId) = content.nativeId { videoContentMatch = self.message?.stableId == stableId && self.media?.id == mediaId @@ -232,7 +241,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio } } - func asyncLayout() -> (_ context: AccountContext, _ theme: PresentationTheme, _ strings: PresentationStrings, _ dateTimeFormat: PresentationDateTimeFormat, _ message: Message, _ media: Media, _ automaticDownload: InteractiveMediaNodeAutodownloadMode, _ peerType: MediaAutoDownloadPeerType, _ sizeCalculation: InteractiveMediaNodeSizeCalculation, _ layoutConstants: ChatMessageItemLayoutConstants, _ contentMode: InteractiveMediaNodeContentMode) -> (CGSize, CGFloat, (CGSize, Bool, Bool, ImageCorners) -> (CGFloat, (CGFloat) -> (CGSize, (ContainedViewLayoutTransition, Bool) -> Void))) { + func asyncLayout() -> (_ context: AccountContext, _ theme: PresentationTheme, _ strings: PresentationStrings, _ dateTimeFormat: PresentationDateTimeFormat, _ message: Message, _ attributes: ChatMessageEntryAttributes, _ media: Media, _ automaticDownload: InteractiveMediaNodeAutodownloadMode, _ peerType: MediaAutoDownloadPeerType, _ sizeCalculation: InteractiveMediaNodeSizeCalculation, _ layoutConstants: ChatMessageItemLayoutConstants, _ contentMode: InteractiveMediaNodeContentMode) -> (CGSize, CGFloat, (CGSize, Bool, Bool, ImageCorners) -> (CGFloat, (CGFloat) -> (CGSize, (ContainedViewLayoutTransition, Bool) -> Void))) { let currentMessage = self.message let currentMedia = self.media let imageLayout = self.imageNode.asyncLayout() @@ -245,7 +254,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio let currentAutomaticDownload = self.automaticDownload let currentAutomaticPlayback = self.automaticPlayback - return { [weak self] context, theme, strings, dateTimeFormat, message, media, automaticDownload, peerType, sizeCalculation, layoutConstants, contentMode in + return { [weak self] context, theme, strings, dateTimeFormat, message, attributes, media, automaticDownload, peerType, sizeCalculation, layoutConstants, contentMode in var nativeSize: CGSize let isSecretMedia = message.containsSecretMedia @@ -674,6 +683,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio if let strongSelf = self { strongSelf.context = context strongSelf.message = message + strongSelf.attributes = attributes strongSelf.media = media strongSelf.wideLayout = wideLayout strongSelf.themeAndStrings = (theme, strings, dateTimeFormat.decimalSeparator) @@ -904,7 +914,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio } private func updateStatus(animated: Bool) { - guard let (theme, strings, decimalSeparator) = self.themeAndStrings, let sizeCalculation = self.sizeCalculation, let message = self.message, var automaticPlayback = self.automaticPlayback, let wideLayout = self.wideLayout else { + guard let (theme, strings, decimalSeparator) = self.themeAndStrings, let sizeCalculation = self.sizeCalculation, let message = self.message, let attributes = self.attributes, var automaticPlayback = self.automaticPlayback, let wideLayout = self.wideLayout else { return } @@ -944,7 +954,9 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio } var progressRequired = false - if secretBeginTimeAndTimeout?.0 != nil { + if attributes.updatingMedia != nil { + progressRequired = true + } else if secretBeginTimeAndTimeout?.0 != nil { progressRequired = true } else if let fetchStatus = self.fetchStatus { switch fetchStatus { @@ -1017,7 +1029,9 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio badgeContent = .text(inset: 0.0, backgroundColor: messageTheme.mediaDateAndStatusFillColor, foregroundColor: messageTheme.mediaDateAndStatusTextColor, text: string) } var animated: Bool = animated - if var fetchStatus = self.fetchStatus { + if let updatingMedia = attributes.updatingMedia { + state = .progress(color: messageTheme.mediaOverlayControlColors.foregroundColor, lineWidth: nil, value: CGFloat(updatingMedia.progress), cancelEnabled: true) + } else if var fetchStatus = self.fetchStatus { var playerPosition: Int32? var playerDuration: Int32 = 0 var active = false @@ -1274,12 +1288,12 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio } } - static func asyncLayout(_ node: ChatMessageInteractiveMediaNode?) -> (_ context: AccountContext, _ theme: PresentationTheme, _ strings: PresentationStrings, _ dateTimeFormat: PresentationDateTimeFormat, _ message: Message, _ media: Media, _ automaticDownload: InteractiveMediaNodeAutodownloadMode, _ peerType: MediaAutoDownloadPeerType, _ sizeCalculation: InteractiveMediaNodeSizeCalculation, _ layoutConstants: ChatMessageItemLayoutConstants, _ contentMode: InteractiveMediaNodeContentMode) -> (CGSize, CGFloat, (CGSize, Bool, Bool, ImageCorners) -> (CGFloat, (CGFloat) -> (CGSize, (ContainedViewLayoutTransition, Bool) -> ChatMessageInteractiveMediaNode))) { + static func asyncLayout(_ node: ChatMessageInteractiveMediaNode?) -> (_ context: AccountContext, _ theme: PresentationTheme, _ strings: PresentationStrings, _ dateTimeFormat: PresentationDateTimeFormat, _ message: Message, _ attributes: ChatMessageEntryAttributes, _ media: Media, _ automaticDownload: InteractiveMediaNodeAutodownloadMode, _ peerType: MediaAutoDownloadPeerType, _ sizeCalculation: InteractiveMediaNodeSizeCalculation, _ layoutConstants: ChatMessageItemLayoutConstants, _ contentMode: InteractiveMediaNodeContentMode) -> (CGSize, CGFloat, (CGSize, Bool, Bool, ImageCorners) -> (CGFloat, (CGFloat) -> (CGSize, (ContainedViewLayoutTransition, Bool) -> ChatMessageInteractiveMediaNode))) { let currentAsyncLayout = node?.asyncLayout() - return { context, theme, strings, dateTimeFormat, message, media, automaticDownload, peerType, sizeCalculation, layoutConstants, contentMode in + return { context, theme, strings, dateTimeFormat, message, attributes, media, automaticDownload, peerType, sizeCalculation, layoutConstants, contentMode in var imageNode: ChatMessageInteractiveMediaNode - var imageLayout: (_ context: AccountContext, _ theme: PresentationTheme, _ strings: PresentationStrings, _ dateTimeFormat: PresentationDateTimeFormat, _ message: Message, _ media: Media, _ automaticDownload: InteractiveMediaNodeAutodownloadMode, _ peerType: MediaAutoDownloadPeerType, _ sizeCalculation: InteractiveMediaNodeSizeCalculation, _ layoutConstants: ChatMessageItemLayoutConstants, _ contentMode: InteractiveMediaNodeContentMode) -> (CGSize, CGFloat, (CGSize, Bool, Bool, ImageCorners) -> (CGFloat, (CGFloat) -> (CGSize, (ContainedViewLayoutTransition, Bool) -> Void))) + var imageLayout: (_ context: AccountContext, _ theme: PresentationTheme, _ strings: PresentationStrings, _ dateTimeFormat: PresentationDateTimeFormat, _ message: Message, _ attributes: ChatMessageEntryAttributes, _ media: Media, _ automaticDownload: InteractiveMediaNodeAutodownloadMode, _ peerType: MediaAutoDownloadPeerType, _ sizeCalculation: InteractiveMediaNodeSizeCalculation, _ layoutConstants: ChatMessageItemLayoutConstants, _ contentMode: InteractiveMediaNodeContentMode) -> (CGSize, CGFloat, (CGSize, Bool, Bool, ImageCorners) -> (CGFloat, (CGFloat) -> (CGSize, (ContainedViewLayoutTransition, Bool) -> Void))) if let node = node, let currentAsyncLayout = currentAsyncLayout { imageNode = node @@ -1289,7 +1303,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio imageLayout = imageNode.asyncLayout() } - let (unboundSize, initialWidth, continueLayout) = imageLayout(context, theme, strings, dateTimeFormat, message, media, automaticDownload, peerType, sizeCalculation, layoutConstants, contentMode) + let (unboundSize, initialWidth, continueLayout) = imageLayout(context, theme, strings, dateTimeFormat, message, attributes, media, automaticDownload, peerType, sizeCalculation, layoutConstants, contentMode) return (unboundSize, initialWidth, { constrainedSize, automaticPlayback, wideLayout, corners in let (finalWidth, finalLayout) = continueLayout(constrainedSize, automaticPlayback, wideLayout, corners) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageInvoiceBubbleContentNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageInvoiceBubbleContentNode.swift index f908a4c8d4..92d81ffb0c 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageInvoiceBubbleContentNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageInvoiceBubbleContentNode.swift @@ -74,7 +74,7 @@ final class ChatMessageInvoiceBubbleContentNode: ChatMessageBubbleContentNode { } } - let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, automaticDownloadSettings, item.associatedData, item.context, item.controllerInteraction, item.message, item.read, title, subtitle, text, nil, mediaAndFlags, nil, nil, nil, false, layoutConstants, constrainedSize) + let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, automaticDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, item.read, title, subtitle, text, nil, mediaAndFlags, nil, nil, nil, false, layoutConstants, constrainedSize) let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 8.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageItem.swift b/submodules/TelegramUI/TelegramUI/ChatMessageItem.swift index 437411d05e..26af9b2098 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageItem.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageItem.swift @@ -43,14 +43,23 @@ public enum ChatMessageItemContent: Sequence { } } - public func makeIterator() -> AnyIterator { + var firstMessageAttributes: ChatMessageEntryAttributes { + switch self { + case let .message(message): + return message.attributes + case let .group(messages): + return messages[0].3 + } + } + + public func makeIterator() -> AnyIterator<(Message, ChatMessageEntryAttributes)> { var index = 0 - return AnyIterator { () -> Message? in + return AnyIterator { () -> (Message, ChatMessageEntryAttributes)? in switch self { - case let .message(message, _, _, _): + case let .message(message): if index == 0 { index += 1 - return message + return (message.message, message.attributes) } else { index += 1 return nil @@ -59,7 +68,7 @@ public enum ChatMessageItemContent: Sequence { if index < messages.count { let currentIndex = index index += 1 - return messages[currentIndex].0 + return (messages[currentIndex].0, messages[currentIndex].3) } else { return nil } diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageMapBubbleContentNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageMapBubbleContentNode.swift index 0bc7c5b130..08fea390f8 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageMapBubbleContentNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageMapBubbleContentNode.swift @@ -172,6 +172,9 @@ class ChatMessageMapBubbleContentNode: ChatMessageBubbleContentNode { let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: textString, backgroundColor: nil, maximumNumberOfLines: 2, truncationType: .end, constrainedSize: CGSize(width: max(1.0, maxTextWidth), height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) var edited = false + if item.attributes.updatingMedia != nil { + edited = true + } var viewCount: Int? for attribute in item.message.attributes { if let attribute = attribute as? EditedMessageAttribute { @@ -211,7 +214,7 @@ class ChatMessageMapBubbleContentNode: ChatMessageBubbleContentNode { } else { if item.message.flags.contains(.Failed) { statusType = .BubbleOutgoing(.Failed) - } else if item.message.flags.isSending && !item.message.isSentOrAcknowledged { + } else if (item.message.flags.isSending && !item.message.isSentOrAcknowledged) || item.attributes.updatingMedia != nil { statusType = .BubbleOutgoing(.Sending) } else { statusType = .BubbleOutgoing(.Sent(read: item.read)) @@ -223,7 +226,7 @@ class ChatMessageMapBubbleContentNode: ChatMessageBubbleContentNode { } else { if item.message.flags.contains(.Failed) { statusType = .ImageOutgoing(.Failed) - } else if item.message.flags.isSending && !item.message.isSentOrAcknowledged { + } else if (item.message.flags.isSending && !item.message.isSentOrAcknowledged) || item.attributes.updatingMedia != nil { statusType = .ImageOutgoing(.Sending) } else { statusType = .ImageOutgoing(.Sent(read: item.read)) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageMediaBubbleContentNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageMediaBubbleContentNode.swift index e60d732459..05bc4f997e 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageMediaBubbleContentNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageMediaBubbleContentNode.swift @@ -70,36 +70,41 @@ class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode { var automaticPlayback: Bool = false var contentMode: InteractiveMediaNodeContentMode = .aspectFit - for media in item.message.media { - if let telegramImage = media as? TelegramMediaImage { - selectedMedia = telegramImage - if shouldDownloadMediaAutomatically(settings: item.controllerInteraction.automaticMediaDownloadSettings, peerType: item.associatedData.automaticDownloadPeerType, networkType: item.associatedData.automaticDownloadNetworkType, authorPeerId: item.message.author?.id, contactsPeerIds: item.associatedData.contactsPeerIds, media: telegramImage) { - automaticDownload = .full - } - } else if let telegramFile = media as? TelegramMediaFile { - selectedMedia = telegramFile - if shouldDownloadMediaAutomatically(settings: item.controllerInteraction.automaticMediaDownloadSettings, peerType: item.associatedData.automaticDownloadPeerType, networkType: item.associatedData.automaticDownloadNetworkType, authorPeerId: item.message.author?.id, contactsPeerIds: item.associatedData.contactsPeerIds, media: telegramFile) { - automaticDownload = .full - } else if shouldPredownloadMedia(settings: item.controllerInteraction.automaticMediaDownloadSettings, peerType: item.associatedData.automaticDownloadPeerType, networkType: item.associatedData.automaticDownloadNetworkType, media: telegramFile) { - automaticDownload = .prefetch - } - - if !item.message.containsSecretMedia { - if telegramFile.isAnimated && item.controllerInteraction.automaticMediaDownloadSettings.autoplayGifs { - if case .full = automaticDownload { - automaticPlayback = true - } else { - automaticPlayback = item.context.account.postbox.mediaBox.completedResourcePath(telegramFile.resource) != nil - } - } else if (telegramFile.isVideo && !telegramFile.isAnimated) && item.controllerInteraction.automaticMediaDownloadSettings.autoplayVideos { - if case .full = automaticDownload { - automaticPlayback = true - } else { - automaticPlayback = item.context.account.postbox.mediaBox.completedResourcePath(telegramFile.resource) != nil + if let updatingMedia = item.attributes.updatingMedia, case let .update(mediaReference) = updatingMedia.media { + selectedMedia = mediaReference.media + } + if selectedMedia == nil { + for media in item.message.media { + if let telegramImage = media as? TelegramMediaImage { + selectedMedia = telegramImage + if shouldDownloadMediaAutomatically(settings: item.controllerInteraction.automaticMediaDownloadSettings, peerType: item.associatedData.automaticDownloadPeerType, networkType: item.associatedData.automaticDownloadNetworkType, authorPeerId: item.message.author?.id, contactsPeerIds: item.associatedData.contactsPeerIds, media: telegramImage) { + automaticDownload = .full + } + } else if let telegramFile = media as? TelegramMediaFile { + selectedMedia = telegramFile + if shouldDownloadMediaAutomatically(settings: item.controllerInteraction.automaticMediaDownloadSettings, peerType: item.associatedData.automaticDownloadPeerType, networkType: item.associatedData.automaticDownloadNetworkType, authorPeerId: item.message.author?.id, contactsPeerIds: item.associatedData.contactsPeerIds, media: telegramFile) { + automaticDownload = .full + } else if shouldPredownloadMedia(settings: item.controllerInteraction.automaticMediaDownloadSettings, peerType: item.associatedData.automaticDownloadPeerType, networkType: item.associatedData.automaticDownloadNetworkType, media: telegramFile) { + automaticDownload = .prefetch + } + + if !item.message.containsSecretMedia { + if telegramFile.isAnimated && item.controllerInteraction.automaticMediaDownloadSettings.autoplayGifs { + if case .full = automaticDownload { + automaticPlayback = true + } else { + automaticPlayback = item.context.account.postbox.mediaBox.completedResourcePath(telegramFile.resource) != nil + } + } else if (telegramFile.isVideo && !telegramFile.isAnimated) && item.controllerInteraction.automaticMediaDownloadSettings.autoplayVideos { + if case .full = automaticDownload { + automaticPlayback = true + } else { + automaticPlayback = item.context.account.postbox.mediaBox.completedResourcePath(telegramFile.resource) != nil + } } } + contentMode = .aspectFill } - contentMode = .aspectFill } } @@ -138,7 +143,7 @@ class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode { sizeCalculation = .unconstrained } - let (unboundSize, initialWidth, refineLayout) = interactiveImageLayout(item.context, item.presentationData.theme.theme, item.presentationData.strings, item.presentationData.dateTimeFormat, item.message, selectedMedia!, automaticDownload, item.associatedData.automaticDownloadPeerType, sizeCalculation, layoutConstants, contentMode) + let (unboundSize, initialWidth, refineLayout) = interactiveImageLayout(item.context, item.presentationData.theme.theme, item.presentationData.strings, item.presentationData.dateTimeFormat, item.message, item.attributes, selectedMedia!, automaticDownload, item.associatedData.automaticDownloadPeerType, sizeCalculation, layoutConstants, contentMode) let forceFullCorners = false let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: true, headerSpacing: 7.0, hidesBackground: .emptyWallpaper, forceFullCorners: forceFullCorners, forceAlignment: .none) @@ -165,6 +170,9 @@ class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode { let (imageSize, imageApply) = finishLayout(boundingWidth - bubbleInsets.left - bubbleInsets.right) var edited = false + if item.attributes.updatingMedia != nil { + edited = true + } var viewCount: Int? for attribute in item.message.attributes { if let attribute = attribute as? EditedMessageAttribute { @@ -200,7 +208,7 @@ class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode { } else { if item.message.flags.contains(.Failed) { statusType = .ImageOutgoing(.Failed) - } else if item.message.flags.isSending && !item.message.isSentOrAcknowledged { + } else if (item.message.flags.isSending && !item.message.isSentOrAcknowledged) || item.attributes.updatingMedia != nil { statusType = .ImageOutgoing(.Sending) } else { statusType = .ImageOutgoing(.Sent(read: item.read)) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessagePollBubbleContentNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessagePollBubbleContentNode.swift index 809eb01d56..4db3123a19 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessagePollBubbleContentNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessagePollBubbleContentNode.swift @@ -583,6 +583,9 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode { let textConstrainedSize = CGSize(width: constrainedSize.width - horizontalInset, height: constrainedSize.height) var edited = false + if item.attributes.updatingMedia != nil { + edited = true + } var viewCount: Int? for attribute in item.message.attributes { if let attribute = attribute as? EditedMessageAttribute { @@ -615,7 +618,7 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode { } else { if message.flags.contains(.Failed) { statusType = .BubbleOutgoing(.Failed) - } else if message.flags.isSending && !message.isSentOrAcknowledged { + } else if (message.flags.isSending && !message.isSentOrAcknowledged) || item.attributes.updatingMedia != nil { statusType = .BubbleOutgoing(.Sending) } else { statusType = .BubbleOutgoing(.Sent(read: item.read)) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageRestrictedBubbleContentNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageRestrictedBubbleContentNode.swift index 14ebb7fc4b..2a410ec9ed 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageRestrictedBubbleContentNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageRestrictedBubbleContentNode.swift @@ -48,6 +48,9 @@ class ChatMessageRestrictedBubbleContentNode: ChatMessageBubbleContentNode { let textConstrainedSize = CGSize(width: min(maxTextWidth, constrainedSize.width - horizontalInset), height: constrainedSize.height) var edited = false + if item.attributes.updatingMedia != nil { + edited = true + } var viewCount: Int? var rawText = "" for attribute in item.message.attributes { diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageTextBubbleContentNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageTextBubbleContentNode.swift index b04c4517ea..ef1007c97c 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageTextBubbleContentNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageTextBubbleContentNode.swift @@ -105,6 +105,9 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { let textConstrainedSize = CGSize(width: min(maxTextWidth, constrainedSize.width - horizontalInset), height: constrainedSize.height) var edited = false + if item.attributes.updatingMedia != nil { + edited = true + } var viewCount: Int? for attribute in item.message.attributes { if let attribute = attribute as? EditedMessageAttribute { @@ -137,7 +140,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { } else { if message.flags.contains(.Failed) { statusType = .BubbleOutgoing(.Failed) - } else if message.flags.isSending && !message.isSentOrAcknowledged { + } else if (message.flags.isSending && !message.isSentOrAcknowledged) || item.attributes.updatingMedia != nil { statusType = .BubbleOutgoing(.Sending) } else { statusType = .BubbleOutgoing(.Sent(read: item.read)) @@ -178,7 +181,11 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { rawText = item.presentationData.strings.Conversation_UnsupportedMediaPlaceholder messageEntities = [MessageTextEntity(range: 0.. { subscriber in subscriber.putNext(.reset) - let avAsset = AVURLAsset(url: URL(fileURLWithPath: resource.path)) + var filteredPath = resource.path + if filteredPath.hasPrefix("file://") { + filteredPath = String(filteredPath[filteredPath.index(filteredPath.startIndex, offsetBy: "file://".count)]) + } + + let avAsset = AVURLAsset(url: URL(fileURLWithPath: filteredPath)) var adjustments: TGVideoEditAdjustments? if let videoAdjustments = resource.adjustments { if let dict = NSKeyedUnarchiver.unarchiveObject(with: videoAdjustments.data.makeData()) as? [AnyHashable : Any] { diff --git a/submodules/TelegramUI/TelegramUI/OverlayPlayerControllerNode.swift b/submodules/TelegramUI/TelegramUI/OverlayPlayerControllerNode.swift index 42333d7a8b..5d4e517339 100644 --- a/submodules/TelegramUI/TelegramUI/OverlayPlayerControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/OverlayPlayerControllerNode.swift @@ -147,7 +147,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu tagMask = .voiceOrInstantVideo } - self.historyNode = ChatHistoryListNode(context: context, chatLocation: .peer(peerId), tagMask: tagMask, subject: .message(initialMessageId), controllerInteraction: self.controllerInteraction, selectedMessages: .single(nil), updatingMedia: .single([:]), mode: .list(search: false, reversed: currentIsReversed)) + self.historyNode = ChatHistoryListNode(context: context, chatLocation: .peer(peerId), tagMask: tagMask, subject: .message(initialMessageId), controllerInteraction: self.controllerInteraction, selectedMessages: .single(nil), mode: .list(search: false, reversed: currentIsReversed)) super.init() @@ -462,7 +462,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu tagMask = .voiceOrInstantVideo } - let historyNode = ChatHistoryListNode(context: self.context, chatLocation: .peer(self.peerId), tagMask: tagMask, subject: .message(messageId), controllerInteraction: self.controllerInteraction, selectedMessages: .single(nil), updatingMedia: .single([:]), mode: .list(search: false, reversed: self.currentIsReversed)) + let historyNode = ChatHistoryListNode(context: self.context, chatLocation: .peer(self.peerId), tagMask: tagMask, subject: .message(messageId), controllerInteraction: self.controllerInteraction, selectedMessages: .single(nil), mode: .list(search: false, reversed: self.currentIsReversed)) historyNode.preloadPages = true historyNode.stackFromBottom = true historyNode.updateFloatingHeaderOffset = { [weak self] offset, _ in diff --git a/submodules/TelegramUI/TelegramUI/PeerMediaCollectionControllerNode.swift b/submodules/TelegramUI/TelegramUI/PeerMediaCollectionControllerNode.swift index 42b7f08b9a..388e5067b4 100644 --- a/submodules/TelegramUI/TelegramUI/PeerMediaCollectionControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/PeerMediaCollectionControllerNode.swift @@ -29,7 +29,7 @@ private func historyNodeImplForMode(_ mode: PeerMediaCollectionMode, context: Ac } return node case .file: - let node = ChatHistoryListNode(context: context, chatLocation: .peer(peerId), tagMask: .file, subject: messageId.flatMap { .message($0) }, controllerInteraction: controllerInteraction, selectedMessages: selectedMessages, updatingMedia: .single([:]), mode: .list(search: true, reversed: false)) + let node = ChatHistoryListNode(context: context, chatLocation: .peer(peerId), tagMask: .file, subject: messageId.flatMap { .message($0) }, controllerInteraction: controllerInteraction, selectedMessages: selectedMessages, mode: .list(search: true, reversed: false)) node.verticalScrollIndicatorColor = theme.list.scrollIndicatorColor node.didEndScrolling = { [weak node] in guard let node = node else { @@ -40,7 +40,7 @@ private func historyNodeImplForMode(_ mode: PeerMediaCollectionMode, context: Ac node.preloadPages = true return node case .music: - let node = ChatHistoryListNode(context: context, chatLocation: .peer(peerId), tagMask: .music, subject: messageId.flatMap { .message($0) }, controllerInteraction: controllerInteraction, selectedMessages: selectedMessages, updatingMedia: .single([:]), mode: .list(search: true, reversed: false)) + let node = ChatHistoryListNode(context: context, chatLocation: .peer(peerId), tagMask: .music, subject: messageId.flatMap { .message($0) }, controllerInteraction: controllerInteraction, selectedMessages: selectedMessages, mode: .list(search: true, reversed: false)) node.verticalScrollIndicatorColor = theme.list.scrollIndicatorColor node.didEndScrolling = { [weak node] in guard let node = node else { @@ -51,7 +51,7 @@ private func historyNodeImplForMode(_ mode: PeerMediaCollectionMode, context: Ac node.preloadPages = true return node case .webpage: - let node = ChatHistoryListNode(context: context, chatLocation: .peer(peerId), tagMask: .webPage, subject: messageId.flatMap { .message($0) }, controllerInteraction: controllerInteraction, selectedMessages: selectedMessages, updatingMedia: .single([:]), mode: .list(search: true, reversed: false)) + let node = ChatHistoryListNode(context: context, chatLocation: .peer(peerId), tagMask: .webPage, subject: messageId.flatMap { .message($0) }, controllerInteraction: controllerInteraction, selectedMessages: selectedMessages, mode: .list(search: true, reversed: false)) node.verticalScrollIndicatorColor = theme.list.scrollIndicatorColor node.didEndScrolling = { [weak node] in guard let node = node else { diff --git a/submodules/TelegramUI/TelegramUI/Resources/PresentationStrings.mapping b/submodules/TelegramUI/TelegramUI/Resources/PresentationStrings.mapping index 8dab42b962..e179668f20 100644 Binary files a/submodules/TelegramUI/TelegramUI/Resources/PresentationStrings.mapping and b/submodules/TelegramUI/TelegramUI/Resources/PresentationStrings.mapping differ