From 5b80b9a85b5595e4c2eac40f644705a181b87330 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Wed, 5 Apr 2023 21:13:59 +0400 Subject: [PATCH] Chat wallpaper improvements --- .../Telegram-iOS/en.lproj/Localizable.strings | 8 ++ .../Themes/ThemeAccentColorController.swift | 12 +- .../ThemeAccentColorControllerNode.swift | 6 +- .../Themes/ThemeColorsGridController.swift | 35 +++++- .../ThemeColorsGridControllerNode.swift | 33 ++++-- .../Sources/Themes/ThemeGridController.swift | 92 ++++----------- .../Themes/ThemeGridControllerNode.swift | 27 ++--- .../Themes/WallpaperGalleryController.swift | 10 +- .../Sources/Themes/WallpaperGalleryItem.swift | 30 ++++- .../Sources/SolidRoundedButtonNode.swift | 9 +- .../TelegramUI/Sources/ChatController.swift | 15 +-- ...hatMessageWallpaperBubbleContentNode.swift | 2 +- .../TelegramUI/Sources/ChatThemeScreen.swift | 107 +++++++++--------- 13 files changed, 207 insertions(+), 179 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index e7f288e6d5..4f21a5b6a0 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -9143,3 +9143,11 @@ Sorry for the inconvenience."; "PeerInfo.Bot.EditCommands" = "Edit Commands"; "PeerInfo.Bot.ChangeSettings" = "Change Bot Settings"; "PeerInfo.Bot.BotFatherInfo" = "Use [@BotFather]() to manage this bot."; + +"WallpaperPreview.NotAppliedInfo" = "Background will not be applied for **%@**"; +"WallpaperPreview.ChatTopText" = "Apply the background in this chat."; +"WallpaperPreview.ChatBottomText" = "Enjoy the view."; + +"Conversation.Theme.SetPhotoWallpaper" = "Choose Background from Photos"; +"Conversation.Theme.SetColorWallpaper" = "Choose Color as a Background"; +"Conversation.Theme.OtherOptions" = "Other Options..."; diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift index 9d9c93a936..41b777cc59 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift @@ -35,9 +35,13 @@ enum ThemeAccentColorControllerMode { } final class ThemeAccentColorController: ViewController { + enum ResultMode { + case `default` + case peer(EnginePeer) + } private let context: AccountContext private let mode: ThemeAccentColorControllerMode - private let forChat: Bool + private let resultMode: ResultMode private let section: ThemeColorSection private let initialBackgroundColor: UIColor? private var presentationData: PresentationData @@ -58,10 +62,10 @@ final class ThemeAccentColorController: ViewController { var completion: (() -> Void)? - init(context: AccountContext, mode: ThemeAccentColorControllerMode, forChat: Bool = false) { + init(context: AccountContext, mode: ThemeAccentColorControllerMode, resultMode: ResultMode = .default) { self.context = context self.mode = mode - self.forChat = forChat + self.resultMode = resultMode self.presentationData = context.sharedContext.currentPresentationData.with { $0 } let section: ThemeColorSection = .background @@ -145,7 +149,7 @@ final class ThemeAccentColorController: ViewController { initialWallpaper = self.presentationData.chatWallpaper } - self.displayNode = ThemeAccentColorControllerNode(context: self.context, mode: self.mode, forChat: self.forChat, theme: theme, wallpaper: initialWallpaper, dismiss: { [weak self] in + self.displayNode = ThemeAccentColorControllerNode(context: self.context, mode: self.mode, resultMode: self.resultMode, theme: theme, wallpaper: initialWallpaper, dismiss: { [weak self] in if let strongSelf = self { strongSelf.dismiss() } diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift index a500239f95..9ead4f5c37 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift @@ -224,7 +224,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate } } - init(context: AccountContext, mode: ThemeAccentColorControllerMode, forChat: Bool, theme: PresentationTheme, wallpaper: TelegramWallpaper, dismiss: @escaping () -> Void, apply: @escaping (ThemeColorState, UIColor?) -> Void, ready: Promise) { + init(context: AccountContext, mode: ThemeAccentColorControllerMode, resultMode: ThemeAccentColorController.ResultMode, theme: PresentationTheme, wallpaper: TelegramWallpaper, dismiss: @escaping () -> Void, apply: @escaping (ThemeColorState, UIColor?) -> Void, ready: Promise) { self.context = context self.mode = mode self.state = ThemeColorState() @@ -305,8 +305,10 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate let doneButtonType: WallpaperGalleryToolbarDoneButtonType if case .edit(_, _, _, _, _, true, _) = self.mode { doneButtonType = .proceed + } else if case .peer = resultMode { + doneButtonType = .setPeer } else { - doneButtonType = forChat ? .setPeer : .set + doneButtonType = .set } self.toolbarNode = WallpaperGalleryToolbarNode(theme: self.theme, strings: self.presentationData.strings, doneButtonType: doneButtonType) self.toolbarNode.setDoneIsSolid(true, transition: .immediate) diff --git a/submodules/SettingsUI/Sources/Themes/ThemeColorsGridController.swift b/submodules/SettingsUI/Sources/Themes/ThemeColorsGridController.swift index 3511eadd64..bc402517a9 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeColorsGridController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeColorsGridController.swift @@ -103,6 +103,29 @@ private func availableColors(theme: PresentationTheme) -> [UInt32] { } public final class ThemeColorsGridController: ViewController { + public enum Mode { + case `default` + case peer(EnginePeer) + + var galleryMode: WallpaperGalleryController.Mode { + switch self { + case .default: + return .default + case let .peer(peer): + return .peer(peer, false) + } + } + + var colorPickerMode: ThemeAccentColorController.ResultMode { + switch self { + case .default: + return .default + case let .peer(peer): + return .peer(peer) + } + } + } + private var controllerNode: ThemeColorsGridControllerNode { return self.displayNode as! ThemeColorsGridControllerNode } @@ -113,7 +136,7 @@ public final class ThemeColorsGridController: ViewController { } private let context: AccountContext - private let peerId: PeerId? + let mode: Mode private var presentationData: PresentationData private var presentationDataDisposable: Disposable? @@ -122,9 +145,9 @@ public final class ThemeColorsGridController: ViewController { private var previousContentOffset: GridNodeVisibleContentOffset? - public init(context: AccountContext, peerId: PeerId? = nil) { + public init(context: AccountContext, mode: Mode = .default) { self.context = context - self.peerId = peerId + self.mode = mode self.presentationData = context.sharedContext.currentPresentationData.with { $0 } super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData)) @@ -172,7 +195,7 @@ public final class ThemeColorsGridController: ViewController { } public override func loadDisplayNode() { - self.displayNode = ThemeColorsGridControllerNode(context: self.context, presentationData: self.presentationData, peerId: self.peerId, gradients: availableGradients(theme: self.presentationData.theme), colors: availableColors(theme: self.presentationData.theme), push: { [weak self] controller in + self.displayNode = ThemeColorsGridControllerNode(context: self.context, presentationData: self.presentationData, controller: self, gradients: availableGradients(theme: self.presentationData.theme), colors: availableColors(theme: self.presentationData.theme), push: { [weak self] controller in self?.push(controller) }, pop: { [weak self] in if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController { @@ -195,8 +218,8 @@ public final class ThemeColorsGridController: ViewController { } else { themeReference = settings.theme } - - let controller = ThemeAccentColorController(context: strongSelf.context, mode: .background(themeReference: themeReference), forChat: strongSelf.peerId != nil) + + let controller = ThemeAccentColorController(context: strongSelf.context, mode: .background(themeReference: themeReference), resultMode: strongSelf.mode.colorPickerMode) controller.completion = { [weak self] in if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController { var controllers = navigationController.viewControllers diff --git a/submodules/SettingsUI/Sources/Themes/ThemeColorsGridControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemeColorsGridControllerNode.swift index d03b53c1fa..72d0a6ca95 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeColorsGridControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeColorsGridControllerNode.swift @@ -63,10 +63,10 @@ private func preparedThemeColorsGridEntryTransition(context: AccountContext, fro return ThemeColorsGridEntryTransition(deletions: deletions, insertions: insertions, updates: updates, updateFirstIndexInSectionOffset: nil, stationaryItems: stationaryItems, scrollToItem: scrollToItem) } -final class ThemeColorsGridControllerNode: ASDisplayNode { +final class ThemeColorsGridControllerNode: ASDisplayNode { private let context: AccountContext + private weak var controller: ThemeColorsGridController? private var presentationData: PresentationData - private let peerId: PeerId? private var controllerInteraction: ThemeColorsGridControllerInteraction? private let push: (ViewController) -> Void private let presentColorPicker: () -> Void @@ -88,9 +88,9 @@ final class ThemeColorsGridControllerNode: ASDisplayNode { private var disposable: Disposable? - init(context: AccountContext, presentationData: PresentationData, peerId: PeerId?, gradients: [[UInt32]], colors: [UInt32], push: @escaping (ViewController) -> Void, pop: @escaping () -> Void, presentColorPicker: @escaping () -> Void) { + init(context: AccountContext, presentationData: PresentationData, controller: ThemeColorsGridController, gradients: [[UInt32]], colors: [UInt32], push: @escaping (ViewController) -> Void, pop: @escaping () -> Void, presentColorPicker: @escaping () -> Void) { self.context = context - self.peerId = peerId + self.controller = controller self.presentationData = presentationData self.push = push self.presentColorPicker = presentColorPicker @@ -128,15 +128,34 @@ final class ThemeColorsGridControllerNode: ASDisplayNode { let previousEntries = Atomic<[ThemeColorsGridControllerEntry]?>(value: nil) + let dismissControllers = { [weak self] in + if let self, let navigationController = self.controller?.navigationController as? NavigationController { + let controllers = navigationController.viewControllers.filter({ controller in + if controller is ThemeColorsGridController || controller is WallpaperGalleryController { + return false + } + return true + }) + navigationController.setViewControllers(controllers, animated: true) + } + } + let interaction = ThemeColorsGridControllerInteraction(openWallpaper: { [weak self] wallpaper in if let strongSelf = self { let entries = previousEntries.with { $0 } if let entries = entries, !entries.isEmpty { let wallpapers = entries.map { $0.wallpaper } - let controller = WallpaperGalleryController(context: context, source: .list(wallpapers: wallpapers, central: wallpaper, type: .colors), mode: strongSelf.peerId.flatMap { .peer($0) } ?? .default) + let controller = WallpaperGalleryController(context: context, source: .list(wallpapers: wallpapers, central: wallpaper, type: .colors), mode: strongSelf.controller?.mode.galleryMode ?? .default) controller.navigationPresentation = .modal - controller.apply = { _, _, _ in - pop() + controller.apply = { [weak self] wallpaper, _, _ in + if let strongSelf = self, let mode = strongSelf.controller?.mode, case let .peer(peer) = mode, case let .wallpaper(wallpaperValue, _) = wallpaper { + let _ = (strongSelf.context.engine.themes.setChatWallpaper(peerId: peer.id, wallpaper: wallpaperValue) + |> deliverOnMainQueue).start(completed: { + dismissControllers() + }) + } else { + pop() + } } strongSelf.push(controller) } diff --git a/submodules/SettingsUI/Sources/Themes/ThemeGridController.swift b/submodules/SettingsUI/Sources/Themes/ThemeGridController.swift index f4c5dc3d57..852059bd5f 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeGridController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeGridController.swift @@ -17,20 +17,6 @@ import PresentationDataUtils import MediaPickerUI public final class ThemeGridController: ViewController { - public enum Mode: Equatable { - case `default` - case peer(EnginePeer.Id, TelegramWallpaper?) - - var galleryMode: WallpaperGalleryController.Mode { - switch self { - case .default: - return .default - case let .peer(peerId, _): - return .peer(peerId) - } - } - } - private var controllerNode: ThemeGridControllerNode { return self.displayNode as! ThemeGridControllerNode } @@ -41,7 +27,6 @@ public final class ThemeGridController: ViewController { } private let context: AccountContext - private let mode: Mode private var presentationData: PresentationData private let presentationDataPromise = Promise() @@ -60,9 +45,8 @@ public final class ThemeGridController: ViewController { private var previousContentOffset: GridNodeVisibleContentOffset? - public init(context: AccountContext, mode: Mode = .default) { + public init(context: AccountContext) { self.context = context - self.mode = mode self.presentationData = context.sharedContext.currentPresentationData.with { $0 } self.presentationDataPromise.set(.single(self.presentationData)) @@ -115,7 +99,7 @@ public final class ThemeGridController: ViewController { self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil) if let isEmpty = self.isEmpty, isEmpty { - } else if case .default = mode { + } else { if self.editingMode { self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Done, style: .done, target: self, action: #selector(self.donePressed)) } else { @@ -133,44 +117,25 @@ public final class ThemeGridController: ViewController { } public override func loadDisplayNode() { - let dismissControllers = { [weak self] in - if let self, let navigationController = self.navigationController as? NavigationController { - let controllers = navigationController.viewControllers.filter({ controller in - if controller is ThemeGridController || controller is WallpaperGalleryController || controller is MediaPickerScreen { - return false - } - return true - }) - navigationController.setViewControllers(controllers, animated: true) - } - } - self.displayNode = ThemeGridControllerNode(context: self.context, presentationData: self.presentationData, mode: self.mode, presentPreviewController: { [weak self] source in + self.displayNode = ThemeGridControllerNode(context: self.context, presentationData: self.presentationData, presentPreviewController: { [weak self] source in if let strongSelf = self { - let controller = WallpaperGalleryController(context: strongSelf.context, source: source, mode: strongSelf.mode.galleryMode) + let controller = WallpaperGalleryController(context: strongSelf.context, source: source) controller.apply = { [weak self, weak controller] wallpaper, options, cropRect in - if let strongSelf = self, case let .wallpaper(wallpaperValue, _) = wallpaper { - switch strongSelf.mode { - case .default: - uploadCustomWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: options, cropRect: cropRect, completion: { [weak self, weak controller] in - if let strongSelf = self { - strongSelf.deactivateSearch(animated: false) - strongSelf.controllerNode.scrollToTop(animated: false) + if let strongSelf = self { + uploadCustomWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: options, cropRect: cropRect, completion: { [weak self, weak controller] in + if let strongSelf = self { + strongSelf.deactivateSearch(animated: false) + strongSelf.controllerNode.scrollToTop(animated: false) + } + if let controller = controller { + switch wallpaper { + case .asset, .contextResult: + controller.dismiss(animated: true) + default: + break } - if let controller = controller { - switch wallpaper { - case .asset, .contextResult: - controller.dismiss(animated: true) - default: - break - } - } - }) - case let .peer(peerId, _): - let _ = (strongSelf.context.engine.themes.setChatWallpaper(peerId: peerId, wallpaper: wallpaperValue) - |> deliverOnMainQueue).start(completed: { - dismissControllers() - }) - } + } + }) } } self?.push(controller) @@ -182,21 +147,14 @@ public final class ThemeGridController: ViewController { guard let strongSelf = self else { return } - let controller = WallpaperGalleryController(context: strongSelf.context, source: .asset(asset), mode: strongSelf.mode.galleryMode) + let controller = WallpaperGalleryController(context: strongSelf.context, source: .asset(asset)) controller.apply = { [weak self, weak controller] wallpaper, options, cropRect in if let strongSelf = self, let controller = controller { - switch strongSelf.mode { - case .default: - uploadCustomWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: options, cropRect: cropRect, completion: { [weak controller] in - if let controller = controller { - controller.dismiss(forceAway: true) - } - }) - case let .peer(peerId, _): - uploadCustomPeerWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: options, cropRect: cropRect, peerId: peerId, completion: { - dismissControllers() - }) - } + uploadCustomWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: options, cropRect: cropRect, completion: { [weak controller] in + if let controller = controller { + controller.dismiss(forceAway: true) + } + }) } } strongSelf.push(controller) @@ -215,7 +173,7 @@ public final class ThemeGridController: ViewController { if empty { strongSelf.navigationItem.setRightBarButton(nil, animated: true) - } else if case .default = strongSelf.mode { + } else { if strongSelf.editingMode { strongSelf.navigationItem.rightBarButtonItem = UIBarButtonItem(title: strongSelf.presentationData.strings.Common_Done, style: .done, target: strongSelf, action: #selector(strongSelf.donePressed)) } else { diff --git a/submodules/SettingsUI/Sources/Themes/ThemeGridControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemeGridControllerNode.swift index d2dc4f4494..7c69c681d9 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeGridControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeGridControllerNode.swift @@ -141,7 +141,6 @@ final class ThemeGridControllerNode: ASDisplayNode { private let context: AccountContext private var presentationData: PresentationData - private let mode: ThemeGridController.Mode private var controllerInteraction: ThemeGridControllerInteraction? private let presentPreviewController: (WallpaperListSource) -> Void @@ -193,9 +192,8 @@ final class ThemeGridControllerNode: ASDisplayNode { private var disposable: Disposable? - init(context: AccountContext, presentationData: PresentationData, mode: ThemeGridController.Mode, presentPreviewController: @escaping (WallpaperListSource) -> Void, presentGallery: @escaping () -> Void, presentColors: @escaping () -> Void, emptyStateUpdated: @escaping (Bool) -> Void, deleteWallpapers: @escaping ([TelegramWallpaper], @escaping () -> Void) -> Void, shareWallpapers: @escaping ([TelegramWallpaper]) -> Void, resetWallpapers: @escaping () -> Void, popViewController: @escaping () -> Void) { + init(context: AccountContext, presentationData: PresentationData, presentPreviewController: @escaping (WallpaperListSource) -> Void, presentGallery: @escaping () -> Void, presentColors: @escaping () -> Void, emptyStateUpdated: @escaping (Bool) -> Void, deleteWallpapers: @escaping ([TelegramWallpaper], @escaping () -> Void) -> Void, shareWallpapers: @escaping ([TelegramWallpaper]) -> Void, resetWallpapers: @escaping () -> Void, popViewController: @escaping () -> Void) { self.context = context - self.mode = mode self.presentationData = presentationData self.presentPreviewController = presentPreviewController self.presentGallery = presentGallery @@ -263,10 +261,9 @@ final class ThemeGridControllerNode: ASDisplayNode { self.gridNode.addSubnode(self.colorItemNode) self.gridNode.addSubnode(self.galleryItemNode) self.gridNode.addSubnode(self.descriptionItemNode) - if case .default = self.mode { - self.gridNode.addSubnode(self.resetItemNode) - self.gridNode.addSubnode(self.resetDescriptionItemNode) - } + self.gridNode.addSubnode(self.resetItemNode) + self.gridNode.addSubnode(self.resetDescriptionItemNode) + self.addSubnode(self.gridNode) let previousEntries = Atomic<[ThemeGridControllerEntry]?>(value: nil) @@ -342,20 +339,13 @@ final class ThemeGridControllerNode: ASDisplayNode { }) self.controllerInteraction = interaction - var selectFirst = true - if case .peer = self.mode { - selectFirst = false - } - let transition = combineLatest(self.wallpapersPromise.get(), deletedWallpaperIdsPromise.get(), context.sharedContext.presentationData) |> map { wallpapers, deletedWallpaperIds, presentationData -> (ThemeGridEntryTransition, Bool) in var entries: [ThemeGridControllerEntry] = [] var index: Int = 0 - if selectFirst { - entries.insert(ThemeGridControllerEntry(index: 0, wallpaper: presentationData.chatWallpaper, isEditable: false, isSelected: true), at: 0) - index += 1 - } + entries.insert(ThemeGridControllerEntry(index: 0, wallpaper: presentationData.chatWallpaper, isEditable: false, isSelected: true), at: 0) + index += 1 var defaultWallpaper: TelegramWallpaper? if !presentationData.chatWallpaper.isBasicallyEqual(to: presentationData.theme.chat.defaultWallpaper) { @@ -756,9 +746,8 @@ final class ThemeGridControllerNode: ASDisplayNode { let makeResetDescriptionLayout = self.resetDescriptionItemNode.asyncLayout() let (resetDescriptionLayout, _) = makeResetDescriptionLayout(self.resetDescriptionItem, params, ItemListNeighbors(top: .none, bottom: .none)) - if case .default = self.mode { - insets.bottom += buttonHeight + 35.0 + resetDescriptionLayout.contentSize.height + 32.0 - } + + insets.bottom += buttonHeight + 35.0 + resetDescriptionLayout.contentSize.height + 32.0 self.gridNode.frame = CGRect(x: 0.0, y: 0.0, width: layout.size.width, height: layout.size.height) self.gridNode.transaction(GridNodeTransaction(deleteItems: [], insertItems: [], updateItems: [], scrollToItem: nil, updateLayout: GridNodeUpdateLayout(layout: GridNodeLayout(size: layout.size, insets: insets, scrollIndicatorInsets: scrollIndicatorInsets, preloadSize: 300.0, type: .fixed(itemSize: imageSize, fillWidth: nil, lineSpacing: spacing, itemSpacing: nil)), transition: transition), itemTransition: .immediate, stationaryItems: .none, updateFirstIndexInSectionOffset: nil), completion: { _ in }) diff --git a/submodules/SettingsUI/Sources/Themes/WallpaperGalleryController.swift b/submodules/SettingsUI/Sources/Themes/WallpaperGalleryController.swift index 89e4136341..e0e357ec39 100644 --- a/submodules/SettingsUI/Sources/Themes/WallpaperGalleryController.swift +++ b/submodules/SettingsUI/Sources/Themes/WallpaperGalleryController.swift @@ -167,7 +167,7 @@ private func updatedFileWallpaper(id: Int64? = nil, accessHash: Int64? = nil, sl public class WallpaperGalleryController: ViewController { public enum Mode { case `default` - case peer(EnginePeer.Id) + case peer(EnginePeer, Bool) } private var galleryNode: GalleryControllerNode { return self.displayNode as! GalleryControllerNode @@ -350,7 +350,7 @@ public class WallpaperGalleryController: ViewController { var i: Int = 0 var updateItems: [GalleryPagerUpdateItem] = [] for entry in entries { - let item = GalleryPagerUpdateItem(index: i, previousIndex: i, item: WallpaperGalleryItem(context: self.context, index: updateItems.count, entry: entry, arguments: arguments, source: self.source)) + let item = GalleryPagerUpdateItem(index: i, previousIndex: i, item: WallpaperGalleryItem(context: self.context, index: updateItems.count, entry: entry, arguments: arguments, source: self.source, mode: self.mode)) updateItems.append(item) i += 1 } @@ -361,7 +361,7 @@ public class WallpaperGalleryController: ViewController { var updateItems: [GalleryPagerUpdateItem] = [] for i in 0 ..< self.entries.count { if i == index { - let item = GalleryPagerUpdateItem(index: index, previousIndex: index, item: WallpaperGalleryItem(context: self.context, index: index, entry: entry, arguments: arguments, source: self.source)) + let item = GalleryPagerUpdateItem(index: index, previousIndex: index, item: WallpaperGalleryItem(context: self.context, index: index, entry: entry, arguments: arguments, source: self.source, mode: self.mode)) updateItems.append(item) } } @@ -495,7 +495,7 @@ public class WallpaperGalleryController: ViewController { } return current.withUpdatedThemeSpecificChatWallpapers(themeSpecificChatWallpapers) }) |> deliverOnMainQueue).start(completed: { - self?.dismiss(forceAway: true) + self?.dismiss(animated: true) }) switch strongSelf.source { @@ -954,7 +954,7 @@ public class WallpaperGalleryController: ViewController { colors = true } - self.galleryNode.pager.replaceItems(zip(0 ..< self.entries.count, self.entries).map({ WallpaperGalleryItem(context: self.context, index: $0, entry: $1, arguments: WallpaperGalleryItemArguments(isColorsList: colors), source: self.source) }), centralItemIndex: self.centralEntryIndex) + self.galleryNode.pager.replaceItems(zip(0 ..< self.entries.count, self.entries).map({ WallpaperGalleryItem(context: self.context, index: $0, entry: $1, arguments: WallpaperGalleryItemArguments(isColorsList: colors), source: self.source, mode: self.mode) }), centralItemIndex: self.centralEntryIndex) if let initialOptions = self.initialOptions, let itemNode = self.galleryNode.pager.centralItemNode() as? WallpaperGalleryItemNode { itemNode.options = initialOptions diff --git a/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift b/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift index 414bce6a22..a63e7ff887 100644 --- a/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift +++ b/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift @@ -18,6 +18,7 @@ import LocalMediaResources import WallpaperResources import AppBundle import WallpaperBackgroundNode +import TextFormat struct WallpaperGalleryItemArguments { let colorPreview: Bool @@ -42,24 +43,26 @@ class WallpaperGalleryItem: GalleryItem { let entry: WallpaperGalleryEntry let arguments: WallpaperGalleryItemArguments let source: WallpaperListSource + let mode: WallpaperGalleryController.Mode - init(context: AccountContext, index: Int, entry: WallpaperGalleryEntry, arguments: WallpaperGalleryItemArguments, source: WallpaperListSource) { + init(context: AccountContext, index: Int, entry: WallpaperGalleryEntry, arguments: WallpaperGalleryItemArguments, source: WallpaperListSource, mode: WallpaperGalleryController.Mode) { self.context = context self.index = index self.entry = entry self.arguments = arguments self.source = source + self.mode = mode } func node(synchronous: Bool) -> GalleryItemNode { let node = WallpaperGalleryItemNode(context: self.context) - node.setEntry(self.entry, arguments: self.arguments, source: self.source) + node.setEntry(self.entry, arguments: self.arguments, source: self.source, mode: self.mode) return node } func updateNode(node: GalleryItemNode, synchronous: Bool) { if let node = node as? WallpaperGalleryItemNode { - node.setEntry(self.entry, arguments: self.arguments, source: self.source) + node.setEntry(self.entry, arguments: self.arguments, source: self.source, mode: self.mode) } } @@ -84,6 +87,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode { var entry: WallpaperGalleryEntry? var source: WallpaperListSource? + var mode: WallpaperGalleryController.Mode? private var colorPreview: Bool = false private var contentSize: CGSize? private var arguments = WallpaperGalleryItemArguments() @@ -263,10 +267,11 @@ final class WallpaperGalleryItemNode: GalleryItemNode { self.dismiss() } - func setEntry(_ entry: WallpaperGalleryEntry, arguments: WallpaperGalleryItemArguments, source: WallpaperListSource) { + func setEntry(_ entry: WallpaperGalleryEntry, arguments: WallpaperGalleryItemArguments, source: WallpaperListSource, mode: WallpaperGalleryController.Mode) { let previousArguments = self.arguments self.arguments = arguments self.source = source + self.mode = mode if self.arguments.colorPreview != previousArguments.colorPreview { if self.arguments.colorPreview { @@ -1063,6 +1068,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode { var topMessageText = "" var bottomMessageText = "" + var serviceMessageText: String? var currentWallpaper: TelegramWallpaper = self.presentationData.chatWallpaper if let entry = self.entry, case let .wallpaper(wallpaper, _) = entry { currentWallpaper = wallpaper @@ -1125,6 +1131,14 @@ final class WallpaperGalleryItemNode: GalleryItemNode { } } + if let mode = self.mode, case let .peer(peer, existing) = mode { + topMessageText = presentationData.strings.WallpaperPreview_ChatTopText + bottomMessageText = presentationData.strings.WallpaperPreview_ChatBottomText + if !existing { + serviceMessageText = presentationData.strings.WallpaperPreview_NotAppliedInfo(peer.compactDisplayTitle).string + } + } + let theme = self.presentationData.theme.withUpdated(preview: true) let message1 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: bottomMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil) @@ -1133,6 +1147,14 @@ final class WallpaperGalleryItemNode: GalleryItemNode { let message2 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: topMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message2], theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.nativeNode, availableReactions: nil, isCentered: false)) + if let serviceMessageText { + let attributedText = convertMarkdownToAttributes(NSAttributedString(string: serviceMessageText)) + let entities = generateChatInputTextEntities(attributedText) + + let message3 = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: attributedText.string, entities: entities))], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil) + items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message3], theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.nativeNode, availableReactions: nil, isCentered: false)) + } + let params = ListViewItemLayoutParams(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, availableHeight: layout.size.height) if let messageNodes = self.messageNodes { if self.validMessages != [topMessageText, bottomMessageText] { diff --git a/submodules/SolidRoundedButtonNode/Sources/SolidRoundedButtonNode.swift b/submodules/SolidRoundedButtonNode/Sources/SolidRoundedButtonNode.swift index 89e9e5bbd8..b8ae91d681 100644 --- a/submodules/SolidRoundedButtonNode/Sources/SolidRoundedButtonNode.swift +++ b/submodules/SolidRoundedButtonNode/Sources/SolidRoundedButtonNode.swift @@ -160,7 +160,6 @@ private final class BadgeNode: ASDisplayNode { public final class SolidRoundedButtonNode: ASDisplayNode { private var theme: SolidRoundedButtonTheme - private var font: SolidRoundedButtonFont private var fontSize: CGFloat private let gloss: Bool @@ -204,6 +203,14 @@ public final class SolidRoundedButtonNode: ASDisplayNode { } } + public var font: SolidRoundedButtonFont { + didSet { + if let width = self.validLayout { + _ = self.updateLayout(width: width, transition: .immediate) + } + } + } + public var subtitle: String? { didSet { self.updateAccessibilityLabels() diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 2e1560dd8d..0a5023201f 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -839,11 +839,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.presentThemeSelection() return true case let .setChatWallpaper(wallpaper): - guard message.effectivelyIncoming(strongSelf.context.account.peerId) else { + guard message.effectivelyIncoming(strongSelf.context.account.peerId), let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer else { return true } strongSelf.chatDisplayNode.dismissInput() - let wallpaperPreviewController = WallpaperGalleryController(context: strongSelf.context, source: .wallpaper(wallpaper, nil, [], nil, nil, nil), mode: .peer(message.id.peerId)) + let wallpaperPreviewController = WallpaperGalleryController(context: strongSelf.context, source: .wallpaper(wallpaper, nil, [], nil, nil, nil), mode: .peer(EnginePeer(peer), true)) wallpaperPreviewController.apply = { wallpaper, options, _ in let _ = (strongSelf.context.engine.themes.setExistingChatWallpaper(messageId: message.id) |> deliverOnMainQueue).start(completed: { [weak wallpaperPreviewController] in @@ -18480,10 +18480,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let _ = (combineLatest(queue: Queue.mainQueue(), self.chatThemeEmoticonPromise.get(), animatedEmojiStickers) |> take(1)).start(next: { [weak self] themeEmoticon, animatedEmojiStickers in - guard let strongSelf = self else { + guard let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer else { return } - + + let selectedEmoticon: String? = themeEmoticon let controller = ChatThemeScreen( @@ -18524,7 +18525,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G guard let strongSelf = self else { return } - let controller = WallpaperGalleryController(context: strongSelf.context, source: .asset(asset), mode: .peer(peerId)) + let controller = WallpaperGalleryController(context: strongSelf.context, source: .asset(asset), mode: .peer(EnginePeer(peer), false)) controller.navigationPresentation = .modal controller.apply = { [weak self] wallpaper, options, cropRect in if let strongSelf = self { @@ -18538,14 +18539,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.push(controller) }, changeColor: { - guard let strongSelf = self, let peerId else { + guard let strongSelf = self else { return } if let themeController = strongSelf.themeScreen { strongSelf.themeScreen = nil themeController.dimTapped() } - let controller = ThemeColorsGridController(context: context, peerId: peerId) + let controller = ThemeColorsGridController(context: context, mode: .peer(EnginePeer(peer))) controller.navigationPresentation = .modal strongSelf.push(controller) }, diff --git a/submodules/TelegramUI/Sources/ChatMessageWallpaperBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageWallpaperBubbleContentNode.swift index 80a24f3387..88cc205b4f 100644 --- a/submodules/TelegramUI/Sources/ChatMessageWallpaperBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageWallpaperBubbleContentNode.swift @@ -187,7 +187,7 @@ class ChatMessageWallpaperBubbleContentNode: ChatMessageBubbleContentNode { let (buttonTitleLayout, buttonTitleApply) = makeButtonTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.presentationData.strings.Notification_Wallpaper_View, font: Font.semibold(15.0), textColor: primaryTextColor, paragraphAlignment: .center), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets())) - let backgroundSize = CGSize(width: width, height: subtitleLayout.size.height + 145.0 + (fromYou ? 0.0 : 37.0)) + let backgroundSize = CGSize(width: width, height: subtitleLayout.size.height + 140.0 + (fromYou ? 0.0 : 42.0)) return (backgroundSize.width, { boundingWidth in return (backgroundSize, { [weak self] animation, synchronousLoads, _ in diff --git a/submodules/TelegramUI/Sources/ChatThemeScreen.swift b/submodules/TelegramUI/Sources/ChatThemeScreen.swift index 32c75da6dd..c021a42b2a 100644 --- a/submodules/TelegramUI/Sources/ChatThemeScreen.swift +++ b/submodules/TelegramUI/Sources/ChatThemeScreen.swift @@ -717,6 +717,7 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega private let wrappingScrollNode: ASScrollNode private let contentContainerNode: ASDisplayNode private let topContentContainerNode: SparseNode + private let buttonsContentContainerNode: SparseNode private let effectNode: ASDisplayNode private let backgroundNode: ASDisplayNode private let contentBackgroundNode: ASDisplayNode @@ -727,9 +728,7 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega private let animationContainerNode: ASDisplayNode private var animationNode: AnimationNode private let doneButton: SolidRoundedButtonNode - private let galleryButton: HighlightableButtonNode private let colorButton: HighlightableButtonNode - private let optionsButton: HighlightableButtonNode private let listNode: ListView private var entries: [ThemeSettingsThemeEntry]? @@ -786,6 +785,9 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega self.topContentContainerNode = SparseNode() self.topContentContainerNode.isOpaque = false + self.buttonsContentContainerNode = SparseNode() + self.buttonsContentContainerNode.isOpaque = false + self.backgroundNode = ASDisplayNode() self.backgroundNode.clipsToBounds = true self.backgroundNode.cornerRadius = 16.0 @@ -822,18 +824,8 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega self.animationNode.isUserInteractionEnabled = false self.doneButton = SolidRoundedButtonNode(theme: SolidRoundedButtonTheme(theme: self.presentationData.theme), height: 52.0, cornerRadius: 11.0, gloss: false) - self.doneButton.title = initiallySelectedEmoticon == nil ? self.presentationData.strings.Conversation_Theme_DontSetTheme : self.presentationData.strings.Conversation_Theme_Apply - self.doneButton.isHidden = true - - self.galleryButton = HighlightableButtonNode() - self.galleryButton.setTitle("Choose Background From Photos", with: Font.regular(17.0), with: self.presentationData.theme.actionSheet.controlAccentColor, for: .normal) self.colorButton = HighlightableButtonNode() - self.colorButton.setTitle("Choose Color as a Background", with: Font.regular(17.0), with: self.presentationData.theme.actionSheet.controlAccentColor, for: .normal) - - self.optionsButton = HighlightableButtonNode() - self.optionsButton.setTitle("Other Options...", with: Font.regular(17.0), with: self.presentationData.theme.actionSheet.controlAccentColor, for: .normal) - self.optionsButton.isHidden = true self.listNode = ListView() self.listNode.transform = CATransform3DMakeRotation(-CGFloat.pi / 2.0, 0.0, 0.0, 1.0) @@ -843,6 +835,8 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega self.backgroundColor = nil self.isOpaque = false + self.updateButtons() + self.addSubnode(self.dimNode) self.wrappingScrollNode.view.delegate = self @@ -851,15 +845,14 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega self.wrappingScrollNode.addSubnode(self.backgroundNode) self.wrappingScrollNode.addSubnode(self.contentContainerNode) self.wrappingScrollNode.addSubnode(self.topContentContainerNode) + self.wrappingScrollNode.addSubnode(self.buttonsContentContainerNode) self.backgroundNode.addSubnode(self.effectNode) self.backgroundNode.addSubnode(self.contentBackgroundNode) self.contentContainerNode.addSubnode(self.titleNode) self.contentContainerNode.addSubnode(self.textNode) - self.contentContainerNode.addSubnode(self.doneButton) - self.contentContainerNode.addSubnode(self.galleryButton) - self.contentContainerNode.addSubnode(self.colorButton) - self.contentContainerNode.addSubnode(self.optionsButton) + self.buttonsContentContainerNode.addSubnode(self.doneButton) + self.buttonsContentContainerNode.addSubnode(self.colorButton) self.topContentContainerNode.addSubnode(self.animationContainerNode) self.animationContainerNode.addSubnode(self.animationNode) @@ -875,9 +868,7 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega strongSelf.completion?(strongSelf.selectedEmoticon) } } - self.galleryButton.addTarget(self, action: #selector(self.galleryButtonPressed), forControlEvents: .touchUpInside) self.colorButton.addTarget(self, action: #selector(self.colorButtonPressed), forControlEvents: .touchUpInside) - self.optionsButton.addTarget(self, action: #selector(self.optionsButtonPressed), forControlEvents: .touchUpInside) self.disposable.set(combineLatest(queue: Queue.mainQueue(), self.context.engine.themes.getChatThemes(accountManager: self.context.sharedContext.accountManager), self.selectedEmoticonPromise.get(), self.isDarkAppearancePromise.get()).start(next: { [weak self] themes, selectedEmoticon, isDarkAppearance in guard let strongSelf = self else { @@ -994,21 +985,7 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega self.selectedEmoticon = emoticon let _ = ensureThemeVisible(listNode: self.listNode, emoticon: emoticon, animated: true) - let doneButtonTitle: String - if emoticon == nil { - self.doneButton.isHidden = true - self.galleryButton.isHidden = false - self.colorButton.isHidden = false - self.optionsButton.isHidden = true - doneButtonTitle = self.initiallySelectedEmoticon == nil ? self.presentationData.strings.Conversation_Theme_DontSetTheme : self.presentationData.strings.Conversation_Theme_Reset - } else { - self.doneButton.isHidden = false - self.galleryButton.isHidden = true - self.colorButton.isHidden = true - self.optionsButton.isHidden = false - doneButtonTitle = self.presentationData.strings.Conversation_Theme_Apply - } - self.doneButton.title = doneButtonTitle + self.updateButtons() self.themeSelectionsCount += 1 if self.themeSelectionsCount == 2 { @@ -1016,6 +993,36 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega } } + private func updateButtons() { + let doneButtonTitle: String + let otherButtonTitle: String + var accentButtonTheme = true + if self.selectedEmoticon == self.initiallySelectedEmoticon { + doneButtonTitle = self.presentationData.strings.Conversation_Theme_SetPhotoWallpaper + otherButtonTitle = self.presentationData.strings.Conversation_Theme_SetColorWallpaper + accentButtonTheme = false + } else if self.selectedEmoticon == nil && self.initiallySelectedEmoticon != nil { + doneButtonTitle = self.presentationData.strings.Conversation_Theme_Reset + otherButtonTitle = self.presentationData.strings.Conversation_Theme_OtherOptions + } else { + doneButtonTitle = self.presentationData.strings.Conversation_Theme_Apply + otherButtonTitle = self.presentationData.strings.Conversation_Theme_OtherOptions + } + + let buttonTheme: SolidRoundedButtonTheme + if accentButtonTheme { + buttonTheme = SolidRoundedButtonTheme(theme: self.presentationData.theme) + } else { + buttonTheme = SolidRoundedButtonTheme(backgroundColor: self.presentationData.theme.actionSheet.itemBackgroundColor, foregroundColor: self.presentationData.theme.actionSheet.controlAccentColor) + } + self.doneButton.title = doneButtonTitle + self.doneButton.font = accentButtonTheme ? .bold : .regular + self.doneButton.updateTheme(buttonTheme) + + + self.colorButton.setTitle(otherButtonTitle, with: Font.regular(17.0), with: self.presentationData.theme.actionSheet.controlAccentColor, for: .normal) + } + func updatePresentationData(_ presentationData: PresentationData) { guard !self.animatedOut else { return @@ -1032,6 +1039,7 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega self.cancelButton.setImage(closeButtonImage(theme: self.presentationData.theme), for: .normal) self.doneButton.updateTheme(SolidRoundedButtonTheme(theme: self.presentationData.theme)) + self.updateButtons() if self.animationNode.isPlaying { if let animationNode = self.animationNode.makeCopy(colors: iconColors(theme: self.presentationData.theme), progress: 0.2) { @@ -1066,18 +1074,10 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega self.cancel?() } - @objc func galleryButtonPressed() { - self.controller?.changeWallpaper() - } - @objc func colorButtonPressed() { self.controller?.changeColor() } - @objc func optionsButtonPressed() { - self.setEmoticon(nil) - } - func dimTapped() { if self.selectedEmoticon == self.initiallySelectedEmoticon { self.cancelButtonPressed() @@ -1135,14 +1135,14 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega self.contentBackgroundNode.layer.animate(from: previousColor.cgColor, to: (self.contentBackgroundNode.backgroundColor ?? .clear).cgColor, keyPath: "backgroundColor", timingFunction: CAMediaTimingFunctionName.linear.rawValue, duration: ChatThemeScreen.themeCrossfadeDuration) } -// if let snapshotView = self.contentContainerNode.view.snapshotView(afterScreenUpdates: false) { -// snapshotView.frame = self.contentContainerNode.frame -// self.contentContainerNode.view.superview?.insertSubview(snapshotView, aboveSubview: self.contentContainerNode.view) -// -// snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: ChatThemeScreen.themeCrossfadeDuration, delay: ChatThemeScreen.themeCrossfadeDelay, timingFunction: CAMediaTimingFunctionName.linear.rawValue, removeOnCompletion: false, completion: { [weak snapshotView] _ in -// snapshotView?.removeFromSuperview() -// }) -// } + if let snapshotView = self.contentContainerNode.view.snapshotView(afterScreenUpdates: false) { + snapshotView.frame = self.contentContainerNode.frame + self.contentContainerNode.view.superview?.insertSubview(snapshotView, aboveSubview: self.contentContainerNode.view) + + snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: ChatThemeScreen.themeCrossfadeDuration, delay: ChatThemeScreen.themeCrossfadeDelay, timingFunction: CAMediaTimingFunctionName.linear.rawValue, removeOnCompletion: false, completion: { [weak snapshotView] _ in + snapshotView?.removeFromSuperview() + }) + } self.listNode.forEachVisibleItemNode { node in if let node = node as? ThemeSettingsThemeItemIconNode { @@ -1295,17 +1295,12 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega let doneButtonHeight = self.doneButton.updateLayout(width: contentFrame.width - buttonInset * 2.0, transition: transition) transition.updateFrame(node: self.doneButton, frame: CGRect(x: buttonInset, y: contentHeight - doneButtonHeight - 50.0 - insets.bottom - 6.0, width: contentFrame.width, height: doneButtonHeight)) - let wallpaperButtonSize = self.galleryButton.measure(CGSize(width: contentFrame.width - buttonInset * 2.0, height: .greatestFiniteMagnitude)) - transition.updateFrame(node: self.galleryButton, frame: CGRect(origin: CGPoint(x: floor((contentFrame.width - wallpaperButtonSize.width) / 2.0), y: contentHeight - doneButtonHeight / 2.0 - wallpaperButtonSize.height / 2.0 - 50.0 - insets.bottom - 6.0), size: wallpaperButtonSize)) - - let colorButtonSize = self.galleryButton.measure(CGSize(width: contentFrame.width - buttonInset * 2.0, height: .greatestFiniteMagnitude)) + let colorButtonSize = self.colorButton.measure(CGSize(width: contentFrame.width - buttonInset * 2.0, height: .greatestFiniteMagnitude)) transition.updateFrame(node: self.colorButton, frame: CGRect(origin: CGPoint(x: floor((contentFrame.width - colorButtonSize.width) / 2.0), y: contentHeight - colorButtonSize.height - insets.bottom - 6.0 - 9.0), size: colorButtonSize)) - let optionsButtonSize = self.galleryButton.measure(CGSize(width: contentFrame.width - buttonInset * 2.0, height: .greatestFiniteMagnitude)) - transition.updateFrame(node: self.optionsButton, frame: CGRect(origin: CGPoint(x: floor((contentFrame.width - optionsButtonSize.width) / 2.0), y: contentHeight - optionsButtonSize.height - insets.bottom - 6.0 - 9.0), size: optionsButtonSize)) - transition.updateFrame(node: self.contentContainerNode, frame: contentContainerFrame) transition.updateFrame(node: self.topContentContainerNode, frame: contentContainerFrame) + transition.updateFrame(node: self.buttonsContentContainerNode, frame: contentContainerFrame) var listInsets = UIEdgeInsets() listInsets.top += layout.safeInsets.left + 12.0