From 10d5bf3d10b0b71b786d2b6b50ea37dd2adf7fb4 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 15 Jan 2019 00:55:31 +0400 Subject: [PATCH] UI fixes --- TelegramUI.xcodeproj/project.pbxproj | 8 + TelegramUI/ChatControllerBackgroundNode.swift | 141 ++++++------ TelegramUI/ComposeController.swift | 8 + TelegramUI/ContactSelectionController.swift | 8 + TelegramUI/ContactsController.swift | 23 +- TelegramUI/LegacyWebSearchGallery.swift | 4 +- TelegramUI/PeerSelectionController.swift | 4 +- TelegramUI/PeerSelectionControllerNode.swift | 13 +- TelegramUI/PhotoResources.swift | 6 +- TelegramUI/PresentationStrings.swift | 208 +++++++++--------- .../Resources/PresentationStrings.mapping | Bin 97825 -> 97825 bytes TelegramUI/SearchDisplayController.swift | 3 + TelegramUI/SettingsThemeWallpaperNode.swift | 2 +- TelegramUI/SuppressContactsWarning.swift | 25 +++ TelegramUI/TelegramRootController.swift | 4 +- .../ThemeColorsGridControllerNode.swift | 10 +- TelegramUI/ThemeGridController.swift | 2 +- TelegramUI/ThemeGridControllerNode.swift | 14 +- TelegramUI/ThemeGridSearchColorsItem.swift | 13 +- TelegramUI/ThemeGridSearchContainerNode.swift | 51 +++-- TelegramUI/ThemeGridSearchItem.swift | 5 +- TelegramUI/WallpaperColorPickerNode.swift | 27 +++ .../WallpaperListPreviewController.swift | 13 +- .../WallpaperListPreviewControllerNode.swift | 79 +++++-- TelegramUI/WebSearchController.swift | 2 +- TelegramUI/WebSearchItem.swift | 6 +- 26 files changed, 430 insertions(+), 249 deletions(-) create mode 100644 TelegramUI/SuppressContactsWarning.swift create mode 100644 TelegramUI/WallpaperColorPickerNode.swift diff --git a/TelegramUI.xcodeproj/project.pbxproj b/TelegramUI.xcodeproj/project.pbxproj index c327f078fd..c3a7ea6364 100644 --- a/TelegramUI.xcodeproj/project.pbxproj +++ b/TelegramUI.xcodeproj/project.pbxproj @@ -89,6 +89,8 @@ 09C9EA3821A044B500E90146 /* StringForDuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09C9EA3721A044B500E90146 /* StringForDuration.swift */; }; 09D304152173C0E900C00567 /* WatchManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09D304142173C0E900C00567 /* WatchManager.swift */; }; 09D304182173C15700C00567 /* WatchSettingsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09D304172173C15700C00567 /* WatchSettingsController.swift */; }; + 09DD5D5021ECC3C400D7007A /* SuppressContactsWarning.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09DD5D4F21ECC3C400D7007A /* SuppressContactsWarning.swift */; }; + 09DD5D5221ED175300D7007A /* WallpaperColorPickerNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09DD5D5121ED175300D7007A /* WallpaperColorPickerNode.swift */; }; 09DD88E921BAF65E000766BC /* ItemListAddressItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09DD88E821BAF65E000766BC /* ItemListAddressItem.swift */; }; 09DD88ED21BDC8B7000766BC /* FormEditableBlockItemNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09DD88EC21BDC8B7000766BC /* FormEditableBlockItemNode.swift */; }; 09DD88EF21BDDE2B000766BC /* Geocoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09DD88EE21BDDE2B000766BC /* Geocoding.swift */; }; @@ -1211,6 +1213,8 @@ 09C9EA3721A044B500E90146 /* StringForDuration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringForDuration.swift; sourceTree = ""; }; 09D304142173C0E900C00567 /* WatchManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchManager.swift; sourceTree = ""; }; 09D304172173C15700C00567 /* WatchSettingsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchSettingsController.swift; sourceTree = ""; }; + 09DD5D4F21ECC3C400D7007A /* SuppressContactsWarning.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuppressContactsWarning.swift; sourceTree = ""; }; + 09DD5D5121ED175300D7007A /* WallpaperColorPickerNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallpaperColorPickerNode.swift; sourceTree = ""; }; 09DD88E821BAF65E000766BC /* ItemListAddressItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemListAddressItem.swift; sourceTree = ""; }; 09DD88EC21BDC8B7000766BC /* FormEditableBlockItemNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormEditableBlockItemNode.swift; sourceTree = ""; }; 09DD88EE21BDDE2B000766BC /* Geocoding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Geocoding.swift; sourceTree = ""; }; @@ -3137,6 +3141,7 @@ 09F664CB21EB552C00AB7E26 /* WallpaperSearchRecentQueries.swift */, 09F664CD21EBB3A100AB7E26 /* ImageBlur.swift */, 09F664CF21EBCFB900AB7E26 /* WallpaperCropNode.swift */, + 09DD5D5121ED175300D7007A /* WallpaperColorPickerNode.swift */, ); name = Themes; sourceTree = ""; @@ -4727,6 +4732,7 @@ 09C9EA32219F79F600E90146 /* ID3Artwork.h */, 09C9EA31219F79F500E90146 /* ID3Artwork.m */, 099529B321D3E5D800805E13 /* CheckDiskSpace.swift */, + 09DD5D4F21ECC3C400D7007A /* SuppressContactsWarning.swift */, ); name = Utils; sourceTree = ""; @@ -5104,6 +5110,7 @@ D0EC6CB61EB9F58800EBF1C3 /* RMGeometry.m in Sources */, 0941A9A0210B057200EBE194 /* OpenInActionSheetController.swift in Sources */, D079FCDD1F05C4F20038FADE /* LocalAuth.swift in Sources */, + 09DD5D5221ED175300D7007A /* WallpaperColorPickerNode.swift in Sources */, D0B2F76820528E3D00D3BFB9 /* UserInfoEditingPhoneActionItem.swift in Sources */, D0EC6CB71EB9F58800EBF1C3 /* RMIntroPageView.m in Sources */, D0EC6CB81EB9F58800EBF1C3 /* RMIntroViewController.m in Sources */, @@ -5206,6 +5213,7 @@ D0EC6CE21EB9F58800EBF1C3 /* PresentationResourcesChatList.swift in Sources */, D0EC6CE31EB9F58800EBF1C3 /* PresentationResourcesChat.swift in Sources */, D0AA840C1FEB2BA3005C6E91 /* OverlayPlayerControlsNode.swift in Sources */, + 09DD5D5021ECC3C400D7007A /* SuppressContactsWarning.swift in Sources */, D0F67FF21EE6B915000E5906 /* ChannelMembersSearchControllerNode.swift in Sources */, D0EC6CE41EB9F58800EBF1C3 /* PresentationData.swift in Sources */, D0EC6CE51EB9F58800EBF1C3 /* PresentationStrings.swift in Sources */, diff --git a/TelegramUI/ChatControllerBackgroundNode.swift b/TelegramUI/ChatControllerBackgroundNode.swift index 3bf17d8eee..eb366fb5b3 100644 --- a/TelegramUI/ChatControllerBackgroundNode.swift +++ b/TelegramUI/ChatControllerBackgroundNode.swift @@ -57,13 +57,13 @@ final class ChatBackgroundNode: ASDisplayNode { } } -private var backgroundImageForWallpaper: (TelegramWallpaper, UIImage)? +private var backgroundImageForWallpaper: (TelegramWallpaper, PresentationWallpaperMode, UIImage)? private var serviceBackgroundColorForWallpaper: (TelegramWallpaper, UIColor)? func chatControllerBackgroundImage(wallpaper: TelegramWallpaper, mode: PresentationWallpaperMode = .still, postbox: Postbox) -> UIImage? { var backgroundImage: UIImage? - if wallpaper == backgroundImageForWallpaper?.0 { - backgroundImage = backgroundImageForWallpaper?.1 + if wallpaper == backgroundImageForWallpaper?.0, mode == backgroundImageForWallpaper?.1 { + backgroundImage = backgroundImageForWallpaper?.2 } else { switch wallpaper { case .builtin: @@ -105,7 +105,7 @@ func chatControllerBackgroundImage(wallpaper: TelegramWallpaper, mode: Presentat } } if let backgroundImage = backgroundImage { - backgroundImageForWallpaper = (wallpaper, backgroundImage) + backgroundImageForWallpaper = (wallpaper, mode, backgroundImage) } } return backgroundImage @@ -188,76 +188,94 @@ func chatServiceBackgroundColor(wallpaper: TelegramWallpaper, postbox: Postbox) } func chatBackgroundContrastColor(wallpaper: TelegramWallpaper, postbox: Postbox) -> Signal { - // if wallpaper == serviceBackgroundColorForWallpaper?.0, let color = serviceBackgroundColorForWallpaper?.1 { - // return .single(color) - // } else { - switch wallpaper { - case .builtin: - return .single(UIColor(rgb: 0x888f96)) - case let .color(color): - return .single(contrastingColor(for: UIColor(rgb: UInt32(bitPattern: color)))) - case let .image(representations): - if let largest = largestImageRepresentation(representations) { - return Signal { subscriber in - let fetch = postbox.mediaBox.fetchedResource(largest.resource, parameters: nil).start() - let data = backgroundContrastColor(for: postbox.mediaBox.resourceData(largest.resource)).start(next: { next in - subscriber.putNext(next) - }, completed: { - subscriber.putCompletion() - }) - return ActionDisposable { - fetch.dispose() - data.dispose() + switch wallpaper { + case .builtin: + return .single(UIColor(rgb: 0x888f96)) + case let .color(color): + return .single(contrastingColor(for: UIColor(rgb: UInt32(bitPattern: color)))) + case let .image(representations): + if let largest = largestImageRepresentation(representations) { + return Signal { subscriber in + let fetch = postbox.mediaBox.fetchedResource(largest.resource, parameters: nil).start() + let imageSignal = postbox.mediaBox.resourceData(largest.resource) + |> mapToSignal { data -> Signal in + if data.complete, let image = UIImage(contentsOfFile: data.path) { + return .single(image) + } else { + return .complete() } } - // |> afterNext { color in - // serviceBackgroundColorForWallpaper = (wallpaper, color) - //} + let data = backgroundContrastColor(for: imageSignal).start(next: { next in + subscriber.putNext(next) + }, completed: { + subscriber.putCompletion() + }) + return ActionDisposable { + fetch.dispose() + data.dispose() + } + } + } else { + return .single(.white) + } + case let .file(file): + return Signal { subscriber in + let fetch = postbox.mediaBox.fetchedResource(file.file.resource, parameters: nil).start() + let imageSignal = postbox.mediaBox.resourceData(file.file.resource) + |> mapToSignal { data -> Signal in + if data.complete, let image = UIImage(contentsOfFile: data.path) { + return .single(image) } else { - return .single(.white) + return .complete() } - case let .file(file): - return Signal { subscriber in - let fetch = postbox.mediaBox.fetchedResource(file.file.resource, parameters: nil).start() - let data = backgroundContrastColor(for: postbox.mediaBox.resourceData(file.file.resource)).start(next: { next in - subscriber.putNext(next) - }, completed: { - subscriber.putCompletion() - }) - return ActionDisposable { - fetch.dispose() - data.dispose() - } - } - // |> afterNext { color in - // serviceBackgroundColorForWallpaper = (wallpaper, color) - //} + } + let data = backgroundContrastColor(for: imageSignal).start(next: { next in + subscriber.putNext(next) + }, completed: { + subscriber.putCompletion() + }) + return ActionDisposable { + fetch.dispose() + data.dispose() + } } - // } + } } -private func backgroundContrastColor(for data: Signal) -> Signal { - return data - |> mapToSignal { data -> Signal in - if data.complete { - let image = UIImage(contentsOfFile: data.path) +func backgroundContrastColor(for image: Signal) -> Signal { + return image + |> map { image -> UIColor in + if let image = image { let context = DrawingContext(size: CGSize(width: 128.0, height: 32.0), scale: 1.0, clear: false) context.withFlippedContext({ context in - if let image = image, let cgImage = image.cgImage { + if let cgImage = image.cgImage { let size = image.size.aspectFilled(CGSize(width: 128.0, height: 128.0)) context.draw(cgImage, in: CGRect(x: floor((128.0 - size.width) / 2.0), y: 0.0, width: size.width, height: size.height)) } }) - let finalContext = DrawingContext(size: CGSize(width: 1.0, height: 1.0), scale: 1.0, clear: false) - finalContext.withFlippedContext({ c in - if let cgImage = context.generateImage()?.cgImage { - c.draw(cgImage, in: CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0)) + + var matching: Int = 0 + var total: Int = Int(context.size.width) * Int(context.size.height) + for y in 0 ..< Int(context.size.height) { + for x in 0 ..< Int(context.size.width) { + var saturation: CGFloat = 0.0 + var brightness: CGFloat = 0.0 + if context.colorAt(CGPoint(x: x, y: y)).getHue(nil, saturation: nil, brightness: &brightness, alpha: nil) { + if brightness > 0.6 { + matching += 1 + } + } } - }) - let color = finalContext.colorAt(CGPoint()) - return .single(contrastingColor(for: color)) + } + + if CGFloat(matching) / CGFloat(total) > 0.4 { + return .black + } else { + return .white + } + } else { + return .black } - return .complete() } } @@ -266,11 +284,10 @@ private func contrastingColor(for color: UIColor) -> UIColor { var green: CGFloat = 0.0 var blue: CGFloat = 0.0 var luminance: CGFloat = 0.0 - var alpha: CGFloat = 0.0; - if color.getRed(&red, green: &green, blue: &blue, alpha: &alpha) { + if color.getRed(&red, green: &green, blue: &blue, alpha: nil) { luminance = red * 0.2126 + green * 0.7152 + blue * 0.0722 - } else if color.getWhite(&luminance, alpha: &alpha) { + } else if color.getWhite(&luminance, alpha: nil) { } if luminance > 0.6 { diff --git a/TelegramUI/ComposeController.swift b/TelegramUI/ComposeController.swift index b7a063d0a9..99b453bb83 100644 --- a/TelegramUI/ComposeController.swift +++ b/TelegramUI/ComposeController.swift @@ -163,6 +163,14 @@ public class ComposeController: ViewController { } } + self.contactsNode.contactListNode.suppressPermissionWarning = { [weak self] in + if let strongSelf = self { + presentContactsWarningSuppression(account: strongSelf.account, present: { c, a in + strongSelf.present(c, in: .window(.root), with: a) + }) + } + } + self.contactsNode.contactListNode.contentOffsetChanged = { [weak self] offset in if let strongSelf = self, let searchContentNode = strongSelf.searchContentNode { searchContentNode.updateListVisibleContentOffset(offset) diff --git a/TelegramUI/ContactSelectionController.swift b/TelegramUI/ContactSelectionController.swift index 5ecbf7192f..ab502e8a34 100644 --- a/TelegramUI/ContactSelectionController.swift +++ b/TelegramUI/ContactSelectionController.swift @@ -154,6 +154,14 @@ class ContactSelectionController: ViewController { self?.openPeer(peer: peer) } + self.contactsNode.contactListNode.suppressPermissionWarning = { [weak self] in + if let strongSelf = self { + presentContactsWarningSuppression(account: strongSelf.account, present: { c, a in + strongSelf.present(c, in: .window(.root), with: a) + }) + } + } + self.contactsNode.dismiss = { [weak self] in self?.presentingViewController?.dismiss(animated: true, completion: nil) } diff --git a/TelegramUI/ContactsController.swift b/TelegramUI/ContactsController.swift index 619eb3d410..fb78a5c68d 100644 --- a/TelegramUI/ContactsController.swift +++ b/TelegramUI/ContactsController.swift @@ -177,26 +177,9 @@ public class ContactsController: ViewController { self.contactsNode.contactListNode.suppressPermissionWarning = { [weak self] in if let strongSelf = self { - let presentationData = strongSelf.account.telegramApplicationContext.currentPresentationData.with { $0 } - strongSelf.present(textAlertController(account: strongSelf.account, title: presentationData.strings.Contacts_PermissionsSuppressWarningTitle, text: presentationData.strings.Contacts_PermissionsSuppressWarningText, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Contacts_PermissionsKeepDisabled, action: { - ApplicationSpecificNotice.setContactsPermissionWarning(postbox: strongSelf.account.postbox, value: Int32(Date().timeIntervalSince1970)) - }), TextAlertAction(type: .defaultAction, title: presentationData.strings.Contacts_PermissionsEnable, action: { [weak self] in - if let strongSelf = self { - let account = strongSelf.account - let _ = (DeviceAccess.authorizationStatus(account: account, subject: .contacts) - |> take(1) - |> deliverOnMainQueue).start(next: { status in - switch status { - case .notDetermined: - DeviceAccess.authorizeAccess(to: .contacts, account: account) - case .denied, .restricted: - account.telegramApplicationContext.applicationBindings.openSettings() - default: - break - } - }) - } - })]), in: .window(.root)) + presentContactsWarningSuppression(account: strongSelf.account, present: { c, a in + strongSelf.present(c, in: .window(.root), with: a) + }) } } diff --git a/TelegramUI/LegacyWebSearchGallery.swift b/TelegramUI/LegacyWebSearchGallery.swift index 7d8c9804e2..3cad293a21 100644 --- a/TelegramUI/LegacyWebSearchGallery.swift +++ b/TelegramUI/LegacyWebSearchGallery.swift @@ -208,6 +208,7 @@ func legacyWebSearchItem(account: Account, result: ChatContextResult) -> LegacyW var thumbnailResource: TelegramMediaResource? var imageResource: TelegramMediaResource? var imageDimensions = CGSize() + var immediateThumbnailData: Data? let thumbnailSignal: Signal let originalSignal: Signal @@ -225,6 +226,7 @@ func legacyWebSearchItem(account: Account, result: ChatContextResult) -> LegacyW imageDimensions = dimensions } case let .internalReference(_, _, _, _, _, image, _, _): + immediateThumbnailData = image?.immediateThumbnailData if let image = image { if let imageRepresentation = imageRepresentationLargerThan(image.representations, size: CGSize(width: 1000.0, height: 800.0)) { imageDimensions = imageRepresentation.dimensions @@ -255,7 +257,7 @@ func legacyWebSearchItem(account: Account, result: ChatContextResult) -> LegacyW representations.append(TelegramMediaImageRepresentation(dimensions: thumbnailDimensions, resource: thumbnailResource)) } representations.append(TelegramMediaImageRepresentation(dimensions: imageDimensions, resource: imageResource)) - let tmpImage = TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: representations, immediateThumbnailData: nil, reference: nil, partialReference: nil) + let tmpImage = TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: representations, immediateThumbnailData: immediateThumbnailData, reference: nil, partialReference: nil) thumbnailSignal = chatMessagePhotoDatas(postbox: account.postbox, photoReference: .standalone(media: tmpImage), autoFetchFullSize: false) |> mapToSignal { (thumbnailData, _, _) -> Signal in if let data = thumbnailData, let image = UIImage(data: data) { diff --git a/TelegramUI/PeerSelectionController.swift b/TelegramUI/PeerSelectionController.swift index f86a545c7a..c209bb3a0d 100644 --- a/TelegramUI/PeerSelectionController.swift +++ b/TelegramUI/PeerSelectionController.swift @@ -104,7 +104,9 @@ public final class PeerSelectionController: ViewController { } override public func loadDisplayNode() { - self.displayNode = PeerSelectionControllerNode(account: self.account, filter: self.filter, hasContactSelector: hasContactSelector, dismiss: { [weak self] in + self.displayNode = PeerSelectionControllerNode(account: self.account, filter: self.filter, hasContactSelector: hasContactSelector, present: { [weak self] c, a in + self?.present(c, in: .window(.root), with: a) + }, dismiss: { [weak self] in self?.presentingViewController?.dismiss(animated: false, completion: nil) }) diff --git a/TelegramUI/PeerSelectionControllerNode.swift b/TelegramUI/PeerSelectionControllerNode.swift index 84c81b0927..bbe42e6a0a 100644 --- a/TelegramUI/PeerSelectionControllerNode.swift +++ b/TelegramUI/PeerSelectionControllerNode.swift @@ -7,6 +7,7 @@ import SwiftSignalKit final class PeerSelectionControllerNode: ASDisplayNode { private let account: Account + private let present: (ViewController, Any?) -> Void private let dismiss: () -> Void private let filter: ChatListNodePeersFilter @@ -49,8 +50,9 @@ final class PeerSelectionControllerNode: ASDisplayNode { } - init(account: Account, filter: ChatListNodePeersFilter, hasContactSelector: Bool, dismiss: @escaping () -> Void) { + init(account: Account, filter: ChatListNodePeersFilter, hasContactSelector: Bool, present: @escaping (ViewController, Any?) -> Void, dismiss: @escaping () -> Void) { self.account = account + self.present = present self.dismiss = dismiss self.filter = filter @@ -253,7 +255,7 @@ final class PeerSelectionControllerNode: ASDisplayNode { strongSelf.requestOpenPeerFromSearch?(peer) } }) - case let .deviceContact(stableId, contact): + case .deviceContact: break } } @@ -336,6 +338,13 @@ final class PeerSelectionControllerNode: ASDisplayNode { self?.requestOpenPeer?(peer.id) } } + contactListNode.suppressPermissionWarning = { [weak self] in + if let strongSelf = self { + presentContactsWarningSuppression(account: strongSelf.account, present: { c, a in + strongSelf.present(c, a) + }) + } + } contactListNode.contentOffsetChanged = { [weak self] offset in self?.contentOffsetChanged?(offset) } diff --git a/TelegramUI/PhotoResources.swift b/TelegramUI/PhotoResources.swift index b9541146df..b7e365ba86 100644 --- a/TelegramUI/PhotoResources.swift +++ b/TelegramUI/PhotoResources.swift @@ -2802,6 +2802,8 @@ func photoWallpaper(postbox: Postbox, photoLibraryResource: PhotoLibraryMediaRes return { arguments in let context = DrawingContext(size: arguments.drawingSize, scale: 1.0, clear: true) + var dimensions = sourceImage?.size + if let thumbnailImage = sourceImage?.cgImage, isThumbnail { var fittedSize = arguments.imageSize if abs(fittedSize.width - arguments.boundingSize.width).isLessThanOrEqualTo(CGFloat(1.0)) { @@ -2846,8 +2848,8 @@ func photoWallpaper(postbox: Postbox, photoLibraryResource: PhotoLibraryMediaRes context.withFlippedContext { c in c.setBlendMode(.copy) - if let sourceImage = sourceImage, let cgImage = sourceImage.cgImage { - let imageSize = sourceImage.size.aspectFilled(arguments.drawingRect.size) + if let sourceImage = sourceImage, let cgImage = sourceImage.cgImage, let dimensions = dimensions { + let imageSize = dimensions.aspectFilled(arguments.drawingRect.size) let fittedRect = CGRect(origin: CGPoint(x: floor((arguments.drawingRect.size.width - imageSize.width) / 2.0), y: floor((arguments.drawingRect.size.height - imageSize.height) / 2.0)), size: imageSize) c.draw(cgImage, in: fittedRect) } diff --git a/TelegramUI/PresentationStrings.swift b/TelegramUI/PresentationStrings.swift index 7185bb7579..2384dce2e2 100644 --- a/TelegramUI/PresentationStrings.swift +++ b/TelegramUI/PresentationStrings.swift @@ -3407,195 +3407,195 @@ public final class PresentationStrings { public var Channel_Setup_TypePublicHelp: String { return self._s[3025]! } public var Passport_Identity_EditInternalPassport: String { return self._s[3026]! } public var PhotoEditor_Skip: String { return self._s[3027]! } - public func LiveLocationUpdated_MinutesAgo(_ value: Int32) -> String { + public func StickerPack_RemoveMaskCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Notifications_Exceptions(_ value: Int32) -> String { + public func SharedMedia_Link(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessageTimer_ShortSeconds(_ value: Int32) -> String { + public func Media_SharePhoto(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[2 * 6 + Int(form.rawValue)]!, "\(value)") } - public func GroupInfo_ParticipantCount(_ value: Int32) -> String { + public func ForwardedFiles(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[3 * 6 + Int(form.rawValue)]!, "\(value)") } - public func PUSH_CHAT_MESSAGES(_ value: Int32) -> String { + public func InviteText_ContactsCountText(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[4 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Call_Minutes(_ value: Int32) -> String { + public func StickerPack_RemoveStickerCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[5 * 6 + Int(form.rawValue)]!, "\(value)") } - public func PUSH_CHANNEL_MESSAGE_ROUNDS(_ value: Int32) -> String { + public func ChatList_DeleteConfirmation(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[6 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedContacts(_ value: Int32) -> String { + public func MessageTimer_ShortDays(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[7 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessageTimer_ShortHours(_ value: Int32) -> String { + public func PUSH_CHANNEL_MESSAGES(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[8 * 6 + Int(form.rawValue)]!, "\(value)") } - public func SharedMedia_Photo(_ value: Int32) -> String { + public func MessageTimer_Minutes(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[9 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Notification_GameScoreSelfSimple(_ value: Int32) -> String { + public func Forward_ConfirmMultipleFiles(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[10 * 6 + Int(form.rawValue)]!, "\(value)") } - public func SharedMedia_DeleteItemsConfirmation(_ value: Int32) -> String { + public func Conversation_LiveLocationMembersCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[11 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedVideos(_ value: Int32) -> String { + public func Contacts_ImportersCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[12 * 6 + Int(form.rawValue)]!, "\(value)") } - public func StickerPack_StickerCount(_ value: Int32) -> String { + public func MessageTimer_Months(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[13 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ServiceMessage_GameScoreSelfExtended(_ value: Int32) -> String { + public func MessagePoll_VotedCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[14 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Media_ShareItem(_ value: Int32) -> String { + public func StickerPack_StickerCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[15 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedAudios(_ value: Int32) -> String { + public func PUSH_MESSAGES(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[16 * 6 + Int(form.rawValue)]!, "\(value)") } - public func InviteText_ContactsCountText(_ value: Int32) -> String { + public func ForwardedVideos(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[17 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Watch_LastSeen_MinutesAgo(_ value: Int32) -> String { + public func MessageTimer_ShortMinutes(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[18 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Map_ETAMinutes(_ value: Int32) -> String { + public func SharedMedia_File(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[19 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessageTimer_ShortDays(_ value: Int32) -> String { + public func PUSH_MESSAGE_VIDEOS(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[20 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MuteExpires_Days(_ value: Int32) -> String { + public func Notifications_ExceptionMuteExpires_Days(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[21 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Notifications_ExceptionMuteExpires_Hours(_ value: Int32) -> String { + public func Notifications_Exceptions(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[22 * 6 + Int(form.rawValue)]!, "\(value)") } - public func StickerPack_RemoveStickerCount(_ value: Int32) -> String { + public func ForwardedPolls(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[23 * 6 + Int(form.rawValue)]!, "\(value)") } - public func PUSH_CHAT_MESSAGE_ROUNDS(_ value: Int32) -> String { + public func MuteExpires_Days(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[24 * 6 + Int(form.rawValue)]!, "\(value)") } - public func DialogList_LiveLocationChatsCount(_ value: Int32) -> String { + public func Conversation_StatusOnline(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[25 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Call_Seconds(_ value: Int32) -> String { + public func Passport_Scans(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[26 * 6 + Int(form.rawValue)]!, "\(value)") } - public func PUSH_CHANNEL_MESSAGES(_ value: Int32) -> String { + public func GroupInfo_ParticipantCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[27 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessageTimer_Years(_ value: Int32) -> String { + public func ForwardedAuthorsOthers(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[28 * 6 + Int(form.rawValue)]!, "\(value)") } - public func PUSH_MESSAGE_PHOTOS(_ value: Int32) -> String { + public func Conversation_StatusMembers(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[29 * 6 + Int(form.rawValue)]!, "\(value)") } - public func PUSH_MESSAGES(_ value: Int32) -> String { + public func LastSeen_HoursAgo(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[30 * 6 + Int(form.rawValue)]!, "\(value)") } - public func PUSH_CHAT_MESSAGE_FWDS(_ value: Int32) -> String { + public func QuickSend_Photos(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[31 * 6 + Int(form.rawValue)]!, "\(value)") } - public func StickerPack_AddMaskCount(_ value: Int32) -> String { + public func Watch_LastSeen_MinutesAgo(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[32 * 6 + Int(form.rawValue)]!, "\(value)") } - public func PasscodeSettings_FailedAttempts(_ value: Int32) -> String { + public func Invitation_Members(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[33 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Conversation_StatusSubscribers(_ value: Int32) -> String { + public func SharedMedia_Photo(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[34 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedFiles(_ value: Int32) -> String { + public func ForwardedVideoMessages(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[35 * 6 + Int(form.rawValue)]!, "\(value)") } - public func PUSH_CHANNEL_MESSAGE_VIDEOS(_ value: Int32) -> String { + public func MuteExpires_Hours(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[36 * 6 + Int(form.rawValue)]!, "\(value)") } - public func QuickSend_Photos(_ value: Int32) -> String { + public func PUSH_CHAT_MESSAGE_PHOTOS(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[37 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedPolls(_ value: Int32) -> String { + public func AttachmentMenu_SendPhoto(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[38 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedLocations(_ value: Int32) -> String { + public func SharedMedia_Generic(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[39 * 6 + Int(form.rawValue)]!, "\(value)") } - public func PUSH_CHAT_MESSAGE_PHOTOS(_ value: Int32) -> String { + public func MuteFor_Days(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[40 * 6 + Int(form.rawValue)]!, "\(value)") } - public func PUSH_CHAT_MESSAGE_VIDEOS(_ value: Int32) -> String { + public func SharedMedia_Video(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[41 * 6 + Int(form.rawValue)]!, "\(value)") } - public func PUSH_MESSAGE_ROUNDS(_ value: Int32) -> String { + public func Notifications_ExceptionMuteExpires_Hours(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[42 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Call_ShortMinutes(_ value: Int32) -> String { + public func Notifications_ExceptionMuteExpires_Minutes(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[43 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Notifications_ExceptionMuteExpires_Minutes(_ value: Int32) -> String { + public func Media_ShareItem(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[44 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessageTimer_Minutes(_ value: Int32) -> String { + public func Call_ShortMinutes(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[45 * 6 + Int(form.rawValue)]!, "\(value)") } - public func SharedMedia_File(_ value: Int32) -> String { + public func Call_ShortSeconds(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[46 * 6 + Int(form.rawValue)]!, "\(value)") } - public func LastSeen_HoursAgo(_ value: Int32) -> String { + public func ServiceMessage_GameScoreSelfExtended(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[47 * 6 + Int(form.rawValue)]!, "\(value)") } @@ -3603,227 +3603,227 @@ public final class PresentationStrings { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[48 * 6 + Int(form.rawValue)]!, "\(value)") } - public func StickerPack_RemoveMaskCount(_ value: Int32) -> String { + public func MuteFor_Hours(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[49 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Conversation_StatusMembers(_ value: Int32) -> String { + public func ServiceMessage_GameScoreExtended(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[50 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessageTimer_ShortWeeks(_ value: Int32) -> String { + public func MessageTimer_Weeks(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[51 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Conversation_LiveLocationMembersCount(_ value: Int32) -> String { + public func StickerPack_AddMaskCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[52 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MuteExpires_Minutes(_ value: Int32) -> String { + public func ForwardedGifs(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[53 * 6 + Int(form.rawValue)]!, "\(value)") } - public func SharedMedia_Generic(_ value: Int32) -> String { + public func ServiceMessage_GameScoreSelfSimple(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[54 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedMessages(_ value: Int32) -> String { + public func PUSH_CHAT_MESSAGES(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[55 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Notification_GameScoreSimple(_ value: Int32) -> String { + public func MuteExpires_Minutes(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[56 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessageTimer_ShortMinutes(_ value: Int32) -> String { + public func PUSH_CHANNEL_MESSAGE_ROUNDS(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[57 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Watch_LastSeen_HoursAgo(_ value: Int32) -> String { + public func MessageTimer_Hours(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[58 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Media_ShareVideo(_ value: Int32) -> String { + public func ForwardedStickers(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[59 * 6 + Int(form.rawValue)]!, "\(value)") } - public func StickerPack_AddStickerCount(_ value: Int32) -> String { + public func DialogList_LiveLocationChatsCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[60 * 6 + Int(form.rawValue)]!, "\(value)") } - public func PUSH_CHANNEL_MESSAGE_PHOTOS(_ value: Int32) -> String { + public func AttachmentMenu_SendVideo(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[61 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Forward_ConfirmMultipleFiles(_ value: Int32) -> String { + public func Map_ETAMinutes(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[62 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MuteFor_Days(_ value: Int32) -> String { + public func ForwardedContacts(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[63 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Conversation_StatusOnline(_ value: Int32) -> String { + public func Map_ETAHours(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[64 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ServiceMessage_GameScoreSimple(_ value: Int32) -> String { + public func AttachmentMenu_SendGif(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[65 * 6 + Int(form.rawValue)]!, "\(value)") } - public func AttachmentMenu_SendPhoto(_ value: Int32) -> String { + public func Notification_GameScoreSelfSimple(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[66 * 6 + Int(form.rawValue)]!, "\(value)") } - public func AttachmentMenu_SendGif(_ value: Int32) -> String { + public func MessageTimer_Seconds(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[67 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Watch_UserInfo_Mute(_ value: Int32) -> String { + public func PUSH_CHANNEL_MESSAGE_FWDS(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[68 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessageTimer_Days(_ value: Int32) -> String { + public func LiveLocationUpdated_MinutesAgo(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[69 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessageTimer_Hours(_ value: Int32) -> String { + public func LiveLocation_MenuChatsCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[70 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Invitation_Members(_ value: Int32) -> String { + public func PUSH_CHAT_MESSAGE_FWDS(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[71 * 6 + Int(form.rawValue)]!, "\(value)") } - public func PUSH_MESSAGE_VIDEOS(_ value: Int32) -> String { + public func Conversation_StatusSubscribers(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[72 * 6 + Int(form.rawValue)]!, "\(value)") } - public func AttachmentMenu_SendItem(_ value: Int32) -> String { + public func MessageTimer_Days(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[73 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MuteExpires_Hours(_ value: Int32) -> String { + public func ServiceMessage_GameScoreSimple(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[74 * 6 + Int(form.rawValue)]!, "\(value)") } - public func LiveLocation_MenuChatsCount(_ value: Int32) -> String { + public func MessageTimer_ShortWeeks(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[75 * 6 + Int(form.rawValue)]!, "\(value)") } - public func SharedMedia_Link(_ value: Int32) -> String { + public func Call_Seconds(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[76 * 6 + Int(form.rawValue)]!, "\(value)") } - public func LastSeen_MinutesAgo(_ value: Int32) -> String { + public func Call_Minutes(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[77 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessageTimer_Months(_ value: Int32) -> String { + public func PUSH_MESSAGE_FWDS(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[78 * 6 + Int(form.rawValue)]!, "\(value)") } - public func PUSH_CHANNEL_MESSAGE_FWDS(_ value: Int32) -> String { + public func PUSH_CHAT_MESSAGE_VIDEOS(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[79 * 6 + Int(form.rawValue)]!, "\(value)") } - public func PUSH_MESSAGE_FWDS(_ value: Int32) -> String { + public func PasscodeSettings_FailedAttempts(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[80 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedGifs(_ value: Int32) -> String { + public func PUSH_MESSAGE_ROUNDS(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[81 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedAuthorsOthers(_ value: Int32) -> String { + public func StickerPack_AddStickerCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[82 * 6 + Int(form.rawValue)]!, "\(value)") } - public func PrivacyLastSeenSettings_AddUsers(_ value: Int32) -> String { + public func Watch_UserInfo_Mute(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[83 * 6 + Int(form.rawValue)]!, "\(value)") } - public func SharedMedia_Video(_ value: Int32) -> String { + public func MessageTimer_ShortSeconds(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[84 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MuteFor_Hours(_ value: Int32) -> String { + public func MessageTimer_Years(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[85 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedStickers(_ value: Int32) -> String { + public func LastSeen_MinutesAgo(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[86 * 6 + Int(form.rawValue)]!, "\(value)") } - public func UserCount(_ value: Int32) -> String { + public func Notification_GameScoreExtended(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[87 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ChatList_DeleteConfirmation(_ value: Int32) -> String { + public func Notification_GameScoreSimple(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[88 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessageTimer_Seconds(_ value: Int32) -> String { + public func ForwardedLocations(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[89 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Map_ETAHours(_ value: Int32) -> String { + public func ForwardedMessages(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[90 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Contacts_ImportersCount(_ value: Int32) -> String { + public func PUSH_MESSAGE_PHOTOS(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[91 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedPhotos(_ value: Int32) -> String { + public func Watch_LastSeen_HoursAgo(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[92 * 6 + Int(form.rawValue)]!, "\(value)") } - public func CreatePoll_AddMoreOptions(_ value: Int32) -> String { + public func PUSH_CHANNEL_MESSAGE_PHOTOS(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[93 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Call_ShortSeconds(_ value: Int32) -> String { + public func MessageTimer_ShortHours(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[94 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Passport_Scans(_ value: Int32) -> String { + public func CreatePoll_AddMoreOptions(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[95 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Notifications_ExceptionMuteExpires_Days(_ value: Int32) -> String { + public func Media_ShareVideo(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[96 * 6 + Int(form.rawValue)]!, "\(value)") } - public func AttachmentMenu_SendVideo(_ value: Int32) -> String { + public func PrivacyLastSeenSettings_AddUsers(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[97 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessagePoll_VotedCount(_ value: Int32) -> String { + public func ForwardedAudios(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[98 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Media_SharePhoto(_ value: Int32) -> String { + public func PUSH_CHAT_MESSAGE_ROUNDS(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[99 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ServiceMessage_GameScoreSelfSimple(_ value: Int32) -> String { + public func SharedMedia_DeleteItemsConfirmation(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[100 * 6 + Int(form.rawValue)]!, "\(value)") } - public func MessageTimer_Weeks(_ value: Int32) -> String { + public func PUSH_CHANNEL_MESSAGE_VIDEOS(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[101 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ServiceMessage_GameScoreExtended(_ value: Int32) -> String { + public func AttachmentMenu_SendItem(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[102 * 6 + Int(form.rawValue)]!, "\(value)") } - public func ForwardedVideoMessages(_ value: Int32) -> String { + public func UserCount(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[103 * 6 + Int(form.rawValue)]!, "\(value)") } - public func Notification_GameScoreExtended(_ value: Int32) -> String { + public func ForwardedPhotos(_ value: Int32) -> String { let form = presentationStringsPluralizationForm(self.lc, value) return String(format: self._ps[104 * 6 + Int(form.rawValue)]!, "\(value)") } diff --git a/TelegramUI/Resources/PresentationStrings.mapping b/TelegramUI/Resources/PresentationStrings.mapping index 897a7797165b4d08e6e8f20d6d154509d750b683..e9d4b89ea1f9ff0484bac63394e54ecca60bb908 100644 GIT binary patch delta 1507 zcmZWpTW=dx5cUA;kTz*)9oumdUt%{QP1|ir%cW2XuH(dp7`t63y#Zn4J&jj&cAY)z zYaHlLXcdWhfU4~ik8LD`gw%_8Ly$ip%ACgDk@|U6qxhYO!3=w9QuuJ3uyPS~b|@ zmX(5P@KKCdFdiNwhmWjVRlH&sO^avkBC~i9pVeS|CPV?E`~{WU3S)+xGAkC3ubN>3 zMY9(xG;f6&n(WZTBltIm$eD3+9VSZ~Rozx?-8AG3TU(*TQ9?yVhgz*ovvW0ue~6(T z!MjZuh6((pO3IkTCk+UndXp}Q;q+dbX9lzM!W6*+WEtX&T9L(oj^g7D7?!39p2FuX znB3=-eT>f2&KZL>=zHrpodqvFT1(q(?F2!h!h~8XkpgLM9Yx6av_++zM1#XIT(5!b z6I{Rev-6J`0wVZb14jFkb(`kGwA1+gCIsM&P)iuzMs)**q<1JTD&oeDu+j}hUn`f` zyM&3MIpRsA;`y$E-oq1h(%o4sTM&i!@njPMBOg$xsIyC8M~M6!{$|4zd?;o&l6J&) zp5lZOGHO{)=Hs1)K6*Jr!Zd8PVDpd3;S9AM-X24(&f|EfXg!UBbe4%#HPOUd+Noe_LSm`K6W(QS z!7MlrgI!ai@Ie6|+SIg$101G-Ioa@372I$GzivWkYL#w^r712s OJGMxNUAwKl2L1;nBc3|| delta 1572 zcmZWpOKcle6!i_Am^S^8CU!h_96N48(@+Mbd{RFBnAlDXnc8&np#_>w?U#5Id&ZtO z<2bP`b&pVmBK5AI>WUSMN-QgNUskLuR8>gq5E2r*EVyrMoHkiJS#!?yz4x7a-hH?y zJ=~M-{sNC{`1>{_`oM>e6d2mAUKoHre8xe>Cr$9fYxsu)<8TD8Hb9mopU-!k&YWH@ zE2?3-4&(jw9l^mYgeI=%manBWKLLYuGM2ri+eKEKvrI=XIQ(@2NANj^0RG(q36A0; z7edl8g5&pFAP;D)ysjCQYMBk-cWsysiCU*#PPJkbnZ-}wi!B%$)EuL*$?Q4HHJy_b zHG$y<#AeeChnZAX{81d06%Ad{O1jOm4y(M;g?sHK-J)UfK}^_i22Nw$h4{!21&NfZ zURBad$?jE$@tzIQXn+WjMWySf8&$(*TuJHMJV@9S{uYNYstz3QU$9)8k6^}zNeCg- zLH2hPlJVCDOa;Oe-&0d#1xutXl|6K)1n09T;E_zMupkR4W`>XN~q{AzpO2+ zscB71&ZpP%3%RA7Hb(G?1C$mcAc(a#1f-7O2?%AO{RzY_R%j8o+gBYCi zq`+7c`e7Q?CWOb{qIh8$&sSQ>vYoEt=LwwNmlP`v^5on2)P~56LYx?bH`!um%A((Q z2ouQ`b?#`4nTj`uvv|8jcD+ckqr$FurA0URP&}6S#g9Y=I;*-#Pcou>g&<)LVKS1^GuT!7mPOb8oLM$Zmc+X>HTV?ANmpr(*dRV{ zL-5GFv7W+jNm(OJpb+B~BMGx+2t4F4PpSDXlQrvx<4sOcS>+D1`2sPAyw|Zr7N50Y zEc_Woc;#Mt8eY=R@9#iDUL^Y9$QBKAQ^gn5Z2Vd`|0~U^v^`2ZN0jVs8PCRf{A&k7 z@C8BxhGW->6pycGxuolmiFnQ_QP&zOZ8!@{V%rR*J=vEjSiF?~#r0ZTAwcxr%hKI1 ze3ihXbe4H{*?fs*8xn8>f7pgd;3iStq&mC8%k>q`au^GJO_W$cy_ETq=1 znOnq&g8Q!TE`c=y#WT$7oLA{FC|W@``EB2B?WbYZzm| diff --git a/TelegramUI/SearchDisplayController.swift b/TelegramUI/SearchDisplayController.swift index 7456d56e9e..6bdbbe8fd4 100644 --- a/TelegramUI/SearchDisplayController.swift +++ b/TelegramUI/SearchDisplayController.swift @@ -30,6 +30,9 @@ final class SearchDisplayController { self.searchBar.cancel = { [weak self] in self?.isDeactivating = true cancel() + } + self.searchBar.clearPrefix = { + } self.contentNode.cancel = { [weak self] in self?.isDeactivating = true diff --git a/TelegramUI/SettingsThemeWallpaperNode.swift b/TelegramUI/SettingsThemeWallpaperNode.swift index 6aa61a6c61..22a28df2da 100644 --- a/TelegramUI/SettingsThemeWallpaperNode.swift +++ b/TelegramUI/SettingsThemeWallpaperNode.swift @@ -36,7 +36,7 @@ final class SettingsThemeWallpaperNode: ASDisplayNode { override init() { self.imageNode.contentAnimations = [.subsequentUpdates] - self.statusNode = RadialStatusNode(backgroundNodeColor: UIColor(white: 0.0, alpha: 0.6)) + self.statusNode = RadialStatusNode(backgroundNodeColor: UIColor(white: 0.0, alpha: 0.3)) let progressDiameter: CGFloat = 50.0 self.statusNode.frame = CGRect(x: 0.0, y: 0.0, width: progressDiameter, height: progressDiameter) self.statusNode.isUserInteractionEnabled = false diff --git a/TelegramUI/SuppressContactsWarning.swift b/TelegramUI/SuppressContactsWarning.swift new file mode 100644 index 0000000000..c16fd40fe8 --- /dev/null +++ b/TelegramUI/SuppressContactsWarning.swift @@ -0,0 +1,25 @@ +import Foundation +import AsyncDisplayKit +import Display +import SwiftSignalKit +import TelegramCore + +func presentContactsWarningSuppression(account: Account, present: (ViewController, Any?) -> Void) { + let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 } + present(textAlertController(account: account, title: presentationData.strings.Contacts_PermissionsSuppressWarningTitle, text: presentationData.strings.Contacts_PermissionsSuppressWarningText, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Contacts_PermissionsKeepDisabled, action: { + ApplicationSpecificNotice.setContactsPermissionWarning(postbox: account.postbox, value: Int32(Date().timeIntervalSince1970)) + }), TextAlertAction(type: .defaultAction, title: presentationData.strings.Contacts_PermissionsEnable, action: { + let _ = (DeviceAccess.authorizationStatus(account: account, subject: .contacts) + |> take(1) + |> deliverOnMainQueue).start(next: { status in + switch status { + case .notDetermined: + DeviceAccess.authorizeAccess(to: .contacts, account: account) + case .denied, .restricted: + account.telegramApplicationContext.applicationBindings.openSettings() + default: + break + } + }) + })]), nil) +} diff --git a/TelegramUI/TelegramRootController.swift b/TelegramUI/TelegramRootController.swift index bf7b30bc44..b7e8981733 100644 --- a/TelegramUI/TelegramRootController.swift +++ b/TelegramUI/TelegramRootController.swift @@ -82,8 +82,8 @@ public final class TelegramRootController: NavigationController { return } - DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) { - //(controller.navigationController as? NavigationController)?.pushViewController(ThemeGridController(account: self.account, mode: .wallpapers)) + DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.15) { + //(controller.navigationController as? NavigationController)?.pushViewController(ThemeGridController(account: self.account)) // let wrapperNode = ASDisplayNode() // let bounds = controller.displayNode.bounds diff --git a/TelegramUI/ThemeColorsGridControllerNode.swift b/TelegramUI/ThemeColorsGridControllerNode.swift index ef967c6a77..a84312d6bd 100644 --- a/TelegramUI/ThemeColorsGridControllerNode.swift +++ b/TelegramUI/ThemeColorsGridControllerNode.swift @@ -154,7 +154,7 @@ final class ThemeColorsGridControllerNode: ASDisplayNode { let entries = previousEntries.with { $0 } if let entries = entries, !entries.isEmpty { let wallpapers = entries.map { $0.wallpaper } - let controller = WallpaperListPreviewController(account: account, source: .list(wallpapers: wallpapers, central: wallpaper, mode: nil)) + let controller = WallpaperListPreviewController(account: account, source: .list(wallpapers: wallpapers, central: wallpaper, type: .colors)) strongSelf.present(controller, nil) } } @@ -225,7 +225,13 @@ final class ThemeColorsGridControllerNode: ASDisplayNode { insets.top += navigationBarHeight let scrollIndicatorInsets = insets - let referenceImageSize = CGSize(width: 108.0, height: 108.0) + let referenceImageSize: CGSize + let screenWidth = min(layout.size.width, layout.size.height) + if screenWidth >= 375.0 { + referenceImageSize = CGSize(width: 108.0, height: 108.0) + } else { + referenceImageSize = CGSize(width: 91.0, height: 91.0) + } let minSpacing: CGFloat = 8.0 diff --git a/TelegramUI/ThemeGridController.swift b/TelegramUI/ThemeGridController.swift index f7ef094483..34ed791aa1 100644 --- a/TelegramUI/ThemeGridController.swift +++ b/TelegramUI/ThemeGridController.swift @@ -125,7 +125,7 @@ final class ThemeGridController: ViewController { let controller = generator(legacyController.context) legacyController.bind(controller: controller) legacyController.deferScreenEdgeGestures = [.top] - controller.selectionBlock = { [weak self] asset, thumbnailImage in + controller.selectionBlock = { [weak self, weak legacyController] asset, thumbnailImage in if let strongSelf = self, let asset = asset { let controller = WallpaperListPreviewController(account: strongSelf.account, source: .asset(asset.backingAsset, thumbnailImage)) controller.apply = { [weak self, weak legacyController, weak controller] wallpaper, mode, cropRect in diff --git a/TelegramUI/ThemeGridControllerNode.swift b/TelegramUI/ThemeGridControllerNode.swift index 3f5dfc89fa..2ce2e2646e 100644 --- a/TelegramUI/ThemeGridControllerNode.swift +++ b/TelegramUI/ThemeGridControllerNode.swift @@ -222,7 +222,7 @@ final class ThemeGridControllerNode: ASDisplayNode { mode = strongSelf.presentationData.chatWallpaperMode } - presentPreviewController(.list(wallpapers: wallpapers, central: wallpaper, mode: mode)) + presentPreviewController(.list(wallpapers: wallpapers, central: wallpaper, type: .wallpapers(mode))) } } }, toggleWallpaperSelection: { [weak self] index, value in @@ -412,7 +412,13 @@ final class ThemeGridControllerNode: ASDisplayNode { let scrollIndicatorInsets = insets let minSpacing: CGFloat = 8.0 - let referenceImageSize = CGSize(width: 108.0, height: 230.0) + let referenceImageSize: CGSize + let screenWidth = min(layout.size.width, layout.size.height) + if screenWidth >= 375.0 { + referenceImageSize = CGSize(width: 108.0, height: 230.0) + } else { + referenceImageSize = CGSize(width: 91.0, height: 161.0) + } let imageCount = Int((layout.size.width - minSpacing * 2.0) / (referenceImageSize.width + minSpacing)) let imageSize = referenceImageSize.aspectFilled(CGSize(width: floor((layout.size.width - CGFloat(imageCount + 1) * minSpacing) / CGFloat(imageCount)), height: referenceImageSize.height)) let spacing = floor((layout.size.width - CGFloat(imageCount) * imageSize.width) / CGFloat(imageCount + 1)) @@ -520,9 +526,9 @@ final class ThemeGridControllerNode: ASDisplayNode { return } - self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, contentNode: ThemeGridSearchContainerNode(account: account, openResult: { [weak self] result, results in + self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, contentNode: ThemeGridSearchContainerNode(account: account, openResult: { [weak self] result in if let strongSelf = self { - strongSelf.presentPreviewController(.contextResults(results: results, central: result)) + strongSelf.presentPreviewController(.contextResult(result)) } }), cancel: { [weak self] in self?.requestDeactivateSearch?() diff --git a/TelegramUI/ThemeGridSearchColorsItem.swift b/TelegramUI/ThemeGridSearchColorsItem.swift index be68e19493..02c602e63b 100644 --- a/TelegramUI/ThemeGridSearchColorsItem.swift +++ b/TelegramUI/ThemeGridSearchColorsItem.swift @@ -38,13 +38,20 @@ private func nodeColor(for color: WallpaperSearchColor) -> UIColor { private class ThemeGridColorNode: HighlightableButtonNode { let action: () -> Void - init(color: WallpaperSearchColor, action: @escaping (WallpaperSearchColor) -> Void) { + init(color: WallpaperSearchColor, strokeColor: UIColor, action: @escaping (WallpaperSearchColor) -> Void) { self.action = { action(color) } super.init() - self.setImage(generateFilledCircleImage(diameter: 42.0, color: nodeColor(for: color)), for: .normal) + + let image: UIImage? + if color == .white { + image = generateCircleImage(diameter: 42.0, lineWidth: 1.0, color: strokeColor) + } else { + image = generateFilledCircleImage(diameter: 42.0, color: nodeColor(for: color)) + } + self.setImage(image, for: .normal) } override func didLoad() { @@ -91,7 +98,7 @@ final class ThemeGridSearchColorsNode: ASDisplayNode { self.addSubnode(self.scrollNode) for color in WallpaperSearchColor.allCases { - let colorNode = ThemeGridColorNode(color: color, action: colorSelected) + let colorNode = ThemeGridColorNode(color: color, strokeColor: theme.list.controlSecondaryColor, action: colorSelected) self.scrollNode.addSubnode(colorNode) } self.scrollNode.view.contentSize = CGSize(width: (inset + diameter) * CGFloat(WallpaperSearchColor.allCases.count) + inset, height: 71.0) diff --git a/TelegramUI/ThemeGridSearchContainerNode.swift b/TelegramUI/ThemeGridSearchContainerNode.swift index 1f0cd2badb..c1164b4468 100644 --- a/TelegramUI/ThemeGridSearchContainerNode.swift +++ b/TelegramUI/ThemeGridSearchContainerNode.swift @@ -268,7 +268,7 @@ final class ThemeGridSearchContainerNode: SearchDisplayControllerContentNode { return self._isSearching.get() } - init(account: Account, openResult: @escaping (ChatContextResult, [ChatContextResult]) -> Void) { + init(account: Account, openResult: @escaping (ChatContextResult) -> Void) { self.account = account self.dimNode = ASDisplayNode() @@ -330,12 +330,8 @@ final class ThemeGridSearchContainerNode: SearchDisplayControllerContentNode { let previousSearchItems = Atomic<[ThemeGridSearchEntry]?>(value: nil) let interaction = ThemeGridSearchInteraction(openResult: { [weak self] result in + openResult(result) self?.dismissInput?() - - let previousEntries = previousSearchItems.with { $0 } - if let entries = previousEntries { - openResult(result, entries.map { $0.result }) - } }, selectColor: { [weak self] color in self?.setQuery?("#color\(color.string) ") }, setSearchQuery: { [weak self] query in @@ -381,23 +377,25 @@ final class ThemeGridSearchContainerNode: SearchDisplayControllerContentNode { } |> mapToSignal { peer -> Signal<([ThemeGridSearchEntry], Bool)?, NoError> in if let user = peer as? TelegramUser, let botInfo = user.botInfo, let _ = botInfo.inlinePlaceholder { - return requestContextResults(account: account, botId: user.id, query: wallpaperQuery, peerId: account.peerId, limit: 16) - |> map { collection -> ([ThemeGridSearchEntry], Bool)? in - guard let collection = collection else { - return nil + return (.complete() |> delay(0.1, queue: Queue.concurrentDefaultQueue())) + |> then( + requestContextResults(account: account, botId: user.id, query: wallpaperQuery, peerId: account.peerId, limit: 16) + |> map { collection -> ([ThemeGridSearchEntry], Bool)? in + guard let collection = collection else { + return nil + } + var entries: [ThemeGridSearchEntry] = [] + var i = 0 + for result in collection.results { + entries.append(ThemeGridSearchEntry(index: i, result: result)) + i += 1 + } + updateSearchContext { _ in + return (ThemeGridSearchContext(result: ThemeGridSearchResult(query: query, items: collection.results, nextOffset: collection.nextOffset), loadMoreIndex: nil), true) + } + return (entries, false) } - var entries: [ThemeGridSearchEntry] = [] - var i = 0 - for result in collection.results { - entries.append(ThemeGridSearchEntry(index: i, result: result)) - i += 1 - } - - updateSearchContext { _ in - return (ThemeGridSearchContext(result: ThemeGridSearchResult(query: query, items: collection.results, nextOffset: collection.nextOffset), loadMoreIndex: nil), true) - } - return (entries, false) - } + ) } else { return .single(nil) } @@ -484,7 +482,6 @@ final class ThemeGridSearchContainerNode: SearchDisplayControllerContentNode { self.backgroundColor = theme.chatList.backgroundColor self.dimNode.backgroundColor = theme.chatList.backgroundColor self.recentListNode.verticalScrollIndicatorColor = theme.list.scrollIndicatorColor - //self.gridNode.verticalScrollIndicatorColor = theme.list.scrollIndicatorColor } // private func updateState(_ f: (ChatListSearchContainerNodeState) -> ChatListSearchContainerNodeState) { @@ -562,7 +559,13 @@ final class ThemeGridSearchContainerNode: SearchDisplayControllerContentNode { self.validLayout = layout let minSpacing: CGFloat = 8.0 - let referenceImageSize = CGSize(width: 108.0, height: 230.0) + let referenceImageSize: CGSize + let screenWidth = min(layout.size.width, layout.size.height) + if screenWidth >= 375.0 { + referenceImageSize = CGSize(width: 108.0, height: 230.0) + } else { + referenceImageSize = CGSize(width: 91.0, height: 161.0) + } let imageCount = Int((layout.size.width - minSpacing * 2.0) / (referenceImageSize.width + minSpacing)) let imageSize = referenceImageSize.aspectFilled(CGSize(width: floor((layout.size.width - CGFloat(imageCount + 1) * minSpacing) / CGFloat(imageCount)), height: referenceImageSize.height)) let spacing = floor((layout.size.width - CGFloat(imageCount) * imageSize.width) / CGFloat(imageCount + 1)) diff --git a/TelegramUI/ThemeGridSearchItem.swift b/TelegramUI/ThemeGridSearchItem.swift index e0104e8d5e..5af59cc8ab 100644 --- a/TelegramUI/ThemeGridSearchItem.swift +++ b/TelegramUI/ThemeGridSearchItem.swift @@ -65,6 +65,7 @@ final class ThemeGridSearchItemNode: GridItemNode { var thumbnailResource: TelegramMediaResource? var imageResource: TelegramMediaResource? var imageDimensions: CGSize? + var immediateThumbnailData: Data? switch item.result { case let .externalReference(_, _, type, _, _, _, content, thumbnail, _): if let content = content, type != "gif" { @@ -75,6 +76,7 @@ final class ThemeGridSearchItemNode: GridItemNode { imageDimensions = content?.dimensions case let .internalReference(_, _, _, _, _, image, file, _): if let image = image { + immediateThumbnailData = image.immediateThumbnailData if let largestRepresentation = largestImageRepresentation(image.representations) { imageDimensions = largestRepresentation.dimensions } @@ -91,6 +93,7 @@ final class ThemeGridSearchItemNode: GridItemNode { } } } else if let file = file { + immediateThumbnailData = file.immediateThumbnailData if let dimensions = file.dimensions { imageDimensions = dimensions } else if let largestRepresentation = largestImageRepresentation(file.previewRepresentations) { @@ -108,7 +111,7 @@ final class ThemeGridSearchItemNode: GridItemNode { representations.append(TelegramMediaImageRepresentation(dimensions: imageDimensions, resource: imageResource)) } if !representations.isEmpty { - let tmpImage = TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: representations, immediateThumbnailData: nil, reference: nil, partialReference: nil) + let tmpImage = TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: representations, immediateThumbnailData: immediateThumbnailData, reference: nil, partialReference: nil) updateImageSignal = mediaGridMessagePhoto(account: item.account, photoReference: .standalone(media: tmpImage)) } else { updateImageSignal = .complete() diff --git a/TelegramUI/WallpaperColorPickerNode.swift b/TelegramUI/WallpaperColorPickerNode.swift new file mode 100644 index 0000000000..870c42a31d --- /dev/null +++ b/TelegramUI/WallpaperColorPickerNode.swift @@ -0,0 +1,27 @@ +import Foundation +import AsyncDisplayKit +import SwiftSignalKit +import Display + +//private class WallpaperColorKnobNode: ASDisplayNode { +// +//} +// +//private class WallpaperColorSpaceNode: ASDisplayNode { +// private let knobNode: WallpaperColorNode +//} +// +// +//private class WallpaperColorBrightnessNode: ASDisplayNode { +// private let knobNode: WallpaperColorNode +// var baseColor: UIColor { +// didSet { +// setNeedsDisplay() +// } +// } +//} +// +//class WallpaperColorPickerNode: ASDisplayNode { +// private baseColorNode: WallpaperColorSpaceNode +// private colorBrightnessNode: WallpaperColorSpaceNode +//} diff --git a/TelegramUI/WallpaperListPreviewController.swift b/TelegramUI/WallpaperListPreviewController.swift index e7cb70559e..e254f1cca8 100644 --- a/TelegramUI/WallpaperListPreviewController.swift +++ b/TelegramUI/WallpaperListPreviewController.swift @@ -6,12 +6,18 @@ import TelegramCore import SwiftSignalKit import Photos +enum WallpaperListType { + case wallpapers(PresentationWallpaperMode?) + case colors +} + enum WallpaperListPreviewSource { - case list(wallpapers: [TelegramWallpaper], central: TelegramWallpaper, mode: PresentationWallpaperMode?) - case slug(String, TelegramMediaFile?) + case list(wallpapers: [TelegramWallpaper], central: TelegramWallpaper, type: WallpaperListType) case wallpaper(TelegramWallpaper) + case slug(String, TelegramMediaFile?) case asset(PHAsset, UIImage?) - case contextResults(results: [ChatContextResult], central: ChatContextResult) + case contextResult(ChatContextResult) + case customColor } final class WallpaperListPreviewController: ViewController { @@ -45,6 +51,7 @@ final class WallpaperListPreviewController: ViewController { super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData)) + self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait) self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBar.style.style self.presentationDataDisposable = (account.telegramApplicationContext.presentationData diff --git a/TelegramUI/WallpaperListPreviewControllerNode.swift b/TelegramUI/WallpaperListPreviewControllerNode.swift index 9782ad4b08..23a9585dc2 100644 --- a/TelegramUI/WallpaperListPreviewControllerNode.swift +++ b/TelegramUI/WallpaperListPreviewControllerNode.swift @@ -48,7 +48,8 @@ private final class WallpaperBackgroundNode: ASDisplayNode { private let statusNode: RadialStatusNode private let blurredNode: BlurredImageNode - let segmentedControlColor = Promise(.white) + let controlsColor = Promise(.white) + let status = Promise(.Local) init(account: Account, wallpaper: WallpaperEntry) { self.wallpaper = wallpaper @@ -133,7 +134,6 @@ private final class WallpaperBackgroundNode: ASDisplayNode { signal = photoWallpaper(postbox: account.postbox, photoLibraryResource: PhotoLibraryMediaResource(localIdentifier: asset.localIdentifier, uniqueId: arc4random64())) fetchSignal = .complete() statusSignal = .single(.Local) - self.wrapperNode.addSubnode(self.cropNode) case let .contextResult(result): var imageDimensions: CGSize? @@ -197,6 +197,7 @@ private final class WallpaperBackgroundNode: ASDisplayNode { } self.wrapperNode.addSubnode(self.statusNode) + let imagePromise = Promise() self.imageNode.setSignal(signal, dispatchOnDisplayLink: false) self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: displaySize, boundingSize: displaySize, intrinsicInsets: UIEdgeInsets()))() self.imageNode.imageUpdated = { [weak self] image in @@ -208,6 +209,7 @@ private final class WallpaperBackgroundNode: ASDisplayNode { } } strongSelf.blurredNode.image = image + imagePromise.set(.single(image)) } } self.fetchDisposable = fetchSignal.start() @@ -230,13 +232,14 @@ private final class WallpaperBackgroundNode: ASDisplayNode { } }) - let segmentedControlColorSignal: Signal + let controlsColorSignal: Signal if case let .wallpaper(wallpaper) = wallpaper { - segmentedControlColorSignal = chatBackgroundContrastColor(wallpaper: wallpaper, postbox: account.postbox) + controlsColorSignal = chatBackgroundContrastColor(wallpaper: wallpaper, postbox: account.postbox) } else { - segmentedControlColorSignal = .complete() + controlsColorSignal = backgroundContrastColor(for: imagePromise.get()) } - self.segmentedControlColor.set(.single(.white) |> then(segmentedControlColorSignal)) + self.controlsColor.set(.single(.white) |> then(controlsColorSignal)) + self.status.set(statusSignal) } deinit { @@ -340,6 +343,7 @@ private final class WallpaperBackgroundNode: ASDisplayNode { final class WallpaperListPreviewControllerNode: ViewControllerTracingNode { private let account: Account private var presentationData: PresentationData + private let source: WallpaperListPreviewSource private let dismiss: () -> Void private let apply: (WallpaperEntry, PresentationWallpaperMode, CGRect?) -> Void @@ -357,6 +361,9 @@ final class WallpaperListPreviewControllerNode: ViewControllerTracingNode { private var segmentedControlColor = Promise(.white) private var segmentedControlColorDisposable: Disposable? + private var status = Promise(.Local) + private var statusDisposable: Disposable? + private var wallpapersDisposable: Disposable? private var wallpapers: [WallpaperEntry]? let ready = ValuePromise(false) @@ -375,6 +382,7 @@ final class WallpaperListPreviewControllerNode: ViewControllerTracingNode { init(account: Account, presentationData: PresentationData, source: WallpaperListPreviewSource, dismiss: @escaping () -> Void, apply: @escaping (WallpaperEntry, PresentationWallpaperMode, CGRect?) -> Void) { self.account = account self.presentationData = presentationData + self.source = source self.dismiss = dismiss self.apply = apply @@ -459,13 +467,27 @@ final class WallpaperListPreviewControllerNode: ViewControllerTracingNode { } }) + self.statusDisposable = (self.status.get() + |> deliverOnMainQueue).start(next: { [weak self] status in + if let strongSelf = self { + switch status { + case .Local: + strongSelf.toolbarButtonApply.isEnabled = true + strongSelf.toolbarButtonApply.alpha = 1.0 + default: + strongSelf.toolbarButtonApply.isEnabled = false + strongSelf.toolbarButtonApply.alpha = 0.3 + } + } + }) + switch source { - case let .list(wallpapers, central, mode): + case let .list(wallpapers, central, type): self.wallpapers = wallpapers.map { .wallpaper($0) } self.centralWallpaper = WallpaperEntry.wallpaper(central) self.ready.set(true) - if let mode = mode { + if case let .wallpapers(wallpaperMode) = type, let mode = wallpaperMode { self.segmentedControl.selectedSegmentIndex = Int(clamping: mode.rawValue) } case let .slug(slug, file): @@ -485,9 +507,12 @@ final class WallpaperListPreviewControllerNode: ViewControllerTracingNode { self.wallpapers = [entry] self.centralWallpaper = entry self.ready.set(true) - case let .contextResults(results, central): - self.wallpapers = results.map { .contextResult($0) } - self.centralWallpaper = WallpaperEntry.contextResult(central) + case let .contextResult(result): + let entry = WallpaperEntry.contextResult(result) + self.wallpapers = [entry] + self.centralWallpaper = entry + self.ready.set(true) + case .customColor: self.ready.set(true) } if let (layout, navigationHeight) = self.validLayout { @@ -500,6 +525,8 @@ final class WallpaperListPreviewControllerNode: ViewControllerTracingNode { deinit { self.wallpapersDisposable?.dispose() + self.segmentedControlColorDisposable?.dispose() + self.statusDisposable?.dispose() } override func didLoad() { @@ -577,9 +604,32 @@ final class WallpaperListPreviewControllerNode: ViewControllerTracingNode { let chatPresentationData = ChatPresentationData(theme: ChatPresentationThemeData(theme: self.presentationData.theme, wallpaper: self.presentationData.chatWallpaper), fontSize: self.presentationData.fontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: false) - items.append(ChatMessageItem(presentationData: chatPresentationData, account: self.account, chatLocation: .peer(peerId), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .contact, automaticDownloadNetworkType: .cellular, isRecentActions: false), controllerInteraction: controllerInteraction, content: .message(message: Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: presentationData.strings.WallpaperPreview_MessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), read: true, selection: .none, isAdmin: false), disableDate: true)) + let topMessageText: String = "" + let bottomMessageText: String = "" +// switch self.source { +// case .wallpaper, .slug: +// topMessageText = presentationData.strings.WallpaperPreview_PreviewTopText +// bottomMessageText = presentationData.strings.WallpaperPreview_PreviewBottomText +// case let .list(_, _, type): +// switch type { +// case .wallpapers: +// topMessageText = presentationData.strings.WallpaperPreview_SwipeTopText +// bottomMessageText = presentationData.strings.WallpaperPreview_SwipeBottomText +// case .colors: +// topMessageText = presentationData.strings.WallpaperPreview_SwipeColorsTopText +// bottomMessageText = presentationData.strings.WallpaperPreview_SwipeColorsBottomText +// } +// case .asset, .contextResult: +// topMessageText = presentationData.strings.WallpaperPreview_CropTopText +// bottomMessageText = presentationData.strings.WallpaperPreview_CropBottomText +// case .customColor: +// topMessageText = presentationData.strings.WallpaperPreview_CustomColorTopText +// bottomMessageText = presentationData.strings.WallpaperPreview_CustomColorBottomText +// } - items.append(ChatMessageItem(presentationData: chatPresentationData, account: self.account, chatLocation: .peer(peerId), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .contact, automaticDownloadNetworkType: .cellular, isRecentActions: false), controllerInteraction: controllerInteraction, content: .message(message: Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: presentationData.strings.WallpaperPreview_SwipeInfo, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), read: true, selection: .none, isAdmin: false), disableDate: true)) + items.append(ChatMessageItem(presentationData: chatPresentationData, account: self.account, chatLocation: .peer(peerId), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .contact, automaticDownloadNetworkType: .cellular, isRecentActions: false), controllerInteraction: controllerInteraction, content: .message(message: Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: topMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), read: true, selection: .none, isAdmin: false), disableDate: true)) + + items.append(ChatMessageItem(presentationData: chatPresentationData, account: self.account, chatLocation: .peer(peerId), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .contact, automaticDownloadNetworkType: .cellular, isRecentActions: false), controllerInteraction: controllerInteraction, content: .message(message: Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: bottomMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), read: true, selection: .none, isAdmin: false), disableDate: true)) let params = ListViewItemLayoutParams(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right) if let messageNodes = self.messageNodes { @@ -687,7 +737,8 @@ final class WallpaperListPreviewControllerNode: ViewControllerTracingNode { } if j == i { - self.segmentedControlColor.set(itemNode.segmentedControlColor.get()) + self.segmentedControlColor.set(itemNode.controlsColor.get()) + self.status.set(itemNode.status.get()) } itemNodeTransition.updateFrame(node: itemNode, frame: itemFrame) diff --git a/TelegramUI/WebSearchController.swift b/TelegramUI/WebSearchController.swift index 7a0d7fe3bb..69106367b7 100644 --- a/TelegramUI/WebSearchController.swift +++ b/TelegramUI/WebSearchController.swift @@ -28,7 +28,7 @@ func requestContextResults(account: Account, botId: PeerId, query: String, peerI collection = results } if let collection = collection, collection.results.count < limit, let nextOffset = collection.nextOffset { - let nextResults = requestContextResults(account: account, botId: botId, query: query, peerId: peerId, offset: nextOffset, existingResults: collection) + let nextResults = requestContextResults(account: account, botId: botId, query: query, peerId: peerId, offset: nextOffset, existingResults: collection, limit: limit) if collection.results.count > 10 { return .single(collection) |> then(nextResults) diff --git a/TelegramUI/WebSearchItem.swift b/TelegramUI/WebSearchItem.swift index b196d8e2e3..e549319179 100644 --- a/TelegramUI/WebSearchItem.swift +++ b/TelegramUI/WebSearchItem.swift @@ -86,6 +86,8 @@ final class WebSearchItemNode: GridItemNode { var thumbnailResource: TelegramMediaResource? var imageResource: TelegramMediaResource? var imageDimensions: CGSize? + var immediateThumbnailData: Data? + switch item.result { case let .externalReference(_, _, type, _, _, _, content, thumbnail, _): if let content = content, type != "gif" { @@ -96,6 +98,7 @@ final class WebSearchItemNode: GridItemNode { imageDimensions = content?.dimensions case let .internalReference(_, _, _, _, _, image, file, _): if let image = image { + immediateThumbnailData = image.immediateThumbnailData if let largestRepresentation = largestImageRepresentation(image.representations) { imageDimensions = largestRepresentation.dimensions } @@ -112,6 +115,7 @@ final class WebSearchItemNode: GridItemNode { } } } else if let file = file { + immediateThumbnailData = file.immediateThumbnailData if let dimensions = file.dimensions { imageDimensions = dimensions } else if let largestRepresentation = largestImageRepresentation(file.previewRepresentations) { @@ -129,7 +133,7 @@ final class WebSearchItemNode: GridItemNode { representations.append(TelegramMediaImageRepresentation(dimensions: imageDimensions, resource: imageResource)) } if !representations.isEmpty { - let tmpImage = TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: representations, immediateThumbnailData: nil, reference: nil, partialReference: nil) + let tmpImage = TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: representations, immediateThumbnailData: immediateThumbnailData, reference: nil, partialReference: nil) updateImageSignal = mediaGridMessagePhoto(account: item.account, photoReference: .standalone(media: tmpImage)) } else { updateImageSignal = .complete()