diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 467f1f58b0..7406d8cc76 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -5867,6 +5867,7 @@ Sorry for the inconvenience."; "Chat.PinnedMessagesHiddenText" = "You will see the bar with pinned messages only if a new message is pinned."; "OpenFile.PotentiallyDangerousContentAlert" = "Previewing this file can potentially expose your IP address to its sender. Continue?"; +"OpenFile.Proceed" = "Proceed"; "Chat.PinnedListPreview.ShowAllMessages" = "Show All Messages"; "Chat.PinnedListPreview.UnpinAllMessages" = "Unpin All Messages"; @@ -5887,3 +5888,5 @@ Sorry for the inconvenience."; "Stats.Message.Views" = "Views"; "Stats.Message.PublicShares" = "Public Shares"; "Stats.Message.PrivateShares" = "Private Shares"; + +"Conversation.TextCopied" = "Text copied to clipboard"; diff --git a/submodules/AccountContext/Sources/GalleryController.swift b/submodules/AccountContext/Sources/GalleryController.swift index 24d7acda1f..5ac13919b4 100644 --- a/submodules/AccountContext/Sources/GalleryController.swift +++ b/submodules/AccountContext/Sources/GalleryController.swift @@ -18,8 +18,9 @@ public final class GalleryControllerActionInteraction { public let openBotCommand: (String) -> Void public let addContact: (String) -> Void public let storeMediaPlaybackState: (MessageId, Double?) -> Void + public let editMedia: (MessageId) -> Void - public init(openUrl: @escaping (String, Bool) -> Void, openUrlIn: @escaping (String) -> Void, openPeerMention: @escaping (String) -> Void, openPeer: @escaping (PeerId) -> Void, openHashtag: @escaping (String?, String) -> Void, openBotCommand: @escaping (String) -> Void, addContact: @escaping (String) -> Void, storeMediaPlaybackState: @escaping (MessageId, Double?) -> Void) { + public init(openUrl: @escaping (String, Bool) -> Void, openUrlIn: @escaping (String) -> Void, openPeerMention: @escaping (String) -> Void, openPeer: @escaping (PeerId) -> Void, openHashtag: @escaping (String?, String) -> Void, openBotCommand: @escaping (String) -> Void, addContact: @escaping (String) -> Void, storeMediaPlaybackState: @escaping (MessageId, Double?) -> Void, editMedia: @escaping (MessageId) -> Void) { self.openUrl = openUrl self.openUrlIn = openUrlIn self.openPeerMention = openPeerMention @@ -28,5 +29,6 @@ public final class GalleryControllerActionInteraction { self.openBotCommand = openBotCommand self.addContact = addContact self.storeMediaPlaybackState = storeMediaPlaybackState + self.editMedia = editMedia } } diff --git a/submodules/ChatListUI/Sources/ChatListControllerNode.swift b/submodules/ChatListUI/Sources/ChatListControllerNode.swift index 1a35682cd4..e3d192d648 100644 --- a/submodules/ChatListUI/Sources/ChatListControllerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListControllerNode.swift @@ -264,6 +264,7 @@ private final class ChatListContainerItemNode: ASDisplayNode { private(set) var emptyNode: ChatListEmptyNode? var emptyShimmerEffectNode: ChatListShimmerNode? + private var shimmerNodeOffset: CGFloat = 0.0 let listNode: ChatListNode private var validLayout: (CGSize, UIEdgeInsets, CGFloat)? @@ -285,8 +286,12 @@ private final class ChatListContainerItemNode: ASDisplayNode { return } var needsShimmerNode = false + var shimmerNodeOffset: CGFloat = 0.0 switch isEmptyState { - case let .empty(isLoading): + case let .empty(isLoading, hasArchiveInfo): + if hasArchiveInfo { + shimmerNodeOffset = 253.0 + } if isLoading { needsShimmerNode = true @@ -326,12 +331,13 @@ private final class ChatListContainerItemNode: ASDisplayNode { } } if needsShimmerNode { + strongSelf.shimmerNodeOffset = shimmerNodeOffset if strongSelf.emptyShimmerEffectNode == nil { let emptyShimmerEffectNode = ChatListShimmerNode() strongSelf.emptyShimmerEffectNode = emptyShimmerEffectNode strongSelf.insertSubnode(emptyShimmerEffectNode, belowSubnode: strongSelf.listNode) if let (size, insets, _) = strongSelf.validLayout, let offset = strongSelf.floatingHeaderOffset { - strongSelf.layoutEmptyShimmerEffectNode(node: emptyShimmerEffectNode, size: size, insets: insets, verticalOffset: offset, transition: .immediate) + strongSelf.layoutEmptyShimmerEffectNode(node: emptyShimmerEffectNode, size: size, insets: insets, verticalOffset: offset + strongSelf.shimmerNodeOffset, transition: .immediate) } } } else if let emptyShimmerEffectNode = strongSelf.emptyShimmerEffectNode { @@ -349,7 +355,7 @@ private final class ChatListContainerItemNode: ASDisplayNode { } strongSelf.floatingHeaderOffset = offset if let (size, insets, _) = strongSelf.validLayout, let emptyShimmerEffectNode = strongSelf.emptyShimmerEffectNode { - strongSelf.layoutEmptyShimmerEffectNode(node: emptyShimmerEffectNode, size: size, insets: insets, verticalOffset: offset, transition: transition) + strongSelf.layoutEmptyShimmerEffectNode(node: emptyShimmerEffectNode, size: size, insets: insets, verticalOffset: offset + strongSelf.shimmerNodeOffset, transition: transition) } } } diff --git a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift index ecfc3045ed..01ed04e0c2 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift @@ -226,25 +226,23 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo self.paneContainerNode.interaction = interaction self.paneContainerNode.currentPaneUpdated = { [weak self] key, transitionFraction, transition in - if let strongSelf = self { - var filterKey: ChatListSearchFilter? - if let key = key { - switch key { - case .chats: - filterKey = .chats - case .media: - filterKey = .media - case .links: - filterKey = .links - case .files: - filterKey = .files - case .music: - filterKey = .music - case .voice: - filterKey = .voice - } + if let strongSelf = self, let key = key { + var filterKey: ChatListSearchFilter + switch key { + case .chats: + filterKey = .chats + case .media: + filterKey = .media + case .links: + filterKey = .links + case .files: + filterKey = .files + case .music: + filterKey = .music + case .voice: + filterKey = .voice } - strongSelf.selectedFilterKey = filterKey.flatMap { .filter($0.id) } + strongSelf.selectedFilterKey = .filter(filterKey.id) strongSelf.selectedFilterKeyPromise.set(.single(strongSelf.selectedFilterKey)) strongSelf.transitionFraction = transitionFraction @@ -306,16 +304,19 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo return .single([]) } } + + let accountPeer = self.context.account.postbox.loadedPeerWithId(self.context.account.peerId) + |> take(1) - self.suggestedFiltersDisposable.set((combineLatest(suggestedPeers, self.suggestedDates.get(), self.selectedFilterKeyPromise.get(), self.searchQuery.get()) - |> mapToSignal { peers, dates, selectedFilter, searchQuery -> Signal<([Peer], [(Date?, Date, String?)], ChatListSearchFilterEntryId?), NoError> in + self.suggestedFiltersDisposable.set((combineLatest(suggestedPeers, self.suggestedDates.get(), self.selectedFilterKeyPromise.get(), self.searchQuery.get(), accountPeer) + |> mapToSignal { peers, dates, selectedFilter, searchQuery, accountPeer -> Signal<([Peer], [(Date?, Date, String?)], ChatListSearchFilterEntryId?, String?, Peer?), NoError> in if searchQuery?.isEmpty ?? true { - return .single((peers, dates, selectedFilter)) + return .single((peers, dates, selectedFilter, searchQuery, accountPeer)) } else { return (.complete() |> delay(0.25, queue: Queue.mainQueue())) - |> then(.single((peers, dates, selectedFilter))) + |> then(.single((peers, dates, selectedFilter, searchQuery, accountPeer))) } - } |> map { peers, dates, selectedFilter -> [ChatListSearchFilter] in + } |> map { peers, dates, selectedFilter, searchQuery, accountPeer -> [ChatListSearchFilter] in var suggestedFilters: [ChatListSearchFilter] = [] if !dates.isEmpty { let formatter = DateFormatter() @@ -327,8 +328,18 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo suggestedFilters.append(.date(minDate.flatMap { Int32($0.timeIntervalSince1970) }, Int32(maxDate.timeIntervalSince1970), title)) } } + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + var existingPeerIds = Set() + var peers = peers + if let accountPeer = accountPeer, let lowercasedQuery = searchQuery?.lowercased(), lowercasedQuery.count > 1 && (presentationData.strings.DialogList_SavedMessages.lowercased().hasPrefix(lowercasedQuery) || "saved messages".hasPrefix(lowercasedQuery)) { + peers.insert(accountPeer, at: 0) + } + if !peers.isEmpty && selectedFilter != .filter(ChatListSearchFilter.chats.id) { for peer in peers { + if existingPeerIds.contains(peer.id) { + continue + } let isGroup: Bool if peer.id.namespace == Namespaces.Peer.SecretChat { continue @@ -339,8 +350,15 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo } else { isGroup = false } - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - suggestedFilters.append(.peer(peer.id, isGroup, peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), peer.compactDisplayTitle)) + + var title: String = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + var compactDisplayTitle = peer.compactDisplayTitle + if peer.id == accountPeer?.id { + title = presentationData.strings.DialogList_SavedMessages + compactDisplayTitle = title + } + suggestedFilters.append(.peer(peer.id, isGroup, title, compactDisplayTitle)) + existingPeerIds.insert(peer.id) } } return suggestedFilters diff --git a/submodules/ChatListUI/Sources/Node/ChatListNode.swift b/submodules/ChatListUI/Sources/Node/ChatListNode.swift index e329990c03..69d4afd6c6 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNode.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNode.swift @@ -403,7 +403,7 @@ public enum ChatListNodeScrollPosition { public enum ChatListNodeEmptyState: Equatable { case notEmpty(containsChats: Bool) - case empty(isLoading: Bool) + case empty(isLoading: Bool, hasArchiveInfo: Bool) } public final class ChatListNode: ListView { @@ -1411,6 +1411,7 @@ public final class ChatListNode: ListView { var isEmpty = false var isLoading = false + var hasArchiveInfo = false if transition.chatListView.filteredEntries.isEmpty { isEmpty = true } else { @@ -1421,6 +1422,9 @@ public final class ChatListNode: ListView { case .GroupReferenceEntry, .HeaderEntry, .HoleEntry: break default: + if case .ArchiveIntro = entry { + hasArchiveInfo = true + } isEmpty = false break loop1 } @@ -1441,14 +1445,21 @@ public final class ChatListNode: ListView { if !hasHoles { isLoading = false } + } else { + for entry in transition.chatListView.filteredEntries.reversed().prefix(2) { + if case .ArchiveIntro = entry { + hasArchiveInfo = true + break + } + } } } let isEmptyState: ChatListNodeEmptyState if transition.chatListView.isLoading { - isEmptyState = .empty(isLoading: true) + isEmptyState = .empty(isLoading: true, hasArchiveInfo: hasArchiveInfo) } else if isEmpty { - isEmptyState = .empty(isLoading: isLoading) + isEmptyState = .empty(isLoading: isLoading, hasArchiveInfo: false) } else { var containsChats = false loop: for entry in transition.chatListView.filteredEntries { diff --git a/submodules/GZip/Sources/GZip.m b/submodules/GZip/Sources/GZip.m index 1c1df4a450..ee2da568dd 100644 --- a/submodules/GZip/Sources/GZip.m +++ b/submodules/GZip/Sources/GZip.m @@ -4,7 +4,7 @@ bool TGIsGzippedData(NSData *data) { const UInt8 *bytes = (const UInt8 *)data.bytes; - return (data.length >= 2 && bytes[0] == 0x1f && bytes[1] == 0x8b); + return data.length >= 2 && ((bytes[0] == 0x1f && bytes[1] == 0x8b) || (bytes[0] == 0x78 && bytes[1] == 0x9c)); } NSData *TGGZipData(NSData *data, float level) { diff --git a/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift b/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift index 164ffa37cf..3c643d9b7d 100644 --- a/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift +++ b/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift @@ -21,6 +21,7 @@ import TextSelectionNode private let deleteImage = generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Accessory Panels/MessageSelectionTrash"), color: .white) private let actionImage = generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Accessory Panels/MessageSelectionForward"), color: .white) +private let editImage = generateTintedImage(image: UIImage(bundleImageName: "Media Gallery/Draw"), color: .white) private let backwardImage = generateTintedImage(image: UIImage(bundleImageName: "Media Gallery/BackwardButton"), color: .white) private let forwardImage = generateTintedImage(image: UIImage(bundleImageName: "Media Gallery/ForwardButton"), color: .white) @@ -47,7 +48,7 @@ private let dateFont = Font.regular(14.0) enum ChatItemGalleryFooterContent: Equatable { case info - case fetch(status: MediaResourceStatus) + case fetch(status: MediaResourceStatus, seekable: Bool) case playback(paused: Bool, seekable: Bool) static func ==(lhs: ChatItemGalleryFooterContent, rhs: ChatItemGalleryFooterContent) -> Bool { @@ -58,8 +59,8 @@ enum ChatItemGalleryFooterContent: Equatable { } else { return false } - case let .fetch(lhsStatus): - if case let .fetch(rhsStatus) = rhs, lhsStatus == rhsStatus { + case let .fetch(lhsStatus, lhsSeekable): + if case let .fetch(rhsStatus, rhsSeekable) = rhs, lhsStatus == rhsStatus, lhsSeekable == rhsSeekable { return true } else { return false @@ -116,6 +117,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll private let contentNode: ASDisplayNode private let deleteButton: UIButton private let actionButton: UIButton + private let editButton: UIButton private let maskNode: ASDisplayNode private let scrollWrapperNode: CaptionScrollWrapperNode private let scrollNode: ASScrollNode @@ -165,11 +167,11 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll self.playbackControlButton.isHidden = true self.statusButtonNode.isHidden = true self.statusNode.isHidden = true - case let .fetch(status): + case let .fetch(status, seekable): self.authorNameNode.isHidden = true self.dateNode.isHidden = true - self.backwardButton.isHidden = true - self.forwardButton.isHidden = true + self.backwardButton.isHidden = !seekable + self.forwardButton.isHidden = !seekable if status == .Local { self.playbackControlButton.isHidden = false self.playbackControlButton.setImage(playImage, for: []) @@ -217,8 +219,8 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll } } didSet { - if let scrubberView = self.scrubberView { - scrubberView.setCollapsed(self.visibilityAlpha < 1.0 ? true : false, animated: false) + if let scrubberView = self.scrubberView { + scrubberView.setCollapsed(self.visibilityAlpha < 1.0, animated: false) self.view.addSubview(scrubberView) scrubberView.updateScrubbingVisual = { [weak self] value in guard let strongSelf = self else { @@ -253,7 +255,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll override func setVisibilityAlpha(_ alpha: CGFloat, animated: Bool) { self.visibilityAlpha = alpha self.contentNode.alpha = alpha - self.scrubberView?.setCollapsed(alpha < 1.0 ? true : false, animated: animated) + self.scrubberView?.setCollapsed(alpha < 1.0, animated: animated) } init(context: AccountContext, presentationData: PresentationData, present: @escaping (ViewController, Any?) -> Void = { _, _ in }) { @@ -268,9 +270,11 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll self.deleteButton = UIButton() self.actionButton = UIButton() + self.editButton = UIButton() self.deleteButton.setImage(deleteImage, for: [.normal]) self.actionButton.setImage(actionImage, for: [.normal]) + self.editButton.setImage(editImage, for: [.normal]) self.scrollWrapperNode = CaptionScrollWrapperNode() self.scrollWrapperNode.clipsToBounds = true @@ -340,6 +344,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll self.contentNode.view.addSubview(self.deleteButton) self.contentNode.view.addSubview(self.actionButton) +// self.contentNode.view.addSubview(self.editButton) self.contentNode.addSubnode(self.scrollWrapperNode) self.scrollWrapperNode.addSubnode(self.scrollNode) self.scrollNode.addSubnode(self.textNode) @@ -356,6 +361,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll self.deleteButton.addTarget(self, action: #selector(self.deleteButtonPressed), for: [.touchUpInside]) self.actionButton.addTarget(self, action: #selector(self.actionButtonPressed), for: [.touchUpInside]) + self.editButton.addTarget(self, action: #selector(self.editButtonPressed), for: [.touchUpInside]) self.backwardButton.addTarget(self, action: #selector(self.backwardButtonPressed), forControlEvents: .touchUpInside) self.forwardButton.addTarget(self, action: #selector(self.forwardButtonPressed), forControlEvents: .touchUpInside) @@ -436,6 +442,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll if origin == nil { self.deleteButton.isHidden = true + self.editButton.isHidden = true } } @@ -444,6 +451,16 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll let canDelete: Bool var canShare = !message.containsSecretMedia && !Namespaces.Message.allScheduled.contains(message.id.namespace) + + var canEdit = false + for media in message.media { + if media is TelegramMediaImage { + canEdit = true + break + } + } + + canEdit = canEdit && !message.containsSecretMedia if let peer = message.peers[message.id.peerId] { if peer is TelegramUser || peer is TelegramSecretChat { canDelete = true @@ -452,17 +469,21 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll } else if let channel = peer as? TelegramChannel { if message.flags.contains(.Incoming) { canDelete = channel.hasPermission(.deleteAllMessages) + canEdit = canEdit && channel.hasPermission(.editAllMessages) } else { canDelete = true } } else { canDelete = false + canEdit = false } } else { canDelete = false canShare = false + canEdit = false } + var authorNameText: String? if let author = message.effectiveAuthor { authorNameText = author.displayTitle(strings: self.strings, displayOrder: self.nameOrder) @@ -496,10 +517,10 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll } messageText = galleryCaptionStringWithAppliedEntities(message.text, entities: entities) } + + self.editButton.isHidden = message.containsSecretMedia - self.actionButton.isHidden = message.containsSecretMedia || Namespaces.Message.allScheduled.contains(message.id.namespace) - - if self.currentMessageText != messageText || canDelete != !self.deleteButton.isHidden || canShare != !self.actionButton.isHidden || self.currentAuthorNameText != authorNameText || self.currentDateText != dateText { + if self.currentMessageText != messageText || canDelete != !self.deleteButton.isHidden || canShare != !self.actionButton.isHidden || canEdit != !self.editButton.isHidden || self.currentAuthorNameText != authorNameText || self.currentDateText != dateText { self.currentMessageText = messageText if messageText.length == 0 { @@ -519,6 +540,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll self.deleteButton.isHidden = !canDelete self.actionButton.isHidden = !canShare + self.editButton.isHidden = !canEdit self.requestLayout?(.immediate) } @@ -620,20 +642,22 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll if self.textNode.isHidden || !displayCaption { panelHeight += 8.0 } else { - scrubberY = panelHeight - bottomInset - 44.0 - 41.0 + scrubberY = panelHeight - bottomInset - 44.0 - 44.0 if contentInset > 0.0 { - scrubberY -= contentInset + 3.0 + scrubberY -= contentInset } } let scrubberFrame = CGRect(origin: CGPoint(x: leftInset, y: scrubberY), size: CGSize(width: width - leftInset - rightInset, height: 34.0)) scrubberView.updateLayout(size: size, leftInset: leftInset, rightInset: rightInset, transition: .immediate) - transition.updateFrame(layer: scrubberView.layer, frame: scrubberFrame) + transition.updateBounds(layer: scrubberView.layer, bounds: CGRect(origin: CGPoint(), size: scrubberFrame.size)) + transition.updatePosition(layer: scrubberView.layer, position: CGPoint(x: scrubberFrame.midX, y: scrubberFrame.midY)) } transition.updateAlpha(node: self.textNode, alpha: displayCaption ? 1.0 : 0.0) self.actionButton.frame = CGRect(origin: CGPoint(x: leftInset, y: panelHeight - bottomInset - 44.0), size: CGSize(width: 44.0, height: 44.0)) self.deleteButton.frame = CGRect(origin: CGPoint(x: width - 44.0 - rightInset, y: panelHeight - bottomInset - 44.0), size: CGSize(width: 44.0, height: 44.0)) + self.editButton.frame = CGRect(origin: CGPoint(x: width - 44.0 - 50.0 - rightInset, y: panelHeight - bottomInset - 44.0), size: CGSize(width: 44.0, height: 44.0)) if let image = self.backwardButton.image(for: .normal) { self.backwardButton.frame = CGRect(origin: CGPoint(x: floor((width - image.size.width) / 2.0) - 66.0, y: panelHeight - bottomInset - 44.0 + 7.0), size: image.size) @@ -708,6 +732,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll self.authorNameNode.alpha = 1.0 self.deleteButton.alpha = 1.0 self.actionButton.alpha = 1.0 + self.editButton.alpha = 1.0 self.backwardButton.alpha = 1.0 self.forwardButton.alpha = 1.0 self.statusNode.alpha = 1.0 @@ -730,6 +755,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll self.authorNameNode.alpha = 0.0 self.deleteButton.alpha = 0.0 self.actionButton.alpha = 0.0 + self.editButton.alpha = 0.0 self.backwardButton.alpha = 0.0 self.forwardButton.alpha = 0.0 self.statusNode.alpha = 0.0 @@ -1049,6 +1075,13 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll } } + @objc func editButtonPressed() { + guard let message = self.currentMessage else { + return + } + self.controllerInteraction?.editMedia(message.id) + } + @objc func playbackControlPressed() { self.playbackControl?() } diff --git a/submodules/GalleryUI/Sources/GalleryController.swift b/submodules/GalleryUI/Sources/GalleryController.swift index 6bf56b2bc1..045a6b6373 100644 --- a/submodules/GalleryUI/Sources/GalleryController.swift +++ b/submodules/GalleryUI/Sources/GalleryController.swift @@ -441,9 +441,9 @@ public class GalleryController: ViewController, StandalonePresentableController namespaces = .not(Namespaces.Message.allScheduled) } return context.account.postbox.aroundMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), anchor: .index(message!.index), count: 50, clipHoles: false, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tagMask: tags, namespaces: namespaces, orderStatistics: [.combinedLocation]) - |> mapToSignal { (view, _, _) -> Signal in - let mapped = GalleryMessageHistoryView.view(view) - return .single(mapped) + |> mapToSignal { (view, _, _) -> Signal in + let mapped = GalleryMessageHistoryView.view(view) + return .single(mapped) } } else { return .single(GalleryMessageHistoryView.entries([MessageHistoryEntry(message: message!, isRead: false, location: nil, monthLocation: nil, attributes: MutableMessageHistoryEntryAttributes(authorIsContact: false))], false, false)) @@ -911,6 +911,11 @@ public class GalleryController: ViewController, StandalonePresentableController if let strongSelf = self { strongSelf.replaceRootController(controller, ready) } + }, editMedia: { [weak self] messageId in + if let strongSelf = self { + strongSelf.dismiss(forceAway: true) + strongSelf.actionInteraction?.editMedia(messageId) + } }) self.displayNode = GalleryControllerNode(controllerInteraction: controllerInteraction) self.displayNodeDidLoad() diff --git a/submodules/GalleryUI/Sources/GalleryFooterContentNode.swift b/submodules/GalleryUI/Sources/GalleryFooterContentNode.swift index d1c25e9205..679c685ada 100644 --- a/submodules/GalleryUI/Sources/GalleryFooterContentNode.swift +++ b/submodules/GalleryUI/Sources/GalleryFooterContentNode.swift @@ -3,16 +3,19 @@ import UIKit import AsyncDisplayKit import Display import SwiftSignalKit +import Postbox public final class GalleryControllerInteraction { public let presentController: (ViewController, ViewControllerPresentationArguments?) -> Void public let dismissController: () -> Void public let replaceRootController: (ViewController, Promise?) -> Void + public let editMedia: (MessageId) -> Void - public init(presentController: @escaping (ViewController, ViewControllerPresentationArguments?) -> Void, dismissController: @escaping () -> Void, replaceRootController: @escaping (ViewController, Promise?) -> Void) { + public init(presentController: @escaping (ViewController, ViewControllerPresentationArguments?) -> Void, dismissController: @escaping () -> Void, replaceRootController: @escaping (ViewController, Promise?) -> Void, editMedia: @escaping (MessageId) -> Void) { self.presentController = presentController self.dismissController = dismissController self.replaceRootController = replaceRootController + self.editMedia = editMedia } } diff --git a/submodules/GalleryUI/Sources/GalleryPagerNode.swift b/submodules/GalleryUI/Sources/GalleryPagerNode.swift index f6ee2f8308..199d822c0b 100644 --- a/submodules/GalleryUI/Sources/GalleryPagerNode.swift +++ b/submodules/GalleryUI/Sources/GalleryPagerNode.swift @@ -517,7 +517,7 @@ public final class GalleryPagerNode: ASDisplayNode, UIScrollViewDelegate, UIGest } if self.itemNodes.isEmpty { let node = self.makeNodeForItem(at: self.centralItemIndex ?? 0, synchronous: synchronous) - node.frame = CGRect(origin: CGPoint(), size: scrollView.bounds.size) + node.frame = CGRect(origin: CGPoint(), size: self.scrollView.bounds.size) if let containerLayout = self.containerLayout { node.containerLayoutUpdated(containerLayout.0, navigationBarHeight: containerLayout.1, transition: .immediate) } diff --git a/submodules/GalleryUI/Sources/GalleryThumbnailContainerNode.swift b/submodules/GalleryUI/Sources/GalleryThumbnailContainerNode.swift index 2c6202d330..0af6fc4002 100644 --- a/submodules/GalleryUI/Sources/GalleryThumbnailContainerNode.swift +++ b/submodules/GalleryUI/Sources/GalleryThumbnailContainerNode.swift @@ -125,9 +125,15 @@ public final class GalleryThumbnailContainerNode: ASDisplayNode, UIScrollViewDel self.items = items self.itemNodes = itemNodes } + + var updatedIndexOnly = false + if let centralIndexAndProgress = self.centralIndexAndProgress, centralIndexAndProgress.0 != centralIndex, centralIndexAndProgress.1 == progress { + updatedIndexOnly = true + } + self.centralIndexAndProgress = (centralIndex, progress) if let size = self.currentLayout { - self.updateLayout(size: size, transition: .immediate) + self.updateLayout(size: size, transition: updatedIndexOnly ? .animated(duration: 0.2, curve: .spring) : .immediate) } } diff --git a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift index 8591cd76b1..414d9441b5 100644 --- a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift @@ -449,8 +449,13 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { if let (previousLayout, _) = self.validLayout, self.dismissOnOrientationChange, previousLayout.size.width > previousLayout.size.height && previousLayout.size.height == layout.size.width { dismiss = true } + let hadLayout = self.validLayout != nil self.validLayout = (layout, navigationBarHeight) + if !hadLayout { + self.zoomableContent = zoomableContent + } + let statusDiameter: CGFloat = 50.0 let statusFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - statusDiameter) / 2.0), y: floor((layout.size.height - statusDiameter) / 2.0)), size: CGSize(width: statusDiameter, height: statusDiameter)) transition.updateFrame(node: self.statusButtonNode, frame: statusFrame) @@ -530,7 +535,6 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { let mediaManager = item.context.sharedContext.mediaManager let videoNode = UniversalVideoNode(postbox: item.context.account.postbox, audioSession: mediaManager.audioSession, manager: mediaManager.universalVideoManager, decoration: GalleryVideoDecoration(), content: item.content, priority: .gallery) - let videoScale: CGFloat if item.content is WebEmbedVideoContent { videoScale = 1.0 @@ -578,6 +582,8 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { self.requiresDownload = true var mediaFileStatus: Signal = .single(nil) + + var hintSeekable = false if let contentInfo = item.contentInfo, case let .message(message) = contentInfo { if Namespaces.Message.allScheduled.contains(message.id.namespace) { disablePictureInPicture = true @@ -611,6 +617,12 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { } } if let file = file { + for attribute in file.attributes { + if case let .Video(duration, _, _) = attribute, duration >= 30 { + hintSeekable = true + break + } + } let status = messageMediaFileStatus(context: item.context, messageId: message.id, file: file) if !isWebpage { self.scrubberView.setFetchStatusSignal(status, strings: self.presentationData.strings, decimalSeparator: self.presentationData.dateTimeFormat.decimalSeparator, fileSize: file.size) @@ -634,7 +646,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { var initialBuffering = false var playing = false var isPaused = true - var seekable = false + var seekable = hintSeekable var hasStarted = false var displayProgress = true if let value = value { @@ -682,13 +694,15 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { if !content.enableSound { isPaused = false } - } else { + } else if strongSelf.actionAtEnd == .stop { strongSelf.updateControlsVisibility(true) strongSelf.controlsTimer?.invalidate() strongSelf.controlsTimer = nil } } - seekable = value.duration >= 30.0 + if !value.duration.isZero { + seekable = value.duration >= 30.0 + } } if strongSelf.isCentral && playing && strongSelf.previousPlaying != true && !disablePlayerControls { @@ -749,7 +763,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { if hasStarted || strongSelf.didPause { strongSelf.footerContentNode.content = .playback(paused: true, seekable: seekable) } else if let fetchStatus = fetchStatus, !strongSelf.requiresDownload { - strongSelf.footerContentNode.content = .fetch(status: fetchStatus) + strongSelf.footerContentNode.content = .fetch(status: fetchStatus, seekable: seekable) } } else { strongSelf.footerContentNode.content = .playback(paused: false, seekable: seekable) @@ -773,11 +787,17 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { } self._rightBarButtonItems.set(.single(barButtonItems)) - videoNode.playbackCompleted = { [weak videoNode] in + videoNode.playbackCompleted = { [weak self, weak videoNode] in Queue.mainQueue().async { item.playbackCompleted() - if !isAnimated { + if let strongSelf = self, !isAnimated { videoNode?.seek(0.0) + + if strongSelf.actionAtEnd == .stop { + strongSelf.updateControlsVisibility(true) + strongSelf.controlsTimer?.invalidate() + strongSelf.controlsTimer = nil + } } } } diff --git a/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift b/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift index 91f58c4643..34fc1e1adf 100644 --- a/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift +++ b/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift @@ -208,6 +208,7 @@ public final class SecretMediaPreviewController: ViewController { }, dismissController: { [weak self] in self?.dismiss(forceAway: true) }, replaceRootController: { _, _ in + }, editMedia: { _ in }) self.displayNode = SecretMediaPreviewControllerNode(controllerInteraction: controllerInteraction) self.displayNodeDidLoad() diff --git a/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift b/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift index 26019a1434..161e3e103c 100644 --- a/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift +++ b/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift @@ -1228,7 +1228,15 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate { } if let map = media.media as? TelegramMediaMap { - let controller = legacyLocationController(message: nil, mapMedia: map, context: self.context, openPeer: { _ in }, sendLiveLocation: { _, _ in }, stopLiveLocation: { }, openUrl: { _ in }) + let controllerParams = LocationViewParams(sendLiveLocation: { _ in + }, stopLiveLocation: { _ in + }, openUrl: { _ in }, openPeer: { _ in + }, showAll: false) + + let peer = TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: 1), accessHash: nil, firstName: "", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: []) + let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer, text: "", attributes: [], media: [map], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: []) + + let controller = LocationViewController(context: self.context, subject: message, params: controllerParams) self.pushController(controller) return } diff --git a/submodules/InstantPageUI/Sources/InstantPageGalleryController.swift b/submodules/InstantPageUI/Sources/InstantPageGalleryController.swift index 91b2d00545..9d661bcd87 100644 --- a/submodules/InstantPageUI/Sources/InstantPageGalleryController.swift +++ b/submodules/InstantPageUI/Sources/InstantPageGalleryController.swift @@ -358,12 +358,13 @@ public class InstantPageGalleryController: ViewController, StandalonePresentable if let strongSelf = self { strongSelf.present(controller, in: .window(.root), with: arguments, blockInteraction: true) } - }, dismissController: { [weak self] in - self?.dismiss(forceAway: true) - }, replaceRootController: { [weak self] controller, ready in - if let strongSelf = self { - strongSelf.replaceRootController(controller, ready) - } + }, dismissController: { [weak self] in + self?.dismiss(forceAway: true) + }, replaceRootController: { [weak self] controller, ready in + if let strongSelf = self { + strongSelf.replaceRootController(controller, ready) + } + }, editMedia: { _ in }) self.displayNode = GalleryControllerNode(controllerInteraction: controllerInteraction) self.displayNodeDidLoad() diff --git a/submodules/InstantPageUI/Sources/InstantPageTextItem.swift b/submodules/InstantPageUI/Sources/InstantPageTextItem.swift index 56b8f119d3..c9483f1fba 100644 --- a/submodules/InstantPageUI/Sources/InstantPageTextItem.swift +++ b/submodules/InstantPageUI/Sources/InstantPageTextItem.swift @@ -753,8 +753,8 @@ func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFlo let cfRunRange = CTRunGetStringRange(run) let runRange = NSMakeRange(cfRunRange.location == kCFNotFound ? NSNotFound : cfRunRange.location, cfRunRange.length) string.enumerateAttributes(in: runRange, options: []) { attributes, range, _ in - if let id = attributes[NSAttributedString.Key.init(rawValue: InstantPageMediaIdAttribute)] as? Int64, let dimensions = attributes[NSAttributedString.Key.init(rawValue: InstantPageMediaDimensionsAttribute)] as? CGSize { - var imageFrame = CGRect(origin: CGPoint(), size: dimensions) + if let id = attributes[NSAttributedString.Key.init(rawValue: InstantPageMediaIdAttribute)] as? Int64, let dimensions = attributes[NSAttributedString.Key.init(rawValue: InstantPageMediaDimensionsAttribute)] as? PixelDimensions { + var imageFrame = CGRect(origin: CGPoint(), size: dimensions.cgSize) let xOffset = CTLineGetOffsetForStringIndex(line, CTRunGetStringRange(run).location, nil) let yOffset = fontLineHeight.isZero ? 0.0 : floorToScreenPixels((fontLineHeight - imageFrame.size.height) / 2.0) diff --git a/submodules/ItemListStickerPackItem/Sources/ItemListStickerPackItem.swift b/submodules/ItemListStickerPackItem/Sources/ItemListStickerPackItem.swift index 52baa70a90..6a691bd2bb 100644 --- a/submodules/ItemListStickerPackItem/Sources/ItemListStickerPackItem.swift +++ b/submodules/ItemListStickerPackItem/Sources/ItemListStickerPackItem.swift @@ -457,9 +457,9 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode { } if let editableControlSizeAndApply = editableControlSizeAndApply { - let editableControlFrame = CGRect(origin: CGPoint(x: params.leftInset + revealOffset, y: 0.0), size: CGSize(width: editableControlSizeAndApply.0, height: layout.size.height)) + let editableControlFrame = CGRect(origin: CGPoint(x: params.leftInset + revealOffset, y: 0.0), size: CGSize(width: editableControlSizeAndApply.0, height: layout.contentSize.height)) if strongSelf.editableControlNode == nil { - let editableControlNode = editableControlSizeAndApply.1(layout.size.height) + let editableControlNode = editableControlSizeAndApply.1(layout.contentSize.height) editableControlNode.tapped = { if let strongSelf = self { strongSelf.setRevealOptionsOpened(true, animated: true) diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/LegacyComponents.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/LegacyComponents.h index 18f24fd501..92120ba582 100644 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/LegacyComponents.h +++ b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/LegacyComponents.h @@ -136,15 +136,7 @@ #import #import #import -#import -#import -#import #import -#import -#import -#import -#import -#import #import #import #import @@ -267,8 +259,6 @@ #import #import #import -#import -#import #import #import #import @@ -294,7 +284,6 @@ #import #import #import -#import #import #import #import diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/LegacyComponentsGlobals.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/LegacyComponentsGlobals.h index 304fe2cd9f..ee8dcc1e23 100644 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/LegacyComponentsGlobals.h +++ b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/LegacyComponentsGlobals.h @@ -58,10 +58,6 @@ typedef enum { - (id)accessChecker; -- (SSignal *)stickerPacksSignal; -- (SSignal *)maskStickerPacksSignal; -- (SSignal *)recentStickerMasksSignal; - - (id)requestAudioSession:(TGAudioSessionType)type interrupted:(void (^)())interrupted; - (SThreadPool *)sharedMediaImageProcessingThreadPool; @@ -71,11 +67,6 @@ typedef enum { - (NSString *)localDocumentDirectoryForLocalDocumentId:(int64_t)localDocumentId version:(int32_t)version; - (NSString *)localDocumentDirectoryForDocumentId:(int64_t)documentId version:(int32_t)version; -- (SSignal *)jsonForHttpLocation:(NSString *)httpLocation; -- (SSignal *)dataForHttpLocation:(NSString *)httpLocation; - -- (NSOperation *)makeHTTPRequestOperationWithRequest:(NSURLRequest *)request; - - (void)pausePictureInPicturePlayback; - (void)resumePictureInPicturePlayback; - (void)maybeReleaseVolumeOverlay; diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGLocationLiveElapsedView.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGLocationLiveElapsedView.h deleted file mode 100644 index 50f45e0d20..0000000000 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGLocationLiveElapsedView.h +++ /dev/null @@ -1,8 +0,0 @@ -#import - -@interface TGLocationLiveElapsedView : UIView - -- (void)setColor:(UIColor *)color; -- (void)setRemaining:(int32_t)remaining period:(int32_t)period; - -@end diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGLocationLiveSessionItemView.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGLocationLiveSessionItemView.h deleted file mode 100644 index eda2a3ab76..0000000000 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGLocationLiveSessionItemView.h +++ /dev/null @@ -1,12 +0,0 @@ -#import -#import -#import - -@class TGUser; -@class TGMessage; - -@interface TGLocationLiveSessionItemView : TGMenuSheetButtonItemView - -- (instancetype)initWithMessage:(TGMessage *)message peer:(id)peer remaining:(SSignal *)remaining action:(void (^)(void))action; - -@end diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGLocationMapViewController.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGLocationMapViewController.h deleted file mode 100644 index 3a7484e750..0000000000 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGLocationMapViewController.h +++ /dev/null @@ -1,84 +0,0 @@ -#import -#import - -#import - -#import - -@class TGLocationMapView; -@class TGLocationOptionsView; - -@class TGSearchBarPallete; - -@interface TGLocationPallete : NSObject - -@property (nonatomic, readonly) UIColor *backgroundColor; -@property (nonatomic, readonly) UIColor *selectionColor; -@property (nonatomic, readonly) UIColor *separatorColor; -@property (nonatomic, readonly) UIColor *textColor; -@property (nonatomic, readonly) UIColor *secondaryTextColor; -@property (nonatomic, readonly) UIColor *accentColor; -@property (nonatomic, readonly) UIColor *destructiveColor; -@property (nonatomic, readonly) UIColor *locationColor; -@property (nonatomic, readonly) UIColor *liveLocationColor; -@property (nonatomic, readonly) UIColor *iconColor; -@property (nonatomic, readonly) UIColor *sectionHeaderBackgroundColor; -@property (nonatomic, readonly) UIColor *sectionHeaderTextColor; -@property (nonatomic, readonly) TGSearchBarPallete *searchBarPallete; -@property (nonatomic, readonly) UIImage *avatarPlaceholder; - -+ (instancetype)palleteWithBackgroundColor:(UIColor *)backgroundColor selectionColor:(UIColor *)selectionColor separatorColor:(UIColor *)separatorColor textColor:(UIColor *)textColor secondaryTextColor:(UIColor *)secondaryTextColor accentColor:(UIColor *)accentColor destructiveColor:(UIColor *)destructiveColor locationColor:(UIColor *)locationColor liveLocationColor:(UIColor *)liveLocationColor iconColor:(UIColor *)iconColor sectionHeaderBackgroundColor:(UIColor *)sectionHeaderBackgroundColor sectionHeaderTextColor:(UIColor *)sectionHeaderTextColor searchBarPallete:(TGSearchBarPallete *)searchBarPallete avatarPlaceholder:(UIImage *)avatarPlaceholder; - -@end - -@interface TGLocationMapViewController : TGViewController -{ - CLLocationManager *_locationManager; - bool _locationServicesDisabled; - - CGFloat _tableViewTopInset; - CGFloat _tableViewBottomInset; - UITableView *_tableView; - UIActivityIndicatorView *_activityIndicator; - UILabel *_messageLabel; - - UIView *_mapViewWrapper; - TGLocationMapView *_mapView; - TGLocationOptionsView *_optionsView; - UIImageView *_edgeView; - UIImageView *_edgeHighlightView; -} - -@property (nonatomic, copy) void (^liveLocationStarted)(CLLocationCoordinate2D coordinate, int32_t period); -@property (nonatomic, copy) void (^liveLocationStopped)(void); - -@property (nonatomic, strong) TGLocationPallete *pallete; -@property (nonatomic, readonly, strong) UIView *locationMapView; - -- (void)userLocationButtonPressed; - -- (void)setMapCenterCoordinate:(CLLocationCoordinate2D)coordinate offset:(CGPoint)offset animated:(bool)animated; -- (void)setMapCenterCoordinate:(CLLocationCoordinate2D)coordinate span:(MKCoordinateSpan)span offset:(CGPoint)offset animated:(bool)animated; - -- (void)updateInsets; -- (void)updateMapHeightAnimated:(bool)animated; - -- (CGFloat)visibleContentHeight; -- (CGFloat)mapHeight; -- (CGFloat)safeAreaInsetBottom; - -- (bool)hasUserLocation; -- (SSignal *)userLocationSignal; -- (bool)locationServicesDisabled; -- (void)updateLocationAvailability; - -@property (nonatomic, strong) id receivingPeer; -- (void)_presentLiveLocationMenu:(CLLocationCoordinate2D)coordinate dismissOnCompletion:(bool)dismissOnCompletion; -- (CGRect)_liveLocationMenuSourceRect; -- (void)_willStartOwnLiveLocation; - -@end - -extern const CGFloat TGLocationMapInset; -extern const CGFloat TGLocationMapClipHeight; -extern const MKCoordinateSpan TGLocationDefaultSpan; diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGLocationPickerController.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGLocationPickerController.h deleted file mode 100644 index 6f76489ad3..0000000000 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGLocationPickerController.h +++ /dev/null @@ -1,29 +0,0 @@ -#import -#import - -#import - -@class TGVenueAttachment; -@class TGUser; -@class TGMessage; - -typedef enum { - TGLocationPickerControllerDefaultIntent, - TGLocationPickerControllerCustomLocationIntent -} TGLocationPickerControllerIntent; - -@interface TGLocationPickerController : TGLocationMapViewController - -@property (nonatomic, copy) void (^locationPicked)(CLLocationCoordinate2D coordinate, TGVenueAttachment *venue, NSString *address); - -@property (nonatomic, copy) SSignal *(^nearbyPlacesSignal)(NSString *query, CLLocation *coordinate); - -- (instancetype)initWithContext:(id)context intent:(TGLocationPickerControllerIntent)intent; - -- (void)setLiveLocationsSignal:(SSignal *)signal; -@property (nonatomic, copy) SSignal *(^remainingTimeForMessage)(TGMessage *message); - -@property (nonatomic, strong) id peer; -@property (nonatomic, assign) bool allowLiveLocationSharing; - -@end diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGLocationPulseView.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGLocationPulseView.h deleted file mode 100644 index 9df57ec177..0000000000 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGLocationPulseView.h +++ /dev/null @@ -1,8 +0,0 @@ -#import - -@interface TGLocationPulseView : UIView - -- (void)start; -- (void)stop; - -@end diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGLocationVenue.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGLocationVenue.h deleted file mode 100644 index f93d5bece2..0000000000 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGLocationVenue.h +++ /dev/null @@ -1,34 +0,0 @@ -#import - -@class TGVenueAttachment; -@class TGLocationMediaAttachment; - -@interface TGLocationVenue : NSObject - -@property (nonatomic, readonly) NSString *identifier; -@property (nonatomic, readonly) NSString *name; -@property (nonatomic, readonly) NSString *displayAddress; -@property (nonatomic, readonly) CLLocationCoordinate2D coordinate; -@property (nonatomic, readonly) NSString *categoryName; -@property (nonatomic, readonly) NSURL *categoryIconUrl; - -@property (nonatomic, readonly) NSString *provider; - -@property (readonly, nonatomic) NSString *country; -@property (readonly, nonatomic) NSString *state; -@property (readonly, nonatomic) NSString *city; -@property (readonly, nonatomic) NSString *address; -@property (readonly, nonatomic) NSString *crossStreet; -@property (readonly, nonatomic) NSString *street; - -- (TGVenueAttachment *)venueAttachment; - -+ (TGLocationVenue *)venueWithFoursquareDictionary:(NSDictionary *)dictionary; -+ (TGLocationVenue *)venueWithGooglePlacesDictionary:(NSDictionary *)dictionary; - -+ (TGLocationVenue *)venueWithLocationAttachment:(TGLocationMediaAttachment *)attachment; - -@end - -extern NSString *const TGLocationGooglePlacesVenueProvider; -extern NSString *const TGLocationFoursquareVenueProvider; diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGLocationViewController.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGLocationViewController.h deleted file mode 100644 index a14cf034c4..0000000000 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGLocationViewController.h +++ /dev/null @@ -1,59 +0,0 @@ -#import -#import - -#import - -@class TGLocationMediaAttachment; -@class TGVenueAttachment; -@class TGMenuSheetController; -@class TGMessage; -@class TGUser; - -@interface TGLiveLocation : NSObject - -@property (nonatomic, strong, readonly) TGMessage *message; -@property (nonatomic, strong, readonly) id peer; -@property (nonatomic, readonly) bool hasOwnSession; -@property (nonatomic, readonly) bool isOwnLocation; -@property (nonatomic, readonly) bool isExpired; - -- (instancetype)initWithMessage:(TGMessage *)message peer:(id)peer hasOwnSession:(bool)hasOwnSession isOwnLocation:(bool)isOwnLocation isExpired:(bool)isExpired; -- (instancetype)initWithMessage:(TGMessage *)message peer:(id)peer; - -- (int64_t)peerId; - -@end - -@interface TGLocationViewController : TGLocationMapViewController; - -@property (nonatomic, assign) bool modalMode; -@property (nonatomic, assign) bool previewMode; - -@property (nonatomic, assign) bool allowLiveLocationSharing; -@property (nonatomic, assign) bool zoomToFitAllLocationsOnScreen; - - -@property (nonatomic, copy) void (^presentActionsMenu)(TGLocationMediaAttachment *, bool); -@property (nonatomic, copy) bool (^presentShareMenu)(TGMenuSheetController *, CLLocationCoordinate2D); -@property (nonatomic, copy) bool (^presentOpenInMenu)(TGLocationViewController *, TGLocationMediaAttachment *, bool, void (^)(TGMenuSheetController *)); -@property (nonatomic, copy) void (^shareAction)(NSArray *peerIds, NSString *caption); - -@property (nonatomic, copy) void (^openLocation)(TGMessage *message); -@property (nonatomic, copy) void (^onViewDidAppear)(void); - -@property (nonatomic, copy) void (^updateRightBarItem)(UIBarButtonItem *, bool, bool); - -@property (nonatomic, readonly) UIButton *directionsButton; - -@property (nonatomic, copy) SSignal *(^remainingTimeForMessage)(TGMessage *message); - -- (instancetype)initWithContext:(id)context liveLocation:(TGLiveLocation *)liveLocation; -- (instancetype)initWithContext:(id)context locationAttachment:(TGLocationMediaAttachment *)locationAttachment peer:(id)peer color:(UIColor *)color; -- (instancetype)initWithContext:(id)context message:(TGMessage *)message peer:(id)peer color:(UIColor *)color; - -- (void)actionsButtonPressed; - -- (void)setLiveLocationsSignal:(SSignal *)signal; -- (void)setFrequentUpdatesHandle:(id)disposable; - -@end diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGLocationWavesView.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGLocationWavesView.h deleted file mode 100644 index 584ccc0a16..0000000000 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGLocationWavesView.h +++ /dev/null @@ -1,11 +0,0 @@ -#import - -@interface TGLocationWavesView : UIView - -@property (nonatomic, strong) UIColor *color; - -- (void)invalidate; -- (void)start; -- (void)stop; - -@end diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGMediaPickerGalleryModel.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGMediaPickerGalleryModel.h index b65cc68ae5..af5300772c 100644 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGMediaPickerGalleryModel.h +++ b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGMediaPickerGalleryModel.h @@ -50,4 +50,6 @@ - (instancetype)initWithContext:(id)context items:(NSArray *)items focusItem:(id)focusItem selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions hasSelectionPanel:(bool)hasSelectionPanel hasCamera:(bool)hasCamera recipientName:(NSString *)recipientName; +- (void)presentPhotoEditorForItem:(id)item tab:(TGPhotoEditorTab)tab; + @end diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoVideoEditor.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoVideoEditor.h index cff37cb96a..7667dcf382 100644 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoVideoEditor.h +++ b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoVideoEditor.h @@ -4,6 +4,6 @@ + (void)presentWithContext:(id)context parentController:(TGViewController *)parentController image:(UIImage *)image video:(NSURL *)video didFinishWithImage:(void (^)(UIImage *image))didFinishWithImage didFinishWithVideo:(void (^)(UIImage *image, NSURL *url, TGVideoEditAdjustments *adjustments))didFinishWithVideo dismissed:(void (^)(void))dismissed; -+ (void)presentWithContext:(id)context controller:(TGViewController *)controller caption:(NSString *)caption entities:(NSArray *)entities withItem:(id)item recipientName:(NSString *)recipientName stickersContext:(id)stickersContext completion:(void (^)(id, TGMediaEditingContext *))completion dismissed:(void (^)())dismissed; ++ (void)presentWithContext:(id)context controller:(TGViewController *)controller caption:(NSString *)caption entities:(NSArray *)entities withItem:(id)item paint:(bool)paint recipientName:(NSString *)recipientName stickersContext:(id)stickersContext completion:(void (^)(id, TGMediaEditingContext *))completion dismissed:(void (^)())dismissed; @end diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGSearchBar.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGSearchBar.h deleted file mode 100644 index feab180b95..0000000000 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGSearchBar.h +++ /dev/null @@ -1,94 +0,0 @@ -#import - -@class TGSearchBar; - -typedef enum { - TGSearchBarStyleDefault = 0, - TGSearchBarStyleDark = 1, - TGSearchBarStyleLight = 2, - TGSearchBarStyleLightPlain = 3, - TGSearchBarStyleLightAlwaysPlain = 4, - TGSearchBarStyleHeader = 5, - TGSearchBarStyleKeyboard = 6 -} TGSearchBarStyle; - -@protocol TGSearchBarDelegate - -- (void)searchBar:(TGSearchBar *)searchBar willChangeHeight:(CGFloat)newHeight; - -@end - -@interface TGSearchBarPallete : NSObject - -@property (nonatomic, readonly) bool isDark; -@property (nonatomic, readonly) UIColor *backgroundColor; -@property (nonatomic, readonly) UIColor *highContrastBackgroundColor; -@property (nonatomic, readonly) UIColor *textColor; -@property (nonatomic, readonly) UIColor *placeholderColor; -@property (nonatomic, readonly) UIImage *clearIcon; -@property (nonatomic, readonly) UIColor *barBackgroundColor; -@property (nonatomic, readonly) UIColor *barSeparatorColor; -@property (nonatomic, readonly) UIColor *plainBackgroundColor; -@property (nonatomic, readonly) UIColor *accentColor; -@property (nonatomic, readonly) UIColor *accentContrastColor; -@property (nonatomic, readonly) UIColor *menuBackgroundColor; -@property (nonatomic, readonly) UIImage *segmentedControlBackgroundImage; -@property (nonatomic, readonly) UIImage *segmentedControlSelectedImage; -@property (nonatomic, readonly) UIImage *segmentedControlHighlightedImage; -@property (nonatomic, readonly) UIImage *segmentedControlDividerImage; - -+ (instancetype)palleteWithDark:(bool)dark backgroundColor:(UIColor *)backgroundColor highContrastBackgroundColor:(UIColor *)highContrastBackgroundColor textColor:(UIColor *)textColor placeholderColor:(UIColor *)placeholderColor clearIcon:(UIImage *)clearIcon barBackgroundColor:(UIColor *)barBackgroundColor barSeparatorColor:(UIColor *)barSeparatorColor plainBackgroundColor:(UIColor *)plainBackgroundColor accentColor:(UIColor *)accentColor accentContrastColor:(UIColor *)accentContrastColor menuBackgroundColor:(UIColor *)menuBackgroundColor segmentedControlBackgroundImage:(UIImage *)segmentedControlBackgroundImage segmentedControlSelectedImage:(UIImage *)segmentedControlSelectedImage segmentedControlHighlightedImage:(UIImage *)segmentedControlHighlightedImage segmentedControlDividerImage:(UIImage *)segmentedControlDividerImage; - -@end - -@interface TGSearchBar : UIView - -+ (CGFloat)searchBarBaseHeight; -+ (CGFloat)searchBarScopeHeight; -- (CGFloat)baseHeight; - -@property (nonatomic, copy) void (^clearPrefix)(bool); - -@property (nonatomic, assign) UIEdgeInsets safeAreaInset; - -@property (nonatomic, weak) id delegate; -@property (nonatomic) bool highContrast; - -@property (nonatomic, strong) UITextField *customTextField; -@property (nonatomic, readonly) UITextField *maybeCustomTextField; - -@property (nonatomic, strong) UIImageView *customBackgroundView; -@property (nonatomic, strong) UIImageView *customActiveBackgroundView; - -@property (nonatomic, strong) NSArray *customScopeButtonTitles; -@property (nonatomic) NSInteger selectedScopeButtonIndex; -@property (nonatomic) bool showsScopeBar; -@property (nonatomic) bool scopeBarCollapsed; - -@property (nonatomic) bool searchBarShouldShowScopeControl; -@property (nonatomic) bool alwaysExtended; -@property (nonatomic) bool hidesCancelButton; - -@property (nonatomic, strong) UIButton *customCancelButton; - -@property (nonatomic) TGSearchBarStyle style; -@property (nonatomic, strong) NSString *text; -@property (nonatomic, strong) NSString *placeholder; -@property (nonatomic, strong) NSAttributedString *prefixText; - -@property (nonatomic) bool showActivity; -@property (nonatomic) bool delayActivity; - -- (instancetype)initWithFrame:(CGRect)frame style:(TGSearchBarStyle)style; - -- (void)setShowsCancelButton:(bool)showsCancelButton animated:(bool)animated; - -- (void)setCustomScopeBarHidden:(bool)hidden; - -- (void)updateClipping:(CGFloat)clippedHeight; - -- (void)localizationUpdated; - -- (void)setPallete:(TGSearchBarPallete *)pallete; - -@end diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGSearchDisplayMixin.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGSearchDisplayMixin.h deleted file mode 100644 index 18f042edf5..0000000000 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGSearchDisplayMixin.h +++ /dev/null @@ -1,46 +0,0 @@ -#import - -@class TGSearchDisplayMixin; -@class TGSearchBar; - -@protocol TGSearchDisplayMixinDelegate - -@required - -- (UITableView *)createTableViewForSearchMixin:(TGSearchDisplayMixin *)searchMixin; -- (UIView *)referenceViewForSearchResults; -- (void)searchMixin:(TGSearchDisplayMixin *)searchMixin hasChangedSearchQuery:(NSString *)searchQuery withScope:(int)scope; - -@optional - -- (void)searchMixinWillActivate:(bool)animated; -- (void)searchMixinWillDeactivate:(bool)animated; - -@end - -@interface TGSearchDisplayMixin : NSObject - -@property (nonatomic, weak) id delegate; - -@property (nonatomic, strong) TGSearchBar *searchBar; -@property (nonatomic) bool isActive; -@property (nonatomic, strong) UITableView *searchResultsTableView; -@property (nonatomic) bool alwaysShowsCancelButton; - -@property (nonatomic) bool searchResultsTableViewHidden; - -@property (nonatomic) bool simpleLayout; - -- (void)setSearchResultsTableViewHidden:(bool)searchResultsTableViewHidden animated:(bool)animated; - -- (void)setIsActive:(bool)isActive animated:(bool)animated; - -- (void)controllerInsetUpdated:(UIEdgeInsets)controllerInset; -- (void)controllerLayoutUpdated:(CGSize)layoutSize; - -- (void)reloadSearchResults; -- (void)resignResponderIfAny; - -- (void)unload; - -@end diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/AttachmentMenuInteractiveCameraIcon.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/AttachmentMenuInteractiveCameraIcon.png deleted file mode 100644 index 4edffbcd9e..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/AttachmentMenuInteractiveCameraIcon.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/AttachmentMenuInteractiveCameraIcon@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/AttachmentMenuInteractiveCameraIcon@2x.png deleted file mode 100644 index daadae95df..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/AttachmentMenuInteractiveCameraIcon@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/AttachmentMenuInteractiveCameraIcon@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/AttachmentMenuInteractiveCameraIcon@3x.png deleted file mode 100644 index aca9c574b7..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/AttachmentMenuInteractiveCameraIcon@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/AttachmentTipIcons@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/AttachmentTipIcons@2x.png deleted file mode 100644 index eb05b2f187..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/AttachmentTipIcons@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CalloutAccessory@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CalloutAccessory@2x.png deleted file mode 100644 index 636dbe1100..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CalloutAccessory@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CalloutArrow@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CalloutArrow@2x.png deleted file mode 100644 index 710487e0db..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CalloutArrow@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CalloutArrow_Highlighted@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CalloutArrow_Highlighted@2x.png deleted file mode 100644 index ea5c91b128..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CalloutArrow_Highlighted@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CalloutBackground@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CalloutBackground@2x.png deleted file mode 100644 index d30a7daf77..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CalloutBackground@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CalloutBackground_Highlighted@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CalloutBackground_Highlighted@2x.png deleted file mode 100644 index 72ed8be57d..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CalloutBackground_Highlighted@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CalloutDrivingBackground@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CalloutDrivingBackground@2x.png deleted file mode 100644 index 1812b32a09..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CalloutDrivingBackground@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CalloutDrivingBackground_Highlighted@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CalloutDrivingBackground_Highlighted@2x.png deleted file mode 100644 index 2697187254..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CalloutDrivingBackground_Highlighted@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CalloutDrivingIcon@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CalloutDrivingIcon@2x.png deleted file mode 100644 index 6eb9fa6052..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CalloutDrivingIcon@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CoubWatermark@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CoubWatermark@2x.png deleted file mode 100644 index 1a1078b4d8..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CoubWatermark@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/EmbedVideoFullScreenIcon@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/EmbedVideoFullScreenIcon@2x.png deleted file mode 100644 index 0ad54e3680..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/EmbedVideoFullScreenIcon@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/EmbedVideoPIPIcon@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/EmbedVideoPIPIcon@2x.png deleted file mode 100644 index 9c6de4b160..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/EmbedVideoPIPIcon@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/EmbedVideoPauseIcon@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/EmbedVideoPauseIcon@2x.png deleted file mode 100644 index 54402daf4b..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/EmbedVideoPauseIcon@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/EmbedVideoPlayIcon@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/EmbedVideoPlayIcon@2x.png deleted file mode 100644 index f2a2e4422e..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/EmbedVideoPlayIcon@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/EmbedVideoTrackHollow@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/EmbedVideoTrackHollow@2x.png deleted file mode 100644 index 7b0f4e5a00..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/EmbedVideoTrackHollow@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/FoursquareAttribution@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/FoursquareAttribution@2x.png deleted file mode 100644 index 6b2650f7a3..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/FoursquareAttribution@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationInfo.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationInfo.png deleted file mode 100644 index 5b1496cd6b..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationInfo.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationInfo@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationInfo@2x.png deleted file mode 100644 index 51f15f8690..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationInfo@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationInfo@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationInfo@3x.png deleted file mode 100644 index 16cdbcec81..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationInfo@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationInfo_Active.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationInfo_Active.png deleted file mode 100644 index d8470628c4..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationInfo_Active.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationInfo_Active@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationInfo_Active@2x.png deleted file mode 100644 index b2816988ca..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationInfo_Active@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationInfo_Active@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationInfo_Active@3x.png deleted file mode 100644 index 6c8c87e511..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationInfo_Active@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationMessageLiveIcon@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationMessageLiveIcon@2x.png deleted file mode 100644 index 92170e69ac..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationMessageLiveIcon@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationMessageLiveIcon@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationMessageLiveIcon@3x.png deleted file mode 100644 index 40f071a3b0..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationMessageLiveIcon@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationMessagePinBackground@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationMessagePinBackground@2x.png deleted file mode 100644 index 35384f6e1f..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationMessagePinBackground@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationMessagePinBackground@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationMessagePinBackground@3x.png deleted file mode 100644 index 5eeda02fa0..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationMessagePinBackground@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationMessagePinIcon@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationMessagePinIcon@2x.png deleted file mode 100644 index cff797ee18..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationMessagePinIcon@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationMessagePinIcon@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationMessagePinIcon@3x.png deleted file mode 100644 index 2c7603bb7d..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationMessagePinIcon@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationMessagePinShadow@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationMessagePinShadow@2x.png deleted file mode 100644 index 709eb48ffe..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationMessagePinShadow@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationMessagePinShadow@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationMessagePinShadow@3x.png deleted file mode 100644 index 38bf099fe4..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationMessagePinShadow@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPanelEdge@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPanelEdge@2x.png deleted file mode 100644 index d1dc083322..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPanelEdge@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPanelEdge@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPanelEdge@3x.png deleted file mode 100644 index 697e0d533e..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPanelEdge@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPanelEdge_Highlighted@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPanelEdge_Highlighted@2x.png deleted file mode 100644 index d85ebddd58..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPanelEdge_Highlighted@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPanelEdge_Highlighted@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPanelEdge_Highlighted@3x.png deleted file mode 100644 index 7b6345b8ad..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPanelEdge_Highlighted@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPin@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPin@2x.png deleted file mode 100644 index 709d3b08f9..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPin@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPinBackground@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPinBackground@2x.png deleted file mode 100644 index 6e2330dde7..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPinBackground@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPinBackground@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPinBackground@3x.png deleted file mode 100644 index c99da533a0..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPinBackground@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPinIcon@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPinIcon@2x.png deleted file mode 100644 index ab6fd29ccb..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPinIcon@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPinIcon@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPinIcon@3x.png deleted file mode 100644 index a57e0d4252..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPinIcon@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPinPoint@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPinPoint@2x.png deleted file mode 100644 index 7584de8b0f..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPinPoint@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPinShadow@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPinShadow@2x.png deleted file mode 100644 index 836010f30f..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPinShadow@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPinShadow@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPinShadow@3x.png deleted file mode 100644 index caffa8f166..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationPinShadow@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationSmallCircle@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationSmallCircle@2x.png deleted file mode 100644 index ae2064ea7c..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationSmallCircle@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationSmallCircle@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationSmallCircle@3x.png deleted file mode 100644 index 5baaa60ba9..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationSmallCircle@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationTopPanel@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationTopPanel@2x.png deleted file mode 100644 index 80c3ac5c2c..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationTopPanel@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationTopPanel@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationTopPanel@3x.png deleted file mode 100644 index 6b3d6b0252..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationTopPanel@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationWave@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationWave@3x.png deleted file mode 100644 index 4819b3c862..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/LocationWave@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernConversationAudioSlideToCancel@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernConversationAudioSlideToCancel@2x.png deleted file mode 100644 index 4eaca6a590..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernConversationAudioSlideToCancel@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernConversationAudioSlideToCancel@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernConversationAudioSlideToCancel@3x.png deleted file mode 100644 index 5799af0f18..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernConversationAudioSlideToCancel@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernSegmentedControlBackground@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernSegmentedControlBackground@2x.png deleted file mode 100644 index 159b99f7c7..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernSegmentedControlBackground@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernSegmentedControlBackground@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernSegmentedControlBackground@3x.png deleted file mode 100644 index 90b1d048b2..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernSegmentedControlBackground@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernSegmentedControlDivider@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernSegmentedControlDivider@2x.png deleted file mode 100644 index fedfad1d89..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernSegmentedControlDivider@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernSegmentedControlDivider@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernSegmentedControlDivider@3x.png deleted file mode 100644 index c165592d51..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernSegmentedControlDivider@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernSegmentedControlHighlighted@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernSegmentedControlHighlighted@2x.png deleted file mode 100644 index 84fc7c3f7c..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernSegmentedControlHighlighted@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernSegmentedControlHighlighted@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernSegmentedControlHighlighted@3x.png deleted file mode 100644 index 5ea1fc964f..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernSegmentedControlHighlighted@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernSegmentedControlSelected@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernSegmentedControlSelected@2x.png deleted file mode 100644 index 4cd1da2062..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernSegmentedControlSelected@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernSegmentedControlSelected@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernSegmentedControlSelected@3x.png deleted file mode 100644 index d3165fced5..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/ModernSegmentedControlSelected@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintBrushIcon@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintBrushIcon@2x.png deleted file mode 100644 index f7f8720e25..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintBrushIcon@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintBrushIcon@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintBrushIcon@3x.png deleted file mode 100644 index 50e0696185..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintBrushIcon@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintCheck@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintCheck@2x.png deleted file mode 100644 index 69d47f8abf..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintCheck@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintEraserIcon@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintEraserIcon@2x.png deleted file mode 100644 index 20d8c4f293..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintEraserIcon@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintEraserIcon@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintEraserIcon@3x.png deleted file mode 100644 index 5b7b7e5bda..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintEraserIcon@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintMirrorIcon@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintMirrorIcon@2x.png deleted file mode 100644 index e39a1d1dca..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintMirrorIcon@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintMirrorIcon@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintMirrorIcon@3x.png deleted file mode 100644 index 2c13f50e35..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintMirrorIcon@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintPopupCenterBackground@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintPopupCenterBackground@2x.png deleted file mode 100644 index 54f036c022..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintPopupCenterBackground@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintPopupLandscapeLeftBackground@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintPopupLandscapeLeftBackground@2x.png deleted file mode 100644 index 1efe4aaf28..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintPopupLandscapeLeftBackground@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintPopupLandscapeRightBackground@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintPopupLandscapeRightBackground@2x.png deleted file mode 100644 index bf878ccb5f..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintPopupLandscapeRightBackground@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintPopupPortraitBackground@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintPopupPortraitBackground@2x.png deleted file mode 100644 index 41cca8ef2f..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintPopupPortraitBackground@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintRedoIcon@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintRedoIcon@2x.png deleted file mode 100644 index 10be9f4ea8..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintRedoIcon@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintSegmentedControlHighlighted@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintSegmentedControlHighlighted@2x.png deleted file mode 100644 index c975d225ae..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintSegmentedControlHighlighted@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintStickersIcon@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintStickersIcon@2x.png deleted file mode 100644 index d06e5f6b3c..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintStickersIcon@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintStickersIcon@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintStickersIcon@3x.png deleted file mode 100644 index 3d757b2e06..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintStickersIcon@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintTextIcon@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintTextIcon@2x.png deleted file mode 100644 index 839068d0dc..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintTextIcon@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintTextIcon@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintTextIcon@3x.png deleted file mode 100644 index 3aceb45c60..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintTextIcon@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintTextSettingsIcon@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintTextSettingsIcon@2x.png deleted file mode 100644 index b890b20bca..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintTextSettingsIcon@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintTextSettingsIcon@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintTextSettingsIcon@3x.png deleted file mode 100644 index 364eb3d186..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintTextSettingsIcon@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintUndoIcon@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintUndoIcon@2x.png deleted file mode 100644 index b371bf5377..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintUndoIcon@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintUndoIcon@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintUndoIcon@3x.png deleted file mode 100644 index b6269a0892..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PaintUndoIcon@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorAspectRatioIcon@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorAspectRatioIcon@2x.png deleted file mode 100644 index c1944b5f66..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorAspectRatioIcon@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorAspectRatioIcon@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorAspectRatioIcon@3x.png deleted file mode 100644 index e4c5bd9b29..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorAspectRatioIcon@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurIcon@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurIcon@2x.png deleted file mode 100644 index 17b1e58928..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurIcon@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurIcon@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurIcon@3x.png deleted file mode 100644 index 0ff98548c3..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurIcon@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurLinear.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurLinear.png deleted file mode 100644 index 1223538117..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurLinear.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurLinear@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurLinear@2x.png deleted file mode 100644 index e3f67c4449..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurLinear@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurLinear@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurLinear@3x.png deleted file mode 100644 index eb6279040c..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurLinear@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurOff.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurOff.png deleted file mode 100644 index 037d980c35..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurOff.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurOff@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurOff@2x.png deleted file mode 100644 index 0dc203196e..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurOff@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurOff@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurOff@3x.png deleted file mode 100644 index 1de339b991..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurOff@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurRadial.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurRadial.png deleted file mode 100644 index f5903ed9ad..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurRadial.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurRadial@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurRadial@2x.png deleted file mode 100644 index e689c5f6fd..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurRadial@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurRadial@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurRadial@3x.png deleted file mode 100644 index a6601bfdb3..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorBlurRadial@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorCaption.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorCaption.png deleted file mode 100644 index 1124711660..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorCaption.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorCaption@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorCaption@2x.png deleted file mode 100644 index 6ed8cb0d45..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorCaption@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorCaption@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorCaption@3x.png deleted file mode 100644 index 3c785a48c1..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorCaption@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorCrop@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorCrop@2x.png deleted file mode 100644 index a6ed7807f2..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorCrop@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorCrop@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorCrop@3x.png deleted file mode 100644 index 1490c67dca..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorCrop@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorCurvesIcon@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorCurvesIcon@2x.png deleted file mode 100644 index 568807854e..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorCurvesIcon@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorCurvesIcon@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorCurvesIcon@3x.png deleted file mode 100644 index 48ce0ee86f..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorCurvesIcon@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorGif@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorGif@2x.png deleted file mode 100644 index 2e10938f3d..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorGif@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorGif@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorGif@3x.png deleted file mode 100644 index cbc638ee95..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorGif@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorGifShadow@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorGifShadow@2x.png deleted file mode 100644 index 43c6612c0c..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorGifShadow@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorGifShadow@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorGifShadow@3x.png deleted file mode 100644 index 9dca9739b5..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorGifShadow@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorPaint@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorPaint@2x.png deleted file mode 100644 index 41f3d9765d..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorPaint@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorPaint@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorPaint@3x.png deleted file mode 100644 index fb8c602ad1..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorPaint@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorQuality@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorQuality@2x.png deleted file mode 100644 index fff3a37e75..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorQuality@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorQuality@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorQuality@3x.png deleted file mode 100644 index 9e6e570152..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorQuality@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorTintIcon@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorTintIcon@2x.png deleted file mode 100644 index 87138622f8..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorTintIcon@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorTintIcon@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorTintIcon@3x.png deleted file mode 100644 index 133880fe7c..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorTintIcon@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorTintTool@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorTintTool@2x.png deleted file mode 100644 index fb64ec8327..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorTintTool@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorTools@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorTools@2x.png deleted file mode 100644 index c814f6114a..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorTools@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorTools@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorTools@3x.png deleted file mode 100644 index df1bb1879f..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/PhotoEditorTools@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/RecordVideoIconOverlay@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/RecordVideoIconOverlay@3x.png deleted file mode 100644 index 7a571bb998..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/RecordVideoIconOverlay@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardFavoriteTab@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardFavoriteTab@2x.png deleted file mode 100644 index d30bef4955..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardFavoriteTab@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardFavoriteTab@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardFavoriteTab@3x.png deleted file mode 100644 index 64706d7681..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardFavoriteTab@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardGifIcon@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardGifIcon@2x.png deleted file mode 100644 index 382c35e033..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardGifIcon@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardGifIcon@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardGifIcon@3x.png deleted file mode 100644 index d760fa4947..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardGifIcon@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardRecentTab@1x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardRecentTab@1x.png deleted file mode 100644 index b48545a8d7..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardRecentTab@1x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardRecentTab@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardRecentTab@2x.png deleted file mode 100644 index 95cc50e35f..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardRecentTab@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardRecentTab@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardRecentTab@3x.png deleted file mode 100644 index 045a394615..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardRecentTab@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardSettingsIcon@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardSettingsIcon@2x.png deleted file mode 100644 index d0dc89b9ff..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardSettingsIcon@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardSettingsIcon@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardSettingsIcon@3x.png deleted file mode 100644 index 54b04299e5..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardSettingsIcon@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardTrendingIcon@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardTrendingIcon@2x.png deleted file mode 100644 index 67de340019..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardTrendingIcon@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardTrendingIcon@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardTrendingIcon@3x.png deleted file mode 100644 index ed14979353..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/StickerKeyboardTrendingIcon@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/TrackingHeading@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/TrackingHeading@2x.png deleted file mode 100644 index be5ecb85d3..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/TrackingHeading@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/TrackingHeading@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/TrackingHeading@3x.png deleted file mode 100644 index a365339ceb..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/TrackingHeading@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/TrackingLocation@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/TrackingLocation@2x.png deleted file mode 100644 index e2dae9e8ff..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/TrackingLocation@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/TrackingLocation@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/TrackingLocation@3x.png deleted file mode 100644 index 7a78214280..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/TrackingLocation@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/TrackingLocationOff@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/TrackingLocationOff@2x.png deleted file mode 100644 index 01f4da7cbc..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/TrackingLocationOff@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/TrackingLocationOff@3x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/TrackingLocationOff@3x.png deleted file mode 100644 index be8ac1a6ab..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/TrackingLocationOff@3x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/VineWatermark@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/VineWatermark@2x.png deleted file mode 100644 index 3457c7df07..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/VineWatermark@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/YoutubeWatermark@2x.png b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/YoutubeWatermark@2x.png deleted file mode 100644 index 63ac731795..0000000000 Binary files a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/YoutubeWatermark@2x.png and /dev/null differ diff --git a/submodules/LegacyComponents/Sources/AVAsset+CBExtension.h b/submodules/LegacyComponents/Sources/AVAsset+CBExtension.h deleted file mode 100755 index eb5cb5c3f4..0000000000 --- a/submodules/LegacyComponents/Sources/AVAsset+CBExtension.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// AVAsset+Extension.h -// CoubPlayer -// -// Created by Pavel Tikhonenko on 19/10/14. -// Copyright (c) 2014 Pavel Tikhonenko. All rights reserved. -// - -#import - -@interface AVAsset (CBExtension) - -@property (nonatomic, readonly) AVAssetTrack *anyVideoTrack; -@property (nonatomic, readonly) AVAssetTrack *anyAudioTrack; - -@end diff --git a/submodules/LegacyComponents/Sources/AVAsset+CBExtension.m b/submodules/LegacyComponents/Sources/AVAsset+CBExtension.m deleted file mode 100755 index 4ecf0fe334..0000000000 --- a/submodules/LegacyComponents/Sources/AVAsset+CBExtension.m +++ /dev/null @@ -1,25 +0,0 @@ -// -// AVAsset+Extension.m -// CoubPlayer -// -// Created by Pavel Tikhonenko on 19/10/14. -// Copyright (c) 2014 Pavel Tikhonenko. All rights reserved. -// - -#import "AVAsset+CBExtension.h" - -@implementation AVAsset (CBExtension) - -- (AVAssetTrack *)anyVideoTrack -{ - NSArray *videoTracks = [self tracksWithMediaType:AVMediaTypeVideo]; - return [videoTracks count] ? videoTracks[0] : nil; -} - -- (AVAssetTrack *)anyAudioTrack -{ - NSArray *audioTracks = [self tracksWithMediaType:AVMediaTypeAudio]; - return [audioTracks count] ? audioTracks[0] : nil; -} - -@end diff --git a/submodules/LegacyComponents/Sources/CBAssetDownloadManager.h b/submodules/LegacyComponents/Sources/CBAssetDownloadManager.h deleted file mode 100755 index 5b91844ea5..0000000000 --- a/submodules/LegacyComponents/Sources/CBAssetDownloadManager.h +++ /dev/null @@ -1,66 +0,0 @@ -// -// Created by Tikhonenko Pavel on 23/05/2014. -// Copyright (c) 2014 Coub. All rights reserved. -// - -#import -#import "CBCoubAsset.h" - -@protocol CBDownloadOperationDelegate; - -typedef NS_ENUM(NSInteger, CBDownloadProcessType) -{ - CBDownloadProcessTypeCoub, - CBDownloadProcessTypeChunks, -}; - -@interface CBAssetDownloadManager : NSObject - -- (void)downloadCoubWithoutChunks:(id)coub - tag:(NSInteger)tag - withDelegate:(id)delegate - downloadSucces:(void (^)(id coub, NSInteger tag))success downloadFailure:(void (^)(id coub, NSInteger tag, NSError *error))failure; - -- (void)downloadCoub:(id)coub - tag:(NSInteger)tag - withDelegate:(id)delegate - withChunks:(BOOL)withChunks - downloadSucces:(void (^)(id coub, NSInteger tag))success downloadFailure:(void (^)(id coub, NSInteger tag, NSError *error))failure; - -#pragma mark - -#pragma mark Downloading video and first chunk - -//- (void)downloadCoub:(id)coub -// tag:(NSInteger)tag -// withDelegate:(id)delegate -// downloadSucces:(void (^)(id coub, NSInteger tag))success downloadFailure:(void (^)(id coub, NSInteger tag, NSError *error))failure; - -- (void)downloadNextCoub:(id)coub - tag:(NSInteger)tag - downloadSucces:(void (^)(id coub, NSInteger tag))success downloadFailure:(void (^)(id coub, NSInteger tag, NSError *error))failure; - -- (void)cancelDownloadingForCoub:(id)coub; - -#pragma mark - -#pragma mark Downloading remaining chunks - -- (void)downloadChunkWithCoub:(id)coub - tag:(NSInteger)tag - chunkIdx:(NSInteger)chunkIdx - downloadSucces:(void (^)(id coub, NSInteger tag))success - downloadFailure:(void (^)(id coub, NSInteger tag, NSError *error))failure; - -- (void)downloadNextChunkWithCoub:(id)coub - downloadSucces:(void (^)(id coub, NSInteger tag))success - downloadFailure:(void (^)(id coub, NSInteger tag, NSError *error))failure; -//- (void)downloadRemainingChunksWithCoub:(id)coub -// tag:(NSInteger)tag -// downloadChunkSucces:(void (^)(id coub, NSInteger tag, NSInteger chunkIdx))chunkDownloaded -// downloadSucces:(void (^)(id coub, NSInteger tag))success -// downloadFailure:(void (^)(id coub, NSInteger tag, NSError *error))failure; - -- (void)stopAllDownloads; - -+ (instancetype)sharedManager; - -@end \ No newline at end of file diff --git a/submodules/LegacyComponents/Sources/CBAssetDownloadManager.m b/submodules/LegacyComponents/Sources/CBAssetDownloadManager.m deleted file mode 100755 index 36792d0480..0000000000 --- a/submodules/LegacyComponents/Sources/CBAssetDownloadManager.m +++ /dev/null @@ -1,290 +0,0 @@ -// -// Created by Tikhonenko Pavel on 23/05/2014. -// Copyright (c) 2014 Coub. All rights reserved. -// - -#import "CBAssetDownloadManager.h" -#import "CBCoubDownloadOperation.h" -#import "CBChunkDownloadOperation.h" -#import "CBDownloadOperation.h" -#import "CBDownloadOperationDelegate.h" - - -@interface CBAssetDownloadManager () - -@property (nonatomic, strong) CBCoubDownloadOperation *currentCoubDownloadingOperation; -@property (nonatomic, strong) CBCoubDownloadOperation *pausedCoubDownloadingOperation; -@property (nonatomic, strong) CBCoubDownloadOperation *nextCoubDownloadingOperation; -@property (nonatomic, strong) CBChunkDownloadOperation *currentChunksDownloadingOperation; - -- (void)resumeCoubDownloading; -- (void)destroyDownloadOperation:(id)downloadOperation; - -- (id)operationWithType:(CBDownloadProcessType)type - coub:(id)coub tag:(NSInteger)tag - downloadSucces:(void (^)(id coub, NSInteger tag))success - downloadFailure:(void (^)(id coub, NSInteger tag, NSError *error))failure; -@end - -@implementation CBAssetDownloadManager - -- (id)init -{ - self = [super init]; - - if(self) - { - } - - return self; -} - -- (void)downloadCoubWithoutChunks:(id)coub - tag:(NSInteger)tag - withDelegate:(id)delegate - downloadSucces:(void (^)(id coub, NSInteger tag))success downloadFailure:(void (^)(id coub, NSInteger tag, NSError *error))failure -{ - if(_currentChunksDownloadingOperation) - { - //_pausedCoubDownloadingOperation = _currentChunksDownloadingOperation; - [self destroyDownloadOperation:_currentChunksDownloadingOperation]; - _currentChunksDownloadingOperation = nil; - } - - [self downloadCoub:coub tag:tag withDelegate:delegate queuePriority:NSOperationQueuePriorityNormal withChunks:NO downloadSucces:success downloadFailure:failure]; -} - - -#pragma mark - -#pragma mark Downloading video and first chunk - -- (void)downloadCoub:(id)coub - tag:(NSInteger)tag - withDelegate:(id)delegate - withChunks:(BOOL)withChunks - downloadSucces:(void (^)(id coub, NSInteger tag))success downloadFailure:(void (^)(id coub, NSInteger tag, NSError *error))failure -{ - if(_currentChunksDownloadingOperation) - { - //_pausedCoubDownloadingOperation = _currentChunksDownloadingOperation; - [self destroyDownloadOperation:_currentChunksDownloadingOperation]; - _currentChunksDownloadingOperation = nil; - } - - [self downloadCoub:coub tag:tag withDelegate:delegate queuePriority:NSOperationQueuePriorityNormal withChunks:withChunks downloadSucces:success downloadFailure:failure]; -} - -- (void)downloadCoub:(id)coub - tag:(NSInteger)tag - withDelegate:(id)delegate - queuePriority:(NSOperationQueuePriority)queuePriority - withChunks:(BOOL)withChunks - downloadSucces:(void (^)(id coub, NSInteger tag))success downloadFailure:(void (^)(id coub, NSInteger tag, NSError *error))failure -{ - if(_currentCoubDownloadingOperation && _currentCoubDownloadingOperation.coub == coub && !_currentChunksDownloadingOperation.comleted) - { - _currentCoubDownloadingOperation.operationViewDelegate = delegate; - [_currentCoubDownloadingOperation setClientSuccess:success]; - [_currentCoubDownloadingOperation setClientFailure:failure]; - return; - } - - if(_nextCoubDownloadingOperation && _nextCoubDownloadingOperation.coub == coub && !_nextCoubDownloadingOperation.comleted) - { - [self destroyDownloadOperation:_nextCoubDownloadingOperation]; - } - - if(_currentCoubDownloadingOperation) - [self destroyDownloadOperation:_currentCoubDownloadingOperation]; - - id downloadOperation = [self operationWithType:CBDownloadProcessTypeCoub - coub:coub tag:tag downloadSucces:success downloadFailure:failure]; - downloadOperation.queuePriority = queuePriority; - - _currentCoubDownloadingOperation = downloadOperation; - _currentCoubDownloadingOperation.chunkDownloadingNeeded = withChunks; - [_currentCoubDownloadingOperation setOperationViewDelegate:delegate]; - [_currentCoubDownloadingOperation start]; -} - -- (void)downloadNextCoub:(id)coub - tag:(NSInteger)tag - downloadSucces:(void (^)(id coub,NSInteger tag))success downloadFailure:(void (^)(id coub,NSInteger tag, NSError *error))failure -{ - if(_currentChunksDownloadingOperation && _currentChunksDownloadingOperation.coub == coub && !_currentChunksDownloadingOperation.comleted) - { - failure(self, 0, nil); - return; - } - - - if(_nextCoubDownloadingOperation) - [self destroyDownloadOperation:_nextCoubDownloadingOperation]; - - - id downloadOperation = [self operationWithType:CBDownloadProcessTypeCoub - coub:coub tag:tag downloadSucces:success downloadFailure:failure]; - downloadOperation.queuePriority = NSOperationQueuePriorityVeryLow; - - _nextCoubDownloadingOperation = downloadOperation; - [_nextCoubDownloadingOperation setOperationViewDelegate:nil]; - [_nextCoubDownloadingOperation start]; -} - -- (void)cancelDownloadingForCoub:(id)coub -{ - if(_currentCoubDownloadingOperation && _currentCoubDownloadingOperation.coub == coub) - [self destroyDownloadOperation:_currentCoubDownloadingOperation]; -} - -#pragma mark - -#pragma mark Downloading remaining chunks - -- (void)downloadChunkWithCoub:(id)coub - tag:(NSInteger)tag - chunkIdx:(NSInteger)chunkIdx - downloadSucces:(void (^)(id coub, NSInteger tag))success - downloadFailure:(void (^)(id coub, NSInteger tag, NSError *error))failure -{ - [self destroyDownloadOperation:_currentChunksDownloadingOperation]; - - _currentChunksDownloadingOperation = [self operationWithType:CBDownloadProcessTypeChunks coub:coub - tag:tag downloadSucces:success downloadFailure:failure]; - - __weak typeof(self) wSelf = self; - - _currentChunksDownloadingOperation.chunkIdx = chunkIdx; - [_currentChunksDownloadingOperation setCompletionBlock:^(id process, NSError *error) { - [wSelf destroyDownloadOperation:process]; - [wSelf resumeCoubDownloading]; - }]; - - [_currentChunksDownloadingOperation start]; -} - -- (void)downloadNextChunkWithCoub:(id)coub - downloadSucces:(void (^)(id coub, NSInteger tag))success - downloadFailure:(void (^)(id coub, NSInteger tag, NSError *error))failure -{ - NSInteger chunkIdx = 0; - [self downloadChunkWithCoub:coub tag:chunkIdx chunkIdx:chunkIdx downloadSucces:success downloadFailure:failure]; -} - -- (void)downloadRemainingChunksWithCoub:(id)coub tag:(NSInteger)tag - downloadChunkSucces:(void (^)(id coub, NSInteger tag, NSInteger chunkIdx))chunkDownloaded - downloadSucces:(void (^)(id coub,NSInteger tag))success - downloadFailure:(void (^)(id coub, NSInteger tag, NSError *error))failure -{ - [self destroyDownloadOperation:_currentChunksDownloadingOperation]; - - _currentChunksDownloadingOperation = [self operationWithType:CBDownloadProcessTypeChunks coub:coub - tag:tag downloadSucces:success downloadFailure:failure]; - - __weak typeof(self) wSelf = self; - - _currentChunksDownloadingOperation.chunkDownloadedBlock = chunkDownloaded; - [_currentChunksDownloadingOperation setCompletionBlock:^(id process, NSError *error) { - [wSelf destroyDownloadOperation:process]; - [wSelf resumeCoubDownloading]; - }]; - - [_currentChunksDownloadingOperation start]; -} - -- (void)stopAllDownloads -{ - [self destroyCurrentOperations]; - - _pausedCoubDownloadingOperation = nil; -} - -#pragma mark - -#pragma mark private method - -- (void)resumeCoubDownloading -{ - if(_pausedCoubDownloadingOperation) - { - _currentCoubDownloadingOperation = _pausedCoubDownloadingOperation; - [_currentCoubDownloadingOperation start]; - } -} - -- (void)destroyCurrentOperations -{ - [self destroyDownloadOperation:_currentCoubDownloadingOperation]; - - [self destroyDownloadOperation:_currentChunksDownloadingOperation]; - - //_pausedCoubDownloadingOperation = nil; -} - -- (void)destroyDownloadOperation:(id)downloadOperation -{ - if(downloadOperation) - [downloadOperation cancel]; - - if(downloadOperation == _currentCoubDownloadingOperation) - _currentCoubDownloadingOperation = nil; - - if(downloadOperation == _currentChunksDownloadingOperation) - _currentChunksDownloadingOperation = nil; -} - -#pragma mark - -#pragma mark Factory method - -- (id)operationWithType:(CBDownloadProcessType)type - coub:(id)coub tag:(NSInteger)tag - downloadSucces:(void (^)(id, NSInteger tag))success - downloadFailure:(void (^)(id, NSInteger tag, NSError *error))failure -{ - id downloadOperation; - - switch(type) - { - case CBDownloadProcessTypeCoub: - { - downloadOperation = [CBCoubDownloadOperation new]; - break; - } - - case CBDownloadProcessTypeChunks: - { - downloadOperation = [CBChunkDownloadOperation new]; - break; - } - } - - [downloadOperation setTag:tag]; - [downloadOperation setCoub:coub]; - [downloadOperation setClientSuccess:success]; - [downloadOperation setClientFailure:failure]; - - __weak typeof(self) wSelf = self; - - [downloadOperation setCompletionBlock:^(id operation, NSError *error) { - [wSelf destroyDownloadOperation:operation]; - [wSelf resumeCoubDownloading]; - }]; - - return downloadOperation; -} - -#pragma mark - -#pragma mark Singleton implementation - -static CBAssetDownloadManager *instance = nil; - -+ (instancetype)sharedManager -{ - if(instance != nil) return instance; - - static dispatch_once_t onceToken = 0; - dispatch_once(&onceToken, ^{ - instance = [[self alloc] init]; - }); - return instance; -} - -@end \ No newline at end of file diff --git a/submodules/LegacyComponents/Sources/CBChunkDownloadOperation.h b/submodules/LegacyComponents/Sources/CBChunkDownloadOperation.h deleted file mode 100755 index d7439ca0d3..0000000000 --- a/submodules/LegacyComponents/Sources/CBChunkDownloadOperation.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// Created by Tikhonenko Pavel on 23/05/2014. -// Copyright (c) 2014 Coub. All rights reserved. -// - -#import "CBGenericDownloadOperation.h" - -@interface CBChunkDownloadOperation : CBGenericDownloadOperation - -@property (nonatomic, assign) NSInteger chunkIdx; - -@property(nonatomic, copy) void (^chunkDownloadedBlock)(id, NSInteger tag, NSInteger chunkIdx); - -@end \ No newline at end of file diff --git a/submodules/LegacyComponents/Sources/CBChunkDownloadOperation.m b/submodules/LegacyComponents/Sources/CBChunkDownloadOperation.m deleted file mode 100755 index 467bd77c95..0000000000 --- a/submodules/LegacyComponents/Sources/CBChunkDownloadOperation.m +++ /dev/null @@ -1,65 +0,0 @@ -// -// Created by Tikhonenko Pavel on 23/05/2014. -// Copyright (c) 2014 Coub. All rights reserved. -// - -#import "CBChunkDownloadOperation.h" - -#import "LegacyComponentsInternal.h" -#import "LegacyHTTPRequestOperation.h" - -@implementation CBChunkDownloadOperation -{ - -} - -- (void)start -{ - [super start]; - [self downloadChunk]; -} - -- (void)downloadChunk -{ - NSURL *localURL = [self.coub localAudioChunkWithIdx:_chunkIdx]; - - NSURL *remoteURL = [self.coub remoteAudioChunkWithIdx:_chunkIdx+1]; - - NSURLRequest *downloadRequest = [NSURLRequest requestWithURL:remoteURL]; - - self.downloadOperation = [[LegacyComponentsGlobals provider] makeHTTPRequestOperationWithRequest:downloadRequest]; - self.downloadOperation.queuePriority = self.queuePriority; - self.downloadOperation.outputStream = [NSOutputStream outputStreamToFileAtPath:localURL.path append:NO]; - //[self.downloadOperation setShouldExecuteAsBackgroundTaskWithExpirationHandler:nil]; - - __weak typeof(self) wSelf = self; - - [self.downloadOperation setCompletionBlockWithSuccess:^(__unused id operation, __unused id responseObject) { - [wSelf successChunkDownload]; - } failure:^(__unused id operation, __unused NSError *error) { - [wSelf failureDownloadWithError:error]; - }]; - - [self.downloadOperation start]; -} - -- (void)successChunkDownload -{ - //NSLog(@"successChunkDownload"); - - [self successDownload]; -} - -- (instancetype)clone -{ - CBChunkDownloadOperation *clone = [CBChunkDownloadOperation new]; - [clone setTag:self.tag]; - [clone setCoub:self.coub]; - [clone setCompletionBlock:self.completionBlock]; - [clone setClientSuccess:self.clientSuccess]; - [clone setClientFailure:self.clientFailure]; - [clone setChunkDownloadedBlock:self.chunkDownloadedBlock]; - return clone; -} - -@end diff --git a/submodules/LegacyComponents/Sources/CBConstance.h b/submodules/LegacyComponents/Sources/CBConstance.h deleted file mode 100755 index f448703234..0000000000 --- a/submodules/LegacyComponents/Sources/CBConstance.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// CBConstance.h -// CoubPlayer -// -// Created by Pavel Tikhonenko on 19/10/14. -// Copyright (c) 2014 Pavel Tikhonenko. All rights reserved. -// - -#import - -typedef void (^CBSuccessBlock)(id result); -//typedef void (^CBSuccessWithUserInfoBlock)(id result, id userInfo); -typedef void (^CBFailureBlock)(NSError *error); - -extern NSString * const kCBServerURL; - -extern NSString * const CBCoubLoopErrorDomain; -enum { - CBCoubLoopErrorUnknown = 1, - CBCoubLoopErrorNoSuchFile, - CBCoubLoopErrorUnsupportedAudioFormat, - CBCoubLoopErrorUnreadableAudioTrack, - CBCoubLoopErrorNoVideoTracks, - CBCoubLoopErrorCanceled, -}; - - -extern NSString *const CBPlayerInterruptionDidBeginNotification; -extern NSString *const CBPlayerInterruptionDidEndNotification; - -@interface CBConstance : NSObject - -@end diff --git a/submodules/LegacyComponents/Sources/CBConstance.m b/submodules/LegacyComponents/Sources/CBConstance.m deleted file mode 100755 index 8528fb4e1c..0000000000 --- a/submodules/LegacyComponents/Sources/CBConstance.m +++ /dev/null @@ -1,21 +0,0 @@ -// -// CBConstance.m -// CoubPlayer -// -// Created by Pavel Tikhonenko on 19/10/14. -// Copyright (c) 2014 Pavel Tikhonenko. All rights reserved. -// - -#import "CBConstance.h" - -NSString *const kCBServerURL = @"http://coub.com"; - -NSString *const CBCoubLoopErrorDomain = @"com.coub.loop.ErrorDomain"; - -NSString *const CBPlayerInterruptionDidBeginNotification = @"CBPlayerInterruptionDidBeginNotification"; -NSString *const CBPlayerInterruptionDidEndNotification = @"CBPlayerInterruptionDidEndNotification"; - - -@implementation CBConstance - -@end diff --git a/submodules/LegacyComponents/Sources/CBCoubAsset.h b/submodules/LegacyComponents/Sources/CBCoubAsset.h deleted file mode 100755 index bb921e8773..0000000000 --- a/submodules/LegacyComponents/Sources/CBCoubAsset.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// Created by Tikhonenko Pavel on 04/04/2014. -// Copyright (c) 2014 Coub. All rights reserved. -// - -#import -#import "CBCoubPlayerContance.h" - -@protocol CBCoubAsset - -@property(nonatomic, readonly) NSString *assetId; //permalink -@property(nonatomic, readonly) NSURL *localVideoFileURL; -@property(nonatomic, readonly) CBCoubAudioType audioType; -@property(nonatomic, readonly) NSURL *externalAudioURL; //may be nil -@property(nonatomic, readonly) NSURL *largeImageURL; - -- (BOOL)failedDownloadChunk; - -- (NSURL *)remoteVideoFileURL; - -- (NSURL *)localAudioChunkWithIdx:(NSInteger)idx; -- (NSURL *)remoteAudioChunkWithIdx:(NSInteger)idx; - - -@end \ No newline at end of file diff --git a/submodules/LegacyComponents/Sources/CBCoubAudioSource.h b/submodules/LegacyComponents/Sources/CBCoubAudioSource.h deleted file mode 100755 index a9161dab91..0000000000 --- a/submodules/LegacyComponents/Sources/CBCoubAudioSource.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// CBCoubAudioSource.h -// Coub -// -// Created by Tikhonenko Pavel on 18/11/2013. -// Copyright (c) 2013 Coub. All rights reserved. -// - -#import - -@interface CBCoubAudioSource : NSObject - -@property (nonatomic, strong) NSString *cover; -@property (nonatomic, strong) NSString *title; -@property (nonatomic, strong) NSString *artist; -@property (nonatomic, strong) NSString *itunesURL; -@property (nonatomic, strong) NSString *songName; - -+ (CBCoubAudioSource *)sourceFromData:(NSDictionary *)dict; - -@end diff --git a/submodules/LegacyComponents/Sources/CBCoubAudioSource.m b/submodules/LegacyComponents/Sources/CBCoubAudioSource.m deleted file mode 100755 index be04846066..0000000000 --- a/submodules/LegacyComponents/Sources/CBCoubAudioSource.m +++ /dev/null @@ -1,32 +0,0 @@ -// -// CBCoubAudioSource.m -// Coub -// -// Created by Tikhonenko Pavel on 18/11/2013. -// Copyright (c) 2013 Coub. All rights reserved. -// - -#import "CBCoubAudioSource.h" - -@implementation CBCoubAudioSource - -+ (CBCoubAudioSource *)sourceFromData:(NSDictionary *)dict -{ - if(!dict.count) return nil; - - - NSDictionary *meta = dict[@"meta"]; - - CBCoubAudioSource *source = [[CBCoubAudioSource alloc] init]; - source.cover = dict[@"image"]; - source.itunesURL = dict[@"url"]; - source.songName = meta[@"title"]; - source.title = source.songName; - source.artist = meta[@"artist"]; - if(source.title == nil || source.itunesURL == nil) - return nil; - - return source; -} - -@end diff --git a/submodules/LegacyComponents/Sources/CBCoubAuthorVO.h b/submodules/LegacyComponents/Sources/CBCoubAuthorVO.h deleted file mode 100755 index 2d1ca547ae..0000000000 --- a/submodules/LegacyComponents/Sources/CBCoubAuthorVO.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// CBCoubAuthorVO.h -// Coub -// -// Created by Tikhonenko Pavel on 21/11/2013. -// Copyright (c) 2013 Coub. All rights reserved. -// - -#import - -@interface CBCoubAuthorVO : NSObject - -@property (nonatomic, strong) NSString *avatarURL; -@property (nonatomic, strong) NSString *largeAvatarURL; -@property (nonatomic, assign) NSInteger followersCount; -@property (nonatomic, assign) NSInteger viewsCount; -@property (nonatomic, strong) NSString *userId; -@property (nonatomic, strong) NSString *name; -@property (nonatomic, strong) NSString *permalink; - -+ (CBCoubAuthorVO *)coubAuthorWithAttributes:(NSDictionary *)attributes; -+ (CBCoubAuthorVO *)currentUser; -@end diff --git a/submodules/LegacyComponents/Sources/CBCoubAuthorVO.m b/submodules/LegacyComponents/Sources/CBCoubAuthorVO.m deleted file mode 100755 index cd54782c86..0000000000 --- a/submodules/LegacyComponents/Sources/CBCoubAuthorVO.m +++ /dev/null @@ -1,42 +0,0 @@ -// -// CBCoubAuthorVO.m -// Coub -// -// Created by Tikhonenko Pavel on 21/11/2013. -// Copyright (c) 2013 Coub. All rights reserved. -// - -#import "CBCoubAuthorVO.h" - -@implementation CBCoubAuthorVO - -+ (CBCoubAuthorVO *)coubAuthorWithAttributes:(NSDictionary *)attributes -{ - CBCoubAuthorVO *author = [CBCoubAuthorVO new]; - author.avatarURL = attributes[@"avatar"]; - author.largeAvatarURL = attributes[@"large_avatar"]; - author.followersCount = [attributes[@"followers_count"] integerValue]; - author.userId = [attributes[@"id"] stringValue]; - author.name = attributes[@"name"]; - author.permalink = attributes[@"permalink"]; - author.viewsCount = [attributes[@"views_count"] integerValue]; - //author.viewsCount; - return author; -} - -//+ (CBCoubAuthorVO *)currentUser -//{ -// CBUserNew *curUser = [CBUserNew currentUser]; -// -// CBCoubAuthorVO *author = [CBCoubAuthorVO new]; -// author.avatarURL = curUser.mediumAvatar; -// author.largeAvatarURL = curUser.largeAvatar; -// author.followersCount = curUser.followerCount; -// author.userId = curUser.coubID; -// author.name = curUser.fullName; -// author.permalink = curUser.permalink; -// author.viewsCount = curUser.viewsCount; -// return author; -//} - -@end diff --git a/submodules/LegacyComponents/Sources/CBCoubDownloadOperation.h b/submodules/LegacyComponents/Sources/CBCoubDownloadOperation.h deleted file mode 100755 index 6fcc7eb0a5..0000000000 --- a/submodules/LegacyComponents/Sources/CBCoubDownloadOperation.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// Created by Tikhonenko Pavel on 23/05/2014. -// Copyright (c) 2014 Coub. All rights reserved. -// - -#import "CBGenericDownloadOperation.h" - -@interface CBCoubDownloadOperation : CBGenericDownloadOperation - -@property (nonatomic, assign) NSInteger neededChunkCount; - -@end \ No newline at end of file diff --git a/submodules/LegacyComponents/Sources/CBCoubDownloadOperation.m b/submodules/LegacyComponents/Sources/CBCoubDownloadOperation.m deleted file mode 100755 index eadca4f671..0000000000 --- a/submodules/LegacyComponents/Sources/CBCoubDownloadOperation.m +++ /dev/null @@ -1,190 +0,0 @@ -// -// Created by Tikhonenko Pavel on 23/05/2014. -// Copyright (c) 2014 Coub. All rights reserved. -// - -#import "CBCoubDownloadOperation.h" -#import "CBDownloadOperationDelegate.h" - -#import "LegacyComponentsInternal.h" - -@implementation CBCoubDownloadOperation -{ - BOOL _isVideoDownloaded; - NSInteger _currentChunkIdx; -} - -- (void)start -{ - [super start]; - - _neededChunkCount = NSNotFound; - _currentChunkIdx = 0; - - [self downloadVideo]; -} - -- (void)downloadVideo -{ - NSURL *remoteURL = [self.coub remoteVideoFileURL]; - NSURL *localURL = [self.coub localVideoFileURL]; - - _isVideoDownloaded = [[NSFileManager defaultManager] fileExistsAtPath:[localURL path]]; - if(_isVideoDownloaded) - { - [self successVideoDownload]; - return; - }else{ - //KALog(@"video doesn't %i", _currentChunkIdx); - } - - NSURLRequest *downloadRequest = [NSURLRequest requestWithURL:remoteURL]; - - __weak typeof(self) wSelf = self; - - self.downloadOperation = [[LegacyComponentsGlobals provider] makeHTTPRequestOperationWithRequest:downloadRequest]; - self.downloadOperation.queuePriority = self.queuePriority; - self.downloadOperation.outputStream = [NSOutputStream outputStreamToFileAtPath:localURL.path append:NO]; - //[self.downloadOperation setShouldExecuteAsBackgroundTaskWithExpirationHandler:nil]; - [self.downloadOperation setDownloadProgressBlock:^(__unused NSInteger bytesRead, NSInteger totalBytesRead, NSInteger totalBytesExpectedToRead) { - float progress = totalBytesRead / (float) totalBytesExpectedToRead; - [wSelf progressDownload:progress]; - }]; - - [self.downloadOperation setCompletionBlockWithSuccess:^(__unused id operation, __unused id responseObject) { - [wSelf successVideoDownload]; - } failure:^(__unused id operation, NSError *error) { - - if([[NSFileManager defaultManager] fileExistsAtPath:[localURL path]]) - [[NSFileManager defaultManager] removeItemAtPath:[localURL path] error:nil]; - - [wSelf failureDownloadWithError:error]; - }]; - - [self.downloadOperation start]; -} - -- (void)downloadChunk -{ - NSURL *localURL = [self.coub localAudioChunkWithIdx:_currentChunkIdx]; - - //int fileExist = [[CBLibrary sharedLibrary] isCoubChunkDownloadedByPermalink:self.coub.permalink idx:_currentChunkIdx]; - int fileExist = [[NSFileManager defaultManager] fileExistsAtPath:[localURL path]]; - - if(fileExist || (_neededChunkCount == NSNotFound && _currentChunkIdx > 1)) - { - [self successDownload]; - return; - } - - NSURL *remoteURL = [self.coub remoteAudioChunkWithIdx:_currentChunkIdx + 1]; - NSURLRequest *downloadRequest = [NSURLRequest requestWithURL:remoteURL]; - - //NSLog(@"chunk idx = %i, remoteURL = %@", _currentChunkIdx, remoteURL); - - __weak typeof(self) wSelf = self; - - self.downloadOperation = [[LegacyComponentsGlobals provider] makeHTTPRequestOperationWithRequest:downloadRequest]; - self.downloadOperation.queuePriority = self.queuePriority; - self.downloadOperation.outputStream = [NSOutputStream outputStreamToFileAtPath:localURL.path append:NO]; - //[self.downloadOperation setShouldExecuteAsBackgroundTaskWithExpirationHandler:nil]; - [self.downloadOperation setDownloadProgressBlock:^(__unused NSInteger bytesRead, NSInteger totalBytesRead, NSInteger totalBytesExpectedToRead) { - - if(wSelf.neededChunkCount == NSNotFound) - { - //NSLog(@"totalBytesExpectedToRead = %llu", totalBytesExpectedToRead); - - wSelf.neededChunkCount = MIN((int) ((1024*1024)/totalBytesExpectedToRead), 4); - wSelf.neededChunkCount = MAX(wSelf.neededChunkCount, 1); - } - - float progress = totalBytesRead / (float) totalBytesExpectedToRead; - [wSelf progressDownload:progress]; - }]; - - [self.downloadOperation setCompletionBlockWithSuccess:^(__unused id operation, __unused id responseObject) { - //[wSelf.coub setFailedDownloadChunk:NO]; - [wSelf successChunkDownload]; - } failure:^(__unused id operation, NSError *error) { - - if([[NSFileManager defaultManager] fileExistsAtPath:[localURL path]]) - [[NSFileManager defaultManager] removeItemAtPath:[localURL path] error:nil]; - - if(error.code == -1011) - { - //NSLog(@"failed download"); - - //[wSelf.coub setFailedDownloadChunk:YES]; - [wSelf successDownload]; - - return; - } - //NSLog(@"failed download unknown"); - - [wSelf failureDownloadWithError:error]; - }]; - - [self.downloadOperation start]; -} - -- (void)successVideoDownload -{ - //[[CBLibrary sharedLibrary] markCoubAsset:self.coub asDownloaded:YES]; - - _isVideoDownloaded = YES; - - if(self.starting) - { - if(self.chunkDownloadingNeeded && [self.coub audioType] == CBCoubAudioTypeExternal) - [self downloadChunk]; - else - [super successDownload]; - } -} - -- (void)successDownload -{ - _currentChunkIdx++; - - if([self.coub audioType] != CBCoubAudioTypeExternal || _currentChunkIdx >= MIN(4, _neededChunkCount)) - { - [super successDownload]; - } - else - [self downloadChunk]; -} - -- (void)successChunkDownload -{ - [self successDownload]; -} - -- (void)progressDownload:(float)progress -{ - if(self.starting && self.operationViewDelegate) - { - float newProgress; - - if(_isVideoDownloaded) - { - newProgress = .5f + (_currentChunkIdx * 1/(float)_neededChunkCount + progress/(float)_neededChunkCount)*.5f; - }else{ - newProgress = progress/2.0f; - } - [self.operationViewDelegate downloadDidReachProgress:newProgress]; - } -} - -- (instancetype)clone -{ - CBCoubDownloadOperation *clone = [CBCoubDownloadOperation new]; - [clone setOperationViewDelegate:self.operationViewDelegate]; - [clone setTag:self.tag]; - [clone setCoub:self.coub]; - [clone setCompletionBlock:self.completionBlock]; - [clone setClientSuccess:self.clientSuccess]; - [clone setClientFailure:self.clientFailure]; - return clone; -} - -@end diff --git a/submodules/LegacyComponents/Sources/CBCoubLoopCompositionMaker.h b/submodules/LegacyComponents/Sources/CBCoubLoopCompositionMaker.h deleted file mode 100755 index e45269c609..0000000000 --- a/submodules/LegacyComponents/Sources/CBCoubLoopCompositionMaker.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// Created by Tikhonenko Pavel on 26/11/2013. -// Copyright (c) 2013 Coub. All rights reserved. -// - - -#import -#import "CBCoubAsset.h" - -#import - -@class CBCoubLoopCompositionMaker; -@protocol CBCoubAsset; - -@protocol CBCoubLoopDelegate - -@required -- (void)coubLoopDidFinishPreparing:(CBCoubLoopCompositionMaker *)loop; -- (void)coubLoop:(CBCoubLoopCompositionMaker *)loop didFailToLoadWithError:(NSError *)error; - -@end - -@interface CBCoubLoopCompositionMaker : NSObject - -@property (nonatomic, weak) id delegate; -@property (nonatomic, strong) id asset; - -@property (nonatomic, strong) AVAsset *videoAsset; -@property (nonatomic, strong) NSError *error; -@property (nonatomic, readonly) BOOL hasAudio; - -@property (nonatomic, assign, getter=isLoopReady) BOOL loopReady; - -- (void)prepareLoop; -- (void)cancelPrepareLoop; - -- (void)notifyObservers; - -+ (instancetype)coubLoopWithAsset:(id)asset; - -@end \ No newline at end of file diff --git a/submodules/LegacyComponents/Sources/CBCoubLoopCompositionMaker.m b/submodules/LegacyComponents/Sources/CBCoubLoopCompositionMaker.m deleted file mode 100755 index 6d552e1839..0000000000 --- a/submodules/LegacyComponents/Sources/CBCoubLoopCompositionMaker.m +++ /dev/null @@ -1,322 +0,0 @@ -// -// Created by Tikhonenko Pavel on 26/11/2013. -// Copyright (c) 2013 Coub. All rights reserved. -// - - -#import -#import "CBCoubLoopCompositionMaker.h" -#import "CBCoubAsset.h" -#import "CBConstance.h" -#import "AVAsset+CBExtension.h" - -#pragma mark - -#pragma mark CBCoubLoopOperation - -static AVURLAsset *gDigitalSilenceAsset = nil; - -@interface CBCoubLoopOperation : NSOperation - -- (id)initWithCoubAsset:(id)asset loop:(CBCoubLoopCompositionMaker *)loop; - -- (void)prepareOperation; -- (void)makeLoop; -- (AVComposition *)makeLoopComposition; - -- (BOOL)checkAssetURL:(NSURL *)assetURL; - -- (void)completeWithError:(NSError *)error; - -@end - -@implementation CBCoubLoopOperation -{ -@private - id _asset; - CBCoubLoopCompositionMaker *_loop; - AVAssetExportSession *_exportSession; - - NSURL *_assetURL; - BOOL _hasExternalAudio; -} - -- (id)initWithCoubAsset:(id)asset loop:(CBCoubLoopCompositionMaker *)loop -{ - self = [super init]; - if(self) - { - _asset = asset; - _loop = loop; - } - return self; -} - -- (void)main -{ - if([self isCancelled]) - return; - - [self prepareOperation]; -} - -- (void)prepareOperation -{ - if(![self checkAssetURL:_asset.localVideoFileURL]) - return; - - _assetURL = _asset.localVideoFileURL; - _hasExternalAudio = _asset.externalAudioURL != nil; - - [self makeLoop]; -} - -- (void)makeLoop -{ - AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:_assetURL options:@{AVURLAssetPreferPreciseDurationAndTimingKey : @YES}]; -// _loop.videoAsset = avAsset; -// [self completeWithError:nil]; -// return; - if(_asset.audioType == CBCoubAudioTypeInternal) - { - AVComposition *composition = [self makeLoopComposition]; - if(![self isCancelled]) - { - _loop.videoAsset = composition; - [self completeWithError:nil]; - }else{ - - } - - }else{ - _loop.videoAsset = avAsset; - [self completeWithError:nil]; - } - -} - -- (AVComposition *)makeLoopComposition -{ - AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:_assetURL options:@{AVURLAssetPreferPreciseDurationAndTimingKey : @YES}]; - NSArray *videoTracks = [avAsset tracksWithMediaType:AVMediaTypeVideo]; - if([videoTracks count] == 0) - { - - //TODO: remove cache file and download again - - NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain - code:CBCoubLoopErrorNoVideoTracks - userInfo:_assetURL ? @{NSURLErrorKey : _assetURL} : nil]; - - [self completeWithError:error]; - - return nil; - } - - if([self isCancelled]) - return nil; - - AVAssetTrack *originalVideoTrack = videoTracks[0]; - AVAssetTrack *originalAudioTrack = _hasExternalAudio ? nil : avAsset.anyAudioTrack; - - if(originalVideoTrack == nil) - { - NSError *error = [NSError errorWithDomain:CBCoubLoopErrorDomain - code:CBCoubLoopErrorNoVideoTracks - userInfo:nil]; - [self completeWithError:error]; - return nil; - } - - CMTimeRange videoTrackTimeRange = originalVideoTrack.timeRange; -// videoTrackTimeRange.start.value = 1; -// videoTrackTimeRange.duration.value -= 2; - - CMTimeRange audioTrackTimeRange = originalAudioTrack ? originalAudioTrack.timeRange : kCMTimeRangeZero; -// if(originalAudioTrack) -// { -// audioTrackTimeRange.start.value = 1; -// audioTrackTimeRange.duration.value -= 2; -// } - - // Calculate the minimum duration of our composition - CMTime minimumCompositionDuration = CMTimeMake(60*audioTrackTimeRange.start.timescale, audioTrackTimeRange.start.timescale); - - if(!_hasExternalAudio) - { - if(originalAudioTrack) - audioTrackTimeRange = CMTimeRangeGetIntersection(audioTrackTimeRange, videoTrackTimeRange); - } - - AVAssetTrack *silence = nil; - CMTimeRange silenceTimeRange = kCMTimeRangeZero; - - if([self isCancelled]) - return nil; - - AVMutableComposition *composition = [AVMutableComposition composition]; - AVMutableCompositionTrack *videoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; - AVMutableCompositionTrack *audioTrack = originalAudioTrack ? [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid] : nil; - - CMTime videoTrackDuration = kCMTimeZero; - NSError *error = nil; - while(CMTIME_COMPARE_INLINE(videoTrackDuration, <, minimumCompositionDuration)) - { - if([self isCancelled]) - return nil; - - if(![videoTrack insertTimeRange:videoTrackTimeRange ofTrack:originalVideoTrack atTime:videoTrackDuration error:&error]) - { -// KAObjectLogError(@"Failed to insert %@ of video track %@ at %@: %@", CBStringFromTimeRange(videoTrackTimeRange), originalVideoTrack, CBStringFromTime(videoTrackDuration), error); - [self completeWithError:error]; - return nil; - } - if(audioTrack) - { - if(![audioTrack insertTimeRange:audioTrackTimeRange ofTrack:originalAudioTrack atTime:videoTrackDuration error:&error]) - { - -// KAObjectLogError(@"Failed to insert %@ of audio track %@ at %@: %@", CBStringFromTimeRange(audioTrackTimeRange), originalAudioTrack, CBStringFromTime(videoTrackDuration), error); - [self completeWithError:error]; - return nil; - } - } - if(silence) - { - if(![audioTrack insertTimeRange:silenceTimeRange ofTrack:silence atTime:CMTimeAdd(videoTrackDuration, audioTrackTimeRange.duration) error:&error]) - { - [self completeWithError:error]; - return nil; - } - } - videoTrackDuration = CMTimeAdd(videoTrackDuration, videoTrackTimeRange.duration); - } - - videoTrack.preferredTransform = originalVideoTrack.preferredTransform; - return composition; -} - -- (BOOL)checkAssetURL:(NSURL *)assetURL -{ - if (assetURL == nil || ([assetURL isFileURL] && ![[NSFileManager defaultManager] fileExistsAtPath: [assetURL path]])) - { - NSLog(@"File doesn't exist: %@", assetURL); - //TODO: remove cache file and download again - - NSError *error = [NSError errorWithDomain:CBCoubLoopErrorDomain - code:CBCoubLoopErrorNoSuchFile - userInfo:assetURL ? @{NSURLErrorKey : assetURL} : nil]; - [self completeWithError:error]; - return NO; - }else{ - return YES; - } -} - -- (void)cancel -{ - [_exportSession cancelExport]; - [super cancel]; -} - -- (void)completeWithError:(NSError *)error -{ - dispatch_async(dispatch_get_main_queue(), ^ - { - [_exportSession cancelExport]; - - _loop.error = error; - [_loop notifyObservers]; - }); -} -@end - -#pragma mark - -#pragma mark CBCoubLoop - -static NSOperationQueue *gOperationQueue = nil; - -@implementation CBCoubLoopCompositionMaker -{ -@private - CBCoubLoopOperation *_operation; -} - -+ (void)initialize -{ - if(!gOperationQueue) - { - gOperationQueue = [NSOperationQueue new]; - [gOperationQueue setMaxConcurrentOperationCount:1]; - } -} - -- (id)initWithAsset:(id)asset -{ - self = [super init]; - - if(self) - { - _asset = asset; - } - - return self; -} - -- (BOOL)hasAudio -{ - return !(_asset.audioType == CBCoubAudioTypeNone); -} - -- (void)prepareLoop -{ - if(gOperationQueue.operations.count) - [gOperationQueue cancelAllOperations]; - - if(!_operation) - { - self.error = nil; - - CBCoubLoopOperation *operation = [[CBCoubLoopOperation alloc] initWithCoubAsset:_asset loop:self]; - [gOperationQueue addOperation:operation]; - - _operation = operation; - //[_operation start]; - } -} - -- (void)cancelPrepareLoop -{ - self.videoAsset = nil; - - [_operation cancel]; - _operation = nil; - - self.error = [NSError errorWithDomain:CBCoubLoopErrorDomain - code:CBCoubLoopErrorCanceled - userInfo:nil]; - [_delegate coubLoop:self didFailToLoadWithError:self.error]; - -} - -- (void)notifyObservers -{ - NSAssert([NSThread isMainThread], @"%s must be called on the main thread", __PRETTY_FUNCTION__); - - if(self.error) - [_delegate coubLoop:self didFailToLoadWithError:self.error]; - else - { - _loopReady = YES; - [_delegate coubLoopDidFinishPreparing:self]; - } - - _operation = nil; -} - -+ (instancetype)coubLoopWithAsset:(id)asset -{ - CBCoubLoopCompositionMaker *instance = [[CBCoubLoopCompositionMaker alloc] initWithAsset:asset]; - return instance; -} - -@end diff --git a/submodules/LegacyComponents/Sources/CBCoubNew.h b/submodules/LegacyComponents/Sources/CBCoubNew.h deleted file mode 100755 index 19b534278a..0000000000 --- a/submodules/LegacyComponents/Sources/CBCoubNew.h +++ /dev/null @@ -1,70 +0,0 @@ -// -// CBCoubNew.h -// Coub -// -// Created by Tikhonenko Pavel on 18/11/2013. -// Copyright (c) 2013 Coub. All rights reserved. -// - -#import -#import "CBCoubAuthorVO.h" -#import "CBCoubAudioSource.h" -#import "CBCoubVideoSource.h" -#import "CBCoubAsset.h" - -@interface CBCoubNew : NSObject - -@property(nonatomic, strong) NSString *coubID; -@property(nonatomic, strong) NSString *permalink; -@property(nonatomic, strong) NSString *originalPermalink; -@property(nonatomic, strong) NSString *visibility; // kCBCoubVisibility*, see above -@property(nonatomic, assign) BOOL isDone; - -@property(nonatomic, strong) CBCoubAuthorVO *author; -@property(nonatomic, strong) CBCoubAuthorVO *recouber; - -@property(nonatomic, strong) NSString *title; -@property(nonatomic, strong) NSDate *creationDate; -@property(nonatomic, strong) NSDate *originalCreationDate; -@property(nonatomic, strong) NSArray *tags; //CBTagNew - -//Stats -@property(nonatomic, assign) NSUInteger viewCount; -@property(nonatomic, assign) NSUInteger likeCount; -@property(nonatomic, assign) NSUInteger recoubCount; -@property(nonatomic, assign) BOOL liked; // whether the current user likes the coub; does not update likeCount -@property(nonatomic, assign) BOOL recoubed; -@property(nonatomic, assign) BOOL cotd; -@property(nonatomic, assign) BOOL flagged; -@property(nonatomic, assign) BOOL deleted; - -@property(nonatomic, assign) CBCoubAudioType audioType; - -@property(nonatomic, strong) NSString *externalDownloadType; -@property(nonatomic, strong) NSString *externalDownloadSource; // youtube/vimeo URL - -//@property (nonatomic, readonly) NSOrderedSet *recoubersOthenThanCurrentUser; -@property (nonatomic, readonly) NSURL *coubWebViewURL; -@property(nonatomic, readonly) NSURL *mediumImageURL; -@property(nonatomic, readonly) NSURL *largeImageURL; -@property(nonatomic, readonly) BOOL isRecoub; -@property(nonatomic, readonly) BOOL isMyCoub; - -@property(nonatomic, retain) NSURL *customLocalVideoFileURL; -@property(nonatomic, retain) NSString *remoteVideoLocation; -@property(nonatomic, retain) NSString *remoteAudioLocation; -@property(nonatomic, retain) NSString *remoteAudioLocationPattern; -@property(nonatomic, retain) NSString *mediumPicture; -@property(nonatomic, retain) NSString *largePicture; -@property(nonatomic, retain) NSString *creationDateAsString; -@property(nonatomic, retain) NSString *originalCreationDateAsString; - -@property(nonatomic, readonly) NSURL *remoteVideoFileURL; - -@property(nonatomic, assign) BOOL isCoubSourcesAvailable; -@property(nonatomic, strong) CBCoubAudioSource *audioSource; -@property(nonatomic, strong) CBCoubVideoSource *videoSource; - -+ (CBCoubNew *)coubWithAttributes:(NSDictionary *)attributes; - -@end diff --git a/submodules/LegacyComponents/Sources/CBCoubNew.m b/submodules/LegacyComponents/Sources/CBCoubNew.m deleted file mode 100755 index 36c1db6f10..0000000000 --- a/submodules/LegacyComponents/Sources/CBCoubNew.m +++ /dev/null @@ -1,199 +0,0 @@ -// -// CBCoubNew.m -// Coub -// -// Created by Tikhonenko Pavel on 18/11/2013. -// Copyright (c) 2013 Coub. All rights reserved. -// - -#import "CBCoubNew.h" -//#import "Formatters.h" -//#import "NSDictionary+Extensions.h" -#import "CBLibrary.h" -#import "CBJSONCoubMapper.h" -#import "CBConstance.h" - -@interface CBCoubNew () -{ - BOOL _failedDownloadChunks; -} -@end - -@implementation CBCoubNew - -//- (void)setNaturalVideoSize:(CGSize)size -//{ -// _naturalVideoSize = size; -//} - -- (BOOL)isDraft -{ - return NO; -} - -//- (NSDate *)creationDate -//{ -// if(!_creationDate) -// _creationDate = [[NSDateFormatter sharedCoubJSONDateFormatter] dateFromString:_creationDateAsString]; -// -// return _creationDate; -//} - -//- (NSDate *)originalCreationDate -//{ -// if(!_originalCreationDate) -// _originalCreationDate = [[NSDateFormatter sharedCoubJSONDateFormatter] dateFromString:_originalCreationDateAsString]; -// -// return _originalCreationDate; -//} - -- (NSURL *)mediumImageURL -{ - NSString *remoteImageFilePath = self.mediumPicture; - if(remoteImageFilePath) - return [NSURL URLWithString:[remoteImageFilePath hasPrefix:@"http://"] ? remoteImageFilePath : [[@"http://" stringByAppendingString:kCBServerURL] stringByAppendingPathComponent:remoteImageFilePath]]; - return nil; -} - - -- (NSURL *)largeImageURL -{ - NSString *remoteImageFilePath = self.largePicture; - if(remoteImageFilePath) - return [NSURL URLWithString:[remoteImageFilePath hasPrefix:@"http://"] ? remoteImageFilePath : [[@"http://" stringByAppendingString:kCBServerURL] stringByAppendingPathComponent:remoteImageFilePath]]; - return nil; -} - -- (BOOL)isRecoub -{ - return _recouber != nil ? YES : NO; -} - -//- (CBCoubStatusFlags)statusFlags -//{ -// CBCoubStatusFlags statusFlags = 0; -// -// if([_visibility isEqualToString:kCBCoubVisibilityFriends]) -// statusFlags |= CBCoubStatusFriendsOnly; -// else if([_visibility isEqualToString:kCBCoubVisibilityPrivate]) -// statusFlags |= CBCoubStatusPrivate; -// else if([_visibility isEqualToString:kCBCoubVisibilityUnlisted]) -// statusFlags |= CBCoubStatusUnlisted; -// switch(_audioType) -// { -// case CBCoubAudioTypeExternal: -// statusFlags |= CBCoubStatusExternalAudio; -// break; -// case CBCoubAudioTypeInternal: -// statusFlags |= CBCoubStatusHasAudioTrack; -// break; -// default: -// break; -// } -// -// return statusFlags; -//} - -- (NSURL *)remoteVideoFileURL -{ - NSURL *url = nil; - - NSString *remoteFilePath = self.remoteVideoLocation; - if([remoteFilePath isKindOfClass:[NSString class]] && remoteFilePath.length > 0) - { - url = [NSURL URLWithString:[remoteFilePath hasPrefix:@"http://"] ? remoteFilePath : [[@"http://" stringByAppendingString:kCBServerURL] stringByAppendingPathComponent:remoteFilePath]]; - if(!url) - [NSException raise:NSInternalInconsistencyException format:@"Could not make a URL from \"%@\"", remoteFilePath]; - } - return url; -} - -- (NSURL *)externalAudioURL -{ - NSURL *url = nil; - - NSString *remoteFilePath = self.remoteAudioLocation; - if([remoteFilePath isKindOfClass:[NSString class]] && remoteFilePath.length > 0) - { - url = [NSURL URLWithString:[remoteFilePath hasPrefix:@"http://"] ? remoteFilePath : [[@"http://" stringByAppendingString:kCBServerURL] stringByAppendingPathComponent:remoteFilePath]]; - if(!url) - [NSException raise:NSInternalInconsistencyException format:@"Could not make a URL from \"%@\"", remoteFilePath]; - } - return url; -} - -- (NSURL *)localVideoFileURL -{ - if (self.customLocalVideoFileURL != nil) - return self.customLocalVideoFileURL; - - if(self.permalink == nil) - return nil; - - - NSString *fileNameExtension = [self.remoteVideoLocation pathExtension] ?: @"mp4"; - NSString *localFileName = [[@"coub " stringByAppendingString:self.permalink] stringByAppendingPathExtension:fileNameExtension]; - NSString *path = [[CBLibrary sharedLibrary].mediaDirectory.path stringByAppendingPathComponent:localFileName]; - return [NSURL fileURLWithPath:path isDirectory:NO]; -} - -- (NSURL *)localAudioFileURL -{ - if(self.permalink == nil) - return nil; - - NSString *fileNameExtension = @"m4a"; - NSString *localFileName = [[@"coub " stringByAppendingString:self.permalink] stringByAppendingPathExtension:fileNameExtension]; - return [NSURL fileURLWithPath:[[CBLibrary sharedLibrary].mediaDirectory.path stringByAppendingPathComponent:localFileName] isDirectory:NO]; -} - -- (NSString *)assetId -{ - return self.permalink; -} - -- (BOOL)isAudioAvailable -{ - return (_audioType != CBCoubAudioTypeNone && !_failedDownloadChunks); -} - -- (BOOL)isEqualToCoub:(CBCoubNew *)coub -{ - return [coub.permalink isEqualToString:self.permalink]; -} - -+ (CBCoubNew *)coubWithAttributes:(NSDictionary *)attributes -{ - return [CBJSONCoubMapper coubFromJSONObject:attributes]; -} - -- (NSURL *)remoteAudioChunkWithIdx:(NSInteger)idx -{ - //NSLog(@"remoteAudioChunkWithIdx = %@ ", [NSURL URLWithString:[NSString stringWithFormat:_remoteAudioLocationPattern, idx]]); - - //NOTE: sometimes _remoteAudioLocationPattern - return [NSURL URLWithString:[NSString stringWithFormat:_remoteAudioLocationPattern, idx]]; -} - -- (NSURL *)localAudioChunkWithIdx:(NSInteger)idx -{ - //NSLog(@"localAudioChunkWithIdx = %i", idx); - - NSString *fileNameExtension = @"mp3"; - NSString *fileName = [[NSString stringWithFormat:@"coub mp3 chunk %i ", idx] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; - NSString *localFileName = [[fileName stringByAppendingString:self.permalink] stringByAppendingPathExtension:fileNameExtension]; - - return [NSURL fileURLWithPath:[[CBLibrary sharedLibrary].mediaDirectory.path stringByAppendingPathComponent:localFileName] isDirectory:NO]; -} - -- (BOOL)failedDownloadChunk -{ - return _failedDownloadChunks; -} - -- (void)setFailedDownloadChunk:(BOOL)failed -{ - _failedDownloadChunks = failed; -} - -@end diff --git a/submodules/LegacyComponents/Sources/CBCoubPlayer.h b/submodules/LegacyComponents/Sources/CBCoubPlayer.h deleted file mode 100755 index b212174afe..0000000000 --- a/submodules/LegacyComponents/Sources/CBCoubPlayer.h +++ /dev/null @@ -1,96 +0,0 @@ -// -// CBCoubPlayer.h -// Coub -// -// Created by Pavel Tikhonenko on 12/08/14. -// Copyright (c) 2014 Coub. All rights reserved. -// - -#import - -@class CBCoubPlayer; -@protocol CBCoubAsset; -@class AVPlayerLayer; - -typedef enum -{ - CBCoubPlayerStateReadyToPlay, - CBCoubPlayerStateRunning = 1, - CBCoubPlayerStatePlaying = (1 << 1) | CBCoubPlayerStateRunning, - CBCoubPlayerStatePaused = (1 << 2) | CBCoubPlayerStatePlaying, - CBCoubPlayerStateInterrupted = (1 << 3) | CBCoubPlayerStatePlaying, - CBCoubPlayerStateStopped = (1 << 4), - CBCoubPlayerStatePseudoStopped = (1 << 5) | CBCoubPlayerStateStopped, - CBCoubPlayerStateError = (1 << 6) | CBCoubPlayerStateStopped, - CBCoubPlayerStatePrepairing = (1 << 7) | CBCoubPlayerStateRunning, - CBCoubPlayerStateUnknown = NSNotFound, -} -CBCoubPlayerState; - -typedef enum -{ - CBCoubPlayerVideoPlayMethodDefault, - CBCoubPlayerVideoPlayMethodStream -} -CBCoubPlayerVideoPlayMethod; - -#pragma mark - -#pragma mark CBCoubPlayerDelegate - -@protocol CBCoubPlayerDelegate -@required -- (void)playerReadyToPlay:(CBCoubPlayer *)player; -- (void)playerDidStartPlaying:(CBCoubPlayer *)player; -- (void)playerDidPause:(CBCoubPlayer *)player withUserAction:(BOOL)isUserAction; -- (void)playerDidResume:(CBCoubPlayer *)player; -- (void)playerDidStop:(CBCoubPlayer *)player; -- (void)playerDidFail:(CBCoubPlayer *)player error:(NSError *)error; -- (void)player:(CBCoubPlayer *)player didReachProgressWhileDownloading:(float)progress; -@end - -#pragma mark - -#pragma mark CBCoubPlayer - -@interface CBCoubPlayer : NSObject - -@property (nonatomic, weak) id delegate; - -/// indicate whether player is playing -@property(nonatomic, readonly) BOOL isPlaying; -/// indicate whether player was paused -@property(nonatomic, readonly) BOOL isPaused; -/// indicate whether player was interrupted by system -@property(nonatomic, readonly) BOOL isInterrupted; -/// If Yes then this instance is current/active player -@property(nonatomic, readonly) BOOL isActivePlayer; -/// set/get current player state -@property(nonatomic, assign) CBCoubPlayerState state; - -/// set/get whether player playback only video -@property(nonatomic, assign) BOOL withoutAudio; //Default NO - -//Temp later move back to private var -@property(nonatomic, strong) id asset; - -@property(nonatomic, assign) CBCoubPlayerVideoPlayMethod videoPlayMethod; - - - -- (instancetype)initWithVideoLayer:(AVPlayerLayer *)layer; - -- (void)playAsset:(id)asset; -- (void)pause; -- (void)resume; -- (void)stop; - -// pause video and mute audio -- (void)pseudoStop; - -- (BOOL)isVideoLayerPlaying:(AVPlayerLayer *)layer; -- (BOOL)coubPlaying:(id)coub; -- (BOOL)coubPrepairing:(id)coub; - -+ (instancetype)activePlayer; -+ (instancetype)setActivePlayer:(CBCoubPlayer *)player; - -@end diff --git a/submodules/LegacyComponents/Sources/CBCoubPlayer.m b/submodules/LegacyComponents/Sources/CBCoubPlayer.m deleted file mode 100755 index 4c2d059adc..0000000000 --- a/submodules/LegacyComponents/Sources/CBCoubPlayer.m +++ /dev/null @@ -1,585 +0,0 @@ -// -// CBCoubPlayer.m -// Coub -// -// Created by Pavel Tikhonenko on 12/08/14. -// Copyright (c) 2014 Coub. All rights reserved. -// - -#import -#import "CBCoubPlayer.h" -#import "CBCoubAsset.h" -#import "CBVideoPlayer.h" -#import "CBCoubLoopCompositionMaker.h" -#import "CBAssetDownloadManager.h" -#import "STKAudioPlayer.h" -#import "CBLibrary.h" -#import "CBConstance.h" -#import "CBDownloadOperationDelegate.h" - -static CBCoubPlayer *gActivePlayer = nil; -static NSLock *gLock = nil; -static BOOL gPlaybackIsInterrupted = NO; - -@interface CBCoubPlayer () -{ - BOOL _shouldPlayWhenReady; - BOOL _shouldResumeWhenAppIsActive; - BOOL _shouldResumeWhenInterruptionEnds; - BOOL _shouldPlayAfterStop; - NSInteger _currentPlayingChunk; - double _startTime; -} - - -@property(nonatomic, strong) CBVideoPlayer *videoPlayer; -@property(nonatomic, strong) STKAudioPlayer *audioPlayer; -@property(nonatomic, strong) CBCoubLoopCompositionMaker *loopMaker; - - -@end - -@implementation CBCoubPlayer - -+ (void)initialize -{ - if(!gLock) - { - NSError *categoryError = NULL; - NSError *activeError = NULL; - - [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&categoryError]; - [[AVAudioSession sharedInstance] setActive:YES error:&activeError]; - - Float32 bufferLength = 0.1; - AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(bufferLength), &bufferLength); - - gLock = [[NSLock alloc] init]; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pauseActivePlayer:) name:UIApplicationWillResignActiveNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resumeActivePlayer:) name:UIApplicationDidBecomeActiveNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pauseActivePlayer:) name:CBPlayerInterruptionDidBeginNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resumeActivePlayer:) name:CBPlayerInterruptionDidEndNotification object:nil]; - } -} - -- (instancetype)initWithVideoLayer:(AVPlayerLayer *)layer -{ - return [self initWithVideoLayer:layer videoPlayMethod:CBCoubPlayerVideoPlayMethodDefault]; -} - -- (instancetype)initWithVideoLayer:(AVPlayerLayer *)layer videoPlayMethod:(CBCoubPlayerVideoPlayMethod)videoPlayMethod -{ - self = [super init]; - - if(self) - { - _currentPlayingChunk = -1; - _videoPlayMethod = videoPlayMethod; - _state = CBCoubPlayerStateUnknown; - - [self createVideoPlayerWithLayer:layer]; - - } - - return self; -} - -#pragma mark - -#pragma mark Getter/Setter - -- (BOOL)isPlaying -{ - return _state == CBCoubPlayerStatePlaying; -} - -- (BOOL)isPaused -{ - return _state == CBCoubPlayerStatePaused; -} - -- (BOOL)isActivePlayer -{ - return (gActivePlayer == self); -} - -#pragma mark - -#pragma mark Public methods - -- (void)playAsset:(id)asset -{ - NSLog(@"playAsset"); - - if(_state == CBCoubPlayerStateRunning && self.asset == asset) - return; - - if(gActivePlayer == self && self.asset == asset && gActivePlayer.state == CBCoubPlayerStatePlaying) - return; - - [[NSNotificationCenter defaultCenter] postNotificationName:@"interruptDownloading" object:nil]; - - //_startTime = [CBUtils timestamp]; - - if(gActivePlayer == self) - { - [_videoPlayer stop]; - [_audioPlayer dispose]; - }else{ - [self stopActivePlayer]; - [self becomeActivePlayer]; - } - - gPlaybackIsInterrupted = NO; //NOTE: note note note - _shouldPlayWhenReady = YES; - self.state = CBCoubPlayerStateRunning; - - self.asset = asset; - - [self downloadMediaAssetsWithCompletion:^(__unused id result) { - [self prepareLoopCompostion]; - }failure:^(NSError *error) { - [self failPlaybackWithError:error]; - }]; -} - -- (void)pause -{ - _shouldPlayWhenReady = NO; - - if(!self.isPlaying) - return; - - self.state = CBCoubPlayerStatePaused; - - [_videoPlayer pause]; - - if(_asset.audioType == CBCoubAudioTypeExternal) - [_audioPlayer pause]; - - if([_delegate respondsToSelector:@selector(playerDidPause:withUserAction:)]) - [_delegate playerDidPause:self withUserAction:YES]; -} - -- (void)resume -{ - _shouldPlayWhenReady = YES; - -// if(_state == CBCoubPlayerStateReadyToPlay) -// { -// [self startPlayingIfPossible]; -// } - if(self.state == CBCoubPlayerStatePaused){ - self.state = STKAudioPlayerStatePlaying; - - [_videoPlayer play]; - - if(_asset.audioType == CBCoubAudioTypeExternal) - [_audioPlayer resume]; - } - - if([_delegate respondsToSelector:@selector(playerDidResume:)]) - [_delegate playerDidResume:self]; -} - -- (void)stop -{ - _shouldPlayWhenReady = NO; - - if(self.state == CBCoubPlayerStateStopped || self.state == NSNotFound) - return; - - //KAObjectLog(@"stop player"); - - //[[CBAssetDownloadManager sharedManager] cancelDownloadingForCoub:_asset]; - - if([_delegate respondsToSelector:@selector(playerDidStop:)]) - [_delegate playerDidStop:self]; - -// [_audioPlayer pause]; - if(_asset.audioType == CBCoubAudioTypeExternal) - { - _audioPlayer.delegate = nil; - [_audioPlayer dispose]; - _audioPlayer = nil; - } - - [_videoPlayer stop]; - -// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ -// -// }); - - self.state = CBCoubPlayerStateStopped; - - [self resignActivePlayer]; -} - -- (void)pseudoStop -{ - _shouldPlayWhenReady = NO; - - if(self.isPlaying) - { - if(_asset.audioType == CBCoubAudioTypeExternal) - [_audioPlayer pause]; - else - [_videoPlayer pause]; - } - - self.state = CBCoubPlayerStatePseudoStopped; -} - -- (void)stopActivePlayer -{ - [gActivePlayer stop]; -} - -- (void)resetCurrentPlayer -{ - self.state = NSNotFound; - _shouldPlayWhenReady = YES; - _currentPlayingChunk = -1; - [self.loopMaker cancelPrepareLoop]; -} - -#pragma mark - -#pragma mark Private methods - -- (void)createVideoPlayerWithLayer:(AVPlayerLayer *)layer -{ - self.videoPlayer = [[CBVideoPlayer alloc] initWithVideoLayer:layer]; -} - -- (void)prepareVideoPlayer -{ - [_videoPlayer prepareWithAVAsset:self.loopMaker.videoAsset completion:^(NSError *error) { - if(error) - [self failPlaybackWithError:error]; - else{ - if([_delegate respondsToSelector:@selector(playerReadyToPlay:)]) - [_delegate playerReadyToPlay:self]; - - [self startPlayingIfPossible]; - } - }]; - - [self.loopMaker cancelPrepareLoop]; -} - -- (void)playVideoPlayer -{ - [_videoPlayer play]; - - if(_shouldPlayWhenReady == NO) - [self pause]; -} - -- (void)createAudioPlayer -{ - self.audioPlayer = [[STKAudioPlayer alloc] init]; - _audioPlayer.delegate = self; -} - -- (void)prepareAudioPlayer -{ - _currentPlayingChunk = -1; - -// STKAudioPlayerState state = _audioPlayer.state; - - [self startPlayingFirstAudioChunk]; -} - -- (void)startPlayingFirstAudioChunk -{ -// NSFileManager *fileManager = [NSFileManager defaultManager]; -// NSDictionary *attributes = [fileManager attributesOfItemAtPath:[_asset localAudioChunkWithIdx:0].path error:nil]; - - _shouldPlayAfterStop = NO; - - NSURL * url = [_asset localAudioChunkWithIdx:0]; - - if (url) { - [_audioPlayer playURL:url]; - } -} - -- (void)startPlayingIfPossible -{ - if(self.state == CBCoubPlayerStatePlaying) - return; - - self.state = CBCoubPlayerStateReadyToPlay; - - if(gPlaybackIsInterrupted && _shouldPlayWhenReady) - [self pauseWhileInterrupted]; - - if(!_shouldPlayWhenReady) - return; - - if(!_withoutAudio && _asset.audioType == CBCoubAudioTypeExternal && _audioPlayer.state != STKAudioPlayerStatePlaying) - { - [self createAudioPlayer]; - [self prepareAudioPlayer]; - return; - } - - [[NSNotificationCenter defaultCenter] postNotificationName:@"resumeDownloading" object:nil]; - - self.state = CBCoubPlayerStatePlaying; - - if([_delegate respondsToSelector:@selector(playerDidStartPlaying:)]) - [_delegate playerDidStartPlaying:self]; - - - [self playVideoPlayer]; - -// NSNumber *number = [NSNumber numberWithDouble:[CBUtils timestamp] - _startTime]; -// NSString *curPlace = [CBAnalyticManager sharedManager].currentPlayerPlace; -// NSString *assetId = _asset.assetId; -// -// NSDictionary *dict = @{@"loading_time":number, -// @"coubId":assetId, -// @"place": curPlace}; -// -// [[CBAnalyticManager sharedManager] track:@"player_started" -// properties:dict -// method:CBAnalyticManagerMethodCES]; -} - -- (void)downloadMediaAssetsWithCompletion:(CBSuccessBlock)success failure:(CBFailureBlock)failure -{ - [[CBAssetDownloadManager sharedManager] downloadCoub:_asset tag:-1 - withDelegate:self - withChunks:!_withoutAudio - downloadSucces:^(__unused id coub, __unused NSInteger tag) { - success(nil); - }downloadFailure:^(__unused id coub, __unused NSInteger tag, NSError *error) { - failure(error); - }]; -} - -- (void)downloadChunk:(NSInteger)idx -{ - if(_asset.audioType != CBCoubAudioTypeExternal) - return; - - [[CBAssetDownloadManager sharedManager] downloadChunkWithCoub:_asset tag:NSNotFound chunkIdx:idx downloadSucces:^(id __unused coub, NSInteger __unused tag) { - [_audioPlayer queueURL:[_asset localAudioChunkWithIdx:idx]]; - } downloadFailure:^(__unused id coub, __unused NSInteger tag, __unused NSError *error) { - - }]; - -// [[CBAssetDownloadManager sharedManager] downloadNextChunkWithCoub:_asset downloadSucces:^(id coub, NSInteger tag) { -// [_audioPlayer queueURL:[_asset localAudioChunkWithIdx:tag]]; -// } downloadFailure:^(id coub, NSInteger tag, NSError *error) { -// -// }]; -} - -- (void)prepareLoopCompostion -{ - if(self.state == CBCoubPlayerStateStopped) - return; - - self.loopMaker = [CBCoubLoopCompositionMaker coubLoopWithAsset:_asset]; - _loopMaker.delegate = self; - [_loopMaker prepareLoop]; -} - -- (void)failPlaybackWithError:(NSError *)error -{ - if(self.state == CBCoubPlayerStateStopped) - return; - - self.state = CBCoubPlayerStateError; - - if([_delegate respondsToSelector:@selector(playerDidFail:error:)]) - [_delegate playerDidFail:self error:error]; -} - -#pragma mark - - -- (void)becomeActivePlayer -{ - [gLock lock]; - if(gActivePlayer != self) - { - //[gActivePlayer pause]; - gActivePlayer = self; - } - [gLock unlock]; -} - - -- (void)resignActivePlayer -{ - [gLock lock]; - if(gActivePlayer == self && self.isPlaying == NO) - gActivePlayer = nil; - [gLock unlock]; -} - -#pragma mark - -#pragma mark Audio Player Delegate methods - -- (void)audioPlayer:(STKAudioPlayer *)audioPlayer stateChanged:(STKAudioPlayerState)state previousState:(STKAudioPlayerState)previousState -{ - if(state == STKAudioPlayerStateStopped && _shouldPlayAfterStop) - { - [self startPlayingFirstAudioChunk]; - return; - } - - if(state == STKAudioPlayerStatePlaying && self.state != CBCoubPlayerStatePlaying) - { - //KAObjectLog(@"STKAudioPlayerStatePlaying"); - - [self startPlayingIfPossible]; - } -} - -- (void)audioPlayer:(STKAudioPlayer *)audioPlayer unexpectedError:(STKAudioPlayerErrorCode)errorCode -{ - [self failPlaybackWithError:nil]; -} - -- (void)audioPlayer:(STKAudioPlayer *)audioPlayer didStartPlayingQueueItemId:(NSObject *)queueItemId -{ - if(_currentPlayingChunk == 3) - _currentPlayingChunk = -1; - - _currentPlayingChunk++; - - NSInteger nextItem = _currentPlayingChunk+1; - nextItem = nextItem > 3 ? 0 : nextItem; - - if([[CBLibrary sharedLibrary] isCoubChunkDownloadedByPermalink:_asset.assetId idx:nextItem]) - [_audioPlayer queueURL:[_asset localAudioChunkWithIdx:nextItem]]; - else - [self downloadChunk:nextItem]; -} - -- (void)audioPlayer:(STKAudioPlayer *)audioPlayer didFinishBufferingSourceWithQueueItemId:(NSObject *)queueItemId -{ - -} - -- (void)audioPlayer:(STKAudioPlayer *)audioPlayer didFinishPlayingQueueItemId:(NSObject *)queueItemId withReason:(STKAudioPlayerStopReason)stopReason andProgress:(double)progress andDuration:(double)duration -{ - -} - -- (void)audioPlayer:(STKAudioPlayer *)audioPlayer logInfo:(NSString *)line -{ - //KAObjectLog(@"%@", line); -} - -#pragma mark - -#pragma mark Download Manager Delegate methods - -- (void)downloadDidReachProgress:(float)progress -{ - if([_delegate respondsToSelector:@selector(player:didReachProgressWhileDownloading:)]) - [_delegate player:self didReachProgressWhileDownloading:progress]; -} - -- (void)downloadHasBeenCancelledWithError:(NSError *)error -{ - if(error == nil) - return; - - [self failPlaybackWithError:error]; -} - -#pragma mark - -#pragma mark Loop Composition Maker Delegate methods - -- (void)coubLoopDidFinishPreparing:(CBCoubLoopCompositionMaker *)loop -{ - [self prepareVideoPlayer]; -} - -- (void)coubLoop:(CBCoubLoopCompositionMaker *)loop didFailToLoadWithError:(NSError *)error -{ - if(error.code == CBCoubLoopErrorCanceled) - return; - - [self failPlaybackWithError:error]; -} - -#pragma mark - - -+ (void)pauseActivePlayer:(NSNotification *)notification -{ - //KAObjectLog(@"pauseActivePlayer %p", gActivePlayer); - - if([[notification name] isEqualToString:UIApplicationWillResignActiveNotification]) - { - [gActivePlayer pauseWhileInBackground]; - }else - { - gPlaybackIsInterrupted = YES; - [gActivePlayer pauseWhileInterrupted]; - } -} - - -+ (void)resumeActivePlayer:(NSNotification *)notification -{ - //KAObjectLog(@"resumeActivePlayer %p", gActivePlayer); - - NSLog(@"resumeActivePlayer"); - - if([[notification name] isEqualToString:UIApplicationDidBecomeActiveNotification]) - { - [gActivePlayer resumeIfPausedWhileInBackground]; - }else - { - gPlaybackIsInterrupted = NO; - [gActivePlayer resumeIfPausedWhileInterrupted]; - } -} - -- (void)pauseWhileInBackground -{ - _shouldResumeWhenAppIsActive = self.isPlaying || _shouldPlayWhenReady; - [self pause]; -} - - -- (void)resumeIfPausedWhileInBackground -{ - NSLog(@"resumeIfPausedWhileInBackground"); - - if(_shouldResumeWhenAppIsActive) - [self resume]; -} - - -- (void)pauseWhileInterrupted -{ - _shouldResumeWhenInterruptionEnds = self.isPlaying || _shouldPlayWhenReady; - [self pause]; -} - - -- (void)resumeIfPausedWhileInterrupted -{ - if(_shouldResumeWhenInterruptionEnds) - [self resume]; -} - -#pragma mark - - -+ (instancetype)activePlayer -{ - return gActivePlayer; -} - -- (void)dealloc -{ - _audioPlayer.delegate = nil; - [_audioPlayer dispose]; -} - -@end diff --git a/submodules/LegacyComponents/Sources/CBCoubPlayerContance.h b/submodules/LegacyComponents/Sources/CBCoubPlayerContance.h deleted file mode 100755 index 935c8e4685..0000000000 --- a/submodules/LegacyComponents/Sources/CBCoubPlayerContance.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// CBCoubPlayerContance.h -// CoubPlayer -// -// Created by Pavel Tikhonenko on 19/10/14. -// Copyright (c) 2014 Pavel Tikhonenko. All rights reserved. -// - -#import - -typedef NS_ENUM(UInt16, CBCoubAudioType) -{ - CBCoubAudioTypeNone = 0, - CBCoubAudioTypeInternal, - CBCoubAudioTypeExternal, -}; - -@interface CBCoubPlayerContance : NSObject - -@end diff --git a/submodules/LegacyComponents/Sources/CBCoubPlayerContance.m b/submodules/LegacyComponents/Sources/CBCoubPlayerContance.m deleted file mode 100755 index d2850886ff..0000000000 --- a/submodules/LegacyComponents/Sources/CBCoubPlayerContance.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// CBCoubPlayerContance.m -// CoubPlayer -// -// Created by Pavel Tikhonenko on 19/10/14. -// Copyright (c) 2014 Pavel Tikhonenko. All rights reserved. -// - -#import "CBCoubPlayerContance.h" - -@implementation CBCoubPlayerContance - -@end diff --git a/submodules/LegacyComponents/Sources/CBCoubVideoSource.h b/submodules/LegacyComponents/Sources/CBCoubVideoSource.h deleted file mode 100755 index a07b1d4c4c..0000000000 --- a/submodules/LegacyComponents/Sources/CBCoubVideoSource.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// CBCoubVideoSource.h -// Coub -// -// Created by Tikhonenko Pavel on 18/11/2013. -// Copyright (c) 2013 Coub. All rights reserved. -// - -#import - -@interface CBCoubVideoSource : NSObject - -@property (nonatomic, strong) NSString *yourtubeURL; -@property (nonatomic, strong) NSString *title; -@property (nonatomic, strong) NSString *thumbnail; -@property (nonatomic, readonly) BOOL isYouTube; - -+ (CBCoubVideoSource *)sourceFromData:(NSDictionary *)dict; - -@end \ No newline at end of file diff --git a/submodules/LegacyComponents/Sources/CBCoubVideoSource.m b/submodules/LegacyComponents/Sources/CBCoubVideoSource.m deleted file mode 100755 index 7226506f97..0000000000 --- a/submodules/LegacyComponents/Sources/CBCoubVideoSource.m +++ /dev/null @@ -1,33 +0,0 @@ -// -// CBCoubVideoSource.m -// Coub -// -// Created by Tikhonenko Pavel on 18/11/2013. -// Copyright (c) 2013 Coub. All rights reserved. -// - -#import "CBCoubVideoSource.h" - -@implementation CBCoubVideoSource - -- (BOOL)isYouTube -{ - return [_yourtubeURL rangeOfString:@"youtube"].length != 0; -} - -+ (CBCoubVideoSource *)sourceFromData:(NSDictionary *)dict -{ - if(!dict.count) return nil; - - CBCoubVideoSource *source = [[CBCoubVideoSource alloc] init]; - source.yourtubeURL = dict[@"url"]; - source.title = dict[@"title"]; - source.thumbnail = dict[@"image"]; - - if(source.yourtubeURL == nil) - return nil; - - return source; -} - -@end diff --git a/submodules/LegacyComponents/Sources/CBDownloadOperation.h b/submodules/LegacyComponents/Sources/CBDownloadOperation.h deleted file mode 100755 index fb98a3edfb..0000000000 --- a/submodules/LegacyComponents/Sources/CBDownloadOperation.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// CBDownloadOperation.h -// CoubPlayer -// -// Created by Pavel Tikhonenko on 19/10/14. -// Copyright (c) 2014 Pavel Tikhonenko. All rights reserved. -// - -#import -@protocol CBCoubAsset; -@protocol CBDownloadOperationDelegate; - -@protocol CBDownloadOperation - -@required -- (void)setTag:(NSInteger)tag; -- (NSInteger)tag; - -- (void)setCoub:(id)coub; -- (id)coub; - -- (void)setQueuePriority:(NSOperationQueuePriority)queuePriority; -- (NSOperationQueuePriority)queuePriority; - -//- (void)setDelegate:(id)delegate; - -- (void)setClientSuccess:(void (^)(id operation, NSInteger tag))success; -- (void)setClientFailure:(void (^)(id operation, NSInteger tag, NSError *error))failure; - -- (void)setCompletionBlock:(void (^)(id operation, NSError *error))completion; - -- (void)start; -- (void)cancel; - -- (instancetype)clone; - -@end diff --git a/submodules/LegacyComponents/Sources/CBDownloadOperationDelegate.h b/submodules/LegacyComponents/Sources/CBDownloadOperationDelegate.h deleted file mode 100755 index 9639ef811b..0000000000 --- a/submodules/LegacyComponents/Sources/CBDownloadOperationDelegate.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// CBDownloadOperationDelegate.h -// CoubPlayer -// -// Created by Pavel Tikhonenko on 19/10/14. -// Copyright (c) 2014 Pavel Tikhonenko. All rights reserved. -// - -#import - -@protocol CBDownloadOperationDelegate - -@optional -- (void)downloadDidReachProgress:(float)progress; -- (void)downloadHasBeenCancelledWithError:(NSError *)error; - -@end diff --git a/submodules/LegacyComponents/Sources/CBGenericDownloadOperation.h b/submodules/LegacyComponents/Sources/CBGenericDownloadOperation.h deleted file mode 100755 index 6b55e97fd5..0000000000 --- a/submodules/LegacyComponents/Sources/CBGenericDownloadOperation.h +++ /dev/null @@ -1,28 +0,0 @@ -#import -#import "CBDownloadOperation.h" -#import "CBCoubAsset.h" -#import "CBDownloadOperationDelegate.h" -#import "LegacyHTTPRequestOperation.h" - -@interface CBGenericDownloadOperation : NSObject - -@property (nonatomic, strong) NSOperation *downloadOperation; -@property (nonatomic, readwrite) NSOperationQueuePriority queuePriority; - -@property (nonatomic, assign) NSInteger tag; -@property (nonatomic, assign) BOOL starting; -@property (nonatomic, assign) BOOL comleted; -@property (nonatomic, assign) BOOL chunkDownloadingNeeded; - -@property (nonatomic, weak) id coub; -@property (nonatomic, weak) id operationViewDelegate; - -@property(nonatomic, copy) void (^clientSuccess)(id, NSInteger tag); -@property(nonatomic, copy) void (^clientFailure)(id, NSInteger tag, NSError *error); - -@property (nonatomic, copy) void (^completionBlock)(id process, NSError *error); - -//protected -- (void)successDownload; -- (void)failureDownloadWithError:(NSError *)error; -@end diff --git a/submodules/LegacyComponents/Sources/CBGenericDownloadOperation.m b/submodules/LegacyComponents/Sources/CBGenericDownloadOperation.m deleted file mode 100755 index a86dfc3b8c..0000000000 --- a/submodules/LegacyComponents/Sources/CBGenericDownloadOperation.m +++ /dev/null @@ -1,89 +0,0 @@ -// -// Created by Tikhonenko Pavel on 27/05/2014. -// Copyright (c) 2014 Coub. All rights reserved. -// - -#import "CBGenericDownloadOperation.h" -#import "CBCoubAsset.h" - -@implementation CBGenericDownloadOperation -{ - NSOperationQueuePriority _queuePriority; -} - -- (NSOperationQueuePriority)queuePriority -{ - return _queuePriority; -} - -- (void)setQueuePriority:(NSOperationQueuePriority)queuePriority -{ - _queuePriority = queuePriority; - - if(_downloadOperation) - _downloadOperation.queuePriority = queuePriority; -} - -- (void)start -{ - self.starting = YES; -} - -- (void)cancel -{ - self.starting = NO; - - NSError *cancelError = nil; - - if (!_downloadOperation.isFinished && !_downloadOperation.isCancelled) - { - //cancelError = [NSError errorWithDomain:kCBAssetDownloadManagerErrorDomain code:99 userInfo:nil]; - [_downloadOperation cancel]; - } - - [_operationViewDelegate downloadHasBeenCancelledWithError:cancelError]; - - self.clientSuccess = nil; - self.clientFailure = nil; -} - -- (void)successDownload -{ - if(self.starting) - { - self.starting = NO; - self.comleted = YES; - - if(self.operationViewDelegate != nil)[self.operationViewDelegate downloadHasBeenCancelledWithError:nil]; - if(self.clientSuccess != nil) self.clientSuccess(self.coub, self.tag); - if(self.completionBlock != nil) self.completionBlock(self, nil); - - self.downloadOperation = nil; - } -} - - -- (void)failureDownloadWithError:(NSError *)error -{ - if(self.starting) - { - self.starting = NO; - self.comleted = YES; - - if(self.operationViewDelegate != nil)[self.operationViewDelegate downloadHasBeenCancelledWithError:error]; - if(self.clientFailure != nil) self.clientFailure(self.coub, self.tag, error); - if(self.completionBlock != nil) self.completionBlock(self, error); - } -} - -- (instancetype)clone -{ - return nil; -} - -- (void)dealloc -{ - self.completionBlock = nil; -} - -@end diff --git a/submodules/LegacyComponents/Sources/CBJSONCoubMapper.h b/submodules/LegacyComponents/Sources/CBJSONCoubMapper.h deleted file mode 100755 index 6effbcbaec..0000000000 --- a/submodules/LegacyComponents/Sources/CBJSONCoubMapper.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// Created by Tikhonenko Pavel on 29/11/2013. -// Copyright (c) 2013 Coub. All rights reserved. -// - - -#import - -@class CBCoubNew; - - -@interface CBJSONCoubMapper : NSObject - -+ (CBCoubNew *)updateCoubFromCoub:(CBCoubNew *)newCoub coub:(CBCoubNew *)coub; -+ (CBCoubNew *)updateCoubFromJSONObject:(NSDictionary *)jsonObj coub:(CBCoubNew *)coub; -+ (CBCoubNew *)coubFromJSONObject:(NSDictionary *)jsonObj; - -@end \ No newline at end of file diff --git a/submodules/LegacyComponents/Sources/CBJSONCoubMapper.m b/submodules/LegacyComponents/Sources/CBJSONCoubMapper.m deleted file mode 100755 index ebdc9e9dcf..0000000000 --- a/submodules/LegacyComponents/Sources/CBJSONCoubMapper.m +++ /dev/null @@ -1,254 +0,0 @@ -// -// Created by Tikhonenko Pavel on 29/11/2013. -// Copyright (c) 2013 Coub. All rights reserved. -// - - -#import "CBJSONCoubMapper.h" -#import "CBCoubNew.h" -#import "NSDictionary+CBExtensions.h" -#import "CBCoubVideoSource.h" -#import "CBCoubAudioSource.h" -#import "CBTagNew.h" - - - -@implementation CBJSONCoubMapper -{ - -} - -+ (CBCoubNew *)updateCoubFromCoub:(CBCoubNew *)newCoub coub:(CBCoubNew *)coub -{ - coub.title = newCoub.title; - coub.liked = newCoub.liked; - coub.visibility = newCoub.visibility; - coub.recoubed = newCoub.recoubed; - coub.likeCount = newCoub.likeCount; - coub.recoubCount = newCoub.recoubCount; - coub.cotd = newCoub.cotd; - coub.flagged = newCoub.flagged; - coub.creationDate = coub.creationDate; - coub.creationDateAsString = coub.creationDateAsString; - -// if(newCoub.isDone) -// coub.state = CBCoubDraftCompleted; - - return coub; -} - -+ (CBCoubNew *)updateCoubFromJSONObject:(NSDictionary *)attributes coub:(CBCoubNew *)coub -{ - static NSDictionary *kCoubJSONKeys = nil; - if(!kCoubJSONKeys) - { - kCoubJSONKeys = @{ - //@"permalink" : @"permalink", - @"title" : @"title", - @"visibility_type" : @"visibility", - //@"created_at" : @"creationDateAsString", - //@"external_download" : @"externalDownloadAsDictionary", - @"like" : @"liked", - @"recoub" : @"recoubed", - @"likes_count" : @"likeCount", - @"views_count" : @"viewCount", - @"recoubs_count" : @"recoubCount", - @"cotd" : @"cotd", - @"flag" : @"flagged", - }; - } - - if ([attributes[@"title"] isKindOfClass:[NSString class]]) - { - NSString *title = attributes[@"title"]; - coub.title = title; - } - - NSDictionary *recoubInfo = nil; - - if(attributes[@"permalink"]) - coub.permalink = attributes[@"permalink"]; - - if(attributes[@"id"]) - coub.coubID = [attributes[@"id"] stringValue]; - - coub.originalPermalink = attributes[@"permalink"]; - coub.originalCreationDateAsString = attributes[@"created_at"]; - - if (coub.author == nil) - { - coub.author = [CBCoubAuthorVO coubAuthorWithAttributes:attributes[@"user"]]; - //coub.authorCD = [CBUserNewuserWithAttributes:attributes[@"user"]]; - } - - if (coub.author.name.length == 0) - { - NSDictionary *channel = attributes[@"channel"]; - if ([channel respondsToSelector:@selector(objectForKey:)]) - coub.author.name = channel[@"title"]; - } - - if(attributes[@"is_done"]) - coub.isDone = [attributes[@"is_done"] boolValue]; - - NSDictionary *fileVersions = attributes[@"file_versions"]; - NSString *remoteVideoLocation = attributes[@"explicitVideoLocation"]; - if (remoteVideoLocation) - { - remoteVideoLocation = [remoteVideoLocation stringByReplacingOccurrencesOfString:@"muted_mp4_med_" withString:@"mp4_med_"]; - remoteVideoLocation = [remoteVideoLocation stringByReplacingOccurrencesOfString:@"_muted_med" withString:@"_med"]; - coub.remoteVideoLocation = remoteVideoLocation; - } - else - { - if (fileVersions) - remoteVideoLocation = fileVersions[@"iphone"][@"url"]; - if(!remoteVideoLocation) - remoteVideoLocation = attributes[@"file"]; - if(!remoteVideoLocation || [remoteVideoLocation isEqual:[NSNull null]]) - remoteVideoLocation = fileVersions[@"html5"][@"video"][@"med"][@"url"]; - - if (remoteVideoLocation) - { - if ([remoteVideoLocation rangeOfString:@"muted_mp4"].location != NSNotFound) - { - remoteVideoLocation = [remoteVideoLocation stringByReplacingOccurrencesOfString:@"muted_mp4_med_" withString:@"mp4_med_"]; - remoteVideoLocation = [remoteVideoLocation stringByReplacingOccurrencesOfString:@"_muted_med" withString:@"_med"]; - coub.remoteVideoLocation = remoteVideoLocation; - } - else - { - NSRange r1 = [remoteVideoLocation rangeOfString:@"iphone_"]; - NSRange r2 = [remoteVideoLocation rangeOfString:@"_iphone"]; - - if (r1.location == NSNotFound) - { - r1 = [remoteVideoLocation rangeOfString:@"gifv_"]; - r2 = [remoteVideoLocation rangeOfString:@"_gifv"]; - } - - if (r1.location != NSNotFound) - { - NSInteger loc = r1.length+r1.location; - NSString *someVideoMetadataString = [remoteVideoLocation substringWithRange:NSMakeRange(loc, r2.location - loc)]; - - remoteVideoLocation = fileVersions[@"web"][@"template"]; - NSRange r3 = [remoteVideoLocation rangeOfString:@"%{"]; - - remoteVideoLocation = [remoteVideoLocation substringToIndex:r3.location]; - remoteVideoLocation = [NSString stringWithFormat:@"%@mp4_med_size_%@_med.mp4", remoteVideoLocation, someVideoMetadataString]; - coub.remoteVideoLocation = remoteVideoLocation; - } - else if ([remoteVideoLocation rangeOfString:@"mp4_med_size_"].location != NSNotFound) - { - coub.remoteVideoLocation = remoteVideoLocation; - } - } - } - } - - NSString *remoteAudioLocation = [attributes[@"audio_versions"] coubURIFromVersionTemplateWithPreferredSubstitutions:@[@"low", @"mid", @"high"]]; - if(!remoteAudioLocation) - remoteAudioLocation = attributes[@"audio_file_url"]; - if(!remoteAudioLocation || [remoteAudioLocation isEqual:[NSNull null]]) - remoteAudioLocation = fileVersions[@"mobile"][@"mp3"]; - if(remoteAudioLocation) - coub.remoteAudioLocation = remoteAudioLocation; - - NSDictionary *chunks = attributes[@"audio_versions"][@"chunks"]; - - if(chunks) - { - NSString *audioTemplate = chunks[@"template"]; - audioTemplate = [audioTemplate stringByReplacingOccurrencesOfString:@"%{version}" withString:@"low"]; - audioTemplate = [audioTemplate stringByReplacingOccurrencesOfString:@"%{chunk}" withString:@"%i"]; - coub.remoteAudioLocationPattern = audioTemplate; - } - - // big, med, small, ios_large - //KALog(@"ff=%@", [attributes[@"first_frame_versions"][@"versions"] componentsJoinedByString: @", "]); - NSString *largePictureLocation = [attributes[@"first_frame_versions"] coubURIFromVersionTemplateWithPreferredSubstitutions:@[@"med", @"big", @"ios_large"]]; - if(largePictureLocation) - coub.largePicture = largePictureLocation; - - // micro, tiny, age_restricted, ios_large, ios_mosaic, big, med, small - NSString *mediumPictureLocation = [attributes[@"image_versions"] coubURIFromVersionTemplateWithPreferredSubstitutions:@[@"ios_mosaic", @"small", @"med"]]; - if(!mediumPictureLocation) - mediumPictureLocation = attributes[@"picture"]; // short JSON - if(mediumPictureLocation) - coub.mediumPicture = mediumPictureLocation; - - // Determine the type of audio based on the values of "has_sound" and "audio_file_url" - if(coub.remoteAudioLocation && ([coub.remoteAudioLocation isKindOfClass:[NSString class]] && [coub.remoteAudioLocation length] < 8)) - coub.remoteAudioLocation = nil; - - if(attributes[@"visibility_type"]) - { - coub.audioType = coub.remoteAudioLocationPattern ? CBCoubAudioTypeExternal : ([attributes[@"has_sound"] boolValue] ? CBCoubAudioTypeInternal : CBCoubAudioTypeNone); - } - // else a short JSON doesn't have any information on sound - - NSDictionary *mediaBlock = attributes[@"media_blocks"]; - - BOOL isCoubAudioSourceAvailable = mediaBlock[@"audio_track"] != nil; - BOOL isCoubVideoSourceAvailable = mediaBlock[@"external_video"] != nil; - - if(isCoubVideoSourceAvailable) - coub.videoSource = [CBCoubVideoSource sourceFromData:mediaBlock[@"external_video"]]; - if(isCoubAudioSourceAvailable) - coub.audioSource = [CBCoubAudioSource sourceFromData:mediaBlock[@"audio_track"]]; - - if(coub.audioSource || coub.videoSource) - coub.isCoubSourcesAvailable = YES; - - NSDictionary *externalDownloadInfo = attributes[@"external_download"]; - if([externalDownloadInfo isKindOfClass:[NSDictionary class]]) - { - coub.externalDownloadType = externalDownloadInfo[@"type"]; - coub.externalDownloadSource = externalDownloadInfo[@"url"]; - }else - { - // Coub API may return a boolean "false" as "external_download" value - coub.externalDownloadType = nil; - coub.externalDownloadSource = nil; - } - - NSArray *tags = attributes[@"tags"]; - if(tags) - { - NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:tags.count]; - [tags enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) - { - [mutableArray addObject:[CBTagNew tagWithAttributes:obj]]; - }]; - - coub.tags = [NSArray arrayWithArray:mutableArray]; - } - - - - if(recoubInfo) - { - coub.recouber = [CBCoubAuthorVO coubAuthorWithAttributes:recoubInfo[@"user"]]; - coub.liked = [recoubInfo[@"like"] boolValue]; - coub.recoubed = [recoubInfo[@"recoub"] boolValue]; - coub.flagged = [recoubInfo[@"flagged"] boolValue]; - } - - if(!coub.coubID) - [NSException raise:NSInternalInconsistencyException format:@"No coub id found in %@", attributes]; - if(!coub.permalink) - [NSException raise:NSInternalInconsistencyException format:@"No coub permalink found in %@", attributes]; - - NSArray *size = attributes[@"dimensions"][@"small"]; - - //coub.naturalVideoSize = CGSizeMake([size[0] floatValue], [size[1] floatValue]); - return coub; -} - -+ (CBCoubNew *)coubFromJSONObject:(NSDictionary *)jsonObj -{ - return [self updateCoubFromJSONObject:jsonObj coub:[CBCoubNew new]]; -} - -@end diff --git a/submodules/LegacyComponents/Sources/CBLibrary.h b/submodules/LegacyComponents/Sources/CBLibrary.h deleted file mode 100755 index bc708069dd..0000000000 --- a/submodules/LegacyComponents/Sources/CBLibrary.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// CBLibrary.h -// Coub -// -// Created by Konstantin Anoshkin on 26.06.12. -// Copyright 2012 Coub. All rights reserved. -// - -#import -#import "CBCoubAsset.h" - -#if TARGET_IPHONE_SIMULATOR -// On iPhone Simulator NSTemporaryDirectory() returns a Mac OS X temporary directory which is outside our application sandbox. -// For consistency's sake we want to make it behave as on an honest-to-goodness iPhone device. -NSString *CBTemporaryDirectory (void); -#define NSTemporaryDirectory() CBTemporaryDirectory() -#endif - -NSString *CBDocumentsDirectory (void); -NSString *CBCachesDirectory (void); - -@interface CBLibrary : NSObject - -+ (CBLibrary *)sharedLibrary; - -- (void)markCoubAsset:(id)coub asDownloaded:(BOOL)downloaded; -- (BOOL)isCoubDownloadedByPermalink:(NSString *)permalink; - -- (void)markCoubChunk:(id)coub idx:(NSInteger)idx asDownloaded:(BOOL)downloaded; -- (BOOL)isCoubChunkDownloadedByPermalink:(NSString *)permalink idx:(NSInteger)idx; - -- (void)cleanUpMediaCache; - -@property (strong, nonatomic) NSURL *mediaDirectory; - -@end diff --git a/submodules/LegacyComponents/Sources/CBLibrary.m b/submodules/LegacyComponents/Sources/CBLibrary.m deleted file mode 100755 index 609349f176..0000000000 --- a/submodules/LegacyComponents/Sources/CBLibrary.m +++ /dev/null @@ -1,236 +0,0 @@ -// -// CBLibrary.m -// Coub -// -// Created by Konstantin Anoshkin on 26.06.12. -// Copyright 2012 Coub. All rights reserved. -// - -#define CBLIBRARY_IMPLEMENTATION_FILE - -#import "CBLibrary.h" -#import - - -#if TARGET_IPHONE_SIMULATOR -NSString *CBTemporaryDirectory (void) -{ - return [NSHomeDirectory() stringByAppendingPathComponent: @"tmp"]; -} -#endif - - -NSString *CBDocumentsDirectory (void) -{ - static NSString *sPath = nil; - if (!sPath) - sPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] copy]; - return sPath; -} - - -NSString *CBCachesDirectory (void) -{ - static NSString *sPath = nil; - if (!sPath) { - sPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] copy]; - if (![[NSFileManager defaultManager] fileExistsAtPath: sPath]) - [[NSFileManager defaultManager] createDirectoryAtPath: sPath withIntermediateDirectories: YES attributes: nil error: NULL]; - } - return sPath; -} - - -NSString *CBMediaDirectory (void) -{ - static NSString *sPath = nil; - if (!sPath) { - sPath = [[[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent: @"Media"] copy]; - } - return sPath; -} - -NSString *const kCBLibraryDatabaseFileNameExtension = @"sqlite"; -NSString *const kCBLibraryCurrentUserID = @"currentUserID"; - - -@implementation CBLibrary -{ -@private - NSURL *_mediaDirectory; - NSMutableDictionary *_cachedMediaFiles; -} - - -+ (CBLibrary *)sharedLibrary -{ - static id sSharedInstance = nil; - static dispatch_once_t onceToken = 0; - dispatch_once(&onceToken, ^ - { - sSharedInstance = [[self alloc] init]; - }); - return sSharedInstance; -} - - -- (id)init -{ - self = [super init]; - - if(self) - { - _cachedMediaFiles = [NSMutableDictionary new]; - } - - return self; -} - -#pragma mark - Paths & URLs - -- (void)setMediaDirectory:(NSURL *)mediaDirectory -{ - if (_mediaDirectory && ![mediaDirectory.absoluteString isEqualToString:_mediaDirectory.absoluteString]) { - [self cleanUpMediaCache]; - } - - if (mediaDirectory && ![mediaDirectory.absoluteString isEqualToString:_mediaDirectory.absoluteString]) { - _mediaDirectory = mediaDirectory; - [self createMediaDirectory]; - } else { - _mediaDirectory = mediaDirectory; - } -} - -- (NSURL *)mediaDirectory -{ - if(!_mediaDirectory) { - _mediaDirectory = [NSURL fileURLWithPath:CBMediaDirectory() isDirectory:YES]; - [self createMediaDirectory]; - } - return _mediaDirectory; -} - -- (void)createMediaDirectory -{ - NSError *error = nil; - NSString *mediaDirectoryPath = [[self mediaDirectory] path]; - if(![[NSFileManager defaultManager] fileExistsAtPath:mediaDirectoryPath]) - { - if(![[NSFileManager defaultManager] createDirectoryAtPath:mediaDirectoryPath withIntermediateDirectories:YES attributes:nil error:&error]) - { - NSLog(@"*** Could not recreate Media directory, %@", error); - return; - } - - if(&NSURLIsExcludedFromBackupKey) - { - if(![[self mediaDirectory] setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:&error]) - NSLog(@"*** Failed to set NSURLIsExcludedFromBackupKey for %@, %@", [self mediaDirectory], error); - }else - { - // Set the Do Not Backup extended attribute, http://developer.apple.com/library/ios/#qa/qa1719/_index.html - - - u_int8_t attrValue = 1; - if(setxattr([mediaDirectoryPath fileSystemRepresentation], "com.apple.MobileBackup", &attrValue, sizeof(attrValue), 0, 0)) - { - //KAObjectLogError(@"setxattr(%@) failed: %s (%d)", mediaDirectoryPath, strerror(errno), errno); - } - } - } - - - -} - -- (void)markCoubAsset:(id)coub asDownloaded:(BOOL)downloaded -{ - if(downloaded) - { - if([self isCoubDownloadedByPermalink:coub.assetId]) - return; - - NSError *error = nil; - NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath:[coub.localVideoFileURL path] error:&error]; - if(attrs) - { - _cachedMediaFiles[coub.assetId] = [NSMutableDictionary dictionaryWithDictionary:@{@"coub" : coub, @"downloadedChunks": @0}]; - }else - { - //KAObjectLogError(@"Can't get attributes at %@: %@", coub.localVideoFileURL, error); - } - }else - { - [_cachedMediaFiles removeObjectForKey:coub.assetId]; - } -} - -- (BOOL)isCoubDownloadedByPermalink:(NSString *)permalink -{ - return _cachedMediaFiles[permalink] != nil; -} - -- (void)markCoubChunk:(id)coub idx:(NSInteger)idx asDownloaded:(BOOL)downloaded -{ - //NSLog(@"markCoubChunk %i", idx); - - NSMutableDictionary *mediaFile = _cachedMediaFiles[coub.assetId]; - - if(mediaFile) - { - NSInteger downloadedChunks = ((NSNumber *)mediaFile[@"downloadedChunks"]).integerValue; - NSInteger normalIdx = 1< - -@interface CBPlayerLayerView : UIView - -@end diff --git a/submodules/LegacyComponents/Sources/CBPlayerLayerView.m b/submodules/LegacyComponents/Sources/CBPlayerLayerView.m deleted file mode 100755 index 9e25cc8573..0000000000 --- a/submodules/LegacyComponents/Sources/CBPlayerLayerView.m +++ /dev/null @@ -1,20 +0,0 @@ -// -// CBPlayerLayerView.m -// Coub -// -// Created by Tikhonenko Pavel on 23/11/2013. -// Copyright (c) 2013 Coub. All rights reserved. -// - -#import "CBPlayerLayerView.h" - -#import - -@implementation CBPlayerLayerView - -+ (Class)layerClass -{ - return [AVPlayerLayer class]; -} - -@end diff --git a/submodules/LegacyComponents/Sources/CBPlayerView.h b/submodules/LegacyComponents/Sources/CBPlayerView.h deleted file mode 100755 index 06350aee73..0000000000 --- a/submodules/LegacyComponents/Sources/CBPlayerView.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// CBPlayerView.h -// CoubPlayer -// -// Created by Pavel Tikhonenko on 17/10/14. -// Copyright (c) 2014 Pavel Tikhonenko. All rights reserved. -// - -#import - -#import - -#import "CBCoubPlayer.h" -#import "CBPlayerLayerView.h" - -@interface CBPlayerView : UIView - -@property (nonatomic, readonly) UIImageView *preview; -@property (nonatomic, readonly) CBPlayerLayerView *videoPlayerView; - -- (void)play; -- (void)stop; - -@end - -//@interface CBPlayerLayerView : UIView -//@end \ No newline at end of file diff --git a/submodules/LegacyComponents/Sources/CBPlayerView.m b/submodules/LegacyComponents/Sources/CBPlayerView.m deleted file mode 100755 index 9bda935f06..0000000000 --- a/submodules/LegacyComponents/Sources/CBPlayerView.m +++ /dev/null @@ -1,101 +0,0 @@ -// -// CBPlayerView.m -// CoubPlayer -// -// Created by Pavel Tikhonenko on 17/10/14. -// Copyright (c) 2014 Pavel Tikhonenko. All rights reserved. -// - -#import "CBPlayerView.h" - - - -@implementation CBPlayerView - -- (id)initWithFrame:(CGRect)frame -{ - self = [super initWithFrame:frame]; - - if(self) - { - [self setupView]; - } - - return self; -} -- (void)setupView -{ - self.clipsToBounds = YES; - - _preview = [[UIImageView alloc] initWithFrame:self.bounds]; - _preview.contentMode = UIViewContentModeScaleAspectFill; - [self addSubview:_preview]; - - _videoPlayerView = [[CBPlayerLayerView alloc] initWithFrame:self.bounds]; - _videoPlayerView.hidden = YES; - ((AVPlayerLayer *) _videoPlayerView.layer).videoGravity = AVLayerVideoGravityResizeAspectFill; - [self addSubview:_videoPlayerView]; -} - -- (void)setContentMode:(UIViewContentMode)contentMode -{ - [super setContentMode:contentMode]; - - _preview.contentMode = contentMode; - ((AVPlayerLayer *)_videoPlayerView.layer).videoGravity = (contentMode == UIViewContentModeScaleAspectFit) ? AVLayerVideoGravityResizeAspect : AVLayerVideoGravityResizeAspectFill; -} - -- (void)layoutSubviews -{ - [super layoutSubviews]; - - CGRect bounds = self.bounds; - - _videoPlayerView.frame = bounds; - _preview.frame = bounds; -} - -- (void)play -{ - _videoPlayerView.hidden = NO; -} - -- (void)stop -{ - _videoPlayerView.hidden = YES; -} - -//- (void) layoutSubviews -//{ -// // We need manual aspect fill/fit layout if we want fluid frame animations -// CGRect bounds = self.bounds; -// //_preview.frame = bounds; -// -// if (self.contentMode == UIViewContentModeScaleAspectFit) { -// CGRect viewFrame = bounds; -// -// CGSize size = _player.loop.videoTrackSize; -// if (size.width && size.height) { -// CGFloat scale = fminf(viewFrame.size.width / size.width, viewFrame.size.height / size.height); -// size.width = roundf(size.width * scale); -// size.height = roundf(size.height * scale); -// viewFrame = CGRectInset(viewFrame, 0.5f * (viewFrame.size.width - size.width), 0.5f * (viewFrame.size.height - size.height)); -// } -// -// _videoPlayerView.frame = viewFrame; -// } else -// _videoPlayerView.frame = bounds; -// -// CGPoint center = (CGPoint) { CGRectGetMidX(bounds), CGRectGetMidY(bounds) }; -// _spinner.center = center; -// _reloadButton.center = center; -//} - -@end - -//#pragma mark - -//#pragma mark CBPlayerLayerView -// -//@implementation CBPlayerLayerView -//+ (Class)layerClass { return [AVPlayerLayer class]; } -//@end diff --git a/submodules/LegacyComponents/Sources/CBTagNew.h b/submodules/LegacyComponents/Sources/CBTagNew.h deleted file mode 100755 index 6052d00c11..0000000000 --- a/submodules/LegacyComponents/Sources/CBTagNew.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// Created by Tikhonenko Pavel on 30/11/2013. -// Copyright (c) 2013 Coub. All rights reserved. -// - - -#import - - -@interface CBTagNew : NSObject -@property (nonatomic, strong) NSNumber *tagId; -@property (nonatomic, strong) NSString *title; -@property (nonatomic, strong) NSString *value; -@property (nonatomic, readonly) NSString *hashTag; - -+ (instancetype)tagWithAttributes:(NSDictionary *)attributes; - -@end \ No newline at end of file diff --git a/submodules/LegacyComponents/Sources/CBTagNew.m b/submodules/LegacyComponents/Sources/CBTagNew.m deleted file mode 100755 index 7229d24414..0000000000 --- a/submodules/LegacyComponents/Sources/CBTagNew.m +++ /dev/null @@ -1,29 +0,0 @@ -// -// Created by Tikhonenko Pavel on 30/11/2013. -// Copyright (c) 2013 Coub. All rights reserved. -// - - -#import "CBTagNew.h" - - -@implementation CBTagNew -{ - -} - -- (NSString *)hashTag -{ - return [@"#" stringByAppendingString:_title]; -} - -+ (instancetype)tagWithAttributes:(NSDictionary *)attributes -{ - CBTagNew *tag = [CBTagNew new]; - tag.tagId = attributes[@"id"]; - tag.title = attributes[@"title"]; - tag.value = attributes[@"value"]; - return tag; -} - -@end \ No newline at end of file diff --git a/submodules/LegacyComponents/Sources/CBVideoPlayer.h b/submodules/LegacyComponents/Sources/CBVideoPlayer.h deleted file mode 100755 index 7bc9cb7f0b..0000000000 --- a/submodules/LegacyComponents/Sources/CBVideoPlayer.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// CBVideoPlayer.h -// Coub -// -// Created by Pavel Tikhonenko on 12/08/14. -// Copyright (c) 2014 Coub. All rights reserved. -// - -#import -#import - -typedef enum -{ - CBVideoPlayerStatusInited, - CBVideoPlayerStatusPrepairing = 1, - CBVideoPlayerStatusReadyToPlay = 1 << 1, - CBVideoPlayerStatusFailed = 1 << 2, - CBVideoPlayerStatusUnknown = NSNotFound - -} -CBVideoPlayerStatus; - -@interface CBVideoPlayer : NSObject - -@property (nonatomic, assign) CBVideoPlayerStatus status; - -- (id)initWithVideoLayer:(AVPlayerLayer *)layer; - -- (void)prepareWithAVAsset:(AVAsset *)asset completion:(void (^)(NSError *error))completion; -- (void)stopPrepairing; - -- (void)play; -- (void)pause; -- (void)stop; - -@end diff --git a/submodules/LegacyComponents/Sources/CBVideoPlayer.m b/submodules/LegacyComponents/Sources/CBVideoPlayer.m deleted file mode 100755 index adae6c2cab..0000000000 --- a/submodules/LegacyComponents/Sources/CBVideoPlayer.m +++ /dev/null @@ -1,193 +0,0 @@ -// -// CBVideoPlayer.m -// Coub -// -// Created by Pavel Tikhonenko on 12/08/14. -// Copyright (c) 2014 Coub. All rights reserved. -// - -#import "CBVideoPlayer.h" - -static void *kPlayerItemContext = (void *) 1; -static void *kPlayerStatusContext = (void *) 2; - -static void *kPlayerLayerReadyToDisplayContext = (void *) 4; - -@interface CBVideoPlayer () - -@property (nonatomic, strong) AVPlayerLayer *layer; -@property (nonatomic, strong) AVPlayer *videoPlayer; -@property (nonatomic, strong) AVPlayerItem *nextItem; -@property (nonatomic, assign) BOOL hasBeenReseted; - -@property (nonatomic, copy) void (^prepairingCompletion)(NSError *error); - -@end - -@implementation CBVideoPlayer - -- (id)initWithVideoLayer:(AVPlayerLayer *)layer -{ - self = [super init]; - - if(self) - { - self.status = CBVideoPlayerStatusUnknown; - self.hasBeenReseted = YES; - - self.layer = layer; - - [self createVideoPlayer]; - - - self.status = CBVideoPlayerStatusInited; - } - - return self; -} - -#pragma mark - -#pragma mark Public methods - -- (void)prepareWithAVAsset:(AVAsset *)asset completion:(void (^)(NSError *error))completion -{ - self.prepairingCompletion = completion; - - self.status = CBVideoPlayerStatusPrepairing; - - if(!_hasBeenReseted) - [self resetPlayer]; - - _hasBeenReseted = NO; - - [self prepareVideoPlayer]; - [self prepareVideoLayer]; - - AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:asset]; - [self.videoPlayer replaceCurrentItemWithPlayerItem:item]; - -} - -- (void)play -{ - [_videoPlayer play]; -} - -- (void)pause -{ - _videoPlayer.rate = 0; -} - -- (void)stop -{ - _videoPlayer.rate = 0; - - [self resetPlayer]; - [self.videoPlayer replaceCurrentItemWithPlayerItem:nil]; -} - -- (void)stopPrepairing -{ -} - -#pragma mark - -#pragma mark Private methods - -- (void)createVideoPlayer -{ - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(restartAVPlayer:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil]; - - self.videoPlayer = [AVPlayer new]; - _videoPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone; - -} - -- (void)prepareVideoPlayer -{ - [_videoPlayer addObserver:self forKeyPath:@"currentItem" options:NSKeyValueObservingOptionNew context:kPlayerItemContext]; - [_videoPlayer addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:kPlayerStatusContext]; -} - -- (void)prepareVideoLayer -{ - [_layer addObserver:self forKeyPath:@"readyForDisplay" options:NSKeyValueObservingOptionNew context:kPlayerLayerReadyToDisplayContext]; -} - -- (void)resetPlayer -{ - @try{ - [_videoPlayer removeObserver:self forKeyPath:@"currentItem" context:kPlayerItemContext]; - }@catch(id anException){} - - @try{ - [_videoPlayer removeObserver:self forKeyPath:@"status" context:kPlayerStatusContext]; - }@catch(id anException){} - - @try{ - [_layer removeObserver:self forKeyPath:@"readyForDisplay" context:kPlayerLayerReadyToDisplayContext]; - }@catch(id anException){} -} - -- (void)prerollPlayer -{ - [_videoPlayer prerollAtRate:1 completionHandler:^(BOOL finished) { - [_layer setPlayer:self.videoPlayer]; - }]; -} -- (void)completeVideoPrepairing -{ - [self resetPlayer]; - self.prepairingCompletion(nil); -} - -- (void)restartAVPlayer:(NSNotification *)notification -{ - AVPlayerItem *playerItem = [notification object]; - if (playerItem == _videoPlayer.currentItem) - [_videoPlayer seekToTime:kCMTimeZero]; -} - -#pragma mark - -#pragma mark Observe value - -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context -{ - AVPlayer *player = (AVPlayer *) object; - - if(context == kPlayerLayerReadyToDisplayContext) - { - [self completeVideoPrepairing]; - } - - if(context == kPlayerStatusContext || context == kPlayerItemContext) - { - //KAObjectLog(@"%@ status: %i", player == self.videoPlayer ? @"videoPlayer" : @"audioPlayer", player.status); - - NSLog(@"status: %i", player.status); - if(context == kPlayerItemContext && player.currentItem == nil && _nextItem) - return; - - if(context == kPlayerItemContext && player.currentItem == nil) - return; - - if(player.status == AVPlayerStatusReadyToPlay) - { - [self prerollPlayer]; - }else if(player.status == AVPlayerStatusFailed) - { - //[self.delegate playerInitialzeProccess:self completeWithError:[NSError errorWithDomain:@"com.coub.player" code:99 userInfo:nil]]; - - }//else if(player.status == AVPlayerStatusUnknown) - //KAObjectLog(@"%@ AVPlayerStatusUnknown: %@", player == self.videoPlayer ? @"videoPlayer" : @"audioPlayer", player.error); - } -} - -- (void)dealloc -{ - @try{ - [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:nil]; - }@catch(id anException){} - - [self resetPlayer]; -} -@end diff --git a/submodules/LegacyComponents/Sources/NSDictionary+CBExtensions.h b/submodules/LegacyComponents/Sources/NSDictionary+CBExtensions.h deleted file mode 100755 index 285d40b3ba..0000000000 --- a/submodules/LegacyComponents/Sources/NSDictionary+CBExtensions.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// NSDictionary+Extensions.h -// Coub -// -// Created by Konstantin Anoshkin on 8.10.13. -// Copyright 2013 Coub. All rights reserved. -// - -#import - - -@interface NSDictionary (CBDictionaryExtensions) - -- (NSString *) coubURIFromVersionTemplateWithPreferredSubstitutions: (NSArray *) preferredVersions; - -@end diff --git a/submodules/LegacyComponents/Sources/NSDictionary+CBExtensions.m b/submodules/LegacyComponents/Sources/NSDictionary+CBExtensions.m deleted file mode 100755 index affd8281b4..0000000000 --- a/submodules/LegacyComponents/Sources/NSDictionary+CBExtensions.m +++ /dev/null @@ -1,38 +0,0 @@ -// -// NSDictionary+Extensions.m -// Coub -// -// Created by Konstantin Anoshkin on 8.10.13. -// Copyright 2013 Coub. All rights reserved. -// - -#import "NSDictionary+CBExtensions.h" - - -@implementation NSDictionary (CBDictionaryExtensions) - - -- (NSString *) coubURIFromVersionTemplateWithPreferredSubstitutions: (NSArray *) preferredVersions -{ - NSString *urlTemplate = self[@"template"]; - if (urlTemplate) { - NSArray *availableVersions = self[@"versions"]; - __block NSString *bestVersion = nil; - [preferredVersions enumerateObjectsUsingBlock: ^(NSString *version, __unused NSUInteger idx, BOOL *stop) { - if ([availableVersions containsObject: version]) { - bestVersion = version; - *stop = YES; - } - }]; - if (bestVersion) { - //KALog(@"%@", [urlTemplate stringByReplacingOccurrencesOfString: @"%{version}" withString: bestVersion]); - return [urlTemplate stringByReplacingOccurrencesOfString: @"%{version}" withString: bestVersion]; - } else { - //KAObjectLogError(@"Could not find appropriate URI version: {%@}", [preferredVersions componentsJoinedByString: @", "]); - } - } - return nil; -} - - -@end diff --git a/submodules/LegacyComponents/Sources/NSMutableArray+STKAudioPlayer.h b/submodules/LegacyComponents/Sources/NSMutableArray+STKAudioPlayer.h deleted file mode 100755 index 12ca8396b4..0000000000 --- a/submodules/LegacyComponents/Sources/NSMutableArray+STKAudioPlayer.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// NSMutableArray+STKAudioPlayer.h -// StreamingKit -// -// Created by Thong Nguyen on 30/01/2014. -// Copyright (c) 2014 Thong Nguyen. All rights reserved. -// - -#import - -@interface NSMutableArray (STKAudioPlayer) --(void) enqueue:(id)obj; --(void) skipQueue:(id)obj; --(void) skipQueueWithQueue:(NSMutableArray*)queue; --(id) dequeue; --(id) peek; -@end diff --git a/submodules/LegacyComponents/Sources/NSMutableArray+STKAudioPlayer.m b/submodules/LegacyComponents/Sources/NSMutableArray+STKAudioPlayer.m deleted file mode 100755 index 493868f45d..0000000000 --- a/submodules/LegacyComponents/Sources/NSMutableArray+STKAudioPlayer.m +++ /dev/null @@ -1,50 +0,0 @@ -// -// NSMutableArray+STKAudioPlayer.m -// StreamingKit -// -// Created by Thong Nguyen on 30/01/2014. -// Copyright (c) 2014 Thong Nguyen. All rights reserved. -// - -#import "NSMutableArray+STKAudioPlayer.h" - -@implementation NSMutableArray (STKAudioPlayer) - --(void) enqueue:(id)obj -{ - [self insertObject:obj atIndex:0]; -} - --(void) skipQueue:(id)obj -{ - [self addObject:obj]; -} - --(void) skipQueueWithQueue:(NSMutableArray*)queue -{ - for (id item in queue) - { - [self addObject:item]; - } -} - --(id) dequeue -{ - if ([self count] == 0) - { - return nil; - } - - id retval = [self lastObject]; - - [self removeLastObject]; - - return retval; -} - --(id) peek -{ - return [self lastObject]; -} - -@end diff --git a/submodules/LegacyComponents/Sources/PGPhotoFilter.h b/submodules/LegacyComponents/Sources/PGPhotoFilter.h deleted file mode 100644 index eddd041ec5..0000000000 --- a/submodules/LegacyComponents/Sources/PGPhotoFilter.h +++ /dev/null @@ -1,19 +0,0 @@ -#import "PGPhotoEditorItem.h" - -@class PGPhotoFilterDefinition; -@class PGPhotoProcessPass; - -@interface PGPhotoFilter : NSObject -{ - PGPhotoProcessPass *_pass; -} - -@property (nonatomic, readonly) PGPhotoFilterDefinition *definition; -@property (nonatomic, retain) PGPhotoProcessPass *pass; -@property (nonatomic, readonly) PGPhotoProcessPass *optimizedPass; - -- (void)invalidate; - -+ (PGPhotoFilter *)filterWithDefinition:(PGPhotoFilterDefinition *)definition; - -@end diff --git a/submodules/LegacyComponents/Sources/PGPhotoFilter.m b/submodules/LegacyComponents/Sources/PGPhotoFilter.m deleted file mode 100644 index f37c7bef8d..0000000000 --- a/submodules/LegacyComponents/Sources/PGPhotoFilter.m +++ /dev/null @@ -1,242 +0,0 @@ -#import "PGPhotoFilter.h" - -#import "TGPhotoEditorGenericToolView.h" - -#import "PGPhotoFilterDefinition.h" - -#import "PGPhotoCustomFilterPass.h" -#import "PGPhotoLookupFilterPass.h" -#import "PGPhotoProcessPass.h" - -@interface PGPhotoFilter () -{ - PGPhotoProcessPass *_parameter; -} -@end - -@implementation PGPhotoFilter - -@synthesize value = _value; -@synthesize tempValue = _tempValue; -@synthesize parameters = _parameters; -@synthesize beingEdited = _beingEdited; -@synthesize shouldBeSkipped = _shouldBeSkipped; -@synthesize parametersChanged = _parametersChanged; -@synthesize disabled = _disabled; -@synthesize segmented = _segmented; - -- (instancetype)initWithDefinition:(PGPhotoFilterDefinition *)definition -{ - self = [super init]; - if (self != nil) - { - _definition = definition; - _value = @(self.defaultValue); - } - return self; -} - -- (instancetype)copyWithZone:(NSZone *)__unused zone -{ - PGPhotoFilter *filter = [[PGPhotoFilter alloc] initWithDefinition:self.definition]; - filter.value = self.value; - return filter; -} - -- (NSString *)title -{ - return _definition.title; -} - -- (NSString *)identifier -{ - return _definition.identifier; -} - -- (PGPhotoProcessPass *)pass -{ - if (_pass == nil) - { - switch (_definition.type) - { - case PGPhotoFilterTypeCustom: - { - _pass = [[PGPhotoCustomFilterPass alloc] initWithShaderFile:_definition.shaderFilename textureFiles:_definition.textureFilenames]; - } - break; - - case PGPhotoFilterTypeLookup: - { - _pass = [[PGPhotoLookupFilterPass alloc] initWithLookupImage:[UIImage imageNamed:[NSString stringWithFormat:@"%@.png", _definition.lookupFilename]]]; - } - break; - - default: - { - _pass = [[PGPhotoProcessPass alloc] init]; - } - break; - } - } - - [self updatePassParameters]; - - return _pass; -} - -- (PGPhotoProcessPass *)optimizedPass -{ - switch (_definition.type) - { - case PGPhotoFilterTypeCustom: - { - return [[PGPhotoCustomFilterPass alloc] initWithShaderFile:_definition.shaderFilename textureFiles:_definition.textureFilenames optimized:true]; - } - break; - - case PGPhotoFilterTypeLookup: - { - return [[PGPhotoLookupFilterPass alloc] initWithLookupImage:[UIImage imageNamed:[NSString stringWithFormat:@"%@.png", _definition.lookupFilename]]]; - } - break; - - default: - break; - } - - return [[PGPhotoProcessPass alloc] init]; -} - -- (Class)valueClass -{ - return [NSNumber class]; -} - -- (CGFloat)minimumValue -{ - return 0.0f; -} - -- (CGFloat)maximumValue -{ - return 100.0f; -} - -- (CGFloat)defaultValue -{ - return 100.0f; -} - -- (id)tempValue -{ - if (self.disabled) - { - if ([_tempValue isKindOfClass:[NSNumber class]]) - return @0; - } - - return _tempValue; -} - -- (id)displayValue -{ - if (self.beingEdited) - return self.tempValue; - - return self.value; -} - -- (void)setValue:(id)value -{ - _value = value; - - if (!self.beingEdited) - [self updateParameters]; -} - -- (void)setTempValue:(id)tempValue -{ - _tempValue = tempValue; - - if (self.beingEdited) - [self updateParameters]; -} - -- (NSArray *)parameters -{ - return _parameters; -} - -- (void)updateParameters -{ - -} - -- (void)updatePassParameters -{ - CGFloat value = ((NSNumber *)self.displayValue).floatValue / self.maximumValue; - - if ([_pass isKindOfClass:[PGPhotoLookupFilterPass class]]) - { - PGPhotoLookupFilterPass *pass = (PGPhotoLookupFilterPass *)_pass; - [pass setIntensity:value]; - } - else if ([_pass isKindOfClass:[PGPhotoCustomFilterPass class]]) - { - PGPhotoCustomFilterPass *pass = (PGPhotoCustomFilterPass *)_pass; - [pass setIntensity:value]; - } -} - -- (void)invalidate -{ - _pass = nil; - _value = @(self.defaultValue); -} - -- (void)reset -{ - [_pass.filter removeAllTargets]; -} - -- (id)itemControlViewWithChangeBlock:(void (^)(id newValue, bool animated))changeBlock -{ - __weak PGPhotoFilter *weakSelf = self; - - id view = [[TGPhotoEditorGenericToolView alloc] initWithEditorItem:self]; - view.valueChanged = ^(id newValue, bool animated) - { - __strong PGPhotoFilter *strongSelf = weakSelf; - if (strongSelf == nil) - return; - - strongSelf.tempValue = newValue; - - if (changeBlock != nil) - changeBlock(newValue, animated); - }; - return view; -} - -- (UIView *)itemAreaViewWithChangeBlock:(void (^)(id newValue))__unused changeBlock -{ - return nil; -} - -- (BOOL)isEqual:(id)object -{ - if (object == self) - return YES; - - if (!object || ![object isKindOfClass:[self class]]) - return NO; - - return ([[(PGPhotoFilter *)object definition].identifier isEqualToString:self.definition.identifier]); -} - -+ (PGPhotoFilter *)filterWithDefinition:(PGPhotoFilterDefinition *)definition -{ - return [[[self class] alloc] initWithDefinition:definition]; -} - -@end diff --git a/submodules/LegacyComponents/Sources/PGPhotoFilterDefinition.h b/submodules/LegacyComponents/Sources/PGPhotoFilterDefinition.h deleted file mode 100644 index 1c15ed0746..0000000000 --- a/submodules/LegacyComponents/Sources/PGPhotoFilterDefinition.h +++ /dev/null @@ -1,21 +0,0 @@ -#import - -typedef enum { - PGPhotoFilterTypePassThrough, - PGPhotoFilterTypeLookup, - PGPhotoFilterTypeCustom -} PGPhotoFilterType; - -@interface PGPhotoFilterDefinition : NSObject - -@property (readonly, nonatomic) NSString *identifier; -@property (readonly, nonatomic) NSString *title; -@property (readonly, nonatomic) PGPhotoFilterType type; -@property (readonly, nonatomic) NSString *lookupFilename; -@property (readonly, nonatomic) NSString *shaderFilename; -@property (readonly, nonatomic) NSArray *textureFilenames; - -+ (PGPhotoFilterDefinition *)originalFilterDefinition; -+ (PGPhotoFilterDefinition *)definitionWithDictionary:(NSDictionary *)dictionary; - -@end diff --git a/submodules/LegacyComponents/Sources/PGPhotoFilterDefinition.m b/submodules/LegacyComponents/Sources/PGPhotoFilterDefinition.m deleted file mode 100644 index f2f3b27995..0000000000 --- a/submodules/LegacyComponents/Sources/PGPhotoFilterDefinition.m +++ /dev/null @@ -1,35 +0,0 @@ -#import "PGPhotoFilterDefinition.h" - -@implementation PGPhotoFilterDefinition - -+ (PGPhotoFilterDefinition *)originalFilterDefinition -{ - PGPhotoFilterDefinition *definition = [[PGPhotoFilterDefinition alloc] init]; - definition->_type = PGPhotoFilterTypePassThrough; - definition->_identifier = @"0_0"; - definition->_title = @"Original"; - - return definition; -} - -+ (PGPhotoFilterDefinition *)definitionWithDictionary:(NSDictionary *)dictionary -{ - PGPhotoFilterDefinition *definition = [[PGPhotoFilterDefinition alloc] init]; - - if ([dictionary[@"type"] isEqualToString:@"lookup"]) - definition->_type = PGPhotoFilterTypeLookup; - else if ([dictionary[@"type"] isEqualToString:@"custom"]) - definition->_type = PGPhotoFilterTypeCustom; - else - return nil; - - definition->_identifier = dictionary[@"id"]; - definition->_title = dictionary[@"title"]; - definition->_lookupFilename = dictionary[@"lookup_name"]; - definition->_shaderFilename = dictionary[@"shader_name"]; - definition->_textureFilenames = dictionary[@"texture_names"]; - - return definition; -} - -@end diff --git a/submodules/LegacyComponents/Sources/PGPhotoFilterThumbnailManager.h b/submodules/LegacyComponents/Sources/PGPhotoFilterThumbnailManager.h deleted file mode 100644 index b215d589ce..0000000000 --- a/submodules/LegacyComponents/Sources/PGPhotoFilterThumbnailManager.h +++ /dev/null @@ -1,20 +0,0 @@ -#import -#import - -@class PGPhotoEditor; -@class PGPhotoFilter; - -@interface PGPhotoFilterThumbnailManager : NSObject - -@property (nonatomic, weak) PGPhotoEditor *photoEditor; - -- (void)setThumbnailImage:(UIImage *)image; -- (void)requestThumbnailImageForFilter:(PGPhotoFilter *)filter completion:(void (^)(UIImage *thumbnailImage, bool cached, bool finished))completion; -- (void)startCachingThumbnailImagesForFilters:(NSArray *)filters; -- (void)stopCachingThumbnailImagesForFilters:(NSArray *)filters; -- (void)stopCachingThumbnailImagesForAllFilters; -- (void)invalidateThumbnailImages; - -- (void)haltCaching; - -@end diff --git a/submodules/LegacyComponents/Sources/PGPhotoFilterThumbnailManager.m b/submodules/LegacyComponents/Sources/PGPhotoFilterThumbnailManager.m deleted file mode 100644 index c1594aa32e..0000000000 --- a/submodules/LegacyComponents/Sources/PGPhotoFilterThumbnailManager.m +++ /dev/null @@ -1,277 +0,0 @@ -#import "PGPhotoFilterThumbnailManager.h" - -#import -#import - -#import - -#import "PGPhotoEditor.h" -#import "PGPhotoFilter.h" -#import "PGPhotoFilterDefinition.h" -#import "PGPhotoProcessPass.h" -#import "PGPhotoEditorPicture.h" - -const NSUInteger TGFilterThumbnailCacheSoftMemoryLimit = 2 * 1024 * 1024; -const NSUInteger TGFilterThumbnailCacheHardMemoryLimit = 2 * 1024 * 1024; - -@interface PGPhotoFilterThumbnailManager () -{ - TGMemoryImageCache *_filterThumbnailCache; - SQueue *_cachingQueue; - - UIImage *_thumbnailImage; - PGPhotoEditorPicture *_thumbnailPicture; - - SQueue *_filteringQueue; - dispatch_queue_t _prepQueue; - - pthread_rwlock_t _callbackLock; - NSMutableDictionary *_callbacksForId; - - NSInteger _version; -} - -@end - -@implementation PGPhotoFilterThumbnailManager - -- (instancetype)init -{ - self = [super init]; - if (self != nil) - { - [self invalidateThumbnailImages]; - - _prepQueue = dispatch_queue_create("ph.pictogra.Pictograph.FilterThumbnailQueue", DISPATCH_QUEUE_CONCURRENT); - - _cachingQueue = [[SQueue alloc] init]; - _callbacksForId = [[NSMutableDictionary alloc] init]; - - _filteringQueue = [[SQueue alloc] init]; - pthread_rwlock_init(&_callbackLock, NULL); - } - return self; -} - -- (void)setThumbnailImage:(UIImage *)image -{ - [self invalidateThumbnailImages]; - _thumbnailImage = image; - - //_thumbnailPicture = [[PGPhotoEditorPicture alloc] initWithImage:_thumbnailImage]; -} - -- (void)requestThumbnailImageForFilter:(PGPhotoFilter *)filter completion:(void (^)(UIImage *image, bool cached, bool finished))completion -{ - if (filter.definition.type == PGPhotoFilterTypePassThrough) - { - if (completion != nil) - { - if (_thumbnailImage != nil) - completion(_thumbnailImage, true, true); - else - completion(nil, true, false); - } - - return; - } - - UIImage *cachedImage = [_filterThumbnailCache imageForKey:filter.identifier attributes:nil]; - if (cachedImage != nil) - { - if (completion != nil) - completion(cachedImage, true, true); - return; - } - - if (_thumbnailImage == nil) - { - completion(nil, true, true); - return; - } - - if (completion != nil) - completion(_thumbnailImage, true, false); - - NSInteger version = _version; - - __weak PGPhotoFilterThumbnailManager *weakSelf = self; - [self _addCallback:completion forId:filter.identifier createCallback:^ - { - __strong PGPhotoFilterThumbnailManager *strongSelf = weakSelf; - if (strongSelf == nil) - return; - - if (version != strongSelf->_version) - return; - - [strongSelf renderFilterThumbnailWithPicture:strongSelf->_thumbnailPicture filter:filter completion:^(UIImage *result) - { - [strongSelf _processCompletionForId:filter.identifier withResult:result]; - }]; - }]; -} - -- (void)startCachingThumbnailImagesForFilters:(NSArray *)filters -{ - if (_thumbnailImage == nil) - return; - - NSMutableArray *filtersToStartCaching = [[NSMutableArray alloc] init]; - - for (PGPhotoFilter *filter in filters) - { - if (filter.definition.type != PGPhotoFilterTypePassThrough && [_filterThumbnailCache imageForKey:filter.identifier attributes:nil] == nil) - [filtersToStartCaching addObject:filter]; - } - - NSInteger version = _version; - - [_cachingQueue dispatch:^ - { - if (version != _version) - return; - - for (PGPhotoFilter *filter in filtersToStartCaching) - { - __weak PGPhotoFilterThumbnailManager *weakSelf = self; - [self _addCallback:nil forId:filter.identifier createCallback:^ - { - __strong PGPhotoFilterThumbnailManager *strongSelf = weakSelf; - if (strongSelf == nil) - return; - - if (version != strongSelf->_version) - return; - - [strongSelf renderFilterThumbnailWithPicture:strongSelf->_thumbnailPicture filter:filter completion:^(UIImage *result) - { - [strongSelf _processCompletionForId:filter.identifier withResult:result]; - }]; - }]; - } - }]; -} - -- (void)stopCachingThumbnailImagesForFilters:(NSArray *)__unused filters -{ - -} - -- (void)stopCachingThumbnailImagesForAllFilters -{ - -} - -- (void)_processCompletionForId:(NSString *)filterId withResult:(UIImage *)result -{ - [_filterThumbnailCache setImage:result forKey:filterId attributes:nil]; - - NSArray *callbacks = [self _callbacksForId:filterId]; - [self _removeCallbacksForId:filterId]; - - for (id callback in callbacks) - { - void(^callbackBlock)(UIImage *image, bool cached, bool finished) = callback; - if (callbackBlock != nil) - callbackBlock(result, false, true); - } -} - -- (void)renderFilterThumbnailWithPicture:(PGPhotoEditorPicture *)picture filter:(PGPhotoFilter *)filter completion:(void (^)(UIImage *result))completion -{ - PGPhotoEditor *photoEditor = self.photoEditor; - if (photoEditor == nil) - return; - - NSInteger version = _version; - dispatch_async(_prepQueue, ^ - { - GPUImageOutput *gpuFilter = filter.optimizedPass.filter; - [_filteringQueue dispatch:^ - { - if (version != _version) - return; - - [picture addTarget:gpuFilter]; - [gpuFilter useNextFrameForImageCapture]; - [picture processSynchronous:true completion:^ - { - UIImage *image = [gpuFilter imageFromCurrentFramebufferWithOrientation:UIImageOrientationUp]; - [picture removeAllTargets]; - - if (completion != nil) - completion(image); - }]; - }]; - }); -} - -- (void)invalidateThumbnailImages -{ - _version = lrand48(); - - _filterThumbnailCache = [[TGMemoryImageCache alloc] initWithSoftMemoryLimit:TGFilterThumbnailCacheSoftMemoryLimit - hardMemoryLimit:TGFilterThumbnailCacheHardMemoryLimit]; -} - -- (void)haltCaching -{ - _version = lrand48(); -} - -- (void)_addCallback:(void (^)(UIImage *, bool, bool))callback forId:(NSString *)filterId createCallback:(void (^)(void))createCallback -{ - if (filterId == nil) - { - callback(nil, true, false); - return; - } - - pthread_rwlock_rdlock(&_callbackLock); - - bool isInitial = false; - if (_callbacksForId[filterId] == nil) - { - isInitial = true; - _callbacksForId[filterId] = [[NSMutableArray alloc] init]; - } - - if (callback != nil) - { - NSMutableArray *callbacksForId = _callbacksForId[filterId]; - [callbacksForId addObject:callback]; - _callbacksForId[filterId] = callbacksForId; - } - - if (isInitial && createCallback != nil) - createCallback(); - - pthread_rwlock_unlock(&_callbackLock); -} - -- (NSArray *)_callbacksForId:(NSString *)filterId -{ - if (filterId == nil) - return nil; - - __block NSArray *callbacksForId; - - pthread_rwlock_rdlock(&_callbackLock); - callbacksForId = _callbacksForId[filterId]; - pthread_rwlock_unlock(&_callbackLock); - - return [callbacksForId copy]; -} - -- (void)_removeCallbacksForId:(NSString *)filterId -{ - if (filterId == nil) - return; - - pthread_rwlock_rdlock(&_callbackLock); - [_callbacksForId removeObjectForKey:filterId]; - pthread_rwlock_unlock(&_callbackLock); -} - -@end diff --git a/submodules/LegacyComponents/Sources/STKAudioPlayer.h b/submodules/LegacyComponents/Sources/STKAudioPlayer.h deleted file mode 100755 index 0ce6d53852..0000000000 --- a/submodules/LegacyComponents/Sources/STKAudioPlayer.h +++ /dev/null @@ -1,266 +0,0 @@ -/********************************************************************************** - AudioPlayer.m - - Created by Thong Nguyen on 14/05/2012. - https://github.com/tumtumtum/StreamingKit - - Inspired by Matt Gallagher's AudioStreamer: - https://github.com/mattgallagher/AudioStreamer - - Copyright (c) 2012-2014 Thong Nguyen (tumtumtum@gmail.com). All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. All advertising materials mentioning features or use of this software - must display the following acknowledgement: - This product includes software developed by Thong Nguyen (tumtumtum@gmail.com) - 4. Neither the name of Thong Nguyen nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Thong Nguyen''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - **********************************************************************************/ - -#import -#import -#import "STKDataSource.h" -#import - -#if TARGET_OS_IPHONE -#include "UIKit/UIApplication.h" -#endif - -typedef enum -{ - STKAudioPlayerStateReady, - STKAudioPlayerStateRunning = 1, - STKAudioPlayerStatePlaying = (1 << 1) | STKAudioPlayerStateRunning, - STKAudioPlayerStateBuffering = (1 << 2) | STKAudioPlayerStateRunning, - STKAudioPlayerStatePaused = (1 << 3) | STKAudioPlayerStateRunning, - STKAudioPlayerStateStopped = (1 << 4), - STKAudioPlayerStateError = (1 << 5), - STKAudioPlayerStateDisposed = (1 << 6) -} -STKAudioPlayerState; - -typedef enum -{ - STKAudioPlayerStopReasonNone = 0, - STKAudioPlayerStopReasonEof, - STKAudioPlayerStopReasonUserAction, - STKAudioPlayerStopReasonPendingNext, - STKAudioPlayerStopReasonDisposed, - STKAudioPlayerStopReasonError = 0xffff -} -STKAudioPlayerStopReason; - -typedef enum -{ - STKAudioPlayerErrorNone = 0, - STKAudioPlayerErrorDataSource, - STKAudioPlayerErrorStreamParseBytesFailed, - STKAudioPlayerErrorAudioSystemError, - STKAudioPlayerErrorCodecError, - STKAudioPlayerErrorDataNotFound, - STKAudioPlayerErrorOther = 0xffff -} -STKAudioPlayerErrorCode; - -typedef struct -{ - /// If YES then seeking a track will cause all pending items to be flushed from the queue - BOOL flushQueueOnSeek; - /// If YES then volume control will be enabled on iOS - BOOL enableVolumeMixer; - /// A pointer to a 0 terminated array of band frequencies (iOS 5.0 and later, OSX 10.9 and later) - Float32 equalizerBandFrequencies[24]; - /// The size of the internal I/O read buffer. This data in this buffer is transient and does not need to be larger. - UInt32 readBufferSize; - /// The size of the decompressed buffer (Default is 10 seconds which uses about 1.7MB of RAM) - UInt32 bufferSizeInSeconds; - /// Number of seconds of decompressed audio is required before playback first starts for each item (Default is 0.5 seconds. Must be larger than bufferSizeInSeconds) - Float32 secondsRequiredToStartPlaying; - /// Seconds after a seek is performed before data needs to come in (after which the state will change to playing/buffering) - Float32 gracePeriodAfterSeekInSeconds; - /// Number of seconds of decompressed audio required before playback resumes after a buffer underrun (Default is 5 seconds. Must be larger than bufferSizeinSeconds) - Float32 secondsRequiredToStartPlayingAfterBufferUnderun; -} -STKAudioPlayerOptions; - -typedef void(^STKFrameFilter)(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UInt32 frameCount, void* frames); - -@interface STKFrameFilterEntry : NSObject -@property (readonly) NSString* name; -@property (readonly) STKFrameFilter filter; -@end - -@class STKAudioPlayer; - -@protocol STKAudioPlayerDelegate - -/// Raised when an item has started playing --(void) audioPlayer:(STKAudioPlayer*)audioPlayer didStartPlayingQueueItemId:(NSObject*)queueItemId; -/// Raised when an item has finished buffering (may or may not be the currently playing item) -/// This event may be raised multiple times for the same item if seek is invoked on the player --(void) audioPlayer:(STKAudioPlayer*)audioPlayer didFinishBufferingSourceWithQueueItemId:(NSObject*)queueItemId; -/// Raised when the state of the player has changed --(void) audioPlayer:(STKAudioPlayer*)audioPlayer stateChanged:(STKAudioPlayerState)state previousState:(STKAudioPlayerState)previousState; -/// Raised when an item has finished playing --(void) audioPlayer:(STKAudioPlayer*)audioPlayer didFinishPlayingQueueItemId:(NSObject*)queueItemId withReason:(STKAudioPlayerStopReason)stopReason andProgress:(double)progress andDuration:(double)duration; -/// Raised when an unexpected and possibly unrecoverable error has occured (usually best to recreate the STKAudioPlauyer) --(void) audioPlayer:(STKAudioPlayer*)audioPlayer unexpectedError:(STKAudioPlayerErrorCode)errorCode; -@optional -/// Optionally implemented to get logging information from the STKAudioPlayer (used internally for debugging) --(void) audioPlayer:(STKAudioPlayer*)audioPlayer logInfo:(NSString*)line; -/// Raised when items queued items are cleared (usually because of a call to play, setDataSource or stop) --(void) audioPlayer:(STKAudioPlayer*)audioPlayer didCancelQueuedItems:(NSArray*)queuedItems; - -@end - -@interface STKAudioPlayer : NSObject - -/// Gets or sets the volume (ranges 0 - 1.0). -/// On iOS the STKAudioPlayerOptionEnableMultichannelMixer option must be enabled for volume to work. -@property (readwrite) Float32 volume; -/// Gets or sets the player muted state -@property (readwrite) BOOL muted; -/// Gets the current item duration in seconds -@property (readonly) double duration; -/// Gets the current item progress in seconds -@property (readonly) double progress; -/// Enables or disables peak and average decibel meteting -@property (readwrite) BOOL meteringEnabled; -/// Enables or disables the EQ -@property (readwrite) BOOL equalizerEnabled; -/// Returns an array of STKFrameFilterEntry objects representing the filters currently in use -@property (readonly) NSArray* frameFilters; -/// Returns the items pending to be played (includes buffering and upcoming items but does not include the current item) -@property (readonly) NSArray* pendingQueue; -/// The number of items pending to be played (includes buffering and upcoming items but does not include the current item) -@property (readonly) NSUInteger pendingQueueCount; -/// Gets the most recently queued item that is still pending to play -@property (readonly) NSObject* mostRecentlyQueuedStillPendingItem; -/// Gets the current state of the player -@property (readwrite) STKAudioPlayerState state; -/// Gets the options provided to the player on startup -@property (readonly) STKAudioPlayerOptions options; -/// Gets the reason why the player is stopped (if any) -@property (readonly) STKAudioPlayerStopReason stopReason; -/// Gets and sets the delegate used for receiving events from the STKAudioPlayer -@property (readwrite, unsafe_unretained) id delegate; - -/// Creates a datasource from a given URL. -/// URLs with FILE schemes will return an STKLocalFileDataSource. -/// URLs with HTTP schemes will return an STKHTTPDataSource wrapped within an STKAutoRecoveringHTTPDataSource. -/// URLs with unrecognised schemes will return nil. -+(STKDataSource*) dataSourceFromURL:(NSURL*)url; - -/// Initializes a new STKAudioPlayer with the default options --(id) init; - -/// Initializes a new STKAudioPlayer with the given options --(id) initWithOptions:(STKAudioPlayerOptions)optionsIn; - -/// Plays an item from the given URL string (all pending queued items are removed). -/// The NSString is used as the queue item ID --(void) play:(NSString*)urlString; - -/// Plays an item from the given URL (all pending queued items are removed) --(void) play:(NSString*)urlString withQueueItemID:(NSObject*)queueItemId; - -/// Plays an item from the given URL (all pending queued items are removed) -/// The NSURL is used as the queue item ID --(void) playURL:(NSURL*)url; - -/// Plays an item from the given URL (all pending queued items are removed) --(void) playURL:(NSURL*)url withQueueItemID:(NSObject*)queueItemId; - -/// Plays the given item (all pending queued items are removed) -/// The STKDataSource is used as the queue item ID --(void) playDataSource:(STKDataSource*)dataSource; - -/// Plays the given item (all pending queued items are removed) --(void) playDataSource:(STKDataSource*)dataSource withQueueItemID:(NSObject*)queueItemId; - -/// Queues the URL string for playback and uses the NSString as the queueItemID --(void) queue:(NSString*)urlString; - -/// Queues the URL string for playback with the given queueItemID --(void) queue:(NSString*)urlString withQueueItemId:(NSObject*)queueItemId; - -/// Queues the URL for playback and uses the NSURL as the queueItemID --(void) queueURL:(NSURL*)url; - -/// Queues the URL for playback with the given queueItemID --(void) queueURL:(NSURL*)url withQueueItemId:(NSObject*)queueItemId; - -/// Queues a DataSource with the given queueItemId --(void) queueDataSource:(STKDataSource*)dataSource withQueueItemId:(NSObject*)queueItemId; - -/// Plays the given item (all pending queued items are removed) --(void) setDataSource:(STKDataSource*)dataSourceIn withQueueItemId:(NSObject*)queueItemId; - -/// Seeks to a specific time (in seconds) --(void) seekToTime:(double)value; - -/// Clears any upcoming items already queued for playback (does not stop the current item). -/// The didCancelItems event will be raised for the items removed from the queue. --(void) clearQueue; - -/// Pauses playback --(void) pause; - -/// Resumes playback from pause --(void) resume; - -/// Stops playback of the current file, flushes all the buffers and removes any pending queued items --(void) stop; - -/// Mutes playback --(void) mute; - -/// Unmutes playback --(void) unmute; - -/// Disposes the STKAudioPlayer and frees up all resources before returning --(void) dispose; - -/// The QueueItemId of the currently playing item --(NSObject*) currentlyPlayingQueueItemId; - -/// Removes a frame filter with the given name --(void) removeFrameFilterWithName:(NSString*)name; - -/// Appends a frame filter with the given name and filter block to the end of the filter chain --(void) appendFrameFilterWithName:(NSString*)name block:(STKFrameFilter)block; - -/// Appends a frame filter with the given name and filter block just after the filter with the given name. -/// If the given name is nil, the filter will be inserted at the beginning of the filter change --(void) addFrameFilterWithName:(NSString*)name afterFilterWithName:(NSString*)afterFilterWithName block:(STKFrameFilter)block; - -/// Reads the peak power in decibals for the given channel (0 or 1). -/// Return values are between -60 (low) and 0 (high). --(float) peakPowerInDecibelsForChannel:(NSUInteger)channelNumber; - -/// Reads the average power in decibals for the given channel (0 or 1) -/// Return values are between -60 (low) and 0 (high). --(float) averagePowerInDecibelsForChannel:(NSUInteger)channelNumber; - -/// Sets the gain value (from -96 low to +24 high) for an equalizer band (0 based index) --(void) setGain:(float)gain forEqualizerBand:(int)bandIndex; - -@end diff --git a/submodules/LegacyComponents/Sources/STKAudioPlayer.m b/submodules/LegacyComponents/Sources/STKAudioPlayer.m deleted file mode 100755 index a00a883d42..0000000000 --- a/submodules/LegacyComponents/Sources/STKAudioPlayer.m +++ /dev/null @@ -1,3157 +0,0 @@ -/********************************************************************************** - AudioPlayer.m - - Created by Thong Nguyen on 14/05/2012. - https://github.com/tumtumtum/StreamingKit - - Copyright (c) 2014 Thong Nguyen (tumtumtum@gmail.com). All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. All advertising materials mentioning features or use of this software - must display the following acknowledgement: - This product includes software developed by Thong Nguyen (tumtumtum@gmail.com) - 4. Neither the name of Thong Nguyen nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Thong Nguyen''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - **********************************************************************************/ - -#import "STKAudioPlayer.h" -#import "AudioToolbox/AudioToolbox.h" -#import "STKHTTPDataSource.h" -#import "STKAutoRecoveringHTTPDataSource.h" -#import "STKLocalFileDataSource.h" -#import "STKQueueEntry.h" -#import "NSMutableArray+STKAudioPlayer.h" -#import "libkern/OSAtomic.h" -#import - -#ifndef DBL_MAX -#define DBL_MAX 1.7976931348623157e+308 -#endif - -#pragma mark Defines - -#define kOutputBus 0 -#define kInputBus 1 - -#define STK_DBMIN (-60) -#define STK_DBOFFSET (-74.0) -#define STK_LOWPASSFILTERTIMESLICE (0.0005) - -#define STK_DEFAULT_PCM_BUFFER_SIZE_IN_SECONDS (10) -#define STK_DEFAULT_SECONDS_REQUIRED_TO_START_PLAYING (1) -#define STK_DEFAULT_SECONDS_REQUIRED_TO_START_PLAYING_AFTER_BUFFER_UNDERRUN (7.5) -#define STK_MAX_COMPRESSED_PACKETS_FOR_BITRATE_CALCULATION (4096) -#define STK_DEFAULT_READ_BUFFER_SIZE (64 * 1024) -#define STK_DEFAULT_PACKET_BUFFER_SIZE (2048) -#define STK_DEFAULT_GRACE_PERIOD_AFTER_SEEK_SECONDS (0.5) - -#define LOGINFO(x) [self logInfo:[NSString stringWithFormat:@"%s %@", sel_getName(_cmd), x]]; - -static void PopulateOptionsWithDefault(STKAudioPlayerOptions* options) -{ - if (options->bufferSizeInSeconds == 0) - { - options->bufferSizeInSeconds = STK_DEFAULT_PCM_BUFFER_SIZE_IN_SECONDS; - } - - if (options->readBufferSize == 0) - { - options->readBufferSize = STK_DEFAULT_READ_BUFFER_SIZE; - } - - if (options->secondsRequiredToStartPlaying == 0) - { - options->secondsRequiredToStartPlaying = MIN(STK_DEFAULT_SECONDS_REQUIRED_TO_START_PLAYING, options->bufferSizeInSeconds); - } - - if (options->secondsRequiredToStartPlayingAfterBufferUnderun == 0) - { - options->secondsRequiredToStartPlayingAfterBufferUnderun = MIN(STK_DEFAULT_SECONDS_REQUIRED_TO_START_PLAYING_AFTER_BUFFER_UNDERRUN, options->bufferSizeInSeconds); - } - - if (options->gracePeriodAfterSeekInSeconds == 0) - { - options->gracePeriodAfterSeekInSeconds = MIN(STK_DEFAULT_GRACE_PERIOD_AFTER_SEEK_SECONDS, options->bufferSizeInSeconds); - } -} - -#define CHECK_STATUS_AND_REPORT(call) \ - if ((status = (call))) \ - { \ - [self unexpectedError:STKAudioPlayerErrorAudioSystemError]; \ - } - -#define CHECK_STATUS_AND_RETURN(call) \ - if ((status = (call))) \ - { \ - [self unexpectedError:STKAudioPlayerErrorAudioSystemError]; \ - return;\ - } - -#define CHECK_STATUS_AND_RETURN_VALUE(call, value) \ - if ((status = (call))) \ - { \ - [self unexpectedError:STKAudioPlayerErrorAudioSystemError]; \ - return value;\ - } - -typedef enum -{ - STKAudioPlayerInternalStateInitialised = 0, - STKAudioPlayerInternalStateRunning = 1, - STKAudioPlayerInternalStatePlaying = (1 << 1) | STKAudioPlayerInternalStateRunning, - STKAudioPlayerInternalStateRebuffering = (1 << 2) | STKAudioPlayerInternalStateRunning, - STKAudioPlayerInternalStateStartingThread = (1 << 3) | STKAudioPlayerInternalStateRunning, - STKAudioPlayerInternalStateWaitingForData = (1 << 4) | STKAudioPlayerInternalStateRunning, - /* Same as STKAudioPlayerInternalStateWaitingForData but isn't immediately raised as a buffering event */ - STKAudioPlayerInternalStateWaitingForDataAfterSeek = (1 << 5) | STKAudioPlayerInternalStateRunning, - STKAudioPlayerInternalStatePaused = (1 << 6) | STKAudioPlayerInternalStateRunning, - STKAudioPlayerInternalStateStopped = (1 << 9), - STKAudioPlayerInternalStatePendingNext = (1 << 10), - STKAudioPlayerInternalStateDisposed = (1 << 30), - STKAudioPlayerInternalStateError = (1 << 31) -} -STKAudioPlayerInternalState; - -#pragma mark STKFrameFilterEntry - -@interface STKFrameFilterEntry() -{ -@public - NSString* name; - STKFrameFilter filter; -} -@end - -@implementation STKFrameFilterEntry --(id) initWithFilter:(STKFrameFilter)filterIn andName:(NSString*)nameIn -{ - if (self = [super init]) - { - self->filter = [filterIn copy]; - self->name = nameIn; - } - - return self; -} - --(NSString*) name -{ - return self->name; -} - --(STKFrameFilter) filter -{ - return self->filter; -} -@end - -#pragma mark STKAudioPlayer - -static UInt32 maxFramesPerSlice = 4096; - -static AudioComponentDescription mixerDescription; -static AudioComponentDescription nbandUnitDescription; -static AudioComponentDescription outputUnitDescription; -static AudioComponentDescription convertUnitDescription; -static AudioStreamBasicDescription canonicalAudioStreamBasicDescription; - -@interface STKAudioPlayer() -{ - BOOL muted; - - UInt8* readBuffer; - int readBufferSize; - STKAudioPlayerInternalState internalState; - - Float32 volume; - Float32 peakPowerDb[2]; - Float32 averagePowerDb[2]; - - BOOL meteringEnabled; - BOOL equalizerOn; - BOOL equalizerEnabled; - STKAudioPlayerOptions options; - - NSMutableArray* converterNodes; - - AUGraph audioGraph; - AUNode eqNode; - AUNode mixerNode; - AUNode outputNode; - - AUNode eqInputNode; - AUNode eqOutputNode; - AUNode mixerInputNode; - AUNode mixerOutputNode; - - AudioComponentInstance eqUnit; - AudioComponentInstance mixerUnit; - AudioComponentInstance outputUnit; - - UInt32 eqBandCount; - int32_t waitingForDataAfterSeekFrameCount; - - UInt32 framesRequiredToStartPlaying; - UInt32 framesRequiredToPlayAfterRebuffering; - UInt32 framesRequiredBeforeWaitingForDataAfterSeekBecomesPlaying; - - STKQueueEntry* volatile currentlyPlayingEntry; - STKQueueEntry* volatile currentlyReadingEntry; - - NSMutableArray* upcomingQueue; - NSMutableArray* bufferingQueue; - - OSSpinLock pcmBufferSpinLock; - OSSpinLock internalStateLock; - volatile UInt32 pcmBufferTotalFrameCount; - volatile UInt32 pcmBufferFrameStartIndex; - volatile UInt32 pcmBufferUsedFrameCount; - volatile UInt32 pcmBufferFrameSizeInBytes; - - AudioBuffer* pcmAudioBuffer; - AudioBufferList pcmAudioBufferList; - AudioConverterRef audioConverterRef; - - AudioStreamBasicDescription audioConverterAudioStreamBasicDescription; - - BOOL deallocating; - BOOL discontinuous; - NSArray* frameFilters; - NSThread* playbackThread; - NSRunLoop* playbackThreadRunLoop; - AudioFileStreamID audioFileStream; - NSConditionLock* threadStartedLock; - NSConditionLock* threadFinishedCondLock; - - void(^stopBackBackgroundTaskBlock)(); - - int32_t seekVersion; - OSSpinLock seekLock; - OSSpinLock currentEntryReferencesLock; - - pthread_mutex_t playerMutex; - pthread_cond_t playerThreadReadyCondition; - pthread_mutex_t mainThreadSyncCallMutex; - pthread_cond_t mainThreadSyncCallReadyCondition; - - volatile BOOL waiting; - volatile double requestedSeekTime; - volatile BOOL disposeWasRequested; - volatile BOOL seekToTimeWasRequested; - volatile STKAudioPlayerStopReason stopReason; -} - -@property (readwrite) STKAudioPlayerInternalState internalState; -@property (readwrite) STKAudioPlayerInternalState stateBeforePaused; - --(void) handlePropertyChangeForFileStream:(AudioFileStreamID)audioFileStreamIn fileStreamPropertyID:(AudioFileStreamPropertyID)propertyID ioFlags:(UInt32*)ioFlags; --(void) handleAudioPackets:(const void*)inputData numberBytes:(UInt32)numberBytes numberPackets:(UInt32)numberPackets packetDescriptions:(AudioStreamPacketDescription*)packetDescriptions; -@end - -static void AudioFileStreamPropertyListenerProc(void* clientData, AudioFileStreamID audioFileStream, AudioFileStreamPropertyID propertyId, UInt32* flags) -{ - STKAudioPlayer* player = (__bridge STKAudioPlayer*)clientData; - - [player handlePropertyChangeForFileStream:audioFileStream fileStreamPropertyID:propertyId ioFlags:flags]; -} - -static void AudioFileStreamPacketsProc(void* clientData, UInt32 numberBytes, UInt32 numberPackets, const void* inputData, AudioStreamPacketDescription* packetDescriptions) -{ - STKAudioPlayer* player = (__bridge STKAudioPlayer*)clientData; - - [player handleAudioPackets:inputData numberBytes:numberBytes numberPackets:numberPackets packetDescriptions:packetDescriptions]; -} - -@implementation STKAudioPlayer - -+(void) initialize -{ - convertUnitDescription = (AudioComponentDescription) - { - .componentManufacturer = kAudioUnitManufacturer_Apple, - .componentType = kAudioUnitType_FormatConverter, - .componentSubType = kAudioUnitSubType_AUConverter, - .componentFlags = 0, - .componentFlagsMask = 0 - }; - - const int bytesPerSample = sizeof(AudioSampleType); - - canonicalAudioStreamBasicDescription = (AudioStreamBasicDescription) - { - .mSampleRate = 44100.00, - .mFormatID = kAudioFormatLinearPCM, - .mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked, - .mFramesPerPacket = 1, - .mChannelsPerFrame = 2, - .mBytesPerFrame = bytesPerSample * 2 /*channelsPerFrame*/, - .mBitsPerChannel = 8 * bytesPerSample, - .mBytesPerPacket = (bytesPerSample * 2) - }; - - outputUnitDescription = (AudioComponentDescription) - { - .componentType = kAudioUnitType_Output, -#if TARGET_OS_IPHONE - .componentSubType = kAudioUnitSubType_RemoteIO, -#else - .componentSubType = kAudioUnitSubType_DefaultOutput, -#endif - .componentFlags = 0, - .componentFlagsMask = 0, - .componentManufacturer = kAudioUnitManufacturer_Apple - }; - - mixerDescription = (AudioComponentDescription) - { - .componentType = kAudioUnitType_Mixer, - .componentSubType = kAudioUnitSubType_MultiChannelMixer, - .componentFlags = 0, - .componentFlagsMask = 0, - .componentManufacturer = kAudioUnitManufacturer_Apple - }; - - nbandUnitDescription = (AudioComponentDescription) - { - .componentType = kAudioUnitType_Effect, - .componentSubType = kAudioUnitSubType_NBandEQ, - .componentManufacturer=kAudioUnitManufacturer_Apple - }; -} --(STKAudioPlayerOptions) options -{ - return options; -} - --(STKAudioPlayerInternalState) internalState -{ - return internalState; -} - --(void) setInternalState:(STKAudioPlayerInternalState)value -{ - [self setInternalState:value ifInState:NULL]; -} - --(void) setInternalState:(STKAudioPlayerInternalState)value ifInState:(BOOL(^)(STKAudioPlayerInternalState))ifInState -{ - STKAudioPlayerState newState; - - switch (value) - { - case STKAudioPlayerInternalStateInitialised: - newState = STKAudioPlayerStateReady; - stopReason = STKAudioPlayerStopReasonNone; - break; - case STKAudioPlayerInternalStateRunning: - case STKAudioPlayerInternalStateStartingThread: - case STKAudioPlayerInternalStatePlaying: - case STKAudioPlayerInternalStateWaitingForDataAfterSeek: - newState = STKAudioPlayerStatePlaying; - stopReason = STKAudioPlayerStopReasonNone; - break; - case STKAudioPlayerInternalStatePendingNext: - case STKAudioPlayerInternalStateRebuffering: - case STKAudioPlayerInternalStateWaitingForData: - newState = STKAudioPlayerStateBuffering; - stopReason = STKAudioPlayerStopReasonNone; - break; - case STKAudioPlayerInternalStateStopped: - newState = STKAudioPlayerStateStopped; - break; - case STKAudioPlayerInternalStatePaused: - newState = STKAudioPlayerStatePaused; - stopReason = STKAudioPlayerStopReasonNone; - break; - case STKAudioPlayerInternalStateDisposed: - newState = STKAudioPlayerStateDisposed; - stopReason = STKAudioPlayerStopReasonUserAction; - break; - case STKAudioPlayerInternalStateError: - newState = STKAudioPlayerStateError; - stopReason = STKAudioPlayerStopReasonError; - break; - } - - OSSpinLockLock(&internalStateLock); - - waitingForDataAfterSeekFrameCount = 0; - - if (value == internalState) - { - OSSpinLockUnlock(&internalStateLock); - - return; - } - - if (ifInState != NULL) - { - if (!ifInState(self->internalState)) - { - OSSpinLockUnlock(&internalStateLock); - - return; - } - } - - internalState = value; - - STKAudioPlayerState previousState = self.state; - - if (newState != previousState && !deallocating) - { - self.state = newState; - - OSSpinLockUnlock(&internalStateLock); - - dispatch_async(dispatch_get_main_queue(), ^ - { - [self.delegate audioPlayer:self stateChanged:self.state previousState:previousState]; - }); - } - else - { - OSSpinLockUnlock(&internalStateLock); - } -} - --(STKAudioPlayerStopReason) stopReason -{ - return stopReason; -} - --(void) logInfo:(NSString*)line -{ - if ([NSThread currentThread].isMainThread) - { - if ([self.delegate respondsToSelector:@selector(audioPlayer:logInfo:)]) - { - [self.delegate audioPlayer:self logInfo:line]; - } - } - else - { - if ([self.delegate respondsToSelector:@selector(audioPlayer:logInfo:)]) - { - [self.delegate audioPlayer:self logInfo:line]; - } - } -} - --(id) init -{ - return [self initWithOptions:(STKAudioPlayerOptions){}]; -} - --(id) initWithOptions:(STKAudioPlayerOptions)optionsIn -{ - if (self = [super init]) - { - options = optionsIn; - - self->volume = 1.0; - self->equalizerEnabled = optionsIn.equalizerBandFrequencies[0] != 0; - - PopulateOptionsWithDefault(&options); - - framesRequiredToStartPlaying = canonicalAudioStreamBasicDescription.mSampleRate * options.secondsRequiredToStartPlaying; - framesRequiredToPlayAfterRebuffering = canonicalAudioStreamBasicDescription.mSampleRate * options.secondsRequiredToStartPlayingAfterBufferUnderun; - framesRequiredBeforeWaitingForDataAfterSeekBecomesPlaying = canonicalAudioStreamBasicDescription.mSampleRate * options.gracePeriodAfterSeekInSeconds; - - pcmAudioBuffer = &pcmAudioBufferList.mBuffers[0]; - - pcmAudioBufferList.mNumberBuffers = 1; - pcmAudioBufferList.mBuffers[0].mDataByteSize = (canonicalAudioStreamBasicDescription.mSampleRate * options.bufferSizeInSeconds) * canonicalAudioStreamBasicDescription.mBytesPerFrame; - pcmAudioBufferList.mBuffers[0].mData = (void*)calloc(pcmAudioBuffer->mDataByteSize, 1); - pcmAudioBufferList.mBuffers[0].mNumberChannels = 2; - - pcmBufferFrameSizeInBytes = canonicalAudioStreamBasicDescription.mBytesPerFrame; - pcmBufferTotalFrameCount = pcmAudioBuffer->mDataByteSize / pcmBufferFrameSizeInBytes; - - readBufferSize = options.readBufferSize; - readBuffer = calloc(sizeof(UInt8), readBufferSize); - - pthread_mutexattr_t attr; - - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - - pthread_mutex_init(&playerMutex, &attr); - pthread_mutex_init(&mainThreadSyncCallMutex, NULL); - pthread_cond_init(&playerThreadReadyCondition, NULL); - pthread_cond_init(&mainThreadSyncCallReadyCondition, NULL); - - threadStartedLock = [[NSConditionLock alloc] initWithCondition:0]; - threadFinishedCondLock = [[NSConditionLock alloc] initWithCondition:0]; - - self.internalState = STKAudioPlayerInternalStateInitialised; - - upcomingQueue = [[NSMutableArray alloc] init]; - bufferingQueue = [[NSMutableArray alloc] init]; - - [self resetPcmBuffers]; - [self createAudioGraph]; - [self createPlaybackThread]; - } - - return self; -} - --(void) destroyAudioResources -{ - if (currentlyReadingEntry) - { - currentlyReadingEntry.dataSource.delegate = nil; - [currentlyReadingEntry.dataSource unregisterForEvents]; - - currentlyReadingEntry = nil; - } - - if (currentlyPlayingEntry) - { - currentlyPlayingEntry.dataSource.delegate = nil; - [currentlyReadingEntry.dataSource unregisterForEvents]; - - OSSpinLockLock(¤tEntryReferencesLock); - - currentlyPlayingEntry = nil; - - OSSpinLockUnlock(¤tEntryReferencesLock); - } - - [self stopAudioUnitWithReason:STKAudioPlayerStopReasonDisposed]; - - [self clearQueue]; - - if (audioFileStream) - { - AudioFileStreamClose(audioFileStream); - audioFileStream = nil; - } - - if (audioConverterRef) - { - AudioConverterDispose(audioConverterRef); - audioConverterRef = nil; - } - - if (audioGraph) - { - AUGraphUninitialize(audioGraph); - AUGraphClose(audioGraph); - DisposeAUGraph(audioGraph); - - audioGraph = nil; - } -} - --(void) dealloc -{ - NSLog(@"STKAudioPlayer dealloc"); - - deallocating = YES; - - [self destroyAudioResources]; - - pthread_mutex_destroy(&playerMutex); - pthread_mutex_destroy(&mainThreadSyncCallMutex); - pthread_cond_destroy(&playerThreadReadyCondition); - pthread_cond_destroy(&mainThreadSyncCallReadyCondition); - - free(readBuffer); -} - --(void) startSystemBackgroundTask -{ -/*#if TARGET_OS_IPHONE - __block UIBackgroundTaskIdentifier backgroundTaskId = UIBackgroundTaskInvalid; - - backgroundTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^ - { - [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskId]; - backgroundTaskId = UIBackgroundTaskInvalid; - }]; - - stopBackBackgroundTaskBlock = [^ - { - if (backgroundTaskId != UIBackgroundTaskInvalid) - { - [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskId]; - backgroundTaskId = UIBackgroundTaskInvalid; - } - } copy]; -#endif*/ -} - --(void) stopSystemBackgroundTask -{ -#if TARGET_OS_IPHONE - if (stopBackBackgroundTaskBlock != NULL) - { - stopBackBackgroundTaskBlock(); - stopBackBackgroundTaskBlock = NULL; - } -#endif -} - -+(STKDataSource*) dataSourceFromURL:(NSURL*)url -{ - STKDataSource* retval = nil; - - if ([url.scheme isEqualToString:@"file"]) - { - retval = [[STKLocalFileDataSource alloc] initWithFilePath:url.path]; - } - else if ([url.scheme caseInsensitiveCompare:@"http"] == NSOrderedSame || [url.scheme caseInsensitiveCompare:@"https"] == NSOrderedSame) - { - retval = [[STKAutoRecoveringHTTPDataSource alloc] initWithHTTPDataSource:[[STKHTTPDataSource alloc] initWithURL:url]]; - } - - return retval; -} - --(void) clearQueue -{ - pthread_mutex_lock(&playerMutex); - { - if ([self.delegate respondsToSelector:@selector(audioPlayer:didCancelQueuedItems:)]) - { - NSMutableArray* array = [[NSMutableArray alloc] initWithCapacity:bufferingQueue.count + upcomingQueue.count]; - - for (STKQueueEntry* entry in upcomingQueue) - { - [array addObject:entry.queueItemId]; - } - - for (STKQueueEntry* entry in bufferingQueue) - { - [array addObject:entry.queueItemId]; - } - - [upcomingQueue removeAllObjects]; - [bufferingQueue removeAllObjects]; - - if (array.count > 0) - { - [self playbackThreadQueueMainThreadSyncBlock:^ - { - if ([self.delegate respondsToSelector:@selector(audioPlayer:didCancelQueuedItems:)]) - { - [self.delegate audioPlayer:self didCancelQueuedItems:array]; - } - }]; - } - } - else - { - [bufferingQueue removeAllObjects]; - [upcomingQueue removeAllObjects]; - } - } - pthread_mutex_unlock(&playerMutex); -} - --(void) play:(NSString*)urlString -{ - [self play:urlString withQueueItemID:urlString]; -} - --(void) play:(NSString*)urlString withQueueItemID:(NSObject*)queueItemId -{ - NSURL* url = [NSURL URLWithString:urlString]; - - [self setDataSource:[STKAudioPlayer dataSourceFromURL:url] withQueueItemId:queueItemId]; -} - --(void) playURL:(NSURL*)url -{ - [self playURL:url withQueueItemID:url]; -} - --(void) playURL:(NSURL*)url withQueueItemID:(NSObject*)queueItemId -{ - [self setDataSource:[STKAudioPlayer dataSourceFromURL:url] withQueueItemId:queueItemId]; -} - --(void) playDataSource:(STKDataSource*)dataSource -{ - [self playDataSource:dataSource withQueueItemID:dataSource]; -} - --(void) playDataSource:(STKDataSource*)dataSource withQueueItemID:(NSObject *)queueItemId -{ - [self setDataSource:dataSource withQueueItemId:queueItemId]; -} - --(void) setDataSource:(STKDataSource*)dataSourceIn withQueueItemId:(NSObject*)queueItemId -{ - pthread_mutex_lock(&playerMutex); - { - LOGINFO(([NSString stringWithFormat:@"Playing: %@", [queueItemId description]])); - - if (![self audioGraphIsRunning]) - { - [self startSystemBackgroundTask]; - } - - [self clearQueue]; - - [upcomingQueue enqueue:[[STKQueueEntry alloc] initWithDataSource:dataSourceIn andQueueItemId:queueItemId]]; - - self.internalState = STKAudioPlayerInternalStatePendingNext; - } - pthread_mutex_unlock(&playerMutex); - - [self wakeupPlaybackThread]; -} - --(void) queue:(NSString*)urlString -{ - return [self queueURL:[NSURL URLWithString:urlString] withQueueItemId:urlString]; -} - --(void) queue:(NSString*)urlString withQueueItemId:(NSObject*)queueItemId -{ - [self queueURL:[NSURL URLWithString:urlString] withQueueItemId:queueItemId]; -} - --(void) queueURL:(NSURL*)url -{ - [self queueURL:url withQueueItemId:url]; -} - --(void) queueURL:(NSURL*)url withQueueItemId:(NSObject*)queueItemId -{ - [self queueDataSource:[STKAudioPlayer dataSourceFromURL:url] withQueueItemId:queueItemId]; -} - --(void) queueDataSource:(STKDataSource*)dataSourceIn withQueueItemId:(NSObject*)queueItemId -{ - pthread_mutex_lock(&playerMutex); - { - if (![self audioGraphIsRunning]) - { - [self startSystemBackgroundTask]; - } - - [upcomingQueue enqueue:[[STKQueueEntry alloc] initWithDataSource:dataSourceIn andQueueItemId:queueItemId]]; - } - pthread_mutex_unlock(&playerMutex); - - [self wakeupPlaybackThread]; -} - --(void) handlePropertyChangeForFileStream:(AudioFileStreamID)inAudioFileStream fileStreamPropertyID:(AudioFileStreamPropertyID)inPropertyID ioFlags:(UInt32*)ioFlags -{ - OSStatus error; - - if (!currentlyReadingEntry) - { - return; - } - - switch (inPropertyID) - { - case kAudioFileStreamProperty_DataOffset: - { - SInt64 offset; - UInt32 offsetSize = sizeof(offset); - - AudioFileStreamGetProperty(audioFileStream, kAudioFileStreamProperty_DataOffset, &offsetSize, &offset); - - currentlyReadingEntry->parsedHeader = YES; - currentlyReadingEntry->audioDataOffset = offset; - - break; - } - case kAudioFileStreamProperty_FileFormat: - { - char fileFormat[4]; - UInt32 fileFormatSize = sizeof(fileFormat); - - AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_FileFormat, &fileFormatSize, &fileFormat); - - break; - } - case kAudioFileStreamProperty_DataFormat: - { - AudioStreamBasicDescription newBasicDescription; - STKQueueEntry* entryToUpdate = currentlyReadingEntry; - - if (!currentlyReadingEntry->parsedHeader) - { - UInt32 size = sizeof(newBasicDescription); - - AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_DataFormat, &size, &newBasicDescription); - - pthread_mutex_lock(&playerMutex); - - entryToUpdate->audioStreamBasicDescription = newBasicDescription; - entryToUpdate->sampleRate = entryToUpdate->audioStreamBasicDescription.mSampleRate; - entryToUpdate->packetDuration = entryToUpdate->audioStreamBasicDescription.mFramesPerPacket / entryToUpdate->sampleRate; - - UInt32 packetBufferSize = 0; - UInt32 sizeOfPacketBufferSize = sizeof(packetBufferSize); - - error = AudioFileStreamGetProperty(audioFileStream, kAudioFileStreamProperty_PacketSizeUpperBound, &sizeOfPacketBufferSize, &packetBufferSize); - - if (error || packetBufferSize == 0) - { - error = AudioFileStreamGetProperty(audioFileStream, kAudioFileStreamProperty_MaximumPacketSize, &sizeOfPacketBufferSize, &packetBufferSize); - - if (error || packetBufferSize == 0) - { - entryToUpdate->packetBufferSize = STK_DEFAULT_PACKET_BUFFER_SIZE; - } - else - { - entryToUpdate->packetBufferSize = packetBufferSize; - } - } - else - { - entryToUpdate->packetBufferSize = packetBufferSize; - } - - [self createAudioConverter:¤tlyReadingEntry->audioStreamBasicDescription]; - - pthread_mutex_unlock(&playerMutex); - } - - break; - } - case kAudioFileStreamProperty_AudioDataByteCount: - { - UInt64 audioDataByteCount; - UInt32 byteCountSize = sizeof(audioDataByteCount); - - AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_AudioDataByteCount, &byteCountSize, &audioDataByteCount); - - currentlyReadingEntry->audioDataByteCount = audioDataByteCount; - - break; - } - case kAudioFileStreamProperty_ReadyToProducePackets: - { - if (!audioConverterAudioStreamBasicDescription.mFormatID == kAudioFormatLinearPCM) - { - discontinuous = YES; - } - - break; - } - case kAudioFileStreamProperty_FormatList: - { - Boolean outWriteable; - UInt32 formatListSize; - OSStatus err = AudioFileStreamGetPropertyInfo(inAudioFileStream, kAudioFileStreamProperty_FormatList, &formatListSize, &outWriteable); - - if (err) - { - break; - } - - AudioFormatListItem* formatList = malloc(formatListSize); - - err = AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_FormatList, &formatListSize, formatList); - - if (err) - { - free(formatList); - break; - } - - for (int i = 0; i * sizeof(AudioFormatListItem) < formatListSize; i += sizeof(AudioFormatListItem)) - { - AudioStreamBasicDescription pasbd = formatList[i].mASBD; - - if (pasbd.mFormatID == kAudioFormatMPEG4AAC_HE || pasbd.mFormatID == kAudioFormatMPEG4AAC_HE_V2) - { - // - // We've found HE-AAC, remember this to tell the audio queue - // when we construct it. - // -#if !TARGET_IPHONE_SIMULATOR - currentlyReadingEntry->audioStreamBasicDescription = pasbd; -#endif - break; - } - } - - free(formatList); - - break; - } - - } -} - --(Float64) currentTimeInFrames -{ - if (audioGraph == nil) - { - return 0; - } - - return 0; -} - --(void) unexpectedError:(STKAudioPlayerErrorCode)errorCodeIn -{ - self.internalState = STKAudioPlayerInternalStateError; - - [self playbackThreadQueueMainThreadSyncBlock:^ - { - [self.delegate audioPlayer:self unexpectedError:errorCodeIn]; - }]; -} - --(double) duration -{ - if (self.internalState == STKAudioPlayerInternalStatePendingNext) - { - return 0; - } - - OSSpinLockLock(¤tEntryReferencesLock); - STKQueueEntry* entry = currentlyPlayingEntry; - OSSpinLockUnlock(¤tEntryReferencesLock); - - if (entry == nil) - { - return 0; - } - - double retval = [entry duration]; - double progress = [self progress]; - - if (retval < progress && retval > 0) - { - return progress; - } - - return retval; -} - --(double) progress -{ - if (seekToTimeWasRequested) - { - return requestedSeekTime; - } - - if (self.internalState == STKAudioPlayerInternalStatePendingNext) - { - return 0; - } - - OSSpinLockLock(¤tEntryReferencesLock); - STKQueueEntry* entry = currentlyPlayingEntry; - OSSpinLockUnlock(¤tEntryReferencesLock); - - if (entry == nil) - { - return 0; - } - - OSSpinLockLock(&entry->spinLock); - double retval = entry->seekTime + (entry->framesPlayed / canonicalAudioStreamBasicDescription.mSampleRate); - OSSpinLockUnlock(&entry->spinLock); - - return retval; -} - --(BOOL) invokeOnPlaybackThread:(void(^)())block -{ - NSRunLoop* runLoop = playbackThreadRunLoop; - - if (runLoop) - { - CFRunLoopPerformBlock([runLoop getCFRunLoop], NSRunLoopCommonModes, block); - CFRunLoopWakeUp([runLoop getCFRunLoop]); - - return YES; - } - - return NO; -} - --(void) wakeupPlaybackThread -{ - [self invokeOnPlaybackThread:^ - { - [self processRunloop]; - }]; - - pthread_mutex_lock(&playerMutex); - - if (waiting) - { - pthread_cond_signal(&playerThreadReadyCondition); - } - - pthread_mutex_unlock(&playerMutex); -} - --(void) seekToTime:(double)value -{ - if (currentlyPlayingEntry == nil) - { - return; - } - - OSSpinLockLock(&seekLock); - - BOOL seekAlreadyRequested = seekToTimeWasRequested; - - seekToTimeWasRequested = YES; - requestedSeekTime = value; - - if (!seekAlreadyRequested) - { - OSAtomicIncrement32(&seekVersion); - - OSSpinLockUnlock(&seekLock); - - [self wakeupPlaybackThread]; - - return; - } - - OSSpinLockUnlock(&seekLock); -} - --(void) createPlaybackThread -{ - playbackThread = [[NSThread alloc] initWithTarget:self selector:@selector(startInternal) object:nil]; - - [playbackThread start]; - - [threadStartedLock lockWhenCondition:1]; - [threadStartedLock unlockWithCondition:0]; - - NSAssert(playbackThreadRunLoop != nil, @"playbackThreadRunLoop != nil"); -} - --(void) audioQueueFinishedPlaying:(STKQueueEntry*)entry -{ - STKQueueEntry* next = [bufferingQueue dequeue]; - - [self processFinishPlayingIfAnyAndPlayingNext:entry withNext:next]; - [self processRunloop]; -} - --(void) setCurrentlyReadingEntry:(STKQueueEntry*)entry andStartPlaying:(BOOL)startPlaying -{ - [self setCurrentlyReadingEntry:entry andStartPlaying:startPlaying clearQueue:YES]; -} - --(void) setCurrentlyReadingEntry:(STKQueueEntry*)entry andStartPlaying:(BOOL)startPlaying clearQueue:(BOOL)clearQueue -{ - LOGINFO(([entry description])); - - if (startPlaying) - { - memset(&pcmAudioBuffer->mData[0], 0, pcmBufferTotalFrameCount * pcmBufferFrameSizeInBytes); - } - - if (audioFileStream) - { - AudioFileStreamClose(audioFileStream); - - audioFileStream = 0; - } - - if (currentlyReadingEntry) - { - currentlyReadingEntry.dataSource.delegate = nil; - [currentlyReadingEntry.dataSource unregisterForEvents]; - [currentlyReadingEntry.dataSource close]; - } - - OSSpinLockLock(¤tEntryReferencesLock); - currentlyReadingEntry = entry; - OSSpinLockUnlock(¤tEntryReferencesLock); - - currentlyReadingEntry.dataSource.delegate = self; - [currentlyReadingEntry.dataSource registerForEvents:[NSRunLoop currentRunLoop]]; - [currentlyReadingEntry.dataSource seekToOffset:0]; - - if (startPlaying) - { - if (clearQueue) - { - [self clearQueue]; - } - - [self processFinishPlayingIfAnyAndPlayingNext:currentlyPlayingEntry withNext:entry]; - - [self startAudioGraph]; - } - else - { - [bufferingQueue enqueue:entry]; - } -} - --(void) processFinishPlayingIfAnyAndPlayingNext:(STKQueueEntry*)entry withNext:(STKQueueEntry*)next -{ - if (entry != currentlyPlayingEntry) - { - return; - } - - LOGINFO(([NSString stringWithFormat:@"Finished: %@, Next: %@, buffering.count=%d,upcoming.count=%d", entry ? [entry description] : @"nothing", [next description], (int)bufferingQueue.count, (int)upcomingQueue.count])); - - NSObject* queueItemId = entry.queueItemId; - double progress = [entry progressInFrames] / canonicalAudioStreamBasicDescription.mSampleRate; - double duration = [entry duration]; - - BOOL isPlayingSameItemProbablySeek = currentlyPlayingEntry == next; - - if (next) - { - if (!isPlayingSameItemProbablySeek) - { - OSSpinLockLock(&next->spinLock); - next->seekTime = 0; - OSSpinLockUnlock(&next->spinLock); - - OSSpinLockLock(&seekLock); - seekToTimeWasRequested = NO; - OSSpinLockUnlock(&seekLock); - } - - OSSpinLockLock(¤tEntryReferencesLock); - currentlyPlayingEntry = next; - NSObject* playingQueueItemId = playingQueueItemId = currentlyPlayingEntry.queueItemId; - OSSpinLockUnlock(¤tEntryReferencesLock); - - if (!isPlayingSameItemProbablySeek && entry) - { - [self playbackThreadQueueMainThreadSyncBlock:^ - { - [self.delegate audioPlayer:self didFinishPlayingQueueItemId:queueItemId withReason:stopReason andProgress:progress andDuration:duration]; - }]; - } - - if (!isPlayingSameItemProbablySeek) - { - [self setInternalState:STKAudioPlayerInternalStateWaitingForData]; - - [self playbackThreadQueueMainThreadSyncBlock:^ - { - [self.delegate audioPlayer:self didStartPlayingQueueItemId:playingQueueItemId]; - }]; - } - } - else - { - OSSpinLockLock(¤tEntryReferencesLock); - currentlyPlayingEntry = nil; - OSSpinLockUnlock(¤tEntryReferencesLock); - - if (!isPlayingSameItemProbablySeek && entry) - { - [self playbackThreadQueueMainThreadSyncBlock:^ - { - [self.delegate audioPlayer:self didFinishPlayingQueueItemId:queueItemId withReason:stopReason andProgress:progress andDuration:duration]; - }]; - } - } - - [self wakeupPlaybackThread]; -} - --(void) dispatchSyncOnMainThread:(void(^)())block -{ - __block BOOL finished = NO; - - if (disposeWasRequested) - { - return; - } - - dispatch_async(dispatch_get_main_queue(), ^ - { - if (!disposeWasRequested) - { - block(); - } - - pthread_mutex_lock(&mainThreadSyncCallMutex); - finished = YES; - pthread_cond_signal(&mainThreadSyncCallReadyCondition); - pthread_mutex_unlock(&mainThreadSyncCallMutex); - }); - - pthread_mutex_lock(&mainThreadSyncCallMutex); - - while (true) - { - if (disposeWasRequested) - { - break; - } - - if (finished) - { - break; - } - - pthread_cond_wait(&mainThreadSyncCallReadyCondition, &mainThreadSyncCallMutex); - } - - pthread_mutex_unlock(&mainThreadSyncCallMutex); -} - --(void) playbackThreadQueueMainThreadSyncBlock:(void(^)())block -{ - block = [block copy]; - - [self invokeOnPlaybackThread:^ - { - if (disposeWasRequested) - { - return; - } - - [self dispatchSyncOnMainThread:block]; - }]; -} - --(void) requeueBufferingEntries -{ - if (bufferingQueue.count > 0) - { - for (STKQueueEntry* queueEntry in bufferingQueue) - { - queueEntry->parsedHeader = NO; - - [queueEntry reset]; - } - - [upcomingQueue skipQueueWithQueue:bufferingQueue]; - - [bufferingQueue removeAllObjects]; - } -} - --(BOOL) processRunloop -{ - pthread_mutex_lock(&playerMutex); - { - if (disposeWasRequested) - { - pthread_mutex_unlock(&playerMutex); - - return NO; - } - else if (self.internalState == STKAudioPlayerInternalStatePaused) - { - pthread_mutex_unlock(&playerMutex); - - return YES; - } - else if (self.internalState == STKAudioPlayerInternalStatePendingNext) - { - STKQueueEntry* entry = [upcomingQueue dequeue]; - - self.internalState = STKAudioPlayerInternalStateWaitingForData; - - [self setCurrentlyReadingEntry:entry andStartPlaying:YES]; - [self resetPcmBuffers]; - } - else if (seekToTimeWasRequested && currentlyPlayingEntry && currentlyPlayingEntry != currentlyReadingEntry) - { - currentlyPlayingEntry->parsedHeader = NO; - [currentlyPlayingEntry reset]; - - if (currentlyReadingEntry != nil) - { - currentlyReadingEntry.dataSource.delegate = nil; - [currentlyReadingEntry.dataSource unregisterForEvents]; - } - - if (self->options.flushQueueOnSeek) - { - self.internalState = STKAudioPlayerInternalStateWaitingForDataAfterSeek; - [self setCurrentlyReadingEntry:currentlyPlayingEntry andStartPlaying:YES clearQueue:YES]; - } - else - { - [self requeueBufferingEntries]; - - self.internalState = STKAudioPlayerInternalStateWaitingForDataAfterSeek; - [self setCurrentlyReadingEntry:currentlyPlayingEntry andStartPlaying:YES clearQueue:NO]; - } - } - else if (currentlyReadingEntry == nil) - { - if (upcomingQueue.count > 0) - { - STKQueueEntry* entry = [upcomingQueue dequeue]; - - BOOL startPlaying = currentlyPlayingEntry == nil; - - self.internalState = STKAudioPlayerInternalStateWaitingForData; - [self setCurrentlyReadingEntry:entry andStartPlaying:startPlaying]; - } - else if (currentlyPlayingEntry == nil) - { - if (self.internalState != STKAudioPlayerInternalStateStopped) - { - [self stopAudioUnitWithReason:STKAudioPlayerStopReasonEof]; - } - } - } - - if (currentlyPlayingEntry && currentlyPlayingEntry->parsedHeader && [currentlyPlayingEntry calculatedBitRate] > 0.0) - { - int32_t originalSeekVersion; - BOOL originalSeekToTimeRequested; - - OSSpinLockLock(&seekLock); - originalSeekVersion = seekVersion; - originalSeekToTimeRequested = seekToTimeWasRequested; - OSSpinLockUnlock(&seekLock); - - if (originalSeekToTimeRequested && currentlyReadingEntry == currentlyPlayingEntry) - { - [self processSeekToTime]; - - OSSpinLockLock(&seekLock); - if (originalSeekVersion == seekVersion) - { - seekToTimeWasRequested = NO; - } - OSSpinLockUnlock(&seekLock); - } - } - else if (currentlyPlayingEntry == nil && seekToTimeWasRequested) - { - seekToTimeWasRequested = NO; - } - } - pthread_mutex_unlock(&playerMutex); - - return YES; -} - --(void) startInternal -{ - @autoreleasepool - { - playbackThreadRunLoop = [NSRunLoop currentRunLoop]; - NSThread.currentThread.threadPriority = 1; - - [threadStartedLock lockWhenCondition:0]; - [threadStartedLock unlockWithCondition:1]; - - [playbackThreadRunLoop addPort:[NSPort port] forMode:NSDefaultRunLoopMode]; - - while (true) - { - @autoreleasepool - { - if (![self processRunloop]) - { - break; - } - } - - NSDate* date = [[NSDate alloc] initWithTimeIntervalSinceNow:10]; - [playbackThreadRunLoop runMode:NSDefaultRunLoopMode beforeDate:date]; - } - - disposeWasRequested = NO; - seekToTimeWasRequested = NO; - - [currentlyReadingEntry.dataSource unregisterForEvents]; - [currentlyPlayingEntry.dataSource unregisterForEvents]; - - currentlyReadingEntry.dataSource.delegate = nil; - currentlyPlayingEntry.dataSource.delegate = nil; - - pthread_mutex_lock(&playerMutex); - OSSpinLockLock(¤tEntryReferencesLock); - currentlyPlayingEntry = nil; - currentlyReadingEntry = nil; - OSSpinLockUnlock(¤tEntryReferencesLock); - pthread_mutex_unlock(&playerMutex); - - self.internalState = STKAudioPlayerInternalStateDisposed; - - playbackThreadRunLoop = nil; - - [self destroyAudioResources]; - - [threadFinishedCondLock lock]; - [threadFinishedCondLock unlockWithCondition:1]; - } -} - --(void) processSeekToTime -{ - OSStatus error; - STKQueueEntry* currentEntry = currentlyReadingEntry; - - NSAssert(currentEntry == currentlyPlayingEntry, @"playing and reading must be the same"); - - if (!currentEntry || ([currentEntry calculatedBitRate] == 0.0 || currentlyPlayingEntry.dataSource.length <= 0)) - { - return; - } - - SInt64 seekByteOffset = currentEntry->audioDataOffset + (requestedSeekTime / self.duration) * (currentlyReadingEntry.audioDataLengthInBytes); - - if (seekByteOffset > currentEntry.dataSource.length - (2 * currentEntry->packetBufferSize)) - { - seekByteOffset = currentEntry.dataSource.length - 2 * currentEntry->packetBufferSize; - } - - OSSpinLockLock(¤tEntry->spinLock); - currentEntry->seekTime = requestedSeekTime; - OSSpinLockUnlock(¤tEntry->spinLock); - - double calculatedBitRate = [currentEntry calculatedBitRate]; - - if (currentEntry->packetDuration > 0 && calculatedBitRate > 0) - { - UInt32 ioFlags = 0; - SInt64 packetAlignedByteOffset; - SInt64 seekPacket = floor(requestedSeekTime / currentEntry->packetDuration); - - error = AudioFileStreamSeek(audioFileStream, seekPacket, &packetAlignedByteOffset, &ioFlags); - - if (!error && !(ioFlags & kAudioFileStreamSeekFlag_OffsetIsEstimated)) - { - double delta = ((seekByteOffset - (SInt64)currentEntry->audioDataOffset) - packetAlignedByteOffset) / calculatedBitRate * 8; - - OSSpinLockLock(¤tEntry->spinLock); - currentEntry->seekTime -= delta; - OSSpinLockUnlock(¤tEntry->spinLock); - - seekByteOffset = packetAlignedByteOffset + currentEntry->audioDataOffset; - } - } - - if (audioConverterRef) - { - AudioConverterReset(audioConverterRef); - } - - [currentEntry reset]; - [currentEntry.dataSource seekToOffset:seekByteOffset]; - - self->waitingForDataAfterSeekFrameCount = 0; - - self.internalState = STKAudioPlayerInternalStateWaitingForDataAfterSeek; - - if (audioGraph) - { - [self resetPcmBuffers]; - } -} - --(void) dataSourceDataAvailable:(STKDataSource*)dataSourceIn -{ - OSStatus error; - - if (currentlyReadingEntry.dataSource != dataSourceIn) - { - return; - } - - if (!currentlyReadingEntry.dataSource.hasBytesAvailable) - { - return; - } - - int read = [currentlyReadingEntry.dataSource readIntoBuffer:readBuffer withSize:readBufferSize]; - - if (read == 0) - { - return; - } - - if (audioFileStream == 0) - { - error = AudioFileStreamOpen((__bridge void*)self, AudioFileStreamPropertyListenerProc, AudioFileStreamPacketsProc, dataSourceIn.audioFileTypeHint, &audioFileStream); - - if (error) - { - [self unexpectedError:STKAudioPlayerErrorAudioSystemError]; - - return; - } - } - - if (read < 0) - { - // iOS will shutdown network connections if the app is backgrounded (i.e. device is locked when player is paused) - // We try to reopen -- should probably add a back-off protocol in the future - - SInt64 position = currentlyReadingEntry.dataSource.position; - - [currentlyReadingEntry.dataSource seekToOffset:position]; - - return; - } - - int flags = 0; - - if (discontinuous) - { - flags = kAudioFileStreamParseFlag_Discontinuity; - } - - if (audioFileStream) - { - error = AudioFileStreamParseBytes(audioFileStream, read, readBuffer, flags); - - if (error) - { - if (dataSourceIn == currentlyPlayingEntry.dataSource) - { - [self unexpectedError:STKAudioPlayerErrorStreamParseBytesFailed]; - } - - return; - } - - OSSpinLockLock(¤tEntryReferencesLock); - - if (currentlyReadingEntry == nil) - { - [dataSourceIn unregisterForEvents]; - [dataSourceIn close]; - } - - OSSpinLockUnlock(¤tEntryReferencesLock); - } -} - --(void) dataSourceErrorOccured:(STKDataSource*)dataSourceIn -{ - if (currentlyReadingEntry.dataSource != dataSourceIn) - { - return; - } - - [self unexpectedError:STKAudioPlayerErrorDataNotFound]; -} - --(void) dataSourceEof:(STKDataSource*)dataSourceIn -{ - if (currentlyReadingEntry == nil || currentlyReadingEntry.dataSource != dataSourceIn) - { - dataSourceIn.delegate = nil; - [dataSourceIn unregisterForEvents]; - [dataSourceIn close]; - - return; - } - - if (disposeWasRequested) - { - return; - } - - NSObject* queueItemId = currentlyReadingEntry.queueItemId; - - [self dispatchSyncOnMainThread:^ - { - [self.delegate audioPlayer:self didFinishBufferingSourceWithQueueItemId:queueItemId]; - }]; - - pthread_mutex_lock(&playerMutex); - - if (currentlyReadingEntry == nil) - { - dataSourceIn.delegate = nil; - [dataSourceIn unregisterForEvents]; - [dataSourceIn close]; - - return; - } - - OSSpinLockLock(¤tlyReadingEntry->spinLock); - currentlyReadingEntry->lastFrameQueued = currentlyReadingEntry->framesQueued; - OSSpinLockUnlock(¤tlyReadingEntry->spinLock); - - currentlyReadingEntry.dataSource.delegate = nil; - [currentlyReadingEntry.dataSource unregisterForEvents]; - [currentlyReadingEntry.dataSource close]; - - OSSpinLockLock(¤tEntryReferencesLock); - currentlyReadingEntry = nil; - OSSpinLockUnlock(¤tEntryReferencesLock); - - pthread_mutex_unlock(&playerMutex); - - [self processRunloop]; -} - --(void) pause -{ - pthread_mutex_lock(&playerMutex); - { - OSStatus error; - - if (self.internalState != STKAudioPlayerInternalStatePaused && (self.internalState & STKAudioPlayerInternalStateRunning)) - { - self.stateBeforePaused = self.internalState; - self.internalState = STKAudioPlayerInternalStatePaused; - - if (audioGraph) - { - error = AUGraphStop(audioGraph); - - if (error) - { - [self unexpectedError:STKAudioPlayerErrorAudioSystemError]; - - pthread_mutex_unlock(&playerMutex); - - return; - } - } - - [self wakeupPlaybackThread]; - } - } - pthread_mutex_unlock(&playerMutex); -} - --(void) resume -{ - pthread_mutex_lock(&playerMutex); - { - OSStatus error; - - if (self.internalState == STKAudioPlayerInternalStatePaused) - { - self.internalState = self.stateBeforePaused; - - if (seekToTimeWasRequested) - { - [self resetPcmBuffers]; - } - - if (audioGraph != nil) - { - error = AUGraphStart(audioGraph); - - if (error) - { - [self unexpectedError:STKAudioPlayerErrorAudioSystemError]; - - pthread_mutex_unlock(&playerMutex); - - return; - } - } - - [self wakeupPlaybackThread]; - } - } - pthread_mutex_unlock(&playerMutex); -} - --(void) resetPcmBuffers -{ - OSSpinLockLock(&pcmBufferSpinLock); - - self->pcmBufferFrameStartIndex = 0; - self->pcmBufferUsedFrameCount = 0; - self->peakPowerDb[0] = STK_DBMIN; - self->peakPowerDb[1] = STK_DBMIN; - self->averagePowerDb[0] = STK_DBMIN; - self->averagePowerDb[1] = STK_DBMIN; - - OSSpinLockUnlock(&pcmBufferSpinLock); -} - --(void) stop -{ - pthread_mutex_lock(&playerMutex); - { - if (self.internalState == STKAudioPlayerInternalStateStopped) - { - pthread_mutex_unlock(&playerMutex); - - return; - } - - [self stopAudioUnitWithReason:STKAudioPlayerStopReasonUserAction]; - - [self resetPcmBuffers]; - - [self invokeOnPlaybackThread:^ - { - pthread_mutex_lock(&playerMutex); - { - currentlyReadingEntry.dataSource.delegate = nil; - [currentlyReadingEntry.dataSource unregisterForEvents]; - [currentlyReadingEntry.dataSource close]; - - if (currentlyPlayingEntry) - { - [self processFinishPlayingIfAnyAndPlayingNext:currentlyPlayingEntry withNext:nil]; - } - - [self clearQueue]; - - OSSpinLockLock(¤tEntryReferencesLock); - currentlyPlayingEntry = nil; - currentlyReadingEntry = nil; - seekToTimeWasRequested = NO; - OSSpinLockUnlock(¤tEntryReferencesLock); - } - pthread_mutex_unlock(&playerMutex); - }]; - - [self wakeupPlaybackThread]; - } - pthread_mutex_unlock(&playerMutex); -} - --(void) stopThread -{ - BOOL wait = NO; - - NSRunLoop* runLoop = playbackThreadRunLoop; - - if (runLoop != nil) - { - wait = YES; - - [self invokeOnPlaybackThread:^ - { - disposeWasRequested = YES; - - CFRunLoopStop(CFRunLoopGetCurrent()); - }]; - - pthread_mutex_lock(&playerMutex); - disposeWasRequested = YES; - pthread_cond_signal(&playerThreadReadyCondition); - pthread_mutex_unlock(&playerMutex); - - pthread_mutex_lock(&mainThreadSyncCallMutex); - disposeWasRequested = YES; - pthread_cond_signal(&mainThreadSyncCallReadyCondition); - pthread_mutex_unlock(&mainThreadSyncCallMutex); - } - - if (wait) - { - [threadFinishedCondLock lockWhenCondition:1]; - [threadFinishedCondLock unlockWithCondition:0]; - } - - [self destroyAudioResources]; - - runLoop = nil; - playbackThread = nil; - playbackThreadRunLoop = nil; -} - --(BOOL) muted -{ - return self->muted; -} - --(void) setMuted:(BOOL)value -{ - self->muted = value; -} - --(void) mute -{ - self.muted = YES; -} - --(void) unmute -{ - self.muted = NO; -} - --(void) dispose -{ - [self stop]; - [self stopThread]; -} - --(NSObject*) currentlyPlayingQueueItemId -{ - OSSpinLockLock(¤tEntryReferencesLock); - - STKQueueEntry* entry = currentlyPlayingEntry; - - if (entry == nil) - { - OSSpinLockUnlock(¤tEntryReferencesLock); - - return nil; - } - - NSObject* retval = entry.queueItemId; - - OSSpinLockUnlock(¤tEntryReferencesLock); - - return retval; -} - -static BOOL GetHardwareCodecClassDesc(UInt32 formatId, AudioClassDescription* classDesc) -{ -#if TARGET_OS_IPHONE - UInt32 size; - - if (AudioFormatGetPropertyInfo(kAudioFormatProperty_Decoders, sizeof(formatId), &formatId, &size) != 0) - { - return NO; - } - - UInt32 decoderCount = size / sizeof(AudioClassDescription); - AudioClassDescription encoderDescriptions[decoderCount]; - - if (AudioFormatGetProperty(kAudioFormatProperty_Decoders, sizeof(formatId), &formatId, &size, encoderDescriptions) != 0) - { - return NO; - } - - for (UInt32 i = 0; i < decoderCount; ++i) - { - if (encoderDescriptions[i].mManufacturer == kAppleHardwareAudioCodecManufacturer) - { - *classDesc = encoderDescriptions[i]; - - return YES; - } - } -#endif - - return NO; -} - --(void) destroyAudioConverter -{ - if (audioConverterRef) - { - AudioConverterDispose(audioConverterRef); - - audioConverterRef = nil; - } -} - --(void) createAudioConverter:(AudioStreamBasicDescription*)asbd -{ - OSStatus status; - Boolean writable; - UInt32 cookieSize; - - if (memcmp(asbd, &audioConverterAudioStreamBasicDescription, sizeof(AudioStreamBasicDescription)) == 0) - { - AudioConverterReset(audioConverterRef); - - return; - } - - [self destroyAudioConverter]; - - AudioClassDescription classDesc; - - if (GetHardwareCodecClassDesc(asbd->mFormatID, &classDesc)) - { - AudioConverterNewSpecific(asbd, &canonicalAudioStreamBasicDescription, 1, &classDesc, &audioConverterRef); - } - - if (!audioConverterRef) - { - status = AudioConverterNew(asbd, &canonicalAudioStreamBasicDescription, &audioConverterRef); - - if (status) - { - [self unexpectedError:STKAudioPlayerErrorAudioSystemError]; - - return; - } - } - - audioConverterAudioStreamBasicDescription = *asbd; - - status = AudioFileStreamGetPropertyInfo(audioFileStream, kAudioFileStreamProperty_MagicCookieData, &cookieSize, &writable); - - if (!status) - { - void* cookieData = alloca(cookieSize); - - status = AudioFileStreamGetProperty(audioFileStream, kAudioFileStreamProperty_MagicCookieData, &cookieSize, cookieData); - - if (status) - { - return; - } - - status = AudioConverterSetProperty(audioConverterRef, kAudioConverterDecompressionMagicCookie, cookieSize, &cookieData); - - if (status) - { - return; - } - } -} - --(void) createOutputUnit -{ - OSStatus status; - - CHECK_STATUS_AND_RETURN(AUGraphAddNode(audioGraph, &outputUnitDescription, &outputNode)); - CHECK_STATUS_AND_RETURN(AUGraphNodeInfo(audioGraph, outputNode, &outputUnitDescription, &outputUnit)); - -#if TARGET_OS_IPHONE - UInt32 flag = 1; - - CHECK_STATUS_AND_RETURN(AudioUnitSetProperty(outputUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, kOutputBus, &flag, sizeof(flag))); - - flag = 0; - - CHECK_STATUS_AND_RETURN(AudioUnitSetProperty(outputUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &flag, sizeof(flag))); -#endif - - CHECK_STATUS_AND_RETURN(AudioUnitSetProperty(outputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, kOutputBus, &canonicalAudioStreamBasicDescription, sizeof(canonicalAudioStreamBasicDescription))); -} - --(void) createMixerUnit -{ - OSStatus status; - - if (!self.options.enableVolumeMixer) - { - return; - } - - CHECK_STATUS_AND_RETURN(AUGraphAddNode(audioGraph, &mixerDescription, &mixerNode)); - CHECK_STATUS_AND_RETURN(AUGraphNodeInfo(audioGraph, mixerNode, &mixerDescription, &mixerUnit)); - CHECK_STATUS_AND_RETURN(AudioUnitSetProperty(mixerUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFramesPerSlice, sizeof(maxFramesPerSlice))); - - UInt32 busCount = 1; - - CHECK_STATUS_AND_RETURN(AudioUnitSetProperty(mixerUnit, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &busCount, sizeof(busCount))); - - Float64 graphSampleRate = 44100.0; - - CHECK_STATUS_AND_RETURN(AudioUnitSetProperty(mixerUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Output, 0, &graphSampleRate, sizeof(graphSampleRate))); - CHECK_STATUS_AND_RETURN(AudioUnitSetParameter(mixerUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Input, 0, 1.0, 0)); -} - --(void) createEqUnit -{ -#if TARGET_OS_MAC && MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_9 - return; -#else - OSStatus status; - - if (self->options.equalizerBandFrequencies[0] == 0) - { - return; - } - - CHECK_STATUS_AND_RETURN(AUGraphAddNode(audioGraph, &nbandUnitDescription, &eqNode)); - CHECK_STATUS_AND_RETURN(AUGraphNodeInfo(audioGraph, eqNode, NULL, &eqUnit)); - CHECK_STATUS_AND_RETURN(AudioUnitSetProperty(eqUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFramesPerSlice, sizeof(maxFramesPerSlice))); - - while (self->options.equalizerBandFrequencies[eqBandCount] != 0) - { - eqBandCount++; - } - - CHECK_STATUS_AND_RETURN(AudioUnitSetProperty(eqUnit, kAUNBandEQProperty_NumberOfBands, kAudioUnitScope_Global, 0, &eqBandCount, sizeof(eqBandCount))); - - for (int i = 0; i < eqBandCount; i++) - { - CHECK_STATUS_AND_RETURN(AudioUnitSetParameter(eqUnit, kAUNBandEQParam_Frequency + i, kAudioUnitScope_Global, 0, (AudioUnitParameterValue)self->options.equalizerBandFrequencies[i], 0)); - } - - for (int i = 0; i < eqBandCount; i++) - { - CHECK_STATUS_AND_RETURN(AudioUnitSetParameter(eqUnit, kAUNBandEQParam_BypassBand + i, kAudioUnitScope_Global, 0, (AudioUnitParameterValue)0, 0)); - } -#endif -} - --(void) setGain:(float)gain forEqualizerBand:(int)bandIndex -{ - if (!eqUnit) - { - return; - } - - OSStatus status; - - CHECK_STATUS_AND_RETURN(AudioUnitSetParameter(eqUnit, kAUNBandEQParam_Gain + bandIndex, kAudioUnitScope_Global, 0, gain, 0)); -} - --(AUNode) createConverterNode:(AudioStreamBasicDescription)srcFormat desFormat:(AudioStreamBasicDescription)desFormat -{ - OSStatus status; - AUNode convertNode; - AudioComponentInstance convertUnit; - - CHECK_STATUS_AND_RETURN_VALUE(AUGraphAddNode(audioGraph, &convertUnitDescription, &convertNode), 0); - CHECK_STATUS_AND_RETURN_VALUE(AUGraphNodeInfo(audioGraph, convertNode, &mixerDescription, &convertUnit), 0); - CHECK_STATUS_AND_RETURN_VALUE(AudioUnitSetProperty(convertUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &srcFormat, sizeof(srcFormat)), 0); - CHECK_STATUS_AND_RETURN_VALUE(AudioUnitSetProperty(convertUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &desFormat, sizeof(desFormat)), 0); - CHECK_STATUS_AND_RETURN_VALUE(AudioUnitSetProperty(convertUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFramesPerSlice, sizeof(maxFramesPerSlice)), 0); - - [converterNodes addObject:@(convertNode)]; - - return convertNode; -} - --(void) connectNodes:(AUNode)srcNode desNode:(AUNode)desNode srcUnit:(AudioComponentInstance)srcUnit desUnit:(AudioComponentInstance)desUnit -{ - OSStatus status; - BOOL addConverter = NO; - AudioStreamBasicDescription srcFormat, desFormat; - UInt32 size = sizeof(AudioStreamBasicDescription); - - CHECK_STATUS_AND_RETURN(AudioUnitGetProperty(srcUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &srcFormat, &size)); - CHECK_STATUS_AND_RETURN(AudioUnitGetProperty(desUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &desFormat, &size)); - - addConverter = memcmp(&srcFormat, &desFormat, sizeof(srcFormat)) != 0; - - if (addConverter) - { - status = AudioUnitSetProperty(desUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &srcFormat, sizeof(srcFormat)); - - addConverter = status != 0; - } - - if (addConverter) - { - AUNode convertNode = [self createConverterNode:srcFormat desFormat:desFormat]; - - CHECK_STATUS_AND_RETURN(AUGraphConnectNodeInput(audioGraph, srcNode, 0, convertNode, 0)); - CHECK_STATUS_AND_RETURN(AUGraphConnectNodeInput(audioGraph, convertNode, 0, desNode, 0)); - } - else - { - CHECK_STATUS_AND_RETURN(AUGraphConnectNodeInput(audioGraph, srcNode, 0, desNode, 0)); - } -} - --(void) setOutputCallbackForFirstNode:(AUNode)firstNode firstUnit:(AudioComponentInstance)firstUnit -{ - OSStatus status; - AURenderCallbackStruct callbackStruct; - - callbackStruct.inputProc = OutputRenderCallback; - callbackStruct.inputProcRefCon = (__bridge void*)self; - - status = AudioUnitSetProperty(firstUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &canonicalAudioStreamBasicDescription, sizeof(canonicalAudioStreamBasicDescription)); - - if (status) - { - AudioStreamBasicDescription format; - UInt32 size = sizeof(format); - - CHECK_STATUS_AND_RETURN(AudioUnitGetProperty(firstUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &format, &size)); - - AUNode converterNode = [self createConverterNode:canonicalAudioStreamBasicDescription desFormat:format]; - - CHECK_STATUS_AND_RETURN(AUGraphSetNodeInputCallback(audioGraph, converterNode, 0, &callbackStruct)); - - CHECK_STATUS_AND_RETURN(AUGraphConnectNodeInput(audioGraph, converterNode, 0, firstNode, 0)); - } - else - { - CHECK_STATUS_AND_RETURN(AUGraphSetNodeInputCallback(audioGraph, firstNode, 0, &callbackStruct)); - } -} - --(void) createAudioGraph -{ - OSStatus status; - converterNodes = [[NSMutableArray alloc] init]; - - CHECK_STATUS_AND_RETURN(NewAUGraph(&audioGraph)); - CHECK_STATUS_AND_RETURN(AUGraphOpen(audioGraph)); - - [self createEqUnit]; - [self createMixerUnit]; - [self createOutputUnit]; - - [self connectGraph]; - - CHECK_STATUS_AND_RETURN(AUGraphInitialize(audioGraph)); - - self.volume = self->volume; -} - --(void) connectGraph -{ - OSStatus status; - NSMutableArray* nodes = [[NSMutableArray alloc] init]; - NSMutableArray* units = [[NSMutableArray alloc] init]; - - AUGraphClearConnections(audioGraph); - - for (NSNumber* converterNode in converterNodes) - { - CHECK_STATUS_AND_REPORT(AUGraphRemoveNode(audioGraph, (AUNode)converterNode.intValue)); - } - - [converterNodes removeAllObjects]; - - if (eqNode) - { - if (self->equalizerEnabled) - { - [nodes addObject:@(eqNode)]; - [units addObject:[NSValue valueWithPointer:eqUnit]]; - - self->equalizerOn = YES; - } - else - { - self->equalizerOn = NO; - } - } - else - { - self->equalizerOn = NO; - } - - if (mixerNode) - { - [nodes addObject:@(mixerNode)]; - [units addObject:[NSValue valueWithPointer:mixerUnit]]; - } - - if (outputNode) - { - [nodes addObject:@(outputNode)]; - [units addObject:[NSValue valueWithPointer:outputUnit]]; - } - - [self setOutputCallbackForFirstNode:(AUNode)[[nodes objectAtIndex:0] intValue] firstUnit:(AudioComponentInstance)[[units objectAtIndex:0] pointerValue]]; - - for (int i = 0; i < nodes.count - 1; i++) - { - AUNode srcNode = [[nodes objectAtIndex:i] intValue]; - AUNode desNode = [[nodes objectAtIndex:i + 1] intValue]; - AudioComponentInstance srcUnit = (AudioComponentInstance)[[units objectAtIndex:i] pointerValue]; - AudioComponentInstance desUnit = (AudioComponentInstance)[[units objectAtIndex:i + 1] pointerValue]; - - [self connectNodes:srcNode desNode:desNode srcUnit:srcUnit desUnit:desUnit]; - } -} - --(BOOL) audioGraphIsRunning -{ - OSStatus status; - Boolean isRunning; - - status = AUGraphIsRunning(audioGraph, &isRunning); - - if (status) - { - return NO; - } - - return isRunning; -} - --(BOOL) startAudioGraph -{ - OSStatus status; - - [self resetPcmBuffers]; - - if ([self audioGraphIsRunning]) - { - return NO; - } - - status = AUGraphStart(audioGraph); - - if (status) - { - [self unexpectedError:STKAudioPlayerErrorAudioSystemError]; - - return NO; - } - - [self stopSystemBackgroundTask]; - - return YES; -} - --(void) stopAudioUnitWithReason:(STKAudioPlayerStopReason)stopReasonIn -{ - OSStatus status; - - if (!audioGraph) - { - stopReason = stopReasonIn; - self.internalState = STKAudioPlayerInternalStateStopped; - - return; - } - - Boolean isRunning; - - status = AUGraphIsRunning(audioGraph, &isRunning); - - if (status) - { - [self unexpectedError:STKAudioPlayerErrorAudioSystemError]; - } - else if (!isRunning) - { - return; - } - - status = AUGraphStop(audioGraph); - - if (status) - { - [self unexpectedError:STKAudioPlayerErrorAudioSystemError]; - } - - [self resetPcmBuffers]; - - stopReason = stopReasonIn; - self.internalState = STKAudioPlayerInternalStateStopped; -} - -typedef struct -{ - BOOL done; - UInt32 numberOfPackets; - AudioBuffer audioBuffer; - AudioStreamPacketDescription* packetDescriptions; -} -AudioConvertInfo; - -OSStatus AudioConverterCallback(AudioConverterRef inAudioConverter, UInt32* ioNumberDataPackets, AudioBufferList* ioData, AudioStreamPacketDescription **outDataPacketDescription, void* inUserData) -{ - AudioConvertInfo* convertInfo = (AudioConvertInfo*)inUserData; - - if (convertInfo->done) - { - ioNumberDataPackets = 0; - - return 100; - } - - ioData->mNumberBuffers = 1; - ioData->mBuffers[0] = convertInfo->audioBuffer; - - if (outDataPacketDescription) - { - *outDataPacketDescription = convertInfo->packetDescriptions; - } - - *ioNumberDataPackets = convertInfo->numberOfPackets; - convertInfo->done = YES; - - return 0; -} - --(void) handleAudioPackets:(const void*)inputData numberBytes:(UInt32)numberBytes numberPackets:(UInt32)numberPackets packetDescriptions:(AudioStreamPacketDescription*)packetDescriptionsIn -{ - if (currentlyReadingEntry == nil) - { - return; - } - - if (!currentlyReadingEntry->parsedHeader) - { - return; - } - - if (disposeWasRequested) - { - return; - } - - if (audioConverterRef == nil) - { - return; - } - - if ((seekToTimeWasRequested && [currentlyPlayingEntry calculatedBitRate] > 0.0)) - { - [self wakeupPlaybackThread]; - - return; - } - - discontinuous = NO; - - OSStatus status; - - AudioConvertInfo convertInfo; - - convertInfo.done = NO; - convertInfo.numberOfPackets = numberPackets; - convertInfo.packetDescriptions = packetDescriptionsIn; - convertInfo.audioBuffer.mData = (void *)inputData; - convertInfo.audioBuffer.mDataByteSize = numberBytes; - convertInfo.audioBuffer.mNumberChannels = audioConverterAudioStreamBasicDescription.mChannelsPerFrame; - - if (packetDescriptionsIn && currentlyReadingEntry->processedPacketsCount < STK_MAX_COMPRESSED_PACKETS_FOR_BITRATE_CALCULATION) - { - int count = MIN(numberPackets, STK_MAX_COMPRESSED_PACKETS_FOR_BITRATE_CALCULATION - currentlyReadingEntry->processedPacketsCount); - - for (int i = 0; i < count; i++) - { - SInt64 packetSize; - - packetSize = packetDescriptionsIn[i].mDataByteSize; - - OSAtomicAdd32((int32_t)packetSize, ¤tlyReadingEntry->processedPacketsSizeTotal); - OSAtomicIncrement32(¤tlyReadingEntry->processedPacketsCount); - } - } - - while (true) - { - OSSpinLockLock(&pcmBufferSpinLock); - UInt32 used = pcmBufferUsedFrameCount; - UInt32 start = pcmBufferFrameStartIndex; - UInt32 end = (pcmBufferFrameStartIndex + pcmBufferUsedFrameCount) % pcmBufferTotalFrameCount; - UInt32 framesLeftInsideBuffer = pcmBufferTotalFrameCount - used; - OSSpinLockUnlock(&pcmBufferSpinLock); - - if (framesLeftInsideBuffer == 0) - { - pthread_mutex_lock(&playerMutex); - - while (true) - { - OSSpinLockLock(&pcmBufferSpinLock); - used = pcmBufferUsedFrameCount; - start = pcmBufferFrameStartIndex; - end = (pcmBufferFrameStartIndex + pcmBufferUsedFrameCount) % pcmBufferTotalFrameCount; - framesLeftInsideBuffer = pcmBufferTotalFrameCount - used; - OSSpinLockUnlock(&pcmBufferSpinLock); - - if (framesLeftInsideBuffer > 0) - { - break; - } - - if (disposeWasRequested - || self.internalState == STKAudioPlayerInternalStateStopped - || self.internalState == STKAudioPlayerInternalStateDisposed - || self.internalState == STKAudioPlayerInternalStatePendingNext) - { - pthread_mutex_unlock(&playerMutex); - - return; - } - - if (seekToTimeWasRequested && [currentlyPlayingEntry calculatedBitRate] > 0.0) - { - pthread_mutex_unlock(&playerMutex); - - [self wakeupPlaybackThread]; - - return; - } - - waiting = YES; - - pthread_cond_wait(&playerThreadReadyCondition, &playerMutex); - - waiting = NO; - } - - pthread_mutex_unlock(&playerMutex); - } - - AudioBuffer* localPcmAudioBuffer; - AudioBufferList localPcmBufferList; - - localPcmBufferList.mNumberBuffers = 1; - localPcmAudioBuffer = &localPcmBufferList.mBuffers[0]; - - if (end >= start) - { - UInt32 framesAdded = 0; - UInt32 framesToDecode = pcmBufferTotalFrameCount - end; - - localPcmAudioBuffer->mData = pcmAudioBuffer->mData + (end * pcmBufferFrameSizeInBytes); - localPcmAudioBuffer->mDataByteSize = framesToDecode * pcmBufferFrameSizeInBytes; - localPcmAudioBuffer->mNumberChannels = pcmAudioBuffer->mNumberChannels; - - status = AudioConverterFillComplexBuffer(audioConverterRef, AudioConverterCallback, (void*)&convertInfo, &framesToDecode, &localPcmBufferList, NULL); - - framesAdded = framesToDecode; - - if (status == 100) - { - OSSpinLockLock(&pcmBufferSpinLock); - pcmBufferUsedFrameCount += framesAdded; - OSSpinLockUnlock(&pcmBufferSpinLock); - - OSSpinLockLock(¤tlyReadingEntry->spinLock); - currentlyReadingEntry->framesQueued += framesAdded; - OSSpinLockUnlock(¤tlyReadingEntry->spinLock); - - return; - } - else if (status != 0) - { - [self unexpectedError:STKAudioPlayerErrorCodecError]; - - return; - } - - framesToDecode = start; - - if (framesToDecode == 0) - { - OSSpinLockLock(&pcmBufferSpinLock); - pcmBufferUsedFrameCount += framesAdded; - OSSpinLockUnlock(&pcmBufferSpinLock); - - OSSpinLockLock(¤tlyReadingEntry->spinLock); - currentlyReadingEntry->framesQueued += framesAdded; - OSSpinLockUnlock(¤tlyReadingEntry->spinLock); - - continue; - } - - localPcmAudioBuffer->mData = pcmAudioBuffer->mData; - localPcmAudioBuffer->mDataByteSize = framesToDecode * pcmBufferFrameSizeInBytes; - localPcmAudioBuffer->mNumberChannels = pcmAudioBuffer->mNumberChannels; - - status = AudioConverterFillComplexBuffer(audioConverterRef, AudioConverterCallback, (void*)&convertInfo, &framesToDecode, &localPcmBufferList, NULL); - - framesAdded += framesToDecode; - - if (status == 100) - { - OSSpinLockLock(&pcmBufferSpinLock); - pcmBufferUsedFrameCount += framesAdded; - OSSpinLockUnlock(&pcmBufferSpinLock); - - OSSpinLockLock(¤tlyReadingEntry->spinLock); - currentlyReadingEntry->framesQueued += framesAdded; - OSSpinLockUnlock(¤tlyReadingEntry->spinLock); - - return; - } - else if (status == 0) - { - OSSpinLockLock(&pcmBufferSpinLock); - pcmBufferUsedFrameCount += framesAdded; - OSSpinLockUnlock(&pcmBufferSpinLock); - - OSSpinLockLock(¤tlyReadingEntry->spinLock); - currentlyReadingEntry->framesQueued += framesAdded; - OSSpinLockUnlock(¤tlyReadingEntry->spinLock); - - continue; - } - else if (status != 0) - { - [self unexpectedError:STKAudioPlayerErrorCodecError]; - - return; - } - } - else - { - UInt32 framesAdded = 0; - UInt32 framesToDecode = start - end; - - localPcmAudioBuffer->mData = pcmAudioBuffer->mData + (end * pcmBufferFrameSizeInBytes); - localPcmAudioBuffer->mDataByteSize = framesToDecode * pcmBufferFrameSizeInBytes; - localPcmAudioBuffer->mNumberChannels = pcmAudioBuffer->mNumberChannels; - - status = AudioConverterFillComplexBuffer(audioConverterRef, AudioConverterCallback, (void*)&convertInfo, &framesToDecode, &localPcmBufferList, NULL); - - framesAdded = framesToDecode; - - if (status == 100) - { - OSSpinLockLock(&pcmBufferSpinLock); - pcmBufferUsedFrameCount += framesAdded; - OSSpinLockUnlock(&pcmBufferSpinLock); - - OSSpinLockLock(¤tlyReadingEntry->spinLock); - currentlyReadingEntry->framesQueued += framesAdded; - OSSpinLockUnlock(¤tlyReadingEntry->spinLock); - - return; - } - else if (status == 0) - { - OSSpinLockLock(&pcmBufferSpinLock); - pcmBufferUsedFrameCount += framesAdded; - OSSpinLockUnlock(&pcmBufferSpinLock); - - OSSpinLockLock(¤tlyReadingEntry->spinLock); - currentlyReadingEntry->framesQueued += framesAdded; - OSSpinLockUnlock(¤tlyReadingEntry->spinLock); - - continue; - } - else if (status != 0) - { - [self unexpectedError:STKAudioPlayerErrorCodecError]; - - return; - } - } - } -} - -static OSStatus OutputRenderCallback(void* inRefCon, AudioUnitRenderActionFlags* ioActionFlags, const AudioTimeStamp* inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList* ioData) -{ - STKAudioPlayer* audioPlayer = (__bridge STKAudioPlayer*)inRefCon; - - OSSpinLockLock(&audioPlayer->currentEntryReferencesLock); - STKQueueEntry* entry = audioPlayer->currentlyPlayingEntry; - STKQueueEntry* currentlyReadingEntry = audioPlayer->currentlyReadingEntry; - OSSpinLockUnlock(&audioPlayer->currentEntryReferencesLock); - - OSSpinLockLock(&audioPlayer->pcmBufferSpinLock); - - BOOL waitForBuffer = NO; - BOOL muted = audioPlayer->muted; - AudioBuffer* audioBuffer = audioPlayer->pcmAudioBuffer; - UInt32 frameSizeInBytes = audioPlayer->pcmBufferFrameSizeInBytes; - UInt32 used = audioPlayer->pcmBufferUsedFrameCount; - UInt32 start = audioPlayer->pcmBufferFrameStartIndex; - STKAudioPlayerInternalState state = audioPlayer->internalState; - UInt32 end = (audioPlayer->pcmBufferFrameStartIndex + audioPlayer->pcmBufferUsedFrameCount) % audioPlayer->pcmBufferTotalFrameCount; - BOOL signal = audioPlayer->waiting && used < audioPlayer->pcmBufferTotalFrameCount / 2; - NSArray* frameFilters = audioPlayer->frameFilters; - - if (entry) - { - if (state == STKAudioPlayerInternalStateWaitingForData) - { - SInt64 framesRequiredToStartPlaying = audioPlayer->framesRequiredToStartPlaying; - - if (entry->lastFrameQueued >= 0) - { - framesRequiredToStartPlaying = MIN(framesRequiredToStartPlaying, entry->lastFrameQueued); - } - - if (entry && currentlyReadingEntry == entry - && entry->framesQueued < framesRequiredToStartPlaying) - { - waitForBuffer = YES; - } - } - else if (state == STKAudioPlayerInternalStateRebuffering) - { - SInt64 framesRequiredToStartPlaying = audioPlayer->framesRequiredToPlayAfterRebuffering; - - if (entry->lastFrameQueued >= 0) - { - framesRequiredToStartPlaying = MIN(framesRequiredToStartPlaying, entry->lastFrameQueued - entry->framesQueued); - } - - if (used < framesRequiredToStartPlaying) - { - waitForBuffer = YES; - } - } - else if (state == STKAudioPlayerInternalStateWaitingForDataAfterSeek) - { - SInt64 framesRequiredToStartPlaying = 1024; - - if (entry->lastFrameQueued >= 0) - { - framesRequiredToStartPlaying = MIN(framesRequiredToStartPlaying, entry->lastFrameQueued - entry->framesQueued); - } - - if (used < framesRequiredToStartPlaying) - { - waitForBuffer = YES; - } - } - } - - OSSpinLockUnlock(&audioPlayer->pcmBufferSpinLock); - - UInt32 totalFramesCopied = 0; - - if (used > 0 && !waitForBuffer && entry != nil && ((state & STKAudioPlayerInternalStateRunning) && state != STKAudioPlayerInternalStatePaused)) - { - if (state == STKAudioPlayerInternalStateWaitingForData) - { - // Starting - } - else if (state == STKAudioPlayerInternalStateRebuffering) - { - // Resuming from buffering - } - - if (end > start) - { - UInt32 framesToCopy = MIN(inNumberFrames, used); - - ioData->mBuffers[0].mNumberChannels = 2; - ioData->mBuffers[0].mDataByteSize = frameSizeInBytes * framesToCopy; - - if (muted) - { - memset(ioData->mBuffers[0].mData, 0, ioData->mBuffers[0].mDataByteSize); - } - else - { - memcpy(ioData->mBuffers[0].mData, audioBuffer->mData + (start * frameSizeInBytes), ioData->mBuffers[0].mDataByteSize); - } - - totalFramesCopied = framesToCopy; - - OSSpinLockLock(&audioPlayer->pcmBufferSpinLock); - audioPlayer->pcmBufferFrameStartIndex = (audioPlayer->pcmBufferFrameStartIndex + totalFramesCopied) % audioPlayer->pcmBufferTotalFrameCount; - audioPlayer->pcmBufferUsedFrameCount -= totalFramesCopied; - OSSpinLockUnlock(&audioPlayer->pcmBufferSpinLock); - } - else - { - UInt32 framesToCopy = MIN(inNumberFrames, audioPlayer->pcmBufferTotalFrameCount - start); - - ioData->mBuffers[0].mNumberChannels = 2; - ioData->mBuffers[0].mDataByteSize = frameSizeInBytes * framesToCopy; - - if (muted) - { - memset(ioData->mBuffers[0].mData, 0, ioData->mBuffers[0].mDataByteSize); - } - else - { - memcpy(ioData->mBuffers[0].mData, audioBuffer->mData + (start * frameSizeInBytes), ioData->mBuffers[0].mDataByteSize); - } - - UInt32 moreFramesToCopy = 0; - UInt32 delta = inNumberFrames - framesToCopy; - - if (delta > 0) - { - moreFramesToCopy = MIN(delta, end); - - ioData->mBuffers[0].mNumberChannels = 2; - ioData->mBuffers[0].mDataByteSize += frameSizeInBytes * moreFramesToCopy; - - if (muted) - { - memset(ioData->mBuffers[0].mData + (framesToCopy * frameSizeInBytes), 0, frameSizeInBytes * moreFramesToCopy); - } - else - { - memcpy(ioData->mBuffers[0].mData + (framesToCopy * frameSizeInBytes), audioBuffer->mData, frameSizeInBytes * moreFramesToCopy); - } - } - - totalFramesCopied = framesToCopy + moreFramesToCopy; - - OSSpinLockLock(&audioPlayer->pcmBufferSpinLock); - audioPlayer->pcmBufferFrameStartIndex = (audioPlayer->pcmBufferFrameStartIndex + totalFramesCopied) % audioPlayer->pcmBufferTotalFrameCount; - audioPlayer->pcmBufferUsedFrameCount -= totalFramesCopied; - OSSpinLockUnlock(&audioPlayer->pcmBufferSpinLock); - } - - [audioPlayer setInternalState:STKAudioPlayerInternalStatePlaying ifInState:^BOOL(STKAudioPlayerInternalState state) - { - return (state & STKAudioPlayerInternalStateRunning) && state != STKAudioPlayerInternalStatePaused; - }]; - } - - if (totalFramesCopied < inNumberFrames) - { - UInt32 delta = inNumberFrames - totalFramesCopied; - - memset(ioData->mBuffers[0].mData + (totalFramesCopied * frameSizeInBytes), 0, delta * frameSizeInBytes); - - if (!(entry == nil || state == STKAudioPlayerInternalStateWaitingForDataAfterSeek || state == STKAudioPlayerInternalStateWaitingForData || state == STKAudioPlayerInternalStateRebuffering)) - { - // Buffering - - [audioPlayer setInternalState:STKAudioPlayerInternalStateRebuffering ifInState:^BOOL(STKAudioPlayerInternalState state) - { - return (state & STKAudioPlayerInternalStateRunning) && state != STKAudioPlayerInternalStatePaused; - }]; - } - else if (state == STKAudioPlayerInternalStateWaitingForDataAfterSeek) - { - if (totalFramesCopied == 0) - { - OSAtomicAdd32(inNumberFrames - totalFramesCopied, &audioPlayer->waitingForDataAfterSeekFrameCount); - - if (audioPlayer->waitingForDataAfterSeekFrameCount > audioPlayer->framesRequiredBeforeWaitingForDataAfterSeekBecomesPlaying) - { - [audioPlayer setInternalState:STKAudioPlayerInternalStatePlaying ifInState:^BOOL(STKAudioPlayerInternalState state) - { - return (state & STKAudioPlayerInternalStateRunning) && state != STKAudioPlayerInternalStatePaused; - }]; - } - } - else - { - audioPlayer->waitingForDataAfterSeekFrameCount = 0; - } - } - } - - if (frameFilters) - { - NSUInteger count = frameFilters.count; - AudioStreamBasicDescription asbd = canonicalAudioStreamBasicDescription; - - for (int i = 0; i < count; i++) - { - STKFrameFilterEntry* entry = [frameFilters objectAtIndex:i]; - - entry->filter(asbd.mChannelsPerFrame, asbd.mBytesPerFrame, inNumberFrames, ioData->mBuffers[0].mData); - } - } - - if (audioPlayer->equalizerEnabled != audioPlayer->equalizerOn) - { - Boolean isUpdated; - - [audioPlayer connectGraph]; - - AUGraphUpdate(audioPlayer->audioGraph, &isUpdated); - - isUpdated = isUpdated; - } - - if (entry == nil) - { - return 0; - } - - OSSpinLockLock(&entry->spinLock); - - SInt64 extraFramesPlayedNotAssigned = 0; - SInt64 framesPlayedForCurrent = totalFramesCopied; - - if (entry->lastFrameQueued >= 0) - { - framesPlayedForCurrent = MIN(entry->lastFrameQueued - entry->framesPlayed, framesPlayedForCurrent); - } - - entry->framesPlayed += framesPlayedForCurrent; - extraFramesPlayedNotAssigned = totalFramesCopied - framesPlayedForCurrent; - - BOOL lastFramePlayed = entry->framesPlayed == entry->lastFrameQueued; - - OSSpinLockUnlock(&entry->spinLock); - - if (signal || lastFramePlayed) - { - pthread_mutex_lock(&audioPlayer->playerMutex); - - OSSpinLockLock(&audioPlayer->currentEntryReferencesLock); - STKQueueEntry* currentlyPlayingEntry = audioPlayer->currentlyPlayingEntry; - OSSpinLockUnlock(&audioPlayer->currentEntryReferencesLock); - - if (lastFramePlayed && entry == currentlyPlayingEntry) - { - [audioPlayer audioQueueFinishedPlaying:entry]; - - while (extraFramesPlayedNotAssigned > 0) - { - OSSpinLockLock(&audioPlayer->currentEntryReferencesLock); - STKQueueEntry* newEntry = audioPlayer->currentlyPlayingEntry; - OSSpinLockUnlock(&audioPlayer->currentEntryReferencesLock); - - if (newEntry != nil) - { - SInt64 framesPlayedForCurrent = extraFramesPlayedNotAssigned; - - OSSpinLockLock(&newEntry->spinLock); - - if (newEntry->lastFrameQueued > 0) - { - framesPlayedForCurrent = MIN(newEntry->lastFrameQueued - newEntry->framesPlayed, framesPlayedForCurrent); - } - - newEntry->framesPlayed += framesPlayedForCurrent; - - if (newEntry->framesPlayed == newEntry->lastFrameQueued) - { - OSSpinLockUnlock(&newEntry->spinLock); - - [audioPlayer audioQueueFinishedPlaying:newEntry]; - } - else - { - OSSpinLockUnlock(&newEntry->spinLock); - } - - extraFramesPlayedNotAssigned -= framesPlayedForCurrent; - } - else - { - break; - } - } - } - - pthread_cond_signal(&audioPlayer->playerThreadReadyCondition); - pthread_mutex_unlock(&audioPlayer->playerMutex); - } - - return 0; -} - --(NSArray*) pendingQueue -{ - pthread_mutex_lock(&playerMutex); - - NSArray* retval; - NSMutableArray* mutableArray = [[NSMutableArray alloc] initWithCapacity:upcomingQueue.count + bufferingQueue.count]; - - for (STKQueueEntry* entry in upcomingQueue) - { - [mutableArray addObject:[entry queueItemId]]; - } - - for (STKQueueEntry* entry in bufferingQueue) - { - [mutableArray addObject:[entry queueItemId]]; - } - - retval = [NSArray arrayWithArray:mutableArray]; - - pthread_mutex_unlock(&playerMutex); - - return retval; -} - --(NSUInteger) pendingQueueCount -{ - pthread_mutex_lock(&playerMutex); - - NSUInteger retval = upcomingQueue.count + bufferingQueue.count; - - pthread_mutex_unlock(&playerMutex); - - return retval; -} - --(NSObject*) mostRecentlyQueuedStillPendingItem -{ - pthread_mutex_lock(&playerMutex); - - if (upcomingQueue.count > 0) - { - NSObject* retval = [[upcomingQueue objectAtIndex:0] queueItemId]; - - pthread_mutex_unlock(&playerMutex); - - return retval; - } - - if (bufferingQueue.count > 0) - { - NSObject* retval = [[bufferingQueue objectAtIndex:0] queueItemId]; - - pthread_mutex_unlock(&playerMutex); - - return retval; - } - - pthread_mutex_unlock(&playerMutex); - - return nil; -} - --(float) peakPowerInDecibelsForChannel:(NSUInteger)channelNumber -{ - if (channelNumber >= canonicalAudioStreamBasicDescription.mChannelsPerFrame) - { - return 0; - } - - return peakPowerDb[channelNumber]; -} - --(float) averagePowerInDecibelsForChannel:(NSUInteger)channelNumber -{ - if (channelNumber >= canonicalAudioStreamBasicDescription.mChannelsPerFrame) - { - return 0; - } - - return averagePowerDb[channelNumber]; -} - --(BOOL) meteringEnabled -{ - return self->meteringEnabled; -} - -#define CALCULATE_METER(channel) \ - Float32 currentFilteredValueOfSampleAmplitude##channel = STK_LOWPASSFILTERTIMESLICE * absoluteValueOfSampleAmplitude##channel + (1.0 - STK_LOWPASSFILTERTIMESLICE) * previousFilteredValueOfSampleAmplitude##channel; \ - previousFilteredValueOfSampleAmplitude##channel = currentFilteredValueOfSampleAmplitude##channel; \ - Float32 sampleDB##channel = 20.0 * log10(currentFilteredValueOfSampleAmplitude##channel) + STK_DBOFFSET; \ - if ((sampleDB##channel == sampleDB##channel) && (sampleDB##channel != -DBL_MAX)) \ - { \ - if(sampleDB##channel > peakValue##channel) \ - { \ - peakValue##channel = sampleDB##channel; \ - } \ - if (sampleDB##channel > -DBL_MAX) \ - { \ - count##channel++; \ - totalValue##channel += sampleDB##channel; \ - } \ - decibels##channel = peakValue##channel; \ - }; - --(void) setMeteringEnabled:(BOOL)value -{ - if (self->meteringEnabled == value) - { - return; - } - - if (!value) - { - [self removeFrameFilterWithName:@"STKMeteringFilter"]; - self->meteringEnabled = NO; - } - else - { - [self appendFrameFilterWithName:@"STKMeteringFilter" block:^(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UInt32 frameCount, void* frames) - { - SInt16* samples16 = (SInt16*)frames; - SInt32* samples32 = (SInt32*)frames; - UInt32 countLeft = 0; - UInt32 countRight = 0; - Float32 decibelsLeft = STK_DBMIN; - Float32 peakValueLeft = STK_DBMIN; - Float64 totalValueLeft = 0; - Float32 previousFilteredValueOfSampleAmplitudeLeft = 0; - Float32 decibelsRight = STK_DBMIN; - Float32 peakValueRight = STK_DBMIN; - Float64 totalValueRight = 0; - Float32 previousFilteredValueOfSampleAmplitudeRight = 0; - - if (bytesPerFrame / channelsPerFrame == 2) - { - for (int i = 0; i < frameCount * channelsPerFrame; i += channelsPerFrame) - { - Float32 absoluteValueOfSampleAmplitudeLeft = abs(samples16[i]); - Float32 absoluteValueOfSampleAmplitudeRight = abs(samples16[i + 1]); - - CALCULATE_METER(Left); - CALCULATE_METER(Right); - } - } - else if (bytesPerFrame / channelsPerFrame == 4) - { - for (int i = 0; i < frameCount * channelsPerFrame; i += channelsPerFrame) - { - Float32 absoluteValueOfSampleAmplitudeLeft = abs(samples32[i]) / 32768.0; - Float32 absoluteValueOfSampleAmplitudeRight = abs(samples32[i + 1]) / 32768.0; - - CALCULATE_METER(Left); - CALCULATE_METER(Right); - } - } - else - { - return; - } - - peakPowerDb[0] = MIN(MAX(decibelsLeft, -60), 0); - peakPowerDb[1] = MIN(MAX(decibelsRight, -60), 0); - - if (countLeft > 0) - { - averagePowerDb[0] = MIN(MAX(totalValueLeft / frameCount, -60), 0); - } - - if (countRight != 0) - { - averagePowerDb[1] = MIN(MAX(totalValueRight / frameCount, -60), 0); - } - }]; - } -} - -#pragma mark Frame Filters - --(NSArray*) frameFilters -{ - return frameFilters; -} - --(void) appendFrameFilterWithName:(NSString*)name block:(STKFrameFilter)block -{ - [self addFrameFilterWithName:name afterFilterWithName:nil block:block]; -} - --(void) removeFrameFilterWithName:(NSString*)name -{ - pthread_mutex_lock(&self->playerMutex); - - NSMutableArray* newFrameFilters = [[NSMutableArray alloc] initWithCapacity:frameFilters.count + 1]; - - for (STKFrameFilterEntry* filterEntry in frameFilters) - { - if (![filterEntry->name isEqualToString:name]) - { - [newFrameFilters addObject:filterEntry]; - } - } - - NSArray* replacement = [NSArray arrayWithArray:newFrameFilters]; - - OSSpinLockLock(&pcmBufferSpinLock); - if (newFrameFilters.count > 0) - { - frameFilters = replacement; - } - else - { - frameFilters = nil; - } - OSSpinLockUnlock(&pcmBufferSpinLock); - - pthread_mutex_unlock(&self->playerMutex); -} - --(void) addFrameFilterWithName:(NSString*)name afterFilterWithName:(NSString*)afterFilterWithName block:(STKFrameFilter)block -{ - pthread_mutex_lock(&self->playerMutex); - - NSMutableArray* newFrameFilters = [[NSMutableArray alloc] initWithCapacity:frameFilters.count + 1]; - - if (afterFilterWithName == nil) - { - [newFrameFilters addObject:[[STKFrameFilterEntry alloc] initWithFilter:block andName:name]]; - [newFrameFilters addObjectsFromArray:frameFilters]; - } - else - { - for (STKFrameFilterEntry* filterEntry in frameFilters) - { - if (afterFilterWithName != nil && [filterEntry->name isEqualToString:afterFilterWithName]) - { - [newFrameFilters addObject:[[STKFrameFilterEntry alloc] initWithFilter:block andName:name]]; - } - - [newFrameFilters addObject:filterEntry]; - } - } - - NSArray* replacement = [NSArray arrayWithArray:newFrameFilters]; - - OSSpinLockLock(&pcmBufferSpinLock); - frameFilters = replacement; - OSSpinLockUnlock(&pcmBufferSpinLock); - - pthread_mutex_unlock(&self->playerMutex); -} - --(void) addFrameFilter:(STKFrameFilter)frameFilter withName:(NSString*)name afterFilterWithName:(NSString*)afterFilterWithName -{ - pthread_mutex_lock(&self->playerMutex); - - NSMutableArray* newFrameFilters = [[NSMutableArray alloc] initWithCapacity:frameFilters.count + 1]; - - if (afterFilterWithName == nil) - { - [newFrameFilters addObjectsFromArray:frameFilters]; - [newFrameFilters addObject:[[STKFrameFilterEntry alloc] initWithFilter:frameFilter andName:name]]; - } - else - { - for (STKFrameFilterEntry* filterEntry in frameFilters) - { - [newFrameFilters addObject:filterEntry]; - - if (afterFilterWithName != nil && [filterEntry->name isEqualToString:afterFilterWithName]) - { - [newFrameFilters addObject:[[STKFrameFilterEntry alloc] initWithFilter:frameFilter andName:name]]; - } - } - } - - NSArray* replacement = [NSArray arrayWithArray:newFrameFilters]; - - OSSpinLockLock(&pcmBufferSpinLock); - frameFilters = replacement; - OSSpinLockUnlock(&pcmBufferSpinLock); - - pthread_mutex_unlock(&self->playerMutex); -} - -#pragma mark Volume - --(void) setVolume:(Float32)value -{ - self->volume = value; - -#if (TARGET_OS_IPHONE) - if (self->mixerNode) - { - AudioUnitSetParameter(self->mixerUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Output, 0, self->volume, 0); - } -#else - if (self->mixerNode) - { - AudioUnitSetParameter(self->mixerUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Output, 0, self->volume, 0); - } - else - { - AudioUnitSetParameter(outputUnit, kHALOutputParam_Volume, kAudioUnitScope_Output, kOutputBus, self->volume, 0); - } -#endif -} - --(Float32) volume -{ - return self->volume; -} - --(BOOL) equalizerEnabled -{ - return self->equalizerEnabled; -} - --(void) setEqualizerEnabled:(BOOL)value -{ - self->equalizerEnabled = value; -} - - -@end diff --git a/submodules/LegacyComponents/Sources/STKAutoRecoveringHTTPDataSource.h b/submodules/LegacyComponents/Sources/STKAutoRecoveringHTTPDataSource.h deleted file mode 100755 index c55895f3b6..0000000000 --- a/submodules/LegacyComponents/Sources/STKAutoRecoveringHTTPDataSource.h +++ /dev/null @@ -1,52 +0,0 @@ -/********************************************************************************** - AudioPlayer.m - - Created by Thong Nguyen on 16/10/2012. - https://github.com/tumtumtum/audjustable - - Copyright (c) 2012-2014 Thong Nguyen (tumtumtum@gmail.com). All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. All advertising materials mentioning features or use of this software - must display the following acknowledgement: - This product includes software developed by Thong Nguyen (tumtumtum@gmail.com) - 4. Neither the name of Thong Nguyen nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - **********************************************************************************/ - -#import "STKDataSource.h" -#import "STKHTTPDataSource.h" -#import "STKDataSourceWrapper.h" - -typedef struct -{ - int watchdogPeriodSeconds; - int inactivePeriodBeforeReconnectSeconds; -} -STKAutoRecoveringHTTPDataSourceOptions; - -@interface STKAutoRecoveringHTTPDataSource : STKDataSourceWrapper - --(id) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSource; - -@property (readonly) STKHTTPDataSource* innerDataSource; - -@end diff --git a/submodules/LegacyComponents/Sources/STKAutoRecoveringHTTPDataSource.m b/submodules/LegacyComponents/Sources/STKAutoRecoveringHTTPDataSource.m deleted file mode 100755 index 37fa5e5a93..0000000000 --- a/submodules/LegacyComponents/Sources/STKAutoRecoveringHTTPDataSource.m +++ /dev/null @@ -1,391 +0,0 @@ -/********************************************************************************** - AudioPlayer.m - - Created by Thong Nguyen on 16/10/2012. - https://github.com/tumtumtum/audjustable - - Copyright (c) 2012-2014 Thong Nguyen (tumtumtum@gmail.com). All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. All advertising materials mentioning features or use of this software - must display the following acknowledgement: - This product includes software developed by Thong Nguyen (tumtumtum@gmail.com) - 4. Neither the name of Thong Nguyen nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Thong Nguyen''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - **********************************************************************************/ - -#import -#import -#import -#import -#import -#import -#import "mach/mach_time.h" -#import -#import -#import "STKAutoRecoveringHTTPDataSource.h" - -#define DEFAULT_WATCHDOG_PERIOD_SECONDS (8) -#define DEFAULT_INACTIVE_PERIOD_BEFORE_RECONNECT_SECONDS (15) - -static uint64_t GetTickCount(void) -{ - static mach_timebase_info_data_t sTimebaseInfo; - uint64_t machTime = mach_absolute_time(); - - if (sTimebaseInfo.denom == 0 ) - { - (void) mach_timebase_info(&sTimebaseInfo); - } - - uint64_t millis = ((machTime / 1000000) * sTimebaseInfo.numer) / sTimebaseInfo.denom; - - return millis; -} - -@interface STKAutoRecoveringHTTPDataSource() -{ - int serial; - int waitSeconds; - NSTimer* timeoutTimer; - BOOL waitingForNetwork; - uint64_t ticksWhenLastDataReceived; - SCNetworkReachabilityRef reachabilityRef; - STKAutoRecoveringHTTPDataSourceOptions options; -} - --(void) reachabilityChanged; - -@end - -static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) -{ - @autoreleasepool - { - STKAutoRecoveringHTTPDataSource* dataSource = (__bridge STKAutoRecoveringHTTPDataSource*)info; - - [dataSource reachabilityChanged]; - } -} - -static void PopulateOptionsWithDefault(STKAutoRecoveringHTTPDataSourceOptions* options) -{ - if (options->watchdogPeriodSeconds == 0) - { - options->watchdogPeriodSeconds = DEFAULT_WATCHDOG_PERIOD_SECONDS; - } - - if (options->inactivePeriodBeforeReconnectSeconds == 0) - { - options->inactivePeriodBeforeReconnectSeconds = DEFAULT_INACTIVE_PERIOD_BEFORE_RECONNECT_SECONDS; - } -} - -@implementation STKAutoRecoveringHTTPDataSource - --(STKHTTPDataSource*) innerHTTPDataSource -{ - return (STKHTTPDataSource*)self.innerDataSource; -} - --(id) initWithDataSource:(STKDataSource *)innerDataSource -{ - return [self initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSource]; -} - --(id) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSourceIn -{ - return [self initWithHTTPDataSource:innerDataSourceIn andOptions:(STKAutoRecoveringHTTPDataSourceOptions){}]; -} - --(id) initWithHTTPDataSource:(STKHTTPDataSource*)innerDataSourceIn andOptions:(STKAutoRecoveringHTTPDataSourceOptions)optionsIn -{ - if (self = [super initWithDataSource:innerDataSourceIn]) - { - self.innerDataSource.delegate = self; - - struct sockaddr_in zeroAddress; - - bzero(&zeroAddress, sizeof(zeroAddress)); - zeroAddress.sin_len = sizeof(zeroAddress); - zeroAddress.sin_family = AF_INET; - - PopulateOptionsWithDefault(&optionsIn); - - self->options = optionsIn; - - reachabilityRef = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)&zeroAddress); - } - - return self; -} - --(BOOL) startNotifierOnRunLoop:(NSRunLoop*)runLoop -{ - BOOL retVal = NO; - SCNetworkReachabilityContext context = { 0, (__bridge void*)self, NULL, NULL, NULL }; - - if (SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context)) - { - if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, runLoop.getCFRunLoop, kCFRunLoopDefaultMode)) - { - retVal = YES; - } - } - - return retVal; -} - --(BOOL) registerForEvents:(NSRunLoop*)runLoop -{ - [super registerForEvents:runLoop]; - [self startNotifierOnRunLoop:runLoop]; - - if (timeoutTimer) - { - [timeoutTimer invalidate]; - timeoutTimer = nil; - } - - ticksWhenLastDataReceived = GetTickCount(); - - [self createTimeoutTimer]; - - return YES; -} - --(void) unregisterForEvents -{ - [super unregisterForEvents]; - [self stopNotifier]; - - [self destroyTimeoutTimer]; -} - --(void) timeoutTimerTick:(NSTimer*)timer -{ - if (![self hasBytesAvailable]) - { - if ([self hasGotNetworkConnection]) - { - uint64_t currentTicks = GetTickCount(); - - if (((currentTicks - ticksWhenLastDataReceived) / 1000) >= options.inactivePeriodBeforeReconnectSeconds) - { - serial++; - - NSLog(@"timeoutTimerTick %lld/%lld", self.position, self.length); - - [self attemptReconnectWithSerial:@(serial)]; - } - } - } -} - --(void) createTimeoutTimer -{ - [self destroyTimeoutTimer]; - - NSRunLoop* runLoop = self.innerDataSource.eventsRunLoop; - - if (runLoop == nil) - { - return; - } - - timeoutTimer = [NSTimer timerWithTimeInterval:options.watchdogPeriodSeconds target:self selector:@selector(timeoutTimerTick:) userInfo:@(serial) repeats:YES]; - - [runLoop addTimer:timeoutTimer forMode:NSRunLoopCommonModes]; -} - --(void) destroyTimeoutTimer -{ - if (timeoutTimer) - { - [timeoutTimer invalidate]; - timeoutTimer = nil; - } -} - --(void) stopNotifier -{ - if (reachabilityRef != NULL) - { - SCNetworkReachabilitySetCallback(reachabilityRef, NULL, NULL); - SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, [self.innerDataSource.eventsRunLoop getCFRunLoop], kCFRunLoopDefaultMode); - } -} - --(BOOL) hasGotNetworkConnection -{ - SCNetworkReachabilityFlags flags; - - if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) - { - return ((flags & kSCNetworkReachabilityFlagsReachable) != 0); - } - - return NO; -} - --(void) seekToOffset:(int64_t)offset -{ - ticksWhenLastDataReceived = GetTickCount(); - - [super seekToOffset:offset]; -} - --(void) close -{ - [self destroyTimeoutTimer]; - [super close]; -} - --(void) dealloc -{ - NSLog(@"STKAutoRecoveringHTTPDataSource dealloc"); - - self.innerDataSource.delegate = nil; - - [self stopNotifier]; - [self destroyTimeoutTimer]; - - [NSObject cancelPreviousPerformRequestsWithTarget:self]; - - if (reachabilityRef!= NULL) - { - CFRelease(reachabilityRef); - } -} - --(void) reachabilityChanged -{ - if (waitingForNetwork) - { - waitingForNetwork = NO; - - NSLog(@"reachabilityChanged %lld/%lld", self.position, self.length); - - serial++; - - [self attemptReconnectWithSerial:@(serial)]; - } -} - --(void) dataSourceDataAvailable:(STKDataSource*)dataSource -{ - if (![self.innerDataSource hasBytesAvailable]) - { - return; - } - - serial++; - waitSeconds = 1; - ticksWhenLastDataReceived = GetTickCount(); - - [super dataSourceDataAvailable:dataSource]; -} - --(void) attemptReconnectWithSerial:(NSNumber*)serialIn -{ - if (serialIn.intValue != self->serial) - { - return; - } - - NSLog(@"attemptReconnect %lld/%lld", self.position, self.length); - - if (self.innerDataSource.eventsRunLoop) - { - [self.innerDataSource reconnect]; - } -} - --(void) attemptReconnectWithTimer:(NSTimer*)timer -{ - [self attemptReconnectWithSerial:(NSNumber*)timer.userInfo]; -} - --(void) processRetryOnError -{ - if (![self hasGotNetworkConnection]) - { - waitingForNetwork = YES; - - return; - } - - waitingForNetwork = NO; - - NSRunLoop* runLoop = self.innerDataSource.eventsRunLoop; - - if (runLoop == nil) - { - // DataSource no longer used - - return; - } - else - { - serial++; - - NSTimer* timer = [NSTimer timerWithTimeInterval:waitSeconds target:self selector:@selector(attemptReconnectWithTimer:) userInfo:@(serial) repeats:NO]; - - [runLoop addTimer:timer forMode:NSRunLoopCommonModes]; - } - - waitSeconds = MIN(waitSeconds + 1, 5); -} - --(void) dataSourceEof:(STKDataSource*)dataSource -{ - NSLog(@"dataSourceEof"); - - if ([self position] < [self length]) - { - [self processRetryOnError]; - - return; - } - - [self.delegate dataSourceEof:self]; -} - --(void) dataSourceErrorOccured:(STKDataSource*)dataSource -{ - NSLog(@"dataSourceErrorOccured"); - - if (self.innerDataSource.httpStatusCode == 416 /* Range out of bounds */) - { - [super dataSourceEof:dataSource]; - } - else - { - [self processRetryOnError]; - } -} - --(NSString*) description -{ - return [NSString stringWithFormat:@"HTTP data source with file length: %lld and position: %lld", self.length, self.position]; -} - -@end diff --git a/submodules/LegacyComponents/Sources/STKCoreFoundationDataSource.h b/submodules/LegacyComponents/Sources/STKCoreFoundationDataSource.h deleted file mode 100755 index 731de5d703..0000000000 --- a/submodules/LegacyComponents/Sources/STKCoreFoundationDataSource.h +++ /dev/null @@ -1,63 +0,0 @@ -/********************************************************************************** - AudioPlayer.m - - Created by Thong Nguyen on 14/05/2012. - https://github.com/tumtumtum/audjustable - - Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. All advertising materials mentioning features or use of this software - must display the following acknowledgement: - This product includes software developed by Thong Nguyen (tumtumtum@gmail.com) - 4. Neither the name of Thong Nguyen nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**********************************************************************************/ - -#import "STKDataSource.h" - -@class STKCoreFoundationDataSource; - -@interface CoreFoundationDataSourceClientInfo : NSObject -@property (readwrite) CFReadStreamRef readStreamRef; -@property (readwrite, retain) STKCoreFoundationDataSource* datasource; -@end - -@interface STKCoreFoundationDataSource : STKDataSource -{ -@protected - BOOL isInErrorState; - CFReadStreamRef stream; - NSRunLoop* eventsRunLoop; -} - -@property (readonly) BOOL isInErrorState; - --(BOOL) reregisterForEvents; - --(void) open; --(void) openCompleted; --(void) dataAvailable; --(void) eof; --(void) errorOccured; --(CFStreamStatus) status; - -@end diff --git a/submodules/LegacyComponents/Sources/STKCoreFoundationDataSource.m b/submodules/LegacyComponents/Sources/STKCoreFoundationDataSource.m deleted file mode 100755 index 1763acd57a..0000000000 --- a/submodules/LegacyComponents/Sources/STKCoreFoundationDataSource.m +++ /dev/null @@ -1,201 +0,0 @@ -/********************************************************************************** - AudioPlayer.m - - Created by Thong Nguyen on 14/05/2012. - https://github.com/tumtumtum/audjustable - - Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. All advertising materials mentioning features or use of this software - must display the following acknowledgement: - This product includes software developed by Thong Nguyen (tumtumtum@gmail.com) - 4. Neither the name of Thong Nguyen nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**********************************************************************************/ - -#import "STKCoreFoundationDataSource.h" - -static void ReadStreamCallbackProc(CFReadStreamRef stream, CFStreamEventType eventType, void* inClientInfo) -{ - STKCoreFoundationDataSource* datasource = (__bridge STKCoreFoundationDataSource*)inClientInfo; - - switch (eventType) - { - case kCFStreamEventErrorOccurred: - [datasource errorOccured]; - break; - case kCFStreamEventEndEncountered: - [datasource eof]; - break; - case kCFStreamEventHasBytesAvailable: - [datasource dataAvailable]; - break; - case kCFStreamEventOpenCompleted: - [datasource openCompleted]; - break; - default: - break; - } -} - -@implementation CoreFoundationDataSourceClientInfo -@synthesize readStreamRef, datasource; -@end - -@implementation STKCoreFoundationDataSource - --(BOOL) isInErrorState -{ - return self->isInErrorState; -} - --(void) dataAvailable -{ - [self.delegate dataSourceDataAvailable:self]; -} - --(void) eof -{ - [self.delegate dataSourceEof:self]; -} - --(void) errorOccured -{ - self->isInErrorState = YES; - - [self.delegate dataSourceErrorOccured:self]; -} - --(void) dealloc -{ - if (stream) - { - if (eventsRunLoop) - { - [self unregisterForEvents]; - } - - [self close]; - - stream = 0; - } -} - --(void) close -{ - if (stream) - { - if (eventsRunLoop) - { - [self unregisterForEvents]; - } - - CFReadStreamClose(stream); - CFRelease(stream); - - stream = 0; - } -} - --(void) open -{ -} - --(void) seekToOffset:(SInt64)offset -{ -} - --(int) readIntoBuffer:(UInt8*)buffer withSize:(int)size -{ - return (int)CFReadStreamRead(stream, buffer, size); -} - --(void) unregisterForEvents -{ - if (stream) - { - CFReadStreamSetClient(stream, kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, NULL, NULL); - CFReadStreamUnscheduleFromRunLoop(stream, [eventsRunLoop getCFRunLoop], kCFRunLoopCommonModes); - - eventsRunLoop = nil; - } -} - --(BOOL) reregisterForEvents -{ - if (eventsRunLoop && stream) - { - CFStreamClientContext context = {0, (__bridge void*)self, NULL, NULL, NULL}; - CFReadStreamSetClient(stream, kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, ReadStreamCallbackProc, &context); - CFReadStreamScheduleWithRunLoop(stream, [eventsRunLoop getCFRunLoop], kCFRunLoopCommonModes); - - return YES; - } - - return NO; -} - --(BOOL) registerForEvents:(NSRunLoop*)runLoop -{ - eventsRunLoop = runLoop; - - if (!stream) - { - // Will register when they open or seek - - return YES; - } - - CFStreamClientContext context = {0, (__bridge void*)self, NULL, NULL, NULL}; - - CFReadStreamSetClient(stream, kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, ReadStreamCallbackProc, &context); - - CFReadStreamScheduleWithRunLoop(stream, [eventsRunLoop getCFRunLoop], kCFRunLoopCommonModes); - - return YES; -} - --(BOOL) hasBytesAvailable -{ - if (!stream) - { - return NO; - } - - return CFReadStreamHasBytesAvailable(stream); -} - --(CFStreamStatus) status -{ - if (stream) - { - return CFReadStreamGetStatus(stream); - } - - return 0; -} - --(void) openCompleted -{ -} - -@end diff --git a/submodules/LegacyComponents/Sources/STKDataSource.h b/submodules/LegacyComponents/Sources/STKDataSource.h deleted file mode 100755 index 69c296196f..0000000000 --- a/submodules/LegacyComponents/Sources/STKDataSource.h +++ /dev/null @@ -1,61 +0,0 @@ -/********************************************************************************** - AudioPlayer.m - - Created by Thong Nguyen on 14/05/2012. - https://github.com/tumtumtum/audjustable - - Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. All advertising materials mentioning features or use of this software - must display the following acknowledgement: - This product includes software developed by Thong Nguyen (tumtumtum@gmail.com) - 4. Neither the name of Thong Nguyen nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**********************************************************************************/ - -#import -#include - -@class STKDataSource; - -@protocol STKDataSourceDelegate --(void) dataSourceDataAvailable:(STKDataSource*)dataSource; --(void) dataSourceErrorOccured:(STKDataSource*)dataSource; --(void) dataSourceEof:(STKDataSource*)dataSource; -@end - -@interface STKDataSource : NSObject - -@property (readonly) SInt64 position; -@property (readonly) SInt64 length; -@property (readonly) BOOL hasBytesAvailable; -@property (readwrite, unsafe_unretained) id delegate; - --(BOOL) registerForEvents:(NSRunLoop*)runLoop; --(void) unregisterForEvents; --(void) close; - --(void) seekToOffset:(SInt64)offset; --(int) readIntoBuffer:(UInt8*)buffer withSize:(int)size; --(AudioFileTypeID) audioFileTypeHint; - -@end diff --git a/submodules/LegacyComponents/Sources/STKDataSource.m b/submodules/LegacyComponents/Sources/STKDataSource.m deleted file mode 100755 index 9abd8215a3..0000000000 --- a/submodules/LegacyComponents/Sources/STKDataSource.m +++ /dev/null @@ -1,82 +0,0 @@ -/********************************************************************************** - AudioPlayer.m - - Created by Thong Nguyen on 14/05/2012. - https://github.com/tumtumtum/audjustable - - Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. All advertising materials mentioning features or use of this software - must display the following acknowledgement: - This product includes software developed by Thong Nguyen (tumtumtum@gmail.com) - 4. Neither the name of Thong Nguyen nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**********************************************************************************/ - -#import "STKDataSource.h" - -@implementation STKDataSource -@synthesize delegate; - --(SInt64) length -{ - return 0; -} - --(void) seekToOffset:(SInt64)offset -{ -} - --(int) readIntoBuffer:(UInt8*)buffer withSize:(int)size -{ - return -1; -} - --(SInt64) position -{ - return 0; -} - --(BOOL) registerForEvents:(NSRunLoop*)runLoop -{ - return NO; -} - --(void) unregisterForEvents -{ -} - --(void) close -{ -} - --(BOOL) hasBytesAvailable -{ - return NO; -} - --(AudioFileTypeID) audioFileTypeHint -{ - return 0; -} - -@end diff --git a/submodules/LegacyComponents/Sources/STKDataSourceWrapper.h b/submodules/LegacyComponents/Sources/STKDataSourceWrapper.h deleted file mode 100755 index 4d3e035d5e..0000000000 --- a/submodules/LegacyComponents/Sources/STKDataSourceWrapper.h +++ /dev/null @@ -1,43 +0,0 @@ -/********************************************************************************** - AudioPlayer.m - - Created by Thong Nguyen on 16/10/2012. - https://github.com/tumtumtum/audjustable - - Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. All advertising materials mentioning features or use of this software - must display the following acknowledgement: - This product includes software developed by Thong Nguyen (tumtumtum@gmail.com) - 4. Neither the name of Thong Nguyen nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Thong Nguyen''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - **********************************************************************************/ - -#import "STKDataSource.h" - -@interface STKDataSourceWrapper : STKDataSource - --(id) initWithDataSource:(STKDataSource*)innerDataSource; - -@property (readonly) STKDataSource* innerDataSource; - -@end diff --git a/submodules/LegacyComponents/Sources/STKDataSourceWrapper.m b/submodules/LegacyComponents/Sources/STKDataSourceWrapper.m deleted file mode 100755 index 76e1634d91..0000000000 --- a/submodules/LegacyComponents/Sources/STKDataSourceWrapper.m +++ /dev/null @@ -1,120 +0,0 @@ -/********************************************************************************** - AudioPlayer.m - - Created by Thong Nguyen on 16/10/2012. - https://github.com/tumtumtum/audjustable - - Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. All advertising materials mentioning features or use of this software - must display the following acknowledgement: - This product includes software developed by Thong Nguyen (tumtumtum@gmail.com) - 4. Neither the name of Thong Nguyen nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Thong Nguyen''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - **********************************************************************************/ - -#import "STKDataSourceWrapper.h" - -@interface STKDataSourceWrapper() -@property (readwrite) STKDataSource* innerDataSource; -@end - -@implementation STKDataSourceWrapper - --(id) initWithDataSource:(STKDataSource*)innerDataSourceIn -{ - if (self = [super init]) - { - self.innerDataSource = innerDataSourceIn; - - self.innerDataSource.delegate = self; - } - - return self; -} - --(AudioFileTypeID) audioFileTypeHint -{ - return self.innerDataSource.audioFileTypeHint; -} - --(void) dealloc -{ - self.innerDataSource.delegate = nil; -} - --(SInt64) length -{ - return self.innerDataSource.length; -} - --(void) seekToOffset:(SInt64)offset -{ - return [self.innerDataSource seekToOffset:offset]; -} - --(int) readIntoBuffer:(UInt8*)buffer withSize:(int)size -{ - return [self.innerDataSource readIntoBuffer:buffer withSize:size]; -} - --(SInt64) position -{ - return self.innerDataSource.position; -} - --(BOOL) registerForEvents:(NSRunLoop*)runLoop -{ - return [self.innerDataSource registerForEvents:runLoop]; -} - --(void) unregisterForEvents -{ - [self.innerDataSource unregisterForEvents]; -} - --(void) close -{ - [self.innerDataSource close]; -} - --(BOOL) hasBytesAvailable -{ - return self.innerDataSource.hasBytesAvailable; -} - --(void) dataSourceDataAvailable:(STKDataSource*)dataSource -{ - [self.delegate dataSourceDataAvailable:self]; -} - --(void) dataSourceErrorOccured:(STKDataSource*)dataSource -{ - [self.delegate dataSourceErrorOccured:self]; -} - --(void) dataSourceEof:(STKDataSource*)dataSource -{ - [self.delegate dataSourceEof:self]; -} - -@end diff --git a/submodules/LegacyComponents/Sources/STKHTTPDataSource.h b/submodules/LegacyComponents/Sources/STKHTTPDataSource.h deleted file mode 100755 index 628a62f6d6..0000000000 --- a/submodules/LegacyComponents/Sources/STKHTTPDataSource.h +++ /dev/null @@ -1,55 +0,0 @@ -/********************************************************************************** - AudioPlayer.m - - Created by Thong Nguyen on 14/05/2012. - https://github.com/tumtumtum/audjustable - - Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. All advertising materials mentioning features or use of this software - must display the following acknowledgement: - This product includes software developed by Thong Nguyen (tumtumtum@gmail.com) - 4. Neither the name of Thong Nguyen nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - **********************************************************************************/ - -#import "STKCoreFoundationDataSource.h" - -@class STKHTTPDataSource; - -typedef void(^STKURLBlock)(NSURL* url); -typedef NSURL*(^STKURLProvider)(); -typedef void(^STKAsyncURLProvider)(STKHTTPDataSource* dataSource, BOOL forSeek, STKURLBlock callback); - -@interface STKHTTPDataSource : STKCoreFoundationDataSource - -@property (readonly, retain) NSURL* url; -@property (readonly) UInt32 httpStatusCode; - -+(AudioFileTypeID) audioFileTypeHintFromMimeType:(NSString*)fileExtension; --(id) initWithURL:(NSURL*)url; --(id) initWithURLProvider:(STKURLProvider)urlProvider; --(id) initWithAsyncURLProvider:(STKAsyncURLProvider)asyncUrlProvider; --(NSRunLoop*) eventsRunLoop; --(void) reconnect; - -@end diff --git a/submodules/LegacyComponents/Sources/STKHTTPDataSource.m b/submodules/LegacyComponents/Sources/STKHTTPDataSource.m deleted file mode 100755 index 8a5f4d3406..0000000000 --- a/submodules/LegacyComponents/Sources/STKHTTPDataSource.m +++ /dev/null @@ -1,383 +0,0 @@ -/********************************************************************************** - AudioPlayer.m - - Created by Thong Nguyen on 14/05/2012. - https://github.com/tumtumtum/audjustable - - Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. All advertising materials mentioning features or use of this software - must display the following acknowledgement: - This product includes software developed by Thong Nguyen (tumtumtum@gmail.com) - 4. Neither the name of Thong Nguyen nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - **********************************************************************************/ - -#import "STKHTTPDataSource.h" -#import "STKLocalFileDataSource.h" - -@interface STKHTTPDataSource() -{ -@private - UInt32 httpStatusCode; - SInt64 seekStart; - SInt64 relativePosition; - SInt64 fileLength; - int discontinuous; - int requestSerialNumber; - - NSURL* currentUrl; - STKAsyncURLProvider asyncUrlProvider; - NSDictionary* httpHeaders; - AudioFileTypeID audioFileTypeHint; -} --(void) open; - -@end - -@implementation STKHTTPDataSource - --(id) initWithURL:(NSURL*)urlIn -{ - return [self initWithURLProvider:^NSURL* { return urlIn; }]; -} - --(id) initWithURLProvider:(STKURLProvider)urlProviderIn -{ - urlProviderIn = [urlProviderIn copy]; - - return [self initWithAsyncURLProvider:^(STKHTTPDataSource* dataSource, BOOL forSeek, STKURLBlock block) - { - block(urlProviderIn()); - }]; -} - --(id) initWithAsyncURLProvider:(STKAsyncURLProvider)asyncUrlProviderIn -{ - if (self = [super init]) - { - seekStart = 0; - relativePosition = 0; - fileLength = -1; - - self->asyncUrlProvider = [asyncUrlProviderIn copy]; - - audioFileTypeHint = [STKLocalFileDataSource audioFileTypeHintFromFileExtension:self->currentUrl.pathExtension]; - } - - return self; -} - --(void) dealloc -{ - NSLog(@"STKHTTPDataSource dealloc"); -} - --(NSURL*) url -{ - return self->currentUrl; -} - -+(AudioFileTypeID) audioFileTypeHintFromMimeType:(NSString*)mimeType -{ - static dispatch_once_t onceToken; - static NSDictionary* fileTypesByMimeType; - - dispatch_once(&onceToken, ^ - { - fileTypesByMimeType = - @{ - @"audio/mp3": @(kAudioFileMP3Type), - @"audio/mpg": @(kAudioFileMP3Type), - @"audio/mpeg": @(kAudioFileMP3Type), - @"audio/wav": @(kAudioFileWAVEType), - @"audio/aifc": @(kAudioFileAIFCType), - @"audio/aiff": @(kAudioFileAIFFType), - @"audio/x-m4a": @(kAudioFileM4AType), - @"audio/x-mp4": @(kAudioFileMPEG4Type), - @"audio/aacp": @(kAudioFileAAC_ADTSType), - @"audio/m4a": @(kAudioFileM4AType), - @"audio/mp4": @(kAudioFileMPEG4Type), - @"audio/caf": @(kAudioFileCAFType), - @"audio/aac": @(kAudioFileAAC_ADTSType), - @"audio/ac3": @(kAudioFileAC3Type), - @"audio/3gp": @(kAudioFile3GPType) - }; - }); - - NSNumber* number = [fileTypesByMimeType objectForKey:mimeType]; - - if (!number) - { - return 0; - } - - return (AudioFileTypeID)number.intValue; -} - --(AudioFileTypeID) audioFileTypeHint -{ - return audioFileTypeHint; -} - --(void) dataAvailable -{ - if (stream == NULL) { - return; - } - - if (self.httpStatusCode == 0) - { - CFTypeRef response = CFReadStreamCopyProperty(stream, kCFStreamPropertyHTTPResponseHeader); - - if (response) - { - httpHeaders = (__bridge_transfer NSDictionary*)CFHTTPMessageCopyAllHeaderFields((CFHTTPMessageRef)response); - - self->httpStatusCode = (UInt32)CFHTTPMessageGetResponseStatusCode((CFHTTPMessageRef)response); - - CFRelease(response); - } - - if (self.httpStatusCode == 200) - { - if (seekStart == 0) - { - fileLength = (SInt64)[[httpHeaders objectForKey:@"Content-Length"] longLongValue]; - } - - NSString* contentType = [httpHeaders objectForKey:@"Content-Type"]; - AudioFileTypeID typeIdFromMimeType = [STKHTTPDataSource audioFileTypeHintFromMimeType:contentType]; - - if (typeIdFromMimeType != 0) - { - audioFileTypeHint = typeIdFromMimeType; - } - } - else if (self.httpStatusCode == 206) - { - NSString* contentRange = [httpHeaders objectForKey:@"Content-Range"]; - NSArray* components = [contentRange componentsSeparatedByString:@"/"]; - - if (components.count == 2) - { - fileLength = [[components objectAtIndex:1] integerValue]; - } - } - else if (self.httpStatusCode == 416) - { - if (self.length >= 0) - { - seekStart = self.length; - } - - [self eof]; - - return; - } - else if (self.httpStatusCode >= 300) - { - [self errorOccured]; - - return; - } - } - - [super dataAvailable]; -} - --(SInt64) position -{ - return seekStart + relativePosition; -} - --(SInt64) length -{ - return fileLength >= 0 ? fileLength : 0; -} - --(void) reconnect -{ - NSRunLoop* savedEventsRunLoop = eventsRunLoop; - - [self close]; - - eventsRunLoop = savedEventsRunLoop; - - [self seekToOffset:self.position]; -} - --(void) seekToOffset:(SInt64)offset -{ - NSRunLoop* savedEventsRunLoop = eventsRunLoop; - - [self close]; - - eventsRunLoop = savedEventsRunLoop; - - NSAssert([NSRunLoop currentRunLoop] == eventsRunLoop, @"Seek called on wrong thread"); - - stream = 0; - relativePosition = 0; - seekStart = offset; - - self->isInErrorState = NO; - - [self openForSeek:YES]; -} - --(int) readIntoBuffer:(UInt8*)buffer withSize:(int)size -{ - if (size == 0) - { - return 0; - } - - int read = (int)CFReadStreamRead(stream, buffer, size); - - if (read < 0) - { - return read; - } - - relativePosition += read; - - return read; -} - --(void) open -{ - return [self openForSeek:NO]; -} - --(void) openForSeek:(BOOL)forSeek -{ - int localRequestSerialNumber; - - requestSerialNumber++; - localRequestSerialNumber = requestSerialNumber; - - asyncUrlProvider(self, forSeek, ^(NSURL* url) - { - if (localRequestSerialNumber != self->requestSerialNumber) - { - return; - } - - self->currentUrl = url; - - if (url == nil) - { - return; - } - - CFHTTPMessageRef message = CFHTTPMessageCreateRequest(NULL, (CFStringRef)@"GET", (__bridge CFURLRef)self->currentUrl, kCFHTTPVersion1_1); - - if (seekStart > 0) - { - CFHTTPMessageSetHeaderFieldValue(message, CFSTR("Range"), (__bridge CFStringRef)[NSString stringWithFormat:@"bytes=%lld-", seekStart]); - - discontinuous = YES; - } - - stream = CFReadStreamCreateForHTTPRequest(NULL, message); - - if (stream == nil) - { - CFRelease(message); - - [self errorOccured]; - - return; - } - - if (!CFReadStreamSetProperty(stream, kCFStreamPropertyHTTPShouldAutoredirect, kCFBooleanTrue)) - { - CFRelease(message); - - [self errorOccured]; - - return; - } - - // Proxy support - - CFDictionaryRef proxySettings = CFNetworkCopySystemProxySettings(); - CFReadStreamSetProperty(stream, kCFStreamPropertyHTTPProxy, proxySettings); - CFRelease(proxySettings); - - // SSL support - - if ([self->currentUrl.scheme caseInsensitiveCompare:@"https"] == NSOrderedSame) - { - NSDictionary* sslSettings = [NSDictionary dictionaryWithObjectsAndKeys: - (NSString*)kCFStreamSocketSecurityLevelNegotiatedSSL, kCFStreamSSLLevel, - [NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredCertificates, - [NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredRoots, - [NSNumber numberWithBool:YES], kCFStreamSSLAllowsAnyRoot, - [NSNumber numberWithBool:NO], kCFStreamSSLValidatesCertificateChain, - [NSNull null], kCFStreamSSLPeerName, - nil]; - - CFReadStreamSetProperty(stream, kCFStreamPropertySSLSettings, (__bridge CFTypeRef)sslSettings); - } - - [self reregisterForEvents]; - - self->httpStatusCode = 0; - - // Open - - if (!CFReadStreamOpen(stream)) - { - CFRelease(stream); - CFRelease(message); - - stream = 0; - - [self errorOccured]; - - return; - } - - self->isInErrorState = NO; - - CFRelease(message); - }); -} - --(UInt32) httpStatusCode -{ - return self->httpStatusCode; -} - --(NSRunLoop*) eventsRunLoop -{ - return self->eventsRunLoop; -} - --(NSString*) description -{ - return [NSString stringWithFormat:@"HTTP data source with file length: %lld and position: %lld", self.length, self.position]; -} - -@end diff --git a/submodules/LegacyComponents/Sources/STKLocalFileDataSource.h b/submodules/LegacyComponents/Sources/STKLocalFileDataSource.h deleted file mode 100755 index 777ee52f66..0000000000 --- a/submodules/LegacyComponents/Sources/STKLocalFileDataSource.h +++ /dev/null @@ -1,43 +0,0 @@ -/********************************************************************************** - AudioPlayer.m - - Created by Thong Nguyen on 14/05/2012. - https://github.com/tumtumtum/audjustable - - Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. All advertising materials mentioning features or use of this software - must display the following acknowledgement: - This product includes software developed by Thong Nguyen (tumtumtum@gmail.com) - 4. Neither the name of Thong Nguyen nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**********************************************************************************/ - -#import "STKCoreFoundationDataSource.h" - -@interface STKLocalFileDataSource : STKCoreFoundationDataSource - -+(AudioFileTypeID) audioFileTypeHintFromFileExtension:(NSString*)fileExtension; -@property (atomic, readonly, copy) NSString* filePath; --(id) initWithFilePath:(NSString*)filePath; - -@end diff --git a/submodules/LegacyComponents/Sources/STKLocalFileDataSource.m b/submodules/LegacyComponents/Sources/STKLocalFileDataSource.m deleted file mode 100755 index 2aded28dd9..0000000000 --- a/submodules/LegacyComponents/Sources/STKLocalFileDataSource.m +++ /dev/null @@ -1,243 +0,0 @@ -/********************************************************************************** - AudioPlayer.m - - Created by Thong Nguyen on 14/05/2012. - https://github.com/tumtumtum/audjustable - - Copyright (c) 2012 Thong Nguyen (tumtumtum@gmail.com). All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. All advertising materials mentioning features or use of this software - must display the following acknowledgement: - This product includes software developed by Thong Nguyen (tumtumtum@gmail.com) - 4. Neither the name of Thong Nguyen nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Thong Nguyen ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THONG NGUYEN BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**********************************************************************************/ - -#import "STKLocalFileDataSource.h" - -@interface STKLocalFileDataSource() -{ - SInt64 position; - SInt64 length; - AudioFileTypeID audioFileTypeHint; -} -@property (readwrite, copy) NSString* filePath; --(void) open; -@end - -@implementation STKLocalFileDataSource -@synthesize filePath; - --(id) initWithFilePath:(NSString*)filePathIn -{ - if (self = [super init]) - { - self.filePath = filePathIn; - - audioFileTypeHint = [STKLocalFileDataSource audioFileTypeHintFromFileExtension:filePathIn.pathExtension]; - } - - return self; -} - -+(AudioFileTypeID) audioFileTypeHintFromFileExtension:(NSString*)fileExtension -{ - static dispatch_once_t onceToken; - static NSDictionary* fileTypesByFileExtensions; - - dispatch_once(&onceToken, ^ - { - fileTypesByFileExtensions = - @{ - @"mp3": @(kAudioFileMP3Type), - @"wav": @(kAudioFileWAVEType), - @"aifc": @(kAudioFileAIFCType), - @"aiff": @(kAudioFileAIFFType), - @"m4a": @(kAudioFileM4AType), - @"mp4": @(kAudioFileMPEG4Type), - @"caf": @(kAudioFileCAFType), - @"aac": @(kAudioFileAAC_ADTSType), - @"ac3": @(kAudioFileAC3Type), - @"3gp": @(kAudioFile3GPType) - }; - }); - - NSNumber* number = [fileTypesByFileExtensions objectForKey:fileExtension]; - - if (!number) - { - return 0; - } - - return (AudioFileTypeID)number.intValue; -} - --(AudioFileTypeID) audioFileTypeHint -{ - return audioFileTypeHint; -} - --(void) dealloc -{ - [self close]; -} - --(void) close -{ - if (stream) - { - [self unregisterForEvents]; - - CFReadStreamClose(stream); - - stream = 0; - } -} - --(void) open -{ - if (stream) - { - [self unregisterForEvents]; - - CFReadStreamClose(stream); - CFRelease(stream); - - stream = 0; - } - - NSURL* url = [[NSURL alloc] initFileURLWithPath:self.filePath]; - - stream = CFReadStreamCreateWithFile(NULL, (__bridge CFURLRef)url); - - NSError* fileError; - NSFileManager* manager = [[NSFileManager alloc] init]; - NSDictionary* attributes = [manager attributesOfItemAtPath:filePath error:&fileError]; - - if (fileError) - { - CFReadStreamClose(stream); - CFRelease(stream); - stream = 0; - return; - } - - NSNumber* number = [attributes objectForKey:@"NSFileSize"]; - - if (number) - { - length = number.longLongValue; - } - - [self reregisterForEvents]; - - CFReadStreamOpen(stream); -} - --(SInt64) position -{ - return position; -} - --(SInt64) length -{ - return length; -} - --(int) readIntoBuffer:(UInt8*)buffer withSize:(int)size -{ - int retval = (int)CFReadStreamRead(stream, buffer, size); - - if (retval > 0) - { - position += retval; - } - else - { - NSNumber* property = (__bridge_transfer NSNumber*)CFReadStreamCopyProperty(stream, kCFStreamPropertyFileCurrentOffset); - - position = property.longLongValue; - } - - return retval; -} - --(void) seekToOffset:(SInt64)offset -{ - CFStreamStatus status = kCFStreamStatusClosed; - - if (stream != 0) - { - status = CFReadStreamGetStatus(stream); - } - - BOOL reopened = NO; - - if (status == kCFStreamStatusAtEnd || status == kCFStreamStatusClosed || status == kCFStreamStatusError) - { - reopened = YES; - - [self close]; - [self open]; - } - - if (stream == 0) - { - CFRunLoopPerformBlock(eventsRunLoop.getCFRunLoop, NSRunLoopCommonModes, ^ - { - [self errorOccured]; - }); - - CFRunLoopWakeUp(eventsRunLoop.getCFRunLoop); - - return; - } - - if (CFReadStreamSetProperty(stream, kCFStreamPropertyFileCurrentOffset, (__bridge CFTypeRef)[NSNumber numberWithLongLong:offset]) != TRUE) - { - position = 0; - } - else - { - position = offset; - } - - if (!reopened) - { - CFRunLoopPerformBlock(eventsRunLoop.getCFRunLoop, NSRunLoopCommonModes, ^ - { - if ([self hasBytesAvailable]) - { - [self dataAvailable]; - } - }); - - CFRunLoopWakeUp(eventsRunLoop.getCFRunLoop); - } -} - --(NSString*) description -{ - return self->filePath; -} - -@end diff --git a/submodules/LegacyComponents/Sources/STKQueueEntry.h b/submodules/LegacyComponents/Sources/STKQueueEntry.h deleted file mode 100755 index 78e3784276..0000000000 --- a/submodules/LegacyComponents/Sources/STKQueueEntry.h +++ /dev/null @@ -1,45 +0,0 @@ -// -// STKQueueEntry.h -// StreamingKit -// -// Created by Thong Nguyen on 30/01/2014. -// Copyright (c) 2014 Thong Nguyen. All rights reserved. -// - -#import "STKDataSource.h" -#import "libkern/OSAtomic.h" -#import "AudioToolbox/AudioToolbox.h" - -@interface STKQueueEntry : NSObject -{ -@public - OSSpinLock spinLock; - - BOOL parsedHeader; - Float64 sampleRate; - double packetDuration; - UInt64 audioDataOffset; - UInt64 audioDataByteCount; - UInt32 packetBufferSize; - volatile Float64 seekTime; - volatile SInt64 framesQueued; - volatile SInt64 framesPlayed; - volatile SInt64 lastFrameQueued; - volatile int processedPacketsCount; - volatile int processedPacketsSizeTotal; - AudioStreamBasicDescription audioStreamBasicDescription; -} - -@property (readonly) UInt64 audioDataLengthInBytes; -@property (readwrite, retain) NSObject* queueItemId; -@property (readwrite, retain) STKDataSource* dataSource; - --(id) initWithDataSource:(STKDataSource*)dataSource andQueueItemId:(NSObject*)queueItemId; - --(void) reset; --(double) duration; --(Float64) progressInFrames; --(double) calculatedBitRate; --(BOOL) isDefinitelyCompatible:(AudioStreamBasicDescription*)basicDescription; - -@end \ No newline at end of file diff --git a/submodules/LegacyComponents/Sources/STKQueueEntry.m b/submodules/LegacyComponents/Sources/STKQueueEntry.m deleted file mode 100755 index 2b6de04a3b..0000000000 --- a/submodules/LegacyComponents/Sources/STKQueueEntry.m +++ /dev/null @@ -1,121 +0,0 @@ -// -// STKQueueEntry.m -// StreamingKit -// -// Created by Thong Nguyen on 30/01/2014. -// Copyright (c) 2014 Thong Nguyen. All rights reserved. -// - -#import "STKQueueEntry.h" -#import "STKDataSource.h" - -#define STK_BIT_RATE_ESTIMATION_MIN_PACKETS_MIN (2) -#define STK_BIT_RATE_ESTIMATION_MIN_PACKETS_PREFERRED (64) - -@implementation STKQueueEntry - --(id) initWithDataSource:(STKDataSource*)dataSourceIn andQueueItemId:(NSObject*)queueItemIdIn -{ - if (self = [super init]) - { - self->spinLock = OS_SPINLOCK_INIT; - - self.dataSource = dataSourceIn; - self.queueItemId = queueItemIdIn; - self->lastFrameQueued = -1; - } - - return self; -} - --(void) reset -{ - OSSpinLockLock(&self->spinLock); - self->framesQueued = 0; - self->framesPlayed = 0; - self->lastFrameQueued = -1; - OSSpinLockUnlock(&self->spinLock); -} - --(double) calculatedBitRate -{ - double retval; - - if (packetDuration > 0) - { - if (processedPacketsCount > STK_BIT_RATE_ESTIMATION_MIN_PACKETS_PREFERRED || (audioStreamBasicDescription.mBytesPerFrame == 0 && processedPacketsCount > STK_BIT_RATE_ESTIMATION_MIN_PACKETS_MIN)) - { - double averagePacketByteSize = processedPacketsSizeTotal / processedPacketsCount; - - retval = averagePacketByteSize / packetDuration * 8; - - return retval; - } - } - - retval = (audioStreamBasicDescription.mBytesPerFrame * audioStreamBasicDescription.mSampleRate) * 8; - - return retval; -} - --(double) duration -{ - if (self->sampleRate <= 0) - { - return 0; - } - - UInt64 audioDataLengthInBytes = [self audioDataLengthInBytes]; - - double calculatedBitRate = [self calculatedBitRate]; - - if (calculatedBitRate < 1.0 || self.dataSource.length == 0) - { - return 0; - } - - return audioDataLengthInBytes / (calculatedBitRate / 8); -} - --(UInt64) audioDataLengthInBytes -{ - if (audioDataByteCount) - { - return audioDataByteCount; - } - else - { - if (!self.dataSource.length) - { - return 0; - } - - return self.dataSource.length - audioDataOffset; - } -} - --(BOOL) isDefinitelyCompatible:(AudioStreamBasicDescription*)basicDescription -{ - if (self->audioStreamBasicDescription.mSampleRate == 0) - { - return NO; - } - - return (memcmp(&(self->audioStreamBasicDescription), basicDescription, sizeof(*basicDescription)) == 0); -} - --(Float64) progressInFrames -{ - OSSpinLockLock(&self->spinLock); - Float64 retval = self->seekTime + self->framesPlayed; - OSSpinLockUnlock(&self->spinLock); - - return retval; -} - --(NSString*) description -{ - return [[self queueItemId] description]; -} - -@end \ No newline at end of file diff --git a/submodules/LegacyComponents/Sources/TGCameraController.m b/submodules/LegacyComponents/Sources/TGCameraController.m index 8482896730..faec38dcbb 100644 --- a/submodules/LegacyComponents/Sources/TGCameraController.m +++ b/submodules/LegacyComponents/Sources/TGCameraController.m @@ -4,8 +4,6 @@ #import -#import - #import #import #import @@ -2431,7 +2429,7 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus + (bool)useLegacyCamera { - return iosMajorVersion() < 7 || [UIDevice currentDevice].platformType == UIDevice4iPhone || [UIDevice currentDevice].platformType == UIDevice4GiPod; + return false; } + (NSArray *)resultSignalsForSelectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext currentItem:(id)currentItem storeAssets:(bool)storeAssets saveEditedPhotos:(bool)saveEditedPhotos descriptionGenerator:(id (^)(id, NSString *, NSArray *, NSString *))descriptionGenerator diff --git a/submodules/LegacyComponents/Sources/TGListsTableView.m b/submodules/LegacyComponents/Sources/TGListsTableView.m index 0f0f104da3..0a191029ab 100644 --- a/submodules/LegacyComponents/Sources/TGListsTableView.m +++ b/submodules/LegacyComponents/Sources/TGListsTableView.m @@ -4,8 +4,6 @@ #import "POPBasicAnimation.h" #import "Freedom.h" -#import "TGSearchBar.h" - #import @interface TGListsTableView () @@ -80,12 +78,6 @@ } } - UIView *tableHeaderView = self.tableHeaderView; - if (tableHeaderView != nil && [tableHeaderView respondsToSelector:@selector(updateClipping:)]) - { - [(TGSearchBar *)tableHeaderView updateClipping:bounds.origin.y + self.contentInset.top]; - } - UIView *indexView = self.subviews.lastObject; if ([NSStringFromClass([indexView class]) rangeOfString:@"ViewIndex"].location != NSNotFound) { diff --git a/submodules/LegacyComponents/Sources/TGLocationAnnotation.h b/submodules/LegacyComponents/Sources/TGLocationAnnotation.h deleted file mode 100644 index 1bd042c825..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationAnnotation.h +++ /dev/null @@ -1,33 +0,0 @@ -#import -#import - -@class TGLocationMediaAttachment; -@class TGUser; - -@interface TGLocationPickerAnnotation: NSObject - -@property (nonatomic, assign) CLLocationCoordinate2D coordinate; -@property (nonatomic, strong) id peer; - -- (instancetype)initWithCoordinate:(CLLocationCoordinate2D)coordinate; - -@end - - -@interface TGLocationAnnotation : NSObject - -@property (nonatomic, readonly) TGLocationMediaAttachment *location; -@property (nonatomic, readonly) bool isLiveLocation; -@property (nonatomic, strong) id peer; -@property (nonatomic, strong) UIColor *color; -@property (nonatomic, assign) CLLocationCoordinate2D coordinate; -@property (nonatomic, assign) int32_t messageId; -@property (nonatomic, assign) bool isOwn; -@property (nonatomic, assign) bool hasSession; -@property (nonatomic, assign) bool isExpired; -@property (nonatomic, strong) NSNumber *heading; - -- (instancetype)initWithLocation:(TGLocationMediaAttachment *)location; -- (instancetype)initWithLocation:(TGLocationMediaAttachment *)location color:(UIColor *)color; - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationAnnotation.m b/submodules/LegacyComponents/Sources/TGLocationAnnotation.m deleted file mode 100644 index 9f5a1c7e39..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationAnnotation.m +++ /dev/null @@ -1,164 +0,0 @@ -#import "TGLocationAnnotation.h" - -#import "TGLocationMediaAttachment.h" - -@interface TGLocationAnnotation () -{ - CLLocationCoordinate2D _coordinate; - NSMutableSet *_observers; -} -@end - -@implementation TGLocationAnnotation - -- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context -{ - NSString *observerId = [NSString stringWithFormat:@"%lu%@", observer.hash, keyPath]; - [_observers addObject:observerId]; - - [super addObserver:observer forKeyPath:keyPath options:options context:context]; -} - -- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath -{ - NSString *observerId = [NSString stringWithFormat:@"%lu%@", observer.hash, keyPath]; - if ([_observers containsObject:observerId]) - { - [_observers removeObject:observerId]; - [super removeObserver:observer forKeyPath:keyPath]; - } -} - -- (instancetype)initWithLocation:(TGLocationMediaAttachment *)location -{ - return [self initWithLocation:location color:nil]; -} - -- (instancetype)initWithLocation:(TGLocationMediaAttachment *)location color:(UIColor *)color -{ - self = [super init]; - if (self != nil) - { - _coordinate = CLLocationCoordinate2DMake(location.latitude, location.longitude); - _color = color; - _location = location; - _observers = [[NSMutableSet alloc] init]; - } - return self; -} - -- (NSString *)title -{ - return @""; -} - -- (NSString *)subtitle -{ - return @""; -} - -- (CLLocationCoordinate2D)coordinate -{ - return _coordinate; -} - -- (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate -{ - if (fabs(newCoordinate.latitude - _coordinate.latitude) > DBL_EPSILON || fabs(newCoordinate.longitude - _coordinate.longitude) > DBL_EPSILON) - { - [self willChangeValueForKey:@"coordinate"]; - _coordinate = newCoordinate; - [self didChangeValueForKey:@"coordinate"]; - } -} - -- (void)setIsExpired:(bool)isExpired -{ - if (isExpired != _isExpired) - { - [self willChangeValueForKey:@"isExpired"]; - _isExpired = isExpired; - [self didChangeValueForKey:@"isExpired"]; - } -} - -- (void)setHeading:(NSNumber *)heading -{ - [self willChangeValueForKey:@"heading"]; - _heading = heading; - [self didChangeValueForKey:@"heading"]; -} - -- (void)setHasSession:(bool)hasSession -{ - if (hasSession != _hasSession) - { - [self willChangeValueForKey:@"hasSession"]; - _hasSession = hasSession; - [self didChangeValueForKey:@"hasSession"]; - } -} - -- (bool)isLiveLocation -{ - return _location.period > 0; -} - -@end - - -@interface TGLocationPickerAnnotation () -{ - CLLocationCoordinate2D _coordinate; - NSMutableSet *_observers; -} -@end - -@implementation TGLocationPickerAnnotation - -- (instancetype)initWithCoordinate:(CLLocationCoordinate2D)coordinate -{ - self = [super init]; - if (self != nil) - { - _coordinate = coordinate; - _observers = [[NSMutableSet alloc] init]; - } - return self; -} - -- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context -{ - NSString *observerId = [NSString stringWithFormat:@"%lu%@", observer.hash, keyPath]; - [_observers addObject:observerId]; - - [super addObserver:observer forKeyPath:keyPath options:options context:context]; -} - -- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath -{ - NSString *observerId = [NSString stringWithFormat:@"%lu%@", observer.hash, keyPath]; - if ([_observers containsObject:observerId]) - { - [_observers removeObject:observerId]; - [super removeObserver:observer forKeyPath:keyPath]; - } -} - - -- (CLLocationCoordinate2D)coordinate -{ - return _coordinate; -} - -- (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate -{ - if (fabs(newCoordinate.latitude - _coordinate.latitude) > DBL_EPSILON || fabs(newCoordinate.longitude - _coordinate.longitude) > DBL_EPSILON) - { - [self willChangeValueForKey:@"coordinate"]; - _coordinate = newCoordinate; - [self didChangeValueForKey:@"coordinate"]; - } -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationCurrentLocationCell.h b/submodules/LegacyComponents/Sources/TGLocationCurrentLocationCell.h deleted file mode 100644 index 930f9352ac..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationCurrentLocationCell.h +++ /dev/null @@ -1,22 +0,0 @@ -#import -#import -#import - -@class TGMessage; -@class TGLocationPallete; - -@interface TGLocationCurrentLocationCell : UITableViewCell - -@property (nonatomic, strong) TGLocationPallete *pallete; -@property (nonatomic, weak) UIImageView *edgeView; - -- (void)configureForCurrentLocationWithAccuracy:(CLLocationAccuracy)accuracy; -- (void)configureForCustomLocationWithAddress:(NSString *)address; -- (void)configureForGroupLocationWithAddress:(NSString *)address; -- (void)configureForLiveLocationWithAccuracy:(CLLocationAccuracy)accuracy; -- (void)configureForStopWithMessage:(TGMessage *)message remaining:(SSignal *)remaining; - -@end - -extern NSString *const TGLocationCurrentLocationCellKind; -extern const CGFloat TGLocationCurrentLocationCellHeight; diff --git a/submodules/LegacyComponents/Sources/TGLocationCurrentLocationCell.m b/submodules/LegacyComponents/Sources/TGLocationCurrentLocationCell.m deleted file mode 100644 index 39541e7d75..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationCurrentLocationCell.m +++ /dev/null @@ -1,409 +0,0 @@ -#import "TGLocationCurrentLocationCell.h" -#import "TGLocationVenueCell.h" - -#import "TGLocationMapViewController.h" -#import "LegacyComponentsInternal.h" -#import "TGColor.h" -#import "TGImageUtils.h" -#import "TGFont.h" -#import "TGLocationUtils.h" -#import "TGDateUtils.h" - -#import "TGMessage.h" - -#import "TGLocationWavesView.h" -#import "TGLocationLiveElapsedView.h" - -NSString *const TGLocationCurrentLocationCellKind = @"TGLocationCurrentLocationCellKind"; -const CGFloat TGLocationCurrentLocationCellHeight = 68; - -@interface TGLocationCurrentLocationCell () -{ - int32_t _messageId; - bool _isCurrentLocation; - - UIView *_highlightView; - - UIImageView *_circleView; - UIImageView *_iconView; - TGLocationWavesView *_wavesView; - - UILabel *_titleLabel; - UILabel *_subtitleLabel; - TGLocationLiveElapsedView *_elapsedView; - UIView *_separatorView; - - SMetaDisposable *_remainingDisposable; -} -@end - -@implementation TGLocationCurrentLocationCell - -- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier -{ - self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; - if (self != nil) - { - self.selectedBackgroundView = [[UIView alloc] init]; - self.selectedBackgroundView.backgroundColor = [UIColor clearColor]; - - _highlightView = [[UIView alloc] initWithFrame:self.bounds]; - _highlightView.alpha = 0.0f; - _highlightView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - _highlightView.backgroundColor = TGSelectionColor(); - _highlightView.userInteractionEnabled = false; - [self.contentView addSubview:_highlightView]; - - _circleView = [[UIImageView alloc] initWithFrame:CGRectMake(12.0f, 10.0f, 48.0f, 48.0f)]; - [self.contentView addSubview:_circleView]; - - _iconView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 48.0f, 48.0f)]; - _iconView.contentMode = UIViewContentModeCenter; - [_circleView addSubview:_iconView]; - - _titleLabel = [[UILabel alloc] init]; - _titleLabel.backgroundColor = [UIColor clearColor]; - _titleLabel.font = TGBoldSystemFontOfSize(16.0); - _titleLabel.text = TGLocalized(@"Map.SendMyCurrentLocation"); - _titleLabel.textColor = TGAccentColor(); - [self.contentView addSubview:_titleLabel]; - - _subtitleLabel = [[UILabel alloc] init]; - _subtitleLabel.backgroundColor = [UIColor clearColor]; - _subtitleLabel.font = TGSystemFontOfSize(13); - _subtitleLabel.text = TGLocalized(@"Map.Locating"); - _subtitleLabel.textColor = UIColorRGB(0xa6a6a6); - [self.contentView addSubview:_subtitleLabel]; - - _elapsedView = [[TGLocationLiveElapsedView alloc] init]; - [self.contentView addSubview:_elapsedView]; - - _separatorView = [[UIView alloc] init]; - _separatorView.backgroundColor = TGSeparatorColor(); - [self addSubview:_separatorView]; - - _wavesView = [[TGLocationWavesView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 48.0f, 48.0f)]; - [_circleView addSubview:_wavesView]; - - _isCurrentLocation = true; - } - return self; -} - -- (void)dealloc -{ - [_wavesView invalidate]; -} - -- (void)setPallete:(TGLocationPallete *)pallete -{ - if (pallete == nil || _pallete == pallete) - return; - - _pallete = pallete; - - self.backgroundColor = pallete.backgroundColor; - _highlightView.backgroundColor = pallete.selectionColor; - _titleLabel.textColor = pallete.accentColor; - _subtitleLabel.textColor = pallete.secondaryTextColor; - _separatorView.backgroundColor = pallete.separatorColor; - [_elapsedView setColor:pallete.accentColor]; -} - -- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated -{ - if (animated) - { - [UIView animateWithDuration:0.2 animations:^ - { - _highlightView.alpha = highlighted ? 1.0f : 0.0f; - _edgeView.alpha = highlighted ? 1.0f : 0.0f; - }]; - } - else - { - _highlightView.alpha = highlighted ? 1.0f : 0.0f; - _edgeView.alpha = highlighted ? 1.0f : 0.0f; - } -} - -- (void)setCircleColor:(UIColor *)color -{ - UIImage *circleImage = [TGLocationVenueCell circleImage]; - _circleView.image = TGTintedImage(circleImage, color); -} - -- (void)configureForCurrentLocationWithAccuracy:(CLLocationAccuracy)accuracy -{ - _messageId = 0; - - - UIImage *icon = TGComponentsImageNamed(@"LocationMessagePinIcon"); - if (_pallete != nil) - icon = TGTintedImage(icon, _pallete.iconColor); - - _iconView.image = icon; - _titleLabel.textColor = self.pallete != nil ? self.pallete.accentColor : TGAccentColor(); - _elapsedView.hidden = true; - - if (!_isCurrentLocation) - { - [UIView transitionWithView:self duration:0.2f options:UIViewAnimationOptionTransitionCrossDissolve animations:^ - { - _titleLabel.text = TGLocalized(@"Map.SendMyCurrentLocation"); - - if (accuracy > DBL_EPSILON) - { - NSString *accuracyString = [TGLocationUtils stringFromAccuracy:(NSInteger)accuracy]; - _subtitleLabel.text = [NSString stringWithFormat:TGLocalized(@"Map.AccurateTo"), accuracyString]; - - _circleView.alpha = 1.0f; - _titleLabel.alpha = 1.0f; - _subtitleLabel.alpha = 1.0f; - } - else - { - _subtitleLabel.text = TGLocalized(@"Map.Locating"); - - _circleView.alpha = 0.5f; - _titleLabel.alpha = 0.5f; - _subtitleLabel.alpha = 0.5f; - } - } completion:nil]; - - _isCurrentLocation = true; - } - else - { - if (accuracy > DBL_EPSILON) - { - NSString *accuracyString = [TGLocationUtils stringFromAccuracy:(NSInteger)accuracy]; - _subtitleLabel.text = [NSString stringWithFormat:TGLocalized(@"Map.AccurateTo"), accuracyString]; - - [UIView animateWithDuration:0.2f animations:^ - { - _circleView.alpha = 1.0f; - _titleLabel.alpha = 1.0f; - _subtitleLabel.alpha = 1.0f; - }]; - } - else - { - _subtitleLabel.text = TGLocalized(@"Map.Locating"); - - _circleView.alpha = 0.5f; - _titleLabel.alpha = 0.5f; - _subtitleLabel.alpha = 0.5f; - } - } - - [self setCircleColor:_pallete != nil ? _pallete.locationColor : UIColorRGB(0x008df2)]; - - _separatorView.hidden = false; - [_wavesView stop]; - _wavesView.hidden = true; - - [self setNeedsLayout]; -} - -- (void)configureForLiveLocationWithAccuracy:(CLLocationAccuracy)accuracy -{ - _messageId = 0; - - UIImage *icon = TGComponentsImageNamed(@"LocationMessageLiveIcon"); - if (_pallete != nil) - icon = TGTintedImage(icon, _pallete.iconColor); - - _iconView.image = icon; - _titleLabel.textColor = self.pallete != nil ? self.pallete.accentColor : TGAccentColor(); - _elapsedView.hidden = true; - - [UIView transitionWithView:self duration:0.2f options:UIViewAnimationOptionTransitionCrossDissolve animations:^ - { - _titleLabel.text = TGLocalized(@"Map.ShareLiveLocation"); - _subtitleLabel.text = TGLocalized(@"Map.ShareLiveLocationHelp"); - - if (accuracy > DBL_EPSILON) - { - _circleView.alpha = 1.0f; - _titleLabel.alpha = 1.0f; - _subtitleLabel.alpha = 1.0f; - } - else - { - _circleView.alpha = 0.5f; - _titleLabel.alpha = 0.5f; - _subtitleLabel.alpha = 0.5f; - } - } completion:nil]; - - [self setCircleColor:_pallete != nil ? _pallete.liveLocationColor : UIColorRGB(0xff6464)]; - - _separatorView.hidden = true; - [_wavesView stop]; - _wavesView.hidden = true; - - [self setNeedsLayout]; -} - -- (void)configureForStopWithMessage:(TGMessage *)message remaining:(SSignal *)remaining -{ - bool changed = message.mid != _messageId; - _messageId = message.mid; - - UIImage *icon = TGComponentsImageNamed(@"LocationMessagePinIcon"); - if (_pallete != nil) - icon = TGTintedImage(icon, _pallete.iconColor); - - _iconView.image = icon; - - _titleLabel.textColor = self.pallete != nil ? self.pallete.destructiveColor : UIColorRGB(0xff3b2f); - _titleLabel.text = TGLocalized(@"Map.StopLiveLocation"); - _subtitleLabel.text = [TGDateUtils stringForRelativeUpdate:[message actualDate]]; - - _circleView.alpha = 1.0f; - _titleLabel.alpha = 1.0f; - _subtitleLabel.alpha = 1.0f; - - [self setCircleColor:_pallete != nil ? _pallete.liveLocationColor : UIColorRGB(0xff6464)]; - - _separatorView.hidden = true; - _wavesView.hidden = false; - _wavesView.color = self.pallete != nil ? _pallete.iconColor : [UIColor whiteColor]; - [_wavesView start]; - - if (changed) - { - _elapsedView.hidden = false; - [self setNeedsLayout]; - - TGLocationMediaAttachment *locationAttachment = message.locationAttachment; - if (_remainingDisposable == nil) - _remainingDisposable = [[SMetaDisposable alloc] init]; - - __weak TGLocationCurrentLocationCell *weakSelf = self; - [_remainingDisposable setDisposable:[remaining startWithNext:^(NSNumber *next) - { - __strong TGLocationCurrentLocationCell *strongSelf = weakSelf; - if (strongSelf != nil) - [strongSelf->_elapsedView setRemaining:next.intValue period:locationAttachment.period]; - } completed:^ - { - __strong TGLocationCurrentLocationCell *strongSelf = weakSelf; - if (strongSelf != nil) - { - strongSelf->_elapsedView.hidden = true; - [strongSelf setNeedsLayout]; - } - }]]; - } -} - -- (void)configureForCustomLocationWithAddress:(NSString *)address -{ - _messageId = 0; - - UIImage *icon = TGComponentsImageNamed(@"LocationMessagePinIcon"); - if (_pallete != nil) - icon = TGTintedImage(icon, _pallete.iconColor); - _iconView.image = icon; - _titleLabel.textColor = self.pallete != nil ? self.pallete.accentColor : TGAccentColor(); - _elapsedView.hidden = true; - - if (_isCurrentLocation) - { - [UIView transitionWithView:self duration:0.2f options:UIViewAnimationOptionTransitionCrossDissolve animations:^ - { - _titleLabel.text = TGLocalized(@"Map.SendThisLocation"); - _subtitleLabel.text = [self _subtitleForAddress:address]; - - _circleView.alpha = 1.0f; - _titleLabel.alpha = 1.0f; - _subtitleLabel.alpha = 1.0f; - } completion:nil]; - - _isCurrentLocation = false; - } - else - { - [UIView transitionWithView:self duration:0.2f options:UIViewAnimationOptionTransitionCrossDissolve animations:^ - { - _subtitleLabel.text = [self _subtitleForAddress:address]; - } completion:nil]; - } - - [self setCircleColor:_pallete != nil ? _pallete.locationColor : UIColorRGB(0x008df2)]; - - _separatorView.hidden = false; - [_wavesView stop]; - _wavesView.hidden = true; - - [self setNeedsLayout]; -} - -- (void)configureForGroupLocationWithAddress:(NSString *)address -{ - _messageId = 0; - - UIImage *icon = TGComponentsImageNamed(@"LocationMessagePinIcon"); - if (_pallete != nil) - icon = TGTintedImage(icon, _pallete.iconColor); - _iconView.image = icon; - _titleLabel.textColor = self.pallete != nil ? self.pallete.accentColor : TGAccentColor(); - _elapsedView.hidden = true; - - if (_isCurrentLocation) - { - [UIView transitionWithView:self duration:0.2f options:UIViewAnimationOptionTransitionCrossDissolve animations:^ - { - _titleLabel.text = TGLocalized(@"Map.SetThisLocation"); - _subtitleLabel.text = [self _subtitleForAddress:address]; - - _circleView.alpha = 1.0f; - _titleLabel.alpha = 1.0f; - _subtitleLabel.alpha = 1.0f; - } completion:nil]; - - _isCurrentLocation = false; - } - else - { - [UIView transitionWithView:self duration:0.2f options:UIViewAnimationOptionTransitionCrossDissolve animations:^ - { - _subtitleLabel.text = [self _subtitleForAddress:address]; - } completion:nil]; - } - - [self setCircleColor:_pallete != nil ? _pallete.locationColor : UIColorRGB(0x008df2)]; - - _separatorView.hidden = true; - [_wavesView stop]; - _wavesView.hidden = true; - - [self setNeedsLayout]; -} - -- (NSString *)_subtitleForAddress:(NSString *)address -{ - if (address != nil && address.length == 0) - return TGLocalized(@"Map.Unknown"); - else if (address == nil) - return TGLocalized(@"Map.Locating"); - - return address; -} - -- (void)layoutSubviews -{ - [super layoutSubviews]; - - CGFloat padding = 76.0f; - CGFloat separatorThickness = TGScreenPixel; - - _titleLabel.frame = CGRectMake(padding, 14, self.frame.size.width - padding - 14 - (_elapsedView.hidden ? 0.0f : 38.0f), 20); - _subtitleLabel.frame = CGRectMake(padding, 36, self.frame.size.width - padding - 14 - (_elapsedView.hidden ? 0.0f : 38.0f), 20); - _separatorView.frame = CGRectMake(padding, self.frame.size.height - separatorThickness, self.frame.size.width - padding, separatorThickness); - _elapsedView.frame = CGRectMake(self.frame.size.width - 30.0f - 15.0f, floor((self.frame.size.height - 30.0f) / 2.0f), 30.0f, 30.0f); -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationInfoCell.h b/submodules/LegacyComponents/Sources/TGLocationInfoCell.h deleted file mode 100644 index 97fbe5fcce..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationInfoCell.h +++ /dev/null @@ -1,23 +0,0 @@ -#import -#import - -@class TGLocationMediaAttachment; -@class TGLocationPallete; - -@interface TGLocationInfoCell : UITableViewCell - -@property (nonatomic, strong) TGLocationPallete *pallete; -@property (nonatomic, assign) UIEdgeInsets safeInset; - -@property (nonatomic, copy) void (^locatePressed)(void); -@property (nonatomic, copy) void (^directionsPressed)(void); - -@property (nonatomic, readonly) UIButton *directionsButton; - -- (void)setLocation:(TGLocationMediaAttachment *)location color:(UIColor *)color messageId:(int32_t)messageId userLocationSignal:(SSignal *)userLocationSignal; - -@end - -extern NSString *const TGLocationInfoCellKind; -extern const CGFloat TGLocationInfoCellHeight; - diff --git a/submodules/LegacyComponents/Sources/TGLocationInfoCell.m b/submodules/LegacyComponents/Sources/TGLocationInfoCell.m deleted file mode 100644 index 46064ac1da..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationInfoCell.m +++ /dev/null @@ -1,357 +0,0 @@ -#import "TGLocationInfoCell.h" -#import "TGLocationVenueCell.h" - -#import "TGLocationMapViewController.h" -#import "TGLocationSignals.h" -#import "TGLocationUtils.h" -#import "TGLocationReverseGeocodeResult.h" - -#import "TGLocationMediaAttachment.h" - -#import "LegacyComponentsInternal.h" -#import "TGColor.h" -#import "TGFont.h" -#import "TGImageUtils.h" - -#import "TGImageView.h" -#import "TGModernButton.h" - -NSString *const TGLocationInfoCellKind = @"TGLocationInfoCell"; -const CGFloat TGLocationInfoCellHeight = 134.0f; - -@interface TGLocationInfoCell () -{ - TGModernButton *_locateButton; - UIImageView *_circleView; - TGImageView *_iconView; - - UILabel *_titleLabel; - UILabel *_addressLabel; - - TGModernButton *_directionsButton; - UILabel *_directionsButtonLabel; - UILabel *_etaLabel; - - SMetaDisposable *_addressDisposable; - int32_t _messageId; -} -@end - -@implementation TGLocationInfoCell - -- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier -{ - self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; - if (self != nil) - { - _messageId = -1; - - _locateButton = [[TGModernButton alloc] init]; - [_locateButton addTarget:self action:@selector(locateButtonPressed) forControlEvents:UIControlEventTouchUpInside]; - [self.contentView addSubview:_locateButton]; - - _circleView = [[UIImageView alloc] init]; - [_circleView setImage:TGTintedImage([TGLocationVenueCell circleImage], UIColorRGB(0x008df2))]; - [_locateButton addSubview:_circleView]; - - _iconView = [[TGImageView alloc] init]; - _iconView.contentMode = UIViewContentModeCenter; - _iconView.image = TGComponentsImageNamed(@"LocationMessagePinIcon"); - [_circleView addSubview:_iconView]; - - _titleLabel = [[UILabel alloc] init]; - _titleLabel.font = TGBoldSystemFontOfSize(17.0f); - _titleLabel.textColor = [UIColor blackColor]; - [_locateButton addSubview:_titleLabel]; - - _addressLabel = [[UILabel alloc] init]; - _addressLabel.font = TGSystemFontOfSize(13); - _addressLabel.textColor = UIColorRGB(0x8e8e93); - [_locateButton addSubview:_addressLabel]; - - static dispatch_once_t onceToken; - static UIImage *buttonImage = nil; - dispatch_once(&onceToken, ^ - { - CGSize size = CGSizeMake(16.0f, 16.0f); - UIGraphicsBeginImageContextWithOptions(size, false, 0.0f); - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSetStrokeColorWithColor(context, TGAccentColor().CGColor); - CGContextSetLineWidth(context, 1.0f); - CGContextStrokeEllipseInRect(context, CGRectMake(0.5f, 0.5f, size.width - 1.0f, size.height - 1.0f)); - buttonImage = [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:(NSInteger)(size.width / 2.0f) topCapHeight:(NSInteger)(size.height / 2.0f)]; - UIGraphicsEndImageContext(); - }); - - _directionsButton = [[TGModernButton alloc] init]; - _directionsButton.adjustsImageWhenHighlighted = false; - [_directionsButton setBackgroundImage:buttonImage forState:UIControlStateNormal]; - [_directionsButton addTarget:self action:@selector(directionsButtonPressed) forControlEvents:UIControlEventTouchUpInside]; - [self.contentView addSubview:_directionsButton]; - - _directionsButtonLabel = [[UILabel alloc] init]; - _directionsButtonLabel.backgroundColor = [UIColor clearColor]; - _directionsButtonLabel.font = TGBoldSystemFontOfSize(17.0f); - _directionsButtonLabel.text = TGLocalized(@"Map.Directions"); - _directionsButtonLabel.textAlignment = NSTextAlignmentCenter; - _directionsButtonLabel.textColor = TGAccentColor(); - _directionsButtonLabel.userInteractionEnabled = false; - [_directionsButtonLabel sizeToFit]; - [_directionsButton addSubview:_directionsButtonLabel]; - - _etaLabel = [[UILabel alloc] init]; - _etaLabel.alpha = 0.0f; - _etaLabel.font = TGSystemFontOfSize(13); - _etaLabel.textAlignment = NSTextAlignmentCenter; - _etaLabel.textColor = TGAccentColor(); - _etaLabel.userInteractionEnabled = false; - [_directionsButton addSubview:_etaLabel]; - } - return self; -} - -- (void)dealloc -{ - [_addressDisposable dispose]; -} - -- (void)setPallete:(TGLocationPallete *)pallete -{ - if (pallete == nil || _pallete == pallete) - return; - - _pallete = pallete; - - self.backgroundColor = pallete.backgroundColor; - [_circleView setImage:TGTintedImage([TGLocationVenueCell circleImage], _pallete.locationColor)]; - _titleLabel.textColor = pallete.textColor; - _addressLabel.textColor = pallete.secondaryTextColor; - _directionsButtonLabel.textColor = pallete.accentColor; - _etaLabel.textColor = pallete.accentColor; - - CGSize size = CGSizeMake(16.0f, 16.0f); - UIGraphicsBeginImageContextWithOptions(size, false, 0.0f); - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSetStrokeColorWithColor(context, pallete.accentColor.CGColor); - CGContextSetLineWidth(context, 1.0f); - CGContextStrokeEllipseInRect(context, CGRectMake(0.5f, 0.5f, size.width - 1.0f, size.height - 1.0f)); - UIImage *buttonImage = [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:(NSInteger)(size.width / 2.0f) topCapHeight:(NSInteger)(size.height / 2.0f)]; - UIGraphicsEndImageContext(); - - [_directionsButton setBackgroundImage:buttonImage forState:UIControlStateNormal]; -} - -- (void)locateButtonPressed -{ - if (self.locatePressed != nil) - self.locatePressed(); -} - -- (void)directionsButtonPressed -{ - if (self.directionsPressed != nil) - self.directionsPressed(); -} - -- (UIButton *)directionsButton -{ - return _directionsButton; -} - -- (void)setLocation:(TGLocationMediaAttachment *)location color:(UIColor *)color messageId:(int32_t)messageId userLocationSignal:(SSignal *)userLocationSignal -{ - if (_messageId == messageId) - return; - - _messageId = messageId; - - _titleLabel.text = location.venue.title.length > 0 ? location.venue.title : TGLocalized(@"Map.Location"); - - UIColor *pinColor = _pallete != nil ? _pallete.iconColor : [UIColor whiteColor]; - if (color != nil) { - [_circleView setImage:TGTintedImage([TGLocationVenueCell circleImage], color)]; - pinColor = [UIColor whiteColor]; - } - - if (location.venue.type.length > 0 && [location.venue.provider isEqualToString:@"foursquare"]) - [_iconView loadUri:[NSString stringWithFormat:@"location-venue-icon://type=%@&width=%d&height=%d&color=%d", location.venue.type, 48, 48, TGColorHexCode(pinColor)] withOptions:nil]; - - SSignal *addressSignal = [SSignal single:@""]; - if (location.venue.address.length > 0) - { - addressSignal = [SSignal single:location.venue.address]; - } - else - { - addressSignal = [[[TGLocationSignals reverseGeocodeCoordinate:CLLocationCoordinate2DMake(location.latitude, location.longitude)] map:^id(TGLocationReverseGeocodeResult *result) - { - return [result displayAddress]; - }] catch:^SSignal *(__unused id error) - { - return [SSignal single:[TGLocationUtils stringForCoordinate:CLLocationCoordinate2DMake(location.latitude, location.longitude)]]; - }]; - addressSignal = [[SSignal single:TGLocalized(@"Map.Locating")] then:addressSignal]; - } - - CLLocation *pointLocation = [[CLLocation alloc] initWithLatitude:location.latitude longitude:location.longitude]; - - if (_addressDisposable == nil) - _addressDisposable = [[SMetaDisposable alloc] init]; - - SSignal *updatedLocationSignal = [userLocationSignal reduceLeftWithPassthrough:nil with:^id(CLLocation *previous, CLLocation *next, void (^emit)(id)) - { - if (next == nil) - return nil; - - if (previous == nil && next != nil) - { - emit(@{@"location":next, @"update":@true}); - return next; - } - else - { - bool update = [next distanceFromLocation:previous] > 100; - emit(@{@"location":next, @"update":@(update)}); - return update ? next : previous; - } - }]; - - SSignal *signal = [[SSignal combineSignals:@[addressSignal, updatedLocationSignal] withInitialStates:@[ TGLocalized(@"Map.Locating"), [NSNull null] ]] mapToSignal:^SSignal *(NSArray *results) - { - NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; - dict[@"address"] = results.firstObject; - - if (![results.lastObject isKindOfClass:[NSNull class]]) - { - CLLocation *newLocation = ((NSDictionary *)results.lastObject)[@"location"]; - bool updateEta = [((NSDictionary *)results.lastObject)[@"update"] boolValue]; - dict[@"distance"] = @([pointLocation distanceFromLocation:newLocation]); - - if (updateEta) - { - return [[SSignal single:dict] then:[[TGLocationSignals driveEta:pointLocation.coordinate] map:^id(NSNumber *eta) - { - NSMutableDictionary *newDict = [dict mutableCopy]; - newDict[@"eta"] = eta; - return newDict; - }]]; - } - } - - return [SSignal single:dict]; - }]; - - __weak TGLocationInfoCell *weakSelf = self; - [_addressDisposable setDisposable:[[signal deliverOn:[SQueue mainQueue]] startWithNext:^(NSDictionary *next) - { - __strong TGLocationInfoCell *strongSelf = weakSelf; - if (strongSelf != nil) - { - NSString *address = next[@"address"]; - CGFloat distanceValue = [next[@"distance"] doubleValue]; - NSString *distance = next[@"distance"] ? [NSString stringWithFormat:TGLocalized(@"Map.DistanceAway"), [TGLocationUtils stringFromDistance:distanceValue]] : nil; - if (next[@"distance"] != nil && distanceValue < 10) - distance = TGLocalized(@"Map.YouAreHere"); - - if (next[@"eta"] != nil) - [strongSelf setDrivingETA:[next[@"eta"] doubleValue]]; - - NSMutableArray *components = [[NSMutableArray alloc] init]; - if (address.length > 0) - [components addObject:address]; - if (distance.length > 0) - [components addObject:distance]; - - NSString *string = [components componentsJoinedByString:@" • "]; - if ([strongSelf->_addressLabel.text isEqualToString:string]) - return; - - if (strongSelf->_addressLabel.text.length == 0) - { - strongSelf->_addressLabel.text = string; - } - else - { - [UIView transitionWithView:strongSelf->_addressLabel duration:0.2 options:UIViewAnimationOptionTransitionCrossDissolve animations:^ - { - strongSelf->_addressLabel.text = string; - } completion:nil]; - } - } - }]]; -} - -- (void)setDrivingETA:(NSTimeInterval)drivingETA -{ - if (drivingETA > 0 && drivingETA < 60 * 60 * 10) - { - drivingETA = MAX(drivingETA, 60); - - NSInteger minutes = (NSInteger)(drivingETA / 60) % 60; - NSInteger hours = (NSInteger)(drivingETA / 3600.0f); - - NSString *string = nil; - - if (hours < 1) - { - string = [NSString stringWithFormat:TGLocalized(@"Map.ETAMinutes_any"), [NSString stringWithFormat:@"%d", (int)minutes]]; - } - else - { - if (hours == 1 && minutes == 0) - { - string = [NSString stringWithFormat:TGLocalized(@"Map.ETAHours_1"), @"1"]; - } - else - { - string = [NSString stringWithFormat:TGLocalized(@"Map.ETAHours_any"), [NSString stringWithFormat:@"%d:%02d", (int)hours, (int)minutes]]; - } - } - - string = [NSString stringWithFormat:TGLocalized(@"Map.DirectionsDriveEta"), string]; - - if ([_etaLabel.text isEqualToString:string]) - return; - - if (_etaLabel.text.length == 0) - { - _etaLabel.text = string; - [UIView animateWithDuration:0.3 animations:^ - { - _etaLabel.alpha = 1.0f; - [self layoutSubviews]; - }]; - } - else - { - [UIView transitionWithView:_etaLabel duration:0.2 options:UIViewAnimationOptionTransitionCrossDissolve animations:^ - { - _etaLabel.text = string; - } completion:nil]; - } - } -} - -- (void)setSafeInset:(UIEdgeInsets)safeInset -{ - _safeInset = safeInset; - [self setNeedsLayout]; -} - -- (void)layoutSubviews -{ - _locateButton.frame = CGRectMake(0.0f, 0.0f, self.frame.size.width, 60.0f); - _circleView.frame = CGRectMake(12.0f + self.safeInset.left, 12.0f, 48.0f, 48.0f); - _iconView.frame = _circleView.bounds; - - _titleLabel.frame = CGRectMake(76.0f + self.safeInset.left, 15.0f, self.frame.size.width - 76.0f - 12.0f - self.safeInset.left - self.safeInset.right, 20.0f); - _addressLabel.frame = CGRectMake(76.0f + self.safeInset.left, 38.0f, self.frame.size.width - 76.0f - 12.0f - self.safeInset.left - self.safeInset.right, 20.0f); - - _directionsButton.frame = CGRectMake(12.0f + self.safeInset.left, 72.0f, self.frame.size.width - 12.0f * 2.0f - self.safeInset.left - self.safeInset.right, 50.0f); - - bool hasEta = _etaLabel.text.length > 0; - _directionsButtonLabel.frame = CGRectMake(0.0f, hasEta ? 6.0f : 14.0f, _directionsButton.frame.size.width, _directionsButtonLabel.frame.size.height); - _etaLabel.frame = CGRectMake(0.0f, hasEta ? 25.0f : 20.0f, _directionsButton.frame.size.width, 20.0f); -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationLiveCell.h b/submodules/LegacyComponents/Sources/TGLocationLiveCell.h deleted file mode 100644 index 362cbd6ebb..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationLiveCell.h +++ /dev/null @@ -1,24 +0,0 @@ -#import -#import - -@class TGUser; -@class TGMessage; -@class TGLocationPallete; - -@interface TGLocationLiveCell : UITableViewCell - -@property (nonatomic, strong) TGLocationPallete *pallete; -@property (nonatomic, assign) UIEdgeInsets safeInset; -@property (nonatomic, copy) void (^longPressed)(void); - -@property (nonatomic, readonly) int32_t messageId; -@property (nonatomic, weak) UIImageView *edgeView; - -- (void)configureWithPeer:(id)peer message:(TGMessage *)message remaining:(SSignal *)remaining userLocationSignal:(SSignal *)userLocationSignal; -- (void)configureForStart; -- (void)configureForStopWithMessage:(TGMessage *)message remaining:(SSignal *)remaining; - -@end - -extern NSString *const TGLocationLiveCellKind; -extern const CGFloat TGLocationLiveCellHeight; diff --git a/submodules/LegacyComponents/Sources/TGLocationLiveCell.m b/submodules/LegacyComponents/Sources/TGLocationLiveCell.m deleted file mode 100644 index 9967dff4f5..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationLiveCell.m +++ /dev/null @@ -1,361 +0,0 @@ -#import "TGLocationLiveCell.h" -#import "TGLocationVenueCell.h" - -#import "TGLocationMapViewController.h" -#import "LegacyComponentsInternal.h" -#import "TGFont.h" -#import "TGColor.h" -#import "TGImageUtils.h" -#import "TGDateUtils.h" -#import "TGLocationUtils.h" - -#import "TGUser.h" -#import "TGMessage.h" -#import "TGConversation.h" -#import "TGLocationMediaAttachment.h" - -#import "TGLetteredAvatarView.h" -#import "TGLocationWavesView.h" -#import "TGLocationLiveElapsedView.h" - -NSString *const TGLocationLiveCellKind = @"TGLocationLiveCell"; -const CGFloat TGLocationLiveCellHeight = 68; - -@interface TGLocationLiveCell () -{ - UIView *_highlightView; - - UIImageView *_circleView; - UIImageView *_iconView; - TGLocationWavesView *_wavesView; - TGLetteredAvatarView *_avatarView; - - UILabel *_titleLabel; - UILabel *_subtitleLabel; - TGLocationLiveElapsedView *_elapsedView; - - UIView *_separatorView; - - SMetaDisposable *_locationDisposable; - SMetaDisposable *_remainingDisposable; - - UILongPressGestureRecognizer *_longPressGestureRecognizer; -} -@end - -@implementation TGLocationLiveCell - -- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier -{ - self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; - if (self != nil) - { - self.selectedBackgroundView = [[UIView alloc] init]; - self.selectedBackgroundView.backgroundColor = [UIColor clearColor]; - - _highlightView = [[UIView alloc] initWithFrame:self.bounds]; - _highlightView.alpha = 0.0f; - _highlightView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - _highlightView.backgroundColor = TGSelectionColor(); - _highlightView.userInteractionEnabled = false; - [self.contentView addSubview:_highlightView]; - - _circleView = [[UIImageView alloc] init]; - [self.contentView addSubview:_circleView]; - - _iconView = [[UIImageView alloc] init]; - _iconView.contentMode = UIViewContentModeCenter; - [_circleView addSubview:_iconView]; - - _avatarView = [[TGLetteredAvatarView alloc] init]; - [_avatarView setSingleFontSize:22.0f doubleFontSize:22.0f useBoldFont:false]; - [self.contentView addSubview:_avatarView]; - - _titleLabel = [[UILabel alloc] init]; - _titleLabel = [[UILabel alloc] init]; - _titleLabel.backgroundColor = [UIColor clearColor]; - _titleLabel.font = TGBoldSystemFontOfSize(16.0); - _titleLabel.text = TGLocalized(@"Map.SendMyCurrentLocation"); - _titleLabel.textColor = TGAccentColor(); - [self.contentView addSubview:_titleLabel]; - - _subtitleLabel = [[UILabel alloc] init]; - _subtitleLabel.backgroundColor = [UIColor clearColor]; - _subtitleLabel.font = TGSystemFontOfSize(13); - _subtitleLabel.text = TGLocalized(@"Map.Locating"); - _subtitleLabel.textColor = UIColorRGB(0xa6a6a6); - [self.contentView addSubview:_subtitleLabel]; - - _elapsedView = [[TGLocationLiveElapsedView alloc] init]; - [self.contentView addSubview:_elapsedView]; - - _separatorView = [[UIView alloc] init]; - _separatorView.backgroundColor = TGSeparatorColor(); - [self addSubview:_separatorView]; - - _wavesView = [[TGLocationWavesView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 48.0f, 48.0f)]; - [_circleView addSubview:_wavesView]; - - _longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handlePress:)]; - [self addGestureRecognizer:_longPressGestureRecognizer]; - } - return self; -} - -- (void)dealloc -{ - [_locationDisposable dispose]; - [_wavesView invalidate]; -} - -- (void)setPallete:(TGLocationPallete *)pallete -{ - if (pallete == nil || _pallete == pallete) - return; - - _pallete = pallete; - - self.backgroundColor = pallete.backgroundColor; - _highlightView.backgroundColor = pallete.selectionColor; - _titleLabel.textColor = pallete.accentColor; - _subtitleLabel.textColor = pallete.secondaryTextColor; - _separatorView.backgroundColor = pallete.separatorColor; - _wavesView.color = pallete.iconColor; - [_elapsedView setColor:pallete.accentColor]; -} - -- (void)handlePress:(UILongPressGestureRecognizer *)gestureRecognizer -{ - if (gestureRecognizer.state == UIGestureRecognizerStateBegan) - { - if (self.longPressed != nil) - self.longPressed(); - } -} - -- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated -{ - if (animated) - { - [UIView animateWithDuration:0.2 animations:^ - { - _highlightView.alpha = highlighted ? 1.0f : 0.0f; - _edgeView.alpha = highlighted ? 1.0f : 0.0f; - }]; - } - else - { - _highlightView.alpha = highlighted ? 1.0f : 0.0f; - _edgeView.alpha = highlighted ? 1.0f : 0.0f; - } -} - -- (void)configureWithPeer:(id)peer message:(TGMessage *)message remaining:(SSignal *)remaining userLocationSignal:(SSignal *)userLocationSignal -{ - bool changed = message.mid != _messageId; - _messageId = message.mid; - - _circleView.hidden = true; - _avatarView.hidden = false; - - CGFloat diameter = 48.0f; - - static UIImage *staticPlaceholder = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^ - { - UIGraphicsBeginImageContextWithOptions(CGSizeMake(diameter, diameter), false, 0.0f); - CGContextRef context = UIGraphicsGetCurrentContext(); - - //!placeholder - CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor); - CGContextFillEllipseInRect(context, CGRectMake(0.0f, 0.0f, diameter, diameter)); - CGContextSetStrokeColorWithColor(context, UIColorRGB(0xd9d9d9).CGColor); - CGContextSetLineWidth(context, 1.0f); - CGContextStrokeEllipseInRect(context, CGRectMake(0.5f, 0.5f, diameter - 1.0f, diameter - 1.0f)); - - staticPlaceholder = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - }); - - UIImage *placeholder = _pallete != nil ? _pallete.avatarPlaceholder : staticPlaceholder; - - bool isUser = [peer isKindOfClass:[TGUser class]]; - NSString *avatarUrl = isUser ? ((TGUser *)peer).photoFullUrlSmall : ((TGConversation *)peer).chatPhotoFullSmall; - if (avatarUrl.length != 0) - { - _avatarView.fadeTransitionDuration = 0.3; - if (![avatarUrl isEqualToString:_avatarView.currentUrl]) - [_avatarView loadImage:avatarUrl filter:@"circle:48x48" placeholder:placeholder]; - } - else - { - if (isUser) - { - [_avatarView loadUserPlaceholderWithSize:CGSizeMake(diameter, diameter) uid:((TGUser *)peer).uid firstName:((TGUser *)peer).firstName lastName:((TGUser *)peer).lastName placeholder:placeholder]; - } - else - { - [_avatarView loadGroupPlaceholderWithSize:CGSizeMake(diameter, diameter) conversationId:((TGConversation *)peer).conversationId title:((TGConversation *)peer).chatTitle placeholder:placeholder]; - } - } - - _titleLabel.textColor = _pallete != nil ? _pallete.textColor : [UIColor blackColor]; - _titleLabel.text = isUser ? ((TGUser *)peer).displayName : ((TGConversation *)peer).chatTitle; - - NSString *subtitle = [TGDateUtils stringForRelativeUpdate:[message actualDate]]; - _subtitleLabel.text = subtitle; - - TGLocationMediaAttachment *locationAttachment = message.locationAttachment; - CLLocation *location = [[CLLocation alloc] initWithLatitude:locationAttachment.latitude longitude:locationAttachment.longitude]; - __weak TGLocationLiveCell *weakSelf = self; - if (_locationDisposable == nil) - _locationDisposable = [[SMetaDisposable alloc] init]; - [_locationDisposable setDisposable:[userLocationSignal startWithNext:^(CLLocation *next) - { - __strong TGLocationLiveCell *strongSelf = weakSelf; - if (strongSelf != nil && next != nil) - { - CGFloat distance = [next distanceFromLocation:location]; - NSString *distanceString = [NSString stringWithFormat:TGLocalized(@"Map.DistanceAway"), [TGLocationUtils stringFromDistance:distance]]; - strongSelf->_subtitleLabel.text = [NSString stringWithFormat:@"%@ • %@", subtitle, distanceString]; - } - }]]; - - if (changed) - { - _elapsedView.hidden = false; - - _avatarView.alpha = 1.0f; - [self setNeedsLayout]; - - if (_remainingDisposable == nil) - _remainingDisposable = [[SMetaDisposable alloc] init]; - - [_remainingDisposable setDisposable:[remaining startWithNext:^(NSNumber *next) - { - __strong TGLocationLiveCell *strongSelf = weakSelf; - if (strongSelf != nil) - [strongSelf->_elapsedView setRemaining:next.intValue period:locationAttachment.period]; - } completed:^ - { - __strong TGLocationLiveCell *strongSelf = weakSelf; - if (strongSelf != nil) - { - strongSelf->_elapsedView.hidden = true; - strongSelf->_avatarView.alpha = 0.5f; - [strongSelf setNeedsLayout]; - } - }]]; - } -} - -- (void)configureForStart -{ - _messageId = 0; - - _avatarView.hidden = true; - _circleView.hidden = false; - _elapsedView.hidden = true; - - UIImage *icon = TGComponentsImageNamed(@"LocationMessageLiveIcon"); - if (_pallete != nil) - icon = TGTintedImage(icon, _pallete.iconColor); - - _iconView.image = icon; - [self setCircleColor:_pallete != nil ? _pallete.liveLocationColor : UIColorRGB(0xff6464)]; - - _titleLabel.textColor = _pallete != nil ? _pallete.accentColor : TGAccentColor(); - _titleLabel.text = TGLocalized(@"Map.ShareLiveLocation"); - _subtitleLabel.text = TGLocalized(@"Map.ShareLiveLocationHelp"); - - [_wavesView stop]; - _wavesView.hidden = true; - - [_locationDisposable setDisposable:nil]; - [_remainingDisposable setDisposable:nil]; - - [self setNeedsLayout]; -} - -- (void)configureForStopWithMessage:(TGMessage *)message remaining:(SSignal *)remaining -{ - bool changed = message.mid != _messageId; - _messageId = message.mid; - - _avatarView.hidden = true; - _circleView.hidden = false; - - UIImage *icon = TGComponentsImageNamed(@"LocationMessagePinIcon"); - if (_pallete != nil) - icon = TGTintedImage(icon, _pallete.iconColor); - _iconView.image = icon; - [self setCircleColor:_pallete != nil ? _pallete.liveLocationColor : UIColorRGB(0xff6464)]; - - _titleLabel.textColor = _pallete != nil ? _pallete.destructiveColor : UIColorRGB(0xff3b2f); - _titleLabel.text = TGLocalized(@"Map.StopLiveLocation"); - _subtitleLabel.text = [TGDateUtils stringForRelativeUpdate:[message actualDate]]; - - _wavesView.hidden = false; - _wavesView.color = _pallete != nil ? _pallete.iconColor : [UIColor whiteColor]; - [_wavesView start]; - - [_locationDisposable setDisposable:nil]; - - if (changed) - { - _elapsedView.hidden = false; - [self setNeedsLayout]; - - TGLocationMediaAttachment *locationAttachment = message.locationAttachment; - if (_remainingDisposable == nil) - _remainingDisposable = [[SMetaDisposable alloc] init]; - - __weak TGLocationLiveCell *weakSelf = self; - [_remainingDisposable setDisposable:[remaining startWithNext:^(NSNumber *next) - { - __strong TGLocationLiveCell *strongSelf = weakSelf; - if (strongSelf != nil) - [strongSelf->_elapsedView setRemaining:next.intValue period:locationAttachment.period]; - } completed:^ - { - __strong TGLocationLiveCell *strongSelf = weakSelf; - if (strongSelf != nil) - { - strongSelf->_elapsedView.hidden = true; - [strongSelf setNeedsLayout]; - } - }]]; - } -} - -- (void)setCircleColor:(UIColor *)color -{ - UIImage *circleImage = [TGLocationVenueCell circleImage]; - _circleView.image = TGTintedImage(circleImage, color); -} - -- (void)setSafeInset:(UIEdgeInsets)safeInset -{ - _safeInset = safeInset; - [self setNeedsLayout]; -} - -- (void)layoutSubviews -{ - [super layoutSubviews]; - - _circleView.frame = CGRectMake(12.0f + self.safeInset.left, 12.0f, 48.0f, 48.0f); - _iconView.frame = _circleView.bounds; - _avatarView.frame = _circleView.frame; - - CGFloat padding = 76.0f + self.safeInset.left; - CGFloat separatorThickness = TGScreenPixel; - - _titleLabel.frame = CGRectMake(padding, 14, self.frame.size.width - padding - 14 - (_elapsedView.hidden ? 0.0f : 38.0f) - self.safeInset.right, 20); - _subtitleLabel.frame = CGRectMake(padding, 36, self.frame.size.width - padding - 14 - (_elapsedView.hidden ? 0.0f : 38.0f) - self.safeInset.right, 20); - _separatorView.frame = CGRectMake(padding, self.frame.size.height - separatorThickness, self.frame.size.width - padding, separatorThickness); - _elapsedView.frame = CGRectMake(self.frame.size.width - 30.0f - 15.0f - self.safeInset.right, floor((self.frame.size.height - 30.0f) / 2.0f), 30.0f, 30.0f); -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationLiveElapsedView.m b/submodules/LegacyComponents/Sources/TGLocationLiveElapsedView.m deleted file mode 100644 index ef3633a778..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationLiveElapsedView.m +++ /dev/null @@ -1,101 +0,0 @@ -#import "TGLocationLiveElapsedView.h" - -#import "LegacyComponentsInternal.h" -#import "TGColor.h" -#import "TGFont.h" - -@interface TGLocationLiveElapsedView () -{ - UIColor *_color; - CGFloat _progress; - NSString *_string; -} -@end - -@implementation TGLocationLiveElapsedView - -- (instancetype)initWithFrame:(CGRect)frame -{ - self = [super initWithFrame:frame]; - if (self != nil) - { - _color = TGAccentColor(); - self.backgroundColor = [UIColor clearColor]; - self.contentMode = UIViewContentModeRedraw; - } - return self; -} - -- (void)setColor:(UIColor *)color -{ - _color = color; - [self setNeedsDisplay]; -} - -- (void)setRemaining:(int32_t)remaining period:(int32_t)period; -{ - NSString *string = nil; - int32_t minutes = ceil(remaining / 60.0f); - if (minutes >= 60) - { - int32_t hours = ceil(remaining / 3600.0f); - string = [[NSString alloc] initWithFormat:TGLocalized(@"Map.LiveLocationShortHour"), [[NSString alloc] initWithFormat:@"%d", hours]]; - } - else - { - string = [[NSString alloc] initWithFormat:@"%d", minutes]; - } - _progress = remaining / (CGFloat)period; - if (_progress > 1.0f - FLT_EPSILON) - _progress = 0.999f; - _string = string; - [self setNeedsDisplay]; -} - -- (void)drawRect:(CGRect)rect -{ - CGRect allRect = self.bounds; - CGContextRef context = UIGraphicsGetCurrentContext(); - - CGContextSetFillColorWithColor(context, _color.CGColor); - CGContextSetStrokeColorWithColor(context, _color.CGColor); - CGContextSetLineWidth(context, 1.5f); - CGContextSetLineCap(context, kCGLineCapRound); - CGContextSetLineJoin(context, kCGLineJoinMiter); - CGContextSetMiterLimit(context, 10); - - CGPoint center = CGPointMake(allRect.size.width / 2, allRect.size.height / 2); - CGFloat radius = 13.0f; - - CGContextSetAlpha(context, 0.2f); - CGContextStrokeEllipseInRect(context, CGRectMake(center.x - radius, center.y - radius, radius * 2, radius * 2)); - CGContextSetAlpha(context, 1.0f); - - CGFloat startAngle = -M_PI_2; - CGFloat endAngle = -M_PI_2 + 2 * M_PI * (1.0f - _progress); - - CGMutablePathRef path = CGPathCreateMutable(); - CGPathAddArc(path, NULL, center.x, center.y, radius, startAngle, endAngle, true); - CGContextAddPath(context, path); - CGPathRelease(path); - CGContextStrokePath(context); - - UIFont *font = [TGFont roundedFontOfSize:14.0f]; - if (font == nil) { - font = [UIFont systemFontOfSize:14.0]; - } - NSDictionary *attributes = @{ NSFontAttributeName: font, NSForegroundColorAttributeName: _color }; - CGSize size = iosMajorVersion() >= 7 ? [_string sizeWithAttributes:attributes] : [_string sizeWithFont:attributes[NSFontAttributeName]]; - if (iosMajorVersion() >= 7) - { - [_string drawAtPoint:CGPointMake((allRect.size.width - size.width) / 2.0f, floor((allRect.size.height - size.height) / 2.0f)) withAttributes:attributes]; - } - else - { - CGContextSetFillColorWithColor(context, _color.CGColor); - [_string drawAtPoint:CGPointMake((allRect.size.width - size.width) / 2.0f, floor((allRect.size.height - size.height) / 2.0f)) forWidth:FLT_MAX withFont:font lineBreakMode:NSLineBreakByWordWrapping]; - } -} - -@end - diff --git a/submodules/LegacyComponents/Sources/TGLocationLiveSessionItemView.m b/submodules/LegacyComponents/Sources/TGLocationLiveSessionItemView.m deleted file mode 100644 index 98d3bfc810..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationLiveSessionItemView.m +++ /dev/null @@ -1,127 +0,0 @@ -#import "TGLocationLiveSessionItemView.h" - -#import "LegacyComponentsInternal.h" - -#import "TGUser.h" -#import "TGConversation.h" - -#import "TGLetteredAvatarView.h" -#import "TGLocationLiveElapsedView.h" - -@interface TGLocationLiveSessionItemView () -{ - TGLetteredAvatarView *_avatarView; - TGLocationLiveElapsedView *_elapsedView; - UILabel *_label; - id _disposable; -} -@end - -@implementation TGLocationLiveSessionItemView - -- (instancetype)initWithMessage:(TGMessage *)message peer:(id)peer remaining:(SSignal *)remaining action:(void (^)(void))action -{ - bool isUser = [peer isKindOfClass:[TGUser class]]; - NSString *title = isUser ? ((TGUser *)peer).displayName : ((TGConversation *)peer).chatTitle; - self = [super initWithTitle:@"" type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:action]; - if (self != nil) - { - _label = [[UILabel alloc] init]; - _label.backgroundColor = [UIColor clearColor]; - _label.font = _button.titleLabel.font; - _label.textColor = [UIColor blackColor]; - _label.text = title; - [_label sizeToFit]; - [_button addSubview:_label]; - - _avatarView = [[TGLetteredAvatarView alloc] init]; - [_avatarView setSingleFontSize:18.0f doubleFontSize:18.0f useBoldFont:false]; - [self addSubview:_avatarView]; - - CGFloat diameter = 36.0f; - - static UIImage *placeholder = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^ - { - UIGraphicsBeginImageContextWithOptions(CGSizeMake(diameter, diameter), false, 0.0f); - CGContextRef context = UIGraphicsGetCurrentContext(); - - //!placeholder - CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor); - CGContextFillEllipseInRect(context, CGRectMake(0.0f, 0.0f, diameter, diameter)); - CGContextSetStrokeColorWithColor(context, UIColorRGB(0xd9d9d9).CGColor); - CGContextSetLineWidth(context, 1.0f); - CGContextStrokeEllipseInRect(context, CGRectMake(0.5f, 0.5f, diameter - 1.0f, diameter - 1.0f)); - - placeholder = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - }); - - NSString *avatarUrl = isUser ? ((TGUser *)peer).photoFullUrlSmall : ((TGConversation *)peer).chatPhotoFullSmall; - if (avatarUrl.length != 0) - { - _avatarView.fadeTransitionDuration = 0.3; - if (![avatarUrl isEqualToString:_avatarView.currentUrl]) - [_avatarView loadImage:avatarUrl filter:@"circle:36x36" placeholder:placeholder]; - } - else - { - if (isUser) - { - [_avatarView loadUserPlaceholderWithSize:CGSizeMake(diameter, diameter) uid:((TGUser *)peer).uid firstName:((TGUser *)peer).firstName lastName:((TGUser *)peer).lastName placeholder:placeholder]; - } - else - { - [_avatarView loadGroupPlaceholderWithSize:CGSizeMake(diameter, diameter) conversationId:((TGConversation *)peer).conversationId title:((TGConversation *)peer).chatTitle placeholder:placeholder]; - } - } - - _elapsedView = [[TGLocationLiveElapsedView alloc] init]; - [self addSubview:_elapsedView]; - - TGLocationMediaAttachment *location = nil; - for (TGMediaAttachment *attachment in message.mediaAttachments) - { - if (attachment.type == TGLocationMediaAttachmentType) - { - location = (TGLocationMediaAttachment *)attachment; - break; - } - } - - __weak TGLocationLiveSessionItemView *weakSelf = self; - _disposable = [remaining startWithNext:^(NSNumber *next) - { - __strong TGLocationLiveSessionItemView *strongSelf = weakSelf; - if (strongSelf != nil) - [strongSelf->_elapsedView setRemaining:next.intValue period:location.period]; - }]; - } - return self; -} - -- (void)dealloc -{ - [_disposable dispose]; -} - -- (void)setPallete:(TGMenuSheetPallete *)pallete -{ - [super setPallete:pallete]; - - _label.textColor = pallete.textColor; - [_elapsedView setColor:pallete.accentColor]; -} - -- (void)layoutSubviews -{ - [super layoutSubviews]; - - _label.frame = CGRectMake(74.0f, (self.frame.size.height - ceil(_label.frame.size.height)) / 2.0f, self.frame.size.width - 74.0f - 52.0f - 10.0f, ceil(_label.frame.size.height)); - _avatarView.frame = CGRectMake(23.0f, 11.0f, 36.0f, 36.0f); - _elapsedView.frame = CGRectMake(self.frame.size.width - 30.0f - 22.0f, round((self.frame.size.height - 30.0f) / 2.0f), 30.0f, 30.0f); -} - -@end - diff --git a/submodules/LegacyComponents/Sources/TGLocationMapModeControl.h b/submodules/LegacyComponents/Sources/TGLocationMapModeControl.h deleted file mode 100644 index 52d228e358..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationMapModeControl.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface TGLocationMapModeControl : UISegmentedControl - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationMapModeControl.m b/submodules/LegacyComponents/Sources/TGLocationMapModeControl.m deleted file mode 100644 index 24e5499617..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationMapModeControl.m +++ /dev/null @@ -1,27 +0,0 @@ -#import "TGLocationMapModeControl.h" - -#import "LegacyComponentsInternal.h" -#import "TGFont.h" -#import "TGColor.h" - -@implementation TGLocationMapModeControl - -- (instancetype)init -{ - self = [super initWithItems:@[TGLocalized(@"Map.Map"), TGLocalized(@"Map.Satellite"), TGLocalized(@"Map.Hybrid")]]; - if (self != nil) - { - [self setBackgroundImage:TGComponentsImageNamed(@"ModernSegmentedControlBackground.png") forState:UIControlStateNormal barMetrics:UIBarMetricsDefault]; - [self setBackgroundImage:TGComponentsImageNamed(@"ModernSegmentedControlSelected.png") forState:UIControlStateSelected barMetrics:UIBarMetricsDefault]; - [self setBackgroundImage:TGComponentsImageNamed(@"ModernSegmentedControlSelected.png") forState:UIControlStateSelected | UIControlStateHighlighted barMetrics:UIBarMetricsDefault]; - [self setBackgroundImage:TGComponentsImageNamed(@"ModernSegmentedControlHighlighted.png") forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault]; - UIImage *dividerImage = TGComponentsImageNamed(@"ModernSegmentedControlDivider.png"); - [self setDividerImage:dividerImage forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault]; - - [self setTitleTextAttributes:@{UITextAttributeTextColor: TGAccentColor(), UITextAttributeTextShadowColor: [UIColor clearColor], UITextAttributeFont: TGSystemFontOfSize(13)} forState:UIControlStateNormal]; - [self setTitleTextAttributes:@{UITextAttributeTextColor: [UIColor whiteColor], UITextAttributeTextShadowColor: [UIColor clearColor], UITextAttributeFont: TGSystemFontOfSize(13)} forState:UIControlStateSelected]; - } - return self; -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationMapView.h b/submodules/LegacyComponents/Sources/TGLocationMapView.h deleted file mode 100644 index 46786a72e4..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationMapView.h +++ /dev/null @@ -1,17 +0,0 @@ -#import - -@interface TGLocationMapView : MKMapView - -@property (nonatomic, copy) void(^singleTap)(void); - -@property (nonatomic, copy) bool(^customAnnotationTap)(CGPoint); - -@property (nonatomic, assign) bool longPressAsTapEnabled; -@property (nonatomic, assign) bool tapEnabled; -@property (nonatomic, assign) bool manipulationEnabled; - -@property (nonatomic, assign) bool allowAnnotationSelectionChanges; - -@property (nonatomic, assign) UIEdgeInsets compassInsets; - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationMapView.m b/submodules/LegacyComponents/Sources/TGLocationMapView.m deleted file mode 100644 index 754c90e311..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationMapView.m +++ /dev/null @@ -1,114 +0,0 @@ -#import "TGLocationMapView.h" - -@interface TGLocationMapView () -{ - UITapGestureRecognizer *_tapGestureRecognizer; - UILongPressGestureRecognizer *_longPressGestureRecognizer; -} -@end - -@implementation TGLocationMapView - -- (instancetype)initWithFrame:(CGRect)frame -{ - self = [super initWithFrame:frame]; - if (self != nil) - { - _manipulationEnabled = true; - _allowAnnotationSelectionChanges = true; - - _tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tg_handleTap:)]; - _tapGestureRecognizer.numberOfTapsRequired = 1; - _tapGestureRecognizer.numberOfTouchesRequired = 1; - [self addGestureRecognizer:_tapGestureRecognizer]; - - _longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(tg_handleLongPress:)]; - _longPressGestureRecognizer.enabled = false; - _longPressGestureRecognizer.minimumPressDuration = 0.2f; - [self addGestureRecognizer:_longPressGestureRecognizer]; - } - return self; -} - -- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer -{ - NSString *viewClass = NSStringFromClass([gestureRecognizer.view class]); - if ([viewClass rangeOfString:@"Compass"].location != NSNotFound) - return true; - - if (self.customAnnotationTap && self.customAnnotationTap([gestureRecognizer locationInView:self])) - return false; - - return self.allowAnnotationSelectionChanges; -} - -- (bool)tapEnabled -{ - return _tapGestureRecognizer.enabled; -} - -- (void)setTapEnabled:(bool)enabled -{ - _tapGestureRecognizer.enabled = enabled; -} - -- (bool)longPressAsTapEnabled -{ - return _longPressGestureRecognizer.enabled; -} - -- (void)setLongPressAsTapEnabled:(bool)enabled -{ - _longPressGestureRecognizer.enabled = enabled; -} - -- (void)tg_handleTap:(UITapGestureRecognizer *)__unused gestureRecognizer -{ - if (self.singleTap != nil) - self.singleTap(); -} - -- (void)tg_handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer -{ - if (gestureRecognizer.state == UIGestureRecognizerStateBegan) - { - if (self.singleTap != nil) - self.singleTap(); - } -} - -- (void)setManipulationEnabled:(bool)enabled -{ - _manipulationEnabled = enabled; - - self.scrollEnabled = enabled; - self.zoomEnabled = enabled; - if ([self respondsToSelector:@selector(setRotateEnabled:)]) - self.rotateEnabled = enabled; - if ([self respondsToSelector:@selector(setPitchEnabled:)]) - self.pitchEnabled = enabled; -} - -- (void)setCompassInsets:(UIEdgeInsets)compassInsets -{ - _compassInsets = compassInsets; - [self setNeedsLayout]; -} - -- (void)layoutSubviews -{ - [super layoutSubviews]; - - if (UIEdgeInsetsEqualToEdgeInsets(self.compassInsets, UIEdgeInsetsZero)) - return; - - for (UIView *view in self.subviews) - { - if ([NSStringFromClass([view class]) rangeOfString:@"Compass"].location != NSNotFound) - { - view.frame = CGRectMake(self.frame.size.width - self.compassInsets.right - view.frame.size.width, self.compassInsets.top, view.frame.size.width, view.frame.size.height); - } - } -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationMapViewController.m b/submodules/LegacyComponents/Sources/TGLocationMapViewController.m deleted file mode 100644 index 3a02f3c329..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationMapViewController.m +++ /dev/null @@ -1,642 +0,0 @@ -#import "TGLocationMapViewController.h" - -#import "Freedom.h" -#import "LegacyComponentsInternal.h" -#import "TGColor.h" -#import "TGImageUtils.h" -#import "TGFont.h" -#import "TGLocationUtils.h" - -#import "TGUser.h" -#import "TGLocationMapView.h" -#import "TGLocationOptionsView.h" - -#import -#import "TGSearchBar.h" - -const MKCoordinateSpan TGLocationDefaultSpan = { 0.008, 0.008 }; -const CGFloat TGLocationMapClipHeight = 1600.0f; -const CGFloat TGLocationMapInset = 100.0f; - -@interface TGLocationTableView : UITableView - -@end - -@interface TGLocationMapViewController () -{ - id _context; - - UIView *_mapClipView; - - SVariable *_userLocation; - SPipe *_userLocationPipe; - - MKPolygon *_darkPolygon; - - void (^_openLiveLocationMenuBlock)(void); -} -@end - -@implementation TGLocationMapViewController - -- (instancetype)initWithContext:(id)context -{ - self = [super initWithContext:context]; - if (self != nil) - { - _context = context; - _userLocationPipe = [[SPipe alloc] init]; - - _locationManager = [[CLLocationManager alloc] init]; - _locationManager.delegate = self; - - _userLocation = [[SVariable alloc] init]; - [_userLocation set:[[SSignal single:nil] then:_userLocationPipe.signalProducer()]]; - } - return self; -} - -- (void)dealloc -{ - _locationManager.delegate = nil; - _mapView.delegate = nil; - _tableView.dataSource = nil; - _tableView.delegate = nil; -} - -- (void)setPallete:(TGLocationPallete *)pallete { - _pallete = pallete; - if ([self isViewLoaded]) { - self.view.backgroundColor = pallete.backgroundColor; - } -} - -- (void)loadView -{ - [super loadView]; - - self.view.backgroundColor = self.pallete.backgroundColor; - self.alwaysUseTallNavigationBarHeight = true; - - _tableView = [[TGLocationTableView alloc] initWithFrame:self.view.bounds]; - if (iosMajorVersion() >= 11) - _tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; - _tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - _tableView.backgroundColor = self.view.backgroundColor; - _tableView.dataSource = self; - _tableView.delegate = self; - _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; - _tableView.delaysContentTouches = false; - _tableView.canCancelContentTouches = true; - [self.view addSubview:_tableView]; - - _activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; - if (self.pallete != nil) - _activityIndicator.color = self.pallete.secondaryTextColor; - _activityIndicator.userInteractionEnabled = false; - [_tableView addSubview:_activityIndicator]; - - _messageLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 20)]; - _messageLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth; - _messageLabel.backgroundColor = [UIColor clearColor]; - _messageLabel.font = TGSystemFontOfSize(16); - _messageLabel.hidden = true; - _messageLabel.textAlignment = NSTextAlignmentCenter; - _messageLabel.textColor = self.pallete != nil ? self.pallete.secondaryTextColor : UIColorRGB(0x8e8e93); - _messageLabel.userInteractionEnabled = false; - [_tableView addSubview:_messageLabel]; - - _tableViewTopInset = [self mapHeight]; - _mapClipView = [[UIView alloc] initWithFrame:CGRectMake(0, -TGLocationMapClipHeight, self.view.frame.size.width, TGLocationMapClipHeight + 10.0f)]; - _mapClipView.autoresizingMask = UIViewAutoresizingFlexibleWidth; - _mapClipView.clipsToBounds = true; - [_tableView addSubview:_mapClipView]; - - _mapViewWrapper = [[UIView alloc] initWithFrame:CGRectMake(0, TGLocationMapClipHeight - _tableViewTopInset, self.view.frame.size.width, _tableViewTopInset + 10.0f)]; - _mapViewWrapper.autoresizingMask = UIViewAutoresizingFlexibleWidth; - [_mapClipView addSubview:_mapViewWrapper]; - - __weak TGLocationMapViewController *weakSelf = self; - _mapView = [[TGLocationMapView alloc] initWithFrame:CGRectMake(0, -TGLocationMapInset, self.view.frame.size.width, _tableViewTopInset + 2 * TGLocationMapInset + 10.0f)]; - _mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth; - _mapView.delegate = self; - _mapView.showsUserLocation = true; - [_mapViewWrapper addSubview:_mapView]; - - _optionsView = [[TGLocationOptionsView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 45.0f, 90.0f)]; - if (self.pallete != nil) - _optionsView.pallete = self.pallete; - _optionsView.mapModeChanged = ^(NSInteger mapMode) { - __strong TGLocationMapViewController *strongSelf = weakSelf; - if (strongSelf != nil) - [strongSelf->_mapView setMapType:(MKMapType)mapMode]; - - }; - _optionsView.trackModePressed = ^{ - __strong TGLocationMapViewController *strongSelf = weakSelf; - if (strongSelf != nil) - [strongSelf userLocationButtonPressed]; - }; - [self.view addSubview:_optionsView]; - - UIImage *edgeImage = TGComponentsImageNamed(@"LocationPanelEdge"); - UIImage *edgeHighlightImage = TGComponentsImageNamed(@"LocationPanelEdge_Highlighted"); - if (self.pallete != nil) - { - UIGraphicsBeginImageContextWithOptions(edgeImage.size, false, 0.0f); - [edgeImage drawAtPoint:CGPointZero]; - [TGTintedImage(edgeHighlightImage, self.pallete.backgroundColor) drawAtPoint:CGPointZero]; - - edgeImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - } - - _edgeView = [[UIImageView alloc] initWithImage:[edgeImage resizableImageWithCapInsets:UIEdgeInsetsMake(0.0f, 10.0f, 0.0f, 10.0f)]]; - _edgeView.frame = CGRectMake(0.0f, _tableViewTopInset - 10.0f, _mapViewWrapper.frame.size.width, _edgeView.frame.size.height); - [_mapViewWrapper addSubview:_edgeView]; - - if (self.pallete != nil) - edgeHighlightImage = TGTintedImage(edgeHighlightImage, self.pallete.selectionColor); - - _edgeHighlightView = [[UIImageView alloc] initWithImage:[edgeHighlightImage resizableImageWithCapInsets:UIEdgeInsetsMake(0.0f, 10.0f, 0.0f, 10.0f)]]; - _edgeHighlightView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - _edgeHighlightView.frame = _edgeView.bounds; - _edgeHighlightView.alpha = 0.0f; - _edgeHighlightView.image = [edgeHighlightImage resizableImageWithCapInsets:UIEdgeInsetsMake(0.0f, 10.0f, 0.0f, 10.0f)]; - [_edgeView addSubview:_edgeHighlightView]; - - self.scrollViewsForAutomaticInsetsAdjustment = @[ _tableView ]; - - if (![self _updateControllerInset:false]) - [self controllerInsetUpdated:UIEdgeInsetsZero]; -} - -- (void)layoutControllerForSize:(CGSize)size duration:(NSTimeInterval)duration -{ - [super layoutControllerForSize:size duration:duration]; - - if (!self.isViewLoaded) - return; - - [self updateMapHeightAnimated:false]; - _optionsView.frame = CGRectMake(self.view.bounds.size.width - 45.0f - 6.0f - self.controllerSafeAreaInset.right, 56.0f + 6.0f, 45.0f, 90.0f); - _tableView.contentOffset = CGPointMake(0.0f, -_tableViewTopInset - self.controllerInset.top); -} - -- (void)setOptionsViewHidden:(bool)hidden -{ - if (_optionsView.userInteractionEnabled == !hidden) - return; - - _optionsView.userInteractionEnabled = !hidden; - [UIView animateWithDuration:0.15 animations:^ - { - _optionsView.alpha = hidden ? 0.0f : 1.0f; - }]; -} - -- (void)userLocationButtonPressed -{ - -} - -- (bool)hasUserLocation -{ - return (_mapView.userLocation != nil && _mapView.userLocation.location != nil); -} - -- (void)updateLocationAvailability -{ - bool locationAvailable = [self hasUserLocation] || _locationServicesDisabled; - [_optionsView setLocationAvailable:locationAvailable animated:true]; -} - -- (void)scrollViewDidScroll:(UIScrollView *)scrollView -{ - if (scrollView == _tableView) - { - CGFloat offset = scrollView.contentInset.top + scrollView.contentOffset.y; - CGFloat mapOffset = MIN(offset, [self mapHeight]); - _mapView.frame = CGRectMake(_mapView.frame.origin.x, -TGLocationMapInset + mapOffset / 2, _mapView.frame.size.width, _mapView.frame.size.height); - - [self setOptionsViewHidden:(scrollView.contentOffset.y > -180.0f)]; - - CGFloat additionalScrollInset = _edgeView.frame.size.height / 2.0f; - if (scrollView.contentOffset.y < -scrollView.contentInset.top) - additionalScrollInset += -scrollView.contentInset.top - scrollView.contentOffset.y; - - scrollView.scrollIndicatorInsets = UIEdgeInsetsMake(self.controllerScrollInset.top + _tableViewTopInset + additionalScrollInset, 0.0f, 0.0f, 0.0f); - } -} - -- (void)_autoAdjustInsetsForScrollView:(UIScrollView *)scrollView previousInset:(UIEdgeInsets)previousInset -{ - CGPoint contentOffset = scrollView.contentOffset; - - UIEdgeInsets controllerInset = self.controllerInset; - controllerInset.top += _tableViewTopInset; - controllerInset.bottom += _tableViewBottomInset; - - UIEdgeInsets scrollInset = self.controllerScrollInset; - scrollInset.top += _tableViewTopInset; - - scrollView.contentInset = controllerInset; - scrollView.scrollIndicatorInsets = scrollInset; - - if (!UIEdgeInsetsEqualToEdgeInsets(previousInset, UIEdgeInsetsZero)) - { - CGFloat maxOffset = scrollView.contentSize.height - (scrollView.frame.size.height - controllerInset.bottom); - - if (![self shouldAdjustScrollViewInsetsForInversedLayout]) - contentOffset.y += previousInset.top - controllerInset.top; - - contentOffset.y = MAX(-controllerInset.top, MIN(contentOffset.y, maxOffset)); - [scrollView setContentOffset:contentOffset animated:false]; - } - else if (contentOffset.y < controllerInset.top) - { - contentOffset.y = -controllerInset.top; - [scrollView setContentOffset:contentOffset animated:false]; - } - - _optionsView.frame = CGRectMake(self.view.bounds.size.width - 45.0f - 6.0f, 56.0f + 6.0f, 45.0f, 90.0f); -} - -- (NSInteger)tableView:(UITableView *)__unused tableView numberOfRowsInSection:(NSInteger)__unused section -{ - return 0; -} - -- (UITableViewCell *)tableView:(UITableView *)__unused tableView cellForRowAtIndexPath:(NSIndexPath *)__unused indexPath -{ - return nil; -} - -- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath -{ -} - -- (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath -{ -} - -- (void)updateInsets -{ - UIEdgeInsets previousInset = _tableView.contentInset; - - CGPoint previousOffset = _tableView.contentOffset; - UIEdgeInsets controllerInset = self.controllerInset; - controllerInset.top += _tableViewTopInset; - controllerInset.bottom += _tableViewBottomInset; - _tableView.contentInset = controllerInset; - - if (previousInset.bottom > FLT_EPSILON) - _tableView.contentOffset = previousOffset; -} - -- (void)updateMapHeightAnimated:(bool)animated -{ - void (^changeBlock)(void) = ^ - { - _tableViewTopInset = [self mapHeight]; - - _mapViewWrapper.frame = CGRectMake(0, TGLocationMapClipHeight - _tableViewTopInset, self.view.frame.size.width, _tableViewTopInset + 10.0f); - _mapView.frame = CGRectMake(0, -TGLocationMapInset, self.view.frame.size.width, _tableViewTopInset + 2 * TGLocationMapInset + 10.0f); - _edgeView.frame = CGRectMake(0.0f, _tableViewTopInset - 10.0f, _mapViewWrapper.frame.size.width, _edgeView.frame.size.height); - - [self updateInsets]; - }; - - if (animated) - { - [UIView animateWithDuration:0.3 delay:0.0 options:7 << 16 animations:^ - { - changeBlock(); - } completion:nil]; - } - else - { - changeBlock(); - } -} - -- (CGFloat)mapHeight -{ - return self.view.frame.size.height - [self visibleContentHeight] - self.controllerInset.top; -} - -- (CGFloat)visibleContentHeight -{ - return 0.0f; -} - -- (CGFloat)safeAreaInsetBottom { - return MAX(self.context.safeAreaInset.bottom, self.controllerSafeAreaInset.bottom); -} - -#pragma mark - - -- (void)setMapCenterCoordinate:(CLLocationCoordinate2D)coordinate offset:(CGPoint)offset animated:(bool)animated -{ - [self setMapCenterCoordinate:coordinate span:TGLocationDefaultSpan offset:offset animated:animated]; -} - -- (void)setMapCenterCoordinate:(CLLocationCoordinate2D)coordinate span:(MKCoordinateSpan)span offset:(CGPoint)offset animated:(bool)animated -{ - @try - { - MKCoordinateRegion region = MKCoordinateRegionMake(coordinate, span); - if (!CGPointEqualToPoint(offset, CGPointZero)) - { - MKMapRect mapRect = [TGLocationUtils MKMapRectForCoordinateRegion:region]; - [_mapView setVisibleMapRect:mapRect edgePadding:UIEdgeInsetsMake(offset.y, offset.x, 0, 0) animated:animated]; - } - else - { - [_mapView setRegion:region animated:animated]; - } - } - @catch (NSException *exception) - { - TGLegacyLog(@"ERROR: failed to set location picker map region with exception: %@", exception); - } -} - -#pragma mark - - -- (UIView *)locationMapView -{ - return _mapView; -} - -- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id)overlay -{ - if (overlay == _darkPolygon) - { - MKPolygonRenderer *renderer = [[MKPolygonRenderer alloc] initWithPolygon:overlay]; - renderer.fillColor = [[UIColor blackColor] colorWithAlphaComponent:0.3f]; - return renderer; - } - - return nil; -} - -- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id )overlay -{ - if ([overlay isKindOfClass:[MKPolygon class]]) - { - MKPolygonView *overlayView = [[MKPolygonView alloc] initWithPolygon:overlay]; - overlayView.fillColor = [[UIColor blackColor] colorWithAlphaComponent:0.3f]; - return overlayView; - } - - return nil; -} - -- (void)mapView:(MKMapView *)__unused mapView didUpdateUserLocation:(MKUserLocation *)userLocation -{ - userLocation.title = @""; - - _locationServicesDisabled = false; - - if (userLocation.location != nil) - _userLocationPipe.sink(userLocation.location); - - [self updateLocationAvailability]; -} - -- (void)mapView:(MKMapView *)__unused mapView didFailToLocateUserWithError:(NSError *)__unused error -{ - if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusRestricted) - { - _userLocationPipe.sink(nil); - _locationServicesDisabled = true; - [self updateLocationAvailability]; - } -} - -- (bool)locationServicesDisabled -{ - return _locationServicesDisabled; -} - -- (SSignal *)userLocationSignal -{ - return [_userLocation signal]; -} - -- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status -{ - if (_openLiveLocationMenuBlock != nil) - { - if (status == kCLAuthorizationStatusAuthorizedAlways) - _openLiveLocationMenuBlock(); - - _openLiveLocationMenuBlock = nil; - } -} - -- (CGRect)_liveLocationMenuSourceRect -{ - return CGRectZero; -} - -- (void)_willStartOwnLiveLocation -{ - -} - -- (void)dismissLiveLocationMenu:(TGMenuSheetController *)controller doNotRemove:(bool)doNotRemove -{ - [self _willStartOwnLiveLocation]; - - if (!doNotRemove) - { - [controller dismissAnimated:true]; - } - else - { - [controller setDimViewHidden:true animated:true]; - [controller removeFromParentViewController]; - } -} - -- (void)_presentLiveLocationMenu:(CLLocationCoordinate2D)coordinate dismissOnCompletion:(bool)dismissOnCompletion -{ - void (^block)(void) = ^ - { - __weak TGLocationMapViewController *weakSelf = self; - CGRect (^sourceRect)(void) = ^CGRect - { - __strong TGLocationMapViewController *strongSelf = weakSelf; - if (strongSelf == nil) - return CGRectZero; - - return [strongSelf _liveLocationMenuSourceRect]; - }; - - TGMenuSheetController *controller = [[TGMenuSheetController alloc] initWithContext:_context dark:false]; - controller.dismissesByOutsideTap = true; - controller.hasSwipeGesture = true; - controller.narrowInLandscape = true; - controller.sourceRect = sourceRect; - - NSMutableArray *itemViews = [[NSMutableArray alloc] init]; - - NSString *title = TGLocalized(@"Map.LiveLocationGroupDescription"); - if ([self.receivingPeer isKindOfClass:[TGUser class]]) - title = [NSString stringWithFormat:TGLocalized(@"Map.LiveLocationPrivateDescription"), [(TGUser *)self.receivingPeer displayFirstName]]; - - TGMenuSheetTitleItemView *titleItem = [[TGMenuSheetTitleItemView alloc] initWithTitle:nil subtitle:title]; - [itemViews addObject:titleItem]; - - __weak TGMenuSheetController *weakController = controller; - TGMenuSheetButtonItemView *for15MinutesItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Map.LiveLocationFor15Minutes") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^ - { - __strong TGLocationMapViewController *strongSelf = weakSelf; - if (strongSelf == nil) - return; - - __strong TGMenuSheetController *strongController = weakController; - if (strongController == nil) - return; - - if (strongSelf.liveLocationStarted != nil) - strongSelf.liveLocationStarted(coordinate, 15 * 60); - - [strongSelf dismissLiveLocationMenu:strongController doNotRemove:!dismissOnCompletion]; - }]; - [itemViews addObject:for15MinutesItem]; - - TGMenuSheetButtonItemView *for1HourItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Map.LiveLocationFor1Hour") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^ - { - __strong TGLocationMapViewController *strongSelf = weakSelf; - if (strongSelf == nil) - return; - - __strong TGMenuSheetController *strongController = weakController; - if (strongController == nil) - return; - - if (strongSelf.liveLocationStarted != nil) - strongSelf.liveLocationStarted(coordinate, 60 * 60 - 1); - - [strongSelf dismissLiveLocationMenu:strongController doNotRemove:!dismissOnCompletion]; - }]; - [itemViews addObject:for1HourItem]; - - TGMenuSheetButtonItemView *for8HoursItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Map.LiveLocationFor8Hours") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^ - { - __strong TGLocationMapViewController *strongSelf = weakSelf; - if (strongSelf == nil) - return; - - __strong TGMenuSheetController *strongController = weakController; - if (strongController == nil) - return; - - if (strongSelf.liveLocationStarted != nil) - strongSelf.liveLocationStarted(coordinate, 8 * 60 * 60); - - [strongSelf dismissLiveLocationMenu:strongController doNotRemove:!dismissOnCompletion]; - }]; - [itemViews addObject:for8HoursItem]; - - TGMenuSheetButtonItemView *cancelItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel fontSize:20.0 action:^ - { - __strong TGMenuSheetController *strongController = weakController; - if (strongController == nil) - return; - - [strongController dismissAnimated:true manual:true]; - }]; - [itemViews addObject:cancelItem]; - - [controller setItemViews:itemViews]; - [controller presentInViewController:self sourceView:self.view animated:true]; - }; - - void (^errorBlock)(void) = ^ - { - [[[LegacyComponentsGlobals provider] accessChecker] checkLocationAuthorizationStatusForIntent:TGLocationAccessIntentLiveLocation alertDismissComlpetion:nil]; - }; - - if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedAlways && [CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedWhenInUse) - { - errorBlock(); - } - else - { - if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedAlways) - { - block(); - } - else - { - if (![TGLocationUtils requestAlwaysUserLocationAuthorizationWithLocationManager:_locationManager]) - errorBlock(); - else - _openLiveLocationMenuBlock = [block copy]; - } - } -} - -@end - - -@implementation TGLocationTableView - -- (BOOL)touchesShouldCancelInContentView:(UIView *)__unused view -{ - return true; -} - -static void TGLocationTableViewAdjustContentOffsetIfNecessary(__unused id self, __unused SEL _cmd) -{ -} - -+ (void)initialize -{ - static bool initialized = false; - if (!initialized) - { - initialized = true; - - FreedomDecoration instanceDecorations[] = - { - { .name = 0x584ab24eU, - .imp = (IMP)&TGLocationTableViewAdjustContentOffsetIfNecessary, - .newIdentifier = FreedomIdentifierEmpty, - .newEncoding = FreedomIdentifierEmpty - } - }; - - freedomClassAutoDecorate(0x5bfec194, NULL, 0, instanceDecorations, sizeof(instanceDecorations) / sizeof(instanceDecorations[0])); - } -} - -@end - -@implementation TGLocationPallete - -+ (instancetype)palleteWithBackgroundColor:(UIColor *)backgroundColor selectionColor:(UIColor *)selectionColor separatorColor:(UIColor *)separatorColor textColor:(UIColor *)textColor secondaryTextColor:(UIColor *)secondaryTextColor accentColor:(UIColor *)accentColor destructiveColor:(UIColor *)destructiveColor locationColor:(UIColor *)locationColor liveLocationColor:(UIColor *)liveLocationColor iconColor:(UIColor *)iconColor sectionHeaderBackgroundColor:(UIColor *)sectionHeaderBackgroundColor sectionHeaderTextColor:(UIColor *)sectionHeaderTextColor searchBarPallete:(TGSearchBarPallete *)searchBarPallete avatarPlaceholder:(UIImage *)avatarPlaceholder -{ - TGLocationPallete *pallete = [[TGLocationPallete alloc] init]; - pallete->_backgroundColor = backgroundColor; - pallete->_selectionColor = selectionColor; - pallete->_separatorColor = separatorColor; - pallete->_textColor = textColor; - pallete->_secondaryTextColor = secondaryTextColor; - pallete->_accentColor = accentColor; - pallete->_destructiveColor = destructiveColor; - pallete->_locationColor = locationColor; - pallete->_liveLocationColor = liveLocationColor; - pallete->_iconColor = iconColor; - pallete->_sectionHeaderBackgroundColor = sectionHeaderBackgroundColor; - pallete->_sectionHeaderTextColor = sectionHeaderTextColor; - pallete->_searchBarPallete = searchBarPallete; - pallete->_avatarPlaceholder = avatarPlaceholder; - return pallete; -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationOptionsView.h b/submodules/LegacyComponents/Sources/TGLocationOptionsView.h deleted file mode 100644 index 5fc7d6a7c4..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationOptionsView.h +++ /dev/null @@ -1,15 +0,0 @@ -#import "TGLocationTrackingButton.h" - -@class TGLocationPallete; - -@interface TGLocationOptionsView : UIView - -@property (nonatomic, strong) TGLocationPallete *pallete; -@property (nonatomic, copy) void (^mapModeChanged)(NSInteger); -@property (nonatomic, copy) void (^trackModePressed)(void); - -- (void)setTrackingMode:(TGLocationTrackingMode)trackingMode animated:(bool)animated; -- (void)setLocationAvailable:(bool)available animated:(bool)animated; -- (void)setMapModeControlHidden:(bool)hidden animated:(bool)animated; - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationOptionsView.m b/submodules/LegacyComponents/Sources/TGLocationOptionsView.m deleted file mode 100644 index 3628d8c094..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationOptionsView.m +++ /dev/null @@ -1,213 +0,0 @@ -#import "TGLocationOptionsView.h" - -#import "TGFont.h" - -#import "TGModernButton.h" -#import "TGLocationMapModeControl.h" - -#import "TGLocationMapViewController.h" -#import "TGSearchBar.h" - -#import "LegacyComponentsInternal.h" -#import "TGImageUtils.h" - -@interface TGLocationOptionsView () -{ - UIImageView *_backgroundView; - TGModernButton *_mapModeButton; - UIView *_mapModeClipView; - UIView *_mapModeBackgroundView; - TGLocationMapModeControl *_mapModeControl; - TGLocationTrackingButton *_trackButton; - UIView *_separatorView; -} -@end - -@implementation TGLocationOptionsView - -- (instancetype)initWithFrame:(CGRect)frame -{ - self = [super initWithFrame:frame]; - if (self != nil) - { - _mapModeClipView = [[UIView alloc] init]; - _mapModeClipView.clipsToBounds = true; - [self addSubview:_mapModeClipView]; - - _backgroundView = [[UIImageView alloc] init]; - _backgroundView.image = [TGComponentsImageNamed(@"LocationTopPanel") resizableImageWithCapInsets:UIEdgeInsetsMake(15.0f, 15.0f, 18.0f, 15.0f)]; - [self addSubview:_backgroundView]; - - UIView *mapModeBackgroundView = nil; - if (iosMajorVersion() >= 8) - { - _mapModeBackgroundView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight]]; - mapModeBackgroundView = ((UIVisualEffectView *)_mapModeBackgroundView).contentView; - } - else - { - _mapModeBackgroundView = [[UIView alloc] init]; - _mapModeBackgroundView.backgroundColor = [UIColor whiteColor]; - mapModeBackgroundView = _mapModeBackgroundView; - } - _mapModeBackgroundView.clipsToBounds = true; - _mapModeBackgroundView.layer.cornerRadius = 4.0f; - _mapModeBackgroundView.alpha = 0.0f; - _mapModeBackgroundView.userInteractionEnabled = false; - _mapModeBackgroundView.hidden = true; - [_mapModeClipView addSubview:_mapModeBackgroundView]; - - _mapModeControl = [[TGLocationMapModeControl alloc] init]; - _mapModeControl.selectedSegmentIndex = 0; - [_mapModeControl addTarget:self action:@selector(modeChanged:) forControlEvents:UIControlEventValueChanged]; - [mapModeBackgroundView addSubview:_mapModeControl]; - - _mapModeButton = [[TGModernButton alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 45.0f, 45.0f)]; - _mapModeButton.adjustsImageWhenHighlighted = false; - [_mapModeButton setImage:TGComponentsImageNamed(@"LocationInfo.png") forState:UIControlStateNormal]; - [_mapModeButton setImage:TGComponentsImageNamed(@"LocationInfo_Active.png") forState:UIControlStateSelected]; - [_mapModeButton setImage:TGComponentsImageNamed(@"LocationInfo_Active.png") forState:UIControlStateSelected | UIControlStateHighlighted]; - [_mapModeButton addTarget:self action:@selector(mapModeButtonPressed) forControlEvents:UIControlEventTouchUpInside]; - [self addSubview:_mapModeButton]; - - _trackButton = [[TGLocationTrackingButton alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 45.0f, 45.0f)]; - [_trackButton addTarget:self action:@selector(trackPressed:) forControlEvents:UIControlEventTouchUpInside]; - [self addSubview:_trackButton]; - - _separatorView = [[UIView alloc] init]; - _separatorView.backgroundColor = UIColorRGB(0xcccccc); - [self addSubview:_separatorView]; - } - return self; -} - -- (void)setPallete:(TGLocationPallete *)pallete -{ - _pallete = pallete; - - if (![_mapModeBackgroundView isKindOfClass:[UIVisualEffectView class]]) - _mapModeBackgroundView.backgroundColor = pallete.backgroundColor; - else - ((UIVisualEffectView *)_mapModeBackgroundView).effect = pallete.searchBarPallete.isDark ? [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark] : [UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight]; - - if (![pallete.backgroundColor isEqual:[UIColor whiteColor]]) - { - UIGraphicsBeginImageContextWithOptions(_backgroundView.image.size, false, 0.0f); - [_backgroundView.image drawAtPoint:CGPointZero]; - - CGContextRef context = UIGraphicsGetCurrentContext(); - [pallete.backgroundColor setFill]; - UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(4.0f, 4.0f, 46.5f, 46.5f) cornerRadius:10.0f]; - CGContextAddPath(context, path.CGPath); - CGContextFillPath(context); - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - _backgroundView.image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(15.0f, 15.0f, 18.0f, 15.0f)]; - } - - _separatorView.backgroundColor = pallete.separatorColor; - - [_mapModeButton setImage:TGTintedImage(TGComponentsImageNamed(@"LocationInfo.png"), pallete.accentColor) forState:UIControlStateNormal]; - [_mapModeButton setImage:TGTintedImage(TGComponentsImageNamed(@"LocationInfo_Active.png"), pallete.accentColor) forState:UIControlStateSelected]; - [_mapModeButton setImage:TGTintedImage(TGComponentsImageNamed(@"LocationInfo_Active.png"), pallete.accentColor) forState:UIControlStateSelected | UIControlStateHighlighted]; - - [_trackButton setAccentColor:pallete.accentColor spinnerColor:pallete.secondaryTextColor]; - - if (pallete != nil && pallete.searchBarPallete.segmentedControlBackgroundImage == nil) - _mapModeButton.tintColor = pallete.accentColor; - - [_mapModeControl setBackgroundImage:pallete.searchBarPallete.segmentedControlBackgroundImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault]; - [_mapModeControl setBackgroundImage:pallete.searchBarPallete.segmentedControlSelectedImage forState:UIControlStateSelected barMetrics:UIBarMetricsDefault]; - [_mapModeControl setBackgroundImage:pallete.searchBarPallete.segmentedControlSelectedImage forState:UIControlStateSelected | UIControlStateHighlighted barMetrics:UIBarMetricsDefault]; - [_mapModeControl setBackgroundImage:pallete.searchBarPallete.segmentedControlHighlightedImage forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault]; - [_mapModeControl setDividerImage:pallete.searchBarPallete.segmentedControlDividerImage forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault]; - - [_mapModeControl setTitleTextAttributes:@{UITextAttributeTextColor:pallete.searchBarPallete.accentColor, UITextAttributeTextShadowColor: [UIColor clearColor], UITextAttributeFont: TGSystemFontOfSize(13)} forState:UIControlStateNormal]; - [_mapModeControl setTitleTextAttributes:@{UITextAttributeTextColor:pallete.searchBarPallete.accentColor, UITextAttributeTextShadowColor: [UIColor clearColor], UITextAttributeFont: TGSystemFontOfSize(13)} forState:UIControlStateSelected]; -} - -- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event -{ - bool result = [super pointInside:point withEvent:event]; - if (!result) - result = [_mapModeControl pointInside:[self convertPoint:point toView:_mapModeControl] withEvent:event]; - - return result; -} - -- (void)mapModeButtonPressed -{ - _mapModeButton.selected = !_mapModeButton.selected; - [self setMapModeControlHidden:!_mapModeButton.selected animated:true]; -} - -- (void)modeChanged:(TGLocationMapModeControl *)sender -{ - if (self.mapModeChanged != nil) - self.mapModeChanged(sender.selectedSegmentIndex); - - _mapModeButton.selected = false; - [self setMapModeControlHidden:true animated:true]; -} - -- (void)trackPressed:(TGLocationTrackingButton *)sender -{ - if (self.trackModePressed != nil) - self.trackModePressed(); -} - -- (void)setTrackingMode:(TGLocationTrackingMode)trackingMode animated:(bool)animated -{ - [_trackButton setTrackingMode:trackingMode animated:animated]; -} - -- (void)setLocationAvailable:(bool)available animated:(bool)animated -{ - [_trackButton setLocationAvailable:available animated:animated]; -} - -- (void)layoutSubviews -{ - _backgroundView.frame = CGRectMake(-5.0f, -5.0f, 45.0f + 10.0f, 90.0f + 5.0f + 6.0f); - _mapModeButton.frame = CGRectMake(0.0f, 0.0f, 45.0f, 45.0f); - _trackButton.frame = CGRectMake(0.0f, 45.0f, 45.0f, 45.0f); - _separatorView.frame = CGRectMake(0.0f, 45.0f, 45.0f, TGScreenPixel); -} - -- (void)setMapModeControlHidden:(bool)hidden animated:(bool)animated -{ - _mapModeBackgroundView.userInteractionEnabled = !hidden; - - if (!hidden) - { - _mapModeClipView.frame = CGRectMake(-self.frame.origin.x + 12.0f, 8.0f, self.superview.frame.size.width - 45.0f - 12.0f, _mapModeControl.frame.size.height); - _mapModeControl.frame = CGRectMake(0.0f, 0.0f, _mapModeClipView.frame.size.width - 16.0f, _mapModeControl.frame.size.height); - - if (_mapModeBackgroundView.hidden) - { - _mapModeBackgroundView.hidden = false; - _mapModeBackgroundView.frame = CGRectMake(_mapModeClipView.frame.size.width, 0.0f, _mapModeClipView.frame.size.width - 16.0f, _mapModeControl.frame.size.height); - } - } - - if (animated) - { - [UIView animateWithDuration:0.3f delay:0.0f options:7 << 16 animations:^ - { - _mapModeBackgroundView.frame = CGRectMake(hidden ? _mapModeClipView.frame.size.width : 0.0f, 0.0f, _mapModeClipView.frame.size.width - 16.0f, _mapModeControl.frame.size.height); - } completion:nil]; - - [UIView animateWithDuration:0.25f animations:^ - { - _mapModeBackgroundView.alpha = hidden ? 0.0f : 1.0f; - }]; - } - else - { - _mapModeBackgroundView.alpha = hidden ? 0.0f : 1.0f; - } -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationPickerController.m b/submodules/LegacyComponents/Sources/TGLocationPickerController.m deleted file mode 100644 index c622a67afa..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationPickerController.m +++ /dev/null @@ -1,1324 +0,0 @@ -#import "TGLocationPickerController.h" - -#import "LegacyComponentsInternal.h" -#import "TGColor.h" -#import "TGImageUtils.h" -#import "TGFont.h" - -#import - -#import "TGLocationUtils.h" - -#import "TGLocationSignals.h" - -#import "TGListsTableView.h" -#import "TGSearchBar.h" -#import "TGSearchDisplayMixin.h" -#import -#import -#import -#import "TGLocationViewController.h" - -#import "TGLocationAnnotation.h" -#import "TGLocationReverseGeocodeResult.h" - -#import "TGLocationMapView.h" - -#import "TGLocationVenue.h" -#import "TGLocationAnnotation.h" - -#import "TGLocationVenueCell.h" -#import "TGLocationCurrentLocationCell.h" -#import "TGLocationSectionHeaderCell.h" -#import "TGLocationOptionsView.h" -#import "TGLocationPinAnnotationView.h" - -const CGPoint TGLocationPickerPinOffset = { 0.0f, 33.0f }; - -@interface TGLocationPair : NSObject - -@property (nonatomic, readonly) CLLocation *location; -@property (nonatomic, readonly, getter=isCurrent) bool current; -@property (nonatomic, assign) bool onlyLocationUpdate; - -@end - -@implementation TGLocationPair - -+ (TGLocationPair *)pairWithLocation:(CLLocation *)location isCurrent:(bool)isCurrent onlyLocationUpdate:(bool)onlyLocationUpdate -{ - TGLocationPair *pair = [[TGLocationPair alloc] init]; - pair->_location = location; - pair->_current = isCurrent; - pair->_onlyLocationUpdate = onlyLocationUpdate; - return pair; -} - -@end - -@interface TGLocationPickerController () -{ - TGLocationPickerControllerIntent _intent; - - bool _nearbyVenuesLoadFailed; - NSArray *_nearbyVenues; - NSArray *_searchResults; - NSString *_searchResultsQuery; - - TGLocationPinAnnotationView *_ownLocationView; - __weak MKAnnotationView *_userLocationView; - - CLLocation *_currentUserLocation; - CLLocation *_startLocation; - CLLocation *_venuesFetchLocation; - SMetaDisposable *_locationUpdateDisposable; - void (^_userLocationObserver)(CLLocation *location); - - SMetaDisposable *_nearbyVenuesDisposable; - SMetaDisposable *_searchDisposable; - SMetaDisposable *_reverseGeocodeDisposable; - - UIView *_pickerPinWrapper; - TGLocationPinAnnotationView *_pickerPinView; - - NSValue *_fullScreenMapSpan; - - bool _mapInFullScreenMode; - bool _pinMovedFromUserLocation; - bool _updatePinAnnotation; - NSString *_customAddress; - - UIView *_searchBarOverlay; - UIBarButtonItem *_searchButtonItem; - UIView *_searchReferenceView; - UIView *_searchBarWrapper; - TGSearchBar *_searchBar; - TGSearchDisplayMixin *_searchMixin; - - UIView *_safeAreaCurtainView; - CGRect _initialCurtainFrame; - - UIImageView *_attributionView; - - bool _placesListVisible; - - id _liveLocationsDisposable; - TGLiveLocation *_liveLocation; -} -@end - -@implementation TGLocationPickerController - -- (instancetype)initWithContext:(id)context intent:(TGLocationPickerControllerIntent)intent -{ - self = [super initWithContext:context]; - if (self != nil) - { - _intent = intent; - - _locationUpdateDisposable = [[SMetaDisposable alloc] init]; - _nearbyVenuesDisposable = [[SMetaDisposable alloc] init]; - - self.title = TGLocalized(@"Map.ChooseLocationTitle"); - [self setLeftBarButtonItem:[[UIBarButtonItem alloc] initWithTitle:TGLocalized(@"Common.Cancel") style:UIBarButtonItemStylePlain target:self action:@selector(cancelButtonPressed)]]; - - _searchButtonItem = [self controllerRightBarButtonItem]; - _searchButtonItem.enabled = false; - [self setRightBarButtonItem:_searchButtonItem]; - - [TGLocationUtils requestWhenInUserLocationAuthorizationWithLocationManager:_locationManager]; - } - return self; -} - -- (void)dealloc -{ - [_locationUpdateDisposable dispose]; - [_nearbyVenuesDisposable dispose]; - [_searchDisposable dispose]; - [_reverseGeocodeDisposable dispose]; - [_liveLocationsDisposable dispose]; - - _searchBar.delegate = nil; - _searchMixin.delegate = nil; -} - -- (void)loadView -{ - _tableViewBottomInset = 400.0f; - - [super loadView]; - - _attributionView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, _tableView.frame.size.width, 55)]; - _attributionView.autoresizingMask = UIViewAutoresizingFlexibleWidth; - _attributionView.contentMode = UIViewContentModeCenter; - _attributionView.hidden = true; - _attributionView.image = self.pallete != nil ? TGTintedImage(TGComponentsImageNamed(@"FoursquareAttribution.png"), self.pallete.secondaryTextColor) : TGComponentsImageNamed(@"FoursquareAttribution.png"); - _tableView.tableFooterView = _attributionView; - - _mapView.tapEnabled = true; - _mapView.longPressAsTapEnabled = true; - if (iosMajorVersion() >= 7) - _mapView.rotateEnabled = false; - - __weak TGLocationPickerController *weakSelf = self; - _mapView.singleTap = ^ - { - __strong TGLocationPickerController *strongSelf = weakSelf; - if (strongSelf == nil) - return; - - [strongSelf switchToFullscreen]; - }; - - _searchBarOverlay = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.navigationController.view.frame.size.width, 44.0f)]; - _searchBarOverlay.alpha = 0.0f; - _searchBarOverlay.autoresizingMask = UIViewAutoresizingFlexibleWidth; - _searchBarOverlay.backgroundColor = self.pallete != nil ? self.pallete.sectionHeaderBackgroundColor : UIColorRGB(0xf7f7f7); - _searchBarOverlay.userInteractionEnabled = false; - [self.navigationController.view addSubview:_searchBarOverlay]; - - CGFloat safeAreaInset = self.controllerSafeAreaInset.top > FLT_EPSILON ? self.controllerSafeAreaInset.top : 0.0f; - _searchBarWrapper = [[UIView alloc] initWithFrame:CGRectMake(0, -44.0f, self.navigationController.view.frame.size.width, 44.0f)]; - _searchBarWrapper.autoresizingMask = UIViewAutoresizingFlexibleWidth; - _searchBarWrapper.backgroundColor = self.pallete != nil ? self.pallete.backgroundColor : [UIColor whiteColor]; - _searchBarWrapper.hidden = true; - [self.navigationController.view addSubview:_searchBarWrapper]; - - _searchBar = [[TGSearchBar alloc] initWithFrame:CGRectMake(0.0f, 0.0f, _searchBarWrapper.frame.size.width, [TGSearchBar searchBarBaseHeight]) style:TGSearchBarStyleHeader]; - if (self.pallete != nil) - [_searchBar setPallete:self.pallete.searchBarPallete]; - _searchBar.autoresizingMask = UIViewAutoresizingFlexibleWidth; - _searchBar.customBackgroundView.image = nil; - _searchBar.customActiveBackgroundView.image = nil; - _searchBar.delegate = self; - [_searchBar setShowsCancelButton:true animated:false]; - [_searchBar setAlwaysExtended:true]; - _searchBar.placeholder = TGLocalized(@"Map.Search"); - [_searchBar sizeToFit]; - _searchBar.delayActivity = false; - [_searchBarWrapper addSubview:_searchBar]; - - _searchMixin = [[TGSearchDisplayMixin alloc] init]; - _searchMixin.searchBar = _searchBar; - _searchMixin.alwaysShowsCancelButton = true; - _searchMixin.delegate = self; - - _searchReferenceView = [[UIView alloc] initWithFrame:self.view.bounds]; - _searchReferenceView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - _searchReferenceView.userInteractionEnabled = false; - [self.view addSubview:_searchReferenceView]; - - _activityIndicator.alpha = 0.0f; - [self setIsLoading:true]; - - if (self.safeAreaInsetBottom > FLT_EPSILON) - { - _safeAreaCurtainView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, _tableView.frame.size.width, self.safeAreaInsetBottom)]; - _safeAreaCurtainView.backgroundColor = self.pallete != nil ? self.pallete.sectionHeaderBackgroundColor : UIColorRGB(0xf7f7f7); - } - - if (![self _updateControllerInset:false]) - [self controllerInsetUpdated:UIEdgeInsetsZero]; - - TGLocationPickerAnnotation *annotation = [[TGLocationPickerAnnotation alloc] initWithCoordinate:kCLLocationCoordinate2DInvalid]; - annotation.peer = self.peer; - - _ownLocationView = [[TGLocationPinAnnotationView alloc] initWithAnnotation:annotation]; - _ownLocationView.pallete = self.pallete; - _ownLocationView.frame = CGRectOffset(_ownLocationView.frame, 21.0f, 22.0f); - - CGFloat pinWrapperWidth = self.view.frame.size.width; - _pickerPinWrapper = [[TGLocationPinWrapperView alloc] initWithFrame:CGRectMake((_mapViewWrapper.frame.size.width - pinWrapperWidth) / 2, (_mapViewWrapper.frame.size.height - pinWrapperWidth) / 2, pinWrapperWidth, pinWrapperWidth)]; - _pickerPinWrapper.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin; - _pickerPinWrapper.hidden = true; - [_mapViewWrapper addSubview:_pickerPinWrapper]; - - _pickerPinView = [[TGLocationPinAnnotationView alloc] initWithAnnotation:annotation]; - _pickerPinView.pallete = self.pallete; - _pickerPinView.center = CGPointMake(_pickerPinWrapper.frame.size.width / 2.0f, _pickerPinWrapper.frame.size.width / 2.0f + 16.0f); - [_pickerPinWrapper addSubview:_pickerPinView]; -} - -- (void)viewWillAppear:(BOOL)animated -{ - [super viewWillAppear:animated]; - - if (_intent == TGLocationPickerControllerCustomLocationIntent) - [self switchToFullscreen]; - - __weak TGLocationPickerController *weakSelf = self; - [_locationUpdateDisposable setDisposable:[[self pickerUserLocationSignal] startWithNext:^(TGLocationPair *locationPair) - { - __strong TGLocationPickerController *strongSelf = weakSelf; - if (strongSelf == nil) - return; - - [strongSelf setCurrentUserLocation:locationPair.location storeLocation:locationPair.isCurrent updateMapView:!locationPair.onlyLocationUpdate]; - - if (strongSelf->_placesListVisible && strongSelf->_intent != TGLocationPickerControllerCustomLocationIntent && locationPair.isCurrent && !locationPair.onlyLocationUpdate) - { - [strongSelf fetchNearbyVenuesWithLocation:locationPair.location]; - } - }]]; - - [self _layoutTableProgressViews]; -} - -- (void)setLiveLocationsSignal:(SSignal *)signal -{ - __weak TGLocationPickerController *weakSelf = self; - _liveLocationsDisposable = [[signal deliverOn:[SQueue mainQueue]] startWithNext:^(TGLiveLocation *liveLocation) - { - __strong TGLocationPickerController *strongSelf = weakSelf; - if (strongSelf == nil) - return; - - strongSelf->_liveLocation = liveLocation; - [strongSelf updateCurrentLocationCell]; - }]; -} - -- (void)fetchNearbyVenuesWithLocation:(CLLocation *)location -{ - _venuesFetchLocation = location; - _messageLabel.hidden = true; - - [self setIsLoading:true]; - - __weak TGLocationPickerController *weakSelf = self; - [_nearbyVenuesDisposable setDisposable:[[self.nearbyPlacesSignal(@"", location) deliverOn:[SQueue mainQueue]] startWithNext:^(NSArray *venues) - { - __strong TGLocationPickerController *strongSelf = weakSelf; - if (strongSelf != nil && venues != nil) - [strongSelf setNearbyVenues:venues]; - } error:^(__unused id error) - { - __strong TGLocationPickerController *strongSelf = weakSelf; - if (strongSelf == nil) - return; - - strongSelf->_nearbyVenuesLoadFailed = true; - - [strongSelf setIsLoading:false]; - - [strongSelf _layoutTableProgressViews]; - strongSelf->_messageLabel.hidden = false; - strongSelf->_messageLabel.text = TGLocalized(@"Map.LoadError"); - } completed:nil]]; -} - -- (void)viewDidAppear:(BOOL)animated -{ - [super viewDidAppear:animated]; - - _searchBarWrapper.hidden = false; - - if (_intent != TGLocationPickerControllerCustomLocationIntent) - { - [[[LegacyComponentsGlobals provider] accessChecker] checkLocationAuthorizationStatusForIntent:TGLocationAccessIntentSend alertDismissComlpetion:^ - { - if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedWhenInUse) - [self switchToFullscreen]; - }]; - } -} - -- (void)viewWillDisappear:(BOOL)animated -{ - [super viewWillDisappear:animated]; - - _searchBarWrapper.hidden = true; -} - -#pragma mark - Actions - -- (void)cancelButtonPressed -{ - [self.presentingViewController dismissViewControllerAnimated:true completion:nil]; -} - -- (void)_sendLocation -{ - _tableView.userInteractionEnabled = false; - - CLLocationCoordinate2D coordinate = _currentUserLocation.coordinate; - if (_mapInFullScreenMode) - coordinate = [self mapCenterCoordinateForPickerPin]; - - if (self.locationPicked != nil) - self.locationPicked(coordinate, nil, _customAddress); -} - -- (void)searchButtonPressed -{ - [self setSearchHidden:false animated:true]; - [_searchBar becomeFirstResponder]; -} - -- (void)_presentVenuesList -{ - if (fabs(_tableView.contentOffset.y + _tableView.contentInset.top) < 1.0f) - { - [_tableView setContentOffset:CGPointMake(0.0f, -_tableView.contentInset.top + (self.view.frame.size.height - [self visibleContentHeight] - self.controllerInset.top * 2.0f) / 2.0f - 16.0f) animated:true]; - } -} - -- (void)userLocationButtonPressed -{ - if (!_pinMovedFromUserLocation || _currentUserLocation == nil) - return; - - [self switchToUserLocation]; - - _mapInFullScreenMode = false; - _pinMovedFromUserLocation = false; - - [self hidePickerAnnotationAnimated:true]; - [_pickerPinView setPinRaised:true avatar:_intent == TGLocationPickerControllerCustomLocationIntent animated:true completion:nil]; - - MKCoordinateSpan span = _fullScreenMapSpan != nil ? _fullScreenMapSpan.MKCoordinateSpanValue : TGLocationDefaultSpan; - [self setMapCenterCoordinate:_mapView.userLocation.location.coordinate span:span offset:TGLocationPickerPinOffset animated:true]; -} - -#pragma mark - Map View Delegate - -- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)__unused animated -{ - UIView *view = mapView.subviews.firstObject; - - for (UIGestureRecognizer *recognizer in view.gestureRecognizers) - { - if(recognizer.state == UIGestureRecognizerStateBegan || recognizer.state == UIGestureRecognizerStateEnded) - { - if (_mapInFullScreenMode) - { - [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(pinPinView) object:nil]; - [self hidePickerAnnotationAnimated:true]; - } - else - { - [self switchToFullscreen]; - } - - [_pickerPinView setPinRaised:true avatar:_intent == TGLocationPickerControllerCustomLocationIntent animated:true completion:nil]; - - _pinMovedFromUserLocation = true; - _updatePinAnnotation = false; - - break; - } - } -} - -- (void)mapView:(MKMapView *)__unused mapView regionDidChangeAnimated:(BOOL)__unused animated -{ - if (_pickerPinView.isPinRaised) - { - NSTimeInterval delay = _pinMovedFromUserLocation ? 0.38 : 0.05; - [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(pinPinView) object:nil]; - [self performSelector:@selector(pinPinView) withObject:nil afterDelay:delay]; - } - else if (_updatePinAnnotation) - { - [self pinPinView]; - } - - for (id annotation in [mapView annotations]) - { - if (![annotation isKindOfClass:[MKUserLocation class]]) - { - MKAnnotationView *view = [mapView viewForAnnotation:annotation]; - [view.superview bringSubviewToFront:view]; - } - } -} - -- (void)pinPinView -{ - __weak TGLocationPickerController *weakSelf = self; - [_pickerPinView setPinRaised:false avatar:_intent == TGLocationPickerControllerCustomLocationIntent animated:true completion:^ - { - __strong TGLocationPickerController *strongSelf = weakSelf; - if (strongSelf == nil) - return; - - if (strongSelf->_mapInFullScreenMode) - { - [strongSelf showPickerAnnotationAnimated:true]; - } - else - { - strongSelf->_ownLocationView.hidden = false; - strongSelf->_pickerPinWrapper.hidden = true; - } - }]; - - if (!_mapInFullScreenMode) - [_pickerPinView setCustomPin:false animated:true]; -} - -- (void)updateLocationAvailability -{ - [super updateLocationAvailability]; - - if (_locationServicesDisabled) - [self switchToFullscreen]; -} - -- (void)mapView:(MKMapView *)__unused mapView didUpdateUserLocation:(MKUserLocation *)userLocation -{ - userLocation.title = @""; - - _locationServicesDisabled = false; - - if (_userLocationObserver != nil) - _userLocationObserver(userLocation.location); - else if (userLocation.location != nil) - _startLocation = userLocation.location; -} - -- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id)annotation -{ - if (annotation == mapView.userLocation) - return nil; - - TGLocationPinAnnotationView *view = (TGLocationPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:TGLocationPinAnnotationKind]; - if (view == nil) - { - view = [[TGLocationPinAnnotationView alloc] initWithAnnotation:annotation]; - view.pallete = self.pallete; - } - else - { - view.annotation = annotation; - } - return view; -} - -- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views -{ - for (MKAnnotationView *view in views) - { - if ([view.annotation isKindOfClass:[MKUserLocation class]]) - { - _userLocationView = view; - if (_ownLocationView != nil) - [_userLocationView addSubview:_ownLocationView]; - } - } -} - -- (void)updatePickerAnnotation -{ - __weak TGLocationPickerController *weakSelf = self; - - CLLocationCoordinate2D coordinate = [self mapCenterCoordinateForPickerPin]; - [_reverseGeocodeDisposable setDisposable:[[[TGLocationSignals reverseGeocodeCoordinate:coordinate] deliverOn:[SQueue mainQueue]] startWithNext:^(TGLocationReverseGeocodeResult *result) - { - __strong TGLocationPickerController *strongSelf = weakSelf; - if (strongSelf == nil) - return; - - NSString *address = @""; - if (result != nil) - address = result.fullAddress; - - strongSelf->_customAddress = address; - [strongSelf updateCurrentLocationCell]; - } error:^(__unused id error) - { - __strong TGLocationPickerController *strongSelf = weakSelf; - if (strongSelf == nil) - return; - - strongSelf->_customAddress = @""; - [strongSelf updateCurrentLocationCell]; - } completed:nil]]; -} - -- (void)showPickerAnnotationAnimated:(bool)__unused animated -{ - [self updatePickerAnnotation]; - [self updateCurrentLocationCell]; -} - -- (void)hidePickerAnnotationAnimated:(bool)__unused animated -{ - [self updateCurrentLocationCell]; -} - -- (CLLocationCoordinate2D)mapCenterCoordinateForPickerPin -{ - return [_mapView convertPoint:CGPointMake((_mapView.frame.size.width + TGLocationPickerPinOffset.x) / 2, (_mapView.frame.size.height + TGLocationPickerPinOffset.y) / 2) toCoordinateFromView:_mapView]; -} - -#pragma mark - Signals - -- (SSignal *)pickerUserLocationSignal -{ - __weak TGLocationPickerController *weakSelf = self; - return [[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) - { - SMetaDisposable *disposable = [[SMetaDisposable alloc] init]; - - [disposable setDisposable:[[[[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) - { - __strong TGLocationPickerController *strongSelf = weakSelf; - if (strongSelf == nil) - return nil; - - if (strongSelf->_startLocation != nil) - { - [subscriber putNext:[TGLocationPair pairWithLocation:strongSelf->_startLocation isCurrent:true onlyLocationUpdate:false]]; - strongSelf->_startLocation = nil; - } - else - { - CLLocation *knownUserLocation = [TGLocationSignals lastKnownUserLocation]; - [subscriber putNext:[TGLocationPair pairWithLocation:knownUserLocation isCurrent:false onlyLocationUpdate:false]]; - } - - strongSelf->_userLocationObserver = ^(CLLocation *location) - { - [subscriber putNext:[TGLocationPair pairWithLocation:location isCurrent:true onlyLocationUpdate:false]]; - }; - - return nil; - }] map:^TGLocationPair *(TGLocationPair *locationPair) - { - if (!locationPair.isCurrent) - return locationPair; - - __strong TGLocationPickerController *strongSelf = weakSelf; - CLLocation *location = locationPair.location; - - if (strongSelf != nil && strongSelf->_venuesFetchLocation != nil) - { - CLLocation *currentLocation = strongSelf->_venuesFetchLocation; - if ([location distanceFromLocation:currentLocation] < 250) - { - if ((location.horizontalAccuracy < currentLocation.horizontalAccuracy || fabs(location.horizontalAccuracy - currentLocation.horizontalAccuracy) < 50)) - { - locationPair.onlyLocationUpdate = true; - } - } - } - - return locationPair; - }] startWithNext:^(TGLocationPair *locationPair) - { - [subscriber putNext:locationPair]; - }]]; - - return disposable; - }]; -} - -- (void)setCurrentUserLocation:(CLLocation *)userLocation storeLocation:(bool)storeLocation updateMapView:(bool)updateMapView -{ - if (userLocation == nil) - return; - - bool hadNoLocation = (_currentUserLocation == nil); - - if (_mapInFullScreenMode && hadNoLocation) - _pinMovedFromUserLocation = true; - - if (storeLocation) - { - [TGLocationSignals storeLastKnownUserLocation:userLocation]; - _currentUserLocation = userLocation; - _searchButtonItem.enabled = true; - [_optionsView setLocationAvailable:true animated:true]; - } - - [self updateCurrentLocationCell]; - - if (updateMapView) - { - if (!_mapInFullScreenMode) - { - [self setMapCenterCoordinate:userLocation.coordinate offset:TGLocationPickerPinOffset animated:true]; - } - else if (_intent == TGLocationPickerControllerCustomLocationIntent && hadNoLocation) - { - _pinMovedFromUserLocation = false; - _updatePinAnnotation = true; - [self setMapCenterCoordinate:userLocation.coordinate offset:TGLocationPickerPinOffset animated:true]; - } - } -} - -#pragma mark - Appearance - -- (void)switchToFullscreen -{ - if (_mapInFullScreenMode) - return; - - _mapInFullScreenMode = true; - _pinMovedFromUserLocation = true; - - _searchButtonItem.enabled = true; - - _ownLocationView.hidden = true; - _pickerPinWrapper.hidden = false; - //if (_intent != TGLocationPickerControllerCustomLocationIntent) { - [_pickerPinView setCustomPin:true animated:true]; - //} - - _mapView.tapEnabled = false; - _mapView.longPressAsTapEnabled = false; - - _tableView.clipsToBounds = false; - _tableView.scrollEnabled = false; - [_mapViewWrapper.superview bringSubviewToFront:_mapViewWrapper]; - - [_safeAreaCurtainView.superview bringSubviewToFront:_safeAreaCurtainView]; - [UIView animateWithDuration:0.25 animations:^ - { - _safeAreaCurtainView.alpha = 1.0f; - }]; - - void (^changeBlock)(void) = ^ - { - _tableView.contentOffset = CGPointMake(0, -_tableView.contentInset.top); - _tableView.frame = CGRectMake(_tableView.frame.origin.x, self.view.frame.size.height - [self mapHeight] - TGLocationCurrentLocationCellHeight - self.controllerInset.top - self.safeAreaInsetBottom, _tableView.frame.size.width, _tableView.frame.size.height); - - _mapViewWrapper.frame = CGRectMake(0, TGLocationMapClipHeight - self.view.frame.size.height + self.controllerInset.top + 20, _mapViewWrapper.frame.size.width, self.view.frame.size.height - self.controllerInset.top - 10.0f); - _mapView.center = CGPointMake(_mapView.center.x, _mapViewWrapper.frame.size.height / 2); - _edgeView.frame = CGRectMake(0.0f, _mapViewWrapper.frame.size.height - _edgeView.frame.size.height, _edgeView.frame.size.width, _edgeView.frame.size.height); - - if (_safeAreaCurtainView != nil) - { - UITableViewCell *firstCell = [_tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; - _safeAreaCurtainView.frame = CGRectMake(0.0f, CGRectGetMaxY(firstCell.frame), _safeAreaCurtainView.frame.size.width,_safeAreaCurtainView.frame.size.height); - } - }; - - void (^completionBlock)(BOOL) = ^(BOOL finished) - { - if (finished) - { - _mapView.manipulationEnabled = true; - - _mapViewWrapper.clipsToBounds = true; - _fullScreenMapSpan = [NSValue valueWithMKCoordinateSpan:_mapView.region.span]; - } - }; - - if (iosMajorVersion() >= 7) - { - [UIView animateWithDuration:0.5f delay:0.0f usingSpringWithDamping:0.75f initialSpringVelocity:0.5f options:UIViewAnimationOptionCurveLinear animations:changeBlock completion:completionBlock]; - } - else - { - [UIView animateWithDuration:0.4f delay:0.0f options:UIViewAnimationOptionCurveEaseInOut animations:changeBlock completion:completionBlock]; - } - - [self updateCurrentLocationCell]; -} - -- (void)switchToUserLocation -{ - if (!_mapInFullScreenMode) - return; - - _mapInFullScreenMode = false; - _mapViewWrapper.clipsToBounds = false; - _searchButtonItem.enabled = !_locationServicesDisabled; - - void (^changeBlock)(void) = ^ - { - _tableView.contentOffset = CGPointMake(0, -_tableView.contentInset.top); - _tableView.frame = self.view.bounds; - - _mapViewWrapper.frame = CGRectMake(0, TGLocationMapClipHeight - _tableViewTopInset, self.view.frame.size.width, _tableViewTopInset + 10.0f); - _mapView.frame = CGRectMake(0, -TGLocationMapInset, self.view.frame.size.width, _tableViewTopInset + 2 * TGLocationMapInset + 10.0f); - _edgeView.frame = CGRectMake(0.0f, _tableViewTopInset - 10.0f, _mapViewWrapper.frame.size.width, _edgeView.frame.size.height); - - _safeAreaCurtainView.frame = CGRectMake(0.0f, _initialCurtainFrame.origin.y, _safeAreaCurtainView.frame.size.width,_safeAreaCurtainView.frame.size.height); - }; - - [_safeAreaCurtainView.superview bringSubviewToFront:_safeAreaCurtainView]; - [UIView animateWithDuration:0.25 animations:^ - { - _safeAreaCurtainView.alpha = 1.0f; - }]; - - void (^completionBlock)(BOOL) = ^(BOOL finished) - { - if (finished) - { - _tableView.clipsToBounds = true; - _tableView.scrollEnabled = true; - - _mapView.tapEnabled = true; - _mapView.longPressAsTapEnabled = true; - } - }; - - if (iosMajorVersion() >= 7) - { - [UIView animateWithDuration:0.5f delay:0.0f usingSpringWithDamping:0.75f initialSpringVelocity:0.5f options:UIViewAnimationOptionCurveLinear animations:changeBlock completion:completionBlock]; - } - else - { - [UIView animateWithDuration:0.4f delay:0.0f options:UIViewAnimationOptionCurveEaseInOut animations:changeBlock completion:completionBlock]; - } -} - -- (UIBarButtonItem *)controllerRightBarButtonItem -{ - if (_intent == TGLocationPickerControllerCustomLocationIntent) { - return nil; - } - if (iosMajorVersion() < 7) - { - TGModernBarButton *searchButton = [[TGModernBarButton alloc] initWithImage:TGComponentsImageNamed(@"NavigationSearchIcon.png")]; - searchButton.portraitAdjustment = CGPointMake(-7, -5); - [searchButton addTarget:self action:@selector(searchButtonPressed) forControlEvents:UIControlEventTouchUpInside]; - return [[UIBarButtonItem alloc] initWithCustomView:searchButton]; - } - - return [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSearch target:self action:@selector(searchButtonPressed)]; -} - -- (CGRect)_liveLocationMenuSourceRect -{ - TGLocationCurrentLocationCell *cell = [_tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; - if ([cell isKindOfClass:[TGLocationCurrentLocationCell class]]) - return [cell convertRect:cell.bounds toView:self.view]; - - return CGRectZero; -} - -#pragma mark - Search - -- (void)setSearchHidden:(bool)hidden animated:(bool)animated -{ - void (^changeBlock)(void) = ^ - { - CGRect frame = _searchBarWrapper.frame; - if (hidden) - { - frame.origin.y = -frame.size.height; - _searchBarOverlay.alpha = 0.0f; - } - else - { - frame.origin.y = 0; - _searchBarOverlay.alpha = 1.0f; - } - _searchBarWrapper.frame = frame; - }; - - if (animated) - [UIView animateWithDuration:0.2f animations:changeBlock]; - else - changeBlock(); -} - -- (void)searchBar:(TGSearchBar *)__unused searchBar willChangeHeight:(CGFloat)__unused newHeight -{ - -} - -- (void)searchMixin:(TGSearchDisplayMixin *)__unused searchMixin hasChangedSearchQuery:(NSString *)searchQuery withScope:(int)__unused scope -{ - if (searchQuery.length == 0) - { - [_searchDisposable setDisposable:nil]; - [_searchMixin reloadSearchResults]; - [_searchMixin setSearchResultsTableViewHidden:true]; - _searchBar.showActivity = false; - } - else - { - __weak TGLocationPickerController *weakSelf = self; - void (^changeActivityIndicatorState)(bool) = ^(bool active) - { - __strong TGLocationPickerController *strongSelf = weakSelf; - if (strongSelf != nil) - strongSelf->_searchBar.showActivity = active; - }; - - SSignal *searchSignal = [[SSignal complete] delay:0.65f onQueue:[SQueue mainQueue]]; - searchSignal = [searchSignal onCompletion:^ - { - changeActivityIndicatorState(true); - }]; - - CLLocationCoordinate2D coordinate = _currentUserLocation.coordinate; - searchSignal = [searchSignal then:[self.nearbyPlacesSignal(searchQuery, _currentUserLocation) deliverOn:[SQueue mainQueue]]]; - - if (_searchDisposable == nil) - _searchDisposable = [[SMetaDisposable alloc] init]; - - [_searchDisposable setDisposable:[[searchSignal onDispose:^ - { - changeActivityIndicatorState(false); - }] startWithNext:^(NSArray *results) - { - __strong TGLocationPickerController *strongSelf = weakSelf; - if (strongSelf != nil) - [strongSelf setSearchResults:results withSearchQuery:searchQuery]; - } error:^(__unused id error) - { - changeActivityIndicatorState(false); - } completed:^ - { - changeActivityIndicatorState(false); - }]]; - } -} - -- (void)searchMixinWillActivate:(bool)__unused animated -{ - if (_mapInFullScreenMode) - return; - - _tableView.scrollEnabled = false; - - [UIView animateWithDuration:0.2f animations:^ - { - _tableView.contentOffset = CGPointMake(0, -_tableView.contentInset.top); - [self _layoutTableProgressViews]; - }]; -} - -- (void)searchMixinWillDeactivate:(bool)animated -{ - [_searchDisposable setDisposable:nil]; - - [self setSearchHidden:true animated:animated]; - - if (_mapInFullScreenMode) - return; - - _tableView.scrollEnabled = true; - - [UIView animateWithDuration:0.2f animations:^ - { - _tableView.contentOffset = CGPointMake(0, -_tableView.contentInset.top); - [self _layoutTableProgressViews]; - }]; -} - -- (UITableView *)createTableViewForSearchMixin:(TGSearchDisplayMixin *)__unused searchMixin -{ - UITableView *tableView = [[UITableView alloc] init]; - tableView.delegate = self; - tableView.dataSource = self; - tableView.separatorStyle = UITableViewCellSeparatorStyleNone; - tableView.tableFooterView = [[UIView alloc] init]; - tableView.backgroundColor = self.pallete != nil ? self.pallete.backgroundColor : [UIColor whiteColor]; - - return tableView; -} - -- (UIView *)referenceViewForSearchResults -{ - return _searchReferenceView; -} - -#pragma mark - Scroll View Delegate - -- (void)scrollViewDidScroll:(UIScrollView *)scrollView -{ - if (_searchMixin.isActive && scrollView == _searchMixin.searchResultsTableView) - { - [_searchBar resignFirstResponder]; - } - else - { - [super scrollViewDidScroll:scrollView]; - [self _layoutTableProgressViews]; - - TGLocationSectionHeaderCell *cell = [_tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:_allowLiveLocationSharing ? 2 : 1 inSection:0]]; - if (cell == nil || ![cell isKindOfClass:[TGLocationSectionHeaderCell class]]) - return; - - if (scrollView.contentOffset.y > -scrollView.contentInset.top) - { - if (!_placesListVisible) - { - _placesListVisible = true; - if (_currentUserLocation != nil) - [self fetchNearbyVenuesWithLocation:_currentUserLocation]; - } - if (_intent != TGLocationPickerControllerCustomLocationIntent) { - [cell configureWithTitle:TGLocalized(@"Map.ChooseAPlace")]; - } - - if (scrollView.contentOffset.y > -scrollView.contentInset.top + TGLocationSectionHeaderHeight) - { - if (_activityIndicator.alpha < FLT_EPSILON) - { - [UIView animateWithDuration:0.25 animations:^ - { - _activityIndicator.alpha = 1.0f; - }]; - } - } - else - { - [UIView animateWithDuration:0.0 animations:^ - { - _activityIndicator.alpha = 0.0f; - }]; - } - - if (_safeAreaCurtainView != nil) - { - [UIView animateWithDuration:0.25 animations:^ - { - _safeAreaCurtainView.alpha = 0.0f; - }]; - } - } - else - { - _activityIndicator.alpha = 0.0f; - if (_intent != TGLocationPickerControllerCustomLocationIntent) { - [cell configureWithTitle:TGLocalized(@"Map.PullUpForPlaces")]; - } - - if (_safeAreaCurtainView != nil) - { - [_safeAreaCurtainView.superview bringSubviewToFront:_safeAreaCurtainView]; - [UIView animateWithDuration:0.25 animations:^ - { - _safeAreaCurtainView.alpha = 1.0f; - }]; - } - } - } -} - -- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView -{ - if (_searchMixin.isActive && scrollView == _searchMixin.searchResultsTableView) - [_searchBar resignFirstResponder]; -} - -#pragma mark - Data - -- (void)updateCurrentLocationCell -{ - UITableViewCell *cell = [_tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; - if ([cell isKindOfClass:[TGLocationCurrentLocationCell class]]) - { - TGLocationCurrentLocationCell *locationCell = (TGLocationCurrentLocationCell *)cell; - - if (_intent == TGLocationPickerControllerCustomLocationIntent) { - [locationCell configureForGroupLocationWithAddress:_customAddress]; - } else { - if (_mapInFullScreenMode) - [locationCell configureForCustomLocationWithAddress:_customAddress]; - else - [locationCell configureForCurrentLocationWithAccuracy:_currentUserLocation.horizontalAccuracy]; - } - } - - cell = [_tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; - if ([cell isKindOfClass:[TGLocationCurrentLocationCell class]]) - { - TGLocationCurrentLocationCell *locationCell = (TGLocationCurrentLocationCell *)cell; - if (_liveLocation != nil) - [locationCell configureForStopWithMessage:_liveLocation.message remaining:self.remainingTimeForMessage(_liveLocation.message)]; - else - [locationCell configureForLiveLocationWithAccuracy:_currentUserLocation.horizontalAccuracy]; - } -} - -- (void)setNearbyVenues:(NSArray *)nearbyVenues -{ - bool shouldFadeIn = (_nearbyVenues.count == 0); - - if (shouldFadeIn) - { - _tableViewBottomInset = 0.0f; - [self updateInsets]; - } - - _nearbyVenues = nearbyVenues; - [_tableView reloadData]; - - [self setIsLoading:false]; - - _attributionView.hidden = (_nearbyVenues.count == 0); - - if (shouldFadeIn) - { - NSMutableArray *animatedCells = [[NSMutableArray alloc] init]; - - for (UIView *cell in _tableView.visibleCells) - { - if ([cell isKindOfClass:[TGLocationVenueCell class]]) - { - cell.alpha = 0.0f; - [animatedCells addObject:cell]; - } - } - - [UIView animateWithDuration:0.14f animations:^ - { - for (UIView *cell in animatedCells) - cell.alpha = 1.0f; - }]; - } -} - -- (void)setSearchResults:(NSArray *)results withSearchQuery:(NSString *)query -{ - _searchResults = results; - _searchResultsQuery = query; - - [_searchMixin reloadSearchResults]; - [_searchMixin setSearchResultsTableViewHidden:query.length == 0]; -} - -#pragma mark - Table View Data Source & Delegate - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath -{ - if (tableView == _tableView && indexPath.row < [self venueEntriesOffset]) - { - if (indexPath.row == 0) - { - [self _sendLocation]; - } - else if (_allowLiveLocationSharing && indexPath.row == 1) - { - if (_liveLocation != nil) - { - if (self.liveLocationStopped != nil) - self.liveLocationStopped(); - - return; - } - else - { - [self _presentLiveLocationMenu:_currentUserLocation.coordinate dismissOnCompletion:false]; - } - - [tableView deselectRowAtIndexPath:tableView.indexPathForSelectedRow animated:true]; - } - else if ((_allowLiveLocationSharing && indexPath.row == 2) || (!_allowLiveLocationSharing && indexPath.row == 1)) - { - if (_intent != TGLocationPickerControllerCustomLocationIntent) { - [self _presentVenuesList]; - } - } - } - else - { - TGLocationVenue *venue = nil; - if (tableView == _tableView) - { - venue = _nearbyVenues[indexPath.row - [self venueEntriesOffset]]; - } - else if (tableView == _searchMixin.searchResultsTableView) - { - venue = _searchResults[indexPath.row]; - [_searchBar resignFirstResponder]; - } - - if (self.locationPicked != nil) - self.locationPicked(venue.coordinate, [venue venueAttachment], _customAddress); - } -} - -- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath -{ - if (tableView == _tableView) - { - if (indexPath.row == 0 || (_allowLiveLocationSharing && indexPath.row == 1)) - return (_mapInFullScreenMode || _currentUserLocation != nil); - } - - return true; -} - -- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath -{ - if ([cell isKindOfClass:[TGLocationSectionHeaderCell class]]) - { - if (_safeAreaCurtainView.superview == nil) - [_tableView addSubview:_safeAreaCurtainView]; - _safeAreaCurtainView.frame = CGRectMake(0.0f, CGRectGetMaxY(cell.frame), _safeAreaCurtainView.frame.size.width, _safeAreaCurtainView.frame.size.height); - _initialCurtainFrame = _safeAreaCurtainView.frame; - } -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath -{ - UITableViewCell *cell = nil; - - if (tableView == _tableView && indexPath.row == 0) - { - TGLocationCurrentLocationCell *locationCell = [tableView dequeueReusableCellWithIdentifier:TGLocationCurrentLocationCellKind]; - if (locationCell == nil) - locationCell = [[TGLocationCurrentLocationCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TGLocationCurrentLocationCellKind]; - locationCell.pallete = self.pallete; - locationCell.edgeView = _edgeHighlightView; - - if (_intent == TGLocationPickerControllerCustomLocationIntent) { - [locationCell configureForGroupLocationWithAddress:_customAddress]; - } else { - if (_mapInFullScreenMode) - [locationCell configureForCustomLocationWithAddress:_customAddress]; - else - [locationCell configureForCurrentLocationWithAccuracy:_currentUserLocation.horizontalAccuracy]; - } - - cell = locationCell; - } - else if (tableView == _tableView && _allowLiveLocationSharing && indexPath.row == 1) - { - TGLocationCurrentLocationCell *locationCell = [tableView dequeueReusableCellWithIdentifier:TGLocationCurrentLocationCellKind]; - if (locationCell == nil) - locationCell = [[TGLocationCurrentLocationCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TGLocationCurrentLocationCellKind]; - locationCell.pallete = self.pallete; - locationCell.edgeView = nil; - - if (_liveLocation != nil) - [locationCell configureForStopWithMessage:_liveLocation.message remaining:self.remainingTimeForMessage(_liveLocation.message)]; - else - [locationCell configureForLiveLocationWithAccuracy:_currentUserLocation.horizontalAccuracy]; - - cell = locationCell; - } - else if (tableView == _tableView && ((_allowLiveLocationSharing && indexPath.row == 2) || (!_allowLiveLocationSharing && indexPath.row == 1))) - { - TGLocationSectionHeaderCell *sectionCell = [tableView dequeueReusableCellWithIdentifier:TGLocationSectionHeaderKind]; - if (sectionCell == nil) - sectionCell = [[TGLocationSectionHeaderCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TGLocationSectionHeaderKind]; - sectionCell.pallete = self.pallete; - - if (_intent != TGLocationPickerControllerCustomLocationIntent) { - if (tableView.contentOffset.y > -tableView.contentInset.top) - [sectionCell configureWithTitle:TGLocalized(@"Map.ChooseAPlace")]; - else - [sectionCell configureWithTitle:TGLocalized(@"Map.PullUpForPlaces")]; - } - - cell = sectionCell; - } - else - { - TGLocationVenueCell *venueCell = [tableView dequeueReusableCellWithIdentifier:TGLocationVenueCellKind]; - if (venueCell == nil) - venueCell = [[TGLocationVenueCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TGLocationVenueCellKind]; - venueCell.pallete = self.pallete; - TGLocationVenue *venue = nil; - if (tableView == _tableView) - venue = _nearbyVenues[indexPath.row - [self venueEntriesOffset]]; - else if (tableView == _searchMixin.searchResultsTableView) - venue = _searchResults[indexPath.row]; - - [venueCell configureWithVenue:venue]; - - cell = venueCell; - } - - return cell; -} - -- (NSInteger)venueEntriesOffset -{ - return _allowLiveLocationSharing ? 3 : 2; -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)__unused section -{ - if (tableView == _tableView) - return _nearbyVenues.count + 2 + (_allowLiveLocationSharing ? 1 : 0); - else if (tableView == _searchMixin.searchResultsTableView) - return _searchResults.count; - - return 0; -} - -- (CGFloat)tableView:(UITableView *)__unused tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath -{ - if (tableView == _tableView) - { - if (indexPath.row == 0 || (_allowLiveLocationSharing && indexPath.row == 1)) - return TGLocationCurrentLocationCellHeight; - else if ((_allowLiveLocationSharing && indexPath.row == 2) || (!_allowLiveLocationSharing && indexPath.row == 1)) - return TGLocationSectionHeaderHeight; - } - - return TGLocationVenueCellHeight; -} - -- (CGFloat)tableView:(UITableView *)__unused tableView heightForFooterInSection:(NSInteger)__unused section -{ - return 0.001f; -} - -- (UIView *)tableView:(UITableView *)__unused tableView viewForFooterInSection:(NSInteger)__unused section -{ - return [[UIView alloc] init]; -} - -#pragma mark - - -- (void)setIsLoading:(bool)isLoading -{ - if (isLoading) - { - if (_nearbyVenues.count == 0) - [_activityIndicator startAnimating]; - } - else - { - [_activityIndicator stopAnimating]; - } -} - -#pragma mark - Layout - -- (BOOL)shouldAutorotate -{ - return false; -} - -- (void)controllerInsetUpdated:(UIEdgeInsets)previousInset -{ - if (_searchMixin != nil) - { - UIEdgeInsets inset = self.controllerInset; - inset.top -= 44; - [_searchMixin controllerInsetUpdated:inset]; - } - - [super controllerInsetUpdated:previousInset]; -} - -- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration -{ - [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration]; - - if (_searchMixin != nil) - [_searchMixin controllerLayoutUpdated:[TGViewController screenSizeForInterfaceOrientation:toInterfaceOrientation]]; -} - -- (void)_layoutTableProgressViews -{ - _activityIndicator.center = CGPointMake(_tableView.frame.size.width / 2, TGLocationCurrentLocationCellHeight * (_allowLiveLocationSharing ? 2 : 1) + TGLocationSectionHeaderHeight + (_tableView.contentInset.top + _tableView.contentOffset.y) / 2); - - _messageLabel.frame = CGRectMake(0, _activityIndicator.center.y - _messageLabel.frame.size.height / 2.0f, _messageLabel.frame.size.width, _messageLabel.frame.size.height); -} - -#pragma mark - - -- (CGFloat)visibleContentHeight -{ - return (_allowLiveLocationSharing ? 165.0f : 97.0f) + self.safeAreaInsetBottom; -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationPinAnnotationView.h b/submodules/LegacyComponents/Sources/TGLocationPinAnnotationView.h deleted file mode 100644 index 9332f8d00e..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationPinAnnotationView.h +++ /dev/null @@ -1,23 +0,0 @@ -#import - -@class TGLocationPallete; - -@interface TGLocationPinAnnotationView : MKAnnotationView - -- (instancetype)initWithAnnotation:(id)annotation; - -@property (nonatomic, assign, getter=isPinRaised) bool pinRaised; -- (void)setPinRaised:(bool)raised avatar:(bool)avatar animated:(bool)animated completion:(void (^)(void))completion; - -- (void)setCustomPin:(bool)customPin animated:(bool)animated; - -@property (nonatomic, strong) TGLocationPallete *pallete; - -@end - -extern NSString * const TGLocationPinAnnotationKind; - - -@interface TGLocationPinWrapperView : UIView - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationPinAnnotationView.m b/submodules/LegacyComponents/Sources/TGLocationPinAnnotationView.m deleted file mode 100644 index d1f0464105..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationPinAnnotationView.m +++ /dev/null @@ -1,679 +0,0 @@ -#import "TGLocationPinAnnotationView.h" - -#import "LegacyComponentsInternal.h" -#import "TGImageUtils.h" - -#import "TGLocationMapViewController.h" - -#import "TGUser.h" -#import "TGConversation.h" -#import "TGLocationAnnotation.h" -#import "TGLocationMediaAttachment.h" - -#import "TGImageView.h" -#import "TGLetteredAvatarView.h" -#import "TGLocationPulseView.h" - -NSString *const TGLocationPinAnnotationKind = @"TGLocationPinAnnotation"; - -@interface TGLocationPinAnnotationView () -{ - TGLocationPulseView *_pulseView; - UIImageView *_smallView; - UIImageView *_shadowView; - UIImageView *_backgroundView; - TGImageView *_iconView; - UIImageView *_dotView; - TGLetteredAvatarView *_avatarView; - UIImageView *_smallArrowView; - UIImageView *_arrowView; - - bool _liveLocation; - SMetaDisposable *_userDisposable; - - bool _animating; - - bool _observingExpiration; -} -@end - -@implementation TGLocationPinAnnotationView - -- (instancetype)initWithAnnotation:(id)annotation -{ - self = [super initWithAnnotation:annotation reuseIdentifier:TGLocationPinAnnotationKind]; - if (self != nil) - { - _pulseView = [[TGLocationPulseView alloc] init]; - [self addSubview:_pulseView]; - - _shadowView = [[UIImageView alloc] initWithImage:TGComponentsImageNamed(@"LocationPinShadow")]; - [self addSubview:_shadowView]; - - _backgroundView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 83.0f, 83.0f)]; - [_shadowView addSubview:_backgroundView]; - - _iconView = [[TGImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 64.0f, 64.0f)]; - _iconView.contentMode = UIViewContentModeCenter; - [_backgroundView addSubview:_iconView]; - - static dispatch_once_t onceToken; - static UIImage *smallDotImage; - static UIImage *largeDotImage; - static UIImage *smallHeadingArrowImage; - static UIImage *largeHeadingArrowImage; - dispatch_once(&onceToken, ^ - { - UIGraphicsBeginImageContextWithOptions(CGSizeMake(6.0f, 6.0f), false, 0.0f); - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSetFillColorWithColor(context, UIColorRGB(0x008df2).CGColor); - CGContextFillEllipseInRect(context, CGRectMake(0.0f, 0.0f, 6.0f, 6.0f)); - - smallDotImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - - UIGraphicsBeginImageContextWithOptions(CGSizeMake(16.0f, 16.0f), false, 0.0f); - context = UIGraphicsGetCurrentContext(); - - CGContextSaveGState(context); - CGContextSetShadowWithColor(context, CGSizeMake(0, 1), 1.0f, [UIColor colorWithWhite:0.0f alpha:0.22f].CGColor); - CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor); - CGContextFillEllipseInRect(context, CGRectMake(2, 2, 12.0, 12.0)); - - CGContextRestoreGState(context); - - CGContextSetFillColorWithColor(context, UIColorRGB(0x008df2).CGColor); - CGContextFillEllipseInRect(context, CGRectMake(4.0f, 4.0f, 8.0f, 8.0f)); - - largeDotImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - - UIGraphicsBeginImageContextWithOptions(CGSizeMake(16.0f, 16.0f), false, 0.0f); - context = UIGraphicsGetCurrentContext(); - - CGContextClearRect(context, CGRectMake(0, 0, 18.0f, 18.0f)); - - CGContextSetFillColorWithColor(context, UIColorRGB(0x3393fe).CGColor); - - CGContextMoveToPoint(context, 9, 0); - CGContextAddLineToPoint(context, 13, 7); - CGContextAddLineToPoint(context, 5, 7); - CGContextClosePath(context); - CGContextFillPath(context); - - CGContextSetBlendMode(context, kCGBlendModeClear); - CGContextFillEllipseInRect(context, CGRectMake(3.0, 3.0, 12.0, 12.0)); - - smallHeadingArrowImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - - UIGraphicsBeginImageContextWithOptions(CGSizeMake(33.0f, 33.0f), false, 0.0f); - context = UIGraphicsGetCurrentContext(); - - CGContextClearRect(context, CGRectMake(0, 0, 16.0f, 16.0f)); - - CGContextSetFillColorWithColor(context, UIColorRGB(0x3393fe).CGColor); - - CGContextMoveToPoint(context, 16.5, 0); - CGContextAddLineToPoint(context, 21.5, 6); - CGContextAddLineToPoint(context, 11.5, 6); - CGContextClosePath(context); - CGContextFillPath(context); - - CGContextSetBlendMode(context, kCGBlendModeClear); - CGContextFillEllipseInRect(context, CGRectMake(3.0, 3.0, 27.0, 27.0)); - - largeHeadingArrowImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - }); - - _smallView = [[UIImageView alloc] initWithImage:TGComponentsImageNamed(@"LocationSmallCircle")]; - _smallView.hidden = true; - [self addSubview:_smallView]; - - UIImage *dotImage = smallDotImage; - if ([annotation isKindOfClass:[TGLocationAnnotation class]]) - { - TGLocationAnnotation *locationAnnotation = (TGLocationAnnotation *)annotation; - if (locationAnnotation.location.period > 0) { - dotImage = largeDotImage; - } - } - - _dotView = [[UIImageView alloc] initWithImage:dotImage]; - [self addSubview:_dotView]; - - _smallArrowView = [[UIImageView alloc] initWithImage:smallHeadingArrowImage]; - _smallArrowView.hidden = true; - [self addSubview:_smallArrowView]; - - _arrowView = [[UIImageView alloc] initWithImage:largeHeadingArrowImage]; - _arrowView.hidden = true; - [self addSubview:_arrowView]; - - [self setAnnotation:annotation]; - } - return self; -} - -- (void)dealloc -{ - [self unsubscribeFromExpiration]; -} - -- (void)prepareForReuse -{ - [_pulseView stop]; - [_iconView reset]; - _smallView.hidden = true; - _backgroundView.hidden = false; -} - -- (void)subscribeForExpiration -{ - if (_observingExpiration) - return; - _observingExpiration = true; - [self addObserver:self forKeyPath:@"annotation.isExpired" options:NSKeyValueObservingOptionNew context:NULL]; - [self addObserver:self forKeyPath:@"annotation.heading" options:NSKeyValueObservingOptionNew context:NULL]; -} - -- (void)unsubscribeFromExpiration -{ - if (!_observingExpiration) - return; - _observingExpiration = false; - [self removeObserver:self forKeyPath:@"annotation.isExpired"]; - [self removeObserver:self forKeyPath:@"annotation.heading"]; -} - -- (void)setSelected:(BOOL)selected animated:(BOOL)animated -{ - if (iosMajorVersion() < 7) - animated = false; - - [super setSelected:selected animated:animated]; - - if (!_liveLocation) - return; - - if (animated) - { - [self layoutSubviews]; - _animating = true; - if (selected) - { - //dispatch_async(dispatch_get_main_queue(), ^ - //{ - UIView *avatarSnapshot = [_avatarView snapshotViewAfterScreenUpdates:false]; - [_smallView addSubview:avatarSnapshot]; - avatarSnapshot.transform = _avatarView.transform; - avatarSnapshot.center = CGPointMake(_smallView.frame.size.width / 2.0f, _smallView.frame.size.height / 2.0f); - - _avatarView.transform = CGAffineTransformIdentity; - [_backgroundView addSubview:_avatarView]; - _avatarView.center = CGPointMake(_backgroundView.frame.size.width / 2.0f, _backgroundView.frame.size.height / 2.0f - 5.0f); - - _dotView.alpha = 0.0f; - - _shadowView.center = CGPointMake(_shadowView.center.x, _shadowView.center.y + _shadowView.frame.size.height / 2.0f); - _shadowView.layer.anchorPoint = CGPointMake(0.5f, 1.0f); - _shadowView.hidden = false; - _shadowView.transform = CGAffineTransformMakeScale(0.1f, 0.1f); - [UIView animateWithDuration:0.35 delay:0.0 usingSpringWithDamping:0.6f initialSpringVelocity:0.5f options:kNilOptions animations:^ - { - _smallView.transform = CGAffineTransformMakeScale(0.001f, 0.001f); - _shadowView.transform = CGAffineTransformIdentity; - if (_dotView.hidden) - _smallView.alpha = 0.0f; - } completion:^(BOOL finished) - { - _animating = false; - _shadowView.layer.anchorPoint = CGPointMake(0.5f, 0.5f); - - _smallView.hidden = true; - _smallView.transform = CGAffineTransformIdentity; - [avatarSnapshot removeFromSuperview]; - - [self addSubview:_avatarView]; - }]; - - [UIView animateWithDuration:0.2 animations:^ - { - _dotView.alpha = 1.0f; - }]; - //}); - } - else - { - UIView *avatarSnapshot = [_avatarView snapshotViewAfterScreenUpdates:false]; - [_backgroundView addSubview:avatarSnapshot]; - avatarSnapshot.transform = _avatarView.transform; - avatarSnapshot.center = CGPointMake(_backgroundView.frame.size.width / 2.0f, _backgroundView.frame.size.height / 2.0f - 5.0f); - - _avatarView.transform = CGAffineTransformMakeScale(0.64f, 0.64f); - [_smallView addSubview:_avatarView]; - _avatarView.center = CGPointMake(_smallView.frame.size.width / 2.0f, _smallView.frame.size.height / 2.0f); - - _smallView.hidden = false; - _smallView.transform = CGAffineTransformMakeScale(0.01f, 0.01f); - - _shadowView.center = CGPointMake(_shadowView.center.x, _shadowView.center.y + _shadowView.frame.size.height / 2.0f); - _shadowView.layer.anchorPoint = CGPointMake(0.5f, 1.0f); - [UIView animateWithDuration:0.35 delay:0.0 usingSpringWithDamping:0.6f initialSpringVelocity:0.5f options:kNilOptions animations:^ - { - _smallView.transform = CGAffineTransformIdentity; - _shadowView.transform = CGAffineTransformMakeScale(0.1f, 0.1f); - if (_dotView.hidden) - _smallView.alpha = 1.0f; - } completion:^(BOOL finished) - { - _animating = false; - _shadowView.layer.anchorPoint = CGPointMake(0.5f, 0.5f); - - _shadowView.hidden = true; - _shadowView.transform = CGAffineTransformIdentity; - [avatarSnapshot removeFromSuperview]; - - [self addSubview:_avatarView]; - }]; - - [UIView animateWithDuration:0.1 animations:^ - { - _dotView.alpha = 0.0f; - } completion:nil]; - } - } - else - { - _smallView.hidden = selected; - _shadowView.hidden = !selected; - _dotView.alpha = selected ? 1.0f : 0.0f; - _smallView.alpha = 1.0f; - [self layoutSubviews]; - } - - [self updateHeading]; -} - -- (void)setPallete:(TGLocationPallete *)pallete -{ - if (pallete == nil || _pallete == pallete) - return; - - _pallete = pallete; - - UIImage *dotImage; - if ([self.annotation isKindOfClass:[TGLocationAnnotation class]]) - { - TGLocationAnnotation *locationAnnotation = (TGLocationAnnotation *)self.annotation; - if (locationAnnotation.location.period > 0) { - UIGraphicsBeginImageContextWithOptions(CGSizeMake(16.0f, 16.0f), false, 0.0f); - CGContextRef context = UIGraphicsGetCurrentContext(); - - CGContextSaveGState(context); - CGContextSetShadowWithColor(context, CGSizeMake(0, 1), 1.0f, [UIColor colorWithWhite:0.0f alpha:0.22f].CGColor); - CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor); - CGContextFillEllipseInRect(context, CGRectMake(2, 2, 12.0, 12.0)); - - CGContextRestoreGState(context); - - CGContextSetFillColorWithColor(context, pallete.locationColor.CGColor); - CGContextFillEllipseInRect(context, CGRectMake(4.0f, 4.0f, 8.0f, 8.0f)); - - dotImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - } - } - - if (dotImage == nil) { - UIGraphicsBeginImageContextWithOptions(CGSizeMake(6.0f, 6.0f), false, 0.0f); - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSetFillColorWithColor(context, pallete.locationColor.CGColor); - CGContextFillEllipseInRect(context, CGRectMake(0.0f, 0.0f, 6.0f, 6.0f)); - - dotImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - } - - _dotView.image = dotImage; - - [self setAnnotation:self.annotation]; -} - -- (void)setAnnotation:(id)annotation -{ - [super setAnnotation:annotation]; - - if ([annotation isKindOfClass:[TGLocationPickerAnnotation class]]) - { - _avatarView.hidden = false; - _avatarView.alpha = 1.0f; - _iconView.hidden = true; - _dotView.hidden = true; - - _backgroundView.image = TGComponentsImageNamed(@"LocationPinBackground"); - - _liveLocation = false; - [self setPeer:((TGLocationPickerAnnotation *)annotation).peer]; - - [self unsubscribeFromExpiration]; - } - else if ([annotation isKindOfClass:[TGLocationAnnotation class]]) - { - TGLocationAnnotation *locationAnnotation = ((TGLocationAnnotation *)annotation); - TGLocationMediaAttachment *location = locationAnnotation.location; - if (location.period == 0) - { - _dotView.hidden = false; - _avatarView.hidden = true; - _avatarView.alpha = 1.0f; - _iconView.hidden = false; - - UIColor *color = _pallete != nil ? _pallete.locationColor : UIColorRGB(0x008df2); - UIColor *pinColor = _pallete != nil ? _pallete.iconColor : [UIColor whiteColor]; - if (locationAnnotation.color != nil) { - color = locationAnnotation.color; - pinColor = [UIColor whiteColor]; - } - - _backgroundView.image = TGTintedImage(TGComponentsImageNamed(@"LocationPinBackground"), color); - if (location.venue.type.length > 0) - { - [_iconView loadUri:[NSString stringWithFormat:@"location-venue-icon://type=%@&width=%d&height=%d&color=%d", location.venue.type, 64, 64, TGColorHexCode(pinColor)] withOptions:nil]; - } - else - { - [_iconView reset]; - UIImage *image = TGComponentsImageNamed(@"LocationPinIcon"); - if (_pallete != nil) - image = TGTintedImage(image, _pallete.iconColor); - - _iconView.image = image; - } - - _liveLocation = false; - - [self unsubscribeFromExpiration]; - } - else - { - _avatarView.hidden = false; - _avatarView.alpha = locationAnnotation.isExpired ? 0.5f : 1.0f; - _iconView.hidden = true; - - _backgroundView.image = TGComponentsImageNamed(@"LocationPinBackground"); - - [self setPeer:locationAnnotation.peer]; - if (!locationAnnotation.isOwn) - { - if (!locationAnnotation.isExpired) - [_pulseView start]; - _dotView.hidden = false; - } - else - { - _dotView.hidden = true; - } - - [self subscribeForExpiration]; - - _liveLocation = true; - - if (!self.selected) - { - _shadowView.hidden = true; - _smallView.hidden = false; - } - } - } -} - -- (void)updateHeading -{ - if ([self.annotation isKindOfClass:[TGLocationAnnotation class]]) { - NSNumber *heading = ((TGLocationAnnotation *)self.annotation).heading; - - if (heading != nil) { - _arrowView.hidden = self.isSelected; - _smallArrowView.hidden = !self.isSelected; - _arrowView.transform = CGAffineTransformMakeRotation(heading.floatValue); - _smallArrowView.transform = CGAffineTransformMakeRotation(heading.floatValue); - } else { - _arrowView.hidden = true; - _smallArrowView.hidden = true; - } - } else { - _arrowView.hidden = true; - _smallArrowView.hidden = true; - } -} - -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context -{ - if ([keyPath isEqualToString:@"annotation.isExpired"]) - { - if (((TGLocationAnnotation *)self.annotation).isExpired) - { - [_pulseView stop]; - _avatarView.alpha = 0.5f; - } - else - { - [_pulseView start]; - _avatarView.alpha = 1.0f; - } - } - else if ([keyPath isEqual:@"annotation.heading"]) - { - [self updateHeading]; - } - else - { - [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; - } -} - -- (void)setPeer:(id)peer -{ - CGFloat diameter = 55.0f; - - static UIImage *placeholder = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^ - { - UIGraphicsBeginImageContextWithOptions(CGSizeMake(diameter, diameter), false, 0.0f); - CGContextRef context = UIGraphicsGetCurrentContext(); - - //!placeholder - CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor); - CGContextFillEllipseInRect(context, CGRectMake(0.0f, 0.0f, diameter, diameter)); - CGContextSetStrokeColorWithColor(context, UIColorRGB(0xd9d9d9).CGColor); - CGContextSetLineWidth(context, 1.0f); - CGContextStrokeEllipseInRect(context, CGRectMake(0.5f, 0.5f, diameter - 1.0f, diameter - 1.0f)); - - placeholder = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - }); - - if (_avatarView == nil) - { - _avatarView = [[TGLetteredAvatarView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 55.0f, 55.0f)]; - [_avatarView setSingleFontSize:24.0f doubleFontSize:24.0f useBoldFont:false]; - [self addSubview:_avatarView]; - } - else - { - [_avatarView.superview bringSubviewToFront:_avatarView]; - } - - bool isUser = [peer isKindOfClass:[TGUser class]]; - NSString *avatarUrl = isUser ? ((TGUser *)peer).photoFullUrlSmall : ((TGConversation *)peer).chatPhotoFullSmall; - if (avatarUrl.length != 0) - { - _avatarView.fadeTransitionDuration = 0.3; - if (![avatarUrl isEqualToString:_avatarView.currentUrl]) - [_avatarView loadImage:avatarUrl filter:@"circle:55x55" placeholder:placeholder]; - } - else - { - if (isUser) - { - [_avatarView loadUserPlaceholderWithSize:CGSizeMake(diameter, diameter) uid:((TGUser *)peer).uid firstName:((TGUser *)peer).firstName lastName:((TGUser *)peer).lastName placeholder:placeholder]; - } - else - { - [_avatarView loadGroupPlaceholderWithSize:CGSizeMake(diameter, diameter) conversationId:((TGConversation *)peer).conversationId title:((TGConversation *)peer).chatTitle placeholder:placeholder]; - } - } -} - -#pragma mark - Layout - -- (void)layoutSubviews -{ - [super layoutSubviews]; - - if (_animating) - return; - - _dotView.center = CGPointZero; - _smallView.center = CGPointZero; - _arrowView.center = CGPointZero; - _smallArrowView.center = CGPointZero; - _shadowView.center = CGPointMake(TGScreenPixel, -36.0f); - _backgroundView.center = CGPointMake(_shadowView.frame.size.width / 2.0f, _shadowView.frame.size.height / 2.0f); - _iconView.center = CGPointMake(_shadowView.frame.size.width / 2.0f, _shadowView.frame.size.height / 2.0f - 5.0f); - - if (_liveLocation) - { - if (self.selected) - { - _avatarView.center = CGPointMake(TGScreenPixel, -41.0f); - _avatarView.transform = CGAffineTransformIdentity; - } - else - { - _avatarView.center = CGPointZero; - _avatarView.transform = CGAffineTransformMakeScale(0.64f, 0.64f); - } - } - else - { - _avatarView.center = CGPointMake(TGScreenPixel, -41.0f); - _avatarView.transform = CGAffineTransformIdentity; - } -} - -- (void)setPinRaised:(bool)raised -{ - [self setPinRaised:raised avatar:false animated:false completion:nil]; -} - -- (void)setPinRaised:(bool)raised avatar:(bool)avatar animated:(bool)animated completion:(void (^)(void))completion -{ - _pinRaised = raised; - avatar = false; - - [_shadowView.layer removeAllAnimations]; - if (iosMajorVersion() < 7) - animated = false; - - if (animated) - { - if (raised) - { - [UIView animateWithDuration:0.2 delay:0.0 options:7 << 16 | UIViewAnimationOptionAllowAnimatedContent animations:^ - { - _shadowView.center = CGPointMake(TGScreenPixel, -66.0f); - if (avatar) - _avatarView.center = CGPointMake(TGScreenPixel, -71.0f); - } completion:^(BOOL finished) { - if (finished && completion != nil) - completion(); - }]; - } - else - { - [UIView animateWithDuration:0.2 delay:0.0 usingSpringWithDamping:0.6 initialSpringVelocity:0.0 options:UIViewAnimationOptionAllowAnimatedContent animations:^ - { - _shadowView.center = CGPointMake(TGScreenPixel, -36.0f); - if (avatar) - _avatarView.center = CGPointMake(TGScreenPixel, -41.0f); - } completion:^(BOOL finished) - { - if (finished && completion != nil) - completion(); - }]; - } - } - else - { - _shadowView.center = CGPointMake(TGScreenPixel, raised ? -66.0f : -36.0f); - if (avatar) - _avatarView.center = CGPointMake(TGScreenPixel, raised ? -71.0 : -41.0f); - - if (completion != nil) - completion(); - } -} - -- (void)setCustomPin:(bool)customPin animated:(bool)animated -{ - if (animated) - { - _animating = true; - UIImage *image = TGComponentsImageNamed(@"LocationPinIcon"); - if (_pallete != nil) - image = TGTintedImage(image, _pallete.iconColor); - - _iconView.image = image; - [_backgroundView addSubview:_avatarView]; - _avatarView.center = CGPointMake(_backgroundView.frame.size.width / 2.0f, _backgroundView.frame.size.height / 2.0f - 5.0f); - _shadowView.center = CGPointMake(TGScreenPixel, -36.0f); - _backgroundView.center = CGPointMake(_shadowView.frame.size.width / 2.0f, _shadowView.frame.size.height / 2.0f); - _iconView.center = CGPointMake(_shadowView.frame.size.width / 2.0f, _shadowView.frame.size.height / 2.0f - 5.0f); - - TGDispatchAfter(0.01, dispatch_get_main_queue(), ^ - { - [UIView transitionWithView:_backgroundView duration:0.2 options:UIViewAnimationOptionTransitionCrossDissolve | UIViewAnimationOptionAllowAnimatedContent animations:^ - { - _backgroundView.image = customPin ? TGTintedImage(TGComponentsImageNamed(@"LocationPinBackground"), _pallete != nil ? _pallete.locationColor : UIColorRGB(0x008df2)) : TGComponentsImageNamed(@"LocationPinBackground"); - _avatarView.hidden = customPin; - _iconView.hidden = !customPin; - } completion:^(BOOL finished) - { - if (!customPin) - [self addSubview:_avatarView]; - _animating = false; - [self setNeedsLayout]; - }]; - }); - - [self setNeedsLayout]; - } - else - { - - } - - _dotView.hidden = !customPin; -} - -@end - -@implementation TGLocationPinWrapperView - -- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event -{ - UIView *view = [super hitTest:point withEvent:event]; - if (view == self) - return nil; - - return view; -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationPinView.h b/submodules/LegacyComponents/Sources/TGLocationPinView.h deleted file mode 100644 index 3561f28de9..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationPinView.h +++ /dev/null @@ -1,11 +0,0 @@ -#import - -@class TGLocationPallete; - -@interface TGLocationPinView : UIView - -@property (nonatomic, strong) TGLocationPallete *pallete; -@property (nonatomic, assign, getter=isPinRaised) bool pinRaised; -- (void)setPinRaised:(bool)raised animated:(bool)animated completion:(void (^)(void))completion; - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationPinView.m b/submodules/LegacyComponents/Sources/TGLocationPinView.m deleted file mode 100644 index 099d43ef2d..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationPinView.m +++ /dev/null @@ -1,125 +0,0 @@ -#import "TGLocationPinView.h" - -#import "TGImageUtils.h" -#import "LegacyComponentsInternal.h" - -#import "TGLocationMapViewController.h" - -const CGSize TGLocationPinSize = { 13.5f, 36 }; -const CGFloat TGLocationPinDamping = 2.0f; -const CGFloat TGLocationPinPinnedOrigin = 47; -const CGFloat TGLocationPinRaisedOrigin = 7; -const CGPoint TGLocationPinShadowPinnedOrigin = { 43, 47 }; -const CGPoint TGLocationPinShadowRaisedOrigin = { 87, -33 }; - -@interface TGLocationPinView () -{ - UIImageView *_pinView; - UIImageView *_pinPointView; - UIImageView *_shadowView; -} -@end - -@implementation TGLocationPinView - -- (instancetype)init -{ - self = [super initWithFrame:CGRectMake(0, 0, 100, 100)]; - if (self != nil) - { - self.userInteractionEnabled = false; - - _shadowView = [[UIImageView alloc] initWithFrame:CGRectMake(43, 47, 32, 39)]; - _shadowView.alpha = 0.9f; - _shadowView.image = TGComponentsImageNamed(@"LocationPinShadow.png"); - [self addSubview:_shadowView]; - - _pinPointView = [[UIImageView alloc] initWithFrame:CGRectMake(CGFloor(self.frame.size.width / 2 - 2), self.frame.size.height - 18.5f, 3.5f, 1.5f)]; - _pinPointView.image = TGComponentsImageNamed(@"LocationPinPoint.png"); - [self addSubview:_pinPointView]; - - _pinView = [[UIImageView alloc] initWithFrame:CGRectMake(CGFloor(self.frame.size.width / 2 - 7), 47, 13.5f, 36)]; - _pinView.image = TGComponentsImageNamed(@"LocationPin.png"); - [self addSubview:_pinView]; - } - return self; -} - -- (void)setPallete:(TGLocationPallete *)pallete -{ - _pallete = pallete; - - _pinView.image = TGTintedImage(_pinView.image, pallete.locationColor); - _pinPointView.image = TGTintedImage(_pinPointView.image, pallete.locationColor); -} - -- (void)setPinRaised:(bool)pinRaised -{ - [self setPinRaised:pinRaised animated:false completion:nil]; -} - -- (void)setPinRaised:(bool)raised animated:(bool)animated completion:(void (^)(void))completion -{ - _pinRaised = raised; - - [_pinView.layer removeAllAnimations]; - [_shadowView.layer removeAllAnimations]; - - if (animated) - { - if (raised) - { - [UIView animateWithDuration:0.2f delay:0.0f options:UIViewAnimationOptionBeginFromCurrentState animations:^ - { - _pinView.frame = CGRectMake(_pinView.frame.origin.x, TGLocationPinRaisedOrigin, TGLocationPinSize.width, TGLocationPinSize.height); - _shadowView.frame = CGRectMake(TGLocationPinShadowRaisedOrigin.x, TGLocationPinShadowRaisedOrigin.y, _shadowView.frame.size.width, _shadowView.frame.size.height); - } completion:^(BOOL finished) - { - if (finished && completion != nil) - completion(); - }]; - } - else - { - [UIView animateWithDuration:0.2f delay:0.0f options:UIViewAnimationOptionBeginFromCurrentState animations:^ - { - _pinView.frame = CGRectMake(_pinView.frame.origin.x, TGLocationPinPinnedOrigin, TGLocationPinSize.width, TGLocationPinSize.height); - _shadowView.frame = CGRectMake(TGLocationPinShadowPinnedOrigin.x, TGLocationPinShadowPinnedOrigin.y, _shadowView.frame.size.width, _shadowView.frame.size.height); - } completion:^(BOOL finished) - { - if (finished) - { - [UIView animateWithDuration:0.1f delay:0.0f options:UIViewAnimationOptionBeginFromCurrentState animations:^ - { - _pinView.frame = CGRectMake(_pinView.frame.origin.x, TGLocationPinPinnedOrigin + TGLocationPinDamping, TGLocationPinSize.width, TGLocationPinSize.height - TGLocationPinDamping); - } completion:^(BOOL finished) - { - if (finished) - { - [UIView animateWithDuration:0.1f delay:0.0f options:UIViewAnimationOptionBeginFromCurrentState animations:^ - { - _pinView.frame = CGRectMake(_pinView.frame.origin.x, TGLocationPinPinnedOrigin, TGLocationPinSize.width, TGLocationPinSize.height); - } completion:^(BOOL finished) - { - if (finished && completion != nil) - completion(); - }]; - } - }]; - } - }]; - } - } - else - { - _pinView.frame = CGRectMake(_pinView.frame.origin.x, raised ? TGLocationPinRaisedOrigin : TGLocationPinPinnedOrigin, TGLocationPinSize.width, TGLocationPinSize.height); - - CGPoint shadowOrigin = raised ? TGLocationPinShadowRaisedOrigin : TGLocationPinShadowPinnedOrigin; - _shadowView.frame = CGRectMake(shadowOrigin.x, shadowOrigin.y, _shadowView.frame.size.width, _shadowView.frame.size.height); - - if (completion != nil) - completion(); - } -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationPulseView.m b/submodules/LegacyComponents/Sources/TGLocationPulseView.m deleted file mode 100644 index 050f8d8fd0..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationPulseView.m +++ /dev/null @@ -1,59 +0,0 @@ -#import "TGLocationPulseView.h" - -#import "LegacyComponentsInternal.h" - -@interface TGLocationPulseView () -{ - CAShapeLayer *_circleLayer; -} -@end - -@implementation TGLocationPulseView - -- (instancetype)initWithFrame:(CGRect)frame -{ - self = [super initWithFrame:frame]; - if (self != nil) - { - self.userInteractionEnabled = false; - - _circleLayer = [CAShapeLayer layer]; - _circleLayer.hidden = true; - _circleLayer.opacity = 0.0f; - _circleLayer.path = CGPathCreateWithEllipseInRect(CGRectMake(-60.0f, -60.0f, 120.0f, 120.0f), NULL); - _circleLayer.fillColor = UIColorRGBA(0x007aff, 0.27f).CGColor; - [self.layer addSublayer:_circleLayer]; - } - return self; -} - -- (void)start -{ - _circleLayer.hidden = false; - - if (_circleLayer.animationKeys.count > 0) - return; - - CAKeyframeAnimation *scaleAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"]; - scaleAnimation.values = @[@0.0f, @0.72f, @1.0f, @1.0f]; - scaleAnimation.keyTimes = @[@0.0, @0.49f, @0.88f, @1.0f]; - scaleAnimation.duration = 3.0; - scaleAnimation.repeatCount = INFINITY; - scaleAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; - [_circleLayer addAnimation:scaleAnimation forKey:@"circle-scale"]; - - CAKeyframeAnimation *opacityAnimation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"]; - opacityAnimation.values = @[@1.0f, @0.2f, @0.0, @0.0f]; - opacityAnimation.keyTimes = @[@0.0, @0.4f, @0.62f, @1.0f]; - opacityAnimation.duration = 3.0; - opacityAnimation.repeatCount = INFINITY; - [_circleLayer addAnimation:opacityAnimation forKey:@"circle-opacity"]; -} - -- (void)stop -{ - _circleLayer.hidden = true; - [_circleLayer removeAllAnimations]; -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationReverseGeocodeResult.h b/submodules/LegacyComponents/Sources/TGLocationReverseGeocodeResult.h deleted file mode 100644 index 02dd86e16f..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationReverseGeocodeResult.h +++ /dev/null @@ -1,23 +0,0 @@ -#import - -@interface TGLocationReverseGeocodeResult : NSObject - -@property (nonatomic, readonly) NSString *identifier; -@property (nonatomic, readonly) CLLocationCoordinate2D coordinate; - -@property (nonatomic, readonly) NSString *displayAddress; - -@property (nonatomic, readonly) NSString *country; -@property (nonatomic, readonly) NSString *countryAbbr; -@property (nonatomic, readonly) NSString *state; -@property (nonatomic, readonly) NSString *stateAbbr; -@property (nonatomic, readonly) NSString *city; -@property (nonatomic, readonly) NSString *district; -@property (nonatomic, readonly) NSString *street; - -@property (nonatomic, readonly) NSString *fullAddress; - -+ (TGLocationReverseGeocodeResult *)reverseGeocodeResultWithDictionary:(NSDictionary *)dictionary; -+ (TGLocationReverseGeocodeResult *)reverseGeocodeResultWithPlacemark:(CLPlacemark *)placemark; - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationReverseGeocodeResult.m b/submodules/LegacyComponents/Sources/TGLocationReverseGeocodeResult.m deleted file mode 100644 index 0274544642..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationReverseGeocodeResult.m +++ /dev/null @@ -1,85 +0,0 @@ -#import "TGLocationReverseGeocodeResult.h" - -@implementation TGLocationReverseGeocodeResult - -+ (TGLocationReverseGeocodeResult *)reverseGeocodeResultWithDictionary:(NSDictionary *)dictionary -{ - TGLocationReverseGeocodeResult *result = [[TGLocationReverseGeocodeResult alloc] init]; - - for (NSDictionary *component in dictionary[@"address_components"]) - { - NSArray *types = component[@"types"]; - __unused NSString *shortName = component[@"short_name"]; - NSString *longName = component[@"long_name"]; - - if ([types containsObject:@"country"]) - { - result->_country = longName; - result->_countryAbbr = shortName; - } - else if ([types containsObject:@"administrative_area_level_1"]) - { - result->_state = longName; - result->_stateAbbr = shortName; - } - else if ([types containsObject:@"locality"]) - { - result->_city = longName; - } - else if ([types containsObject:@"sublocality"]) - { - result->_district = longName; - } - else if ([types containsObject:@"neighborhood"]) - { - if (result->_district.length == 0) - result->_district = longName; - } - else if ([types containsObject:@"route"]) - { - result->_street = longName; - } - } - - return result; -} - -+ (TGLocationReverseGeocodeResult *)reverseGeocodeResultWithPlacemark:(CLPlacemark *)placemark -{ - TGLocationReverseGeocodeResult *result = [[TGLocationReverseGeocodeResult alloc] init]; - result->_country = placemark.country; - result->_countryAbbr = placemark.ISOcountryCode; - result->_city = placemark.locality; - result->_district = placemark.subLocality; - result->_street = placemark.thoroughfare; - if (placemark.name.length > 0 && result->_street.length == 0) { - result->_street = placemark.name; - } - return result; -} - -- (NSString *)displayAddress -{ - if (self.street.length > 0) - return self.street; - else if (self.city.length > 0) - return self.city; - else if (self.country.length > 0) - return self.country; - - return nil; -} - -- (NSString *)fullAddress -{ - NSMutableArray *components = [[NSMutableArray alloc] init]; - if (self.street.length > 0) - [components addObject:self.street]; - if (self.city.length > 0) - [components addObject:self.city]; - if (self.country.length > 0) - [components addObject:self.country]; - return [components componentsJoinedByString:@", "]; -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationSectionHeaderCell.h b/submodules/LegacyComponents/Sources/TGLocationSectionHeaderCell.h deleted file mode 100644 index d6d2169451..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationSectionHeaderCell.h +++ /dev/null @@ -1,14 +0,0 @@ -#import - -@class TGLocationPallete; - -@interface TGLocationSectionHeaderCell : UITableViewCell - -@property (nonatomic, strong) TGLocationPallete *pallete; - -- (void)configureWithTitle:(NSString *)title; - -@end - -extern NSString *const TGLocationSectionHeaderKind; -extern const CGFloat TGLocationSectionHeaderHeight; diff --git a/submodules/LegacyComponents/Sources/TGLocationSectionHeaderCell.m b/submodules/LegacyComponents/Sources/TGLocationSectionHeaderCell.m deleted file mode 100644 index 1ba6be10da..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationSectionHeaderCell.m +++ /dev/null @@ -1,73 +0,0 @@ -#import "TGLocationSectionHeaderCell.h" - -#import "TGLocationMapViewController.h" -#import "LegacyComponentsInternal.h" -#import "TGFont.h" - -NSString *const TGLocationSectionHeaderKind = @"TGLocationSectionHeaderKind"; -const CGFloat TGLocationSectionHeaderHeight = 29.0f; - -@interface TGLocationSectionHeaderCell () -{ - UILabel *_titleLabel; -} -@end - -@implementation TGLocationSectionHeaderCell - -- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier -{ - self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; - if (self != nil) - { - self.backgroundColor = UIColorRGB(0xf7f7f7); - self.selectedBackgroundView = [[UIView alloc] init]; - - _titleLabel = [[UILabel alloc] init]; - _titleLabel.backgroundColor = self.backgroundColor; - _titleLabel.font = TGMediumSystemFontOfSize(12); - _titleLabel.textColor = UIColorRGB(0x8e8e93); - [self addSubview:_titleLabel]; - } - return self; -} - -- (void)setPallete:(TGLocationPallete *)pallete -{ - if (pallete == nil || _pallete == pallete) - return; - - _pallete = pallete; - - self.backgroundColor = pallete.sectionHeaderBackgroundColor; - _titleLabel.backgroundColor = self.backgroundColor; - _titleLabel.textColor = pallete.sectionHeaderTextColor; -} - -- (void)configureWithTitle:(NSString *)title -{ - title = [title uppercaseString]; - - void (^changeBlock)(void) = ^ - { - _titleLabel.text = title; - }; - - if ([_titleLabel.text isEqualToString:title]) - return; - - if (_titleLabel.text.length == 0) - changeBlock(); - else - [UIView transitionWithView:_titleLabel duration:0.2 options:UIViewAnimationOptionTransitionCrossDissolve animations:changeBlock completion:nil]; -} - -- (void)layoutSubviews -{ - [super layoutSubviews]; - - CGFloat padding = 14.0f; - _titleLabel.frame = CGRectMake(padding, 1.0f, self.frame.size.width - padding, self.frame.size.height - 2.0f); -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationSignals.h b/submodules/LegacyComponents/Sources/TGLocationSignals.h deleted file mode 100644 index 5d534a4814..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationSignals.h +++ /dev/null @@ -1,18 +0,0 @@ -#import -#import - -@interface TGLocationSignals : NSObject - -+ (SSignal *)geocodeAddress:(NSString *)address; -+ (SSignal *)geocodeAddressDictionary:(NSDictionary *)dictionary; - -+ (SSignal *)reverseGeocodeCoordinate:(CLLocationCoordinate2D)coordinate; -+ (SSignal *)cityForCoordinate:(CLLocationCoordinate2D)coordinate; -+ (SSignal *)driveEta:(CLLocationCoordinate2D)coordinate; - -+ (void)storeLastKnownUserLocation:(CLLocation *)location; -+ (CLLocation *)lastKnownUserLocation; - -+ (SSignal *)userLocation:(SVariable *)locationRequired; - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationSignals.m b/submodules/LegacyComponents/Sources/TGLocationSignals.m deleted file mode 100644 index 46b631dba4..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationSignals.m +++ /dev/null @@ -1,257 +0,0 @@ -#import "TGLocationSignals.h" - -#import "LegacyComponentsInternal.h" -#import "TGStringUtils.h" - -#import - -#import -#import - -#import "TGLocationVenue.h" -#import "TGLocationReverseGeocodeResult.h" - -NSString *const TGLocationGoogleGeocodeLocale = @"en"; - -@interface TGLocationHelper : NSObject { - CLLocationManager *_locationManager; - void (^_locationDetermined)(CLLocation *); - bool _startedUpdating; -} - -@end - -@implementation TGLocationHelper - -- (instancetype)initWithLocationDetermined:(void (^)(CLLocation *))locationDetermined { - self = [super init]; - if (self != nil) { - _locationDetermined = [locationDetermined copy]; - - _locationManager = [[CLLocationManager alloc] init]; - _locationManager.delegate = self; - _locationManager.distanceFilter = kCLDistanceFilterNone; - _locationManager.desiredAccuracy = kCLLocationAccuracyBest; - - bool startUpdating = false; - if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) { - switch ([CLLocationManager authorizationStatus]) - { - case kCLAuthorizationStatusAuthorizedAlways: - case kCLAuthorizationStatusAuthorizedWhenInUse: - startUpdating = true; - default: - break; - } - } - - if (startUpdating) { - [self startUpdating]; - } - } - return self; -} - -- (void)dealloc { - [_locationManager stopUpdatingLocation]; -} - -- (void)startUpdating { - if (!_startedUpdating) { - _startedUpdating = true; - if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) { - [_locationManager requestWhenInUseAuthorization]; - } - [_locationManager startUpdatingLocation]; - } -} - -- (void)locationManager:(CLLocationManager *)__unused manager didUpdateLocations:(NSArray *)locations { - if (locations.count != 0) { - if (_locationDetermined) { - _locationDetermined([locations lastObject]); - } - } -} - -@end - -@implementation TGLocationSignals - -+ (SSignal *)geocodeAddress:(NSString *)address -{ - return [[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) - { - CLGeocoder *geocoder = [[CLGeocoder alloc] init]; - [geocoder geocodeAddressString:address completionHandler:^(NSArray * _Nullable placemarks, NSError * _Nullable error) - { - if (error != nil) - { - [subscriber putError:error]; - return; - } - else - { - [subscriber putNext:placemarks.firstObject]; - [subscriber putCompletion]; - } - }]; - - return [[SBlockDisposable alloc] initWithBlock:^ - { - [geocoder cancelGeocode]; - }]; - }]; -} - -+ (SSignal *)geocodeAddressDictionary:(NSDictionary *)dictionary -{ - return [[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) - { - CLGeocoder *geocoder = [[CLGeocoder alloc] init]; - [geocoder geocodeAddressDictionary:dictionary completionHandler:^(NSArray * _Nullable placemarks, NSError * _Nullable error) - { - if (error != nil) - { - [subscriber putError:error]; - return; - } - else - { - [subscriber putNext:placemarks.firstObject]; - [subscriber putCompletion]; - } - }]; - - return [[SBlockDisposable alloc] initWithBlock:^ - { - [geocoder cancelGeocode]; - }]; - }]; -} - -+ (SSignal *)reverseGeocodeCoordinate:(CLLocationCoordinate2D)coordinate -{ - return [[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) - { - CLGeocoder *geocoder = [[CLGeocoder alloc] init]; - [geocoder reverseGeocodeLocation:[[CLLocation alloc] initWithLatitude:coordinate.latitude longitude:coordinate.longitude] completionHandler:^(NSArray *placemarks, NSError *error) - { - if (error != nil) - { - [subscriber putError:error]; - return; - } - else - { - [subscriber putNext:[TGLocationReverseGeocodeResult reverseGeocodeResultWithPlacemark:placemarks.firstObject]]; - [subscriber putCompletion]; - } - }]; - - return [[SBlockDisposable alloc] initWithBlock:^ - { - [geocoder cancelGeocode]; - }]; - }]; -} - -+ (SSignal *)cityForCoordinate:(CLLocationCoordinate2D)coordinate -{ - return [[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) - { - CLGeocoder *geocoder = [[CLGeocoder alloc] init]; - [geocoder reverseGeocodeLocation:[[CLLocation alloc] initWithLatitude:coordinate.latitude longitude:coordinate.longitude] completionHandler:^(NSArray *placemarks, NSError *error) - { - if (error != nil) - { - [subscriber putError:error]; - return; - } - else - { - [subscriber putNext:[placemarks.firstObject locality]]; - [subscriber putCompletion]; - } - }]; - - return [[SBlockDisposable alloc] initWithBlock:^ - { - [geocoder cancelGeocode]; - }]; - }]; -} - -+ (SSignal *)driveEta:(CLLocationCoordinate2D)destinationCoordinate -{ - if (iosMajorVersion() < 7) - return [SSignal single:@0]; - - return [[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) - { - MKPlacemark *destinationPlacemark = [[MKPlacemark alloc] initWithCoordinate:destinationCoordinate addressDictionary:nil]; - MKMapItem *destinationMapItem = [[MKMapItem alloc] initWithPlacemark:destinationPlacemark]; - - MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init]; - request.source = [MKMapItem mapItemForCurrentLocation]; - request.destination = destinationMapItem; - request.transportType = MKDirectionsTransportTypeAutomobile; - request.requestsAlternateRoutes = false; - - MKDirections *directions = [[MKDirections alloc] initWithRequest:request]; - [directions calculateETAWithCompletionHandler:^(MKETAResponse *response, NSError *error) - { - if (error != nil) - { - [subscriber putError:error]; - return; - } - - [subscriber putNext:@(response.expectedTravelTime)]; - [subscriber putCompletion]; - }]; - - - return [[SBlockDisposable alloc] initWithBlock:^ - { - [directions cancel]; - }]; - }]; -} - -#pragma mark - - -static CLLocation *lastKnownUserLocation; - -+ (void)storeLastKnownUserLocation:(CLLocation *)location -{ - lastKnownUserLocation = location; -} - -+ (CLLocation *)lastKnownUserLocation -{ - NSTimeInterval locationAge = -[lastKnownUserLocation.timestamp timeIntervalSinceNow]; - if (locationAge > 600) - lastKnownUserLocation = nil; - - return lastKnownUserLocation; -} - -+ (SSignal *)userLocation:(SVariable *)locationRequired { - return [[[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { - TGLocationHelper *helper = [[TGLocationHelper alloc] initWithLocationDetermined:^(CLLocation *location) { - [subscriber putNext:location]; - }]; - - id requiredDisposable = [[[[locationRequired signal] take:1] deliverOn:[SQueue mainQueue]] startWithNext:^(__unused id next) { - [helper startUpdating]; - }]; - - return [[SBlockDisposable alloc] initWithBlock:^{ - [helper description]; // keep reference - [requiredDisposable dispose]; - }]; - }] startOn:[SQueue mainQueue]]; -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationTitleView.h b/submodules/LegacyComponents/Sources/TGLocationTitleView.h deleted file mode 100644 index aa96ebd5fe..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationTitleView.h +++ /dev/null @@ -1,12 +0,0 @@ -#import - -@interface TGLocationTitleView : UIView - -@property (nonatomic, strong) NSString *title; -@property (nonatomic, strong) NSString *address; - -@property (nonatomic, assign) UIInterfaceOrientation interfaceOrientation; -@property (nonatomic, assign) CGFloat backButtonWidth; -@property (nonatomic, assign) CGFloat actionsButtonWidth; - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationTitleView.m b/submodules/LegacyComponents/Sources/TGLocationTitleView.m deleted file mode 100644 index d8198d51e8..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationTitleView.m +++ /dev/null @@ -1,135 +0,0 @@ -#import "TGLocationTitleView.h" - -#import "LegacyComponentsInternal.h" -#import "TGFont.h" - -@interface TGLocationTitleView () -{ - UILabel *_titleLabel; - UILabel *_addressLabel; -} -@end - -@implementation TGLocationTitleView - -- (instancetype)initWithFrame:(CGRect)frame -{ - self = [super initWithFrame:frame]; - if (self != nil) - { - _titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 5, frame.size.width, 20)]; - _titleLabel.backgroundColor = [UIColor clearColor]; - _titleLabel.font = TGBoldSystemFontOfSize(17); - _titleLabel.textColor = [UIColor blackColor]; - _titleLabel.textAlignment = NSTextAlignmentCenter; - [self addSubview:_titleLabel]; - - _addressLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 21, frame.size.width, 21)]; - _addressLabel.backgroundColor = [UIColor clearColor]; - _addressLabel.font = TGSystemFontOfSize(13.0f); - _addressLabel.textColor = UIColorRGB(0x787878); - _addressLabel.textAlignment = NSTextAlignmentCenter; - [self addSubview:_addressLabel]; - } - return self; -} - -- (NSString *)title -{ - return _titleLabel.text; -} - -- (void)setTitle:(NSString *)title -{ - _titleLabel.text = title; - [self setNeedsLayout]; -} - -- (NSString *)address -{ - return _addressLabel.text; -} - -- (void)setAddress:(NSString *)address -{ - _addressLabel.text = address; - [self setNeedsLayout]; -} - -- (UIView *)_findNavigationBar:(UIView *)view -{ - if (view.superview == nil) - return nil; - else if ([view.superview isKindOfClass:[UINavigationBar class]]) - return view.superview; - else - return [self _findNavigationBar:view.superview]; -} - -- (void)layoutSubviews -{ - [super layoutSubviews]; - - [_titleLabel sizeToFit]; - [_addressLabel sizeToFit]; - - CGRect titleFrame = _titleLabel.frame; - titleFrame.size.width = CGCeil(titleFrame.size.width); - - CGRect addressFrame = _addressLabel.frame; - addressFrame.size.width = CGCeil(addressFrame.size.width); - - UIView *navigationBar = [self _findNavigationBar:self]; - CGRect offsetRect = [self.superview convertRect:self.frame toView:navigationBar]; - - UIEdgeInsets edges = UIEdgeInsetsMake(0, self.backButtonWidth, 0, navigationBar.frame.size.width - self.actionsButtonWidth); - - if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) - { - if (_addressLabel.text.length > 0) - titleFrame.origin.y = 5; - else - titleFrame.origin.y = 12; - - addressFrame.origin.y = 23.5f; - - titleFrame.origin.x = (navigationBar.frame.size.width - titleFrame.size.width) / 2; - if (titleFrame.origin.x < edges.left || CGRectGetMaxX(titleFrame) > edges.right) - { - titleFrame.origin.x = edges.left; - titleFrame.size.width = edges.right - edges.left; - } - - CGFloat titleCenter = CGRectGetMidX(titleFrame); - addressFrame.origin.x = titleCenter - addressFrame.size.width / 2; - if (addressFrame.origin.x < edges.left || CGRectGetMaxX(addressFrame) > edges.right) - { - addressFrame.origin.x = edges.left; - addressFrame.size.width = edges.right - edges.left; - } - } - else - { - titleFrame.origin.y = 10; - addressFrame.origin.y = 13; - - CGFloat jointWidth = titleFrame.size.width + addressFrame.size.width + 6; - CGFloat jointOrigin = (navigationBar.frame.size.width - jointWidth) / 2; - if (jointOrigin < edges.left || jointOrigin + jointWidth > edges.right) - { - jointOrigin = edges.left; - - CGFloat newJointWidth = edges.right - edges.left; - addressFrame.size.width -= (jointWidth - newJointWidth); - jointWidth = newJointWidth; - } - - titleFrame.origin.x = jointOrigin; - addressFrame.origin.x = jointOrigin + jointWidth - addressFrame.size.width; - } - - _titleLabel.frame = CGRectOffset(titleFrame, -offsetRect.origin.x, 0); - _addressLabel.frame = CGRectOffset(addressFrame, -offsetRect.origin.x, 0); -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationTrackingButton.h b/submodules/LegacyComponents/Sources/TGLocationTrackingButton.h deleted file mode 100644 index 351babf281..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationTrackingButton.h +++ /dev/null @@ -1,23 +0,0 @@ -#import -#import "TGModernButton.h" - -typedef enum { - TGLocationTrackingModeNone, - TGLocationTrackingModeFollow, - TGLocationTrackingModeFollowWithHeading -} TGLocationTrackingMode; - -@interface TGLocationTrackingButton : TGModernButton - -@property (nonatomic, assign) TGLocationTrackingMode trackingMode; -- (void)setTrackingMode:(TGLocationTrackingMode)trackingMode animated:(bool)animated; - -@property (nonatomic, assign, getter=isLocationAvailable) bool locationAvailable; -- (void)setLocationAvailable:(bool)available animated:(bool)animated; - -- (void)setAccentColor:(UIColor *)accentColor spinnerColor:(UIColor *)spinnerColor; - -+ (TGLocationTrackingMode)locationTrackingModeWithUserTrackingMode:(MKUserTrackingMode)mode; -+ (MKUserTrackingMode)userTrackingModeWithLocationTrackingMode:(TGLocationTrackingMode)mode; - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationTrackingButton.m b/submodules/LegacyComponents/Sources/TGLocationTrackingButton.m deleted file mode 100644 index 0735912848..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationTrackingButton.m +++ /dev/null @@ -1,151 +0,0 @@ -#import "TGLocationTrackingButton.h" - -#import "TGImageUtils.h" -#import "LegacyComponentsInternal.h" - -@interface TGLocationTrackingButton () -{ - UIImageView *_noneModeIconView; - UIImageView *_followModeIconView; - UIImageView *_followWithHeadingModeIconView; - UIActivityIndicatorView *_activityIndicator; -} -@end - -@implementation TGLocationTrackingButton - -- (instancetype)initWithFrame:(CGRect)frame -{ - self = [super initWithFrame:frame]; - if (self != nil) - { - self.exclusiveTouch = true; - - _noneModeIconView = [[UIImageView alloc] initWithFrame:self.bounds]; - _noneModeIconView.contentMode = UIViewContentModeCenter; - _noneModeIconView.image = TGComponentsImageNamed(@"TrackingLocationOff.png"); - [self addSubview:_noneModeIconView]; - - _followModeIconView = [[UIImageView alloc] initWithFrame:self.bounds]; - _followModeIconView.contentMode = UIViewContentModeCenter; - _followModeIconView.image = TGComponentsImageNamed(@"TrackingLocation.png"); - [self addSubview:_followModeIconView]; - - _followWithHeadingModeIconView = [[UIImageView alloc] initWithFrame:CGRectOffset(self.bounds, 1, 0.5f)]; - _followWithHeadingModeIconView.contentMode = UIViewContentModeCenter; - _followWithHeadingModeIconView.image = TGComponentsImageNamed(@"TrackingHeading.png"); - [self addSubview:_followWithHeadingModeIconView]; - - _activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; - _activityIndicator.userInteractionEnabled = false; - _activityIndicator.frame = CGRectOffset(_activityIndicator.frame, 0, 0); - _activityIndicator.alpha = 0.0f; - _activityIndicator.transform = CGAffineTransformMakeScale(0.1f, 0.1f); - [self addSubview:_activityIndicator]; - - _locationAvailable = true; - [self setTrackingMode:TGLocationTrackingModeNone]; - } - return self; -} - -- (void)setAccentColor:(UIColor *)accentColor spinnerColor:(UIColor *)spinnerColor -{ - _noneModeIconView.image = TGTintedImage(TGComponentsImageNamed(@"TrackingLocationOff.png"), accentColor); - _followModeIconView.image = TGTintedImage(TGComponentsImageNamed(@"TrackingLocation.png"), accentColor); - _followWithHeadingModeIconView.image = TGTintedImage(TGComponentsImageNamed(@"TrackingHeading.png"), accentColor); - _activityIndicator.color = spinnerColor; -} - -- (void)setTrackingMode:(TGLocationTrackingMode)trackingMode -{ - [self setTrackingMode:trackingMode animated:false]; -} - -- (void)setTrackingMode:(TGLocationTrackingMode)trackingMode animated:(bool)animated -{ - _trackingMode = trackingMode; - - CGFloat noneModeAlpha = (trackingMode == TGLocationTrackingModeNone) ? 1.0f : 0.0f; - CGFloat followModeAlpha = (trackingMode == TGLocationTrackingModeFollow) ? 1.0f : 0.0f; - CGFloat followWithHeadingModeAlpha = (trackingMode == TGLocationTrackingModeFollowWithHeading) ? 1.0f : 0.0f; - - void (^changeBlock)(void) = ^ - { - _noneModeIconView.alpha = noneModeAlpha; - _followModeIconView.alpha = followModeAlpha; - _followWithHeadingModeIconView.alpha = followWithHeadingModeAlpha; - - if (followWithHeadingModeAlpha < FLT_EPSILON) - { - _noneModeIconView.transform = CGAffineTransformIdentity; - _followModeIconView.transform = CGAffineTransformIdentity; - _followWithHeadingModeIconView.transform = CGAffineTransformMakeScale(0.1f, 0.1f); - } - else - { - _noneModeIconView.transform = CGAffineTransformMakeScale(0.1f, 0.1f); - _followModeIconView.transform = CGAffineTransformMakeScale(0.1f, 0.1f); - _followWithHeadingModeIconView.transform = CGAffineTransformIdentity; - } - }; - - if (animated) - [UIView animateWithDuration:0.2f delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:changeBlock completion:nil]; - else - changeBlock(); -} - -- (void)setIsLocationAvailable:(bool)available -{ - [self setLocationAvailable:available animated:false]; -} - -- (void)setLocationAvailable:(bool)available animated:(bool)animated -{ - if (available == _locationAvailable) - return; - - _locationAvailable = available; - - if (animated) - { - - } - else - { - - } -} - -+ (TGLocationTrackingMode)locationTrackingModeWithUserTrackingMode:(MKUserTrackingMode)mode -{ - switch (mode) - { - case MKUserTrackingModeFollow: - return TGLocationTrackingModeFollow; - - case MKUserTrackingModeFollowWithHeading: - return TGLocationTrackingModeFollowWithHeading; - - default: - return TGLocationTrackingModeNone; - } -} - -+ (MKUserTrackingMode)userTrackingModeWithLocationTrackingMode:(TGLocationTrackingMode)mode -{ - switch (mode) - { - case TGLocationTrackingModeFollow: - return MKUserTrackingModeFollow; - - case TGLocationTrackingModeFollowWithHeading: - return MKUserTrackingModeFollowWithHeading; - - default: - return MKUserTrackingModeNone; - } -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationUtils.h b/submodules/LegacyComponents/Sources/TGLocationUtils.h deleted file mode 100644 index 56bd839f3c..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationUtils.h +++ /dev/null @@ -1,50 +0,0 @@ -#import -#import - -@interface TGLocationUtils : NSObject - -+ (MKMapRect)MKMapRectForCoordinateRegion:(MKCoordinateRegion)region; - -+ (bool)requestWhenInUserLocationAuthorizationWithLocationManager:(CLLocationManager *)locationManager; -+ (bool)requestAlwaysUserLocationAuthorizationWithLocationManager:(CLLocationManager *)locationManager; - -+ (NSString *)stringFromDistance:(CLLocationDistance)distance; -+ (NSString *)stringFromAccuracy:(CLLocationAccuracy)accuracy; - -+ (NSString *)stringForCoordinate:(CLLocationCoordinate2D)coordinate; - -@end - -@interface TGLocationUtils (GoogleMaps) - -+ (CLLocationDegrees)adjustGMapLatitude:(CLLocationDegrees)latitude withPixelOffset:(NSInteger)offset zoom:(NSInteger)zoom; -+ (CLLocationDegrees)adjustGMapLongitude:(CLLocationDegrees)longitude withPixelOffset:(NSInteger)offset zoom:(NSInteger)zoom; -+ (CLLocationCoordinate2D)adjustGMapCoordinate:(CLLocationCoordinate2D)coordinate withPixelOffset:(CGPoint)offset zoom:(NSInteger)zoom; - -@end - -@interface TGLocationUtils (ThirdPartyAppLauncher) - -+ (void)openMapsWithCoordinate:(CLLocationCoordinate2D)coordinate withDirections:(bool)withDirections locationName:(NSString *)locationName; - -+ (void)openGoogleMapsWithCoordinate:(CLLocationCoordinate2D)coordinate withDirections:(bool)withDirections; -+ (bool)isGoogleMapsInstalled; - -+ (void)openGoogleWithPlaceId:(NSString *)placeId; - -+ (void)openFoursquareWithVenueId:(NSString *)venueId; -+ (bool)isFoursquareInstalled; - -+ (void)openHereMapsWithCoordinate:(CLLocationCoordinate2D)coordinate; -+ (bool)isHereMapsInstalled; - -+ (void)openYandexMapsWithCoordinate:(CLLocationCoordinate2D)coordinate withDirections:(bool)withDirections; -+ (bool)isYandexMapsInstalled; - -+ (void)openDirectionsInYandexNavigatorWithCoordinate:(CLLocationCoordinate2D)coordinate; -+ (bool)isYandexNavigatorInstalled; - -+ (void)openWazeWithCoordinate:(CLLocationCoordinate2D)coordinate withDirections:(bool)withDirections; -+ (bool)isWazeInstalled; - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationUtils.m b/submodules/LegacyComponents/Sources/TGLocationUtils.m deleted file mode 100644 index 30d4a1fbea..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationUtils.m +++ /dev/null @@ -1,381 +0,0 @@ -#import "TGLocationUtils.h" - -#import "LegacyComponentsInternal.h" -#import "TGLocalization.h" - -#import - -@implementation TGLocationUtils - -+ (MKMapRect)MKMapRectForCoordinateRegion:(MKCoordinateRegion)region -{ - MKMapPoint a = MKMapPointForCoordinate(CLLocationCoordinate2DMake(region.center.latitude + region.span.latitudeDelta / 2, - region.center.longitude - region.span.longitudeDelta / 2)); - MKMapPoint b = MKMapPointForCoordinate(CLLocationCoordinate2DMake(region.center.latitude - region.span.latitudeDelta / 2, - region.center.longitude + region.span.longitudeDelta / 2)); - return MKMapRectMake(MIN(a.x,b.x), MIN(a.y,b.y), ABS(a.x-b.x), ABS(a.y-b.y)); -} - -+ (bool)requestWhenInUserLocationAuthorizationWithLocationManager:(CLLocationManager *)locationManager -{ - CLAuthorizationStatus authorizationStatus = [CLLocationManager authorizationStatus]; - - if (authorizationStatus == kCLAuthorizationStatusDenied || authorizationStatus == kCLAuthorizationStatusRestricted) - return false; - - if ([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) - { - if (authorizationStatus == kCLAuthorizationStatusNotDetermined) - [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"TG_askedForAlwaysAuthorization_v0"]; - - [locationManager requestWhenInUseAuthorization]; - return true; - } - - return false; -} - -+ (bool)requestAlwaysUserLocationAuthorizationWithLocationManager:(CLLocationManager *)locationManager -{ - CLAuthorizationStatus authorizationStatus = [CLLocationManager authorizationStatus]; - if (authorizationStatus == kCLAuthorizationStatusDenied || authorizationStatus == kCLAuthorizationStatusRestricted) - return false; - - if ([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) - { - NSString *key = @"TG_askedForAlwaysAuthorization_v0"; - bool askedForAlwaysAuthorization = [[[NSUserDefaults standardUserDefaults] objectForKey:key] boolValue]; - if (authorizationStatus == kCLAuthorizationStatusAuthorizedWhenInUse && askedForAlwaysAuthorization) - return false; - - [locationManager requestAlwaysAuthorization]; - [[NSUserDefaults standardUserDefaults] setObject:@true forKey:key]; - - return true; - } - - return false; -} - -+ (NSString *)stringFromDistance:(CLLocationDistance)distance -{ - if (iosMajorVersion() >= 7) - { - MKDistanceFormatter *formatter = [self sharedDistanceFormatter]; - NSString *systemLocale = [NSLocale currentLocale].localeIdentifier; - NSString *finalLocale = legacyEffectiveLocalization().code; - NSRange range = [systemLocale rangeOfString:@"_"]; - if (range.location != NSNotFound) { - finalLocale = [finalLocale stringByAppendingString:[systemLocale substringFromIndex:range.location]]; - } - formatter.locale = [NSLocale localeWithLocaleIdentifier:finalLocale]; - if ([[formatter.locale objectForKey:NSLocaleUsesMetricSystem] boolValue]) - formatter.unitStyle = MKDistanceFormatterUnitStyleAbbreviated; - else - formatter.unitStyle = MKDistanceFormatterUnitStyleDefault; - - return [[self sharedDistanceFormatter] stringFromDistance:distance]; - } - else - { - return [self _customStringFromDistance:distance]; - } -} - -+ (NSString *)stringFromAccuracy:(CLLocationAccuracy)accuracy -{ - if (iosMajorVersion() >= 7) - { - MKDistanceFormatter *formatter = [self sharedAccuracyFormatter]; - //formatter.locale = [NSLocale localeWithLocaleIdentifier:legacyEffectiveLocalization().code]; - return [[self sharedAccuracyFormatter] stringFromDistance:accuracy]; - } - else - { - return [self _customStringFromDistance:accuracy]; - } -} - -+ (NSString *)stringForCoordinate:(CLLocationCoordinate2D)coordinate -{ - NSInteger latSeconds = (NSInteger)(coordinate.latitude * 3600); - NSInteger latDegrees = latSeconds / 3600; - latSeconds = labs(latSeconds % 3600); - NSInteger latMinutes = latSeconds / 60; - latSeconds %= 60; - - NSInteger longSeconds = (NSInteger)(coordinate.longitude * 3600); - NSInteger longDegrees = longSeconds / 3600; - longSeconds = labs(longSeconds % 3600); - NSInteger longMinutes = longSeconds / 60; - longSeconds %= 60; - - NSString *result = [NSString stringWithFormat:@"%@%02ld° %02ld' %02ld\" %@%02ld° %02ld' %02ld\"", latDegrees >= 0 ? @"N" : @"S", labs(latDegrees), (long)latMinutes, (long)latSeconds, longDegrees >= 0 ? @"E" : @"W", labs(longDegrees), (long)longMinutes, (long)longSeconds]; - - return result; -} - -+ (NSString *)_customStringFromDistance:(CLLocationDistance)distance -{ - NSLocale *locale = [NSLocale localeWithLocaleIdentifier:legacyEffectiveLocalization().code]; - bool metricUnits = [[locale objectForKey:NSLocaleUsesMetricSystem] boolValue]; - - NSString *distanceString = nil; - - if (metricUnits) - { - if (distance >= 1000 * 1000) - distanceString = [[NSString alloc] initWithFormat:@"%.1fK km", distance / (1000.0 * 1000.0)]; - else if (distance > 1000) - distanceString = [[NSString alloc] initWithFormat:@"%.1f km", distance / 1000.0]; - else - distanceString = [[NSString alloc] initWithFormat:@"%d m", (int)distance]; - } - else - { - double feetDistance = distance / 0.3048; - - if (feetDistance >= 5280) - { - char buf[32]; - snprintf(buf, 32, "%.1f", feetDistance / 5280.0); - bool dot = false; - for (int i = 0; i < 32; i++) - { - char c = buf[i]; - if (c == '\0') - break; - else if (c < '0' || c > '9') - { - dot = true; - break; - } - } - distanceString = [[NSString alloc] initWithFormat:@"%s mile%s", buf, dot || feetDistance / 5280.0 > 1.0 ? "s" : ""]; - } - else - { - distanceString = [[NSString alloc] initWithFormat:@"%d %s", (int)feetDistance, (int)feetDistance != 1 ? "feet" : "foot"]; - } - } - - return distanceString; -} - -+ (MKDistanceFormatter *)sharedDistanceFormatter -{ - static dispatch_once_t once; - static MKDistanceFormatter *distanceFormatter; - dispatch_once(&once, ^ - { - distanceFormatter = [[MKDistanceFormatter alloc] init]; - }); - - return distanceFormatter; -} - -+ (MKDistanceFormatter *)sharedAccuracyFormatter -{ - static dispatch_once_t once; - static MKDistanceFormatter *accuracyFormatter; - dispatch_once(&once, ^ - { - accuracyFormatter = [[MKDistanceFormatter alloc] init]; - accuracyFormatter.unitStyle = MKDistanceFormatterUnitStyleFull; - }); - - return accuracyFormatter; -} - -@end - -const NSInteger TGGoogleMapsOffset = 268435456; -const CGFloat TGGoogleMapsRadius = TGGoogleMapsOffset / (CGFloat)M_PI; - -@implementation TGLocationUtils (GoogleMaps) - -+ (CLLocationCoordinate2D)adjustGMapCoordinate:(CLLocationCoordinate2D)coordinate withPixelOffset:(CGPoint)offset zoom:(NSInteger)zoom -{ - return CLLocationCoordinate2DMake([self adjustGMapLatitude:coordinate.latitude withPixelOffset:(NSInteger)offset.y zoom:zoom], [self adjustGMapLongitude:coordinate.longitude withPixelOffset:(NSInteger)offset.x zoom:zoom]); -} - -+ (CLLocationDegrees)adjustGMapLatitude:(CLLocationDegrees)latitude withPixelOffset:(NSInteger)offset zoom:(NSInteger)zoom -{ - return [self _yToLatitude:([self _latitudeToY:latitude] + (offset << (21 - zoom)))]; -} - -+ (CLLocationDegrees)adjustGMapLongitude:(CLLocationDegrees)longitude withPixelOffset:(NSInteger)offset zoom:(NSInteger)zoom -{ - return [self _xToLongitude:([self _longitudeToX:longitude] + (offset << (21 - zoom)))]; -} - -+ (NSInteger)_latitudeToY:(CLLocationDegrees)latitude -{ - return (NSInteger)round(TGGoogleMapsOffset - TGGoogleMapsRadius * log((1 + sin(latitude * M_PI / 180.0)) / (1 - sin(latitude * M_PI / 180.0))) / 2); -} - -+ (CLLocationDegrees)_yToLatitude:(NSInteger)y -{ - return (M_PI_2 - 2 * atan(exp((y - TGGoogleMapsOffset) / TGGoogleMapsRadius))) * 180.0 / M_PI; -} - -+ (NSInteger)_longitudeToX:(CLLocationDegrees)longitude -{ - return (NSInteger)round(TGGoogleMapsOffset + TGGoogleMapsRadius * longitude * M_PI / 180); -} - -+ (CLLocationDegrees)_xToLongitude:(NSInteger)x -{ - return (x - TGGoogleMapsOffset) / TGGoogleMapsRadius * 180.0 / M_PI; -} - -@end - -@implementation TGLocationUtils (ThirdPartyAppLauncher) - -#pragma mark Apple Maps - -+ (void)openMapsWithCoordinate:(CLLocationCoordinate2D)coordinate withDirections:(bool)withDirections locationName:(NSString *)locationName -{ - MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:coordinate - addressDictionary:nil]; - MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:placemark]; - [mapItem setName:locationName]; - - if (withDirections) - { - NSDictionary *options = @{ MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving }; - MKMapItem *currentLocationMapItem = [MKMapItem mapItemForCurrentLocation]; - [MKMapItem openMapsWithItems:@[ currentLocationMapItem, mapItem ] - launchOptions:options]; - } - else - { - [mapItem openInMapsWithLaunchOptions:nil]; - } -} - -#pragma mark Google Maps - -+ (void)openGoogleMapsWithCoordinate:(CLLocationCoordinate2D)coordinate withDirections:(bool)withDirections -{ - NSURL *url = nil; - NSString *coordinatePair = [NSString stringWithFormat:@"%f,%f", coordinate.latitude, coordinate.longitude]; - - if (withDirections) - { - url = [NSURL URLWithString:[[NSString alloc] initWithFormat:@"comgooglemaps-x-callback://?daddr=%@&directionsmode=driving&x-success=telegram://?resume=true&&x-source=Telegram", coordinatePair]]; - } - else - { - url = [NSURL URLWithString:[[NSString alloc] initWithFormat:@"comgooglemaps-x-callback://?center=%@&q=%@&x-success=telegram://?resume=true&&x-source=Telegram", coordinatePair, coordinatePair]]; - } - - [[LegacyComponentsGlobals provider] openURL:url]; -} - -+ (bool)isGoogleMapsInstalled -{ - return [[LegacyComponentsGlobals provider] canOpenURL:[NSURL URLWithString:@"comgooglemaps-x-callback://"]]; -} - - -+ (void)openGoogleWithPlaceId:(NSString *)placeId -{ - NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://maps.google.com/maps/place?cid=%@", placeId]]; - [[LegacyComponentsGlobals provider] openURL:url]; -} -#pragma mark Foursquare - -+ (void)openFoursquareWithVenueId:(NSString *)venueId -{ - NSURL *url = nil; - - if ([self isFoursquareInstalled]) - url = [NSURL URLWithString:[NSString stringWithFormat:@"foursquare://venues/%@", venueId]]; - else - url = [NSURL URLWithString:[NSString stringWithFormat:@"https://foursquare.com/venue/%@", venueId]]; - - [[LegacyComponentsGlobals provider] openURL:url]; -} - -+ (bool)isFoursquareInstalled -{ - return [[LegacyComponentsGlobals provider] canOpenURL:[NSURL URLWithString:@"foursquare://"]]; -} - -#pragma mark Here Maps - -+ (void)openHereMapsWithCoordinate:(CLLocationCoordinate2D)coordinate -{ - NSURL *url = [NSURL URLWithString:[[NSString alloc] initWithFormat:@"here-location://%f,%f", coordinate.latitude, coordinate.longitude]]; - - [[LegacyComponentsGlobals provider] openURL:url]; -} - -+ (bool)isHereMapsInstalled -{ - return [[LegacyComponentsGlobals provider] canOpenURL:[NSURL URLWithString:@"here-location://"]]; -} - -#pragma mark Yandex Maps - -+ (void)openYandexMapsWithCoordinate:(CLLocationCoordinate2D)coordinate withDirections:(bool)withDirections -{ - NSURL *url = nil; - - if (withDirections) - { - url = [NSURL URLWithString:[[NSString alloc] initWithFormat:@"yandexmaps://build_route_on_map?lat_to=%f&lon_to=%f", coordinate.latitude, coordinate.longitude]]; - } - else - { - url = [NSURL URLWithString:[[NSString alloc] initWithFormat:@"yandexmaps://maps.yandex.ru/?pt=%f,%f&z=16", coordinate.longitude, coordinate.latitude]]; - } - - [[LegacyComponentsGlobals provider] openURL:url]; -} - -+ (bool)isYandexMapsInstalled -{ - return [[LegacyComponentsGlobals provider] canOpenURL:[NSURL URLWithString:@"yandexmaps://"]]; -} - -#pragma mark Yandex Navigator - -+ (void)openDirectionsInYandexNavigatorWithCoordinate:(CLLocationCoordinate2D)coordinate -{ - NSURL *url = [NSURL URLWithString:[[NSString alloc] initWithFormat:@"yandexnavi://build_route_on_map?lat_to=%f&lon_to=%f", coordinate.latitude, coordinate.longitude]]; - - [[LegacyComponentsGlobals provider] openURL:url]; -} - -+ (bool)isYandexNavigatorInstalled -{ - return [[LegacyComponentsGlobals provider] canOpenURL:[NSURL URLWithString:@"yandexnavi://"]]; -} - -#pragma mark - Waze - -+ (void)openWazeWithCoordinate:(CLLocationCoordinate2D)coordinate withDirections:(bool)withDirections -{ - NSURL *url = nil; - - if (withDirections) - { - url = [NSURL URLWithString:[[NSString alloc] initWithFormat:@"waze://?ll=%f,%f&navigate=yes", coordinate.latitude, coordinate.longitude]]; - } - else - { - url = [NSURL URLWithString:[[NSString alloc] initWithFormat:@"waze://?ll=%f,%f", coordinate.latitude, coordinate.longitude]]; - } - - [[LegacyComponentsGlobals provider] openURL:url]; -} - -+ (bool)isWazeInstalled -{ - return [[LegacyComponentsGlobals provider] canOpenURL:[NSURL URLWithString:@"waze://"]]; -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationVenue.m b/submodules/LegacyComponents/Sources/TGLocationVenue.m deleted file mode 100644 index b981c95cd2..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationVenue.m +++ /dev/null @@ -1,118 +0,0 @@ -#import "TGLocationVenue.h" - -#import - -NSString *const TGLocationGooglePlacesVenueProvider = @"google"; -NSString *const TGLocationFoursquareVenueProvider = @"foursquare"; - -@interface TGLocationVenue () -{ - NSString *_displayAddress; -} -@end - -@implementation TGLocationVenue - -+ (TGLocationVenue *)venueWithFoursquareDictionary:(NSDictionary *)dictionary -{ - TGLocationVenue *venue = [[TGLocationVenue alloc] init]; - venue->_identifier = dictionary[@"id"]; - venue->_name = dictionary[@"name"]; - - NSDictionary *location = dictionary[@"location"]; - venue->_coordinate = CLLocationCoordinate2DMake([location[@"lat"] doubleValue], [location[@"lng"] doubleValue]); - - NSArray *categories = dictionary[@"categories"]; - if (categories.count > 0) - { - NSDictionary *category = categories.firstObject; - NSDictionary *icon = category[@"icon"]; - if (icon != nil) - venue->_categoryIconUrl = [NSURL URLWithString:[NSString stringWithFormat:@"%@64%@", icon[@"prefix"], icon[@"suffix"]]]; - - NSURL *url = [NSURL URLWithString:icon[@"prefix"]]; - NSArray *components = url.pathComponents; - NSString *categoryName = [[NSString stringWithFormat:@"%@/%@", [components objectAtIndex:components.count - 2], components.lastObject] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"_"]]; - venue->_categoryName = categoryName; - } - - venue->_country = location[@"country"]; - venue->_state = location[@"state"]; - venue->_city = location[@"city"]; - venue->_address = location[@"address"]; - venue->_crossStreet = location[@"crossStreet"]; - - venue->_provider = TGLocationFoursquareVenueProvider; - - return venue; -} - -+ (TGLocationVenue *)venueWithGooglePlacesDictionary:(NSDictionary *)dictionary -{ - TGLocationVenue *venue = [[TGLocationVenue alloc] init]; - venue->_identifier = dictionary[@"place_id"]; - venue->_name = dictionary[@"name"]; - - NSDictionary *location = dictionary[@"geometry"][@"location"]; - venue->_coordinate = CLLocationCoordinate2DMake([location[@"lat"] doubleValue], [location[@"lng"] doubleValue]); - - NSArray *types = dictionary[@"types"]; - if (types.count > 0) - { - if ([types containsObject:@"political"]) - return nil; - - venue->_categoryName = types.firstObject; - } - - venue->_displayAddress = dictionary[@"vicinity"]; - - venue->_provider = TGLocationGooglePlacesVenueProvider; - - return venue; -} - -+ (TGLocationVenue *)venueWithLocationAttachment:(TGLocationMediaAttachment *)attachment -{ - TGLocationVenue *venue = [[TGLocationVenue alloc] init]; - venue->_identifier = attachment.venue.venueId; - venue->_name = attachment.venue.title; - - venue->_coordinate = CLLocationCoordinate2DMake(attachment.latitude, attachment.longitude); - venue->_categoryName = attachment.venue.type; - - venue->_displayAddress = attachment.venue.address; - - venue->_provider = attachment.venue.provider; - - return venue; -} - -- (NSString *)displayAddress -{ - if (_displayAddress.length > 0) - return _displayAddress; - if (self.street.length > 0) - return self.street; - else if (self.city.length > 0) - return self.city; - else if (self.country.length > 0) - return self.country; - - return nil; -} - -- (NSString *)street -{ - if (self.address.length > 0) - return self.address; - else - return self.crossStreet; -} - -- (TGVenueAttachment *)venueAttachment -{ - return [[TGVenueAttachment alloc] initWithTitle:self.name address:self.displayAddress provider:self.provider venueId:self.identifier type:self.categoryName]; -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationVenueCell.h b/submodules/LegacyComponents/Sources/TGLocationVenueCell.h deleted file mode 100644 index 0019c192b6..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationVenueCell.h +++ /dev/null @@ -1,17 +0,0 @@ -#import - -@class TGLocationVenue; -@class TGLocationPallete; - -@interface TGLocationVenueCell : UITableViewCell - -@property (nonatomic, strong) TGLocationPallete *pallete; - -- (void)configureWithVenue:(TGLocationVenue *)venue; - -+ (UIImage *)circleImage; - -@end - -extern NSString *const TGLocationVenueCellKind; -extern const CGFloat TGLocationVenueCellHeight; diff --git a/submodules/LegacyComponents/Sources/TGLocationVenueCell.m b/submodules/LegacyComponents/Sources/TGLocationVenueCell.m deleted file mode 100644 index 90a2bd7446..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationVenueCell.m +++ /dev/null @@ -1,140 +0,0 @@ -#import "TGLocationVenueCell.h" - -#import "TGLocationMapViewController.h" -#import "LegacyComponentsInternal.h" -#import "TGColor.h" -#import "TGFont.h" -#import "TGStringUtils.h" -#import "TGImageUtils.h" - -#import "TGLocationVenue.h" - -#import - -NSString *const TGLocationVenueCellKind = @"TGLocationVenueCell"; -const CGFloat TGLocationVenueCellHeight = 56.0f; - -@interface TGLocationVenueCell () -{ - UIImageView *_circleView; - TGImageView *_iconView; - UILabel *_titleLabel; - UILabel *_addressLabel; - UIView *_separatorView; -} -@end - -@implementation TGLocationVenueCell - -- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier -{ - self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; - if (self != nil) - { - self.selectedBackgroundView = [[UIView alloc] init]; - self.selectedBackgroundView.backgroundColor = TGSelectionColor(); - - _circleView = [[UIImageView alloc] initWithFrame:CGRectMake(12.0f, 12.0f, 48.0f, 48.0f)]; - [self setCircleColor:UIColorRGB(0xf2f2f2)]; - [self.contentView addSubview:_circleView]; - - _iconView = [[TGImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 48.0f, 48.0f)]; - _iconView.contentMode = UIViewContentModeCenter; - [_circleView addSubview:_iconView]; - - _titleLabel = [[UILabel alloc] init]; - _titleLabel.backgroundColor = [UIColor clearColor]; - _titleLabel.font = TGSystemFontOfSize(16.0f); - _titleLabel.textColor = [UIColor blackColor]; - [self.contentView addSubview:_titleLabel]; - - _addressLabel = [[UILabel alloc] init]; - _addressLabel.backgroundColor = [UIColor clearColor]; - _addressLabel.font = TGSystemFontOfSize(13); - _addressLabel.textColor = UIColorRGB(0x8e8e93); - [self.contentView addSubview:_addressLabel]; - - _separatorView = [[UIView alloc] init]; - _separatorView.backgroundColor = TGSeparatorColor(); - [self addSubview:_separatorView]; - } - return self; -} - -- (void)setPallete:(TGLocationPallete *)pallete -{ - if (pallete == nil || _pallete == pallete) - return; - - _pallete = pallete; - - self.backgroundColor = pallete.backgroundColor; - self.selectedBackgroundView.backgroundColor = pallete.selectionColor; - [self setCircleColor:pallete.sectionHeaderBackgroundColor]; - _titleLabel.textColor = pallete.textColor; - _addressLabel.textColor = pallete.secondaryTextColor; - _separatorView.backgroundColor = pallete.separatorColor; -} - -- (void)setCircleColor:(UIColor *)color -{ - UIImage *circleImage = [TGLocationVenueCell circleImage]; - _circleView.image = TGTintedImage(circleImage, color); -} - -- (void)prepareForReuse -{ - [super prepareForReuse]; - [_iconView reset]; -} - -- (void)configureWithVenue:(TGLocationVenue *)venue -{ - _titleLabel.text = venue.name; - _addressLabel.text = venue.displayAddress; - if (venue.categoryName.length > 0) - { - [_iconView loadUri:[NSString stringWithFormat:@"location-venue-icon://type=%@&width=%d&height=%d&color=%d", venue.categoryName, 48, 48, TGColorHexCode(_pallete != nil ? _pallete.sectionHeaderTextColor : UIColorRGB(0xa0a0a0))] withOptions:nil]; - } - else - { - UIImage *pinImage = TGComponentsImageNamed(@"LocationMessagePinIcon"); - if (self.pallete != nil) - pinImage = TGTintedImage(pinImage, self.pallete.sectionHeaderTextColor); - else - pinImage = TGTintedImage(pinImage, UIColorRGB(0xa0a0a0)); - [_iconView loadUri:@"embedded://" withOptions:@{ TGImageViewOptionEmbeddedImage:pinImage }]; - } -} - -- (void)layoutSubviews -{ - [super layoutSubviews]; - - CGFloat padding = 76.0f; - CGFloat separatorThickness = TGScreenPixel; - - _circleView.frame = CGRectMake(12.0f, 4.0f, 48.0f, 48.0f); - _iconView.frame = CGRectMake(0.0f, 0.0f, 48.0f, 48.0f); - _titleLabel.frame = CGRectMake(padding, 8, self.frame.size.width - padding - 14, 20); - _addressLabel.frame = CGRectMake(padding, 29, self.frame.size.width - padding - 14, 20); - _separatorView.frame = CGRectMake(padding, self.frame.size.height - separatorThickness, self.frame.size.width - padding, separatorThickness); -} - -+ (UIImage *)circleImage -{ - static dispatch_once_t onceToken; - static UIImage *circleImage; - dispatch_once(&onceToken, ^ - { - UIGraphicsBeginImageContextWithOptions(CGSizeMake(48.0f, 48.0f), false, 0.0f); - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor); - CGContextFillEllipseInRect(context, CGRectMake(0.0f, 0.0f, 48.0f, 48.0f)); - circleImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - }); - return circleImage; -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationViewController.m b/submodules/LegacyComponents/Sources/TGLocationViewController.m deleted file mode 100644 index a2d540b4e8..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationViewController.m +++ /dev/null @@ -1,1410 +0,0 @@ -#import "TGLocationViewController.h" - -#import "LegacyComponentsInternal.h" - -#import "TGNavigationBar.h" -#import "TGUser.h" -#import "TGConversation.h" -#import "TGMessage.h" -#import "TGImageUtils.h" -#import "TGFont.h" - -#import - -#import "TGLocationUtils.h" -#import "TGLocationSignals.h" - -#import "TGLocationVenue.h" -#import "TGLocationAnnotation.h" - -#import "TGLocationTitleView.h" -#import "TGLocationMapView.h" -#import "TGLocationTrackingButton.h" -#import "TGLocationMapModeControl.h" -#import "TGLocationPinAnnotationView.h" - -#import "TGLocationOptionsView.h" -#import "TGLocationInfoCell.h" -#import "TGLocationLiveCell.h" - -#import - -@interface TGLiveLocation () - -- (CLLocation *)location; - -@end - -@interface TGLocationViewController () -{ - id _context; - bool _dismissing; - - id _peer; - TGMessage *_message; - TGLocationMediaAttachment *_locationAttachment; - UIColor *_venueColor; - - TGLocationAnnotation *_annotation; - - UIBarButtonItem *_actionsBarItem; - bool _didSetRightBarButton; - - SVariable *_reloadReady; - SMetaDisposable *_reloadDisposable; - - id _frequentUpdatesDisposable; - - SSignal *_signal; - TGLiveLocation *_currentLiveLocation; - SMetaDisposable *_liveLocationsDisposable; - NSArray *_initialLiveLocations; - NSArray *_liveLocations; - bool _hasOwnLiveLocation; - bool _ownLocationExpired; - - bool _presentedLiveLocations; - bool _selectedCurrentLiveLocation; - - bool _ignoreNextUpdates; - bool _focusOnOwnLocation; - bool _throttle; - TGLocationPinAnnotationView *_ownLiveLocationView; - __weak MKAnnotationView *_userLocationView; - - UIImageView *_headingArrowView; -} -@end - -@implementation TGLocationViewController - -- (instancetype)initWithContext:(id)context locationAttachment:(TGLocationMediaAttachment *)locationAttachment peer:(id)peer color:(UIColor *)color -{ - self = [self initWithContext:context]; - if (self != nil) - { - _locationAttachment = locationAttachment; - _venueColor = color; - - _reloadDisposable = [[SMetaDisposable alloc] init]; - _reloadReady = [[SVariable alloc] init]; - [self setReloadReady:true]; - - _context = context; - _peer = peer; - - if (locationAttachment.period == 0) - _annotation = [[TGLocationAnnotation alloc] initWithLocation:locationAttachment color:color]; - - _liveLocationsDisposable = [[SMetaDisposable alloc] init]; - - self.titleText = locationAttachment.period > 0 ? TGLocalized(@"Map.LiveLocationTitle") : TGLocalized(@"Map.LocationTitle"); - } - return self; -} - -- (instancetype)initWithContext:(id)context liveLocation:(TGLiveLocation *)liveLocation -{ - self = [self initWithContext:context]; - if (self != nil) - { - _message = liveLocation.message; - _locationAttachment = liveLocation.message.locationAttachment; - _currentLiveLocation = liveLocation; - if (liveLocation) - { - _liveLocations = @[liveLocation]; - _hasOwnLiveLocation = liveLocation.hasOwnSession; - if (_hasOwnLiveLocation) - _ownLocationExpired = liveLocation.isExpired; - } - _reloadDisposable = [[SMetaDisposable alloc] init]; - _reloadReady = [[SVariable alloc] init]; - [self setReloadReady:true]; - - _context = context; - _peer = liveLocation.peer; - - _liveLocationsDisposable = [[SMetaDisposable alloc] init]; - - self.titleText = _locationAttachment.period > 0 ? TGLocalized(@"Map.LiveLocationTitle") : TGLocalized(@"Map.LocationTitle"); - } - return self; -} - -- (instancetype)initWithContext:(id)context message:(TGMessage *)message peer:(id)peer color:(UIColor *)color -{ - self = [self initWithContext:context]; - if (self != nil) - { - _message = message; - _locationAttachment = message.locationAttachment; - - _reloadDisposable = [[SMetaDisposable alloc] init]; - _reloadReady = [[SVariable alloc] init]; - [self setReloadReady:true]; - - _context = context; - _peer = peer; - _venueColor = color; - - if (_locationAttachment.period == 0) - _annotation = [[TGLocationAnnotation alloc] initWithLocation:_locationAttachment color:color]; - - _liveLocationsDisposable = [[SMetaDisposable alloc] init]; - - self.titleText = _locationAttachment.period > 0 ? TGLocalized(@"Map.LiveLocationTitle") : TGLocalized(@"Map.LocationTitle"); - } - return self; -} - -- (void)dealloc -{ - _mapView.delegate = nil; - [_liveLocationsDisposable dispose]; - [_reloadDisposable dispose]; - [_frequentUpdatesDisposable dispose]; - - [_locationManager stopUpdatingHeading]; -} - -- (void)tg_setRightBarButtonItem:(UIBarButtonItem *)barButtonItem action:(bool)action animated:(bool)animated { - if (self.updateRightBarItem != nil) { - self.updateRightBarItem(barButtonItem, action, animated); - } else { - [self setRightBarButtonItem:barButtonItem animated:animated]; - } -} - -- (void)setFrequentUpdatesHandle:(id)disposable -{ - _frequentUpdatesDisposable = disposable; -} - -- (void)setLiveLocationsSignal:(SSignal *)signal -{ - if (_currentLiveLocation.isOwnLocation) - { - _signal = [[signal reduceLeftWithPassthrough:nil with:^id(id current, id value, void (^emit)(id)) - { - if (current == nil) - { - emit([SSignal single:value]); - return @true; - } - else - { - emit([[SSignal single:value] delay:0.25 onQueue:[SQueue concurrentDefaultQueue]]); - return current; - } - }] switchToLatest]; - } - else - { - __weak TGLocationViewController *weakSelf = self; - _signal = [signal mapToSignal:^SSignal *(id value) - { - __strong TGLocationViewController *strongSelf = weakSelf; - if (strongSelf == nil) - return nil; - - if (strongSelf->_throttle) - return [[SSignal single:value] delay:0.25 onQueue:[SQueue concurrentDefaultQueue]]; - else - return [SSignal single:value]; - }]; - } - - [self setupSignals]; -} - -- (void)setLiveLocations:(NSArray *)liveLocations actual:(bool)actual -{ - if (liveLocations.count == 0 && _currentLiveLocation != nil) - liveLocations = @[ _currentLiveLocation ]; - - TGLiveLocation *ownLiveLocation = nil; - for (TGLiveLocation *liveLocation in liveLocations) - { - if (liveLocation.hasOwnSession) - { - ownLiveLocation = liveLocation; - break; - } - } - - _hasOwnLiveLocation = ownLiveLocation != nil; - _ownLocationExpired = ownLiveLocation.isExpired; - - if (_hasOwnLiveLocation && !_ownLocationExpired) - { - TGLocationAnnotation *annotation = [[TGLocationAnnotation alloc] initWithLocation:ownLiveLocation.message.locationAttachment]; - annotation.peer = ownLiveLocation.peer; - annotation.isOwn = true; - - if (_ownLiveLocationView == nil) - { - _ownLiveLocationView = [[TGLocationPinAnnotationView alloc] initWithAnnotation:annotation]; - _ownLiveLocationView.pallete = self.pallete; - _ownLiveLocationView.frame = CGRectOffset(_ownLiveLocationView.frame, 21.0f, 22.0f); - [_userLocationView addSubview:_ownLiveLocationView]; - - if (_currentLiveLocation.hasOwnSession) - [self selectOwnAnnotationAnimated:false]; - } - else - { - _ownLiveLocationView.annotation = annotation; - } - } - else - { - [_ownLiveLocationView removeFromSuperview]; - _ownLiveLocationView = nil; - } - - CGFloat previousLocationsCount = _liveLocations.count; - _liveLocations = liveLocations; - [self reloadData]; - - if (!_presentedLiveLocations && actual) - { - _presentedLiveLocations = true; - if (previousLocationsCount < liveLocations.count > 0) - { - CGFloat updatedHeight = [self possibleContentHeight] - [self visibleContentHeight]; - if (fabs(-_tableView.contentInset.top + updatedHeight - _tableView.contentOffset.y) > FLT_EPSILON) - { - TGDispatchAfter(0.3, dispatch_get_main_queue(), ^ - { - [self setReloadReady:false]; - [_tableView setContentOffset:CGPointMake(0.0f, -_tableView.contentInset.top + updatedHeight) animated:true]; - }); - } - } - - if (_currentLiveLocation.hasOwnSession && !_ownLocationExpired && !self.zoomToFitAllLocationsOnScreen) - { - [_mapView setUserTrackingMode:[TGLocationTrackingButton userTrackingModeWithLocationTrackingMode:TGLocationTrackingModeFollow] animated:false]; - [_optionsView setTrackingMode:TGLocationTrackingModeFollow animated:true]; - } - } - [self updateAnnotations]; - - if ([self isLiveLocation]) - { - if ([self hasMoreThanOneLocation]) - { - if (!_didSetRightBarButton) - { - _didSetRightBarButton = true; - [self tg_setRightBarButtonItem:_actionsBarItem action:false animated:true]; - } - - if (actual && self.zoomToFitAllLocationsOnScreen) - { - _zoomToFitAllLocationsOnScreen = false; - dispatch_async(dispatch_get_main_queue(), ^ - { - MKMapRect visibleMapRect = _mapView.visibleMapRect; - NSSet *visibleAnnotations = [_mapView annotationsInMapRect:visibleMapRect]; - if (visibleAnnotations.count == _mapView.annotations.count) - return; - - [self showAllPressed]; - }); - } - } - else - { - if (_didSetRightBarButton) - { - _didSetRightBarButton = false; - [self tg_setRightBarButtonItem:nil action:false animated:true]; - } - } - } - - if (_focusOnOwnLocation) - { - if (_ownLiveLocationView != nil && !_ownLiveLocationView.isSelected) - { - [self selectOwnAnnotationAnimated:false]; - _focusOnOwnLocation = false; - _throttle = false; - - dispatch_async(dispatch_get_main_queue(), ^ - { - MKMapRect visibleMapRect = _mapView.visibleMapRect; - NSSet *visibleAnnotations = [_mapView annotationsInMapRect:visibleMapRect]; - if (visibleAnnotations.count == _mapView.annotations.count) - return; - - [self showAllPressed]; - }); - } - } -} - -- (bool)handleOwnAnnotationTap:(CGPoint)location -{ - if (_ownLiveLocationView == nil) - return false; - - if (CGRectContainsPoint([_ownLiveLocationView.superview convertRect:CGRectInset(_ownLiveLocationView.frame, -16.0f, - 16.0f) toView:_mapView], location)) - { - [self selectOwnAnnotation]; - [self setMapCenterCoordinate:_ownLiveLocationView.annotation.coordinate offset:CGPointZero animated:true]; - return true; - } - - return false; -} - -- (void)reloadData -{ - [_reloadDisposable setDisposable:[[self reloadReadySignal] startWithNext:nil completed:^ - { - [_tableView reloadData]; - _edgeView.highlighted = false; - }]]; -} - -double DegreesToRadians(double degrees) {return degrees * M_PI / 180.0;}; -double RadiansToDegrees(double radians) {return radians * 180.0/M_PI;}; - -- (double)bearingFromLocation:(CLLocationCoordinate2D)fromLocation toLocation:(CLLocationCoordinate2D)toLocation -{ - double lat1 = DegreesToRadians(fromLocation.latitude); - double lon1 = DegreesToRadians(fromLocation.longitude); - - double lat2 = DegreesToRadians(toLocation.latitude); - double lon2 = DegreesToRadians(toLocation.longitude); - - double dLon = lon2 - lon1; - - double y = sin(dLon) * cos(lat2); - double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon); - double radiansBearing = atan2(y, x); - - return radiansBearing; -} - -- (void)updateAnnotations -{ - NSMutableDictionary *liveLocations = [[NSMutableDictionary alloc] init]; - for (TGLiveLocation *liveLocation in _liveLocations) - { - if (!liveLocation.hasOwnSession || liveLocation.isExpired) - liveLocations[@(liveLocation.message.mid)] = liveLocation; - } - - TGLocationAnnotation *currentAnnotation = nil; - NSMutableSet *annotationsToRemove = [[NSMutableSet alloc] init]; - for (TGLocationAnnotation *annotation in _mapView.annotations) - { - if (![annotation isKindOfClass:[TGLocationAnnotation class]] || annotation == _annotation) - continue; - - if (liveLocations[@(annotation.messageId)] != nil) - { - [UIView animateWithDuration:0.3 animations:^{ - CLLocationCoordinate2D previousCoordinate = annotation.coordinate; - annotation.coordinate = [(TGLiveLocation *)liveLocations[@(annotation.messageId)] location].coordinate; - - - CLLocation *previous = [[CLLocation alloc] initWithLatitude:previousCoordinate.latitude longitude:previousCoordinate.longitude]; - CLLocation *new = [[CLLocation alloc] initWithLatitude:annotation.coordinate.latitude longitude:annotation.coordinate.longitude]; -// if ([new distanceFromLocation:previous] > 20) { - CGFloat hdg = [self bearingFromLocation:previousCoordinate toLocation:annotation.coordinate]; - if (hdg != 0.0) { - annotation.heading = @(hdg); - } -// } - }]; - annotation.isExpired = [(TGLiveLocation *)liveLocations[@(annotation.messageId)] isExpired]; - [liveLocations removeObjectForKey:@(annotation.messageId)]; - - if (annotation.messageId == _currentLiveLocation.message.mid) - currentAnnotation = annotation; - } - else - { - [annotationsToRemove addObject:annotation]; - } - } - - [_mapView removeAnnotations:annotationsToRemove.allObjects]; - - NSMutableArray *newAnnotations = [[NSMutableArray alloc] init]; - for (TGLiveLocation *liveLocation in liveLocations.allValues) - { - TGLocationAnnotation *annotation = [[TGLocationAnnotation alloc] initWithLocation:liveLocation.message.locationAttachment]; - annotation.peer = liveLocation.peer; - annotation.messageId = liveLocation.message.mid; - annotation.isExpired = liveLocation.isExpired; - - [newAnnotations addObject:annotation]; - - if (annotation.messageId == _currentLiveLocation.message.mid) - currentAnnotation = annotation; - } - - [_mapView addAnnotations:newAnnotations]; - - NSInteger annotationsCount = _ownLiveLocationView != nil ? 1 : 0; - for (TGLocationAnnotation *annotation in _mapView.annotations) - { - if ([annotation isKindOfClass:[TGLocationAnnotation class]] && ((TGLocationAnnotation *)annotation).isLiveLocation) - annotationsCount += 1; - } - - _mapView.allowAnnotationSelectionChanges = annotationsCount; - - if (!_selectedCurrentLiveLocation && currentAnnotation != nil) - { - _selectedCurrentLiveLocation = true; - dispatch_async(dispatch_get_main_queue(), ^ - { - [_mapView setSelectedAnnotations:@[currentAnnotation]]; - }); - } -} - -- (void)loadView -{ - [super loadView]; - - static UIImage *headingArrowImage = nil; - static dispatch_once_t onceToken; - - dispatch_once(&onceToken, ^ - { - UIGraphicsBeginImageContextWithOptions(CGSizeMake(28.0f, 28.0f), false, 0.0f); - CGContextRef context = UIGraphicsGetCurrentContext(); - - CGContextClearRect(context, CGRectMake(0, 0, 28, 28)); - - CGContextSetFillColorWithColor(context, UIColorRGB(0x3393fe).CGColor); - - CGContextMoveToPoint(context, 14, 0); - CGContextAddLineToPoint(context, 19, 7); - CGContextAddLineToPoint(context, 9, 7); - CGContextClosePath(context); - CGContextFillPath(context); - - CGContextSetBlendMode(context, kCGBlendModeClear); - CGContextFillEllipseInRect(context, CGRectMake(5.0, 5.0, 18.0, 18.0)); - - headingArrowImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - }); - - _headingArrowView = [[UIImageView alloc] init]; - _headingArrowView.hidden = true; - _headingArrowView.frame = CGRectMake(0.0, 0.0, 28.0, 28.0); - _headingArrowView.image = headingArrowImage; - - _tableView.scrollsToTop = false; - _mapView.tapEnabled = false; - - __weak TGLocationViewController *weakSelf = self; - _mapView.customAnnotationTap = ^bool(CGPoint location) - { - __strong TGLocationViewController *strongSelf = weakSelf; - if (strongSelf == nil) - return false; - return [strongSelf handleOwnAnnotationTap:location]; - }; - - if (TGIsPad() || _modalMode) - { - [self setLeftBarButtonItem:[[UIBarButtonItem alloc] initWithTitle:TGLocalized(@"Common.Done") style:UIBarButtonItemStyleDone target:self action:@selector(dismissButtonPressed)]]; - } - - if ([self isLiveLocation]) - { - NSString *actionsButtonTitle = TGLocalized(@"Map.LiveLocationShowAll"); - _actionsBarItem = [[UIBarButtonItem alloc] initWithTitle:actionsButtonTitle style:UIBarButtonItemStylePlain target:self action:@selector(showAllPressed)]; - } - else - { - if (iosMajorVersion() >= 7) - { - _actionsBarItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(actionsButtonPressed)]; - [self tg_setRightBarButtonItem:_actionsBarItem action:true animated:false]; - } - else - { - NSString *actionsButtonTitle = TGLocalized(@"Common.More"); - _actionsBarItem = [[UIBarButtonItem alloc] initWithTitle:actionsButtonTitle style:UIBarButtonItemStylePlain target:self action:@selector(actionsButtonPressed)]; - [self tg_setRightBarButtonItem:_actionsBarItem action:true animated:false]; - } - } - - if (_previewMode) - _optionsView.hidden = true; -} - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - [_mapView addAnnotation:_annotation]; - [_mapView selectAnnotation:_annotation animated:false]; - - _mapView.region = MKCoordinateRegionMake([self locationCoordinate], MKCoordinateSpanMake(0.008, 0.008)); - - [TGLocationUtils requestWhenInUserLocationAuthorizationWithLocationManager:_locationManager]; -} - -- (void)viewWillAppear:(BOOL)animated -{ - [super viewWillAppear:animated]; - - [_locationManager startUpdatingHeading]; - - if (self.previewMode && !animated) - { - UIView *contentView = [[_mapView subviews] firstObject]; - UIView *annotationContainer = nil; - for (NSUInteger i = 1; i < contentView.subviews.count; i++) - { - UIView *view = contentView.subviews[i]; - if ([NSStringFromClass(view.class) rangeOfString:@"AnnotationContainer"].location != NSNotFound) - { - annotationContainer = view; - break; - } - } - - for (UIView *view in annotationContainer.subviews) - view.frame = CGRectOffset(view.frame, 0, 48.5f); - } - - if ([_tableView numberOfRowsInSection:0] > 0) - [_tableView layoutSubviews]; - - CGFloat updatedHeight = [self possibleContentHeight] - [self visibleContentHeight]; - [_tableView setContentOffset:CGPointMake(0.0f, -_tableView.contentInset.top + updatedHeight) animated:false]; - - if (_initialLiveLocations.count > 0) - { - [self setLiveLocations:_initialLiveLocations actual:false]; - _initialLiveLocations = nil; - } -} - -- (void)viewDidAppear:(BOOL)animated -{ - [super viewDidAppear:animated]; - if (self.onViewDidAppear != nil) - self.onViewDidAppear(); -} - -- (void)setupSignals -{ - SSignal *combinedSignal = [SSignal combineSignals:@[ [[[self userLocationSignal] deliverOn:[SQueue concurrentBackgroundQueue]] map:^id(id location) { - if (location != nil) - return location; - else - return [NSNull null]; - }], _signal ]]; - - __weak TGLocationViewController *weakSelf = self; - [_liveLocationsDisposable setDisposable:[combinedSignal startWithNext:^(NSArray *next) - { - __strong TGLocationViewController *strongSelf = weakSelf; - if (strongSelf == nil) - return; - - if (strongSelf->_dismissing) - return; - - CLLocation *currentLocation = [next.firstObject isKindOfClass:[CLLocation class]] ? next.firstObject : nil; - NSArray *liveLocations = next.lastObject; - bool actual = liveLocations.count > 0; - - NSMutableArray *filteredLiveLocations = [[NSMutableArray alloc] init]; - bool hasCurrentLocation = false; - bool currentExpiredLocationIsOwn = false; - for (TGLiveLocation *liveLocation in liveLocations) - { - if (!liveLocation.isExpired) - [filteredLiveLocations addObject:liveLocation]; - if (liveLocation.message.mid == strongSelf->_currentLiveLocation.message.mid) - hasCurrentLocation = true; - } - if (!hasCurrentLocation && strongSelf->_currentLiveLocation != nil) - { - bool isChannel = [strongSelf->_currentLiveLocation.peer isKindOfClass:[TGConversation class]] && !((TGConversation *)strongSelf->_currentLiveLocation.peer).isChannelGroup; - - TGLiveLocation *currentExpiredLiveLocation = [[TGLiveLocation alloc] initWithMessage:strongSelf->_currentLiveLocation.message peer:strongSelf->_currentLiveLocation.peer hasOwnSession:strongSelf->_currentLiveLocation.hasOwnSession isOwnLocation:strongSelf->_currentLiveLocation.isOwnLocation isExpired:isChannel ? strongSelf->_currentLiveLocation.isExpired : true]; - [filteredLiveLocations addObject:currentExpiredLiveLocation]; - - if (currentExpiredLiveLocation.isOwnLocation && currentExpiredLiveLocation.isExpired) - currentExpiredLocationIsOwn = true; - } - liveLocations = filteredLiveLocations; - - for (TGLiveLocation *location in filteredLiveLocations) - { - if (strongSelf->_ignoreNextUpdates && location.hasOwnSession && !location.isExpired && (currentExpiredLocationIsOwn || (strongSelf->_currentLiveLocation.isOwnLocation && strongSelf->_currentLiveLocation.isExpired))) - { - strongSelf->_dismissing = true; - TGDispatchOnMainThread(^ - { - if (strongSelf.openLocation != nil) - strongSelf.openLocation(location.message); - }); - return; - } - } - - if (strongSelf->_ignoreNextUpdates) - return; - - NSMutableArray *sortedLiveLocations = [liveLocations mutableCopy]; - if (currentLocation != nil) - { - [sortedLiveLocations sortUsingComparator:^NSComparisonResult(TGLiveLocation *obj1, TGLiveLocation *obj2) - { - if (obj1.hasOwnSession) - return NSOrderedAscending; - else if (obj2.hasOwnSession) - return NSOrderedDescending; - - if (obj1.message.mid == strongSelf->_currentLiveLocation.message.mid) - return NSOrderedAscending; - else if (obj2.message.mid == strongSelf->_currentLiveLocation.message.mid) - return NSOrderedDescending; - - CGFloat distance1 = [obj1.location distanceFromLocation:currentLocation]; - CGFloat distance2 = [obj2.location distanceFromLocation:currentLocation]; - - if (distance1 > distance2) - return NSOrderedDescending; - else if (distance1 < distance2) - return NSOrderedAscending; - - return NSOrderedSame; - }]; - } - else - { - [sortedLiveLocations sortUsingComparator:^NSComparisonResult(TGLiveLocation *obj1, TGLiveLocation *obj2) - { - if (obj1.hasOwnSession) - return NSOrderedAscending; - else if (obj2.hasOwnSession) - return NSOrderedDescending; - - if (obj1.message.mid == strongSelf->_currentLiveLocation.message.mid) - return NSOrderedAscending; - else if (obj2.message.mid == strongSelf->_currentLiveLocation.message.mid) - return NSOrderedDescending; - - int32_t date1 = [obj1.message actualDate]; - int32_t date2 = [obj2.message actualDate]; - - if (date1 > date2) - return NSOrderedAscending; - else if (date1 < date2) - return NSOrderedDescending; - - return NSOrderedSame; - }]; - } - - TGDispatchOnMainThread(^ - { - if ([strongSelf isViewLoaded]) - [strongSelf setLiveLocations:sortedLiveLocations actual:actual]; - else - strongSelf->_initialLiveLocations = sortedLiveLocations; - }); - }]]; -} - -#pragma mark - - -- (void)setPreviewMode:(bool)previewMode -{ - _previewMode = previewMode; - - if (!previewMode) - { - [self setRightBarButtonItem:_actionsBarItem]; - _optionsView.hidden = false; - } -} - -#pragma mark - Actions - -- (void)fitAllLocations:(NSArray *)locations -{ - MKMapRect zoomRect = MKMapRectNull; - for (CLLocation *location in locations) - { - MKMapPoint annotationPoint = MKMapPointForCoordinate(location.coordinate); - MKMapRect pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1); - zoomRect = MKMapRectUnion(zoomRect, pointRect); - } - UIEdgeInsets insets = UIEdgeInsetsMake(TGLocationMapInset + 110.0f, 80.0f, TGLocationMapInset + 110.0f, 80.0f); - zoomRect = [_mapView mapRectThatFits:zoomRect edgePadding:insets]; - [_mapView setVisibleMapRect:zoomRect animated:true]; -} - -- (void)showAllPressed -{ - NSMutableArray *locations = [[NSMutableArray alloc] init]; - for (id annotation in _mapView.annotations) - { - CLLocation *location = [[CLLocation alloc] initWithLatitude:annotation.coordinate.latitude longitude:annotation.coordinate.longitude]; - [locations addObject:location]; - } - - [self fitAllLocations:locations]; -} - -- (void)dismissButtonPressed -{ - [self.presentingViewController dismissViewControllerAnimated:true completion:nil]; -} - -- (void)actionsButtonPressed -{ - TGLocationMediaAttachment *locationAttachment = _locationAttachment; - if (locationAttachment == nil) - return; - - if (self.presentActionsMenu != nil) - { - self.presentActionsMenu(locationAttachment, false); - return; - } - - CGRect (^sourceRect)(void) = ^CGRect - { - return CGRectZero; - }; - - __weak TGLocationViewController *weakSelf = self; - if (_presentOpenInMenu && _presentOpenInMenu(self, locationAttachment, false, ^(TGMenuSheetController *menuController) - { - __strong TGLocationViewController *strongSelf = weakSelf; - if (strongSelf != nil && strongSelf->_presentShareMenu) { - strongSelf->_presentShareMenu(menuController, [strongSelf locationCoordinate]); - } - })) - { - } - else - { - TGMenuSheetController *controller = [[TGMenuSheetController alloc] initWithContext:_context dark:false]; - controller.dismissesByOutsideTap = true; - controller.hasSwipeGesture = true; - controller.narrowInLandscape = true; - controller.sourceRect = sourceRect; - controller.barButtonItem = self.navigationItem.rightBarButtonItem; - - NSMutableArray *itemViews = [[NSMutableArray alloc] init]; - - __weak TGMenuSheetController *weakController = controller; - TGMenuSheetButtonItemView *openItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Map.OpenInMaps") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^ - { - __strong TGLocationViewController *strongSelf = weakSelf; - if (strongSelf == nil) - return; - - __strong TGMenuSheetController *strongController = weakController; - if (strongController == nil) - return; - - [strongController dismissAnimated:true]; - [TGLocationUtils openMapsWithCoordinate:[strongSelf locationCoordinate] withDirections:false locationName:strongSelf->_annotation.title]; - }]; - [itemViews addObject:openItem]; - - TGMenuSheetButtonItemView *shareItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Conversation.ContextMenuShare") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^ - { - __strong TGMenuSheetController *strongController = weakController; - if (strongController == nil) - return; - - __strong TGLocationViewController *strongSelf = weakSelf; - if (strongSelf != nil && strongSelf->_presentShareMenu) { - strongSelf->_presentShareMenu(strongController, [strongSelf locationCoordinate]); - } - }]; - [itemViews addObject:shareItem]; - - TGMenuSheetButtonItemView *cancelItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel fontSize:20.0 action:^ - { - __strong TGMenuSheetController *strongController = weakController; - if (strongController == nil) - return; - - [strongController dismissAnimated:true manual:true]; - }]; - [itemViews addObject:cancelItem]; - - [controller setItemViews:itemViews]; - [controller presentInViewController:self sourceView:self.view animated:true]; - } -} - -- (void)userLocationButtonPressed -{ - if (![self hasUserLocation]) - { - if (![TGLocationUtils requestWhenInUserLocationAuthorizationWithLocationManager:_locationManager]) - { - if (_locationServicesDisabled) - [[[LegacyComponentsGlobals provider] accessChecker] checkLocationAuthorizationStatusForIntent:TGLocationAccessIntentTracking alertDismissComlpetion:nil]; - } - - [self updateLocationAvailability]; - return; - } - - TGLocationTrackingMode newMode = TGLocationTrackingModeNone; - switch ([TGLocationTrackingButton locationTrackingModeWithUserTrackingMode:_mapView.userTrackingMode]) - { - case TGLocationTrackingModeFollow: - newMode = TGLocationTrackingModeFollowWithHeading; - break; - - case TGLocationTrackingModeFollowWithHeading: - newMode = TGLocationTrackingModeNone; - break; - - default: - newMode = TGLocationTrackingModeFollow; - break; - } - - [_mapView setUserTrackingMode:[TGLocationTrackingButton userTrackingModeWithLocationTrackingMode:newMode] animated:true]; - [_optionsView setTrackingMode:newMode animated:true]; - - if (newMode != TGLocationTrackingModeNone && _ownLiveLocationView != nil) - [self selectOwnAnnotation]; -} - -- (void)selectOwnAnnotation -{ - [self selectOwnAnnotationAnimated:true]; -} - -- (void)selectOwnAnnotationAnimated:(bool)animated -{ - if (!_ownLiveLocationView.isSelected) - [_ownLiveLocationView setSelected:true animated:animated]; - [_mapView deselectAnnotation:_mapView.selectedAnnotations.firstObject animated:true]; - [_ownLiveLocationView.superview.superview bringSubviewToFront:_ownLiveLocationView.superview]; -} - -- (void)getDirectionsPressed:(TGLocationMediaAttachment *)locationAttachment prompt:(bool)prompt -{ - if (self.presentActionsMenu != nil) - { - self.presentActionsMenu(locationAttachment, true); - return; - } - - if (_presentOpenInMenu && _presentOpenInMenu(self, locationAttachment, true, nil)) - { - } - else - { - void (^block)(void) = ^ - { - NSString *title = @""; - if (locationAttachment.venue != nil) - title = locationAttachment.venue.title; - else if ([_peer isKindOfClass:[TGUser class]]) - title = ((TGUser *)_peer).displayName; - else if ([_peer isKindOfClass:[TGConversation class]]) - title = ((TGConversation *)_peer).chatTitle; - - [TGLocationUtils openMapsWithCoordinate:[self locationCoordinate] withDirections:true locationName:title]; - }; - - if (prompt) - { - TGMenuSheetController *controller = [[TGMenuSheetController alloc] initWithContext:_context dark:false]; - controller.dismissesByOutsideTap = true; - controller.narrowInLandscape = true; - - __weak TGMenuSheetController *weakController = controller; - NSArray *items = @ - [ - [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Map.GetDirections") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^ - { - __strong TGMenuSheetController *strongController = weakController; - if (strongController == nil) - return; - - [strongController dismissAnimated:true]; - block(); - }], - [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Common.Cancel") type:TGMenuSheetButtonTypeCancel fontSize:20.0 action:^ - { - __strong TGMenuSheetController *strongController = weakController; - if (strongController != nil) - [strongController dismissAnimated:true]; - }] - ]; - - [controller setItemViews:items]; - controller.sourceRect = ^ - { - return CGRectZero; - }; - controller.permittedArrowDirections = UIPopoverArrowDirectionUp; - [controller presentInViewController:self sourceView:self.view animated:true]; - } - else - { - block(); - } - } -} - -- (UIButton *)directionsButton -{ - TGLocationInfoCell *infoCell = [_tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; - if ([infoCell isKindOfClass:[TGLocationInfoCell class]]) - return infoCell.directionsButton; - - return nil; -} - -- (CGRect)_liveLocationMenuSourceRect -{ - TGLocationLiveCell *cell = [_tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; - if ([cell isKindOfClass:[TGLocationLiveCell class]]) - return [cell convertRect:cell.bounds toView:self.view]; - - return CGRectZero; -} - -#pragma mark - Map View Delegate - -- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id)annotation -{ - if (annotation == mapView.userLocation) - return nil; - - TGLocationPinAnnotationView *view = (TGLocationPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:TGLocationPinAnnotationKind]; - if (view == nil) - { - view = [[TGLocationPinAnnotationView alloc] initWithAnnotation:annotation]; - view.pallete = self.pallete; - } - else - { - view.annotation = annotation; - } - view.layer.zPosition = -1; - - return view; -} - -- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views -{ - for (MKAnnotationView *view in views) - { - if ([view.annotation isKindOfClass:[MKUserLocation class]]) - { - _userLocationView = view; - - [_userLocationView addSubview:_headingArrowView]; - _headingArrowView.center = CGPointMake(view.frame.size.width / 2.0, view.frame.size.height / 2.0); - - if (_ownLiveLocationView != nil) - { - [_userLocationView addSubview:_ownLiveLocationView]; - - if (_currentLiveLocation.hasOwnSession && _mapView.selectedAnnotations.count == 0) - [_ownLiveLocationView setSelected:true animated:false]; - } - } - } -} - -- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view -{ - if (_ownLiveLocationView.isSelected) - [_ownLiveLocationView setSelected:false animated:true]; - - [self setMapCenterCoordinate:view.annotation.coordinate offset:CGPointZero animated:true]; - - [_optionsView setTrackingMode:TGLocationTrackingModeNone animated:true]; -} - -- (void)mapView:(MKMapView *)mapView didChangeUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated -{ - if (mode == MKUserTrackingModeNone) - [_optionsView setTrackingMode:TGLocationTrackingModeNone animated:true]; -} - -- (CLLocationCoordinate2D)locationCoordinate -{ - return CLLocationCoordinate2DMake(_locationAttachment.latitude, _locationAttachment.longitude); -} - -- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading -{ - if (newHeading != nil) { - _headingArrowView.hidden = false; - _headingArrowView.transform = CGAffineTransformMakeRotation(newHeading.magneticHeading / 180.0 * M_PI); - } -} - -#pragma mark - - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section -{ - NSInteger count = 0; - if (![self isLiveLocation]) - count += 1; - - if (_liveLocations.count > 0) - { - count += _liveLocations.count; - if (self.allowLiveLocationSharing && !_hasOwnLiveLocation) - count += 1; - } - return count; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath -{ - __weak TGLocationViewController *weakSelf = self; - if (indexPath.row == 0 && ![self isLiveLocation]) - { - TGLocationInfoCell *cell = [tableView dequeueReusableCellWithIdentifier:TGLocationInfoCellKind]; - if (cell == nil) - cell = [[TGLocationInfoCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TGLocationInfoCellKind]; - cell.pallete = self.pallete; - [cell setLocation:_locationAttachment color: _venueColor messageId:_message.mid userLocationSignal:[self userLocationSignal]]; - cell.locatePressed = ^ - { - __strong TGLocationViewController *strongSelf = weakSelf; - if (strongSelf != nil) - { - [strongSelf->_mapView deselectAnnotation:strongSelf->_mapView.selectedAnnotations.firstObject animated:true]; - [strongSelf setMapCenterCoordinate:[strongSelf locationCoordinate] offset:CGPointZero animated:true]; - } - }; - cell.directionsPressed = ^ - { - __strong TGLocationViewController *strongSelf = weakSelf; - if (strongSelf != nil) - [strongSelf getDirectionsPressed:strongSelf->_locationAttachment prompt:false]; - }; - cell.safeInset = self.controllerSafeAreaInset; - return cell; - } - else - { - TGLocationLiveCell *cell = [tableView dequeueReusableCellWithIdentifier:TGLocationLiveCellKind]; - if (cell == nil) - cell = [[TGLocationLiveCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TGLocationLiveCellKind]; - cell.pallete = self.pallete; - cell.edgeView = indexPath.row == 0 ? _edgeHighlightView : nil; - cell.safeInset = self.controllerSafeAreaInset; - - if (self.allowLiveLocationSharing && (indexPath.row == 0 || (![self isLiveLocation] && indexPath.row == 1))) - { - if (_hasOwnLiveLocation) - { - TGLiveLocation *liveLocation = _liveLocations.firstObject; - if (liveLocation.isExpired) - [cell configureForStart]; - else - [cell configureForStopWithMessage:liveLocation.message remaining:self.remainingTimeForMessage(liveLocation.message)]; - } - else - { - [cell configureForStart]; - } - - cell.longPressed = nil; - } - else - { - NSInteger index = indexPath.row; - if (![self isLiveLocation]) - index -= 1; - if (self.allowLiveLocationSharing && !_hasOwnLiveLocation) - index -= 1; - - TGLiveLocation *liveLocation = index >= 0 && index < _liveLocations.count ? _liveLocations[index] : nil; - [cell configureWithPeer:liveLocation.peer message:liveLocation.message remaining:self.remainingTimeForMessage(liveLocation.message) userLocationSignal:[self userLocationSignal]]; - - cell.longPressed = ^ - { - __strong TGLocationViewController *strongSelf = weakSelf; - if (strongSelf != nil) - [strongSelf getDirectionsPressed:liveLocation.message.locationAttachment prompt:true]; - }; - } - return cell; - } - - return nil; -} - -- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath -{ - if (indexPath.row == 0 && ![self isLiveLocation]) - return false; - - return true; -} - -- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath -{ - [super tableView:tableView didHighlightRowAtIndexPath:indexPath]; - [self setReloadReady:false]; -} - -- (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath -{ - [super tableView:tableView didUnhighlightRowAtIndexPath:indexPath]; - if (!_tableView.isTracking) - [self setReloadReady:true]; -} - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath -{ - bool animated = true; - if (indexPath.row == 0 && ![self isLiveLocation]) - { - - } - else - { - TGLocationLiveCell *cell = [tableView dequeueReusableCellWithIdentifier:TGLocationLiveCellKind]; - if (cell == nil) - cell = [[TGLocationLiveCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TGLocationInfoCellKind]; - - if (self.allowLiveLocationSharing && (indexPath.row == 0 || (![self isLiveLocation] && indexPath.row == 1))) - { - if (_hasOwnLiveLocation && !_ownLocationExpired) - { - if (self.liveLocationStopped != nil) - self.liveLocationStopped(); - } - else - { - [[[self userLocationSignal] take:1] startWithNext:^(CLLocation *location) - { - [self _presentLiveLocationMenu:location.coordinate dismissOnCompletion:true]; - }]; - } - } - else - { - NSInteger index = indexPath.row; - if (![self isLiveLocation]) - index -= 1; - if (self.allowLiveLocationSharing && !_hasOwnLiveLocation) - index -= 1; - - TGLiveLocation *liveLocation = _liveLocations[index]; - for (TGLocationAnnotation *annotation in _mapView.annotations) - { - if (![annotation isKindOfClass:[TGLocationAnnotation class]]) - continue; - - if (annotation.messageId == liveLocation.message.mid) - { - if ([_mapView.selectedAnnotations containsObject:annotation]) - [self setMapCenterCoordinate:annotation.coordinate offset:CGPointZero animated:true]; - else - [_mapView selectAnnotation:annotation animated:true]; - break; - } - } - } - } - [tableView deselectRowAtIndexPath:indexPath animated:animated]; -} - -- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath -{ - if (indexPath.row == 0 && ![self isLiveLocation]) - return TGLocationInfoCellHeight; - else - return TGLocationLiveCellHeight; - - return 0; -} - -- (CGFloat)visibleContentHeight -{ - if (![self isLiveLocation]) - return TGLocationInfoCellHeight + self.safeAreaInsetBottom; - else - return TGLocationLiveCellHeight + self.safeAreaInsetBottom; -} - -- (CGFloat)possibleContentHeight -{ - if (![self isLiveLocation]) - { - CGFloat height = TGLocationInfoCellHeight; - if (_liveLocations.count > 0) - { - CGFloat count = _liveLocations.count; - if (self.allowLiveLocationSharing && !_hasOwnLiveLocation) - count += 1; - count = MIN(1.5f, count); - height += count * TGLocationLiveCellHeight; - } - return height + self.safeAreaInsetBottom; - } - else - { - CGFloat count = _liveLocations.count; - if (self.allowLiveLocationSharing && !_hasOwnLiveLocation) - count += 1; - count = MIN(2.5f, count); - CGFloat height = count * TGLocationLiveCellHeight; - return height + self.safeAreaInsetBottom; - } -} - -- (bool)isLiveLocation -{ - return _locationAttachment.period > 0; -} - -- (bool)hasMoreThanOneLocation -{ - return ((_hasOwnLiveLocation && _liveLocations.count > 1) || (!_hasOwnLiveLocation && _liveLocations.count > 0)); -} - -- (void)setReloadReady:(bool)ready -{ - [_reloadReady set:[SSignal single:@(ready)]]; -} - -- (SSignal *)reloadReadySignal -{ - return [[_reloadReady.signal filter:^bool(NSNumber *value) { - return value.boolValue; - }] take:1]; -} - -- (void)scrollViewDidScroll:(UIScrollView *)scrollView -{ - [super scrollViewDidScroll:scrollView]; - - _mapView.compassInsets = UIEdgeInsetsMake(TGLocationMapInset + 120.0f + (scrollView.contentOffset.y + scrollView.contentInset.top) / 2.0f, 0.0f, 0.0f, 10.0f + TGScreenPixel); -} - -- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView -{ - [self setReloadReady:false]; -} - -- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView -{ - if (!scrollView.isTracking) - [self setReloadReady:true]; -} - -- (void)scrollViewDidEndDragging:(UIScrollView *)__unused scrollView willDecelerate:(BOOL)decelerate -{ - if (!decelerate) - [self setReloadReady:true]; -} - -- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)__unused scrollView -{ - if (!scrollView.isTracking) - [self setReloadReady:true]; -} - -- (void)_willStartOwnLiveLocation -{ - _focusOnOwnLocation = true; - - if (_currentLiveLocation.isOwnLocation) - _ignoreNextUpdates = true; - else - _throttle = true; -} - -- (void)layoutControllerForSize:(CGSize)size duration:(NSTimeInterval)duration -{ - [super layoutControllerForSize:size duration:duration]; - - if (!self.isViewLoaded) - return; - - for (UITableViewCell *cell in _tableView.visibleCells) - { - if ([cell isKindOfClass:[TGLocationInfoCell class]]) - { - ((TGLocationInfoCell *)cell).safeInset = self.controllerSafeAreaInset; - } else if ([cell isKindOfClass:[TGLocationLiveCell class]]) - { - ((TGLocationLiveCell *)cell).safeInset = self.controllerSafeAreaInset; - } - } -} - -@end - - -@implementation TGLiveLocation - -- (instancetype)initWithMessage:(TGMessage *)message peer:(id)peer hasOwnSession:(bool)hasOwnSession isOwnLocation:(bool)isOwnLocation isExpired:(bool)isExpired -{ - self = [super init]; - if (self != nil) - { - _message = message; - _peer = peer; - _hasOwnSession = hasOwnSession; - _isOwnLocation = isOwnLocation; - _isExpired = isExpired; - } - return self; -} - - -- (instancetype)initWithMessage:(TGMessage *)message peer:(id)peer -{ - self = [super init]; - if (self != nil) - { - _message = message; - _peer = peer; - _hasOwnSession = true; - _isOwnLocation = true; - _isExpired = false; - } - return self; -} - -- (int64_t)peerId -{ - return [_peer isKindOfClass:[TGUser class]] ? ((TGUser *)_peer).uid : ((TGConversation *)_peer).conversationId; -} - -- (CLLocation *)location -{ - TGLocationMediaAttachment *location = _message.locationAttachment; - if (location == nil) - return nil; - - return [[CLLocation alloc] initWithLatitude:location.latitude longitude:location.longitude]; -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGLocationWavesView.m b/submodules/LegacyComponents/Sources/TGLocationWavesView.m deleted file mode 100644 index e9580806f5..0000000000 --- a/submodules/LegacyComponents/Sources/TGLocationWavesView.m +++ /dev/null @@ -1,126 +0,0 @@ -#import "TGLocationWavesView.h" - -#import "LegacyComponentsInternal.h" -#import "TGImageUtils.h" -#import "TGPhotoEditorUtils.h" - -@interface TGLocationWavesView () -{ - CADisplayLink *_displayLink; - NSTimeInterval _previousTime; - - CGFloat _progress; - UIImage *_image; -} -@end - -@implementation TGLocationWavesView - -- (instancetype)initWithFrame:(CGRect)frame -{ - self = [super initWithFrame:frame]; - if (self != nil) - { - self.backgroundColor = [UIColor clearColor]; - _image = TGComponentsImageNamed(@"LocationWave"); - self.userInteractionEnabled = false; - _color = [UIColor whiteColor]; - } - return self; -} - -- (void)invalidate -{ - [_displayLink invalidate]; - _displayLink = nil; -} - -- (CADisplayLink *)displayLink { - if (_displayLink == nil) { - _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkUpdate)]; - _displayLink.paused = true; - [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; - } - return _displayLink; -} - -- (void)setColor:(UIColor *)color -{ - _color = color; - _image = TGTintedImage(TGComponentsImageNamed(@"LocationWave"), color); -} - -- (void)start -{ - [self displayLink].paused = false; -} - -- (void)stop -{ - _displayLink.paused = true; -} - -- (void)drawRect:(CGRect)rect -{ - CGPoint center = CGPointMake(rect.size.width / 2.0f, rect.size.height / 2.0f); - CGFloat length = 9.0f; - - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSetFillColorWithColor(context, _color.CGColor); - - void (^draw)(CGFloat, bool) = ^(CGFloat pos, bool right) - { - CGMutablePathRef path = CGPathCreateMutable(); - CGPathAddArc(path, NULL, center.x, center.y, length * pos + 7.0f, right ? TGDegreesToRadians(-26) : TGDegreesToRadians(154), right ? TGDegreesToRadians(26) : TGDegreesToRadians(206), false); - - CGPathRef strokedArc = CGPathCreateCopyByStrokingPath(path, NULL, 1.65f, kCGLineCapRound, kCGLineJoinMiter, 10); - - CGContextAddPath(context, strokedArc); - - CGPathRelease(strokedArc); - CGPathRelease(path); - - CGContextFillPath(context); - }; - - CGFloat position = _progress; - CGFloat alpha = position / 0.5f; - if (alpha > 1.0f) - alpha = 2.0f - alpha; - CGContextSetAlpha(context, alpha * 0.7f); - - draw(position, false); - draw(position, true); - - CGFloat progress = _progress + 0.5f; - if (progress > 1.0f) - progress = progress - 1.0f; - - CGFloat largerPos = progress; - CGFloat largerAlpha = largerPos / 0.5f; - if (largerAlpha > 1.0f) - largerAlpha = 2.0f - largerAlpha; - CGContextSetAlpha(context, largerAlpha * 0.7f); - - draw(largerPos, false); - draw(largerPos, true); -} - -- (void)displayLinkUpdate -{ - NSTimeInterval previousTime = _previousTime; - NSTimeInterval currentTime = CACurrentMediaTime(); - _previousTime = currentTime; - - NSTimeInterval delta = previousTime > DBL_EPSILON ? currentTime - previousTime : 0.0; - if (delta < DBL_EPSILON) - return; - - _progress += delta * 0.52; - if (_progress > 1.0f) - _progress = 1.0f - _progress; - - [self setNeedsDisplay]; -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGMediaAssetsController.m b/submodules/LegacyComponents/Sources/TGMediaAssetsController.m index 2f0f9b13af..df17228fe4 100644 --- a/submodules/LegacyComponents/Sources/TGMediaAssetsController.m +++ b/submodules/LegacyComponents/Sources/TGMediaAssetsController.m @@ -17,7 +17,6 @@ #import "TGModernBarButton.h" #import -#import "TGMediaAssetsTipView.h" #import #import @@ -586,23 +585,6 @@ } } -- (void)viewWillAppear:(BOOL)animated -{ - [super viewWillAppear:animated]; - - if (_intent == TGMediaAssetsControllerSendFileIntent && self.shouldShowFileTipIfNeeded && iosMajorVersion() >= 7) - { - if (![[[NSUserDefaults standardUserDefaults] objectForKey:@"didShowDocumentPickerTip_v2"] boolValue]) - { - [[NSUserDefaults standardUserDefaults] setObject:@true forKey:@"didShowDocumentPickerTip_v2"]; - - TGMediaAssetsTipView *tipView = [[TGMediaAssetsTipView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.view.bounds.size.width, self.view.bounds.size.height)]; - tipView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - [self.navigationController.view addSubview:tipView]; - } - } -} - - (NSArray *)resultSignalsWithCurrentItem:(TGMediaAsset *)currentItem descriptionGenerator:(id (^)(id, NSString *, NSArray *, NSString *))descriptionGenerator { bool storeAssets = (_editingContext != nil) && self.shouldStoreAssets; diff --git a/submodules/LegacyComponents/Sources/TGMediaAssetsGifCell.m b/submodules/LegacyComponents/Sources/TGMediaAssetsGifCell.m index 819953cfe1..ca3015a6e4 100644 --- a/submodules/LegacyComponents/Sources/TGMediaAssetsGifCell.m +++ b/submodules/LegacyComponents/Sources/TGMediaAssetsGifCell.m @@ -59,7 +59,7 @@ NSString *const TGMediaAssetsGifCellKind = @"TGMediaAssetsGifCellKind"; _typeLabel.textColor = [UIColor whiteColor]; _typeLabel.backgroundColor = [UIColor clearColor]; _typeLabel.textAlignment = NSTextAlignmentLeft; - _typeLabel.font = TGSystemFontOfSize(12.0f); + _typeLabel.font = TGBoldSystemFontOfSize(13); _typeLabel.text = @"GIF"; [_typeLabel sizeToFit]; [self addSubview:_typeLabel]; @@ -78,7 +78,9 @@ NSString *const TGMediaAssetsGifCellKind = @"TGMediaAssetsGifCellKind"; [super layoutSubviews]; _shadowView.frame = (CGRect){ { 0, self.frame.size.height - _shadowView.frame.size.height }, {self.frame.size.width, _shadowView.frame.size.height } }; - _typeLabel.frame = (CGRect){ { 5, _shadowView.frame.origin.y }, {self.frame.size.width - 5 - 4, _shadowView.frame.size.height } }; + + CGSize typeSize = _typeLabel.frame.size; + _typeLabel.frame = CGRectMake(self.frame.size.width - floor(typeSize.width) - 5.0, self.frame.size.height - floor(typeSize.height) - 4.0, typeSize.width, typeSize.height); } @end diff --git a/submodules/LegacyComponents/Sources/TGMediaAssetsTipView.h b/submodules/LegacyComponents/Sources/TGMediaAssetsTipView.h deleted file mode 100644 index ab5b611419..0000000000 --- a/submodules/LegacyComponents/Sources/TGMediaAssetsTipView.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface TGMediaAssetsTipView : UIView - -@end diff --git a/submodules/LegacyComponents/Sources/TGMediaAssetsTipView.m b/submodules/LegacyComponents/Sources/TGMediaAssetsTipView.m deleted file mode 100644 index fa1ed784a7..0000000000 --- a/submodules/LegacyComponents/Sources/TGMediaAssetsTipView.m +++ /dev/null @@ -1,97 +0,0 @@ -#import "TGMediaAssetsTipView.h" - -#import "LegacyComponentsInternal.h" -#import "TGColor.h" -#import "TGImageUtils.h" -#import "TGFont.h" -#import "TGStringUtils.h" - -#import - -@interface TGMediaAssetsTipView () -{ - UIView *_wrapperView; - UIImageView *_imageView; - UILabel *_titleLabel; - UILabel *_textLabel; - TGModernButton *_doneButton; -} -@end - -@implementation TGMediaAssetsTipView - -- (instancetype)initWithFrame:(CGRect)frame -{ - self = [super initWithFrame:frame]; - if (self != nil) - { - self.backgroundColor = [UIColor whiteColor]; - - _wrapperView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)]; - [self addSubview:_wrapperView]; - - _imageView = [[UIImageView alloc] initWithImage:TGComponentsImageNamed(@"AttachmentTipIcons")]; - [self addSubview:_imageView]; - - _titleLabel = [[UILabel alloc] init]; - _titleLabel.backgroundColor = [UIColor clearColor]; - _titleLabel.textColor = UIColorRGB(0x222222); - _titleLabel.font = TGSystemFontOfSize(19.0f + TGRetinaPixel); - _titleLabel.text = TGLocalized(@"ShareFileTip.Title"); - [_wrapperView addSubview:_titleLabel]; - - _textLabel = [[UILabel alloc] init]; - _textLabel.backgroundColor = [UIColor clearColor]; - _textLabel.textColor = UIColorRGB(0x808080); - _textLabel.font = TGSystemFontOfSize(15.0f + TGRetinaPixel); - - NSString *shareTipText = [[NSString alloc] initWithFormat:TGLocalized(@"ShareFileTip.Text"), [TGStringUtils stringForDeviceType]]; - _textLabel.attributedText = [shareTipText attributedFormattedStringWithRegularFont:TGSystemFontOfSize(15.0f + TGRetinaPixel) boldFont:TGBoldSystemFontOfSize(15.0f + TGRetinaPixel) lineSpacing:3.0f paragraphSpacing:-1.0f alignment:NSTextAlignmentCenter]; - _textLabel.numberOfLines = 0; - _textLabel.lineBreakMode = NSLineBreakByWordWrapping; - [_wrapperView addSubview:_textLabel]; - - _doneButton = [[TGModernButton alloc] init]; - [_doneButton setTitle:TGLocalized(@"ShareFileTip.CloseTip") forState:UIControlStateNormal]; - _doneButton.titleLabel.font = TGSystemFontOfSize(18.0f); - [_doneButton setTitleColor:TGAccentColor()]; - _doneButton.contentEdgeInsets = UIEdgeInsetsMake(8.0f, 20.0f, 8.0f, 20.0f); - [_doneButton sizeToFit]; - [_doneButton addTarget:self action:@selector(doneButtonPressed) forControlEvents:UIControlEventTouchUpInside]; - [self addSubview:_doneButton]; - } - return self; -} - -- (void)doneButtonPressed -{ - [UIView animateWithDuration:0.4 animations:^ - { - self.frame = CGRectMake(0.0f, self.superview.frame.size.height, self.frame.size.width, self.frame.size.height); - } completion:^(__unused BOOL finished) - { - [self removeFromSuperview]; - }]; -} - -- (void)layoutSubviews -{ - [super layoutSubviews]; - - _imageView.frame = CGRectMake((self.frame.size.width - _imageView.frame.size.width) / 2, 0, _imageView.frame.size.width, _imageView.frame.size.height); - - CGFloat padding = 22.0f; - - CGSize titleSize = [_titleLabel sizeThatFits:CGSizeMake(self.bounds.size.width - padding * 2.0f, CGFLOAT_MAX)]; - _titleLabel.frame = CGRectMake(padding, CGRectGetMaxY(_imageView.frame) + 22.0f + TGRetinaPixel, titleSize.width, titleSize.height); - - CGSize textSize = [_textLabel sizeThatFits:CGSizeMake(self.bounds.size.width - padding * 2.0f, CGFLOAT_MAX)]; - _textLabel.frame = CGRectMake(padding, CGRectGetMaxY(_titleLabel.frame) + 15.0f + TGRetinaPixel, textSize.width, textSize.height); - - CGFloat wrapperHeight = CGRectGetMaxY(_textLabel.frame); - _wrapperView.frame = CGRectMake(0, floor((self.frame.size.height - wrapperHeight) / 2.0f) - 30.0f, self.frame.size.width, wrapperHeight); - - _doneButton.frame = CGRectMake(CGFloor((self.bounds.size.width - _doneButton.frame.size.width) / 2.0f), self.frame.size.height - _doneButton.frame.size.height - 16.0f + TGRetinaPixel, _doneButton.frame.size.width, _doneButton.frame.size.height); -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGMediaAssetsVideoCell.m b/submodules/LegacyComponents/Sources/TGMediaAssetsVideoCell.m index e88099df21..69a26f9b7b 100644 --- a/submodules/LegacyComponents/Sources/TGMediaAssetsVideoCell.m +++ b/submodules/LegacyComponents/Sources/TGMediaAssetsVideoCell.m @@ -67,13 +67,12 @@ NSString *const TGMediaAssetsVideoCellKind = @"TGMediaAssetsVideoCellKind"; _iconView = [[UIImageView alloc] init]; _iconView.contentMode = UIViewContentModeCenter; - [self addSubview:_iconView]; _durationLabel = [[UILabel alloc] init]; _durationLabel.textColor = [UIColor whiteColor]; _durationLabel.backgroundColor = [UIColor clearColor]; _durationLabel.textAlignment = NSTextAlignmentRight; - _durationLabel.font = TGSystemFontOfSize(12.0f); + _durationLabel.font = TGBoldSystemFontOfSize(13); [_durationLabel sizeToFit]; [self addSubview:_durationLabel]; @@ -113,6 +112,7 @@ NSString *const TGMediaAssetsVideoCellKind = @"TGMediaAssetsVideoCellKind"; durationString = [NSString stringWithFormat:@"%d:%02d", duration / 60, duration % 60]; _durationLabel.text = durationString; + [_durationLabel sizeToFit]; if (asset.subtypes & TGMediaAssetSubtypeVideoTimelapse) _iconView.image = TGComponentsImageNamed(@"ModernMediaItemTimelapseIcon"); @@ -235,7 +235,9 @@ NSString *const TGMediaAssetsVideoCellKind = @"TGMediaAssetsVideoCellKind"; self.checkButton.frame = (CGRect){ { self.frame.size.width - self.checkButton.frame.size.width - 2, 2 }, self.checkButton.frame.size }; _shadowView.frame = (CGRect){ { 0, self.frame.size.height - _shadowView.frame.size.height }, {self.frame.size.width, _shadowView.frame.size.height } }; _iconView.frame = CGRectMake(0, self.frame.size.height - 19, 19, 19); - _durationLabel.frame = (CGRect){ { 5, _shadowView.frame.origin.y }, {self.frame.size.width - 5 - 4, _shadowView.frame.size.height } }; + + CGSize durationSize = _durationLabel.frame.size; + _durationLabel.frame = CGRectMake(self.frame.size.width - floor(durationSize.width) - 5.0, self.frame.size.height - floor(durationSize.height) - 4.0, durationSize.width, durationSize.height); } @end diff --git a/submodules/LegacyComponents/Sources/TGMediaPickerLayoutMetrics.m b/submodules/LegacyComponents/Sources/TGMediaPickerLayoutMetrics.m index a180be82f1..14eef45878 100644 --- a/submodules/LegacyComponents/Sources/TGMediaPickerLayoutMetrics.m +++ b/submodules/LegacyComponents/Sources/TGMediaPickerLayoutMetrics.m @@ -51,40 +51,49 @@ CGSize itemSize = TGPhotoThumbnailSizeForCurrentScreen(); if ([UIScreen mainScreen].scale >= 2.0f - FLT_EPSILON) { - if (widescreenWidth >= 736.0f - FLT_EPSILON) + if (widescreenWidth >= 844.0f - FLT_EPSILON) { metrics->_normalItemSize = itemSize; metrics->_wideItemSize = itemSize; - metrics->_normalEdgeInsets = UIEdgeInsetsMake(4.0f, 0.0f, 2.0f, 0.0f); - metrics->_wideEdgeInsets = UIEdgeInsetsMake(4.0f, 2.0f, 1.0f, 2.0f); - metrics->_normalLineSpacing = 1.0f; + metrics->_normalEdgeInsets = UIEdgeInsetsMake(2.0f, 0.0f, 2.0f, 0.0f); + metrics->_wideEdgeInsets = UIEdgeInsetsMake(2.0f, 2.0f, 1.0f, 2.0f); + metrics->_normalLineSpacing = 2.0f; + metrics->_wideLineSpacing = 2.0f; + } + else if (widescreenWidth >= 736.0f - FLT_EPSILON) + { + metrics->_normalItemSize = itemSize; + metrics->_wideItemSize = itemSize; + metrics->_normalEdgeInsets = UIEdgeInsetsMake(2.0f, 0.0f, 2.0f, 0.0f); + metrics->_wideEdgeInsets = UIEdgeInsetsMake(2.0f, 2.0f, 1.0f, 2.0f); + metrics->_normalLineSpacing = 2.0f; metrics->_wideLineSpacing = 2.0f; } else if (widescreenWidth >= 667.0f - FLT_EPSILON) { metrics->_normalItemSize = itemSize; metrics->_wideItemSize = CGSizeMake(floor(itemSize.width), floor(itemSize.height)); - metrics->_normalEdgeInsets = UIEdgeInsetsMake(4.0f, 0.0f, 2.0f, 0.0f); - metrics->_wideEdgeInsets = UIEdgeInsetsMake(4.0f, 2.0f, 1.0f, 2.0f); - metrics->_normalLineSpacing = 1.0f; + metrics->_normalEdgeInsets = UIEdgeInsetsMake(2.0f, 0.0f, 2.0f, 0.0f); + metrics->_wideEdgeInsets = UIEdgeInsetsMake(2.0f, 2.0f, 1.0f, 2.0f); + metrics->_normalLineSpacing = 2.0f; metrics->_wideLineSpacing = 2.0f; } else { metrics->_normalItemSize = itemSize; metrics->_wideItemSize = CGSizeMake(floor(itemSize.width), floor(itemSize.height)); - metrics->_normalEdgeInsets = UIEdgeInsetsMake(4.0f, 0.0f, 2.0f, 0.0f); - metrics->_wideEdgeInsets = UIEdgeInsetsMake(4.0f, 1.0f, 1.0f, 1.0f); + metrics->_normalEdgeInsets = UIEdgeInsetsMake(2.0f, 0.0f, 2.0f, 0.0f); + metrics->_wideEdgeInsets = UIEdgeInsetsMake(2.0f, 1.0f, 1.0f, 1.0f); metrics->_normalLineSpacing = 2.0f; - metrics->_wideLineSpacing = 3.0f; + metrics->_wideLineSpacing = 2.0f; } } else { metrics->_normalItemSize = itemSize; metrics->_wideItemSize = CGSizeMake(floor(itemSize.width), floor(itemSize.height)); - metrics->_normalEdgeInsets = UIEdgeInsetsMake(4.0f, 0.0f, 2.0f, 0.0f); - metrics->_wideEdgeInsets = UIEdgeInsetsMake(4.0f, 1.0f, 1.0f, 1.0f); + metrics->_normalEdgeInsets = UIEdgeInsetsMake(2.0f, 0.0f, 2.0f, 0.0f); + metrics->_wideEdgeInsets = UIEdgeInsetsMake(2.0f, 1.0f, 1.0f, 1.0f); metrics->_normalLineSpacing = 2.0f; metrics->_wideLineSpacing = 2.0f; } diff --git a/submodules/LegacyComponents/Sources/TGMentionPanelCell.m b/submodules/LegacyComponents/Sources/TGMentionPanelCell.m index b9affa9f34..c316003e8a 100644 --- a/submodules/LegacyComponents/Sources/TGMentionPanelCell.m +++ b/submodules/LegacyComponents/Sources/TGMentionPanelCell.m @@ -59,7 +59,7 @@ NSString *const TGMentionPanelCellKind = @"TGMentionPanelCell"; self.selectedBackgroundView.backgroundColor = selectionColor; _avatarView = [[TGLetteredAvatarView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 32.0f, 32.0f)]; - [_avatarView setSingleFontSize:18.0f doubleFontSize:18.0f useBoldFont:false]; + [_avatarView setSingleFontSize:16.0f doubleFontSize:16.0f useBoldFont:false]; _avatarView.fadeTransition = true; [self.contentView addSubview:_avatarView]; diff --git a/submodules/LegacyComponents/Sources/TGNavigationBar.m b/submodules/LegacyComponents/Sources/TGNavigationBar.m index 9db9f3ba8f..57a2ba7d6c 100644 --- a/submodules/LegacyComponents/Sources/TGNavigationBar.m +++ b/submodules/LegacyComponents/Sources/TGNavigationBar.m @@ -204,9 +204,23 @@ static id _musicPlayerProvider; - (void)layoutSubviews { - [self updateLayout]; - [super layoutSubviews]; + + for (UIView *view in self.subviews) { + if (iosMajorVersion() >= 11) { + view.frame = CGRectOffset(view.frame, 0.0, 6.0); + } + } + + [self updateLayout]; +} + +- (CGSize)sizeThatFits:(CGSize)size { + if (iosMajorVersion() < 11) { + return CGSizeMake(MAX(self.frame.size.width, size.width), 36.0 - 6.0); + } else { + return [super sizeThatFits:size]; + } } - (void)updateLayout @@ -217,7 +231,13 @@ static id _musicPlayerProvider; if (iosMajorVersion() >= 11 && self.superview.safeAreaInsets.top > FLT_EPSILON) backgroundOverflow = self.superview.safeAreaInsets.top; - _backgroundContainerView.frame = CGRectMake(0, -backgroundOverflow, self.bounds.size.width, backgroundOverflow + self.bounds.size.height); + CGFloat heightAddition = 0.0; + if (iosMajorVersion() < 11) { + backgroundOverflow = 20.0; + heightAddition = 6.0 + TGScreenPixel; + } + + _backgroundContainerView.frame = CGRectMake(0, -backgroundOverflow, self.bounds.size.width, backgroundOverflow + self.bounds.size.height + heightAddition); if (_barBackgroundView != nil) _barBackgroundView.frame = _backgroundContainerView.bounds; @@ -298,6 +318,10 @@ static id _musicPlayerProvider; - (void)setFrame:(CGRect)frame { + if (frame.size.height < 56.0) { + frame.size.height = 56.0; + } + [super setFrame:frame]; if (_statusBarBackgroundView != nil && _statusBarBackgroundView.superview != nil) diff --git a/submodules/LegacyComponents/Sources/TGPhotoBrushSettingsView.m b/submodules/LegacyComponents/Sources/TGPhotoBrushSettingsView.m index 6547a3c5ca..144cf5b68a 100644 --- a/submodules/LegacyComponents/Sources/TGPhotoBrushSettingsView.m +++ b/submodules/LegacyComponents/Sources/TGPhotoBrushSettingsView.m @@ -24,10 +24,6 @@ const CGFloat TGPhotoBrushSettingsItemHeight = 44.0f; NSArray *_brushViews; NSArray *_brushIconViews; NSArray *_brushSeparatorViews; - - UIImage *_landscapeLeftBackgroundImage; - UIImage *_landscapeRightBackgroundImage; - UIImage *_portraitBackgroundImage; } @end diff --git a/submodules/LegacyComponents/Sources/TGPhotoEditorBlurToolView.m b/submodules/LegacyComponents/Sources/TGPhotoEditorBlurToolView.m index c7eeaefa5b..331e050725 100644 --- a/submodules/LegacyComponents/Sources/TGPhotoEditorBlurToolView.m +++ b/submodules/LegacyComponents/Sources/TGPhotoEditorBlurToolView.m @@ -280,17 +280,22 @@ _sliderView.frame = CGRectMake((self.frame.size.width - 32) / 2, TGPhotoEditorSliderViewMargin, 32, self.frame.size.height - 2 * TGPhotoEditorSliderViewMargin); + CGFloat titleOffset = 10; + if (MAX(_offButton.title.length, MAX(_radialButton.title.length, _linearButton.title.length)) > 7) { + titleOffset = -2; + } + [UIView performWithoutAnimation:^ { if (orientation == UIInterfaceOrientationLandscapeLeft) { _titleLabel.transform = CGAffineTransformMakeRotation(M_PI_2); - _titleLabel.frame = CGRectMake(self.frame.size.width - _titleLabel.frame.size.width - 10, (self.frame.size.height - _titleLabel.frame.size.height) / 2, _titleLabel.frame.size.width, _titleLabel.frame.size.height); + _titleLabel.frame = CGRectMake(self.frame.size.width - _titleLabel.frame.size.width - titleOffset, (self.frame.size.height - _titleLabel.frame.size.height) / 2, _titleLabel.frame.size.width, _titleLabel.frame.size.height); } else if (orientation == UIInterfaceOrientationLandscapeRight) { _titleLabel.transform = CGAffineTransformMakeRotation(-M_PI_2); - _titleLabel.frame = CGRectMake(10, (self.frame.size.height - _titleLabel.frame.size.height) / 2, _titleLabel.frame.size.width, _titleLabel.frame.size.height); + _titleLabel.frame = CGRectMake(titleOffset, (self.frame.size.height - _titleLabel.frame.size.height) / 2, _titleLabel.frame.size.width, _titleLabel.frame.size.height); } }]; } diff --git a/submodules/LegacyComponents/Sources/TGPhotoEditorBlurTypeButton.m b/submodules/LegacyComponents/Sources/TGPhotoEditorBlurTypeButton.m index 8c9da4e3e2..cb74b72a2a 100644 --- a/submodules/LegacyComponents/Sources/TGPhotoEditorBlurTypeButton.m +++ b/submodules/LegacyComponents/Sources/TGPhotoEditorBlurTypeButton.m @@ -121,7 +121,7 @@ - (void)layoutSubviews { _imageView.frame = CGRectMake((self.frame.size.width - 50) / 2, (self.frame.size.height - 68) / 2, 50, 50); - _titleLabel.frame = CGRectMake(0, _imageView.frame.origin.y +_imageView.frame.size.height - 1, self.frame.size.width, 16); + _titleLabel.frame = CGRectMake(0, _imageView.frame.origin.y + _imageView.frame.size.height - 1, self.frame.size.width, 16); } @end diff --git a/submodules/LegacyComponents/Sources/TGPhotoEditorCollectionView.h b/submodules/LegacyComponents/Sources/TGPhotoEditorCollectionView.h index a15141fc27..df00dfb4aa 100644 --- a/submodules/LegacyComponents/Sources/TGPhotoEditorCollectionView.h +++ b/submodules/LegacyComponents/Sources/TGPhotoEditorCollectionView.h @@ -1,9 +1,7 @@ #import -@class PGPhotoFilter; @class PGPhotoTool; -@protocol TGPhotoEditorCollectionViewFiltersDataSource; @protocol TGPhotoEditorCollectionViewToolsDataSource; @interface TGPhotoEditorCollectionView : UICollectionView @@ -11,9 +9,7 @@ @property (nonatomic, copy) void(^interactionBegan)(void); @property (nonatomic, copy) void(^interactionEnded)(void); -@property (nonatomic, weak) id filtersDataSource; @property (nonatomic, weak) id toolsDataSource; -@property (nonatomic, strong) UIImage *filterThumbnailImage; @property (nonatomic, readonly) bool hasAnyTracking; @@ -24,15 +20,6 @@ @end -@protocol TGPhotoEditorCollectionViewFiltersDataSource - -- (NSInteger)numberOfFiltersInCollectionView:(TGPhotoEditorCollectionView *)collectionView; -- (PGPhotoFilter *)collectionView:(TGPhotoEditorCollectionView *)collectionView filterAtIndex:(NSInteger)index; -- (void)collectionView:(TGPhotoEditorCollectionView *)collectionView didSelectFilterWithIndex:(NSInteger)index; -- (void)collectionView:(TGPhotoEditorCollectionView *)collectionView requestThumbnailImageForFilterAtIndex:(NSInteger)index completion:(void (^)(UIImage *thumbnailImage, bool cached, bool finished))completion; - -@end - @protocol TGPhotoEditorCollectionViewToolsDataSource - (NSInteger)numberOfToolsInCollectionView:(TGPhotoEditorCollectionView *)collectionView; diff --git a/submodules/LegacyComponents/Sources/TGPhotoEditorCollectionView.m b/submodules/LegacyComponents/Sources/TGPhotoEditorCollectionView.m index 71ad38a911..bcd4c64165 100644 --- a/submodules/LegacyComponents/Sources/TGPhotoEditorCollectionView.m +++ b/submodules/LegacyComponents/Sources/TGPhotoEditorCollectionView.m @@ -2,9 +2,6 @@ #import "LegacyComponentsInternal.h" -#import "PGPhotoFilter.h" - -#import "TGPhotoFilterCell.h" #import "TGPhotoToolCell.h" #import "TGPhotoEditorSliderView.h" @@ -43,7 +40,6 @@ const CGPoint TGPhotoEditorEdgeScrollTriggerOffset = { 100, 150 }; self.showsHorizontalScrollIndicator = false; self.showsVerticalScrollIndicator = false; - [self registerClass:[TGPhotoFilterCell class] forCellWithReuseIdentifier:TGPhotoFilterCellKind]; [self registerClass:[TGPhotoToolCell class] forCellWithReuseIdentifier:TGPhotoToolCellKind]; } return self; @@ -106,13 +102,6 @@ const CGPoint TGPhotoEditorEdgeScrollTriggerOffset = { 100, 150 }; - (void)setSelectedItemIndexPath:(NSIndexPath *)indexPath { - NSArray *visibleItemsIndexPathes = self.indexPathsForVisibleItems; - for (NSIndexPath *i in visibleItemsIndexPathes) - { - UICollectionViewCell *cell = [self cellForItemAtIndexPath:i]; - if ([cell isKindOfClass:[TGPhotoFilterCell class]]) - [(TGPhotoFilterCell *)cell setFilterSelected:[i isEqual:indexPath]]; - } } - (void)selectItemAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UICollectionViewScrollPosition)scrollPosition @@ -140,12 +129,9 @@ const CGPoint TGPhotoEditorEdgeScrollTriggerOffset = { 100, 150 }; - (NSInteger)collectionView:(UICollectionView *)__unused collectionView numberOfItemsInSection:(NSInteger)__unused section { - id filtersDataSource = self.filtersDataSource; id toolsDataSource = self.toolsDataSource; - if ([filtersDataSource respondsToSelector:@selector(numberOfFiltersInCollectionView:)]) - return [filtersDataSource numberOfFiltersInCollectionView:self]; - else if ([toolsDataSource respondsToSelector:@selector(numberOfToolsInCollectionView:)]) + if ([toolsDataSource respondsToSelector:@selector(numberOfToolsInCollectionView:)]) return [toolsDataSource numberOfToolsInCollectionView:self]; return 0; @@ -153,29 +139,11 @@ const CGPoint TGPhotoEditorEdgeScrollTriggerOffset = { 100, 150 }; - (UICollectionViewCell *)collectionView:(UICollectionView *)__unused collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { - id filtersDataSource = self.filtersDataSource; id toolsDataSource = self.toolsDataSource; UICollectionViewCell *cell = nil; - if ([filtersDataSource respondsToSelector:@selector(collectionView:filterAtIndex:)]) - { - PGPhotoFilter *filter = [filtersDataSource collectionView:self filterAtIndex:indexPath.row]; - - cell = [self dequeueReusableCellWithReuseIdentifier:TGPhotoFilterCellKind forIndexPath:indexPath]; - [(TGPhotoFilterCell *)cell setPhotoFilter:filter]; - [(TGPhotoFilterCell *)cell setFilterSelected:[_selectedItemIndexPath isEqual:indexPath]]; - - [filtersDataSource collectionView:self requestThumbnailImageForFilterAtIndex:indexPath.row completion:^(UIImage *thumbnailImage, bool cached, __unused bool finished) - { - TGDispatchOnMainThread(^ - { - if ([[(TGPhotoFilterCell *)cell filterIdentifier] isEqualToString:filter.identifier]) - [(TGPhotoFilterCell *)cell setImage:thumbnailImage animated:!cached]; - }); - }]; - } - else if ([toolsDataSource respondsToSelector:@selector(collectionView:toolAtIndex:)]) + if ([toolsDataSource respondsToSelector:@selector(collectionView:toolAtIndex:)]) { cell = [self dequeueReusableCellWithReuseIdentifier:TGPhotoToolCellKind forIndexPath:indexPath]; cell.alpha = 1.0f; @@ -231,97 +199,6 @@ const CGPoint TGPhotoEditorEdgeScrollTriggerOffset = { 100, 150 }; block(); } -- (void)collectionView:(UICollectionView *)__unused collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath -{ - id filtersDataSource = self.filtersDataSource; - - if ([filtersDataSource respondsToSelector:@selector(collectionView:didSelectFilterWithIndex:)]) - { - bool vertical = false; - if (self.frame.size.height > self.frame.size.width) - vertical = true; - - CGFloat screenSize = 0; - CGFloat contentSize = 0; - CGFloat contentOffset = 0; - CGFloat itemPosition = 0; - CGFloat itemSize = 0; - CGFloat targetOverlap = 0; - CGFloat startInset = 0; - CGFloat endInset = 0; - - CGFloat triggerOffset = 0; - - if (!vertical) - { - screenSize = self.frame.size.width; - contentSize = self.contentSize.width; - contentOffset = self.contentOffset.x; - itemPosition = [self.collectionViewLayout layoutAttributesForItemAtIndexPath:indexPath].frame.origin.x; - itemSize = ((UICollectionViewFlowLayout *)self.collectionViewLayout).itemSize.width; - startInset = self.contentInset.left; - endInset = self.contentInset.right; - triggerOffset = TGPhotoEditorEdgeScrollTriggerOffset.x; - targetOverlap = itemSize / 2 + ((UICollectionViewFlowLayout *)self.collectionViewLayout).minimumLineSpacing; - } - else - { - screenSize = self.frame.size.height; - contentSize = self.contentSize.height; - contentOffset = self.contentOffset.y; - itemPosition = [self.collectionViewLayout layoutAttributesForItemAtIndexPath:indexPath].frame.origin.y; - itemSize = ((UICollectionViewFlowLayout *)self.collectionViewLayout).itemSize.height; - startInset = self.contentInset.top; - endInset = self.contentInset.bottom; - triggerOffset = TGPhotoEditorEdgeScrollTriggerOffset.y; - targetOverlap = itemSize + 2 * ((UICollectionViewFlowLayout *)self.collectionViewLayout).minimumLineSpacing; - } - - CGFloat itemsScreenPosition = itemPosition - contentOffset; - - if (itemsScreenPosition < triggerOffset) - { - CGFloat targetContentOffset = MAX(-startInset, itemPosition - targetOverlap); - - if (!vertical && targetContentOffset < startInset + itemSize) - targetContentOffset = -startInset; - - if (contentOffset > targetContentOffset) - { - if (!vertical) - [self setContentOffset:CGPointMake(targetContentOffset, -self.contentInset.top) animated:YES]; - else - [self setContentOffset:CGPointMake(-self.contentInset.left, targetContentOffset) animated:YES]; - - self.scrollEnabled = false; - } - } - else if (itemsScreenPosition > screenSize - triggerOffset) - { - CGFloat targetContentOffset = MIN(contentSize - screenSize + endInset, - itemPosition - screenSize + itemSize + targetOverlap); - - if (!vertical && targetContentOffset > contentSize - screenSize - endInset - itemSize) - targetContentOffset = contentSize - screenSize + endInset; - - if (contentOffset < targetContentOffset) - { - if (!vertical) - [self setContentOffset:CGPointMake(targetContentOffset, -self.contentInset.top) animated:YES]; - else - [self setContentOffset:CGPointMake(-self.contentInset.left, targetContentOffset) animated:YES]; - - self.scrollEnabled = false; - } - } - - [filtersDataSource collectionView:self didSelectFilterWithIndex:indexPath.row]; - - _selectedItemIndexPath = indexPath; - [self setSelectedItemIndexPath:indexPath]; - } -} - - (BOOL)collectionView:(UICollectionView *)__unused collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)__unused indexPath { return false; diff --git a/submodules/LegacyComponents/Sources/TGPhotoEditorInterfaceAssets.m b/submodules/LegacyComponents/Sources/TGPhotoEditorInterfaceAssets.m index 67f1ec0008..0f24694816 100644 --- a/submodules/LegacyComponents/Sources/TGPhotoEditorInterfaceAssets.m +++ b/submodules/LegacyComponents/Sources/TGPhotoEditorInterfaceAssets.m @@ -69,7 +69,7 @@ + (UIImage *)paintIcon { - return TGTintedImage([UIImage imageNamed:@"Editor/Drawing"], [self toolbarIconColor]); + return TGTintedImage([UIImage imageNamed:@"Editor/BrushSelectedPen"], [self toolbarIconColor]); } + (UIImage *)stickerIcon diff --git a/submodules/LegacyComponents/Sources/TGPhotoEditorUtils.m b/submodules/LegacyComponents/Sources/TGPhotoEditorUtils.m index c2a2882fe3..43490ea095 100644 --- a/submodules/LegacyComponents/Sources/TGPhotoEditorUtils.m +++ b/submodules/LegacyComponents/Sources/TGPhotoEditorUtils.m @@ -26,27 +26,31 @@ CGSize TGPhotoThumbnailSizeForCurrentScreen() { if (widescreenWidth >= 896.0f - FLT_EPSILON) { - return CGSizeMake(103.0f, 103.0f); + return CGSizeMake(137.0f - TGScreenPixel, 137.0f - TGScreenPixel); + } + else if (widescreenWidth >= 844.0f - FLT_EPSILON) + { + return CGSizeMake(129.0f - TGScreenPixel, 129.0f - TGScreenPixel); } else if (widescreenWidth >= 812.0f - FLT_EPSILON) { - return CGSizeMake(93.0f, 93.0f); + return CGSizeMake(124.0f - TGScreenPixel, 124.0f - TGScreenPixel); } else if (widescreenWidth >= 736.0f - FLT_EPSILON) { - return CGSizeMake(103.0f, 103.0f); + return CGSizeMake(137.0f - TGScreenPixel, 137.0f - TGScreenPixel); } else if (widescreenWidth >= 667.0f - FLT_EPSILON) { - return CGSizeMake(93.0f, 93.5f); + return CGSizeMake(124.0f - TGScreenPixel, 124.0f - TGScreenPixel); } else { - return CGSizeMake(78.5f, 78.5f); + return CGSizeMake(106.0f - TGScreenPixel, 106.0f - TGScreenPixel); } } - return CGSizeMake(78.5f, 78.5f); + return CGSizeMake(106.0f, 106.0f); } CGSize TGScaleToSize(CGSize size, CGSize maxSize) diff --git a/submodules/LegacyComponents/Sources/TGPhotoFilterCell.h b/submodules/LegacyComponents/Sources/TGPhotoFilterCell.h deleted file mode 100644 index 5a2cca3956..0000000000 --- a/submodules/LegacyComponents/Sources/TGPhotoFilterCell.h +++ /dev/null @@ -1,19 +0,0 @@ -#import - -@class PGPhotoFilter; - -@interface TGPhotoFilterCell : UICollectionViewCell - -@property (nonatomic, readonly) NSString *filterIdentifier; - -- (void)setPhotoFilter:(PGPhotoFilter *)photoFilter; -- (void)setFilterSelected:(BOOL)selected; - -- (void)setImage:(UIImage *)image; -- (void)setImage:(UIImage *)image animated:(bool)animated; - -+ (CGFloat)filterCellWidth; - -@end - -extern NSString * const TGPhotoFilterCellKind; diff --git a/submodules/LegacyComponents/Sources/TGPhotoFilterCell.m b/submodules/LegacyComponents/Sources/TGPhotoFilterCell.m deleted file mode 100644 index d558038669..0000000000 --- a/submodules/LegacyComponents/Sources/TGPhotoFilterCell.m +++ /dev/null @@ -1,126 +0,0 @@ -#import "TGPhotoFilterCell.h" - -#import "PGPhotoFilter.h" -#import "PGPhotoFilterDefinition.h" - -#import "TGPhotoEditorInterfaceAssets.h" - -NSString * const TGPhotoFilterCellKind = @"TGPhotoFilterCellKind"; - -@interface TGPhotoFilterCell () -{ - UIImageView *_imageView; - UIImageView *_selectionView; - UILabel *_titleLabel; -} -@end - -@implementation TGPhotoFilterCell - -- (instancetype)initWithFrame:(CGRect)frame -{ - self = [super initWithFrame:frame]; - if (self != nil) - { - _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.width)]; - _imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - [self addSubview:_imageView]; - - _titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, _imageView.frame.origin.y + _imageView.frame.size.height + 5, frame.size.width, 17)]; - _titleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth; - _titleLabel.backgroundColor = [UIColor clearColor]; - _titleLabel.font = [TGPhotoEditorInterfaceAssets editorItemTitleFont]; - _titleLabel.textAlignment = NSTextAlignmentCenter; - _titleLabel.textColor = [TGPhotoEditorInterfaceAssets editorItemTitleColor]; - _titleLabel.highlightedTextColor = [TGPhotoEditorInterfaceAssets editorActiveItemTitleColor]; - [self addSubview:_titleLabel]; - - static UIImage *selectionImage = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^ - { - CGFloat width = [TGPhotoFilterCell filterCellWidth]; - UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, width), false, 0.0f); - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSetFillColorWithColor(context, [TGPhotoEditorInterfaceAssets filterSelectionColor].CGColor); - - UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(3, 3, width - 2 * 3, width - 2 * 3)]; - [path appendPath:[UIBezierPath bezierPathWithRect:CGRectMake(0, 0, width, width)]]; - path.usesEvenOddFillRule = true; - [path fill]; - - selectionImage = [UIGraphicsGetImageFromCurrentImageContext() resizableImageWithCapInsets:UIEdgeInsetsMake(3, 3, 3, 3)]; - UIGraphicsEndImageContext(); - }); - - _selectionView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.width)]; - _selectionView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - _selectionView.image = selectionImage; - _selectionView.hidden = true; - [self addSubview:_selectionView]; - } - return self; -} - -- (void)setPhotoFilter:(PGPhotoFilter *)photoFilter -{ - _filterIdentifier = photoFilter.identifier; - _titleLabel.text = photoFilter.definition.title; -} - -- (void)setFilterSelected:(BOOL)selected -{ - [super setSelected:selected]; - - _titleLabel.highlighted = selected; - _selectionView.hidden = !selected; -} - -- (void)setImage:(UIImage *)image -{ - [self setImage:image animated:false]; -} - -- (void)setImage:(UIImage *)image animated:(bool)animated -{ - if (_imageView.image == nil) - animated = false; - - if (animated) - { - UIImageView *transitionView = [[UIImageView alloc] initWithImage:_imageView.image]; - transitionView.frame = _imageView.frame; - [self insertSubview:transitionView aboveSubview:_imageView]; - - _imageView.image = image; - - [UIView animateWithDuration:0.3f animations:^ - { - transitionView.alpha = 0.0f; - } completion:^(__unused BOOL finished) - { - [transitionView removeFromSuperview]; - }]; - } - else - { - _imageView.image = image; - } -} - -- (void)setSelected:(BOOL)__unused selected -{ - -} - -- (void)setHighlighted:(BOOL)__unused highlighted -{ - -} - -+ (CGFloat)filterCellWidth -{ - return 64; -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGPhotoPaintController.m b/submodules/LegacyComponents/Sources/TGPhotoPaintController.m index 06583aa272..f90dad60c1 100644 --- a/submodules/LegacyComponents/Sources/TGPhotoPaintController.m +++ b/submodules/LegacyComponents/Sources/TGPhotoPaintController.m @@ -347,7 +347,7 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f; [_doneButton setTitle:TGLocalized(@"Common.Done") forState:UIControlStateNormal]; _doneButton.titleLabel.font = TGSystemFontOfSize(17.0); [_doneButton sizeToFit]; - [_wrapperView addSubview:_doneButton]; +// [_wrapperView addSubview:_doneButton]; void (^settingsPressed)(void) = ^ { diff --git a/submodules/LegacyComponents/Sources/TGPhotoPaintSettingsView.h b/submodules/LegacyComponents/Sources/TGPhotoPaintSettingsView.h index bc962f881f..035895cab6 100644 --- a/submodules/LegacyComponents/Sources/TGPhotoPaintSettingsView.h +++ b/submodules/LegacyComponents/Sources/TGPhotoPaintSettingsView.h @@ -35,10 +35,6 @@ typedef enum - (void)setIcon:(TGPhotoPaintSettingsViewIcon)icon animated:(bool)animated; - (void)setHighlighted:(bool)highlighted; -+ (UIImage *)landscapeLeftBackgroundImage; -+ (UIImage *)landscapeRightBackgroundImage; -+ (UIImage *)portraitBackgroundImage; - @end @protocol TGPhotoPaintPanelView diff --git a/submodules/LegacyComponents/Sources/TGPhotoPaintSettingsView.m b/submodules/LegacyComponents/Sources/TGPhotoPaintSettingsView.m index 6a9489a2ed..9a48e7c7c5 100644 --- a/submodules/LegacyComponents/Sources/TGPhotoPaintSettingsView.m +++ b/submodules/LegacyComponents/Sources/TGPhotoPaintSettingsView.m @@ -236,37 +236,4 @@ const CGFloat TGPhotoPaintSettingsPadPickerWidth = 360.0f; } } -+ (UIImage *)landscapeLeftBackgroundImage -{ - static dispatch_once_t onceToken; - static UIImage *image; - dispatch_once(&onceToken, ^ - { - image = [TGTintedImage(TGComponentsImageNamed(@"PaintPopupLandscapeLeftBackground"), UIColorRGB(0xf7f7f7)) resizableImageWithCapInsets:UIEdgeInsetsMake(32.0f, 32.0f, 32.0f, 32.0f)]; - }); - return image; -} - -+ (UIImage *)landscapeRightBackgroundImage -{ - static dispatch_once_t onceToken; - static UIImage *image; - dispatch_once(&onceToken, ^ - { - image = [TGTintedImage(TGComponentsImageNamed(@"PaintPopupLandscapeRightBackground"), UIColorRGB(0xf7f7f7)) resizableImageWithCapInsets:UIEdgeInsetsMake(32.0f, 32.0f, 32.0f, 32.0f)]; - }); - return image; -} - -+ (UIImage *)portraitBackgroundImage -{ - static dispatch_once_t onceToken; - static UIImage *image; - dispatch_once(&onceToken, ^ - { - image = [TGTintedImage(TGComponentsImageNamed(@"PaintPopupPortraitBackground"), UIColorRGB(0xf7f7f7)) resizableImageWithCapInsets:UIEdgeInsetsMake(32.0f, 32.0f, 32.0f, 32.0f)]; - }); - return image; -} - @end diff --git a/submodules/LegacyComponents/Sources/TGPhotoVideoEditor.m b/submodules/LegacyComponents/Sources/TGPhotoVideoEditor.m index 8d9a75c1d4..e45d5b3673 100644 --- a/submodules/LegacyComponents/Sources/TGPhotoVideoEditor.m +++ b/submodules/LegacyComponents/Sources/TGPhotoVideoEditor.m @@ -102,7 +102,7 @@ } } -+ (void)presentWithContext:(id)context controller:(TGViewController *)controller caption:(NSString *)caption entities:(NSArray *)entities withItem:(id)item recipientName:(NSString *)recipientName stickersContext:(id)stickersContext completion:(void (^)(id, TGMediaEditingContext *))completion dismissed:(void (^)())dismissed ++ (void)presentWithContext:(id)context controller:(TGViewController *)controller caption:(NSString *)caption entities:(NSArray *)entities withItem:(id)item paint:(bool)paint recipientName:(NSString *)recipientName stickersContext:(id)stickersContext completion:(void (^)(id, TGMediaEditingContext *))completion dismissed:(void (^)())dismissed { id windowManager = [context makeOverlayWindowManager]; id windowContext = [windowManager context]; @@ -173,14 +173,6 @@ completion(item.asset, editingContext); [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) @@ -207,10 +199,14 @@ dismissed(); } }; - + TGOverlayControllerWindow *controllerWindow = [[TGOverlayControllerWindow alloc] initWithManager:windowManager parentController:controller contentController:galleryController]; controllerWindow.hidden = false; galleryController.view.clipsToBounds = true; + +// if (paint) { +// [model presentPhotoEditorForItem:galleryItem tab:TGPhotoEditorPaintTab]; +// } } @end diff --git a/submodules/LegacyComponents/Sources/TGSearchBar.m b/submodules/LegacyComponents/Sources/TGSearchBar.m deleted file mode 100644 index 150b84d8b9..0000000000 --- a/submodules/LegacyComponents/Sources/TGSearchBar.m +++ /dev/null @@ -1,1197 +0,0 @@ -#import "TGSearchBar.h" - -#import "LegacyComponentsInternal.h" -#import "TGColor.h" - -#import -#import - -#import - -#import - -#import - -#import - -@interface TGSearchBar () -{ - CGFloat _cancelButtonWidth; - - TGSearchBarPallete *_pallete; -} - -@property (nonatomic, strong) UIView *wrappingClip; -@property (nonatomic, strong) UIView *wrappingView; - -@property (nonatomic, strong) UIImageView *textFieldBackground; - -@property (nonatomic, strong) UIImage *normalTextFieldBackgroundImage; -@property (nonatomic, strong) UIImage *activeTextFieldBackgroundImage; - -@property (nonatomic) bool showsCustomCancelButton; -@property (nonatomic, strong) UILabel *placeholderLabel; -@property (nonatomic, strong) UILabel *prefixLabel; -@property (nonatomic, strong) UIImageView *customSearchIcon; -@property (nonatomic, strong) UIActivityIndicatorView *customSearchActivityIndicator; -@property (nonatomic, strong) NSTimer *searchActivityTimer; -@property (nonatomic, strong) UIButton *customClearButton; - -@property (nonatomic, strong) UIView *customScopeButtonContainer; -@property (nonatomic, strong) UISegmentedControl *customSegmentedControl; -@property (nonatomic) int customCurrentScope; - -@end - -@implementation TGSearchBar - -+ (CGFloat)searchBarBaseHeight -{ - return 44.0f; -} - -- (CGFloat)baseHeight { - if (self.showsScopeBar) - return 44.0f; - if (_style == TGSearchBarStyleKeyboard) { - return [self inputHeight] + 17.0f; - } - return [self inputHeight] + 12.0f; -} - -- (CGFloat)inputContentOffset { - if (_style == TGSearchBarStyleKeyboard) { - return 3.0f; - } - return _style == TGSearchBarStyleLightAlwaysPlain ? 3.0f : 0.0f; -} - -- (CGFloat)searchIconOffset { - return _style == TGSearchBarStyleLightAlwaysPlain ? TGScreenPixel : 0.0f; -} - -- (CGFloat)inputHeight { - if (_style == TGSearchBarStyleKeyboard) { - return 33.0f; - } else { - return _style == TGSearchBarStyleLightAlwaysPlain ? 36.0f : 28.0f; - } -} - -+ (CGFloat)searchBarScopeHeight -{ - return 44.0f; -} - -- (CGFloat)topPadding -{ - if (_style == TGSearchBarStyleKeyboard) - return 4.0f; - - return -1.0f; -} - -- (CGFloat)cancelButtonPadding -{ - if (_style == TGSearchBarStyleKeyboard) - return -2.0f; - - return 0.0f; -} - -- (id)initWithFrame:(CGRect)frame -{ - return [self initWithFrame:frame style:TGSearchBarStyleLightPlain]; -} - -- (instancetype)initWithFrame:(CGRect)frame style:(TGSearchBarStyle)style -{ - self = [super initWithFrame:frame]; - if (self != nil) - { - _delayActivity = true; - - _wrappingClip = [[UIView alloc] initWithFrame:CGRectMake(0.0f, -20.0f, frame.size.width, frame.size.height + 20.0f)]; - _wrappingClip.clipsToBounds = true; - [self addSubview:_wrappingClip]; - - _wrappingView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 20.0f, frame.size.width, frame.size.height)]; - [_wrappingClip addSubview:_wrappingView]; - - _style = style; - - NSString *backgroundFileName = nil; - NSString *backgroundActiveFileName = nil; - - UIImage *backgroundManualImage = nil; - UIImage *backgroundManualActiveImage = nil; - - if (_style == TGSearchBarStyleDefault) - { - backgroundFileName = @"SearchBarBackground.png"; - backgroundActiveFileName = @"SearchBarBackground_Active.png"; - } - else if (_style == TGSearchBarStyleDark) - { - backgroundFileName = @"SearchBarBackgroundDark.png"; - backgroundActiveFileName = @"SearchBarBackgroundDark.png"; - } - else if (_style == TGSearchBarStyleLight || _style == TGSearchBarStyleLightPlain || _style == TGSearchBarStyleLightAlwaysPlain || _style == TGSearchBarStyleHeader) - { - static UIImage *image = nil; - static UIImage *imagePlain = nil; - static UIImage *imagePlainForced = nil; - static UIImage *imageHeader = nil; - - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^ - { - UIGraphicsBeginImageContextWithOptions(CGSizeMake(1.0f, 3.0f), false, 0.0f); - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSetFillColorWithColor(context, [UIColor clearColor].CGColor); - CGContextFillRect(context, CGRectMake(0.0f, 0.0f, 1.0f, 3.0f)); - imagePlain = [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:0 topCapHeight:1]; - CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor); - CGContextFillRect(context, CGRectMake(0.0f, 0.0f, 1.0f, 3.0f)); - imagePlainForced = [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:0 topCapHeight:1]; - - CGContextSetFillColorWithColor(context, UIColorRGB(0xc8c7cc).CGColor); - CGFloat separatorHeight = TGScreenPixel; - CGContextFillRect(context, CGRectMake(0.0f, 3.0f - separatorHeight, 1.0f, separatorHeight)); - - image = [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:0 topCapHeight:1]; - UIGraphicsEndImageContext(); - - - UIGraphicsBeginImageContextWithOptions(CGSizeMake(1.0f, 3.0f), true, 0.0f); - context = UIGraphicsGetCurrentContext(); - CGContextSetFillColorWithColor(context, UIColorRGB(0xf7f7f7).CGColor); - CGContextFillRect(context, CGRectMake(0.0f, 0.0f, 1.0f, 3.0f)); - - CGContextSetFillColorWithColor(context, UIColorRGB(0xc8c7cc).CGColor); - CGContextFillRect(context, CGRectMake(0.0f, 3.0f - separatorHeight, 1.0f, separatorHeight)); - - imageHeader = [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:0 topCapHeight:1]; - - UIGraphicsEndImageContext(); - }); - - if (_style == TGSearchBarStyleHeader) - { - backgroundManualImage = imageHeader; - backgroundManualActiveImage = imageHeader; - } - else - { - backgroundManualImage = _style == TGSearchBarStyleLight ? image : imagePlain; - backgroundManualActiveImage = _style == TGSearchBarStyleLightAlwaysPlain ? imagePlainForced : image; - } - } - - UIImage *backgroundImage = nil; - if (backgroundManualImage != nil) - backgroundImage = backgroundManualImage; - else - backgroundImage = [TGImageNamed(backgroundFileName) stretchableImageWithLeftCapWidth:1 topCapHeight:1]; - _customBackgroundView = [[UIImageView alloc] initWithFrame:self.bounds]; - _customBackgroundView.image = backgroundImage; - _customBackgroundView.userInteractionEnabled = true; - [_customBackgroundView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(backgroundTapGesture:)]]; - [_wrappingView addSubview:_customBackgroundView]; - - UIImage *activeBackgroundImage = nil; - if (backgroundManualActiveImage != nil) - activeBackgroundImage = backgroundManualActiveImage; - else - activeBackgroundImage = [TGImageNamed(backgroundActiveFileName) stretchableImageWithLeftCapWidth:1 topCapHeight:1]; - _customActiveBackgroundView = [[UIImageView alloc] initWithFrame:self.bounds]; - _customActiveBackgroundView.image = activeBackgroundImage; - _customActiveBackgroundView.alpha = 0.0f; - [_wrappingView addSubview:_customActiveBackgroundView]; - - _textFieldBackground = [[UIImageView alloc] initWithImage:self.normalTextFieldBackgroundImage]; - _textFieldBackground.userInteractionEnabled = false; - [_wrappingView addSubview:_textFieldBackground]; - - UIColor *placeholderColor = nil; - if (_style == TGSearchBarStyleDefault) - placeholderColor = UIColorRGB(0x8e8e93); - else if (_style == TGSearchBarStyleDark) - placeholderColor = [UIColor whiteColor]; - else if (_style == TGSearchBarStyleLight || _style == TGSearchBarStyleLightPlain || _style == TGSearchBarStyleLightAlwaysPlain || _style == TGSearchBarStyleHeader) - placeholderColor = UIColorRGB(0x8e8e93); - - _placeholderLabel = [[UILabel alloc] init]; - _placeholderLabel.textAlignment = NSTextAlignmentLeft; - _placeholderLabel.userInteractionEnabled = false; - _placeholderLabel.textColor = placeholderColor; - _placeholderLabel.backgroundColor = [UIColor clearColor]; - _placeholderLabel.font = TGSystemFontOfSize(style == TGSearchBarStyleLightAlwaysPlain ? 16.0f : 14.0f); - _placeholderLabel.text = TGLocalized(@"Common.Search"); - [_wrappingView addSubview:_placeholderLabel]; - - _prefixLabel = [[UILabel alloc] init]; - _prefixLabel.textAlignment = NSTextAlignmentLeft; - _prefixLabel.userInteractionEnabled = false; - _prefixLabel.textColor = placeholderColor; - _prefixLabel.backgroundColor = [UIColor clearColor]; - _prefixLabel.font = TGSystemFontOfSize(style == TGSearchBarStyleLightAlwaysPlain ? 16.0f : 14.0f); - [_wrappingView addSubview:_prefixLabel]; - - UIImage *iconImage = nil; - if (_style == TGSearchBarStyleDefault) - { - iconImage = TGImageNamed(@"SearchBarIcon.png"); - } - else if (_style == TGSearchBarStyleDark) - { - iconImage = TGImageNamed(@"SearchBarIconDark.png"); - } - else if (_style == TGSearchBarStyleLight || _style == TGSearchBarStyleLightPlain || _style == TGSearchBarStyleHeader) - { - iconImage = [TGSearchBar searchBarIcon:UIColorRGB(0x8e8e93)]; - } - else if (_style == TGSearchBarStyleLightAlwaysPlain || _style == TGSearchBarStyleKeyboard) - { - iconImage = TGImageNamed(@"SearchBarIconLightLarge.png"); - } - - _customSearchIcon = [[UIImageView alloc] initWithImage:iconImage]; - _customSearchIcon.userInteractionEnabled = false; - [_wrappingView addSubview:_customSearchIcon]; - } - return self; -} - -- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event -{ - return [super hitTest:point withEvent:event]; -} - -+ (UIImage *)searchBarIcon:(UIColor *)color -{ - UIGraphicsBeginImageContextWithOptions(CGSizeMake(13, 13), false, 0.0f); - - CGContextRef context = UIGraphicsGetCurrentContext(); - - CGContextSetStrokeColorWithColor(context, color.CGColor); - CGContextSetLineWidth(context, 1.0f); - CGContextSetLineCap(context, kCGLineCapRound); - CGContextStrokeEllipseInRect(context, CGRectMake(0.5f, 0.5f, 9.0f, 9.0f)); - - CGContextSetLineWidth(context, 1.5f); - CGContextMoveToPoint(context, 8.5f, 8.5f); - CGContextAddLineToPoint(context, 8.5f + 3.5f, 8.5f + 3.5f); - CGContextStrokePath(context); - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - return image; -} - -- (void)setHighContrast:(bool)highContrast { - if (_highContrast != highContrast) { - _highContrast = highContrast; - _textFieldBackground.image = _showsCustomCancelButton ? self.activeTextFieldBackgroundImage : self.normalTextFieldBackgroundImage; - } -} - -- (void)setAlwaysExtended:(bool)alwaysExtended -{ - if (_alwaysExtended != alwaysExtended) - { - _alwaysExtended = alwaysExtended; - - [self layoutSubviews]; - } -} - -- (void)setFrame:(CGRect)frame -{ - [super setFrame:frame]; -} - -- (void)sizeToFit -{ - CGFloat requiredHeight = 0; - - if (_searchBarShouldShowScopeControl && ![self landscapeMode] && !_scopeBarCollapsed) - { - requiredHeight = [self baseHeight] + [TGSearchBar searchBarScopeHeight]; - } - else - { - requiredHeight = [self baseHeight]; - } - - if (_style == TGSearchBarStyleLight) - requiredHeight += 4.0f; - - CGRect frame = self.frame; - frame.size.height = requiredHeight; - self.frame = frame; -} - -- (BOOL)showsCancelButton -{ - return _showsCustomCancelButton; -} - -- (void)setPallete:(TGSearchBarPallete *)pallete -{ - _pallete = pallete; - - _customSearchActivityIndicator.color = _pallete.placeholderColor; - - _customTextField.textColor = pallete.textColor; - _prefixLabel.textColor = pallete.placeholderColor; - _placeholderLabel.textColor = pallete.placeholderColor; - - [UIView performWithoutAnimation:^ - { - bool shouldFlip = _customTextField.isFirstResponder; - if (shouldFlip) - [_customTextField resignFirstResponder]; - _customTextField.keyboardAppearance = _style == TGSearchBarStyleDark || _pallete.isDark ? UIKeyboardAppearanceAlert : UIKeyboardAppearanceDefault; - if (shouldFlip) - [_customTextField becomeFirstResponder]; - }]; - _customSearchIcon.image = [TGSearchBar searchBarIcon:pallete.placeholderColor]; - [_customClearButton setBackgroundImage:_pallete.clearIcon forState:UIControlStateNormal]; - - _normalTextFieldBackgroundImage = nil; - _activeTextFieldBackgroundImage = nil; - _textFieldBackground.image = _showsCustomCancelButton ? self.activeTextFieldBackgroundImage : self.normalTextFieldBackgroundImage; - - UIImage *backgroundManualImage = nil; - UIImage *backgroundManualActiveImage = nil; - - if (_style == TGSearchBarStyleLight || _style == TGSearchBarStyleLightPlain || _style == TGSearchBarStyleLightAlwaysPlain || _style == TGSearchBarStyleHeader || _style == TGSearchBarStyleKeyboard) - { - [(TGModernButton *)_customCancelButton setTitleColor:_pallete.accentColor]; - - UIGraphicsBeginImageContextWithOptions(CGSizeMake(1.0f, 3.0f), false, 0.0f); - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSetFillColorWithColor(context, [UIColor clearColor].CGColor); - CGContextFillRect(context, CGRectMake(0.0f, 0.0f, 1.0f, 3.0f)); - UIImage *imagePlain = [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:0 topCapHeight:1]; - CGContextSetFillColorWithColor(context, _style == TGSearchBarStyleLightAlwaysPlain ? pallete.menuBackgroundColor.CGColor : pallete.plainBackgroundColor.CGColor); - CGContextFillRect(context, CGRectMake(0.0f, 0.0f, 1.0f, 3.0f)); - UIImage *imagePlainForced = [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:0 topCapHeight:1]; - - CGContextSetFillColorWithColor(context, pallete.barSeparatorColor.CGColor); - CGFloat separatorHeight = TGScreenPixel; - CGContextFillRect(context, CGRectMake(0.0f, 3.0f - separatorHeight, 1.0f, separatorHeight)); - - UIImage *image = [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:0 topCapHeight:1]; - UIGraphicsEndImageContext(); - - - UIGraphicsBeginImageContextWithOptions(CGSizeMake(1.0f, 3.0f), true, 0.0f); - context = UIGraphicsGetCurrentContext(); - CGContextSetFillColorWithColor(context, pallete.barBackgroundColor.CGColor); - CGContextFillRect(context, CGRectMake(0.0f, 0.0f, 1.0f, 3.0f)); - - CGContextSetFillColorWithColor(context, pallete.barSeparatorColor.CGColor); - CGContextFillRect(context, CGRectMake(0.0f, 3.0f - separatorHeight, 1.0f, separatorHeight)); - - UIImage *imageHeader = [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:0 topCapHeight:1]; - - UIGraphicsEndImageContext(); - - if (_style == TGSearchBarStyleHeader) - { - backgroundManualImage = imageHeader; - backgroundManualActiveImage = imageHeader; - } - else - { - backgroundManualImage = _style == TGSearchBarStyleLight ? image : imagePlain; - backgroundManualActiveImage = _style == TGSearchBarStyleLightAlwaysPlain ? imagePlainForced : image; - } - - if (backgroundManualImage != nil) - _customBackgroundView.image = backgroundManualImage; - - if (backgroundManualActiveImage != nil) - _customActiveBackgroundView.image = backgroundManualActiveImage; - } -} - -- (UIImage *)normalTextFieldBackgroundImage -{ - if (_highContrast) { - UIColor *highContrastColor = _pallete != nil ? _pallete.highContrastBackgroundColor : UIColorRGB(0xe5e5e5); - CGFloat diameter = 14.0f; - UIGraphicsBeginImageContextWithOptions(CGSizeMake(diameter, diameter), false, 0.0f); - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSetFillColorWithColor(context, highContrastColor.CGColor); - CGContextFillEllipseInRect(context, CGRectMake(0.0f, 0.0f, diameter, diameter)); - UIImage *image = [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:(NSInteger)(diameter / 2.0f) topCapHeight:(NSInteger)(diameter / 2.0f)]; - UIGraphicsEndImageContext(); - - return image; - } else if (_normalTextFieldBackgroundImage == nil) { - NSString *fileName = nil; - - if (_style == TGSearchBarStyleDefault) - fileName = @"SearchInputField.png"; - else if (_style == TGSearchBarStyleDark) - fileName = @"SearchInputFieldDark.png"; - else if (_style == TGSearchBarStyleLight || _style == TGSearchBarStyleLightPlain) - { - UIColor *color = _pallete != nil ? _pallete.backgroundColor : UIColorRGB(0xf1f1f1); - UIGraphicsBeginImageContextWithOptions(CGSizeMake(14.0f, 14.0f), false, 0.0f); - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSetFillColorWithColor(context, color.CGColor); - CGContextFillEllipseInRect(context, CGRectMake(0.0f, 0.0f, 14.0f, 14.0f)); - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - image = [image stretchableImageWithLeftCapWidth:(int)(image.size.width / 2) topCapHeight:(int)(image.size.height / 2)]; - UIGraphicsEndImageContext(); - - _normalTextFieldBackgroundImage = image; - return _normalTextFieldBackgroundImage; - } - else if (_style == TGSearchBarStyleLightAlwaysPlain) - { - CGFloat diameter = 16.0f; - UIGraphicsBeginImageContextWithOptions(CGSizeMake(diameter, diameter), false, 0.0f); - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSetFillColorWithColor(context, (_pallete != nil ? _pallete.highContrastBackgroundColor : UIColorRGB(0xe4e4e4)).CGColor); - CGContextFillEllipseInRect(context, CGRectMake(0.0f, 0.0f, diameter, diameter)); - UIImage *image = [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:(NSInteger)(diameter / 2.0f) topCapHeight:(NSInteger)(diameter / 2.0f)]; - UIGraphicsEndImageContext(); - - _normalTextFieldBackgroundImage = image; - return _normalTextFieldBackgroundImage; - } - else if (_style == TGSearchBarStyleKeyboard) - { - CGFloat diameter = 33.0; - UIGraphicsBeginImageContextWithOptions(CGSizeMake(diameter, diameter), false, 0.0f); - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSetFillColorWithColor(context, (_pallete != nil ? _pallete.highContrastBackgroundColor : UIColorRGB(0xe4e4e4)).CGColor); - CGContextFillEllipseInRect(context, CGRectMake(0.0f, 0.0f, diameter, diameter)); - UIImage *image = [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:(NSInteger)(diameter / 2.0f) topCapHeight:(NSInteger)(diameter / 2.0f)]; - UIGraphicsEndImageContext(); - - _normalTextFieldBackgroundImage = image; - return _normalTextFieldBackgroundImage; - } - else if (_style == TGSearchBarStyleHeader) - { - CGFloat diameter = 10.0f; - UIGraphicsBeginImageContextWithOptions(CGSizeMake(diameter, diameter), false, 0.0f); - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSetFillColorWithColor(context, (_pallete != nil ? _pallete.highContrastBackgroundColor : UIColorRGB(0xe4e4e4)).CGColor); - CGContextFillEllipseInRect(context, CGRectMake(0.0f, 0.0f, diameter, diameter)); - UIImage *headerImage = [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:(NSInteger)(diameter / 2.0f) topCapHeight:(NSInteger)(diameter / 2.0f)]; - UIGraphicsEndImageContext(); - - _normalTextFieldBackgroundImage = headerImage; - return _normalTextFieldBackgroundImage; - } - - UIImage *rawImage = TGImageNamed(fileName); - _normalTextFieldBackgroundImage = [rawImage stretchableImageWithLeftCapWidth:(int)(rawImage.size.width / 2) topCapHeight:(int)(rawImage.size.height / 2)]; - } - - return _normalTextFieldBackgroundImage; -} - -- (UIImage *)activeTextFieldBackgroundImage -{ - if (_activeTextFieldBackgroundImage == nil) - { - NSString *fileName = nil; - - if (_style == TGSearchBarStyleDefault) - fileName = @"SearchInputField_Active.png"; - else if (_style == TGSearchBarStyleDark) - fileName = @"SearchInputFieldDark.png"; - else if (_style == TGSearchBarStyleLight || _style == TGSearchBarStyleLightPlain) - { - UIColor *color = _pallete != nil ? _pallete.backgroundColor : UIColorRGB(0xf1f1f1); - UIGraphicsBeginImageContextWithOptions(CGSizeMake(14.0f, 14.0f), false, 0.0f); - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSetFillColorWithColor(context, color.CGColor); - CGContextFillEllipseInRect(context, CGRectMake(0.0f, 0.0f, 14.0f, 14.0f)); - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - image = [image stretchableImageWithLeftCapWidth:(int)(image.size.width / 2) topCapHeight:(int)(image.size.height / 2)]; - UIGraphicsEndImageContext(); - - _activeTextFieldBackgroundImage = image; - return _activeTextFieldBackgroundImage; - } - else if (_style == TGSearchBarStyleLightAlwaysPlain || _style == TGSearchBarStyleHeader || _style == TGSearchBarStyleKeyboard) { - _activeTextFieldBackgroundImage = [self normalTextFieldBackgroundImage]; - return _activeTextFieldBackgroundImage; - } - - UIImage *rawImage = TGImageNamed(fileName); - _activeTextFieldBackgroundImage = [rawImage stretchableImageWithLeftCapWidth:(int)(rawImage.size.width / 2) topCapHeight:(int)(rawImage.size.height / 2)]; - } - - return _activeTextFieldBackgroundImage; -} - -- (UITextField *)maybeCustomTextField -{ - return _customTextField; -} - -- (UITextField *)customTextField -{ - if (_customTextField == nil) - { - CGRect frame = _textFieldBackground.frame; - frame.origin.y -= TGIsRetina() ? 0.0f : 0.0f; - frame.origin.x += 27; - frame.size.width -= 27 + 8 + 14; - _customTextField = [[TGTextField alloc] initWithFrame:frame]; - __weak TGSearchBar *weakSelf = self; - ((TGTextField *)_customTextField).deleteBackwardEmpty = ^{ - __strong TGSearchBar *strongSelf = weakSelf; - if (strongSelf != nil && strongSelf->_clearPrefix) { - strongSelf->_clearPrefix(false); - } - }; - _customTextField.font = _placeholderLabel.font; - if (iosMajorVersion() >= 7) - _customTextField.textAlignment = NSTextAlignmentNatural; - _customTextField.autocapitalizationType = UITextAutocapitalizationTypeNone; - _customTextField.autocorrectionType = UITextAutocorrectionTypeNo; - - UIColor *textColor = nil; - UIImage *clearImage = nil; - - if (_style == TGSearchBarStyleDefault || _style == TGSearchBarStyleLight || _style == TGSearchBarStyleLightPlain || _style == TGSearchBarStyleLightAlwaysPlain || _style == TGSearchBarStyleHeader || _style == TGSearchBarStyleKeyboard) - { - textColor = _pallete != nil ? _pallete.textColor : [UIColor blackColor]; - clearImage = TGImageNamed(@"SearchBarClearIcon.png"); - } - else if (_style == TGSearchBarStyleDark) - { - textColor = [UIColor whiteColor]; - clearImage = TGImageNamed(@"SearchBarClearIconDark.png"); - } - - _customTextField.textColor = textColor; - - _customTextField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter; - _customTextField.returnKeyType = UIReturnKeySearch; - _customTextField.keyboardAppearance = _style == TGSearchBarStyleDark || _pallete.isDark ? UIKeyboardAppearanceAlert : UIKeyboardAppearanceDefault; - _customTextField.delegate = self; - [_customTextField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged]; - - _customClearButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, clearImage.size.width, clearImage.size.height)]; - [_customClearButton setBackgroundImage:_pallete != nil ? _pallete.clearIcon : clearImage forState:UIControlStateNormal]; - [_customClearButton addTarget:self action:@selector(customClearButtonPressed) forControlEvents:UIControlEventTouchUpInside]; - _customClearButton.hidden = true; - - [_wrappingView addSubview:_customTextField]; - [_wrappingView addSubview:_customClearButton]; - - [self setNeedsLayout]; - } - - return _customTextField; -} - -- (UIButton *)customCancelButton -{ - if (_customCancelButton == nil) - { - _cancelButtonWidth = [TGLocalized(@"Common.Cancel") sizeWithFont:TGSystemFontOfSize(17.0f)].width + 11.0f; - - CGRect textFieldBackgroundFrame = _textFieldBackground.frame; - _customCancelButton = [[TGModernButton alloc] initWithFrame:CGRectMake(textFieldBackgroundFrame.origin.x + textFieldBackgroundFrame.size.width + 10, 0, _cancelButtonWidth, [self baseHeight])]; - [_customCancelButton setTitle:TGLocalized(@"Common.Cancel") forState:UIControlStateNormal]; - - UIColor *buttonColor = nil; - - if (_style == TGSearchBarStyleDefault || _style == TGSearchBarStyleLight || _style == TGSearchBarStyleLightPlain || _style == TGSearchBarStyleLightAlwaysPlain || _style == TGSearchBarStyleHeader || _style == TGSearchBarStyleKeyboard) - buttonColor = _pallete != nil ? _pallete.accentColor : TGAccentColor(); - else if (_style == TGSearchBarStyleDark) - buttonColor = [UIColor whiteColor]; - - [(TGModernButton *)_customCancelButton setTitleColor:buttonColor]; - _customCancelButton.titleLabel.font = TGSystemFontOfSize(17.0f); - _customCancelButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight; - _customCancelButton.hidden = true; - [_customCancelButton addTarget:self action:@selector(searchCancelButtonPressed) forControlEvents:UIControlEventTouchUpInside]; - [_wrappingView addSubview:_customCancelButton]; - } - - return _customCancelButton; -} - -- (void)setShowsCancelButton:(BOOL)showsCancelButton -{ - [self setShowsCancelButton:showsCancelButton animated:false]; -} - -- (void)setShowsCancelButton:(bool)showsCancelButton animated:(bool)animated -{ - if (_showsCustomCancelButton != showsCancelButton) - { - if (showsCancelButton) - { - [self customCancelButton]; - _customCancelButton.hidden = _hidesCancelButton; - - if (_customScopeButtonTitles.count > 1) - { - self.customScopeButtonContainer.hidden = false; - [_customSegmentedControl setSelectedSegmentIndex:0]; - } - } - else - { - [_customTextField setText:@""]; - [self updatePlaceholder:@""]; - } - - _textFieldBackground.image = showsCancelButton ? self.activeTextFieldBackgroundImage : self.normalTextFieldBackgroundImage; - - _showsCustomCancelButton = showsCancelButton; - - if (animated) - { - if (showsCancelButton) - _wrappingClip.clipsToBounds = false; - - [UIView animateWithDuration:0.2 animations:^ - { - if (!showsCancelButton) - { - _customTextField.alpha = 0.0f; - _customClearButton.alpha = 0.0f; - } - - if (_customScopeButtonTitles.count > 1) - { - [self setSearchBarShouldShowScopeControl:showsCancelButton]; - _customScopeButtonContainer.alpha = showsCancelButton ? 1.0f : 0.0f; - } - - [self layoutSubviews]; - - _customActiveBackgroundView.alpha = showsCancelButton ? 1.0f : 0.0f; - } completion:^(__unused BOOL finished) - { - //if (finished) - { - if (showsCancelButton) - { - _customTextField.alpha = 1.0f; - _customClearButton.alpha = 1.0f; - } - else - { - _customCancelButton.hidden = true; - _customScopeButtonContainer.hidden = true; - - _wrappingClip.clipsToBounds = true; - } - } - }]; - } - else - { - _wrappingClip.clipsToBounds = !showsCancelButton; - - if (_customScopeButtonTitles.count > 1) - { - [self setSearchBarShouldShowScopeControl:showsCancelButton]; - _customScopeButtonContainer.alpha = showsCancelButton ? 1.0f : 0.0f; - } - - _customTextField.alpha = showsCancelButton ? 1.0f : 0.0f; - _customClearButton.alpha = _customTextField.alpha; - _customActiveBackgroundView.alpha = showsCancelButton ? 1.0f : 0.0f; - _customCancelButton.hidden = !showsCancelButton; - _customScopeButtonContainer.hidden = !showsCancelButton; - - [self layoutSubviews]; - } - } -} - -- (void)setSafeAreaInset:(UIEdgeInsets)safeAreaInset -{ - _safeAreaInset = safeAreaInset; - [self setNeedsLayout]; -} - -- (void)layoutSubviews -{ - [super layoutSubviews]; - - CGRect bounds = self.bounds; - - bool landscapeMode = [self landscapeMode]; - - CGRect clippingFrame = _wrappingClip.frame; - clippingFrame.size = CGSizeMake(bounds.size.width, bounds.size.height + 20.0f); - _wrappingClip.frame = clippingFrame; - - CGRect wrappingFrame = _wrappingView.frame; - wrappingFrame.size = bounds.size; - _wrappingView.frame = wrappingFrame; - - float retinaPixel = TGIsRetina() ? TGScreenPixel : 0.0f; - const float scopeBarHorizontalWidth = 220; - - CGFloat rightPadding = _showsCustomCancelButton && !_hidesCancelButton ? ((_customScopeButtonContainer != nil && landscapeMode ? scopeBarHorizontalWidth : 0) + _cancelButtonWidth) : 0.0f; - - CGFloat safeInsetHeight = self.safeAreaInset.top > FLT_EPSILON ? self.safeAreaInset.top : 20.0f; - _customBackgroundView.frame = CGRectMake(0, ((_showsCustomCancelButton || _alwaysExtended) ? -safeInsetHeight : 0.0f), self.frame.size.width, self.frame.size.height + (_showsCustomCancelButton || _alwaysExtended ? safeInsetHeight : 0.0f)); - _customActiveBackgroundView.frame = _customBackgroundView.frame; - - _textFieldBackground.frame = CGRectMake(8 + _safeAreaInset.left, 9 + [self topPadding], self.frame.size.width - 16 - rightPadding - _safeAreaInset.left - _safeAreaInset.right, [self inputHeight]); - - CGFloat prefixOffset = 0.0f; - { - [_prefixLabel sizeToFit]; - - CGRect frame = _textFieldBackground.frame; - frame.origin.y += 5.0f; - frame.origin.x += 27; - frame.size = _prefixLabel.bounds.size; - - frame.size.width = MIN(frame.size.width, CGFloor((bounds.size.width - rightPadding - 20.0f) / 2.0f)); - - _prefixLabel.frame = frame; - - prefixOffset = frame.size.width; - } - - CGSize placeholderSize = [_placeholderLabel.text sizeWithFont:_placeholderLabel.font]; - placeholderSize.width = MIN(placeholderSize.width, self.frame.size.width - rightPadding - 50.0f - prefixOffset); - - _customSearchIcon.frame = CGRectMake(_showsCustomCancelButton ? (_textFieldBackground.frame.origin.x + 8.0f) : ((CGFloor((self.frame.size.width - placeholderSize.width) / 2) + 10 + TGScreenPixel) - 20), [self searchIconOffset] + [self inputContentOffset] + 16 + retinaPixel + [self topPadding], _customSearchIcon.frame.size.width, _customSearchIcon.frame.size.height); - - _customSearchActivityIndicator.frame = (CGRect){{CGFloor(_customSearchIcon.frame.origin.x + (_customSearchIcon.frame.size.width - _customSearchActivityIndicator.frame.size.width) / 2.0f), CGFloor(_customSearchIcon.frame.origin.y + (_customSearchIcon.frame.size.height - _customSearchActivityIndicator.frame.size.height) / 2.0f) + 1.0f + TGScreenPixel}, _customSearchActivityIndicator.frame.size}; - - _placeholderLabel.frame = CGRectMake(_showsCustomCancelButton ? ((TGIsRTL() ? (CGRectGetMaxX(_textFieldBackground.frame) - placeholderSize.width - 32.0f) : 36 + _safeAreaInset.left) + prefixOffset) : (CGFloor((self.frame.size.width - placeholderSize.width) / 2) + 10 + TGScreenPixel), [self inputContentOffset] + 14 + [self topPadding], placeholderSize.width, placeholderSize.height); - - if (_customTextField != nil) - { - CGRect frame = _textFieldBackground.frame; - frame.origin.y -= retinaPixel; - frame.origin.x += 27; - frame.size.width -= 27 + 8 + 24; - - frame.origin.x += prefixOffset; - frame.size.width -= prefixOffset; - - _customTextField.frame = frame; - - _customClearButton.frame = CGRectMake(CGRectGetMaxX(_textFieldBackground.frame) - 22, [self inputContentOffset] + 16 + [self topPadding] + (_style == TGSearchBarStyleLightAlwaysPlain ? 1.0f : 0.0f), _customClearButton.frame.size.width, _customClearButton.frame.size.height); - } - - if (_customCancelButton != nil) - { - _customCancelButton.frame = CGRectMake(self.frame.size.width + (_showsCustomCancelButton ? (-_customCancelButton.frame.size.width - 9 - self.safeAreaInset.right) : 9), [self topPadding] + 2.0f + [self cancelButtonPadding], _cancelButtonWidth, [self baseHeight]); - } - - if (_customScopeButtonContainer != nil) - { - if (_showsCustomCancelButton) - { - if (!landscapeMode) - _customScopeButtonContainer.frame = CGRectMake(7.0f, self.frame.size.height - 29.0f - 9.0f + [self topPadding], self.frame.size.width - 14.0f, 29.0f); - else - _customScopeButtonContainer.frame = CGRectMake(self.frame.size.width - scopeBarHorizontalWidth - _customCancelButton.frame.size.width - self.safeAreaInset.right, 5.0f + [self topPadding], scopeBarHorizontalWidth - 14.0f, 32.0f); - } - else - { - if (!landscapeMode) - _customScopeButtonContainer.frame = CGRectMake(7.0f, self.frame.size.height - 29.0f - 9.0f + [self topPadding], self.frame.size.width - 14.0f, 29.0f); - else - _customScopeButtonContainer.frame = CGRectMake(self.frame.size.width + 71.0f, 5.0f + [self topPadding], scopeBarHorizontalWidth - 14.0f, 29.0f); - } - } -} - -- (bool)landscapeMode -{ - static CGFloat landscapeScreenWidth = 0.0f; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^ - { - CGSize screenSize = TGScreenSize(); - landscapeScreenWidth = MAX(screenSize.width, screenSize.height); - }); - - return self.frame.size.width >= landscapeScreenWidth - FLT_EPSILON; -} - -- (void)setSearchBarShouldShowScopeControl:(bool)searchBarShouldShowScopeControl -{ - _searchBarShouldShowScopeControl = searchBarShouldShowScopeControl; - - if (_searchBarShouldShowScopeControl) - self.customScopeButtonContainer.hidden = false; - - CGFloat requiredHeight = 0; - - if (_searchBarShouldShowScopeControl && ![self landscapeMode]) - requiredHeight = [self baseHeight] + [TGSearchBar searchBarScopeHeight]; - else - requiredHeight = [self baseHeight]; - - if (ABS(requiredHeight - self.frame.size.height) > FLT_EPSILON) - { - id delegate = (id)self.delegate; - if ([delegate respondsToSelector:@selector(searchBar:willChangeHeight:)]) - [delegate searchBar:self willChangeHeight:requiredHeight]; - } -} - -- (void)setCustomScopeBarHidden:(bool)hidden -{ - self.customScopeButtonContainer.alpha = hidden ? 0.0f : 1.0f; - self.customScopeButtonContainer.userInteractionEnabled = !hidden; -} - -#pragma mark - - -- (void)tappedSearchBar:(id)__unused arg -{ -} - -- (BOOL)becomeFirstResponder -{ - if (![_customTextField isFirstResponder]) - { - bool shouldBeginEditing = true; - id delegate = self.delegate; - if ([delegate respondsToSelector:@selector(searchBarShouldBeginEditing:)]) - shouldBeginEditing = [delegate searchBarShouldBeginEditing:(UISearchBar *)self]; - - if (shouldBeginEditing) - { - [self.customTextField becomeFirstResponder]; - - if ([delegate respondsToSelector:@selector(searchBarTextDidBeginEditing:)]) - [delegate searchBarTextDidBeginEditing:(UISearchBar *)self]; - - return true; - } - } - - return false; -} - -- (BOOL)resignFirstResponder -{ - return [_customTextField resignFirstResponder]; -} - -- (BOOL)canBecomeFirstResponder -{ - return _customTextField == nil || [_customTextField canBecomeFirstResponder]; -} - -- (BOOL)canResignFirstResponder -{ - return [_customTextField canResignFirstResponder]; -} - -- (BOOL)isFirstResponder { - return [_customTextField isFirstResponder]; -} - -#pragma mark - - -- (void)searchCancelButtonPressed -{ - id delegate = self.delegate; - - if ([delegate respondsToSelector:@selector(searchBarCancelButtonClicked:)]) - [delegate searchBarCancelButtonClicked:(UISearchBar *)self]; -} - -- (UIView *)customScopeButtonContainer -{ - if (_customScopeButtonContainer == nil) - { - CGRect frame = CGRectZero; - if (![self landscapeMode]) - frame = CGRectMake(7.0f, self.frame.size.height - 29.0f - 9.0f, self.frame.size.width - 14.0f, 29.0f); - else - frame = CGRectMake(0, 0, self.frame.size.width, 29.0f); - - _customScopeButtonContainer = [[UIView alloc] initWithFrame:frame]; - _customScopeButtonContainer.alpha = 0.0f; - [_wrappingView insertSubview:_customScopeButtonContainer aboveSubview:_customActiveBackgroundView]; - - _customSegmentedControl = [[UISegmentedControl alloc] initWithItems:self.customScopeButtonTitles]; - - [_customSegmentedControl setBackgroundImage:_pallete != nil ? _pallete.segmentedControlBackgroundImage : TGComponentsImageNamed(@"ModernSegmentedControlBackground.png") forState:UIControlStateNormal barMetrics:UIBarMetricsDefault]; - [_customSegmentedControl setBackgroundImage:_pallete != nil ? _pallete.segmentedControlSelectedImage : TGComponentsImageNamed(@"ModernSegmentedControlSelected.png") forState:UIControlStateSelected barMetrics:UIBarMetricsDefault]; - [_customSegmentedControl setBackgroundImage:_pallete != nil ? _pallete.segmentedControlSelectedImage : TGComponentsImageNamed(@"ModernSegmentedControlSelected.png") forState:UIControlStateSelected | UIControlStateHighlighted barMetrics:UIBarMetricsDefault]; - [_customSegmentedControl setBackgroundImage:_pallete != nil ? _pallete.segmentedControlHighlightedImage : TGComponentsImageNamed(@"ModernSegmentedControlHighlighted.png") forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault]; - [_customSegmentedControl setDividerImage:_pallete != nil ? _pallete.segmentedControlDividerImage : TGComponentsImageNamed(@"ModernSegmentedControlDivider.png") forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault]; - - [_customSegmentedControl setTitleTextAttributes:@{UITextAttributeTextColor:_pallete != nil ? _pallete.accentColor : TGAccentColor(), UITextAttributeTextShadowColor: [UIColor clearColor], UITextAttributeFont: TGSystemFontOfSize(13)} forState:UIControlStateNormal]; - [_customSegmentedControl setTitleTextAttributes:@{UITextAttributeTextColor:_pallete != nil ? _pallete.accentContrastColor : [UIColor whiteColor], UITextAttributeTextShadowColor: [UIColor clearColor], UITextAttributeFont: TGSystemFontOfSize(13)} forState:UIControlStateSelected]; - - _customSegmentedControl.frame = CGRectMake(0, _customScopeButtonContainer.frame.size.height - 29.0f, _customScopeButtonContainer.frame.size.width, 29.0f); - _customSegmentedControl.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; - - [_customSegmentedControl setSelectedSegmentIndex:0]; - [_customSegmentedControl addTarget:self action:@selector(segmentedControlChanged) forControlEvents:UIControlEventValueChanged]; - - [_customScopeButtonContainer addSubview:_customSegmentedControl]; - } - - return _customScopeButtonContainer; -} - -- (void)backgroundTapGesture:(UITapGestureRecognizer *)recognizer -{ - if (recognizer.state == UIGestureRecognizerStateRecognized) - { - if (![_customTextField isFirstResponder]) - { - bool shouldBeginEditing = true; - id delegate = self.delegate; - if ([delegate respondsToSelector:@selector(searchBarShouldBeginEditing:)]) - shouldBeginEditing = [delegate searchBarShouldBeginEditing:(UISearchBar *)self]; - - if (shouldBeginEditing) - { - [self.customTextField becomeFirstResponder]; - - if ([delegate respondsToSelector:@selector(searchBarTextDidBeginEditing:)]) - [delegate searchBarTextDidBeginEditing:(UISearchBar *)self]; - } - } - } -} - -- (void)updatePlaceholder:(NSString *)text -{ - _placeholderLabel.hidden = text.length != 0; - _customClearButton.hidden = !_placeholderLabel.hidden && _prefixText.length == 0; -} - -- (void)textFieldDidChange:(UITextField *)textField -{ - if (textField == _customTextField) - { - NSString *text = textField.text; - - id delegate = self.delegate; - if ([delegate respondsToSelector:@selector(searchBar:textDidChange:)]) - [delegate searchBar:(UISearchBar *)self textDidChange:text]; - - [self updatePlaceholder:text]; - } -} - -- (BOOL)textFieldShouldReturn:(UITextField *)textField -{ - if (textField == _customTextField) - { - if (textField.text.length != 0) - { - id delegate = self.delegate; - if ([delegate respondsToSelector:@selector(searchBarSearchButtonClicked:)]) - [delegate searchBarSearchButtonClicked:(UISearchBar *)self]; - } - - [textField resignFirstResponder]; - - return false; - } - - return false; -} - -- (void)customClearButtonPressed -{ - if (_customTextField.text.length == 0) { - if (_prefixText.length != 0) { - if (_clearPrefix) { - _clearPrefix(true); - } - } - } else { - [_customTextField setText:@""]; - [self updatePlaceholder:@""]; - - [self becomeFirstResponder]; - - NSString *text = @""; - - id delegate = self.delegate; - if ([delegate respondsToSelector:@selector(searchBar:textDidChange:)]) - [delegate searchBar:(UISearchBar *)self textDidChange:text]; - } -} - -- (NSInteger)selectedScopeButtonIndex -{ - return _customSegmentedControl.selectedSegmentIndex; -} - -- (void)setSelectedScopeButtonIndex:(NSInteger)selectedScopeButtonIndex -{ - [self.customSegmentedControl setSelectedSegmentIndex:selectedScopeButtonIndex]; -} - -- (void)setPlaceholder:(NSString *)placeholder -{ - _placeholder = placeholder; - _placeholderLabel.text = placeholder; - - [self setNeedsLayout]; -} - -- (NSString *)text -{ - return _customTextField.text; -} - -- (void)setText:(NSString *)text -{ - bool layout = _customTextField == nil; - self.customTextField.text = text; - if (layout) - [self setNeedsLayout]; - - [self textFieldDidChange:_customTextField]; -} - -- (void)segmentedControlChanged -{ - if (_showsCustomCancelButton) - { - id delegate = self.delegate; - if ([delegate respondsToSelector:@selector(searchBar:selectedScopeButtonIndexDidChange:)]) - [delegate searchBar:(UISearchBar *)self selectedScopeButtonIndexDidChange:_customSegmentedControl.selectedSegmentIndex]; - } -} - -- (void)updateClipping:(CGFloat)clippedHeight -{ - CGFloat offset = self.frame.size.height + MAX(0.0f, MIN(clippedHeight, self.frame.size.height)); - - CGRect frame = _wrappingClip.frame; - frame.origin.y = offset - frame.size.height + 20.0f; - _wrappingClip.frame = frame; - - CGRect wrapFrame = _wrappingView.frame; - wrapFrame.origin.y = -offset + wrapFrame.size.height; - _wrappingView.frame = wrapFrame; -} - -- (void)localizationUpdated -{ - _placeholderLabel.text = TGLocalized(@"Common.Search"); - - _cancelButtonWidth = [TGLocalized(@"Common.Cancel") sizeWithFont:TGSystemFontOfSize(17.0f)].width + 11.0f; - - CGRect textFieldBackgroundFrame = _textFieldBackground.frame; - _customCancelButton.frame = CGRectMake(textFieldBackgroundFrame.origin.x + textFieldBackgroundFrame.size.width + 10, _customCancelButton.frame.origin.y, _cancelButtonWidth, [self baseHeight]); - [_customCancelButton setTitle:TGLocalized(@"Common.Cancel") forState:UIControlStateNormal]; - - [_customSegmentedControl removeAllSegments]; - int index = -1; - for (NSString *itemText in _customScopeButtonTitles) - { - index++; - [_customSegmentedControl insertSegmentWithTitle:itemText atIndex:(NSUInteger)index animated:false]; - } - - [self setNeedsLayout]; -} - -- (void)setShowActivity:(bool)showActivity -{ - if (_showActivity != showActivity) - { - [_searchActivityTimer invalidate]; - _searchActivityTimer = nil; - - _showActivity = showActivity; - - if (_delayActivity && showActivity) - { - _searchActivityTimer = [TGTimerTarget scheduledMainThreadTimerWithTarget:self action:@selector(searchActivityTimerEvent) interval:0.2 repeat:false]; - } - else - [self searchActivityTimerEvent]; - } -} - -- (void)searchActivityTimerEvent -{ - _customSearchIcon.hidden = _showActivity; - UIActivityIndicatorView *indicator = _customSearchActivityIndicator; - if (_showActivity) - { - if (indicator == nil) - { - indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:4]; - if (_pallete != nil) - indicator.color = _pallete.placeholderColor; - indicator.userInteractionEnabled = false; - indicator.hidden = true; - [_wrappingView addSubview:indicator]; - - _customSearchActivityIndicator = indicator; - } - - indicator.hidden = false; - indicator.frame = (CGRect){{CGFloor(_customSearchIcon.frame.origin.x + (_customSearchIcon.frame.size.width - indicator.frame.size.width) / 2.0f), CGFloor(_customSearchIcon.frame.origin.y + (_customSearchIcon.frame.size.height - indicator.frame.size.height) / 2.0f) + 1.0f}, indicator.frame.size}; - [indicator startAnimating]; - } - else - { - indicator.hidden = true; - [indicator stopAnimating]; - } -} - -- (void)setPrefixText:(NSAttributedString *)prefixText { - _prefixText = prefixText; - _prefixLabel.attributedText = prefixText; - _customClearButton.hidden = !_placeholderLabel.hidden && _prefixText.length == 0; - - [self setNeedsLayout]; -} - -@end - - -@implementation TGSearchBarPallete - -+ (instancetype)palleteWithDark:(bool)dark backgroundColor:(UIColor *)backgroundColor highContrastBackgroundColor:(UIColor *)highContrastBackgroundColor textColor:(UIColor *)textColor placeholderColor:(UIColor *)placeholderColor clearIcon:(UIImage *)clearIcon barBackgroundColor:(UIColor *)barBackgroundColor barSeparatorColor:(UIColor *)barSeparatorColor plainBackgroundColor:(UIColor *)plainBackgroundColor accentColor:(UIColor *)accentColor accentContrastColor:(UIColor *)accentContrastColor menuBackgroundColor:(UIColor *)menuBackgroundColor segmentedControlBackgroundImage:(UIImage *)segmentedControlBackgroundImage segmentedControlSelectedImage:(UIImage *)segmentedControlSelectedImage segmentedControlHighlightedImage:(UIImage *)segmentedControlHighlightedImage segmentedControlDividerImage:(UIImage *)segmentedControlDividerImage -{ - TGSearchBarPallete *pallete = [[TGSearchBarPallete alloc] init]; - pallete->_isDark = dark; - pallete->_backgroundColor = backgroundColor; - pallete->_highContrastBackgroundColor = highContrastBackgroundColor; - pallete->_textColor = textColor; - pallete->_placeholderColor = placeholderColor; - pallete->_clearIcon = clearIcon; - pallete->_barBackgroundColor = barBackgroundColor; - pallete->_barSeparatorColor = barSeparatorColor; - pallete->_plainBackgroundColor = plainBackgroundColor; - pallete->_accentColor = accentColor; - pallete->_accentContrastColor = accentContrastColor; - pallete->_menuBackgroundColor = menuBackgroundColor; - pallete->_segmentedControlBackgroundImage = segmentedControlBackgroundImage; - pallete->_segmentedControlSelectedImage = segmentedControlSelectedImage; - pallete->_segmentedControlHighlightedImage = segmentedControlHighlightedImage; - pallete->_segmentedControlDividerImage = segmentedControlDividerImage; - return pallete; -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGSearchDisplayMixin.m b/submodules/LegacyComponents/Sources/TGSearchDisplayMixin.m deleted file mode 100644 index 25da3a30ac..0000000000 --- a/submodules/LegacyComponents/Sources/TGSearchDisplayMixin.m +++ /dev/null @@ -1,457 +0,0 @@ -#import "TGSearchDisplayMixin.h" - -#import "LegacyComponentsInternal.h" -#import "TGColor.h" -#import "TGHacks.h" - -#import "TGSearchBar.h" - -#import - -@interface TGSearchDisplayMixin () - -@property (nonatomic) UIEdgeInsets controllerInset; - -@property (nonatomic, strong) UIView *dimView; - -@property (nonatomic, strong) UIView *tableViewContainer; - -@end - -@implementation TGSearchDisplayMixin - -- (instancetype)init -{ - self = [super init]; - if (self != nil) - { - - } - return self; -} - -- (void)dealloc -{ - [self unload]; -} - -- (void)unload -{ - [self _unloadTableView]; -} - -- (void)_unloadTableView -{ - [_searchResultsTableView removeFromSuperview]; - - _searchResultsTableView.delegate = nil; - _searchResultsTableView.dataSource = nil; - _searchResultsTableView = nil; -} - -- (void)setSearchBar:(UISearchBar *)searchBar -{ - if (_searchBar != nil) - _searchBar.delegate = nil; - - _searchBar = (TGSearchBar *)searchBar; - _searchBar.delegate = self; -} - -- (void)setIsActive:(bool)isActive -{ - [self setIsActive:isActive animated:true]; -} - -- (void)setIsActive:(bool)isActive animated:(bool)animated -{ - if (_isActive != isActive) - { - _isActive = isActive; - - if (isActive || !self.alwaysShowsCancelButton) - [_searchBar setShowsCancelButton:isActive animated:animated]; - - if (isActive) - { - id delegate = _delegate; - - UIView *referenceView = [delegate referenceViewForSearchResults]; - - [self setSearchResultsTableViewHidden:true]; - _searchResultsTableView.alpha = 1.0f; - - if (_dimView == nil) - { - _dimView = [[UIView alloc] init]; - _dimView.backgroundColor = UIColorRGBA(0x000000, 0.4f); - _dimView.alpha = 0.0f; - _dimView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - } - - if (_tableViewContainer == nil) - { - _tableViewContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; - _tableViewContainer.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - - UIView *tapView = [[UIView alloc] initWithFrame:_tableViewContainer.bounds]; - tapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - [tapView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dimViewTapped:)]]; - [_tableViewContainer addSubview:tapView]; - } - - CGRect dimViewFrame = referenceView.bounds; - - if ([referenceView isKindOfClass:[UIScrollView class]]) - { - UIScrollView *referenceScrollView = (UIScrollView *)referenceView; - dimViewFrame.origin.y = -referenceScrollView.contentOffset.y + _searchBar.frame.size.height; - } - else - { - if (_simpleLayout) { - dimViewFrame.origin.y = _controllerInset.top; - } else { - CGRect searchBarReferenceFrame = [_searchBar convertRect:_searchBar.bounds toView:referenceView.superview]; - dimViewFrame.origin.y = searchBarReferenceFrame.origin.y + searchBarReferenceFrame.size.height; - } - } - - [[referenceView superview] insertSubview:_tableViewContainer aboveSubview:referenceView]; - - [[referenceView superview] insertSubview:_dimView aboveSubview:referenceView]; - - _dimView.frame = dimViewFrame; - - _dimView.layer.frame = dimViewFrame; - - CGRect tableViewContainerFrame = referenceView.frame; - if (_simpleLayout) { - tableViewContainerFrame.origin.y = _controllerInset.top; - } else { - tableViewContainerFrame.origin.y = _controllerInset.top + _searchBar.frame.size.height; - } - _tableViewContainer.frame = tableViewContainerFrame; - - _tableViewContainer.layer.frame = _tableViewContainer.frame; - - if (animated) - { - [UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^ - { - _dimView.alpha = 1.0f; - } completion:nil]; - } - else - { - _dimView.alpha = 1.0f; - } - - [self _updateSearchBarLayout:animated]; - - if ([delegate respondsToSelector:@selector(searchMixinWillActivate:)]) - [delegate searchMixinWillActivate:animated]; - } - else - { - [self _updateSearchBarLayout:animated]; - - [_searchBar resignFirstResponder]; - [_searchBar setText:@""]; - - if (animated) - { - id delegate = _delegate; - if ([delegate respondsToSelector:@selector(searchMixinWillDeactivate:)]) - [delegate searchMixinWillDeactivate:animated]; - - [UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^ - { - _dimView.alpha = 0.0f; - _searchResultsTableView.alpha = 0.0f; - } completion:^(BOOL finished) - { - if (finished) - { - [_dimView removeFromSuperview]; - [_tableViewContainer removeFromSuperview]; - [_searchResultsTableView removeFromSuperview]; - - [self _unloadTableView]; - } - }]; - } - else - { - id delegate = _delegate; - if ([delegate respondsToSelector:@selector(searchMixinWillDeactivate:)]) - [delegate searchMixinWillDeactivate:animated]; - - _dimView.alpha = 0.0f; - - [_dimView removeFromSuperview]; - [_tableViewContainer removeFromSuperview]; - [_searchResultsTableView removeFromSuperview]; - - [self _unloadTableView]; - } - } - } -} - -- (void)_updateSearchBarLayout:(bool)animated -{ - CGFloat currentHeight = _searchBar.frame.size.height; - - if (((TGSearchBar *)_searchBar).customScopeButtonTitles.count > 1) - { - bool updateSize = false; - - updateSize = true; - - if (updateSize) - [_searchBar sizeToFit]; - } - - if (ABS(currentHeight - _searchBar.frame.size.height) > FLT_EPSILON) - { - if (animated) - { - [UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^ - { - [self searchBar:(TGSearchBar *)_searchBar willChangeHeight:_searchBar.frame.size.height]; - [_searchBar layoutSubviews]; - } completion:^(BOOL finished) - { - if (finished) - { - } - }]; - } - else - { - [self searchBar:(TGSearchBar *)_searchBar willChangeHeight:_searchBar.frame.size.height]; - [_searchBar layoutSubviews]; - } - } -} - -- (void)controllerInsetUpdated:(UIEdgeInsets)controllerInset -{ - _controllerInset = controllerInset; - - [self controllerLayoutUpdated:CGSizeZero]; -} - -- (void)controllerLayoutUpdated:(CGSize)__unused layoutSize -{ - [self _updateSearchBarLayout:false]; - - if (_dimView != nil && _dimView.superview != nil) - { - CGRect frame = _dimView.superview.bounds; - if (_simpleLayout) { - frame.origin.y = _controllerInset.top; - } else { - frame.origin.y = _controllerInset.top + _searchBar.frame.size.height; - } - _dimView.frame = frame; - } - - if (_tableViewContainer != nil && _tableViewContainer.superview != nil) - { - CGRect tableViewContainerFrame = _tableViewContainer.frame; - if (_simpleLayout) { - tableViewContainerFrame.origin.y = _controllerInset.top; - } else { - tableViewContainerFrame.origin.y = _controllerInset.top + _searchBar.frame.size.height; - } - _tableViewContainer.frame = tableViewContainerFrame; - } - - if (_searchResultsTableView != nil && _searchResultsTableView.superview != nil) - { - UIEdgeInsets tableInset = _controllerInset; - tableInset.bottom += tableInset.top + _searchBar.frame.size.height; - tableInset.top = 0; - _searchResultsTableView.contentInset = tableInset; - _searchResultsTableView.scrollIndicatorInsets = tableInset; - } - - if (_searchBar.showsScopeBar) - { - CATransition *transition = [CATransition animation]; - transition.duration = 0.2 * TGAnimationSpeedFactor(); - transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; - [_searchBar.layer addAnimation:transition forKey:@"content"]; - } -} - -- (void)searchBar:(TGSearchBar *)searchBar willChangeHeight:(CGFloat)newHeight -{ - if (searchBar == _searchBar) - { - id delegate = _delegate; - UIView *referenceView = [delegate referenceViewForSearchResults]; - - if ([referenceView isKindOfClass:[UITableView class]]) - { - static NSInvocation *invocation = nil; - - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^ - { - SEL selector = NSSelectorFromString(TGEncodeText(@"`ubcmfIfbefsIfjhiuEjeDibohfUpIfjhiu;", -1)); - - NSMethodSignature *signature = [[UITableView class] instanceMethodSignatureForSelector:selector]; - if (signature == nil) - { - TGLegacyLog(@"***** Method not found"); - } - else - { - invocation = [NSInvocation invocationWithMethodSignature:signature]; - [invocation setSelector:selector]; - } - }); - - if (invocation != nil) - { - [invocation setTarget:referenceView]; - CGFloat height = newHeight; - [invocation setArgument:&height atIndex:2]; - [invocation invoke]; - - [invocation setTarget:nil]; - } - } - } -} - -- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar -{ - if (searchBar == (UISearchBar *)_searchBar) - { - [self setIsActive:true animated:true]; - } -} - -- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText -{ - if (searchBar == (UISearchBar *)_searchBar) - { - id delegate = _delegate; - if ([delegate respondsToSelector:@selector(searchMixin:hasChangedSearchQuery:withScope:)]) - { - [delegate searchMixin:self hasChangedSearchQuery:searchText withScope:(int)_searchBar.selectedScopeButtonIndex]; - } - - //if (searchText.length == 0) - // [self setSearchResultsTableViewHidden:false]; - } -} - -- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar -{ - if (searchBar == (UISearchBar *)_searchBar) - { - [self setIsActive:false animated:true]; - } -} - -- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar -{ - if (searchBar == (UISearchBar *)_searchBar) - { - [_searchBar resignFirstResponder]; - } -} - -- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope -{ - if (searchBar == (UISearchBar *)_searchBar) - { - id delegate = _delegate; - if ([delegate respondsToSelector:@selector(searchMixin:hasChangedSearchQuery:withScope:)]) - [delegate searchMixin:self hasChangedSearchQuery:_searchBar.text withScope:(int)selectedScope]; - } -} - -- (void)dimViewTapped:(UITapGestureRecognizer *)recognizer -{ - if (recognizer.state == UIGestureRecognizerStateRecognized) - { - if (_searchResultsTableView == nil || _searchResultsTableView.hidden) - [self setIsActive:false animated:true]; - } -} - -#pragma mark - - -- (bool)searchResultsTableViewHidden -{ - return _searchResultsTableView == nil || _searchResultsTableView.hidden; -} - -- (void)setSearchResultsTableViewHidden:(bool)searchResultsTableViewHidden -{ - [self setSearchResultsTableViewHidden:searchResultsTableViewHidden animated:false]; -} - -- (void)setSearchResultsTableViewHidden:(bool)searchResultsTableViewHidden animated:(bool)animated -{ - bool wasHidden = _searchResultsTableView.hidden; - - _searchResultsTableView.hidden = searchResultsTableViewHidden; - _dimView.hidden = !searchResultsTableViewHidden; - - if (animated && wasHidden && !searchResultsTableViewHidden) - { - _searchResultsTableView.alpha = 0.0f; - [UIView animateWithDuration:0.25 animations:^ - { - _searchResultsTableView.alpha = 1.0f; - }]; - } -} - -- (void)reloadSearchResults -{ - if (_searchResultsTableView == nil) - { - id delegate = _delegate; - - _searchResultsTableView = [delegate createTableViewForSearchMixin:self]; - _searchResultsTableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpartial-availability" - if (iosMajorVersion() >= 11) - _searchResultsTableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; -#pragma clang diagnostic pop - - [self setSearchResultsTableViewHidden:true]; - } - - if (_searchResultsTableView.superview == nil) - { - _searchResultsTableView.frame = _tableViewContainer.bounds; - - UIEdgeInsets tableInset = _controllerInset; - tableInset.bottom += tableInset.top + _searchBar.frame.size.height; - tableInset.top = 0; - _searchResultsTableView.contentInset = tableInset; - _searchResultsTableView.scrollIndicatorInsets = tableInset; - - [_tableViewContainer addSubview:_searchResultsTableView]; - } - - [_searchResultsTableView reloadData]; -} - -- (void)resignResponderIfAny -{ - [_searchBar resignFirstResponder]; -} - -@end diff --git a/submodules/LegacyComponents/Sources/TGViewController.mm b/submodules/LegacyComponents/Sources/TGViewController.mm index bf00939383..d8dd2aad62 100644 --- a/submodules/LegacyComponents/Sources/TGViewController.mm +++ b/submodules/LegacyComponents/Sources/TGViewController.mm @@ -1026,7 +1026,7 @@ static id _defaultContext = nil; - (CGFloat)navigationBarHeightForInterfaceOrientation:(UIInterfaceOrientation)orientation { - static CGFloat portraitHeight = 44.0f; + static CGFloat portraitHeight = 56.0f; static CGFloat landscapeHeight = 32.0f; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^ @@ -1035,13 +1035,13 @@ static id _defaultContext = nil; CGFloat widescreenWidth = MAX(screenSize.width, screenSize.height); if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone && ABS(widescreenWidth - 736) > FLT_EPSILON) { - portraitHeight = 44.0f; - landscapeHeight = 32.0f; + portraitHeight = 56.0f; + landscapeHeight = 56.0f; } else { - portraitHeight = 44.0f; - landscapeHeight = 44.0f; + portraitHeight = 56.0f; + landscapeHeight = 56.0f; } }); bool large = UIInterfaceOrientationIsPortrait(orientation) || self.alwaysUseTallNavigationBarHeight; @@ -1072,7 +1072,7 @@ static id _defaultContext = nil; + (UIEdgeInsets)safeAreaInsetForOrientation:(UIInterfaceOrientation)orientation hasOnScreenNavigation:(bool)hasOnScreenNavigation { int height = (int)TGScreenSize().height; - if (!TGIsPad() && (height != 812 && height != 896)) + if (!TGIsPad() && (height != 812 && height != 896 && height != 780 && height != 844 && height != 926)) return UIEdgeInsetsZero; if (TGIsPad()) { diff --git a/submodules/LegacyComponents/Sources/UIDevice+PlatformInfo.m b/submodules/LegacyComponents/Sources/UIDevice+PlatformInfo.m deleted file mode 100644 index ad7639756d..0000000000 --- a/submodules/LegacyComponents/Sources/UIDevice+PlatformInfo.m +++ /dev/null @@ -1,216 +0,0 @@ -#import "UIDevice+PlatformInfo.h" - -#include // Per msqr -#include -#include -#include - -@implementation UIDevice (PlatformInfo) - -/* - Platforms - - iFPGA -> ?? - - iPhone1,1 -> iPhone 1G, M68 - iPhone1,2 -> iPhone 3G, N82 - iPhone2,1 -> iPhone 3GS, N88 - iPhone3,1 -> iPhone 4/AT&T, N89 - iPhone3,2 -> iPhone 4/Other Carrier?, ?? - iPhone3,3 -> iPhone 4/Verizon, TBD - iPhone4,1 -> (iPhone 4S/GSM), TBD - iPhone4,2 -> (iPhone 4S/CDMA), TBD - iPhone4,3 -> (iPhone 4S/???) - iPhone5,1 -> iPhone Next Gen, TBD - iPhone5,1 -> iPhone Next Gen, TBD - iPhone5,1 -> iPhone Next Gen, TBD - - iPod1,1 -> iPod touch 1G, N45 - iPod2,1 -> iPod touch 2G, N72 - iPod2,2 -> Unknown, ?? - iPod3,1 -> iPod touch 3G, N18 - iPod4,1 -> iPod touch 4G, N80 - - // Thanks NSForge - iPad1,1 -> iPad 1G, WiFi and 3G, K48 - iPad2,1 -> iPad 2G, WiFi, K93 - iPad2,2 -> iPad 2G, GSM 3G, K94 - iPad2,3 -> iPad 2G, CDMA 3G, K95 - iPad3,1 -> (iPad 3G, WiFi) - iPad3,2 -> (iPad 3G, GSM) - iPad3,3 -> (iPad 3G, CDMA) - iPad4,1 -> (iPad 4G, WiFi) - iPad4,2 -> (iPad 4G, GSM) - iPad4,3 -> (iPad 4G, CDMA) - - AppleTV2,1 -> AppleTV 2, K66 - AppleTV3,1 -> AppleTV 3, ?? - - i386, x86_64 -> iPhone Simulator - */ - - -#pragma mark sysctlbyname utils -- (NSString *) getSysInfoByName:(char *)typeSpecifier -{ - size_t size; - sysctlbyname(typeSpecifier, NULL, &size, NULL, 0); - - char *answer = malloc(size); - sysctlbyname(typeSpecifier, answer, &size, NULL, 0); - - NSString *results = [NSString stringWithCString:answer encoding: NSUTF8StringEncoding]; - - free(answer); - return results; -} - -- (NSString *) platform -{ - return [self getSysInfoByName:"hw.machine"]; -} - -#pragma mark sysctl utils -- (NSUInteger) getSysInfo: (uint) typeSpecifier -{ - size_t size = sizeof(int); - int results; - int mib[2] = {CTL_HW, typeSpecifier}; - sysctl(mib, 2, &results, &size, NULL, 0); - return (NSUInteger) results; -} - -#pragma mark platform type and name utils -- (NSUInteger) platformType -{ - NSString *platform = [self platform]; - - // The ever mysterious iFPGA - if ([platform isEqualToString:@"iFPGA"]) return UIDeviceIFPGA; - - // iPhone - if ([platform isEqualToString:@"iPhone1,1"]) return UIDevice1GiPhone; - if ([platform isEqualToString:@"iPhone1,2"]) return UIDevice3GiPhone; - if ([platform hasPrefix:@"iPhone2"]) return UIDevice3GSiPhone; - if ([platform hasPrefix:@"iPhone3"]) return UIDevice4iPhone; - if ([platform hasPrefix:@"iPhone4"]) return UIDevice4SiPhone; - if ([platform hasPrefix:@"iPhone5"]) return UIDevice5iPhone; - if ([platform hasPrefix:@"iPhone6"]) return UIDevice5SiPhone; - - if ([platform isEqualToString:@"iPhone7,1"]) return UIDevice6PlusiPhone; - if ([platform isEqualToString:@"iPhone7,2"]) return UIDevice6iPhone; - if ([platform isEqualToString:@"iPhone8,1"]) return UIDevice6siPhone; - if ([platform isEqualToString:@"iPhone8,2"]) return UIDevice6SPlusiPhone; - - if ([platform isEqualToString:@"iPhone9,2"]) return UIDevice7PlusiPhone; - if ([platform isEqualToString:@"iPhone9,1"]) return UIDevice7iPhone; - if ([platform isEqualToString:@"iPhone9,3"]) return UIDevice7iPhone; - if ([platform isEqualToString:@"iPhone9,4"]) return UIDevice7PlusiPhone; - - if ([platform isEqualToString:@"iPhone8,4"]) return UIDeviceSEPhone; - - // iPod - if ([platform hasPrefix:@"iPod1"]) return UIDevice1GiPod; - if ([platform hasPrefix:@"iPod2"]) return UIDevice2GiPod; - if ([platform hasPrefix:@"iPod3"]) return UIDevice3GiPod; - if ([platform hasPrefix:@"iPod4"]) return UIDevice4GiPod; - if ([platform hasPrefix:@"iPod5"]) return UIDevice5GiPod; - if ([platform hasPrefix:@"iPod7"]) return UIDevice6GiPod; - - // iPad - if ([platform hasPrefix:@"iPad1"]) return UIDevice1GiPad; - if ([platform hasPrefix:@"iPad2"]) return UIDevice2GiPad; - if ([platform hasPrefix:@"iPad3"]) return UIDevice3GiPad; - if ([platform hasPrefix:@"iPad4"]) return UIDevice4GiPad; - if ([platform hasPrefix:@"iPad5"]) return UIDevice5GiPad; - if ([platform hasPrefix:@"iPad6"]) return UIDevice6GiPad; - - // Apple TV - if ([platform hasPrefix:@"AppleTV2"]) return UIDeviceAppleTV2; - if ([platform hasPrefix:@"AppleTV3"]) return UIDeviceAppleTV3; - - if ([platform hasPrefix:@"iPhone"]) return UIDeviceUnknowniPhone; - if ([platform hasPrefix:@"iPod"]) return UIDeviceUnknowniPod; - if ([platform hasPrefix:@"iPad"]) return UIDeviceUnknowniPad; - if ([platform hasPrefix:@"AppleTV"]) return UIDeviceUnknownAppleTV; - - // Simulator thanks Jordan Breeding - if ([platform hasSuffix:@"86"] || [platform isEqual:@"x86_64"]) - { - BOOL smallerScreen = [[UIScreen mainScreen] bounds].size.width < 768; - return smallerScreen ? UIDeviceSimulatoriPhone : UIDeviceSimulatoriPad; - } - - return UIDeviceUnknown; -} - -- (NSString *) platformString -{ - switch ([self platformType]) - { - case UIDevice1GiPhone: return IPHONE_1G_NAMESTRING; - case UIDevice3GiPhone: return IPHONE_3G_NAMESTRING; - case UIDevice3GSiPhone: return IPHONE_3GS_NAMESTRING; - case UIDevice4iPhone: return IPHONE_4_NAMESTRING; - case UIDevice4SiPhone: return IPHONE_4S_NAMESTRING; - case UIDevice5iPhone: return IPHONE_5_NAMESTRING; - case UIDevice5SiPhone: return IPHONE_5S_NAMESTRING; - case UIDevice6iPhone: return IPHONE_6_NAMESTRING; - case UIDevice6PlusiPhone: return IPHONE_6Plus_NAMESTRING; - case UIDevice6siPhone: return IPHONE_6S_NAMESTRING; - case UIDevice6SPlusiPhone: return IPHONE_6SPlus_NAMESTRING; - case UIDevice7iPhone: return IPHONE_7_NAMESTRING; - case UIDeviceSEPhone: return IPHONE_SE_NAMESTRING; - case UIDevice7PlusiPhone: return IPHONE_7Plus_NAMESTRING; - - case UIDeviceUnknowniPhone: return IPHONE_UNKNOWN_NAMESTRING; - - case UIDevice1GiPod: return IPOD_1G_NAMESTRING; - case UIDevice2GiPod: return IPOD_2G_NAMESTRING; - case UIDevice3GiPod: return IPOD_3G_NAMESTRING; - case UIDevice4GiPod: return IPOD_4G_NAMESTRING; - case UIDevice5GiPod: return IPOD_5G_NAMESTRING; - case UIDevice6GiPod: return IPOD_6G_NAMESTRING; - case UIDeviceUnknowniPod: return IPOD_UNKNOWN_NAMESTRING; - - case UIDevice1GiPad : return IPAD_1G_NAMESTRING; - case UIDevice2GiPad : return IPAD_2G_NAMESTRING; - case UIDevice3GiPad : return IPAD_3G_NAMESTRING; - case UIDevice4GiPad : return IPAD_4G_NAMESTRING; - case UIDevice5GiPad : return IPAD_5G_NAMESTRING; - case UIDevice6GiPad : return IPAD_6G_NAMESTRING; - case UIDeviceUnknowniPad : return IPAD_UNKNOWN_NAMESTRING; - - case UIDeviceAppleTV2 : return APPLETV_2G_NAMESTRING; - case UIDeviceAppleTV3 : return APPLETV_3G_NAMESTRING; - case UIDeviceAppleTV4 : return APPLETV_4G_NAMESTRING; - case UIDeviceUnknownAppleTV: return APPLETV_UNKNOWN_NAMESTRING; - - case UIDeviceSimulator: return SIMULATOR_NAMESTRING; - case UIDeviceSimulatoriPhone: return SIMULATOR_IPHONE_NAMESTRING; - case UIDeviceSimulatoriPad: return SIMULATOR_IPAD_NAMESTRING; - case UIDeviceSimulatorAppleTV: return SIMULATOR_APPLETV_NAMESTRING; - - case UIDeviceIFPGA: return IFPGA_NAMESTRING; - - default: return IOS_FAMILY_UNKNOWN_DEVICE; - } -} - -- (BOOL) hasRetinaDisplay -{ - return ([UIScreen mainScreen].scale == 2.0f); -} - -- (UIDeviceFamily) deviceFamily -{ - NSString *platform = [self platform]; - if ([platform hasPrefix:@"iPhone"]) return UIDeviceFamilyiPhone; - if ([platform hasPrefix:@"iPod"]) return UIDeviceFamilyiPod; - if ([platform hasPrefix:@"iPad"]) return UIDeviceFamilyiPad; - if ([platform hasPrefix:@"AppleTV"]) return UIDeviceFamilyAppleTV; - - return UIDeviceFamilyUnknown; -} - -@end diff --git a/submodules/LegacyMediaPickerUI/Sources/LegacyAttachmentMenu.swift b/submodules/LegacyMediaPickerUI/Sources/LegacyAttachmentMenu.swift index 12c55fbd7e..67603bbb04 100644 --- a/submodules/LegacyMediaPickerUI/Sources/LegacyAttachmentMenu.swift +++ b/submodules/LegacyMediaPickerUI/Sources/LegacyAttachmentMenu.swift @@ -59,6 +59,60 @@ public enum LegacyAttachmentMenuMediaEditing { case file } +public func legacyMediaEditor(context: AccountContext, peer: Peer, media: AnyMediaReference, initialCaption: String, presentStickers: @escaping (@escaping (TelegramMediaFile, Bool, UIView, CGRect) -> Void) -> TGPhotoPaintStickersScreen?, sendMessagesWithSignals: @escaping ([Any]?, Bool, Int32) -> Void, present: @escaping (ViewController, Any?) -> Void) { + let _ = (fetchMediaData(context: context, postbox: context.account.postbox, mediaReference: media) + |> 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 paintStickersContext = LegacyPaintStickersContext(context: context) + paintStickersContext.presentStickersController = { completion in + return presentStickers({ file, animated, view, rect in + let coder = PostboxEncoder() + coder.encodeRootObject(file) + completion?(coder.makeData(), animated, view, rect) + }) + } + + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + let recipientName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + + let legacyController = LegacyController(presentation: .custom, theme: presentationData.theme, initialLayout: nil) + legacyController.blocksBackgroundWhenInOverlay = true + legacyController.acceptsFocusWhenInOverlay = true + 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) + + legacyController.enableSizeClassSignal = true + + present(legacyController, nil) + + TGPhotoVideoEditor.present(with: legacyController.context, controller: emptyController, caption: initialCaption, entities: [], withItem: item, paint: true, recipientName: recipientName, stickersContext: paintStickersContext, 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) + }, dismissed: { [weak legacyController] in + legacyController?.dismiss() + }) + }) +} + public func legacyAttachmentMenu(context: AccountContext, peer: Peer, chatLocation: ChatLocation, 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, presentTimerPicker: @escaping (@escaping (Int32) -> Void) -> Void, sendMessagesWithSignals: @escaping ([Any]?, Bool, Int32) -> Void, selectRecentlyUsedInlineBot: @escaping (Peer) -> Void, presentStickers: @escaping (@escaping (TelegramMediaFile, Bool, UIView, CGRect) -> Void) -> TGPhotoPaintStickersScreen?, present: @escaping (ViewController, Any?) -> Void) -> TGMenuSheetController { let defaultVideoPreset = defaultVideoPresetForContext(context) UserDefaults.standard.set(defaultVideoPreset.rawValue as NSNumber, forKey: "TG_preferredVideoPreset_v0") @@ -261,45 +315,14 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, chatLocati present(legacyController, nil) - TGPhotoVideoEditor.present(with: legacyController.context, controller: emptyController, caption: "", entities: [], withItem: item, recipientName: recipientName, stickersContext: paintStickersContext, completion: { result, editingContext in + TGPhotoVideoEditor.present(with: legacyController.context, controller: emptyController, caption: "", entities: [], withItem: item, paint: false, recipientName: recipientName, stickersContext: paintStickersContext, 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) } diff --git a/submodules/LegacyMediaPickerUI/Sources/LegacyAvatarPicker.swift b/submodules/LegacyMediaPickerUI/Sources/LegacyAvatarPicker.swift index a508bc1035..dc7ffe7c9d 100644 --- a/submodules/LegacyMediaPickerUI/Sources/LegacyAvatarPicker.swift +++ b/submodules/LegacyMediaPickerUI/Sources/LegacyAvatarPicker.swift @@ -6,32 +6,6 @@ import LegacyComponents import TelegramPresentationData import LegacyUI -public func presentLegacyAvatarEditor(theme: PresentationTheme, image: UIImage?, video: URL?, present: (ViewController, Any?) -> Void, imageCompletion: @escaping (UIImage) -> Void, videoCompletion: @escaping (UIImage, URL, TGVideoEditAdjustments?) -> Void) { - let legacyController = LegacyController(presentation: .custom, theme: theme) - legacyController.statusBar.statusBarStyle = .Ignore - - let emptyController = LegacyEmptyController(context: legacyController.context)! - let navigationController = makeLegacyNavigationController(rootController: emptyController) - navigationController.setNavigationBarHidden(true, animated: false) - navigationController.navigationBar.transform = CGAffineTransform(translationX: -1000.0, y: 0.0) - - legacyController.bind(controller: navigationController) - - present(legacyController, nil) - - TGPhotoVideoEditor.present(with: legacyController.context, parentController: emptyController, image: image, video: video, didFinishWithImage: { image in - if let image = image { - imageCompletion(image) - } - }, didFinishWithVideo: { image, asset, adjustments in - if let image = image { -// videoCompletion(image, url, adjustments) - } - }, dismissed: { [weak legacyController] in - legacyController?.dismiss() - }) -} - public func presentLegacyAvatarPicker(holder: Atomic, signup: Bool, theme: PresentationTheme, present: (ViewController, Any?) -> Void, openCurrent: (() -> Void)?, completion: @escaping (UIImage) -> Void, videoCompletion: @escaping (UIImage, Any?, TGVideoEditAdjustments?) -> Void = { _, _, _ in}) { let legacyController = LegacyController(presentation: .custom, theme: theme) legacyController.statusBar.statusBarStyle = .Ignore diff --git a/submodules/LegacyMediaPickerUI/Sources/LegacySuggestionContext.swift b/submodules/LegacyMediaPickerUI/Sources/LegacySuggestionContext.swift index ab405bf084..53258c65b3 100644 --- a/submodules/LegacyMediaPickerUI/Sources/LegacySuggestionContext.swift +++ b/submodules/LegacyMediaPickerUI/Sources/LegacySuggestionContext.swift @@ -17,8 +17,8 @@ public func legacySuggestionContext(context: AccountContext, peerId: PeerId, cha let disposable = searchPeerMembers(context: context, peerId: peerId, chatLocation: chatLocation, query: query, scope: .mention).start(next: { peers in let users = NSMutableArray() for peer in peers { - let user = TGUser() if let peer = peer as? TelegramUser { + let user = TGUser() user.uid = peer.id.id user.firstName = peer.firstName user.lastName = peer.lastName diff --git a/submodules/LegacyUI/Sources/LegacyComponentsStickers.swift b/submodules/LegacyUI/Sources/LegacyComponentsStickers.swift deleted file mode 100644 index ddcdbe4018..0000000000 --- a/submodules/LegacyUI/Sources/LegacyComponentsStickers.swift +++ /dev/null @@ -1,221 +0,0 @@ -import Foundation -import UIKit -import LegacyComponents -import Postbox -import TelegramCore -import SyncCore -import SwiftSignalKit -import Display -import StickerResources - -public func stickerFromLegacyDocument(_ documentAttachment: TGDocumentMediaAttachment) -> TelegramMediaFile? { - if documentAttachment.isSticker() { - for case let sticker as TGDocumentAttributeSticker in documentAttachment.attributes { - var attributes: [TelegramMediaFileAttribute] = [] - var packReference: StickerPackReference? - if let legacyPackReference = sticker.packReference as? TGStickerPackIdReference { - packReference = .id(id: legacyPackReference.packId, accessHash: legacyPackReference.packAccessHash) - } else if let legacyPackReference = sticker.packReference as? TGStickerPackShortnameReference { - packReference = .name(legacyPackReference.shortName) - } - attributes.append(.Sticker(displayText: sticker.alt, packReference: packReference, maskData: nil)) - - var fileReference: Data? - if let originInfo = documentAttachment.originInfo, let data = originInfo.fileReference { - fileReference = data - } - - return TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudFile, id: documentAttachment.documentId), partialReference: nil, resource: CloudDocumentMediaResource(datacenterId: Int(documentAttachment.datacenterId), fileId: documentAttachment.documentId, accessHash: documentAttachment.accessHash, size: Int(documentAttachment.size), fileReference: fileReference, fileName: documentAttachment.fileName()), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: documentAttachment.mimeType, size: Int(documentAttachment.size), attributes: attributes) - } - } - return nil -} - -func legacyComponentsStickers(postbox: Postbox, namespace: Int32) -> SSignal { - return SSignal { subscriber in - let disposable = (postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [namespace], aroundIndex: nil, count: 200 * 200)).start(next: { view in - var stickerPackDocuments: [ItemCollectionId: [Any]] = [:] - - for entry in view.entries { - if let item = entry.item as? StickerPackItem { - if item.file.isAnimatedSticker { - continue - } - let document = TGDocumentMediaAttachment() - document.documentId = item.file.fileId.id - if let resource = item.file.resource as? CloudDocumentMediaResource { - document.accessHash = resource.accessHash - document.datacenterId = Int32(resource.datacenterId) - var stickerPackId: Int64 = 0 - var accessHash: Int64 = 0 - for case let .Sticker(sticker) in item.file.attributes { - if let packReference = sticker.packReference, case let .id(id, h) = packReference { - stickerPackId = id - accessHash = h - } - break - } - document.originInfo = TGMediaOriginInfo(fileReference: resource.fileReference ?? Data(), fileReferences: [:], stickerPackId: stickerPackId, accessHash: accessHash) - } - document.mimeType = item.file.mimeType - if let size = item.file.size { - document.size = Int32(size) - } - if let thumbnail = item.file.previewRepresentations.first { - let imageInfo = TGImageInfo() - let encoder = PostboxEncoder() - encoder.encodeRootObject(thumbnail.resource) - let dataString = encoder.makeData().base64EncodedString(options: []) - imageInfo.addImage(with: thumbnail.dimensions.cgSize, url: dataString) - document.thumbnailInfo = imageInfo - } - var attributes: [Any] = [] - for attribute in item.file.attributes { - switch attribute { - case let .Sticker(displayText, _, maskData): - attributes.append(TGDocumentAttributeSticker(alt: displayText, packReference: nil, mask: maskData.flatMap { - return TGStickerMaskDescription(n: $0.n, point: CGPoint(x: CGFloat($0.x), y: CGFloat($0.y)), zoom: CGFloat($0.zoom)) - })) - case let .ImageSize(size): - attributes.append(TGDocumentAttributeImageSize(size: size.cgSize)) - default: - break - } - } - document.attributes = attributes - if stickerPackDocuments[entry.index.collectionId] == nil { - stickerPackDocuments[entry.index.collectionId] = [] - } - stickerPackDocuments[entry.index.collectionId]!.append(document) - } - } - - let stickerPacks = NSMutableArray() - for (id, info, _) in view.collectionInfos { - if let info = info as? StickerPackCollectionInfo, !info.flags.contains(.isAnimated) { - let pack = TGStickerPack(packReference: TGStickerPackIdReference(), title: info.title, stickerAssociations: [], documents: stickerPackDocuments[id] ?? [], packHash: info.hash, hidden: false, isMask: true, isFeatured: false, installedDate: 0)! - stickerPacks.add(pack) - } - } - - var dict: [AnyHashable: Any] = [:] - dict["packs"] = stickerPacks - subscriber?.putNext(dict) - }) - - return SBlockDisposable { - disposable.dispose() - } - } -} - -private final class LegacyStickerImageDataTask: NSObject { - private let disposable = DisposableSet() - - init(account: Account, file: TelegramMediaFile, small: Bool, fitSize: CGSize, completion: @escaping (UIImage?) -> Void) { - super.init() - - self.disposable.add(chatMessageLegacySticker(account: account, file: file, small: small, fitSize: fitSize, fetched: true, onlyFullSize: true).start(next: { generator in - if let image = generator(TransformImageArguments(corners: ImageCorners(), imageSize: fitSize, boundingSize: fitSize, intrinsicInsets: UIEdgeInsets()))?.generateImage() { - completion(image) - } - })) - } - - deinit { - self.disposable.dispose() - } - - func cancel() { - self.disposable.dispose() - } -} - -private let sharedImageCache = TGMemoryImageCache(softMemoryLimit: 2 * 1024 * 1024, hardMemoryLimit: 3 * 1024 * 1024)! - -final class LegacyStickerImageDataSource: TGImageDataSource { - private let account: () -> Account? - - init(account: @escaping () -> Account?) { - self.account = account - - super.init() - } - - override func canHandleUri(_ uri: String!) -> Bool { - if let uri = uri { - if uri.hasPrefix("sticker-preview://") { - return true - } else if uri.hasPrefix("sticker://") { - return true - } - } - return false - } - - override func loadDataSync(withUri uri: String!, canWait: Bool, acceptPartialData: Bool, asyncTaskId: AutoreleasingUnsafeMutablePointer!, progress: ((Float) -> Void)!, partialCompletion: ((TGDataResource?) -> Void)!, completion: ((TGDataResource?) -> Void)!) -> TGDataResource! { - if let image = sharedImageCache.image(forKey: uri, attributes: nil) { - return TGDataResource(image: image, decoded: true) - } - return nil - } - - override func loadDataAsync(withUri uri: String!, progress: ((Float) -> Void)!, partialCompletion: ((TGDataResource?) -> Void)!, completion: ((TGDataResource?) -> Void)!) -> Any! { - if let account = self.account() { - let args: [AnyHashable : Any] - var highQuality: Bool - if uri.hasPrefix("sticker-preview://") { - let argumentsString = String(uri[uri.index(uri.startIndex, offsetBy: "sticker-preview://?".count)...]) - args = TGStringUtils.argumentDictionary(inUrlString: argumentsString)! - highQuality = Int((args["highQuality"] as! String))! != 0 - } else if uri.hasPrefix("sticker://") { - let argumentsString = String(uri[uri.index(uri.startIndex, offsetBy: "sticker://?".count)...]) - args = TGStringUtils.argumentDictionary(inUrlString: argumentsString)! - highQuality = true - } else { - return nil - } - - let documentId = Int64((args["documentId"] as! String))! - let datacenterId = Int((args["datacenterId"] as! String))! - let accessHash = Int64((args["accessHash"] as! String))! - let size: Int? = nil - - let width = Int((args["width"] as! String))! - let height = Int((args["height"] as! String))! - - if width < 128 { - highQuality = false - } - - let fitSize = CGSize(width: CGFloat(width), height: CGFloat(height)) - - var attributes: [TelegramMediaFileAttribute] = [] - if let originInfoString = args["origin_info"] as? String, let originInfo = TGMediaOriginInfo(stringRepresentation: originInfoString), let stickerPackId = originInfo.stickerPackId?.int64Value, let stickerPackAccessHash = originInfo.stickerPackAccessHash?.int64Value { - attributes.append(.Sticker(displayText: "", packReference: .id(id: stickerPackId, accessHash: stickerPackAccessHash), maskData: nil)) - } - - var previewRepresentations: [TelegramMediaImageRepresentation] = [] - if let legacyThumbnailUri = args["legacyThumbnailUri"] as? String, let data = Data(base64Encoded: legacyThumbnailUri, options: []) { - if let resource = PostboxDecoder(buffer: MemoryBuffer(data: data)).decodeRootObject() as? TelegramMediaResource { - previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 140, height: 140), resource: resource, progressiveSizes: [])) - } - } - - return LegacyStickerImageDataTask(account: account, file: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudFile, id: documentId), partialReference: nil, resource: CloudDocumentMediaResource(datacenterId: datacenterId, fileId: documentId, accessHash: accessHash, size: size, fileReference: nil, fileName: fileNameFromFileAttributes(attributes)), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "image/webp", size: size, attributes: attributes), small: !highQuality, fitSize: fitSize, completion: { image in - if let image = image { - sharedImageCache.setImage(image, forKey: uri, attributes: nil) - completion?(TGDataResource(image: image, decoded: true)) - } - }) - } else { - return nil - } - } - - override func cancelTask(byId taskId: Any!) { - if let task = taskId as? LegacyStickerImageDataTask { - task.cancel() - } - } -} diff --git a/submodules/LegacyUI/Sources/LegacyHTTPOperationImpl.swift b/submodules/LegacyUI/Sources/LegacyHTTPOperationImpl.swift deleted file mode 100644 index 637d5f6aeb..0000000000 --- a/submodules/LegacyUI/Sources/LegacyHTTPOperationImpl.swift +++ /dev/null @@ -1,7 +0,0 @@ -import Foundation -import MtProtoKit - -import LegacyComponents - -@objc class LegacyHTTPOperationImpl: AFHTTPRequestOperation, LegacyHTTPRequestOperation { -} diff --git a/submodules/LegacyUI/Sources/LegacyLocationVenueIconDataSource.swift b/submodules/LegacyUI/Sources/LegacyLocationVenueIconDataSource.swift deleted file mode 100644 index 112d02e0cd..0000000000 --- a/submodules/LegacyUI/Sources/LegacyLocationVenueIconDataSource.swift +++ /dev/null @@ -1,193 +0,0 @@ -import Foundation -import UIKit -import LegacyComponents -import Postbox -import TelegramCore -import SyncCore -import SwiftSignalKit -import Display - -private let sharedImageCache = TGMemoryImageCache(softMemoryLimit: 2 * 1024 * 1024, hardMemoryLimit: 3 * 1024 * 1024)! - -private let placeholderImage = generateFilledCircleImage(diameter: 40.0, color: UIColor(rgb: 0xf2f2f2)) - -private final class LegacyLocationVenueIconTask: NSObject { - private let disposable = DisposableSet() - - init(account: Account, url: String, completion: @escaping (Data?) -> Void) { - super.init() - - let resource = HttpReferenceMediaResource(url: url, size: nil) - self.disposable.add(account.postbox.mediaBox.resourceData(resource).start(next: { data in - if data.complete { - if let loadedData = try? Data(contentsOf: URL(fileURLWithPath: data.path)) { - completion(loadedData) - } - } - })) - self.disposable.add(account.postbox.mediaBox.fetchedResource(resource, parameters: nil).start()) - } - - deinit { - self.disposable.dispose() - } - - func cancel() { - self.disposable.dispose() - } -} - -private let genericIconImage = TGComponentsImageNamed("LocationMessagePinIcon")?.precomposed() - -final class LegacyLocationVenueIconDataSource: TGImageDataSource { - private let account: () -> Account? - - init(account: @escaping () -> Account?) { - self.account = account - - super.init() - } - - override func canHandleUri(_ uri: String!) -> Bool { - if let uri = uri { - if uri.hasPrefix("location-venue-icon://") { - return true - } - } - return false - } - - override func loadAttributeSync(forUri uri: String!, attribute: String!) -> Any! { - if attribute == "placeholder" { - return placeholderImage - } - return nil - } - - override func loadDataSync(withUri uri: String!, canWait: Bool, acceptPartialData: Bool, asyncTaskId: AutoreleasingUnsafeMutablePointer!, progress: ((Float) -> Void)!, partialCompletion: ((TGDataResource?) -> Void)!, completion: ((TGDataResource?) -> Void)!) -> TGDataResource! { - if let image = sharedImageCache.image(forKey: uri, attributes: nil) { - return TGDataResource(image: image, decoded: true) - } - return nil - } - - private static func unavailableImage(for uri: String) -> TGDataResource? { - let args: [AnyHashable : Any] - let argumentsString = String(uri[uri.index(uri.startIndex, offsetBy: "location-venue-icon://".count)...]) - args = TGStringUtils.argumentDictionary(inUrlString: argumentsString)! - - guard let width = Int((args["width"] as! String)), width > 1 else { - return nil - } - guard let height = Int((args["height"] as! String)), height > 1 else { - return nil - } - - guard let colorN = (args["color"] as? String).flatMap({ Int($0) }) else { - return nil - } - - let color = UIColor(rgb: UInt32(colorN)) - - let size = CGSize(width: CGFloat(width), height: CGFloat(height)) - - guard let iconSourceImage = genericIconImage.flatMap({ generateTintedImage(image: $0, color: color) }) else { - return nil - } - - UIGraphicsBeginImageContextWithOptions(iconSourceImage.size, false, iconSourceImage.scale) - var context = UIGraphicsGetCurrentContext()! - iconSourceImage.draw(at: CGPoint()) - context.setBlendMode(.sourceAtop) - context.setFillColor(color.cgColor) - context.fill(CGRect(origin: CGPoint(), size: iconSourceImage.size)) - - let tintedIconImage = UIGraphicsGetImageFromCurrentImageContext() - UIGraphicsEndImageContext() - - UIGraphicsBeginImageContextWithOptions(size, false, 0.0) - context = UIGraphicsGetCurrentContext()! - let fitSize = CGSize(width: size.width - 4.0 * 2.0, height: size.height - 4.0 * 2.0) - let imageSize = iconSourceImage.size.aspectFitted(fitSize) - let imageRect = CGRect(origin: CGPoint(x: floor((size.width - imageSize.width) / 2.0), y: floor((size.height - imageSize.height) / 2.0)), size: imageSize) - tintedIconImage?.draw(in: imageRect) - - let iconImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext() - - if let iconImage = iconImage { - sharedImageCache.setImage(iconImage, forKey: uri, attributes: nil) - return TGDataResource(image: iconImage, decoded: true) - } - - return nil - } - - override func loadDataAsync(withUri uri: String!, progress: ((Float) -> Void)!, partialCompletion: ((TGDataResource?) -> Void)!, completion: ((TGDataResource?) -> Void)!) -> Any! { - if let account = self.account() { - let args: [AnyHashable : Any] - let argumentsString = String(uri[uri.index(uri.startIndex, offsetBy: "location-venue-icon://".count)...]) - args = TGStringUtils.argumentDictionary(inUrlString: argumentsString)! - - guard let width = Int((args["width"] as! String)), width > 1 else { - return nil - } - guard let height = Int((args["height"] as! String)), height > 1 else { - return nil - } - - guard let colorN = (args["color"] as? String).flatMap({ Int($0) }) else { - return nil - } - - guard let type = args["type"] as? String else { - return LegacyLocationVenueIconDataSource.unavailableImage(for: uri) - } - - let color = UIColor(rgb: UInt32(colorN)) - - let url = "https://ss3.4sqi.net/img/categories_v2/\(type)_88.png" - - let size = CGSize(width: CGFloat(width), height: CGFloat(height)) - - return LegacyLocationVenueIconTask(account: account, url: url, completion: { data in - if let data = data, let iconSourceImage = UIImage(data: data) { - UIGraphicsBeginImageContextWithOptions(iconSourceImage.size, false, iconSourceImage.scale) - var context = UIGraphicsGetCurrentContext()! - iconSourceImage.draw(at: CGPoint()) - context.setBlendMode(.sourceAtop) - context.setFillColor(color.cgColor) - context.fill(CGRect(origin: CGPoint(), size: iconSourceImage.size)) - - let tintedIconImage = UIGraphicsGetImageFromCurrentImageContext() - UIGraphicsEndImageContext() - - UIGraphicsBeginImageContextWithOptions(size, false, 0.0) - context = UIGraphicsGetCurrentContext()! - let imageRect = CGRect(x: 4.0, y: 4.0, width: size.width - 4.0 * 2.0, height: size.height - 4.0 * 2.0) - tintedIconImage?.draw(in: imageRect) - - let iconImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext() - - if let iconImage = iconImage { - sharedImageCache.setImage(iconImage, forKey: uri, attributes: nil) - completion?(TGDataResource(image: iconImage, decoded: true)) - } - } else { - if let image = LegacyLocationVenueIconDataSource.unavailableImage(for: uri) { - completion?(image) - } - } - }) - } else { - return nil - } - } - - override func cancelTask(byId taskId: Any!) { - if let disposable = taskId as? LegacyLocationVenueIconTask { - disposable.cancel() - } - } -} diff --git a/submodules/LegacyUI/Sources/TelegramInitializeLegacyComponents.swift b/submodules/LegacyUI/Sources/TelegramInitializeLegacyComponents.swift index 1c5d394d0a..19bf7578d7 100644 --- a/submodules/LegacyUI/Sources/TelegramInitializeLegacyComponents.swift +++ b/submodules/LegacyUI/Sources/TelegramInitializeLegacyComponents.swift @@ -196,30 +196,6 @@ private final class LegacyComponentsGlobalsProviderImpl: NSObject, LegacyCompone return LegacyComponentsAccessCheckerImpl(context: legacyContext) } - public func stickerPacksSignal() -> SSignal! { - if let legacyContext = legacyContext { - return legacyComponentsStickers(postbox: legacyContext.account.postbox, namespace: Namespaces.ItemCollection.CloudStickerPacks) - } else { - var dict: [AnyHashable: Any] = [:] - dict["packs"] = NSArray() - return SSignal.single(dict) - } - } - - public func maskStickerPacksSignal() -> SSignal! { - if let legacyContext = legacyContext { - return legacyComponentsStickers(postbox: legacyContext.account.postbox, namespace: Namespaces.ItemCollection.CloudMaskPacks) - } else { - var dict: [AnyHashable: Any] = [:] - dict["packs"] = NSArray() - return SSignal.single(dict) - } - } - - public func recentStickerMasksSignal() -> SSignal! { - return SSignal.single(NSArray()) - } - public func request(_ type: TGAudioSessionType, interrupted: (() -> Void)!) -> SDisposable! { if let legacyContext = legacyContext { let convertedType: ManagedAudioSessionType @@ -262,40 +238,6 @@ private final class LegacyComponentsGlobalsProviderImpl: NSObject, LegacyCompone return "" } - public func json(forHttpLocation httpLocation: String!) -> SSignal! { - return self.data(forHttpLocation: httpLocation).map(toSignal: { next in - if let next = next as? Data { - if let object = try? JSONSerialization.jsonObject(with: next, options: []) { - return SSignal.single(object) - } - } - return SSignal.fail(nil) - }) - } - - public func data(forHttpLocation httpLocation: String!) -> SSignal! { - return SSignal { subscriber in - if let httpLocation = httpLocation, let url = URL(string: httpLocation) { - let disposable = MTHttpRequestOperation.data(forHttpUrl: url).start(next: { next in - subscriber?.putNext(next) - }, error: { error in - subscriber?.putError(error) - }, completed: { - subscriber?.putCompletion() - }) - return SBlockDisposable(block: { - disposable?.dispose() - }) - } else { - return nil - } - } - } - - public func makeHTTPRequestOperation(with request: URLRequest!) -> (Operation & LegacyHTTPRequestOperation)! { - return LegacyHTTPOperationImpl(request: request) - } - public func pausePictureInPicturePlayback() { } @@ -377,15 +319,9 @@ public func initializeLegacyComponents(application: UIApplication?, currentSizeC TGRemoteImageView.setSharedCache(TGCache()) - TGImageDataSource.register(LegacyStickerImageDataSource(account: { - return legacyContext?.account - })) TGImageDataSource.register(LegacyPeerAvatarPlaceholderDataSource(account: { return legacyContext?.account })) - TGImageDataSource.register(LegacyLocationVenueIconDataSource(account: { - return legacyContext?.account - })) ASActor.registerClass(LegacyImageDownloadActor.self) LegacyComponentsGlobals.setProvider(LegacyComponentsGlobalsProviderImpl()) } diff --git a/submodules/LocationUI/Sources/LegacyLocationController.swift b/submodules/LocationUI/Sources/LegacyLocationController.swift deleted file mode 100644 index 3411e9a7ee..0000000000 --- a/submodules/LocationUI/Sources/LegacyLocationController.swift +++ /dev/null @@ -1,288 +0,0 @@ -import Foundation -import UIKit -import Display -import SwiftSignalKit -import LegacyComponents -import TelegramCore -import SyncCore -import Postbox -import TelegramPresentationData -import AccountContext -import ShareController -import LegacyUI -import OpenInExternalAppUI -import AppBundle -import LocationResources -import DeviceLocationManager - -private func generateClearIcon(color: UIColor) -> UIImage? { - return generateTintedImage(image: UIImage(bundleImageName: "Components/Search Bar/Clear"), color: color) -} - -func makeLegacyPeer(_ peer: Peer) -> AnyObject? { - if let user = peer as? TelegramUser { - let legacyUser = TGUser() - legacyUser.uid = user.id.id - legacyUser.firstName = user.firstName - legacyUser.lastName = user.lastName - if let representation = smallestImageRepresentation(user.photo) { - legacyUser.photoUrlSmall = legacyImageLocationUri(resource: representation.resource) - } - return legacyUser - } else if let channel = peer as? TelegramChannel { - let legacyConversation = TGConversation() - legacyConversation.conversationId = Int64(channel.id.id) - legacyConversation.chatTitle = channel.title - if let representation = smallestImageRepresentation(channel.photo) { - legacyConversation.chatPhotoSmall = legacyImageLocationUri(resource: representation.resource) - } - return legacyConversation - } else { - return nil - } -} - -private func makeLegacyMessage(_ message: Message) -> TGMessage { - let result = TGMessage() - result.mid = message.id.id - result.date = Double(message.timestamp) - if message.flags.contains(.Failed) { - result.deliveryState = TGMessageDeliveryStateFailed - } else if message.flags.contains(.Sending) { - result.deliveryState = TGMessageDeliveryStatePending - } else { - result.deliveryState = TGMessageDeliveryStateDelivered - } - - for attribute in message.attributes { - if let attribute = attribute as? EditedMessageAttribute { - result.editDate = Double(attribute.date) - } - } - - var media: [Any] = [] - for m in message.media { - if let mapMedia = m as? TelegramMediaMap { - let legacyLocation = TGLocationMediaAttachment() - legacyLocation.latitude = mapMedia.latitude - legacyLocation.longitude = mapMedia.longitude - if let venue = mapMedia.venue { - legacyLocation.venue = TGVenueAttachment(title: venue.title, address: venue.address, provider: venue.provider, venueId: venue.id, type: venue.type) - } - if let liveBroadcastingTimeout = mapMedia.liveBroadcastingTimeout { - legacyLocation.period = liveBroadcastingTimeout - } - - media.append(legacyLocation) - } - } - if !media.isEmpty { - result.mediaAttachments = media - } - - return result -} - -private func legacyRemainingTime(message: TGMessage) -> SSignal { - var liveBroadcastingTimeoutValue: Int32? - if let mediaAttachments = message.mediaAttachments { - for media in mediaAttachments { - if let m = media as? TGLocationMediaAttachment, m.period != 0 { - liveBroadcastingTimeoutValue = m.period - } - } - } - guard let liveBroadcastingTimeout = liveBroadcastingTimeoutValue else { - return SSignal.fail(nil) - } - - if message.deliveryState != TGMessageDeliveryStateDelivered { - return SSignal.single(liveBroadcastingTimeout as NSNumber) - } - - let remainingTime = SSignal.`defer`({ - let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) - let remainingTime = max(0, Int32(message.date) + liveBroadcastingTimeout - currentTime) - var signal = SSignal.single(remainingTime as NSNumber) - if remainingTime == 0 { - signal = signal?.then(SSignal.fail(nil)) - } - return signal - })! - - return (remainingTime.then(SSignal.complete().delay(5.0, on: SQueue.main()))).restart().`catch`({ _ in - return SSignal.complete() - }) -} - -private func telegramMap(for location: TGLocationMediaAttachment) -> TelegramMediaMap { - let mapVenue: MapVenue? - if let venue = location.venue { - mapVenue = MapVenue(title: venue.title ?? "", address: venue.address ?? "", provider: venue.provider ?? "", id: venue.venueId ?? "", type: venue.type ?? "") - } else { - mapVenue = nil - } - return TelegramMediaMap(latitude: location.latitude, longitude: location.longitude, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: mapVenue, liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil) -} - -func legacyLocationPalette(from theme: PresentationTheme) -> TGLocationPallete { - let listTheme = theme.list - let searchTheme = theme.rootController.navigationSearchBar - return TGLocationPallete(backgroundColor: listTheme.plainBackgroundColor, selectionColor: listTheme.itemHighlightedBackgroundColor, separatorColor: listTheme.itemPlainSeparatorColor, textColor: listTheme.itemPrimaryTextColor, secondaryTextColor: listTheme.itemSecondaryTextColor, accentColor: listTheme.itemAccentColor, destructiveColor: listTheme.itemDestructiveColor, locationColor: UIColor(rgb: 0x008df2), liveLocationColor: UIColor(rgb: 0xff6464), iconColor: searchTheme.backgroundColor, sectionHeaderBackgroundColor: theme.chatList.sectionHeaderFillColor, sectionHeaderTextColor: theme.chatList.sectionHeaderTextColor, searchBarPallete: TGSearchBarPallete(dark: theme.overallDarkAppearance, backgroundColor: searchTheme.backgroundColor, highContrastBackgroundColor: searchTheme.backgroundColor, textColor: searchTheme.inputTextColor, placeholderColor: searchTheme.inputPlaceholderTextColor, clearIcon: generateClearIcon(color: theme.rootController.navigationSearchBar.inputClearButtonColor), barBackgroundColor: searchTheme.backgroundColor, barSeparatorColor: searchTheme.separatorColor, plainBackgroundColor: searchTheme.backgroundColor, accentColor: searchTheme.accentColor, accentContrastColor: searchTheme.backgroundColor, menuBackgroundColor: searchTheme.backgroundColor, segmentedControlBackgroundImage: nil, segmentedControlSelectedImage: nil, segmentedControlHighlightedImage: nil, segmentedControlDividerImage: nil), avatarPlaceholder: nil) -} - -public func legacyLocationController(message: Message?, mapMedia: TelegramMediaMap, context: AccountContext, openPeer: @escaping (Peer) -> Void, sendLiveLocation: @escaping (CLLocationCoordinate2D, Int32) -> Void, stopLiveLocation: @escaping () -> Void, openUrl: @escaping (String) -> Void) -> ViewController { - let legacyLocation = TGLocationMediaAttachment() - legacyLocation.latitude = mapMedia.latitude - legacyLocation.longitude = mapMedia.longitude - if let venue = mapMedia.venue { - legacyLocation.venue = TGVenueAttachment(title: venue.title, address: venue.address, provider: venue.provider, venueId: venue.id, type: venue.type) - } - - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - - let legacyController = LegacyController(presentation: .navigation, theme: presentationData.theme, strings: presentationData.strings) - legacyController.navigationPresentation = .modal - let controller: TGLocationViewController - - let venueColor = mapMedia.venue?.type.flatMap { venueIconColor(type: $0) } - if let message = message { - let legacyMessage = makeLegacyMessage(message) - let legacyAuthor: AnyObject? = message.author.flatMap(makeLegacyPeer) - - let updatedLocations = SSignal(generator: { subscriber in - let disposable = topPeerActiveLiveLocationMessages(viewTracker: context.account.viewTracker, accountPeerId: context.account.peerId, peerId: message.id.peerId).start(next: { (_, messages) in - var result: [Any] = [] - let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) - loop: for message in messages { - var liveBroadcastingTimeout: Int32 = 0 - - mediaLoop: for media in message.media { - if let map = media as? TelegramMediaMap, let timeout = map.liveBroadcastingTimeout { - liveBroadcastingTimeout = timeout - break mediaLoop - } - } - - let legacyMessage = makeLegacyMessage(message) - guard let legacyAuthor = message.author.flatMap(makeLegacyPeer) else { - continue loop - } - let remainingTime = max(0, message.timestamp + liveBroadcastingTimeout - currentTime) - if legacyMessage.locationAttachment?.period != 0 { - let hasOwnSession = message.localTags.contains(.OutgoingLiveLocation) - var isOwn = false - if !message.flags.contains(.Incoming) { - isOwn = true - } else if let peer = message.peers[message.id.peerId] as? TelegramChannel { - isOwn = peer.hasPermission(.sendMessages) - } - - let liveLocation = TGLiveLocation(message: legacyMessage, peer: legacyAuthor, hasOwnSession: hasOwnSession, isOwnLocation: isOwn, isExpired: remainingTime == 0)! - result.append(liveLocation) - } - } - subscriber?.putNext(result) - }) - - return SBlockDisposable(block: { - disposable.dispose() - }) - })! - - if let liveBroadcastingTimeout = mapMedia.liveBroadcastingTimeout { - let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) - let remainingTime = max(0, message.timestamp + liveBroadcastingTimeout - currentTime) - - let messageLiveLocation = TGLiveLocation(message: legacyMessage, peer: legacyAuthor, hasOwnSession: false, isOwnLocation: false, isExpired: remainingTime == 0)! - - controller = TGLocationViewController(context: legacyController.context, liveLocation: messageLiveLocation) - - if remainingTime == 0 { - let freezeLocations: [Any] = [messageLiveLocation] - controller.setLiveLocationsSignal(.single(freezeLocations)) - } else { - controller.setLiveLocationsSignal(updatedLocations) - if message.flags.contains(.Incoming) { - context.account.viewTracker.updateSeenLiveLocationForMessageIds(messageIds: Set([message.id])) - } - } - } else { - controller = TGLocationViewController(context: legacyController.context, message: legacyMessage, peer: legacyAuthor, color: venueColor)! - controller.receivingPeer = message.peers[message.id.peerId].flatMap(makeLegacyPeer) - controller.setLiveLocationsSignal(updatedLocations) - } - - let namespacesWithEnabledLiveLocation: Set = Set([ - Namespaces.Peer.CloudChannel, - Namespaces.Peer.CloudGroup, - Namespaces.Peer.CloudUser - ]) - if namespacesWithEnabledLiveLocation.contains(message.id.peerId.namespace) { - controller.allowLiveLocationSharing = true - } - } else { - let attachment = TGLocationMediaAttachment() - attachment.latitude = mapMedia.latitude - attachment.longitude = mapMedia.longitude - controller = TGLocationViewController(context: legacyController.context, locationAttachment: attachment, peer: nil, color: venueColor) - } - - controller.remainingTimeForMessage = { message in - return legacyRemainingTime(message: message!) - } - controller.liveLocationStarted = { [weak legacyController] coordinate, period in - sendLiveLocation(coordinate, period) - legacyController?.dismiss() - } - controller.liveLocationStopped = { [weak legacyController] in - stopLiveLocation() - legacyController?.dismiss() - } - - let theme = (context.sharedContext.currentPresentationData.with { $0 }).theme - controller.pallete = legacyLocationPalette(from: theme) - - controller.modalMode = true - controller.presentActionsMenu = { [weak legacyController] legacyLocation, directions in - if let strongLegacyController = legacyController, let location = legacyLocation { - let map = telegramMap(for: location) - - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - let shareAction = OpenInControllerAction(title: presentationData.strings.Conversation_ContextMenuShare, action: { - strongLegacyController.present(ShareController(context: context, subject: .mapMedia(map), externalShare: true), in: .window(.root), with: nil) - }) - - strongLegacyController.present(OpenInActionSheetController(context: context, item: .location(location: map, withDirections: directions), additionalAction: !directions ? shareAction : nil, openUrl: openUrl), in: .window(.root), with: nil) - } - } - - controller.onViewDidAppear = { [weak controller] in - if let strongController = controller { - strongController.view.disablesInteractiveModalDismiss = true - strongController.view.disablesInteractiveTransitionGestureRecognizer = true - strongController.locationMapView.interactiveTransitionGestureRecognizerTest = { point -> Bool in - return point.x > 30.0 - } - } - } - - legacyController.navigationItem.title = controller.navigationItem.title - controller.updateRightBarItem = { item, action, animated in - if action { - legacyController.navigationItem.rightBarButtonItem = UIBarButtonItem(image: PresentationResourcesRootController.navigationShareIcon(theme), style: .plain, target: controller, action: #selector(controller.actionsButtonPressed)) - } else { - legacyController.navigationItem.setRightBarButton(item, animated: animated) - } - } - legacyController.bind(controller: controller) - - let presentationDisposable = context.sharedContext.presentationData.start(next: { [weak controller] presentationData in - if let controller = controller { - controller.pallete = legacyLocationPalette(from: presentationData.theme) - } - }) - legacyController.disposables.add(presentationDisposable) - - return legacyController -} diff --git a/submodules/LocationUI/Sources/LegacyLocationPicker.swift b/submodules/LocationUI/Sources/LegacyLocationPicker.swift deleted file mode 100644 index 108de5e611..0000000000 --- a/submodules/LocationUI/Sources/LegacyLocationPicker.swift +++ /dev/null @@ -1,113 +0,0 @@ -import Foundation -import UIKit -import Display -import LegacyComponents -import TelegramCore -import SyncCore -import Postbox -import SwiftSignalKit -import TelegramPresentationData -import AccountContext -import LegacyUI -import AppBundle - -private func generateClearIcon(color: UIColor) -> UIImage? { - return generateTintedImage(image: UIImage(bundleImageName: "Components/Search Bar/Clear"), color: color) -} - -public func legacyLocationPickerController(context: AccountContext, selfPeer: Peer, peer: Peer, sendLocation: @escaping (CLLocationCoordinate2D, MapVenue?, String?) -> Void, sendLiveLocation: @escaping (CLLocationCoordinate2D, Int32) -> Void, theme: PresentationTheme, customLocationPicker: Bool = false, hasLiveLocation: Bool = true, presentationCompleted: @escaping () -> Void = {}) -> ViewController { - let legacyController = LegacyController(presentation: .navigation, theme: theme) - legacyController.navigationPresentation = .modal - let controller = TGLocationPickerController(context: legacyController.context, intent: customLocationPicker ? TGLocationPickerControllerCustomLocationIntent : TGLocationPickerControllerDefaultIntent)! - legacyController.presentationCompleted = { [weak controller] in - presentationCompleted() - - controller?.view.disablesInteractiveModalDismiss = true - controller?.view.disablesInteractiveTransitionGestureRecognizer = true - } - controller.peer = makeLegacyPeer(selfPeer) - controller.receivingPeer = makeLegacyPeer(peer) - controller.pallete = legacyLocationPalette(from: theme) - let namespacesWithEnabledLiveLocation: Set = Set([ - Namespaces.Peer.CloudChannel, - Namespaces.Peer.CloudGroup, - Namespaces.Peer.CloudUser - ]) - if namespacesWithEnabledLiveLocation.contains(peer.id.namespace) && !customLocationPicker && hasLiveLocation { - controller.allowLiveLocationSharing = true - } - let navigationController = TGNavigationController(controllers: [controller])! - controller.navigation_setDismiss({ [weak legacyController] in - legacyController?.dismiss() - }, rootController: nil) - legacyController.bind(controller: navigationController) - legacyController.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait) - controller.locationPicked = { [weak legacyController] coordinate, venue, address in - sendLocation(coordinate, venue.flatMap { venue in - return MapVenue(title: venue.title, address: venue.address, provider: venue.provider, id: venue.venueId, type: venue.type) - }, address) - legacyController?.dismiss() - } - controller.liveLocationStarted = { [weak legacyController] coordinate, period in - sendLiveLocation(coordinate, period) - legacyController?.dismiss() - } - controller.nearbyPlacesSignal = { query, location in - return SSignal(generator: { subscriber in - let nearbyPlacesSignal: Signal<[TGLocationVenue], NoError> = resolvePeerByName(account: context.account, name: "foursquare") - |> take(1) - |> mapToSignal { peerId -> Signal in - guard let peerId = peerId else { - return .single(nil) - } - return requestChatContextResults(account: context.account, botId: peerId, peerId: selfPeer.id, query: query ?? "", location: .single((location?.coordinate.latitude ?? 0.0, location?.coordinate.longitude ?? 0.0)), offset: "") - |> map { results -> ChatContextResultCollection? in - return results?.results - } - |> `catch` { error -> Signal in - return .single(nil) - } - } - |> mapToSignal { contextResult -> Signal<[TGLocationVenue], NoError> in - guard let contextResult = contextResult else { - return .single([]) - } - - var list: [TGLocationVenue] = [] - for result in contextResult.results { - switch result.message { - case let .mapLocation(mapMedia, _): - let legacyLocation = TGLocationMediaAttachment() - legacyLocation.latitude = mapMedia.latitude - legacyLocation.longitude = mapMedia.longitude - if let venue = mapMedia.venue { - legacyLocation.venue = TGVenueAttachment(title: venue.title, address: venue.address, provider: venue.provider, venueId: venue.id, type: venue.type) - } - list.append(TGLocationVenue(locationAttachment: legacyLocation)) - default: - break - } - } - - return .single(list) - } - - let disposable = nearbyPlacesSignal.start(next: { next in - subscriber?.putNext(next as NSArray) - }, completed: { - subscriber?.putCompletion() - }) - - return SBlockDisposable(block: { - disposable.dispose() - }) - }) - } - let presentationDisposable = context.sharedContext.presentationData.start(next: { [weak controller] presentationData in - if let controller = controller { - controller.pallete = legacyLocationPalette(from: presentationData.theme) - } - }) - legacyController.disposables.add(presentationDisposable) - return legacyController -} diff --git a/submodules/LocationUI/Sources/LocationUtils.swift b/submodules/LocationUI/Sources/LocationUtils.swift index 30475fa14a..7d658b057c 100644 --- a/submodules/LocationUI/Sources/LocationUtils.swift +++ b/submodules/LocationUI/Sources/LocationUtils.swift @@ -81,7 +81,7 @@ func stringForEstimatedDuration(strings: PresentationStrings, eta: Double) -> St if hours == 1 && minutes == 0 { string = strings.Map_ETAHours(1) } else { - string = strings.Map_ETAHours(9999).replacingOccurrences(of: "9999", with: String(format: "%d:%02d", arguments: [hours, minutes])) + string = strings.Map_ETAHours(10).replacingOccurrences(of: "10", with: String(format: "%d:%02d", arguments: [hours, minutes])) } } else { string = strings.Map_ETAMinutes(minutes) diff --git a/submodules/MediaPlayer/Sources/MediaPlayer.swift b/submodules/MediaPlayer/Sources/MediaPlayer.swift index 1ac1ab6327..750330d180 100644 --- a/submodules/MediaPlayer/Sources/MediaPlayer.swift +++ b/submodules/MediaPlayer/Sources/MediaPlayer.swift @@ -870,12 +870,12 @@ private final class MediaPlayerContext { var statusTimestamp = CACurrentMediaTime() let playbackStatus: MediaPlayerPlaybackStatus + var isPlaying = false + if case .playing = self.state { + isPlaying = true + } if let bufferingProgress = bufferingProgress { - var whilePlaying = false - if case .playing = self.state { - whilePlaying = true - } - playbackStatus = .buffering(initial: false, whilePlaying: whilePlaying, progress: Float(bufferingProgress), display: true) + playbackStatus = .buffering(initial: false, whilePlaying: isPlaying, progress: Float(bufferingProgress), display: true) } else if !rate.isZero { if reportRate.isZero { //playbackStatus = .buffering(initial: false, whilePlaying: true) @@ -885,8 +885,13 @@ private final class MediaPlayerContext { playbackStatus = .playing } } else { - playbackStatus = .paused + if performActionAtEndNow && !self.stoppedAtEnd, case .loop = self.actionAtEnd, isPlaying { + playbackStatus = .playing + } else { + playbackStatus = .paused + } } + if self.lastStatusUpdateTimestamp == nil || self.lastStatusUpdateTimestamp! < statusTimestamp + 500 { lastStatusUpdateTimestamp = statusTimestamp var reportTimestamp = timestamp diff --git a/submodules/MtProtoKit/Sources/MTApiEnvironment.m b/submodules/MtProtoKit/Sources/MTApiEnvironment.m index ea79285863..e6e67a701e 100644 --- a/submodules/MtProtoKit/Sources/MTApiEnvironment.m +++ b/submodules/MtProtoKit/Sources/MTApiEnvironment.m @@ -36,6 +36,11 @@ #define IPHONE_11_NAMESTRING @"iPhone 11" #define IPHONE_11PRO_NAMESTRING @"iPhone 11 Pro" #define IPHONE_11PROMAX_NAMESTRING @"iPhone 11 Pro Max" +#define IPHONE_12MINI_NAMESTRING @"iPhone 12 mini" +#define IPHONE_12_NAMESTRING @"iPhone 12" +#define IPHONE_12PRO_NAMESTRING @"iPhone 12 Pro" +#define IPHONE_12PROMAX_NAMESTRING @"iPhone 12 Pro Max" + #define IPHONE_UNKNOWN_NAMESTRING @"Unknown iPhone" #define IPOD_1G_NAMESTRING @"iPod touch 1G" @@ -112,6 +117,10 @@ typedef enum { UIDevice11iPhone, UIDevice11ProiPhone, UIDevice11ProMaxiPhone, + UIDevice12MiniiPhone, + UIDevice12iPhone, + UIDevice12ProiPhone, + UIDevice12ProMaxiPhone, UIDevice1GiPod, UIDevice2GiPod, @@ -604,6 +613,10 @@ NSString *suffix = @""; case UIDevice11iPhone: return IPHONE_11_NAMESTRING; case UIDevice11ProiPhone: return IPHONE_11PRO_NAMESTRING; case UIDevice11ProMaxiPhone: return IPHONE_11PROMAX_NAMESTRING; + case UIDevice12MiniiPhone: return IPHONE_12MINI_NAMESTRING; + case UIDevice12iPhone: return IPHONE_12_NAMESTRING; + case UIDevice12ProiPhone: return IPHONE_12PRO_NAMESTRING; + case UIDevice12ProMaxiPhone: return IPHONE_12PROMAX_NAMESTRING; case UIDeviceUnknowniPhone: return IPHONE_UNKNOWN_NAMESTRING; case UIDevice1GiPod: return IPOD_1G_NAMESTRING; @@ -695,11 +708,14 @@ NSString *suffix = @""; if ([platform isEqualToString:@"iPhone11,6"]) return UIDeviceXSMaxiPhone; if ([platform isEqualToString:@"iPhone11,4"]) return UIDeviceXSMaxiPhone; if ([platform isEqualToString:@"iPhone11,8"]) return UIDeviceXRiPhone; - if ([platform isEqualToString:@"iPhone12,1"]) return UIDevice11iPhone; if ([platform isEqualToString:@"iPhone12,3"]) return UIDevice11ProiPhone; if ([platform isEqualToString:@"iPhone12,5"]) return UIDevice11ProMaxiPhone; if ([platform isEqualToString:@"iPhone12,8"]) return UIDeviceSE2Phone; + if ([platform isEqualToString:@"iPhone13,1"]) return UIDevice12MiniiPhone; + if ([platform isEqualToString:@"iPhone13,2"]) return UIDevice12iPhone; + if ([platform isEqualToString:@"iPhone13,3"]) return UIDevice12ProiPhone; + if ([platform isEqualToString:@"iPhone13,4"]) return UIDevice12ProMaxiPhone; if ([platform isEqualToString:@"iPhone8,4"]) return UIDeviceSEPhone; diff --git a/submodules/PassportUI/Sources/SecureIdDocumentGalleryController.swift b/submodules/PassportUI/Sources/SecureIdDocumentGalleryController.swift index 37c901c718..ce02da88e0 100644 --- a/submodules/PassportUI/Sources/SecureIdDocumentGalleryController.swift +++ b/submodules/PassportUI/Sources/SecureIdDocumentGalleryController.swift @@ -177,12 +177,13 @@ class SecureIdDocumentGalleryController: ViewController, StandalonePresentableCo if let strongSelf = self { strongSelf.present(controller, in: .window(.root), with: arguments, blockInteraction: true) } - }, dismissController: { [weak self] in - self?.dismiss(forceAway: true) - }, replaceRootController: { [weak self] controller, ready in - if let strongSelf = self { - strongSelf.replaceRootController(controller, ready) - } + }, dismissController: { [weak self] in + self?.dismiss(forceAway: true) + }, replaceRootController: { [weak self] controller, ready in + if let strongSelf = self { + strongSelf.replaceRootController(controller, ready) + } + }, editMedia: { _ in }) self.displayNode = GalleryControllerNode(controllerInteraction: controllerInteraction) self.displayNodeDidLoad() diff --git a/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift b/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift index f1b913406f..4e6d60ce92 100644 --- a/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift +++ b/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift @@ -517,6 +517,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr if let strongSelf = self { strongSelf.replaceRootController(controller, ready) } + }, editMedia: { _ in }) self.displayNode = GalleryControllerNode(controllerInteraction: controllerInteraction) self.displayNodeDidLoad() diff --git a/submodules/PeerInfoUI/Sources/ChannelMembersSearchContainerNode.swift b/submodules/PeerInfoUI/Sources/ChannelMembersSearchContainerNode.swift index 2e451d1400..99240510c5 100644 --- a/submodules/PeerInfoUI/Sources/ChannelMembersSearchContainerNode.swift +++ b/submodules/PeerInfoUI/Sources/ChannelMembersSearchContainerNode.swift @@ -17,6 +17,18 @@ import ContactsPeerItem import ChatListSearchItemHeader import ItemListUI +enum ParticipantRevealActionType { + case promote + case restrict + case remove +} + +struct ParticipantRevealAction: Equatable { + let type: ItemListPeerItemRevealOptionType + let title: String + let action: ParticipantRevealActionType +} + public enum ChannelMembersSearchMode { case searchMembers case searchAdmins diff --git a/submodules/PeerInfoUI/Sources/GroupInfoController.swift b/submodules/PeerInfoUI/Sources/GroupInfoController.swift deleted file mode 100644 index 72f2de42d4..0000000000 --- a/submodules/PeerInfoUI/Sources/GroupInfoController.swift +++ /dev/null @@ -1,2555 +0,0 @@ -import Foundation -import UIKit -import AsyncDisplayKit -import Display -import SwiftSignalKit -import Postbox -import TelegramCore -import SyncCore -import LegacyComponents -import TelegramPresentationData -import SafariServices -import TelegramUIPreferences -import ItemListUI -import PresentationDataUtils -import TextFormat -import AccountContext -import TelegramStringFormatting -import TemporaryCachedPeerDataManager -import ShareController -import AlertUI -import PresentationDataUtils -import MediaResources -import PhotoResources -import LocationResources -import GalleryUI -import LegacyUI -import LocationUI -import ItemListPeerItem -import ContactListUI -import ItemListAvatarAndNameInfoItem -import ItemListPeerActionItem -import WebSearchUI -import Geocoding -import PeerAvatarGalleryUI -import Emoji -import NotificationMuteSettingsUI -import MapResourceToAvatarSizes -import NotificationSoundSelectionUI -import ItemListAddressItem -import AppBundle -import Markdown -import LocalizedPeerData - -private let maxParticipantsDisplayedLimit: Int32 = 50 -private let maxParticipantsDisplayedCollapseLimit: Int32 = 60 - -private final class GroupInfoArguments { - let context: AccountContext - - let avatarAndNameInfoContext: ItemListAvatarAndNameInfoItemContext - let tapAvatarAction: () -> Void - let changeProfilePhoto: () -> Void - let pushController: (ViewController) -> Void - let presentController: (ViewController, ViewControllerPresentationArguments) -> Void - let changeNotificationMuteSettings: () -> Void - let openPreHistory: () -> Void - let openSharedMedia: () -> Void - let openAdministrators: () -> Void - let openPermissions: () -> Void - let updateEditingName: (ItemListAvatarAndNameInfoItemName) -> Void - let updateEditingDescriptionText: (String) -> Void - let setPeerIdWithRevealedOptions: (PeerId?, PeerId?) -> Void - let addMember: () -> Void - let promotePeer: (RenderedChannelParticipant) -> Void - let restrictPeer: (RenderedChannelParticipant) -> Void - let removePeer: (PeerId) -> Void - let leave: () -> Void - let displayUsernameShareMenu: (String) -> Void - let displayUsernameContextMenu: (String) -> Void - let displayAboutContextMenu: (String) -> Void - let aboutLinkAction: (TextLinkItemActionType, TextLinkItem) -> Void - let openStickerPackSetup: () -> Void - let openGroupTypeSetup: () -> Void - let openLinkedChannelSetup: () -> Void - let openLocation: (PeerGeoLocation) -> Void - let changeLocation: () -> Void - let displayLocationContextMenu: (String) -> Void - let expandParticipants: () -> Void - - init(context: AccountContext, avatarAndNameInfoContext: ItemListAvatarAndNameInfoItemContext, tapAvatarAction: @escaping () -> Void, changeProfilePhoto: @escaping () -> Void, pushController: @escaping (ViewController) -> Void, presentController: @escaping (ViewController, ViewControllerPresentationArguments) -> Void, changeNotificationMuteSettings: @escaping () -> Void, openPreHistory: @escaping () -> Void, openSharedMedia: @escaping () -> Void, openAdministrators: @escaping () -> Void, openPermissions: @escaping () -> Void, updateEditingName: @escaping (ItemListAvatarAndNameInfoItemName) -> Void, updateEditingDescriptionText: @escaping (String) -> Void, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, addMember: @escaping () -> Void, promotePeer: @escaping (RenderedChannelParticipant) -> Void, restrictPeer: @escaping (RenderedChannelParticipant) -> Void, removePeer: @escaping (PeerId) -> Void, leave: @escaping () -> Void, displayUsernameShareMenu: @escaping (String) -> Void, displayUsernameContextMenu: @escaping (String) -> Void, displayAboutContextMenu: @escaping (String) -> Void, aboutLinkAction: @escaping (TextLinkItemActionType, TextLinkItem) -> Void, openStickerPackSetup: @escaping () -> Void, openGroupTypeSetup: @escaping () -> Void, openLinkedChannelSetup: @escaping () -> Void, openLocation: @escaping (PeerGeoLocation) -> Void, changeLocation: @escaping () -> Void, displayLocationContextMenu: @escaping (String) -> Void, expandParticipants: @escaping () -> Void) { - self.context = context - self.avatarAndNameInfoContext = avatarAndNameInfoContext - self.tapAvatarAction = tapAvatarAction - self.changeProfilePhoto = changeProfilePhoto - self.pushController = pushController - self.presentController = presentController - self.changeNotificationMuteSettings = changeNotificationMuteSettings - self.openPreHistory = openPreHistory - self.openSharedMedia = openSharedMedia - self.openAdministrators = openAdministrators - self.openPermissions = openPermissions - self.updateEditingName = updateEditingName - self.updateEditingDescriptionText = updateEditingDescriptionText - self.setPeerIdWithRevealedOptions = setPeerIdWithRevealedOptions - self.addMember = addMember - self.promotePeer = promotePeer - self.restrictPeer = restrictPeer - self.removePeer = removePeer - self.leave = leave - self.displayUsernameShareMenu = displayUsernameShareMenu - self.displayUsernameContextMenu = displayUsernameContextMenu - self.displayAboutContextMenu = displayAboutContextMenu - self.aboutLinkAction = aboutLinkAction - self.openStickerPackSetup = openStickerPackSetup - self.openGroupTypeSetup = openGroupTypeSetup - self.openLinkedChannelSetup = openLinkedChannelSetup - self.openLocation = openLocation - self.changeLocation = changeLocation - self.displayLocationContextMenu = displayLocationContextMenu - self.expandParticipants = expandParticipants - } -} - -private enum GroupInfoSection: ItemListSectionId { - case info - case about - case infoManagement - case sharedMediaAndNotifications - case memberManagement - case members - case leave -} - -private enum GroupInfoEntryTag { - case about - case link - case location -} - -private enum GroupInfoMemberStatus: Equatable { - case member - case admin(rank: String?) - case owner(rank: String?) -} - -private enum GroupEntryStableId: Hashable, Equatable { - case peer(PeerId) - case index(Int) - - static func ==(lhs: GroupEntryStableId, rhs: GroupEntryStableId) -> Bool { - switch lhs { - case let .peer(peerId): - if case .peer(peerId) = rhs { - return true - } else { - return false - } - case let .index(index): - if case .index(index) = rhs { - return true - } else { - return false - } - } - } - - var hashValue: Int { - switch self { - case let .peer(peerId): - return peerId.hashValue - case let .index(index): - return index.hashValue - } - } -} - -enum ParticipantRevealActionType { - case promote - case restrict - case remove -} - -struct ParticipantRevealAction: Equatable { - let type: ItemListPeerItemRevealOptionType - let title: String - let action: ParticipantRevealActionType -} - -private enum GroupInfoEntry: ItemListNodeEntry { - case info(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, peer: Peer?, cachedData: CachedPeerData?, state: ItemListAvatarAndNameInfoItemState, updatingAvatar: ItemListAvatarAndNameInfoItemUpdatingAvatar?) - case setGroupPhoto(PresentationTheme, String) - case groupDescriptionSetup(PresentationTheme, String, String) - case about(PresentationTheme, String) - case locationHeader(PresentationTheme, String) - case location(PresentationTheme, PeerGeoLocation) - case changeLocation(PresentationTheme, String) - case link(PresentationTheme, String) - case sharedMedia(PresentationTheme, String) - case notifications(PresentationTheme, String, String) - case stickerPack(PresentationTheme, String, String) - case groupTypeSetup(PresentationTheme, String, String) - case linkedChannelSetup(PresentationTheme, String, String) - case preHistory(PresentationTheme, String, String) - case administrators(PresentationTheme, String, String) - case permissions(PresentationTheme, String, String) - case addMember(PresentationTheme, String, editing: Bool) - case member(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, index: Int, peerId: PeerId, peer: Peer, participant: RenderedChannelParticipant?, presence: PeerPresence?, memberStatus: GroupInfoMemberStatus, editing: ItemListPeerItemEditing, revealActions: [ParticipantRevealAction], enabled: Bool, selectable: Bool) - case expand(PresentationTheme, String) - case leave(PresentationTheme, String) - - var section: ItemListSectionId { - switch self { - case .info, .setGroupPhoto, .groupDescriptionSetup, .about: - return GroupInfoSection.info.rawValue - case .locationHeader, .location, .changeLocation, .link: - return GroupInfoSection.about.rawValue - case .groupTypeSetup, .linkedChannelSetup, .preHistory, .stickerPack: - return GroupInfoSection.infoManagement.rawValue - case .sharedMedia, .notifications: - return GroupInfoSection.sharedMediaAndNotifications.rawValue - case .permissions, .administrators: - return GroupInfoSection.memberManagement.rawValue - case .addMember, .member, .expand: - return GroupInfoSection.members.rawValue - case .leave: - return GroupInfoSection.leave.rawValue - } - } - - static func ==(lhs: GroupInfoEntry, rhs: GroupInfoEntry) -> Bool { - switch lhs { - case let .info(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsPeer, lhsCachedData, lhsState, lhsUpdatingAvatar): - if case let .info(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsPeer, rhsCachedData, rhsState, rhsUpdatingAvatar) = rhs { - if lhsTheme !== rhsTheme { - return false - } - if lhsStrings !== rhsStrings { - return false - } - if lhsDateTimeFormat != rhsDateTimeFormat { - return false - } - if let lhsPeer = lhsPeer, let rhsPeer = rhsPeer { - if !lhsPeer.isEqual(rhsPeer) { - return false - } - } else if (lhsPeer == nil) != (rhsPeer != nil) { - return false - } - if let lhsCachedData = lhsCachedData, let rhsCachedData = rhsCachedData { - if !lhsCachedData.isEqual(to: rhsCachedData) { - return false - } - } else if (lhsCachedData != nil) != (rhsCachedData != nil) { - return false - } - if lhsState != rhsState { - return false - } - if lhsUpdatingAvatar != rhsUpdatingAvatar { - return false - } - return true - } else { - return false - } - case let .setGroupPhoto(lhsTheme, lhsText): - if case let .setGroupPhoto(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { - return true - } else { - return false - } - case let .groupDescriptionSetup(lhsTheme, lhsPlaceholder, lhsText): - if case let .groupDescriptionSetup(rhsTheme, rhsPlaceholder, rhsText) = rhs, lhsTheme === rhsTheme, lhsPlaceholder == rhsPlaceholder, lhsText == rhsText { - return true - } else { - return false - } - case let .sharedMedia(lhsTheme, lhsText): - if case let .sharedMedia(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { - return true - } else { - return false - } - case let .leave(lhsTheme, lhsText): - if case let .leave(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { - return true - } else { - return false - } - case let .about(lhsTheme, lhsText): - if case let .about(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { - return true - } else { - return false - } - case let .locationHeader(lhsTheme, lhsText): - if case let .locationHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { - return true - } else { - return false - } - case let .location(lhsTheme, lhsLocation): - if case let .location(rhsTheme, rhsLocation) = rhs, lhsTheme === rhsTheme, lhsLocation == rhsLocation { - return true - } else { - return false - } - case let .changeLocation(lhsTheme, lhsText): - if case let .changeLocation(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { - return true - } else { - return false - } - case let .link(lhsTheme, lhsText): - if case let .link(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { - return true - } else { - return false - } - case let .notifications(lhsTheme, lhsTitle, lhsText): - if case let .notifications(rhsTheme, rhsTitle, rhsText) = rhs { - if lhsTheme !== rhsTheme { - return false - } - if lhsTitle != rhsTitle { - return false - } - if lhsText != rhsText { - return false - } - return true - } else { - return false - } - case let .stickerPack(lhsTheme, lhsTitle, lhsValue): - if case let .stickerPack(rhsTheme, rhsTitle, rhsValue) = rhs { - if lhsTheme !== rhsTheme { - return false - } - if lhsTitle != rhsTitle { - return false - } - if lhsValue != rhsValue { - return false - } - return true - } else { - return false - } - case let .preHistory(lhsTheme, lhsTitle, lhsValue): - if case let .preHistory(rhsTheme, rhsTitle, rhsValue) = rhs, lhsTheme === rhsTheme, lhsTitle == rhsTitle, lhsValue == rhsValue { - return true - } else { - return false - } - case let .groupTypeSetup(lhsTheme, lhsTitle, lhsText): - if case let .groupTypeSetup(rhsTheme, rhsTitle, rhsText) = rhs, lhsTheme === rhsTheme, lhsTitle == rhsTitle, lhsText == rhsText { - return true - } else { - return false - } - case let .linkedChannelSetup(lhsTheme, lhsTitle, lhsText): - if case let .linkedChannelSetup(rhsTheme, rhsTitle, rhsText) = rhs, lhsTheme === rhsTheme, lhsTitle == rhsTitle, lhsText == rhsText { - return true - } else { - return false - } - case let .permissions(lhsTheme, lhsTitle, lhsText): - if case let .permissions(rhsTheme, rhsTitle, rhsText) = rhs, lhsTheme === rhsTheme, lhsTitle == rhsTitle, lhsText == rhsText { - return true - } else { - return false - } - case let .administrators(lhsTheme, lhsTitle, lhsText): - if case let .administrators(rhsTheme, rhsTitle, rhsText) = rhs, lhsTheme === rhsTheme, lhsTitle == rhsTitle, lhsText == rhsText { - return true - } else { - return false - } - case let .addMember(lhsTheme, lhsTitle, lhsEditing): - if case let .addMember(rhsTheme, rhsTitle, rhsEditing) = rhs, lhsTheme === rhsTheme, lhsTitle == rhsTitle, lhsEditing == rhsEditing { - return true - } else { - return false - } - case let .member(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsNameDisplayOrder, lhsIndex, lhsPeerId, lhsPeer, lhsParticipant, lhsPresence, lhsMemberStatus, lhsEditing, lhsActions, lhsEnabled, lhsSelectable): - if case let .member(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsNameDisplayOrder, rhsIndex, rhsPeerId, rhsPeer, rhsParticipant, rhsPresence, rhsMemberStatus, rhsEditing, rhsActions, rhsEnabled, rhsSelectable) = rhs { - if lhsTheme !== rhsTheme { - return false - } - if lhsStrings !== rhsStrings { - return false - } - if lhsDateTimeFormat != rhsDateTimeFormat { - return false - } - if lhsNameDisplayOrder != rhsNameDisplayOrder { - return false - } - if lhsIndex != rhsIndex { - return false - } - if lhsMemberStatus != rhsMemberStatus { - return false - } - if lhsPeerId != rhsPeerId { - return false - } - if !lhsPeer.isEqual(rhsPeer) { - return false - } - if lhsParticipant != rhsParticipant { - return false - } - if let lhsPresence = lhsPresence, let rhsPresence = rhsPresence { - if !lhsPresence.isEqual(to: rhsPresence) { - return false - } - } else if (lhsPresence != nil) != (rhsPresence != nil) { - return false - } - if lhsEditing != rhsEditing { - return false - } - if lhsActions != rhsActions { - return false - } - if lhsEnabled != rhsEnabled { - return false - } - if lhsSelectable != rhsSelectable { - return false - } - return true - } else { - return false - } - case let .expand(lhsTheme, lhsText): - if case let .expand(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { - return true - } else { - return false - } - } - } - - var stableId: GroupEntryStableId { - switch self { - case let .member(_, _, _, _, _, peerId, _, _, _, _, _, _, _, _): - return .peer(peerId) - default: - return .index(self.sortIndex) - } - } - - private var sortIndex: Int { - switch self { - case .info: - return 0 - case .setGroupPhoto: - return 1 - case .groupDescriptionSetup: - return 2 - case .about: - return 3 - case .locationHeader: - return 4 - case .location: - return 5 - case .changeLocation: - return 6 - case .link: - return 7 - case .groupTypeSetup: - return 8 - case .linkedChannelSetup: - return 9 - case .preHistory: - return 10 - case .stickerPack: - return 11 - case .notifications: - return 12 - case .sharedMedia: - return 13 - case .permissions: - return 14 - case .administrators: - return 15 - case .addMember: - return 16 - case let .member(_, _, _, _, index, _, _, _, _, _, _, _, _, _): - return 20 + index - case .expand: - return 200000 + 1 - case .leave: - return 200000 + 2 - } - } - - static func <(lhs: GroupInfoEntry, rhs: GroupInfoEntry) -> Bool { - return lhs.sortIndex < rhs.sortIndex - } - - func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem { - let arguments = arguments as! GroupInfoArguments - switch self { - case let .info(theme, strings, dateTimeFormat, peer, cachedData, state, updatingAvatar): - return ItemListAvatarAndNameInfoItem(accountContext: arguments.context, presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .generic, peer: peer, presence: nil, cachedData: cachedData, state: state, sectionId: self.section, style: .blocks(withTopInset: false, withExtendedBottomInset: false), editingNameUpdated: { editingName in - arguments.updateEditingName(editingName) - }, avatarTapped: { - arguments.tapAvatarAction() - }, context: arguments.avatarAndNameInfoContext, updatingImage: updatingAvatar) - case let .setGroupPhoto(theme, text): - return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: { - arguments.changeProfilePhoto() - }) - case let .about(theme, text): - return ItemListMultilineTextItem(presentationData: presentationData, text: foldMultipleLineBreaks(text), enabledEntityTypes: [.allUrl, .mention, .hashtag], sectionId: self.section, style: .blocks, longTapAction: { - arguments.displayAboutContextMenu(text) - }, linkItemAction: { action, itemLink in - arguments.aboutLinkAction(action, itemLink) - }, tag: GroupInfoEntryTag.about) - case let .locationHeader(theme, text): - return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) - case let .location(theme, location): - let imageSignal = chatMapSnapshotImage(account: arguments.context.account, resource: MapSnapshotMediaResource(latitude: location.latitude, longitude: location.longitude, width: 90, height: 90)) - return ItemListAddressItem(theme: theme, label: "", text: location.address.replacingOccurrences(of: ", ", with: "\n"), imageSignal: imageSignal, selected: nil, sectionId: self.section, style: .blocks, action: { - arguments.openLocation(location) - }, longTapAction: { - arguments.displayLocationContextMenu(location.address.replacingOccurrences(of: "\n", with: ", ")) - }, tag: GroupInfoEntryTag.location) - case let .changeLocation(theme, text): - return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: { - arguments.changeLocation() - }, clearHighlightAutomatically: false) - case let .link(theme, url): - return ItemListActionItem(presentationData: presentationData, title: url, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: { - arguments.displayUsernameShareMenu(url) - }, longTapAction: { - arguments.displayUsernameContextMenu(url) - }, tag: GroupInfoEntryTag.link) - case let .notifications(theme, title, text): - return ItemListDisclosureItem(presentationData: presentationData, title: title, label: text, sectionId: self.section, style: .blocks, action: { - arguments.changeNotificationMuteSettings() - }) - case let .stickerPack(theme, title, value): - return ItemListDisclosureItem(presentationData: presentationData, title: title, label: value, sectionId: self.section, style: .blocks, action: { - arguments.openStickerPackSetup() - }) - case let .preHistory(theme, title, value): - return ItemListDisclosureItem(presentationData: presentationData, title: title, label: value, sectionId: self.section, style: .blocks, action: { - arguments.openPreHistory() - }) - case let .sharedMedia(theme, title): - return ItemListDisclosureItem(presentationData: presentationData, title: title, label: "", sectionId: self.section, style: .blocks, action: { - arguments.openSharedMedia() - }) - case let .addMember(theme, title, editing): - return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.addPersonIcon(theme), title: title, sectionId: self.section, editing: editing, action: { - arguments.addMember() - }) - case let .groupTypeSetup(theme, title, text): - return ItemListDisclosureItem(presentationData: presentationData, title: title, label: text, sectionId: self.section, style: .blocks, action: { - arguments.openGroupTypeSetup() - }) - case let .linkedChannelSetup(theme, title, text): - return ItemListDisclosureItem(presentationData: presentationData, title: title, label: text, sectionId: self.section, style: .blocks, action: { - arguments.openLinkedChannelSetup() - }) - case let .groupDescriptionSetup(theme, placeholder, text): - return ItemListMultilineInputItem(presentationData: presentationData, text: text, placeholder: placeholder, maxLength: ItemListMultilineInputItemTextLimit(value: 255, display: true), sectionId: self.section, style: .blocks, textUpdated: { updatedText in - arguments.updateEditingDescriptionText(updatedText) - }) - case let .permissions(theme, title, text): - return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesChat.groupInfoPermissionsIcon(theme), title: title, label: text, sectionId: self.section, style: .blocks, action: { - arguments.openPermissions() - }) - case let .administrators(theme, title, text): - return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesChat.groupInfoAdminsIcon(theme), title: title, label: text, sectionId: self.section, style: .blocks, action: { - arguments.openAdministrators() - }) - case let .member(theme, strings, dateTimeFormat, nameDisplayOrder, _, _, peer, participant, presence, memberStatus, editing, actions, enabled, selectable): - let label: String? - switch memberStatus { - case let .owner(rank): - label = rank?.trimmingEmojis ?? strings.GroupInfo_LabelOwner - case let .admin(rank): - label = rank?.trimmingEmojis ?? strings.GroupInfo_LabelAdmin - case .member: - label = nil - } - var options: [ItemListPeerItemRevealOption] = [] - for action in actions { - options.append(ItemListPeerItemRevealOption(type: action.type, title: action.title, action: { - switch action.action { - case .promote: - if let participant = participant { - arguments.promotePeer(participant) - } - case .restrict: - if let participant = participant { - arguments.restrictPeer(participant) - } - case .remove: - arguments.removePeer(peer.id) - } - })) - } - return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, context: arguments.context, peer: peer, presence: presence, text: .presence, label: label == nil ? .none : .text(label!, .standard), editing: editing, revealOptions: ItemListPeerItemRevealOptions(options: options), switchValue: nil, enabled: enabled, selectable: selectable, sectionId: self.section, action: { - if let infoController = arguments.context.sharedContext.makePeerInfoController(context: arguments.context, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false), selectable { - arguments.pushController(infoController) - } - }, setPeerIdWithRevealedOptions: { peerId, fromPeerId in - arguments.setPeerIdWithRevealedOptions(peerId, fromPeerId) - }, removePeer: { peerId in - arguments.removePeer(peerId) - }) - case let .expand(theme, title): - return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.downArrowImage(theme), title: title, sectionId: self.section, editing: false, action: { - arguments.expandParticipants() - }) - case let .leave(theme, title): - return ItemListActionItem(presentationData: presentationData, title: title, kind: .destructive, alignment: .center, sectionId: self.section, style: .blocks, action: { - arguments.leave() - }) - default: - preconditionFailure() - } - } -} - -private struct TemporaryParticipant: Equatable { - let peer: Peer - let presence: PeerPresence? - let timestamp: Int32 - - static func ==(lhs: TemporaryParticipant, rhs: TemporaryParticipant) -> Bool { - if !lhs.peer.isEqual(rhs.peer) { - return false - } - if let lhsPresence = lhs.presence, let rhsPresence = rhs.presence { - if !lhsPresence.isEqual(to: rhsPresence) { - return false - } - } else if (lhs.presence != nil) != (rhs.presence != nil) { - return false - } - return true - } -} - -private struct GroupInfoState: Equatable { - let updatingAvatar: ItemListAvatarAndNameInfoItemUpdatingAvatar? - let editingState: GroupInfoEditingState? - let updatingName: ItemListAvatarAndNameInfoItemName? - let peerIdWithRevealedOptions: PeerId? - let expandedParticipants: Bool - - let temporaryParticipants: [TemporaryParticipant] - let successfullyAddedParticipantIds: Set - let removingParticipantIds: Set - - let savingData: Bool - - let searchingMembers: Bool - - static func ==(lhs: GroupInfoState, rhs: GroupInfoState) -> Bool { - if lhs.updatingAvatar != rhs.updatingAvatar { - return false - } - if lhs.editingState != rhs.editingState { - return false - } - if lhs.updatingName != rhs.updatingName { - return false - } - if lhs.peerIdWithRevealedOptions != rhs.peerIdWithRevealedOptions { - return false - } - if lhs.expandedParticipants != rhs.expandedParticipants { - return false - } - if lhs.temporaryParticipants != rhs.temporaryParticipants { - return false - } - if lhs.successfullyAddedParticipantIds != rhs.successfullyAddedParticipantIds { - return false - } - if lhs.removingParticipantIds != rhs.removingParticipantIds { - return false - } - if lhs.savingData != rhs.savingData { - return false - } - if lhs.searchingMembers != rhs.searchingMembers { - return false - } - return true - } - - func withUpdatedUpdatingAvatar(_ updatingAvatar: ItemListAvatarAndNameInfoItemUpdatingAvatar?) -> GroupInfoState { - return GroupInfoState(updatingAvatar: updatingAvatar, editingState: self.editingState, updatingName: self.updatingName, peerIdWithRevealedOptions: self.peerIdWithRevealedOptions, expandedParticipants: self.expandedParticipants, temporaryParticipants: self.temporaryParticipants, successfullyAddedParticipantIds: self.successfullyAddedParticipantIds, removingParticipantIds: self.removingParticipantIds, savingData: self.savingData, searchingMembers: self.searchingMembers) - } - - func withUpdatedEditingState(_ editingState: GroupInfoEditingState?) -> GroupInfoState { - return GroupInfoState(updatingAvatar: self.updatingAvatar, editingState: editingState, updatingName: self.updatingName, peerIdWithRevealedOptions: self.peerIdWithRevealedOptions, expandedParticipants: self.expandedParticipants, temporaryParticipants: self.temporaryParticipants, successfullyAddedParticipantIds: self.successfullyAddedParticipantIds, removingParticipantIds: self.removingParticipantIds, savingData: self.savingData, searchingMembers: self.searchingMembers) - } - - func withUpdatedUpdatingName(_ updatingName: ItemListAvatarAndNameInfoItemName?) -> GroupInfoState { - return GroupInfoState(updatingAvatar: self.updatingAvatar, editingState: self.editingState, updatingName: updatingName, peerIdWithRevealedOptions: self.peerIdWithRevealedOptions, expandedParticipants: self.expandedParticipants, temporaryParticipants: self.temporaryParticipants, successfullyAddedParticipantIds: self.successfullyAddedParticipantIds, removingParticipantIds: self.removingParticipantIds, savingData: self.savingData, searchingMembers: self.searchingMembers) - } - - func withUpdatedPeerIdWithRevealedOptions(_ peerIdWithRevealedOptions: PeerId?) -> GroupInfoState { - return GroupInfoState(updatingAvatar: self.updatingAvatar, editingState: self.editingState, updatingName: self.updatingName, peerIdWithRevealedOptions: peerIdWithRevealedOptions, expandedParticipants: self.expandedParticipants, temporaryParticipants: self.temporaryParticipants, successfullyAddedParticipantIds: self.successfullyAddedParticipantIds, removingParticipantIds: self.removingParticipantIds, savingData: self.savingData, searchingMembers: self.searchingMembers) - } - - func withUpdatedExpandedParticipants(_ expandedParticipants: Bool) -> GroupInfoState { - return GroupInfoState(updatingAvatar: self.updatingAvatar, editingState: self.editingState, updatingName: self.updatingName, peerIdWithRevealedOptions: self.peerIdWithRevealedOptions, expandedParticipants: expandedParticipants, temporaryParticipants: self.temporaryParticipants, successfullyAddedParticipantIds: self.successfullyAddedParticipantIds, removingParticipantIds: self.removingParticipantIds, savingData: self.savingData, searchingMembers: self.searchingMembers) - } - - func withUpdatedTemporaryParticipants(_ temporaryParticipants: [TemporaryParticipant]) -> GroupInfoState { - return GroupInfoState(updatingAvatar: self.updatingAvatar, editingState: self.editingState, updatingName: self.updatingName, peerIdWithRevealedOptions: self.peerIdWithRevealedOptions, expandedParticipants: self.expandedParticipants, temporaryParticipants: temporaryParticipants, successfullyAddedParticipantIds: self.successfullyAddedParticipantIds, removingParticipantIds: self.removingParticipantIds, savingData: self.savingData, searchingMembers: self.searchingMembers) - } - - func withUpdatedSuccessfullyAddedParticipantIds(_ successfullyAddedParticipantIds: Set) -> GroupInfoState { - return GroupInfoState(updatingAvatar: self.updatingAvatar, editingState: self.editingState, updatingName: self.updatingName, peerIdWithRevealedOptions: self.peerIdWithRevealedOptions, expandedParticipants: self.expandedParticipants, temporaryParticipants: self.temporaryParticipants, successfullyAddedParticipantIds: successfullyAddedParticipantIds, removingParticipantIds: self.removingParticipantIds, savingData: self.savingData, searchingMembers: self.searchingMembers) - } - - func withUpdatedRemovingParticipantIds(_ removingParticipantIds: Set) -> GroupInfoState { - return GroupInfoState(updatingAvatar: self.updatingAvatar, editingState: self.editingState, updatingName: self.updatingName, peerIdWithRevealedOptions: self.peerIdWithRevealedOptions, expandedParticipants: self.expandedParticipants, temporaryParticipants: self.temporaryParticipants, successfullyAddedParticipantIds: self.successfullyAddedParticipantIds, removingParticipantIds: removingParticipantIds, savingData: self.savingData, searchingMembers: self.searchingMembers) - } - - func withUpdatedSavingData(_ savingData: Bool) -> GroupInfoState { - return GroupInfoState(updatingAvatar: self.updatingAvatar, editingState: self.editingState, updatingName: self.updatingName, peerIdWithRevealedOptions: self.peerIdWithRevealedOptions, expandedParticipants: self.expandedParticipants, temporaryParticipants: self.temporaryParticipants, successfullyAddedParticipantIds: self.successfullyAddedParticipantIds, removingParticipantIds: self.removingParticipantIds, savingData: savingData, searchingMembers: self.searchingMembers) - } - - func withUpdatedSearchingMembers(_ searchingMembers: Bool) -> GroupInfoState { - return GroupInfoState(updatingAvatar: self.updatingAvatar, editingState: self.editingState, updatingName: self.updatingName, peerIdWithRevealedOptions: self.peerIdWithRevealedOptions, expandedParticipants: self.expandedParticipants, temporaryParticipants: self.temporaryParticipants, successfullyAddedParticipantIds: self.successfullyAddedParticipantIds, removingParticipantIds: self.removingParticipantIds, savingData: self.savingData, searchingMembers: searchingMembers) - } -} - -private struct GroupInfoEditingState: Equatable { - let editingName: ItemListAvatarAndNameInfoItemName? - let editingDescriptionText: String - - func withUpdatedEditingDescriptionText(_ editingDescriptionText: String) -> GroupInfoEditingState { - return GroupInfoEditingState(editingName: self.editingName, editingDescriptionText: editingDescriptionText) - } - - static func ==(lhs: GroupInfoEditingState, rhs: GroupInfoEditingState) -> Bool { - if lhs.editingName != rhs.editingName { - return false - } - if lhs.editingDescriptionText != rhs.editingDescriptionText { - return false - } - return true - } -} - -private func canRemoveParticipant(account: Account, isAdmin: Bool, participantId: PeerId, invitedBy: PeerId?) -> Bool { - if participantId == account.peerId { - return false - } - - if account.peerId == invitedBy { - return true - } - - return isAdmin -} - -private func canRemoveParticipant(account: Account, channel: TelegramChannel, participant: ChannelParticipant) -> Bool { - if participant.peerId == account.peerId { - return false - } - - if channel.flags.contains(.isCreator) { - return true - } - - switch participant { - case .creator: - return false - case let .member(_, _, adminInfo, _, _): - if channel.hasPermission(.banMembers) { - if let adminInfo = adminInfo { - return adminInfo.promotedBy == account.peerId - } else { - return false - } - } else { - return false - } - } -} - - -private func groupInfoEntries(account: Account, presentationData: PresentationData, view: PeerView, channelMembers: [RenderedChannelParticipant], globalNotificationSettings: GlobalNotificationSettings, state: GroupInfoState) -> [GroupInfoEntry] { - var entries: [GroupInfoEntry] = [] - - var canEditGroupInfo = false - var canEditMembers = false - var canAddMembers = false - var isPublic = false - var isCreator = false - if let group = view.peers[view.peerId] as? TelegramGroup { - if case .creator = group.role { - isCreator = true - } - switch group.role { - case .admin, .creator: - canEditGroupInfo = true - canEditMembers = true - canAddMembers = true - case .member: - break - } - if !group.hasBannedPermission(.banChangeInfo) { - canEditGroupInfo = true - } - if !group.hasBannedPermission(.banAddMembers) { - canAddMembers = true - } - } else if let channel = view.peers[view.peerId] as? TelegramChannel { - isPublic = channel.username != nil - if !isPublic, let cachedChannelData = view.cachedData as? CachedChannelData, cachedChannelData.peerGeoLocation != nil { - isPublic = true - } - - isCreator = channel.flags.contains(.isCreator) - if channel.hasPermission(.changeInfo) { - canEditGroupInfo = true - } - if channel.hasPermission(.banMembers) { - canEditMembers = true - } - if channel.hasPermission(.inviteMembers) { - canAddMembers = true - } - } - - if let peer = peerViewMainPeer(view) { - let infoState = ItemListAvatarAndNameInfoItemState(editingName: canEditGroupInfo ? state.editingState?.editingName : nil, updatingName: state.updatingName) - entries.append(.info(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer: peer, cachedData: view.cachedData, state: infoState, updatingAvatar: state.updatingAvatar)) - } - - let peerNotificationSettings: TelegramPeerNotificationSettings = (view.notificationSettings as? TelegramPeerNotificationSettings) ?? TelegramPeerNotificationSettings.defaultSettings - let notificationsText: String - - if case let .muted(until) = peerNotificationSettings.muteState, until >= Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970) { - if until < Int32.max - 1 { - notificationsText = stringForRemainingMuteInterval(strings: presentationData.strings, muteInterval: until) - } else { - notificationsText = presentationData.strings.UserInfo_NotificationsDisabled - } - } else if case .default = peerNotificationSettings.messageSound { - notificationsText = presentationData.strings.UserInfo_NotificationsEnabled - } else { - notificationsText = localizedPeerNotificationSoundString(strings: presentationData.strings, sound: peerNotificationSettings.messageSound, default: globalNotificationSettings.effective.channels.sound) - } - - if let editingState = state.editingState { - if canEditGroupInfo { - entries.append(GroupInfoEntry.setGroupPhoto(presentationData.theme, presentationData.strings.GroupInfo_SetGroupPhoto)) - - entries.append(GroupInfoEntry.groupDescriptionSetup(presentationData.theme, presentationData.strings.Channel_About_Placeholder, editingState.editingDescriptionText)) - } - - if let group = view.peers[view.peerId] as? TelegramGroup, let cachedGroupData = view.cachedData as? CachedGroupData { - if case .creator = group.role { - if cachedGroupData.flags.contains(.canChangeUsername) { - entries.append(GroupInfoEntry.groupTypeSetup(presentationData.theme, presentationData.strings.GroupInfo_GroupType, presentationData.strings.Channel_Setup_TypePrivate)) - } - entries.append(GroupInfoEntry.preHistory(presentationData.theme, presentationData.strings.GroupInfo_GroupHistory, presentationData.strings.GroupInfo_GroupHistoryHidden)) - - var activePermissionCount: Int? - if let defaultBannedRights = group.defaultBannedRights { - var count = 0 - for (right, _) in allGroupPermissionList { - if !defaultBannedRights.flags.contains(right) { - count += 1 - } - } - activePermissionCount = count - } - entries.append(GroupInfoEntry.permissions(presentationData.theme, presentationData.strings.GroupInfo_Permissions, activePermissionCount.flatMap({ "\($0)/\(allGroupPermissionList.count)" }) ?? "")) - entries.append(.administrators(presentationData.theme, presentationData.strings.GroupInfo_Administrators, "")) - } - } else if let channel = view.peers[view.peerId] as? TelegramChannel, let cachedChannelData = view.cachedData as? CachedChannelData { - if isCreator, let location = cachedChannelData.peerGeoLocation { - entries.append(.locationHeader(presentationData.theme, presentationData.strings.GroupInfo_Location.uppercased())) - entries.append(.location(presentationData.theme, location)) - if cachedChannelData.flags.contains(.canChangePeerGeoLocation) { - entries.append(.changeLocation(presentationData.theme, presentationData.strings.Group_Location_ChangeLocation)) - } - } - - if isCreator || (channel.adminRights != nil && channel.hasPermission(.pinMessages)) { - if cachedChannelData.peerGeoLocation != nil { - if isCreator { - entries.append(GroupInfoEntry.groupTypeSetup(presentationData.theme, presentationData.strings.GroupInfo_PublicLink, channel.addressName ?? presentationData.strings.GroupInfo_PublicLinkAdd)) - } - } else { - if cachedChannelData.flags.contains(.canChangeUsername) { - entries.append(GroupInfoEntry.groupTypeSetup(presentationData.theme, presentationData.strings.GroupInfo_GroupType, isPublic ? presentationData.strings.Channel_Setup_TypePublic : presentationData.strings.Channel_Setup_TypePrivate)) - if case let .known(maybeLinkedDiscussionPeerId) = cachedChannelData.linkedDiscussionPeerId, let linkedDiscussionPeerId = maybeLinkedDiscussionPeerId, let peer = view.peers[linkedDiscussionPeerId] { - let peerTitle: String - if let addressName = peer.addressName, !addressName.isEmpty { - peerTitle = "@\(addressName)" - } else { - peerTitle = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) - } - entries.append(GroupInfoEntry.linkedChannelSetup(presentationData.theme, presentationData.strings.Group_LinkedChannel, peerTitle)) - } - } - if !isPublic && cachedChannelData.linkedDiscussionPeerId == nil { - entries.append(GroupInfoEntry.preHistory(presentationData.theme, presentationData.strings.GroupInfo_GroupHistory, cachedChannelData.flags.contains(.preHistoryEnabled) ? presentationData.strings.GroupInfo_GroupHistoryVisible : presentationData.strings.GroupInfo_GroupHistoryHidden)) - } - } - } - - if cachedChannelData.flags.contains(.canSetStickerSet) && canEditGroupInfo { - entries.append(GroupInfoEntry.stickerPack(presentationData.theme, presentationData.strings.Stickers_GroupStickers, cachedChannelData.stickerPack?.title ?? presentationData.strings.GroupInfo_SharedMediaNone)) - } - - var canViewAdminsAndBanned = false - if let channel = view.peers[view.peerId] as? TelegramChannel { - if let adminRights = channel.adminRights, !adminRights.isEmpty { - canViewAdminsAndBanned = true - } else if channel.flags.contains(.isCreator) { - canViewAdminsAndBanned = true - } - } - - if canViewAdminsAndBanned { - var activePermissionCount: Int? - if let defaultBannedRights = channel.defaultBannedRights { - var count = 0 - for (right, _) in allGroupPermissionList { - if !defaultBannedRights.flags.contains(right) { - count += 1 - } - } - activePermissionCount = count - } - - entries.append(GroupInfoEntry.permissions(presentationData.theme, presentationData.strings.GroupInfo_Permissions, activePermissionCount.flatMap({ "\($0)/\(allGroupPermissionList.count)" }) ?? "")) - entries.append(GroupInfoEntry.administrators(presentationData.theme, presentationData.strings.GroupInfo_Administrators, cachedChannelData.participantsSummary.adminCount.flatMap { "\(presentationStringsFormattedNumber($0, presentationData.dateTimeFormat.groupingSeparator))" } ?? "")) - } - } - } else { - if let peer = peerViewMainPeer(view), peer.isScam { - entries.append(.about(presentationData.theme, presentationData.strings.GroupInfo_ScamGroupWarning)) - } - else if let cachedChannelData = view.cachedData as? CachedChannelData { - if let about = cachedChannelData.about, !about.isEmpty { - entries.append(.about(presentationData.theme, about)) - } - if let peer = view.peers[view.peerId] as? TelegramChannel { - if let location = cachedChannelData.peerGeoLocation { - entries.append(.locationHeader(presentationData.theme, presentationData.strings.GroupInfo_Location.uppercased())) - entries.append(.location(presentationData.theme, location)) - } - if let username = peer.username, !username.isEmpty { - entries.append(.link(presentationData.theme, "t.me/" + username)) - } - } - } else if let cachedGroupData = view.cachedData as? CachedGroupData { - if let about = cachedGroupData.about, !about.isEmpty { - entries.append(.about(presentationData.theme, about)) - } - } - - entries.append(GroupInfoEntry.notifications(presentationData.theme, presentationData.strings.GroupInfo_Notifications, notificationsText)) - entries.append(GroupInfoEntry.sharedMedia(presentationData.theme, presentationData.strings.GroupInfo_SharedMedia)) - } - - var canRemoveAnyMember = false - if let cachedGroupData = view.cachedData as? CachedGroupData, let participants = cachedGroupData.participants { - for participant in participants.participants { - if canRemoveParticipant(account: account, isAdmin: canEditMembers, participantId: participant.peerId, invitedBy: participant.invitedBy) { - canRemoveAnyMember = true - break - } - } - } else if let channel = view.peers[view.peerId] as? TelegramChannel { - for participant in channelMembers { - if canRemoveParticipant(account: account, channel: channel, participant: participant.participant) { - canRemoveAnyMember = true - break - } - } - } - - if canAddMembers { - entries.append(GroupInfoEntry.addMember(presentationData.theme, presentationData.strings.GroupInfo_AddParticipant, editing: state.editingState != nil && canRemoveAnyMember)) - } - - if let group = view.peers[view.peerId] as? TelegramGroup, let cachedGroupData = view.cachedData as? CachedGroupData, let participants = cachedGroupData.participants { - var updatedParticipants = participants.participants - let existingParticipantIds = Set(updatedParticipants.map { $0.peerId }) - - var peerPresences: [PeerId: PeerPresence] = view.peerPresences - var peers: [PeerId: Peer] = view.peers - var disabledPeerIds = state.removingParticipantIds - - if !state.temporaryParticipants.isEmpty { - for participant in state.temporaryParticipants { - if !existingParticipantIds.contains(participant.peer.id) { - updatedParticipants.append(.member(id: participant.peer.id, invitedBy: account.peerId, invitedAt: participant.timestamp)) - if let presence = participant.presence, peerPresences[participant.peer.id] == nil { - peerPresences[participant.peer.id] = presence - } - if peers[participant.peer.id] == nil { - peers[participant.peer.id] = participant.peer - } - disabledPeerIds.insert(participant.peer.id) - } - } - } - - let sortedParticipants = updatedParticipants.sorted(by: { lhs, rhs in - let lhsPresence = peerPresences[lhs.peerId] as? TelegramUserPresence - let rhsPresence = peerPresences[rhs.peerId] as? TelegramUserPresence - if let lhsPresence = lhsPresence, let rhsPresence = rhsPresence { - if lhsPresence.status < rhsPresence.status { - return false - } else if lhsPresence.status > rhsPresence.status { - return true - } - } else if let _ = lhsPresence { - return true - } else if let _ = rhsPresence { - return false - } - - switch lhs { - case .creator: - return false - case let .admin(lhsId, _, lhsInvitedAt): - switch rhs { - case .creator: - return true - case let .admin(rhsId, _, rhsInvitedAt): - if lhsInvitedAt == rhsInvitedAt { - return lhsId.id < rhsId.id - } - return lhsInvitedAt > rhsInvitedAt - case let .member(rhsId, _, rhsInvitedAt): - if lhsInvitedAt == rhsInvitedAt { - return lhsId.id < rhsId.id - } - return lhsInvitedAt > rhsInvitedAt - } - case let .member(lhsId, _, lhsInvitedAt): - switch rhs { - case .creator: - return true - case let .admin(rhsId, _, rhsInvitedAt): - if lhsInvitedAt == rhsInvitedAt { - return lhsId.id < rhsId.id - } - return lhsInvitedAt > rhsInvitedAt - case let .member(rhsId, _, rhsInvitedAt): - if lhsInvitedAt == rhsInvitedAt { - return lhsId.id < rhsId.id - } - return lhsInvitedAt > rhsInvitedAt - } - } - }) - - for i in 0 ..< sortedParticipants.count { - if let peer = peers[sortedParticipants[i].peerId] { - let memberStatus: GroupInfoMemberStatus - let participant: ChannelParticipant - switch sortedParticipants[i] { - case .creator: - participant = .creator(id: sortedParticipants[i].peerId, adminInfo: nil, rank: nil) - memberStatus = .owner(rank: nil) - case .admin: - participant = .member(id: sortedParticipants[i].peerId, invitedAt: 0, adminInfo: ChannelParticipantAdminInfo(rights: TelegramChatAdminRights(flags: .groupSpecific), promotedBy: account.peerId, canBeEditedByAccountPeer: true), banInfo: nil, rank: nil) - memberStatus = .admin(rank: nil) - case .member: - participant = .member(id: sortedParticipants[i].peerId, invitedAt: 0, adminInfo: nil, banInfo: nil, rank: nil) - memberStatus = .member - } - - var canPromote: Bool - var canRestrict: Bool - if sortedParticipants[i].peerId == account.peerId { - canPromote = false - canRestrict = false - } else { - switch group.role { - case .creator: - canPromote = true - canRestrict = true - case .member: - canPromote = false - switch sortedParticipants[i] { - case .creator, .admin: - canPromote = false - canRestrict = false - case let .member(member): - if member.invitedBy == account.peerId { - canRestrict = true - } else { - canRestrict = false - } - } - case .admin: - switch sortedParticipants[i] { - case .creator, .admin: - canPromote = false - canRestrict = false - case .member: - canPromote = false - canRestrict = true - } - } - } - - var peerActions: [ParticipantRevealAction] = [] - if canPromote { - peerActions.append(ParticipantRevealAction(type: .neutral, title: presentationData.strings.GroupInfo_ActionPromote, action: .promote)) - } - if canRestrict { - peerActions.append(ParticipantRevealAction(type: .warning, title: presentationData.strings.GroupInfo_ActionRestrict, action: .restrict)) - peerActions.append(ParticipantRevealAction(type: .destructive, title: presentationData.strings.Common_Delete, action: .remove)) - } - - entries.append(GroupInfoEntry.member(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, index: i, peerId: peer.id, peer: peer, participant: RenderedChannelParticipant(participant: participant, peer: peer), presence: peerPresences[peer.id], memberStatus: memberStatus, editing: ItemListPeerItemEditing(editable: canRemoveParticipant(account: account, isAdmin: canEditMembers, participantId: peer.id, invitedBy: sortedParticipants[i].invitedBy), editing: state.editingState != nil && canRemoveAnyMember, revealed: state.peerIdWithRevealedOptions == peer.id), revealActions: peerActions, enabled: !disabledPeerIds.contains(peer.id), selectable: peer.id != account.peerId)) - } - } - } else if let channel = view.peers[view.peerId] as? TelegramChannel, let cachedChannelData = view.cachedData as? CachedChannelData, let memberCount = cachedChannelData.participantsSummary.memberCount { - var updatedParticipants = channelMembers - let existingParticipantIds = Set(updatedParticipants.map { $0.peer.id }) - - var peerPresences: [PeerId: PeerPresence] = view.peerPresences - var peers: [PeerId: Peer] = view.peers - - if !state.temporaryParticipants.isEmpty { - for participant in state.temporaryParticipants { - if !existingParticipantIds.contains(participant.peer.id) { - updatedParticipants.append(RenderedChannelParticipant(participant: ChannelParticipant.member(id: participant.peer.id, invitedAt: participant.timestamp, adminInfo: nil, banInfo: nil, rank: nil), peer: participant.peer)) - if let presence = participant.presence, peerPresences[participant.peer.id] == nil { - peerPresences[participant.peer.id] = presence - } - if peers[participant.peer.id] == nil { - peers[participant.peer.id] = participant.peer - } - //disabledPeerIds.insert(participant.peer.id) - } - } - } - - let sortedParticipants: [RenderedChannelParticipant] - if memberCount < 200 { - sortedParticipants = updatedParticipants.sorted(by: { lhs, rhs in - let lhsPresence = lhs.presences[lhs.peer.id] as? TelegramUserPresence - let rhsPresence = rhs.presences[rhs.peer.id] as? TelegramUserPresence - if let lhsPresence = lhsPresence, let rhsPresence = rhsPresence { - if lhsPresence.status < rhsPresence.status { - return false - } else if lhsPresence.status > rhsPresence.status { - return true - } - } else if let _ = lhsPresence { - return true - } else if let _ = rhsPresence { - return false - } - - switch lhs.participant { - case .creator: - return false - case let .member(lhsId, lhsInvitedAt, _, _, _): - switch rhs.participant { - case .creator: - return true - case let .member(rhsId, rhsInvitedAt, _, _, _): - if lhsInvitedAt == rhsInvitedAt { - return lhsId.id < rhsId.id - } - return lhsInvitedAt > rhsInvitedAt - } - } - }) - } else { - sortedParticipants = updatedParticipants - } - - var expanded = state.expandedParticipants - let participants: [RenderedChannelParticipant] - if expanded { - participants = sortedParticipants - } else { - if sortedParticipants.count > maxParticipantsDisplayedCollapseLimit { - participants = Array(sortedParticipants.prefix(Int(maxParticipantsDisplayedLimit))) - } else { - participants = sortedParticipants - expanded = true - } - } - - for i in 0 ..< participants.count { - let participant = participants[i] - let memberStatus: GroupInfoMemberStatus - switch participant.participant { - case let .creator(_, _, rank): - memberStatus = .owner(rank: rank) - case let .member(_, _, adminInfo, _, rank): - if adminInfo != nil { - memberStatus = .admin(rank: rank) - } else { - memberStatus = .member - } - } - - var canPromote: Bool - var canRestrict: Bool - if participant.peer.id == account.peerId { - canPromote = false - canRestrict = false - } else { - switch participant.participant { - case .creator: - canPromote = false - canRestrict = false - case let .member(_, _, adminRights, bannedRights, _): - if channel.hasPermission(.addAdmins) { - canPromote = true - } else { - canPromote = false - } - if channel.hasPermission(.banMembers) { - canRestrict = true - } else { - canRestrict = false - } - if canPromote { - if let bannedRights = bannedRights { - if bannedRights.restrictedBy != account.peerId && !channel.flags.contains(.isCreator) { - canPromote = false - } - } - } - if canRestrict { - if let adminRights = adminRights { - if adminRights.promotedBy != account.peerId && !channel.flags.contains(.isCreator) { - canRestrict = false - } - } - } - } - } - - var peerActions: [ParticipantRevealAction] = [] - if canPromote { - peerActions.append(ParticipantRevealAction(type: .neutral, title: presentationData.strings.GroupInfo_ActionPromote, action: .promote)) - } - if canRestrict { - peerActions.append(ParticipantRevealAction(type: .warning, title: presentationData.strings.GroupInfo_ActionRestrict, action: .restrict)) - peerActions.append(ParticipantRevealAction(type: .destructive, title: presentationData.strings.Common_Delete, action: .remove)) - } - - entries.append(GroupInfoEntry.member(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, index: i, peerId: participant.peer.id, peer: participant.peer, participant: participant, presence: participant.presences[participant.peer.id], memberStatus: memberStatus, editing: ItemListPeerItemEditing(editable: !peerActions.isEmpty, editing: state.editingState != nil && canRemoveAnyMember, revealed: state.peerIdWithRevealedOptions == participant.peer.id), revealActions: peerActions, enabled: true, selectable: participant.peer.id != account.peerId)) - } - - if !expanded { - entries.append(GroupInfoEntry.expand(presentationData.theme, presentationData.strings.GroupInfo_ShowMoreMembers(Int32(memberCount - maxParticipantsDisplayedLimit)))) - } - } - - if let group = view.peers[view.peerId] as? TelegramGroup { - if case .Member = group.membership { - entries.append(.leave(presentationData.theme, presentationData.strings.Group_LeaveGroup)) - } - } else if let channel = view.peers[view.peerId] as? TelegramChannel { - if case .member = channel.participationStatus { - if channel.flags.contains(.isCreator) { - if let cachedChannelData = view.cachedData as? CachedChannelData, let memberCount = cachedChannelData.participantsSummary.memberCount, memberCount <= 200 { - if state.editingState != nil { - entries.append(.leave(presentationData.theme, presentationData.strings.ChannelInfo_DeleteGroup)) - } else { - entries.append(.leave(presentationData.theme, presentationData.strings.Group_LeaveGroup)) - } - } - } else { - entries.append(.leave(presentationData.theme, presentationData.strings.Group_LeaveGroup)) - } - } - } - - return entries -} - -private func valuesRequiringUpdate(state: GroupInfoState, view: PeerView) -> (title: String?, description: String?) { - if let peer = view.peers[view.peerId] as? TelegramGroup { - var titleValue: String? - var descriptionValue: String? - if let editingState = state.editingState { - if let title = editingState.editingName?.composedTitle, title != peer.title { - titleValue = title - } - if let cachedData = view.cachedData as? CachedGroupData { - if let about = cachedData.about { - if about != editingState.editingDescriptionText { - descriptionValue = editingState.editingDescriptionText - } - } else if !editingState.editingDescriptionText.isEmpty { - descriptionValue = editingState.editingDescriptionText - } - } - } - return (titleValue, descriptionValue) - } else if let peer = view.peers[view.peerId] as? TelegramChannel { - var titleValue: String? - var descriptionValue: String? - if let editingState = state.editingState { - if let title = editingState.editingName?.composedTitle, title != peer.title { - titleValue = title - } - if let cachedData = view.cachedData as? CachedChannelData { - if let about = cachedData.about { - if about != editingState.editingDescriptionText { - descriptionValue = editingState.editingDescriptionText - } - } else if !editingState.editingDescriptionText.isEmpty { - descriptionValue = editingState.editingDescriptionText - } - } - } - return (titleValue, descriptionValue) - } else { - return (nil, nil) - } -} - -public func groupInfoController(context: AccountContext, peerId originalPeerId: PeerId, membersLoaded: @escaping () -> Void = {}) -> ViewController { - let statePromise = ValuePromise(GroupInfoState(updatingAvatar: nil, editingState: nil, updatingName: nil, peerIdWithRevealedOptions: nil, expandedParticipants: false, temporaryParticipants: [], successfullyAddedParticipantIds: Set(), removingParticipantIds: Set(), savingData: false, searchingMembers: false), ignoreRepeated: true) - let stateValue = Atomic(value: GroupInfoState(updatingAvatar: nil, editingState: nil, updatingName: nil, peerIdWithRevealedOptions: nil, expandedParticipants: false, temporaryParticipants: [], successfullyAddedParticipantIds: Set(), removingParticipantIds: Set(), savingData: false, searchingMembers: false)) - let updateState: ((GroupInfoState) -> GroupInfoState) -> Void = { f in - statePromise.set(stateValue.modify { f($0) }) - } - - var pushControllerImpl: ((ViewController) -> Void)? - var presentControllerImpl: ((ViewController, Any?) -> Void)? - var replaceControllerImpl: ((ViewController?, ViewController) -> Void)? - var endEditingImpl: (() -> Void)? - var removePeerChatImpl: ((Peer, Bool) -> Void)? - var errorImpl: (() -> Void)? - var clearHighlightImpl: (() -> Void)? - var dismissInputImpl: (() -> Void)? - - let actionsDisposable = DisposableSet() - - let updatePeerNameDisposable = MetaDisposable() - actionsDisposable.add(updatePeerNameDisposable) - - let updatePeerDescriptionDisposable = MetaDisposable() - actionsDisposable.add(updatePeerDescriptionDisposable) - - let addMemberDisposable = MetaDisposable() - actionsDisposable.add(addMemberDisposable) - let selectAddMemberDisposable = MetaDisposable() - actionsDisposable.add(selectAddMemberDisposable) - - let removeMemberDisposable = MetaDisposable() - actionsDisposable.add(removeMemberDisposable) - - let changeMuteSettingsDisposable = MetaDisposable() - actionsDisposable.add(changeMuteSettingsDisposable) - - let hiddenAvatarRepresentationDisposable = MetaDisposable() - actionsDisposable.add(hiddenAvatarRepresentationDisposable) - - let updateAvatarDisposable = MetaDisposable() - actionsDisposable.add(updateAvatarDisposable) - let currentAvatarMixin = Atomic(value: nil) - - let navigateDisposable = MetaDisposable() - actionsDisposable.add(navigateDisposable) - - let upgradeDisposable = MetaDisposable() - actionsDisposable.add(upgradeDisposable) - - var avatarGalleryTransitionArguments: ((AvatarGalleryEntry) -> GalleryTransitionArguments?)? - let avatarAndNameInfoContext = ItemListAvatarAndNameInfoItemContext() - var updateHiddenAvatarImpl: (() -> Void)? - - var displayCopyContextMenuImpl: ((String, GroupInfoEntryTag) -> Void)? - var aboutLinkActionImpl: ((TextLinkItemActionType, TextLinkItem) -> Void)? - - var upgradedToSupergroupImpl: ((PeerId, @escaping () -> Void) -> Void)? - - let actualPeerId = Promise() - actualPeerId.set(context.account.viewTracker.peerView(originalPeerId) - |> map { peerView -> PeerId in - if let peer = peerView.peers[peerView.peerId] as? TelegramGroup, let migrationReference = peer.migrationReference { - return migrationReference.peerId - } else { - return originalPeerId - } - } - |> distinctUntilChanged) - - let peerView = Promise() - let peerViewSignal = actualPeerId.get() - |> distinctUntilChanged - |> mapToSignal { peerId -> Signal in - return context.account.viewTracker.peerView(peerId, updateData: true) - } - peerView.set(peerViewSignal) - - let arguments = GroupInfoArguments(context: context, avatarAndNameInfoContext: avatarAndNameInfoContext, tapAvatarAction: { - let _ = (peerView.get() - |> take(1) - |> deliverOnMainQueue).start(next: { peerView in - guard let peer = peerView.peers[peerView.peerId] else { - return - } - if peer.profileImageRepresentations.isEmpty { - return - } - - let galleryController = AvatarGalleryController(context: context, peer: peer, replaceRootController: { controller, ready in - - }) - hiddenAvatarRepresentationDisposable.set((galleryController.hiddenMedia |> deliverOnMainQueue).start(next: { entry in - avatarAndNameInfoContext.hiddenAvatarRepresentation = entry?.representations.first?.representation - updateHiddenAvatarImpl?() - })) - presentControllerImpl?(galleryController, AvatarGalleryControllerPresentationArguments(transitionArguments: { entry in - return avatarGalleryTransitionArguments?(entry) - })) - }) - }, changeProfilePhoto: { - endEditingImpl?() - let _ = (peerView.get() - |> take(1) - |> deliverOnMainQueue).start(next: { peerView in - let _ = (context.account.postbox.transaction { transaction -> (Peer?, SearchBotsConfiguration) in - return (transaction.getPeer(peerView.peerId), currentSearchBotsConfiguration(transaction: transaction)) - } |> deliverOnMainQueue).start(next: { peer, searchBotsConfiguration in - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - - let legacyController = LegacyController(presentation: .custom, theme: presentationData.theme) - legacyController.statusBar.statusBarStyle = .Ignore - - let emptyController = LegacyEmptyController(context: legacyController.context)! - let navigationController = makeLegacyNavigationController(rootController: emptyController) - navigationController.setNavigationBarHidden(true, animated: false) - navigationController.navigationBar.transform = CGAffineTransform(translationX: -1000.0, y: 0.0) - - legacyController.bind(controller: navigationController) - - presentControllerImpl?(legacyController, nil) - - var hasPhotos = false - if let peer = peer, !peer.profileImageRepresentations.isEmpty { - hasPhotos = true - } - - let completedImpl: (UIImage) -> Void = { image in - if let data = image.jpegData(compressionQuality: 0.6) { - let resource = LocalFileMediaResource(fileId: arc4random64()) - context.account.postbox.mediaBox.storeResourceData(resource.id, data: data) - let representation = TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 640, height: 640), resource: resource, progressiveSizes: []) - updateState { - $0.withUpdatedUpdatingAvatar(.image(representation, true)) - } - updateAvatarDisposable.set((updatePeerPhoto(postbox: context.account.postbox, network: context.account.network, stateManager: context.account.stateManager, accountPeerId: context.account.peerId, peerId: peerView.peerId, photo: uploadedPeerPhoto(postbox: context.account.postbox, network: context.account.network, resource: resource), mapResourceToAvatarSizes: { resource, representations in - return mapResourceToAvatarSizes(postbox: context.account.postbox, resource: resource, representations: representations) - }) |> deliverOnMainQueue).start(next: { result in - switch result { - case .complete: - updateState { - $0.withUpdatedUpdatingAvatar(nil) - } - case .progress: - break - } - })) - } - } - - let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: hasPhotos, hasViewButton: false, personalPhoto: false, isVideo: false, saveEditedPhotos: false, saveCapturedMedia: false, signup: true)! - let _ = currentAvatarMixin.swap(mixin) - mixin.requestSearchController = { assetsController in - let controller = WebSearchController(context: context, peer: peer, chatLocation: nil, configuration: searchBotsConfiguration, mode: .avatar(initialQuery: peer?.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), completion: { result in - assetsController?.dismiss() - completedImpl(result) - })) - presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) - } - mixin.didFinishWithImage = { image in - if let image = image { - completedImpl(image) - } - } - mixin.didFinishWithDelete = { - let _ = currentAvatarMixin.swap(nil) - updateState { - if let profileImage = peer?.smallProfileImage { - return $0.withUpdatedUpdatingAvatar(.image(profileImage, false)) - } else { - return $0.withUpdatedUpdatingAvatar(.none) - } - } - updateAvatarDisposable.set((updatePeerPhoto(postbox: context.account.postbox, network: context.account.network, stateManager: context.account.stateManager, accountPeerId: context.account.peerId, peerId: peerView.peerId, photo: nil, mapResourceToAvatarSizes: { resource, representations in - return mapResourceToAvatarSizes(postbox: context.account.postbox, resource: resource, representations: representations) - }) |> deliverOnMainQueue).start(next: { result in - switch result { - case .complete: - updateState { - $0.withUpdatedUpdatingAvatar(nil) - } - case .progress: - break - } - })) - } - mixin.didDismiss = { [weak legacyController] in - let _ = currentAvatarMixin.swap(nil) - legacyController?.dismiss() - } - let menuController = mixin.present() - if let menuController = menuController { - menuController.customRemoveFromParentViewController = { [weak legacyController] in - legacyController?.dismiss() - } - } - }) - }) - }, pushController: { controller in - pushControllerImpl?(controller) - }, presentController: { controller, presentationArguments in - presentControllerImpl?(controller, presentationArguments) - }, changeNotificationMuteSettings: { - let _ = (peerView.get() - |> take(1) - |> deliverOnMainQueue).start(next: { peerView in - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - let _ = (context.account.postbox.transaction { transaction -> (TelegramPeerNotificationSettings, GlobalNotificationSettings) in - let peerSettings: TelegramPeerNotificationSettings = (transaction.getPeerNotificationSettings(peerView.peerId) as? TelegramPeerNotificationSettings) ?? TelegramPeerNotificationSettings.defaultSettings - let globalSettings: GlobalNotificationSettings = (transaction.getPreferencesEntry(key: PreferencesKeys.globalNotifications) as? GlobalNotificationSettings) ?? GlobalNotificationSettings.defaultSettings - return (peerSettings, globalSettings) - } - |> deliverOnMainQueue).start(next: { peerSettings, globalSettings in - let soundSettings: NotificationSoundSettings? - if case .default = peerSettings.messageSound { - soundSettings = NotificationSoundSettings(value: nil) - } else { - soundSettings = NotificationSoundSettings(value: peerSettings.messageSound) - } - let controller = notificationMuteSettingsController(presentationData: presentationData, notificationSettings: globalSettings.effective.groupChats, soundSettings: soundSettings, openSoundSettings: { - let controller = notificationSoundSelectionController(context: context, isModal: true, currentSound: peerSettings.messageSound, defaultSound: globalSettings.effective.groupChats.sound, completion: { sound in - let _ = updatePeerNotificationSoundInteractive(account: context.account, peerId: peerView.peerId, sound: sound).start() - }) - presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) - }, updateSettings: { value in - changeMuteSettingsDisposable.set(updatePeerMuteSetting(account: context.account, peerId: peerView.peerId, muteInterval: value).start()) - }) - presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) - }) - }) - }, openPreHistory: { - let _ = (peerView.get() - |> take(1) - |> deliverOnMainQueue).start(next: { peerView in - presentControllerImpl?(groupPreHistorySetupController(context: context, peerId: peerView.peerId, upgradedToSupergroup: { peerId, f in - upgradedToSupergroupImpl?(peerId, f) - }), ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) - }) - }, openSharedMedia: { - let _ = (peerView.get() - |> take(1) - |> deliverOnMainQueue).start(next: { peerView in - if let controller = context.sharedContext.makePeerSharedMediaController(context: context, peerId: peerView.peerId) { - pushControllerImpl?(controller) - } - }) - }, openAdministrators: { - let _ = (peerView.get() - |> take(1) - |> deliverOnMainQueue).start(next: { peerView in - pushControllerImpl?(channelAdminsController(context: context, peerId: peerView.peerId)) - }) - }, openPermissions: { - let _ = (peerView.get() - |> take(1) - |> deliverOnMainQueue).start(next: { peerView in - pushControllerImpl?(channelPermissionsController(context: context, peerId: peerView.peerId)) - }) - }, updateEditingName: { editingName in - updateState { state in - if let editingState = state.editingState { - return state.withUpdatedEditingState(GroupInfoEditingState(editingName: editingName, editingDescriptionText: editingState.editingDescriptionText)) - } else { - return state - } - } - }, updateEditingDescriptionText: { text in - updateState { state in - if let editingState = state.editingState { - return state.withUpdatedEditingState(editingState.withUpdatedEditingDescriptionText(text)) - } - return state - } - }, setPeerIdWithRevealedOptions: { peerId, fromPeerId in - updateState { state in - if (peerId == nil && fromPeerId == state.peerIdWithRevealedOptions) || (peerId != nil && fromPeerId == nil) { - return state.withUpdatedPeerIdWithRevealedOptions(peerId) - } else { - return state - } - } - }, addMember: { - let _ = (peerView.get() - |> take(1) - |> deliverOnMainQueue).start(next: { peerView in - let members: Promise<[PeerId]> = Promise() - if peerView.peerId.namespace == Namespaces.Peer.CloudChannel { - var membersDisposable: Disposable? - let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerView.peerId, updated: { listState in - members.set(.single(listState.list.map {$0.peer.id})) - membersDisposable?.dispose() - }) - membersDisposable = disposable - } else { - members.set(.single([])) - } - - let _ = (combineLatest(queue: .mainQueue(), context.account.postbox.loadedPeerWithId(peerView.peerId) - |> deliverOnMainQueue, members.get() |> take(1) |> deliverOnMainQueue)).start(next: { groupPeer, recentIds in - var confirmationImpl: ((PeerId) -> Signal)? - var options: [ContactListAdditionalOption] = [] - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - var inviteByLinkImpl: (() -> Void)? - - var canCreateInviteLink = false - if let group = groupPeer as? TelegramGroup { - switch group.role { - case .creator, .admin: - canCreateInviteLink = true - default: - break - } - } else if let channel = groupPeer as? TelegramChannel { - if channel.hasPermission(.inviteMembers) { - if channel.flags.contains(.isCreator) || (channel.adminRights != nil && channel.username == nil) { - canCreateInviteLink = true - } - } - } - - if canCreateInviteLink { - options.append(ContactListAdditionalOption(title: presentationData.strings.GroupInfo_InviteByLink, icon: .generic(UIImage(bundleImageName: "Contact List/LinkActionIcon")!), action: { - inviteByLinkImpl?() - })) - } - - let contactsController: ViewController - if peerView.peerId.namespace == Namespaces.Peer.CloudGroup { - contactsController = context.sharedContext.makeContactSelectionController(ContactSelectionControllerParams(context: context, autoDismiss: false, title: { $0.GroupInfo_AddParticipantTitle }, options: options, confirmation: { peer in - if let confirmationImpl = confirmationImpl, case let .peer(peer, _, _) = peer { - return confirmationImpl(peer.id) - } else { - return .single(false) - } - })) - } else { - contactsController = context.sharedContext.makeContactMultiselectionController(ContactMultiselectionControllerParams(context: context, mode: .peerSelection(searchChatList: false, searchGroups: false, searchChannels: false), options: options, filters: [.excludeSelf, .disable(recentIds)])) - } - - confirmationImpl = { [weak contactsController] peerId in - return context.account.postbox.loadedPeerWithId(peerId) - |> deliverOnMainQueue - |> mapToSignal { peer in - let result = ValuePromise() - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - if let contactsController = contactsController { - let alertController = textAlertController(context: context, title: nil, text: presentationData.strings.GroupInfo_AddParticipantConfirmation(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).0, actions: [ - TextAlertAction(type: .genericAction, title: presentationData.strings.Common_No, action: { - result.set(false) - }), - TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Yes, action: { - result.set(true) - }) - ]) - contactsController.present(alertController, in: .window(.root)) - } - - return result.get() - } - } - - let addMember: (ContactListPeer) -> Signal = { memberPeer -> Signal in - if case let .peer(selectedPeer, _, _) = memberPeer { - let memberId = selectedPeer.id - if peerView.peerId.namespace == Namespaces.Peer.CloudChannel { - return context.peerChannelMemberCategoriesContextsManager.addMember(account: context.account, peerId: peerView.peerId, memberId: memberId) - |> map { _ -> Void in - return Void() - } - |> `catch` { _ -> Signal in - return .complete() - } - } - - if let peer = peerView.peers[memberId] { - updateState { state in - var found = false - for participant in state.temporaryParticipants { - if participant.peer.id == memberId { - found = true - break - } - } - if !found { - let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970) - var temporaryParticipants = state.temporaryParticipants - temporaryParticipants.append(TemporaryParticipant(peer: peer, presence: peerView.peerPresences[memberId], timestamp: timestamp)) - return state.withUpdatedTemporaryParticipants(temporaryParticipants) - } else { - return state - } - } - } - - return addGroupMember(account: context.account, peerId: peerView.peerId, memberId: memberId) - |> deliverOnMainQueue - |> afterCompleted { - updateState { state in - var successfullyAddedParticipantIds = state.successfullyAddedParticipantIds - successfullyAddedParticipantIds.insert(memberId) - - return state.withUpdatedSuccessfullyAddedParticipantIds(successfullyAddedParticipantIds) - } - } - |> `catch` { error -> Signal in - switch error { - case .generic: - updateState { state in - var temporaryParticipants = state.temporaryParticipants - for i in 0 ..< temporaryParticipants.count { - if temporaryParticipants[i].peer.id == memberId { - temporaryParticipants.remove(at: i) - break - } - } - var successfullyAddedParticipantIds = state.successfullyAddedParticipantIds - successfullyAddedParticipantIds.remove(memberId) - - return state.withUpdatedTemporaryParticipants(temporaryParticipants).withUpdatedSuccessfullyAddedParticipantIds(successfullyAddedParticipantIds) - } - return .complete() - case .privacy, .notMutualContact: - let _ = (context.account.postbox.loadedPeerWithId(memberId) - |> deliverOnMainQueue).start(next: { peer in - presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(peer.compactDisplayTitle, peer.compactDisplayTitle).0, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {})]), nil) - }) - - updateState { state in - var temporaryParticipants = state.temporaryParticipants - for i in 0 ..< temporaryParticipants.count { - if temporaryParticipants[i].peer.id == memberId { - temporaryParticipants.remove(at: i) - break - } - } - var successfullyAddedParticipantIds = state.successfullyAddedParticipantIds - successfullyAddedParticipantIds.remove(memberId) - - return state.withUpdatedTemporaryParticipants(temporaryParticipants).withUpdatedSuccessfullyAddedParticipantIds(successfullyAddedParticipantIds) - } - return .complete() - case .tooManyChannels: - let _ = (context.account.postbox.loadedPeerWithId(memberId) - |> deliverOnMainQueue).start(next: { peer in - presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Invite_ChannelsTooMuch, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {})]), nil) - }) - - updateState { state in - var temporaryParticipants = state.temporaryParticipants - for i in 0 ..< temporaryParticipants.count { - if temporaryParticipants[i].peer.id == memberId { - temporaryParticipants.remove(at: i) - break - } - } - var successfullyAddedParticipantIds = state.successfullyAddedParticipantIds - successfullyAddedParticipantIds.remove(memberId) - - return state.withUpdatedTemporaryParticipants(temporaryParticipants).withUpdatedSuccessfullyAddedParticipantIds(successfullyAddedParticipantIds) - } - return .complete() - case .groupFull: - let signal = convertGroupToSupergroup(account: context.account, peerId: peerView.peerId) - |> map(Optional.init) - |> `catch` { error -> Signal in - switch error { - case .tooManyChannels: - Queue.mainQueue().async { - pushControllerImpl?(oldChannelsController(context: context, intent: .upgrade)) - } - default: - break - } - return .single(nil) - } - |> mapToSignal { upgradedPeerId -> Signal in - guard let upgradedPeerId = upgradedPeerId else { - return .single(nil) - } - return context.peerChannelMemberCategoriesContextsManager.addMember(account: context.account, peerId: upgradedPeerId, memberId: memberId) - |> `catch` { _ -> Signal in - return .complete() - } - |> mapToSignal { _ -> Signal in - return .complete() - } - |> then(.single(upgradedPeerId)) - } - |> deliverOnMainQueue - |> mapToSignal { upgradedPeerId -> Signal in - if let upgradedPeerId = upgradedPeerId { - upgradedToSupergroupImpl?(upgradedPeerId, {}) - } - return .complete() - } - return signal - } - } - } else { - return .complete() - } - } - - let addMembers: ([ContactListPeerId]) -> Signal = { members -> Signal in - let memberIds = members.compactMap { contact -> PeerId? in - switch contact { - case let .peer(peerId): - return peerId - default: - return nil - } - } - return context.account.postbox.multiplePeersView(memberIds) - |> take(1) - |> deliverOnMainQueue - |> mapError { _ in return .generic} - |> mapToSignal { view -> Signal in - if memberIds.count == 1 { - return context.peerChannelMemberCategoriesContextsManager.addMember(account: context.account, peerId: peerView.peerId, memberId: memberIds[0]) - |> map { _ -> Void in - return Void() - } - } else { - return context.peerChannelMemberCategoriesContextsManager.addMembers(account: context.account, peerId: peerView.peerId, memberIds: memberIds) |> map { _ in - updateState { state in - var state = state - for (memberId, peer) in view.peers { - var found = false - for participant in state.temporaryParticipants { - if participant.peer.id == memberId { - found = true - break - } - } - if !found { - let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970) - var temporaryParticipants = state.temporaryParticipants - temporaryParticipants.append(TemporaryParticipant(peer: peer, presence: view.presences[memberId], timestamp: timestamp)) - state = state.withUpdatedTemporaryParticipants(temporaryParticipants) - } - } - - return state - } - } - } - } - } - - inviteByLinkImpl = { [weak contactsController] in - let mode: ChannelVisibilityControllerMode - if groupPeer.addressName != nil { - mode = .generic - } else { - mode = .privateLink - } - let controller = channelVisibilityController(context: context, peerId: peerView.peerId, mode: mode, upgradedToSupergroup: { updatedPeerId, f in - upgradedToSupergroupImpl?(updatedPeerId, f) - }) - controller.navigationPresentation = .modal - replaceControllerImpl?(contactsController, controller) - } - - presentControllerImpl?(contactsController, ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) - if let contactsController = contactsController as? ContactSelectionController { - selectAddMemberDisposable.set((contactsController.result - |> deliverOnMainQueue).start(next: { [weak contactsController] memberPeer in - guard let (memberPeer, _) = memberPeer else { - return - } - - contactsController?.displayProgress = true - addMemberDisposable.set((addMember(memberPeer) - |> deliverOnMainQueue).start(completed: { - contactsController?.dismiss() - })) - })) - contactsController.dismissed = { - selectAddMemberDisposable.set(nil) - addMemberDisposable.set(nil) - } - } - if let contactsController = contactsController as? ContactMultiselectionController { - selectAddMemberDisposable.set((contactsController.result - |> deliverOnMainQueue).start(next: { [weak contactsController] result in - var peers: [ContactListPeerId] = [] - if case let .result(peerIdsValue, _) = result { - peers = peerIdsValue - } - - contactsController?.displayProgress = true - addMemberDisposable.set((addMembers(peers) - |> deliverOnMainQueue).start(error: { error in - if peers.count == 1, case .restricted = error { - switch peers[0] { - case let .peer(peerId): - let _ = (context.account.postbox.loadedPeerWithId(peerId) - |> deliverOnMainQueue).start(next: { peer in - presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(peer.compactDisplayTitle, peer.compactDisplayTitle).0, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {})]), nil) - }) - default: - break - } - } else if case .tooMuchJoined = error { - presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Invite_ChannelsTooMuch, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {})]), nil) - } - - contactsController?.dismiss() - },completed: { - contactsController?.dismiss() - })) - })) - contactsController.dismissed = { - selectAddMemberDisposable.set(nil) - addMemberDisposable.set(nil) - } - } - }) - }) - }, promotePeer: { participant in - let _ = (peerView.get() - |> take(1) - |> deliverOnMainQueue).start(next: { peerView in - pushControllerImpl?(channelAdminController(context: context, peerId: peerView.peerId, adminId: participant.peer.id, initialParticipant: participant.participant, updated: { _ in - }, upgradedToSupergroup: { upgradedPeerId, f in - upgradedToSupergroupImpl?(upgradedPeerId, f) - }, transferedOwnership: { _ in })) - }) - }, restrictPeer: { participant in - let _ = (peerView.get() - |> take(1) - |> deliverOnMainQueue).start(next: { peerView in - presentControllerImpl?(channelBannedMemberController(context: context, peerId: peerView.peerId, memberId: participant.peer.id, initialParticipant: participant.participant, updated: { _ in - }, upgradedToSupergroup: { upgradedPeerId, f in - upgradedToSupergroupImpl?(upgradedPeerId, f) - }), ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) - }) - }, removePeer: { memberId in - let _ = (peerView.get() - |> take(1) - |> deliverOnMainQueue).start(next: { peerView in - let signal = context.account.postbox.loadedPeerWithId(memberId) - |> deliverOnMainQueue - |> mapToSignal { peer -> Signal in - let result = ValuePromise() - result.set(true) - return result.get() - } - |> mapToSignal { value -> Signal in - if value { - updateState { state in - var temporaryParticipants = state.temporaryParticipants - for i in 0 ..< state.temporaryParticipants.count { - if state.temporaryParticipants[i].peer.id == memberId { - temporaryParticipants.remove(at: i) - break - } - } - var successfullyAddedParticipantIds = state.successfullyAddedParticipantIds - successfullyAddedParticipantIds.remove(memberId) - - var removingParticipantIds = state.removingParticipantIds - removingParticipantIds.insert(memberId) - - return state.withUpdatedTemporaryParticipants(temporaryParticipants).withUpdatedSuccessfullyAddedParticipantIds(successfullyAddedParticipantIds).withUpdatedRemovingParticipantIds(removingParticipantIds) - } - - if peerView.peerId.namespace == Namespaces.Peer.CloudChannel { - return context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: context.account, peerId: peerView.peerId, memberId: memberId, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: Int32.max)) - |> afterDisposed { - Queue.mainQueue().async { - updateState { state in - var removingParticipantIds = state.removingParticipantIds - removingParticipantIds.remove(memberId) - - return state.withUpdatedRemovingParticipantIds(removingParticipantIds) - } - } - } - } - - return removePeerMember(account: context.account, peerId: peerView.peerId, memberId: memberId) - |> deliverOnMainQueue - |> afterDisposed { - updateState { state in - var removingParticipantIds = state.removingParticipantIds - removingParticipantIds.remove(memberId) - - return state.withUpdatedRemovingParticipantIds(removingParticipantIds) - } - } - } else { - return .complete() - } - } - removeMemberDisposable.set(signal.start()) - }) - }, leave: { - let _ = (peerView.get() - |> take(1) - |> deliverOnMainQueue).start(next: { peerView in - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - - if let channel = peerView.peers[peerView.peerId] as? TelegramChannel, channel.flags.contains(.isCreator), stateValue.with({ $0 }).editingState != nil { - let controller = ActionSheetController(presentationData: presentationData) - let dismissAction: () -> Void = { [weak controller] in - controller?.dismissAnimated() - } - - var items: [ActionSheetItem] = [] - items.append(ActionSheetTextItem(title: presentationData.strings.ChannelInfo_DeleteGroupConfirmation)) - items.append(ActionSheetButtonItem(title: presentationData.strings.ChannelInfo_DeleteGroup, color: .destructive, action: { - dismissAction() - removePeerChatImpl?(channel, true) - })) - controller.setItemGroups([ - ActionSheetItemGroup(items: items), - ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })]) - ]) - presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) - } else if let peer = peerView.peers[peerView.peerId] { - let controller = ActionSheetController(presentationData: presentationData) - let dismissAction: () -> Void = { [weak controller] in - controller?.dismissAnimated() - } - - var items: [ActionSheetItem] = [] - if peerView.peerId.namespace == Namespaces.Peer.CloudGroup { - items.append(ActionSheetTextItem(title: presentationData.strings.GroupInfo_DeleteAndExitConfirmation)) - } - items.append(ActionSheetButtonItem(title: presentationData.strings.Group_LeaveGroup, color: .destructive, action: { - dismissAction() - removePeerChatImpl?(peer, false) - })) - controller.setItemGroups([ - ActionSheetItemGroup(items: items), - ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })]) - ]) - presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) - } - }) - }, displayUsernameShareMenu: { text in - let shareController = ShareController(context: context, subject: .url(text)) - presentControllerImpl?(shareController, nil) - }, displayUsernameContextMenu: { text in - displayCopyContextMenuImpl?(text, .link) - }, displayAboutContextMenu: { text in - displayCopyContextMenuImpl?(text, .about) - }, aboutLinkAction: { action, itemLink in - aboutLinkActionImpl?(action, itemLink) - }, openStickerPackSetup: { - let _ = (peerView.get() - |> take(1) - |> deliverOnMainQueue).start(next: { peerView in - let _ = (context.account.postbox.transaction { transaction -> StickerPackCollectionInfo? in - return (transaction.getPeerCachedData(peerId: peerView.peerId) as? CachedChannelData)?.stickerPack - } - |> deliverOnMainQueue).start(next: { stickerPack in - presentControllerImpl?(groupStickerPackSetupController(context: context, peerId: peerView.peerId, currentPackInfo: stickerPack), ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) - }) - }) - }, openGroupTypeSetup: { - let _ = (peerView.get() - |> take(1) - |> deliverOnMainQueue).start(next: { peerView in - presentControllerImpl?(channelVisibilityController(context: context, peerId: peerView.peerId, mode: .generic, upgradedToSupergroup: { updatedPeerId, f in - upgradedToSupergroupImpl?(updatedPeerId, f) - }), ViewControllerPresentationArguments(presentationAnimation: ViewControllerPresentationAnimation.modalSheet)) - }) - }, openLinkedChannelSetup: { - let _ = (peerView.get() - |> take(1) - |> deliverOnMainQueue).start(next: { peerView in - pushControllerImpl?(channelDiscussionGroupSetupController(context: context, peerId: peerView.peerId)) - }) - }, openLocation: { location in - let _ = (peerView.get() - |> take(1) - |> deliverOnMainQueue).start(next: { peerView in - guard let peer = peerView.peers[peerView.peerId] else { - return - } - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - let mapMedia = TelegramMediaMap(latitude: location.latitude, longitude: location.longitude, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: MapVenue(title: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), address: location.address, provider: nil, id: nil, type: nil), liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil) - let controller = legacyLocationController(message: nil, mapMedia: mapMedia, context: context, openPeer: { _ in }, sendLiveLocation: { _, _ in }, stopLiveLocation: {}, openUrl: { url in - context.sharedContext.applicationBindings.openUrl(url) - }) - pushControllerImpl?(controller) - }) - }, changeLocation: { - let _ = (peerView.get() - |> take(1) - |> deliverOnMainQueue).start(next: { peerView in - guard let peer = peerView.peers[peerView.peerId] else { - return - } - - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - let controller = legacyLocationPickerController(context: context, selfPeer: peer, peer: peer, sendLocation: { coordinate, _, address in - let addressSignal: Signal - if let address = address { - addressSignal = .single(address) - } else { - addressSignal = reverseGeocodeLocation(latitude: coordinate.latitude, longitude: coordinate.longitude) - |> map { placemark in - if let placemark = placemark { - return placemark.fullAddress - } else { - return "\(coordinate.latitude), \(coordinate.longitude)" - } - } - } - - let _ = (addressSignal - |> mapToSignal { address -> Signal in - return updateChannelGeoLocation(postbox: context.account.postbox, network: context.account.network, channelId: peer.id, coordinate: (coordinate.latitude, coordinate.longitude), address: address) - } - |> deliverOnMainQueue).start(error: { errror in - presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {})]), nil) - }) - }, sendLiveLocation: { _, _ in }, theme: presentationData.theme, customLocationPicker: true, presentationCompleted: { - clearHighlightImpl?() - }) - pushControllerImpl?(controller) - }) - }, displayLocationContextMenu: { text in - displayCopyContextMenuImpl?(text, .location) - }, expandParticipants: { - updateState { - $0.withUpdatedExpandedParticipants(true) - } - }) - - let loadMoreControl = Atomic<(PeerId, PeerChannelMemberCategoryControl)?>(value: nil) - let channelMembersPromise = Promise<[RenderedChannelParticipant]>() - - let channelMembersDisposable = MetaDisposable() - actionsDisposable.add(channelMembersDisposable) - - var membersLoadedCalled = false - - actionsDisposable.add((actualPeerId.get() - |> distinctUntilChanged - |> deliverOnMainQueue).start(next: { peerId in - if peerId.namespace == Namespaces.Peer.CloudChannel { - let (disposable, control) = context.peerChannelMemberCategoriesContextsManager.recent(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, updated: { state in - channelMembersPromise.set(.single(state.list)) - if case .loading(true) = state.loadingState { - } else if !membersLoadedCalled { - membersLoadedCalled = true - membersLoaded() - } - }) - if let control = control { - let _ = loadMoreControl.swap((peerId, control)) - } else { - let _ = loadMoreControl.swap(nil) - } - channelMembersDisposable.set(disposable) - } else { - let _ = loadMoreControl.swap(nil) - channelMembersPromise.set(.single([])) - channelMembersDisposable.set(nil) - if !membersLoadedCalled { - membersLoadedCalled = true - membersLoaded() - } - } - })) - - let previousStateValue = Atomic(value: nil) - let previousChannelMembers = Atomic<[PeerId]?>(value: nil) - - let searchContext = GroupMembersSearchContext(context: context, peerId: originalPeerId) - - let globalNotificationsKey: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.globalNotifications])) - let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, statePromise.get(), peerView.get(), context.account.postbox.combinedView(keys: [globalNotificationsKey]), channelMembersPromise.get()) - |> map { presentationData, state, view, combinedView, channelMembers -> (ItemListControllerState, (ItemListNodeState, Any)) in - let peer = peerViewMainPeer(view) - - var globalNotificationSettings: GlobalNotificationSettings = GlobalNotificationSettings.defaultSettings - if let preferencesView = combinedView.views[globalNotificationsKey] as? PreferencesView { - if let settings = preferencesView.values[PreferencesKeys.globalNotifications] as? GlobalNotificationSettings { - globalNotificationSettings = settings - } - } - - var canEditGroupInfo = false - if let group = view.peers[view.peerId] as? TelegramGroup { - switch group.role { - case .admin, .creator: - canEditGroupInfo = true - case .member: - break - } - if !group.hasBannedPermission(.banChangeInfo) { - canEditGroupInfo = true - } - } else if let channel = view.peers[view.peerId] as? TelegramChannel { - if channel.hasPermission(.changeInfo) || !(channel.adminRights?.flags ?? []).isEmpty { - canEditGroupInfo = true - } - } - - var rightNavigationButton: ItemListNavigationButton? - var secondaryRightNavigationButton: ItemListNavigationButton? - if let editingState = state.editingState { - var doneEnabled = true - if let editingName = editingState.editingName, editingName.isEmpty { - doneEnabled = false - } - if peer is TelegramChannel { - if (view.cachedData as? CachedChannelData) == nil { - doneEnabled = false - } - } - - if state.savingData { - rightNavigationButton = ItemListNavigationButton(content: .none, style: .activity, enabled: doneEnabled, action: {}) - } else { - rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Done), style: .bold, enabled: doneEnabled, action: { - var updateValues: (title: String?, description: String?) = (nil, nil) - var failed = false - updateState { state in - updateValues = valuesRequiringUpdate(state: state, view: view) - if updateValues.0 != nil || updateValues.1 != nil { - if (updateValues.description?.count ?? 0) > 255 { - failed = true - return state - } - return state.withUpdatedSavingData(true) - } else { - return state.withUpdatedEditingState(nil) - } - } - - guard !failed else { - errorImpl?() - return - } - - let updateTitle: Signal - if let titleValue = updateValues.title { - updateTitle = updatePeerTitle(account: context.account, peerId: view.peerId, title: titleValue) - |> mapError { _ in return Void() } - } else { - updateTitle = .complete() - } - - let updateDescription: Signal - if let descriptionValue = updateValues.description { - updateDescription = updatePeerDescription(account: context.account, peerId: view.peerId, description: descriptionValue.isEmpty ? nil : descriptionValue) - |> mapError { _ in return Void() } - } else { - updateDescription = .complete() - } - - let signal = combineLatest(queue: .mainQueue(), - updateTitle, - updateDescription - ) - - updatePeerNameDisposable.set((signal - |> deliverOnMainQueue).start(error: { _ in - updateState { state in - return state.withUpdatedSavingData(false) - } - }, completed: { - updateState { state in - return state.withUpdatedSavingData(false).withUpdatedEditingState(nil) - } - })) - }) - } - } else if canEditGroupInfo { - rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Edit), style: .regular, enabled: true, action: { - if let peer = peer as? TelegramGroup { - var text = "" - if let cachedData = view.cachedData as? CachedGroupData, let about = cachedData.about { - text = about - } - updateState { state in - return state.withUpdatedEditingState(GroupInfoEditingState(editingName: ItemListAvatarAndNameInfoItemName(peer), editingDescriptionText: text)) - } - } else if let channel = peer as? TelegramChannel, case .group = channel.info { - var text = "" - if let cachedData = view.cachedData as? CachedChannelData, let about = cachedData.about { - text = about - } - updateState { state in - return state.withUpdatedEditingState(GroupInfoEditingState(editingName: ItemListAvatarAndNameInfoItemName(channel), editingDescriptionText: text)) - } - } - }) - if peer is TelegramChannel { - secondaryRightNavigationButton = ItemListNavigationButton(content: .icon(.search), style: .regular, enabled: true, action: { - updateState { state in - return state.withUpdatedSearchingMembers(true) - } - }) - } - } else { - if peer is TelegramChannel { - rightNavigationButton = ItemListNavigationButton(content: .icon(.search), style: .regular, enabled: true, action: { - updateState { state in - return state.withUpdatedSearchingMembers(true) - } - }) - } - } - - var searchItem: ItemListControllerSearch? - if state.searchingMembers { - searchItem = ChannelMembersSearchItem(context: context, peerId: view.peerId, searchContext: searchContext, cancel: { - updateState { state in - return state.withUpdatedSearchingMembers(false) - } - }, openPeer: { peer, _ in - if let infoController = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) { - arguments.pushController(infoController) - } - }, pushController: { c in - pushControllerImpl?(c) - }, dismissInput: { - dismissInputImpl?() - }) - } - - let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.GroupInfo_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, secondaryRightNavigationButton: secondaryRightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back)) - - let entries = groupInfoEntries(account: context.account, presentationData: presentationData, view: view, channelMembers: channelMembers, globalNotificationSettings: globalNotificationSettings, state: state) - var memberIds: [PeerId] = [] - for entry in entries { - switch entry { - case let .member(member): - memberIds.append(member.peerId) - default: - break - } - } - let previousState = previousStateValue.swap(state) - let previousMembers = previousChannelMembers.swap(memberIds) ?? [] - - var animateChanges = previousMembers.count > memberIds.count || (previousState != nil && (previousState!.editingState != nil) != (state.editingState != nil)) - if presentationData.disableAnimations { - if Set(memberIds) == Set(previousMembers) && memberIds != previousMembers { - animateChanges = false - } - } - - let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: entries, style: .blocks, searchItem: searchItem, animateChanges: animateChanges) - - return (controllerState, (listState, arguments)) - } - |> afterDisposed { - actionsDisposable.dispose() - } - - let controller = ItemListController(context: context, state: signal) - - pushControllerImpl = { [weak controller] value in - (controller?.navigationController as? NavigationController)?.pushViewController(value) - } - presentControllerImpl = { [weak controller] value, presentationArguments in - controller?.view.endEditing(true) - controller?.present(value, in: .window(.root), with: presentationArguments, blockInteraction: true) - } - replaceControllerImpl = { [weak controller] previous, updated in - if let navigationController = controller?.navigationController as? NavigationController { - var controllers = navigationController.viewControllers - if let previous = previous { - controllers.removeAll(where: { $0 === previous }) - } - controllers.append(updated) - navigationController.setViewControllers(controllers, animated: true) - } - } - dismissInputImpl = { [weak controller] in - controller?.view.endEditing(true) - } - upgradedToSupergroupImpl = { [weak controller] upgradedPeerId, f in - let _ = (context.account.postbox.transaction { transaction -> Peer? in - return transaction.getPeer(upgradedPeerId) - } - |> deliverOnMainQueue).start(next: { peer in - guard let controller = controller, let navigationController = controller.navigationController as? NavigationController, let _ = peer else { - return - } - let infoController = groupInfoController(context: context, peerId: upgradedPeerId, membersLoaded: { - f() - }) - let chatController = context.sharedContext.makeChatController(context: context, chatLocation: .peer(upgradedPeerId), subject: nil, botStart: nil, mode: .standard(previewing: false)) - var viewControllers: [UIViewController] = [] - if let first = navigationController.viewControllers.first { - viewControllers.append(first) - } - viewControllers.append(chatController) - viewControllers.append(infoController) - navigationController.setViewControllers(viewControllers, animated: false) - }) - } - removePeerChatImpl = { [weak controller] peer, deleteGloballyIfPossible in - guard let controller = controller, let navigationController = controller.navigationController as? NavigationController else { - return - } - guard let tabController = navigationController.viewControllers.first as? TabBarController else { - return - } - for childController in tabController.controllers { - if let chatListController = childController as? ChatListController { - chatListController.maybeAskForPeerChatRemoval(peer: RenderedPeer(peer: peer), joined: false, deleteGloballyIfPossible: deleteGloballyIfPossible, completion: { [weak navigationController] removed in - if removed { - navigationController?.popToRoot(animated: true) - } - }, removed: { - }) - break - } - } - } - displayCopyContextMenuImpl = { [weak controller] text, tag in - if let strongController = controller { - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - var resultItemNode: ListViewItemNode? - let _ = strongController.frameForItemNode({ itemNode in - var itemTag: GroupInfoEntryTag? = nil - if let itemNode = itemNode as? ItemListMultilineTextItemNode { - if let tag = itemNode.tag as? GroupInfoEntryTag { - itemTag = tag - } - } - else if let itemNode = itemNode as? ItemListActionItemNode { - if let tag = itemNode.tag as? GroupInfoEntryTag { - itemTag = tag - } - } - else if let itemNode = itemNode as? ItemListAddressItemNode { - if let tag = itemNode.tag as? GroupInfoEntryTag { - itemTag = tag - } - } - if itemTag == tag { - resultItemNode = itemNode - return true - } - return false - }) - if let resultItemNode = resultItemNode { - let contextMenuController = ContextMenuController(actions: [ContextMenuAction(content: .text(title: presentationData.strings.Conversation_ContextMenuCopy, accessibilityLabel: presentationData.strings.Conversation_ContextMenuCopy), action: { - UIPasteboard.general.string = text - })]) - strongController.present(contextMenuController, in: .window(.root), with: ContextMenuControllerPresentationArguments(sourceNodeAndRect: { [weak resultItemNode] in - if let strongController = controller, let resultItemNode = resultItemNode { - return (resultItemNode, resultItemNode.contentBounds.insetBy(dx: 0.0, dy: -2.0), strongController.displayNode, strongController.view.bounds) - } else { - return nil - } - })) - - } - } - } - - aboutLinkActionImpl = { [weak context, weak controller] action, itemLink in - let _ = (peerView.get() - |> take(1) - |> deliverOnMainQueue).start(next: { peerView in - if let controller = controller, let context = context { - context.sharedContext.handleTextLinkAction(context: context, peerId: peerView.peerId, navigateDisposable: navigateDisposable, controller: controller, action: action, itemLink: itemLink) - } - }) - } - - avatarGalleryTransitionArguments = { [weak controller] entry in - if let controller = controller { - var result: ((ASDisplayNode, CGRect, () -> (UIView?, UIView?)), CGRect)? - controller.forEachItemNode { itemNode in - if let itemNode = itemNode as? ItemListAvatarAndNameInfoItemNode { - result = itemNode.avatarTransitionNode() - } - } - if let (node, _) = result { - return GalleryTransitionArguments(transitionNode: node, addToTransitionSurface: { _ in - }) - } - } - return nil - } - updateHiddenAvatarImpl = { [weak controller] in - if let controller = controller { - controller.forEachItemNode { itemNode in - if let itemNode = itemNode as? ItemListAvatarAndNameInfoItemNode { - itemNode.updateAvatarHidden() - } - } - } - } - endEditingImpl = { - [weak controller] in - controller?.view.endEditing(true) - } - clearHighlightImpl = { [weak controller] in - controller?.clearItemNodesHighlight(animated: true) - } - - let hapticFeedback = HapticFeedback() - errorImpl = { [weak controller] in - hapticFeedback.error() - controller?.forEachItemNode { itemNode in - if let itemNode = itemNode as? ItemListMultilineInputItemNode { - itemNode.animateError() - } - } - } - - controller.visibleBottomContentOffsetChanged = { offset in - if let (peerId, loadMoreControl) = loadMoreControl.with({ $0 }), case let .known(value) = offset, value < 40.0 { - if stateValue.with({ $0 }).expandedParticipants { - context.peerChannelMemberCategoriesContextsManager.loadMore(peerId: peerId, control: loadMoreControl) - } - } - } - return controller -} diff --git a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift index e649afab06..2ac4929c00 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift @@ -522,15 +522,15 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting let twoStepAuthDataValue = Promise(nil) let hasTwoStepAuthDataValue = twoStepAuthDataValue.get() - |> map { data -> Bool? in + |> mapToSignal { data -> Signal in if let data = data { if case .set = data { - return true + return .single(true) } else { - return false + return .single(false) } } else { - return nil + return .complete() } } diff --git a/submodules/SettingsUI/Sources/Themes/WallpaperGalleryController.swift b/submodules/SettingsUI/Sources/Themes/WallpaperGalleryController.swift index c0fe85ad60..14d418621d 100644 --- a/submodules/SettingsUI/Sources/Themes/WallpaperGalleryController.swift +++ b/submodules/SettingsUI/Sources/Themes/WallpaperGalleryController.swift @@ -312,6 +312,7 @@ public class WallpaperGalleryController: ViewController { }, dismissController: { [weak self] in self?.dismiss(forceAway: true) }, replaceRootController: { controller, ready in + }, editMedia: { _ in }) self.displayNode = WallpaperGalleryControllerNode(controllerInteraction: controllerInteraction, pageGap: 0.0) self.displayNodeDidLoad() diff --git a/submodules/SolidRoundedButtonNode/Sources/SolidRoundedButtonNode.swift b/submodules/SolidRoundedButtonNode/Sources/SolidRoundedButtonNode.swift index c5c6f42d3f..671f2a3690 100644 --- a/submodules/SolidRoundedButtonNode/Sources/SolidRoundedButtonNode.swift +++ b/submodules/SolidRoundedButtonNode/Sources/SolidRoundedButtonNode.swift @@ -129,7 +129,7 @@ public final class SolidRoundedButtonNode: ASDisplayNode { } public func updateLayout(width: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat { - return self.updateLayout(width: width, previousSubtitle: nil, transition: transition) + return self.updateLayout(width: width, previousSubtitle: self.subtitle, transition: transition) } private func updateLayout(width: CGFloat, previousSubtitle: String?, transition: ContainedViewLayoutTransition) -> CGFloat { diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index 945dca125c..08e6253e2b 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -296,6 +296,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-374917894] = { return Api.PhotoSize.parse_photoCachedSize($0) } dict[-525288402] = { return Api.PhotoSize.parse_photoStrippedSize($0) } dict[1520986705] = { return Api.PhotoSize.parse_photoSizeProgressive($0) } + dict[-668906175] = { return Api.PhotoSize.parse_photoPathSize($0) } dict[-244016606] = { return Api.messages.Stickers.parse_stickersNotModified($0) } dict[-463889475] = { return Api.messages.Stickers.parse_stickers($0) } dict[-1096616924] = { return Api.GlobalPrivacySettings.parse_globalPrivacySettings($0) } diff --git a/submodules/TelegramApi/Sources/Api1.swift b/submodules/TelegramApi/Sources/Api1.swift index 839d1773ca..b500198b76 100644 --- a/submodules/TelegramApi/Sources/Api1.swift +++ b/submodules/TelegramApi/Sources/Api1.swift @@ -9467,6 +9467,7 @@ public extension Api { case photoCachedSize(type: String, location: Api.FileLocation, w: Int32, h: Int32, bytes: Buffer) case photoStrippedSize(type: String, bytes: Buffer) case photoSizeProgressive(type: String, location: Api.FileLocation, w: Int32, h: Int32, sizes: [Int32]) + case photoPathSize(type: String, bytes: Buffer) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { @@ -9517,6 +9518,13 @@ public extension Api { serializeInt32(item, buffer: buffer, boxed: false) } break + case .photoPathSize(let type, let bytes): + if boxed { + buffer.appendInt32(-668906175) + } + serializeString(type, buffer: buffer, boxed: false) + serializeBytes(bytes, buffer: buffer, boxed: false) + break } } @@ -9532,6 +9540,8 @@ public extension Api { return ("photoStrippedSize", [("type", type), ("bytes", bytes)]) case .photoSizeProgressive(let type, let location, let w, let h, let sizes): return ("photoSizeProgressive", [("type", type), ("location", location), ("w", w), ("h", h), ("sizes", sizes)]) + case .photoPathSize(let type, let bytes): + return ("photoPathSize", [("type", type), ("bytes", bytes)]) } } @@ -9637,6 +9647,20 @@ public extension Api { return nil } } + public static func parse_photoPathSize(_ reader: BufferReader) -> PhotoSize? { + var _1: String? + _1 = parseString(reader) + var _2: Buffer? + _2 = parseBytes(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.PhotoSize.photoPathSize(type: _1!, bytes: _2!) + } + else { + return nil + } + } } public enum GlobalPrivacySettings: TypeConstructorDescription { diff --git a/submodules/TelegramCore/Sources/EnqueueMessage.swift b/submodules/TelegramCore/Sources/EnqueueMessage.swift index cfee4712d7..78e7581da3 100644 --- a/submodules/TelegramCore/Sources/EnqueueMessage.swift +++ b/submodules/TelegramCore/Sources/EnqueueMessage.swift @@ -31,6 +31,15 @@ public enum EnqueueMessage { return .forward(source: source, grouping: grouping, attributes: f(attributes)) } } + + public func withUpdatedGroupingKey(_ f: (Int64?) -> Int64?) -> EnqueueMessage { + switch self { + case let .message(text, attributes, mediaReference, replyToMessageId, localGroupingKey): + return .message(text: text, attributes: attributes, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: f(localGroupingKey)) + case .forward: + return self + } + } } func augmentMediaWithReference(_ mediaReference: AnyMediaReference) -> Media { @@ -192,7 +201,7 @@ public func enqueueMessagesToMultiplePeers(account: Account, peerIds: [PeerId], return account.postbox.transaction { transaction -> [MessageId] in var messageIds: [MessageId] = [] for peerId in peerIds { - for id in enqueueMessages(transaction: transaction, account: account, peerId: peerId, messages: messages, disableAutoremove: false) { + for id in enqueueMessages(transaction: transaction, account: account, peerId: peerId, messages: messages, disableAutoremove: false, transformGroupingKeysWithPeerId: true) { if let id = id { messageIds.append(id) } @@ -233,12 +242,22 @@ public func resendMessages(account: Account, messageIds: [MessageId]) -> Signal< } } -func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId, messages: [(Bool, EnqueueMessage)], disableAutoremove: Bool = false) -> [MessageId?] { +func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId, messages: [(Bool, EnqueueMessage)], disableAutoremove: Bool = false, transformGroupingKeysWithPeerId: Bool = false) -> [MessageId?] { var updatedMessages: [(Bool, EnqueueMessage)] = [] outer: for (transformedMedia, message) in messages { + var updatedMessage = message + if transformGroupingKeysWithPeerId { + updatedMessage = updatedMessage.withUpdatedGroupingKey { groupingKey -> Int64? in + if let groupingKey = groupingKey { + return groupingKey &+ peerId.toInt64() + } else { + return nil + } + } + } switch message { - case let .message(desc): - if let replyToMessageId = desc.replyToMessageId, replyToMessageId.peerId != peerId, let replyMessage = transaction.getMessage(replyToMessageId) { + case let .message(_, _, _, replyToMessageId, _): + if let replyToMessageId = replyToMessageId, replyToMessageId.peerId != peerId, let replyMessage = transaction.getMessage(replyToMessageId) { var canBeForwarded = true if replyMessage.id.namespace != Namespaces.Message.Cloud { canBeForwarded = false @@ -265,7 +284,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId, continue outer } } - updatedMessages.append((transformedMedia, message)) + updatedMessages.append((transformedMedia, updatedMessage)) } if let peer = transaction.getPeer(peerId), let accountPeer = transaction.getPeer(account.peerId) { diff --git a/submodules/TelegramCore/Sources/StickerPack.swift b/submodules/TelegramCore/Sources/StickerPack.swift index 97f3245721..5d60dce51a 100644 --- a/submodules/TelegramCore/Sources/StickerPack.swift +++ b/submodules/TelegramCore/Sources/StickerPack.swift @@ -5,7 +5,7 @@ import SwiftSignalKit import SyncCore import MtProtoKit -func telegramStickerPachThumbnailRepresentationFromApiSize(datacenterId: Int32, size: Api.PhotoSize) -> TelegramMediaImageRepresentation? { +func telegramStickerPackThumbnailRepresentationFromApiSize(datacenterId: Int32, size: Api.PhotoSize) -> TelegramMediaImageRepresentation? { switch size { case let .photoCachedSize(_, location, w, h, _): switch location { @@ -25,6 +25,8 @@ func telegramStickerPachThumbnailRepresentationFromApiSize(datacenterId: Int32, let resource = CloudStickerPackThumbnailMediaResource(datacenterId: datacenterId, volumeId: volumeId, localId: localId) return TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, progressiveSizes: sizes) } + case let .photoPathSize(_, data): + return nil case .photoStrippedSize: return nil case .photoSizeEmpty: @@ -49,7 +51,7 @@ extension StickerPackCollectionInfo { var thumbnailRepresentation: TelegramMediaImageRepresentation? if let thumb = thumb, let thumbDcId = thumbDcId { - thumbnailRepresentation = telegramStickerPachThumbnailRepresentationFromApiSize(datacenterId: thumbDcId, size: thumb) + thumbnailRepresentation = telegramStickerPackThumbnailRepresentationFromApiSize(datacenterId: thumbDcId, size: thumb) } self.init(id: ItemCollectionId(namespace: namespace, id: id), flags: setFlags, accessHash: accessHash, title: title, shortName: shortName, thumbnail: thumbnailRepresentation, hash: nHash, count: count) diff --git a/submodules/TelegramCore/Sources/TelegramMediaFile.swift b/submodules/TelegramCore/Sources/TelegramMediaFile.swift index d1285decc8..d75d737956 100644 --- a/submodules/TelegramCore/Sources/TelegramMediaFile.swift +++ b/submodules/TelegramCore/Sources/TelegramMediaFile.swift @@ -143,6 +143,8 @@ func telegramMediaFileThumbnailRepresentationsFromApiSizes(datacenterId: Int32, let resource = CloudDocumentSizeMediaResource(datacenterId: datacenterId, documentId: documentId, accessHash: accessHash, sizeSpec: type, volumeId: volumeId, localId: localId, fileReference: fileReference) representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, progressiveSizes: sizes)) } + case let .photoPathSize(_, data): + immediateThumbnailData = data.makeData() case let .photoStrippedSize(_, data): immediateThumbnailData = data.makeData() case .photoSizeEmpty: diff --git a/submodules/TelegramCore/Sources/TelegramMediaImage.swift b/submodules/TelegramCore/Sources/TelegramMediaImage.swift index 674c5afd12..5dca93ac69 100644 --- a/submodules/TelegramCore/Sources/TelegramMediaImage.swift +++ b/submodules/TelegramCore/Sources/TelegramMediaImage.swift @@ -31,6 +31,8 @@ func telegramMediaImageRepresentationsFromApiSizes(datacenterId: Int32, photoId: } case let .photoStrippedSize(_, data): immediateThumbnailData = data.makeData() + case .photoPathSize: + break case .photoSizeEmpty: break } diff --git a/submodules/TelegramPresentationData/Sources/PresentationStrings.swift b/submodules/TelegramPresentationData/Sources/PresentationStrings.swift index 7f30643b51..0c92bd4737 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationStrings.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationStrings.swift @@ -514,5380 +514,5382 @@ public final class PresentationStrings: Equatable { public var Channel_Info_Management: String { return self._s[309]! } public var Passport_Language_hr: String { return self._s[310]! } public var EditTheme_Edit_Preview_IncomingText: String { return self._s[312]! } - public var Conversation_SecretChatContextBotAlert: String { return self._s[314]! } - public var GroupInfo_Permissions_SlowmodeValue_Off: String { return self._s[315]! } - public var Privacy_Calls_P2PContacts: String { return self._s[316]! } - public var Appearance_PickAccentColor: String { return self._s[317]! } - public var MediaPicker_TapToUngroupDescription: String { return self._s[318]! } - public var Localization_EnglishLanguageName: String { return self._s[319]! } - public var Stickers_SuggestStickers: String { return self._s[320]! } - public var Passport_Language_ko: String { return self._s[321]! } - public var Settings_ProxyDisabled: String { return self._s[322]! } - public var PrivacySettings_PasscodeOff: String { return self._s[323]! } - public var Undo_LeftChannel: String { return self._s[324]! } - public var Appearance_AutoNightThemeDisabled: String { return self._s[325]! } - public var TextFormat_Bold: String { return self._s[326]! } - public var Login_InfoTitle: String { return self._s[327]! } - public var Channel_BanUser_PermissionSendPolls: String { return self._s[328]! } - public var Settings_AddAnotherAccount: String { return self._s[329]! } - public var GroupPermission_NewTitle: String { return self._s[330]! } - public var Login_SelectCountry_Title: String { return self._s[331]! } - public var Cache_ServiceFiles: String { return self._s[332]! } - public var Passport_Language_nl: String { return self._s[333]! } - public var Contacts_TopSection: String { return self._s[334]! } - public var Passport_Identity_DateOfBirthPlaceholder: String { return self._s[335]! } - public var Conversation_ContextMenuReport: String { return self._s[337]! } + public var OpenFile_Proceed: String { return self._s[313]! } + public var Conversation_SecretChatContextBotAlert: String { return self._s[315]! } + public var GroupInfo_Permissions_SlowmodeValue_Off: String { return self._s[316]! } + public var Privacy_Calls_P2PContacts: String { return self._s[317]! } + public var Appearance_PickAccentColor: String { return self._s[318]! } + public var MediaPicker_TapToUngroupDescription: String { return self._s[319]! } + public var Localization_EnglishLanguageName: String { return self._s[320]! } + public var Stickers_SuggestStickers: String { return self._s[321]! } + public var Passport_Language_ko: String { return self._s[322]! } + public var Settings_ProxyDisabled: String { return self._s[323]! } + public var PrivacySettings_PasscodeOff: String { return self._s[324]! } + public var Undo_LeftChannel: String { return self._s[325]! } + public var Appearance_AutoNightThemeDisabled: String { return self._s[326]! } + public var TextFormat_Bold: String { return self._s[327]! } + public var Login_InfoTitle: String { return self._s[328]! } + public var Channel_BanUser_PermissionSendPolls: String { return self._s[329]! } + public var Settings_AddAnotherAccount: String { return self._s[330]! } + public var GroupPermission_NewTitle: String { return self._s[331]! } + public var Login_SelectCountry_Title: String { return self._s[332]! } + public var Cache_ServiceFiles: String { return self._s[333]! } + public var Passport_Language_nl: String { return self._s[334]! } + public var Contacts_TopSection: String { return self._s[335]! } + public var Passport_Identity_DateOfBirthPlaceholder: String { return self._s[336]! } + public var Conversation_ContextMenuReport: String { return self._s[338]! } public func Login_BannedPhoneBody(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[338]!, self._r[338]!, [_0]) + return formatWithArgumentRanges(self._s[339]!, self._r[339]!, [_0]) } - public var Conversation_Search: String { return self._s[339]! } - public var Group_Setup_HistoryVisibleHelp: String { return self._s[341]! } - public var ReportPeer_AlertSuccess: String { return self._s[343]! } - public var AutoNightTheme_Title: String { return self._s[345]! } + public var Conversation_Search: String { return self._s[340]! } + public var Group_Setup_HistoryVisibleHelp: String { return self._s[342]! } + public var ReportPeer_AlertSuccess: String { return self._s[344]! } + public var AutoNightTheme_Title: String { return self._s[346]! } public func Notification_PinnedTextMessage(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[347]!, self._r[347]!, [_0, _1]) + return formatWithArgumentRanges(self._s[348]!, self._r[348]!, [_0, _1]) } public func Conversation_OpenBotLinkText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[348]!, self._r[348]!, [_0]) + return formatWithArgumentRanges(self._s[349]!, self._r[349]!, [_0]) } - public var Conversation_ShareBotContactConfirmation: String { return self._s[349]! } - public var TwoStepAuth_RecoveryCode: String { return self._s[350]! } - public var SocksProxySetup_ConnectAndSave: String { return self._s[351]! } + public var Conversation_ShareBotContactConfirmation: String { return self._s[350]! } + public var TwoStepAuth_RecoveryCode: String { return self._s[351]! } + public var SocksProxySetup_ConnectAndSave: String { return self._s[352]! } public func MESSAGE_INVOICE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[352]!, self._r[352]!, [_1, _2]) + return formatWithArgumentRanges(self._s[353]!, self._r[353]!, [_1, _2]) } public func Channel_AdminLog_MessageChangedGroupUsername(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[353]!, self._r[353]!, [_0]) + return formatWithArgumentRanges(self._s[354]!, self._r[354]!, [_0]) } - public var Replies_BlockAndDeleteRepliesActionTitle: String { return self._s[354]! } + public var Replies_BlockAndDeleteRepliesActionTitle: String { return self._s[355]! } public func Notification_GroupInviter(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[355]!, self._r[355]!, [_0]) + return formatWithArgumentRanges(self._s[356]!, self._r[356]!, [_0]) } - public var Conversation_InfoGroup: String { return self._s[356]! } + public var Conversation_InfoGroup: String { return self._s[357]! } public func Map_AccurateTo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[358]!, self._r[358]!, [_0]) + return formatWithArgumentRanges(self._s[359]!, self._r[359]!, [_0]) } - public var Conversation_ChatBackground: String { return self._s[359]! } - public var PhotoEditor_Set: String { return self._s[360]! } + public var Conversation_ChatBackground: String { return self._s[360]! } + public var PhotoEditor_Set: String { return self._s[361]! } public func Channel_Management_PromotedBy(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[362]!, self._r[362]!, [_0]) + return formatWithArgumentRanges(self._s[363]!, self._r[363]!, [_0]) } - public var IntentsSettings_SuggestedChatsContacts: String { return self._s[363]! } - public var Passport_Phone_Title: String { return self._s[365]! } - public var Conversation_EditingMessageMediaChange: String { return self._s[366]! } - public var Channel_LinkItem: String { return self._s[367]! } + public var IntentsSettings_SuggestedChatsContacts: String { return self._s[364]! } + public var Passport_Phone_Title: String { return self._s[366]! } + public var Conversation_EditingMessageMediaChange: String { return self._s[367]! } + public var Channel_LinkItem: String { return self._s[368]! } public func PUSH_CHAT_DELETE_MEMBER(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[368]!, self._r[368]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[369]!, self._r[369]!, [_1, _2, _3]) } - public var Conversation_DeleteManyMessages: String { return self._s[369]! } - public var Notifications_Badge_IncludeMutedChats: String { return self._s[370]! } - public var AuthSessions_AddedDeviceTitle: String { return self._s[373]! } - public var Privacy_Calls_NeverAllow_Placeholder: String { return self._s[374]! } - public var Settings_ProxyConnecting: String { return self._s[375]! } - public var Theme_Colors_Accent: String { return self._s[376]! } - public var Theme_Colors_ColorWallpaperWarning: String { return self._s[377]! } + public var Conversation_DeleteManyMessages: String { return self._s[370]! } + public var Notifications_Badge_IncludeMutedChats: String { return self._s[371]! } + public var AuthSessions_AddedDeviceTitle: String { return self._s[374]! } + public var Privacy_Calls_NeverAllow_Placeholder: String { return self._s[375]! } + public var Settings_ProxyConnecting: String { return self._s[376]! } + public var Theme_Colors_Accent: String { return self._s[377]! } + public var Theme_Colors_ColorWallpaperWarning: String { return self._s[378]! } public func PUSH_PHONE_CALL_MISSED(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[378]!, self._r[378]!, [_1]) + return formatWithArgumentRanges(self._s[379]!, self._r[379]!, [_1]) } - public var Passport_Language_lo: String { return self._s[379]! } - public var Wallet_WordCheck_Continue: String { return self._s[380]! } + public var Passport_Language_lo: String { return self._s[380]! } + public var Wallet_WordCheck_Continue: String { return self._s[381]! } public func Watch_Time_ShortWeekdayAt(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[382]!, self._r[382]!, [_1, _2]) + return formatWithArgumentRanges(self._s[383]!, self._r[383]!, [_1, _2]) } - public var Permissions_NotificationsText_v0: String { return self._s[383]! } - public var ChatList_Context_RemoveFromRecents: String { return self._s[384]! } - public var Watch_GroupInfo_Title: String { return self._s[385]! } - public var Settings_AddDevice: String { return self._s[387]! } - public var WallpaperPreview_SwipeColorsTopText: String { return self._s[388]! } + public var Permissions_NotificationsText_v0: String { return self._s[384]! } + public var ChatList_Context_RemoveFromRecents: String { return self._s[385]! } + public var Watch_GroupInfo_Title: String { return self._s[386]! } + public var Settings_AddDevice: String { return self._s[388]! } + public var WallpaperPreview_SwipeColorsTopText: String { return self._s[389]! } public func PUSH_CHANNEL_ALBUM(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[389]!, self._r[389]!, [_1]) + return formatWithArgumentRanges(self._s[390]!, self._r[390]!, [_1]) } - public var TwoStepAuth_Disable: String { return self._s[391]! } + public var TwoStepAuth_Disable: String { return self._s[392]! } public func Conversation_AddNameToContacts(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[392]!, self._r[392]!, [_0]) + return formatWithArgumentRanges(self._s[393]!, self._r[393]!, [_0]) } public func Time_PreciseDate_m10(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[393]!, self._r[393]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[394]!, self._r[394]!, [_1, _2, _3]) } public func Login_WillSendSms(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[394]!, self._r[394]!, [_0]) + return formatWithArgumentRanges(self._s[395]!, self._r[395]!, [_0]) } - public var Channel_AdminLog_BanReadMessages: String { return self._s[395]! } - public var Undo_ChatDeleted: String { return self._s[396]! } - public var ContactInfo_URLLabelHomepage: String { return self._s[397]! } + public var Channel_AdminLog_BanReadMessages: String { return self._s[396]! } + public var Undo_ChatDeleted: String { return self._s[397]! } + public var ContactInfo_URLLabelHomepage: String { return self._s[398]! } public func PUSH_CHAT_MESSAGE_STICKER(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[398]!, self._r[398]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[399]!, self._r[399]!, [_1, _2, _3]) } - public var FastTwoStepSetup_EmailHelp: String { return self._s[399]! } - public var Contacts_SelectAll: String { return self._s[400]! } - public var Privacy_ContactsReset: String { return self._s[401]! } - public var AttachmentMenu_File: String { return self._s[403]! } - public var PasscodeSettings_EncryptData: String { return self._s[404]! } - public var EditTheme_ThemeTemplateAlertText: String { return self._s[405]! } + public var FastTwoStepSetup_EmailHelp: String { return self._s[400]! } + public var Contacts_SelectAll: String { return self._s[401]! } + public var Privacy_ContactsReset: String { return self._s[402]! } + public var AttachmentMenu_File: String { return self._s[404]! } + public var PasscodeSettings_EncryptData: String { return self._s[405]! } + public var EditTheme_ThemeTemplateAlertText: String { return self._s[406]! } public func Wallet_Time_PreciseDate_m6(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[407]!, self._r[407]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[408]!, self._r[408]!, [_1, _2, _3]) } public func Privacy_GroupsAndChannels_InviteToChannelError(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[408]!, self._r[408]!, [_0, _1]) - } - public func Profile_CreateEncryptedChatOutdatedError(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[409]!, self._r[409]!, [_0, _1]) } - public var PhotoEditor_ShadowsTint: String { return self._s[411]! } - public var GroupInfo_ChatAdmins: String { return self._s[412]! } - public var ArchivedChats_IntroTitle2: String { return self._s[413]! } - public var Cache_LowDiskSpaceText: String { return self._s[414]! } - public var CreatePoll_Anonymous: String { return self._s[415]! } - public var Wallet_Created_ExportErrorText: String { return self._s[416]! } - public var Checkout_PaymentMethod_New: String { return self._s[417]! } - public var Wallet_Info_RefreshErrorText: String { return self._s[418]! } - public var Invitation_JoinGroup: String { return self._s[419]! } + public func Profile_CreateEncryptedChatOutdatedError(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[410]!, self._r[410]!, [_0, _1]) + } + public var PhotoEditor_ShadowsTint: String { return self._s[412]! } + public var GroupInfo_ChatAdmins: String { return self._s[413]! } + public var ArchivedChats_IntroTitle2: String { return self._s[414]! } + public var Cache_LowDiskSpaceText: String { return self._s[415]! } + public var CreatePoll_Anonymous: String { return self._s[416]! } + public var Wallet_Created_ExportErrorText: String { return self._s[417]! } + public var Checkout_PaymentMethod_New: String { return self._s[418]! } + public var Wallet_Info_RefreshErrorText: String { return self._s[419]! } + public var Invitation_JoinGroup: String { return self._s[420]! } public func Time_MonthOfYear_m4(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[422]!, self._r[422]!, [_0]) + return formatWithArgumentRanges(self._s[423]!, self._r[423]!, [_0]) } - public var CheckoutInfo_SaveInfoHelp: String { return self._s[423]! } - public var Notification_Reply: String { return self._s[425]! } - public var Wallet_Month_GenSeptember: String { return self._s[426]! } + public var CheckoutInfo_SaveInfoHelp: String { return self._s[424]! } + public var Notification_Reply: String { return self._s[426]! } + public var Wallet_Month_GenSeptember: String { return self._s[427]! } public func Login_PhoneBannedEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[427]!, self._r[427]!, [_0]) + return formatWithArgumentRanges(self._s[428]!, self._r[428]!, [_0]) } - public var Login_PhoneTitle: String { return self._s[428]! } - public var VoiceOver_Media_PlaybackRateNormal: String { return self._s[429]! } + public var Login_PhoneTitle: String { return self._s[429]! } + public var VoiceOver_Media_PlaybackRateNormal: String { return self._s[430]! } public func PUSH_CHAT_MESSAGE_INVOICE(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[430]!, self._r[430]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[431]!, self._r[431]!, [_1, _2, _3]) } - public var Appearance_TextSize_Title: String { return self._s[431]! } - public var NetworkUsageSettings_MediaImageDataSection: String { return self._s[433]! } - public var VoiceOver_Navigation_Compose: String { return self._s[434]! } - public var Passport_InfoText: String { return self._s[435]! } - public var ApplyLanguage_ApplyLanguageAction: String { return self._s[436]! } - public var MessagePoll_LabelClosed: String { return self._s[438]! } - public var AttachmentMenu_SendAsFiles: String { return self._s[439]! } - public var KeyCommand_FocusOnInputField: String { return self._s[440]! } - public var Conversation_ContextViewThread: String { return self._s[441]! } - public var Privacy_SecretChatsLinkPreviews: String { return self._s[443]! } - public var Permissions_PeopleNearbyAllow_v0: String { return self._s[444]! } - public var Conversation_ContextMenuMention: String { return self._s[446]! } - public var CreatePoll_QuizInfo: String { return self._s[447]! } - public var Appearance_ThemePreview_ChatList_2_Name: String { return self._s[448]! } - public var Username_LinkCopied: String { return self._s[449]! } - public var IntentsSettings_SuggestedAndSpotlightChatsInfo: String { return self._s[450]! } - public var TwoStepAuth_ChangePassword: String { return self._s[451]! } - public var Watch_Suggestion_Thanks: String { return self._s[452]! } - public var Channel_TitleInfo: String { return self._s[453]! } - public var ChatList_ChatTypesSection: String { return self._s[454]! } + public var Appearance_TextSize_Title: String { return self._s[432]! } + public var NetworkUsageSettings_MediaImageDataSection: String { return self._s[434]! } + public var VoiceOver_Navigation_Compose: String { return self._s[435]! } + public var Passport_InfoText: String { return self._s[436]! } + public var ApplyLanguage_ApplyLanguageAction: String { return self._s[437]! } + public var MessagePoll_LabelClosed: String { return self._s[439]! } + public var AttachmentMenu_SendAsFiles: String { return self._s[440]! } + public var KeyCommand_FocusOnInputField: String { return self._s[441]! } + public var Conversation_ContextViewThread: String { return self._s[442]! } + public var Privacy_SecretChatsLinkPreviews: String { return self._s[444]! } + public var Permissions_PeopleNearbyAllow_v0: String { return self._s[445]! } + public var Conversation_ContextMenuMention: String { return self._s[447]! } + public var CreatePoll_QuizInfo: String { return self._s[448]! } + public var Appearance_ThemePreview_ChatList_2_Name: String { return self._s[449]! } + public var Username_LinkCopied: String { return self._s[450]! } + public var IntentsSettings_SuggestedAndSpotlightChatsInfo: String { return self._s[451]! } + public var TwoStepAuth_ChangePassword: String { return self._s[452]! } + public var Watch_Suggestion_Thanks: String { return self._s[453]! } + public var Channel_TitleInfo: String { return self._s[454]! } + public var ChatList_ChatTypesSection: String { return self._s[455]! } public func Watch_LastSeen_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[455]!, self._r[455]!, [_0]) - } - public func Channel_AdminLog_PollStopped(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[456]!, self._r[456]!, [_0]) } - public var AuthSessions_AddDevice_InvalidQRCode: String { return self._s[457]! } + public func Channel_AdminLog_PollStopped(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[457]!, self._r[457]!, [_0]) + } + public var AuthSessions_AddDevice_InvalidQRCode: String { return self._s[458]! } public func Call_MicrophoneOff(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[458]!, self._r[458]!, [_0]) + return formatWithArgumentRanges(self._s[459]!, self._r[459]!, [_0]) } - public var Channel_AdminLogFilter_ChannelEventsInfo: String { return self._s[459]! } - public var Profile_MessageLifetimeForever: String { return self._s[460]! } - public var ArchivedChats_IntroText1: String { return self._s[461]! } - public var Notifications_ChannelNotificationsPreview: String { return self._s[462]! } - public var Map_PullUpForPlaces: String { return self._s[464]! } - public var UserInfo_TelegramCall: String { return self._s[465]! } - public var Conversation_ShareMyContactInfo: String { return self._s[466]! } - public var ChatList_Tabs_All: String { return self._s[467]! } - public var Notification_PassportValueEmail: String { return self._s[468]! } - public var Notification_VideoCallIncoming: String { return self._s[469]! } - public var SettingsSearch_Synonyms_Appearance_AutoNightTheme: String { return self._s[470]! } - public var Channel_Username_InvalidTaken: String { return self._s[471]! } - public var GroupPermission_EditingDisabled: String { return self._s[472]! } - public var ChatContextMenu_TextSelectionTip: String { return self._s[473]! } - public var Passport_Language_pl: String { return self._s[475]! } - public var Call_Accept: String { return self._s[476]! } - public var ChatListFolder_NameSectionHeader: String { return self._s[477]! } + public var Channel_AdminLogFilter_ChannelEventsInfo: String { return self._s[460]! } + public var Profile_MessageLifetimeForever: String { return self._s[461]! } + public var ArchivedChats_IntroText1: String { return self._s[462]! } + public var Notifications_ChannelNotificationsPreview: String { return self._s[463]! } + public var Map_PullUpForPlaces: String { return self._s[465]! } + public var UserInfo_TelegramCall: String { return self._s[466]! } + public var Conversation_ShareMyContactInfo: String { return self._s[467]! } + public var ChatList_Tabs_All: String { return self._s[468]! } + public var Notification_PassportValueEmail: String { return self._s[469]! } + public var Notification_VideoCallIncoming: String { return self._s[470]! } + public var SettingsSearch_Synonyms_Appearance_AutoNightTheme: String { return self._s[471]! } + public var Channel_Username_InvalidTaken: String { return self._s[472]! } + public var GroupPermission_EditingDisabled: String { return self._s[473]! } + public var ChatContextMenu_TextSelectionTip: String { return self._s[474]! } + public var Passport_Language_pl: String { return self._s[476]! } + public var Call_Accept: String { return self._s[477]! } + public var ChatListFolder_NameSectionHeader: String { return self._s[478]! } public func Passport_Identity_NativeNameTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[478]!, self._r[478]!, [_0]) + return formatWithArgumentRanges(self._s[479]!, self._r[479]!, [_0]) } - public var ClearCache_Forever: String { return self._s[479]! } + public var ClearCache_Forever: String { return self._s[480]! } public func ChannelInfo_AddParticipantConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[481]!, self._r[481]!, [_0]) + return formatWithArgumentRanges(self._s[482]!, self._r[482]!, [_0]) } - public var Group_EditAdmin_RankAdminPlaceholder: String { return self._s[482]! } - public var Calls_SubmitRating: String { return self._s[483]! } - public var Location_LiveLocationRequired_ShareLocation: String { return self._s[484]! } + public var Group_EditAdmin_RankAdminPlaceholder: String { return self._s[483]! } + public var Calls_SubmitRating: String { return self._s[484]! } + public var Location_LiveLocationRequired_ShareLocation: String { return self._s[485]! } public func ChatList_AddedToFolderTooltip(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[485]!, self._r[485]!, [_1, _2]) + return formatWithArgumentRanges(self._s[486]!, self._r[486]!, [_1, _2]) } - public var IntentsSettings_MainAccountInfo: String { return self._s[486]! } - public var Map_Hybrid: String { return self._s[488]! } - public var ChatList_Context_Archive: String { return self._s[489]! } - public var Message_PinnedDocumentMessage: String { return self._s[490]! } - public var State_ConnectingToProxyInfo: String { return self._s[491]! } - public var Wallet_Month_GenDecember: String { return self._s[492]! } - public var Passport_Identity_NativeNameGenericTitle: String { return self._s[494]! } - public var Settings_AppLanguage: String { return self._s[495]! } + public var IntentsSettings_MainAccountInfo: String { return self._s[487]! } + public var Map_Hybrid: String { return self._s[489]! } + public var ChatList_Context_Archive: String { return self._s[490]! } + public var Message_PinnedDocumentMessage: String { return self._s[491]! } + public var State_ConnectingToProxyInfo: String { return self._s[492]! } + public var Wallet_Month_GenDecember: String { return self._s[493]! } + public var Passport_Identity_NativeNameGenericTitle: String { return self._s[495]! } + public var Settings_AppLanguage: String { return self._s[496]! } public func Checkout_SavePasswordTimeoutAndFaceId(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[496]!, self._r[496]!, [_0]) + return formatWithArgumentRanges(self._s[497]!, self._r[497]!, [_0]) } - public var Notifications_PermissionsEnable: String { return self._s[498]! } - public var CheckoutInfo_ShippingInfoAddress1Placeholder: String { return self._s[499]! } + public var Notifications_PermissionsEnable: String { return self._s[499]! } + public var CheckoutInfo_ShippingInfoAddress1Placeholder: String { return self._s[500]! } public func UserInfo_BlockActionTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[500]!, self._r[500]!, [_0]) - } - public func AuthSessions_Message(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[501]!, self._r[501]!, [_0]) } - public var NotificationsSound_Aurora: String { return self._s[504]! } - public var ScheduledMessages_ClearAll: String { return self._s[507]! } + public func AuthSessions_Message(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[502]!, self._r[502]!, [_0]) + } + public var NotificationsSound_Aurora: String { return self._s[505]! } + public var ScheduledMessages_ClearAll: String { return self._s[508]! } public func CancelResetAccount_TextSMS(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[508]!, self._r[508]!, [_0]) + return formatWithArgumentRanges(self._s[509]!, self._r[509]!, [_0]) } - public var Settings_BlockedUsers: String { return self._s[510]! } + public var Settings_BlockedUsers: String { return self._s[511]! } public func UserInfo_StartSecretChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[512]!, self._r[512]!, [_0]) + return formatWithArgumentRanges(self._s[513]!, self._r[513]!, [_0]) } - public var Passport_Language_hu: String { return self._s[513]! } + public var Passport_Language_hu: String { return self._s[514]! } public func Conversation_ScheduleMessage_SendTomorrow(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[514]!, self._r[514]!, [_0]) + return formatWithArgumentRanges(self._s[515]!, self._r[515]!, [_0]) } - public var StickerPack_Share: String { return self._s[515]! } - public var Checkout_NewCard_SaveInfoEnableHelp: String { return self._s[516]! } + public var StickerPack_Share: String { return self._s[516]! } + public var Checkout_NewCard_SaveInfoEnableHelp: String { return self._s[517]! } public func ForwardedAuthors2(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[517]!, self._r[517]!, [_0, _1]) + return formatWithArgumentRanges(self._s[518]!, self._r[518]!, [_0, _1]) } - public var Privacy_ContactsResetConfirmation: String { return self._s[518]! } - public var AppleWatch_ReplyPresets: String { return self._s[519]! } - public var Bot_GenericBotStatus: String { return self._s[520]! } - public var Appearance_ShareThemeColor: String { return self._s[521]! } - public var AuthSessions_AddDevice_UrlLoginHint: String { return self._s[522]! } - public var ReportGroupLocation_Title: String { return self._s[523]! } + public var Privacy_ContactsResetConfirmation: String { return self._s[519]! } + public var AppleWatch_ReplyPresets: String { return self._s[520]! } + public var Bot_GenericBotStatus: String { return self._s[521]! } + public var Appearance_ShareThemeColor: String { return self._s[522]! } + public var AuthSessions_AddDevice_UrlLoginHint: String { return self._s[523]! } + public var ReportGroupLocation_Title: String { return self._s[524]! } public func Activity_RemindAboutUser(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[524]!, self._r[524]!, [_0]) + return formatWithArgumentRanges(self._s[525]!, self._r[525]!, [_0]) } - public var Profile_CreateEncryptedChatError: String { return self._s[525]! } - public var Channel_EditAdmin_TransferOwnership: String { return self._s[526]! } - public var Wallpaper_ErrorNotFound: String { return self._s[527]! } - public var Bot_GenericSupportStatus: String { return self._s[528]! } - public var Activity_UploadingPhoto: String { return self._s[530]! } - public var Watch_UserInfo_Title: String { return self._s[532]! } - public var SocksProxySetup_ProxyTelegram: String { return self._s[533]! } - public var Appearance_ThemeDay: String { return self._s[534]! } + public var Profile_CreateEncryptedChatError: String { return self._s[526]! } + public var Channel_EditAdmin_TransferOwnership: String { return self._s[527]! } + public var Wallpaper_ErrorNotFound: String { return self._s[528]! } + public var Bot_GenericSupportStatus: String { return self._s[529]! } + public var Activity_UploadingPhoto: String { return self._s[531]! } + public var Watch_UserInfo_Title: String { return self._s[533]! } + public var SocksProxySetup_ProxyTelegram: String { return self._s[534]! } + public var Appearance_ThemeDay: String { return self._s[535]! } public func ApplyLanguage_ChangeLanguageOfficialText(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[535]!, self._r[535]!, [_1]) + return formatWithArgumentRanges(self._s[536]!, self._r[536]!, [_1]) } public func FileSize_B(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[536]!, self._r[536]!, [_0]) + return formatWithArgumentRanges(self._s[537]!, self._r[537]!, [_0]) } - public var Passport_Title: String { return self._s[539]! } + public var Passport_Title: String { return self._s[540]! } public func Time_PreciseDate_m3(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[541]!, self._r[541]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[542]!, self._r[542]!, [_1, _2, _3]) } - public var Wallet_Sent_Title: String { return self._s[542]! } - public var CheckoutInfo_ShippingInfoCountryPlaceholder: String { return self._s[543]! } - public var SocksProxySetup_ShareLink: String { return self._s[546]! } - public var AuthSessions_OtherDevices: String { return self._s[547]! } - public var IntentsSettings_SuggestedChatsGroups: String { return self._s[548]! } - public var Watch_MessageView_Reply: String { return self._s[549]! } - public var Camera_FlashOn: String { return self._s[551]! } + public var Wallet_Sent_Title: String { return self._s[543]! } + public var CheckoutInfo_ShippingInfoCountryPlaceholder: String { return self._s[544]! } + public var SocksProxySetup_ShareLink: String { return self._s[547]! } + public var AuthSessions_OtherDevices: String { return self._s[548]! } + public var IntentsSettings_SuggestedChatsGroups: String { return self._s[549]! } + public var Watch_MessageView_Reply: String { return self._s[550]! } + public var Camera_FlashOn: String { return self._s[552]! } public func PUSH_MESSAGE_STICKER(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[552]!, self._r[552]!, [_1, _2]) + return formatWithArgumentRanges(self._s[553]!, self._r[553]!, [_1, _2]) } - public var Conversation_ContextMenuBlock: String { return self._s[554]! } - public var Channel_EditAdmin_PermissionEditMessages: String { return self._s[555]! } - public var Privacy_Calls_NeverAllow: String { return self._s[556]! } - public var SharedMedia_CategoryLinks: String { return self._s[557]! } - public var Conversation_PinMessageAlertGroup: String { return self._s[560]! } - public var Passport_Identity_ScansHelp: String { return self._s[561]! } - public var ShareMenu_CopyShareLink: String { return self._s[562]! } - public var StickerSettings_MaskContextInfo: String { return self._s[563]! } - public var SocksProxySetup_ProxyStatusChecking: String { return self._s[564]! } - public var Conversation_WalletRequiredText: String { return self._s[565]! } - public var AutoDownloadSettings_AutodownloadPhotos: String { return self._s[567]! } - public var Checkout_ErrorPrecheckoutFailed: String { return self._s[569]! } - public var NotificationsSound_Popcorn: String { return self._s[570]! } - public var FeatureDisabled_Oops: String { return self._s[571]! } + public var Conversation_ContextMenuBlock: String { return self._s[555]! } + public var Channel_EditAdmin_PermissionEditMessages: String { return self._s[556]! } + public var Privacy_Calls_NeverAllow: String { return self._s[557]! } + public var SharedMedia_CategoryLinks: String { return self._s[558]! } + public var Conversation_PinMessageAlertGroup: String { return self._s[561]! } + public var Passport_Identity_ScansHelp: String { return self._s[562]! } + public var ShareMenu_CopyShareLink: String { return self._s[563]! } + public var StickerSettings_MaskContextInfo: String { return self._s[564]! } + public var SocksProxySetup_ProxyStatusChecking: String { return self._s[565]! } + public var Conversation_WalletRequiredText: String { return self._s[566]! } + public var AutoDownloadSettings_AutodownloadPhotos: String { return self._s[568]! } + public var Checkout_ErrorPrecheckoutFailed: String { return self._s[570]! } + public var NotificationsSound_Popcorn: String { return self._s[571]! } + public var FeatureDisabled_Oops: String { return self._s[572]! } public func Channel_AdminLog_MessageChangedChannelAbout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[572]!, self._r[572]!, [_0]) + return formatWithArgumentRanges(self._s[573]!, self._r[573]!, [_0]) } - public var Notification_PinnedMessage: String { return self._s[573]! } - public var Tour_Title4: String { return self._s[574]! } - public var Watch_Suggestion_OK: String { return self._s[575]! } - public var Compose_TokenListPlaceholder: String { return self._s[576]! } - public var EditTheme_Edit_TopInfo: String { return self._s[577]! } - public var Gif_NoGifsFound: String { return self._s[578]! } - public var Login_InvalidCountryCode: String { return self._s[579]! } - public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsExceptions: String { return self._s[580]! } + public var Notification_PinnedMessage: String { return self._s[574]! } + public var Tour_Title4: String { return self._s[575]! } + public var Watch_Suggestion_OK: String { return self._s[576]! } + public var Compose_TokenListPlaceholder: String { return self._s[577]! } + public var EditTheme_Edit_TopInfo: String { return self._s[578]! } + public var Gif_NoGifsFound: String { return self._s[579]! } + public var Login_InvalidCountryCode: String { return self._s[580]! } + public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsExceptions: String { return self._s[581]! } public func PUSH_LOCKED_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[582]!, self._r[582]!, [_1]) + return formatWithArgumentRanges(self._s[583]!, self._r[583]!, [_1]) } - public var Profile_CreateNewContact: String { return self._s[583]! } - public var AutoDownloadSettings_DataUsageLow: String { return self._s[584]! } - public var SettingsSearch_Synonyms_Notifications_InAppNotificationsPreview: String { return self._s[585]! } - public var Group_Setup_TypePublic: String { return self._s[586]! } - public var Weekday_ShortSaturday: String { return self._s[587]! } + public var Profile_CreateNewContact: String { return self._s[584]! } + public var AutoDownloadSettings_DataUsageLow: String { return self._s[585]! } + public var SettingsSearch_Synonyms_Notifications_InAppNotificationsPreview: String { return self._s[586]! } + public var Group_Setup_TypePublic: String { return self._s[587]! } + public var Weekday_ShortSaturday: String { return self._s[588]! } public func Time_MonthOfYear_m12(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[588]!, self._r[588]!, [_0]) + return formatWithArgumentRanges(self._s[589]!, self._r[589]!, [_0]) } - public var LiveLocation_MenuStopAll: String { return self._s[589]! } + public var LiveLocation_MenuStopAll: String { return self._s[590]! } public func DialogList_EncryptedChatStartedIncoming(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[590]!, self._r[590]!, [_0]) + return formatWithArgumentRanges(self._s[591]!, self._r[591]!, [_0]) } - public var ChatListFolder_NamePlaceholder: String { return self._s[591]! } - public var Channel_OwnershipTransfer_ErrorPublicChannelsTooMuch: String { return self._s[592]! } + public var ChatListFolder_NamePlaceholder: String { return self._s[592]! } + public var Channel_OwnershipTransfer_ErrorPublicChannelsTooMuch: String { return self._s[593]! } public func PUSH_CHAT_MESSAGE_GAME(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[593]!, self._r[593]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[594]!, self._r[594]!, [_1, _2, _3]) } public func Wallet_SecureStorageChanged_BiometryText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[595]!, self._r[595]!, [_0]) + return formatWithArgumentRanges(self._s[596]!, self._r[596]!, [_0]) } - public var Chat_GenericPsaTooltip: String { return self._s[596]! } + public var Chat_GenericPsaTooltip: String { return self._s[597]! } public func Message_ForwardedMessageShort(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[597]!, self._r[597]!, [_0]) + return formatWithArgumentRanges(self._s[598]!, self._r[598]!, [_0]) } - public var PrivacyLastSeenSettings_AlwaysShareWith_Placeholder: String { return self._s[598]! } - public var Login_PhoneAndCountryHelp: String { return self._s[599]! } - public var SaveIncomingPhotosSettings_From: String { return self._s[600]! } - public var Conversation_JumpToDate: String { return self._s[601]! } - public var AuthSessions_AddDevice: String { return self._s[602]! } - public var Settings_FAQ: String { return self._s[604]! } - public var Username_Title: String { return self._s[605]! } - public var DialogList_Read: String { return self._s[606]! } - public var Conversation_InstantPagePreview: String { return self._s[607]! } - public var Login_ResetAccountProtected_Title: String { return self._s[609]! } - public var CallFeedback_ReasonDistortedSpeech: String { return self._s[610]! } - public var Channel_EditAdmin_PermissionChangeInfo: String { return self._s[611]! } + public var PrivacyLastSeenSettings_AlwaysShareWith_Placeholder: String { return self._s[599]! } + public var Login_PhoneAndCountryHelp: String { return self._s[600]! } + public var SaveIncomingPhotosSettings_From: String { return self._s[601]! } + public var Conversation_JumpToDate: String { return self._s[602]! } + public var AuthSessions_AddDevice: String { return self._s[603]! } + public var Settings_FAQ: String { return self._s[605]! } + public var Username_Title: String { return self._s[606]! } + public var DialogList_Read: String { return self._s[607]! } + public var Conversation_InstantPagePreview: String { return self._s[608]! } + public var Login_ResetAccountProtected_Title: String { return self._s[610]! } + public var CallFeedback_ReasonDistortedSpeech: String { return self._s[611]! } + public var Channel_EditAdmin_PermissionChangeInfo: String { return self._s[612]! } public func Channel_AdminLog_MessageRankUsername(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[612]!, self._r[612]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[613]!, self._r[613]!, [_1, _2, _3]) } - public var WallpaperPreview_PreviewBottomText: String { return self._s[614]! } - public var Privacy_SecretChatsTitle: String { return self._s[617]! } + public var WallpaperPreview_PreviewBottomText: String { return self._s[615]! } + public var Privacy_SecretChatsTitle: String { return self._s[618]! } public func Notification_PassportValuesSentMessage(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[618]!, self._r[618]!, [_1, _2]) + return formatWithArgumentRanges(self._s[619]!, self._r[619]!, [_1, _2]) } - public var Checkout_NewCard_SaveInfoHelp: String { return self._s[619]! } - public var Conversation_ClousStorageInfo_Description4: String { return self._s[620]! } - public var PasscodeSettings_TurnPasscodeOn: String { return self._s[621]! } - public var Message_ReplyActionButtonShowReceipt: String { return self._s[622]! } + public var Checkout_NewCard_SaveInfoHelp: String { return self._s[620]! } + public var Conversation_ClousStorageInfo_Description4: String { return self._s[621]! } + public var PasscodeSettings_TurnPasscodeOn: String { return self._s[622]! } + public var Message_ReplyActionButtonShowReceipt: String { return self._s[623]! } public func PrivacyPolicy_AgeVerificationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[623]!, self._r[623]!, [_0]) + return formatWithArgumentRanges(self._s[624]!, self._r[624]!, [_0]) } - public var GroupInfo_DeleteAndExitConfirmation: String { return self._s[625]! } - public var TwoStepAuth_ConfirmationAbort: String { return self._s[626]! } - public var PrivacySettings_LastSeenEverybody: String { return self._s[627]! } - public var CallFeedback_ReasonDropped: String { return self._s[628]! } + public var GroupInfo_DeleteAndExitConfirmation: String { return self._s[626]! } + public var TwoStepAuth_ConfirmationAbort: String { return self._s[627]! } + public var PrivacySettings_LastSeenEverybody: String { return self._s[628]! } + public var CallFeedback_ReasonDropped: String { return self._s[629]! } public func ScheduledMessages_ScheduledDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[629]!, self._r[629]!, [_0]) + return formatWithArgumentRanges(self._s[630]!, self._r[630]!, [_0]) } - public var WebSearch_Images: String { return self._s[630]! } - public var Passport_Identity_Surname: String { return self._s[631]! } - public var Channel_Stickers_CreateYourOwn: String { return self._s[632]! } - public var TwoFactorSetup_Email_Title: String { return self._s[633]! } - public var Cache_ClearEmpty: String { return self._s[634]! } - public var AuthSessions_AddDeviceIntro_Action: String { return self._s[635]! } - public var Theme_Context_Apply: String { return self._s[636]! } - public var GroupInfo_Permissions_SearchPlaceholder: String { return self._s[637]! } - public var Wallet_Send_ErrorNotEnoughFundsText: String { return self._s[638]! } - public var AutoDownloadSettings_DocumentsTitle: String { return self._s[639]! } + public var WebSearch_Images: String { return self._s[631]! } + public var Passport_Identity_Surname: String { return self._s[632]! } + public var Channel_Stickers_CreateYourOwn: String { return self._s[633]! } + public var TwoFactorSetup_Email_Title: String { return self._s[634]! } + public var Cache_ClearEmpty: String { return self._s[635]! } + public var AuthSessions_AddDeviceIntro_Action: String { return self._s[636]! } + public var Theme_Context_Apply: String { return self._s[637]! } + public var GroupInfo_Permissions_SearchPlaceholder: String { return self._s[638]! } + public var Wallet_Send_ErrorNotEnoughFundsText: String { return self._s[639]! } + public var AutoDownloadSettings_DocumentsTitle: String { return self._s[640]! } public func NetworkUsageSettings_CellularUsageSince(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[640]!, self._r[640]!, [_0]) + return formatWithArgumentRanges(self._s[641]!, self._r[641]!, [_0]) } - public var Call_StatusRinging: String { return self._s[641]! } + public var Call_StatusRinging: String { return self._s[642]! } public func Map_DistanceAway(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[642]!, self._r[642]!, [_0]) - } - public func DialogList_SingleTypingSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[643]!, self._r[643]!, [_0]) } - public var Cache_ClearNone: String { return self._s[644]! } - public var Wallet_Receive_CopyAddress: String { return self._s[645]! } - public var PrivacyPolicy_Accept: String { return self._s[646]! } - public var Wallet_TransactionInfo_SenderHeader: String { return self._s[647]! } - public var Contacts_PhoneNumber: String { return self._s[648]! } - public var Passport_Identity_OneOfTypePassport: String { return self._s[649]! } - public var PhotoEditor_HighlightsTint: String { return self._s[651]! } - public var AutoDownloadSettings_AutodownloadVideos: String { return self._s[652]! } - public var Checkout_PaymentMethod_Title: String { return self._s[655]! } - public var Month_GenAugust: String { return self._s[657]! } - public var DialogList_Draft: String { return self._s[658]! } - public var ChatList_EmptyChatListFilterText: String { return self._s[659]! } - public var PeopleNearby_Description: String { return self._s[660]! } - public var WallpaperPreview_SwipeColorsBottomText: String { return self._s[661]! } - public var AppWallet_TransactionInfo_FeeInfoURL: String { return self._s[662]! } - public var SettingsSearch_Synonyms_Privacy_Data_TopPeers: String { return self._s[664]! } - public var Watch_Message_ForwardedFrom: String { return self._s[665]! } - public var Wallet_Words_NotDoneOk: String { return self._s[666]! } - public var Notification_Mute1h: String { return self._s[667]! } - public var Appearance_ThemePreview_Chat_3_TextWithLink: String { return self._s[668]! } - public var SettingsSearch_Synonyms_Privacy_AuthSessions: String { return self._s[670]! } - public var Channel_Edit_LinkItem: String { return self._s[671]! } - public var Presence_online: String { return self._s[672]! } - public var AutoDownloadSettings_Title: String { return self._s[673]! } - public var Conversation_MessageDialogRetry: String { return self._s[674]! } - public var SettingsSearch_Synonyms_ChatSettings_OpenLinksIn: String { return self._s[676]! } - public var Channel_About_Placeholder: String { return self._s[678]! } - public var Passport_Language_sl: String { return self._s[679]! } - public var AppleWatch_Title: String { return self._s[681]! } - public var RepliesChat_DescriptionText: String { return self._s[683]! } - public var Settings_ViewPhoto: String { return self._s[684]! } - public var Stats_Message_PrivateShares: String { return self._s[685]! } - public var ChatList_DeleteSavedMessagesConfirmation: String { return self._s[686]! } - public var Cache_ClearProgress: String { return self._s[687]! } - public var Cache_Music: String { return self._s[688]! } - public var Conversation_ContextMenuShare: String { return self._s[690]! } - public var AutoDownloadSettings_Unlimited: String { return self._s[691]! } - public var Channel_OwnershipTransfer_ErrorPrivacyRestricted: String { return self._s[692]! } - public var Contacts_PermissionsAllow: String { return self._s[693]! } - public var Passport_Language_vi: String { return self._s[695]! } + public func DialogList_SingleTypingSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[644]!, self._r[644]!, [_0]) + } + public var Cache_ClearNone: String { return self._s[645]! } + public var Wallet_Receive_CopyAddress: String { return self._s[646]! } + public var PrivacyPolicy_Accept: String { return self._s[647]! } + public var Wallet_TransactionInfo_SenderHeader: String { return self._s[648]! } + public var Contacts_PhoneNumber: String { return self._s[649]! } + public var Passport_Identity_OneOfTypePassport: String { return self._s[650]! } + public var PhotoEditor_HighlightsTint: String { return self._s[652]! } + public var AutoDownloadSettings_AutodownloadVideos: String { return self._s[653]! } + public var Checkout_PaymentMethod_Title: String { return self._s[656]! } + public var Month_GenAugust: String { return self._s[658]! } + public var DialogList_Draft: String { return self._s[659]! } + public var ChatList_EmptyChatListFilterText: String { return self._s[660]! } + public var PeopleNearby_Description: String { return self._s[661]! } + public var WallpaperPreview_SwipeColorsBottomText: String { return self._s[662]! } + public var AppWallet_TransactionInfo_FeeInfoURL: String { return self._s[663]! } + public var SettingsSearch_Synonyms_Privacy_Data_TopPeers: String { return self._s[665]! } + public var Watch_Message_ForwardedFrom: String { return self._s[666]! } + public var Wallet_Words_NotDoneOk: String { return self._s[667]! } + public var Notification_Mute1h: String { return self._s[668]! } + public var Appearance_ThemePreview_Chat_3_TextWithLink: String { return self._s[669]! } + public var SettingsSearch_Synonyms_Privacy_AuthSessions: String { return self._s[671]! } + public var Channel_Edit_LinkItem: String { return self._s[672]! } + public var Presence_online: String { return self._s[673]! } + public var AutoDownloadSettings_Title: String { return self._s[674]! } + public var Conversation_MessageDialogRetry: String { return self._s[675]! } + public var SettingsSearch_Synonyms_ChatSettings_OpenLinksIn: String { return self._s[677]! } + public var Channel_About_Placeholder: String { return self._s[679]! } + public var Passport_Language_sl: String { return self._s[680]! } + public var AppleWatch_Title: String { return self._s[682]! } + public var RepliesChat_DescriptionText: String { return self._s[684]! } + public var Settings_ViewPhoto: String { return self._s[685]! } + public var Stats_Message_PrivateShares: String { return self._s[686]! } + public var ChatList_DeleteSavedMessagesConfirmation: String { return self._s[687]! } + public var Cache_ClearProgress: String { return self._s[688]! } + public var Cache_Music: String { return self._s[689]! } + public var Conversation_ContextMenuShare: String { return self._s[691]! } + public var AutoDownloadSettings_Unlimited: String { return self._s[692]! } + public var Channel_OwnershipTransfer_ErrorPrivacyRestricted: String { return self._s[693]! } + public var Contacts_PermissionsAllow: String { return self._s[694]! } + public var Passport_Language_vi: String { return self._s[696]! } public func PUSH_MESSAGE_TEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[698]!, self._r[698]!, [_1, _2]) + return formatWithArgumentRanges(self._s[699]!, self._r[699]!, [_1, _2]) } - public var Passport_Language_de: String { return self._s[699]! } - public var Notifications_PermissionsText: String { return self._s[701]! } - public var GroupRemoved_AddToGroup: String { return self._s[702]! } - public var Appearance_ThemePreview_ChatList_4_Text: String { return self._s[703]! } - public var ChangePhoneNumberCode_RequestingACall: String { return self._s[704]! } - public var Login_TermsOfServiceAgree: String { return self._s[705]! } - public var VoiceOver_Navigation_ProxySettings: String { return self._s[706]! } + public var Passport_Language_de: String { return self._s[700]! } + public var Notifications_PermissionsText: String { return self._s[702]! } + public var GroupRemoved_AddToGroup: String { return self._s[703]! } + public var Appearance_ThemePreview_ChatList_4_Text: String { return self._s[704]! } + public var ChangePhoneNumberCode_RequestingACall: String { return self._s[705]! } + public var Login_TermsOfServiceAgree: String { return self._s[706]! } + public var VoiceOver_Navigation_ProxySettings: String { return self._s[707]! } public func PUSH_CHAT_JOINED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[707]!, self._r[707]!, [_1, _2]) + return formatWithArgumentRanges(self._s[708]!, self._r[708]!, [_1, _2]) } - public var SettingsSearch_Synonyms_Data_CallsUseLessData: String { return self._s[709]! } - public var ChatListFolder_NameGroups: String { return self._s[710]! } - public var SocksProxySetup_ProxyDetailsTitle: String { return self._s[711]! } + public var SettingsSearch_Synonyms_Data_CallsUseLessData: String { return self._s[710]! } + public var ChatListFolder_NameGroups: String { return self._s[711]! } + public var SocksProxySetup_ProxyDetailsTitle: String { return self._s[712]! } public func Channel_AdminLog_MessageChangedLinkedGroup(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[712]!, self._r[712]!, [_1, _2]) + return formatWithArgumentRanges(self._s[713]!, self._r[713]!, [_1, _2]) } - public var Watch_Suggestion_TalkLater: String { return self._s[713]! } - public var Checkout_ShippingOption_Title: String { return self._s[714]! } - public var Conversation_TitleRepliesEmpty: String { return self._s[715]! } - public var CreatePoll_TextHeader: String { return self._s[716]! } - public var VoiceOver_Chat_Message: String { return self._s[718]! } - public var InfoPlist_NSLocationWhenInUseUsageDescription: String { return self._s[719]! } - public var ContactInfo_Note: String { return self._s[721]! } - public var Channel_AdminLog_InfoPanelAlertText: String { return self._s[722]! } - public var Wallet_Receive_AmountHeader: String { return self._s[723]! } - public var Checkout_NewCard_CardholderNameTitle: String { return self._s[724]! } - public var AutoDownloadSettings_Photos: String { return self._s[725]! } - public var UserInfo_NotificationsDefaultDisabled: String { return self._s[726]! } - public var Channel_Info_Subscribers: String { return self._s[727]! } - public var ChatList_DeleteForCurrentUser: String { return self._s[728]! } - public var ChatListFolderSettings_FoldersSection: String { return self._s[729]! } + public var Watch_Suggestion_TalkLater: String { return self._s[714]! } + public var Checkout_ShippingOption_Title: String { return self._s[715]! } + public var Conversation_TitleRepliesEmpty: String { return self._s[716]! } + public var CreatePoll_TextHeader: String { return self._s[717]! } + public var VoiceOver_Chat_Message: String { return self._s[719]! } + public var InfoPlist_NSLocationWhenInUseUsageDescription: String { return self._s[720]! } + public var ContactInfo_Note: String { return self._s[722]! } + public var Channel_AdminLog_InfoPanelAlertText: String { return self._s[723]! } + public var Wallet_Receive_AmountHeader: String { return self._s[724]! } + public var Checkout_NewCard_CardholderNameTitle: String { return self._s[725]! } + public var AutoDownloadSettings_Photos: String { return self._s[726]! } + public var UserInfo_NotificationsDefaultDisabled: String { return self._s[727]! } + public var Channel_Info_Subscribers: String { return self._s[728]! } + public var ChatList_DeleteForCurrentUser: String { return self._s[729]! } + public var ChatListFolderSettings_FoldersSection: String { return self._s[730]! } public func Time_PreciseDate_m9(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[733]!, self._r[733]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[734]!, self._r[734]!, [_1, _2, _3]) } - public var AutoNightTheme_System: String { return self._s[734]! } - public var Call_StatusWaiting: String { return self._s[735]! } - public var GroupInfo_GroupHistoryHidden: String { return self._s[736]! } + public var AutoNightTheme_System: String { return self._s[735]! } + public var Call_StatusWaiting: String { return self._s[736]! } + public var GroupInfo_GroupHistoryHidden: String { return self._s[737]! } public func CHAT_MESSAGE_INVOICE(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[737]!, self._r[737]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[738]!, self._r[738]!, [_1, _2, _3]) } - public var Conversation_ContextMenuCopy: String { return self._s[739]! } - public var Notifications_MessageNotificationsPreview: String { return self._s[740]! } - public var Notifications_InAppNotificationsVibrate: String { return self._s[741]! } + public var Conversation_ContextMenuCopy: String { return self._s[740]! } + public var Notifications_MessageNotificationsPreview: String { return self._s[741]! } + public var Notifications_InAppNotificationsVibrate: String { return self._s[742]! } public func Conversation_RestrictedTextTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[742]!, self._r[742]!, [_0]) + return formatWithArgumentRanges(self._s[743]!, self._r[743]!, [_0]) } - public var Group_Status: String { return self._s[744]! } - public var Group_Setup_HistoryVisible: String { return self._s[745]! } - public var Conversation_DiscardVoiceMessageAction: String { return self._s[746]! } - public var Paint_Edit: String { return self._s[747]! } - public var Channel_EditAdmin_CannotEdit: String { return self._s[749]! } - public var Username_InvalidTooShort: String { return self._s[750]! } - public var ClearCache_StorageOtherApps: String { return self._s[751]! } - public var Wallet_Configuration_SourceJSON: String { return self._s[752]! } - public var Conversation_ViewMessage: String { return self._s[753]! } - public var GroupInfo_PublicLinkAdd: String { return self._s[755]! } + public var Group_Status: String { return self._s[745]! } + public var Group_Setup_HistoryVisible: String { return self._s[746]! } + public var Conversation_DiscardVoiceMessageAction: String { return self._s[747]! } + public var Paint_Edit: String { return self._s[748]! } + public var Channel_EditAdmin_CannotEdit: String { return self._s[750]! } + public var Username_InvalidTooShort: String { return self._s[751]! } + public var ClearCache_StorageOtherApps: String { return self._s[752]! } + public var Wallet_Configuration_SourceJSON: String { return self._s[753]! } + public var Conversation_ViewMessage: String { return self._s[754]! } + public var GroupInfo_PublicLinkAdd: String { return self._s[756]! } public func Notification_RemovedGroupPhoto(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[756]!, self._r[756]!, [_0]) + return formatWithArgumentRanges(self._s[757]!, self._r[757]!, [_0]) } - public var CallSettings_Title: String { return self._s[757]! } + public var CallSettings_Title: String { return self._s[758]! } public func Conversation_BotInteractiveUrlAlert(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[758]!, self._r[758]!, [_0]) + return formatWithArgumentRanges(self._s[759]!, self._r[759]!, [_0]) } public func VoiceOver_Chat_ContactFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[761]!, self._r[761]!, [_0]) + return formatWithArgumentRanges(self._s[762]!, self._r[762]!, [_0]) } - public var PUSH_SENDER_YOU: String { return self._s[764]! } - public var Profile_ShareContactButton: String { return self._s[765]! } - public var GroupInfo_Permissions_SectionTitle: String { return self._s[766]! } - public var Map_ShareLiveLocation: String { return self._s[767]! } - public var ChatListFolder_TitleEdit: String { return self._s[768]! } - public var Wallet_Send_ErrorInvalidAddress: String { return self._s[769]! } - public var Passport_Address_Address: String { return self._s[771]! } - public var LastSeen_JustNow: String { return self._s[773]! } + public var PUSH_SENDER_YOU: String { return self._s[765]! } + public var Profile_ShareContactButton: String { return self._s[766]! } + public var GroupInfo_Permissions_SectionTitle: String { return self._s[767]! } + public var Map_ShareLiveLocation: String { return self._s[768]! } + public var ChatListFolder_TitleEdit: String { return self._s[769]! } + public var Wallet_Send_ErrorInvalidAddress: String { return self._s[770]! } + public var Passport_Address_Address: String { return self._s[772]! } + public var LastSeen_JustNow: String { return self._s[774]! } public func SecretImage_NotViewedYet(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[774]!, self._r[774]!, [_0]) + return formatWithArgumentRanges(self._s[775]!, self._r[775]!, [_0]) } - public var ContactInfo_PhoneLabelOther: String { return self._s[775]! } - public var PasscodeSettings_DoNotMatch: String { return self._s[776]! } - public var Weekday_Today: String { return self._s[779]! } - public var DialogList_Title: String { return self._s[780]! } - public var SettingsSearch_Synonyms_Notifications_MessageNotificationsPreview: String { return self._s[781]! } - public var Cache_ClearCache: String { return self._s[782]! } - public var CreatePoll_ExplanationInfo: String { return self._s[783]! } - public var Notifications_ResetAllNotificationsHelp: String { return self._s[785]! } - public var Stats_MessageTitle: String { return self._s[786]! } - public var Passport_Address_Street: String { return self._s[788]! } - public var Wallet_Receive_ShareUrlInfo: String { return self._s[789]! } + public var ContactInfo_PhoneLabelOther: String { return self._s[776]! } + public var PasscodeSettings_DoNotMatch: String { return self._s[777]! } + public var Weekday_Today: String { return self._s[780]! } + public var DialogList_Title: String { return self._s[781]! } + public var SettingsSearch_Synonyms_Notifications_MessageNotificationsPreview: String { return self._s[782]! } + public var Cache_ClearCache: String { return self._s[783]! } + public var CreatePoll_ExplanationInfo: String { return self._s[784]! } + public var Notifications_ResetAllNotificationsHelp: String { return self._s[786]! } + public var Stats_MessageTitle: String { return self._s[787]! } + public var Passport_Address_Street: String { return self._s[789]! } + public var Wallet_Receive_ShareUrlInfo: String { return self._s[790]! } public func Channel_AdminLog_MessageRemovedGroupUsername(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[790]!, self._r[790]!, [_0]) + return formatWithArgumentRanges(self._s[791]!, self._r[791]!, [_0]) } - public var Channel_AdminLog_ChannelEmptyText: String { return self._s[791]! } + public var Channel_AdminLog_ChannelEmptyText: String { return self._s[792]! } public func Login_PhoneGenericEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[792]!, self._r[792]!, [_0]) + return formatWithArgumentRanges(self._s[793]!, self._r[793]!, [_0]) } - public var TwoStepAuth_Email: String { return self._s[794]! } - public var Wallet_Words_Text: String { return self._s[795]! } - public var Conversation_SecretLinkPreviewAlert: String { return self._s[796]! } - public var PrivacySettings_PasscodeOn: String { return self._s[797]! } - public var Wallet_Receive_CopyInvoiceUrl: String { return self._s[799]! } - public var Wallet_Send_AddressInfo: String { return self._s[800]! } - public var Camera_SquareMode: String { return self._s[801]! } - public var Wallet_Month_ShortJuly: String { return self._s[802]! } - public var SocksProxySetup_Port: String { return self._s[803]! } - public var Watch_LastSeen_JustNow: String { return self._s[805]! } + public var TwoStepAuth_Email: String { return self._s[795]! } + public var Wallet_Words_Text: String { return self._s[796]! } + public var Conversation_SecretLinkPreviewAlert: String { return self._s[797]! } + public var PrivacySettings_PasscodeOn: String { return self._s[798]! } + public var Wallet_Receive_CopyInvoiceUrl: String { return self._s[800]! } + public var Wallet_Send_AddressInfo: String { return self._s[801]! } + public var Camera_SquareMode: String { return self._s[802]! } + public var Wallet_Month_ShortJuly: String { return self._s[803]! } + public var SocksProxySetup_Port: String { return self._s[804]! } + public var Watch_LastSeen_JustNow: String { return self._s[806]! } public func PUSH_MESSAGE_GAME(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[806]!, self._r[806]!, [_1, _2]) + return formatWithArgumentRanges(self._s[807]!, self._r[807]!, [_1, _2]) } public func Watch_LastSeen_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[807]!, self._r[807]!, [_0]) + return formatWithArgumentRanges(self._s[808]!, self._r[808]!, [_0]) } public func Location_ProximityAlertSetText(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[808]!, self._r[808]!, [_1, _2]) + return formatWithArgumentRanges(self._s[809]!, self._r[809]!, [_1, _2]) } - public var EditTheme_Expand_Preview_OutgoingText: String { return self._s[809]! } - public var Channel_AdminLogFilter_EventsTitle: String { return self._s[810]! } - public var Wallet_AccessDenied_Settings: String { return self._s[812]! } - public var Watch_Suggestion_HoldOn: String { return self._s[814]! } + public var EditTheme_Expand_Preview_OutgoingText: String { return self._s[810]! } + public var Channel_AdminLogFilter_EventsTitle: String { return self._s[811]! } + public var Wallet_AccessDenied_Settings: String { return self._s[813]! } + public var Watch_Suggestion_HoldOn: String { return self._s[815]! } public func PUSH_CHANNEL_MESSAGE_GEOLIVE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[815]!, self._r[815]!, [_1]) + return formatWithArgumentRanges(self._s[816]!, self._r[816]!, [_1]) } - public var CallSettings_TabIcon: String { return self._s[816]! } - public var ScheduledMessages_SendNow: String { return self._s[817]! } - public var Stats_GroupTopWeekdaysTitle: String { return self._s[818]! } - public var Wallet_WordImport_IncorrectTitle: String { return self._s[819]! } - public var UserInfo_PhoneCall: String { return self._s[820]! } - public var Month_GenMarch: String { return self._s[821]! } - public var Camera_Discard: String { return self._s[822]! } - public var InfoPlist_NSFaceIDUsageDescription: String { return self._s[823]! } - public var Passport_RequestedInformation: String { return self._s[824]! } - public var Passport_Language_ro: String { return self._s[826]! } + public var CallSettings_TabIcon: String { return self._s[817]! } + public var ScheduledMessages_SendNow: String { return self._s[818]! } + public var Stats_GroupTopWeekdaysTitle: String { return self._s[819]! } + public var Wallet_WordImport_IncorrectTitle: String { return self._s[820]! } + public var UserInfo_PhoneCall: String { return self._s[821]! } + public var Month_GenMarch: String { return self._s[822]! } + public var Camera_Discard: String { return self._s[823]! } + public var InfoPlist_NSFaceIDUsageDescription: String { return self._s[824]! } + public var Passport_RequestedInformation: String { return self._s[825]! } + public var Passport_Language_ro: String { return self._s[827]! } public func Notification_ProximityYouReached(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[827]!, self._r[827]!, [_1, _2]) - } - public func PUSH_CHAT_MESSAGE_DOC(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[828]!, self._r[828]!, [_1, _2]) } - public var AutoDownloadSettings_ResetHelp: String { return self._s[829]! } - public var Passport_Identity_DocumentDetails: String { return self._s[831]! } - public var Passport_Address_ScansHelp: String { return self._s[832]! } - public var Location_LiveLocationRequired_Title: String { return self._s[833]! } - public var ClearCache_StorageCache: String { return self._s[834]! } - public var Theme_Colors_ColorWallpaperWarningProceed: String { return self._s[835]! } - public var Conversation_RestrictedText: String { return self._s[836]! } - public var Notifications_MessageNotifications: String { return self._s[838]! } - public var Passport_Scans: String { return self._s[839]! } - public var TwoStepAuth_SetupHintTitle: String { return self._s[841]! } - public var LogoutOptions_ContactSupportTitle: String { return self._s[842]! } - public var Passport_Identity_SelfieHelp: String { return self._s[843]! } - public var Permissions_NotificationsUnreachableText_v0: String { return self._s[844]! } - public var Privacy_PaymentsClear_PaymentInfo: String { return self._s[845]! } - public var ShareMenu_CopyShareLinkGame: String { return self._s[846]! } - public var PeerInfo_ButtonSearch: String { return self._s[847]! } + public func PUSH_CHAT_MESSAGE_DOC(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[829]!, self._r[829]!, [_1, _2]) + } + public var AutoDownloadSettings_ResetHelp: String { return self._s[830]! } + public var Passport_Identity_DocumentDetails: String { return self._s[832]! } + public var Passport_Address_ScansHelp: String { return self._s[833]! } + public var Location_LiveLocationRequired_Title: String { return self._s[834]! } + public var ClearCache_StorageCache: String { return self._s[835]! } + public var Theme_Colors_ColorWallpaperWarningProceed: String { return self._s[836]! } + public var Conversation_RestrictedText: String { return self._s[837]! } + public var Notifications_MessageNotifications: String { return self._s[839]! } + public var Passport_Scans: String { return self._s[840]! } + public var TwoStepAuth_SetupHintTitle: String { return self._s[842]! } + public var LogoutOptions_ContactSupportTitle: String { return self._s[843]! } + public var Passport_Identity_SelfieHelp: String { return self._s[844]! } + public var Permissions_NotificationsUnreachableText_v0: String { return self._s[845]! } + public var Privacy_PaymentsClear_PaymentInfo: String { return self._s[846]! } + public var ShareMenu_CopyShareLinkGame: String { return self._s[847]! } + public var PeerInfo_ButtonSearch: String { return self._s[848]! } public func Notification_ProximityReachedYou(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[850]!, self._r[850]!, [_1, _2]) + return formatWithArgumentRanges(self._s[851]!, self._r[851]!, [_1, _2]) } - public var SettingsSearch_Synonyms_Privacy_Data_ClearPaymentsInfo: String { return self._s[851]! } - public var Passport_FieldIdentityTranslationHelp: String { return self._s[853]! } - public var Conversation_InputTextSilentBroadcastPlaceholder: String { return self._s[854]! } - public var Month_GenSeptember: String { return self._s[855]! } + public var SettingsSearch_Synonyms_Privacy_Data_ClearPaymentsInfo: String { return self._s[852]! } + public var Passport_FieldIdentityTranslationHelp: String { return self._s[854]! } + public var Conversation_InputTextSilentBroadcastPlaceholder: String { return self._s[855]! } + public var Month_GenSeptember: String { return self._s[856]! } public func Call_GroupFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[857]!, self._r[857]!, [_1, _2]) + return formatWithArgumentRanges(self._s[858]!, self._r[858]!, [_1, _2]) } - public var StickerPacksSettings_ArchivedPacks: String { return self._s[858]! } + public var StickerPacksSettings_ArchivedPacks: String { return self._s[859]! } public func Channel_Username_LinkHint(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[860]!, self._r[860]!, [_0]) + return formatWithArgumentRanges(self._s[861]!, self._r[861]!, [_0]) } public func PUSH_PINNED_CONTACT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[862]!, self._r[862]!, [_1, _2]) + return formatWithArgumentRanges(self._s[863]!, self._r[863]!, [_1, _2]) } - public var LogoutOptions_LogOutWalletInfo: String { return self._s[863]! } + public var LogoutOptions_LogOutWalletInfo: String { return self._s[864]! } public func PUSH_MESSAGE_VIDEOS(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[864]!, self._r[864]!, [_1, _2]) + return formatWithArgumentRanges(self._s[865]!, self._r[865]!, [_1, _2]) } - public var Calls_NotNow: String { return self._s[866]! } - public var Wallet_Completed_Text: String { return self._s[869]! } - public var Settings_ChatFolders: String { return self._s[871]! } - public var Login_PadPhoneHelpTitle: String { return self._s[872]! } - public var TwoStepAuth_EnterPasswordInvalid: String { return self._s[873]! } - public var Settings_ChatBackground: String { return self._s[874]! } + public var Calls_NotNow: String { return self._s[867]! } + public var Wallet_Completed_Text: String { return self._s[870]! } + public var Settings_ChatFolders: String { return self._s[872]! } + public var Login_PadPhoneHelpTitle: String { return self._s[873]! } + public var TwoStepAuth_EnterPasswordInvalid: String { return self._s[874]! } + public var Settings_ChatBackground: String { return self._s[875]! } public func PUSH_CHAT_MESSAGE_CONTACT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[876]!, self._r[876]!, [_1, _2]) + return formatWithArgumentRanges(self._s[877]!, self._r[877]!, [_1, _2]) } - public var ProxyServer_VoiceOver_Active: String { return self._s[877]! } - public var Call_StatusBusy: String { return self._s[878]! } - public var Conversation_MessageDeliveryFailed: String { return self._s[879]! } - public var Login_NetworkError: String { return self._s[881]! } - public var TwoStepAuth_SetupPasswordDescription: String { return self._s[882]! } - public var Privacy_Calls_Integration: String { return self._s[883]! } - public var DialogList_SearchSectionMessages: String { return self._s[884]! } - public var AutoDownloadSettings_VideosTitle: String { return self._s[885]! } - public var Preview_DeletePhoto: String { return self._s[886]! } - public var PrivacySettings_PhoneNumber: String { return self._s[888]! } - public var Forward_ErrorDisabledForChat: String { return self._s[889]! } - public var Watch_Compose_CurrentLocation: String { return self._s[890]! } - public var Wallet_Info_TransactionFrom: String { return self._s[891]! } - public var Settings_CallSettings: String { return self._s[892]! } - public var AutoDownloadSettings_TypePrivateChats: String { return self._s[893]! } - public var ChatList_Context_MarkAllAsRead: String { return self._s[894]! } - public var ChatSettings_AutoPlayAnimations: String { return self._s[895]! } - public var SaveIncomingPhotosSettings_Title: String { return self._s[896]! } - public var OwnershipTransfer_SecurityRequirements: String { return self._s[897]! } - public var Map_LiveLocationFor1Hour: String { return self._s[898]! } + public var ProxyServer_VoiceOver_Active: String { return self._s[878]! } + public var Call_StatusBusy: String { return self._s[879]! } + public var Conversation_MessageDeliveryFailed: String { return self._s[880]! } + public var Login_NetworkError: String { return self._s[882]! } + public var TwoStepAuth_SetupPasswordDescription: String { return self._s[883]! } + public var Privacy_Calls_Integration: String { return self._s[884]! } + public var DialogList_SearchSectionMessages: String { return self._s[885]! } + public var AutoDownloadSettings_VideosTitle: String { return self._s[886]! } + public var Preview_DeletePhoto: String { return self._s[887]! } + public var PrivacySettings_PhoneNumber: String { return self._s[889]! } + public var Forward_ErrorDisabledForChat: String { return self._s[890]! } + public var Watch_Compose_CurrentLocation: String { return self._s[891]! } + public var Wallet_Info_TransactionFrom: String { return self._s[892]! } + public var Settings_CallSettings: String { return self._s[893]! } + public var AutoDownloadSettings_TypePrivateChats: String { return self._s[894]! } + public var ChatList_Context_MarkAllAsRead: String { return self._s[895]! } + public var ChatSettings_AutoPlayAnimations: String { return self._s[896]! } + public var SaveIncomingPhotosSettings_Title: String { return self._s[897]! } + public var OwnershipTransfer_SecurityRequirements: String { return self._s[898]! } + public var Map_LiveLocationFor1Hour: String { return self._s[899]! } public func Privacy_GroupsAndChannels_InviteToGroupError(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[899]!, self._r[899]!, [_0, _1]) + return formatWithArgumentRanges(self._s[900]!, self._r[900]!, [_0, _1]) } public func Notification_PinnedLiveLocationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[900]!, self._r[900]!, [_0]) + return formatWithArgumentRanges(self._s[901]!, self._r[901]!, [_0]) } - public var Conversation_UnvotePoll: String { return self._s[901]! } - public var TwoStepAuth_EnterEmailCode: String { return self._s[902]! } + public var Conversation_UnvotePoll: String { return self._s[902]! } + public var TwoStepAuth_EnterEmailCode: String { return self._s[903]! } public func LOCAL_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[903]!, self._r[903]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[904]!, self._r[904]!, [_1, "\(_2)"]) } - public var Passport_InfoTitle: String { return self._s[904]! } + public var Passport_InfoTitle: String { return self._s[905]! } public func Conversation_Bytes(_ _0: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[905]!, self._r[905]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[906]!, self._r[906]!, ["\(_0)"]) } - public var AccentColor_Title: String { return self._s[906]! } + public var AccentColor_Title: String { return self._s[907]! } public func PUSH_MESSAGE_INVOICE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[907]!, self._r[907]!, [_1, _2]) + return formatWithArgumentRanges(self._s[908]!, self._r[908]!, [_1, _2]) } public func Notification_JoinedChannel(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[910]!, self._r[910]!, [_0]) + return formatWithArgumentRanges(self._s[911]!, self._r[911]!, [_0]) } - public var AutoDownloadSettings_DataUsageCustom: String { return self._s[911]! } - public var Conversation_ShareBotLocationConfirmation: String { return self._s[912]! } - public var PrivacyPhoneNumberSettings_WhoCanSeeMyPhoneNumber: String { return self._s[913]! } - public var VoiceOver_Editing_ClearText: String { return self._s[914]! } - public var Conversation_Unarchive: String { return self._s[915]! } - public var Notification_CallOutgoing: String { return self._s[916]! } - public var Channel_Setup_PublicNoLink: String { return self._s[917]! } - public var Passport_Identity_GenderPlaceholder: String { return self._s[918]! } - public var Message_Animation: String { return self._s[919]! } - public var SettingsSearch_Synonyms_Appearance_Animations: String { return self._s[920]! } - public var ChatSettings_ConnectionType_Title: String { return self._s[921]! } + public var AutoDownloadSettings_DataUsageCustom: String { return self._s[912]! } + public var Conversation_ShareBotLocationConfirmation: String { return self._s[913]! } + public var PrivacyPhoneNumberSettings_WhoCanSeeMyPhoneNumber: String { return self._s[914]! } + public var VoiceOver_Editing_ClearText: String { return self._s[915]! } + public var Conversation_Unarchive: String { return self._s[916]! } + public var Notification_CallOutgoing: String { return self._s[917]! } + public var Channel_Setup_PublicNoLink: String { return self._s[918]! } + public var Passport_Identity_GenderPlaceholder: String { return self._s[919]! } + public var Message_Animation: String { return self._s[920]! } + public var SettingsSearch_Synonyms_Appearance_Animations: String { return self._s[921]! } + public var ChatSettings_ConnectionType_Title: String { return self._s[922]! } public func Watch_Time_ShortFullAt(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[922]!, self._r[922]!, [_1, _2]) + return formatWithArgumentRanges(self._s[923]!, self._r[923]!, [_1, _2]) } - public var Notification_CallBack: String { return self._s[924]! } - public var Appearance_Title: String { return self._s[926]! } - public var NotificationsSound_Glass: String { return self._s[928]! } - public var AutoDownloadSettings_CellularTitle: String { return self._s[930]! } - public var Notifications_PermissionsSuppressWarningTitle: String { return self._s[932]! } - public var ChatSearch_SearchPlaceholder: String { return self._s[933]! } - public var Passport_Identity_AddPassport: String { return self._s[934]! } + public var Notification_CallBack: String { return self._s[925]! } + public var Appearance_Title: String { return self._s[927]! } + public var NotificationsSound_Glass: String { return self._s[929]! } + public var AutoDownloadSettings_CellularTitle: String { return self._s[931]! } + public var Notifications_PermissionsSuppressWarningTitle: String { return self._s[933]! } + public var ChatSearch_SearchPlaceholder: String { return self._s[934]! } + public var Passport_Identity_AddPassport: String { return self._s[935]! } public func Wallet_Time_PreciseDate_m1(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[936]!, self._r[936]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[937]!, self._r[937]!, [_1, _2, _3]) } - public var GroupPermission_NoAddMembers: String { return self._s[937]! } - public var ContactList_Context_SendMessage: String { return self._s[938]! } - public var PhotoEditor_GrainTool: String { return self._s[939]! } - public var Settings_CopyPhoneNumber: String { return self._s[940]! } - public var Passport_Address_City: String { return self._s[941]! } - public var ChannelRemoved_RemoveInfo: String { return self._s[942]! } - public var SocksProxySetup_Password: String { return self._s[944]! } - public var Wallet_Configuration_ApplyErrorTextJSONInvalidData: String { return self._s[945]! } - public var Settings_Passport: String { return self._s[946]! } - public var Channel_MessagePhotoUpdated: String { return self._s[948]! } - public var Stats_LanguagesTitle: String { return self._s[949]! } - public var ChatList_PeerTypeGroup: String { return self._s[950]! } - public var Privacy_Calls_P2PHelp: String { return self._s[951]! } - public var VoiceOver_Chat_PollNoVotes: String { return self._s[952]! } - public var Embed_PlayingInPIP: String { return self._s[953]! } - public var BlockedUsers_BlockUser: String { return self._s[956]! } - public var Login_CancelPhoneVerificationContinue: String { return self._s[957]! } + public var GroupPermission_NoAddMembers: String { return self._s[938]! } + public var ContactList_Context_SendMessage: String { return self._s[939]! } + public var PhotoEditor_GrainTool: String { return self._s[940]! } + public var Settings_CopyPhoneNumber: String { return self._s[941]! } + public var Passport_Address_City: String { return self._s[942]! } + public var ChannelRemoved_RemoveInfo: String { return self._s[943]! } + public var SocksProxySetup_Password: String { return self._s[945]! } + public var Wallet_Configuration_ApplyErrorTextJSONInvalidData: String { return self._s[946]! } + public var Settings_Passport: String { return self._s[947]! } + public var Channel_MessagePhotoUpdated: String { return self._s[949]! } + public var Stats_LanguagesTitle: String { return self._s[950]! } + public var ChatList_PeerTypeGroup: String { return self._s[951]! } + public var Privacy_Calls_P2PHelp: String { return self._s[952]! } + public var VoiceOver_Chat_PollNoVotes: String { return self._s[953]! } + public var Embed_PlayingInPIP: String { return self._s[954]! } + public var BlockedUsers_BlockUser: String { return self._s[957]! } + public var Login_CancelPhoneVerificationContinue: String { return self._s[958]! } public func PUSH_CHANNEL_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[958]!, self._r[958]!, [_1]) + return formatWithArgumentRanges(self._s[959]!, self._r[959]!, [_1]) } - public var AuthSessions_LoggedIn: String { return self._s[959]! } - public var Channel_AdminLog_MessagePreviousCaption: String { return self._s[960]! } - public var Wallet_SecureStorageReset_PasscodeText: String { return self._s[961]! } - public var Activity_UploadingDocument: String { return self._s[962]! } - public var PeopleNearby_NoMembers: String { return self._s[963]! } - public var SettingsSearch_Synonyms_Stickers_Masks: String { return self._s[966]! } - public var ChatSettings_AutoPlayVideos: String { return self._s[967]! } - public var VoiceOver_Chat_OpenLinkHint: String { return self._s[968]! } - public var Settings_ViewVideo: String { return self._s[970]! } - public var Map_ShowPlaces: String { return self._s[972]! } - public var Passport_Phone_UseTelegramNumberHelp: String { return self._s[973]! } - public var SettingsSearch_Synonyms_Appearance_ChatBackground_Custom: String { return self._s[974]! } + public var AuthSessions_LoggedIn: String { return self._s[960]! } + public var Channel_AdminLog_MessagePreviousCaption: String { return self._s[961]! } + public var Wallet_SecureStorageReset_PasscodeText: String { return self._s[962]! } + public var Activity_UploadingDocument: String { return self._s[963]! } + public var PeopleNearby_NoMembers: String { return self._s[964]! } + public var SettingsSearch_Synonyms_Stickers_Masks: String { return self._s[967]! } + public var ChatSettings_AutoPlayVideos: String { return self._s[968]! } + public var VoiceOver_Chat_OpenLinkHint: String { return self._s[969]! } + public var Settings_ViewVideo: String { return self._s[971]! } + public var Map_ShowPlaces: String { return self._s[973]! } + public var Passport_Phone_UseTelegramNumberHelp: String { return self._s[974]! } + public var SettingsSearch_Synonyms_Appearance_ChatBackground_Custom: String { return self._s[975]! } public func PrivacySettings_LastSeenContactsPlus(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[975]!, self._r[975]!, [_0]) + return formatWithArgumentRanges(self._s[976]!, self._r[976]!, [_0]) } - public var Wallet_Month_ShortNovember: String { return self._s[976]! } - public var Conversation_StatusLeftGroup: String { return self._s[977]! } - public var Theme_Colors_Messages: String { return self._s[978]! } - public var AuthSessions_EmptyText: String { return self._s[979]! } + public var Wallet_Month_ShortNovember: String { return self._s[977]! } + public var Conversation_StatusLeftGroup: String { return self._s[978]! } + public var Theme_Colors_Messages: String { return self._s[979]! } + public var AuthSessions_EmptyText: String { return self._s[980]! } public func PUSH_MESSAGE_CONTACT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[980]!, self._r[980]!, [_1]) + return formatWithArgumentRanges(self._s[981]!, self._r[981]!, [_1]) } - public var UserInfo_StartSecretChat: String { return self._s[981]! } - public var ChatListFolderSettings_EditFoldersInfo: String { return self._s[982]! } - public var Channel_Edit_PrivatePublicLinkAlert: String { return self._s[983]! } - public var Conversation_ReportSpamGroupConfirmation: String { return self._s[984]! } - public var Conversation_PrivateMessageLinkCopied: String { return self._s[986]! } - public var PeerInfo_PaneFiles: String { return self._s[987]! } - public var PrivacySettings_AutoArchive: String { return self._s[988]! } - public var Camera_VideoMode: String { return self._s[989]! } - public var NotificationsSound_Alert: String { return self._s[990]! } - public var Privacy_Forwards_NeverAllow_Title: String { return self._s[991]! } - public var Appearance_AutoNightTheme: String { return self._s[992]! } - public var Passport_Language_he: String { return self._s[993]! } - public var Wallet_Configuration_BlockchainNameChangedText: String { return self._s[994]! } - public var Passport_InvalidPasswordError: String { return self._s[995]! } - public var Conversation_PinMessageAlert_OnlyPin: String { return self._s[996]! } - public var UserInfo_InviteBotToGroup: String { return self._s[997]! } - public var Conversation_SilentBroadcastTooltipOff: String { return self._s[998]! } - public var Common_TakePhoto: String { return self._s[999]! } - public var Passport_Email_UseTelegramEmailHelp: String { return self._s[1000]! } - public var Wallet_Configuration_ApplyErrorTextURLInvalid: String { return self._s[1001]! } - public var ChatList_Context_JoinChannel: String { return self._s[1002]! } - public var MediaPlayer_UnknownArtist: String { return self._s[1003]! } - public var KeyCommand_JumpToPreviousUnreadChat: String { return self._s[1006]! } - public var Channel_OwnershipTransfer_Title: String { return self._s[1007]! } - public var EditTheme_UploadEditedTheme: String { return self._s[1008]! } - public var Settings_SetProfilePhotoOrVideo: String { return self._s[1010]! } - public var Passport_FieldOneOf_Delimeter: String { return self._s[1011]! } - public var MessagePoll_ViewResults: String { return self._s[1012]! } - public var Group_Setup_TypePrivateHelp: String { return self._s[1013]! } - public var Passport_Address_OneOfTypeUtilityBill: String { return self._s[1014]! } - public var ChatList_Search_ShowLess: String { return self._s[1015]! } - public var UserInfo_ShareBot: String { return self._s[1016]! } - public var Privacy_Calls_P2P: String { return self._s[1018]! } - public var WebBrowser_InAppSafari: String { return self._s[1019]! } - public var SharedMedia_EmptyFilesText: String { return self._s[1020]! } - public var Channel_AdminLog_MessagePreviousMessage: String { return self._s[1022]! } - public var GroupInfo_SetSound: String { return self._s[1023]! } - public var Permissions_PeopleNearbyAllowInSettings_v0: String { return self._s[1024]! } - public var Channel_AdminLog_MessagePreviousDescription: String { return self._s[1025]! } - public var Channel_AdminLogFilter_EventsAll: String { return self._s[1026]! } - public var CallSettings_UseLessData: String { return self._s[1027]! } - public var InfoPlist_NSCameraUsageDescription: String { return self._s[1028]! } - public var NotificationsSound_Chord: String { return self._s[1029]! } - public var PhotoEditor_CurvesTool: String { return self._s[1030]! } - public var Appearance_ThemePreview_Chat_2_Text: String { return self._s[1031]! } - public var Resolve_ErrorNotFound: String { return self._s[1032]! } - public var Activity_PlayingGame: String { return self._s[1033]! } - public var Wallet_Send_UninitializedText: String { return self._s[1036]! } - public var StickerPacksSettings_AnimatedStickersInfo: String { return self._s[1037]! } + public var UserInfo_StartSecretChat: String { return self._s[982]! } + public var ChatListFolderSettings_EditFoldersInfo: String { return self._s[983]! } + public var Channel_Edit_PrivatePublicLinkAlert: String { return self._s[984]! } + public var Conversation_ReportSpamGroupConfirmation: String { return self._s[985]! } + public var Conversation_PrivateMessageLinkCopied: String { return self._s[987]! } + public var PeerInfo_PaneFiles: String { return self._s[988]! } + public var PrivacySettings_AutoArchive: String { return self._s[989]! } + public var Camera_VideoMode: String { return self._s[990]! } + public var NotificationsSound_Alert: String { return self._s[991]! } + public var Privacy_Forwards_NeverAllow_Title: String { return self._s[992]! } + public var Appearance_AutoNightTheme: String { return self._s[993]! } + public var Passport_Language_he: String { return self._s[994]! } + public var Wallet_Configuration_BlockchainNameChangedText: String { return self._s[995]! } + public var Passport_InvalidPasswordError: String { return self._s[996]! } + public var Conversation_PinMessageAlert_OnlyPin: String { return self._s[997]! } + public var UserInfo_InviteBotToGroup: String { return self._s[998]! } + public var Conversation_SilentBroadcastTooltipOff: String { return self._s[999]! } + public var Common_TakePhoto: String { return self._s[1000]! } + public var Passport_Email_UseTelegramEmailHelp: String { return self._s[1001]! } + public var Wallet_Configuration_ApplyErrorTextURLInvalid: String { return self._s[1002]! } + public var ChatList_Context_JoinChannel: String { return self._s[1003]! } + public var MediaPlayer_UnknownArtist: String { return self._s[1004]! } + public var KeyCommand_JumpToPreviousUnreadChat: String { return self._s[1007]! } + public var Channel_OwnershipTransfer_Title: String { return self._s[1008]! } + public var EditTheme_UploadEditedTheme: String { return self._s[1009]! } + public var Settings_SetProfilePhotoOrVideo: String { return self._s[1011]! } + public var Passport_FieldOneOf_Delimeter: String { return self._s[1012]! } + public var MessagePoll_ViewResults: String { return self._s[1013]! } + public var Group_Setup_TypePrivateHelp: String { return self._s[1014]! } + public var Passport_Address_OneOfTypeUtilityBill: String { return self._s[1015]! } + public var ChatList_Search_ShowLess: String { return self._s[1016]! } + public var UserInfo_ShareBot: String { return self._s[1017]! } + public var Privacy_Calls_P2P: String { return self._s[1019]! } + public var WebBrowser_InAppSafari: String { return self._s[1020]! } + public var SharedMedia_EmptyFilesText: String { return self._s[1021]! } + public var Channel_AdminLog_MessagePreviousMessage: String { return self._s[1023]! } + public var GroupInfo_SetSound: String { return self._s[1024]! } + public var Permissions_PeopleNearbyAllowInSettings_v0: String { return self._s[1025]! } + public var Channel_AdminLog_MessagePreviousDescription: String { return self._s[1026]! } + public var Channel_AdminLogFilter_EventsAll: String { return self._s[1027]! } + public var CallSettings_UseLessData: String { return self._s[1028]! } + public var InfoPlist_NSCameraUsageDescription: String { return self._s[1029]! } + public var NotificationsSound_Chord: String { return self._s[1030]! } + public var PhotoEditor_CurvesTool: String { return self._s[1031]! } + public var Appearance_ThemePreview_Chat_2_Text: String { return self._s[1032]! } + public var Resolve_ErrorNotFound: String { return self._s[1033]! } + public var Activity_PlayingGame: String { return self._s[1034]! } + public var Wallet_Send_UninitializedText: String { return self._s[1037]! } + public var StickerPacksSettings_AnimatedStickersInfo: String { return self._s[1038]! } public func PUSH_CHANNEL_MESSAGE_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1038]!, self._r[1038]!, [_1]) + return formatWithArgumentRanges(self._s[1039]!, self._r[1039]!, [_1]) } - public var Conversation_ShareBotContactConfirmationTitle: String { return self._s[1039]! } - public var Notification_CallIncoming: String { return self._s[1040]! } - public var Stats_EnabledNotifications: String { return self._s[1041]! } - public var Notifications_PermissionsOpenSettings: String { return self._s[1042]! } - public var Checkout_ErrorProviderAccountTimeout: String { return self._s[1043]! } + public var Conversation_ShareBotContactConfirmationTitle: String { return self._s[1040]! } + public var Notification_CallIncoming: String { return self._s[1041]! } + public var Stats_EnabledNotifications: String { return self._s[1042]! } + public var Notifications_PermissionsOpenSettings: String { return self._s[1043]! } + public var Checkout_ErrorProviderAccountTimeout: String { return self._s[1044]! } public func Activity_RemindAboutChannel(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1044]!, self._r[1044]!, [_0]) + return formatWithArgumentRanges(self._s[1045]!, self._r[1045]!, [_0]) } - public var VoiceOver_Chat_ReplyToYourMessage: String { return self._s[1045]! } - public var Channel_DiscussionGroup_MakeHistoryPublic: String { return self._s[1046]! } - public var StickerPacksSettings_Title: String { return self._s[1047]! } + public var VoiceOver_Chat_ReplyToYourMessage: String { return self._s[1046]! } + public var Channel_DiscussionGroup_MakeHistoryPublic: String { return self._s[1047]! } + public var StickerPacksSettings_Title: String { return self._s[1048]! } public func Channel_AdminLog_MessageGroupPreHistoryVisible(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1048]!, self._r[1048]!, [_0]) + return formatWithArgumentRanges(self._s[1049]!, self._r[1049]!, [_0]) } - public var Watch_NoConnection: String { return self._s[1049]! } - public var EncryptionKey_Title: String { return self._s[1050]! } - public var Widget_AuthRequired: String { return self._s[1051]! } + public var Watch_NoConnection: String { return self._s[1050]! } + public var EncryptionKey_Title: String { return self._s[1051]! } + public var Widget_AuthRequired: String { return self._s[1052]! } public func PUSH_MESSAGE_ROUND(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1052]!, self._r[1052]!, [_1]) + return formatWithArgumentRanges(self._s[1053]!, self._r[1053]!, [_1]) } - public var Notifications_ExceptionsTitle: String { return self._s[1053]! } - public var EditTheme_Expand_TopInfo: String { return self._s[1054]! } + public var Notifications_ExceptionsTitle: String { return self._s[1054]! } + public var EditTheme_Expand_TopInfo: String { return self._s[1055]! } public func Contacts_AddPhoneNumber(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1055]!, self._r[1055]!, [_0]) + return formatWithArgumentRanges(self._s[1056]!, self._r[1056]!, [_0]) } - public var Channel_AdminLogFilter_EventsRestrictions: String { return self._s[1057]! } - public var Notifications_GroupNotificationsSound: String { return self._s[1058]! } - public var Passport_Email_EnterOtherEmail: String { return self._s[1059]! } - public var Conversation_AddToContacts: String { return self._s[1062]! } - public var AutoDownloadSettings_DataUsageMedium: String { return self._s[1063]! } - public var AuthSessions_LogOutApplications: String { return self._s[1065]! } - public var ChatList_Context_Unpin: String { return self._s[1066]! } - public var PeopleNearby_DiscoverDescription: String { return self._s[1067]! } - public var Notification_MessageLifetime1d: String { return self._s[1068]! } - public var PrivacyLastSeenSettings_NeverShareWith_Title: String { return self._s[1069]! } - public var ChatListFolder_CategoryChannels: String { return self._s[1070]! } - public var VoiceOver_Chat_SeenByRecipient: String { return self._s[1071]! } - public var Notifications_PermissionsAllow: String { return self._s[1072]! } - public var Undo_ScheduledMessagesCleared: String { return self._s[1073]! } - public var AutoDownloadSettings_PrivateChats: String { return self._s[1075]! } - public var ApplyLanguage_ChangeLanguageAction: String { return self._s[1076]! } + public var Channel_AdminLogFilter_EventsRestrictions: String { return self._s[1058]! } + public var Notifications_GroupNotificationsSound: String { return self._s[1059]! } + public var Passport_Email_EnterOtherEmail: String { return self._s[1060]! } + public var Conversation_AddToContacts: String { return self._s[1063]! } + public var AutoDownloadSettings_DataUsageMedium: String { return self._s[1064]! } + public var AuthSessions_LogOutApplications: String { return self._s[1066]! } + public var ChatList_Context_Unpin: String { return self._s[1067]! } + public var PeopleNearby_DiscoverDescription: String { return self._s[1068]! } + public var Notification_MessageLifetime1d: String { return self._s[1069]! } + public var PrivacyLastSeenSettings_NeverShareWith_Title: String { return self._s[1070]! } + public var ChatListFolder_CategoryChannels: String { return self._s[1071]! } + public var VoiceOver_Chat_SeenByRecipient: String { return self._s[1072]! } + public var Notifications_PermissionsAllow: String { return self._s[1073]! } + public var Undo_ScheduledMessagesCleared: String { return self._s[1074]! } + public var AutoDownloadSettings_PrivateChats: String { return self._s[1076]! } + public var ApplyLanguage_ChangeLanguageAction: String { return self._s[1077]! } public func PrivacySettings_LastSeenNobodyPlus(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1077]!, self._r[1077]!, [_0]) + return formatWithArgumentRanges(self._s[1078]!, self._r[1078]!, [_0]) } - public var Wallet_WordImport_Title: String { return self._s[1078]! } - public var Notifications_MessageNotificationsHelp: String { return self._s[1081]! } - public var WallpaperSearch_ColorPink: String { return self._s[1082]! } - public var ContactInfo_PhoneNumberHidden: String { return self._s[1083]! } - public var Passport_Identity_IssueDate: String { return self._s[1085]! } + public var Wallet_WordImport_Title: String { return self._s[1079]! } + public var Notifications_MessageNotificationsHelp: String { return self._s[1082]! } + public var WallpaperSearch_ColorPink: String { return self._s[1083]! } + public var ContactInfo_PhoneNumberHidden: String { return self._s[1084]! } + public var Passport_Identity_IssueDate: String { return self._s[1086]! } public func PUSH_CHAT_MESSAGE_GIF(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1086]!, self._r[1086]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1087]!, self._r[1087]!, [_1, _2]) } - public var PrivacySettings_DeleteAccountIfAwayFor: String { return self._s[1087]! } - public var Channel_Info_Description: String { return self._s[1088]! } - public var Common_Back: String { return self._s[1089]! } - public var Weekday_ShortTuesday: String { return self._s[1090]! } - public var Chat_PinnedMessagesHiddenTitle: String { return self._s[1092]! } - public var ChatListFolder_AddChats: String { return self._s[1093]! } - public var Common_Close: String { return self._s[1095]! } - public var Map_OpenIn: String { return self._s[1096]! } - public var Group_Setup_HistoryTitle: String { return self._s[1097]! } + public var PrivacySettings_DeleteAccountIfAwayFor: String { return self._s[1088]! } + public var Channel_Info_Description: String { return self._s[1089]! } + public var Common_Back: String { return self._s[1090]! } + public var Weekday_ShortTuesday: String { return self._s[1091]! } + public var Chat_PinnedMessagesHiddenTitle: String { return self._s[1093]! } + public var ChatListFolder_AddChats: String { return self._s[1094]! } + public var Common_Close: String { return self._s[1096]! } + public var Map_OpenIn: String { return self._s[1097]! } + public var Group_Setup_HistoryTitle: String { return self._s[1098]! } public func Wallet_Info_TransactionDateHeaderYear(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1098]!, self._r[1098]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1099]!, self._r[1099]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_Data_AutoDownloadUsingWifi: String { return self._s[1099]! } - public var Notification_MessageLifetime1h: String { return self._s[1100]! } + public var SettingsSearch_Synonyms_Data_AutoDownloadUsingWifi: String { return self._s[1100]! } + public var Notification_MessageLifetime1h: String { return self._s[1101]! } public func CancelResetAccount_Success(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1101]!, self._r[1101]!, [_0]) + return formatWithArgumentRanges(self._s[1102]!, self._r[1102]!, [_0]) } - public var Watch_Contacts_NoResults: String { return self._s[1103]! } - public var TwoStepAuth_SetupResendEmailCode: String { return self._s[1104]! } - public var Checkout_Phone: String { return self._s[1105]! } - public var OwnershipTransfer_ComeBackLater: String { return self._s[1106]! } + public var Watch_Contacts_NoResults: String { return self._s[1104]! } + public var TwoStepAuth_SetupResendEmailCode: String { return self._s[1105]! } + public var Checkout_Phone: String { return self._s[1106]! } + public var OwnershipTransfer_ComeBackLater: String { return self._s[1107]! } public func DialogList_MultipleTypingSuffix(_ _0: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1107]!, self._r[1107]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[1108]!, self._r[1108]!, ["\(_0)"]) } public func Channel_CommentsGroup_HeaderGroupSet(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1108]!, self._r[1108]!, [_0]) + return formatWithArgumentRanges(self._s[1109]!, self._r[1109]!, [_0]) } - public var ChatAdmins_Title: String { return self._s[1109]! } - public var Appearance_ThemePreview_Chat_7_Text: String { return self._s[1110]! } + public var ChatAdmins_Title: String { return self._s[1110]! } + public var Appearance_ThemePreview_Chat_7_Text: String { return self._s[1111]! } public func PUSH_CHANNEL_MESSAGE_POLL(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1111]!, self._r[1111]!, [_1]) + return formatWithArgumentRanges(self._s[1112]!, self._r[1112]!, [_1]) } - public var Common_Done: String { return self._s[1112]! } - public var Wallet_Send_AddressHeader: String { return self._s[1115]! } + public var Common_Done: String { return self._s[1113]! } + public var Wallet_Send_AddressHeader: String { return self._s[1116]! } public func PUSH_PINNED_VIDEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1117]!, self._r[1117]!, [_1]) + return formatWithArgumentRanges(self._s[1118]!, self._r[1118]!, [_1]) } - public var Appearance_ThemeCarouselNight: String { return self._s[1118]! } - public var Preview_OpenInInstagram: String { return self._s[1120]! } - public var Wallpaper_SetColor: String { return self._s[1124]! } - public var VoiceOver_Media_PlaybackRate: String { return self._s[1125]! } - public var ChatSettings_Groups: String { return self._s[1126]! } + public var Appearance_ThemeCarouselNight: String { return self._s[1119]! } + public var Preview_OpenInInstagram: String { return self._s[1121]! } + public var Wallpaper_SetColor: String { return self._s[1125]! } + public var VoiceOver_Media_PlaybackRate: String { return self._s[1126]! } + public var ChatSettings_Groups: String { return self._s[1127]! } public func VoiceOver_Chat_VoiceMessageFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1127]!, self._r[1127]!, [_0]) + return formatWithArgumentRanges(self._s[1128]!, self._r[1128]!, [_0]) } - public var Contacts_SortedByName: String { return self._s[1128]! } - public var SettingsSearch_Synonyms_Notifications_ContactJoined: String { return self._s[1129]! } - public var Wallet_Send_Title: String { return self._s[1130]! } - public var Channel_Management_LabelCreator: String { return self._s[1131]! } - public var Contacts_PermissionsSuppressWarningTitle: String { return self._s[1132]! } + public var Contacts_SortedByName: String { return self._s[1129]! } + public var SettingsSearch_Synonyms_Notifications_ContactJoined: String { return self._s[1130]! } + public var Wallet_Send_Title: String { return self._s[1131]! } + public var Channel_Management_LabelCreator: String { return self._s[1132]! } + public var Contacts_PermissionsSuppressWarningTitle: String { return self._s[1133]! } public func PrivacySettings_LastSeenContactsMinusPlus(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1133]!, self._r[1133]!, [_0, _1]) + return formatWithArgumentRanges(self._s[1134]!, self._r[1134]!, [_0, _1]) } - public var Group_PublicLink_Title: String { return self._s[1134]! } - public var Channel_OwnershipTransfer_ErrorAdminsTooMuch: String { return self._s[1135]! } - public var VoiceOver_Chat_Photo: String { return self._s[1136]! } - public var TwoFactorSetup_EmailVerification_Placeholder: String { return self._s[1137]! } - public var IntentsSettings_SuggestBy: String { return self._s[1138]! } - public var Privacy_Calls_AlwaysAllow_Placeholder: String { return self._s[1139]! } - public var Appearance_ThemePreview_ChatList_1_Name: String { return self._s[1140]! } - public var PhoneNumberHelp_ChangeNumber: String { return self._s[1141]! } - public var LogoutOptions_SetPasscodeText: String { return self._s[1142]! } - public var Map_OpenInMaps: String { return self._s[1143]! } - public var ContactInfo_PhoneLabelWorkFax: String { return self._s[1144]! } - public var BlockedUsers_Unblock: String { return self._s[1145]! } + public var Group_PublicLink_Title: String { return self._s[1135]! } + public var Channel_OwnershipTransfer_ErrorAdminsTooMuch: String { return self._s[1136]! } + public var VoiceOver_Chat_Photo: String { return self._s[1137]! } + public var TwoFactorSetup_EmailVerification_Placeholder: String { return self._s[1138]! } + public var IntentsSettings_SuggestBy: String { return self._s[1139]! } + public var Privacy_Calls_AlwaysAllow_Placeholder: String { return self._s[1140]! } + public var Appearance_ThemePreview_ChatList_1_Name: String { return self._s[1141]! } + public var PhoneNumberHelp_ChangeNumber: String { return self._s[1142]! } + public var LogoutOptions_SetPasscodeText: String { return self._s[1143]! } + public var Map_OpenInMaps: String { return self._s[1144]! } + public var ContactInfo_PhoneLabelWorkFax: String { return self._s[1145]! } + public var BlockedUsers_Unblock: String { return self._s[1146]! } public func Settings_ApplyProxyAlert(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1146]!, self._r[1146]!, [_1, _2]) - } - public func Channel_AdminLog_MessageRestrictedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[1147]!, self._r[1147]!, [_1, _2]) } - public var Conversation_Block: String { return self._s[1149]! } - public var Passport_Scans_UploadNew: String { return self._s[1150]! } - public var Share_Title: String { return self._s[1151]! } - public var Wallet_Send_SendAnyway: String { return self._s[1152]! } + public func Channel_AdminLog_MessageRestrictedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1148]!, self._r[1148]!, [_1, _2]) + } + public var Conversation_Block: String { return self._s[1150]! } + public var Passport_Scans_UploadNew: String { return self._s[1151]! } + public var Share_Title: String { return self._s[1152]! } + public var Wallet_Send_SendAnyway: String { return self._s[1153]! } public func Wallet_Time_PreciseDate_m8(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1153]!, self._r[1153]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1154]!, self._r[1154]!, [_1, _2, _3]) } - public var Conversation_ApplyLocalization: String { return self._s[1154]! } - public var SharedMedia_EmptyLinksText: String { return self._s[1155]! } - public var Settings_NotificationsAndSounds: String { return self._s[1156]! } - public var Stats_ViewsByHoursTitle: String { return self._s[1157]! } - public var PhotoEditor_QualityMedium: String { return self._s[1158]! } - public var Conversation_ContextMenuCancelSending: String { return self._s[1159]! } + public var Conversation_ApplyLocalization: String { return self._s[1155]! } + public var SharedMedia_EmptyLinksText: String { return self._s[1156]! } + public var Settings_NotificationsAndSounds: String { return self._s[1157]! } + public var Stats_ViewsByHoursTitle: String { return self._s[1158]! } + public var PhotoEditor_QualityMedium: String { return self._s[1159]! } + public var Conversation_ContextMenuCancelSending: String { return self._s[1160]! } public func PUSH_CHANNEL_MESSAGE_GAME(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1160]!, self._r[1160]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1161]!, self._r[1161]!, [_1, _2]) } - public var Conversation_RestrictedInline: String { return self._s[1161]! } - public var Passport_Language_tr: String { return self._s[1162]! } - public var Call_Mute: String { return self._s[1163]! } + public var Conversation_RestrictedInline: String { return self._s[1162]! } + public var Passport_Language_tr: String { return self._s[1163]! } + public var Call_Mute: String { return self._s[1164]! } public func Conversation_NoticeInvitedByInGroup(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1164]!, self._r[1164]!, [_0]) + return formatWithArgumentRanges(self._s[1165]!, self._r[1165]!, [_0]) } - public var Passport_Language_bn: String { return self._s[1165]! } - public var AccessDenied_LocationTracking: String { return self._s[1167]! } - public var Month_ShortOctober: String { return self._s[1168]! } - public var AutoDownloadSettings_WiFi: String { return self._s[1169]! } - public var ProfilePhoto_SetMainPhoto: String { return self._s[1171]! } - public var ChangePhoneNumberNumber_NewNumber: String { return self._s[1172]! } + public var Passport_Language_bn: String { return self._s[1166]! } + public var AccessDenied_LocationTracking: String { return self._s[1168]! } + public var Month_ShortOctober: String { return self._s[1169]! } + public var AutoDownloadSettings_WiFi: String { return self._s[1170]! } + public var ProfilePhoto_SetMainPhoto: String { return self._s[1172]! } + public var ChangePhoneNumberNumber_NewNumber: String { return self._s[1173]! } public func Time_MonthOfYear_m3(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1173]!, self._r[1173]!, [_0]) + return formatWithArgumentRanges(self._s[1174]!, self._r[1174]!, [_0]) } - public var Watch_ChannelInfo_Title: String { return self._s[1174]! } - public var State_Updating: String { return self._s[1175]! } - public var Conversation_UnblockUser: String { return self._s[1176]! } - public var Notifications_ChannelNotificationsSound: String { return self._s[1177]! } - public var Map_GetDirections: String { return self._s[1178]! } - public var Watch_Compose_AddContact: String { return self._s[1180]! } - public var Conversation_Dice_u26BD: String { return self._s[1181]! } - public var AccessDenied_PhotosRestricted: String { return self._s[1182]! } + public var Watch_ChannelInfo_Title: String { return self._s[1175]! } + public var State_Updating: String { return self._s[1176]! } + public var Conversation_UnblockUser: String { return self._s[1177]! } + public var Notifications_ChannelNotificationsSound: String { return self._s[1178]! } + public var Map_GetDirections: String { return self._s[1179]! } + public var Watch_Compose_AddContact: String { return self._s[1181]! } + public var Conversation_Dice_u26BD: String { return self._s[1182]! } + public var AccessDenied_PhotosRestricted: String { return self._s[1183]! } public func Channel_AdminLog_MessageRank(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1183]!, self._r[1183]!, [_1]) + return formatWithArgumentRanges(self._s[1184]!, self._r[1184]!, [_1]) } - public var Wallet_UnknownError: String { return self._s[1185]! } - public var Map_LoadError: String { return self._s[1186]! } - public var SettingsSearch_Synonyms_Privacy_Calls: String { return self._s[1187]! } - public var PhotoEditor_CropAuto: String { return self._s[1188]! } - public var Wallet_Month_ShortApril: String { return self._s[1191]! } + public var Wallet_UnknownError: String { return self._s[1186]! } + public var Map_LoadError: String { return self._s[1187]! } + public var SettingsSearch_Synonyms_Privacy_Calls: String { return self._s[1188]! } + public var PhotoEditor_CropAuto: String { return self._s[1189]! } + public var Wallet_Month_ShortApril: String { return self._s[1192]! } public func Target_ShareGameConfirmationPrivate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1192]!, self._r[1192]!, [_0]) + return formatWithArgumentRanges(self._s[1193]!, self._r[1193]!, [_0]) } public func PUSH_PINNED_GAME(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1194]!, self._r[1194]!, [_1]) + return formatWithArgumentRanges(self._s[1195]!, self._r[1195]!, [_1]) } - public var Username_TooManyPublicUsernamesError: String { return self._s[1195]! } - public var Settings_PhoneNumber: String { return self._s[1196]! } + public var Username_TooManyPublicUsernamesError: String { return self._s[1196]! } + public var Settings_PhoneNumber: String { return self._s[1197]! } public func Channel_AdminLog_MessageTransferedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1197]!, self._r[1197]!, [_1]) + return formatWithArgumentRanges(self._s[1198]!, self._r[1198]!, [_1]) } - public var Month_GenJune: String { return self._s[1199]! } - public var Notifications_ExceptionsGroupPlaceholder: String { return self._s[1200]! } - public var ChatListFolder_CategoryRead: String { return self._s[1201]! } - public var LoginPassword_ResetAccount: String { return self._s[1202]! } + public var Month_GenJune: String { return self._s[1200]! } + public var Notifications_ExceptionsGroupPlaceholder: String { return self._s[1201]! } + public var ChatListFolder_CategoryRead: String { return self._s[1202]! } + public var LoginPassword_ResetAccount: String { return self._s[1203]! } public func DialogList_SingleUploadingFileSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1203]!, self._r[1203]!, [_0]) + return formatWithArgumentRanges(self._s[1204]!, self._r[1204]!, [_0]) } - public var Call_CameraConfirmationConfirm: String { return self._s[1204]! } - public var Notification_RenamedChannel: String { return self._s[1205]! } + public var Call_CameraConfirmationConfirm: String { return self._s[1205]! } + public var Notification_RenamedChannel: String { return self._s[1206]! } public func Channel_AdminLog_MessageUnpinned(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1206]!, self._r[1206]!, [_0]) + return formatWithArgumentRanges(self._s[1207]!, self._r[1207]!, [_0]) } - public var Channel_AdminLogFilter_EventsAdmins: String { return self._s[1207]! } - public var IntentsSettings_Title: String { return self._s[1209]! } - public var Settings_AppleWatch: String { return self._s[1210]! } - public var DialogList_NoMessagesText: String { return self._s[1211]! } - public var GroupPermission_NoChangeInfo: String { return self._s[1212]! } - public var Channel_ErrorAccessDenied: String { return self._s[1214]! } - public var ScheduledMessages_EmptyPlaceholder: String { return self._s[1215]! } + public var Channel_AdminLogFilter_EventsAdmins: String { return self._s[1208]! } + public var IntentsSettings_Title: String { return self._s[1210]! } + public var Settings_AppleWatch: String { return self._s[1211]! } + public var DialogList_NoMessagesText: String { return self._s[1212]! } + public var GroupPermission_NoChangeInfo: String { return self._s[1213]! } + public var Channel_ErrorAccessDenied: String { return self._s[1215]! } + public var ScheduledMessages_EmptyPlaceholder: String { return self._s[1216]! } public func Message_StickerText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1217]!, self._r[1217]!, [_0]) + return formatWithArgumentRanges(self._s[1218]!, self._r[1218]!, [_0]) } - public var AuthSessions_TerminateOtherSessionsHelp: String { return self._s[1218]! } - public var StickerPacksSettings_AnimatedStickers: String { return self._s[1219]! } - public var Month_ShortJanuary: String { return self._s[1220]! } - public var Conversation_UnreadMessages: String { return self._s[1221]! } - public var Conversation_PrivateChannelTooltip: String { return self._s[1223]! } - public var PrivacySettings_DeleteAccountTitle: String { return self._s[1225]! } - public var Channel_Members_AddBannedErrorAdmin: String { return self._s[1226]! } + public var AuthSessions_TerminateOtherSessionsHelp: String { return self._s[1219]! } + public var StickerPacksSettings_AnimatedStickers: String { return self._s[1220]! } + public var Month_ShortJanuary: String { return self._s[1221]! } + public var Conversation_UnreadMessages: String { return self._s[1222]! } + public var Conversation_PrivateChannelTooltip: String { return self._s[1224]! } + public var PrivacySettings_DeleteAccountTitle: String { return self._s[1226]! } + public var Channel_Members_AddBannedErrorAdmin: String { return self._s[1227]! } public func Conversation_ShareMyPhoneNumberConfirmation(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1229]!, self._r[1229]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1230]!, self._r[1230]!, [_1, _2]) } - public var Widget_ApplicationLocked: String { return self._s[1230]! } + public var Widget_ApplicationLocked: String { return self._s[1231]! } public func TextFormat_AddLinkText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1231]!, self._r[1231]!, [_0]) + return formatWithArgumentRanges(self._s[1232]!, self._r[1232]!, [_0]) } - public var Common_TakePhotoOrVideo: String { return self._s[1232]! } - public var Passport_Language_ru: String { return self._s[1233]! } - public var MediaPicker_VideoMuteDescription: String { return self._s[1234]! } - public var EditTheme_ErrorLinkTaken: String { return self._s[1235]! } + public var Common_TakePhotoOrVideo: String { return self._s[1233]! } + public var Passport_Language_ru: String { return self._s[1234]! } + public var MediaPicker_VideoMuteDescription: String { return self._s[1235]! } + public var EditTheme_ErrorLinkTaken: String { return self._s[1236]! } public func Group_EditAdmin_RankInfo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1237]!, self._r[1237]!, [_0]) + return formatWithArgumentRanges(self._s[1238]!, self._r[1238]!, [_0]) } - public var Channel_Members_AddAdminErrorBlacklisted: String { return self._s[1238]! } - public var Conversation_Owner: String { return self._s[1240]! } - public var Settings_FAQ_Intro: String { return self._s[1241]! } - public var PhotoEditor_QualityLow: String { return self._s[1243]! } - public var Widget_GalleryTitle: String { return self._s[1244]! } - public var Call_End: String { return self._s[1245]! } - public var StickerPacksSettings_FeaturedPacks: String { return self._s[1247]! } - public var Privacy_ContactsSyncHelp: String { return self._s[1248]! } - public var OldChannels_NoticeUpgradeText: String { return self._s[1252]! } - public var Conversation_Call: String { return self._s[1254]! } - public var Watch_MessageView_Title: String { return self._s[1255]! } + public var Channel_Members_AddAdminErrorBlacklisted: String { return self._s[1239]! } + public var Conversation_Owner: String { return self._s[1241]! } + public var Settings_FAQ_Intro: String { return self._s[1242]! } + public var PhotoEditor_QualityLow: String { return self._s[1244]! } + public var Widget_GalleryTitle: String { return self._s[1245]! } + public var Call_End: String { return self._s[1246]! } + public var StickerPacksSettings_FeaturedPacks: String { return self._s[1248]! } + public var Privacy_ContactsSyncHelp: String { return self._s[1249]! } + public var OldChannels_NoticeUpgradeText: String { return self._s[1253]! } + public var Conversation_Call: String { return self._s[1255]! } + public var Watch_MessageView_Title: String { return self._s[1256]! } public func Notification_RenamedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1256]!, self._r[1256]!, [_0]) + return formatWithArgumentRanges(self._s[1257]!, self._r[1257]!, [_0]) } - public var Passport_PasswordCompleteSetup: String { return self._s[1257]! } + public var Passport_PasswordCompleteSetup: String { return self._s[1258]! } public func Notification_ChangedGroupVideo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1258]!, self._r[1258]!, [_0]) + return formatWithArgumentRanges(self._s[1259]!, self._r[1259]!, [_0]) } public func TwoFactorSetup_EmailVerification_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1260]!, self._r[1260]!, [_0]) + return formatWithArgumentRanges(self._s[1261]!, self._r[1261]!, [_0]) } - public var Map_Location: String { return self._s[1261]! } - public var Watch_MessageView_ViewOnPhone: String { return self._s[1262]! } - public var Login_CountryCode: String { return self._s[1263]! } - public var Wallet_Settings_ConfigurationInfo: String { return self._s[1264]! } - public var Channel_DiscussionGroup_PrivateGroup: String { return self._s[1265]! } - public var ChatState_ConnectingToProxy: String { return self._s[1266]! } - public var Login_CallRequestState3: String { return self._s[1267]! } - public var NetworkUsageSettings_MediaAudioDataSection: String { return self._s[1269]! } - public var SocksProxySetup_ProxyStatusConnecting: String { return self._s[1270]! } - public var PrivacyLastSeenSettings_NeverShareWith_Placeholder: String { return self._s[1273]! } - public var Call_StatusEnded: String { return self._s[1274]! } - public var MusicPlayer_VoiceNote: String { return self._s[1277]! } + public var Map_Location: String { return self._s[1262]! } + public var Watch_MessageView_ViewOnPhone: String { return self._s[1263]! } + public var Login_CountryCode: String { return self._s[1264]! } + public var Wallet_Settings_ConfigurationInfo: String { return self._s[1265]! } + public var Channel_DiscussionGroup_PrivateGroup: String { return self._s[1266]! } + public var ChatState_ConnectingToProxy: String { return self._s[1267]! } + public var Login_CallRequestState3: String { return self._s[1268]! } + public var NetworkUsageSettings_MediaAudioDataSection: String { return self._s[1270]! } + public var SocksProxySetup_ProxyStatusConnecting: String { return self._s[1271]! } + public var PrivacyLastSeenSettings_NeverShareWith_Placeholder: String { return self._s[1274]! } + public var Call_StatusEnded: String { return self._s[1275]! } + public var MusicPlayer_VoiceNote: String { return self._s[1278]! } public func PUSH_CHANNEL_MESSAGE_TEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1278]!, self._r[1278]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1279]!, self._r[1279]!, [_1, _2]) } - public var VoiceOver_MessageContextShare: String { return self._s[1279]! } - public var ProfilePhoto_SearchWeb: String { return self._s[1280]! } - public var EditProfile_Title: String { return self._s[1281]! } + public var VoiceOver_MessageContextShare: String { return self._s[1280]! } + public var ProfilePhoto_SearchWeb: String { return self._s[1281]! } + public var EditProfile_Title: String { return self._s[1282]! } public func Notification_PinnedQuizMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1282]!, self._r[1282]!, [_0]) + return formatWithArgumentRanges(self._s[1283]!, self._r[1283]!, [_0]) } - public var ChangePhoneNumberCode_CodePlaceholder: String { return self._s[1283]! } - public var NetworkUsageSettings_ResetStats: String { return self._s[1285]! } - public var Wallet_Qr_ScanCode: String { return self._s[1286]! } - public var NetworkUsageSettings_GeneralDataSection: String { return self._s[1287]! } - public var StickerPackActionInfo_AddedTitle: String { return self._s[1288]! } - public var Channel_BanUser_PermissionSendStickersAndGifs: String { return self._s[1289]! } + public var ChangePhoneNumberCode_CodePlaceholder: String { return self._s[1284]! } + public var NetworkUsageSettings_ResetStats: String { return self._s[1286]! } + public var Wallet_Qr_ScanCode: String { return self._s[1287]! } + public var NetworkUsageSettings_GeneralDataSection: String { return self._s[1288]! } + public var StickerPackActionInfo_AddedTitle: String { return self._s[1289]! } + public var Channel_BanUser_PermissionSendStickersAndGifs: String { return self._s[1290]! } public func Call_ParticipantVideoVersionOutdatedError(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1290]!, self._r[1290]!, [_0]) + return formatWithArgumentRanges(self._s[1291]!, self._r[1291]!, [_0]) } - public var AuthSessions_AddDeviceIntro_Text1: String { return self._s[1292]! } - public var Location_ProximityNotification_Title: String { return self._s[1294]! } - public var Passport_Identity_LatinNameHelp: String { return self._s[1295]! } - public var AuthSessions_AddDeviceIntro_Text2: String { return self._s[1296]! } - public var Stats_GroupMembersTitle: String { return self._s[1297]! } - public var AuthSessions_AddDeviceIntro_Text3: String { return self._s[1298]! } - public var Contacts_PermissionsSuppressWarningText: String { return self._s[1299]! } - public var OpenFile_PotentiallyDangerousContentAlert: String { return self._s[1300]! } - public var Wallet_Info_Address: String { return self._s[1301]! } - public var Settings_SetUsername: String { return self._s[1302]! } - public var GroupInfo_ActionRestrict: String { return self._s[1303]! } + public var AuthSessions_AddDeviceIntro_Text1: String { return self._s[1293]! } + public var Location_ProximityNotification_Title: String { return self._s[1295]! } + public var Passport_Identity_LatinNameHelp: String { return self._s[1296]! } + public var AuthSessions_AddDeviceIntro_Text2: String { return self._s[1297]! } + public var Stats_GroupMembersTitle: String { return self._s[1298]! } + public var AuthSessions_AddDeviceIntro_Text3: String { return self._s[1299]! } + public var Contacts_PermissionsSuppressWarningText: String { return self._s[1300]! } + public var OpenFile_PotentiallyDangerousContentAlert: String { return self._s[1301]! } + public var Wallet_Info_Address: String { return self._s[1302]! } + public var Settings_SetUsername: String { return self._s[1303]! } + public var GroupInfo_ActionRestrict: String { return self._s[1304]! } public func Wallet_Configuration_ApplyErrorTextURLUnreachable(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1304]!, self._r[1304]!, [_0]) + return formatWithArgumentRanges(self._s[1305]!, self._r[1305]!, [_0]) } - public var SettingsSearch_Synonyms_SavedMessages: String { return self._s[1305]! } + public var SettingsSearch_Synonyms_SavedMessages: String { return self._s[1306]! } public func Time_PreciseDate_m2(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1306]!, self._r[1306]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1307]!, self._r[1307]!, [_1, _2, _3]) } - public var Notifications_DisplayNamesOnLockScreenInfoWithLink: String { return self._s[1307]! } - public var Notification_Exceptions_AlwaysOff: String { return self._s[1308]! } - public var Conversation_ContextMenuDelete: String { return self._s[1309]! } - public var Privacy_Calls_WhoCanCallMe: String { return self._s[1310]! } - public var ChatList_PsaAlert_covid: String { return self._s[1313]! } - public var DialogList_Pin: String { return self._s[1314]! } - public var PrivacySettings_SecurityTitle: String { return self._s[1315]! } - public var GroupPermission_NotAvailableInPublicGroups: String { return self._s[1316]! } - public var PeopleNearby_Groups: String { return self._s[1317]! } - public var Message_File: String { return self._s[1318]! } - public var Calls_NoCallsPlaceholder: String { return self._s[1319]! } - public var ChatList_GenericPsaLabel: String { return self._s[1321]! } - public var UserInfo_LastNamePlaceholder: String { return self._s[1322]! } - public var IntentsSettings_Reset: String { return self._s[1324]! } - public var Call_ConnectionErrorTitle: String { return self._s[1325]! } - public var PhotoEditor_SaturationTool: String { return self._s[1326]! } - public var ChatSettings_AutomaticVideoMessageDownload: String { return self._s[1327]! } - public var SettingsSearch_Synonyms_Stickers_ArchivedPacks: String { return self._s[1328]! } - public var Conversation_SearchNoResults: String { return self._s[1329]! } - public var Channel_DiscussionGroup_PrivateChannel: String { return self._s[1330]! } - public var Map_OpenInWaze: String { return self._s[1331]! } - public var WallpaperPreview_Title: String { return self._s[1332]! } + public var Notifications_DisplayNamesOnLockScreenInfoWithLink: String { return self._s[1308]! } + public var Notification_Exceptions_AlwaysOff: String { return self._s[1309]! } + public var Conversation_ContextMenuDelete: String { return self._s[1310]! } + public var Privacy_Calls_WhoCanCallMe: String { return self._s[1311]! } + public var ChatList_PsaAlert_covid: String { return self._s[1314]! } + public var DialogList_Pin: String { return self._s[1315]! } + public var PrivacySettings_SecurityTitle: String { return self._s[1316]! } + public var GroupPermission_NotAvailableInPublicGroups: String { return self._s[1317]! } + public var PeopleNearby_Groups: String { return self._s[1318]! } + public var Message_File: String { return self._s[1319]! } + public var Calls_NoCallsPlaceholder: String { return self._s[1320]! } + public var ChatList_GenericPsaLabel: String { return self._s[1322]! } + public var UserInfo_LastNamePlaceholder: String { return self._s[1323]! } + public var IntentsSettings_Reset: String { return self._s[1325]! } + public var Call_ConnectionErrorTitle: String { return self._s[1326]! } + public var PhotoEditor_SaturationTool: String { return self._s[1327]! } + public var ChatSettings_AutomaticVideoMessageDownload: String { return self._s[1328]! } + public var SettingsSearch_Synonyms_Stickers_ArchivedPacks: String { return self._s[1329]! } + public var Conversation_SearchNoResults: String { return self._s[1330]! } + public var Channel_DiscussionGroup_PrivateChannel: String { return self._s[1331]! } + public var Map_OpenInWaze: String { return self._s[1332]! } + public var WallpaperPreview_Title: String { return self._s[1333]! } public func Passport_AcceptHelp(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1334]!, self._r[1334]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1335]!, self._r[1335]!, [_1, _2]) } - public var AuthSessions_AddDeviceIntro_Title: String { return self._s[1335]! } - public var VoiceOver_Chat_RecordModeVideoMessageInfo: String { return self._s[1336]! } - public var Wallet_Month_ShortMay: String { return self._s[1337]! } - public var Wallet_Send_OwnAddressAlertTitle: String { return self._s[1338]! } - public var Passport_Identity_OneOfTypeInternalPassport: String { return self._s[1339]! } - public var Notifications_PermissionsUnreachableTitle: String { return self._s[1341]! } - public var Stats_Total: String { return self._s[1344]! } - public var Stats_GroupMessages: String { return self._s[1345]! } - public var TwoFactorSetup_Email_SkipAction: String { return self._s[1346]! } - public var CheckoutInfo_ErrorPhoneInvalid: String { return self._s[1347]! } - public var Wallet_TransactionInfo_OtherFeeInfoUrl: String { return self._s[1348]! } - public var Passport_Identity_Translation: String { return self._s[1349]! } - public var Notifications_TextTone: String { return self._s[1351]! } - public var Settings_RemoveConfirmation: String { return self._s[1353]! } - public var ScheduledMessages_Delete: String { return self._s[1354]! } - public var Channel_AdminLog_BanEmbedLinks: String { return self._s[1355]! } - public var Passport_PasswordNext: String { return self._s[1356]! } + public var AuthSessions_AddDeviceIntro_Title: String { return self._s[1336]! } + public var VoiceOver_Chat_RecordModeVideoMessageInfo: String { return self._s[1337]! } + public var Wallet_Month_ShortMay: String { return self._s[1338]! } + public var Wallet_Send_OwnAddressAlertTitle: String { return self._s[1339]! } + public var Passport_Identity_OneOfTypeInternalPassport: String { return self._s[1340]! } + public var Notifications_PermissionsUnreachableTitle: String { return self._s[1342]! } + public var Stats_Total: String { return self._s[1345]! } + public var Stats_GroupMessages: String { return self._s[1346]! } + public var TwoFactorSetup_Email_SkipAction: String { return self._s[1347]! } + public var CheckoutInfo_ErrorPhoneInvalid: String { return self._s[1348]! } + public var Wallet_TransactionInfo_OtherFeeInfoUrl: String { return self._s[1349]! } + public var Passport_Identity_Translation: String { return self._s[1350]! } + public var Notifications_TextTone: String { return self._s[1352]! } + public var Settings_RemoveConfirmation: String { return self._s[1354]! } + public var ScheduledMessages_Delete: String { return self._s[1355]! } + public var Channel_AdminLog_BanEmbedLinks: String { return self._s[1356]! } + public var Passport_PasswordNext: String { return self._s[1357]! } public func PUSH_ENCRYPTED_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1357]!, self._r[1357]!, [_1]) + return formatWithArgumentRanges(self._s[1358]!, self._r[1358]!, [_1]) } - public var Passport_Address_EditBankStatement: String { return self._s[1358]! } - public var PhotoEditor_ShadowsTool: String { return self._s[1359]! } - public var Notification_VideoCallMissed: String { return self._s[1360]! } - public var Wallet_WordCheck_IncorrectText: String { return self._s[1361]! } - public var AccessDenied_CameraDisabled: String { return self._s[1362]! } - public var AuthSessions_AddDevice_ScanInfo: String { return self._s[1363]! } - public var Notifications_ExceptionsMuted: String { return self._s[1364]! } - public var Conversation_ScheduleMessage_SendWhenOnline: String { return self._s[1365]! } - public var Wallet_Receive_ShareInvoiceUrl: String { return self._s[1366]! } - public var Channel_BlackList_Title: String { return self._s[1367]! } - public var PasscodeSettings_4DigitCode: String { return self._s[1368]! } - public var NotificationsSound_Bamboo: String { return self._s[1369]! } - public var PrivacySettings_LastSeenContacts: String { return self._s[1370]! } - public var Passport_Address_TypeUtilityBill: String { return self._s[1371]! } - public var Passport_Address_CountryPlaceholder: String { return self._s[1372]! } - public var GroupPermission_SectionTitle: String { return self._s[1373]! } + public var Passport_Address_EditBankStatement: String { return self._s[1359]! } + public var PhotoEditor_ShadowsTool: String { return self._s[1360]! } + public var Notification_VideoCallMissed: String { return self._s[1361]! } + public var Wallet_WordCheck_IncorrectText: String { return self._s[1362]! } + public var AccessDenied_CameraDisabled: String { return self._s[1363]! } + public var AuthSessions_AddDevice_ScanInfo: String { return self._s[1364]! } + public var Notifications_ExceptionsMuted: String { return self._s[1365]! } + public var Conversation_ScheduleMessage_SendWhenOnline: String { return self._s[1366]! } + public var Wallet_Receive_ShareInvoiceUrl: String { return self._s[1367]! } + public var Channel_BlackList_Title: String { return self._s[1368]! } + public var PasscodeSettings_4DigitCode: String { return self._s[1369]! } + public var NotificationsSound_Bamboo: String { return self._s[1370]! } + public var PrivacySettings_LastSeenContacts: String { return self._s[1371]! } + public var Passport_Address_TypeUtilityBill: String { return self._s[1372]! } + public var Passport_Address_CountryPlaceholder: String { return self._s[1373]! } + public var GroupPermission_SectionTitle: String { return self._s[1374]! } public func Notification_InvitedMultiple(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1374]!, self._r[1374]!, [_0, _1]) + return formatWithArgumentRanges(self._s[1375]!, self._r[1375]!, [_0, _1]) } - public var CheckoutInfo_ShippingInfoStatePlaceholder: String { return self._s[1375]! } - public var Channel_LeaveChannel: String { return self._s[1376]! } - public var Watch_Notification_Joined: String { return self._s[1377]! } - public var PeerInfo_ButtonMore: String { return self._s[1378]! } - public var Passport_FieldEmailHelp: String { return self._s[1379]! } - public var ChatList_Context_Pin: String { return self._s[1380]! } + public var CheckoutInfo_ShippingInfoStatePlaceholder: String { return self._s[1376]! } + public var Channel_LeaveChannel: String { return self._s[1377]! } + public var Watch_Notification_Joined: String { return self._s[1378]! } + public var PeerInfo_ButtonMore: String { return self._s[1379]! } + public var Passport_FieldEmailHelp: String { return self._s[1380]! } + public var ChatList_Context_Pin: String { return self._s[1381]! } public func Time_MonthOfYear_m9(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1381]!, self._r[1381]!, [_0]) + return formatWithArgumentRanges(self._s[1382]!, self._r[1382]!, [_0]) } - public var Group_Location_CreateInThisPlace: String { return self._s[1382]! } - public var PhotoEditor_QualityVeryHigh: String { return self._s[1383]! } - public var Wallet_Receive_CreateInvoiceInfo: String { return self._s[1384]! } - public var Wallet_TransactionInfo_StorageFeeInfoUrl: String { return self._s[1385]! } + public var Group_Location_CreateInThisPlace: String { return self._s[1383]! } + public var PhotoEditor_QualityVeryHigh: String { return self._s[1384]! } + public var Wallet_Receive_CreateInvoiceInfo: String { return self._s[1385]! } + public var Wallet_TransactionInfo_StorageFeeInfoUrl: String { return self._s[1386]! } public func PUSH_CHAT_MESSAGE_FWD(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1386]!, self._r[1386]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1387]!, self._r[1387]!, [_1, _2]) } - public var Tour_Title5: String { return self._s[1387]! } - public var Wallet_Navigation_Back: String { return self._s[1388]! } - public var Passport_Language_en: String { return self._s[1389]! } - public var Checkout_Name: String { return self._s[1390]! } + public var Tour_Title5: String { return self._s[1388]! } + public var Wallet_Navigation_Back: String { return self._s[1389]! } + public var Passport_Language_en: String { return self._s[1390]! } + public var Checkout_Name: String { return self._s[1391]! } public func NetworkUsageSettings_WifiUsageSince(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1391]!, self._r[1391]!, [_0]) + return formatWithArgumentRanges(self._s[1392]!, self._r[1392]!, [_0]) } - public var Wallet_Send_Confirmation: String { return self._s[1392]! } - public var PhotoEditor_EnhanceTool: String { return self._s[1393]! } + public var Wallet_Send_Confirmation: String { return self._s[1393]! } + public var PhotoEditor_EnhanceTool: String { return self._s[1394]! } public func PUSH_CHAT_DELETE_YOU(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1394]!, self._r[1394]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1395]!, self._r[1395]!, [_1, _2]) } public func Login_TermsOfService_ProceedBot(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1395]!, self._r[1395]!, [_0]) + return formatWithArgumentRanges(self._s[1396]!, self._r[1396]!, [_0]) } - public var Group_ErrorSendRestrictedMedia: String { return self._s[1396]! } + public var Group_ErrorSendRestrictedMedia: String { return self._s[1397]! } public func UserInfo_NotificationsDefaultSound(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1397]!, self._r[1397]!, [_0]) + return formatWithArgumentRanges(self._s[1398]!, self._r[1398]!, [_0]) } - public var Login_UnknownError: String { return self._s[1398]! } - public var Passport_Identity_TypeDriversLicense: String { return self._s[1401]! } - public var ChatList_AutoarchiveSuggestion_Title: String { return self._s[1402]! } - public var Watch_PhotoView_Title: String { return self._s[1403]! } - public var Appearance_ThemePreview_ChatList_3_Text: String { return self._s[1404]! } - public var Checkout_TotalAmount: String { return self._s[1405]! } - public var ChatList_RemoveFolderAction: String { return self._s[1406]! } - public var GroupInfo_SetGroupPhoto: String { return self._s[1407]! } - public var Watch_AppName: String { return self._s[1408]! } + public var Login_UnknownError: String { return self._s[1399]! } + public var Passport_Identity_TypeDriversLicense: String { return self._s[1402]! } + public var ChatList_AutoarchiveSuggestion_Title: String { return self._s[1403]! } + public var Watch_PhotoView_Title: String { return self._s[1404]! } + public var Appearance_ThemePreview_ChatList_3_Text: String { return self._s[1405]! } + public var Checkout_TotalAmount: String { return self._s[1406]! } + public var ChatList_RemoveFolderAction: String { return self._s[1407]! } + public var GroupInfo_SetGroupPhoto: String { return self._s[1408]! } + public var Watch_AppName: String { return self._s[1409]! } public func PUSH_PINNED_GAME_SCORE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1409]!, self._r[1409]!, [_1]) + return formatWithArgumentRanges(self._s[1410]!, self._r[1410]!, [_1]) } - public var Channel_Username_CheckingUsername: String { return self._s[1410]! } - public var ContactList_Context_Call: String { return self._s[1411]! } - public var ChatList_ReorderTabs: String { return self._s[1412]! } - public var Watch_ChatList_Compose: String { return self._s[1413]! } + public var Channel_Username_CheckingUsername: String { return self._s[1411]! } + public var ContactList_Context_Call: String { return self._s[1412]! } + public var ChatList_ReorderTabs: String { return self._s[1413]! } + public var Watch_ChatList_Compose: String { return self._s[1414]! } public func Conversation_LiveLocationYouAnd(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1414]!, self._r[1414]!, [_0]) + return formatWithArgumentRanges(self._s[1415]!, self._r[1415]!, [_0]) } - public var Channel_AdminLog_EmptyFilterTitle: String { return self._s[1415]! } - public var ArchivedChats_IntroTitle1: String { return self._s[1416]! } + public var Channel_AdminLog_EmptyFilterTitle: String { return self._s[1416]! } + public var ArchivedChats_IntroTitle1: String { return self._s[1417]! } public func PUSH_ENCRYPTION_ACCEPT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1417]!, self._r[1417]!, [_1]) + return formatWithArgumentRanges(self._s[1418]!, self._r[1418]!, [_1]) } - public var Call_StatusRequesting: String { return self._s[1419]! } - public var Checkout_TotalPaidAmount: String { return self._s[1420]! } - public var Weekday_Friday: String { return self._s[1422]! } - public var CreateGroup_ChannelsTooMuch: String { return self._s[1423]! } - public var Watch_ChatList_NoConversationsText: String { return self._s[1424]! } + public var Call_StatusRequesting: String { return self._s[1420]! } + public var Checkout_TotalPaidAmount: String { return self._s[1421]! } + public var Weekday_Friday: String { return self._s[1423]! } + public var CreateGroup_ChannelsTooMuch: String { return self._s[1424]! } + public var Watch_ChatList_NoConversationsText: String { return self._s[1425]! } public func Channel_AdminLog_MessageChangedGroupStickerPack(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1425]!, self._r[1425]!, [_0]) + return formatWithArgumentRanges(self._s[1426]!, self._r[1426]!, [_0]) } - public var SecretVideo_Title: String { return self._s[1426]! } + public var SecretVideo_Title: String { return self._s[1427]! } public func Notification_PinnedStickerMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1429]!, self._r[1429]!, [_0]) + return formatWithArgumentRanges(self._s[1430]!, self._r[1430]!, [_0]) } - public var Undo_Undo: String { return self._s[1430]! } - public var Watch_Microphone_Access: String { return self._s[1431]! } + public var Undo_Undo: String { return self._s[1431]! } + public var Watch_Microphone_Access: String { return self._s[1432]! } public func PUSH_CHAT_MESSAGE_PHOTO(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1432]!, self._r[1432]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1433]!, self._r[1433]!, [_1, _2]) } public func ChatList_Search_NoResultsQueryDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1433]!, self._r[1433]!, [_0]) + return formatWithArgumentRanges(self._s[1434]!, self._r[1434]!, [_0]) } - public var Wallet_Configuration_SourceURL: String { return self._s[1434]! } - public var Wallet_Intro_CreateErrorTitle: String { return self._s[1435]! } - public var Checkout_NewCard_PostcodeTitle: String { return self._s[1436]! } - public var TwoFactorSetup_Intro_Action: String { return self._s[1437]! } - public var Passport_Language_ne: String { return self._s[1439]! } - public var TwoStepAuth_EmailHelp: String { return self._s[1441]! } - public var Profile_MessageLifetime2s: String { return self._s[1442]! } + public var Wallet_Configuration_SourceURL: String { return self._s[1435]! } + public var Wallet_Intro_CreateErrorTitle: String { return self._s[1436]! } + public var Checkout_NewCard_PostcodeTitle: String { return self._s[1437]! } + public var TwoFactorSetup_Intro_Action: String { return self._s[1438]! } + public var Passport_Language_ne: String { return self._s[1440]! } + public var TwoStepAuth_EmailHelp: String { return self._s[1442]! } + public var Profile_MessageLifetime2s: String { return self._s[1443]! } public func Conversation_MessageDialogRetryAll(_ _1: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1443]!, self._r[1443]!, ["\(_1)"]) + return formatWithArgumentRanges(self._s[1444]!, self._r[1444]!, ["\(_1)"]) } public func Items_NOfM(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1444]!, self._r[1444]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1445]!, self._r[1445]!, [_1, _2]) } - public var GroupPermission_NoPinMessages: String { return self._s[1445]! } + public var GroupPermission_NoPinMessages: String { return self._s[1446]! } public func PUSH_CHAT_TITLE_EDITED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1446]!, self._r[1446]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1447]!, self._r[1447]!, [_1, _2]) } - public var Wallet_Month_GenJuly: String { return self._s[1447]! } + public var Wallet_Month_GenJuly: String { return self._s[1448]! } public func Notification_CreatedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1448]!, self._r[1448]!, [_0]) + return formatWithArgumentRanges(self._s[1449]!, self._r[1449]!, [_0]) } - public var FastTwoStepSetup_HintHelp: String { return self._s[1449]! } - public var WallpaperSearch_ColorRed: String { return self._s[1450]! } - public var Watch_ConnectionDescription: String { return self._s[1451]! } - public var Notification_Exceptions_AddException: String { return self._s[1452]! } - public var LocalGroup_IrrelevantWarning: String { return self._s[1453]! } - public var VoiceOver_MessageContextDelete: String { return self._s[1454]! } - public var LogoutOptions_AlternativeOptionsSection: String { return self._s[1455]! } - public var Passport_PasswordPlaceholder: String { return self._s[1456]! } - public var TwoStepAuth_RecoveryEmailAddDescription: String { return self._s[1457]! } - public var Stats_MessageInteractionsTitle: String { return self._s[1458]! } - public var Appearance_ThemeCarouselClassic: String { return self._s[1459]! } - public var TwoFactorSetup_Email_SkipConfirmationText: String { return self._s[1461]! } - public var Channel_AdminLog_PinMessages: String { return self._s[1462]! } - public var Passport_Address_AddRentalAgreement: String { return self._s[1463]! } - public var Watch_Message_Game: String { return self._s[1464]! } - public var PrivacyLastSeenSettings_NeverShareWith: String { return self._s[1465]! } - public var PrivacyPolicy_DeclineLastWarning: String { return self._s[1466]! } - public var EditTheme_FileReadError: String { return self._s[1467]! } - public var Group_ErrorAddBlocked: String { return self._s[1468]! } - public var CallSettings_UseLessDataLongDescription: String { return self._s[1469]! } + public var FastTwoStepSetup_HintHelp: String { return self._s[1450]! } + public var WallpaperSearch_ColorRed: String { return self._s[1451]! } + public var Watch_ConnectionDescription: String { return self._s[1452]! } + public var Notification_Exceptions_AddException: String { return self._s[1453]! } + public var LocalGroup_IrrelevantWarning: String { return self._s[1454]! } + public var VoiceOver_MessageContextDelete: String { return self._s[1455]! } + public var LogoutOptions_AlternativeOptionsSection: String { return self._s[1456]! } + public var Passport_PasswordPlaceholder: String { return self._s[1457]! } + public var TwoStepAuth_RecoveryEmailAddDescription: String { return self._s[1458]! } + public var Stats_MessageInteractionsTitle: String { return self._s[1459]! } + public var Appearance_ThemeCarouselClassic: String { return self._s[1460]! } + public var TwoFactorSetup_Email_SkipConfirmationText: String { return self._s[1462]! } + public var Channel_AdminLog_PinMessages: String { return self._s[1463]! } + public var Passport_Address_AddRentalAgreement: String { return self._s[1464]! } + public var Watch_Message_Game: String { return self._s[1465]! } + public var PrivacyLastSeenSettings_NeverShareWith: String { return self._s[1466]! } + public var PrivacyPolicy_DeclineLastWarning: String { return self._s[1467]! } + public var EditTheme_FileReadError: String { return self._s[1468]! } + public var Group_ErrorAddBlocked: String { return self._s[1469]! } + public var CallSettings_UseLessDataLongDescription: String { return self._s[1470]! } public func PUSH_MESSAGE_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1471]!, self._r[1471]!, [_1]) + return formatWithArgumentRanges(self._s[1472]!, self._r[1472]!, [_1]) } public func UserInfo_BlockConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1472]!, self._r[1472]!, [_0]) + return formatWithArgumentRanges(self._s[1473]!, self._r[1473]!, [_0]) } - public var CheckoutInfo_ShippingInfoAddress2Placeholder: String { return self._s[1473]! } - public var TwoFactorSetup_EmailVerification_Action: String { return self._s[1474]! } + public var CheckoutInfo_ShippingInfoAddress2Placeholder: String { return self._s[1474]! } + public var TwoFactorSetup_EmailVerification_Action: String { return self._s[1475]! } public func Username_LinkHint(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1475]!, self._r[1475]!, [_0]) + return formatWithArgumentRanges(self._s[1476]!, self._r[1476]!, [_0]) } - public var ConversationProfile_ErrorCreatingConversation: String { return self._s[1476]! } - public var Bot_GroupStatusReadsHistory: String { return self._s[1477]! } - public var PhotoEditor_CurvesRed: String { return self._s[1478]! } - public var InstantPage_TapToOpenLink: String { return self._s[1479]! } - public var FastTwoStepSetup_PasswordHelp: String { return self._s[1480]! } - public var Conversation_DiscussionNotStarted: String { return self._s[1481]! } - public var Notification_CallMissedShort: String { return self._s[1482]! } + public var ConversationProfile_ErrorCreatingConversation: String { return self._s[1477]! } + public var Bot_GroupStatusReadsHistory: String { return self._s[1478]! } + public var PhotoEditor_CurvesRed: String { return self._s[1479]! } + public var InstantPage_TapToOpenLink: String { return self._s[1480]! } + public var FastTwoStepSetup_PasswordHelp: String { return self._s[1481]! } + public var Conversation_DiscussionNotStarted: String { return self._s[1482]! } + public var Notification_CallMissedShort: String { return self._s[1483]! } public func Notification_JoinedGroupByLink(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1483]!, self._r[1483]!, [_0]) + return formatWithArgumentRanges(self._s[1484]!, self._r[1484]!, [_0]) } - public var Conversation_DeleteMessagesForEveryone: String { return self._s[1484]! } - public var Wallet_Words_NotDoneTitle: String { return self._s[1485]! } - public var Permissions_SiriTitle_v0: String { return self._s[1486]! } - public var GroupInfo_AddUserLeftError: String { return self._s[1487]! } - public var Conversation_SendMessage_SendSilently: String { return self._s[1488]! } - public var Paint_Duplicate: String { return self._s[1489]! } - public var AttachmentMenu_WebSearch: String { return self._s[1490]! } - public var Bot_Stop: String { return self._s[1492]! } - public var Conversation_PrivateChannelTimeLimitedAlertTitle: String { return self._s[1493]! } - public var Wallet_TransactionInfo_SendGrams: String { return self._s[1494]! } - public var ReportGroupLocation_Report: String { return self._s[1495]! } - public var Compose_Create: String { return self._s[1496]! } - public var Stats_GroupViewers: String { return self._s[1497]! } - public var AutoDownloadSettings_Channels: String { return self._s[1498]! } - public var PhotoEditor_QualityHigh: String { return self._s[1499]! } - public var Call_Speaker: String { return self._s[1500]! } + public var Conversation_DeleteMessagesForEveryone: String { return self._s[1485]! } + public var Wallet_Words_NotDoneTitle: String { return self._s[1486]! } + public var Permissions_SiriTitle_v0: String { return self._s[1487]! } + public var GroupInfo_AddUserLeftError: String { return self._s[1488]! } + public var Conversation_SendMessage_SendSilently: String { return self._s[1489]! } + public var Paint_Duplicate: String { return self._s[1490]! } + public var AttachmentMenu_WebSearch: String { return self._s[1491]! } + public var Bot_Stop: String { return self._s[1493]! } + public var Conversation_PrivateChannelTimeLimitedAlertTitle: String { return self._s[1494]! } + public var Wallet_TransactionInfo_SendGrams: String { return self._s[1495]! } + public var ReportGroupLocation_Report: String { return self._s[1496]! } + public var Compose_Create: String { return self._s[1497]! } + public var Stats_GroupViewers: String { return self._s[1498]! } + public var AutoDownloadSettings_Channels: String { return self._s[1499]! } + public var PhotoEditor_QualityHigh: String { return self._s[1500]! } + public var Call_Speaker: String { return self._s[1501]! } public func ChatList_LeaveGroupConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1501]!, self._r[1501]!, [_0]) + return formatWithArgumentRanges(self._s[1502]!, self._r[1502]!, [_0]) } - public var Conversation_CloudStorage_ChatStatus: String { return self._s[1502]! } - public var Chat_AttachmentMultipleFilesDisabled: String { return self._s[1503]! } - public var ChatList_Context_AddToFolder: String { return self._s[1504]! } + public var Conversation_CloudStorage_ChatStatus: String { return self._s[1503]! } + public var Chat_AttachmentMultipleFilesDisabled: String { return self._s[1504]! } + public var ChatList_Context_AddToFolder: String { return self._s[1505]! } public func Wallet_SecureStorageReset_BiometryText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1505]!, self._r[1505]!, [_0]) + return formatWithArgumentRanges(self._s[1506]!, self._r[1506]!, [_0]) } - public var Conversation_Unblock: String { return self._s[1506]! } - public var SettingsSearch_Synonyms_Proxy_UseForCalls: String { return self._s[1507]! } + public var Conversation_Unblock: String { return self._s[1507]! } + public var SettingsSearch_Synonyms_Proxy_UseForCalls: String { return self._s[1508]! } public func Time_PreciseDate_m8(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1508]!, self._r[1508]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1509]!, self._r[1509]!, [_1, _2, _3]) } - public var Conversation_ContextMenuReply: String { return self._s[1509]! } - public var Contacts_SearchLabel: String { return self._s[1510]! } - public var Forward_ErrorPublicQuizDisabledInChannels: String { return self._s[1511]! } - public var Stats_GroupMessagesTitle: String { return self._s[1513]! } - public var Wallet_Send_UninitializedTitle: String { return self._s[1514]! } - public var Notification_CallCanceled: String { return self._s[1515]! } - public var VoiceOver_Chat_Selected: String { return self._s[1516]! } - public var NotificationsSound_Tremolo: String { return self._s[1518]! } - public var ChatList_Search_NoResultsDescription: String { return self._s[1519]! } - public var AccessDenied_PhotosAndVideos: String { return self._s[1520]! } - public var AppWallet_Intro_Text: String { return self._s[1521]! } - public var LogoutOptions_ClearCacheText: String { return self._s[1523]! } - public var ChatListFolder_NameUnread: String { return self._s[1524]! } - public var PeerInfo_ButtonMessage: String { return self._s[1526]! } - public var InfoPlist_NSPhotoLibraryAddUsageDescription: String { return self._s[1527]! } - public var BlockedUsers_SelectUserTitle: String { return self._s[1528]! } - public var ChatSettings_Other: String { return self._s[1529]! } - public var UserInfo_NotificationsEnabled: String { return self._s[1530]! } - public var CreatePoll_OptionsHeader: String { return self._s[1531]! } - public var Wallet_Created_Title: String { return self._s[1534]! } - public var Appearance_RemoveThemeColorConfirmation: String { return self._s[1535]! } - public var Channel_Moderator_Title: String { return self._s[1536]! } - public var Channel_AdminLog_MessageRestrictedForever: String { return self._s[1537]! } - public var WallpaperColors_Title: String { return self._s[1538]! } - public var PrivacyPolicy_DeclineMessage: String { return self._s[1540]! } - public var AutoDownloadSettings_VoiceMessagesTitle: String { return self._s[1541]! } - public var Your_card_was_declined: String { return self._s[1542]! } - public var SettingsSearch_FAQ: String { return self._s[1544]! } - public var EditTheme_Expand_Preview_IncomingReplyName: String { return self._s[1545]! } - public var Conversation_ReportSpamConfirmation: String { return self._s[1546]! } - public var OwnershipTransfer_SecurityCheck: String { return self._s[1548]! } - public var PrivacySettings_DataSettingsHelp: String { return self._s[1549]! } - public var Settings_About_Help: String { return self._s[1550]! } + public var Conversation_ContextMenuReply: String { return self._s[1510]! } + public var Contacts_SearchLabel: String { return self._s[1511]! } + public var Forward_ErrorPublicQuizDisabledInChannels: String { return self._s[1512]! } + public var Stats_GroupMessagesTitle: String { return self._s[1514]! } + public var Wallet_Send_UninitializedTitle: String { return self._s[1515]! } + public var Notification_CallCanceled: String { return self._s[1516]! } + public var VoiceOver_Chat_Selected: String { return self._s[1517]! } + public var NotificationsSound_Tremolo: String { return self._s[1519]! } + public var ChatList_Search_NoResultsDescription: String { return self._s[1520]! } + public var AccessDenied_PhotosAndVideos: String { return self._s[1521]! } + public var AppWallet_Intro_Text: String { return self._s[1522]! } + public var LogoutOptions_ClearCacheText: String { return self._s[1524]! } + public var ChatListFolder_NameUnread: String { return self._s[1525]! } + public var PeerInfo_ButtonMessage: String { return self._s[1527]! } + public var InfoPlist_NSPhotoLibraryAddUsageDescription: String { return self._s[1528]! } + public var BlockedUsers_SelectUserTitle: String { return self._s[1529]! } + public var ChatSettings_Other: String { return self._s[1530]! } + public var UserInfo_NotificationsEnabled: String { return self._s[1531]! } + public var CreatePoll_OptionsHeader: String { return self._s[1532]! } + public var Wallet_Created_Title: String { return self._s[1535]! } + public var Appearance_RemoveThemeColorConfirmation: String { return self._s[1536]! } + public var Channel_Moderator_Title: String { return self._s[1537]! } + public var Channel_AdminLog_MessageRestrictedForever: String { return self._s[1538]! } + public var WallpaperColors_Title: String { return self._s[1539]! } + public var PrivacyPolicy_DeclineMessage: String { return self._s[1541]! } + public var AutoDownloadSettings_VoiceMessagesTitle: String { return self._s[1542]! } + public var Your_card_was_declined: String { return self._s[1543]! } + public var SettingsSearch_FAQ: String { return self._s[1545]! } + public var EditTheme_Expand_Preview_IncomingReplyName: String { return self._s[1546]! } + public var Conversation_ReportSpamConfirmation: String { return self._s[1547]! } + public var OwnershipTransfer_SecurityCheck: String { return self._s[1549]! } + public var PrivacySettings_DataSettingsHelp: String { return self._s[1550]! } + public var Settings_About_Help: String { return self._s[1551]! } public func Channel_DiscussionGroup_HeaderGroupSet(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1551]!, self._r[1551]!, [_0]) + return formatWithArgumentRanges(self._s[1552]!, self._r[1552]!, [_0]) } - public var Wallet_Settings_Title: String { return self._s[1552]! } - public var Settings_Proxy: String { return self._s[1553]! } - public var TwoStepAuth_ResetAccountConfirmation: String { return self._s[1554]! } - public var Passport_Identity_TypePassportUploadScan: String { return self._s[1556]! } - public var NotificationsSound_Bell: String { return self._s[1557]! } - public var PrivacySettings_Title: String { return self._s[1559]! } - public var PrivacySettings_DataSettings: String { return self._s[1560]! } - public var ConversationMedia_Title: String { return self._s[1561]! } + public var Wallet_Settings_Title: String { return self._s[1553]! } + public var Settings_Proxy: String { return self._s[1554]! } + public var TwoStepAuth_ResetAccountConfirmation: String { return self._s[1555]! } + public var Passport_Identity_TypePassportUploadScan: String { return self._s[1557]! } + public var NotificationsSound_Bell: String { return self._s[1558]! } + public var PrivacySettings_Title: String { return self._s[1560]! } + public var PrivacySettings_DataSettings: String { return self._s[1561]! } + public var ConversationMedia_Title: String { return self._s[1562]! } public func Conversation_EncryptedPlaceholderTitleIncoming(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1562]!, self._r[1562]!, [_0]) + return formatWithArgumentRanges(self._s[1563]!, self._r[1563]!, [_0]) } - public var PrivacySettings_BlockedPeersEmpty: String { return self._s[1563]! } - public var ReportPeer_ReasonPornography: String { return self._s[1565]! } - public var Privacy_Calls: String { return self._s[1566]! } - public var TwoFactorSetup_Email_Text: String { return self._s[1567]! } - public var Conversation_EncryptedDescriptionTitle: String { return self._s[1568]! } + public var PrivacySettings_BlockedPeersEmpty: String { return self._s[1564]! } + public var ReportPeer_ReasonPornography: String { return self._s[1566]! } + public var Privacy_Calls: String { return self._s[1567]! } + public var TwoFactorSetup_Email_Text: String { return self._s[1568]! } + public var Conversation_EncryptedDescriptionTitle: String { return self._s[1569]! } public func VoiceOver_Chat_MusicTitle(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1569]!, self._r[1569]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1570]!, self._r[1570]!, [_1, _2]) } - public var Passport_Identity_FrontSideHelp: String { return self._s[1570]! } - public var GroupInfo_Permissions_SlowmodeHeader: String { return self._s[1572]! } - public var ContactList_Context_VideoCall: String { return self._s[1573]! } - public var Settings_SaveIncomingPhotos: String { return self._s[1574]! } - public var Passport_Identity_MiddleName: String { return self._s[1575]! } - public var MessagePoll_QuizNoUsers: String { return self._s[1576]! } - public var OldChannels_ChannelFormat: String { return self._s[1577]! } - public var Watch_Message_Call: String { return self._s[1578]! } - public var Wallpaper_Title: String { return self._s[1579]! } - public var PasscodeSettings_TurnPasscodeOff: String { return self._s[1580]! } - public var IntentsSettings_SuggestedChatsSavedMessages: String { return self._s[1581]! } - public var ReportGroupLocation_Text: String { return self._s[1582]! } - public var InviteText_URL: String { return self._s[1583]! } - public var ClearCache_StorageServiceFiles: String { return self._s[1584]! } - public var MessageTimer_Custom: String { return self._s[1585]! } - public var Message_PinnedLocationMessage: String { return self._s[1586]! } + public var Passport_Identity_FrontSideHelp: String { return self._s[1571]! } + public var GroupInfo_Permissions_SlowmodeHeader: String { return self._s[1573]! } + public var ContactList_Context_VideoCall: String { return self._s[1574]! } + public var Settings_SaveIncomingPhotos: String { return self._s[1575]! } + public var Passport_Identity_MiddleName: String { return self._s[1576]! } + public var MessagePoll_QuizNoUsers: String { return self._s[1577]! } + public var OldChannels_ChannelFormat: String { return self._s[1578]! } + public var Watch_Message_Call: String { return self._s[1579]! } + public var Wallpaper_Title: String { return self._s[1580]! } + public var PasscodeSettings_TurnPasscodeOff: String { return self._s[1581]! } + public var IntentsSettings_SuggestedChatsSavedMessages: String { return self._s[1582]! } + public var ReportGroupLocation_Text: String { return self._s[1583]! } + public var InviteText_URL: String { return self._s[1584]! } + public var ClearCache_StorageServiceFiles: String { return self._s[1585]! } + public var MessageTimer_Custom: String { return self._s[1586]! } + public var Message_PinnedLocationMessage: String { return self._s[1587]! } public func VoiceOver_Chat_ContactOrganization(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1587]!, self._r[1587]!, [_0]) + return formatWithArgumentRanges(self._s[1588]!, self._r[1588]!, [_0]) } - public var EditTheme_UploadNewTheme: String { return self._s[1588]! } + public var EditTheme_UploadNewTheme: String { return self._s[1589]! } public func AutoDownloadSettings_UpToForAll(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1590]!, self._r[1590]!, [_0]) + return formatWithArgumentRanges(self._s[1591]!, self._r[1591]!, [_0]) } - public var Login_CodeSentCall: String { return self._s[1592]! } - public var Conversation_Report: String { return self._s[1593]! } - public var NotificationSettings_ContactJoined: String { return self._s[1594]! } + public var Login_CodeSentCall: String { return self._s[1593]! } + public var Conversation_Report: String { return self._s[1594]! } + public var NotificationSettings_ContactJoined: String { return self._s[1595]! } public func PUSH_MESSAGE_SCREENSHOT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1595]!, self._r[1595]!, [_1]) + return formatWithArgumentRanges(self._s[1596]!, self._r[1596]!, [_1]) } - public var StickerPacksSettings_ShowStickersButtonHelp: String { return self._s[1596]! } - public var IntentsSettings_SuggestByAll: String { return self._s[1597]! } - public var StickerPacksSettings_ShowStickersButton: String { return self._s[1598]! } - public var AuthSessions_Title: String { return self._s[1599]! } - public var Channel_AdminLog_TitleAllEvents: String { return self._s[1600]! } - public var Wallet_Completed_ViewWallet: String { return self._s[1601]! } - public var KeyCommand_JumpToNextUnreadChat: String { return self._s[1602]! } - public var Passport_Address_AddPassportRegistration: String { return self._s[1606]! } - public var AutoDownloadSettings_MaxVideoSize: String { return self._s[1607]! } - public var ExplicitContent_AlertTitle: String { return self._s[1608]! } - public var Channel_UpdatePhotoItem: String { return self._s[1609]! } - public var ChatList_AutoarchiveSuggestion_Text: String { return self._s[1611]! } - public var Channel_DiscussionGroup_LinkGroup: String { return self._s[1612]! } + public var StickerPacksSettings_ShowStickersButtonHelp: String { return self._s[1597]! } + public var IntentsSettings_SuggestByAll: String { return self._s[1598]! } + public var StickerPacksSettings_ShowStickersButton: String { return self._s[1599]! } + public var AuthSessions_Title: String { return self._s[1600]! } + public var Channel_AdminLog_TitleAllEvents: String { return self._s[1601]! } + public var Wallet_Completed_ViewWallet: String { return self._s[1602]! } + public var KeyCommand_JumpToNextUnreadChat: String { return self._s[1603]! } + public var Passport_Address_AddPassportRegistration: String { return self._s[1607]! } + public var AutoDownloadSettings_MaxVideoSize: String { return self._s[1608]! } + public var ExplicitContent_AlertTitle: String { return self._s[1609]! } + public var Channel_UpdatePhotoItem: String { return self._s[1610]! } + public var ChatList_AutoarchiveSuggestion_Text: String { return self._s[1612]! } + public var Channel_DiscussionGroup_LinkGroup: String { return self._s[1613]! } public func Call_BatteryLow(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1613]!, self._r[1613]!, [_0]) + return formatWithArgumentRanges(self._s[1614]!, self._r[1614]!, [_0]) } - public var Login_HaveNotReceivedCodeInternal: String { return self._s[1614]! } - public var WallpaperPreview_PatternPaternApply: String { return self._s[1615]! } - public var Notifications_MessageNotificationsSound: String { return self._s[1616]! } - public var CommentsGroup_ErrorAccessDenied: String { return self._s[1617]! } - public var Appearance_AccentColor: String { return self._s[1619]! } - public var GroupInfo_SharedMedia: String { return self._s[1620]! } - public var Login_PhonePlaceholder: String { return self._s[1621]! } - public var Appearance_TextSize_Automatic: String { return self._s[1622]! } - public var EmptyGroupInfo_Line2: String { return self._s[1623]! } + public var Login_HaveNotReceivedCodeInternal: String { return self._s[1615]! } + public var WallpaperPreview_PatternPaternApply: String { return self._s[1616]! } + public var Notifications_MessageNotificationsSound: String { return self._s[1617]! } + public var CommentsGroup_ErrorAccessDenied: String { return self._s[1618]! } + public var Appearance_AccentColor: String { return self._s[1620]! } + public var GroupInfo_SharedMedia: String { return self._s[1621]! } + public var Login_PhonePlaceholder: String { return self._s[1622]! } + public var Appearance_TextSize_Automatic: String { return self._s[1623]! } + public var EmptyGroupInfo_Line2: String { return self._s[1624]! } public func PUSH_CHAT_CREATED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1624]!, self._r[1624]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1625]!, self._r[1625]!, [_1, _2]) } - public var Conversation_WalletRequiredNotNow: String { return self._s[1626]! } - public var Appearance_AppIconDefaultX: String { return self._s[1627]! } - public var EditProfile_NameAndPhotoOrVideoHelp: String { return self._s[1628]! } - public var CheckoutInfo_ShippingInfoPostcodePlaceholder: String { return self._s[1629]! } - public var Notifications_GroupNotificationsHelp: String { return self._s[1630]! } + public var Conversation_WalletRequiredNotNow: String { return self._s[1627]! } + public var Appearance_AppIconDefaultX: String { return self._s[1628]! } + public var EditProfile_NameAndPhotoOrVideoHelp: String { return self._s[1629]! } + public var CheckoutInfo_ShippingInfoPostcodePlaceholder: String { return self._s[1630]! } + public var Notifications_GroupNotificationsHelp: String { return self._s[1631]! } public func PUSH_CHAT_MESSAGE_NOTEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1631]!, self._r[1631]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1632]!, self._r[1632]!, [_1, _2]) } - public var ChatList_EmptyChatListEditFilter: String { return self._s[1632]! } - public var ChatSettings_ConnectionType_UseProxy: String { return self._s[1635]! } - public var Chat_PinnedMessagesHiddenText: String { return self._s[1636]! } + public var ChatList_EmptyChatListEditFilter: String { return self._s[1633]! } + public var ChatSettings_ConnectionType_UseProxy: String { return self._s[1636]! } + public var Chat_PinnedMessagesHiddenText: String { return self._s[1637]! } public func Message_PinnedGenericMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1637]!, self._r[1637]!, [_0]) - } - public func Location_ProximityTip(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[1638]!, self._r[1638]!, [_0]) } - public var UserInfo_NotificationsEnable: String { return self._s[1639]! } - public var Checkout_PayWithTouchId: String { return self._s[1640]! } - public var SharedMedia_ViewInChat: String { return self._s[1641]! } - public func Notification_CreatedChatWithTitle(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1642]!, self._r[1642]!, [_0, _1]) + public func Location_ProximityTip(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1639]!, self._r[1639]!, [_0]) } - public var ChatSettings_AutoDownloadSettings_OffForAll: String { return self._s[1643]! } + public var UserInfo_NotificationsEnable: String { return self._s[1640]! } + public var Checkout_PayWithTouchId: String { return self._s[1641]! } + public var SharedMedia_ViewInChat: String { return self._s[1642]! } + public func Notification_CreatedChatWithTitle(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1643]!, self._r[1643]!, [_0, _1]) + } + public var ChatSettings_AutoDownloadSettings_OffForAll: String { return self._s[1644]! } public func Channel_DiscussionGroup_PublicChannelLink(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1644]!, self._r[1644]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1645]!, self._r[1645]!, [_1, _2]) } public func Cache_Clear(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1646]!, self._r[1646]!, [_0]) + return formatWithArgumentRanges(self._s[1647]!, self._r[1647]!, [_0]) } - public var Conversation_PeerNearbyText: String { return self._s[1648]! } - public var Conversation_StopPollConfirmationTitle: String { return self._s[1649]! } - public var PhotoEditor_Skip: String { return self._s[1650]! } - public var SettingsSearch_Synonyms_Appearance_ChatBackground_SetColor: String { return self._s[1651]! } - public var ChatList_EmptyChatList: String { return self._s[1652]! } - public var Channel_BanUser_Unban: String { return self._s[1653]! } + public var Conversation_PeerNearbyText: String { return self._s[1649]! } + public var Conversation_StopPollConfirmationTitle: String { return self._s[1650]! } + public var PhotoEditor_Skip: String { return self._s[1651]! } + public var SettingsSearch_Synonyms_Appearance_ChatBackground_SetColor: String { return self._s[1652]! } + public var ChatList_EmptyChatList: String { return self._s[1653]! } + public var Channel_BanUser_Unban: String { return self._s[1654]! } public func Message_GenericForwardedPsa(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1654]!, self._r[1654]!, [_0]) + return formatWithArgumentRanges(self._s[1655]!, self._r[1655]!, [_0]) } - public var Appearance_TextSize_Apply: String { return self._s[1655]! } - public var Wallet_Send_SyncInProgress: String { return self._s[1656]! } + public var Appearance_TextSize_Apply: String { return self._s[1656]! } + public var Wallet_Send_SyncInProgress: String { return self._s[1657]! } public func Conversation_MessageViewCommentsFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1657]!, self._r[1657]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1658]!, self._r[1658]!, [_1, _2]) } - public var Login_InfoFirstNamePlaceholder: String { return self._s[1658]! } - public var Wallet_Configuration_SourceHeader: String { return self._s[1659]! } - public var TwoStepAuth_HintPlaceholder: String { return self._s[1660]! } - public var TwoStepAuth_EmailSkip: String { return self._s[1662]! } - public var ChatList_UndoArchiveMultipleTitle: String { return self._s[1663]! } - public var TwoFactorSetup_Email_SkipConfirmationTitle: String { return self._s[1664]! } + public var Login_InfoFirstNamePlaceholder: String { return self._s[1659]! } + public var Wallet_Configuration_SourceHeader: String { return self._s[1660]! } + public var TwoStepAuth_HintPlaceholder: String { return self._s[1661]! } + public var TwoStepAuth_EmailSkip: String { return self._s[1663]! } + public var ChatList_UndoArchiveMultipleTitle: String { return self._s[1664]! } + public var TwoFactorSetup_Email_SkipConfirmationTitle: String { return self._s[1665]! } public func PUSH_MESSAGE_QUIZ(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1665]!, self._r[1665]!, [_1]) + return formatWithArgumentRanges(self._s[1666]!, self._r[1666]!, [_1]) } - public var State_WaitingForNetwork: String { return self._s[1667]! } - public var AccessDenied_CameraRestricted: String { return self._s[1668]! } - public var ChatSettings_Appearance: String { return self._s[1669]! } - public var ScheduledMessages_BotActionUnavailable: String { return self._s[1670]! } + public var State_WaitingForNetwork: String { return self._s[1668]! } + public var AccessDenied_CameraRestricted: String { return self._s[1669]! } + public var ChatSettings_Appearance: String { return self._s[1670]! } + public var ScheduledMessages_BotActionUnavailable: String { return self._s[1671]! } public func Wallet_Time_PreciseDate_m3(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1671]!, self._r[1671]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1672]!, self._r[1672]!, [_1, _2, _3]) } - public var GroupInfo_InviteLink_CopyAlert_Success: String { return self._s[1672]! } - public var Channel_DiscussionGroupAdd: String { return self._s[1673]! } - public var Map_NoPlacesNearby: String { return self._s[1675]! } - public var AuthSessions_IncompleteAttemptsInfo: String { return self._s[1676]! } - public var GroupRemoved_Title: String { return self._s[1677]! } - public var TwoStepAuth_EnterPasswordHelp: String { return self._s[1679]! } - public var Paint_Marker: String { return self._s[1680]! } + public var GroupInfo_InviteLink_CopyAlert_Success: String { return self._s[1673]! } + public var Channel_DiscussionGroupAdd: String { return self._s[1674]! } + public var Map_NoPlacesNearby: String { return self._s[1676]! } + public var AuthSessions_IncompleteAttemptsInfo: String { return self._s[1677]! } + public var GroupRemoved_Title: String { return self._s[1678]! } + public var TwoStepAuth_EnterPasswordHelp: String { return self._s[1680]! } + public var Paint_Marker: String { return self._s[1681]! } public func AddContact_ContactWillBeSharedAfterMutual(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1681]!, self._r[1681]!, [_1]) + return formatWithArgumentRanges(self._s[1682]!, self._r[1682]!, [_1]) } - public var SocksProxySetup_ShareProxyList: String { return self._s[1682]! } - public var GroupInfo_InvitationLinkDoesNotExist: String { return self._s[1683]! } + public var SocksProxySetup_ShareProxyList: String { return self._s[1683]! } + public var GroupInfo_InvitationLinkDoesNotExist: String { return self._s[1684]! } public func VoiceOver_Chat_Size(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1684]!, self._r[1684]!, [_0]) + return formatWithArgumentRanges(self._s[1685]!, self._r[1685]!, [_0]) } - public var EditTheme_ErrorInvalidCharacters: String { return self._s[1685]! } - public var Appearance_ThemePreview_ChatList_7_Name: String { return self._s[1686]! } - public var Notifications_GroupNotificationsAlert: String { return self._s[1687]! } - public var SocksProxySetup_ShareQRCode: String { return self._s[1688]! } - public var Compose_NewGroup: String { return self._s[1689]! } + public var EditTheme_ErrorInvalidCharacters: String { return self._s[1686]! } + public var Appearance_ThemePreview_ChatList_7_Name: String { return self._s[1687]! } + public var Notifications_GroupNotificationsAlert: String { return self._s[1688]! } + public var SocksProxySetup_ShareQRCode: String { return self._s[1689]! } + public var Compose_NewGroup: String { return self._s[1690]! } public func Passport_Address_UploadOneOfScan(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1690]!, self._r[1690]!, [_0]) + return formatWithArgumentRanges(self._s[1691]!, self._r[1691]!, [_0]) } - public var Conversation_ClearGroupHistory: String { return self._s[1692]! } - public var Location_LiveLocationRequired_Description: String { return self._s[1693]! } - public var GroupInfo_InviteLink_Help: String { return self._s[1696]! } - public var Channel_BanUser_BlockFor: String { return self._s[1697]! } - public var Bot_Start: String { return self._s[1698]! } - public var Your_card_has_expired: String { return self._s[1699]! } - public var Channel_About_Title: String { return self._s[1700]! } - public var Passport_Identity_ExpiryDatePlaceholder: String { return self._s[1701]! } - public var SettingsSearch_Synonyms_Notifications_MessageNotificationsExceptions: String { return self._s[1703]! } - public var Wallet_Info_Updating: String { return self._s[1704]! } - public var Conversation_FileDropbox: String { return self._s[1705]! } - public var Conversation_WalletRequiredTitle: String { return self._s[1706]! } - public var ChatList_Search_NoResultsFitlerMusic: String { return self._s[1707]! } - public var Month_GenNovember: String { return self._s[1708]! } - public var IntentsSettings_SuggestByShare: String { return self._s[1709]! } + public var Conversation_ClearGroupHistory: String { return self._s[1693]! } + public var Location_LiveLocationRequired_Description: String { return self._s[1694]! } + public var GroupInfo_InviteLink_Help: String { return self._s[1697]! } + public var Channel_BanUser_BlockFor: String { return self._s[1698]! } + public var Bot_Start: String { return self._s[1699]! } + public var Your_card_has_expired: String { return self._s[1700]! } + public var Channel_About_Title: String { return self._s[1701]! } + public var Passport_Identity_ExpiryDatePlaceholder: String { return self._s[1702]! } + public var SettingsSearch_Synonyms_Notifications_MessageNotificationsExceptions: String { return self._s[1704]! } + public var Wallet_Info_Updating: String { return self._s[1705]! } + public var Conversation_FileDropbox: String { return self._s[1706]! } + public var Conversation_WalletRequiredTitle: String { return self._s[1707]! } + public var ChatList_Search_NoResultsFitlerMusic: String { return self._s[1708]! } + public var Month_GenNovember: String { return self._s[1709]! } + public var IntentsSettings_SuggestByShare: String { return self._s[1710]! } public func Call_PrivacyErrorMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1710]!, self._r[1710]!, [_0]) + return formatWithArgumentRanges(self._s[1711]!, self._r[1711]!, [_0]) } - public var StickerPack_Add: String { return self._s[1711]! } - public var Theme_ErrorNotFound: String { return self._s[1712]! } - public var Wallpaper_SearchShort: String { return self._s[1714]! } - public var Channel_BanUser_PermissionsHeader: String { return self._s[1715]! } - public var ConversationProfile_UsersTooMuchError: String { return self._s[1716]! } - public var ChatList_FolderAllChats: String { return self._s[1717]! } - public var Passport_Authorize: String { return self._s[1718]! } + public var StickerPack_Add: String { return self._s[1712]! } + public var Theme_ErrorNotFound: String { return self._s[1713]! } + public var Wallpaper_SearchShort: String { return self._s[1715]! } + public var Channel_BanUser_PermissionsHeader: String { return self._s[1716]! } + public var ConversationProfile_UsersTooMuchError: String { return self._s[1717]! } + public var ChatList_FolderAllChats: String { return self._s[1718]! } + public var Passport_Authorize: String { return self._s[1719]! } public func Channel_AdminLog_MessageChangedLinkedChannel(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1719]!, self._r[1719]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1720]!, self._r[1720]!, [_1, _2]) } - public var GroupInfo_GroupHistoryVisible: String { return self._s[1720]! } + public var GroupInfo_GroupHistoryVisible: String { return self._s[1721]! } public func PUSH_MESSAGE_VIDEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1721]!, self._r[1721]!, [_1]) + return formatWithArgumentRanges(self._s[1722]!, self._r[1722]!, [_1]) } - public var LocalGroup_ButtonTitle: String { return self._s[1722]! } - public var UserInfo_GroupsInCommon: String { return self._s[1724]! } - public var Wallpaper_Set: String { return self._s[1725]! } - public var LoginPassword_Title: String { return self._s[1726]! } - public var Stats_InteractionsTitle: String { return self._s[1727]! } - public var Wallet_TransactionInfo_StorageFeeHeader: String { return self._s[1729]! } + public var LocalGroup_ButtonTitle: String { return self._s[1723]! } + public var UserInfo_GroupsInCommon: String { return self._s[1725]! } + public var Wallpaper_Set: String { return self._s[1726]! } + public var LoginPassword_Title: String { return self._s[1727]! } + public var Stats_InteractionsTitle: String { return self._s[1728]! } + public var Wallet_TransactionInfo_StorageFeeHeader: String { return self._s[1730]! } public func SecretGIF_NotViewedYet(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1730]!, self._r[1730]!, [_0]) + return formatWithArgumentRanges(self._s[1731]!, self._r[1731]!, [_0]) } - public var Conversation_MessageDialogEdit: String { return self._s[1731]! } - public var Paint_Outlined: String { return self._s[1732]! } + public var Conversation_MessageDialogEdit: String { return self._s[1732]! } + public var Paint_Outlined: String { return self._s[1733]! } public func Login_ResetAccountProtected_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1733]!, self._r[1733]!, [_0]) - } - public func Conversation_SetReminder_RemindTomorrow(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[1734]!, self._r[1734]!, [_0]) } - public var Invite_LargeRecipientsCountWarning: String { return self._s[1735]! } - public var Passport_Address_Street1Placeholder: String { return self._s[1736]! } - public var Appearance_ColorThemeNight: String { return self._s[1737]! } - public var ChannelInfo_Stats: String { return self._s[1738]! } - public var TwoStepAuth_RecoveryTitle: String { return self._s[1739]! } - public var MediaPicker_TimerTooltip: String { return self._s[1740]! } - public var Common_ChoosePhoto: String { return self._s[1741]! } - public var ChatSettings_AutoDownloadVideos: String { return self._s[1742]! } - public var PeerInfo_PaneGroups: String { return self._s[1743]! } - public var Wallet_Month_ShortMarch: String { return self._s[1745]! } - public var ChangePhoneNumberNumber_Title: String { return self._s[1746]! } - public var SocksProxySetup_UsernamePlaceholder: String { return self._s[1747]! } - public var ContactInfo_PhoneLabelMobile: String { return self._s[1748]! } - public var OldChannels_ChannelsHeader: String { return self._s[1749]! } - public var MuteFor_Forever: String { return self._s[1750]! } - public var Passport_Address_PostcodePlaceholder: String { return self._s[1751]! } - public var SettingsSearch_Synonyms_Appearance_ChatBackground: String { return self._s[1752]! } - public var MessagePoll_LabelAnonymous: String { return self._s[1753]! } - public var ContactInfo_Job: String { return self._s[1754]! } - public var Passport_Language_mk: String { return self._s[1755]! } - public var EditTheme_ShortLink: String { return self._s[1756]! } - public var AutoDownloadSettings_PhotosTitle: String { return self._s[1758]! } - public var Wallet_Send_Send: String { return self._s[1759]! } - public var Month_GenApril: String { return self._s[1761]! } - public var Channel_DiscussionGroup_HeaderLabel: String { return self._s[1763]! } - public var NetworkUsageSettings_TotalSection: String { return self._s[1764]! } - public var EditTheme_Create_Preview_OutgoingText: String { return self._s[1765]! } - public var EditTheme_Title: String { return self._s[1766]! } - public var Conversation_LinkDialogCopy: String { return self._s[1767]! } + public func Conversation_SetReminder_RemindTomorrow(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1735]!, self._r[1735]!, [_0]) + } + public var Invite_LargeRecipientsCountWarning: String { return self._s[1736]! } + public var Passport_Address_Street1Placeholder: String { return self._s[1737]! } + public var Appearance_ColorThemeNight: String { return self._s[1738]! } + public var ChannelInfo_Stats: String { return self._s[1739]! } + public var TwoStepAuth_RecoveryTitle: String { return self._s[1740]! } + public var MediaPicker_TimerTooltip: String { return self._s[1741]! } + public var Common_ChoosePhoto: String { return self._s[1742]! } + public var ChatSettings_AutoDownloadVideos: String { return self._s[1743]! } + public var PeerInfo_PaneGroups: String { return self._s[1744]! } + public var Wallet_Month_ShortMarch: String { return self._s[1746]! } + public var ChangePhoneNumberNumber_Title: String { return self._s[1747]! } + public var SocksProxySetup_UsernamePlaceholder: String { return self._s[1748]! } + public var ContactInfo_PhoneLabelMobile: String { return self._s[1749]! } + public var OldChannels_ChannelsHeader: String { return self._s[1750]! } + public var MuteFor_Forever: String { return self._s[1751]! } + public var Passport_Address_PostcodePlaceholder: String { return self._s[1752]! } + public var SettingsSearch_Synonyms_Appearance_ChatBackground: String { return self._s[1753]! } + public var MessagePoll_LabelAnonymous: String { return self._s[1754]! } + public var ContactInfo_Job: String { return self._s[1755]! } + public var Passport_Language_mk: String { return self._s[1756]! } + public var EditTheme_ShortLink: String { return self._s[1757]! } + public var AutoDownloadSettings_PhotosTitle: String { return self._s[1759]! } + public var Wallet_Send_Send: String { return self._s[1760]! } + public var Month_GenApril: String { return self._s[1762]! } + public var Channel_DiscussionGroup_HeaderLabel: String { return self._s[1764]! } + public var NetworkUsageSettings_TotalSection: String { return self._s[1765]! } + public var EditTheme_Create_Preview_OutgoingText: String { return self._s[1766]! } + public var EditTheme_Title: String { return self._s[1767]! } + public var Conversation_LinkDialogCopy: String { return self._s[1768]! } public func Channel_AdminLog_MessageInvitedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1768]!, self._r[1768]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1769]!, self._r[1769]!, [_1, _2]) } - public var Passport_ForgottenPassword: String { return self._s[1769]! } - public var WallpaperSearch_Recent: String { return self._s[1770]! } - public var ChatSettings_Title: String { return self._s[1775]! } - public var Appearance_ReduceMotionInfo: String { return self._s[1776]! } + public var Passport_ForgottenPassword: String { return self._s[1770]! } + public var WallpaperSearch_Recent: String { return self._s[1771]! } + public var ChatSettings_Title: String { return self._s[1776]! } + public var Appearance_ReduceMotionInfo: String { return self._s[1777]! } public func StickerPackActionInfo_AddedText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1777]!, self._r[1777]!, [_0]) + return formatWithArgumentRanges(self._s[1778]!, self._r[1778]!, [_0]) } - public var SocksProxySetup_UseForCallsHelp: String { return self._s[1778]! } - public var LastSeen_WithinAMonth: String { return self._s[1779]! } - public var PeerInfo_ButtonCall: String { return self._s[1780]! } - public var SettingsSearch_Synonyms_Appearance_Title: String { return self._s[1781]! } - public var Group_Username_InvalidStartsWithNumber: String { return self._s[1782]! } - public var Call_AudioRouteHide: String { return self._s[1783]! } - public var DialogList_SavedMessages: String { return self._s[1784]! } - public var ChatList_Context_Mute: String { return self._s[1785]! } - public var Conversation_StatusKickedFromChannel: String { return self._s[1786]! } + public var SocksProxySetup_UseForCallsHelp: String { return self._s[1779]! } + public var LastSeen_WithinAMonth: String { return self._s[1780]! } + public var PeerInfo_ButtonCall: String { return self._s[1781]! } + public var SettingsSearch_Synonyms_Appearance_Title: String { return self._s[1782]! } + public var Group_Username_InvalidStartsWithNumber: String { return self._s[1783]! } + public var Call_AudioRouteHide: String { return self._s[1784]! } + public var DialogList_SavedMessages: String { return self._s[1785]! } + public var ChatList_Context_Mute: String { return self._s[1786]! } + public var Conversation_StatusKickedFromChannel: String { return self._s[1787]! } public func Notification_Exceptions_MutedUntil(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1787]!, self._r[1787]!, [_0]) + return formatWithArgumentRanges(self._s[1788]!, self._r[1788]!, [_0]) } - public var Passport_Language_et: String { return self._s[1788]! } - public var Conversation_MessageLeaveCommentShort: String { return self._s[1789]! } - public var PhotoEditor_CropReset: String { return self._s[1790]! } - public var Wallet_Send_TransactionInProgress: String { return self._s[1791]! } - public var Privacy_GroupsAndChannels_AlwaysAllow: String { return self._s[1792]! } - public var SocksProxySetup_HostnamePlaceholder: String { return self._s[1793]! } - public var CreateGroup_ErrorLocatedGroupsTooMuch: String { return self._s[1794]! } - public var WallpaperSearch_ColorWhite: String { return self._s[1797]! } - public var Channel_AdminLog_CanEditMessages: String { return self._s[1799]! } - public var Privacy_PaymentsClearInfoDoneHelp: String { return self._s[1800]! } - public var Channel_Username_InvalidStartsWithNumber: String { return self._s[1802]! } - public var CheckoutInfo_ReceiverInfoName: String { return self._s[1804]! } - public var Map_YouAreHere: String { return self._s[1806]! } - public var Core_ServiceUserStatus: String { return self._s[1807]! } - public var Channel_Setup_TypePrivateHelp: String { return self._s[1810]! } - public var SettingsSearch_Synonyms_Notifications_BadgeCountUnreadMessages: String { return self._s[1811]! } - public var MediaPicker_Videos: String { return self._s[1813]! } - public var Map_LiveLocationFor15Minutes: String { return self._s[1815]! } - public var Passport_Identity_TranslationsHelp: String { return self._s[1816]! } - public var SharedMedia_CategoryMedia: String { return self._s[1817]! } - public var Wallet_Month_ShortJanuary: String { return self._s[1818]! } + public var Passport_Language_et: String { return self._s[1789]! } + public var Conversation_MessageLeaveCommentShort: String { return self._s[1790]! } + public var PhotoEditor_CropReset: String { return self._s[1791]! } + public var Wallet_Send_TransactionInProgress: String { return self._s[1792]! } + public var Privacy_GroupsAndChannels_AlwaysAllow: String { return self._s[1793]! } + public var SocksProxySetup_HostnamePlaceholder: String { return self._s[1794]! } + public var CreateGroup_ErrorLocatedGroupsTooMuch: String { return self._s[1795]! } + public var WallpaperSearch_ColorWhite: String { return self._s[1798]! } + public var Channel_AdminLog_CanEditMessages: String { return self._s[1800]! } + public var Privacy_PaymentsClearInfoDoneHelp: String { return self._s[1801]! } + public var Channel_Username_InvalidStartsWithNumber: String { return self._s[1803]! } + public var CheckoutInfo_ReceiverInfoName: String { return self._s[1805]! } + public var Map_YouAreHere: String { return self._s[1807]! } + public var Core_ServiceUserStatus: String { return self._s[1808]! } + public var Channel_Setup_TypePrivateHelp: String { return self._s[1811]! } + public var SettingsSearch_Synonyms_Notifications_BadgeCountUnreadMessages: String { return self._s[1812]! } + public var MediaPicker_Videos: String { return self._s[1814]! } + public var Map_LiveLocationFor15Minutes: String { return self._s[1816]! } + public var Passport_Identity_TranslationsHelp: String { return self._s[1817]! } + public var SharedMedia_CategoryMedia: String { return self._s[1818]! } + public var Wallet_Month_ShortJanuary: String { return self._s[1819]! } public func MediaPicker_Nof(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1819]!, self._r[1819]!, [_0]) + return formatWithArgumentRanges(self._s[1820]!, self._r[1820]!, [_0]) } - public var ChatSettings_AutoPlayGifs: String { return self._s[1820]! } - public var Passport_Identity_CountryPlaceholder: String { return self._s[1821]! } - public var Bot_GroupStatusDoesNotReadHistory: String { return self._s[1822]! } - public var Notification_Exceptions_RemoveFromExceptions: String { return self._s[1823]! } + public var ChatSettings_AutoPlayGifs: String { return self._s[1821]! } + public var Passport_Identity_CountryPlaceholder: String { return self._s[1822]! } + public var Bot_GroupStatusDoesNotReadHistory: String { return self._s[1823]! } + public var Notification_Exceptions_RemoveFromExceptions: String { return self._s[1824]! } public func Chat_SlowmodeTooltip(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1824]!, self._r[1824]!, [_0]) + return formatWithArgumentRanges(self._s[1825]!, self._r[1825]!, [_0]) } - public var Web_Error: String { return self._s[1825]! } - public var PhotoEditor_SkinTool: String { return self._s[1826]! } - public var ApplyLanguage_UnsufficientDataTitle: String { return self._s[1827]! } - public var ChatSettings_ConnectionType_UseSocks5: String { return self._s[1828]! } - public var PasscodeSettings_Help: String { return self._s[1829]! } - public var Appearance_ColorTheme: String { return self._s[1830]! } + public var Web_Error: String { return self._s[1826]! } + public var PhotoEditor_SkinTool: String { return self._s[1827]! } + public var ApplyLanguage_UnsufficientDataTitle: String { return self._s[1828]! } + public var ChatSettings_ConnectionType_UseSocks5: String { return self._s[1829]! } + public var PasscodeSettings_Help: String { return self._s[1830]! } + public var Appearance_ColorTheme: String { return self._s[1831]! } public func Channel_AdminLog_MessageRestrictedNewSetting(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1831]!, self._r[1831]!, [_0]) + return formatWithArgumentRanges(self._s[1832]!, self._r[1832]!, [_0]) } public func PUSH_PINNED_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1832]!, self._r[1832]!, [_1]) + return formatWithArgumentRanges(self._s[1833]!, self._r[1833]!, [_1]) } - public var GroupInfo_LeftStatus: String { return self._s[1833]! } - public var EditTheme_Preview: String { return self._s[1834]! } - public var Watch_Suggestion_WhatsUp: String { return self._s[1835]! } + public var GroupInfo_LeftStatus: String { return self._s[1834]! } + public var EditTheme_Preview: String { return self._s[1835]! } + public var Watch_Suggestion_WhatsUp: String { return self._s[1836]! } public func AutoDownloadSettings_PreloadVideoInfo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1836]!, self._r[1836]!, [_0]) + return formatWithArgumentRanges(self._s[1837]!, self._r[1837]!, [_0]) } - public var NotificationsSound_Keys: String { return self._s[1837]! } - public var PasscodeSettings_UnlockWithTouchId: String { return self._s[1838]! } - public var ChatList_Context_MarkAsUnread: String { return self._s[1839]! } - public var DialogList_AdNoticeAlert: String { return self._s[1840]! } - public var UserInfo_Invite: String { return self._s[1841]! } - public var Checkout_Email: String { return self._s[1842]! } - public var Stats_GroupActionsTitle: String { return self._s[1843]! } - public var Wallet_Navigation_Done: String { return self._s[1844]! } - public var Coub_TapForSound: String { return self._s[1845]! } - public var Theme_ThemeChangedText: String { return self._s[1846]! } - public var Call_ExternalCallInProgressMessage: String { return self._s[1847]! } - public var Settings_ApplyProxyAlertEnable: String { return self._s[1848]! } - public var ScheduledMessages_ScheduledToday: String { return self._s[1849]! } - public var Channel_AdminLog_DefaultRestrictionsUpdated: String { return self._s[1850]! } - public var Call_ReportIncludeLogDescription: String { return self._s[1851]! } - public var Settings_FrequentlyAskedQuestions: String { return self._s[1853]! } - public var Wallet_Words_NotDoneText: String { return self._s[1854]! } - public var Channel_MessagePhotoRemoved: String { return self._s[1855]! } - public var Passport_Email_Delete: String { return self._s[1856]! } + public var NotificationsSound_Keys: String { return self._s[1838]! } + public var PasscodeSettings_UnlockWithTouchId: String { return self._s[1839]! } + public var ChatList_Context_MarkAsUnread: String { return self._s[1840]! } + public var DialogList_AdNoticeAlert: String { return self._s[1841]! } + public var UserInfo_Invite: String { return self._s[1842]! } + public var Checkout_Email: String { return self._s[1843]! } + public var Stats_GroupActionsTitle: String { return self._s[1844]! } + public var Wallet_Navigation_Done: String { return self._s[1845]! } + public var Coub_TapForSound: String { return self._s[1846]! } + public var Theme_ThemeChangedText: String { return self._s[1847]! } + public var Call_ExternalCallInProgressMessage: String { return self._s[1848]! } + public var Settings_ApplyProxyAlertEnable: String { return self._s[1849]! } + public var ScheduledMessages_ScheduledToday: String { return self._s[1850]! } + public var Channel_AdminLog_DefaultRestrictionsUpdated: String { return self._s[1851]! } + public var Call_ReportIncludeLogDescription: String { return self._s[1852]! } + public var Settings_FrequentlyAskedQuestions: String { return self._s[1854]! } + public var Wallet_Words_NotDoneText: String { return self._s[1855]! } + public var Channel_MessagePhotoRemoved: String { return self._s[1856]! } + public var Passport_Email_Delete: String { return self._s[1857]! } public func PUSH_PINNED_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1857]!, self._r[1857]!, [_1]) + return formatWithArgumentRanges(self._s[1858]!, self._r[1858]!, [_1]) } - public var NotificationSettings_ShowNotificationsAllAccountsInfoOn: String { return self._s[1858]! } - public var Channel_AdminLog_CanAddAdmins: String { return self._s[1859]! } - public var SocksProxySetup_FailedToConnect: String { return self._s[1861]! } - public var SettingsSearch_Synonyms_Data_NetworkUsage: String { return self._s[1862]! } - public var Wallet_Month_GenMay: String { return self._s[1863]! } - public var Common_of: String { return self._s[1864]! } - public var PeerInfo_ButtonUnmute: String { return self._s[1867]! } + public var NotificationSettings_ShowNotificationsAllAccountsInfoOn: String { return self._s[1859]! } + public var Channel_AdminLog_CanAddAdmins: String { return self._s[1860]! } + public var SocksProxySetup_FailedToConnect: String { return self._s[1862]! } + public var SettingsSearch_Synonyms_Data_NetworkUsage: String { return self._s[1863]! } + public var Wallet_Month_GenMay: String { return self._s[1864]! } + public var Common_of: String { return self._s[1865]! } + public var PeerInfo_ButtonUnmute: String { return self._s[1868]! } public func ChatSettings_AutoDownloadSettings_TypeFile(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1868]!, self._r[1868]!, [_0]) + return formatWithArgumentRanges(self._s[1869]!, self._r[1869]!, [_0]) } - public var ChatList_AddChatsToFolder: String { return self._s[1869]! } - public var Login_ResetAccountProtected_LimitExceeded: String { return self._s[1870]! } - public var Settings_Title: String { return self._s[1872]! } - public var AutoDownloadSettings_Contacts: String { return self._s[1874]! } - public var Appearance_BubbleCornersSetting: String { return self._s[1875]! } - public var Privacy_Calls_AlwaysAllow: String { return self._s[1876]! } - public var Privacy_Forwards_AlwaysAllow_Title: String { return self._s[1878]! } - public var WallpaperPreview_CropBottomText: String { return self._s[1879]! } - public var SecretTimer_VideoDescription: String { return self._s[1880]! } - public var WallpaperPreview_Blurred: String { return self._s[1881]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsExceptions: String { return self._s[1882]! } - public var ChatListFolder_ExcludedSectionHeader: String { return self._s[1884]! } - public var DialogList_PasscodeLockHelp: String { return self._s[1885]! } - public var SocksProxySetup_SecretPlaceholder: String { return self._s[1886]! } - public var NetworkUsageSettings_CallDataSection: String { return self._s[1887]! } - public var SettingsSearch_Synonyms_Wallet: String { return self._s[1888]! } - public var TwoStepAuth_PasswordRemovePassportConfirmation: String { return self._s[1889]! } - public var Passport_FieldAddressTranslationHelp: String { return self._s[1890]! } - public var SocksProxySetup_Connection: String { return self._s[1891]! } - public var Passport_Address_TypePassportRegistration: String { return self._s[1892]! } - public var Contacts_PermissionsAllowInSettings: String { return self._s[1893]! } - public var Conversation_Unpin: String { return self._s[1894]! } - public var Notifications_MessageNotificationsExceptionsHelp: String { return self._s[1895]! } - public var TwoFactorSetup_Hint_Placeholder: String { return self._s[1896]! } - public var Call_ReportSkip: String { return self._s[1897]! } + public var ChatList_AddChatsToFolder: String { return self._s[1870]! } + public var Login_ResetAccountProtected_LimitExceeded: String { return self._s[1871]! } + public var Settings_Title: String { return self._s[1873]! } + public var AutoDownloadSettings_Contacts: String { return self._s[1875]! } + public var Appearance_BubbleCornersSetting: String { return self._s[1876]! } + public var Privacy_Calls_AlwaysAllow: String { return self._s[1877]! } + public var Privacy_Forwards_AlwaysAllow_Title: String { return self._s[1879]! } + public var WallpaperPreview_CropBottomText: String { return self._s[1880]! } + public var SecretTimer_VideoDescription: String { return self._s[1881]! } + public var WallpaperPreview_Blurred: String { return self._s[1882]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsExceptions: String { return self._s[1883]! } + public var ChatListFolder_ExcludedSectionHeader: String { return self._s[1885]! } + public var DialogList_PasscodeLockHelp: String { return self._s[1886]! } + public var SocksProxySetup_SecretPlaceholder: String { return self._s[1887]! } + public var NetworkUsageSettings_CallDataSection: String { return self._s[1888]! } + public var SettingsSearch_Synonyms_Wallet: String { return self._s[1889]! } + public var TwoStepAuth_PasswordRemovePassportConfirmation: String { return self._s[1890]! } + public var Passport_FieldAddressTranslationHelp: String { return self._s[1891]! } + public var SocksProxySetup_Connection: String { return self._s[1892]! } + public var Passport_Address_TypePassportRegistration: String { return self._s[1893]! } + public var Contacts_PermissionsAllowInSettings: String { return self._s[1894]! } + public var Conversation_Unpin: String { return self._s[1895]! } + public var Notifications_MessageNotificationsExceptionsHelp: String { return self._s[1896]! } + public var TwoFactorSetup_Hint_Placeholder: String { return self._s[1897]! } + public var Call_ReportSkip: String { return self._s[1898]! } public func VoiceOver_Chat_PhotoFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1898]!, self._r[1898]!, [_0]) + return formatWithArgumentRanges(self._s[1899]!, self._r[1899]!, [_0]) } public func VoiceOver_Chat_Caption(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1900]!, self._r[1900]!, [_0]) + return formatWithArgumentRanges(self._s[1901]!, self._r[1901]!, [_0]) } - public var AutoNightTheme_Automatic: String { return self._s[1901]! } - public var Wallet_TransactionInfo_AddressCopied: String { return self._s[1902]! } - public var Wallet_Month_GenMarch: String { return self._s[1903]! } - public var Passport_Language_az: String { return self._s[1904]! } - public var SettingsSearch_Synonyms_Data_Storage_ClearCache: String { return self._s[1905]! } - public var Watch_UserInfo_Unmute: String { return self._s[1906]! } - public var Channel_Stickers_YourStickers: String { return self._s[1907]! } - public var Channel_DiscussionGroup_UnlinkChannel: String { return self._s[1908]! } - public var Tour_Text1: String { return self._s[1909]! } - public var Common_Delete: String { return self._s[1910]! } - public var Settings_EditPhoto: String { return self._s[1911]! } - public var Common_Edit: String { return self._s[1912]! } - public var ShareMenu_ShareTo: String { return self._s[1914]! } - public var Passport_Identity_ExpiryDate: String { return self._s[1915]! } - public var Preview_DeleteGif: String { return self._s[1916]! } - public var WallpaperPreview_PatternPaternDiscard: String { return self._s[1917]! } - public var ChatSettings_AutoDownloadUsingCellular: String { return self._s[1918]! } - public var Conversation_ViewReply: String { return self._s[1919]! } - public var Stats_LoadingText: String { return self._s[1920]! } - public var Channel_EditAdmin_PermissinAddAdminOn: String { return self._s[1921]! } - public var CheckoutInfo_ReceiverInfoEmailPlaceholder: String { return self._s[1922]! } - public var Channel_AdminLog_CanChangeInfo: String { return self._s[1923]! } + public var AutoNightTheme_Automatic: String { return self._s[1902]! } + public var Wallet_TransactionInfo_AddressCopied: String { return self._s[1903]! } + public var Wallet_Month_GenMarch: String { return self._s[1904]! } + public var Passport_Language_az: String { return self._s[1905]! } + public var SettingsSearch_Synonyms_Data_Storage_ClearCache: String { return self._s[1906]! } + public var Watch_UserInfo_Unmute: String { return self._s[1907]! } + public var Channel_Stickers_YourStickers: String { return self._s[1908]! } + public var Channel_DiscussionGroup_UnlinkChannel: String { return self._s[1909]! } + public var Tour_Text1: String { return self._s[1910]! } + public var Common_Delete: String { return self._s[1911]! } + public var Settings_EditPhoto: String { return self._s[1912]! } + public var Common_Edit: String { return self._s[1913]! } + public var ShareMenu_ShareTo: String { return self._s[1915]! } + public var Passport_Identity_ExpiryDate: String { return self._s[1916]! } + public var Preview_DeleteGif: String { return self._s[1917]! } + public var WallpaperPreview_PatternPaternDiscard: String { return self._s[1918]! } + public var ChatSettings_AutoDownloadUsingCellular: String { return self._s[1919]! } + public var Conversation_ViewReply: String { return self._s[1920]! } + public var Stats_LoadingText: String { return self._s[1921]! } + public var Channel_EditAdmin_PermissinAddAdminOn: String { return self._s[1922]! } + public var CheckoutInfo_ReceiverInfoEmailPlaceholder: String { return self._s[1923]! } + public var Channel_AdminLog_CanChangeInfo: String { return self._s[1924]! } public func Passport_Phone_UseTelegramNumber(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1924]!, self._r[1924]!, [_0]) - } - public func Time_MonthOfYear_m2(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[1925]!, self._r[1925]!, [_0]) } + public func Time_MonthOfYear_m2(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1926]!, self._r[1926]!, [_0]) + } public func VoiceOver_Chat_VideoMessageFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1927]!, self._r[1927]!, [_0]) + return formatWithArgumentRanges(self._s[1928]!, self._r[1928]!, [_0]) } - public var Passport_Address_OneOfTypeRentalAgreement: String { return self._s[1928]! } - public var Wallet_SecureStorageChanged_ImportWallet: String { return self._s[1931]! } - public var IntentsSettings_MainAccount: String { return self._s[1932]! } - public var Group_MessagePhotoRemoved: String { return self._s[1935]! } - public var Conversation_ContextMenuSelect: String { return self._s[1936]! } - public var GroupInfo_Permissions_Exceptions: String { return self._s[1938]! } - public var GroupRemoved_UsersSectionTitle: String { return self._s[1939]! } - public var Contacts_PermissionsEnable: String { return self._s[1940]! } - public var Channel_EditAdmin_PermissionDeleteMessagesOfOthers: String { return self._s[1941]! } - public var Common_NotNow: String { return self._s[1942]! } - public var Notification_CreatedChannel: String { return self._s[1943]! } - public var Stats_ViewsBySourceTitle: String { return self._s[1945]! } - public var Appearance_AppIconClassic: String { return self._s[1946]! } - public var PhotoEditor_QualityTool: String { return self._s[1947]! } - public var ClearCache_ClearCache: String { return self._s[1948]! } - public var TwoFactorSetup_Password_PlaceholderConfirmPassword: String { return self._s[1949]! } - public var AutoDownloadSettings_Videos: String { return self._s[1950]! } - public var GroupPermission_Duration: String { return self._s[1951]! } - public var ChatList_Read: String { return self._s[1952]! } + public var Passport_Address_OneOfTypeRentalAgreement: String { return self._s[1929]! } + public var Wallet_SecureStorageChanged_ImportWallet: String { return self._s[1932]! } + public var IntentsSettings_MainAccount: String { return self._s[1933]! } + public var Group_MessagePhotoRemoved: String { return self._s[1936]! } + public var Conversation_ContextMenuSelect: String { return self._s[1937]! } + public var GroupInfo_Permissions_Exceptions: String { return self._s[1939]! } + public var GroupRemoved_UsersSectionTitle: String { return self._s[1940]! } + public var Contacts_PermissionsEnable: String { return self._s[1941]! } + public var Channel_EditAdmin_PermissionDeleteMessagesOfOthers: String { return self._s[1942]! } + public var Common_NotNow: String { return self._s[1943]! } + public var Notification_CreatedChannel: String { return self._s[1944]! } + public var Stats_ViewsBySourceTitle: String { return self._s[1946]! } + public var Appearance_AppIconClassic: String { return self._s[1947]! } + public var PhotoEditor_QualityTool: String { return self._s[1948]! } + public var ClearCache_ClearCache: String { return self._s[1949]! } + public var TwoFactorSetup_Password_PlaceholderConfirmPassword: String { return self._s[1950]! } + public var AutoDownloadSettings_Videos: String { return self._s[1951]! } + public var GroupPermission_Duration: String { return self._s[1952]! } + public var ChatList_Read: String { return self._s[1953]! } public func Group_OwnershipTransfer_DescriptionInfo(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1953]!, self._r[1953]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1954]!, self._r[1954]!, [_1, _2]) } - public var CallFeedback_Send: String { return self._s[1954]! } - public var Channel_Stickers_Searching: String { return self._s[1955]! } - public var ScheduledMessages_ReminderNotification: String { return self._s[1956]! } - public var FastTwoStepSetup_HintSection: String { return self._s[1957]! } - public var ChatSettings_AutoDownloadVideoMessages: String { return self._s[1958]! } - public var EditTheme_CreateTitle: String { return self._s[1959]! } - public var Application_Name: String { return self._s[1960]! } - public var Paint_Stickers: String { return self._s[1961]! } - public var Appearance_ThemePreview_Chat_1_Text: String { return self._s[1962]! } - public var Call_StatusFailed: String { return self._s[1963]! } - public var Stickers_FavoriteStickers: String { return self._s[1964]! } - public var ClearCache_Clear: String { return self._s[1965]! } - public var Passport_Language_mn: String { return self._s[1966]! } - public var WallpaperPreview_PreviewTopText: String { return self._s[1967]! } - public var LogoutOptions_ClearCacheTitle: String { return self._s[1968]! } - public var TwoFactorSetup_Hint_Text: String { return self._s[1971]! } - public var WallpaperPreview_PatternIntensity: String { return self._s[1972]! } - public var CheckoutInfo_ErrorShippingNotAvailable: String { return self._s[1973]! } - public var Wallet_RestoreFailed_CreateWallet: String { return self._s[1974]! } - public var Passport_Address_AddBankStatement: String { return self._s[1975]! } + public var CallFeedback_Send: String { return self._s[1955]! } + public var Channel_Stickers_Searching: String { return self._s[1956]! } + public var ScheduledMessages_ReminderNotification: String { return self._s[1957]! } + public var FastTwoStepSetup_HintSection: String { return self._s[1958]! } + public var ChatSettings_AutoDownloadVideoMessages: String { return self._s[1959]! } + public var EditTheme_CreateTitle: String { return self._s[1960]! } + public var Application_Name: String { return self._s[1961]! } + public var Paint_Stickers: String { return self._s[1962]! } + public var Appearance_ThemePreview_Chat_1_Text: String { return self._s[1963]! } + public var Call_StatusFailed: String { return self._s[1964]! } + public var Stickers_FavoriteStickers: String { return self._s[1965]! } + public var ClearCache_Clear: String { return self._s[1966]! } + public var Passport_Language_mn: String { return self._s[1967]! } + public var WallpaperPreview_PreviewTopText: String { return self._s[1968]! } + public var LogoutOptions_ClearCacheTitle: String { return self._s[1969]! } + public var TwoFactorSetup_Hint_Text: String { return self._s[1972]! } + public var WallpaperPreview_PatternIntensity: String { return self._s[1973]! } + public var CheckoutInfo_ErrorShippingNotAvailable: String { return self._s[1974]! } + public var Wallet_RestoreFailed_CreateWallet: String { return self._s[1975]! } + public var Passport_Address_AddBankStatement: String { return self._s[1976]! } public func Conversation_TitleRepliesFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1977]!, self._r[1977]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1978]!, self._r[1978]!, [_1, _2]) } - public var ChatListFolderSettings_RecommendedNewFolder: String { return self._s[1978]! } - public var UserInfo_ShareContact: String { return self._s[1979]! } - public var Passport_Identity_NamePlaceholder: String { return self._s[1980]! } - public var Wallet_Receive_InvoiceUrlCopied: String { return self._s[1982]! } - public var Call_RateCall: String { return self._s[1983]! } - public var Contacts_AccessDeniedError: String { return self._s[1984]! } - public var Invite_ChannelsTooMuch: String { return self._s[1985]! } - public var CheckoutInfo_ShippingInfoPostcode: String { return self._s[1986]! } - public var Channel_BanUser_PermissionReadMessages: String { return self._s[1987]! } - public var Cache_NoLimit: String { return self._s[1989]! } - public var Conversation_EmptyPlaceholder: String { return self._s[1993]! } - public var Privacy_GroupsAndChannels_AlwaysAllow_Placeholder: String { return self._s[1994]! } - public var GroupRemoved_RemoveInfo: String { return self._s[1996]! } - public var Privacy_Calls_IntegrationHelp: String { return self._s[1997]! } + public var ChatListFolderSettings_RecommendedNewFolder: String { return self._s[1979]! } + public var UserInfo_ShareContact: String { return self._s[1980]! } + public var Passport_Identity_NamePlaceholder: String { return self._s[1981]! } + public var Wallet_Receive_InvoiceUrlCopied: String { return self._s[1983]! } + public var Call_RateCall: String { return self._s[1984]! } + public var Contacts_AccessDeniedError: String { return self._s[1985]! } + public var Invite_ChannelsTooMuch: String { return self._s[1986]! } + public var CheckoutInfo_ShippingInfoPostcode: String { return self._s[1987]! } + public var Channel_BanUser_PermissionReadMessages: String { return self._s[1988]! } + public var Cache_NoLimit: String { return self._s[1990]! } + public var Conversation_EmptyPlaceholder: String { return self._s[1994]! } + public var Privacy_GroupsAndChannels_AlwaysAllow_Placeholder: String { return self._s[1995]! } + public var GroupRemoved_RemoveInfo: String { return self._s[1997]! } + public var Privacy_Calls_IntegrationHelp: String { return self._s[1998]! } public func PUSH_VIDEO_CALL_MISSED(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1998]!, self._r[1998]!, [_1]) + return formatWithArgumentRanges(self._s[1999]!, self._r[1999]!, [_1]) } - public var VoiceOver_Media_PlaybackRateFast: String { return self._s[1999]! } - public var Theme_ThemeChanged: String { return self._s[2000]! } - public var Privacy_GroupsAndChannels_NeverAllow: String { return self._s[2002]! } - public var AutoDownloadSettings_MediaTypes: String { return self._s[2003]! } + public var VoiceOver_Media_PlaybackRateFast: String { return self._s[2000]! } + public var Theme_ThemeChanged: String { return self._s[2001]! } + public var Privacy_GroupsAndChannels_NeverAllow: String { return self._s[2003]! } + public var AutoDownloadSettings_MediaTypes: String { return self._s[2004]! } public func Notification_PinnedDocumentMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2004]!, self._r[2004]!, [_0]) + return formatWithArgumentRanges(self._s[2005]!, self._r[2005]!, [_0]) } - public var Channel_AdminLog_InfoPanelTitle: String { return self._s[2005]! } - public var Passport_Language_da: String { return self._s[2007]! } - public var Wallet_Receive_AmountText: String { return self._s[2008]! } - public var Chat_SlowmodeSendError: String { return self._s[2009]! } - public var Application_Update: String { return self._s[2011]! } - public var SocksProxySetup_SaveProxy: String { return self._s[2012]! } + public var Channel_AdminLog_InfoPanelTitle: String { return self._s[2006]! } + public var Passport_Language_da: String { return self._s[2008]! } + public var Wallet_Receive_AmountText: String { return self._s[2009]! } + public var Chat_SlowmodeSendError: String { return self._s[2010]! } + public var Application_Update: String { return self._s[2012]! } + public var SocksProxySetup_SaveProxy: String { return self._s[2013]! } public func PUSH_AUTH_REGION(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2013]!, self._r[2013]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2014]!, self._r[2014]!, [_1, _2]) } - public var Wallet_Receive_ShareAddress: String { return self._s[2015]! } - public var Privacy_AddNewPeer: String { return self._s[2016]! } - public var Channel_DiscussionGroup_MakeHistoryPublicProceed: String { return self._s[2018]! } - public var Wallet_Receive_CommentInfo: String { return self._s[2019]! } - public var Channel_Members_Title: String { return self._s[2020]! } - public var Settings_LogoutConfirmationText: String { return self._s[2021]! } - public var Chat_UnsendMyMessages: String { return self._s[2022]! } - public var Conversation_EditingMessageMediaEditCurrentVideo: String { return self._s[2024]! } - public var ChatListFilter_AddChatsTitle: String { return self._s[2025]! } - public var Passport_FloodError: String { return self._s[2026]! } - public var NotificationSettings_ContactJoinedInfo: String { return self._s[2027]! } - public var SettingsSearch_Synonyms_Privacy_Data_SecretChatLinkPreview: String { return self._s[2028]! } - public var CallSettings_TabIconDescription: String { return self._s[2029]! } - public var Wallet_Intro_Text: String { return self._s[2030]! } - public var Group_Setup_HistoryHeader: String { return self._s[2032]! } - public var TwoStepAuth_EmailTitle: String { return self._s[2033]! } - public var GroupInfo_Permissions_Removed: String { return self._s[2034]! } - public var DialogList_ClearHistoryConfirmation: String { return self._s[2035]! } - public var Contacts_Title: String { return self._s[2037]! } + public var Wallet_Receive_ShareAddress: String { return self._s[2016]! } + public var Privacy_AddNewPeer: String { return self._s[2017]! } + public var Channel_DiscussionGroup_MakeHistoryPublicProceed: String { return self._s[2019]! } + public var Wallet_Receive_CommentInfo: String { return self._s[2020]! } + public var Channel_Members_Title: String { return self._s[2021]! } + public var Settings_LogoutConfirmationText: String { return self._s[2022]! } + public var Chat_UnsendMyMessages: String { return self._s[2023]! } + public var Conversation_EditingMessageMediaEditCurrentVideo: String { return self._s[2025]! } + public var ChatListFilter_AddChatsTitle: String { return self._s[2026]! } + public var Passport_FloodError: String { return self._s[2027]! } + public var NotificationSettings_ContactJoinedInfo: String { return self._s[2028]! } + public var SettingsSearch_Synonyms_Privacy_Data_SecretChatLinkPreview: String { return self._s[2029]! } + public var CallSettings_TabIconDescription: String { return self._s[2030]! } + public var Wallet_Intro_Text: String { return self._s[2031]! } + public var Group_Setup_HistoryHeader: String { return self._s[2033]! } + public var TwoStepAuth_EmailTitle: String { return self._s[2034]! } + public var GroupInfo_Permissions_Removed: String { return self._s[2035]! } + public var DialogList_ClearHistoryConfirmation: String { return self._s[2036]! } + public var Contacts_Title: String { return self._s[2038]! } public func Notification_Invited(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2038]!, self._r[2038]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2039]!, self._r[2039]!, [_0, _1]) } - public var ChatList_PeerTypeBot: String { return self._s[2041]! } + public var ChatList_PeerTypeBot: String { return self._s[2042]! } public func Channel_AdminLog_SetSlowmode(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2042]!, self._r[2042]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2043]!, self._r[2043]!, [_1, _2]) } - public var Appearance_ThemePreview_Chat_6_Text: String { return self._s[2043]! } + public var Appearance_ThemePreview_Chat_6_Text: String { return self._s[2044]! } public func Time_PreciseDate_m1(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2044]!, self._r[2044]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2045]!, self._r[2045]!, [_1, _2, _3]) } - public var Camera_PhotoMode: String { return self._s[2046]! } + public var Camera_PhotoMode: String { return self._s[2047]! } public func PUSH_MESSAGE_GAME_SCORE(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2047]!, self._r[2047]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2048]!, self._r[2048]!, [_1, _2, _3]) } - public var ContactInfo_PhoneLabelPager: String { return self._s[2048]! } - public var SettingsSearch_Synonyms_FAQ: String { return self._s[2049]! } - public var Call_CallAgain: String { return self._s[2050]! } - public var TwoStepAuth_PasswordSet: String { return self._s[2051]! } + public var ContactInfo_PhoneLabelPager: String { return self._s[2049]! } + public var SettingsSearch_Synonyms_FAQ: String { return self._s[2050]! } + public var Call_CallAgain: String { return self._s[2051]! } + public var TwoStepAuth_PasswordSet: String { return self._s[2052]! } public func Channel_Management_RestrictedBy(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2052]!, self._r[2052]!, [_0]) + return formatWithArgumentRanges(self._s[2053]!, self._r[2053]!, [_0]) } - public var GroupInfo_InviteLink_RevokeAlert_Success: String { return self._s[2053]! } - public var ClearCache_FreeSpaceDescription: String { return self._s[2054]! } - public var Permissions_ContactsAllowInSettings_v0: String { return self._s[2055]! } - public var Group_LeaveGroup: String { return self._s[2056]! } - public var Wallet_WordImport_IncorrectText: String { return self._s[2059]! } - public var GroupInfo_LabelAdmin: String { return self._s[2060]! } - public var CheckoutInfo_ErrorStateInvalid: String { return self._s[2062]! } - public var Notification_PassportValuePersonalDetails: String { return self._s[2063]! } + public var GroupInfo_InviteLink_RevokeAlert_Success: String { return self._s[2054]! } + public var ClearCache_FreeSpaceDescription: String { return self._s[2055]! } + public var Permissions_ContactsAllowInSettings_v0: String { return self._s[2056]! } + public var Group_LeaveGroup: String { return self._s[2057]! } + public var Wallet_WordImport_IncorrectText: String { return self._s[2060]! } + public var GroupInfo_LabelAdmin: String { return self._s[2061]! } + public var CheckoutInfo_ErrorStateInvalid: String { return self._s[2063]! } + public var Notification_PassportValuePersonalDetails: String { return self._s[2064]! } public func WebSearch_SearchNoResultsDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2064]!, self._r[2064]!, [_0]) + return formatWithArgumentRanges(self._s[2065]!, self._r[2065]!, [_0]) } - public var Stats_GroupNewMembersBySourceTitle: String { return self._s[2065]! } - public var Appearance_Preview: String { return self._s[2066]! } - public var VoiceOver_Chat_Contact: String { return self._s[2067]! } - public var Passport_Language_th: String { return self._s[2068]! } - public var PhotoEditor_CropAspectRatioOriginal: String { return self._s[2071]! } - public var LastSeen_Offline: String { return self._s[2074]! } - public var Map_OpenInHereMaps: String { return self._s[2075]! } - public var SettingsSearch_Synonyms_Data_AutoplayVideos: String { return self._s[2076]! } - public var AutoDownloadSettings_Reset: String { return self._s[2078]! } - public var Wallet_Month_GenFebruary: String { return self._s[2079]! } - public var Conversation_SendMessage_SetReminder: String { return self._s[2080]! } - public var Channel_AdminLog_EmptyMessageText: String { return self._s[2081]! } + public var Stats_GroupNewMembersBySourceTitle: String { return self._s[2066]! } + public var Appearance_Preview: String { return self._s[2067]! } + public var VoiceOver_Chat_Contact: String { return self._s[2068]! } + public var Passport_Language_th: String { return self._s[2069]! } + public var PhotoEditor_CropAspectRatioOriginal: String { return self._s[2072]! } + public var LastSeen_Offline: String { return self._s[2075]! } + public var Map_OpenInHereMaps: String { return self._s[2076]! } + public var SettingsSearch_Synonyms_Data_AutoplayVideos: String { return self._s[2077]! } + public var AutoDownloadSettings_Reset: String { return self._s[2079]! } + public var Wallet_Month_GenFebruary: String { return self._s[2080]! } + public var Conversation_SendMessage_SetReminder: String { return self._s[2081]! } + public var Channel_AdminLog_EmptyMessageText: String { return self._s[2082]! } public func AddContact_StatusSuccess(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2082]!, self._r[2082]!, [_0]) - } - public func AuthCode_Alert(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2083]!, self._r[2083]!, [_0]) } - public var Passport_Identity_EditDriversLicense: String { return self._s[2084]! } - public var ChatListFolder_NameNonMuted: String { return self._s[2085]! } - public var Username_Placeholder: String { return self._s[2086]! } + public func AuthCode_Alert(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2084]!, self._r[2084]!, [_0]) + } + public var Passport_Identity_EditDriversLicense: String { return self._s[2085]! } + public var ChatListFolder_NameNonMuted: String { return self._s[2086]! } + public var Username_Placeholder: String { return self._s[2087]! } public func PUSH_ALBUM(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2087]!, self._r[2087]!, [_1]) + return formatWithArgumentRanges(self._s[2088]!, self._r[2088]!, [_1]) } - public var Wallet_Send_NetworkErrorText: String { return self._s[2088]! } - public var Checkout_NewCard_SaveInfo: String { return self._s[2089]! } - public var Passport_Language_it: String { return self._s[2090]! } + public var Wallet_Send_NetworkErrorText: String { return self._s[2089]! } + public var Checkout_NewCard_SaveInfo: String { return self._s[2090]! } + public var Passport_Language_it: String { return self._s[2091]! } public func Channel_OwnershipTransfer_DescriptionInfo(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2091]!, self._r[2091]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2092]!, self._r[2092]!, [_1, _2]) } - public var NotificationsSound_Pulse: String { return self._s[2092]! } - public var MessagePoll_NoVotes: String { return self._s[2096]! } - public var Message_Wallpaper: String { return self._s[2097]! } - public var Wallet_Created_Proceed: String { return self._s[2098]! } - public var Appearance_Other: String { return self._s[2099]! } - public var Passport_Identity_NativeNameHelp: String { return self._s[2101]! } - public var Group_PublicLink_Placeholder: String { return self._s[2104]! } - public var Appearance_ThemePreview_ChatList_2_Text: String { return self._s[2105]! } - public var VoiceOver_Recording_StopAndPreview: String { return self._s[2106]! } - public var ChatListFolder_NameBots: String { return self._s[2107]! } - public var Conversation_StopPollConfirmation: String { return self._s[2108]! } - public var UserInfo_DeleteContact: String { return self._s[2109]! } + public var NotificationsSound_Pulse: String { return self._s[2093]! } + public var MessagePoll_NoVotes: String { return self._s[2097]! } + public var Message_Wallpaper: String { return self._s[2098]! } + public var Wallet_Created_Proceed: String { return self._s[2099]! } + public var Appearance_Other: String { return self._s[2100]! } + public var Passport_Identity_NativeNameHelp: String { return self._s[2102]! } + public var Group_PublicLink_Placeholder: String { return self._s[2105]! } + public var Appearance_ThemePreview_ChatList_2_Text: String { return self._s[2106]! } + public var VoiceOver_Recording_StopAndPreview: String { return self._s[2107]! } + public var ChatListFolder_NameBots: String { return self._s[2108]! } + public var Conversation_StopPollConfirmation: String { return self._s[2109]! } + public var UserInfo_DeleteContact: String { return self._s[2110]! } public func Time_MonthOfYear_m11(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2110]!, self._r[2110]!, [_0]) + return formatWithArgumentRanges(self._s[2111]!, self._r[2111]!, [_0]) } - public var Wallpaper_Wallpaper: String { return self._s[2112]! } + public var Wallpaper_Wallpaper: String { return self._s[2113]! } public func PUSH_MESSAGE_NOTEXT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2113]!, self._r[2113]!, [_1]) + return formatWithArgumentRanges(self._s[2114]!, self._r[2114]!, [_1]) } - public var LoginPassword_ForgotPassword: String { return self._s[2114]! } - public var FeaturedStickerPacks_Title: String { return self._s[2115]! } - public var Paint_Pen: String { return self._s[2116]! } - public var Channel_AdminLogFilter_EventsInfo: String { return self._s[2117]! } - public var ChatListFolderSettings_Info: String { return self._s[2118]! } - public var FastTwoStepSetup_HintPlaceholder: String { return self._s[2119]! } - public var PhotoEditor_CurvesAll: String { return self._s[2121]! } - public var Wallet_Info_UnknownTransaction: String { return self._s[2122]! } + public var LoginPassword_ForgotPassword: String { return self._s[2115]! } + public var FeaturedStickerPacks_Title: String { return self._s[2116]! } + public var Paint_Pen: String { return self._s[2117]! } + public var Channel_AdminLogFilter_EventsInfo: String { return self._s[2118]! } + public var ChatListFolderSettings_Info: String { return self._s[2119]! } + public var FastTwoStepSetup_HintPlaceholder: String { return self._s[2120]! } + public var PhotoEditor_CurvesAll: String { return self._s[2122]! } + public var Wallet_Info_UnknownTransaction: String { return self._s[2123]! } public func Time_PreciseDate_m12(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2124]!, self._r[2124]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2125]!, self._r[2125]!, [_1, _2, _3]) } - public var Passport_Address_TypeRentalAgreement: String { return self._s[2126]! } - public var Message_ImageExpired: String { return self._s[2127]! } - public var Call_ConnectionErrorMessage: String { return self._s[2128]! } - public var SearchImages_NoImagesFound: String { return self._s[2130]! } - public var PeerInfo_PaneGifs: String { return self._s[2131]! } - public var Passport_DeletePersonalDetailsConfirmation: String { return self._s[2132]! } - public var EnterPasscode_RepeatNewPasscode: String { return self._s[2133]! } - public var PhotoEditor_VignetteTool: String { return self._s[2134]! } - public var Passport_Language_dz: String { return self._s[2135]! } - public var Notifications_ChannelNotificationsHelp: String { return self._s[2136]! } - public var Conversation_BlockUser: String { return self._s[2137]! } + public var Passport_Address_TypeRentalAgreement: String { return self._s[2127]! } + public var Message_ImageExpired: String { return self._s[2128]! } + public var Call_ConnectionErrorMessage: String { return self._s[2129]! } + public var SearchImages_NoImagesFound: String { return self._s[2131]! } + public var PeerInfo_PaneGifs: String { return self._s[2132]! } + public var Passport_DeletePersonalDetailsConfirmation: String { return self._s[2133]! } + public var EnterPasscode_RepeatNewPasscode: String { return self._s[2134]! } + public var PhotoEditor_VignetteTool: String { return self._s[2135]! } + public var Passport_Language_dz: String { return self._s[2136]! } + public var Notifications_ChannelNotificationsHelp: String { return self._s[2137]! } + public var Conversation_BlockUser: String { return self._s[2138]! } public func Wallet_Send_Balance(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2139]!, self._r[2139]!, [_0]) + return formatWithArgumentRanges(self._s[2140]!, self._r[2140]!, [_0]) } - public var GroupPermission_PermissionDisabledByDefault: String { return self._s[2140]! } - public var Group_OwnershipTransfer_ErrorAdminsTooMuch: String { return self._s[2141]! } + public var GroupPermission_PermissionDisabledByDefault: String { return self._s[2141]! } + public var Group_OwnershipTransfer_ErrorAdminsTooMuch: String { return self._s[2142]! } public func Time_MonthOfYear_m8(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2142]!, self._r[2142]!, [_0]) + return formatWithArgumentRanges(self._s[2143]!, self._r[2143]!, [_0]) } - public var KeyCommand_NewMessage: String { return self._s[2143]! } - public var EditTheme_Edit_Preview_IncomingReplyText: String { return self._s[2145]! } + public var KeyCommand_NewMessage: String { return self._s[2144]! } + public var EditTheme_Edit_Preview_IncomingReplyText: String { return self._s[2146]! } public func PUSH_CHAT_MESSAGE_GEO(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2147]!, self._r[2147]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2148]!, self._r[2148]!, [_1, _2]) } - public var ContactList_Context_StartSecretChat: String { return self._s[2148]! } - public var VoiceOver_Chat_File: String { return self._s[2149]! } - public var ChatList_EditFolder: String { return self._s[2151]! } - public var Appearance_BubbleCorners_Title: String { return self._s[2152]! } - public var PeerInfo_PaneAudio: String { return self._s[2153]! } - public var Wallet_SecureStorageReset_Title: String { return self._s[2154]! } - public var ChatListFolder_CategoryContacts: String { return self._s[2156]! } + public var ContactList_Context_StartSecretChat: String { return self._s[2149]! } + public var VoiceOver_Chat_File: String { return self._s[2150]! } + public var ChatList_EditFolder: String { return self._s[2152]! } + public var Appearance_BubbleCorners_Title: String { return self._s[2153]! } + public var PeerInfo_PaneAudio: String { return self._s[2154]! } + public var Wallet_SecureStorageReset_Title: String { return self._s[2155]! } + public var ChatListFolder_CategoryContacts: String { return self._s[2157]! } public func Login_InvalidPhoneEmailBody(_ _1: String, _ _2: String, _ _3: String, _ _4: String, _ _5: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2157]!, self._r[2157]!, [_1, _2, _3, _4, _5]) + return formatWithArgumentRanges(self._s[2158]!, self._r[2158]!, [_1, _2, _3, _4, _5]) } - public var ChatList_PeerTypeChannel: String { return self._s[2158]! } - public var VoiceOver_Navigation_Search: String { return self._s[2159]! } - public var Settings_Search: String { return self._s[2160]! } - public var WallpaperSearch_ColorYellow: String { return self._s[2161]! } - public var Login_PhoneBannedError: String { return self._s[2162]! } - public var KeyCommand_JumpToNextChat: String { return self._s[2163]! } - public var Passport_Language_fa: String { return self._s[2164]! } - public var Settings_About: String { return self._s[2165]! } - public var Wallet_Configuration_Title: String { return self._s[2166]! } - public var AutoDownloadSettings_MaxFileSize: String { return self._s[2167]! } - public var Channel_AdminLog_InfoPanelChannelAlertText: String { return self._s[2168]! } - public var AutoDownloadSettings_DataUsageHigh: String { return self._s[2169]! } + public var ChatList_PeerTypeChannel: String { return self._s[2159]! } + public var VoiceOver_Navigation_Search: String { return self._s[2160]! } + public var Settings_Search: String { return self._s[2161]! } + public var WallpaperSearch_ColorYellow: String { return self._s[2162]! } + public var Login_PhoneBannedError: String { return self._s[2163]! } + public var KeyCommand_JumpToNextChat: String { return self._s[2164]! } + public var Passport_Language_fa: String { return self._s[2165]! } + public var Settings_About: String { return self._s[2166]! } + public var Wallet_Configuration_Title: String { return self._s[2167]! } + public var AutoDownloadSettings_MaxFileSize: String { return self._s[2168]! } + public var Channel_AdminLog_InfoPanelChannelAlertText: String { return self._s[2169]! } + public var AutoDownloadSettings_DataUsageHigh: String { return self._s[2170]! } public func PUSH_CHAT_MESSAGE_TEXT(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2170]!, self._r[2170]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2171]!, self._r[2171]!, [_1, _2, _3]) } - public var Common_OK: String { return self._s[2171]! } - public var Contacts_SortBy: String { return self._s[2172]! } - public var AutoNightTheme_PreferredTheme: String { return self._s[2173]! } + public var Common_OK: String { return self._s[2172]! } + public var Contacts_SortBy: String { return self._s[2173]! } + public var AutoNightTheme_PreferredTheme: String { return self._s[2174]! } public func AutoDownloadSettings_OnFor(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2175]!, self._r[2175]!, [_0]) + return formatWithArgumentRanges(self._s[2176]!, self._r[2176]!, [_0]) } - public var CallFeedback_IncludeLogs: String { return self._s[2178]! } + public var CallFeedback_IncludeLogs: String { return self._s[2179]! } public func External_OpenIn(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2179]!, self._r[2179]!, [_0]) + return formatWithArgumentRanges(self._s[2180]!, self._r[2180]!, [_0]) } - public var Passcode_AppLockedAlert: String { return self._s[2180]! } - public var TwoStepAuth_SetupPasswordTitle: String { return self._s[2181]! } - public var Wallet_Send_ErrorDecryptionFailed: String { return self._s[2182]! } - public var Channel_NotificationLoading: String { return self._s[2184]! } - public var Passport_Identity_DocumentNumber: String { return self._s[2185]! } - public var VoiceOver_Chat_PagePreview: String { return self._s[2186]! } - public var VoiceOver_Chat_OpenHint: String { return self._s[2187]! } - public var Weekday_ShortFriday: String { return self._s[2188]! } - public var Wallet_CreateInvoice_Title: String { return self._s[2189]! } - public var Conversation_TitleMute: String { return self._s[2190]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsSound: String { return self._s[2191]! } - public var ScheduledMessages_PollUnavailable: String { return self._s[2192]! } - public var DialogList_LanguageTooltip: String { return self._s[2193]! } - public var Channel_AdminLogFilter_EventsPinned: String { return self._s[2195]! } + public var Passcode_AppLockedAlert: String { return self._s[2181]! } + public var TwoStepAuth_SetupPasswordTitle: String { return self._s[2182]! } + public var Wallet_Send_ErrorDecryptionFailed: String { return self._s[2183]! } + public var Channel_NotificationLoading: String { return self._s[2185]! } + public var Passport_Identity_DocumentNumber: String { return self._s[2186]! } + public var VoiceOver_Chat_PagePreview: String { return self._s[2187]! } + public var VoiceOver_Chat_OpenHint: String { return self._s[2188]! } + public var Weekday_ShortFriday: String { return self._s[2189]! } + public var Wallet_CreateInvoice_Title: String { return self._s[2190]! } + public var Conversation_TitleMute: String { return self._s[2191]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsSound: String { return self._s[2192]! } + public var ScheduledMessages_PollUnavailable: String { return self._s[2193]! } + public var DialogList_LanguageTooltip: String { return self._s[2194]! } + public var Channel_AdminLogFilter_EventsPinned: String { return self._s[2196]! } public func DialogList_SingleUploadingVideoSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2196]!, self._r[2196]!, [_0]) + return formatWithArgumentRanges(self._s[2197]!, self._r[2197]!, [_0]) } - public var TwoStepAuth_SetupResendEmailCodeAlert: String { return self._s[2198]! } - public var Privacy_Calls_AlwaysAllow_Title: String { return self._s[2199]! } - public var Settings_EditVideo: String { return self._s[2200]! } - public var Stickers_FrequentlyUsed: String { return self._s[2201]! } - public var GroupPermission_Title: String { return self._s[2202]! } - public var AccessDenied_VideoMessageCamera: String { return self._s[2203]! } - public var Appearance_ThemeCarouselDay: String { return self._s[2204]! } + public var TwoStepAuth_SetupResendEmailCodeAlert: String { return self._s[2199]! } + public var Privacy_Calls_AlwaysAllow_Title: String { return self._s[2200]! } + public var Settings_EditVideo: String { return self._s[2201]! } + public var Stickers_FrequentlyUsed: String { return self._s[2202]! } + public var GroupPermission_Title: String { return self._s[2203]! } + public var AccessDenied_VideoMessageCamera: String { return self._s[2204]! } + public var Appearance_ThemeCarouselDay: String { return self._s[2205]! } public func PUSH_CHAT_MESSAGE_AUDIO(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2205]!, self._r[2205]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2206]!, self._r[2206]!, [_1, _2]) } - public var Passport_Identity_DocumentNumberPlaceholder: String { return self._s[2206]! } - public var Tour_Title6: String { return self._s[2207]! } - public var EmptyGroupInfo_Title: String { return self._s[2208]! } + public var Passport_Identity_DocumentNumberPlaceholder: String { return self._s[2207]! } + public var Tour_Title6: String { return self._s[2208]! } + public var EmptyGroupInfo_Title: String { return self._s[2209]! } public func Channel_AdminLog_MessageToggleSignaturesOn(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2209]!, self._r[2209]!, [_0]) + return formatWithArgumentRanges(self._s[2210]!, self._r[2210]!, [_0]) } - public var Passport_Language_sk: String { return self._s[2210]! } - public var VoiceOver_Chat_YourAnonymousPoll: String { return self._s[2211]! } - public var Preview_SaveToCameraRoll: String { return self._s[2212]! } - public var LogoutOptions_SetPasscodeTitle: String { return self._s[2213]! } - public var Passport_Address_TypeUtilityBillUploadScan: String { return self._s[2214]! } - public var Conversation_ContextMenuMore: String { return self._s[2215]! } - public var Conversation_ForwardAuthorHiddenTooltip: String { return self._s[2216]! } - public var Channel_AdminLog_CanBeAnonymous: String { return self._s[2217]! } - public var CallFeedback_ReasonSilentLocal: String { return self._s[2219]! } - public var UserInfo_NotificationsDisable: String { return self._s[2220]! } + public var Passport_Language_sk: String { return self._s[2211]! } + public var VoiceOver_Chat_YourAnonymousPoll: String { return self._s[2212]! } + public var Preview_SaveToCameraRoll: String { return self._s[2213]! } + public var LogoutOptions_SetPasscodeTitle: String { return self._s[2214]! } + public var Passport_Address_TypeUtilityBillUploadScan: String { return self._s[2215]! } + public var Conversation_ContextMenuMore: String { return self._s[2216]! } + public var Conversation_ForwardAuthorHiddenTooltip: String { return self._s[2217]! } + public var Channel_AdminLog_CanBeAnonymous: String { return self._s[2218]! } + public var CallFeedback_ReasonSilentLocal: String { return self._s[2220]! } + public var UserInfo_NotificationsDisable: String { return self._s[2221]! } public func Channel_AdminLog_EmptyFilterQueryText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2222]!, self._r[2222]!, [_0]) + return formatWithArgumentRanges(self._s[2223]!, self._r[2223]!, [_0]) } - public var SettingsSearch_Synonyms_EditProfile_Bio: String { return self._s[2223]! } + public var SettingsSearch_Synonyms_EditProfile_Bio: String { return self._s[2224]! } public func Date_ChatDateHeader(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2225]!, self._r[2225]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2226]!, self._r[2226]!, [_1, _2]) } - public var WallpaperSearch_ColorPrefix: String { return self._s[2226]! } + public var WallpaperSearch_ColorPrefix: String { return self._s[2227]! } public func Message_ForwardedPsa_covid(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2227]!, self._r[2227]!, [_0]) + return formatWithArgumentRanges(self._s[2228]!, self._r[2228]!, [_0]) } - public var Conversation_RestrictedMedia: String { return self._s[2229]! } - public var Group_MessageVideoUpdated: String { return self._s[2230]! } - public var NetworkUsageSettings_ResetStatsConfirmation: String { return self._s[2231]! } - public var GroupInfo_DeleteAndExit: String { return self._s[2232]! } - public var TwoFactorSetup_Email_Action: String { return self._s[2233]! } - public var Media_ShareThisVideo: String { return self._s[2235]! } - public var DialogList_Replies: String { return self._s[2236]! } + public var Conversation_RestrictedMedia: String { return self._s[2230]! } + public var Group_MessageVideoUpdated: String { return self._s[2231]! } + public var NetworkUsageSettings_ResetStatsConfirmation: String { return self._s[2232]! } + public var GroupInfo_DeleteAndExit: String { return self._s[2233]! } + public var TwoFactorSetup_Email_Action: String { return self._s[2234]! } + public var Media_ShareThisVideo: String { return self._s[2236]! } + public var DialogList_Replies: String { return self._s[2237]! } public func Conversation_Moderate_DeleteAllMessages(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2237]!, self._r[2237]!, [_0]) + return formatWithArgumentRanges(self._s[2238]!, self._r[2238]!, [_0]) } - public var CheckoutInfo_ShippingInfoAddress1: String { return self._s[2238]! } - public var Watch_Suggestion_OnMyWay: String { return self._s[2239]! } - public var CheckoutInfo_ShippingInfoAddress2: String { return self._s[2240]! } + public var CheckoutInfo_ShippingInfoAddress1: String { return self._s[2239]! } + public var Watch_Suggestion_OnMyWay: String { return self._s[2240]! } + public var CheckoutInfo_ShippingInfoAddress2: String { return self._s[2241]! } public func PUSH_PINNED_POLL(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2241]!, self._r[2241]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2242]!, self._r[2242]!, [_1, _2]) } public func GroupInfo_InvitationLinkAcceptChannel(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2242]!, self._r[2242]!, [_0]) + return formatWithArgumentRanges(self._s[2243]!, self._r[2243]!, [_0]) } - public var Channel_EditAdmin_PermissinAddAdminOff: String { return self._s[2243]! } - public var Conversation_WalletRequiredSetup: String { return self._s[2244]! } - public var ChatAdmins_AllMembersAreAdminsOnHelp: String { return self._s[2245]! } - public var Channel_Members_InviteLink: String { return self._s[2246]! } - public var ChatList_Search_NoResultsFitlerMedia: String { return self._s[2247]! } - public var Conversation_TapAndHoldToRecord: String { return self._s[2248]! } - public var Wallet_Info_Receive: String { return self._s[2249]! } - public var WatchRemote_AlertText: String { return self._s[2250]! } + public var Channel_EditAdmin_PermissinAddAdminOff: String { return self._s[2244]! } + public var Conversation_WalletRequiredSetup: String { return self._s[2245]! } + public var ChatAdmins_AllMembersAreAdminsOnHelp: String { return self._s[2246]! } + public var Channel_Members_InviteLink: String { return self._s[2247]! } + public var ChatList_Search_NoResultsFitlerMedia: String { return self._s[2248]! } + public var Conversation_TapAndHoldToRecord: String { return self._s[2249]! } + public var Wallet_Info_Receive: String { return self._s[2250]! } + public var WatchRemote_AlertText: String { return self._s[2251]! } public func Channel_DiscussionGroup_PrivateChannelLink(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2251]!, self._r[2251]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2252]!, self._r[2252]!, [_1, _2]) } - public var Conversation_Pin: String { return self._s[2252]! } - public var InfoPlist_NSMicrophoneUsageDescription: String { return self._s[2253]! } - public var Stickers_RemoveFromFavorites: String { return self._s[2254]! } + public var Conversation_Pin: String { return self._s[2253]! } + public var InfoPlist_NSMicrophoneUsageDescription: String { return self._s[2254]! } + public var Stickers_RemoveFromFavorites: String { return self._s[2255]! } public func Notification_PinnedPollMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2255]!, self._r[2255]!, [_0]) + return formatWithArgumentRanges(self._s[2256]!, self._r[2256]!, [_0]) } - public var Appearance_AppIconFilled: String { return self._s[2256]! } - public var StickerPack_ErrorNotFound: String { return self._s[2257]! } + public var Appearance_AppIconFilled: String { return self._s[2257]! } + public var StickerPack_ErrorNotFound: String { return self._s[2258]! } public func Channel_AdminLog_MessageRestrictedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2258]!, self._r[2258]!, [_1]) + return formatWithArgumentRanges(self._s[2259]!, self._r[2259]!, [_1]) } - public var Passport_Identity_AddIdentityCard: String { return self._s[2259]! } + public var Passport_Identity_AddIdentityCard: String { return self._s[2260]! } public func PUSH_CHANNEL_MESSAGE_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2260]!, self._r[2260]!, [_1]) + return formatWithArgumentRanges(self._s[2261]!, self._r[2261]!, [_1]) } - public var Call_Camera: String { return self._s[2261]! } - public var GroupInfo_InviteLink_RevokeAlert_Text: String { return self._s[2262]! } - public var Group_Location_Info: String { return self._s[2263]! } - public var Watch_LastSeen_WithinAMonth: String { return self._s[2264]! } - public var UserInfo_NotificationsDefaultEnabled: String { return self._s[2265]! } + public var Call_Camera: String { return self._s[2262]! } + public var GroupInfo_InviteLink_RevokeAlert_Text: String { return self._s[2263]! } + public var Group_Location_Info: String { return self._s[2264]! } + public var Watch_LastSeen_WithinAMonth: String { return self._s[2265]! } + public var UserInfo_NotificationsDefaultEnabled: String { return self._s[2266]! } public func DialogList_PinLimitError(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2266]!, self._r[2266]!, [_0]) + return formatWithArgumentRanges(self._s[2267]!, self._r[2267]!, [_0]) } - public var Weekday_Yesterday: String { return self._s[2267]! } - public var TwoStepAuth_SetupPasswordEnterPasswordNew: String { return self._s[2268]! } - public var ArchivedPacksAlert_Title: String { return self._s[2269]! } - public var PeerInfo_PaneMembers: String { return self._s[2270]! } - public var PhotoEditor_SelectCoverFrame: String { return self._s[2271]! } + public var Weekday_Yesterday: String { return self._s[2268]! } + public var TwoStepAuth_SetupPasswordEnterPasswordNew: String { return self._s[2269]! } + public var ArchivedPacksAlert_Title: String { return self._s[2270]! } + public var PeerInfo_PaneMembers: String { return self._s[2271]! } + public var PhotoEditor_SelectCoverFrame: String { return self._s[2272]! } public func Location_ProximityAlertSetTextGroup(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2272]!, self._r[2272]!, [_0]) + return formatWithArgumentRanges(self._s[2273]!, self._r[2273]!, [_0]) } - public var ContactInfo_PhoneLabelMain: String { return self._s[2273]! } + public var ContactInfo_PhoneLabelMain: String { return self._s[2274]! } public func Time_PreciseDate_m7(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2274]!, self._r[2274]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2275]!, self._r[2275]!, [_1, _2, _3]) } - public var TwoFactorSetup_EmailVerification_ChangeAction: String { return self._s[2275]! } - public var Channel_DiscussionGroup: String { return self._s[2276]! } - public var EditTheme_Edit_Preview_IncomingReplyName: String { return self._s[2277]! } - public var Channel_EditAdmin_PermissionsHeader: String { return self._s[2279]! } - public var VoiceOver_MessageContextForward: String { return self._s[2280]! } - public var SocksProxySetup_TypeNone: String { return self._s[2281]! } - public var CreatePoll_MultipleChoiceQuizAlert: String { return self._s[2283]! } - public var ProfilePhoto_OpenInEditor: String { return self._s[2285]! } - public var WallpaperSearch_ColorPurple: String { return self._s[2286]! } - public var ChatListFolder_IncludeChatsTitle: String { return self._s[2287]! } - public var Group_Username_InvalidTooShort: String { return self._s[2288]! } - public var Location_ProximityNotification_DistanceM: String { return self._s[2289]! } + public var TwoFactorSetup_EmailVerification_ChangeAction: String { return self._s[2276]! } + public var Channel_DiscussionGroup: String { return self._s[2277]! } + public var EditTheme_Edit_Preview_IncomingReplyName: String { return self._s[2278]! } + public var Channel_EditAdmin_PermissionsHeader: String { return self._s[2280]! } + public var VoiceOver_MessageContextForward: String { return self._s[2281]! } + public var SocksProxySetup_TypeNone: String { return self._s[2282]! } + public var CreatePoll_MultipleChoiceQuizAlert: String { return self._s[2284]! } + public var ProfilePhoto_OpenInEditor: String { return self._s[2286]! } + public var WallpaperSearch_ColorPurple: String { return self._s[2287]! } + public var ChatListFolder_IncludeChatsTitle: String { return self._s[2288]! } + public var Group_Username_InvalidTooShort: String { return self._s[2289]! } + public var Location_ProximityNotification_DistanceM: String { return self._s[2290]! } public func Login_EmailPhoneBody(_ _0: String, _ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2290]!, self._r[2290]!, [_0, _1, _2]) + return formatWithArgumentRanges(self._s[2291]!, self._r[2291]!, [_0, _1, _2]) } - public var Passport_Language_tk: String { return self._s[2291]! } - public var ConvertToSupergroup_Title: String { return self._s[2292]! } - public var Channel_BanUser_PermissionEmbedLinks: String { return self._s[2293]! } - public var Cache_KeepMediaHelp: String { return self._s[2294]! } - public var Channel_Management_Title: String { return self._s[2295]! } + public var Passport_Language_tk: String { return self._s[2292]! } + public var ConvertToSupergroup_Title: String { return self._s[2293]! } + public var Channel_BanUser_PermissionEmbedLinks: String { return self._s[2294]! } + public var Cache_KeepMediaHelp: String { return self._s[2295]! } + public var Channel_Management_Title: String { return self._s[2296]! } public func PUSH_MESSAGE_PHOTO_SECRET(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2296]!, self._r[2296]!, [_1]) + return formatWithArgumentRanges(self._s[2297]!, self._r[2297]!, [_1]) } - public var Conversation_ForwardChats: String { return self._s[2297]! } - public var Passport_Language_bg: String { return self._s[2298]! } - public var SocksProxySetup_TypeSocks: String { return self._s[2299]! } - public var Permissions_PrivacyPolicy: String { return self._s[2300]! } - public var VoiceOver_Chat_YourMusic: String { return self._s[2301]! } - public var SettingsSearch_Synonyms_Notifications_ResetAllNotifications: String { return self._s[2302]! } - public var Conversation_EmptyGifPanelPlaceholder: String { return self._s[2303]! } - public var Conversation_ContextMenuOpenChannel: String { return self._s[2304]! } - public var Activity_UploadingVideo: String { return self._s[2305]! } - public var PrivacyPolicy_AgeVerificationAgree: String { return self._s[2307]! } - public var Wallet_Sending_Text: String { return self._s[2308]! } - public var SocksProxySetup_Credentials: String { return self._s[2310]! } - public var Preview_SaveGif: String { return self._s[2311]! } - public var Cache_Photos: String { return self._s[2312]! } - public var Conversation_ContextMenuCancelEditing: String { return self._s[2313]! } - public var Wallet_Intro_NotNow: String { return self._s[2314]! } - public var Contacts_FailedToSendInvitesMessage: String { return self._s[2315]! } - public var Passport_Language_lt: String { return self._s[2316]! } - public var Passport_DeleteDocument: String { return self._s[2317]! } - public var GroupInfo_SetGroupPhotoStop: String { return self._s[2318]! } + public var Conversation_ForwardChats: String { return self._s[2298]! } + public var Passport_Language_bg: String { return self._s[2299]! } + public var SocksProxySetup_TypeSocks: String { return self._s[2300]! } + public var Permissions_PrivacyPolicy: String { return self._s[2301]! } + public var VoiceOver_Chat_YourMusic: String { return self._s[2302]! } + public var SettingsSearch_Synonyms_Notifications_ResetAllNotifications: String { return self._s[2303]! } + public var Conversation_EmptyGifPanelPlaceholder: String { return self._s[2304]! } + public var Conversation_ContextMenuOpenChannel: String { return self._s[2305]! } + public var Activity_UploadingVideo: String { return self._s[2306]! } + public var PrivacyPolicy_AgeVerificationAgree: String { return self._s[2308]! } + public var Wallet_Sending_Text: String { return self._s[2309]! } + public var SocksProxySetup_Credentials: String { return self._s[2311]! } + public var Preview_SaveGif: String { return self._s[2312]! } + public var Cache_Photos: String { return self._s[2313]! } + public var Conversation_ContextMenuCancelEditing: String { return self._s[2314]! } + public var Wallet_Intro_NotNow: String { return self._s[2315]! } + public var Contacts_FailedToSendInvitesMessage: String { return self._s[2316]! } + public var Passport_Language_lt: String { return self._s[2317]! } + public var Passport_DeleteDocument: String { return self._s[2318]! } + public var GroupInfo_SetGroupPhotoStop: String { return self._s[2319]! } public func Location_ProximityNotification_NotifyLong(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2319]!, self._r[2319]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2320]!, self._r[2320]!, [_1, _2]) } - public var AccessDenied_VideoMessageMicrophone: String { return self._s[2320]! } + public var AccessDenied_VideoMessageMicrophone: String { return self._s[2321]! } public func PeopleNearby_VisibleUntil(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2321]!, self._r[2321]!, [_0]) + return formatWithArgumentRanges(self._s[2322]!, self._r[2322]!, [_0]) } - public var AccessDenied_VideoCallCamera: String { return self._s[2322]! } + public var AccessDenied_VideoCallCamera: String { return self._s[2323]! } public func Channel_AdminLog_MessageDeleted(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2323]!, self._r[2323]!, [_0]) + return formatWithArgumentRanges(self._s[2324]!, self._r[2324]!, [_0]) } - public var PhotoEditor_SharpenTool: String { return self._s[2324]! } + public var PhotoEditor_SharpenTool: String { return self._s[2325]! } public func PUSH_CHANNEL_MESSAGE_AUDIO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2325]!, self._r[2325]!, [_1]) + return formatWithArgumentRanges(self._s[2326]!, self._r[2326]!, [_1]) } - public var DialogList_Unpin: String { return self._s[2326]! } - public var Stickers_NoStickersFound: String { return self._s[2327]! } - public var UserInfo_AddContact: String { return self._s[2329]! } + public var DialogList_Unpin: String { return self._s[2327]! } + public var Stickers_NoStickersFound: String { return self._s[2328]! } + public var UserInfo_AddContact: String { return self._s[2330]! } public func AddContact_SharedContactExceptionInfo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2331]!, self._r[2331]!, [_0]) - } - public func Notification_PinnedLocationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2332]!, self._r[2332]!, [_0]) } - public var CallFeedback_VideoReasonDistorted: String { return self._s[2333]! } - public var Tour_Text2: String { return self._s[2334]! } + public func Notification_PinnedLocationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2333]!, self._r[2333]!, [_0]) + } + public var CallFeedback_VideoReasonDistorted: String { return self._s[2334]! } + public var Tour_Text2: String { return self._s[2335]! } public func Conversation_TitleCommentsFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2336]!, self._r[2336]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2337]!, self._r[2337]!, [_1, _2]) } - public var Wallet_SecureStorageChanged_CreateWallet: String { return self._s[2337]! } - public var Paint_Delete: String { return self._s[2339]! } - public var SettingsSearch_Synonyms_Notifications_InAppNotificationsVibrate: String { return self._s[2340]! } + public var Wallet_SecureStorageChanged_CreateWallet: String { return self._s[2338]! } + public var Paint_Delete: String { return self._s[2340]! } + public var SettingsSearch_Synonyms_Notifications_InAppNotificationsVibrate: String { return self._s[2341]! } public func PrivacySettings_LastSeenEverybodyMinus(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2342]!, self._r[2342]!, [_0]) + return formatWithArgumentRanges(self._s[2343]!, self._r[2343]!, [_0]) } - public var Privacy_Calls_NeverAllow_Title: String { return self._s[2343]! } - public var Notification_CallOutgoingShort: String { return self._s[2344]! } - public var Checkout_PasswordEntry_Title: String { return self._s[2345]! } - public var Channel_AdminLogFilter_AdminsAll: String { return self._s[2346]! } - public var Notification_MessageLifetime1m: String { return self._s[2347]! } - public var Wallet_TransactionInfo_CommentHeader: String { return self._s[2349]! } - public var BlockedUsers_AddNew: String { return self._s[2350]! } - public var Wallet_Intro_CreateErrorText: String { return self._s[2351]! } - public var FastTwoStepSetup_EmailSection: String { return self._s[2352]! } - public var Settings_SaveEditedPhotos: String { return self._s[2353]! } - public var GroupInfo_GroupNamePlaceholder: String { return self._s[2354]! } - public var Channel_AboutItem: String { return self._s[2355]! } - public var GroupInfo_InviteLink_RevokeLink: String { return self._s[2356]! } - public var Privacy_Calls_P2PNever: String { return self._s[2358]! } - public var Wallet_Weekday_Yesterday: String { return self._s[2359]! } - public var Passport_Language_uk: String { return self._s[2360]! } - public var NetworkUsageSettings_Wifi: String { return self._s[2361]! } - public var Conversation_Moderate_Report: String { return self._s[2362]! } - public var Wallpaper_ResetWallpapersConfirmation: String { return self._s[2363]! } - public var VoiceOver_Chat_SeenByRecipients: String { return self._s[2364]! } - public var Permissions_SiriText_v0: String { return self._s[2365]! } - public var Theme_Colors_Background: String { return self._s[2366]! } - public var Notification_CallMissed: String { return self._s[2367]! } - public var Stats_ZoomOut: String { return self._s[2368]! } - public var Profile_AddToExisting: String { return self._s[2369]! } - public var Passport_FieldAddressUploadHelp: String { return self._s[2372]! } - public var Undo_DeletedChannel: String { return self._s[2373]! } + public var Privacy_Calls_NeverAllow_Title: String { return self._s[2344]! } + public var Notification_CallOutgoingShort: String { return self._s[2345]! } + public var Checkout_PasswordEntry_Title: String { return self._s[2346]! } + public var Channel_AdminLogFilter_AdminsAll: String { return self._s[2347]! } + public var Notification_MessageLifetime1m: String { return self._s[2348]! } + public var Wallet_TransactionInfo_CommentHeader: String { return self._s[2350]! } + public var BlockedUsers_AddNew: String { return self._s[2351]! } + public var Wallet_Intro_CreateErrorText: String { return self._s[2352]! } + public var FastTwoStepSetup_EmailSection: String { return self._s[2353]! } + public var Settings_SaveEditedPhotos: String { return self._s[2354]! } + public var GroupInfo_GroupNamePlaceholder: String { return self._s[2355]! } + public var Channel_AboutItem: String { return self._s[2356]! } + public var GroupInfo_InviteLink_RevokeLink: String { return self._s[2357]! } + public var Privacy_Calls_P2PNever: String { return self._s[2359]! } + public var Wallet_Weekday_Yesterday: String { return self._s[2360]! } + public var Passport_Language_uk: String { return self._s[2361]! } + public var NetworkUsageSettings_Wifi: String { return self._s[2362]! } + public var Conversation_Moderate_Report: String { return self._s[2363]! } + public var Wallpaper_ResetWallpapersConfirmation: String { return self._s[2364]! } + public var VoiceOver_Chat_SeenByRecipients: String { return self._s[2365]! } + public var Permissions_SiriText_v0: String { return self._s[2366]! } + public var Theme_Colors_Background: String { return self._s[2367]! } + public var Notification_CallMissed: String { return self._s[2368]! } + public var Stats_ZoomOut: String { return self._s[2369]! } + public var Profile_AddToExisting: String { return self._s[2370]! } + public var Passport_FieldAddressUploadHelp: String { return self._s[2373]! } + public var Undo_DeletedChannel: String { return self._s[2374]! } public func Channel_AdminLog_MessagePinned(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2374]!, self._r[2374]!, [_0]) + return formatWithArgumentRanges(self._s[2375]!, self._r[2375]!, [_0]) } - public var Login_ResetAccountProtected_TimerTitle: String { return self._s[2375]! } - public var Map_LiveLocationGroupDescription: String { return self._s[2376]! } - public var Passport_InfoFAQ_URL: String { return self._s[2377]! } - public var IntentsSettings_SuggestedChats: String { return self._s[2379]! } + public var Login_ResetAccountProtected_TimerTitle: String { return self._s[2376]! } + public var Map_LiveLocationGroupDescription: String { return self._s[2377]! } + public var Passport_InfoFAQ_URL: String { return self._s[2378]! } + public var IntentsSettings_SuggestedChats: String { return self._s[2380]! } public func PUSH_MESSAGE_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2380]!, self._r[2380]!, [_1]) + return formatWithArgumentRanges(self._s[2381]!, self._r[2381]!, [_1]) } - public var State_connecting: String { return self._s[2381]! } - public var Passport_Identity_Country: String { return self._s[2382]! } - public var Passport_PasswordDescription: String { return self._s[2383]! } - public var ChatList_PsaLabel_covid: String { return self._s[2384]! } + public var State_connecting: String { return self._s[2382]! } + public var Passport_Identity_Country: String { return self._s[2383]! } + public var Passport_PasswordDescription: String { return self._s[2384]! } + public var ChatList_PsaLabel_covid: String { return self._s[2385]! } public func PUSH_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2385]!, self._r[2385]!, [_1]) + return formatWithArgumentRanges(self._s[2386]!, self._r[2386]!, [_1]) } - public var Contacts_AddPeopleNearby: String { return self._s[2386]! } - public var OwnershipTransfer_SetupTwoStepAuth: String { return self._s[2387]! } - public var ClearCache_Description: String { return self._s[2388]! } - public var Localization_LanguageName: String { return self._s[2389]! } + public var Contacts_AddPeopleNearby: String { return self._s[2387]! } + public var OwnershipTransfer_SetupTwoStepAuth: String { return self._s[2388]! } + public var ClearCache_Description: String { return self._s[2389]! } + public var Localization_LanguageName: String { return self._s[2390]! } public func UserInfo_UnblockConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2390]!, self._r[2390]!, [_0]) + return formatWithArgumentRanges(self._s[2391]!, self._r[2391]!, [_0]) } - public var ChatList_TabIconFoldersTooltipEmptyFolders: String { return self._s[2391]! } - public var UserInfo_CreateNewContact: String { return self._s[2392]! } - public var Channel_Stickers_NotFound: String { return self._s[2393]! } - public var Watch_Message_Poll: String { return self._s[2394]! } - public var Privacy_Forwards_WhoCanForward: String { return self._s[2395]! } + public var ChatList_TabIconFoldersTooltipEmptyFolders: String { return self._s[2392]! } + public var UserInfo_CreateNewContact: String { return self._s[2393]! } + public var Channel_Stickers_NotFound: String { return self._s[2394]! } + public var Watch_Message_Poll: String { return self._s[2395]! } + public var Privacy_Forwards_WhoCanForward: String { return self._s[2396]! } public func Notification_Kicked(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2396]!, self._r[2396]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2397]!, self._r[2397]!, [_0, _1]) } - public var Login_InfoDeletePhoto: String { return self._s[2397]! } - public var Appearance_ThemePreview_ChatList_6_Name: String { return self._s[2398]! } - public var InstantPage_FeedbackButton: String { return self._s[2399]! } - public var Appearance_PreviewReplyText: String { return self._s[2400]! } - public var Passport_FieldPhoneHelp: String { return self._s[2401]! } - public var Group_ErrorAddTooMuchBots: String { return self._s[2402]! } - public var Media_SendingOptionsTooltip: String { return self._s[2403]! } - public var ScheduledMessages_ScheduledOnline: String { return self._s[2404]! } - public var Notifications_Badge: String { return self._s[2405]! } - public var VoiceOver_Chat_VideoMessage: String { return self._s[2406]! } - public var TwoStepAuth_RecoveryCodeExpired: String { return self._s[2407]! } - public var Wallet_Configuration_ApplyErrorTitle: String { return self._s[2408]! } + public var Login_InfoDeletePhoto: String { return self._s[2398]! } + public var Appearance_ThemePreview_ChatList_6_Name: String { return self._s[2399]! } + public var InstantPage_FeedbackButton: String { return self._s[2400]! } + public var Appearance_PreviewReplyText: String { return self._s[2401]! } + public var Passport_FieldPhoneHelp: String { return self._s[2402]! } + public var Group_ErrorAddTooMuchBots: String { return self._s[2403]! } + public var Media_SendingOptionsTooltip: String { return self._s[2404]! } + public var ScheduledMessages_ScheduledOnline: String { return self._s[2405]! } + public var Notifications_Badge: String { return self._s[2406]! } + public var VoiceOver_Chat_VideoMessage: String { return self._s[2407]! } + public var TwoStepAuth_RecoveryCodeExpired: String { return self._s[2408]! } + public var Wallet_Configuration_ApplyErrorTitle: String { return self._s[2409]! } public func Notification_PinnedPhotoMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2410]!, self._r[2410]!, [_0]) + return formatWithArgumentRanges(self._s[2411]!, self._r[2411]!, [_0]) } - public var Wallet_Info_Send: String { return self._s[2411]! } - public var Passport_InfoLearnMore: String { return self._s[2412]! } - public var EnterPasscode_EnterTitle: String { return self._s[2413]! } - public var Appearance_EditTheme: String { return self._s[2414]! } - public var EditTheme_Expand_BottomInfo: String { return self._s[2415]! } - public var Stats_FollowersTitle: String { return self._s[2416]! } - public var Passport_Identity_SurnamePlaceholder: String { return self._s[2417]! } - public var Channel_Subscribers_Title: String { return self._s[2418]! } - public var Group_ErrorSupergroupConversionNotPossible: String { return self._s[2419]! } + public var Wallet_Info_Send: String { return self._s[2412]! } + public var Passport_InfoLearnMore: String { return self._s[2413]! } + public var EnterPasscode_EnterTitle: String { return self._s[2414]! } + public var Appearance_EditTheme: String { return self._s[2415]! } + public var EditTheme_Expand_BottomInfo: String { return self._s[2416]! } + public var Stats_FollowersTitle: String { return self._s[2417]! } + public var Passport_Identity_SurnamePlaceholder: String { return self._s[2418]! } + public var Channel_Subscribers_Title: String { return self._s[2419]! } + public var Group_ErrorSupergroupConversionNotPossible: String { return self._s[2420]! } public func Wallet_Time_PreciseDate_m5(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2420]!, self._r[2420]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2421]!, self._r[2421]!, [_1, _2, _3]) } - public var EditTheme_ThemeTemplateAlertTitle: String { return self._s[2421]! } - public var Wallet_Intro_CreateWallet: String { return self._s[2422]! } - public var Conversation_AddToReadingList: String { return self._s[2423]! } - public var EditTheme_Create_Preview_IncomingText: String { return self._s[2424]! } + public var EditTheme_ThemeTemplateAlertTitle: String { return self._s[2422]! } + public var Wallet_Intro_CreateWallet: String { return self._s[2423]! } + public var Conversation_AddToReadingList: String { return self._s[2424]! } + public var EditTheme_Create_Preview_IncomingText: String { return self._s[2425]! } public func Notifications_ExceptionsChangeSound(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2425]!, self._r[2425]!, [_0]) + return formatWithArgumentRanges(self._s[2426]!, self._r[2426]!, [_0]) } - public var Group_AdminLog_EmptyText: String { return self._s[2426]! } - public var Passport_Identity_EditInternalPassport: String { return self._s[2427]! } - public var Wallet_Sending_Title: String { return self._s[2429]! } - public var Watch_Location_Current: String { return self._s[2430]! } - public var PrivacyPolicy_Title: String { return self._s[2431]! } - public var Privacy_GroupsAndChannels_CustomHelp: String { return self._s[2438]! } - public var Channel_TypeSetup_Title: String { return self._s[2441]! } - public var Appearance_PreviewReplyAuthor: String { return self._s[2442]! } - public var Passport_Language_ja: String { return self._s[2443]! } - public var ReportPeer_ReasonSpam: String { return self._s[2444]! } - public var Widget_GalleryDescription: String { return self._s[2445]! } - public var Privacy_PaymentsClearInfoHelp: String { return self._s[2446]! } - public var Conversation_EditingMessageMediaEditCurrentPhoto: String { return self._s[2448]! } - public var Channel_AdminLog_ChangeInfo: String { return self._s[2449]! } - public var ChatListFolder_NameNonContacts: String { return self._s[2450]! } - public var Call_Audio: String { return self._s[2451]! } - public var PhotoEditor_CurvesGreen: String { return self._s[2452]! } - public var Wallet_Updated_JustNow: String { return self._s[2453]! } - public var ChatList_Search_NoResultsFitlerFiles: String { return self._s[2454]! } - public var Settings_PrivacySettings: String { return self._s[2455]! } - public var Stats_Followers: String { return self._s[2456]! } - public var Notifications_AddExceptionTitle: String { return self._s[2457]! } - public var TwoFactorSetup_Password_Title: String { return self._s[2458]! } - public var ChannelMembers_WhoCanAddMembersAllHelp: String { return self._s[2459]! } - public var OldChannels_NoticeText: String { return self._s[2460]! } - public var Conversation_SavedMessages: String { return self._s[2461]! } + public var Group_AdminLog_EmptyText: String { return self._s[2427]! } + public var Passport_Identity_EditInternalPassport: String { return self._s[2428]! } + public var Wallet_Sending_Title: String { return self._s[2430]! } + public var Watch_Location_Current: String { return self._s[2431]! } + public var PrivacyPolicy_Title: String { return self._s[2432]! } + public var Privacy_GroupsAndChannels_CustomHelp: String { return self._s[2439]! } + public var Channel_TypeSetup_Title: String { return self._s[2442]! } + public var Appearance_PreviewReplyAuthor: String { return self._s[2443]! } + public var Passport_Language_ja: String { return self._s[2444]! } + public var ReportPeer_ReasonSpam: String { return self._s[2445]! } + public var Widget_GalleryDescription: String { return self._s[2446]! } + public var Privacy_PaymentsClearInfoHelp: String { return self._s[2447]! } + public var Conversation_EditingMessageMediaEditCurrentPhoto: String { return self._s[2449]! } + public var Channel_AdminLog_ChangeInfo: String { return self._s[2450]! } + public var ChatListFolder_NameNonContacts: String { return self._s[2451]! } + public var Call_Audio: String { return self._s[2452]! } + public var PhotoEditor_CurvesGreen: String { return self._s[2453]! } + public var Wallet_Updated_JustNow: String { return self._s[2454]! } + public var ChatList_Search_NoResultsFitlerFiles: String { return self._s[2455]! } + public var Settings_PrivacySettings: String { return self._s[2456]! } + public var Stats_Followers: String { return self._s[2457]! } + public var Notifications_AddExceptionTitle: String { return self._s[2458]! } + public var TwoFactorSetup_Password_Title: String { return self._s[2459]! } + public var ChannelMembers_WhoCanAddMembersAllHelp: String { return self._s[2460]! } + public var OldChannels_NoticeText: String { return self._s[2461]! } + public var Conversation_SavedMessages: String { return self._s[2462]! } public func Conversation_PeerNearbyTitle(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2463]!, self._r[2463]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2464]!, self._r[2464]!, [_1, _2]) } - public var Passport_Address_TypeResidentialAddress: String { return self._s[2464]! } + public var Passport_Address_TypeResidentialAddress: String { return self._s[2465]! } public func Wallet_Info_TransactionBlockchainFee(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2465]!, self._r[2465]!, [_0]) + return formatWithArgumentRanges(self._s[2466]!, self._r[2466]!, [_0]) } - public var Appearance_ThemeNightBlue: String { return self._s[2466]! } - public var Notification_ChannelInviterSelf: String { return self._s[2467]! } - public var Watch_UserInfo_Service: String { return self._s[2469]! } - public var ChatList_Context_Back: String { return self._s[2470]! } - public var Passport_Email_Title: String { return self._s[2471]! } - public var Wallet_Month_ShortDecember: String { return self._s[2472]! } - public var Stats_GroupTopAdmin_Promote: String { return self._s[2473]! } + public var Appearance_ThemeNightBlue: String { return self._s[2467]! } + public var Notification_ChannelInviterSelf: String { return self._s[2468]! } + public var Watch_UserInfo_Service: String { return self._s[2470]! } + public var ChatList_Context_Back: String { return self._s[2471]! } + public var Passport_Email_Title: String { return self._s[2472]! } + public var Wallet_Month_ShortDecember: String { return self._s[2473]! } + public var Stats_GroupTopAdmin_Promote: String { return self._s[2474]! } public func PUSH_PINNED_INVOICE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2474]!, self._r[2474]!, [_1]) + return formatWithArgumentRanges(self._s[2475]!, self._r[2475]!, [_1]) } - public var Conversation_UnsupportedMedia: String { return self._s[2475]! } - public var Passport_Address_OneOfTypePassportRegistration: String { return self._s[2476]! } - public var Privacy_TopPeersHelp: String { return self._s[2478]! } - public var Privacy_Forwards_AlwaysLink: String { return self._s[2479]! } - public var Notifications_Badge_CountUnreadMessages_InfoOn: String { return self._s[2480]! } - public var Permissions_NotificationsTitle_v0: String { return self._s[2481]! } + public var Conversation_UnsupportedMedia: String { return self._s[2476]! } + public var Passport_Address_OneOfTypePassportRegistration: String { return self._s[2477]! } + public var Privacy_TopPeersHelp: String { return self._s[2479]! } + public var Privacy_Forwards_AlwaysLink: String { return self._s[2480]! } + public var Notifications_Badge_CountUnreadMessages_InfoOn: String { return self._s[2481]! } + public var Permissions_NotificationsTitle_v0: String { return self._s[2482]! } public func Location_ProximityNotification_AlreadyClose(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2482]!, self._r[2482]!, [_0]) + return formatWithArgumentRanges(self._s[2483]!, self._r[2483]!, [_0]) } - public var Notification_PassportValueProofOfAddress: String { return self._s[2483]! } - public var Map_Map: String { return self._s[2484]! } - public var WallpaperSearch_ColorBlue: String { return self._s[2485]! } - public var Privacy_Calls_CustomShareHelp: String { return self._s[2486]! } - public var PhotoEditor_BlurToolRadial: String { return self._s[2487]! } - public var ChatList_Search_FilterMusic: String { return self._s[2488]! } - public var SettingsSearch_Synonyms_Data_AutoplayGifs: String { return self._s[2489]! } - public var Privacy_PaymentsClear_ShippingInfo: String { return self._s[2490]! } - public var Settings_LogoutConfirmationTitle: String { return self._s[2492]! } + public var Notification_PassportValueProofOfAddress: String { return self._s[2484]! } + public var Map_Map: String { return self._s[2485]! } + public var WallpaperSearch_ColorBlue: String { return self._s[2486]! } + public var Privacy_Calls_CustomShareHelp: String { return self._s[2487]! } + public var PhotoEditor_BlurToolRadial: String { return self._s[2488]! } + public var ChatList_Search_FilterMusic: String { return self._s[2489]! } + public var SettingsSearch_Synonyms_Data_AutoplayGifs: String { return self._s[2490]! } + public var Privacy_PaymentsClear_ShippingInfo: String { return self._s[2491]! } + public var Settings_LogoutConfirmationTitle: String { return self._s[2493]! } public func PUSH_CHANNEL_MESSAGE_VIDEOS(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2493]!, self._r[2493]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2494]!, self._r[2494]!, [_1, _2]) } public func Notification_ChangedGroupPhoto(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2494]!, self._r[2494]!, [_0]) + return formatWithArgumentRanges(self._s[2495]!, self._r[2495]!, [_0]) } - public var Channel_Username_RevokeExistingUsernamesInfo: String { return self._s[2495]! } - public var Group_Username_CreatePublicLinkHelp: String { return self._s[2496]! } - public var GroupInfo_Location: String { return self._s[2499]! } - public var Passport_Language_ka: String { return self._s[2500]! } + public var Channel_Username_RevokeExistingUsernamesInfo: String { return self._s[2496]! } + public var Group_Username_CreatePublicLinkHelp: String { return self._s[2497]! } + public var GroupInfo_Location: String { return self._s[2500]! } + public var Passport_Language_ka: String { return self._s[2501]! } public func TwoStepAuth_SetupPendingEmail(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2501]!, self._r[2501]!, [_0]) + return formatWithArgumentRanges(self._s[2502]!, self._r[2502]!, [_0]) } - public var Conversation_ContextMenuOpenChannelProfile: String { return self._s[2502]! } - public var ScheduledMessages_ClearAllConfirmation: String { return self._s[2505]! } - public var DialogList_SearchSectionRecent: String { return self._s[2506]! } - public var Passport_Address_OneOfTypeTemporaryRegistration: String { return self._s[2507]! } - public var Conversation_Timer_Send: String { return self._s[2508]! } - public var ChatState_Updating: String { return self._s[2510]! } - public var ChannelMembers_WhoCanAddMembers: String { return self._s[2511]! } - public var ChannelInfo_DeleteGroup: String { return self._s[2512]! } - public var TwoStepAuth_RecoveryFailed: String { return self._s[2513]! } - public var Channel_OwnershipTransfer_EnterPassword: String { return self._s[2514]! } - public var ChatListFolderSettings_AddRecommended: String { return self._s[2516]! } - public var ChatList_Search_NoResults: String { return self._s[2517]! } - public var ChangePhoneNumberCode_Called: String { return self._s[2518]! } - public var PeerInfo_GroupAboutItem: String { return self._s[2519]! } - public var Wallet_Info_YourBalance: String { return self._s[2521]! } + public var Conversation_ContextMenuOpenChannelProfile: String { return self._s[2503]! } + public var ScheduledMessages_ClearAllConfirmation: String { return self._s[2506]! } + public var DialogList_SearchSectionRecent: String { return self._s[2507]! } + public var Passport_Address_OneOfTypeTemporaryRegistration: String { return self._s[2508]! } + public var Conversation_Timer_Send: String { return self._s[2509]! } + public var ChatState_Updating: String { return self._s[2511]! } + public var ChannelMembers_WhoCanAddMembers: String { return self._s[2512]! } + public var ChannelInfo_DeleteGroup: String { return self._s[2513]! } + public var TwoStepAuth_RecoveryFailed: String { return self._s[2514]! } + public var Channel_OwnershipTransfer_EnterPassword: String { return self._s[2515]! } + public var ChatListFolderSettings_AddRecommended: String { return self._s[2517]! } + public var ChatList_Search_NoResults: String { return self._s[2518]! } + public var ChangePhoneNumberCode_Called: String { return self._s[2519]! } + public var PeerInfo_GroupAboutItem: String { return self._s[2520]! } + public var Wallet_Info_YourBalance: String { return self._s[2522]! } public func LiveLocationUpdated_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2522]!, self._r[2522]!, [_0]) + return formatWithArgumentRanges(self._s[2523]!, self._r[2523]!, [_0]) } - public var PrivacySettings_AuthSessions: String { return self._s[2523]! } - public var Passport_Address_Postcode: String { return self._s[2524]! } - public var VoiceOver_Chat_YourVideoMessage: String { return self._s[2525]! } - public var Passport_Address_Street2Placeholder: String { return self._s[2526]! } - public var Group_Location_Title: String { return self._s[2527]! } - public var SettingsSearch_Synonyms_Data_AutoDownloadReset: String { return self._s[2528]! } - public var PeopleNearby_UsersEmpty: String { return self._s[2529]! } - public var SettingsSearch_Synonyms_Data_Title: String { return self._s[2531]! } + public var PrivacySettings_AuthSessions: String { return self._s[2524]! } + public var Passport_Address_Postcode: String { return self._s[2525]! } + public var VoiceOver_Chat_YourVideoMessage: String { return self._s[2526]! } + public var Passport_Address_Street2Placeholder: String { return self._s[2527]! } + public var Group_Location_Title: String { return self._s[2528]! } + public var SettingsSearch_Synonyms_Data_AutoDownloadReset: String { return self._s[2529]! } + public var PeopleNearby_UsersEmpty: String { return self._s[2530]! } + public var SettingsSearch_Synonyms_Data_Title: String { return self._s[2532]! } public func Checkout_PasswordEntry_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2533]!, self._r[2533]!, [_0]) + return formatWithArgumentRanges(self._s[2534]!, self._r[2534]!, [_0]) } - public var Proxy_TooltipUnavailable: String { return self._s[2534]! } - public var Map_Search: String { return self._s[2535]! } - public var AutoDownloadSettings_TypeContacts: String { return self._s[2536]! } - public var Conversation_SearchByName_Prefix: String { return self._s[2537]! } + public var Proxy_TooltipUnavailable: String { return self._s[2535]! } + public var Map_Search: String { return self._s[2536]! } + public var AutoDownloadSettings_TypeContacts: String { return self._s[2537]! } + public var Conversation_SearchByName_Prefix: String { return self._s[2538]! } public func Channel_AdminLog_MessageToggleSignaturesOff(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2538]!, self._r[2538]!, [_0]) + return formatWithArgumentRanges(self._s[2539]!, self._r[2539]!, [_0]) } - public var TwoStepAuth_EmailAddSuccess: String { return self._s[2539]! } - public var ProfilePhoto_MainPhoto: String { return self._s[2540]! } - public var SettingsSearch_Synonyms_Notifications_InAppNotificationsSound: String { return self._s[2541]! } - public var SharedMedia_EmptyMusicText: String { return self._s[2542]! } - public var ChatSettings_AutoDownloadPhotos: String { return self._s[2543]! } - public var NetworkUsageSettings_BytesReceived: String { return self._s[2544]! } - public var Channel_AdminLog_EmptyText: String { return self._s[2545]! } - public var Channel_BanUser_PermissionSendMessages: String { return self._s[2546]! } - public var Undo_ChatDeletedForBothSides: String { return self._s[2547]! } - public var Notifications_GroupNotifications: String { return self._s[2548]! } - public var Wallet_Configuration_BlockchainNameChangedTitle: String { return self._s[2549]! } - public var Wallet_AccessDenied_Title: String { return self._s[2550]! } - public var AccessDenied_SaveMedia: String { return self._s[2551]! } - public var GroupInfo_LabelOwner: String { return self._s[2552]! } - public var Passport_Language_id: String { return self._s[2553]! } - public var ChatSettings_AutoDownloadTitle: String { return self._s[2554]! } - public var Conversation_UnpinMessageAlert: String { return self._s[2555]! } + public var TwoStepAuth_EmailAddSuccess: String { return self._s[2540]! } + public var ProfilePhoto_MainPhoto: String { return self._s[2541]! } + public var SettingsSearch_Synonyms_Notifications_InAppNotificationsSound: String { return self._s[2542]! } + public var SharedMedia_EmptyMusicText: String { return self._s[2543]! } + public var ChatSettings_AutoDownloadPhotos: String { return self._s[2544]! } + public var NetworkUsageSettings_BytesReceived: String { return self._s[2545]! } + public var Channel_AdminLog_EmptyText: String { return self._s[2546]! } + public var Channel_BanUser_PermissionSendMessages: String { return self._s[2547]! } + public var Undo_ChatDeletedForBothSides: String { return self._s[2548]! } + public var Notifications_GroupNotifications: String { return self._s[2549]! } + public var Wallet_Configuration_BlockchainNameChangedTitle: String { return self._s[2550]! } + public var Wallet_AccessDenied_Title: String { return self._s[2551]! } + public var AccessDenied_SaveMedia: String { return self._s[2552]! } + public var GroupInfo_LabelOwner: String { return self._s[2553]! } + public var Passport_Language_id: String { return self._s[2554]! } + public var ChatSettings_AutoDownloadTitle: String { return self._s[2555]! } + public var Conversation_UnpinMessageAlert: String { return self._s[2556]! } public func LiveLocationUpdated_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2556]!, self._r[2556]!, [_0]) - } - public func Call_RemoteVideoPaused(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2557]!, self._r[2557]!, [_0]) } - public var TwoFactorSetup_Done_Text: String { return self._s[2558]! } + public func Call_RemoteVideoPaused(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2558]!, self._r[2558]!, [_0]) + } + public var TwoFactorSetup_Done_Text: String { return self._s[2559]! } public func LastSeen_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2559]!, self._r[2559]!, [_0]) + return formatWithArgumentRanges(self._s[2560]!, self._r[2560]!, [_0]) } - public var Wallet_Words_Title: String { return self._s[2560]! } - public var NetworkUsageSettings_BytesSent: String { return self._s[2561]! } - public var OwnershipTransfer_Transfer: String { return self._s[2562]! } + public var Wallet_Words_Title: String { return self._s[2561]! } + public var NetworkUsageSettings_BytesSent: String { return self._s[2562]! } + public var OwnershipTransfer_Transfer: String { return self._s[2563]! } public func Notification_Exceptions_Sound(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2563]!, self._r[2563]!, [_0]) + return formatWithArgumentRanges(self._s[2564]!, self._r[2564]!, [_0]) } - public var Passport_Language_pt: String { return self._s[2564]! } - public var PrivacySettings_WebSessions: String { return self._s[2565]! } - public var PrivacyPolicy_DeclineDeleteNow: String { return self._s[2567]! } - public var TwoFactorSetup_Hint_Title: String { return self._s[2568]! } + public var Passport_Language_pt: String { return self._s[2565]! } + public var PrivacySettings_WebSessions: String { return self._s[2566]! } + public var PrivacyPolicy_DeclineDeleteNow: String { return self._s[2568]! } + public var TwoFactorSetup_Hint_Title: String { return self._s[2569]! } public func Notification_Joined(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2569]!, self._r[2569]!, [_0]) + return formatWithArgumentRanges(self._s[2570]!, self._r[2570]!, [_0]) } - public var Group_Username_RemoveExistingUsernamesInfo: String { return self._s[2570]! } - public var PrivacyLastSeenSettings_CustomShareSettings_Delete: String { return self._s[2571]! } - public var AutoNightTheme_Scheduled: String { return self._s[2572]! } - public var CreatePoll_ExplanationHeader: String { return self._s[2573]! } - public var Calls_TabTitle: String { return self._s[2574]! } - public var ChatList_UndoArchiveHiddenText: String { return self._s[2575]! } - public var Notification_VideoCallCanceled: String { return self._s[2576]! } - public var Login_CodeSentInternal: String { return self._s[2577]! } - public var SettingsSearch_Synonyms_Proxy_AddProxy: String { return self._s[2578]! } - public var Call_RecordingDisabledMessage: String { return self._s[2580]! } - public var AutoDownloadSettings_TypeChannels: String { return self._s[2582]! } - public var Wallet_Configuration_BlockchainNameChangedProceed: String { return self._s[2583]! } - public var Channel_Info_Stickers: String { return self._s[2584]! } - public var Passport_DeleteAddressConfirmation: String { return self._s[2585]! } + public var Group_Username_RemoveExistingUsernamesInfo: String { return self._s[2571]! } + public var PrivacyLastSeenSettings_CustomShareSettings_Delete: String { return self._s[2572]! } + public var AutoNightTheme_Scheduled: String { return self._s[2573]! } + public var CreatePoll_ExplanationHeader: String { return self._s[2574]! } + public var Calls_TabTitle: String { return self._s[2575]! } + public var ChatList_UndoArchiveHiddenText: String { return self._s[2576]! } + public var Notification_VideoCallCanceled: String { return self._s[2577]! } + public var Login_CodeSentInternal: String { return self._s[2578]! } + public var SettingsSearch_Synonyms_Proxy_AddProxy: String { return self._s[2579]! } + public var Call_RecordingDisabledMessage: String { return self._s[2581]! } + public var AutoDownloadSettings_TypeChannels: String { return self._s[2583]! } + public var Wallet_Configuration_BlockchainNameChangedProceed: String { return self._s[2584]! } + public var Channel_Info_Stickers: String { return self._s[2585]! } + public var Passport_DeleteAddressConfirmation: String { return self._s[2586]! } public func Conversation_PeerNearbyDistance(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2586]!, self._r[2586]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2587]!, self._r[2587]!, [_1, _2]) } - public var ChannelMembers_WhoCanAddMembers_Admins: String { return self._s[2587]! } + public var ChannelMembers_WhoCanAddMembers_Admins: String { return self._s[2588]! } public func Call_StatusOngoing(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2588]!, self._r[2588]!, [_0]) + return formatWithArgumentRanges(self._s[2589]!, self._r[2589]!, [_0]) } - public var Passport_DiscardMessageTitle: String { return self._s[2589]! } - public var Localization_LanguageOther: String { return self._s[2590]! } - public var Conversation_EncryptionCanceled: String { return self._s[2591]! } - public var ChatSettings_AutomaticPhotoDownload: String { return self._s[2592]! } + public var Passport_DiscardMessageTitle: String { return self._s[2590]! } + public var Localization_LanguageOther: String { return self._s[2591]! } + public var Conversation_EncryptionCanceled: String { return self._s[2592]! } + public var ChatSettings_AutomaticPhotoDownload: String { return self._s[2593]! } public func Notification_SecretChatMessageScreenshot(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2594]!, self._r[2594]!, [_0]) + return formatWithArgumentRanges(self._s[2595]!, self._r[2595]!, [_0]) } - public var Target_InviteToGroupErrorAlreadyInvited: String { return self._s[2596]! } - public var SocksProxySetup_SavedProxies: String { return self._s[2597]! } + public var Target_InviteToGroupErrorAlreadyInvited: String { return self._s[2597]! } + public var SocksProxySetup_SavedProxies: String { return self._s[2598]! } public func ApplyLanguage_ChangeLanguageAlreadyActive(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2598]!, self._r[2598]!, [_1]) + return formatWithArgumentRanges(self._s[2599]!, self._r[2599]!, [_1]) } - public var Conversation_ScamWarning: String { return self._s[2599]! } - public var Channel_AdminLog_InfoPanelAlertTitle: String { return self._s[2600]! } - public var LocalGroup_Title: String { return self._s[2601]! } - public var SettingsSearch_Synonyms_Notifications_MessageNotificationsAlert: String { return self._s[2602]! } - public var SettingsSearch_Synonyms_Privacy_PasscodeAndFaceId: String { return self._s[2603]! } - public var Login_PhoneFloodError: String { return self._s[2604]! } - public var Username_InvalidTaken: String { return self._s[2606]! } - public var SocksProxySetup_AddProxy: String { return self._s[2608]! } - public var PrivacyLastSeenSettings_WhoCanSeeMyTimestamp: String { return self._s[2609]! } - public var MediaPicker_UngroupDescription: String { return self._s[2610]! } - public var Login_CodeExpired: String { return self._s[2611]! } - public var Localization_ChooseLanguage: String { return self._s[2612]! } - public var Checkout_NewCard_PostcodePlaceholder: String { return self._s[2613]! } + public var Conversation_ScamWarning: String { return self._s[2600]! } + public var Channel_AdminLog_InfoPanelAlertTitle: String { return self._s[2601]! } + public var LocalGroup_Title: String { return self._s[2602]! } + public var SettingsSearch_Synonyms_Notifications_MessageNotificationsAlert: String { return self._s[2603]! } + public var SettingsSearch_Synonyms_Privacy_PasscodeAndFaceId: String { return self._s[2604]! } + public var Login_PhoneFloodError: String { return self._s[2605]! } + public var Username_InvalidTaken: String { return self._s[2607]! } + public var SocksProxySetup_AddProxy: String { return self._s[2609]! } + public var PrivacyLastSeenSettings_WhoCanSeeMyTimestamp: String { return self._s[2610]! } + public var MediaPicker_UngroupDescription: String { return self._s[2611]! } + public var Login_CodeExpired: String { return self._s[2612]! } + public var Localization_ChooseLanguage: String { return self._s[2613]! } + public var Checkout_NewCard_PostcodePlaceholder: String { return self._s[2614]! } public func ChangePhone_ErrorOccupied(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2614]!, self._r[2614]!, [_0]) - } - public func Channel_DiscussionGroup_HeaderSet(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2615]!, self._r[2615]!, [_0]) } - public var ReportPeer_ReasonOther_Title: String { return self._s[2617]! } - public var Conversation_ScheduleMessage_Title: String { return self._s[2618]! } - public var PeerInfo_ButtonDiscuss: String { return self._s[2619]! } - public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedPublicGroups: String { return self._s[2620]! } - public var Call_StatusNoAnswer: String { return self._s[2621]! } - public var ScheduledMessages_DeleteMany: String { return self._s[2623]! } - public var Channel_DiscussionGroupInfo: String { return self._s[2624]! } - public var Conversation_UnarchiveDone: String { return self._s[2625]! } - public var LogoutOptions_AddAccountText: String { return self._s[2626]! } - public var Message_PinnedContactMessage: String { return self._s[2627]! } + public func Channel_DiscussionGroup_HeaderSet(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2616]!, self._r[2616]!, [_0]) + } + public var ReportPeer_ReasonOther_Title: String { return self._s[2618]! } + public var Conversation_ScheduleMessage_Title: String { return self._s[2619]! } + public var PeerInfo_ButtonDiscuss: String { return self._s[2620]! } + public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedPublicGroups: String { return self._s[2621]! } + public var Call_StatusNoAnswer: String { return self._s[2622]! } + public var ScheduledMessages_DeleteMany: String { return self._s[2624]! } + public var Channel_DiscussionGroupInfo: String { return self._s[2625]! } + public var Conversation_UnarchiveDone: String { return self._s[2626]! } + public var LogoutOptions_AddAccountText: String { return self._s[2627]! } + public var Message_PinnedContactMessage: String { return self._s[2628]! } public func FileSize_GB(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2629]!, self._r[2629]!, [_0]) + return formatWithArgumentRanges(self._s[2630]!, self._r[2630]!, [_0]) } - public var Stats_GroupLanguagesTitle: String { return self._s[2630]! } - public var Passport_FieldAddressHelp: String { return self._s[2631]! } + public var Stats_GroupLanguagesTitle: String { return self._s[2631]! } + public var Passport_FieldAddressHelp: String { return self._s[2632]! } public func Passport_FieldOneOf_Or(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2632]!, self._r[2632]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2633]!, self._r[2633]!, [_1, _2]) } - public var ChatSettings_OpenLinksIn: String { return self._s[2634]! } - public var TwoFactorSetup_Hint_SkipAction: String { return self._s[2635]! } - public var Message_Photo: String { return self._s[2636]! } - public var MediaPicker_AddCaption: String { return self._s[2638]! } - public var LogoutOptions_Title: String { return self._s[2639]! } + public var ChatSettings_OpenLinksIn: String { return self._s[2635]! } + public var TwoFactorSetup_Hint_SkipAction: String { return self._s[2636]! } + public var Message_Photo: String { return self._s[2637]! } + public var MediaPicker_AddCaption: String { return self._s[2639]! } + public var LogoutOptions_Title: String { return self._s[2640]! } public func PUSH_PINNED_GIF(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2640]!, self._r[2640]!, [_1]) + return formatWithArgumentRanges(self._s[2641]!, self._r[2641]!, [_1]) } - public var Conversation_StatusKickedFromGroup: String { return self._s[2641]! } - public var Channel_AdminLogFilter_AdminsTitle: String { return self._s[2642]! } - public var ChatList_DeleteSavedMessagesConfirmationTitle: String { return self._s[2643]! } - public var Channel_AdminLogFilter_Title: String { return self._s[2644]! } - public var Passport_Address_TypeRentalAgreementUploadScan: String { return self._s[2645]! } + public var Conversation_StatusKickedFromGroup: String { return self._s[2642]! } + public var Channel_AdminLogFilter_AdminsTitle: String { return self._s[2643]! } + public var ChatList_DeleteSavedMessagesConfirmationTitle: String { return self._s[2644]! } + public var Channel_AdminLogFilter_Title: String { return self._s[2645]! } + public var Passport_Address_TypeRentalAgreementUploadScan: String { return self._s[2646]! } public func Wallet_Info_TransactionDateHeader(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2646]!, self._r[2646]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2647]!, self._r[2647]!, [_1, _2]) } - public var Compose_GroupTokenListPlaceholder: String { return self._s[2647]! } - public var Wallet_Words_NotDoneResponse: String { return self._s[2648]! } - public var Notifications_MessageNotificationsExceptions: String { return self._s[2649]! } - public var ChannelIntro_Title: String { return self._s[2650]! } - public var Stats_Message_Views: String { return self._s[2651]! } - public var Stickers_Install: String { return self._s[2652]! } + public var Compose_GroupTokenListPlaceholder: String { return self._s[2648]! } + public var Wallet_Words_NotDoneResponse: String { return self._s[2649]! } + public var Notifications_MessageNotificationsExceptions: String { return self._s[2650]! } + public var ChannelIntro_Title: String { return self._s[2651]! } + public var Stats_Message_Views: String { return self._s[2652]! } + public var Stickers_Install: String { return self._s[2653]! } public func VoiceOver_Chat_FileFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2653]!, self._r[2653]!, [_0]) + return formatWithArgumentRanges(self._s[2654]!, self._r[2654]!, [_0]) } - public var EditTheme_Create_Preview_IncomingReplyText: String { return self._s[2654]! } - public var Conversation_SwipeToReplyHintTitle: String { return self._s[2656]! } - public var Settings_Username: String { return self._s[2659]! } - public var FastTwoStepSetup_Title: String { return self._s[2660]! } - public var Notifications_Badge_CountUnreadMessages_InfoOff: String { return self._s[2661]! } - public var SettingsSearch_Synonyms_Privacy_Title: String { return self._s[2662]! } - public var Passport_Identity_IssueDatePlaceholder: String { return self._s[2663]! } - public var CallFeedback_ReasonEcho: String { return self._s[2664]! } + public var EditTheme_Create_Preview_IncomingReplyText: String { return self._s[2655]! } + public var Conversation_SwipeToReplyHintTitle: String { return self._s[2657]! } + public var Settings_Username: String { return self._s[2660]! } + public var FastTwoStepSetup_Title: String { return self._s[2661]! } + public var Notifications_Badge_CountUnreadMessages_InfoOff: String { return self._s[2662]! } + public var SettingsSearch_Synonyms_Privacy_Title: String { return self._s[2663]! } + public var Passport_Identity_IssueDatePlaceholder: String { return self._s[2664]! } + public var CallFeedback_ReasonEcho: String { return self._s[2665]! } public func Time_MonthOfYear_m1(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2665]!, self._r[2665]!, [_0]) + return formatWithArgumentRanges(self._s[2666]!, self._r[2666]!, [_0]) } - public var Conversation_OpenBotLinkTitle: String { return self._s[2666]! } - public var SocksProxySetup_Title: String { return self._s[2667]! } - public var CallFeedback_Success: String { return self._s[2668]! } - public var WallpaperPreview_SwipeTopText: String { return self._s[2670]! } - public var InstantPage_AutoNightTheme: String { return self._s[2672]! } - public var Watch_Conversation_Reply: String { return self._s[2673]! } - public var Chat_PanelUnpinAllMessages: String { return self._s[2675]! } - public var WallpaperPreview_Pattern: String { return self._s[2676]! } - public var CheckoutInfo_ReceiverInfoEmail: String { return self._s[2677]! } - public var Wallet_Send_ErrorNotEnoughFundsTitle: String { return self._s[2678]! } + public var Conversation_OpenBotLinkTitle: String { return self._s[2667]! } + public var SocksProxySetup_Title: String { return self._s[2668]! } + public var CallFeedback_Success: String { return self._s[2669]! } + public var WallpaperPreview_SwipeTopText: String { return self._s[2671]! } + public var InstantPage_AutoNightTheme: String { return self._s[2673]! } + public var Watch_Conversation_Reply: String { return self._s[2674]! } + public var Chat_PanelUnpinAllMessages: String { return self._s[2676]! } + public var WallpaperPreview_Pattern: String { return self._s[2677]! } + public var CheckoutInfo_ReceiverInfoEmail: String { return self._s[2678]! } + public var Wallet_Send_ErrorNotEnoughFundsTitle: String { return self._s[2679]! } public func Conversation_DeleteMessagesFor(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2679]!, self._r[2679]!, [_0]) + return formatWithArgumentRanges(self._s[2680]!, self._r[2680]!, [_0]) } - public var AutoDownloadSettings_TypeGroupChats: String { return self._s[2680]! } - public var DialogList_SavedMessagesTooltip: String { return self._s[2682]! } - public var Update_Title: String { return self._s[2683]! } - public var Conversation_ShareMyPhoneNumber: String { return self._s[2684]! } + public var AutoDownloadSettings_TypeGroupChats: String { return self._s[2681]! } + public var DialogList_SavedMessagesTooltip: String { return self._s[2683]! } + public var Update_Title: String { return self._s[2684]! } + public var Conversation_ShareMyPhoneNumber: String { return self._s[2685]! } public func Wallet_WordCheck_Text(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2685]!, self._r[2685]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2686]!, self._r[2686]!, [_1, _2, _3]) } - public var Wallet_SecureStorageReset_BiometryTouchId: String { return self._s[2686]! } - public var WallpaperPreview_CropTopText: String { return self._s[2688]! } - public var Channel_EditMessageErrorGeneric: String { return self._s[2689]! } - public var AccessDenied_LocationAlwaysDenied: String { return self._s[2690]! } - public var ChatListFolder_DiscardCancel: String { return self._s[2691]! } - public var Message_PinnedPhotoMessage: String { return self._s[2692]! } - public var Appearance_ThemeDayClassic: String { return self._s[2693]! } - public var SocksProxySetup_ProxySocks5: String { return self._s[2694]! } - public var AccessDenied_Wallpapers: String { return self._s[2700]! } + public var Wallet_SecureStorageReset_BiometryTouchId: String { return self._s[2687]! } + public var WallpaperPreview_CropTopText: String { return self._s[2689]! } + public var Channel_EditMessageErrorGeneric: String { return self._s[2690]! } + public var AccessDenied_LocationAlwaysDenied: String { return self._s[2691]! } + public var ChatListFolder_DiscardCancel: String { return self._s[2692]! } + public var Message_PinnedPhotoMessage: String { return self._s[2693]! } + public var Appearance_ThemeDayClassic: String { return self._s[2694]! } + public var SocksProxySetup_ProxySocks5: String { return self._s[2695]! } + public var AccessDenied_Wallpapers: String { return self._s[2701]! } public func Channel_AdminLog_MessageChangedGroupAbout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2701]!, self._r[2701]!, [_0]) + return formatWithArgumentRanges(self._s[2702]!, self._r[2702]!, [_0]) } - public var Weekday_Sunday: String { return self._s[2702]! } - public var SettingsSearch_Synonyms_Privacy_GroupsAndChannels: String { return self._s[2704]! } - public var PeopleNearby_MakeVisibleDescription: String { return self._s[2705]! } - public var AccessDenied_LocationDisabled: String { return self._s[2706]! } - public var Tour_Text3: String { return self._s[2707]! } - public var AuthSessions_AddDevice_ScanTitle: String { return self._s[2708]! } + public var Weekday_Sunday: String { return self._s[2703]! } + public var SettingsSearch_Synonyms_Privacy_GroupsAndChannels: String { return self._s[2705]! } + public var PeopleNearby_MakeVisibleDescription: String { return self._s[2706]! } + public var AccessDenied_LocationDisabled: String { return self._s[2707]! } + public var Tour_Text3: String { return self._s[2708]! } + public var AuthSessions_AddDevice_ScanTitle: String { return self._s[2709]! } public func Time_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2709]!, self._r[2709]!, [_0]) + return formatWithArgumentRanges(self._s[2710]!, self._r[2710]!, [_0]) } - public var Privacy_SecretChatsLinkPreviewsHelp: String { return self._s[2710]! } - public var Conversation_ClearCache: String { return self._s[2711]! } - public var StickerPacksSettings_ArchivedMasks_Info: String { return self._s[2712]! } - public var ChatList_Tabs_AllChats: String { return self._s[2713]! } - public var DialogList_RecentTitlePeople: String { return self._s[2714]! } - public var Stickers_AddToFavorites: String { return self._s[2715]! } - public var ChatList_Context_RemoveFromFolder: String { return self._s[2716]! } - public var Settings_RemoveVideo: String { return self._s[2717]! } - public var PhotoEditor_CropAspectRatioSquare: String { return self._s[2718]! } - public var ConversationProfile_LeaveDeleteAndExit: String { return self._s[2719]! } - public var VoiceOver_Chat_YourFile: String { return self._s[2720]! } - public var SettingsSearch_Synonyms_Privacy_Forwards: String { return self._s[2721]! } - public var Group_OwnershipTransfer_ErrorPrivacyRestricted: String { return self._s[2722]! } - public var Channel_AdminLog_AddMembers: String { return self._s[2723]! } - public var Map_SendThisLocation: String { return self._s[2725]! } - public var TwoStepAuth_EmailSkipAlert: String { return self._s[2727]! } - public var IntentsSettings_SuggestedChatsPrivateChats: String { return self._s[2728]! } - public var CloudStorage_Title: String { return self._s[2729]! } - public var TwoFactorSetup_Password_Action: String { return self._s[2730]! } - public var TwoStepAuth_ConfirmationText: String { return self._s[2731]! } - public var Passport_Address_EditTemporaryRegistration: String { return self._s[2733]! } - public var Undo_LeftGroup: String { return self._s[2734]! } - public var Conversation_StopLiveLocation: String { return self._s[2736]! } - public var NotificationSettings_ShowNotificationsFromAccountsSection: String { return self._s[2737]! } - public var Message_PinnedInvoice: String { return self._s[2738]! } - public var ApplyLanguage_LanguageNotSupportedError: String { return self._s[2739]! } + public var Privacy_SecretChatsLinkPreviewsHelp: String { return self._s[2711]! } + public var Conversation_ClearCache: String { return self._s[2712]! } + public var StickerPacksSettings_ArchivedMasks_Info: String { return self._s[2713]! } + public var ChatList_Tabs_AllChats: String { return self._s[2714]! } + public var DialogList_RecentTitlePeople: String { return self._s[2715]! } + public var Stickers_AddToFavorites: String { return self._s[2716]! } + public var ChatList_Context_RemoveFromFolder: String { return self._s[2717]! } + public var Settings_RemoveVideo: String { return self._s[2718]! } + public var PhotoEditor_CropAspectRatioSquare: String { return self._s[2719]! } + public var ConversationProfile_LeaveDeleteAndExit: String { return self._s[2720]! } + public var VoiceOver_Chat_YourFile: String { return self._s[2721]! } + public var SettingsSearch_Synonyms_Privacy_Forwards: String { return self._s[2722]! } + public var Group_OwnershipTransfer_ErrorPrivacyRestricted: String { return self._s[2723]! } + public var Channel_AdminLog_AddMembers: String { return self._s[2724]! } + public var Map_SendThisLocation: String { return self._s[2726]! } + public var TwoStepAuth_EmailSkipAlert: String { return self._s[2728]! } + public var IntentsSettings_SuggestedChatsPrivateChats: String { return self._s[2729]! } + public var CloudStorage_Title: String { return self._s[2730]! } + public var TwoFactorSetup_Password_Action: String { return self._s[2731]! } + public var TwoStepAuth_ConfirmationText: String { return self._s[2732]! } + public var Passport_Address_EditTemporaryRegistration: String { return self._s[2734]! } + public var Undo_LeftGroup: String { return self._s[2735]! } + public var Conversation_StopLiveLocation: String { return self._s[2737]! } + public var NotificationSettings_ShowNotificationsFromAccountsSection: String { return self._s[2738]! } + public var Message_PinnedInvoice: String { return self._s[2739]! } + public var ApplyLanguage_LanguageNotSupportedError: String { return self._s[2740]! } public func PUSH_CHAT_MESSAGE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2740]!, self._r[2740]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2741]!, self._r[2741]!, [_1, _2]) } public func Notification_PinnedAudioMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2741]!, self._r[2741]!, [_0]) + return formatWithArgumentRanges(self._s[2742]!, self._r[2742]!, [_0]) } - public var Weekday_Tuesday: String { return self._s[2742]! } - public var ChangePhoneNumberCode_Code: String { return self._s[2743]! } - public var VoiceOver_Chat_YourMessage: String { return self._s[2744]! } - public var Calls_CallTabDescription: String { return self._s[2745]! } - public var SocksProxySetup_UseProxy: String { return self._s[2747]! } - public var SettingsSearch_Synonyms_Stickers_Title: String { return self._s[2748]! } - public var PasscodeSettings_AlphanumericCode: String { return self._s[2749]! } - public var VoiceOver_Chat_YourVideo: String { return self._s[2750]! } - public var ChannelMembers_WhoCanAddMembersAdminsHelp: String { return self._s[2752]! } - public var SettingsSearch_Synonyms_Privacy_DeleteAccountIfAwayFor: String { return self._s[2753]! } - public var Exceptions_AddToExceptions: String { return self._s[2754]! } - public var UserInfo_Title: String { return self._s[2755]! } - public var Passport_DeleteDocumentConfirmation: String { return self._s[2757]! } - public var ChatList_Unmute: String { return self._s[2759]! } - public var SettingsSearch_Synonyms_Privacy_Data_ContactsSync: String { return self._s[2760]! } - public var Stats_GroupTopPostersTitle: String { return self._s[2761]! } - public var Username_CheckingUsername: String { return self._s[2762]! } - public var WallpaperColors_SetCustomColor: String { return self._s[2763]! } - public var AuthSessions_AddedDeviceTerminate: String { return self._s[2767]! } - public var Location_ProximityAlertSetTitle: String { return self._s[2768]! } - public var Privacy_ProfilePhoto_CustomHelp: String { return self._s[2769]! } - public var Settings_ChangePhoneNumber: String { return self._s[2770]! } - public var PeerInfo_PaneLinks: String { return self._s[2771]! } - public var Appearance_ThemePreview_ChatList_1_Text: String { return self._s[2774]! } - public var Channel_EditAdmin_PermissionInviteSubscribers: String { return self._s[2776]! } - public var LogoutOptions_ChangePhoneNumberText: String { return self._s[2777]! } - public var VoiceOver_Media_PlaybackPause: String { return self._s[2778]! } - public var Wallet_RestoreFailed_Title: String { return self._s[2779]! } - public var Stats_FollowersBySourceTitle: String { return self._s[2781]! } + public var Weekday_Tuesday: String { return self._s[2743]! } + public var ChangePhoneNumberCode_Code: String { return self._s[2744]! } + public var VoiceOver_Chat_YourMessage: String { return self._s[2745]! } + public var Calls_CallTabDescription: String { return self._s[2746]! } + public var SocksProxySetup_UseProxy: String { return self._s[2748]! } + public var SettingsSearch_Synonyms_Stickers_Title: String { return self._s[2749]! } + public var PasscodeSettings_AlphanumericCode: String { return self._s[2750]! } + public var VoiceOver_Chat_YourVideo: String { return self._s[2751]! } + public var ChannelMembers_WhoCanAddMembersAdminsHelp: String { return self._s[2753]! } + public var SettingsSearch_Synonyms_Privacy_DeleteAccountIfAwayFor: String { return self._s[2754]! } + public var Exceptions_AddToExceptions: String { return self._s[2755]! } + public var UserInfo_Title: String { return self._s[2756]! } + public var Passport_DeleteDocumentConfirmation: String { return self._s[2758]! } + public var ChatList_Unmute: String { return self._s[2760]! } + public var SettingsSearch_Synonyms_Privacy_Data_ContactsSync: String { return self._s[2761]! } + public var Stats_GroupTopPostersTitle: String { return self._s[2762]! } + public var Username_CheckingUsername: String { return self._s[2763]! } + public var WallpaperColors_SetCustomColor: String { return self._s[2764]! } + public var AuthSessions_AddedDeviceTerminate: String { return self._s[2768]! } + public var Location_ProximityAlertSetTitle: String { return self._s[2769]! } + public var Privacy_ProfilePhoto_CustomHelp: String { return self._s[2770]! } + public var Settings_ChangePhoneNumber: String { return self._s[2771]! } + public var PeerInfo_PaneLinks: String { return self._s[2772]! } + public var Appearance_ThemePreview_ChatList_1_Text: String { return self._s[2775]! } + public var Channel_EditAdmin_PermissionInviteSubscribers: String { return self._s[2777]! } + public var LogoutOptions_ChangePhoneNumberText: String { return self._s[2778]! } + public var VoiceOver_Media_PlaybackPause: String { return self._s[2779]! } + public var Wallet_RestoreFailed_Title: String { return self._s[2780]! } + public var Stats_FollowersBySourceTitle: String { return self._s[2782]! } public func Conversation_ScheduleMessage_SendOn(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2782]!, self._r[2782]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2783]!, self._r[2783]!, [_0, _1]) } - public var Compose_NewEncryptedChatTitle: String { return self._s[2783]! } - public var Channel_CommentsGroup_Header: String { return self._s[2785]! } + public var Compose_NewEncryptedChatTitle: String { return self._s[2784]! } + public var Channel_CommentsGroup_Header: String { return self._s[2786]! } public func ShareFileTip_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2789]!, self._r[2789]!, [_0]) + return formatWithArgumentRanges(self._s[2790]!, self._r[2790]!, [_0]) } public func PUSH_MESSAGE_AUDIO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2790]!, self._r[2790]!, [_1]) + return formatWithArgumentRanges(self._s[2791]!, self._r[2791]!, [_1]) } - public var Group_Setup_BasicHistoryHiddenHelp: String { return self._s[2792]! } + public var Group_Setup_BasicHistoryHiddenHelp: String { return self._s[2793]! } public func TwoStepAuth_RecoveryEmailUnavailable(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2793]!, self._r[2793]!, [_0]) + return formatWithArgumentRanges(self._s[2794]!, self._r[2794]!, [_0]) } - public var Conversation_OpenBotLinkOpen: String { return self._s[2794]! } - public var VoiceOver_Chat_RecordModeVoiceMessage: String { return self._s[2795]! } - public var PrivacySettings_LastSeen: String { return self._s[2797]! } - public var SettingsSearch_Synonyms_Privacy_Passcode: String { return self._s[2798]! } - public var Theme_Colors_Proceed: String { return self._s[2799]! } - public var UserInfo_ScamBotWarning: String { return self._s[2800]! } - public var LogoutOptions_LogOut: String { return self._s[2802]! } - public var Conversation_SendMessage: String { return self._s[2803]! } - public var Passport_Address_Region: String { return self._s[2805]! } - public var MediaPicker_CameraRoll: String { return self._s[2807]! } + public var Conversation_OpenBotLinkOpen: String { return self._s[2795]! } + public var VoiceOver_Chat_RecordModeVoiceMessage: String { return self._s[2796]! } + public var PrivacySettings_LastSeen: String { return self._s[2798]! } + public var SettingsSearch_Synonyms_Privacy_Passcode: String { return self._s[2799]! } + public var Theme_Colors_Proceed: String { return self._s[2800]! } + public var UserInfo_ScamBotWarning: String { return self._s[2801]! } + public var LogoutOptions_LogOut: String { return self._s[2803]! } + public var Conversation_SendMessage: String { return self._s[2804]! } + public var Passport_Address_Region: String { return self._s[2806]! } + public var MediaPicker_CameraRoll: String { return self._s[2808]! } public func VoiceOver_Chat_ForwardedFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2809]!, self._r[2809]!, [_0]) + return formatWithArgumentRanges(self._s[2810]!, self._r[2810]!, [_0]) } - public var Call_ReportSend: String { return self._s[2811]! } - public var Month_ShortJune: String { return self._s[2812]! } - public var AutoDownloadSettings_GroupChats: String { return self._s[2813]! } + public var Call_ReportSend: String { return self._s[2812]! } + public var Month_ShortJune: String { return self._s[2813]! } + public var AutoDownloadSettings_GroupChats: String { return self._s[2814]! } public func Channel_AdminLog_CaptionEdited(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2816]!, self._r[2816]!, [_0]) + return formatWithArgumentRanges(self._s[2817]!, self._r[2817]!, [_0]) } - public var TwoStepAuth_DisableSuccess: String { return self._s[2817]! } - public var Cache_KeepMedia: String { return self._s[2818]! } + public var TwoStepAuth_DisableSuccess: String { return self._s[2818]! } + public var Cache_KeepMedia: String { return self._s[2819]! } public func Date_ChatDateHeaderYear(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2819]!, self._r[2819]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2820]!, self._r[2820]!, [_1, _2, _3]) } - public var Wallet_Alert_OK: String { return self._s[2820]! } - public var Appearance_LargeEmoji: String { return self._s[2821]! } + public var Wallet_Alert_OK: String { return self._s[2821]! } + public var Appearance_LargeEmoji: String { return self._s[2822]! } public func Notification_NewAuthDetected(_ _1: String, _ _2: String, _ _3: String, _ _4: String, _ _5: String, _ _6: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2822]!, self._r[2822]!, [_1, _2, _3, _4, _5, _6]) + return formatWithArgumentRanges(self._s[2823]!, self._r[2823]!, [_1, _2, _3, _4, _5, _6]) } - public var Chat_AttachmentMultipleForwardDisabled: String { return self._s[2823]! } - public var Wallet_Navigation_Close: String { return self._s[2824]! } - public var Call_CameraConfirmationText: String { return self._s[2825]! } + public var Chat_AttachmentMultipleForwardDisabled: String { return self._s[2824]! } + public var Wallet_Navigation_Close: String { return self._s[2825]! } + public var Call_CameraConfirmationText: String { return self._s[2826]! } public func AuthSessions_AppUnofficial(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2827]!, self._r[2827]!, [_0]) + return formatWithArgumentRanges(self._s[2828]!, self._r[2828]!, [_0]) } - public var VoiceOver_MessageContextReport: String { return self._s[2829]! } - public var ChatListFolder_ExcludeChatsTitle: String { return self._s[2830]! } - public var NotificationsSound_Tritone: String { return self._s[2832]! } - public var Wallet_Configuration_BlockchainIdHeader: String { return self._s[2833]! } - public var Notifications_InAppNotificationsPreview: String { return self._s[2836]! } - public var Stats_GroupTopAdmin_Actions: String { return self._s[2837]! } - public var PeerInfo_AddToContacts: String { return self._s[2838]! } - public var AccessDenied_Title: String { return self._s[2839]! } - public var Tour_Title1: String { return self._s[2840]! } - public var VoiceOver_AttachMedia: String { return self._s[2841]! } + public var VoiceOver_MessageContextReport: String { return self._s[2830]! } + public var ChatListFolder_ExcludeChatsTitle: String { return self._s[2831]! } + public var NotificationsSound_Tritone: String { return self._s[2833]! } + public var Wallet_Configuration_BlockchainIdHeader: String { return self._s[2834]! } + public var Notifications_InAppNotificationsPreview: String { return self._s[2837]! } + public var Stats_GroupTopAdmin_Actions: String { return self._s[2838]! } + public var PeerInfo_AddToContacts: String { return self._s[2839]! } + public var AccessDenied_Title: String { return self._s[2840]! } + public var Tour_Title1: String { return self._s[2841]! } + public var VoiceOver_AttachMedia: String { return self._s[2842]! } public func SharedMedia_SearchNoResultsDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2843]!, self._r[2843]!, [_0]) + return formatWithArgumentRanges(self._s[2844]!, self._r[2844]!, [_0]) } - public var Chat_Gifs_SavedSectionHeader: String { return self._s[2844]! } - public var LogoutOptions_ChangePhoneNumberTitle: String { return self._s[2845]! } + public var Chat_Gifs_SavedSectionHeader: String { return self._s[2845]! } + public var LogoutOptions_ChangePhoneNumberTitle: String { return self._s[2846]! } public func Passport_Scans_ScanIndex(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2846]!, self._r[2846]!, [_0]) + return formatWithArgumentRanges(self._s[2847]!, self._r[2847]!, [_0]) } - public var Channel_AdminLog_MessagePreviousLink: String { return self._s[2847]! } - public var Wallet_Send_AddressText: String { return self._s[2848]! } - public var OldChannels_Title: String { return self._s[2849]! } - public var LoginPassword_FloodError: String { return self._s[2850]! } - public var Checkout_ErrorPaymentFailed: String { return self._s[2852]! } + public var Channel_AdminLog_MessagePreviousLink: String { return self._s[2848]! } + public var Wallet_Send_AddressText: String { return self._s[2849]! } + public var OldChannels_Title: String { return self._s[2850]! } + public var LoginPassword_FloodError: String { return self._s[2851]! } + public var Checkout_ErrorPaymentFailed: String { return self._s[2853]! } public func Time_MonthOfYear_m7(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2853]!, self._r[2853]!, [_0]) + return formatWithArgumentRanges(self._s[2854]!, self._r[2854]!, [_0]) } - public var VoiceOver_Media_PlaybackPlay: String { return self._s[2856]! } - public var Passport_CorrectErrors: String { return self._s[2858]! } + public var VoiceOver_Media_PlaybackPlay: String { return self._s[2857]! } + public var Passport_CorrectErrors: String { return self._s[2859]! } public func PUSH_CHAT_PHOTO_EDITED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2859]!, self._r[2859]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2860]!, self._r[2860]!, [_1, _2]) } - public var ChatListFolderSettings_Title: String { return self._s[2860]! } + public var ChatListFolderSettings_Title: String { return self._s[2861]! } public func AutoDownloadSettings_UpToFor(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2861]!, self._r[2861]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2862]!, self._r[2862]!, [_1, _2]) } - public var PhotoEditor_HighlightsTool: String { return self._s[2862]! } - public var Contacts_NotRegisteredSection: String { return self._s[2865]! } + public var PhotoEditor_HighlightsTool: String { return self._s[2863]! } + public var Contacts_NotRegisteredSection: String { return self._s[2866]! } public func PUSH_PINNED_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2866]!, self._r[2866]!, [_1]) + return formatWithArgumentRanges(self._s[2867]!, self._r[2867]!, [_1]) } - public var User_DeletedAccount: String { return self._s[2867]! } - public var Conversation_ViewContactDetails: String { return self._s[2868]! } - public var WebSearch_GIFs: String { return self._s[2869]! } - public var ChatList_DeleteSavedMessagesConfirmationAction: String { return self._s[2870]! } - public var Appearance_PreviewOutgoingText: String { return self._s[2871]! } - public var Calls_CallTabTitle: String { return self._s[2872]! } + public var User_DeletedAccount: String { return self._s[2868]! } + public var Conversation_ViewContactDetails: String { return self._s[2869]! } + public var WebSearch_GIFs: String { return self._s[2870]! } + public var ChatList_DeleteSavedMessagesConfirmationAction: String { return self._s[2871]! } + public var Appearance_PreviewOutgoingText: String { return self._s[2872]! } + public var Calls_CallTabTitle: String { return self._s[2873]! } public func LastSeen_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2873]!, self._r[2873]!, [_0]) + return formatWithArgumentRanges(self._s[2874]!, self._r[2874]!, [_0]) } - public var Channel_Status: String { return self._s[2874]! } - public var Conversation_SendMessageErrorGroupRestricted: String { return self._s[2876]! } - public var VoiceOver_Chat_OptionSelected: String { return self._s[2877]! } - public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsAlert: String { return self._s[2878]! } + public var Channel_Status: String { return self._s[2875]! } + public var Conversation_SendMessageErrorGroupRestricted: String { return self._s[2877]! } + public var VoiceOver_Chat_OptionSelected: String { return self._s[2878]! } + public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsAlert: String { return self._s[2879]! } public func ClearCache_Success(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2879]!, self._r[2879]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2880]!, self._r[2880]!, [_0, _1]) } - public var Passport_Identity_ExpiryDateNone: String { return self._s[2881]! } - public var Your_cards_expiration_month_is_invalid: String { return self._s[2883]! } - public var Month_ShortDecember: String { return self._s[2884]! } - public var Username_Help: String { return self._s[2885]! } - public var Login_InfoAvatarAdd: String { return self._s[2886]! } - public var Month_ShortMay: String { return self._s[2887]! } - public var DialogList_UnknownPinLimitError: String { return self._s[2888]! } - public var PasscodeSettings_AutoLock_IfAwayFor_5hours: String { return self._s[2889]! } - public var TwoStepAuth_EnabledSuccess: String { return self._s[2890]! } - public var Weekday_ShortSunday: String { return self._s[2891]! } - public var Channel_Username_InvalidTooShort: String { return self._s[2892]! } - public var AuthSessions_TerminateSession: String { return self._s[2893]! } - public var Passport_Identity_FilesTitle: String { return self._s[2894]! } + public var Passport_Identity_ExpiryDateNone: String { return self._s[2882]! } + public var Your_cards_expiration_month_is_invalid: String { return self._s[2884]! } + public var Month_ShortDecember: String { return self._s[2885]! } + public var Username_Help: String { return self._s[2886]! } + public var Login_InfoAvatarAdd: String { return self._s[2887]! } + public var Month_ShortMay: String { return self._s[2888]! } + public var DialogList_UnknownPinLimitError: String { return self._s[2889]! } + public var PasscodeSettings_AutoLock_IfAwayFor_5hours: String { return self._s[2890]! } + public var TwoStepAuth_EnabledSuccess: String { return self._s[2891]! } + public var Weekday_ShortSunday: String { return self._s[2892]! } + public var Channel_Username_InvalidTooShort: String { return self._s[2893]! } + public var AuthSessions_TerminateSession: String { return self._s[2894]! } + public var Passport_Identity_FilesTitle: String { return self._s[2895]! } public func Notification_PinnedRoundMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2895]!, self._r[2895]!, [_0]) + return formatWithArgumentRanges(self._s[2896]!, self._r[2896]!, [_0]) } - public var PeopleNearby_MakeVisible: String { return self._s[2897]! } + public var PeopleNearby_MakeVisible: String { return self._s[2898]! } public func Conversation_RestrictedMediaTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2898]!, self._r[2898]!, [_0]) + return formatWithArgumentRanges(self._s[2899]!, self._r[2899]!, [_0]) } public func Notification_MessageLifetimeChanged(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2899]!, self._r[2899]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2900]!, self._r[2900]!, [_1, _2]) } public func GroupInfo_AddParticipantConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2900]!, self._r[2900]!, [_0]) + return formatWithArgumentRanges(self._s[2901]!, self._r[2901]!, [_0]) } - public var PrivacyPolicy_DeclineDeclineAndDelete: String { return self._s[2901]! } - public var Conversation_ContextMenuForward: String { return self._s[2902]! } + public var PrivacyPolicy_DeclineDeclineAndDelete: String { return self._s[2902]! } + public var Conversation_ContextMenuForward: String { return self._s[2903]! } public func PUSH_CHAT_MESSAGE_QUIZ(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2904]!, self._r[2904]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2905]!, self._r[2905]!, [_1, _2, _3]) } - public var Notification_GroupInviterSelf: String { return self._s[2905]! } - public var Privacy_Forwards_NeverLink: String { return self._s[2906]! } - public var AuthSessions_CurrentSession: String { return self._s[2907]! } - public var Passport_Address_EditPassportRegistration: String { return self._s[2908]! } - public var ChannelInfo_DeleteChannelConfirmation: String { return self._s[2909]! } - public var ChatSearch_ResultsTooltip: String { return self._s[2911]! } - public var CheckoutInfo_Pay: String { return self._s[2912]! } + public var Notification_GroupInviterSelf: String { return self._s[2906]! } + public var Privacy_Forwards_NeverLink: String { return self._s[2907]! } + public var AuthSessions_CurrentSession: String { return self._s[2908]! } + public var Passport_Address_EditPassportRegistration: String { return self._s[2909]! } + public var ChannelInfo_DeleteChannelConfirmation: String { return self._s[2910]! } + public var ChatSearch_ResultsTooltip: String { return self._s[2912]! } + public var CheckoutInfo_Pay: String { return self._s[2913]! } public func Channel_AdminLog_MessageChangedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2914]!, self._r[2914]!, [_0]) + return formatWithArgumentRanges(self._s[2915]!, self._r[2915]!, [_0]) } - public var GroupInfo_AddParticipant: String { return self._s[2915]! } - public var GroupPermission_ApplyAlertAction: String { return self._s[2916]! } - public var ChatList_UndoArchiveText1: String { return self._s[2917]! } - public var Localization_LanguageCustom: String { return self._s[2918]! } - public var SettingsSearch_Synonyms_Passport: String { return self._s[2919]! } - public var Settings_UsernameEmpty: String { return self._s[2920]! } - public var Settings_FAQ_URL: String { return self._s[2921]! } + public var GroupInfo_AddParticipant: String { return self._s[2916]! } + public var GroupPermission_ApplyAlertAction: String { return self._s[2917]! } + public var ChatList_UndoArchiveText1: String { return self._s[2918]! } + public var Localization_LanguageCustom: String { return self._s[2919]! } + public var SettingsSearch_Synonyms_Passport: String { return self._s[2920]! } + public var Settings_UsernameEmpty: String { return self._s[2921]! } + public var Settings_FAQ_URL: String { return self._s[2922]! } public func Conversation_PinMessagesFor(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2922]!, self._r[2922]!, [_0]) + return formatWithArgumentRanges(self._s[2923]!, self._r[2923]!, [_0]) } - public var Common_Select: String { return self._s[2924]! } - public var Notification_MessageLifetimeRemovedOutgoing: String { return self._s[2925]! } - public var Notification_PassportValueAddress: String { return self._s[2926]! } - public var Conversation_MessageDialogDelete: String { return self._s[2927]! } - public var Map_OpenInYandexNavigator: String { return self._s[2929]! } - public var DialogList_SearchSectionDialogs: String { return self._s[2930]! } - public var AccessDenied_Contacts: String { return self._s[2931]! } - public var SettingsSearch_Synonyms_Privacy_Data_DeleteDrafts: String { return self._s[2933]! } - public var Passport_ScanPassportHelp: String { return self._s[2934]! } - public var Chat_PinnedListPreview_HidePinnedMessages: String { return self._s[2935]! } - public var ChatListFolder_NameChannels: String { return self._s[2936]! } - public var Appearance_ThemePreview_Chat_5_Text: String { return self._s[2937]! } + public var Common_Select: String { return self._s[2925]! } + public var Notification_MessageLifetimeRemovedOutgoing: String { return self._s[2926]! } + public var Notification_PassportValueAddress: String { return self._s[2927]! } + public var Conversation_MessageDialogDelete: String { return self._s[2928]! } + public var Map_OpenInYandexNavigator: String { return self._s[2930]! } + public var DialogList_SearchSectionDialogs: String { return self._s[2931]! } + public var AccessDenied_Contacts: String { return self._s[2932]! } + public var SettingsSearch_Synonyms_Privacy_Data_DeleteDrafts: String { return self._s[2934]! } + public var Passport_ScanPassportHelp: String { return self._s[2935]! } + public var Chat_PinnedListPreview_HidePinnedMessages: String { return self._s[2936]! } + public var ChatListFolder_NameChannels: String { return self._s[2937]! } + public var Appearance_ThemePreview_Chat_5_Text: String { return self._s[2938]! } public func Channel_OwnershipTransfer_TransferCompleted(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2938]!, self._r[2938]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2939]!, self._r[2939]!, [_1, _2]) } - public var Checkout_ErrorInvoiceAlreadyPaid: String { return self._s[2939]! } - public var Conversation_GifTooltip: String { return self._s[2940]! } - public var Passport_Identity_TypeDriversLicenseUploadScan: String { return self._s[2942]! } - public var AutoDownloadSettings_OffForAll: String { return self._s[2943]! } - public var Privacy_GroupsAndChannels_InviteToChannelMultipleError: String { return self._s[2944]! } - public var AutoDownloadSettings_PreloadVideo: String { return self._s[2945]! } - public var CreatePoll_Quiz: String { return self._s[2946]! } - public var TwoFactorSetup_Email_Placeholder: String { return self._s[2947]! } - public var Watch_Message_Invoice: String { return self._s[2948]! } - public var Settings_AddAnotherAccount_Help: String { return self._s[2949]! } - public var Watch_Message_Unsupported: String { return self._s[2950]! } + public var Checkout_ErrorInvoiceAlreadyPaid: String { return self._s[2940]! } + public var Conversation_GifTooltip: String { return self._s[2941]! } + public var Passport_Identity_TypeDriversLicenseUploadScan: String { return self._s[2943]! } + public var AutoDownloadSettings_OffForAll: String { return self._s[2944]! } + public var Privacy_GroupsAndChannels_InviteToChannelMultipleError: String { return self._s[2945]! } + public var AutoDownloadSettings_PreloadVideo: String { return self._s[2946]! } + public var CreatePoll_Quiz: String { return self._s[2947]! } + public var TwoFactorSetup_Email_Placeholder: String { return self._s[2948]! } + public var Watch_Message_Invoice: String { return self._s[2949]! } + public var Settings_AddAnotherAccount_Help: String { return self._s[2950]! } + public var Watch_Message_Unsupported: String { return self._s[2951]! } public func Call_CameraOff(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2952]!, self._r[2952]!, [_0]) + return formatWithArgumentRanges(self._s[2953]!, self._r[2953]!, [_0]) } - public var AuthSessions_TerminateOtherSessions: String { return self._s[2953]! } - public var CreatePoll_AllOptionsAdded: String { return self._s[2955]! } - public var TwoStepAuth_RecoveryEmailTitle: String { return self._s[2956]! } - public var Call_IncomingVoiceCall: String { return self._s[2957]! } + public var AuthSessions_TerminateOtherSessions: String { return self._s[2954]! } + public var CreatePoll_AllOptionsAdded: String { return self._s[2956]! } + public var TwoStepAuth_RecoveryEmailTitle: String { return self._s[2957]! } + public var Call_IncomingVoiceCall: String { return self._s[2958]! } public func Channel_AdminLog_MessageTransferedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2958]!, self._r[2958]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2959]!, self._r[2959]!, [_1, _2]) } - public var PrivacySettings_DeleteAccountHelp: String { return self._s[2959]! } - public var Passport_Address_TypePassportRegistrationUploadScan: String { return self._s[2960]! } - public var Group_EditAdmin_RankOwnerPlaceholder: String { return self._s[2961]! } - public var Group_ErrorAccessDenied: String { return self._s[2962]! } - public var PasscodeSettings_HelpTop: String { return self._s[2963]! } - public var Watch_ChatList_NoConversationsTitle: String { return self._s[2964]! } - public var AddContact_SharedContactException: String { return self._s[2965]! } - public var AccessDenied_MicrophoneRestricted: String { return self._s[2966]! } - public var Privacy_TopPeers: String { return self._s[2967]! } - public var Web_OpenExternal: String { return self._s[2968]! } - public var Group_ErrorSendRestrictedStickers: String { return self._s[2969]! } - public var Channel_Management_LabelAdministrator: String { return self._s[2970]! } + public var PrivacySettings_DeleteAccountHelp: String { return self._s[2960]! } + public var Passport_Address_TypePassportRegistrationUploadScan: String { return self._s[2961]! } + public var Group_EditAdmin_RankOwnerPlaceholder: String { return self._s[2962]! } + public var Group_ErrorAccessDenied: String { return self._s[2963]! } + public var PasscodeSettings_HelpTop: String { return self._s[2964]! } + public var Watch_ChatList_NoConversationsTitle: String { return self._s[2965]! } + public var AddContact_SharedContactException: String { return self._s[2966]! } + public var AccessDenied_MicrophoneRestricted: String { return self._s[2967]! } + public var Privacy_TopPeers: String { return self._s[2968]! } + public var Web_OpenExternal: String { return self._s[2969]! } + public var Group_ErrorSendRestrictedStickers: String { return self._s[2970]! } + public var Channel_Management_LabelAdministrator: String { return self._s[2971]! } public func ChangePhoneNumberCode_CallTimer(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2971]!, self._r[2971]!, [_0]) + return formatWithArgumentRanges(self._s[2972]!, self._r[2972]!, [_0]) } - public var Permissions_Skip: String { return self._s[2972]! } - public var Notifications_GroupNotificationsExceptions: String { return self._s[2973]! } - public var PeopleNearby_Title: String { return self._s[2974]! } - public var GroupInfo_SharedMediaNone: String { return self._s[2975]! } + public var Permissions_Skip: String { return self._s[2973]! } + public var Notifications_GroupNotificationsExceptions: String { return self._s[2974]! } + public var PeopleNearby_Title: String { return self._s[2975]! } + public var GroupInfo_SharedMediaNone: String { return self._s[2976]! } public func PUSH_MESSAGE_GEOLIVE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2977]!, self._r[2977]!, [_1]) + return formatWithArgumentRanges(self._s[2978]!, self._r[2978]!, [_1]) } - public var Profile_MessageLifetime1w: String { return self._s[2978]! } + public var Profile_MessageLifetime1w: String { return self._s[2979]! } public func Time_PreciseDate_m6(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2979]!, self._r[2979]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2980]!, self._r[2980]!, [_1, _2, _3]) } - public var WebBrowser_DefaultBrowser: String { return self._s[2980]! } - public var Conversation_PinOlderMessageAlertTitle: String { return self._s[2982]! } - public var EditTheme_Edit_BottomInfo: String { return self._s[2983]! } - public var Privacy_Forwards_Preview: String { return self._s[2984]! } - public var Settings_EditAccount: String { return self._s[2985]! } + public var WebBrowser_DefaultBrowser: String { return self._s[2981]! } + public var Conversation_PinOlderMessageAlertTitle: String { return self._s[2983]! } + public var EditTheme_Edit_BottomInfo: String { return self._s[2984]! } + public var Privacy_Forwards_Preview: String { return self._s[2985]! } + public var Settings_EditAccount: String { return self._s[2986]! } public func Conversation_RestrictedInlineTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2986]!, self._r[2986]!, [_0]) + return formatWithArgumentRanges(self._s[2987]!, self._r[2987]!, [_0]) } - public var TwoFactorSetup_Intro_Title: String { return self._s[2987]! } + public var TwoFactorSetup_Intro_Title: String { return self._s[2988]! } public func Channel_AdminLog_MessagePromotedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2989]!, self._r[2989]!, [_1]) + return formatWithArgumentRanges(self._s[2990]!, self._r[2990]!, [_1]) } - public var PeerInfo_ButtonVideoCall: String { return self._s[2990]! } + public var PeerInfo_ButtonVideoCall: String { return self._s[2991]! } public func DialogList_SingleUploadingPhotoSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2991]!, self._r[2991]!, [_0]) + return formatWithArgumentRanges(self._s[2992]!, self._r[2992]!, [_0]) } - public var Login_InfoHelp: String { return self._s[2992]! } - public var Notification_SecretChatMessageScreenshotSelf: String { return self._s[2993]! } - public var Profile_MessageLifetime1d: String { return self._s[2994]! } - public var Group_UpgradeConfirmation: String { return self._s[2995]! } + public var Login_InfoHelp: String { return self._s[2993]! } + public var Notification_SecretChatMessageScreenshotSelf: String { return self._s[2994]! } + public var Profile_MessageLifetime1d: String { return self._s[2995]! } + public var Group_UpgradeConfirmation: String { return self._s[2996]! } public func PUSH_PINNED_STICKER(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2996]!, self._r[2996]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2997]!, self._r[2997]!, [_1, _2]) } - public var Appearance_RemoveThemeColor: String { return self._s[2997]! } - public var Channel_AdminLog_TitleSelectedEvents: String { return self._s[2998]! } - public var Wallet_Configuration_BlockchainIdInfo: String { return self._s[2999]! } + public var Appearance_RemoveThemeColor: String { return self._s[2998]! } + public var Channel_AdminLog_TitleSelectedEvents: String { return self._s[2999]! } + public var Wallet_Configuration_BlockchainIdInfo: String { return self._s[3000]! } public func Call_AnsweringWithAccount(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3000]!, self._r[3000]!, [_0]) + return formatWithArgumentRanges(self._s[3001]!, self._r[3001]!, [_0]) } - public var UserInfo_BotSettings: String { return self._s[3001]! } + public var UserInfo_BotSettings: String { return self._s[3002]! } public func Notification_ChannelInviter(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3003]!, self._r[3003]!, [_0]) + return formatWithArgumentRanges(self._s[3004]!, self._r[3004]!, [_0]) } - public var Permissions_ContactsText_v0: String { return self._s[3004]! } - public var Conversation_PinMessagesForMe: String { return self._s[3005]! } - public var Conversation_DiscussionStarted: String { return self._s[3007]! } - public var SettingsSearch_Synonyms_Privacy_TwoStepAuth: String { return self._s[3008]! } - public var SharedMedia_SearchNoResults: String { return self._s[3010]! } + public var Permissions_ContactsText_v0: String { return self._s[3005]! } + public var Conversation_PinMessagesForMe: String { return self._s[3006]! } + public var Conversation_DiscussionStarted: String { return self._s[3008]! } + public var SettingsSearch_Synonyms_Privacy_TwoStepAuth: String { return self._s[3009]! } + public var SharedMedia_SearchNoResults: String { return self._s[3011]! } public func Login_EmailPhoneSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3012]!, self._r[3012]!, [_0]) + return formatWithArgumentRanges(self._s[3013]!, self._r[3013]!, [_0]) } public func Conversation_ShareMyPhoneNumber_StatusSuccess(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3014]!, self._r[3014]!, [_0]) + return formatWithArgumentRanges(self._s[3015]!, self._r[3015]!, [_0]) } - public var ReportPeer_ReasonOther_Placeholder: String { return self._s[3015]! } - public var ContactInfo_PhoneLabelHomeFax: String { return self._s[3016]! } - public var Call_AudioRouteHeadphones: String { return self._s[3017]! } + public var ReportPeer_ReasonOther_Placeholder: String { return self._s[3016]! } + public var ContactInfo_PhoneLabelHomeFax: String { return self._s[3017]! } + public var Call_AudioRouteHeadphones: String { return self._s[3018]! } public func PUSH_AUTH_UNKNOWN(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3018]!, self._r[3018]!, [_1]) + return formatWithArgumentRanges(self._s[3019]!, self._r[3019]!, [_1]) } - public var Passport_Identity_FilesView: String { return self._s[3019]! } - public var TwoStepAuth_SetupEmail: String { return self._s[3020]! } - public var Widget_ApplicationStartRequired: String { return self._s[3021]! } - public var PhotoEditor_Original: String { return self._s[3022]! } - public var Call_YourMicrophoneOff: String { return self._s[3023]! } - public var Permissions_ContactsAllow_v0: String { return self._s[3024]! } - public var Notification_Exceptions_PreviewAlwaysOn: String { return self._s[3025]! } - public var PrivacyPolicy_Decline: String { return self._s[3026]! } - public var SettingsSearch_Synonyms_ChatFolders: String { return self._s[3027]! } - public var TwoStepAuth_PasswordRemoveConfirmation: String { return self._s[3028]! } - public var ChatListFolder_IncludeSectionInfo: String { return self._s[3029]! } + public var Passport_Identity_FilesView: String { return self._s[3020]! } + public var TwoStepAuth_SetupEmail: String { return self._s[3021]! } + public var Widget_ApplicationStartRequired: String { return self._s[3022]! } + public var PhotoEditor_Original: String { return self._s[3023]! } + public var Call_YourMicrophoneOff: String { return self._s[3024]! } + public var Permissions_ContactsAllow_v0: String { return self._s[3025]! } + public var Notification_Exceptions_PreviewAlwaysOn: String { return self._s[3026]! } + public var PrivacyPolicy_Decline: String { return self._s[3027]! } + public var SettingsSearch_Synonyms_ChatFolders: String { return self._s[3028]! } + public var TwoStepAuth_PasswordRemoveConfirmation: String { return self._s[3029]! } + public var ChatListFolder_IncludeSectionInfo: String { return self._s[3030]! } public func Map_DirectionsDriveEta(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3030]!, self._r[3030]!, [_0]) + return formatWithArgumentRanges(self._s[3031]!, self._r[3031]!, [_0]) } - public var Passport_Identity_Name: String { return self._s[3031]! } - public var WallpaperPreview_PatternTitle: String { return self._s[3033]! } - public var VoiceOver_Chat_RecordModeVideoMessage: String { return self._s[3034]! } - public var WallpaperSearch_ColorOrange: String { return self._s[3036]! } - public var Appearance_ThemePreview_ChatList_5_Name: String { return self._s[3037]! } - public var GroupInfo_Permissions_SlowmodeInfo: String { return self._s[3038]! } - public var Your_cards_security_code_is_invalid: String { return self._s[3039]! } - public var IntentsSettings_ResetAll: String { return self._s[3040]! } - public var SettingsSearch_Synonyms_Calls_CallTab: String { return self._s[3042]! } - public var Group_EditAdmin_TransferOwnership: String { return self._s[3043]! } - public var Notification_Exceptions_Add: String { return self._s[3044]! } - public var Cache_Help: String { return self._s[3045]! } - public var Call_AudioRouteMute: String { return self._s[3046]! } - public var VoiceOver_Chat_YourVoiceMessage: String { return self._s[3047]! } - public var SocksProxySetup_ProxyEnabled: String { return self._s[3048]! } + public var Passport_Identity_Name: String { return self._s[3032]! } + public var WallpaperPreview_PatternTitle: String { return self._s[3034]! } + public var VoiceOver_Chat_RecordModeVideoMessage: String { return self._s[3035]! } + public var WallpaperSearch_ColorOrange: String { return self._s[3037]! } + public var Appearance_ThemePreview_ChatList_5_Name: String { return self._s[3038]! } + public var GroupInfo_Permissions_SlowmodeInfo: String { return self._s[3039]! } + public var Your_cards_security_code_is_invalid: String { return self._s[3040]! } + public var IntentsSettings_ResetAll: String { return self._s[3041]! } + public var SettingsSearch_Synonyms_Calls_CallTab: String { return self._s[3043]! } + public var Group_EditAdmin_TransferOwnership: String { return self._s[3044]! } + public var Notification_Exceptions_Add: String { return self._s[3045]! } + public var Cache_Help: String { return self._s[3046]! } + public var Call_AudioRouteMute: String { return self._s[3047]! } + public var VoiceOver_Chat_YourVoiceMessage: String { return self._s[3048]! } + public var SocksProxySetup_ProxyEnabled: String { return self._s[3049]! } public func ApplyLanguage_UnsufficientDataText(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3049]!, self._r[3049]!, [_1]) + return formatWithArgumentRanges(self._s[3050]!, self._r[3050]!, [_1]) } public func Call_CallInProgressMessage(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3050]!, self._r[3050]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3051]!, self._r[3051]!, [_1, _2]) } - public var AutoDownloadSettings_VideoMessagesTitle: String { return self._s[3051]! } - public var Channel_BanUser_PermissionAddMembers: String { return self._s[3052]! } - public var Contacts_MemberSearchSectionTitleGroup: String { return self._s[3053]! } + public var AutoDownloadSettings_VideoMessagesTitle: String { return self._s[3052]! } + public var Channel_BanUser_PermissionAddMembers: String { return self._s[3053]! } + public var Contacts_MemberSearchSectionTitleGroup: String { return self._s[3054]! } public func Wallet_Time_PreciseDate_m10(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3054]!, self._r[3054]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3055]!, self._r[3055]!, [_1, _2, _3]) } - public var TwoStepAuth_RecoveryCodeHelp: String { return self._s[3055]! } - public var ClearCache_StorageFree: String { return self._s[3056]! } + public var TwoStepAuth_RecoveryCodeHelp: String { return self._s[3056]! } + public var ClearCache_StorageFree: String { return self._s[3057]! } public func DialogList_SingleRecordingVideoMessageSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3057]!, self._r[3057]!, [_0]) + return formatWithArgumentRanges(self._s[3058]!, self._r[3058]!, [_0]) } - public var Privacy_Forwards_CustomHelp: String { return self._s[3058]! } - public var Group_ErrorAddTooMuchAdmins: String { return self._s[3060]! } - public var DialogList_Typing: String { return self._s[3061]! } + public var Privacy_Forwards_CustomHelp: String { return self._s[3059]! } + public var Group_ErrorAddTooMuchAdmins: String { return self._s[3061]! } + public var DialogList_Typing: String { return self._s[3062]! } public func Login_EmailCodeSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3062]!, self._r[3062]!, [_0]) + return formatWithArgumentRanges(self._s[3063]!, self._r[3063]!, [_0]) } - public var Target_SelectGroup: String { return self._s[3063]! } - public var AuthSessions_IncompleteAttempts: String { return self._s[3064]! } + public var Target_SelectGroup: String { return self._s[3064]! } + public var AuthSessions_IncompleteAttempts: String { return self._s[3065]! } public func Notification_ProximityReached(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3065]!, self._r[3065]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3066]!, self._r[3066]!, [_1, _2, _3]) } - public var Chat_PinnedListPreview_ShowAllMessages: String { return self._s[3066]! } - public var TwoStepAuth_EmailChangeSuccess: String { return self._s[3067]! } + public var Chat_PinnedListPreview_ShowAllMessages: String { return self._s[3067]! } + public var TwoStepAuth_EmailChangeSuccess: String { return self._s[3068]! } public func Settings_CheckPhoneNumberTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3068]!, self._r[3068]!, [_0]) + return formatWithArgumentRanges(self._s[3069]!, self._r[3069]!, [_0]) } - public var Channel_AdminLog_CanSendMessages: String { return self._s[3069]! } - public var TwoFactorSetup_EmailVerification_Title: String { return self._s[3070]! } - public var ChatSettings_TextSize: String { return self._s[3071]! } - public var Channel_AdminLogFilter_EventsEditedMessages: String { return self._s[3073]! } - public var Map_SendThisPlace: String { return self._s[3074]! } - public var Login_PhoneNumberAlreadyAuthorized: String { return self._s[3075]! } - public var ContactInfo_BirthdayLabel: String { return self._s[3076]! } - public var Call_ShareStats: String { return self._s[3077]! } - public var ChatList_UndoArchiveRevealedText: String { return self._s[3079]! } - public var Notifications_GroupNotificationsPreview: String { return self._s[3080]! } - public var Settings_Support: String { return self._s[3081]! } - public var GroupInfo_ChannelListNamePlaceholder: String { return self._s[3082]! } + public var Channel_AdminLog_CanSendMessages: String { return self._s[3070]! } + public var TwoFactorSetup_EmailVerification_Title: String { return self._s[3071]! } + public var ChatSettings_TextSize: String { return self._s[3072]! } + public var Channel_AdminLogFilter_EventsEditedMessages: String { return self._s[3074]! } + public var Map_SendThisPlace: String { return self._s[3075]! } + public var Conversation_TextCopied: String { return self._s[3076]! } + public var Login_PhoneNumberAlreadyAuthorized: String { return self._s[3077]! } + public var ContactInfo_BirthdayLabel: String { return self._s[3078]! } + public var Call_ShareStats: String { return self._s[3079]! } + public var ChatList_UndoArchiveRevealedText: String { return self._s[3081]! } + public var Notifications_GroupNotificationsPreview: String { return self._s[3082]! } + public var Settings_Support: String { return self._s[3083]! } + public var GroupInfo_ChannelListNamePlaceholder: String { return self._s[3084]! } public func EmptyGroupInfo_Line1(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3084]!, self._r[3084]!, [_0]) + return formatWithArgumentRanges(self._s[3086]!, self._r[3086]!, [_0]) } - public var Watch_Conversation_GroupInfo: String { return self._s[3085]! } - public var Tour_Text4: String { return self._s[3086]! } - public var PasscodeSettings_AutoLock: String { return self._s[3088]! } - public var Channel_BanList_BlockedTitle: String { return self._s[3089]! } - public var Bot_DescriptionTitle: String { return self._s[3090]! } - public var Map_LocationTitle: String { return self._s[3091]! } - public var ChatListFolder_ExcludeSectionInfo: String { return self._s[3092]! } + public var Watch_Conversation_GroupInfo: String { return self._s[3087]! } + public var Tour_Text4: String { return self._s[3088]! } + public var PasscodeSettings_AutoLock: String { return self._s[3090]! } + public var Channel_BanList_BlockedTitle: String { return self._s[3091]! } + public var Bot_DescriptionTitle: String { return self._s[3092]! } + public var Map_LocationTitle: String { return self._s[3093]! } + public var ChatListFolder_ExcludeSectionInfo: String { return self._s[3094]! } public func Notification_MessageLifetimeChangedOutgoing(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3093]!, self._r[3093]!, [_1]) + return formatWithArgumentRanges(self._s[3095]!, self._r[3095]!, [_1]) } - public var Login_EmailNotConfiguredError: String { return self._s[3094]! } - public var AutoDownloadSettings_LimitBySize: String { return self._s[3095]! } - public var PrivacySettings_LastSeenNobody: String { return self._s[3096]! } - public var Permissions_CellularDataText_v0: String { return self._s[3097]! } - public var Conversation_EncryptionProcessing: String { return self._s[3098]! } - public var GroupPermission_Delete: String { return self._s[3099]! } - public var Contacts_SortByName: String { return self._s[3100]! } - public var TwoStepAuth_RecoveryUnavailable: String { return self._s[3101]! } - public var Compose_ChannelTokenListPlaceholder: String { return self._s[3102]! } - public var Group_Management_AddModeratorHelp: String { return self._s[3104]! } - public var SettingsSearch_Synonyms_EditProfile_Logout: String { return self._s[3105]! } - public var Forward_ErrorPublicPollDisabledInChannels: String { return self._s[3106]! } + public var Login_EmailNotConfiguredError: String { return self._s[3096]! } + public var AutoDownloadSettings_LimitBySize: String { return self._s[3097]! } + public var PrivacySettings_LastSeenNobody: String { return self._s[3098]! } + public var Permissions_CellularDataText_v0: String { return self._s[3099]! } + public var Conversation_EncryptionProcessing: String { return self._s[3100]! } + public var GroupPermission_Delete: String { return self._s[3101]! } + public var Contacts_SortByName: String { return self._s[3102]! } + public var TwoStepAuth_RecoveryUnavailable: String { return self._s[3103]! } + public var Compose_ChannelTokenListPlaceholder: String { return self._s[3104]! } + public var Group_Management_AddModeratorHelp: String { return self._s[3106]! } + public var SettingsSearch_Synonyms_EditProfile_Logout: String { return self._s[3107]! } + public var Forward_ErrorPublicPollDisabledInChannels: String { return self._s[3108]! } public func Wallet_Time_PreciseDate_m7(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3108]!, self._r[3108]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3110]!, self._r[3110]!, [_1, _2, _3]) } - public var CallFeedback_IncludeLogsInfo: String { return self._s[3109]! } + public var CallFeedback_IncludeLogsInfo: String { return self._s[3111]! } public func PUSH_CHANNEL_MESSAGE_QUIZ(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3110]!, self._r[3110]!, [_1]) + return formatWithArgumentRanges(self._s[3112]!, self._r[3112]!, [_1]) } public func SecretVideo_NotViewedYet(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3111]!, self._r[3111]!, [_0]) + return formatWithArgumentRanges(self._s[3113]!, self._r[3113]!, [_0]) } - public var ChatList_Context_Delete: String { return self._s[3112]! } - public var PrivacyPhoneNumberSettings_CustomDisabledHelp: String { return self._s[3113]! } - public var Conversation_Processing: String { return self._s[3114]! } - public var TwoStepAuth_EmailCodeExpired: String { return self._s[3115]! } - public var ChatSettings_Stickers: String { return self._s[3116]! } - public var AppleWatch_ReplyPresetsHelp: String { return self._s[3117]! } - public var Passport_Language_cs: String { return self._s[3118]! } - public var GroupInfo_InvitationLinkGroupFull: String { return self._s[3120]! } - public var Conversation_Contact: String { return self._s[3121]! } - public var Passport_Identity_ReverseSideHelp: String { return self._s[3122]! } - public var SocksProxySetup_PasteFromClipboard: String { return self._s[3123]! } - public var Wallet_VoiceOver_Editing_ClearText: String { return self._s[3124]! } - public var Theme_Unsupported: String { return self._s[3125]! } - public var Wallet_SecureStorageNotAvailable_Text: String { return self._s[3126]! } - public var Privacy_TopPeersWarning: String { return self._s[3127]! } + public var ChatList_Context_Delete: String { return self._s[3114]! } + public var PrivacyPhoneNumberSettings_CustomDisabledHelp: String { return self._s[3115]! } + public var Conversation_Processing: String { return self._s[3116]! } + public var TwoStepAuth_EmailCodeExpired: String { return self._s[3117]! } + public var ChatSettings_Stickers: String { return self._s[3118]! } + public var AppleWatch_ReplyPresetsHelp: String { return self._s[3119]! } + public var Passport_Language_cs: String { return self._s[3120]! } + public var GroupInfo_InvitationLinkGroupFull: String { return self._s[3122]! } + public var Conversation_Contact: String { return self._s[3123]! } + public var Passport_Identity_ReverseSideHelp: String { return self._s[3124]! } + public var SocksProxySetup_PasteFromClipboard: String { return self._s[3125]! } + public var Wallet_VoiceOver_Editing_ClearText: String { return self._s[3126]! } + public var Theme_Unsupported: String { return self._s[3127]! } + public var Wallet_SecureStorageNotAvailable_Text: String { return self._s[3128]! } + public var Privacy_TopPeersWarning: String { return self._s[3129]! } public func UserInfo_BlockConfirmationTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3129]!, self._r[3129]!, [_0]) + return formatWithArgumentRanges(self._s[3131]!, self._r[3131]!, [_0]) } - public var Conversation_SilentBroadcastTooltipOn: String { return self._s[3130]! } - public var TwoStepAuth_RemovePassword: String { return self._s[3131]! } - public var Settings_CheckPhoneNumberText: String { return self._s[3132]! } - public var PeopleNearby_Users: String { return self._s[3133]! } - public var Appearance_TextSize_UseSystem: String { return self._s[3134]! } - public var Settings_SetProfilePhoto: String { return self._s[3135]! } - public var Conversation_ContextMenuBan: String { return self._s[3136]! } - public var KeyCommand_ScrollUp: String { return self._s[3137]! } - public var Settings_ChatSettings: String { return self._s[3139]! } + public var Conversation_SilentBroadcastTooltipOn: String { return self._s[3132]! } + public var TwoStepAuth_RemovePassword: String { return self._s[3133]! } + public var Settings_CheckPhoneNumberText: String { return self._s[3134]! } + public var PeopleNearby_Users: String { return self._s[3135]! } + public var Appearance_TextSize_UseSystem: String { return self._s[3136]! } + public var Settings_SetProfilePhoto: String { return self._s[3137]! } + public var Conversation_ContextMenuBan: String { return self._s[3138]! } + public var KeyCommand_ScrollUp: String { return self._s[3139]! } + public var Settings_ChatSettings: String { return self._s[3141]! } public func PUSH_CHAT_MESSAGE_VIDEO(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3140]!, self._r[3140]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3142]!, self._r[3142]!, [_1, _2]) } - public var Stats_GroupTopInvitersTitle: String { return self._s[3141]! } - public var Passport_Phone_EnterOtherNumber: String { return self._s[3142]! } - public var Passport_Identity_MiddleNamePlaceholder: String { return self._s[3144]! } - public var Passport_Address_OneOfTypeBankStatement: String { return self._s[3145]! } - public var Stats_GroupTopPoster_Promote: String { return self._s[3146]! } - public var Cache_Title: String { return self._s[3147]! } - public var Clipboard_SendPhoto: String { return self._s[3148]! } - public var Notifications_ExceptionsMessagePlaceholder: String { return self._s[3150]! } - public var TwoStepAuth_EnterPasswordForgot: String { return self._s[3151]! } - public var WatchRemote_AlertTitle: String { return self._s[3152]! } - public var Appearance_ReduceMotion: String { return self._s[3153]! } + public var Stats_GroupTopInvitersTitle: String { return self._s[3143]! } + public var Passport_Phone_EnterOtherNumber: String { return self._s[3144]! } + public var Passport_Identity_MiddleNamePlaceholder: String { return self._s[3146]! } + public var Passport_Address_OneOfTypeBankStatement: String { return self._s[3147]! } + public var Stats_GroupTopPoster_Promote: String { return self._s[3148]! } + public var Cache_Title: String { return self._s[3149]! } + public var Clipboard_SendPhoto: String { return self._s[3150]! } + public var Notifications_ExceptionsMessagePlaceholder: String { return self._s[3152]! } + public var TwoStepAuth_EnterPasswordForgot: String { return self._s[3153]! } + public var WatchRemote_AlertTitle: String { return self._s[3154]! } + public var Appearance_ReduceMotion: String { return self._s[3155]! } public func PUSH_CHAT_MESSAGE_ROUND(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3156]!, self._r[3156]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3158]!, self._r[3158]!, [_1, _2]) } - public var Notifications_PermissionsSuppressWarningText: String { return self._s[3157]! } - public var ChatList_UndoArchiveHiddenTitle: String { return self._s[3158]! } - public var Passport_Identity_TypePersonalDetails: String { return self._s[3159]! } - public var Wallet_TransactionInfo_CopyAddress: String { return self._s[3161]! } + public var Notifications_PermissionsSuppressWarningText: String { return self._s[3159]! } + public var ChatList_UndoArchiveHiddenTitle: String { return self._s[3160]! } + public var Passport_Identity_TypePersonalDetails: String { return self._s[3161]! } + public var Wallet_TransactionInfo_CopyAddress: String { return self._s[3163]! } public func Passport_Identity_UploadOneOfScan(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3162]!, self._r[3162]!, [_0]) - } - public var ChatListFolder_DiscardConfirmation: String { return self._s[3163]! } - public func Conversation_RestrictedStickersTimed(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3164]!, self._r[3164]!, [_0]) } - public var ChatState_WaitingForNetwork: String { return self._s[3165]! } - public var GroupInfo_Sound: String { return self._s[3166]! } - public var NotificationsSound_Telegraph: String { return self._s[3167]! } - public var NotificationsSound_Hello: String { return self._s[3168]! } - public var Passport_FieldIdentityDetailsHelp: String { return self._s[3169]! } - public var Wallet_Settings_BackupWallet: String { return self._s[3170]! } - public var Group_Members_AddMemberBotErrorNotAllowed: String { return self._s[3171]! } - public var Conversation_HoldForVideo: String { return self._s[3172]! } - public var Conversation_PinOlderMessageAlertText: String { return self._s[3173]! } - public var Wallet_Configuration_ApplyErrorTextURLInvalidData: String { return self._s[3174]! } - public var Wallet_RestoreFailed_EnterWords: String { return self._s[3175]! } - public var Appearance_ShareTheme: String { return self._s[3176]! } - public var TwoStepAuth_SetupHint: String { return self._s[3177]! } - public var Wallet_Created_Text: String { return self._s[3180]! } - public var Stats_GrowthTitle: String { return self._s[3181]! } - public var GroupInfo_InviteLink_ShareLink: String { return self._s[3182]! } - public var Conversation_DefaultRestrictedMedia: String { return self._s[3183]! } - public var Channel_EditAdmin_PermissionPostMessages: String { return self._s[3184]! } - public var GroupPermission_NoSendMessages: String { return self._s[3186]! } - public var Conversation_SetReminder_Title: String { return self._s[3187]! } - public var Privacy_Calls_CustomHelp: String { return self._s[3188]! } - public var CheckoutInfo_ErrorPostcodeInvalid: String { return self._s[3189]! } + public var ChatListFolder_DiscardConfirmation: String { return self._s[3165]! } + public func Conversation_RestrictedStickersTimed(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3166]!, self._r[3166]!, [_0]) + } + public var ChatState_WaitingForNetwork: String { return self._s[3167]! } + public var GroupInfo_Sound: String { return self._s[3168]! } + public var NotificationsSound_Telegraph: String { return self._s[3169]! } + public var NotificationsSound_Hello: String { return self._s[3170]! } + public var Passport_FieldIdentityDetailsHelp: String { return self._s[3171]! } + public var Wallet_Settings_BackupWallet: String { return self._s[3172]! } + public var Group_Members_AddMemberBotErrorNotAllowed: String { return self._s[3173]! } + public var Conversation_HoldForVideo: String { return self._s[3174]! } + public var Conversation_PinOlderMessageAlertText: String { return self._s[3175]! } + public var Wallet_Configuration_ApplyErrorTextURLInvalidData: String { return self._s[3176]! } + public var Wallet_RestoreFailed_EnterWords: String { return self._s[3177]! } + public var Appearance_ShareTheme: String { return self._s[3178]! } + public var TwoStepAuth_SetupHint: String { return self._s[3179]! } + public var Wallet_Created_Text: String { return self._s[3182]! } + public var Stats_GrowthTitle: String { return self._s[3183]! } + public var GroupInfo_InviteLink_ShareLink: String { return self._s[3184]! } + public var Conversation_DefaultRestrictedMedia: String { return self._s[3185]! } + public var Channel_EditAdmin_PermissionPostMessages: String { return self._s[3186]! } + public var GroupPermission_NoSendMessages: String { return self._s[3188]! } + public var Conversation_SetReminder_Title: String { return self._s[3189]! } + public var Privacy_Calls_CustomHelp: String { return self._s[3190]! } + public var CheckoutInfo_ErrorPostcodeInvalid: String { return self._s[3191]! } public func ClearCache_StorageTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3190]!, self._r[3190]!, [_0]) + return formatWithArgumentRanges(self._s[3192]!, self._r[3192]!, [_0]) } - public var Undo_SecretChatDeleted: String { return self._s[3192]! } - public var PhotoEditor_ContrastTool: String { return self._s[3193]! } - public var Privacy_Forwards: String { return self._s[3194]! } - public var AuthSessions_LoggedInWithTelegram: String { return self._s[3195]! } - public var KeyCommand_SendMessage: String { return self._s[3197]! } + public var Undo_SecretChatDeleted: String { return self._s[3194]! } + public var PhotoEditor_ContrastTool: String { return self._s[3195]! } + public var Privacy_Forwards: String { return self._s[3196]! } + public var AuthSessions_LoggedInWithTelegram: String { return self._s[3197]! } + public var KeyCommand_SendMessage: String { return self._s[3199]! } public func InstantPage_RelatedArticleAuthorAndDateTitle(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3198]!, self._r[3198]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3200]!, self._r[3200]!, [_1, _2]) } - public var GroupPermission_NoSendGifs: String { return self._s[3199]! } - public var Wallet_Month_ShortJune: String { return self._s[3200]! } - public var Notification_MessageLifetime2s: String { return self._s[3201]! } - public var Message_Theme: String { return self._s[3202]! } - public var Conversation_Dice_u1F3AF: String { return self._s[3205]! } + public var GroupPermission_NoSendGifs: String { return self._s[3201]! } + public var Wallet_Month_ShortJune: String { return self._s[3202]! } + public var Notification_MessageLifetime2s: String { return self._s[3203]! } + public var Message_Theme: String { return self._s[3204]! } + public var Conversation_Dice_u1F3AF: String { return self._s[3207]! } public func DialogList_SinglePlayingGameSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3206]!, self._r[3206]!, [_0]) + return formatWithArgumentRanges(self._s[3208]!, self._r[3208]!, [_0]) } - public var Group_UpgradeNoticeHeader: String { return self._s[3208]! } - public var PeerInfo_BioExpand: String { return self._s[3209]! } - public var Passport_DeletePersonalDetails: String { return self._s[3210]! } - public var Widget_NoUsers: String { return self._s[3211]! } - public var TwoStepAuth_AddHintTitle: String { return self._s[3212]! } - public var Login_TermsOfServiceDecline: String { return self._s[3213]! } - public var CreatePoll_QuizTip: String { return self._s[3215]! } - public var Watch_LastSeen_WithinAWeek: String { return self._s[3216]! } - public var MessagePoll_SubmitVote: String { return self._s[3218]! } - public var ChatSettings_AutoDownloadEnabled: String { return self._s[3219]! } - public var Passport_Address_EditRentalAgreement: String { return self._s[3220]! } - public var Conversation_SearchByName_Placeholder: String { return self._s[3221]! } - public var Conversation_UpdateTelegram: String { return self._s[3222]! } + public var Group_UpgradeNoticeHeader: String { return self._s[3210]! } + public var PeerInfo_BioExpand: String { return self._s[3211]! } + public var Passport_DeletePersonalDetails: String { return self._s[3212]! } + public var Widget_NoUsers: String { return self._s[3213]! } + public var TwoStepAuth_AddHintTitle: String { return self._s[3214]! } + public var Login_TermsOfServiceDecline: String { return self._s[3215]! } + public var CreatePoll_QuizTip: String { return self._s[3217]! } + public var Watch_LastSeen_WithinAWeek: String { return self._s[3218]! } + public var MessagePoll_SubmitVote: String { return self._s[3220]! } + public var ChatSettings_AutoDownloadEnabled: String { return self._s[3221]! } + public var Passport_Address_EditRentalAgreement: String { return self._s[3222]! } + public var Conversation_SearchByName_Placeholder: String { return self._s[3223]! } + public var Conversation_UpdateTelegram: String { return self._s[3224]! } public func FileSize_KB(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3223]!, self._r[3223]!, [_0]) + return formatWithArgumentRanges(self._s[3225]!, self._r[3225]!, [_0]) } - public var UserInfo_About_Placeholder: String { return self._s[3224]! } - public var CallSettings_Always: String { return self._s[3225]! } - public var ChannelInfo_ScamChannelWarning: String { return self._s[3226]! } - public var Login_TermsOfServiceHeader: String { return self._s[3227]! } - public var KeyCommand_ChatInfo: String { return self._s[3228]! } - public var MessagePoll_LabelPoll: String { return self._s[3229]! } - public var Paint_Clear: String { return self._s[3230]! } - public var PeerInfo_ButtonMute: String { return self._s[3231]! } - public var LastSeen_WithinAWeek: String { return self._s[3232]! } - public var Passport_Identity_FrontSide: String { return self._s[3233]! } - public var Stickers_GroupStickers: String { return self._s[3234]! } - public var ChangePhoneNumberNumber_NumberPlaceholder: String { return self._s[3235]! } + public var UserInfo_About_Placeholder: String { return self._s[3226]! } + public var CallSettings_Always: String { return self._s[3227]! } + public var ChannelInfo_ScamChannelWarning: String { return self._s[3228]! } + public var Login_TermsOfServiceHeader: String { return self._s[3229]! } + public var KeyCommand_ChatInfo: String { return self._s[3230]! } + public var MessagePoll_LabelPoll: String { return self._s[3231]! } + public var Paint_Clear: String { return self._s[3232]! } + public var PeerInfo_ButtonMute: String { return self._s[3233]! } + public var LastSeen_WithinAWeek: String { return self._s[3234]! } + public var Passport_Identity_FrontSide: String { return self._s[3235]! } + public var Stickers_GroupStickers: String { return self._s[3236]! } + public var ChangePhoneNumberNumber_NumberPlaceholder: String { return self._s[3237]! } public func Map_SearchNoResultsDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3236]!, self._r[3236]!, [_0]) + return formatWithArgumentRanges(self._s[3238]!, self._r[3238]!, [_0]) } public func PUSH_MESSAGE_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3239]!, self._r[3239]!, [_1]) + return formatWithArgumentRanges(self._s[3241]!, self._r[3241]!, [_1]) } - public var SocksProxySetup_ProxyStatusConnected: String { return self._s[3240]! } - public var Chat_MultipleTextMessagesDisabled: String { return self._s[3241]! } + public var SocksProxySetup_ProxyStatusConnected: String { return self._s[3242]! } + public var Chat_MultipleTextMessagesDisabled: String { return self._s[3243]! } public func Notification_LeftChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3242]!, self._r[3242]!, [_0]) + return formatWithArgumentRanges(self._s[3244]!, self._r[3244]!, [_0]) } - public var Wallet_Send_AmountText: String { return self._s[3243]! } - public var WebSearch_SearchNoResults: String { return self._s[3245]! } - public var Channel_DiscussionGroup_Create: String { return self._s[3246]! } - public var Passport_Language_es: String { return self._s[3247]! } - public var EnterPasscode_EnterCurrentPasscode: String { return self._s[3248]! } - public var Wallet_Intro_Title: String { return self._s[3249]! } - public var Map_LiveLocationShowAll: String { return self._s[3250]! } - public var Cache_MaximumCacheSizeHelp: String { return self._s[3252]! } - public var Map_OpenInGoogleMaps: String { return self._s[3253]! } - public var CheckoutInfo_ErrorNameInvalid: String { return self._s[3255]! } - public var EditTheme_Create_BottomInfo: String { return self._s[3256]! } - public var PhotoEditor_BlurToolLinear: String { return self._s[3257]! } + public var Wallet_Send_AmountText: String { return self._s[3245]! } + public var WebSearch_SearchNoResults: String { return self._s[3247]! } + public var Channel_DiscussionGroup_Create: String { return self._s[3248]! } + public var Passport_Language_es: String { return self._s[3249]! } + public var EnterPasscode_EnterCurrentPasscode: String { return self._s[3250]! } + public var Wallet_Intro_Title: String { return self._s[3251]! } + public var Map_LiveLocationShowAll: String { return self._s[3252]! } + public var Cache_MaximumCacheSizeHelp: String { return self._s[3254]! } + public var Map_OpenInGoogleMaps: String { return self._s[3255]! } + public var CheckoutInfo_ErrorNameInvalid: String { return self._s[3257]! } + public var EditTheme_Create_BottomInfo: String { return self._s[3258]! } + public var PhotoEditor_BlurToolLinear: String { return self._s[3259]! } public func Channel_AdminLog_MessageEdited(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3258]!, self._r[3258]!, [_0]) + return formatWithArgumentRanges(self._s[3260]!, self._r[3260]!, [_0]) } - public var Passport_Phone_Delete: String { return self._s[3259]! } - public var Channel_Username_CreatePrivateLinkHelp: String { return self._s[3260]! } - public var PrivacySettings_PrivacyTitle: String { return self._s[3261]! } - public var CheckoutInfo_ReceiverInfoNamePlaceholder: String { return self._s[3262]! } + public var Passport_Phone_Delete: String { return self._s[3261]! } + public var Channel_Username_CreatePrivateLinkHelp: String { return self._s[3262]! } + public var PrivacySettings_PrivacyTitle: String { return self._s[3263]! } + public var CheckoutInfo_ReceiverInfoNamePlaceholder: String { return self._s[3264]! } public func EncryptionKey_Description(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3263]!, self._r[3263]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3265]!, self._r[3265]!, [_1, _2]) } - public var LogoutOptions_LogOutInfo: String { return self._s[3264]! } - public var Wallet_Month_GenAugust: String { return self._s[3265]! } - public var Cache_ByPeerHeader: String { return self._s[3266]! } - public var Username_InvalidCharacters: String { return self._s[3267]! } - public var Wallet_Qr_Title: String { return self._s[3269]! } - public var Checkout_ShippingAddress: String { return self._s[3270]! } + public var LogoutOptions_LogOutInfo: String { return self._s[3266]! } + public var Wallet_Month_GenAugust: String { return self._s[3267]! } + public var Cache_ByPeerHeader: String { return self._s[3268]! } + public var Username_InvalidCharacters: String { return self._s[3269]! } + public var Wallet_Qr_Title: String { return self._s[3271]! } + public var Checkout_ShippingAddress: String { return self._s[3272]! } public func PUSH_CHAT_MESSAGE_GAME_SCORE(_ _1: String, _ _2: String, _ _3: String, _ _4: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3271]!, self._r[3271]!, [_1, _2, _3, _4]) + return formatWithArgumentRanges(self._s[3273]!, self._r[3273]!, [_1, _2, _3, _4]) } - public var Conversation_AddContact: String { return self._s[3273]! } - public var Passport_Address_EditUtilityBill: String { return self._s[3274]! } - public var Message_Video: String { return self._s[3275]! } + public var Conversation_AddContact: String { return self._s[3275]! } + public var Passport_Address_EditUtilityBill: String { return self._s[3276]! } + public var Message_Video: String { return self._s[3277]! } public func Watch_Time_ShortYesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3276]!, self._r[3276]!, [_0]) + return formatWithArgumentRanges(self._s[3278]!, self._r[3278]!, [_0]) } public func Conversation_Megabytes(_ _0: Float) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3277]!, self._r[3277]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[3279]!, self._r[3279]!, ["\(_0)"]) } - public var Passport_Language_km: String { return self._s[3278]! } + public var Passport_Language_km: String { return self._s[3280]! } public func PUSH_MESSAGE_CHANNEL_MESSAGE_GAME_SCORE(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3279]!, self._r[3279]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3281]!, self._r[3281]!, [_1, _2, _3]) } - public var EmptyGroupInfo_Line4: String { return self._s[3280]! } - public var Conversation_SendMessageErrorTooMuchScheduled: String { return self._s[3282]! } - public var Notification_CallCanceledShort: String { return self._s[3283]! } - public var PhotoEditor_FadeTool: String { return self._s[3284]! } - public var Group_PublicLink_Info: String { return self._s[3285]! } - public var Contacts_DeselectAll: String { return self._s[3286]! } - public var Conversation_Moderate_Delete: String { return self._s[3287]! } - public var TwoStepAuth_RecoveryCodeInvalid: String { return self._s[3288]! } - public var NotificationsSound_Note: String { return self._s[3291]! } + public var EmptyGroupInfo_Line4: String { return self._s[3282]! } + public var Conversation_SendMessageErrorTooMuchScheduled: String { return self._s[3284]! } + public var Notification_CallCanceledShort: String { return self._s[3285]! } + public var PhotoEditor_FadeTool: String { return self._s[3286]! } + public var Group_PublicLink_Info: String { return self._s[3287]! } + public var Contacts_DeselectAll: String { return self._s[3288]! } + public var Conversation_Moderate_Delete: String { return self._s[3289]! } + public var TwoStepAuth_RecoveryCodeInvalid: String { return self._s[3290]! } + public var NotificationsSound_Note: String { return self._s[3293]! } public func Message_PaymentSent(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3292]!, self._r[3292]!, [_0]) + return formatWithArgumentRanges(self._s[3294]!, self._r[3294]!, [_0]) } - public var Appearance_ThemePreview_ChatList_7_Text: String { return self._s[3293]! } - public var Channel_EditAdmin_PermissionInviteViaLink: String { return self._s[3294]! } - public var DialogList_SearchSectionGlobal: String { return self._s[3295]! } - public var AccessDenied_Settings: String { return self._s[3296]! } - public var Passport_Identity_TypeIdentityCardUploadScan: String { return self._s[3297]! } - public var AuthSessions_EmptyTitle: String { return self._s[3298]! } - public var TwoStepAuth_PasswordChangeSuccess: String { return self._s[3299]! } - public var GroupInfo_GroupType: String { return self._s[3300]! } - public var Calls_Missed: String { return self._s[3301]! } - public var UserInfo_GenericPhoneLabel: String { return self._s[3302]! } - public var Passport_Language_uz: String { return self._s[3303]! } - public var Conversation_StopQuizConfirmationTitle: String { return self._s[3304]! } - public var PhotoEditor_BlurToolPortrait: String { return self._s[3305]! } - public var Map_ChooseLocationTitle: String { return self._s[3306]! } - public var Checkout_EnterPassword: String { return self._s[3307]! } - public var GroupInfo_ConvertToSupergroup: String { return self._s[3308]! } - public var AutoNightTheme_UpdateLocation: String { return self._s[3309]! } - public var NetworkUsageSettings_Title: String { return self._s[3310]! } - public var Location_ProximityAlertCancelled: String { return self._s[3311]! } - public var SettingsSearch_Synonyms_ChatSettings_IntentsSettings: String { return self._s[3312]! } - public var Message_PinnedLiveLocationMessage: String { return self._s[3313]! } - public var Compose_NewChannel: String { return self._s[3314]! } - public var Privacy_PaymentsClearInfo: String { return self._s[3316]! } + public var Appearance_ThemePreview_ChatList_7_Text: String { return self._s[3295]! } + public var Channel_EditAdmin_PermissionInviteViaLink: String { return self._s[3296]! } + public var DialogList_SearchSectionGlobal: String { return self._s[3297]! } + public var AccessDenied_Settings: String { return self._s[3298]! } + public var Passport_Identity_TypeIdentityCardUploadScan: String { return self._s[3299]! } + public var AuthSessions_EmptyTitle: String { return self._s[3300]! } + public var TwoStepAuth_PasswordChangeSuccess: String { return self._s[3301]! } + public var GroupInfo_GroupType: String { return self._s[3302]! } + public var Calls_Missed: String { return self._s[3303]! } + public var UserInfo_GenericPhoneLabel: String { return self._s[3304]! } + public var Passport_Language_uz: String { return self._s[3305]! } + public var Conversation_StopQuizConfirmationTitle: String { return self._s[3306]! } + public var PhotoEditor_BlurToolPortrait: String { return self._s[3307]! } + public var Map_ChooseLocationTitle: String { return self._s[3308]! } + public var Checkout_EnterPassword: String { return self._s[3309]! } + public var GroupInfo_ConvertToSupergroup: String { return self._s[3310]! } + public var AutoNightTheme_UpdateLocation: String { return self._s[3311]! } + public var NetworkUsageSettings_Title: String { return self._s[3312]! } + public var Location_ProximityAlertCancelled: String { return self._s[3313]! } + public var SettingsSearch_Synonyms_ChatSettings_IntentsSettings: String { return self._s[3314]! } + public var Message_PinnedLiveLocationMessage: String { return self._s[3315]! } + public var Compose_NewChannel: String { return self._s[3316]! } + public var Privacy_PaymentsClearInfo: String { return self._s[3318]! } public func PUSH_MESSAGE_POLL(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3317]!, self._r[3317]!, [_1]) + return formatWithArgumentRanges(self._s[3319]!, self._r[3319]!, [_1]) } - public var Notification_Exceptions_AlwaysOn: String { return self._s[3318]! } - public var Privacy_GroupsAndChannels_WhoCanAddMe: String { return self._s[3319]! } - public var AutoNightTheme_AutomaticSection: String { return self._s[3322]! } - public var WallpaperSearch_ColorBrown: String { return self._s[3323]! } - public var Appearance_AppIconDefault: String { return self._s[3324]! } - public var Wallet_Month_GenJune: String { return self._s[3327]! } - public var StickerSettings_ContextInfo: String { return self._s[3328]! } - public var Channel_AddBotErrorNoRights: String { return self._s[3329]! } - public var Passport_FieldPhone: String { return self._s[3331]! } - public var Contacts_PermissionsTitle: String { return self._s[3332]! } - public var TwoFactorSetup_Email_SkipConfirmationSkip: String { return self._s[3333]! } + public var Notification_Exceptions_AlwaysOn: String { return self._s[3320]! } + public var Privacy_GroupsAndChannels_WhoCanAddMe: String { return self._s[3321]! } + public var AutoNightTheme_AutomaticSection: String { return self._s[3324]! } + public var WallpaperSearch_ColorBrown: String { return self._s[3325]! } + public var Appearance_AppIconDefault: String { return self._s[3326]! } + public var Wallet_Month_GenJune: String { return self._s[3329]! } + public var StickerSettings_ContextInfo: String { return self._s[3330]! } + public var Channel_AddBotErrorNoRights: String { return self._s[3331]! } + public var Passport_FieldPhone: String { return self._s[3333]! } + public var Contacts_PermissionsTitle: String { return self._s[3334]! } + public var TwoFactorSetup_Email_SkipConfirmationSkip: String { return self._s[3335]! } public func Notification_JoinedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3334]!, self._r[3334]!, [_0]) + return formatWithArgumentRanges(self._s[3336]!, self._r[3336]!, [_0]) } - public var Bot_Unblock: String { return self._s[3335]! } - public var PasscodeSettings_SimplePasscode: String { return self._s[3336]! } - public var Passport_PasswordHelp: String { return self._s[3337]! } - public var Watch_Conversation_UserInfo: String { return self._s[3338]! } + public var Bot_Unblock: String { return self._s[3337]! } + public var PasscodeSettings_SimplePasscode: String { return self._s[3338]! } + public var Passport_PasswordHelp: String { return self._s[3339]! } + public var Watch_Conversation_UserInfo: String { return self._s[3340]! } public func Channel_AdminLog_MessageChangedGroupGeoLocation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3342]!, self._r[3342]!, [_0]) + return formatWithArgumentRanges(self._s[3344]!, self._r[3344]!, [_0]) } - public var State_Connecting: String { return self._s[3344]! } - public var Passport_Address_TypeTemporaryRegistration: String { return self._s[3345]! } - public var TextFormat_AddLinkPlaceholder: String { return self._s[3346]! } - public var Conversation_Dice_u1F3B2: String { return self._s[3347]! } + public var State_Connecting: String { return self._s[3346]! } + public var Passport_Address_TypeTemporaryRegistration: String { return self._s[3347]! } + public var TextFormat_AddLinkPlaceholder: String { return self._s[3348]! } + public var Conversation_Dice_u1F3B2: String { return self._s[3349]! } public func Call_StatusBar(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3348]!, self._r[3348]!, [_0]) + return formatWithArgumentRanges(self._s[3350]!, self._r[3350]!, [_0]) } - public var Conversation_SendingOptionsTooltip: String { return self._s[3349]! } - public var ChatList_UndoArchiveTitle: String { return self._s[3350]! } - public var ChatList_EmptyChatListNewMessage: String { return self._s[3351]! } - public var WallpaperSearch_ColorGreen: String { return self._s[3353]! } - public var PhotoEditor_BlurToolOff: String { return self._s[3354]! } - public var SocksProxySetup_PortPlaceholder: String { return self._s[3355]! } - public var Weekday_Saturday: String { return self._s[3356]! } - public var DialogList_Unread: String { return self._s[3357]! } - public var Watch_LastSeen_ALongTimeAgo: String { return self._s[3358]! } - public var Stats_GroupPosters: String { return self._s[3359]! } + public var Conversation_SendingOptionsTooltip: String { return self._s[3351]! } + public var ChatList_UndoArchiveTitle: String { return self._s[3352]! } + public var ChatList_EmptyChatListNewMessage: String { return self._s[3353]! } + public var WallpaperSearch_ColorGreen: String { return self._s[3355]! } + public var PhotoEditor_BlurToolOff: String { return self._s[3356]! } + public var SocksProxySetup_PortPlaceholder: String { return self._s[3357]! } + public var Weekday_Saturday: String { return self._s[3358]! } + public var DialogList_Unread: String { return self._s[3359]! } + public var Watch_LastSeen_ALongTimeAgo: String { return self._s[3360]! } + public var Stats_GroupPosters: String { return self._s[3361]! } public func PUSH_ENCRYPTION_REQUEST(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3360]!, self._r[3360]!, [_1]) + return formatWithArgumentRanges(self._s[3362]!, self._r[3362]!, [_1]) } public func Target_ShareGameConfirmationGroup(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3363]!, self._r[3363]!, [_0]) + return formatWithArgumentRanges(self._s[3365]!, self._r[3365]!, [_0]) } - public var ReportPeer_ReasonChildAbuse: String { return self._s[3364]! } + public var ReportPeer_ReasonChildAbuse: String { return self._s[3366]! } public func Channel_AdminLog_MessageUnkickedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3365]!, self._r[3365]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3367]!, self._r[3367]!, [_1, _2]) } - public var InfoPlist_NSContactsUsageDescription: String { return self._s[3366]! } - public var AutoNightTheme_UseSunsetSunrise: String { return self._s[3368]! } - public var Channel_OwnershipTransfer_ChangeOwner: String { return self._s[3369]! } - public var Passport_Language_dv: String { return self._s[3370]! } - public var GroupPermission_AddSuccess: String { return self._s[3373]! } - public var Passport_Email_Help: String { return self._s[3374]! } - public var Call_ReportPlaceholder: String { return self._s[3375]! } - public var CreatePoll_AddOption: String { return self._s[3376]! } - public var MessagePoll_LabelAnonymousQuiz: String { return self._s[3377]! } - public var PeerInfo_ButtonLeave: String { return self._s[3378]! } - public var PhotoEditor_TiltShift: String { return self._s[3381]! } - public var SecretGif_Title: String { return self._s[3383]! } - public var PhotoEditor_QualityVeryLow: String { return self._s[3384]! } - public var SocksProxySetup_Connecting: String { return self._s[3385]! } - public var PrivacySettings_PasscodeAndFaceId: String { return self._s[3386]! } - public var ContactInfo_PhoneLabelWork: String { return self._s[3387]! } - public var Stats_GroupTopHoursTitle: String { return self._s[3388]! } - public var Compose_NewMessage: String { return self._s[3389]! } - public var NotificationsSound_Synth: String { return self._s[3390]! } - public var Conversation_FileOpenIn: String { return self._s[3391]! } - public var AutoDownloadSettings_WifiTitle: String { return self._s[3392]! } - public var UserInfo_SendMessage: String { return self._s[3393]! } - public var Checkout_PayWithFaceId: String { return self._s[3394]! } + public var InfoPlist_NSContactsUsageDescription: String { return self._s[3368]! } + public var AutoNightTheme_UseSunsetSunrise: String { return self._s[3370]! } + public var Channel_OwnershipTransfer_ChangeOwner: String { return self._s[3371]! } + public var Passport_Language_dv: String { return self._s[3372]! } + public var GroupPermission_AddSuccess: String { return self._s[3375]! } + public var Passport_Email_Help: String { return self._s[3376]! } + public var Call_ReportPlaceholder: String { return self._s[3377]! } + public var CreatePoll_AddOption: String { return self._s[3378]! } + public var MessagePoll_LabelAnonymousQuiz: String { return self._s[3379]! } + public var PeerInfo_ButtonLeave: String { return self._s[3380]! } + public var PhotoEditor_TiltShift: String { return self._s[3383]! } + public var SecretGif_Title: String { return self._s[3385]! } + public var PhotoEditor_QualityVeryLow: String { return self._s[3386]! } + public var SocksProxySetup_Connecting: String { return self._s[3387]! } + public var PrivacySettings_PasscodeAndFaceId: String { return self._s[3388]! } + public var ContactInfo_PhoneLabelWork: String { return self._s[3389]! } + public var Stats_GroupTopHoursTitle: String { return self._s[3390]! } + public var Compose_NewMessage: String { return self._s[3391]! } + public var NotificationsSound_Synth: String { return self._s[3392]! } + public var Conversation_FileOpenIn: String { return self._s[3393]! } + public var AutoDownloadSettings_WifiTitle: String { return self._s[3394]! } + public var UserInfo_SendMessage: String { return self._s[3395]! } + public var Checkout_PayWithFaceId: String { return self._s[3396]! } public func Map_LiveLocationShortHour(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3395]!, self._r[3395]!, [_0]) + return formatWithArgumentRanges(self._s[3397]!, self._r[3397]!, [_0]) } - public var TextFormat_Strikethrough: String { return self._s[3396]! } - public var SettingsSearch_Synonyms_Notifications_DisplayNamesOnLockScreen: String { return self._s[3397]! } - public var Conversation_ViewChannel: String { return self._s[3398]! } + public var TextFormat_Strikethrough: String { return self._s[3398]! } + public var SettingsSearch_Synonyms_Notifications_DisplayNamesOnLockScreen: String { return self._s[3399]! } + public var Conversation_ViewChannel: String { return self._s[3400]! } public func Message_ForwardedMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3399]!, self._r[3399]!, [_0]) + return formatWithArgumentRanges(self._s[3401]!, self._r[3401]!, [_0]) } - public var Channel_Stickers_Placeholder: String { return self._s[3400]! } - public var Channel_OwnershipTransfer_PasswordPlaceholder: String { return self._s[3401]! } - public var Camera_FlashAuto: String { return self._s[3402]! } - public var Conversation_EncryptedDescription1: String { return self._s[3403]! } - public var LocalGroup_Text: String { return self._s[3404]! } - public var SettingsSearch_Synonyms_Data_Storage_KeepMedia: String { return self._s[3405]! } - public var UserInfo_FirstNamePlaceholder: String { return self._s[3406]! } - public var Conversation_SendMessageErrorFlood: String { return self._s[3407]! } - public var Conversation_EncryptedDescription2: String { return self._s[3408]! } - public var Notification_GroupActivated: String { return self._s[3409]! } - public var LastSeen_Lately: String { return self._s[3410]! } - public var Conversation_EncryptedDescription3: String { return self._s[3411]! } - public var SettingsSearch_Synonyms_Privacy_ProfilePhoto: String { return self._s[3412]! } - public var Conversation_SwipeToReplyHintText: String { return self._s[3413]! } - public var Conversation_EncryptedDescription4: String { return self._s[3414]! } - public var SharedMedia_EmptyTitle: String { return self._s[3415]! } - public var Wallet_Configuration_Apply: String { return self._s[3416]! } - public var Appearance_CreateTheme: String { return self._s[3417]! } - public var Stats_SharesPerPost: String { return self._s[3418]! } - public var Contacts_TabTitle: String { return self._s[3419]! } - public var Weekday_ShortThursday: String { return self._s[3420]! } - public var MessageTimer_Forever: String { return self._s[3421]! } - public var ChatListFolder_CategoryArchived: String { return self._s[3422]! } - public var Channel_EditAdmin_PermissionDeleteMessages: String { return self._s[3423]! } - public var EditTheme_Create_TopInfo: String { return self._s[3425]! } - public var Month_GenDecember: String { return self._s[3426]! } - public var EnterPasscode_EnterPasscode: String { return self._s[3427]! } - public var SettingsSearch_Synonyms_Appearance_LargeEmoji: String { return self._s[3428]! } - public var PeopleNearby_CreateGroup: String { return self._s[3430]! } - public var Group_EditAdmin_PermissionChangeInfo: String { return self._s[3431]! } - public var Paint_ClearConfirm: String { return self._s[3432]! } - public var ChatList_ReadAll: String { return self._s[3433]! } - public var ChatSettings_IntentsSettings: String { return self._s[3434]! } - public var Passport_PassportInformation: String { return self._s[3436]! } - public var Login_CheckOtherSessionMessages: String { return self._s[3438]! } - public var Location_ProximityNotification_DistanceMI: String { return self._s[3441]! } - public var PhotoEditor_ExposureTool: String { return self._s[3442]! } - public var Group_Username_CreatePrivateLinkHelp: String { return self._s[3443]! } - public var SettingsSearch_Synonyms_Watch: String { return self._s[3444]! } - public var Stats_GroupTopPoster_History: String { return self._s[3445]! } - public var UserInfo_AddPhone: String { return self._s[3446]! } - public var Media_SendWithTimer: String { return self._s[3448]! } - public var SettingsSearch_Synonyms_Notifications_Title: String { return self._s[3449]! } - public var Channel_EditAdmin_PermissionEnabledByDefault: String { return self._s[3450]! } - public var PasscodeSettings_AutoLock_Disabled: String { return self._s[3451]! } - public var ChatList_Context_Unarchive: String { return self._s[3453]! } + public var Channel_Stickers_Placeholder: String { return self._s[3402]! } + public var Channel_OwnershipTransfer_PasswordPlaceholder: String { return self._s[3403]! } + public var Camera_FlashAuto: String { return self._s[3404]! } + public var Conversation_EncryptedDescription1: String { return self._s[3405]! } + public var LocalGroup_Text: String { return self._s[3406]! } + public var SettingsSearch_Synonyms_Data_Storage_KeepMedia: String { return self._s[3407]! } + public var UserInfo_FirstNamePlaceholder: String { return self._s[3408]! } + public var Conversation_SendMessageErrorFlood: String { return self._s[3409]! } + public var Conversation_EncryptedDescription2: String { return self._s[3410]! } + public var Notification_GroupActivated: String { return self._s[3411]! } + public var LastSeen_Lately: String { return self._s[3412]! } + public var Conversation_EncryptedDescription3: String { return self._s[3413]! } + public var SettingsSearch_Synonyms_Privacy_ProfilePhoto: String { return self._s[3414]! } + public var Conversation_SwipeToReplyHintText: String { return self._s[3415]! } + public var Conversation_EncryptedDescription4: String { return self._s[3416]! } + public var SharedMedia_EmptyTitle: String { return self._s[3417]! } + public var Wallet_Configuration_Apply: String { return self._s[3418]! } + public var Appearance_CreateTheme: String { return self._s[3419]! } + public var Stats_SharesPerPost: String { return self._s[3420]! } + public var Contacts_TabTitle: String { return self._s[3421]! } + public var Weekday_ShortThursday: String { return self._s[3422]! } + public var MessageTimer_Forever: String { return self._s[3423]! } + public var ChatListFolder_CategoryArchived: String { return self._s[3424]! } + public var Channel_EditAdmin_PermissionDeleteMessages: String { return self._s[3425]! } + public var EditTheme_Create_TopInfo: String { return self._s[3427]! } + public var Month_GenDecember: String { return self._s[3428]! } + public var EnterPasscode_EnterPasscode: String { return self._s[3429]! } + public var SettingsSearch_Synonyms_Appearance_LargeEmoji: String { return self._s[3430]! } + public var PeopleNearby_CreateGroup: String { return self._s[3432]! } + public var Group_EditAdmin_PermissionChangeInfo: String { return self._s[3433]! } + public var Paint_ClearConfirm: String { return self._s[3434]! } + public var ChatList_ReadAll: String { return self._s[3435]! } + public var ChatSettings_IntentsSettings: String { return self._s[3436]! } + public var Passport_PassportInformation: String { return self._s[3438]! } + public var Login_CheckOtherSessionMessages: String { return self._s[3440]! } + public var Location_ProximityNotification_DistanceMI: String { return self._s[3443]! } + public var PhotoEditor_ExposureTool: String { return self._s[3444]! } + public var Group_Username_CreatePrivateLinkHelp: String { return self._s[3445]! } + public var SettingsSearch_Synonyms_Watch: String { return self._s[3446]! } + public var Stats_GroupTopPoster_History: String { return self._s[3447]! } + public var UserInfo_AddPhone: String { return self._s[3448]! } + public var Media_SendWithTimer: String { return self._s[3450]! } + public var SettingsSearch_Synonyms_Notifications_Title: String { return self._s[3451]! } + public var Channel_EditAdmin_PermissionEnabledByDefault: String { return self._s[3452]! } + public var PasscodeSettings_AutoLock_Disabled: String { return self._s[3453]! } + public var ChatList_Context_Unarchive: String { return self._s[3455]! } public func DialogList_LiveLocationSharingTo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3454]!, self._r[3454]!, [_0]) + return formatWithArgumentRanges(self._s[3456]!, self._r[3456]!, [_0]) } - public var BlockedUsers_Title: String { return self._s[3456]! } - public var TwoStepAuth_EmailPlaceholder: String { return self._s[3457]! } - public var Media_ShareThisPhoto: String { return self._s[3458]! } - public var Notifications_DisplayNamesOnLockScreen: String { return self._s[3459]! } - public var Conversation_FilePhotoOrVideo: String { return self._s[3460]! } - public var Appearance_ThemePreview_Chat_2_ReplyName: String { return self._s[3464]! } + public var BlockedUsers_Title: String { return self._s[3458]! } + public var TwoStepAuth_EmailPlaceholder: String { return self._s[3459]! } + public var Media_ShareThisPhoto: String { return self._s[3460]! } + public var Notifications_DisplayNamesOnLockScreen: String { return self._s[3461]! } + public var Conversation_FilePhotoOrVideo: String { return self._s[3462]! } + public var Appearance_ThemePreview_Chat_2_ReplyName: String { return self._s[3466]! } public func PUSH_CHAT_MESSAGE_DOCS(_ _1: String, _ _2: String, _ _3: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3465]!, self._r[3465]!, [_1, _2, "\(_3)"]) + return formatWithArgumentRanges(self._s[3467]!, self._r[3467]!, [_1, _2, "\(_3)"]) } - public var CallFeedback_ReasonNoise: String { return self._s[3466]! } - public var WebBrowser_Title: String { return self._s[3468]! } + public var CallFeedback_ReasonNoise: String { return self._s[3468]! } + public var WebBrowser_Title: String { return self._s[3470]! } public func Checkout_SavePasswordTimeoutAndTouchId(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3469]!, self._r[3469]!, [_0]) + return formatWithArgumentRanges(self._s[3471]!, self._r[3471]!, [_0]) } - public var Notification_MessageLifetime5s: String { return self._s[3470]! } - public var Passport_Address_AddResidentialAddress: String { return self._s[3471]! } - public var Profile_MessageLifetime1m: String { return self._s[3472]! } - public var Stats_LoadingTitle: String { return self._s[3474]! } - public var Passport_ScanPassport: String { return self._s[3475]! } - public var Passport_Address_AddTemporaryRegistration: String { return self._s[3478]! } - public var Permissions_NotificationsAllow_v0: String { return self._s[3479]! } - public var Login_InvalidFirstNameError: String { return self._s[3480]! } - public var Undo_ChatCleared: String { return self._s[3482]! } + public var Notification_MessageLifetime5s: String { return self._s[3472]! } + public var Passport_Address_AddResidentialAddress: String { return self._s[3473]! } + public var Profile_MessageLifetime1m: String { return self._s[3474]! } + public var Stats_LoadingTitle: String { return self._s[3476]! } + public var Passport_ScanPassport: String { return self._s[3477]! } + public var Passport_Address_AddTemporaryRegistration: String { return self._s[3480]! } + public var Permissions_NotificationsAllow_v0: String { return self._s[3481]! } + public var Login_InvalidFirstNameError: String { return self._s[3482]! } + public var Undo_ChatCleared: String { return self._s[3484]! } public func ApplyLanguage_ChangeLanguageUnofficialText(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3484]!, self._r[3484]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3486]!, self._r[3486]!, [_1, _2]) } - public var Conversation_PinMessageAlertPin: String { return self._s[3485]! } + public var Conversation_PinMessageAlertPin: String { return self._s[3487]! } public func Login_PhoneBannedEmailBody(_ _1: String, _ _2: String, _ _3: String, _ _4: String, _ _5: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3486]!, self._r[3486]!, [_1, _2, _3, _4, _5]) + return formatWithArgumentRanges(self._s[3488]!, self._r[3488]!, [_1, _2, _3, _4, _5]) } public func PUSH_MESSAGE_FWD(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3487]!, self._r[3487]!, [_1]) + return formatWithArgumentRanges(self._s[3489]!, self._r[3489]!, [_1]) } - public var Share_MultipleMessagesDisabled: String { return self._s[3488]! } - public var TwoStepAuth_EmailInvalid: String { return self._s[3489]! } - public var EnterPasscode_ChangeTitle: String { return self._s[3491]! } + public var Share_MultipleMessagesDisabled: String { return self._s[3490]! } + public var TwoStepAuth_EmailInvalid: String { return self._s[3491]! } + public var EnterPasscode_ChangeTitle: String { return self._s[3493]! } public func Wallet_Send_ConfirmationText(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3492]!, self._r[3492]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3494]!, self._r[3494]!, [_1, _2, _3]) } - public var CallSettings_RecentCalls: String { return self._s[3493]! } - public var GroupInfo_DeactivatedStatus: String { return self._s[3494]! } - public var AuthSessions_OtherSessions: String { return self._s[3495]! } - public var PrivacyLastSeenSettings_CustomHelp: String { return self._s[3496]! } - public var Tour_Text5: String { return self._s[3497]! } - public var Login_PadPhoneHelp: String { return self._s[3498]! } - public var Wallpaper_PhotoLibrary: String { return self._s[3500]! } - public var Conversation_ViewGroup: String { return self._s[3501]! } - public var PeopleNearby_MakeVisibleTitle: String { return self._s[3503]! } - public var VoiceOver_Chat_YourContact: String { return self._s[3504]! } - public var Watch_AuthRequired: String { return self._s[3505]! } - public var VoiceOver_Chat_ForwardedFromYou: String { return self._s[3506]! } - public var Conversation_ForwardContacts: String { return self._s[3507]! } - public var Conversation_InputTextPlaceholder: String { return self._s[3508]! } + public var CallSettings_RecentCalls: String { return self._s[3495]! } + public var GroupInfo_DeactivatedStatus: String { return self._s[3496]! } + public var AuthSessions_OtherSessions: String { return self._s[3497]! } + public var PrivacyLastSeenSettings_CustomHelp: String { return self._s[3498]! } + public var Tour_Text5: String { return self._s[3499]! } + public var Login_PadPhoneHelp: String { return self._s[3500]! } + public var Wallpaper_PhotoLibrary: String { return self._s[3502]! } + public var Conversation_ViewGroup: String { return self._s[3503]! } + public var PeopleNearby_MakeVisibleTitle: String { return self._s[3505]! } + public var VoiceOver_Chat_YourContact: String { return self._s[3506]! } + public var Watch_AuthRequired: String { return self._s[3507]! } + public var VoiceOver_Chat_ForwardedFromYou: String { return self._s[3508]! } + public var Conversation_ForwardContacts: String { return self._s[3509]! } + public var Conversation_InputTextPlaceholder: String { return self._s[3510]! } public func PUSH_CHANNEL_MESSAGE_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3509]!, self._r[3509]!, [_1]) + return formatWithArgumentRanges(self._s[3511]!, self._r[3511]!, [_1]) } public func Conversation_MessageViaUser(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3510]!, self._r[3510]!, [_0]) - } - public var Channel_Setup_TypePrivate: String { return self._s[3511]! } - public func Conversation_NoticeInvitedByInChannel(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3512]!, self._r[3512]!, [_0]) } - public var InfoPlist_NSSiriUsageDescription: String { return self._s[3513]! } - public var Wallet_ContextMenuCopy: String { return self._s[3514]! } - public var EmptyGroupInfo_Subtitle: String { return self._s[3515]! } - public var AutoDownloadSettings_Delimeter: String { return self._s[3516]! } - public var UserInfo_StartSecretChatStart: String { return self._s[3517]! } + public var Channel_Setup_TypePrivate: String { return self._s[3513]! } + public func Conversation_NoticeInvitedByInChannel(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3514]!, self._r[3514]!, [_0]) + } + public var InfoPlist_NSSiriUsageDescription: String { return self._s[3515]! } + public var Wallet_ContextMenuCopy: String { return self._s[3516]! } + public var EmptyGroupInfo_Subtitle: String { return self._s[3517]! } + public var AutoDownloadSettings_Delimeter: String { return self._s[3518]! } + public var UserInfo_StartSecretChatStart: String { return self._s[3519]! } public func GroupPermission_AddedInfo(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3518]!, self._r[3518]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3520]!, self._r[3520]!, [_1, _2]) } public func Channel_AdminLog_MessageRestricted(_ _0: String, _ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3519]!, self._r[3519]!, [_0, _1, _2]) + return formatWithArgumentRanges(self._s[3521]!, self._r[3521]!, [_0, _1, _2]) } - public var PrivacySettings_AutoArchiveTitle: String { return self._s[3520]! } - public var GroupInfo_InviteLink_LinkSection: String { return self._s[3521]! } - public var FastTwoStepSetup_EmailPlaceholder: String { return self._s[3522]! } - public var Wallet_SecureStorageReset_BiometryFaceId: String { return self._s[3523]! } - public var StickerPacksSettings_ArchivedMasks: String { return self._s[3525]! } - public var NewContact_Title: String { return self._s[3528]! } - public var Appearance_ThemeCarouselTintedNight: String { return self._s[3529]! } - public var Notifications_PermissionsKeepDisabled: String { return self._s[3530]! } + public var PrivacySettings_AutoArchiveTitle: String { return self._s[3522]! } + public var GroupInfo_InviteLink_LinkSection: String { return self._s[3523]! } + public var FastTwoStepSetup_EmailPlaceholder: String { return self._s[3524]! } + public var Wallet_SecureStorageReset_BiometryFaceId: String { return self._s[3525]! } + public var StickerPacksSettings_ArchivedMasks: String { return self._s[3527]! } + public var NewContact_Title: String { return self._s[3530]! } + public var Appearance_ThemeCarouselTintedNight: String { return self._s[3531]! } + public var Notifications_PermissionsKeepDisabled: String { return self._s[3532]! } public func Time_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3531]!, self._r[3531]!, [_0]) + return formatWithArgumentRanges(self._s[3533]!, self._r[3533]!, [_0]) } public func AutoNightTheme_LocationHelp(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3532]!, self._r[3532]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3534]!, self._r[3534]!, [_0, _1]) } - public var Chat_SlowmodeTooltipPending: String { return self._s[3533]! } - public var Wallet_WordCheck_TryAgain: String { return self._s[3534]! } - public var CallFeedback_ReasonInterruption: String { return self._s[3536]! } - public var ContactInfo_PhoneLabelHome: String { return self._s[3537]! } - public var Passport_Identity_OneOfTypeDriversLicense: String { return self._s[3538]! } + public var Chat_SlowmodeTooltipPending: String { return self._s[3535]! } + public var Wallet_WordCheck_TryAgain: String { return self._s[3536]! } + public var CallFeedback_ReasonInterruption: String { return self._s[3538]! } + public var ContactInfo_PhoneLabelHome: String { return self._s[3539]! } + public var Passport_Identity_OneOfTypeDriversLicense: String { return self._s[3540]! } public func PUSH_MESSAGE_DOCS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3540]!, self._r[3540]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[3542]!, self._r[3542]!, [_1, "\(_2)"]) } - public var Conversation_MessageEditedLabel: String { return self._s[3541]! } - public var Wallet_Settings_DeleteWalletInfo: String { return self._s[3542]! } - public var SocksProxySetup_PasswordPlaceholder: String { return self._s[3543]! } - public var ChatList_Context_AddToContacts: String { return self._s[3544]! } - public var Passport_Language_is: String { return self._s[3545]! } - public var Notification_PassportValueProofOfIdentity: String { return self._s[3546]! } - public var Wallet_Month_ShortOctober: String { return self._s[3547]! } - public var PhotoEditor_CurvesBlue: String { return self._s[3548]! } + public var Conversation_MessageEditedLabel: String { return self._s[3543]! } + public var Wallet_Settings_DeleteWalletInfo: String { return self._s[3544]! } + public var SocksProxySetup_PasswordPlaceholder: String { return self._s[3545]! } + public var ChatList_Context_AddToContacts: String { return self._s[3546]! } + public var Passport_Language_is: String { return self._s[3547]! } + public var Notification_PassportValueProofOfIdentity: String { return self._s[3548]! } + public var Wallet_Month_ShortOctober: String { return self._s[3549]! } + public var PhotoEditor_CurvesBlue: String { return self._s[3550]! } public func FileSize_MB(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3549]!, self._r[3549]!, [_0]) + return formatWithArgumentRanges(self._s[3551]!, self._r[3551]!, [_0]) } - public var SocksProxySetup_Username: String { return self._s[3550]! } - public var Login_SmsRequestState3: String { return self._s[3551]! } - public var Message_PinnedVideoMessage: String { return self._s[3552]! } - public var SharedMedia_TitleLink: String { return self._s[3553]! } - public var Passport_FieldIdentity: String { return self._s[3554]! } - public var Wallet_Configuration_SourceInfo: String { return self._s[3555]! } + public var SocksProxySetup_Username: String { return self._s[3552]! } + public var Login_SmsRequestState3: String { return self._s[3553]! } + public var Message_PinnedVideoMessage: String { return self._s[3554]! } + public var SharedMedia_TitleLink: String { return self._s[3555]! } + public var Passport_FieldIdentity: String { return self._s[3556]! } + public var Wallet_Configuration_SourceInfo: String { return self._s[3557]! } public func Conversation_EncryptedPlaceholderTitleOutgoing(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3559]!, self._r[3559]!, [_0]) + return formatWithArgumentRanges(self._s[3561]!, self._r[3561]!, [_0]) } - public var DialogList_ProxyConnectionIssuesTooltip: String { return self._s[3562]! } - public var ReportSpam_DeleteThisChat: String { return self._s[3563]! } - public var Checkout_NewCard_CardholderNamePlaceholder: String { return self._s[3564]! } - public var Passport_Identity_DateOfBirth: String { return self._s[3565]! } - public var Call_StatusIncoming: String { return self._s[3566]! } - public var Wallet_TransactionInfo_NoAddress: String { return self._s[3567]! } - public var ChatAdmins_AdminLabel: String { return self._s[3568]! } - public var Wallet_WordCheck_IncorrectHeader: String { return self._s[3569]! } + public var DialogList_ProxyConnectionIssuesTooltip: String { return self._s[3564]! } + public var ReportSpam_DeleteThisChat: String { return self._s[3565]! } + public var Checkout_NewCard_CardholderNamePlaceholder: String { return self._s[3566]! } + public var Passport_Identity_DateOfBirth: String { return self._s[3567]! } + public var Call_StatusIncoming: String { return self._s[3568]! } + public var Wallet_TransactionInfo_NoAddress: String { return self._s[3569]! } + public var ChatAdmins_AdminLabel: String { return self._s[3570]! } + public var Wallet_WordCheck_IncorrectHeader: String { return self._s[3571]! } public func Time_MonthOfYear_m10(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3571]!, self._r[3571]!, [_0]) + return formatWithArgumentRanges(self._s[3573]!, self._r[3573]!, [_0]) } - public var Message_PinnedAnimationMessage: String { return self._s[3572]! } - public var Conversation_ReportSpamAndLeave: String { return self._s[3573]! } - public var Preview_CopyAddress: String { return self._s[3574]! } - public var MediaPlayer_UnknownTrack: String { return self._s[3575]! } - public var Login_CancelSignUpConfirmation: String { return self._s[3576]! } - public var Map_OpenInYandexMaps: String { return self._s[3578]! } + public var Message_PinnedAnimationMessage: String { return self._s[3574]! } + public var Conversation_ReportSpamAndLeave: String { return self._s[3575]! } + public var Preview_CopyAddress: String { return self._s[3576]! } + public var MediaPlayer_UnknownTrack: String { return self._s[3577]! } + public var Login_CancelSignUpConfirmation: String { return self._s[3578]! } + public var Map_OpenInYandexMaps: String { return self._s[3580]! } public func Time_PreciseDate_m11(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3581]!, self._r[3581]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3583]!, self._r[3583]!, [_1, _2, _3]) } - public var GroupRemoved_Remove: String { return self._s[3582]! } - public var ChatListFolder_TitleCreate: String { return self._s[3583]! } + public var GroupRemoved_Remove: String { return self._s[3584]! } + public var ChatListFolder_TitleCreate: String { return self._s[3585]! } public func InstantPage_AuthorAndDateTitle(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3585]!, self._r[3585]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3587]!, self._r[3587]!, [_1, _2]) } - public var Watch_UserInfo_MuteTitle: String { return self._s[3586]! } - public var Group_UpgradeNoticeText2: String { return self._s[3588]! } - public var Stats_GroupGrowthTitle: String { return self._s[3589]! } - public var CreatePoll_CancelConfirmation: String { return self._s[3592]! } - public var Month_GenOctober: String { return self._s[3593]! } - public var Conversation_TitleCommentsEmpty: String { return self._s[3594]! } - public var Settings_Appearance: String { return self._s[3595]! } + public var Watch_UserInfo_MuteTitle: String { return self._s[3588]! } + public var Group_UpgradeNoticeText2: String { return self._s[3590]! } + public var Stats_GroupGrowthTitle: String { return self._s[3591]! } + public var CreatePoll_CancelConfirmation: String { return self._s[3594]! } + public var Month_GenOctober: String { return self._s[3595]! } + public var Conversation_TitleCommentsEmpty: String { return self._s[3596]! } + public var Settings_Appearance: String { return self._s[3597]! } public func Time_MonthOfYear_m6(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3596]!, self._r[3596]!, [_0]) + return formatWithArgumentRanges(self._s[3598]!, self._r[3598]!, [_0]) } - public var Wallet_Completed_Title: String { return self._s[3597]! } - public var UserInfo_AddToExisting: String { return self._s[3598]! } - public var Call_PhoneCallInProgressMessage: String { return self._s[3599]! } - public var Map_HomeAndWorkInfo: String { return self._s[3600]! } - public var Paint_Arrow: String { return self._s[3601]! } - public var CancelResetAccount_Title: String { return self._s[3602]! } - public var NotificationsSound_Circles: String { return self._s[3603]! } - public var Notifications_GroupNotificationsExceptionsHelp: String { return self._s[3604]! } - public var ChatState_Connecting: String { return self._s[3606]! } - public var Profile_MessageLifetime5s: String { return self._s[3607]! } + public var Wallet_Completed_Title: String { return self._s[3599]! } + public var UserInfo_AddToExisting: String { return self._s[3600]! } + public var Call_PhoneCallInProgressMessage: String { return self._s[3601]! } + public var Map_HomeAndWorkInfo: String { return self._s[3602]! } + public var Paint_Arrow: String { return self._s[3603]! } + public var CancelResetAccount_Title: String { return self._s[3604]! } + public var NotificationsSound_Circles: String { return self._s[3605]! } + public var Notifications_GroupNotificationsExceptionsHelp: String { return self._s[3606]! } + public var ChatState_Connecting: String { return self._s[3608]! } + public var Profile_MessageLifetime5s: String { return self._s[3609]! } public func DialogList_AwaitingEncryption(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3608]!, self._r[3608]!, [_0]) + return formatWithArgumentRanges(self._s[3610]!, self._r[3610]!, [_0]) } - public var PrivacyPolicy_AgeVerificationTitle: String { return self._s[3609]! } - public var Channel_Username_CreatePublicLinkHelp: String { return self._s[3610]! } - public var AutoNightTheme_ScheduledTo: String { return self._s[3611]! } - public var Conversation_DefaultRestrictedStickers: String { return self._s[3612]! } - public var TwoStepAuth_ConfirmationTitle: String { return self._s[3613]! } + public var PrivacyPolicy_AgeVerificationTitle: String { return self._s[3611]! } + public var Channel_Username_CreatePublicLinkHelp: String { return self._s[3612]! } + public var AutoNightTheme_ScheduledTo: String { return self._s[3613]! } + public var Conversation_DefaultRestrictedStickers: String { return self._s[3614]! } + public var TwoStepAuth_ConfirmationTitle: String { return self._s[3615]! } public func Chat_UnsendMyMessagesAlertTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3614]!, self._r[3614]!, [_0]) + return formatWithArgumentRanges(self._s[3616]!, self._r[3616]!, [_0]) } - public var Passport_Phone_Help: String { return self._s[3615]! } - public var Privacy_ContactsSync: String { return self._s[3616]! } - public var CheckoutInfo_ReceiverInfoPhone: String { return self._s[3617]! } - public var Channel_AdminLogFilter_EventsLeavingSubscribers: String { return self._s[3618]! } - public var Map_SendMyCurrentLocation: String { return self._s[3619]! } - public var Map_AddressOnMap: String { return self._s[3620]! } + public var Passport_Phone_Help: String { return self._s[3617]! } + public var Privacy_ContactsSync: String { return self._s[3618]! } + public var CheckoutInfo_ReceiverInfoPhone: String { return self._s[3619]! } + public var Channel_AdminLogFilter_EventsLeavingSubscribers: String { return self._s[3620]! } + public var Map_SendMyCurrentLocation: String { return self._s[3621]! } + public var Map_AddressOnMap: String { return self._s[3622]! } public func Wallet_Time_PreciseDate_m2(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3621]!, self._r[3621]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3623]!, self._r[3623]!, [_1, _2, _3]) } - public var DialogList_SearchLabel: String { return self._s[3623]! } - public var Notification_Exceptions_NewException_NotificationHeader: String { return self._s[3624]! } - public var ConversationProfile_UnknownAddMemberError: String { return self._s[3625]! } - public var ChatList_Search_ShowMore: String { return self._s[3626]! } - public var DialogList_EncryptionRejected: String { return self._s[3627]! } - public var Wallet_WordImport_Text: String { return self._s[3628]! } - public var DialogList_DeleteBotConfirmation: String { return self._s[3629]! } - public var Privacy_TopPeersDelete: String { return self._s[3630]! } - public var AttachmentMenu_SendAsFile: String { return self._s[3631]! } - public var ChatList_GenericPsaAlert: String { return self._s[3633]! } - public var SecretTimer_ImageDescription: String { return self._s[3635]! } + public var DialogList_SearchLabel: String { return self._s[3625]! } + public var Notification_Exceptions_NewException_NotificationHeader: String { return self._s[3626]! } + public var ConversationProfile_UnknownAddMemberError: String { return self._s[3627]! } + public var ChatList_Search_ShowMore: String { return self._s[3628]! } + public var DialogList_EncryptionRejected: String { return self._s[3629]! } + public var Wallet_WordImport_Text: String { return self._s[3630]! } + public var DialogList_DeleteBotConfirmation: String { return self._s[3631]! } + public var Privacy_TopPeersDelete: String { return self._s[3632]! } + public var AttachmentMenu_SendAsFile: String { return self._s[3633]! } + public var ChatList_GenericPsaAlert: String { return self._s[3635]! } + public var SecretTimer_ImageDescription: String { return self._s[3637]! } public func Conversation_SetReminder_RemindOn(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3636]!, self._r[3636]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3638]!, self._r[3638]!, [_0, _1]) } - public var ChatSettings_TextSizeUnits: String { return self._s[3637]! } - public var Notification_RenamedGroup: String { return self._s[3638]! } - public var Wallet_Info_RefreshErrorNetworkText: String { return self._s[3639]! } - public var Tour_Title2: String { return self._s[3640]! } - public var Settings_CopyUsername: String { return self._s[3641]! } - public var Compose_NewEncryptedChat: String { return self._s[3642]! } - public var Conversation_CloudStorageInfo_Title: String { return self._s[3643]! } - public var Month_ShortSeptember: String { return self._s[3644]! } - public var AutoDownloadSettings_OnForAll: String { return self._s[3645]! } - public var ChatList_DeleteForEveryoneConfirmationText: String { return self._s[3646]! } - public var Settings_Wallet: String { return self._s[3647]! } - public var Call_StatusConnecting: String { return self._s[3649]! } - public var Privacy_GroupsAndChannels_NeverAllow_Placeholder: String { return self._s[3650]! } - public var Map_ShareLiveLocationHelp: String { return self._s[3651]! } - public var Cache_Files: String { return self._s[3652]! } - public var Notifications_Reset: String { return self._s[3653]! } + public var ChatSettings_TextSizeUnits: String { return self._s[3639]! } + public var Notification_RenamedGroup: String { return self._s[3640]! } + public var Wallet_Info_RefreshErrorNetworkText: String { return self._s[3641]! } + public var Tour_Title2: String { return self._s[3642]! } + public var Settings_CopyUsername: String { return self._s[3643]! } + public var Compose_NewEncryptedChat: String { return self._s[3644]! } + public var Conversation_CloudStorageInfo_Title: String { return self._s[3645]! } + public var Month_ShortSeptember: String { return self._s[3646]! } + public var AutoDownloadSettings_OnForAll: String { return self._s[3647]! } + public var ChatList_DeleteForEveryoneConfirmationText: String { return self._s[3648]! } + public var Settings_Wallet: String { return self._s[3649]! } + public var Call_StatusConnecting: String { return self._s[3651]! } + public var Privacy_GroupsAndChannels_NeverAllow_Placeholder: String { return self._s[3652]! } + public var Map_ShareLiveLocationHelp: String { return self._s[3653]! } + public var Cache_Files: String { return self._s[3654]! } + public var Notifications_Reset: String { return self._s[3655]! } public func Settings_KeepPhoneNumber(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3654]!, self._r[3654]!, [_0]) + return formatWithArgumentRanges(self._s[3656]!, self._r[3656]!, [_0]) } - public var Privacy_GroupsAndChannels_AlwaysAllow_Title: String { return self._s[3655]! } + public var Privacy_GroupsAndChannels_AlwaysAllow_Title: String { return self._s[3657]! } public func Conversation_OpenBotLinkLogin(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3656]!, self._r[3656]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3658]!, self._r[3658]!, [_1, _2]) } - public var Notification_CallIncomingShort: String { return self._s[3657]! } - public var UserInfo_BotPrivacy: String { return self._s[3659]! } - public var Appearance_BubbleCorners_Apply: String { return self._s[3660]! } - public var WebSearch_RecentClearConfirmation: String { return self._s[3661]! } - public var Conversation_ContextMenuLookUp: String { return self._s[3662]! } - public var Calls_RatingTitle: String { return self._s[3663]! } - public var SecretImage_Title: String { return self._s[3664]! } - public var Weekday_Monday: String { return self._s[3665]! } + public var Notification_CallIncomingShort: String { return self._s[3659]! } + public var UserInfo_BotPrivacy: String { return self._s[3661]! } + public var Appearance_BubbleCorners_Apply: String { return self._s[3662]! } + public var WebSearch_RecentClearConfirmation: String { return self._s[3663]! } + public var Conversation_ContextMenuLookUp: String { return self._s[3664]! } + public var Calls_RatingTitle: String { return self._s[3665]! } + public var SecretImage_Title: String { return self._s[3666]! } + public var Weekday_Monday: String { return self._s[3667]! } public func Passport_PrivacyPolicy(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3667]!, self._r[3667]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3669]!, self._r[3669]!, [_1, _2]) } - public var KeyCommand_JumpToPreviousChat: String { return self._s[3668]! } + public var KeyCommand_JumpToPreviousChat: String { return self._s[3670]! } public func Wallet_Updated_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3669]!, self._r[3669]!, [_0]) + return formatWithArgumentRanges(self._s[3671]!, self._r[3671]!, [_0]) } public func DialogList_SearchSubtitleFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3670]!, self._r[3670]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3672]!, self._r[3672]!, [_1, _2]) } - public var Stats_GroupMembers: String { return self._s[3671]! } - public var Camera_Retake: String { return self._s[3672]! } - public var Conversation_SearchPlaceholder: String { return self._s[3674]! } + public var Stats_GroupMembers: String { return self._s[3673]! } + public var Camera_Retake: String { return self._s[3674]! } + public var Conversation_SearchPlaceholder: String { return self._s[3676]! } public func Passport_Identity_NativeNameGenericHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3675]!, self._r[3675]!, [_0]) + return formatWithArgumentRanges(self._s[3677]!, self._r[3677]!, [_0]) } - public var Channel_DiscussionGroup_Info: String { return self._s[3676]! } - public var SocksProxySetup_Hostname: String { return self._s[3677]! } - public var Wallet_Send_OwnAddressAlertProceed: String { return self._s[3678]! } - public var PrivacyLastSeenSettings_EmpryUsersPlaceholder: String { return self._s[3679]! } - public var Privacy_DeleteDrafts: String { return self._s[3680]! } + public var Channel_DiscussionGroup_Info: String { return self._s[3678]! } + public var SocksProxySetup_Hostname: String { return self._s[3679]! } + public var Wallet_Send_OwnAddressAlertProceed: String { return self._s[3680]! } + public var PrivacyLastSeenSettings_EmpryUsersPlaceholder: String { return self._s[3681]! } + public var Privacy_DeleteDrafts: String { return self._s[3682]! } public func Checkout_LiabilityAlert(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3681]!, self._r[3681]!, [_1, _1, _1, _2]) + return formatWithArgumentRanges(self._s[3683]!, self._r[3683]!, [_1, _1, _1, _2]) } - public var Wallet_RestoreFailed_Text: String { return self._s[3682]! } - public var Wallet_Settings_DeleteWallet: String { return self._s[3683]! } - public var Login_CancelPhoneVerification: String { return self._s[3684]! } - public var TwoStepAuth_ResetAccountHelp: String { return self._s[3686]! } + public var Wallet_RestoreFailed_Text: String { return self._s[3684]! } + public var Wallet_Settings_DeleteWallet: String { return self._s[3685]! } + public var Login_CancelPhoneVerification: String { return self._s[3686]! } + public var TwoStepAuth_ResetAccountHelp: String { return self._s[3688]! } public func SocksProxySetup_ProxyStatusPing(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3687]!, self._r[3687]!, [_0]) + return formatWithArgumentRanges(self._s[3689]!, self._r[3689]!, [_0]) } - public var TwoStepAuth_EmailSent: String { return self._s[3688]! } - public var Cache_Indexing: String { return self._s[3689]! } - public var Notifications_ExceptionsNone: String { return self._s[3690]! } - public var MessagePoll_LabelQuiz: String { return self._s[3691]! } - public var Call_EncryptionKey_Title: String { return self._s[3692]! } - public var Common_Yes: String { return self._s[3693]! } - public var Channel_ErrorAddBlocked: String { return self._s[3694]! } - public var Month_GenJanuary: String { return self._s[3695]! } - public var Checkout_NewCard_Title: String { return self._s[3696]! } - public var Wallet_TransactionInfo_OtherFeeHeader: String { return self._s[3697]! } + public var TwoStepAuth_EmailSent: String { return self._s[3690]! } + public var Cache_Indexing: String { return self._s[3691]! } + public var Notifications_ExceptionsNone: String { return self._s[3692]! } + public var MessagePoll_LabelQuiz: String { return self._s[3693]! } + public var Call_EncryptionKey_Title: String { return self._s[3694]! } + public var Common_Yes: String { return self._s[3695]! } + public var Channel_ErrorAddBlocked: String { return self._s[3696]! } + public var Month_GenJanuary: String { return self._s[3697]! } + public var Checkout_NewCard_Title: String { return self._s[3698]! } + public var Wallet_TransactionInfo_OtherFeeHeader: String { return self._s[3699]! } public func TwoStepAuth_EnterPasswordHint(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3698]!, self._r[3698]!, [_0]) + return formatWithArgumentRanges(self._s[3700]!, self._r[3700]!, [_0]) } - public var PasscodeSettings_AutoLock_IfAwayFor_1hour: String { return self._s[3700]! } - public var Conversation_SendDice: String { return self._s[3701]! } - public var Conversation_InputTextPlaceholderReply: String { return self._s[3702]! } + public var PasscodeSettings_AutoLock_IfAwayFor_1hour: String { return self._s[3702]! } + public var Conversation_SendDice: String { return self._s[3703]! } + public var Conversation_InputTextPlaceholderReply: String { return self._s[3704]! } public func ChatSettings_AutoDownloadSettings_TypeVideo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3703]!, self._r[3703]!, [_0]) + return formatWithArgumentRanges(self._s[3705]!, self._r[3705]!, [_0]) } public func VoiceOver_Chat_VideoFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3704]!, self._r[3704]!, [_0]) + return formatWithArgumentRanges(self._s[3706]!, self._r[3706]!, [_0]) } - public var Weekday_Wednesday: String { return self._s[3705]! } - public var ReportPeer_ReasonOther_Send: String { return self._s[3706]! } - public var PasscodeSettings_EncryptDataHelp: String { return self._s[3707]! } - public var PrivacyLastSeenSettings_CustomShareSettingsHelp: String { return self._s[3708]! } - public var OldChannels_NoticeTitle: String { return self._s[3709]! } - public var TwoStepAuth_ChangeEmail: String { return self._s[3710]! } - public var PasscodeSettings_PasscodeOptions: String { return self._s[3711]! } - public var InfoPlist_NSPhotoLibraryUsageDescription: String { return self._s[3712]! } - public var Passport_Address_AddUtilityBill: String { return self._s[3713]! } + public var Weekday_Wednesday: String { return self._s[3707]! } + public var ReportPeer_ReasonOther_Send: String { return self._s[3708]! } + public var PasscodeSettings_EncryptDataHelp: String { return self._s[3709]! } + public var PrivacyLastSeenSettings_CustomShareSettingsHelp: String { return self._s[3710]! } + public var OldChannels_NoticeTitle: String { return self._s[3711]! } + public var TwoStepAuth_ChangeEmail: String { return self._s[3712]! } + public var PasscodeSettings_PasscodeOptions: String { return self._s[3713]! } + public var InfoPlist_NSPhotoLibraryUsageDescription: String { return self._s[3714]! } + public var Passport_Address_AddUtilityBill: String { return self._s[3715]! } public func Time_PreciseDate_m5(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3715]!, self._r[3715]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3717]!, self._r[3717]!, [_1, _2, _3]) } - public var TwoFactorSetup_EmailVerification_ResendAction: String { return self._s[3717]! } - public var Stats_GroupTopAdminsTitle: String { return self._s[3718]! } - public var Paint_Regular: String { return self._s[3719]! } - public var Message_Contact: String { return self._s[3720]! } - public var NetworkUsageSettings_MediaVideoDataSection: String { return self._s[3721]! } - public var VoiceOver_Chat_YourPhoto: String { return self._s[3722]! } - public var Notification_Mute1hMin: String { return self._s[3723]! } + public var TwoFactorSetup_EmailVerification_ResendAction: String { return self._s[3719]! } + public var Stats_GroupTopAdminsTitle: String { return self._s[3720]! } + public var Paint_Regular: String { return self._s[3721]! } + public var Message_Contact: String { return self._s[3722]! } + public var NetworkUsageSettings_MediaVideoDataSection: String { return self._s[3723]! } + public var VoiceOver_Chat_YourPhoto: String { return self._s[3724]! } + public var Notification_Mute1hMin: String { return self._s[3725]! } public func Login_BannedPhoneSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3724]!, self._r[3724]!, [_0]) + return formatWithArgumentRanges(self._s[3726]!, self._r[3726]!, [_0]) } - public var Profile_MessageLifetime1h: String { return self._s[3725]! } - public var TwoStepAuth_GenericHelp: String { return self._s[3726]! } - public var TextFormat_Monospace: String { return self._s[3727]! } - public var VoiceOver_Media_PlaybackRateChange: String { return self._s[3729]! } - public var Conversation_DeleteMessagesForMe: String { return self._s[3730]! } - public var ChatList_DeleteChat: String { return self._s[3731]! } - public var Channel_OwnershipTransfer_EnterPasswordText: String { return self._s[3734]! } + public var Profile_MessageLifetime1h: String { return self._s[3727]! } + public var TwoStepAuth_GenericHelp: String { return self._s[3728]! } + public var TextFormat_Monospace: String { return self._s[3729]! } + public var VoiceOver_Media_PlaybackRateChange: String { return self._s[3731]! } + public var Conversation_DeleteMessagesForMe: String { return self._s[3732]! } + public var ChatList_DeleteChat: String { return self._s[3733]! } + public var Channel_OwnershipTransfer_EnterPasswordText: String { return self._s[3736]! } public func Settings_ApplyProxyAlertCredentials(_ _1: String, _ _2: String, _ _3: String, _ _4: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3735]!, self._r[3735]!, [_1, _2, _3, _4]) + return formatWithArgumentRanges(self._s[3737]!, self._r[3737]!, [_1, _2, _3, _4]) } - public var Login_CancelPhoneVerificationStop: String { return self._s[3736]! } - public var Appearance_ThemePreview_ChatList_4_Name: String { return self._s[3737]! } - public var MediaPicker_MomentsDateRangeSameMonthYearFormat: String { return self._s[3738]! } - public var Wallet_Settings_Configuration: String { return self._s[3739]! } - public var Notifications_Badge_IncludeChannels: String { return self._s[3740]! } + public var Login_CancelPhoneVerificationStop: String { return self._s[3738]! } + public var Appearance_ThemePreview_ChatList_4_Name: String { return self._s[3739]! } + public var MediaPicker_MomentsDateRangeSameMonthYearFormat: String { return self._s[3740]! } + public var Wallet_Settings_Configuration: String { return self._s[3741]! } + public var Notifications_Badge_IncludeChannels: String { return self._s[3742]! } public func Channel_AdminLog_MessageToggleInvitesOn(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3741]!, self._r[3741]!, [_0]) + return formatWithArgumentRanges(self._s[3743]!, self._r[3743]!, [_0]) } - public var Wallet_Sent_ViewWallet: String { return self._s[3742]! } - public var StickerPack_ViewPack: String { return self._s[3745]! } - public var FastTwoStepSetup_PasswordConfirmationPlaceholder: String { return self._s[3747]! } - public var EditTheme_Expand_Preview_IncomingText: String { return self._s[3748]! } - public var Notifications_Title: String { return self._s[3749]! } - public var Wallet_WordImport_Continue: String { return self._s[3750]! } - public var GroupInfo_PublicLink: String { return self._s[3751]! } - public var Conversation_InputTextPlaceholderComment: String { return self._s[3752]! } - public var VoiceOver_DiscardPreparedContent: String { return self._s[3753]! } - public var Conversation_Moderate_Ban: String { return self._s[3757]! } + public var Wallet_Sent_ViewWallet: String { return self._s[3744]! } + public var StickerPack_ViewPack: String { return self._s[3747]! } + public var FastTwoStepSetup_PasswordConfirmationPlaceholder: String { return self._s[3749]! } + public var EditTheme_Expand_Preview_IncomingText: String { return self._s[3750]! } + public var Notifications_Title: String { return self._s[3751]! } + public var Wallet_WordImport_Continue: String { return self._s[3752]! } + public var GroupInfo_PublicLink: String { return self._s[3753]! } + public var Conversation_InputTextPlaceholderComment: String { return self._s[3754]! } + public var VoiceOver_DiscardPreparedContent: String { return self._s[3755]! } + public var Conversation_Moderate_Ban: String { return self._s[3759]! } public func Activity_RemindAboutGroup(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3758]!, self._r[3758]!, [_0]) + return formatWithArgumentRanges(self._s[3760]!, self._r[3760]!, [_0]) } - public var TextFormat_Underline: String { return self._s[3759]! } + public var TextFormat_Underline: String { return self._s[3761]! } public func DownloadingStatus(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3760]!, self._r[3760]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3762]!, self._r[3762]!, [_0, _1]) } public func PUSH_PINNED_ROUND(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3761]!, self._r[3761]!, [_1]) + return formatWithArgumentRanges(self._s[3763]!, self._r[3763]!, [_1]) } - public var PollResults_Collapse: String { return self._s[3763]! } - public var Contacts_GlobalSearch: String { return self._s[3764]! } + public var PollResults_Collapse: String { return self._s[3765]! } + public var Contacts_GlobalSearch: String { return self._s[3766]! } public func Conversation_EncryptionWaiting(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3765]!, self._r[3765]!, [_0]) + return formatWithArgumentRanges(self._s[3767]!, self._r[3767]!, [_0]) } - public var Channel_Management_LabelEditor: String { return self._s[3766]! } - public var SettingsSearch_Synonyms_Stickers_FeaturedPacks: String { return self._s[3768]! } - public var Conversation_Theme: String { return self._s[3769]! } + public var Channel_Management_LabelEditor: String { return self._s[3768]! } + public var SettingsSearch_Synonyms_Stickers_FeaturedPacks: String { return self._s[3770]! } + public var Conversation_Theme: String { return self._s[3771]! } public func PUSH_CHANNEL_MESSAGE_DOCS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3770]!, self._r[3770]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[3772]!, self._r[3772]!, [_1, "\(_2)"]) } - public var Conversation_LinkDialogSave: String { return self._s[3771]! } - public var EnterPasscode_TouchId: String { return self._s[3772]! } - public var Stats_MessageOverview: String { return self._s[3773]! } - public var Privacy_Calls_P2PAlways: String { return self._s[3775]! } - public var Message_Sticker: String { return self._s[3776]! } - public var Conversation_Mute: String { return self._s[3778]! } - public var ContactInfo_Title: String { return self._s[3779]! } + public var Conversation_LinkDialogSave: String { return self._s[3773]! } + public var EnterPasscode_TouchId: String { return self._s[3774]! } + public var Stats_MessageOverview: String { return self._s[3775]! } + public var Privacy_Calls_P2PAlways: String { return self._s[3777]! } + public var Message_Sticker: String { return self._s[3778]! } + public var Conversation_Mute: String { return self._s[3780]! } + public var ContactInfo_Title: String { return self._s[3781]! } public func PUSH_CHANNEL_MESSAGE_CONTACT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3780]!, self._r[3780]!, [_1]) + return formatWithArgumentRanges(self._s[3782]!, self._r[3782]!, [_1]) } - public var Channel_Setup_TypeHeader: String { return self._s[3781]! } - public var AuthSessions_LogOut: String { return self._s[3782]! } - public var Wallet_WordCheck_ViewWords: String { return self._s[3783]! } - public var ChatSettings_AutoDownloadReset: String { return self._s[3784]! } - public var ChatListFolderSettings_NewFolder: String { return self._s[3786]! } - public var Appearance_ThemePreview_ChatList_3_AuthorName: String { return self._s[3787]! } - public var CreatePoll_Title: String { return self._s[3788]! } - public var EditTheme_EditTitle: String { return self._s[3789]! } - public var ChatListFolderSettings_RecommendedFoldersSection: String { return self._s[3790]! } - public var TwoStepAuth_SetPassword: String { return self._s[3791]! } - public var Wallet_Words_Done: String { return self._s[3792]! } + public var Channel_Setup_TypeHeader: String { return self._s[3783]! } + public var AuthSessions_LogOut: String { return self._s[3784]! } + public var Wallet_WordCheck_ViewWords: String { return self._s[3785]! } + public var ChatSettings_AutoDownloadReset: String { return self._s[3786]! } + public var ChatListFolderSettings_NewFolder: String { return self._s[3788]! } + public var Appearance_ThemePreview_ChatList_3_AuthorName: String { return self._s[3789]! } + public var CreatePoll_Title: String { return self._s[3790]! } + public var EditTheme_EditTitle: String { return self._s[3791]! } + public var ChatListFolderSettings_RecommendedFoldersSection: String { return self._s[3792]! } + public var TwoStepAuth_SetPassword: String { return self._s[3793]! } + public var Wallet_Words_Done: String { return self._s[3794]! } public func Login_InvalidPhoneEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3793]!, self._r[3793]!, [_0]) + return formatWithArgumentRanges(self._s[3795]!, self._r[3795]!, [_0]) } - public var BlockedUsers_Info: String { return self._s[3794]! } - public var AuthSessions_Sessions: String { return self._s[3795]! } - public var Group_EditAdmin_RankTitle: String { return self._s[3796]! } + public var BlockedUsers_Info: String { return self._s[3796]! } + public var AuthSessions_Sessions: String { return self._s[3797]! } + public var Group_EditAdmin_RankTitle: String { return self._s[3798]! } public func Wallet_Time_PreciseDate_m11(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3797]!, self._r[3797]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3799]!, self._r[3799]!, [_1, _2, _3]) } - public var Common_ActionNotAllowedError: String { return self._s[3798]! } - public var WebPreview_GettingLinkInfo: String { return self._s[3799]! } - public var Appearance_AppIconFilledX: String { return self._s[3800]! } - public var Wallet_TransactionInfo_StorageFeeInfo: String { return self._s[3801]! } - public var Passport_Email_EmailPlaceholder: String { return self._s[3802]! } - public var FeaturedStickers_OtherSection: String { return self._s[3803]! } - public var EditTheme_Edit_Preview_OutgoingText: String { return self._s[3804]! } - public var Profile_Username: String { return self._s[3805]! } - public var Appearance_RemoveTheme: String { return self._s[3806]! } - public var TwoStepAuth_SetupPasswordConfirmPassword: String { return self._s[3807]! } - public var Message_PinnedStickerMessage: String { return self._s[3808]! } - public var AccessDenied_VideoMicrophone: String { return self._s[3809]! } - public var WallpaperPreview_CustomColorBottomText: String { return self._s[3810]! } - public var Passport_Address_RegionPlaceholder: String { return self._s[3811]! } - public var SettingsSearch_Synonyms_Data_Storage_Title: String { return self._s[3812]! } - public var TwoStepAuth_Title: String { return self._s[3813]! } - public var Checkout_WebConfirmation_Title: String { return self._s[3814]! } - public var AutoDownloadSettings_VoiceMessagesInfo: String { return self._s[3815]! } - public var ChatListFolder_CategoryGroups: String { return self._s[3817]! } - public var Stats_GroupTopInviter_Promote: String { return self._s[3818]! } - public var Month_GenJuly: String { return self._s[3819]! } - public var Passport_Identity_Gender: String { return self._s[3820]! } - public var Channel_DiscussionGroup_UnlinkGroup: String { return self._s[3821]! } - public var Notification_Exceptions_DeleteAll: String { return self._s[3822]! } + public var Common_ActionNotAllowedError: String { return self._s[3800]! } + public var WebPreview_GettingLinkInfo: String { return self._s[3801]! } + public var Appearance_AppIconFilledX: String { return self._s[3802]! } + public var Wallet_TransactionInfo_StorageFeeInfo: String { return self._s[3803]! } + public var Passport_Email_EmailPlaceholder: String { return self._s[3804]! } + public var FeaturedStickers_OtherSection: String { return self._s[3805]! } + public var EditTheme_Edit_Preview_OutgoingText: String { return self._s[3806]! } + public var Profile_Username: String { return self._s[3807]! } + public var Appearance_RemoveTheme: String { return self._s[3808]! } + public var TwoStepAuth_SetupPasswordConfirmPassword: String { return self._s[3809]! } + public var Message_PinnedStickerMessage: String { return self._s[3810]! } + public var AccessDenied_VideoMicrophone: String { return self._s[3811]! } + public var WallpaperPreview_CustomColorBottomText: String { return self._s[3812]! } + public var Passport_Address_RegionPlaceholder: String { return self._s[3813]! } + public var SettingsSearch_Synonyms_Data_Storage_Title: String { return self._s[3814]! } + public var TwoStepAuth_Title: String { return self._s[3815]! } + public var Checkout_WebConfirmation_Title: String { return self._s[3816]! } + public var AutoDownloadSettings_VoiceMessagesInfo: String { return self._s[3817]! } + public var ChatListFolder_CategoryGroups: String { return self._s[3819]! } + public var Stats_GroupTopInviter_Promote: String { return self._s[3820]! } + public var Month_GenJuly: String { return self._s[3821]! } + public var Passport_Identity_Gender: String { return self._s[3822]! } + public var Channel_DiscussionGroup_UnlinkGroup: String { return self._s[3823]! } + public var Notification_Exceptions_DeleteAll: String { return self._s[3824]! } public func Conversation_FileHowToText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3823]!, self._r[3823]!, [_0]) + return formatWithArgumentRanges(self._s[3825]!, self._r[3825]!, [_0]) } public func Channel_AdminLog_MessageAdmin(_ _0: String, _ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3824]!, self._r[3824]!, [_0, _1, _2]) + return formatWithArgumentRanges(self._s[3826]!, self._r[3826]!, [_0, _1, _2]) } - public var Login_CodeSentSms: String { return self._s[3825]! } + public var Login_CodeSentSms: String { return self._s[3827]! } public func VoiceOver_Chat_ReplyFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3827]!, self._r[3827]!, [_0]) + return formatWithArgumentRanges(self._s[3829]!, self._r[3829]!, [_0]) } - public var Login_CallRequestState2: String { return self._s[3828]! } - public var Channel_DiscussionGroup_Header: String { return self._s[3829]! } + public var Login_CallRequestState2: String { return self._s[3830]! } + public var Channel_DiscussionGroup_Header: String { return self._s[3831]! } public func Channel_AdminLog_MessageToggleInvitesOff(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3830]!, self._r[3830]!, [_0]) + return formatWithArgumentRanges(self._s[3832]!, self._r[3832]!, [_0]) } - public var Passport_Language_ms: String { return self._s[3831]! } - public var PeopleNearby_MakeInvisible: String { return self._s[3833]! } - public var ChatList_Search_FilterVoice: String { return self._s[3835]! } - public var Camera_TapAndHoldForVideo: String { return self._s[3837]! } - public var Permissions_NotificationsAllowInSettings_v0: String { return self._s[3838]! } + public var Passport_Language_ms: String { return self._s[3833]! } + public var PeopleNearby_MakeInvisible: String { return self._s[3835]! } + public var ChatList_Search_FilterVoice: String { return self._s[3837]! } + public var Camera_TapAndHoldForVideo: String { return self._s[3839]! } + public var Permissions_NotificationsAllowInSettings_v0: String { return self._s[3840]! } public func Notification_LeftChannel(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3839]!, self._r[3839]!, [_0]) + return formatWithArgumentRanges(self._s[3841]!, self._r[3841]!, [_0]) } public func Wallet_Time_PreciseDate_m9(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3840]!, self._r[3840]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3842]!, self._r[3842]!, [_1, _2, _3]) } - public var Wallet_Info_TransactionTo: String { return self._s[3841]! } - public var Map_Locating: String { return self._s[3842]! } + public var Wallet_Info_TransactionTo: String { return self._s[3843]! } + public var Map_Locating: String { return self._s[3844]! } public func Checkout_SavePasswordTimeout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3844]!, self._r[3844]!, [_0]) + return formatWithArgumentRanges(self._s[3846]!, self._r[3846]!, [_0]) } - public var Passport_Identity_TypeInternalPassport: String { return self._s[3846]! } - public var Appearance_ThemePreview_Chat_4_Text: String { return self._s[3847]! } - public var SettingsSearch_Synonyms_EditProfile_Username: String { return self._s[3848]! } - public var Stickers_Installed: String { return self._s[3849]! } - public var Notifications_PermissionsAllowInSettings: String { return self._s[3850]! } - public var StickerPackActionInfo_RemovedTitle: String { return self._s[3851]! } - public var CallSettings_Never: String { return self._s[3853]! } - public var Wallet_AccessDenied_Camera: String { return self._s[3854]! } - public var Channel_Setup_TypePublicHelp: String { return self._s[3855]! } + public var Passport_Identity_TypeInternalPassport: String { return self._s[3848]! } + public var Appearance_ThemePreview_Chat_4_Text: String { return self._s[3849]! } + public var SettingsSearch_Synonyms_EditProfile_Username: String { return self._s[3850]! } + public var Stickers_Installed: String { return self._s[3851]! } + public var Notifications_PermissionsAllowInSettings: String { return self._s[3852]! } + public var StickerPackActionInfo_RemovedTitle: String { return self._s[3853]! } + public var CallSettings_Never: String { return self._s[3855]! } + public var Wallet_AccessDenied_Camera: String { return self._s[3856]! } + public var Channel_Setup_TypePublicHelp: String { return self._s[3857]! } public func ChatList_DeleteForEveryone(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3857]!, self._r[3857]!, [_0]) + return formatWithArgumentRanges(self._s[3859]!, self._r[3859]!, [_0]) } - public var Message_Game: String { return self._s[3858]! } - public var Call_Message: String { return self._s[3859]! } + public var Message_Game: String { return self._s[3860]! } + public var Call_Message: String { return self._s[3861]! } public func PUSH_CHANNEL_MESSAGE_VIDEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3860]!, self._r[3860]!, [_1]) + return formatWithArgumentRanges(self._s[3862]!, self._r[3862]!, [_1]) } - public var ChannelIntro_Text: String { return self._s[3861]! } - public var StickerPack_Send: String { return self._s[3862]! } - public var Share_AuthDescription: String { return self._s[3863]! } - public var PasscodeSettings_AutoLock_IfAwayFor_5minutes: String { return self._s[3864]! } - public var CallFeedback_WhatWentWrong: String { return self._s[3865]! } - public var Common_Create: String { return self._s[3868]! } - public var Passport_Language_hy: String { return self._s[3869]! } - public var CreatePoll_Explanation: String { return self._s[3870]! } - public var GroupPermission_AddMembersNotAvailable: String { return self._s[3871]! } - public var Undo_ChatClearedForBothSides: String { return self._s[3872]! } - public var DialogList_NoMessagesTitle: String { return self._s[3873]! } - public var GroupInfo_Title: String { return self._s[3875]! } - public var Channel_AdminLog_CanBanUsers: String { return self._s[3876]! } - public var PhoneNumberHelp_Help: String { return self._s[3877]! } - public var TwoStepAuth_AdditionalPassword: String { return self._s[3878]! } - public var Settings_Logout: String { return self._s[3879]! } - public var Privacy_PaymentsTitle: String { return self._s[3880]! } - public var StickerPacksSettings_StickerPacksSection: String { return self._s[3881]! } - public var Tour_Text6: String { return self._s[3882]! } - public var Channel_Username_Help: String { return self._s[3884]! } - public var Wallet_Info_RefreshErrorTitle: String { return self._s[3885]! } - public var VoiceOver_Chat_RecordModeVoiceMessageInfo: String { return self._s[3886]! } - public var AttachmentMenu_Poll: String { return self._s[3887]! } - public var EditTheme_Create_Preview_IncomingReplyName: String { return self._s[3888]! } - public var Conversation_ReportSpamChannelConfirmation: String { return self._s[3889]! } - public var Passport_DeletePassport: String { return self._s[3890]! } - public var Login_Code: String { return self._s[3891]! } - public var Notification_SecretChatScreenshot: String { return self._s[3892]! } - public var Login_CodeFloodError: String { return self._s[3893]! } + public var ChannelIntro_Text: String { return self._s[3863]! } + public var StickerPack_Send: String { return self._s[3864]! } + public var Share_AuthDescription: String { return self._s[3865]! } + public var PasscodeSettings_AutoLock_IfAwayFor_5minutes: String { return self._s[3866]! } + public var CallFeedback_WhatWentWrong: String { return self._s[3867]! } + public var Common_Create: String { return self._s[3870]! } + public var Passport_Language_hy: String { return self._s[3871]! } + public var CreatePoll_Explanation: String { return self._s[3872]! } + public var GroupPermission_AddMembersNotAvailable: String { return self._s[3873]! } + public var Undo_ChatClearedForBothSides: String { return self._s[3874]! } + public var DialogList_NoMessagesTitle: String { return self._s[3875]! } + public var GroupInfo_Title: String { return self._s[3877]! } + public var Channel_AdminLog_CanBanUsers: String { return self._s[3878]! } + public var PhoneNumberHelp_Help: String { return self._s[3879]! } + public var TwoStepAuth_AdditionalPassword: String { return self._s[3880]! } + public var Settings_Logout: String { return self._s[3881]! } + public var Privacy_PaymentsTitle: String { return self._s[3882]! } + public var StickerPacksSettings_StickerPacksSection: String { return self._s[3883]! } + public var Tour_Text6: String { return self._s[3884]! } + public var Channel_Username_Help: String { return self._s[3886]! } + public var Wallet_Info_RefreshErrorTitle: String { return self._s[3887]! } + public var VoiceOver_Chat_RecordModeVoiceMessageInfo: String { return self._s[3888]! } + public var AttachmentMenu_Poll: String { return self._s[3889]! } + public var EditTheme_Create_Preview_IncomingReplyName: String { return self._s[3890]! } + public var Conversation_ReportSpamChannelConfirmation: String { return self._s[3891]! } + public var Passport_DeletePassport: String { return self._s[3892]! } + public var Login_Code: String { return self._s[3893]! } + public var Notification_SecretChatScreenshot: String { return self._s[3894]! } + public var Login_CodeFloodError: String { return self._s[3895]! } public func Notification_PinnedAnimationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3894]!, self._r[3894]!, [_0]) + return formatWithArgumentRanges(self._s[3896]!, self._r[3896]!, [_0]) } public func Channel_Username_UsernameIsAvailable(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3895]!, self._r[3895]!, [_0]) + return formatWithArgumentRanges(self._s[3897]!, self._r[3897]!, [_0]) } - public var Watch_Stickers_Recents: String { return self._s[3896]! } - public var Generic_ErrorMoreInfo: String { return self._s[3897]! } + public var Watch_Stickers_Recents: String { return self._s[3898]! } + public var Generic_ErrorMoreInfo: String { return self._s[3899]! } public func Call_AccountIsLoggedOnCurrentDevice(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3898]!, self._r[3898]!, [_0]) + return formatWithArgumentRanges(self._s[3900]!, self._r[3900]!, [_0]) } - public var AutoDownloadSettings_DataUsage: String { return self._s[3899]! } - public var Conversation_ViewTheme: String { return self._s[3900]! } - public var Contacts_InviteSearchLabel: String { return self._s[3901]! } - public var Settings_CancelUpload: String { return self._s[3903]! } - public var Settings_AppLanguage_Unofficial: String { return self._s[3904]! } + public var AutoDownloadSettings_DataUsage: String { return self._s[3901]! } + public var Conversation_ViewTheme: String { return self._s[3902]! } + public var Contacts_InviteSearchLabel: String { return self._s[3903]! } + public var Settings_CancelUpload: String { return self._s[3905]! } + public var Settings_AppLanguage_Unofficial: String { return self._s[3906]! } public func ChatList_ClearChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3905]!, self._r[3905]!, [_0]) + return formatWithArgumentRanges(self._s[3907]!, self._r[3907]!, [_0]) } - public var ChatList_AddFolder: String { return self._s[3906]! } - public var Conversation_Location: String { return self._s[3908]! } - public var Appearance_BubbleCorners_AdjustAdjacent: String { return self._s[3909]! } - public var DialogList_AdLabel: String { return self._s[3910]! } + public var ChatList_AddFolder: String { return self._s[3908]! } + public var Conversation_Location: String { return self._s[3910]! } + public var Appearance_BubbleCorners_AdjustAdjacent: String { return self._s[3911]! } + public var DialogList_AdLabel: String { return self._s[3912]! } public func Time_TomorrowAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3912]!, self._r[3912]!, [_0]) + return formatWithArgumentRanges(self._s[3914]!, self._r[3914]!, [_0]) } - public var Message_InvoiceLabel: String { return self._s[3913]! } - public var Channel_TooMuchBots: String { return self._s[3914]! } + public var Message_InvoiceLabel: String { return self._s[3915]! } + public var Channel_TooMuchBots: String { return self._s[3916]! } public func Channel_AdminLog_MessageRemovedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3915]!, self._r[3915]!, [_0]) + return formatWithArgumentRanges(self._s[3917]!, self._r[3917]!, [_0]) } - public var Wallet_Month_ShortAugust: String { return self._s[3916]! } - public var Call_IncomingVideoCall: String { return self._s[3917]! } - public var Conversation_LiveLocation: String { return self._s[3918]! } - public var TwoStepAuth_SetupPasswordEnterPasswordChange: String { return self._s[3919]! } - public var Passport_Identity_EditPassport: String { return self._s[3920]! } - public var Permissions_CellularDataTitle_v0: String { return self._s[3922]! } - public var ChatList_Search_NoResultsFitlerVoice: String { return self._s[3923]! } - public var GroupInfo_Permissions_AddException: String { return self._s[3924]! } - public var Channel_AdminLog_CanInviteUsers: String { return self._s[3926]! } - public var Channel_MessageVideoUpdated: String { return self._s[3927]! } - public var GroupInfo_Permissions_EditingDisabled: String { return self._s[3928]! } - public var AccessDenied_Camera: String { return self._s[3931]! } + public var Wallet_Month_ShortAugust: String { return self._s[3918]! } + public var Call_IncomingVideoCall: String { return self._s[3919]! } + public var Conversation_LiveLocation: String { return self._s[3920]! } + public var TwoStepAuth_SetupPasswordEnterPasswordChange: String { return self._s[3921]! } + public var Passport_Identity_EditPassport: String { return self._s[3922]! } + public var Permissions_CellularDataTitle_v0: String { return self._s[3924]! } + public var ChatList_Search_NoResultsFitlerVoice: String { return self._s[3925]! } + public var GroupInfo_Permissions_AddException: String { return self._s[3926]! } + public var Channel_AdminLog_CanInviteUsers: String { return self._s[3928]! } + public var Channel_MessageVideoUpdated: String { return self._s[3929]! } + public var GroupInfo_Permissions_EditingDisabled: String { return self._s[3930]! } + public var AccessDenied_Camera: String { return self._s[3933]! } public func Target_InviteToGroupConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3932]!, self._r[3932]!, [_0]) + return formatWithArgumentRanges(self._s[3934]!, self._r[3934]!, [_0]) } - public var Theme_Context_ChangeColors: String { return self._s[3933]! } - public var PrivacySettings_TwoStepAuth: String { return self._s[3934]! } - public var Privacy_Forwards_PreviewMessageText: String { return self._s[3935]! } - public var Login_CodeExpiredError: String { return self._s[3936]! } - public var State_ConnectingToProxy: String { return self._s[3937]! } - public var TextFormat_Link: String { return self._s[3938]! } - public var Passport_Language_lv: String { return self._s[3939]! } - public var AccessDenied_VoiceMicrophone: String { return self._s[3940]! } - public var WallpaperPreview_SwipeBottomText: String { return self._s[3941]! } - public var ProfilePhoto_SetMainVideo: String { return self._s[3942]! } - public var AutoDownloadSettings_Cellular: String { return self._s[3944]! } - public var ChatSettings_AutoDownloadVoiceMessages: String { return self._s[3945]! } + public var Theme_Context_ChangeColors: String { return self._s[3935]! } + public var PrivacySettings_TwoStepAuth: String { return self._s[3936]! } + public var Privacy_Forwards_PreviewMessageText: String { return self._s[3937]! } + public var Login_CodeExpiredError: String { return self._s[3938]! } + public var State_ConnectingToProxy: String { return self._s[3939]! } + public var TextFormat_Link: String { return self._s[3940]! } + public var Passport_Language_lv: String { return self._s[3941]! } + public var AccessDenied_VoiceMicrophone: String { return self._s[3942]! } + public var WallpaperPreview_SwipeBottomText: String { return self._s[3943]! } + public var ProfilePhoto_SetMainVideo: String { return self._s[3944]! } + public var AutoDownloadSettings_Cellular: String { return self._s[3946]! } + public var ChatSettings_AutoDownloadVoiceMessages: String { return self._s[3947]! } public func Channel_AdminLog_MessageKickedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3946]!, self._r[3946]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3948]!, self._r[3948]!, [_1, _2]) } - public var ChatList_EmptyChatListFilterTitle: String { return self._s[3947]! } - public var Checkout_PayNone: String { return self._s[3948]! } - public var NotificationsSound_Complete: String { return self._s[3950]! } - public var TwoStepAuth_ConfirmEmailCodePlaceholder: String { return self._s[3951]! } - public var AuthSessions_DevicesTitle: String { return self._s[3952]! } + public var ChatList_EmptyChatListFilterTitle: String { return self._s[3949]! } + public var Checkout_PayNone: String { return self._s[3950]! } + public var NotificationsSound_Complete: String { return self._s[3952]! } + public var TwoStepAuth_ConfirmEmailCodePlaceholder: String { return self._s[3953]! } + public var AuthSessions_DevicesTitle: String { return self._s[3954]! } public func DialogList_MultipleTyping(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3953]!, self._r[3953]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3955]!, self._r[3955]!, [_0, _1]) } - public var Message_LiveLocation: String { return self._s[3954]! } - public var Watch_Suggestion_BRB: String { return self._s[3955]! } - public var Channel_BanUser_Title: String { return self._s[3956]! } - public var SettingsSearch_Synonyms_Privacy_Data_Title: String { return self._s[3957]! } - public var Conversation_Dice_u1F3C0: String { return self._s[3958]! } - public var Conversation_ClearSelfHistory: String { return self._s[3959]! } - public var ProfilePhoto_OpenGallery: String { return self._s[3960]! } - public var PrivacySettings_LastSeenTitle: String { return self._s[3961]! } - public var Weekday_Thursday: String { return self._s[3962]! } - public var BroadcastListInfo_AddRecipient: String { return self._s[3963]! } - public var Privacy_ProfilePhoto: String { return self._s[3965]! } - public var StickerPacksSettings_ArchivedPacks_Info: String { return self._s[3966]! } + public var Message_LiveLocation: String { return self._s[3956]! } + public var Watch_Suggestion_BRB: String { return self._s[3957]! } + public var Channel_BanUser_Title: String { return self._s[3958]! } + public var SettingsSearch_Synonyms_Privacy_Data_Title: String { return self._s[3959]! } + public var Conversation_Dice_u1F3C0: String { return self._s[3960]! } + public var Conversation_ClearSelfHistory: String { return self._s[3961]! } + public var ProfilePhoto_OpenGallery: String { return self._s[3962]! } + public var PrivacySettings_LastSeenTitle: String { return self._s[3963]! } + public var Weekday_Thursday: String { return self._s[3964]! } + public var BroadcastListInfo_AddRecipient: String { return self._s[3965]! } + public var Privacy_ProfilePhoto: String { return self._s[3967]! } + public var StickerPacksSettings_ArchivedPacks_Info: String { return self._s[3968]! } public func Channel_AdminLog_MessageChangedUnlinkedGroup(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3967]!, self._r[3967]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3969]!, self._r[3969]!, [_1, _2]) } - public var Message_Audio: String { return self._s[3968]! } - public var Conversation_Info: String { return self._s[3969]! } - public var Cache_Videos: String { return self._s[3970]! } - public var Appearance_ThemePreview_ChatList_6_Text: String { return self._s[3971]! } - public var Channel_ErrorAddTooMuch: String { return self._s[3972]! } + public var Message_Audio: String { return self._s[3970]! } + public var Conversation_Info: String { return self._s[3971]! } + public var Cache_Videos: String { return self._s[3972]! } + public var Appearance_ThemePreview_ChatList_6_Text: String { return self._s[3973]! } + public var Channel_ErrorAddTooMuch: String { return self._s[3974]! } public func ChatList_DeleteSecretChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3973]!, self._r[3973]!, [_0]) + return formatWithArgumentRanges(self._s[3975]!, self._r[3975]!, [_0]) } - public var ChannelMembers_ChannelAdminsTitle: String { return self._s[3975]! } - public var ScheduledMessages_Title: String { return self._s[3977]! } - public var ShareFileTip_Title: String { return self._s[3980]! } - public var Chat_Gifs_TrendingSectionHeader: String { return self._s[3981]! } - public var ChatList_RemoveFolderConfirmation: String { return self._s[3982]! } + public var ChannelMembers_ChannelAdminsTitle: String { return self._s[3977]! } + public var ScheduledMessages_Title: String { return self._s[3979]! } + public var ShareFileTip_Title: String { return self._s[3982]! } + public var Chat_Gifs_TrendingSectionHeader: String { return self._s[3983]! } + public var ChatList_RemoveFolderConfirmation: String { return self._s[3984]! } public func PUSH_CHAT_MESSAGE_GEOLIVE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3983]!, self._r[3983]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3985]!, self._r[3985]!, [_1, _2]) } - public var Conversation_ContextViewStats: String { return self._s[3985]! } - public var Channel_DiscussionGroup_SearchPlaceholder: String { return self._s[3986]! } - public var PasscodeSettings_Title: String { return self._s[3987]! } - public var Channel_AdminLog_SendPolls: String { return self._s[3988]! } - public var LastSeen_ALongTimeAgo: String { return self._s[3989]! } + public var Conversation_ContextViewStats: String { return self._s[3987]! } + public var Channel_DiscussionGroup_SearchPlaceholder: String { return self._s[3988]! } + public var PasscodeSettings_Title: String { return self._s[3989]! } + public var Channel_AdminLog_SendPolls: String { return self._s[3990]! } + public var LastSeen_ALongTimeAgo: String { return self._s[3991]! } public func PUSH_CHANNEL_MESSAGE_GIF(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3990]!, self._r[3990]!, [_1]) + return formatWithArgumentRanges(self._s[3992]!, self._r[3992]!, [_1]) } - public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChannels: String { return self._s[3991]! } - public var CallFeedback_VideoReasonLowQuality: String { return self._s[3992]! } - public var Conversation_PinnedPreviousMessage: String { return self._s[3993]! } - public var SocksProxySetup_AddProxyTitle: String { return self._s[3994]! } - public var Passport_Identity_AddInternalPassport: String { return self._s[3995]! } + public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChannels: String { return self._s[3993]! } + public var CallFeedback_VideoReasonLowQuality: String { return self._s[3994]! } + public var Conversation_PinnedPreviousMessage: String { return self._s[3995]! } + public var SocksProxySetup_AddProxyTitle: String { return self._s[3996]! } + public var Passport_Identity_AddInternalPassport: String { return self._s[3997]! } public func ChatList_RemovedFromFolderTooltip(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3996]!, self._r[3996]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3998]!, self._r[3998]!, [_1, _2]) } public func Conversation_SetReminder_RemindToday(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3997]!, self._r[3997]!, [_0]) + return formatWithArgumentRanges(self._s[3999]!, self._r[3999]!, [_0]) } - public var Passport_Identity_GenderFemale: String { return self._s[3998]! } - public var ConvertToSupergroup_HelpTitle: String { return self._s[4001]! } - public var Location_ProximityNotification_DistanceKM: String { return self._s[4002]! } - public var SharedMedia_TitleAll: String { return self._s[4003]! } - public var Settings_Context_Logout: String { return self._s[4004]! } - public var GroupInfo_SetGroupPhotoDelete: String { return self._s[4006]! } - public var Settings_About_Title: String { return self._s[4007]! } - public var StickerSettings_ContextHide: String { return self._s[4008]! } + public var Passport_Identity_GenderFemale: String { return self._s[4000]! } + public var ConvertToSupergroup_HelpTitle: String { return self._s[4003]! } + public var Location_ProximityNotification_DistanceKM: String { return self._s[4004]! } + public var SharedMedia_TitleAll: String { return self._s[4005]! } + public var Settings_Context_Logout: String { return self._s[4006]! } + public var GroupInfo_SetGroupPhotoDelete: String { return self._s[4008]! } + public var Settings_About_Title: String { return self._s[4009]! } + public var StickerSettings_ContextHide: String { return self._s[4010]! } public func AutoDownloadSettings_UpTo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4009]!, self._r[4009]!, [_0]) + return formatWithArgumentRanges(self._s[4011]!, self._r[4011]!, [_0]) } public func Conversation_LiveLocationYouAndOther(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4010]!, self._r[4010]!, [_0]) + return formatWithArgumentRanges(self._s[4012]!, self._r[4012]!, [_0]) } - public var Common_Cancel: String { return self._s[4012]! } - public var CallFeedback_Title: String { return self._s[4014]! } + public var Common_Cancel: String { return self._s[4014]! } + public var CallFeedback_Title: String { return self._s[4016]! } public func Notification_PinnedContactMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4015]!, self._r[4015]!, [_0]) + return formatWithArgumentRanges(self._s[4017]!, self._r[4017]!, [_0]) } - public var Activity_UploadingVideoMessage: String { return self._s[4016]! } - public var Wallet_TransactionInfo_OtherFeeInfo: String { return self._s[4017]! } - public var MediaPicker_Send: String { return self._s[4018]! } - public var PasscodeSettings_AutoLock_IfAwayFor_1minute: String { return self._s[4019]! } - public var Conversation_LiveLocationYou: String { return self._s[4020]! } - public var Notifications_ExceptionsUnmuted: String { return self._s[4021]! } + public var Activity_UploadingVideoMessage: String { return self._s[4018]! } + public var Wallet_TransactionInfo_OtherFeeInfo: String { return self._s[4019]! } + public var MediaPicker_Send: String { return self._s[4020]! } + public var PasscodeSettings_AutoLock_IfAwayFor_1minute: String { return self._s[4021]! } + public var Conversation_LiveLocationYou: String { return self._s[4022]! } + public var Notifications_ExceptionsUnmuted: String { return self._s[4023]! } public func Channel_AdminLog_MessageGroupPreHistoryHidden(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4022]!, self._r[4022]!, [_0]) + return formatWithArgumentRanges(self._s[4024]!, self._r[4024]!, [_0]) } public func PUSH_CHAT_ADD_YOU(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4023]!, self._r[4023]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4025]!, self._r[4025]!, [_1, _2]) } - public var Conversation_ViewBackground: String { return self._s[4024]! } - public var ChatSettings_PrivateChats: String { return self._s[4027]! } - public var Conversation_ErrorInaccessibleMessage: String { return self._s[4028]! } - public var Wallet_Receive_AmountInfo: String { return self._s[4029]! } - public var Appearance_ThemeNight: String { return self._s[4030]! } - public var Common_Search: String { return self._s[4031]! } - public var TwoStepAuth_ReEnterPasswordTitle: String { return self._s[4032]! } - public var ChangePhoneNumberNumber_Help: String { return self._s[4034]! } - public var Stickers_SuggestAdded: String { return self._s[4035]! } - public var Conversation_DiscardVoiceMessageDescription: String { return self._s[4038]! } - public var NetworkUsageSettings_Cellular: String { return self._s[4039]! } - public var CheckoutInfo_Title: String { return self._s[4040]! } - public var Conversation_ShareBotLocationConfirmationTitle: String { return self._s[4041]! } - public var Channel_BotDoesntSupportGroups: String { return self._s[4042]! } + public var Conversation_ViewBackground: String { return self._s[4026]! } + public var ChatSettings_PrivateChats: String { return self._s[4029]! } + public var Conversation_ErrorInaccessibleMessage: String { return self._s[4030]! } + public var Wallet_Receive_AmountInfo: String { return self._s[4031]! } + public var Appearance_ThemeNight: String { return self._s[4032]! } + public var Common_Search: String { return self._s[4033]! } + public var TwoStepAuth_ReEnterPasswordTitle: String { return self._s[4034]! } + public var ChangePhoneNumberNumber_Help: String { return self._s[4036]! } + public var Stickers_SuggestAdded: String { return self._s[4037]! } + public var Conversation_DiscardVoiceMessageDescription: String { return self._s[4040]! } + public var NetworkUsageSettings_Cellular: String { return self._s[4041]! } + public var CheckoutInfo_Title: String { return self._s[4042]! } + public var Conversation_ShareBotLocationConfirmationTitle: String { return self._s[4043]! } + public var Channel_BotDoesntSupportGroups: String { return self._s[4044]! } public func DialogList_SingleRecordingAudioSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4043]!, self._r[4043]!, [_0]) + return formatWithArgumentRanges(self._s[4045]!, self._r[4045]!, [_0]) } - public var MaskStickerSettings_Info: String { return self._s[4044]! } - public var GroupRemoved_DeleteUser: String { return self._s[4045]! } - public var Contacts_ShareTelegram: String { return self._s[4046]! } - public var Group_UpgradeNoticeText1: String { return self._s[4047]! } + public var MaskStickerSettings_Info: String { return self._s[4046]! } + public var GroupRemoved_DeleteUser: String { return self._s[4047]! } + public var Contacts_ShareTelegram: String { return self._s[4048]! } + public var Group_UpgradeNoticeText1: String { return self._s[4049]! } public func PUSH_PHONE_CALL_REQUEST(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4048]!, self._r[4048]!, [_1]) + return formatWithArgumentRanges(self._s[4050]!, self._r[4050]!, [_1]) } - public var PrivacyLastSeenSettings_Title: String { return self._s[4049]! } - public var SettingsSearch_Synonyms_Support: String { return self._s[4053]! } - public var PhotoEditor_TintTool: String { return self._s[4054]! } - public var Wallet_Receive_InvoiceUrlHeader: String { return self._s[4056]! } - public var GroupPermission_NoSendPolls: String { return self._s[4057]! } - public var NotificationsSound_None: String { return self._s[4058]! } + public var PrivacyLastSeenSettings_Title: String { return self._s[4051]! } + public var SettingsSearch_Synonyms_Support: String { return self._s[4055]! } + public var PhotoEditor_TintTool: String { return self._s[4056]! } + public var Wallet_Receive_InvoiceUrlHeader: String { return self._s[4058]! } + public var GroupPermission_NoSendPolls: String { return self._s[4059]! } + public var NotificationsSound_None: String { return self._s[4060]! } public func LOCAL_CHANNEL_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4059]!, self._r[4059]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[4061]!, self._r[4061]!, [_1, "\(_2)"]) } - public var CheckoutInfo_ShippingInfoCityPlaceholder: String { return self._s[4061]! } - public var ExplicitContent_AlertChannel: String { return self._s[4063]! } - public var Conversation_ClousStorageInfo_Description1: String { return self._s[4064]! } - public var Contacts_SortedByPresence: String { return self._s[4065]! } - public var WallpaperSearch_ColorGray: String { return self._s[4066]! } - public var Channel_AdminLogFilter_EventsNewSubscribers: String { return self._s[4067]! } - public var Conversation_ReportSpam: String { return self._s[4068]! } - public var ChatList_Search_NoResultsFilter: String { return self._s[4071]! } - public var WallpaperSearch_ColorBlack: String { return self._s[4072]! } - public var ArchivedChats_IntroTitle3: String { return self._s[4073]! } - public var Conversation_DefaultRestrictedText: String { return self._s[4074]! } - public var Settings_Devices: String { return self._s[4075]! } - public var Call_AudioRouteSpeaker: String { return self._s[4076]! } - public var GroupInfo_InviteLink_CopyLink: String { return self._s[4077]! } - public var Passport_Address_Country: String { return self._s[4079]! } - public var Cache_MaximumCacheSize: String { return self._s[4080]! } - public var Chat_PanelHidePinnedMessages: String { return self._s[4081]! } - public var Notifications_Badge_IncludePublicGroups: String { return self._s[4082]! } - public var Wallet_Receive_CreateInvoice: String { return self._s[4084]! } - public var ChatSettings_AutoDownloadUsingWiFi: String { return self._s[4085]! } - public var Login_TermsOfServiceLabel: String { return self._s[4086]! } - public var Calls_NoMissedCallsPlacehoder: String { return self._s[4087]! } - public var SocksProxySetup_RequiredCredentials: String { return self._s[4088]! } - public var VoiceOver_MessageContextOpenMessageMenu: String { return self._s[4089]! } - public var AutoNightTheme_ScheduledFrom: String { return self._s[4090]! } - public var ChatSettings_AutoDownloadDocuments: String { return self._s[4091]! } - public var ConvertToSupergroup_Note: String { return self._s[4093]! } - public var Settings_SetNewProfilePhotoOrVideo: String { return self._s[4094]! } - public var PrivacySettings_PasscodeAndTouchId: String { return self._s[4095]! } - public var Common_More: String { return self._s[4096]! } - public var ShareMenu_SelectChats: String { return self._s[4098]! } + public var CheckoutInfo_ShippingInfoCityPlaceholder: String { return self._s[4063]! } + public var ExplicitContent_AlertChannel: String { return self._s[4065]! } + public var Conversation_ClousStorageInfo_Description1: String { return self._s[4066]! } + public var Contacts_SortedByPresence: String { return self._s[4067]! } + public var WallpaperSearch_ColorGray: String { return self._s[4068]! } + public var Channel_AdminLogFilter_EventsNewSubscribers: String { return self._s[4069]! } + public var Conversation_ReportSpam: String { return self._s[4070]! } + public var ChatList_Search_NoResultsFilter: String { return self._s[4073]! } + public var WallpaperSearch_ColorBlack: String { return self._s[4074]! } + public var ArchivedChats_IntroTitle3: String { return self._s[4075]! } + public var Conversation_DefaultRestrictedText: String { return self._s[4076]! } + public var Settings_Devices: String { return self._s[4077]! } + public var Call_AudioRouteSpeaker: String { return self._s[4078]! } + public var GroupInfo_InviteLink_CopyLink: String { return self._s[4079]! } + public var Passport_Address_Country: String { return self._s[4081]! } + public var Cache_MaximumCacheSize: String { return self._s[4082]! } + public var Chat_PanelHidePinnedMessages: String { return self._s[4083]! } + public var Notifications_Badge_IncludePublicGroups: String { return self._s[4084]! } + public var Wallet_Receive_CreateInvoice: String { return self._s[4086]! } + public var ChatSettings_AutoDownloadUsingWiFi: String { return self._s[4087]! } + public var Login_TermsOfServiceLabel: String { return self._s[4088]! } + public var Calls_NoMissedCallsPlacehoder: String { return self._s[4089]! } + public var SocksProxySetup_RequiredCredentials: String { return self._s[4090]! } + public var VoiceOver_MessageContextOpenMessageMenu: String { return self._s[4091]! } + public var AutoNightTheme_ScheduledFrom: String { return self._s[4092]! } + public var ChatSettings_AutoDownloadDocuments: String { return self._s[4093]! } + public var ConvertToSupergroup_Note: String { return self._s[4095]! } + public var Settings_SetNewProfilePhotoOrVideo: String { return self._s[4096]! } + public var PrivacySettings_PasscodeAndTouchId: String { return self._s[4097]! } + public var Common_More: String { return self._s[4098]! } + public var ShareMenu_SelectChats: String { return self._s[4100]! } public func Conversation_ScheduleMessage_SendToday(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4100]!, self._r[4100]!, [_0]) + return formatWithArgumentRanges(self._s[4102]!, self._r[4102]!, [_0]) } public func Channel_AdminLog_MessageRemovedGroupStickerPack(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4101]!, self._r[4101]!, [_0]) + return formatWithArgumentRanges(self._s[4103]!, self._r[4103]!, [_0]) } - public var Contacts_PermissionsKeepDisabled: String { return self._s[4103]! } + public var Contacts_PermissionsKeepDisabled: String { return self._s[4105]! } public func Call_ParticipantVersionOutdatedError(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4104]!, self._r[4104]!, [_0]) + return formatWithArgumentRanges(self._s[4106]!, self._r[4106]!, [_0]) } - public var WatchRemote_AlertOpen: String { return self._s[4105]! } + public var WatchRemote_AlertOpen: String { return self._s[4107]! } public func PUSH_CHAT_ADD_MEMBER(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4106]!, self._r[4106]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[4108]!, self._r[4108]!, [_1, _2, _3]) } - public var Channel_Members_AddMembersHelp: String { return self._s[4107]! } - public var Shortcut_SwitchAccount: String { return self._s[4108]! } - public var Map_LiveLocationFor8Hours: String { return self._s[4109]! } + public var Channel_Members_AddMembersHelp: String { return self._s[4109]! } + public var Shortcut_SwitchAccount: String { return self._s[4110]! } + public var Map_LiveLocationFor8Hours: String { return self._s[4111]! } public func AutoNightTheme_AutomaticHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4110]!, self._r[4110]!, [_0]) + return formatWithArgumentRanges(self._s[4112]!, self._r[4112]!, [_0]) } - public var Compose_NewGroupTitle: String { return self._s[4111]! } - public var DialogList_You: String { return self._s[4112]! } - public var ReportPeer_ReasonViolence: String { return self._s[4113]! } + public var Compose_NewGroupTitle: String { return self._s[4113]! } + public var DialogList_You: String { return self._s[4114]! } + public var ReportPeer_ReasonViolence: String { return self._s[4115]! } public func PUSH_CHANNEL_MESSAGE_STICKER(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4114]!, self._r[4114]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4116]!, self._r[4116]!, [_1, _2]) } - public var KeyCommand_ScrollDown: String { return self._s[4118]! } - public var ChatSettings_DownloadInBackground: String { return self._s[4119]! } - public var Wallpaper_ResetWallpapers: String { return self._s[4120]! } - public var Channel_BanList_RestrictedTitle: String { return self._s[4121]! } - public var ArchivedChats_IntroText3: String { return self._s[4122]! } - public var HashtagSearch_AllChats: String { return self._s[4124]! } - public var Channel_Info_BlackList: String { return self._s[4126]! } - public var Contacts_SearchUsersAndGroupsLabel: String { return self._s[4127]! } - public var PrivacyPhoneNumberSettings_DiscoveryHeader: String { return self._s[4128]! } - public var Paint_Neon: String { return self._s[4130]! } - public var SettingsSearch_Synonyms_AppLanguage: String { return self._s[4131]! } - public var AutoDownloadSettings_AutoDownload: String { return self._s[4132]! } + public var KeyCommand_ScrollDown: String { return self._s[4120]! } + public var ChatSettings_DownloadInBackground: String { return self._s[4121]! } + public var Wallpaper_ResetWallpapers: String { return self._s[4122]! } + public var Channel_BanList_RestrictedTitle: String { return self._s[4123]! } + public var ArchivedChats_IntroText3: String { return self._s[4124]! } + public var HashtagSearch_AllChats: String { return self._s[4126]! } + public var Channel_Info_BlackList: String { return self._s[4128]! } + public var Contacts_SearchUsersAndGroupsLabel: String { return self._s[4129]! } + public var PrivacyPhoneNumberSettings_DiscoveryHeader: String { return self._s[4130]! } + public var Paint_Neon: String { return self._s[4132]! } + public var SettingsSearch_Synonyms_AppLanguage: String { return self._s[4133]! } + public var AutoDownloadSettings_AutoDownload: String { return self._s[4134]! } public func Notification_PinnedVideoMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4134]!, self._r[4134]!, [_0]) + return formatWithArgumentRanges(self._s[4136]!, self._r[4136]!, [_0]) } - public var Map_StopLiveLocation: String { return self._s[4135]! } - public var SettingsSearch_Synonyms_Data_SaveEditedPhotos: String { return self._s[4136]! } - public var Channel_Username_InvalidCharacters: String { return self._s[4137]! } - public var InstantPage_Reference: String { return self._s[4138]! } - public var ChatList_HideAction: String { return self._s[4140]! } - public var Conversation_FileICloudDrive: String { return self._s[4142]! } + public var Map_StopLiveLocation: String { return self._s[4137]! } + public var SettingsSearch_Synonyms_Data_SaveEditedPhotos: String { return self._s[4138]! } + public var Channel_Username_InvalidCharacters: String { return self._s[4139]! } + public var InstantPage_Reference: String { return self._s[4140]! } + public var ChatList_HideAction: String { return self._s[4142]! } + public var Conversation_FileICloudDrive: String { return self._s[4144]! } public func PUSH_PINNED_GEOLIVE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4143]!, self._r[4143]!, [_1]) + return formatWithArgumentRanges(self._s[4145]!, self._r[4145]!, [_1]) } - public var Passport_PasswordReset: String { return self._s[4145]! } - public var ChatList_Context_UnhideArchive: String { return self._s[4147]! } - public var ConvertToSupergroup_HelpText: String { return self._s[4148]! } - public var Calls_AddTab: String { return self._s[4149]! } - public var TwoStepAuth_ConfirmEmailResendCode: String { return self._s[4150]! } - public var SettingsSearch_Synonyms_Stickers_SuggestStickers: String { return self._s[4151]! } - public var Privacy_GroupsAndChannels: String { return self._s[4153]! } - public var AutoNightTheme_Disabled: String { return self._s[4154]! } - public var CreatePoll_MultipleChoice: String { return self._s[4155]! } + public var Passport_PasswordReset: String { return self._s[4147]! } + public var ChatList_Context_UnhideArchive: String { return self._s[4149]! } + public var ConvertToSupergroup_HelpText: String { return self._s[4150]! } + public var Calls_AddTab: String { return self._s[4151]! } + public var TwoStepAuth_ConfirmEmailResendCode: String { return self._s[4152]! } + public var SettingsSearch_Synonyms_Stickers_SuggestStickers: String { return self._s[4153]! } + public var Privacy_GroupsAndChannels: String { return self._s[4155]! } + public var AutoNightTheme_Disabled: String { return self._s[4156]! } + public var CreatePoll_MultipleChoice: String { return self._s[4157]! } public func PINNED_INVOICE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4156]!, self._r[4156]!, [_1]) + return formatWithArgumentRanges(self._s[4158]!, self._r[4158]!, [_1]) } - public var Watch_Bot_Restart: String { return self._s[4158]! } + public var Watch_Bot_Restart: String { return self._s[4160]! } public func Conversation_Kilobytes(_ _0: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4159]!, self._r[4159]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[4161]!, self._r[4161]!, ["\(_0)"]) } - public var GroupInfo_ScamGroupWarning: String { return self._s[4160]! } - public var Conversation_EditingMessagePanelMedia: String { return self._s[4161]! } - public var Appearance_PreviewIncomingText: String { return self._s[4162]! } - public var Notifications_ChannelNotificationsExceptionsHelp: String { return self._s[4163]! } - public var ChatList_UndoArchiveRevealedTitle: String { return self._s[4165]! } - public var Stats_GroupOverview: String { return self._s[4167]! } - public var ScheduledMessages_EditTime: String { return self._s[4170]! } - public var Month_GenFebruary: String { return self._s[4171]! } - public var ChatList_AutoarchiveSuggestion_OpenSettings: String { return self._s[4172]! } - public var Stickers_ClearRecent: String { return self._s[4173]! } - public var TwoStepAuth_EnterPasswordPassword: String { return self._s[4174]! } - public var Stats_Message_PublicShares: String { return self._s[4175]! } + public var GroupInfo_ScamGroupWarning: String { return self._s[4162]! } + public var Conversation_EditingMessagePanelMedia: String { return self._s[4163]! } + public var Appearance_PreviewIncomingText: String { return self._s[4164]! } + public var Notifications_ChannelNotificationsExceptionsHelp: String { return self._s[4165]! } + public var ChatList_UndoArchiveRevealedTitle: String { return self._s[4167]! } + public var Stats_GroupOverview: String { return self._s[4169]! } + public var ScheduledMessages_EditTime: String { return self._s[4172]! } + public var Month_GenFebruary: String { return self._s[4173]! } + public var ChatList_AutoarchiveSuggestion_OpenSettings: String { return self._s[4174]! } + public var Stickers_ClearRecent: String { return self._s[4175]! } + public var TwoStepAuth_EnterPasswordPassword: String { return self._s[4176]! } + public var Stats_Message_PublicShares: String { return self._s[4177]! } public func Checkout_PayPrice(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4176]!, self._r[4176]!, [_0]) + return formatWithArgumentRanges(self._s[4178]!, self._r[4178]!, [_0]) } - public var Login_TermsOfServiceSignupDecline: String { return self._s[4177]! } - public var CheckoutInfo_ErrorCityInvalid: String { return self._s[4178]! } - public var VoiceOver_Chat_PlayHint: String { return self._s[4179]! } - public var ChatAdmins_AllMembersAreAdminsOffHelp: String { return self._s[4180]! } - public var CheckoutInfo_ShippingInfoTitle: String { return self._s[4182]! } - public var CreatePoll_Create: String { return self._s[4183]! } - public var ChatList_Search_FilterLinks: String { return self._s[4184]! } - public var Your_cards_number_is_invalid: String { return self._s[4185]! } - public var Month_ShortApril: String { return self._s[4186]! } - public var SocksProxySetup_UseForCalls: String { return self._s[4187]! } - public var Conversation_EditingCaptionPanelTitle: String { return self._s[4188]! } - public var SocksProxySetup_Status: String { return self._s[4189]! } - public var ChannelInfo_DeleteGroupConfirmation: String { return self._s[4190]! } - public var ChatListFolder_CategoryBots: String { return self._s[4191]! } - public var Passport_FieldIdentitySelfieHelp: String { return self._s[4193]! } - public var GroupInfo_BroadcastListNamePlaceholder: String { return self._s[4194]! } - public var Chat_PinnedListPreview_UnpinAllMessages: String { return self._s[4195]! } - public var Wallpaper_ResetWallpapersInfo: String { return self._s[4196]! } - public var Conversation_TitleUnmute: String { return self._s[4197]! } - public var Group_Setup_TypeHeader: String { return self._s[4198]! } - public var Stats_ViewsPerPost: String { return self._s[4199]! } - public var CheckoutInfo_ShippingInfoCountry: String { return self._s[4200]! } - public var Passport_Identity_TranslationHelp: String { return self._s[4201]! } + public var Login_TermsOfServiceSignupDecline: String { return self._s[4179]! } + public var CheckoutInfo_ErrorCityInvalid: String { return self._s[4180]! } + public var VoiceOver_Chat_PlayHint: String { return self._s[4181]! } + public var ChatAdmins_AllMembersAreAdminsOffHelp: String { return self._s[4182]! } + public var CheckoutInfo_ShippingInfoTitle: String { return self._s[4184]! } + public var CreatePoll_Create: String { return self._s[4185]! } + public var ChatList_Search_FilterLinks: String { return self._s[4186]! } + public var Your_cards_number_is_invalid: String { return self._s[4187]! } + public var Month_ShortApril: String { return self._s[4188]! } + public var SocksProxySetup_UseForCalls: String { return self._s[4189]! } + public var Conversation_EditingCaptionPanelTitle: String { return self._s[4190]! } + public var SocksProxySetup_Status: String { return self._s[4191]! } + public var ChannelInfo_DeleteGroupConfirmation: String { return self._s[4192]! } + public var ChatListFolder_CategoryBots: String { return self._s[4193]! } + public var Passport_FieldIdentitySelfieHelp: String { return self._s[4195]! } + public var GroupInfo_BroadcastListNamePlaceholder: String { return self._s[4196]! } + public var Chat_PinnedListPreview_UnpinAllMessages: String { return self._s[4197]! } + public var Wallpaper_ResetWallpapersInfo: String { return self._s[4198]! } + public var Conversation_TitleUnmute: String { return self._s[4199]! } + public var Group_Setup_TypeHeader: String { return self._s[4200]! } + public var Stats_ViewsPerPost: String { return self._s[4201]! } + public var CheckoutInfo_ShippingInfoCountry: String { return self._s[4202]! } + public var Passport_Identity_TranslationHelp: String { return self._s[4203]! } public func PUSH_CHANNEL_MESSAGE_FWD(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4202]!, self._r[4202]!, [_1]) + return formatWithArgumentRanges(self._s[4204]!, self._r[4204]!, [_1]) } - public var GroupInfo_Administrators_Title: String { return self._s[4203]! } + public var GroupInfo_Administrators_Title: String { return self._s[4205]! } public func Channel_AdminLog_MessageRankName(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4204]!, self._r[4204]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4206]!, self._r[4206]!, [_1, _2]) } public func PUSH_CHAT_MESSAGE_POLL(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4205]!, self._r[4205]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[4207]!, self._r[4207]!, [_1, _2, _3]) } - public var Wallet_Receive_Title: String { return self._s[4206]! } - public var CheckoutInfo_ShippingInfoState: String { return self._s[4207]! } - public var Passport_Language_my: String { return self._s[4209]! } - public var PrivacyLastSeenSettings_AlwaysShareWith_Title: String { return self._s[4210]! } - public var Map_PlacesNearby: String { return self._s[4211]! } - public var Channel_About_Help: String { return self._s[4212]! } - public var LogoutOptions_AddAccountTitle: String { return self._s[4213]! } - public var ChatSettings_AutomaticAudioDownload: String { return self._s[4214]! } - public var Channel_Username_Title: String { return self._s[4215]! } - public var Activity_RecordingVideoMessage: String { return self._s[4216]! } + public var Wallet_Receive_Title: String { return self._s[4208]! } + public var CheckoutInfo_ShippingInfoState: String { return self._s[4209]! } + public var Passport_Language_my: String { return self._s[4211]! } + public var PrivacyLastSeenSettings_AlwaysShareWith_Title: String { return self._s[4212]! } + public var Map_PlacesNearby: String { return self._s[4213]! } + public var Channel_About_Help: String { return self._s[4214]! } + public var LogoutOptions_AddAccountTitle: String { return self._s[4215]! } + public var ChatSettings_AutomaticAudioDownload: String { return self._s[4216]! } + public var Channel_Username_Title: String { return self._s[4217]! } + public var Activity_RecordingVideoMessage: String { return self._s[4218]! } public func StickerPackActionInfo_RemovedText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4217]!, self._r[4217]!, [_0]) + return formatWithArgumentRanges(self._s[4219]!, self._r[4219]!, [_0]) } - public var CheckoutInfo_ShippingInfoCity: String { return self._s[4218]! } - public var Passport_DiscardMessageDescription: String { return self._s[4219]! } - public var Conversation_LinkDialogOpen: String { return self._s[4220]! } - public var ChatList_Context_HideArchive: String { return self._s[4221]! } + public var CheckoutInfo_ShippingInfoCity: String { return self._s[4220]! } + public var Passport_DiscardMessageDescription: String { return self._s[4221]! } + public var Conversation_LinkDialogOpen: String { return self._s[4222]! } + public var ChatList_Context_HideArchive: String { return self._s[4223]! } public func Message_AuthorPinnedGame(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4222]!, self._r[4222]!, [_0]) + return formatWithArgumentRanges(self._s[4224]!, self._r[4224]!, [_0]) } - public var Privacy_GroupsAndChannels_CustomShareHelp: String { return self._s[4223]! } - public var Conversation_Admin: String { return self._s[4224]! } - public var DialogList_TabTitle: String { return self._s[4225]! } + public var Privacy_GroupsAndChannels_CustomShareHelp: String { return self._s[4225]! } + public var Conversation_Admin: String { return self._s[4226]! } + public var DialogList_TabTitle: String { return self._s[4227]! } public func PUSH_CHAT_ALBUM(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4226]!, self._r[4226]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4228]!, self._r[4228]!, [_1, _2]) } - public var Notifications_PermissionsUnreachableText: String { return self._s[4227]! } - public var Passport_Identity_GenderMale: String { return self._s[4229]! } - public var SettingsSearch_Synonyms_Privacy_BlockedUsers: String { return self._s[4231]! } - public var PhoneNumberHelp_Alert: String { return self._s[4232]! } - public var EnterPasscode_EnterNewPasscodeChange: String { return self._s[4233]! } - public var Notifications_InAppNotifications: String { return self._s[4234]! } + public var Notifications_PermissionsUnreachableText: String { return self._s[4229]! } + public var Passport_Identity_GenderMale: String { return self._s[4231]! } + public var SettingsSearch_Synonyms_Privacy_BlockedUsers: String { return self._s[4233]! } + public var PhoneNumberHelp_Alert: String { return self._s[4234]! } + public var EnterPasscode_EnterNewPasscodeChange: String { return self._s[4235]! } + public var Notifications_InAppNotifications: String { return self._s[4236]! } public func Update_AppVersion(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4235]!, self._r[4235]!, [_0]) + return formatWithArgumentRanges(self._s[4237]!, self._r[4237]!, [_0]) } - public var Notification_VideoCallOutgoing: String { return self._s[4236]! } - public var Login_InvalidCodeError: String { return self._s[4237]! } - public var Conversation_PrivateChannelTimeLimitedAlertJoin: String { return self._s[4238]! } + public var Notification_VideoCallOutgoing: String { return self._s[4238]! } + public var Login_InvalidCodeError: String { return self._s[4239]! } + public var Conversation_PrivateChannelTimeLimitedAlertJoin: String { return self._s[4240]! } public func LastSeen_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4239]!, self._r[4239]!, [_0]) + return formatWithArgumentRanges(self._s[4241]!, self._r[4241]!, [_0]) } - public var Conversation_InputTextCaptionPlaceholder: String { return self._s[4241]! } - public var ReportPeer_Report: String { return self._s[4242]! } - public var Camera_FlashOff: String { return self._s[4245]! } - public var Conversation_InputTextBroadcastPlaceholder: String { return self._s[4248]! } - public var PrivacyPolicy_DeclineTitle: String { return self._s[4251]! } - public var SettingsSearch_Synonyms_Privacy_PasscodeAndTouchId: String { return self._s[4252]! } - public var Passport_FieldEmail: String { return self._s[4253]! } + public var Conversation_InputTextCaptionPlaceholder: String { return self._s[4243]! } + public var ReportPeer_Report: String { return self._s[4244]! } + public var Camera_FlashOff: String { return self._s[4247]! } + public var Conversation_InputTextBroadcastPlaceholder: String { return self._s[4250]! } + public var PrivacyPolicy_DeclineTitle: String { return self._s[4253]! } + public var SettingsSearch_Synonyms_Privacy_PasscodeAndTouchId: String { return self._s[4254]! } + public var Passport_FieldEmail: String { return self._s[4255]! } public func Channel_AdminLog_MessageKickedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4254]!, self._r[4254]!, [_1]) + return formatWithArgumentRanges(self._s[4256]!, self._r[4256]!, [_1]) } - public var Notifications_ExceptionsResetToDefaults: String { return self._s[4255]! } - public var PeerInfo_PaneVoiceAndVideo: String { return self._s[4256]! } - public var Group_OwnershipTransfer_Title: String { return self._s[4257]! } - public var Conversation_DefaultRestrictedInline: String { return self._s[4258]! } - public var Login_PhoneNumberHelp: String { return self._s[4260]! } - public var Channel_AdminLogFilter_EventsNewMembers: String { return self._s[4261]! } - public var Conversation_PinnedQuiz: String { return self._s[4262]! } - public var CreateGroup_SoftUserLimitAlert: String { return self._s[4263]! } - public var Login_PhoneNumberAlreadyAuthorizedSwitch: String { return self._s[4264]! } - public var Group_MessagePhotoUpdated: String { return self._s[4265]! } - public var LoginPassword_PasswordPlaceholder: String { return self._s[4266]! } - public var Passport_Identity_Translations: String { return self._s[4268]! } - public var ChatAdmins_AllMembersAreAdmins: String { return self._s[4269]! } - public var ChannelInfo_DeleteChannel: String { return self._s[4271]! } - public var PasscodeSettings_HelpBottom: String { return self._s[4272]! } - public var Channel_Members_AddMembers: String { return self._s[4273]! } - public var AutoDownloadSettings_LastDelimeter: String { return self._s[4274]! } - public var Notification_Exceptions_DeleteAllConfirmation: String { return self._s[4276]! } - public var Conversation_HoldForAudio: String { return self._s[4277]! } - public var Watch_LastSeen_Lately: String { return self._s[4279]! } - public var ChatList_Context_MarkAsRead: String { return self._s[4280]! } - public var Conversation_PinnedMessage: String { return self._s[4281]! } - public var SettingsSearch_Synonyms_Appearance_ColorTheme: String { return self._s[4282]! } - public var Passport_UpdateRequiredError: String { return self._s[4284]! } - public var PrivacySettings_Passcode: String { return self._s[4285]! } + public var Notifications_ExceptionsResetToDefaults: String { return self._s[4257]! } + public var PeerInfo_PaneVoiceAndVideo: String { return self._s[4258]! } + public var Group_OwnershipTransfer_Title: String { return self._s[4259]! } + public var Conversation_DefaultRestrictedInline: String { return self._s[4260]! } + public var Login_PhoneNumberHelp: String { return self._s[4262]! } + public var Channel_AdminLogFilter_EventsNewMembers: String { return self._s[4263]! } + public var Conversation_PinnedQuiz: String { return self._s[4264]! } + public var CreateGroup_SoftUserLimitAlert: String { return self._s[4265]! } + public var Login_PhoneNumberAlreadyAuthorizedSwitch: String { return self._s[4266]! } + public var Group_MessagePhotoUpdated: String { return self._s[4267]! } + public var LoginPassword_PasswordPlaceholder: String { return self._s[4268]! } + public var Passport_Identity_Translations: String { return self._s[4270]! } + public var ChatAdmins_AllMembersAreAdmins: String { return self._s[4271]! } + public var ChannelInfo_DeleteChannel: String { return self._s[4273]! } + public var PasscodeSettings_HelpBottom: String { return self._s[4274]! } + public var Channel_Members_AddMembers: String { return self._s[4275]! } + public var AutoDownloadSettings_LastDelimeter: String { return self._s[4276]! } + public var Notification_Exceptions_DeleteAllConfirmation: String { return self._s[4278]! } + public var Conversation_HoldForAudio: String { return self._s[4279]! } + public var Watch_LastSeen_Lately: String { return self._s[4281]! } + public var ChatList_Context_MarkAsRead: String { return self._s[4282]! } + public var Conversation_PinnedMessage: String { return self._s[4283]! } + public var SettingsSearch_Synonyms_Appearance_ColorTheme: String { return self._s[4284]! } + public var Passport_UpdateRequiredError: String { return self._s[4286]! } + public var PrivacySettings_Passcode: String { return self._s[4287]! } public func Call_EmojiDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4286]!, self._r[4286]!, [_0]) + return formatWithArgumentRanges(self._s[4288]!, self._r[4288]!, [_0]) } - public var AutoNightTheme_NotAvailable: String { return self._s[4287]! } - public var Conversation_PressVolumeButtonForSound: String { return self._s[4288]! } - public var LoginPassword_InvalidPasswordError: String { return self._s[4289]! } - public var ChatListFolder_IncludedSectionHeader: String { return self._s[4290]! } - public var Channel_SignMessages_Help: String { return self._s[4291]! } - public var ChatList_DeleteForEveryoneConfirmationTitle: String { return self._s[4292]! } - public var Conversation_TitleNoComments: String { return self._s[4293]! } - public var MediaPicker_LivePhotoDescription: String { return self._s[4294]! } - public var GroupInfo_Permissions: String { return self._s[4295]! } - public var GroupPermission_NoSendLinks: String { return self._s[4298]! } - public var Passport_Identity_ResidenceCountry: String { return self._s[4299]! } - public var Appearance_ThemeCarouselNightBlue: String { return self._s[4301]! } - public var ChatList_ArchiveAction: String { return self._s[4302]! } + public var AutoNightTheme_NotAvailable: String { return self._s[4289]! } + public var Conversation_PressVolumeButtonForSound: String { return self._s[4290]! } + public var LoginPassword_InvalidPasswordError: String { return self._s[4291]! } + public var ChatListFolder_IncludedSectionHeader: String { return self._s[4292]! } + public var Channel_SignMessages_Help: String { return self._s[4293]! } + public var ChatList_DeleteForEveryoneConfirmationTitle: String { return self._s[4294]! } + public var Conversation_TitleNoComments: String { return self._s[4295]! } + public var MediaPicker_LivePhotoDescription: String { return self._s[4296]! } + public var GroupInfo_Permissions: String { return self._s[4297]! } + public var GroupPermission_NoSendLinks: String { return self._s[4300]! } + public var Passport_Identity_ResidenceCountry: String { return self._s[4301]! } + public var Appearance_ThemeCarouselNightBlue: String { return self._s[4303]! } + public var ChatList_ArchiveAction: String { return self._s[4304]! } public func Channel_AdminLog_DisabledSlowmode(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4303]!, self._r[4303]!, [_0]) + return formatWithArgumentRanges(self._s[4305]!, self._r[4305]!, [_0]) } - public var GroupInfo_GroupHistory: String { return self._s[4304]! } + public var GroupInfo_GroupHistory: String { return self._s[4306]! } public func Channel_Management_ErrorNotMember(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4306]!, self._r[4306]!, [_0]) + return formatWithArgumentRanges(self._s[4308]!, self._r[4308]!, [_0]) } - public var Privacy_Forwards_LinkIfAllowed: String { return self._s[4308]! } - public var Channel_Info_Banned: String { return self._s[4309]! } - public var Paint_RecentStickers: String { return self._s[4310]! } - public var VoiceOver_MessageContextSend: String { return self._s[4311]! } - public var Group_ErrorNotMutualContact: String { return self._s[4312]! } - public var ReportPeer_ReasonOther: String { return self._s[4314]! } - public var Channel_BanUser_PermissionChangeGroupInfo: String { return self._s[4315]! } - public var SocksProxySetup_ShareQRCodeInfo: String { return self._s[4317]! } - public var KeyCommand_Find: String { return self._s[4318]! } + public var Privacy_Forwards_LinkIfAllowed: String { return self._s[4310]! } + public var Channel_Info_Banned: String { return self._s[4311]! } + public var Paint_RecentStickers: String { return self._s[4312]! } + public var VoiceOver_MessageContextSend: String { return self._s[4313]! } + public var Group_ErrorNotMutualContact: String { return self._s[4314]! } + public var ReportPeer_ReasonOther: String { return self._s[4316]! } + public var Channel_BanUser_PermissionChangeGroupInfo: String { return self._s[4317]! } + public var SocksProxySetup_ShareQRCodeInfo: String { return self._s[4319]! } + public var KeyCommand_Find: String { return self._s[4320]! } public func Channel_MessageTitleUpdated(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4319]!, self._r[4319]!, [_0]) + return formatWithArgumentRanges(self._s[4321]!, self._r[4321]!, [_0]) } - public var ChatList_Context_Unmute: String { return self._s[4320]! } - public var Chat_SlowmodeAttachmentLimitReached: String { return self._s[4321]! } - public var Stickers_GroupStickersHelp: String { return self._s[4322]! } - public var Wallet_Configuration_BlockchainIdPlaceholder: String { return self._s[4323]! } - public var Checkout_Title: String { return self._s[4324]! } - public var Activity_RecordingAudio: String { return self._s[4325]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsPreview: String { return self._s[4326]! } - public var BlockedUsers_BlockTitle: String { return self._s[4327]! } - public var Wallet_Month_ShortFebruary: String { return self._s[4329]! } - public var Calls_All: String { return self._s[4330]! } - public var DialogList_SavedMessagesHelp: String { return self._s[4332]! } - public var Settings_FAQ_Button: String { return self._s[4333]! } - public var Conversation_Dice_u1F3B0: String { return self._s[4335]! } + public var ChatList_Context_Unmute: String { return self._s[4322]! } + public var Chat_SlowmodeAttachmentLimitReached: String { return self._s[4323]! } + public var Stickers_GroupStickersHelp: String { return self._s[4324]! } + public var Wallet_Configuration_BlockchainIdPlaceholder: String { return self._s[4325]! } + public var Checkout_Title: String { return self._s[4326]! } + public var Activity_RecordingAudio: String { return self._s[4327]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsPreview: String { return self._s[4328]! } + public var BlockedUsers_BlockTitle: String { return self._s[4329]! } + public var Wallet_Month_ShortFebruary: String { return self._s[4331]! } + public var Calls_All: String { return self._s[4332]! } + public var DialogList_SavedMessagesHelp: String { return self._s[4334]! } + public var Settings_FAQ_Button: String { return self._s[4335]! } + public var Conversation_Dice_u1F3B0: String { return self._s[4337]! } public func Time_MonthOfYear_m5(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4336]!, self._r[4336]!, [_0]) + return formatWithArgumentRanges(self._s[4338]!, self._r[4338]!, [_0]) } - public var Conversation_ReportGroupLocation: String { return self._s[4337]! } - public var Passport_Scans_Upload: String { return self._s[4338]! } - public var Channel_EditAdmin_PermissionPinMessages: String { return self._s[4340]! } - public var ChatList_UnarchiveAction: String { return self._s[4341]! } - public var Stats_GroupTopInviter_History: String { return self._s[4342]! } - public var GroupInfo_Permissions_Title: String { return self._s[4343]! } - public var Passport_Language_el: String { return self._s[4344]! } + public var Conversation_ReportGroupLocation: String { return self._s[4339]! } + public var Passport_Scans_Upload: String { return self._s[4340]! } + public var Channel_EditAdmin_PermissionPinMessages: String { return self._s[4342]! } + public var ChatList_UnarchiveAction: String { return self._s[4343]! } + public var Stats_GroupTopInviter_History: String { return self._s[4344]! } + public var GroupInfo_Permissions_Title: String { return self._s[4345]! } + public var Passport_Language_el: String { return self._s[4346]! } public func Wallet_Time_PreciseDate_m4(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4345]!, self._r[4345]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[4347]!, self._r[4347]!, [_1, _2, _3]) } - public var Channel_DiscussionMessageUnavailable: String { return self._s[4346]! } - public var GroupInfo_ActionPromote: String { return self._s[4347]! } - public var Group_OwnershipTransfer_ErrorLocatedGroupsTooMuch: String { return self._s[4348]! } + public var Channel_DiscussionMessageUnavailable: String { return self._s[4348]! } + public var GroupInfo_ActionPromote: String { return self._s[4349]! } + public var Group_OwnershipTransfer_ErrorLocatedGroupsTooMuch: String { return self._s[4350]! } public func TwoStepAuth_PendingEmailHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4349]!, self._r[4349]!, [_0]) + return formatWithArgumentRanges(self._s[4351]!, self._r[4351]!, [_0]) } - public var VoiceOver_Chat_Reply: String { return self._s[4350]! } - public var Month_GenMay: String { return self._s[4351]! } - public var DialogList_DeleteBotConversationConfirmation: String { return self._s[4352]! } - public var Chat_PsaTooltip_covid: String { return self._s[4353]! } - public var Watch_Suggestion_CantTalk: String { return self._s[4354]! } - public var Privacy_GroupsAndChannels_NeverAllow_Title: String { return self._s[4355]! } - public var AppUpgrade_Running: String { return self._s[4356]! } - public var PasscodeSettings_UnlockWithFaceId: String { return self._s[4359]! } - public var Notification_Exceptions_PreviewAlwaysOff: String { return self._s[4360]! } - public var SharedMedia_EmptyText: String { return self._s[4361]! } - public var Passport_Address_EditResidentialAddress: String { return self._s[4362]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsAlert: String { return self._s[4363]! } - public var Message_PinnedGame: String { return self._s[4364]! } - public var KeyCommand_SearchInChat: String { return self._s[4365]! } - public var Appearance_ThemeCarouselNewNight: String { return self._s[4366]! } - public var ChatList_Search_FilterMedia: String { return self._s[4367]! } - public var Message_PinnedAudioMessage: String { return self._s[4368]! } - public var ChannelInfo_ConfirmLeave: String { return self._s[4369]! } + public var VoiceOver_Chat_Reply: String { return self._s[4352]! } + public var Month_GenMay: String { return self._s[4353]! } + public var DialogList_DeleteBotConversationConfirmation: String { return self._s[4354]! } + public var Chat_PsaTooltip_covid: String { return self._s[4355]! } + public var Watch_Suggestion_CantTalk: String { return self._s[4356]! } + public var Privacy_GroupsAndChannels_NeverAllow_Title: String { return self._s[4357]! } + public var AppUpgrade_Running: String { return self._s[4358]! } + public var PasscodeSettings_UnlockWithFaceId: String { return self._s[4361]! } + public var Notification_Exceptions_PreviewAlwaysOff: String { return self._s[4362]! } + public var SharedMedia_EmptyText: String { return self._s[4363]! } + public var Passport_Address_EditResidentialAddress: String { return self._s[4364]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsAlert: String { return self._s[4365]! } + public var Message_PinnedGame: String { return self._s[4366]! } + public var KeyCommand_SearchInChat: String { return self._s[4367]! } + public var Appearance_ThemeCarouselNewNight: String { return self._s[4368]! } + public var ChatList_Search_FilterMedia: String { return self._s[4369]! } + public var Message_PinnedAudioMessage: String { return self._s[4370]! } + public var ChannelInfo_ConfirmLeave: String { return self._s[4371]! } public func Channel_AdminLog_MessagePromotedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4370]!, self._r[4370]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4372]!, self._r[4372]!, [_1, _2]) } - public var SocksProxySetup_ProxyStatusUnavailable: String { return self._s[4371]! } + public var SocksProxySetup_ProxyStatusUnavailable: String { return self._s[4373]! } public func Passport_Email_CodeHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4372]!, self._r[4372]!, [_0]) - } - public var Wallet_Receive_AddressCopied: String { return self._s[4373]! } - public func Message_PinnedTextMessage(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[4374]!, self._r[4374]!, [_0]) } - public var Settings_AddAccount: String { return self._s[4375]! } - public var Channel_AdminLog_CanDeleteMessages: String { return self._s[4376]! } - public var Conversation_DiscardVoiceMessageTitle: String { return self._s[4377]! } - public var Channel_JoinChannel: String { return self._s[4378]! } - public var Watch_UserInfo_Unblock: String { return self._s[4379]! } - public var PhoneLabel_Title: String { return self._s[4380]! } - public var Group_Setup_HistoryHiddenHelp: String { return self._s[4382]! } - public var Privacy_ProfilePhoto_AlwaysShareWith_Title: String { return self._s[4383]! } + public var Wallet_Receive_AddressCopied: String { return self._s[4375]! } + public func Message_PinnedTextMessage(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[4376]!, self._r[4376]!, [_0]) + } + public var Settings_AddAccount: String { return self._s[4377]! } + public var Channel_AdminLog_CanDeleteMessages: String { return self._s[4378]! } + public var Conversation_DiscardVoiceMessageTitle: String { return self._s[4379]! } + public var Channel_JoinChannel: String { return self._s[4380]! } + public var Watch_UserInfo_Unblock: String { return self._s[4381]! } + public var PhoneLabel_Title: String { return self._s[4382]! } + public var Group_Setup_HistoryHiddenHelp: String { return self._s[4384]! } + public var Privacy_ProfilePhoto_AlwaysShareWith_Title: String { return self._s[4385]! } public func Login_PhoneGenericEmailBody(_ _1: String, _ _2: String, _ _3: String, _ _4: String, _ _5: String, _ _6: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4384]!, self._r[4384]!, [_1, _2, _3, _4, _5, _6]) + return formatWithArgumentRanges(self._s[4386]!, self._r[4386]!, [_1, _2, _3, _4, _5, _6]) } - public var Wallet_Month_GenOctober: String { return self._s[4385]! } - public var Channel_AddBotErrorHaveRights: String { return self._s[4386]! } - public var ChatList_TabIconFoldersTooltipNonEmptyFolders: String { return self._s[4387]! } - public var DialogList_EncryptionProcessing: String { return self._s[4388]! } - public var ChatList_Search_FilterChats: String { return self._s[4389]! } - public var WatchRemote_NotificationText: String { return self._s[4390]! } - public var EditTheme_ChangeColors: String { return self._s[4391]! } - public var GroupRemoved_ViewUserInfo: String { return self._s[4392]! } - public var Wallet_TransactionInfo_RecipientHeader: String { return self._s[4393]! } - public var CallSettings_OnMobile: String { return self._s[4395]! } - public var Month_ShortFebruary: String { return self._s[4397]! } - public var VoiceOver_MessageContextReply: String { return self._s[4398]! } + public var Wallet_Month_GenOctober: String { return self._s[4387]! } + public var Channel_AddBotErrorHaveRights: String { return self._s[4388]! } + public var ChatList_TabIconFoldersTooltipNonEmptyFolders: String { return self._s[4389]! } + public var DialogList_EncryptionProcessing: String { return self._s[4390]! } + public var ChatList_Search_FilterChats: String { return self._s[4391]! } + public var WatchRemote_NotificationText: String { return self._s[4392]! } + public var EditTheme_ChangeColors: String { return self._s[4393]! } + public var GroupRemoved_ViewUserInfo: String { return self._s[4394]! } + public var Wallet_TransactionInfo_RecipientHeader: String { return self._s[4395]! } + public var CallSettings_OnMobile: String { return self._s[4397]! } + public var Month_ShortFebruary: String { return self._s[4399]! } + public var VoiceOver_MessageContextReply: String { return self._s[4400]! } public func PUSH_VIDEO_CALL_REQUEST(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4399]!, self._r[4399]!, [_1]) + return formatWithArgumentRanges(self._s[4401]!, self._r[4401]!, [_1]) } - public var Group_Location_ChangeLocation: String { return self._s[4400]! } - public var Passport_Address_TypeBankStatementUploadScan: String { return self._s[4401]! } - public var Wallet_Send_EncryptComment: String { return self._s[4402]! } - public var VoiceOver_Media_PlaybackStop: String { return self._s[4403]! } - public var SettingsSearch_Synonyms_Data_SaveIncomingPhotos: String { return self._s[4404]! } + public var Group_Location_ChangeLocation: String { return self._s[4402]! } + public var Passport_Address_TypeBankStatementUploadScan: String { return self._s[4403]! } + public var Wallet_Send_EncryptComment: String { return self._s[4404]! } + public var VoiceOver_Media_PlaybackStop: String { return self._s[4405]! } + public var SettingsSearch_Synonyms_Data_SaveIncomingPhotos: String { return self._s[4406]! } public func Channel_AdminLog_MessageRestrictedUntil(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4406]!, self._r[4406]!, [_0]) + return formatWithArgumentRanges(self._s[4408]!, self._r[4408]!, [_0]) } - public var PhotoEditor_WarmthTool: String { return self._s[4407]! } - public var Login_InfoAvatarPhoto: String { return self._s[4408]! } - public var Notification_Exceptions_NewException_MessagePreviewHeader: String { return self._s[4409]! } - public var Permissions_CellularDataAllowInSettings_v0: String { return self._s[4410]! } - public var Map_PlacesInThisArea: String { return self._s[4411]! } - public var VoiceOver_Chat_ContactEmail: String { return self._s[4412]! } - public var Notifications_InAppNotificationsSounds: String { return self._s[4413]! } + public var PhotoEditor_WarmthTool: String { return self._s[4409]! } + public var Login_InfoAvatarPhoto: String { return self._s[4410]! } + public var Notification_Exceptions_NewException_MessagePreviewHeader: String { return self._s[4411]! } + public var Permissions_CellularDataAllowInSettings_v0: String { return self._s[4412]! } + public var Map_PlacesInThisArea: String { return self._s[4413]! } + public var VoiceOver_Chat_ContactEmail: String { return self._s[4414]! } + public var Notifications_InAppNotificationsSounds: String { return self._s[4415]! } public func PUSH_PINNED_NOTEXT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4414]!, self._r[4414]!, [_1]) + return formatWithArgumentRanges(self._s[4416]!, self._r[4416]!, [_1]) } - public var ShareMenu_Send: String { return self._s[4415]! } - public var Username_InvalidStartsWithNumber: String { return self._s[4416]! } - public var Appearance_AppIconClassicX: String { return self._s[4417]! } + public var ShareMenu_Send: String { return self._s[4417]! } + public var Username_InvalidStartsWithNumber: String { return self._s[4418]! } + public var Appearance_AppIconClassicX: String { return self._s[4419]! } public func PUSH_CHANNEL_MESSAGE_ROUND(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4418]!, self._r[4418]!, [_1]) + return formatWithArgumentRanges(self._s[4420]!, self._r[4420]!, [_1]) } - public var Conversation_StopPoll: String { return self._s[4419]! } - public var InfoPlist_NSLocationAlwaysUsageDescription: String { return self._s[4421]! } - public var Passport_Identity_EditIdentityCard: String { return self._s[4422]! } - public var Appearance_ThemePreview_ChatList_3_Name: String { return self._s[4423]! } - public var Wallet_WordCheck_Title: String { return self._s[4424]! } - public var Conversation_Timer_Title: String { return self._s[4425]! } - public var Common_Next: String { return self._s[4426]! } - public var Notification_Exceptions_NewException: String { return self._s[4427]! } + public var Conversation_StopPoll: String { return self._s[4421]! } + public var InfoPlist_NSLocationAlwaysUsageDescription: String { return self._s[4423]! } + public var Passport_Identity_EditIdentityCard: String { return self._s[4424]! } + public var Appearance_ThemePreview_ChatList_3_Name: String { return self._s[4425]! } + public var Wallet_WordCheck_Title: String { return self._s[4426]! } + public var Conversation_Timer_Title: String { return self._s[4427]! } + public var Common_Next: String { return self._s[4428]! } + public var Notification_Exceptions_NewException: String { return self._s[4429]! } public func Generic_OpenHiddenLinkAlert(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4428]!, self._r[4428]!, [_0]) + return formatWithArgumentRanges(self._s[4430]!, self._r[4430]!, [_0]) } - public var AccessDenied_CallMicrophone: String { return self._s[4429]! } - public var SettingsSearch_Synonyms_Data_AutoDownloadUsingCellular: String { return self._s[4430]! } - public var ChangePhoneNumberCode_Help: String { return self._s[4431]! } - public var Passport_Identity_OneOfTypeIdentityCard: String { return self._s[4432]! } - public var Channel_AdminLogFilter_EventsLeaving: String { return self._s[4433]! } - public var BlockedUsers_LeavePrefix: String { return self._s[4434]! } + public var AccessDenied_CallMicrophone: String { return self._s[4431]! } + public var SettingsSearch_Synonyms_Data_AutoDownloadUsingCellular: String { return self._s[4432]! } + public var ChangePhoneNumberCode_Help: String { return self._s[4433]! } + public var Passport_Identity_OneOfTypeIdentityCard: String { return self._s[4434]! } + public var Channel_AdminLogFilter_EventsLeaving: String { return self._s[4435]! } + public var BlockedUsers_LeavePrefix: String { return self._s[4436]! } public func Passport_RequestHeader(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4435]!, self._r[4435]!, [_0]) + return formatWithArgumentRanges(self._s[4437]!, self._r[4437]!, [_0]) } - public var Group_About_Help: String { return self._s[4436]! } - public var TwoStepAuth_ChangePasswordDescription: String { return self._s[4437]! } - public var Tour_Title3: String { return self._s[4438]! } - public var Watch_Conversation_Unblock: String { return self._s[4439]! } - public var Watch_UserInfo_Block: String { return self._s[4440]! } - public var Notifications_ChannelNotificationsAlert: String { return self._s[4441]! } - public var TwoFactorSetup_Hint_Action: String { return self._s[4442]! } - public var IntentsSettings_SuggestedChatsInfo: String { return self._s[4443]! } - public var Wallet_Alert_Cancel: String { return self._s[4444]! } - public var TextFormat_AddLinkTitle: String { return self._s[4445]! } - public var GroupInfo_InviteLink_RevokeAlert_Revoke: String { return self._s[4446]! } - public var TwoStepAuth_EnterPasswordTitle: String { return self._s[4447]! } - public var FastTwoStepSetup_PasswordSection: String { return self._s[4448]! } - public var Compose_ChannelMembers: String { return self._s[4449]! } - public var Conversation_ForwardTitle: String { return self._s[4450]! } + public var Group_About_Help: String { return self._s[4438]! } + public var TwoStepAuth_ChangePasswordDescription: String { return self._s[4439]! } + public var Tour_Title3: String { return self._s[4440]! } + public var Watch_Conversation_Unblock: String { return self._s[4441]! } + public var Watch_UserInfo_Block: String { return self._s[4442]! } + public var Notifications_ChannelNotificationsAlert: String { return self._s[4443]! } + public var TwoFactorSetup_Hint_Action: String { return self._s[4444]! } + public var IntentsSettings_SuggestedChatsInfo: String { return self._s[4445]! } + public var Wallet_Alert_Cancel: String { return self._s[4446]! } + public var TextFormat_AddLinkTitle: String { return self._s[4447]! } + public var GroupInfo_InviteLink_RevokeAlert_Revoke: String { return self._s[4448]! } + public var TwoStepAuth_EnterPasswordTitle: String { return self._s[4449]! } + public var FastTwoStepSetup_PasswordSection: String { return self._s[4450]! } + public var Compose_ChannelMembers: String { return self._s[4451]! } + public var Conversation_ForwardTitle: String { return self._s[4452]! } public func Wallet_Updated_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4451]!, self._r[4451]!, [_0]) + return formatWithArgumentRanges(self._s[4453]!, self._r[4453]!, [_0]) } - public var Conversation_PinnedPoll: String { return self._s[4453]! } + public var Conversation_PinnedPoll: String { return self._s[4455]! } public func VoiceOver_Chat_AnonymousPollFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4454]!, self._r[4454]!, [_0]) + return formatWithArgumentRanges(self._s[4456]!, self._r[4456]!, [_0]) } - public var SettingsSearch_Synonyms_EditProfile_AddAccount: String { return self._s[4455]! } - public var Conversation_ContextMenuStickerPackAdd: String { return self._s[4456]! } - public var Stats_Overview: String { return self._s[4457]! } - public var Map_HomeAndWorkTitle: String { return self._s[4458]! } - public var Wallet_Intro_Terms: String { return self._s[4459]! } + public var SettingsSearch_Synonyms_EditProfile_AddAccount: String { return self._s[4457]! } + public var Conversation_ContextMenuStickerPackAdd: String { return self._s[4458]! } + public var Stats_Overview: String { return self._s[4459]! } + public var Map_HomeAndWorkTitle: String { return self._s[4460]! } + public var Wallet_Intro_Terms: String { return self._s[4461]! } public func Time_PreciseDate_m4(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4460]!, self._r[4460]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[4462]!, self._r[4462]!, [_1, _2, _3]) } - public var Passport_Address_CityPlaceholder: String { return self._s[4461]! } - public var InfoPlist_NSLocationAlwaysAndWhenInUseUsageDescription: String { return self._s[4462]! } - public var Privacy_PhoneNumber: String { return self._s[4463]! } - public var ChatList_Search_FilterFiles: String { return self._s[4464]! } - public var ChatList_DeleteForEveryoneConfirmationAction: String { return self._s[4465]! } - public var ChannelIntro_CreateChannel: String { return self._s[4466]! } - public var Conversation_InputTextAnonymousPlaceholder: String { return self._s[4467]! } + public var Passport_Address_CityPlaceholder: String { return self._s[4463]! } + public var InfoPlist_NSLocationAlwaysAndWhenInUseUsageDescription: String { return self._s[4464]! } + public var Privacy_PhoneNumber: String { return self._s[4465]! } + public var ChatList_Search_FilterFiles: String { return self._s[4466]! } + public var ChatList_DeleteForEveryoneConfirmationAction: String { return self._s[4467]! } + public var ChannelIntro_CreateChannel: String { return self._s[4468]! } + public var Conversation_InputTextAnonymousPlaceholder: String { return self._s[4469]! } public func Login_EmailCodeBody(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4468]!, self._r[4468]!, [_0]) + return formatWithArgumentRanges(self._s[4470]!, self._r[4470]!, [_0]) } - public var Weekday_ShortMonday: String { return self._s[4469]! } - public var Passport_Language_ar: String { return self._s[4471]! } - public var SettingsSearch_Synonyms_EditProfile_Title: String { return self._s[4472]! } - public var TwoFactorSetup_Done_Title: String { return self._s[4473]! } - public var Calls_RatingFeedback: String { return self._s[4474]! } - public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsPreview: String { return self._s[4475]! } - public var AutoDownloadSettings_ResetSettings: String { return self._s[4478]! } - public var Watch_Compose_Send: String { return self._s[4479]! } - public var PasscodeSettings_ChangePasscode: String { return self._s[4480]! } - public var WebSearch_RecentSectionClear: String { return self._s[4481]! } + public var Weekday_ShortMonday: String { return self._s[4471]! } + public var Passport_Language_ar: String { return self._s[4473]! } + public var SettingsSearch_Synonyms_EditProfile_Title: String { return self._s[4474]! } + public var TwoFactorSetup_Done_Title: String { return self._s[4475]! } + public var Calls_RatingFeedback: String { return self._s[4476]! } + public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsPreview: String { return self._s[4477]! } + public var AutoDownloadSettings_ResetSettings: String { return self._s[4480]! } + public var Watch_Compose_Send: String { return self._s[4481]! } + public var PasscodeSettings_ChangePasscode: String { return self._s[4482]! } + public var WebSearch_RecentSectionClear: String { return self._s[4483]! } public func Contacts_AccessDeniedHelpPortrait(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4482]!, self._r[4482]!, [_0]) + return formatWithArgumentRanges(self._s[4484]!, self._r[4484]!, [_0]) } - public var WallpaperSearch_ColorTeal: String { return self._s[4483]! } - public var Wallpaper_SetCustomBackgroundInfo: String { return self._s[4484]! } - public var Permissions_ContactsTitle_v0: String { return self._s[4485]! } - public var Checkout_PasswordEntry_Pay: String { return self._s[4487]! } - public var Settings_SavedMessages: String { return self._s[4488]! } - public var TwoStepAuth_ReEnterPasswordDescription: String { return self._s[4489]! } - public var Month_ShortMarch: String { return self._s[4490]! } - public var Message_Location: String { return self._s[4491]! } + public var WallpaperSearch_ColorTeal: String { return self._s[4485]! } + public var Wallpaper_SetCustomBackgroundInfo: String { return self._s[4486]! } + public var Permissions_ContactsTitle_v0: String { return self._s[4487]! } + public var Checkout_PasswordEntry_Pay: String { return self._s[4489]! } + public var Settings_SavedMessages: String { return self._s[4490]! } + public var TwoStepAuth_ReEnterPasswordDescription: String { return self._s[4491]! } + public var Month_ShortMarch: String { return self._s[4492]! } + public var Message_Location: String { return self._s[4493]! } public func PUSH_MESSAGE_GIF(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4492]!, self._r[4492]!, [_1]) + return formatWithArgumentRanges(self._s[4494]!, self._r[4494]!, [_1]) } public func Notification_CallTimeFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4493]!, self._r[4493]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4495]!, self._r[4495]!, [_1, _2]) } - public var VoiceOver_Chat_VoiceMessage: String { return self._s[4495]! } + public var VoiceOver_Chat_VoiceMessage: String { return self._s[4497]! } public func Channel_AdminLog_MessageChangedUnlinkedChannel(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4496]!, self._r[4496]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4498]!, self._r[4498]!, [_1, _2]) } - public var GroupPermission_NoSendMedia: String { return self._s[4497]! } - public var Conversation_ClousStorageInfo_Description2: String { return self._s[4498]! } - public var SharedMedia_CategoryDocs: String { return self._s[4499]! } - public var Appearance_RemoveThemeConfirmation: String { return self._s[4500]! } - public var Paint_Framed: String { return self._s[4501]! } - public var Channel_EditAdmin_PermissionAddAdmins: String { return self._s[4502]! } - public var Passport_Identity_DoesNotExpire: String { return self._s[4503]! } - public var Channel_SignMessages: String { return self._s[4504]! } - public var Contacts_AccessDeniedHelpON: String { return self._s[4505]! } - public var Conversation_ContextMenuStickerPackInfo: String { return self._s[4506]! } + public var GroupPermission_NoSendMedia: String { return self._s[4499]! } + public var Conversation_ClousStorageInfo_Description2: String { return self._s[4500]! } + public var SharedMedia_CategoryDocs: String { return self._s[4501]! } + public var Appearance_RemoveThemeConfirmation: String { return self._s[4502]! } + public var Paint_Framed: String { return self._s[4503]! } + public var Channel_EditAdmin_PermissionAddAdmins: String { return self._s[4504]! } + public var Passport_Identity_DoesNotExpire: String { return self._s[4505]! } + public var Channel_SignMessages: String { return self._s[4506]! } + public var Contacts_AccessDeniedHelpON: String { return self._s[4507]! } + public var Conversation_ContextMenuStickerPackInfo: String { return self._s[4508]! } public func PUSH_CHAT_LEFT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4507]!, self._r[4507]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4509]!, self._r[4509]!, [_1, _2]) } - public var GroupInfo_UpgradeButton: String { return self._s[4508]! } - public var Channel_EditAdmin_PermissionInviteMembers: String { return self._s[4509]! } - public var AutoDownloadSettings_Files: String { return self._s[4510]! } + public var GroupInfo_UpgradeButton: String { return self._s[4510]! } + public var Channel_EditAdmin_PermissionInviteMembers: String { return self._s[4511]! } + public var AutoDownloadSettings_Files: String { return self._s[4512]! } public func Notification_ChangedGroupName(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4511]!, self._r[4511]!, [_0, _1]) + return formatWithArgumentRanges(self._s[4513]!, self._r[4513]!, [_0, _1]) } - public var Login_SendCodeViaSms: String { return self._s[4513]! } - public var Update_UpdateApp: String { return self._s[4514]! } - public var Channel_Setup_TypePublic: String { return self._s[4515]! } - public var Watch_Compose_CreateMessage: String { return self._s[4516]! } + public var Login_SendCodeViaSms: String { return self._s[4515]! } + public var Update_UpdateApp: String { return self._s[4516]! } + public var Channel_Setup_TypePublic: String { return self._s[4517]! } + public var Watch_Compose_CreateMessage: String { return self._s[4518]! } public func PUSH_CHAT_MESSAGE_VIDEOS(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4517]!, self._r[4517]!, [_1, _2, _3]) - } - public var StickerPacksSettings_ManagingHelp: String { return self._s[4518]! } - public func Wallet_Time_PreciseDate_m12(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[4519]!, self._r[4519]!, [_1, _2, _3]) } - public var VoiceOver_Chat_Video: String { return self._s[4520]! } - public var Forward_ChannelReadOnly: String { return self._s[4521]! } - public var StickerPack_HideStickers: String { return self._s[4522]! } - public var ChatListFolder_NameContacts: String { return self._s[4523]! } - public var Profile_BotInfo: String { return self._s[4524]! } - public var Document_TargetConfirmationFormat: String { return self._s[4525]! } - public var GroupInfo_InviteByLink: String { return self._s[4526]! } - public var Channel_AdminLog_BanSendStickersAndGifs: String { return self._s[4527]! } - public var Watch_Stickers_RecentPlaceholder: String { return self._s[4528]! } - public var Broadcast_AdminLog_EmptyText: String { return self._s[4529]! } - public var Passport_NotLoggedInMessage: String { return self._s[4530]! } - public var Conversation_StopQuizConfirmation: String { return self._s[4531]! } - public var Checkout_PaymentMethod: String { return self._s[4532]! } - public var ChatList_ArchivedChatsTitle: String { return self._s[4536]! } - public var TwoStepAuth_SetupPasswordConfirmFailed: String { return self._s[4537]! } - public var VoiceOver_Chat_RecordPreviewVoiceMessage: String { return self._s[4538]! } - public var PrivacyLastSeenSettings_GroupsAndChannelsHelp: String { return self._s[4539]! } - public var SettingsSearch_Synonyms_Privacy_Data_ContactsReset: String { return self._s[4540]! } - public var Camera_Title: String { return self._s[4541]! } - public var Map_Directions: String { return self._s[4542]! } - public var Wallet_Intro_ImportExisting: String { return self._s[4543]! } - public var Stats_MessagePublicForwardsTitle: String { return self._s[4544]! } - public var Privacy_ProfilePhoto_WhoCanSeeMyPhoto: String { return self._s[4546]! } - public var Profile_EncryptionKey: String { return self._s[4547]! } + public var StickerPacksSettings_ManagingHelp: String { return self._s[4520]! } + public func Wallet_Time_PreciseDate_m12(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[4521]!, self._r[4521]!, [_1, _2, _3]) + } + public var VoiceOver_Chat_Video: String { return self._s[4522]! } + public var Forward_ChannelReadOnly: String { return self._s[4523]! } + public var StickerPack_HideStickers: String { return self._s[4524]! } + public var ChatListFolder_NameContacts: String { return self._s[4525]! } + public var Profile_BotInfo: String { return self._s[4526]! } + public var Document_TargetConfirmationFormat: String { return self._s[4527]! } + public var GroupInfo_InviteByLink: String { return self._s[4528]! } + public var Channel_AdminLog_BanSendStickersAndGifs: String { return self._s[4529]! } + public var Watch_Stickers_RecentPlaceholder: String { return self._s[4530]! } + public var Broadcast_AdminLog_EmptyText: String { return self._s[4531]! } + public var Passport_NotLoggedInMessage: String { return self._s[4532]! } + public var Conversation_StopQuizConfirmation: String { return self._s[4533]! } + public var Checkout_PaymentMethod: String { return self._s[4534]! } + public var ChatList_ArchivedChatsTitle: String { return self._s[4538]! } + public var TwoStepAuth_SetupPasswordConfirmFailed: String { return self._s[4539]! } + public var VoiceOver_Chat_RecordPreviewVoiceMessage: String { return self._s[4540]! } + public var PrivacyLastSeenSettings_GroupsAndChannelsHelp: String { return self._s[4541]! } + public var SettingsSearch_Synonyms_Privacy_Data_ContactsReset: String { return self._s[4542]! } + public var Camera_Title: String { return self._s[4543]! } + public var Map_Directions: String { return self._s[4544]! } + public var Wallet_Intro_ImportExisting: String { return self._s[4545]! } + public var Stats_MessagePublicForwardsTitle: String { return self._s[4546]! } + public var Privacy_ProfilePhoto_WhoCanSeeMyPhoto: String { return self._s[4548]! } + public var Profile_EncryptionKey: String { return self._s[4549]! } public func LOCAL_CHAT_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4548]!, self._r[4548]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[4550]!, self._r[4550]!, [_1, "\(_2)"]) } public func Compatibility_SecretMediaVersionTooLow(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4549]!, self._r[4549]!, [_0, _1]) + return formatWithArgumentRanges(self._s[4551]!, self._r[4551]!, [_0, _1]) } - public var Passport_Identity_TypePassport: String { return self._s[4550]! } - public var CreatePoll_QuizOptionsHeader: String { return self._s[4552]! } - public var Common_No: String { return self._s[4553]! } - public var Conversation_SendMessage_ScheduleMessage: String { return self._s[4554]! } - public var SettingsSearch_Synonyms_Privacy_LastSeen: String { return self._s[4555]! } - public var Settings_AboutEmpty: String { return self._s[4556]! } - public var TwoStepAuth_FloodError: String { return self._s[4558]! } - public var SettingsSearch_Synonyms_Appearance_TextSize: String { return self._s[4559]! } + public var Passport_Identity_TypePassport: String { return self._s[4552]! } + public var CreatePoll_QuizOptionsHeader: String { return self._s[4554]! } + public var Common_No: String { return self._s[4555]! } + public var Conversation_SendMessage_ScheduleMessage: String { return self._s[4556]! } + public var SettingsSearch_Synonyms_Privacy_LastSeen: String { return self._s[4557]! } + public var Settings_AboutEmpty: String { return self._s[4558]! } + public var TwoStepAuth_FloodError: String { return self._s[4560]! } + public var SettingsSearch_Synonyms_Appearance_TextSize: String { return self._s[4561]! } public func Channel_AdminLog_MessageUnkickedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4561]!, self._r[4561]!, [_1]) + return formatWithArgumentRanges(self._s[4563]!, self._r[4563]!, [_1]) } - public var Conversation_Edit: String { return self._s[4564]! } - public var CheckoutInfo_SaveInfo: String { return self._s[4565]! } - public var VoiceOver_Chat_AnonymousPoll: String { return self._s[4566]! } - public var Call_CameraTooltip: String { return self._s[4568]! } - public var InstantPage_FeedbackButtonShort: String { return self._s[4569]! } - public var Contacts_InviteToTelegram: String { return self._s[4570]! } - public var Wallet_WordImport_CanNotRemember: String { return self._s[4571]! } - public var Notifications_ResetAllNotifications: String { return self._s[4572]! } - public var Calls_NewCall: String { return self._s[4573]! } - public var VoiceOver_Chat_Music: String { return self._s[4576]! } - public var Channel_Members_AddAdminErrorNotAMember: String { return self._s[4577]! } - public var Channel_Edit_AboutItem: String { return self._s[4578]! } - public var Message_VideoExpired: String { return self._s[4579]! } - public var Passport_Address_TypeTemporaryRegistrationUploadScan: String { return self._s[4580]! } + public var Conversation_Edit: String { return self._s[4566]! } + public var CheckoutInfo_SaveInfo: String { return self._s[4567]! } + public var VoiceOver_Chat_AnonymousPoll: String { return self._s[4568]! } + public var Call_CameraTooltip: String { return self._s[4570]! } + public var InstantPage_FeedbackButtonShort: String { return self._s[4571]! } + public var Contacts_InviteToTelegram: String { return self._s[4572]! } + public var Wallet_WordImport_CanNotRemember: String { return self._s[4573]! } + public var Notifications_ResetAllNotifications: String { return self._s[4574]! } + public var Calls_NewCall: String { return self._s[4575]! } + public var VoiceOver_Chat_Music: String { return self._s[4578]! } + public var Channel_Members_AddAdminErrorNotAMember: String { return self._s[4579]! } + public var Channel_Edit_AboutItem: String { return self._s[4580]! } + public var Message_VideoExpired: String { return self._s[4581]! } + public var Passport_Address_TypeTemporaryRegistrationUploadScan: String { return self._s[4582]! } public func PUSH_CHAT_RETURNED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4581]!, self._r[4581]!, [_1, _2]) + return formatWithArgumentRanges(self._s[4583]!, self._r[4583]!, [_1, _2]) } - public var NotificationsSound_Input: String { return self._s[4583]! } - public var Notifications_ClassicTones: String { return self._s[4584]! } - public var Conversation_StatusTyping: String { return self._s[4585]! } - public var Checkout_ErrorProviderAccountInvalid: String { return self._s[4586]! } - public var ChatSettings_AutoDownloadSettings_Delimeter: String { return self._s[4587]! } - public var Wallet_Month_ShortSeptember: String { return self._s[4588]! } - public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChats: String { return self._s[4589]! } - public var Conversation_MessageLeaveComment: String { return self._s[4590]! } - public var UserInfo_TapToCall: String { return self._s[4591]! } - public var EnterPasscode_EnterNewPasscodeNew: String { return self._s[4592]! } - public var Conversation_ClearAll: String { return self._s[4594]! } - public var UserInfo_NotificationsDefault: String { return self._s[4595]! } - public var Wallet_Send_OwnAddressAlertText: String { return self._s[4596]! } - public var Location_ProximityGroupTip: String { return self._s[4597]! } - public var Map_ChooseAPlace: String { return self._s[4598]! } + public var NotificationsSound_Input: String { return self._s[4585]! } + public var Notifications_ClassicTones: String { return self._s[4586]! } + public var Conversation_StatusTyping: String { return self._s[4587]! } + public var Checkout_ErrorProviderAccountInvalid: String { return self._s[4588]! } + public var ChatSettings_AutoDownloadSettings_Delimeter: String { return self._s[4589]! } + public var Wallet_Month_ShortSeptember: String { return self._s[4590]! } + public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChats: String { return self._s[4591]! } + public var Conversation_MessageLeaveComment: String { return self._s[4592]! } + public var UserInfo_TapToCall: String { return self._s[4593]! } + public var EnterPasscode_EnterNewPasscodeNew: String { return self._s[4594]! } + public var Conversation_ClearAll: String { return self._s[4596]! } + public var UserInfo_NotificationsDefault: String { return self._s[4597]! } + public var Wallet_Send_OwnAddressAlertText: String { return self._s[4598]! } + public var Location_ProximityGroupTip: String { return self._s[4599]! } + public var Map_ChooseAPlace: String { return self._s[4600]! } public func Wallet_Receive_ShareInvoiceUrlInfo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4599]!, self._r[4599]!, [_0]) + return formatWithArgumentRanges(self._s[4601]!, self._r[4601]!, [_0]) } - public var GroupInfo_AddParticipantTitle: String { return self._s[4600]! } - public var ChatList_PeerTypeNonContact: String { return self._s[4601]! } - public var Conversation_SlideToCancel: String { return self._s[4602]! } - public var Month_ShortJuly: String { return self._s[4603]! } - public var SocksProxySetup_ProxyType: String { return self._s[4604]! } + public var GroupInfo_AddParticipantTitle: String { return self._s[4602]! } + public var ChatList_PeerTypeNonContact: String { return self._s[4603]! } + public var Conversation_SlideToCancel: String { return self._s[4604]! } + public var Month_ShortJuly: String { return self._s[4605]! } + public var SocksProxySetup_ProxyType: String { return self._s[4606]! } public func ChatList_DeleteChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4605]!, self._r[4605]!, [_0]) + return formatWithArgumentRanges(self._s[4607]!, self._r[4607]!, [_0]) } - public var ChatList_EditFolders: String { return self._s[4606]! } - public var TwoStepAuth_SetPasswordHelp: String { return self._s[4607]! } - public var Wallet_Send_ConfirmationConfirm: String { return self._s[4609]! } - public var Wallet_Created_ExportErrorTitle: String { return self._s[4610]! } + public var ChatList_EditFolders: String { return self._s[4608]! } + public var TwoStepAuth_SetPasswordHelp: String { return self._s[4609]! } + public var Wallet_Send_ConfirmationConfirm: String { return self._s[4611]! } + public var Wallet_Created_ExportErrorTitle: String { return self._s[4612]! } public func GroupPermission_ApplyAlertText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[4611]!, self._r[4611]!, [_0]) - } - public var Permissions_PeopleNearbyTitle_v0: String { return self._s[4612]! } - public var ScheduledMessages_RemindersTitle: String { return self._s[4613]! } - public var Your_cards_expiration_year_is_invalid: String { return self._s[4614]! } - public var Wallet_Info_TransactionPendingHeader: String { return self._s[4616]! } - public var UserInfo_ShareMyContactInfo: String { return self._s[4617]! } - public var Passport_DeleteAddress: String { return self._s[4619]! } - public var Passport_DeletePassportConfirmation: String { return self._s[4620]! } - public var Passport_Identity_ReverseSide: String { return self._s[4621]! } - public var CheckoutInfo_ErrorEmailInvalid: String { return self._s[4622]! } - public var Login_InfoLastNamePlaceholder: String { return self._s[4623]! } - public var Passport_FieldAddress: String { return self._s[4624]! } - public var SettingsSearch_Synonyms_Calls_Title: String { return self._s[4625]! } - public var Passport_Identity_ResidenceCountryPlaceholder: String { return self._s[4627]! } - public var Map_Home: String { return self._s[4629]! } - public var PollResults_Title: String { return self._s[4630]! } - public var ArchivedChats_IntroText2: String { return self._s[4632]! } - public var PasscodeSettings_SimplePasscodeHelp: String { return self._s[4633]! } - public var VoiceOver_Chat_ContactPhoneNumber: String { return self._s[4634]! } - public var CallFeedback_ReasonSilentRemote: String { return self._s[4636]! } - public var Passport_Identity_AddPersonalDetails: String { return self._s[4638]! } - public var Group_Info_AdminLog: String { return self._s[4640]! } - public var ChatSettings_AutoPlayTitle: String { return self._s[4641]! } - public var Appearance_Animations: String { return self._s[4642]! } - public var Appearance_TextSizeSetting: String { return self._s[4643]! } - public func Stats_GroupTopPosterChars(_ 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 Chat_MessagesUnpinned(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ChatList_Search_Messages(_ 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 ForwardedStickers(_ 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 ForwardedPhotos(_ 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 ChatList_SelectedChats(_ 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 Conversation_TitleReplies(_ 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 MessageTimer_ShortWeeks(_ 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 ChatList_DeletedChats(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[8 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notification_GameScoreSelfExtended(_ 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 LastSeen_HoursAgo(_ 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 ForwardedLocations(_ 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 SharedMedia_DeleteItemsConfirmation(_ 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 MessagePoll_VotedCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[13 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[14 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func Conversation_ContextViewReplies(_ 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 ChatList_MessagePhotos(_ 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 VoiceOver_Chat_PollOptionCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[17 * 6 + Int(form.rawValue)]!, stringValue) + return formatWithArgumentRanges(self._s[4613]!, self._r[4613]!, [_0]) } + public var Permissions_PeopleNearbyTitle_v0: String { return self._s[4614]! } + public var ScheduledMessages_RemindersTitle: String { return self._s[4615]! } + public var Your_cards_expiration_year_is_invalid: String { return self._s[4616]! } + public var Wallet_Info_TransactionPendingHeader: String { return self._s[4618]! } + public var UserInfo_ShareMyContactInfo: String { return self._s[4619]! } + public var Passport_DeleteAddress: String { return self._s[4621]! } + public var Passport_DeletePassportConfirmation: String { return self._s[4622]! } + public var Passport_Identity_ReverseSide: String { return self._s[4623]! } + public var CheckoutInfo_ErrorEmailInvalid: String { return self._s[4624]! } + public var Login_InfoLastNamePlaceholder: String { return self._s[4625]! } + public var Passport_FieldAddress: String { return self._s[4626]! } + public var SettingsSearch_Synonyms_Calls_Title: String { return self._s[4627]! } + public var Passport_Identity_ResidenceCountryPlaceholder: String { return self._s[4629]! } + public var Map_Home: String { return self._s[4631]! } + public var PollResults_Title: String { return self._s[4632]! } + public var ArchivedChats_IntroText2: String { return self._s[4634]! } + public var PasscodeSettings_SimplePasscodeHelp: String { return self._s[4635]! } + public var VoiceOver_Chat_ContactPhoneNumber: String { return self._s[4636]! } + public var CallFeedback_ReasonSilentRemote: String { return self._s[4638]! } + public var Passport_Identity_AddPersonalDetails: String { return self._s[4640]! } + public var Group_Info_AdminLog: String { return self._s[4642]! } + public var ChatSettings_AutoPlayTitle: String { return self._s[4643]! } + public var Appearance_Animations: String { return self._s[4644]! } + public var Appearance_TextSizeSetting: String { return self._s[4645]! } public func PUSH_CHANNEL_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[18 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func AttachmentMenu_SendGif(_ 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 Contacts_ImportersCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[20 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Watch_LastSeen_MinutesAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[21 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ChatList_MessageFiles(_ 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 Stats_GroupTopAdminKicks(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[23 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessagePoll_QuizCount(_ 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 Call_Seconds(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[25 * 6 + Int(form.rawValue)]!, stringValue) - } - public func StickerPack_StickerCount(_ 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 ChatListFilter_ShowMoreChats(_ 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 MessageTimer_Days(_ 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 Stats_GroupTopPosterMessages(_ 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 MessageTimer_ShortDays(_ 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 Map_ETAMinutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[31 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Weeks(_ 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_MESSAGE_FWDS(_ 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 Conversation_StatusMembers(_ 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 MuteExpires_Days(_ 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 MessageTimer_ShortMinutes(_ 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 ForwardedAuthorsOthers(_ selector: Int32, _ _0: String, _ _1: String) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[37 * 6 + Int(form.rawValue)]!, _0, _1) - } - public func PUSH_CHANNEL_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[38 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func SharedMedia_Video(_ 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 CreatePoll_AddMoreOptions(_ 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 MuteFor_Days(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[41 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHANNEL_MESSAGE_DOCS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[42 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func ServiceMessage_GameScoreSelfSimple(_ 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 PasscodeSettings_FailedAttempts(_ 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 ForwardedPolls(_ 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 ForwardedVideoMessages(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[46 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Call_ShortMinutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[47 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Watch_UserInfo_Mute(_ 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 VoiceOver_Chat_ContactPhoneNumberCount(_ 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 ChatList_DeleteConfirmation(_ 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 SharedMedia_File(_ 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 VoiceOver_Chat_ContactEmailCount(_ 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 Stats_GroupShowMoreTopAdmins(_ 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 UserCount(_ 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 ServiceMessage_GameScoreSimple(_ 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 Notification_GameScoreSimple(_ 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 Notifications_ExceptionMuteExpires_Days(_ 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_FWDS(_ 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 PUSH_CHAT_MESSAGE_FWDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[59 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func ForwardedFiles(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[60 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MuteFor_Hours(_ 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 Chat_DeleteMessagesConfirmation(_ 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_CHANNEL_MESSAGES(_ 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 Wallet_Updated_MinutesAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[64 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedMessages(_ 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 Contacts_InviteContacts(_ 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 Media_ShareItem(_ 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 Media_ShareVideo(_ 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 Notification_GameScoreSelfSimple(_ 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 Stats_GroupShowMoreTopPosters(_ 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 StickerPack_RemoveMaskCount(_ 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 VoiceOver_Chat_PollVotes(_ 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 ServiceMessage_GameScoreSelfExtended(_ 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 Stats_MessageForwards(_ 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 PrivacyLastSeenSettings_AddUsers(_ 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 ForwardedContacts(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[76 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHANNEL_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[77 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func InstantPage_Views(_ 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_ShortSeconds(_ 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 PUSH_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[80 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func Conversation_TitleComments(_ 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 LiveLocation_MenuChatsCount(_ 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 StickerPack_AddStickerCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[83 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGES(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[84 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func ForwardedVideos(_ 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 AttachmentMenu_SendItem(_ 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 Conversation_LiveLocationMembersCount(_ 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 MuteExpires_Hours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[88 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Conversation_SelectedMessages(_ 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 Passport_Scans(_ 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 MessageTimer_Years(_ 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 ServiceMessage_GameScoreExtended(_ 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 Chat_TitlePinnedMessages(_ 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 Theme_UsersCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[94 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Seconds(_ 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 Call_Minutes(_ 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 Notifications_Exceptions(_ 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 PUSH_CHAT_MESSAGE_DOCS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[98 * 6 + Int(form.rawValue)]!, _2, _1, _3) + return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, _1, _2) } public func Stats_GroupTopAdminDeletions(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[99 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, stringValue) } - public func LiveLocationUpdated_MinutesAgo(_ 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[100 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[2 * 6 + Int(form.rawValue)]!, stringValue) } - public func PUSH_CHAT_MESSAGE_PHOTOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + public func Stats_GroupTopPosterChars(_ 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 Stats_GroupShowMoreTopInviters(_ 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 Media_ShareVideo(_ 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 Stats_GroupTopInviterInvites(_ 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_CHAT_MESSAGE_ROUNDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[101 * 6 + Int(form.rawValue)]!, _2, _1, _3) + return String(format: self._ps[7 * 6 + Int(form.rawValue)]!, _2, _1, _3) } - public func GroupInfo_ParticipantCount(_ 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[102 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[8 * 6 + Int(form.rawValue)]!, stringValue) } - public func Conversation_ContextMenuSelectAll(_ value: Int32) -> String { + public func MessageTimer_Days(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[103 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[9 * 6 + Int(form.rawValue)]!, stringValue) } - public func ChatList_MessageMusic(_ 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[104 * 6 + Int(form.rawValue)]!, stringValue) - } - public func AttachmentMenu_SendVideo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[105 * 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[106 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PollResults_ShowMore(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[107 * 6 + Int(form.rawValue)]!, stringValue) - } - public func OldChannels_Leave(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[108 * 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[109 * 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[110 * 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[111 * 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[112 * 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[113 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Forward_ConfirmMultipleFiles(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[114 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PeopleNearby_ShowMorePeople(_ 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 ChatList_MessageVideos(_ 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 PUSH_CHAT_MESSAGE_VIDEOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[117 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - 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[118 * 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[119 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[10 * 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[120 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[11 * 6 + Int(form.rawValue)]!, stringValue) } - public func QuickSend_Photos(_ value: Int32) -> String { + public func PUSH_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[12 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func StickerPack_AddStickerCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[121 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[13 * 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[14 * 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[15 * 6 + Int(form.rawValue)]!, stringValue) + } + public func StickerPack_RemoveStickerCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[16 * 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[17 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Stats_GroupShowMoreTopAdmins(_ 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 LiveLocation_MenuChatsCount(_ 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 ChatList_Search_Messages(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[20 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MuteExpires_Hours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[21 * 6 + Int(form.rawValue)]!, stringValue) } public func Map_ETAHours(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[122 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[22 * 6 + Int(form.rawValue)]!, stringValue) + } + public func InstantPage_Views(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[23 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ChatList_DeleteConfirmation(_ 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 Notifications_ExceptionMuteExpires_Hours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[25 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Conversation_ContextViewReplies(_ 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_File(_ 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 MessageTimer_Minutes(_ 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 MuteFor_Hours(_ 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 Contacts_InviteContacts(_ 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 Notifications_ExceptionMuteExpires_Days(_ 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 ForwardedAuthorsOthers(_ selector: Int32, _ _0: String, _ _1: String) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[32 * 6 + Int(form.rawValue)]!, _0, _1) + } + 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[33 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func ForwardedAudios(_ 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 SharedMedia_Photo(_ 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 QuickSend_Photos(_ 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 PeopleNearby_ShowMorePeople(_ 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 UserCount(_ 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 VoiceOver_Chat_PollVotes(_ 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 Chat_DeleteMessagesConfirmation(_ 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 Forward_ConfirmMultipleFiles(_ 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 Notification_GameScoreExtended(_ 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 MuteExpires_Days(_ 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 Chat_MessagesUnpinned(_ 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 ForwardedVideoMessages(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[45 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Years(_ 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 MessageTimer_ShortHours(_ 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 Chat_TitlePinnedMessages(_ 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 ForwardedLocations(_ 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 VoiceOver_Chat_ContactEmailCount(_ 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 Call_ShortSeconds(_ 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 ChatList_MessageFiles(_ 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 SharedMedia_Video(_ 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_ROUNDS(_ 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 MessageTimer_ShortDays(_ 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_StatusOnline(_ 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 Conversation_SelectedMessages(_ 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 Stats_GroupTopPosterMessages(_ 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 SharedMedia_Link(_ 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 MessageTimer_ShortMinutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[60 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Watch_UserInfo_Mute(_ 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 PUSH_CHANNEL_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[62 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func MuteFor_Days(_ 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 CreatePoll_AddMoreOptions(_ 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_Weeks(_ 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 MessageTimer_Seconds(_ 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 MessageTimer_ShortSeconds(_ 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 StickerPack_AddMaskCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[68 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Months(_ 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 ForwardedPolls(_ 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 PollResults_ShowMore(_ 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 PasscodeSettings_FailedAttempts(_ 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 PUSH_CHAT_MESSAGE_DOCS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[73 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func LastSeen_HoursAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[74 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGE_DOCS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[75 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func MessageTimer_ShortWeeks(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[76 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ChatListFilter_ShowMoreChats(_ 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 Call_Seconds(_ 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 ChatList_DeletedChats(_ 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 PUSH_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[80 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func ChatList_MessageMusic(_ 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 InviteText_ContactsCountText(_ 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 Call_Minutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[83 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[84 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func Conversation_StatusSubscribers(_ 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 PUSH_CHANNEL_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[86 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func AttachmentMenu_SendItem(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[87 * 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[88 * 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[89 * 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[90 * 6 + Int(form.rawValue)]!, stringValue) + } + public func GroupInfo_ParticipantCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[91 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedFiles(_ 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 ForwardedPhotos(_ 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 Media_ShareItem(_ 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 Wallpaper_DeleteConfirmation(_ 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 OldChannels_InactiveMonth(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[96 * 6 + Int(form.rawValue)]!, stringValue) + } + public func OldChannels_GroupFormat(_ 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 PUSH_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[98 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func PUSH_CHAT_MESSAGE_PHOTOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[99 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func AttachmentMenu_SendVideo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[100 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ServiceMessage_GameScoreExtended(_ 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 LastSeen_MinutesAgo(_ 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 ForwardedVideos(_ 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 SharedMedia_DeleteItemsConfirmation(_ 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 PrivacyLastSeenSettings_AddUsers(_ 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 Notification_GameScoreSelfSimple(_ 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 MessagePoll_QuizCount(_ 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 Wallet_Updated_MinutesAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[108 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Watch_LastSeen_HoursAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[109 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Passport_Scans(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[110 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Wallet_Updated_HoursAgo(_ 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 Conversation_TitleReplies(_ 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 Media_SharePhoto(_ 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 Notification_GameScoreSelfExtended(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[114 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Contacts_ImportersCount(_ 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 ServiceMessage_GameScoreSimple(_ 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 LiveLocationUpdated_MinutesAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[117 * 6 + Int(form.rawValue)]!, stringValue) } public func Stats_GroupTopAdminBans(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[123 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[118 * 6 + Int(form.rawValue)]!, stringValue) } - public func Invitation_Members(_ 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[124 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[119 * 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[120 * 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[121 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Conversation_TitleComments(_ 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 Notification_GameScoreSimple(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[123 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[124 * 6 + Int(form.rawValue)]!, _1, _2) } public func Conversation_MessageViewComments(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[125 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_Minutes(_ value: Int32) -> String { + public func AttachmentMenu_SendGif(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[126 * 6 + Int(form.rawValue)]!, stringValue) } - public func LastSeen_MinutesAgo(_ value: Int32) -> String { + public func Call_ShortMinutes(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[127 * 6 + Int(form.rawValue)]!, stringValue) } - public func Stats_MessageViews(_ value: Int32) -> String { + public func GroupInfo_ShowMoreMembers(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[128 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_ShortHours(_ value: Int32) -> String { + public func ForwardedMessages(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[129 * 6 + Int(form.rawValue)]!, stringValue) } - public func Stats_GroupTopInviterInvites(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[130 * 6 + Int(form.rawValue)]!, stringValue) - } - public func OldChannels_InactiveMonth(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[131 * 6 + Int(form.rawValue)]!, stringValue) + public func PUSH_CHANNEL_MESSAGE_DOCS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[130 * 6 + Int(form.rawValue)]!, _1, _2) } public func MessageTimer_Hours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[131 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ServiceMessage_GameScoreSelfExtended(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[132 * 6 + Int(form.rawValue)]!, stringValue) } - public func Notification_GameScoreExtended(_ value: Int32) -> String { + public func ChatList_MessagePhotos(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[133 * 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[134 * 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[134 * 6 + Int(form.rawValue)]!, _2, _1, _3) } - public func ForwardedAudios(_ value: Int32) -> String { + public func Conversation_StatusMembers(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[135 * 6 + Int(form.rawValue)]!, stringValue) } - public func Wallpaper_DeleteConfirmation(_ 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[136 * 6 + Int(form.rawValue)]!, stringValue) } - public func PUSH_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[137 * 6 + Int(form.rawValue)]!, _1, _2) + public func Stats_GroupShowMoreTopPosters(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[137 * 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[138 * 6 + Int(form.rawValue)]!, _1, _2) + public func Stats_MessageViews(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[138 * 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[139 * 6 + Int(form.rawValue)]!, _2, _1, _3) + public func ForwardedContacts(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[139 * 6 + Int(form.rawValue)]!, stringValue) } - public func Stats_GroupShowMoreTopInviters(_ value: Int32) -> String { + public func Stats_GroupTopAdminKicks(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[140 * 6 + Int(form.rawValue)]!, stringValue) } - public func Conversation_StatusSubscribers(_ value: Int32) -> String { + public func ForwardedGifs(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[141 * 6 + Int(form.rawValue)]!, stringValue) } - public func OldChannels_GroupFormat(_ value: Int32) -> String { + public func Stats_MessageForwards(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[142 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_Months(_ value: Int32) -> String { + public func Invitation_Members(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[143 * 6 + Int(form.rawValue)]!, stringValue) } - public func InviteText_ContactsCountText(_ value: Int32) -> String { + public func ForwardedStickers(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[144 * 6 + Int(form.rawValue)]!, stringValue) } - public func Conversation_StatusOnline(_ value: Int32) -> String { + public func ChatList_MessageVideos(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[145 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedGifs(_ value: Int32) -> String { + public func VoiceOver_Chat_PollOptionCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[146 * 6 + Int(form.rawValue)]!, stringValue) } - public func Watch_LastSeen_HoursAgo(_ value: Int32) -> String { + public func AttachmentMenu_SendPhoto(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[147 * 6 + Int(form.rawValue)]!, stringValue) } - public func Media_SharePhoto(_ value: Int32) -> String { + public func Conversation_ContextMenuSelectAll(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[148 * 6 + Int(form.rawValue)]!, stringValue) } - public func OldChannels_InactiveWeek(_ value: Int32) -> String { + public func MessagePoll_VotedCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[149 * 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[150 * 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[150 * 6 + Int(form.rawValue)]!, _1, _2) } - public func AttachmentMenu_SendPhoto(_ value: Int32) -> String { + public func Notifications_Exceptions(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[151 * 6 + Int(form.rawValue)]!, stringValue) } - public func StickerPack_RemoveStickerCount(_ value: Int32) -> String { + public func Conversation_LiveLocationMembersCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[152 * 6 + Int(form.rawValue)]!, stringValue) } - public func PUSH_MESSAGE_DOCS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[153 * 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[153 * 6 + Int(form.rawValue)]!, stringValue) } - public func Notifications_ExceptionMuteExpires_Hours(_ value: Int32) -> String { + 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[154 * 6 + Int(form.rawValue)]!, stringValue) diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Caption.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Caption.imageset/Contents.json new file mode 100644 index 0000000000..ebb7714e79 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Caption.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_menu_font1.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Caption.imageset/ic_menu_font1.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Caption.imageset/ic_menu_font1.pdf new file mode 100644 index 0000000000..3df88ff7e2 Binary files /dev/null and b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Caption.imageset/ic_menu_font1.pdf differ diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Draw.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Draw.imageset/Contents.json new file mode 100644 index 0000000000..e6a3712dd8 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Draw.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_menu_brush1.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Draw.imageset/ic_menu_brush1.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Draw.imageset/ic_menu_brush1.pdf new file mode 100644 index 0000000000..7e189831a4 Binary files /dev/null and b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Draw.imageset/ic_menu_brush1.pdf differ diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Replace.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Replace.imageset/Contents.json new file mode 100644 index 0000000000..f4b248a373 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Replace.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_menu_replace.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Replace.imageset/ic_menu_replace.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Replace.imageset/ic_menu_replace.pdf new file mode 100644 index 0000000000..182d7a0236 Binary files /dev/null and b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Replace.imageset/ic_menu_replace.pdf differ diff --git a/submodules/TelegramUI/Images.xcassets/Media Gallery/Contents.json b/submodules/TelegramUI/Images.xcassets/Media Gallery/Contents.json index 38f0c81fc2..6e965652df 100644 --- a/submodules/TelegramUI/Images.xcassets/Media Gallery/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Media Gallery/Contents.json @@ -1,9 +1,9 @@ { "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 }, "properties" : { "provides-namespace" : true } -} \ No newline at end of file +} diff --git a/submodules/TelegramUI/Images.xcassets/Media Gallery/Draw.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Media Gallery/Draw.imageset/Contents.json new file mode 100644 index 0000000000..0402056ad7 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Media Gallery/Draw.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_editor_brush1.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Media Gallery/Draw.imageset/ic_editor_brush1.pdf b/submodules/TelegramUI/Images.xcassets/Media Gallery/Draw.imageset/ic_editor_brush1.pdf new file mode 100644 index 0000000000..cafe10024a Binary files /dev/null and b/submodules/TelegramUI/Images.xcassets/Media Gallery/Draw.imageset/ic_editor_brush1.pdf differ diff --git a/submodules/TelegramUI/Images.xcassets/Settings/Permissions/Contents.json b/submodules/TelegramUI/Images.xcassets/Settings/Permissions/Contents.json index 38f0c81fc2..6e965652df 100644 --- a/submodules/TelegramUI/Images.xcassets/Settings/Permissions/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Settings/Permissions/Contents.json @@ -1,9 +1,9 @@ { "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 }, "properties" : { "provides-namespace" : true } -} \ No newline at end of file +} diff --git a/submodules/TelegramUI/Images.xcassets/Settings/Permissions/Siri.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Settings/Permissions/Siri.imageset/Contents.json deleted file mode 100644 index 5842000dfb..0000000000 --- a/submodules/TelegramUI/Images.xcassets/Settings/Permissions/Siri.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "Siri@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "Siri@3x.png", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Settings/Permissions/Siri.imageset/Siri@2x.png b/submodules/TelegramUI/Images.xcassets/Settings/Permissions/Siri.imageset/Siri@2x.png deleted file mode 100644 index 457b2d53c7..0000000000 Binary files a/submodules/TelegramUI/Images.xcassets/Settings/Permissions/Siri.imageset/Siri@2x.png and /dev/null differ diff --git a/submodules/TelegramUI/Images.xcassets/Settings/Permissions/Siri.imageset/Siri@3x.png b/submodules/TelegramUI/Images.xcassets/Settings/Permissions/Siri.imageset/Siri@3x.png deleted file mode 100644 index 3fc45952bc..0000000000 Binary files a/submodules/TelegramUI/Images.xcassets/Settings/Permissions/Siri.imageset/Siri@3x.png and /dev/null differ diff --git a/submodules/TelegramUI/Resources/PresentationStrings.mapping b/submodules/TelegramUI/Resources/PresentationStrings.mapping index af11113fbe..4f2616d403 100644 Binary files a/submodules/TelegramUI/Resources/PresentationStrings.mapping and b/submodules/TelegramUI/Resources/PresentationStrings.mapping differ diff --git a/submodules/TelegramUI/Sources/ChatBotInfoItem.swift b/submodules/TelegramUI/Sources/ChatBotInfoItem.swift index 7743358b27..e97d668d82 100644 --- a/submodules/TelegramUI/Sources/ChatBotInfoItem.swift +++ b/submodules/TelegramUI/Sources/ChatBotInfoItem.swift @@ -119,7 +119,7 @@ final class ChatBotInfoItemNode: ListViewItemNode { break case .ignore: return .fail - case .url, .peerMention, .textMention, .botCommand, .hashtag, .instantPage, .wallpaper, .theme, .call, .openMessage, .timecode, .bankCard, .tooltip, .openPollResults: + case .url, .peerMention, .textMention, .botCommand, .hashtag, .instantPage, .wallpaper, .theme, .call, .openMessage, .timecode, .bankCard, .tooltip, .openPollResults, .copy: return .waitForSingleTap } } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 8ba77a354d..3d973b4930 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -615,6 +615,47 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G storedState = MediaPlaybackStoredState(timestamp: timestamp, playbackRate: .x1) } let _ = updateMediaPlaybackStoredStateInteractively(postbox: strongSelf.context.account.postbox, messageId: messageId, state: storedState).start() + }, editMedia: { [weak self] messageId in + guard let strongSelf = self else { + return + } + + let _ = (strongSelf.context.account.postbox.transaction { transaction -> Message? in + return transaction.getMessage(messageId) + } |> deliverOnMainQueue).start(next: { [weak self] message in + guard let strongSelf = self, let message = message else { + return + } + + var mediaReference: AnyMediaReference? + for m in message.media { + if let image = m as? TelegramMediaImage { + mediaReference = AnyMediaReference.standalone(media: image) + } + } + + if let mediaReference = mediaReference, let peer = message.peers[message.id.peerId] { + legacyMediaEditor(context: strongSelf.context, peer: peer, media: mediaReference, initialCaption: message.text, presentStickers: { [weak self] completion in + if let strongSelf = self { + let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, node, rect in + completion(fileReference.media, fileReference.media.isAnimatedSticker, node.view, rect) + return true + }) + strongSelf.present(controller, in: .window(.root)) + return controller + } else { + return nil + } + }, sendMessagesWithSignals: { [weak self] signals, _, _ in + if let strongSelf = self { + strongSelf.interfaceInteraction?.setupEditMessage(messageId, { _ in }) + strongSelf.editMessageMediaWithLegacySignals(signals!) + } + }, present: { [weak self] c, a in + self?.present(c, in: .window(.root), with: a) + }) + } + }) }))) }, openPeer: { [weak self] id, navigation, fromMessage in self?.openPeer(peerId: id, navigation: navigation, fromMessage: fromMessage) @@ -643,7 +684,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G break } } - let _ = combineLatest(queue: .mainQueue(), contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState: strongSelf.presentationInterfaceState, context: strongSelf.context, messages: updatedMessages, controllerInteraction: strongSelf.controllerInteraction, selectAll: selectAll, interfaceInteraction: strongSelf.interfaceInteraction), loadedStickerPack(postbox: strongSelf.context.account.postbox, network: strongSelf.context.account.network, reference: .animatedEmoji, forceActualized: false), ApplicationSpecificNotice.getChatTextSelectionTips(accountManager: strongSelf.context.sharedContext.accountManager) + let _ = combineLatest(queue: .mainQueue(), contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState: strongSelf.presentationInterfaceState, context: strongSelf.context, messages: updatedMessages, controllerInteraction: strongSelf.controllerInteraction, selectAll: selectAll, interfaceInteraction: strongSelf.interfaceInteraction), loadedStickerPack(postbox: strongSelf.context.account.postbox, network: strongSelf.context.account.network, reference: .animatedEmoji, forceActualized: false), ApplicationSpecificNotice.getChatTextSelectionTips(accountManager: strongSelf.context.sharedContext.accountManager) ).start(next: { actions, animatedEmojiStickers, chatTextSelectionTips in guard let strongSelf = self, !actions.isEmpty else { return @@ -2275,6 +2316,65 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } strongSelf.push(messageStatsController(context: context, messageId: id, cachedPeerData: cachedPeerData)) }) + }, editMessageMedia: { [weak self] messageId, draw in + guard let strongSelf = self else { + return + } + + strongSelf.chatDisplayNode.dismissInput() + + if draw { + let _ = (strongSelf.context.account.postbox.transaction { transaction -> Message? in + return transaction.getMessage(messageId) + } |> deliverOnMainQueue).start(next: { [weak self] message in + guard let strongSelf = self, let message = message else { + return + } + + var mediaReference: AnyMediaReference? + for m in message.media { + if let image = m as? TelegramMediaImage { + mediaReference = AnyMediaReference.standalone(media: image) + } + } + + if let mediaReference = mediaReference, let peer = message.peers[message.id.peerId] { + legacyMediaEditor(context: strongSelf.context, peer: peer, media: mediaReference, initialCaption: message.text, presentStickers: { [weak self] completion in + if let strongSelf = self { + let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, node, rect in + completion(fileReference.media, fileReference.media.isAnimatedSticker, node.view, rect) + return true + }) + strongSelf.present(controller, in: .window(.root)) + return controller + } else { + return nil + } + }, sendMessagesWithSignals: { [weak self] signals, _, _ in + if let strongSelf = self { + strongSelf.interfaceInteraction?.setupEditMessage(messageId, { _ in }) + strongSelf.editMessageMediaWithLegacySignals(signals!) + } + }, present: { [weak self] c, a in + self?.present(c, in: .window(.root), with: a) + }) + } + }) + } else { + strongSelf.presentMediaPicker(fileMode: false, editingMedia: true, completion: { signals, _, _ in + self?.interfaceInteraction?.setupEditMessage(messageId, { _ in }) + self?.editMessageMediaWithLegacySignals(signals) + }) + } + }, copyText: { [weak self] text in + if let strongSelf = self { + storeMessageTextInPasteboard(text, entities: nil) + + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .succeed(text: presentationData.strings.Conversation_TextCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in + return true + }), in: .current) + } }, requestMessageUpdate: { [weak self] id in if let strongSelf = self { strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(id) @@ -4326,7 +4426,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G break } } - var inputTextMaxLength: Int32? + var inputTextMaxLength: Int32 = 4096 for media in message.media { if media is TelegramMediaImage || media is TelegramMediaFile { inputTextMaxLength = strongSelf.context.currentLimitsConfiguration.with { $0 }.maxMediaCaptionLength diff --git a/submodules/TelegramUI/Sources/ChatControllerInteraction.swift b/submodules/TelegramUI/Sources/ChatControllerInteraction.swift index d6b1b7ea43..ed9093bba4 100644 --- a/submodules/TelegramUI/Sources/ChatControllerInteraction.swift +++ b/submodules/TelegramUI/Sources/ChatControllerInteraction.swift @@ -116,6 +116,8 @@ public final class ChatControllerInteraction { let openMessageReplies: (MessageId, Bool, Bool) -> Void let openReplyThreadOriginalMessage: (Message) -> Void let openMessageStats: (MessageId) -> Void + let editMessageMedia: (MessageId, Bool) -> Void + let copyText: (String) -> Void let requestMessageUpdate: (MessageId) -> Void let cancelInteractiveKeyboardGestures: () -> Void @@ -203,6 +205,8 @@ public final class ChatControllerInteraction { openMessageReplies: @escaping (MessageId, Bool, Bool) -> Void, openReplyThreadOriginalMessage: @escaping (Message) -> Void, openMessageStats: @escaping (MessageId) -> Void, + editMessageMedia: @escaping (MessageId, Bool) -> Void, + copyText: @escaping (String) -> Void, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, automaticMediaDownloadSettings: MediaAutoDownloadSettings, @@ -277,6 +281,8 @@ public final class ChatControllerInteraction { self.openMessageReplies = openMessageReplies self.openReplyThreadOriginalMessage = openReplyThreadOriginalMessage self.openMessageStats = openMessageStats + self.editMessageMedia = editMessageMedia + self.copyText = copyText self.requestMessageUpdate = requestMessageUpdate self.cancelInteractiveKeyboardGestures = cancelInteractiveKeyboardGestures @@ -328,6 +334,8 @@ public final class ChatControllerInteraction { }, openMessageReplies: { _, _, _ in }, openReplyThreadOriginalMessage: { _ in }, openMessageStats: { _ in + }, editMessageMedia: { _, _ in + }, copyText: { _ in }, requestMessageUpdate: { _ in }, cancelInteractiveKeyboardGestures: { }, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 2eafbe9ccd..2c75544895 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -493,7 +493,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.inputPanelBackgroundSeparatorNode.backgroundColor = self.chatPresentationInterfaceState.theme.chat.inputPanel.panelSeparatorColor self.inputPanelBackgroundSeparatorNode.isLayerBacked = true - self.navigateButtons = ChatHistoryNavigationButtons(theme: self.chatPresentationInterfaceState.theme) + self.navigateButtons = ChatHistoryNavigationButtons(theme: self.chatPresentationInterfaceState.theme, dateTimeFormat: self.chatPresentationInterfaceState.dateTimeFormat) self.navigateButtons.accessibilityElementsHidden = true self.navigationBarBackroundNode = ASDisplayNode() @@ -1919,7 +1919,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { let updateInputTextState = self.chatPresentationInterfaceState.interfaceState.effectiveInputState != chatPresentationInterfaceState.interfaceState.effectiveInputState self.chatPresentationInterfaceState = chatPresentationInterfaceState - self.navigateButtons.updateTheme(theme: chatPresentationInterfaceState.theme) + self.navigateButtons.update(theme: chatPresentationInterfaceState.theme, dateTimeFormat: chatPresentationInterfaceState.dateTimeFormat) if themeUpdated { if case let .color(color) = self.chatPresentationInterfaceState.chatWallpaper, UIColor(rgb: color).isEqual(self.chatPresentationInterfaceState.theme.chat.inputPanel.panelBackgroundColorNoWallpaper) { diff --git a/submodules/TelegramUI/Sources/ChatHistoryNavigationButtons.swift b/submodules/TelegramUI/Sources/ChatHistoryNavigationButtons.swift index 90103f08e3..0cbd2d86a5 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryNavigationButtons.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryNavigationButtons.swift @@ -6,6 +6,7 @@ import TelegramPresentationData final class ChatHistoryNavigationButtons: ASDisplayNode { private var theme: PresentationTheme + private var dateTimeFormat: PresentationDateTimeFormat private let mentionsButton: ChatHistoryNavigationButtonNode private let mentionsButtonTapNode: ASDisplayNode @@ -31,7 +32,7 @@ final class ChatHistoryNavigationButtons: ASDisplayNode { var unreadCount: Int32 = 0 { didSet { if self.unreadCount != 0 { - self.downButton.badge = "\(self.unreadCount)" + self.downButton.badge = compactNumericCountString(Int(self.unreadCount), decimalSeparator: self.dateTimeFormat.decimalSeparator) } else { self.downButton.badge = "" } @@ -41,7 +42,7 @@ final class ChatHistoryNavigationButtons: ASDisplayNode { var mentionCount: Int32 = 0 { didSet { if self.mentionCount != 0 { - self.mentionsButton.badge = "\(self.mentionCount)" + self.mentionsButton.badge = compactNumericCountString(Int(self.mentionCount), decimalSeparator: self.dateTimeFormat.decimalSeparator) } else { self.mentionsButton.badge = "" } @@ -52,8 +53,9 @@ final class ChatHistoryNavigationButtons: ASDisplayNode { } } - init(theme: PresentationTheme) { + init(theme: PresentationTheme, dateTimeFormat: PresentationDateTimeFormat) { self.theme = theme + self.dateTimeFormat = dateTimeFormat self.mentionsButton = ChatHistoryNavigationButtonNode(theme: theme, type: .mentions) self.mentionsButton.alpha = 0.0 @@ -81,9 +83,10 @@ final class ChatHistoryNavigationButtons: ASDisplayNode { self.mentionsButtonTapNode.view.addGestureRecognizer(tapRecognizer) } - func updateTheme(theme: PresentationTheme) { - if self.theme !== theme { + func update(theme: PresentationTheme, dateTimeFormat: PresentationDateTimeFormat) { + if self.theme !== theme || self.dateTimeFormat != dateTimeFormat { self.theme = theme + self.dateTimeFormat = dateTimeFormat self.mentionsButton.updateTheme(theme: theme) self.downButton.updateTheme(theme: theme) diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift index 7a7c16a30a..3755ac4861 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift @@ -276,7 +276,7 @@ func updatedChatEditInterfaceMessageState(state: ChatPresentationInterfaceState, return updated } -func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, messages: [Message], controllerInteraction: ChatControllerInteraction?, selectAll: Bool, interfaceInteraction: ChatPanelInterfaceInteraction?) -> Signal<[ContextMenuItem], NoError> { +func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, messages: [Message], controllerInteraction: ChatControllerInteraction?, selectAll: Bool, interfaceInteraction: ChatPanelInterfaceInteraction?) -> Signal<[ContextMenuItem], NoError> { guard let interfaceInteraction = interfaceInteraction, let controllerInteraction = controllerInteraction else { return .single([]) } @@ -643,6 +643,17 @@ func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState: } if data.canEdit && !isPinnedMessages { + var mediaReference: AnyMediaReference? + for media in message.media { + if let image = media as? TelegramMediaImage, let _ = largestImageRepresentation(image.representations) { + mediaReference = ImageMediaReference.standalone(media: image).abstract + break + } else if let file = media as? TelegramMediaFile { + mediaReference = FileMediaReference.standalone(media: file).abstract + break + } + } + actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_MessageDialogEdit, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Edit"), color: theme.actionSheet.primaryTextColor) }, action: { _, f in @@ -763,7 +774,7 @@ func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState: let presentationData = context.sharedContext.currentPresentationData.with { $0 } var warnAboutPrivate = false - if case let .peer = chatPresentationInterfaceState.chatLocation { + if case .peer = chatPresentationInterfaceState.chatLocation { if channel.addressName == nil { warnAboutPrivate = true } diff --git a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift index 00601fe12a..1a3247afc9 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift @@ -146,19 +146,7 @@ func preparedChatMediaInputGridEntryTransition(account: Account, view: ItemColle firstIndexInSectionOffset = Int(index.itemIndex.index) } } - - if case .initial = update { - switch toEntries[0].index { - case .search: - if toEntries.count > 1 { - //scrollToItem = GridNodeScrollToItem(index: 1, position: .top, transition: .immediate, directionHint: .up, adjustForSection: true) - } - break - default: - break - } - } - + let opaqueState = ChatMediaInputStickerPaneOpaqueState(hasLower: view.lower != nil) return ChatMediaInputGridTransition(deletions: deletions, insertions: insertions, updates: updates, updateFirstIndexInSectionOffset: firstIndexInSectionOffset, stationaryItems: stationaryItems, scrollToItem: scrollToItem, updateOpaqueState: opaqueState, animated: animated) diff --git a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift index 9b895fd2d8..6465a70e05 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift @@ -190,7 +190,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { self.containerNode = ContextControllerSourceNode() self.imageNode = TransformImageNode() self.dateAndStatusNode = ChatMessageDateAndStatusNode() - + super.init(layerBacked: false) self.containerNode.shouldBegin = { [weak self] location in @@ -1117,7 +1117,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { switch recognizer.state { case .ended: if let (gesture, location) = recognizer.lastRecognizedGestureAndLocation { - if let action = self.gestureRecognized(gesture: gesture, location: location, recognizer: nil) { + if let action = self.gestureRecognized(gesture: gesture, location: location, recognizer: recognizer) { if case .doubleTap = gesture { self.containerNode.cancelGesture() } @@ -1224,7 +1224,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { item.controllerInteraction.displayDiceTooltip(dice) }) } else if let _ = self.emojiFile { - if let animationNode = self.animationNode as? AnimatedStickerNode { + if let animationNode = self.animationNode as? AnimatedStickerNode, let _ = recognizer { var startTime: Signal var shouldPlay = false if !animationNode.isPlaying { @@ -1248,86 +1248,63 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { } if let text = self.item?.message.text, let firstScalar = text.unicodeScalars.first { - if beatingHearts.contains(firstScalar.value) || firstScalar.value == peach { + return .optionalAction({ if shouldPlay { - animationNode.play() - } - return .optionalAction({ - let _ = startTime.start(next: { [weak self] time in + let _ = (appConfiguration + |> deliverOnMainQueue).start(next: { [weak self, weak animationNode] appConfiguration in guard let strongSelf = self else { return } - - var haptic: EmojiHaptic - if let current = strongSelf.haptic { - haptic = current - } else { - if beatingHearts.contains(firstScalar.value) { - haptic = HeartbeatHaptic() - } else { - haptic = PeachHaptic() - } - haptic.enabled = true - strongSelf.haptic = haptic - } - if !haptic.active { - haptic.start(time: time) - } - }) - }) - } else { - return .optionalAction({ - if shouldPlay { - let _ = (appConfiguration - |> deliverOnMainQueue).start(next: { [weak self, weak animationNode] appConfiguration in - guard let strongSelf = self else { - return - } - let emojiSounds = AnimatedEmojiSoundsConfiguration.with(appConfiguration: appConfiguration, account: item.context.account) - for (emoji, file) in emojiSounds.sounds { - if emoji.unicodeScalars.first == firstScalar { - let mediaManager = item.context.sharedContext.mediaManager - let mediaPlayer = MediaPlayer(audioSessionManager: mediaManager.audioSession, postbox: item.context.account.postbox, resourceReference: .standalone(resource: file.resource), streamable: .none, video: false, preferSoftwareDecoding: false, enableSound: true, fetchAutomatically: true, ambient: true) - mediaPlayer.togglePlayPause() - mediaPlayer.actionAtEnd = .action({ [weak self] in - self?.mediaPlayer = nil - }) - strongSelf.mediaPlayer = mediaPlayer - - strongSelf.mediaStatusDisposable.set((mediaPlayer.status - |> deliverOnMainQueue).start(next: { [weak self, weak animationNode] status in - if let strongSelf = self { - if firstScalar.value == coffin { - var haptic: EmojiHaptic - if let current = strongSelf.haptic { - haptic = current - } else { + let emojiSounds = AnimatedEmojiSoundsConfiguration.with(appConfiguration: appConfiguration, account: item.context.account) + for (emoji, file) in emojiSounds.sounds { + if emoji.strippedEmoji == text.strippedEmoji { + let mediaManager = item.context.sharedContext.mediaManager + let mediaPlayer = MediaPlayer(audioSessionManager: mediaManager.audioSession, postbox: item.context.account.postbox, resourceReference: .standalone(resource: file.resource), streamable: .none, video: false, preferSoftwareDecoding: false, enableSound: true, fetchAutomatically: true, ambient: true) + mediaPlayer.togglePlayPause() + mediaPlayer.actionAtEnd = .action({ [weak self] in + self?.mediaPlayer = nil + }) + strongSelf.mediaPlayer = mediaPlayer + + strongSelf.mediaStatusDisposable.set((mediaPlayer.status + |> deliverOnMainQueue).start(next: { [weak self, weak animationNode] status in + if let strongSelf = self { + if firstScalar.value == coffin || firstScalar.value == peach { + var haptic: EmojiHaptic + if let current = strongSelf.haptic { + haptic = current + } else { + if beatingHearts.contains(firstScalar.value) { + haptic = HeartbeatHaptic() + } else if firstScalar.value == coffin { haptic = CoffinHaptic() - haptic.enabled = true - strongSelf.haptic = haptic - } - if !haptic.active { - haptic.start(time: 0.0) + } else { + haptic = PeachHaptic() } + haptic.enabled = true + strongSelf.haptic = haptic } - - switch status.status { - case .playing: - animationNode?.play() - strongSelf.mediaStatusDisposable.set(nil) - default: - break + if !haptic.active { + haptic.start(time: 0.0) } } - })) - return - } + + switch status.status { + case .playing: + animationNode?.play() + strongSelf.mediaStatusDisposable.set(nil) + default: + break + } + } + })) + return } - animationNode?.play() - }) - } - }) - } + } + animationNode?.play() + }) + } + }) } } } diff --git a/submodules/TelegramUI/Sources/ChatMessageBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageBubbleContentNode.swift index 3aaefaea07..323e2a7b45 100644 --- a/submodules/TelegramUI/Sources/ChatMessageBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageBubbleContentNode.swift @@ -97,6 +97,7 @@ enum ChatMessageBubbleContentTapAction { case bankCard(String) case ignore case openPollResults(Data) + case copy(String) } final class ChatMessageBubbleContentItem { diff --git a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift index effd6a8f2d..9df3dbb7ff 100644 --- a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift @@ -643,7 +643,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode break case .ignore: return .fail - case .url, .peerMention, .textMention, .botCommand, .hashtag, .instantPage, .wallpaper, .theme, .call, .openMessage, .timecode, .bankCard, .tooltip, .openPollResults: + case .url, .peerMention, .textMention, .botCommand, .hashtag, .instantPage, .wallpaper, .theme, .call, .openMessage, .timecode, .bankCard, .tooltip, .openPollResults, .copy: return .waitForSingleTap } } @@ -3122,6 +3122,12 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode item.controllerInteraction.openMessagePollResults(item.message.id, option) }) } + case let .copy(text): + if let item = self.item { + return .optionalAction({ + item.controllerInteraction.copyText(text) + }) + } } } return nil @@ -3198,6 +3204,8 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode break case .openPollResults: break + case .copy: + break } } if let tapMessage = tapMessage { diff --git a/submodules/TelegramUI/Sources/ChatMessageInteractiveFileNode.swift b/submodules/TelegramUI/Sources/ChatMessageInteractiveFileNode.swift index 2dca499f43..e894620c02 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInteractiveFileNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInteractiveFileNode.swift @@ -940,6 +940,8 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { self.streamingStatusNode = streamingStatusNode streamingStatusNode.frame = streamingCacheStatusFrame self.addSubnode(streamingStatusNode) + } else if let streamingStatusNode = self.streamingStatusNode { + streamingStatusNode.backgroundNodeColor = backgroundNodeColor } if let statusNode = self.statusNode { diff --git a/submodules/TelegramUI/Sources/ChatMessageItem.swift b/submodules/TelegramUI/Sources/ChatMessageItem.swift index b704489ea5..546e288117 100644 --- a/submodules/TelegramUI/Sources/ChatMessageItem.swift +++ b/submodules/TelegramUI/Sources/ChatMessageItem.swift @@ -349,7 +349,7 @@ public final class ChatMessageItem: ListViewItem, CustomStringConvertible { loop: for media in self.message.media { if let telegramFile = media as? TelegramMediaFile { - if telegramFile.isAnimatedSticker, (self.message.id.peerId.namespace == Namespaces.Peer.SecretChat || !telegramFile.previewRepresentations.isEmpty), let size = telegramFile.size, size > 0 && size <= 128 * 1024 { + if telegramFile.isAnimatedSticker, let size = telegramFile.size, size > 0 && size <= 128 * 1024 { if self.message.id.peerId.namespace == Namespaces.Peer.SecretChat { if telegramFile.fileId.namespace == Namespaces.Media.CloudFile { var isValidated = false diff --git a/submodules/TelegramUI/Sources/ChatMessageNotificationItem.swift b/submodules/TelegramUI/Sources/ChatMessageNotificationItem.swift index e5aa07c7fa..a5d3a5e03b 100644 --- a/submodules/TelegramUI/Sources/ChatMessageNotificationItem.swift +++ b/submodules/TelegramUI/Sources/ChatMessageNotificationItem.swift @@ -248,6 +248,24 @@ final class ChatMessageNotificationItemNode: NotificationItemNode { title = nil messageText = rawText } + case .video: + let rawText = presentationData.strings.PUSH_CHANNEL_MESSAGE_VIDEOS(Int32(item.messages.count), peer.displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder), Int32(item.messages.count)) + if let index = rawText.firstIndex(of: "|") { + title = String(rawText[rawText.startIndex ..< index]) + messageText = String(rawText[rawText.index(after: index)...]) + } else { + title = nil + messageText = rawText + } + case .file: + let rawText = presentationData.strings.PUSH_CHANNEL_MESSAGE_DOCS(Int32(item.messages.count), peer.displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder), Int32(item.messages.count)) + if let index = rawText.firstIndex(of: "|") { + title = String(rawText[rawText.startIndex ..< index]) + messageText = String(rawText[rawText.index(after: index)...]) + } else { + title = nil + messageText = rawText + } default: let rawText = presentationData.strings.PUSH_CHANNEL_MESSAGES(Int32(item.messages.count), peer.displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder), Int32(item.messages.count)) if let index = rawText.firstIndex(of: "|") { @@ -272,6 +290,24 @@ final class ChatMessageNotificationItemNode: NotificationItemNode { title = nil messageText = rawText } + case .video: + let rawText = presentationData.strings.PUSH_CHAT_MESSAGE_VIDEOS(Int32(item.messages.count), author.compactDisplayTitle, peer.displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder), Int32(item.messages.count)) + if let index = rawText.firstIndex(of: "|") { + title = String(rawText[rawText.startIndex ..< index]) + messageText = String(rawText[rawText.index(after: index)...]) + } else { + title = nil + messageText = rawText + } + case .file: + let rawText = presentationData.strings.PUSH_CHAT_MESSAGE_DOCS(Int32(item.messages.count), author.compactDisplayTitle, peer.displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder), Int32(item.messages.count)) + if let index = rawText.firstIndex(of: "|") { + title = String(rawText[rawText.startIndex ..< index]) + messageText = String(rawText[rawText.index(after: index)...]) + } else { + title = nil + messageText = rawText + } default: let rawText = presentationData.strings.PUSH_CHAT_MESSAGES(Int32(item.messages.count), author.compactDisplayTitle, peer.displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder), Int32(item.messages.count)) if let index = rawText.firstIndex(of: "|") { @@ -293,6 +329,24 @@ final class ChatMessageNotificationItemNode: NotificationItemNode { title = nil messageText = rawText } + case .video: + let rawText = presentationData.strings.PUSH_MESSAGE_VIDEOS(Int32(item.messages.count), peer.displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder), Int32(item.messages.count)) + if let index = rawText.firstIndex(of: "|") { + title = String(rawText[rawText.startIndex ..< index]) + messageText = String(rawText[rawText.index(after: index)...]) + } else { + title = nil + messageText = rawText + } + case .file: + let rawText = presentationData.strings.PUSH_MESSAGE_DOCS(Int32(item.messages.count), peer.displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder), Int32(item.messages.count)) + if let index = rawText.firstIndex(of: "|") { + title = String(rawText[rawText.startIndex ..< index]) + messageText = String(rawText[rawText.index(after: index)...]) + } else { + title = nil + messageText = rawText + } default: let rawText = presentationData.strings.PUSH_MESSAGES(Int32(item.messages.count), peer.displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder), Int32(item.messages.count)) if let index = rawText.firstIndex(of: "|") { diff --git a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift index 91dc7b9678..f54ab56e51 100644 --- a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift @@ -450,6 +450,8 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { return .timecode(timecode.time, timecode.text) } else if let bankCard = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.BankCard)] as? String { return .bankCard(bankCard) + } else if let pre = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.Pre)] as? String { + return .copy(pre) } else { return .none } diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift index eae9201b4a..54c2bcb967 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift @@ -455,6 +455,8 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { }, openMessageReplies: { _, _, _ in }, openReplyThreadOriginalMessage: { _ in }, openMessageStats: { _ in + }, editMessageMedia: { _, _ in + }, copyText: { _ in }, requestMessageUpdate: { _ in }, cancelInteractiveKeyboardGestures: { }, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings, diff --git a/submodules/TelegramUI/Sources/ChatTextInputActionButtonsNode.swift b/submodules/TelegramUI/Sources/ChatTextInputActionButtonsNode.swift index 514f8698d2..ac26274088 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputActionButtonsNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputActionButtonsNode.swift @@ -31,8 +31,6 @@ final class ChatTextInputActionButtonsNode: ASDisplayNode { self.micButton = ChatTextInputMediaRecordingButton(theme: theme, strings: strings, presentController: presentController) self.sendButton = HighlightTrackingButtonNode(pointerStyle: .lift) - //self.sendButton.adjustsImageWhenHighlighted = false - //self.sendButton.adjustsImageWhenDisabled = false self.expandMediaInputButton = HighlightableButtonNode(pointerStyle: .default) diff --git a/submodules/TelegramUI/Sources/DrawingStickersScreen.swift b/submodules/TelegramUI/Sources/DrawingStickersScreen.swift index 110bdf9431..cb4eca5ec0 100644 --- a/submodules/TelegramUI/Sources/DrawingStickersScreen.swift +++ b/submodules/TelegramUI/Sources/DrawingStickersScreen.swift @@ -148,6 +148,8 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode { }, openMessageReplies: { _, _, _ in }, openReplyThreadOriginalMessage: { _ in }, openMessageStats: { _ in + }, editMessageMedia: { _, _ in + }, copyText: { _ in }, requestMessageUpdate: { _ in }, cancelInteractiveKeyboardGestures: { }, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, diff --git a/submodules/TelegramUI/Sources/OpenChatMessage.swift b/submodules/TelegramUI/Sources/OpenChatMessage.swift index 99d23e3b4b..47ce3c94ec 100644 --- a/submodules/TelegramUI/Sources/OpenChatMessage.swift +++ b/submodules/TelegramUI/Sources/OpenChatMessage.swift @@ -114,7 +114,15 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool { let controller = ShareController(context: params.context, subject: .media(.standalone(media: file)), immediateExternalShare: true) params.present(controller, nil) } else if let rootController = params.navigationController?.view.window?.rootViewController { - presentDocumentPreviewController(rootController: rootController, theme: presentationData.theme, strings: presentationData.strings, postbox: params.context.account.postbox, file: file) + let proceed = { + presentDocumentPreviewController(rootController: rootController, theme: presentationData.theme, strings: presentationData.strings, postbox: params.context.account.postbox, file: file) + } + if file.mimeType.contains("image/svg") { + let presentationData = params.context.sharedContext.currentPresentationData.with { $0 } + params.present(textAlertController(context: params.context, title: nil, text: presentationData.strings.OpenFile_PotentiallyDangerousContentAlert, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: presentationData.strings.OpenFile_Proceed, action: { proceed() })] ), nil) + } else { + proceed() + } } return true case let .audio(file): @@ -217,9 +225,7 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool { let path = params.context.account.postbox.mediaBox.completedResourcePath(media.resource) var previewTheme: PresentationTheme? if let path = path, let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe) { - let startTime = CACurrentMediaTime() previewTheme = makePresentationTheme(data: data) - print("time \(CACurrentMediaTime() - startTime)") } guard let theme = previewTheme else { @@ -306,6 +312,8 @@ func openChatTheme(context: AccountContext, message: Message, pushController: @e } else { displayUnsupportedAlert() } + } else { + displayUnsupportedAlert() } } else { displayUnsupportedAlert() diff --git a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift index 4bd124d7bf..e392578bfd 100644 --- a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift +++ b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift @@ -138,6 +138,8 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu }, openMessageReplies: { _, _, _ in }, openReplyThreadOriginalMessage: { _ in }, openMessageStats: { _ in + }, editMessageMedia: { _, _ in + }, copyText: { _ in }, requestMessageUpdate: { _ in }, cancelInteractiveKeyboardGestures: { }, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: false)) diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index a536be47e3..066cc3e6b6 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -1969,6 +1969,8 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD }, openMessageReplies: { _, _, _ in }, openReplyThreadOriginalMessage: { _ in }, openMessageStats: { _ in + }, editMessageMedia: { _, _ in + }, copyText: { _ in }, requestMessageUpdate: { _ in }, cancelInteractiveKeyboardGestures: { }, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, @@ -3648,19 +3650,27 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } let context = self.context let presentationData = self.presentationData - let mapMedia = TelegramMediaMap(latitude: location.latitude, longitude: location.longitude, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: MapVenue(title: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), address: location.address, provider: nil, id: nil, type: nil), liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil) - let locationController = legacyLocationController(message: nil, mapMedia: mapMedia, context: context, openPeer: { _ in }, sendLiveLocation: { _, _ in }, stopLiveLocation: {}, openUrl: { url in + let map = TelegramMediaMap(latitude: location.latitude, longitude: location.longitude, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: MapVenue(title: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), address: location.address, provider: nil, id: nil, type: nil), liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil) + + let controllerParams = LocationViewParams(sendLiveLocation: { _ in + }, stopLiveLocation: { _ in + }, openUrl: { url in context.sharedContext.applicationBindings.openUrl(url) - }) - self.controller?.push(locationController) + }, openPeer: { _ in + }, showAll: false) + + let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer, text: "", attributes: [], media: [map], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: []) + + let controller = LocationViewController(context: context, subject: message, params: controllerParams) + self.controller?.push(controller) } private func editingOpenSetupLocation() { guard let data = self.data, let peer = data.peer else { return } - let presentationData = self.presentationData - let locationController = legacyLocationPickerController(context: self.context, selfPeer: peer, peer: peer, sendLocation: { [weak self] coordinate, _, address in + + let controller = LocationPickerController(context: self.context, mode: .pick, completion: { [weak self] location, address in guard let strongSelf = self else { return } @@ -3668,12 +3678,12 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD if let address = address { addressSignal = .single(address) } else { - addressSignal = reverseGeocodeLocation(latitude: coordinate.latitude, longitude: coordinate.longitude) + addressSignal = reverseGeocodeLocation(latitude: location.latitude, longitude: location.longitude) |> map { placemark in if let placemark = placemark { return placemark.fullAddress } else { - return "\(coordinate.latitude), \(coordinate.longitude)" + return "\(location.latitude), \(location.longitude)" } } } @@ -3681,12 +3691,11 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD let context = strongSelf.context let _ = (addressSignal |> mapToSignal { address -> Signal in - return updateChannelGeoLocation(postbox: context.account.postbox, network: context.account.network, channelId: peer.id, coordinate: (coordinate.latitude, coordinate.longitude), address: address) + return updateChannelGeoLocation(postbox: context.account.postbox, network: context.account.network, channelId: peer.id, coordinate: (location.latitude, location.longitude), address: address) } |> deliverOnMainQueue).start() - }, sendLiveLocation: { _, _ in }, theme: presentationData.theme, customLocationPicker: true, presentationCompleted: { }) - self.controller?.push(locationController) + self.controller?.push(controller) } private func openPeerInfo(peer: Peer, isMember: Bool) { diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index e8be1acdc0..c309999b54 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -1238,6 +1238,8 @@ public final class SharedAccountContextImpl: SharedAccountContext { }, openMessageReplies: { _, _, _ in }, openReplyThreadOriginalMessage: { _ in }, openMessageStats: { _ in + }, editMessageMedia: { _, _ in + }, copyText: { _ in }, requestMessageUpdate: { _ in }, cancelInteractiveKeyboardGestures: { }, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, diff --git a/submodules/TelegramUI/Sources/StickerShimmerEffectNode.swift b/submodules/TelegramUI/Sources/StickerShimmerEffectNode.swift new file mode 100644 index 0000000000..7e35bfc1ce --- /dev/null +++ b/submodules/TelegramUI/Sources/StickerShimmerEffectNode.swift @@ -0,0 +1,605 @@ +import Foundation +import AsyncDisplayKit +import Display +import Postbox +import TelegramPresentationData +import GZip + +private final class ShimmerEffectForegroundNode: ASDisplayNode { + private var currentBackgroundColor: UIColor? + private var currentForegroundColor: UIColor? + private let imageNodeContainer: ASDisplayNode + private let imageNode: ASImageNode + + private var absoluteLocation: (CGRect, CGSize)? + private var isCurrentlyInHierarchy = false + private var shouldBeAnimating = false + + override init() { + self.imageNodeContainer = ASDisplayNode() + self.imageNodeContainer.isLayerBacked = true + + self.imageNode = ASImageNode() + self.imageNode.isLayerBacked = true + self.imageNode.displaysAsynchronously = false + self.imageNode.displayWithoutProcessing = true + self.imageNode.contentMode = .scaleToFill + + super.init() + + self.isLayerBacked = true + self.clipsToBounds = true + + self.imageNodeContainer.addSubnode(self.imageNode) + self.addSubnode(self.imageNodeContainer) + } + + override func didEnterHierarchy() { + super.didEnterHierarchy() + + self.isCurrentlyInHierarchy = true + self.updateAnimation() + } + + override func didExitHierarchy() { + super.didExitHierarchy() + + self.isCurrentlyInHierarchy = false + self.updateAnimation() + } + + func update(backgroundColor: UIColor, foregroundColor: UIColor) { + if let currentBackgroundColor = self.currentBackgroundColor, currentBackgroundColor.isEqual(backgroundColor), let currentForegroundColor = self.currentForegroundColor, currentForegroundColor.isEqual(foregroundColor) { + return + } + self.currentBackgroundColor = backgroundColor + self.currentForegroundColor = foregroundColor + + let image = generateImage(CGSize(width: 320.0, height: 16.0), opaque: false, scale: 1.0, rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + context.setFillColor(backgroundColor.cgColor) + context.fill(CGRect(origin: CGPoint(), size: size)) + + context.clip(to: CGRect(origin: CGPoint(), size: size)) + + let transparentColor = foregroundColor.withAlphaComponent(0.0).cgColor + let peakColor = foregroundColor.cgColor + + var locations: [CGFloat] = [0.0, 0.5, 1.0] + let colors: [CGColor] = [transparentColor, peakColor, transparentColor] + + let colorSpace = CGColorSpaceCreateDeviceRGB() + let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &locations)! + + context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: size.width, y: 0.0), options: CGGradientDrawingOptions()) + }) + self.imageNode.image = image + } + + func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) { + if let absoluteLocation = self.absoluteLocation, absoluteLocation.0 == rect && absoluteLocation.1 == containerSize { + return + } + let sizeUpdated = self.absoluteLocation?.1 != containerSize + let frameUpdated = self.absoluteLocation?.0 != rect + self.absoluteLocation = (rect, containerSize) + + if sizeUpdated { + if self.shouldBeAnimating { + self.imageNode.layer.removeAnimation(forKey: "shimmer") + self.addImageAnimation() + } else { + self.updateAnimation() + } + } + + if frameUpdated { + self.imageNodeContainer.frame = CGRect(origin: CGPoint(x: -rect.minX, y: -rect.minY), size: containerSize) + } + } + + private func updateAnimation() { + let shouldBeAnimating = self.isCurrentlyInHierarchy && self.absoluteLocation != nil + if shouldBeAnimating != self.shouldBeAnimating { + self.shouldBeAnimating = shouldBeAnimating + if shouldBeAnimating { + self.addImageAnimation() + } else { + self.imageNode.layer.removeAnimation(forKey: "shimmer") + } + } + } + + private func addImageAnimation() { + guard let containerSize = self.absoluteLocation?.1 else { + return + } + let gradientHeight: CGFloat = 320.0 + self.imageNode.frame = CGRect(origin: CGPoint(x: -gradientHeight, y: 0.0), size: CGSize(width: gradientHeight, height: containerSize.height)) + let animation = self.imageNode.layer.makeAnimation(from: 0.0 as NSNumber, to: (containerSize.width + gradientHeight) as NSNumber, keyPath: "position.x", timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, duration: 1.3 * 1.0, delay: 0.0, mediaTimingFunction: nil, removeOnCompletion: true, additive: true) + animation.repeatCount = Float.infinity + animation.beginTime = 1.0 + self.imageNode.layer.add(animation, forKey: "shimmer") + } +} + +class StickerShimmerEffectNode: ASDisplayNode { + private let backgroundNode: ASDisplayNode + private let effectNode: ShimmerEffectForegroundNode + private let foregroundNode: ASImageNode + + private var maskView: UIImageView? + + private var currentData: Data? + private var currentBackgroundColor: UIColor? + private var currentForegroundColor: UIColor? + private var currentShimmeringColor: UIColor? + private var currentSize = CGSize() + + override init() { + self.backgroundNode = ASDisplayNode() + self.effectNode = ShimmerEffectForegroundNode() + self.foregroundNode = ASImageNode() + + super.init() + + self.addSubnode(self.backgroundNode) + self.addSubnode(self.effectNode) + self.addSubnode(self.foregroundNode) + } + + public func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) { + self.effectNode.updateAbsoluteRect(rect, within: containerSize) + } + + public func update(backgroundColor: UIColor?, foregroundColor: UIColor, shimmeringColor: UIColor, data: Data?, size: CGSize) { + if self.currentData == data, let currentBackgroundColor = self.currentBackgroundColor, currentBackgroundColor.isEqual(backgroundColor), let currentForegroundColor = self.currentForegroundColor, currentForegroundColor.isEqual(foregroundColor), let currentShimmeringColor = self.currentShimmeringColor, currentShimmeringColor.isEqual(shimmeringColor), self.currentSize == size { + return + } + + self.currentBackgroundColor = backgroundColor + self.currentForegroundColor = foregroundColor + self.currentShimmeringColor = shimmeringColor + self.currentData = data + self.currentSize = size + + self.backgroundNode.backgroundColor = foregroundColor + + self.effectNode.update(backgroundColor: backgroundColor == nil ? .clear : foregroundColor, foregroundColor: shimmeringColor) + + let image = generateImage(size, rotatedContext: { size, context in + if let backgroundColor = backgroundColor { + context.setFillColor(backgroundColor.cgColor) + context.setBlendMode(.copy) + context.fill(CGRect(origin: CGPoint(), size: size)) + + context.setFillColor(UIColor.clear.cgColor) + } else { + context.clear(CGRect(origin: CGPoint(), size: size)) + + context.setFillColor(UIColor.black.cgColor) + } + + if let data = data, let unpackedData = TGGUnzipData(data, 5 * 1024 * 1024), let path = String(data: unpackedData, encoding: .utf8) { + let reader = PathDataReader(input: path) + let segments = reader.read() + + var currentX: Double = 0.0 + var currentY: Double = 0.0 + + let mul: Double = Double(size.width) / 512.0 + + for segment in segments { + switch segment.type { + case .M, .m: + let x = segment.data[0] + let y = segment.data[1] + + if segment.isAbsolute() { + currentX = x + currentY = y + } else { + currentX += x + currentY += y + } + + context.move(to: CGPoint(x: currentX * mul, y: currentY * mul)) + case .L, .l: + let x = segment.data[0] + let y = segment.data[1] + + let effectiveX: Double + let effectiveY: Double + if segment.isAbsolute() { + effectiveX = x + effectiveY = y + } else { + effectiveX = currentX + x + effectiveY = currentY + y + } + + currentX = effectiveX + currentY = effectiveY + + context.addLine(to: CGPoint(x: effectiveX * mul, y: effectiveY * mul)) + case .C, .c: + let x1 = segment.data[0] + let y1 = segment.data[1] + let x2 = segment.data[2] + let y2 = segment.data[3] + let x = segment.data[4] + let y = segment.data[5] + + let effectiveX1: Double + let effectiveY1: Double + let effectiveX2: Double + let effectiveY2: Double + let effectiveX: Double + let effectiveY: Double + + if segment.isAbsolute() { + effectiveX1 = x1 + effectiveY1 = y1 + effectiveX2 = x2 + effectiveY2 = y2 + effectiveX = x + effectiveY = y + } else { + effectiveX1 = currentX + x1 + effectiveY1 = currentY + y1 + effectiveX2 = currentX + x2 + effectiveY2 = currentY + y2 + effectiveX = currentX + x + effectiveY = currentY + y + } + + currentX = effectiveX + currentY = effectiveY + + context.addCurve(to: CGPoint(x: effectiveX * mul, y: effectiveY * mul), control1: CGPoint(x: effectiveX1 * mul, y: effectiveY1 * mul), control2: CGPoint(x: effectiveX2 * mul, y: effectiveY2 * mul)) + case .z: + context.fillPath() + default: + break + } + } + } else { + let path = UIBezierPath(roundedRect: CGRect(origin: CGPoint(), size: size), byRoundingCorners: [.topLeft, .topRight, .bottomLeft, .bottomRight], cornerRadii: CGSize(width: 10.0, height: 10.0)) + UIGraphicsPushContext(context) + path.fill() + UIGraphicsPopContext() + } + }) + + if backgroundColor == nil { + self.foregroundNode.image = nil + + let maskView: UIImageView + if let current = self.maskView { + maskView = current + } else { + maskView = UIImageView() + maskView.frame = CGRect(origin: CGPoint(), size: size) + self.maskView = maskView + self.view.mask = maskView + } + + } else { + self.foregroundNode.image = image + + if let _ = self.maskView { + self.view.mask = nil + self.maskView = nil + } + } + + self.maskView?.image = image + + self.backgroundNode.frame = CGRect(origin: CGPoint(), size: size) + self.foregroundNode.frame = CGRect(origin: CGPoint(), size: size) + self.effectNode.frame = CGRect(origin: CGPoint(), size: size) + } +} + +open class PathSegment: Equatable { + public enum SegmentType { + case M + case L + case C + case Q + case A + case z + case H + case V + case S + case T + case m + case l + case c + case q + case a + case h + case v + case s + case t + case E + case e + } + + public let type: SegmentType + public let data: [Double] + + public init(type: PathSegment.SegmentType = .M, data: [Double] = []) { + self.type = type + self.data = data + } + + open func isAbsolute() -> Bool { + switch type { + case .M, .L, .H, .V, .C, .S, .Q, .T, .A, .E: + return true + default: + return false + } + } + + public static func == (lhs: PathSegment, rhs: PathSegment) -> Bool { + return lhs.type == rhs.type && lhs.data == rhs.data + } +} + +private class PathDataReader { + private let input: String + private var current: UnicodeScalar? + private var previous: UnicodeScalar? + private var iterator: String.UnicodeScalarView.Iterator + + private static let spaces: Set = Set("\n\r\t ,".unicodeScalars) + + init(input: String) { + self.input = input + self.iterator = input.unicodeScalars.makeIterator() + } + + public func read() -> [PathSegment] { + readNext() + var segments = [PathSegment]() + while let array = readSegments() { + segments.append(contentsOf: array) + } + return segments + } + + private func readSegments() -> [PathSegment]? { + if let type = readSegmentType() { + let argCount = getArgCount(segment: type) + if argCount == 0 { + return [PathSegment(type: type)] + } + var result = [PathSegment]() + let data: [Double] + if type == .a || type == .A { + data = readDataOfASegment() + } else { + data = readData() + } + var index = 0 + var isFirstSegment = true + while index < data.count { + let end = index + argCount + if end > data.count { + break + } + var currentType = type + if type == .M && !isFirstSegment { + currentType = .L + } + if type == .m && !isFirstSegment { + currentType = .l + } + result.append(PathSegment(type: currentType, data: Array(data[index.. [Double] { + var data = [Double]() + while true { + skipSpaces() + if let value = readNum() { + data.append(value) + } else { + return data + } + } + } + + private func readDataOfASegment() -> [Double] { + let argCount = getArgCount(segment: .A) + var data: [Double] = [] + var index = 0 + while true { + skipSpaces() + let value: Double? + let indexMod = index % argCount + if indexMod == 3 || indexMod == 4 { + value = readFlag() + } else { + value = readNum() + } + guard let doubleValue = value else { + return data + } + data.append(doubleValue) + index += 1 + } + return data + } + + private func skipSpaces() { + var currentCharacter = current + while let character = currentCharacter, Self.spaces.contains(character) { + currentCharacter = readNext() + } + } + + private func readFlag() -> Double? { + guard let ch = current else { + return .none + } + readNext() + switch ch { + case "0": + return 0 + case "1": + return 1 + default: + return .none + } + } + + fileprivate func readNum() -> Double? { + guard let ch = current else { + return .none + } + + guard ch >= "0" && ch <= "9" || ch == "." || ch == "-" else { + return .none + } + + var chars = [ch] + var hasDot = ch == "." + while let ch = readDigit(&hasDot) { + chars.append(ch) + } + + var buf = "" + buf.unicodeScalars.append(contentsOf: chars) + guard let value = Double(buf) else { + return .none + } + return value + } + + fileprivate func readDigit(_ hasDot: inout Bool) -> UnicodeScalar? { + if let ch = readNext() { + if (ch >= "0" && ch <= "9") || ch == "e" || (previous == "e" && ch == "-") { + return ch + } else if ch == "." && !hasDot { + hasDot = true + return ch + } + } + return nil + } + + fileprivate func isNum(ch: UnicodeScalar, hasDot: inout Bool) -> Bool { + switch ch { + case "0"..."9": + return true + case ".": + if hasDot { + return false + } + hasDot = true + default: + return true + } + return false + } + + @discardableResult + private func readNext() -> UnicodeScalar? { + previous = current + current = iterator.next() + return current + } + + private func isAcceptableSeparator(_ ch: UnicodeScalar?) -> Bool { + if let ch = ch { + return "\n\r\t ,".contains(String(ch)) + } + return false + } + + private func readSegmentType() -> PathSegment.SegmentType? { + while true { + if let type = getPathSegmentType() { + readNext() + return type + } + if readNext() == nil { + return nil + } + } + } + + fileprivate func getPathSegmentType() -> PathSegment.SegmentType? { + if let ch = current { + switch ch { + case "M": + return .M + case "m": + return .m + case "L": + return .L + case "l": + return .l + case "C": + return .C + case "c": + return .c + case "Q": + return .Q + case "q": + return .q + case "A": + return .A + case "a": + return .a + case "z", "Z": + return .z + case "H": + return .H + case "h": + return .h + case "V": + return .V + case "v": + return .v + case "S": + return .S + case "s": + return .s + case "T": + return .T + case "t": + return .t + default: + break + } + } + return nil + } + + fileprivate func getArgCount(segment: PathSegment.SegmentType) -> Int { + switch segment { + case .H, .h, .V, .v: + return 1 + case .M, .m, .L, .l, .T, .t: + return 2 + case .S, .s, .Q, .q: + return 4 + case .C, .c: + return 6 + case .A, .a: + return 7 + default: + return 0 + } + } +} diff --git a/submodules/TextFormat/Sources/StringWithAppliedEntities.swift b/submodules/TextFormat/Sources/StringWithAppliedEntities.swift index e3cad1726e..78dc7c3abd 100644 --- a/submodules/TextFormat/Sources/StringWithAppliedEntities.swift +++ b/submodules/TextFormat/Sources/StringWithAppliedEntities.swift @@ -160,15 +160,17 @@ public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEnti if case .Mention = entities[i + 1].type { let nextRange = NSRange(location: entities[i + 1].range.lowerBound, length: entities[i + 1].range.upperBound - entities[i + 1].range.lowerBound) if nextRange.location == range.location + range.length + 1 && nsString!.character(at: range.location + range.length) == 43 { - let peerName: String = nsString!.substring(with: NSRange(location: nextRange.location + 1, length: nextRange.length - 1)) - skipEntity = true - let combinedRange = NSRange(location: range.location, length: nextRange.location + nextRange.length - range.location) - string.addAttribute(NSAttributedString.Key.foregroundColor, value: linkColor, range: combinedRange) - if linkColor.isEqual(baseColor) { - string.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.single.rawValue as NSNumber, range: combinedRange) + if nextRange.length > 0 { + let peerName: String = nsString!.substring(with: NSRange(location: nextRange.location + 1, length: nextRange.length - 1)) + + let combinedRange = NSRange(location: range.location, length: nextRange.location + nextRange.length - range.location) + string.addAttribute(NSAttributedString.Key.foregroundColor, value: linkColor, range: combinedRange) + if linkColor.isEqual(baseColor) { + string.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.single.rawValue as NSNumber, range: combinedRange) + } + string.addAttribute(NSAttributedString.Key(rawValue: TelegramTextAttributes.Hashtag), value: TelegramHashtag(peerName: peerName, hashtag: hashtag), range: combinedRange) } - string.addAttribute(NSAttributedString.Key(rawValue: TelegramTextAttributes.Hashtag), value: TelegramHashtag(peerName: peerName, hashtag: hashtag), range: combinedRange) } } } @@ -190,6 +192,10 @@ public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEnti string.addAttribute(NSAttributedString.Key(rawValue: TelegramTextAttributes.BotCommand), value: nsString!.substring(with: range), range: range) case .Code, .Pre: string.addAttribute(NSAttributedString.Key.font, value: fixedFont, range: range) + if nsString == nil { + nsString = text as NSString + } + string.addAttribute(NSAttributedString.Key(rawValue: TelegramTextAttributes.Pre), value: nsString!.substring(with: range), range: range) case .BlockQuote: if let fontAttribute = fontAttributes[range] { fontAttributes[range] = fontAttribute.union(.blockQuote) diff --git a/submodules/TextFormat/Sources/TelegramAttributes.swift b/submodules/TextFormat/Sources/TelegramAttributes.swift index ab276a41e3..7ce2749909 100644 --- a/submodules/TextFormat/Sources/TelegramAttributes.swift +++ b/submodules/TextFormat/Sources/TelegramAttributes.swift @@ -40,4 +40,5 @@ public struct TelegramTextAttributes { public static let BankCard = "TelegramBankCard" public static let Timecode = "TelegramTimecode" public static let BlockQuote = "TelegramBlockQuote" + public static let Pre = "TelegramPre" } diff --git a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift index 6674aed6f0..8fbe7afcdc 100644 --- a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift +++ b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift @@ -142,7 +142,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.textNode.attributedText = attributedText self.textNode.maximumNumberOfLines = 2 displayUndo = false - self.originalRemainingSeconds = 5 + self.originalRemainingSeconds = 3 case let .info(text): self.iconNode = nil self.iconCheckNode = nil diff --git a/submodules/WebSearchUI/Sources/WebSearchGalleryController.swift b/submodules/WebSearchUI/Sources/WebSearchGalleryController.swift index d5941381e7..87245d1f08 100644 --- a/submodules/WebSearchUI/Sources/WebSearchGalleryController.swift +++ b/submodules/WebSearchUI/Sources/WebSearchGalleryController.swift @@ -222,12 +222,13 @@ class WebSearchGalleryController: ViewController { if let strongSelf = self { strongSelf.present(controller, in: .window(.root), with: arguments, blockInteraction: true) } - }, dismissController: { [weak self] in - self?.dismiss(forceAway: true) - }, replaceRootController: { [weak self] controller, ready in - if let strongSelf = self { - strongSelf.replaceRootController(controller, ready) - } + }, dismissController: { [weak self] in + self?.dismiss(forceAway: true) + }, replaceRootController: { [weak self] controller, ready in + if let strongSelf = self { + strongSelf.replaceRootController(controller, ready) + } + }, editMedia: { _ in }) self.displayNode = GalleryControllerNode(controllerInteraction: controllerInteraction) self.displayNodeDidLoad() diff --git a/submodules/rlottie/BUILD b/submodules/rlottie/BUILD index a0a038abbb..0d2b59b685 100644 --- a/submodules/rlottie/BUILD +++ b/submodules/rlottie/BUILD @@ -24,6 +24,7 @@ objc_library( copts = [ "-Dpixman_region_selfcheck(x)=1", "-DLOTTIE_DISABLE_ARM_NEON=1", + "-DLOTTIE_THREAD_SAFE=1", "-DLOTTIE_IMAGE_MODULE_DISABLED=1", "-I{}".format(package_name()), "-I{}/rlottie/inc".format(package_name()),