From 630b0f30a3f46ab4f337b6ad7bce7ec0a37fa794 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Wed, 25 Dec 2019 16:34:07 +0300 Subject: [PATCH 1/4] Vertically center tab icons if titles are invisible --- submodules/Display/Display/TabBarNode.swift | 35 ++++++++++++--------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/submodules/Display/Display/TabBarNode.swift b/submodules/Display/Display/TabBarNode.swift index 47a91dcc36..f83a6b1289 100644 --- a/submodules/Display/Display/TabBarNode.swift +++ b/submodules/Display/Display/TabBarNode.swift @@ -4,7 +4,7 @@ import AsyncDisplayKit import SwiftSignalKit private let separatorHeight: CGFloat = 1.0 / UIScreen.main.scale -private func tabBarItemImage(_ image: UIImage?, title: String, backgroundColor: UIColor, tintColor: UIColor, horizontal: Bool, imageMode: Bool) -> (UIImage, CGFloat) { +private func tabBarItemImage(_ image: UIImage?, title: String, backgroundColor: UIColor, tintColor: UIColor, horizontal: Bool, imageMode: Bool, centered: Bool = false) -> (UIImage, CGFloat) { let font = horizontal ? Font.regular(13.0) : Font.medium(10.0) let titleSize = (title as NSString).boundingRect(with: CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude), options: [.usesLineFragmentOrigin], attributes: [NSAttributedString.Key.font: font], context: nil).size @@ -25,10 +25,12 @@ private func tabBarItemImage(_ image: UIImage?, title: String, backgroundColor: let size: CGSize let contentWidth: CGFloat if horizontal { - size = CGSize(width: max(1.0, ceil(titleSize.width) + horizontalSpacing + imageSize.width), height: 34.0) + let width = max(1.0, centered ? imageSize.width : ceil(titleSize.width) + horizontalSpacing + imageSize.width) + size = CGSize(width: width, height: 34.0) contentWidth = size.width } else { - size = CGSize(width: max(1.0, max(ceil(titleSize.width), imageSize.width), 1.0), height: 45.0) + let width = max(1.0, centered ? imageSize.width : max(ceil(titleSize.width), imageSize.width), 1.0) + size = CGSize(width: width, height: 45.0) contentWidth = imageSize.width } @@ -53,7 +55,7 @@ private func tabBarItemImage(_ image: UIImage?, title: String, backgroundColor: } context.restoreGState() } else { - let imageRect = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - imageSize.width) / 2.0), y: 0.0), size: imageSize) + let imageRect = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - imageSize.width) / 2.0), y: centered ? floor((size.height - imageSize.height) / 2.0) : 0.0), size: imageSize) context.saveGState() context.translateBy(x: imageRect.midX, y: imageRect.midY) context.scaleBy(x: 1.0, y: -1.0) @@ -215,6 +217,7 @@ class TabBarNode: ASDisplayNode { private var theme: TabBarControllerTheme private var validLayout: (CGSize, CGFloat, CGFloat, CGFloat)? private var horizontal: Bool = false + private var centered: Bool = false private var badgeImage: UIImage @@ -289,6 +292,8 @@ class TabBarNode: ASDisplayNode { node.badgeContainerNode.removeFromSupernode() } + self.centered = self.theme.tabBarTextColor == .clear + var tabBarNodeContainers: [TabBarNodeContainer] = [] for i in 0 ..< self.tabBarItems.count { let item = self.tabBarItems[i] @@ -304,15 +309,15 @@ class TabBarNode: ASDisplayNode { self?.updateNodeImage(i, layout: true) }) if let selectedIndex = self.selectedIndex, selectedIndex == i { - let (textImage, contentWidth) = tabBarItemImage(item.selectedImage, title: item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarSelectedTextColor, horizontal: self.horizontal, imageMode: false) - let (image, imageContentWidth) = tabBarItemImage(item.selectedImage, title: item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarSelectedTextColor, horizontal: self.horizontal, imageMode: true) + let (textImage, contentWidth) = tabBarItemImage(item.selectedImage, title: item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarSelectedTextColor, horizontal: self.horizontal, imageMode: false, centered: self.centered) + let (image, imageContentWidth) = tabBarItemImage(item.selectedImage, title: item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarSelectedTextColor, horizontal: self.horizontal, imageMode: true, centered: self.centered) node.textImageNode.image = textImage node.imageNode.image = image node.accessibilityLabel = item.title node.contentWidth = max(contentWidth, imageContentWidth) } else { - let (textImage, contentWidth) = tabBarItemImage(item.image, title: item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarTextColor, horizontal: self.horizontal, imageMode: false) - let (image, imageContentWidth) = tabBarItemImage(item.image, title: item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarTextColor, horizontal: self.horizontal, imageMode: true) + let (textImage, contentWidth) = tabBarItemImage(item.image, title: item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarTextColor, horizontal: self.horizontal, imageMode: false, centered: self.centered) + let (image, imageContentWidth) = tabBarItemImage(item.image, title: item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarIconColor, horizontal: self.horizontal, imageMode: true, centered: self.centered) node.textImageNode.image = textImage node.accessibilityLabel = item.title node.imageNode.image = image @@ -337,18 +342,20 @@ class TabBarNode: ASDisplayNode { let node = self.tabBarNodeContainers[index].imageNode let item = self.tabBarItems[index] + self.centered = self.theme.tabBarTextColor == .clear + let previousImageSize = node.imageNode.image?.size ?? CGSize() let previousTextImageSize = node.textImageNode.image?.size ?? CGSize() if let selectedIndex = self.selectedIndex, selectedIndex == index { - let (textImage, contentWidth) = tabBarItemImage(item.selectedImage, title: item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarSelectedTextColor, horizontal: self.horizontal, imageMode: false) - let (image, imageContentWidth) = tabBarItemImage(item.selectedImage, title: item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarSelectedIconColor, horizontal: self.horizontal, imageMode: true) + let (textImage, contentWidth) = tabBarItemImage(item.selectedImage, title: item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarSelectedTextColor, horizontal: self.horizontal, imageMode: false, centered: self.centered) + let (image, imageContentWidth) = tabBarItemImage(item.selectedImage, title: item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarSelectedIconColor, horizontal: self.horizontal, imageMode: true, centered: self.centered) node.textImageNode.image = textImage node.accessibilityLabel = item.title node.imageNode.image = image node.contentWidth = max(contentWidth, imageContentWidth) } else { - let (textImage, contentWidth) = tabBarItemImage(item.image, title: item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarTextColor, horizontal: self.horizontal, imageMode: false) - let (image, imageContentWidth) = tabBarItemImage(item.image, title: item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarIconColor, horizontal: self.horizontal, imageMode: true) + let (textImage, contentWidth) = tabBarItemImage(item.image, title: item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarTextColor, horizontal: self.horizontal, imageMode: false, centered: self.centered) + let (image, imageContentWidth) = tabBarItemImage(item.image, title: item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarIconColor, horizontal: self.horizontal, imageMode: true, centered: self.centered) node.textImageNode.image = textImage node.accessibilityLabel = item.title node.imageNode.image = image @@ -433,10 +440,10 @@ class TabBarNode: ASDisplayNode { let backgroundSize = CGSize(width: hasSingleLetterValue ? 18.0 : max(18.0, badgeSize.width + 10.0 + 1.0), height: 18.0) let backgroundFrame: CGRect if horizontal { - backgroundFrame = CGRect(origin: CGPoint(x: originX + 10.0, y: 2.0), size: backgroundSize) + backgroundFrame = CGRect(origin: CGPoint(x: originX + 15.0, y: 3.0), size: backgroundSize) } else { let contentWidth = node.contentWidth ?? node.frame.width - backgroundFrame = CGRect(origin: CGPoint(x: floor(originX + node.frame.width / 2.0) + contentWidth - backgroundSize.width - 5.0, y: 2.0), size: backgroundSize) + backgroundFrame = CGRect(origin: CGPoint(x: floor(originX + node.frame.width / 2.0) + contentWidth - backgroundSize.width - 5.0, y: self.centered ? 9.0 : 2.0), size: backgroundSize) } transition.updateFrame(node: container.badgeContainerNode, frame: backgroundFrame) container.badgeBackgroundNode.frame = CGRect(origin: CGPoint(), size: backgroundFrame.size) From aea6a5b69a09e960484aa5ed5f518b5b9c4878df Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Wed, 25 Dec 2019 16:34:24 +0300 Subject: [PATCH 2/4] Fix wallpaper settings serialization --- submodules/TelegramCore/Sources/Wallpaper.swift | 3 --- 1 file changed, 3 deletions(-) diff --git a/submodules/TelegramCore/Sources/Wallpaper.swift b/submodules/TelegramCore/Sources/Wallpaper.swift index 11cea3a8c4..6a13cce534 100644 --- a/submodules/TelegramCore/Sources/Wallpaper.swift +++ b/submodules/TelegramCore/Sources/Wallpaper.swift @@ -28,9 +28,6 @@ func apiWallpaperSettings(_ wallpaperSettings: WallpaperSettings) -> Api.WallPap if let _ = wallpaperSettings.bottomColor { flags |= (1 << 4) } - if let _ = wallpaperSettings.rotation { - flags |= (1 << 4) - } return .wallPaperSettings(flags: flags, backgroundColor: wallpaperSettings.color, secondBackgroundColor: wallpaperSettings.bottomColor, intensity: wallpaperSettings.intensity, rotation: wallpaperSettings.rotation) } From e7ae760fda9d0a8cafb9d759309684f900f2470f Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Wed, 25 Dec 2019 21:09:42 +0300 Subject: [PATCH 3/4] Theme fixes --- .../Sources/Themes/EditThemeController.swift | 4 +- .../Themes/ThemeAccentColorController.swift | 40 +-- .../ThemeAutoNightSettingsController.swift | 21 +- .../Themes/ThemeSettingsAccentColorItem.swift | 24 +- .../Themes/ThemeSettingsController.swift | 337 ++++++++---------- .../Themes/ThemeSettingsThemeItem.swift | 22 +- .../TelegramCore/Sources/Wallpaper.swift | 3 + .../DefaultDarkPresentationTheme.swift | 4 +- .../DefaultDarkTintedPresentationTheme.swift | 4 +- .../Sources/DefaultDayPresentationTheme.swift | 4 +- .../Sources/MakePresentationTheme.swift | 16 +- .../TelegramUI/ThemeUpdateManager.swift | 2 +- .../TelegramUI/WallpaperUploadManager.swift | 2 +- .../Sources/PresentationThemeSettings.swift | 89 ++--- .../Sources/WallpaperResources.swift | 139 +++++--- 15 files changed, 340 insertions(+), 371 deletions(-) diff --git a/submodules/SettingsUI/Sources/Themes/EditThemeController.swift b/submodules/SettingsUI/Sources/Themes/EditThemeController.swift index 6006ed94e6..bd1121cc73 100644 --- a/submodules/SettingsUI/Sources/Themes/EditThemeController.swift +++ b/submodules/SettingsUI/Sources/Themes/EditThemeController.swift @@ -515,7 +515,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers themeSpecificChatWallpapers[themeReference.index] = nil - return PresentationThemeSettings(theme: themeReference, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificCustomColors: current.themeSpecificCustomColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) + return PresentationThemeSettings(theme: themeReference, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) }) |> deliverOnMainQueue).start(completed: { if !hasCustomFile { saveThemeTemplateFile(state.title, themeResource, { @@ -549,7 +549,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers themeSpecificChatWallpapers[themeReference.index] = nil - return PresentationThemeSettings(theme: themeReference, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificCustomColors: current.themeSpecificCustomColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) + return PresentationThemeSettings(theme: themeReference, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) }) |> deliverOnMainQueue).start(completed: { if let themeResource = themeResource, !hasCustomFile { saveThemeTemplateFile(state.title, themeResource, { diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift index a32575de45..adf2fda3be 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift @@ -228,6 +228,7 @@ final class ThemeAccentColorController: ViewController { } let settings = TelegramThemeSettings(baseTheme: baseTheme, accentColor: accentColor, messageColors: bubbleColors, wallpaper: wallpaper) + let baseThemeReference = PresentationThemeReference.builtin(PresentationBuiltinThemeReference(baseTheme: baseTheme)) let save: Signal @@ -246,7 +247,10 @@ final class ThemeAccentColorController: ViewController { var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers themeSpecificChatWallpapers[themeReference.index] = nil - return PresentationThemeSettings(theme: themeReference, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificCustomColors: current.themeSpecificCustomColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) + var themeSpecificAccentColors = current.themeSpecificAccentColors + themeSpecificAccentColors[baseThemeReference.index] = PresentationThemeAccentColor(themeIndex: themeReference.index) + + return PresentationThemeSettings(theme: themeReference, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) }) |> deliverOnMainQueue).start(completed: { if let strongSelf = self { strongSelf.completion?() @@ -272,7 +276,10 @@ final class ThemeAccentColorController: ViewController { var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers themeSpecificChatWallpapers[themeReference.index] = nil - return PresentationThemeSettings(theme: themeReference, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificCustomColors: current.themeSpecificCustomColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) + var themeSpecificAccentColors = current.themeSpecificAccentColors + themeSpecificAccentColors[baseThemeReference.index] = PresentationThemeAccentColor(themeIndex: themeReference.index) + + return PresentationThemeSettings(theme: themeReference, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) }) |> deliverOnMainQueue).start(completed: { if let strongSelf = self { strongSelf.completion?() @@ -283,35 +290,6 @@ final class ThemeAccentColorController: ViewController { }, error: { error in }) } - -// let _ = (prepare -// |> then(updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in -// let autoNightModeTriggered = context.sharedContext.currentPresentationData.with { $0 }.autoNightModeTriggered -// var currentTheme = current.theme -// if autoNightModeTriggered { -// currentTheme = current.automaticThemeSwitchSetting.theme -// } -// -// -// -// if create { -// -// } else { -// -// } -// -// var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers -// -// -// themeSpecificChatWallpapers[coloredThemeIndex(reference: currentTheme, accentColor: nil)] = wallpaper -// -// return PresentationThemeSettings(theme: current.theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificCustomColors: current.themeSpecificCustomColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) -// })) |> deliverOnMainQueue).start(completed: { [weak self] in -// if let strongSelf = self { -// strongSelf.completion?() -// strongSelf.dismiss() -// } -// }) } } }) diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAutoNightSettingsController.swift b/submodules/SettingsUI/Sources/Themes/ThemeAutoNightSettingsController.swift index c002f3be53..34b81ce429 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAutoNightSettingsController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAutoNightSettingsController.swift @@ -68,7 +68,7 @@ private enum ThemeAutoNightSettingsControllerEntry: ItemListNodeEntry { case settingInfo(PresentationTheme, String) case themeHeader(PresentationTheme, String) - case themeItem(PresentationTheme, PresentationStrings, [PresentationThemeReference], PresentationThemeReference, [Int64: PresentationThemeAccentColor], [Int64: TelegramWallpaper]) + case themeItem(PresentationTheme, PresentationStrings, [PresentationThemeReference], [PresentationThemeReference], PresentationThemeReference, [Int64: PresentationThemeAccentColor], [Int64: TelegramWallpaper]) var section: ItemListSectionId { switch self { @@ -186,8 +186,8 @@ private enum ThemeAutoNightSettingsControllerEntry: ItemListNodeEntry { } else { return false } - case let .themeItem(lhsTheme, lhsStrings, lhsThemes, lhsCurrentTheme, lhsThemeAccentColors, lhsThemeChatWallpapers): - if case let .themeItem(rhsTheme, rhsStrings, rhsThemes, rhsCurrentTheme, rhsThemeAccentColors, rhsThemeChatWallpapers) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsThemes == rhsThemes, lhsCurrentTheme == rhsCurrentTheme, lhsThemeAccentColors == rhsThemeAccentColors, lhsThemeChatWallpapers == rhsThemeChatWallpapers { + case let .themeItem(lhsTheme, lhsStrings, lhsThemes, lhsAllThemes, lhsCurrentTheme, lhsThemeAccentColors, lhsThemeChatWallpapers): + if case let .themeItem(rhsTheme, rhsStrings, rhsThemes, rhsAllThemes, rhsCurrentTheme, rhsThemeAccentColors, rhsThemeChatWallpapers) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsThemes == rhsThemes, lhsAllThemes == rhsAllThemes, lhsCurrentTheme == rhsCurrentTheme, lhsThemeAccentColors == rhsThemeAccentColors, lhsThemeChatWallpapers == rhsThemeChatWallpapers { return true } else { return false @@ -244,8 +244,8 @@ private enum ThemeAutoNightSettingsControllerEntry: ItemListNodeEntry { return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section) case let .themeHeader(theme, title): return ItemListSectionHeaderItem(presentationData: presentationData, text: title, sectionId: self.section) - case let .themeItem(theme, strings, themes, currentTheme, themeSpecificAccentColors, themeSpecificChatWallpapers): - return ThemeSettingsThemeItem(context: arguments.context, theme: theme, strings: strings, sectionId: self.section, themes: themes, displayUnsupported: false, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, currentTheme: currentTheme, updatedTheme: { theme in + case let .themeItem(theme, strings, themes, allThemes, currentTheme, themeSpecificAccentColors, themeSpecificChatWallpapers): + return ThemeSettingsThemeItem(context: arguments.context, theme: theme, strings: strings, sectionId: self.section, themes: themes, allThemes: allThemes, displayUnsupported: false, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, currentTheme: currentTheme, updatedTheme: { theme in arguments.updateTheme(theme) }, contextAction: nil) } @@ -313,7 +313,16 @@ private func themeAutoNightSettingsControllerEntries(theme: PresentationTheme, s break case .system, .timeBased, .brightness: entries.append(.themeHeader(theme, strings.AutoNightTheme_PreferredTheme)) - entries.append(.themeItem(theme, strings, availableThemes, switchSetting.theme, settings.themeSpecificAccentColors, settings.themeSpecificChatWallpapers)) + + let generalThemes: [PresentationThemeReference] = availableThemes.filter { reference in + if case let .cloud(theme) = reference { + return theme.theme.settings == nil + } else { + return true + } + } + + entries.append(.themeItem(theme, strings, generalThemes, availableThemes, switchSetting.theme, settings.themeSpecificAccentColors, settings.themeSpecificChatWallpapers)) } return entries diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsAccentColorItem.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsAccentColorItem.swift index 462af36f40..189c6c7e92 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsAccentColorItem.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsAccentColorItem.swift @@ -341,7 +341,7 @@ private final class ThemeSettingsAccentColorIconItemNode : ListViewItemNode { var updatedAccentColor = false var updatedSelected = false - if currentItem == nil || currentItem?.color != item.color { + if currentItem == nil || currentItem?.color != item.color || currentItem?.themeReference != item.themeReference { updatedAccentColor = true } if currentItem?.selected != item.selected { @@ -418,7 +418,7 @@ private final class ThemeSettingsAccentColorIconItemNode : ListViewItemNode { strongSelf.dotsNode.bounds = bounds if updatedSelected { - strongSelf.setSelected(item.selected, animated: currentItem != nil && !animated) + strongSelf.setSelected(item.selected, animated: !updatedAccentColor && currentItem != nil) } } }) @@ -663,17 +663,17 @@ private struct ThemeSettingsAccentColorItemNodeTransition { let deletions: [ListViewDeleteItem] let insertions: [ListViewInsertItem] let updates: [ListViewUpdateItem] - let crossfade: Bool + let updatePosition: Bool } -private func preparedTransition(action: @escaping (ThemeSettingsColorOption?, Bool) -> Void, contextAction: ((ThemeSettingsColorOption?, Bool, ASDisplayNode, ContextGesture?) -> Void)?, openColorPicker: @escaping (Bool) -> Void, from fromEntries: [ThemeSettingsColorEntry], to toEntries: [ThemeSettingsColorEntry], crossfade: Bool) -> ThemeSettingsAccentColorItemNodeTransition { +private func preparedTransition(action: @escaping (ThemeSettingsColorOption?, Bool) -> Void, contextAction: ((ThemeSettingsColorOption?, Bool, ASDisplayNode, ContextGesture?) -> Void)?, openColorPicker: @escaping (Bool) -> Void, from fromEntries: [ThemeSettingsColorEntry], to toEntries: [ThemeSettingsColorEntry], updatePosition: Bool) -> ThemeSettingsAccentColorItemNodeTransition { let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries) let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) } let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(action: action, contextAction: contextAction, openColorPicker: openColorPicker), directionHint: .Down) } let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(action: action, contextAction: contextAction, openColorPicker: openColorPicker), directionHint: nil) } - return ThemeSettingsAccentColorItemNodeTransition(deletions: deletions, insertions: insertions, updates: updates, crossfade: crossfade) + return ThemeSettingsAccentColorItemNodeTransition(deletions: deletions, insertions: insertions, updates: updates, updatePosition: updatePosition) } private func ensureColorVisible(listNode: ListView, accentColor: ThemeSettingsColorOption?, animated: Bool) -> Bool { @@ -758,19 +758,15 @@ class ThemeSettingsAccentColorItemNode: ListViewItemNode, ItemListItemNode { self.enqueuedTransitions.remove(at: 0) var options = ListViewDeleteAndInsertOptions() - if self.initialized && transition.crossfade { - options.insert(.AnimateCrossfade) - } - var scrollToItem: ListViewScrollToItem? - if !self.initialized || transition.crossfade { + if !self.initialized || transition.updatePosition { if let index = item.colors.firstIndex(where: { $0.index == item.currentColor?.index }) { scrollToItem = ListViewScrollToItem(index: index, position: .bottom(-56.0), animated: false, curve: .Default(duration: 0.0), directionHint: .Down) self.initialized = true } } - - self.listNode.transaction(deleteIndices: transition.deletions, insertIndicesAndItems: transition.insertions, updateIndicesAndItems: transition.updates, options: options, scrollToItem: scrollToItem, updateSizeAndInsets: nil, updateOpaqueState: nil, completion: { _ in + + self.listNode.transaction(deleteIndices: transition.deletions, insertIndicesAndItems: transition.insertions, updateIndicesAndItems: transition.updates, options: options, scrollToItem: scrollToItem, updateSizeAndInsets: nil, updateOpaqueState: nil, completion: { [weak self] _ in }) } @@ -932,8 +928,8 @@ class ThemeSettingsAccentColorItemNode: ListViewItemNode, ItemListItemNode { } let previousEntries = strongSelf.entries ?? [] - let crossfade = previousEntries.count != entries.count || (currentItem != nil && (currentItem?.generalThemeReference.index != item.generalThemeReference.index)) - let transition = preparedTransition(action: action, contextAction: contextAction, openColorPicker: openColorPicker, from: previousEntries, to: entries, crossfade: crossfade) + let updatePosition = currentItem != nil && (previousEntries.count != entries.count || (currentItem?.generalThemeReference.index != item.generalThemeReference.index)) + let transition = preparedTransition(action: action, contextAction: contextAction, openColorPicker: openColorPicker, from: previousEntries, to: entries, updatePosition: updatePosition) strongSelf.enqueueTransition(transition) strongSelf.entries = entries diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift index c2a271b38a..fd3fee4c71 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift @@ -133,10 +133,10 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry { case fontSize(PresentationTheme, PresentationFontSize) case chatPreview(PresentationTheme, PresentationTheme, TelegramWallpaper, PresentationFontSize, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, [ChatPreviewMessageItem]) case wallpaper(PresentationTheme, String) - case accentColor(PresentationTheme, PresentationThemeReference, PresentationThemeReference, PresentationThemeCustomColors?, [PresentationThemeReference], ThemeSettingsColorOption?) + case accentColor(PresentationTheme, PresentationThemeReference, PresentationThemeReference, [PresentationThemeReference], ThemeSettingsColorOption?) case autoNightTheme(PresentationTheme, String, String) case textSize(PresentationTheme, String, String) - case themeItem(PresentationTheme, PresentationStrings, [PresentationThemeReference], PresentationThemeReference, [Int64: PresentationThemeAccentColor], [Int64: TelegramWallpaper], PresentationThemeAccentColor?) + case themeItem(PresentationTheme, PresentationStrings, [PresentationThemeReference], [PresentationThemeReference], PresentationThemeReference, [Int64: PresentationThemeAccentColor], [Int64: TelegramWallpaper], PresentationThemeAccentColor?) case iconHeader(PresentationTheme, String) case iconItem(PresentationTheme, PresentationStrings, [PresentationAppIcon], String?) case otherHeader(PresentationTheme, String) @@ -208,8 +208,8 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry { } else { return false } - case let .accentColor(lhsTheme, lhsGeneralTheme, lhsCurrentTheme, lhsCustomColors, lhsThemes, lhsColor): - if case let .accentColor(rhsTheme, rhsGeneralTheme, rhsCurrentTheme, rhsCustomColors, rhsThemes, rhsColor) = rhs, lhsTheme === rhsTheme, lhsCurrentTheme == rhsCurrentTheme, lhsCustomColors == rhsCustomColors, lhsThemes == rhsThemes, lhsColor == rhsColor { + case let .accentColor(lhsTheme, lhsGeneralTheme, lhsCurrentTheme, lhsThemes, lhsColor): + if case let .accentColor(rhsTheme, rhsGeneralTheme, rhsCurrentTheme, rhsThemes, rhsColor) = rhs, lhsTheme === rhsTheme, lhsCurrentTheme == rhsCurrentTheme, lhsThemes == rhsThemes, lhsColor == rhsColor { return true } else { return false @@ -232,8 +232,8 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry { } else { return false } - case let .themeItem(lhsTheme, lhsStrings, lhsThemes, lhsCurrentTheme, lhsThemeAccentColors, lhsThemeSpecificChatWallpapers, lhsCurrentColor): - if case let .themeItem(rhsTheme, rhsStrings, rhsThemes, rhsCurrentTheme, rhsThemeAccentColors, rhsThemeSpecificChatWallpapers, rhsCurrentColor) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsThemes == rhsThemes, lhsCurrentTheme == rhsCurrentTheme, lhsThemeAccentColors == rhsThemeAccentColors, lhsThemeSpecificChatWallpapers == rhsThemeSpecificChatWallpapers, lhsCurrentColor == rhsCurrentColor { + case let .themeItem(lhsTheme, lhsStrings, lhsThemes, lhsAllThemes, lhsCurrentTheme, lhsThemeAccentColors, lhsThemeSpecificChatWallpapers, lhsCurrentColor): + if case let .themeItem(rhsTheme, rhsStrings, rhsThemes, rhsAllThemes, rhsCurrentTheme, rhsThemeAccentColors, rhsThemeSpecificChatWallpapers, rhsCurrentColor) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsThemes == rhsThemes, lhsAllThemes == rhsAllThemes, lhsCurrentTheme == rhsCurrentTheme, lhsThemeAccentColors == rhsThemeAccentColors, lhsThemeSpecificChatWallpapers == rhsThemeSpecificChatWallpapers, lhsCurrentColor == rhsCurrentColor { return true } else { return false @@ -308,7 +308,7 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry { return ItemListDisclosureItem(presentationData: presentationData, title: text, label: "", sectionId: self.section, style: .blocks, action: { arguments.openWallpaperSettings() }) - case let .accentColor(theme, generalThemeReference, currentTheme, customColors, themes, color): + case let .accentColor(theme, generalThemeReference, currentTheme, themes, color): var colorItems: [ThemeSettingsAccentColor] = [] for theme in themes { @@ -317,7 +317,7 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry { var defaultColor: PresentationThemeAccentColor? = PresentationThemeAccentColor(baseColor: .blue) var colors = PresentationThemeBaseColor.allCases - colors = colors.filter { $0 != .custom && $0 != .preset } + colors = colors.filter { $0 != .custom && $0 != .preset && $0 != .theme } if case let .builtin(name) = generalThemeReference { if name == .dayClassic { colorItems.append(.default) @@ -358,14 +358,6 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry { let currentColor = color ?? defaultColor.flatMap { .accentColor($0) } colorItems.append(contentsOf: colors.map { .color($0) }) - if let customColors = customColors { -// colorItems.insert(contentsOf: customColors.colors.reversed().map { .custom($0) }, at: 0) - } else { -// if let currentColor = currentColor, currentColor.baseColor == .custom { -// colorItems.insert(.custom(currentColor), at: 0) -// } - } - return ThemeSettingsAccentColorItem(theme: theme, sectionId: self.section, generalThemeReference: generalThemeReference, themeReference: currentTheme, colors: colorItems, currentColor: currentColor, updated: { color in if let color = color { switch color { @@ -392,9 +384,9 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry { }) case let .themeListHeader(theme, text): return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) - case let .themeItem(theme, strings, themes, currentTheme, themeSpecificAccentColors, themeSpecificChatWallpapers, _): - return ThemeSettingsThemeItem(context: arguments.context, theme: theme, strings: strings, sectionId: self.section, themes: themes, displayUnsupported: true, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, currentTheme: currentTheme, updatedTheme: { theme in - if case let .cloud(theme) = theme, theme.theme.file == nil { + case let .themeItem(theme, strings, themes, allThemes, currentTheme, themeSpecificAccentColors, themeSpecificChatWallpapers, _): + return ThemeSettingsThemeItem(context: arguments.context, theme: theme, strings: strings, sectionId: self.section, themes: themes, allThemes: allThemes, displayUnsupported: true, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, currentTheme: currentTheme, updatedTheme: { theme in + if case let .cloud(theme) = theme, theme.theme.file == nil && theme.theme.settings == nil { if theme.theme.isCreator { arguments.editTheme(theme) } @@ -448,8 +440,8 @@ private func themeSettingsControllerEntries(presentationData: PresentationData, } else { generalThemeReference = themeReference } - - entries.append(.themeItem(presentationData.theme, presentationData.strings, generalThemes, generalThemeReference, presentationThemeSettings.themeSpecificAccentColors, presentationThemeSettings.themeSpecificChatWallpapers, presentationThemeSettings.themeSpecificAccentColors[themeReference.index])) + + entries.append(.themeItem(presentationData.theme, presentationData.strings, generalThemes, availableThemes, themeReference, presentationThemeSettings.themeSpecificAccentColors, presentationThemeSettings.themeSpecificChatWallpapers, presentationThemeSettings.themeSpecificAccentColors[themeReference.index])) if case let .builtin(builtinTheme) = generalThemeReference { let colorThemes = availableThemes.filter { reference in @@ -467,7 +459,7 @@ private func themeSettingsControllerEntries(presentationData: PresentationData, colorOption = .theme(themeReference) } - entries.append(.accentColor(presentationData.theme, generalThemeReference, themeReference, presentationThemeSettings.themeSpecificCustomColors[generalThemeReference.index], colorThemes, colorOption)) + entries.append(.accentColor(presentationData.theme, generalThemeReference, themeReference, colorThemes, colorOption)) } entries.append(.wallpaper(presentationData.theme, strings.Settings_ChatBackground)) @@ -526,6 +518,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The var presentCrossfadeControllerImpl: ((Bool) -> Void)? var selectThemeImpl: ((PresentationThemeReference) -> Void)? + var selectAccentColorImpl: ((PresentationThemeAccentColor?) -> Void)? var moreImpl: (() -> Void)? let _ = telegramWallpapers(postbox: context.account.postbox, network: context.account.network).start() @@ -555,87 +548,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The }, openWallpaperSettings: { pushControllerImpl?(ThemeGridController(context: context)) }, selectAccentColor: { accentColor in - var wallpaperSignal: Signal = .single(nil) - if let colorWallpaper = accentColor?.wallpaper, case let .file(file) = colorWallpaper { - wallpaperSignal = cachedWallpaper(account: context.account, slug: file.slug, settings: colorWallpaper.settings) - |> mapToSignal { cachedWallpaper in - if let wallpaper = cachedWallpaper?.wallpaper, case let .file(file) = wallpaper { - let resource = file.file.resource - let representation = CachedPatternWallpaperRepresentation(color: file.settings.color ?? 0xd6e2ee, bottomColor: file.settings.bottomColor, intensity: file.settings.intensity ?? 50, rotation: file.settings.rotation) - - var data: Data? - if let path = context.account.postbox.mediaBox.completedResourcePath(resource), let maybeData = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) { - data = maybeData - } else if let path = context.sharedContext.accountManager.mediaBox.completedResourcePath(resource), let maybeData = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) { - data = maybeData - } - - if let data = data { - context.sharedContext.accountManager.mediaBox.storeResourceData(resource.id, data: data, synchronous: true) - return (context.sharedContext.accountManager.mediaBox.cachedResourceRepresentation(resource, representation: representation, complete: true, fetch: true) - |> filter({ $0.complete }) - |> take(1) - |> mapToSignal { _ -> Signal in - return .single(wallpaper) - }) - } else { - return .single(nil) - } - } else { - return .single(nil) - } - } - } - - let _ = (wallpaperSignal - |> deliverOnMainQueue).start(next: { presetWallpaper in - let _ = updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in - let autoNightModeTriggered = context.sharedContext.currentPresentationData.with { $0 }.autoNightModeTriggered - var currentTheme = current.theme - if autoNightModeTriggered { - currentTheme = current.automaticThemeSwitchSetting.theme - } - - let generalThemeReference: PresentationThemeReference - if case let .cloud(theme) = currentTheme, let settings = theme.theme.settings { - generalThemeReference = .builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)) - } else { - generalThemeReference = currentTheme - } - - currentTheme = generalThemeReference - var updatedTheme = current.theme - var updatedAutomaticThemeSwitchSetting = current.automaticThemeSwitchSetting - - if autoNightModeTriggered { - var updatedAutomaticThemeSwitchSetting = current.automaticThemeSwitchSetting - updatedAutomaticThemeSwitchSetting.theme = generalThemeReference - } else { - updatedTheme = generalThemeReference - } - - guard let theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: generalThemeReference, accentColor: accentColor?.color, wallpaper: presetWallpaper) else { - return current - } - - var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers - var themeSpecificAccentColors = current.themeSpecificAccentColors - themeSpecificAccentColors[generalThemeReference.index] = accentColor?.withUpdatedWallpaper(presetWallpaper) - - if case let .builtin(theme) = generalThemeReference { - if let wallpaper = current.themeSpecificChatWallpapers[coloredThemeIndex(reference: currentTheme, accentColor: accentColor)], wallpaper.isColorOrGradient || wallpaper.isPattern || wallpaper.isBuiltin { - themeSpecificChatWallpapers[currentTheme.index] = nil - if let accentColor = accentColor { - themeSpecificChatWallpapers[coloredThemeIndex(reference: currentTheme, accentColor: accentColor)] = nil - } - } - } - - return PresentationThemeSettings(theme: updatedTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificCustomColors: current.themeSpecificCustomColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, automaticThemeSwitchSetting: updatedAutomaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) - }).start() - - presentCrossfadeControllerImpl?(true) - }) + selectAccentColorImpl?(accentColor) }, openAccentColorPicker: { themeReference, create in let controller = ThemeAccentColorController(context: context, mode: .colors(themeReference: themeReference, create: create)) pushControllerImpl?(controller) @@ -971,15 +884,24 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The let _ = (cloudThemes.get() |> delay(0.5, queue: Queue.mainQueue()) |> take(1) |> deliverOnMainQueue).start(next: { themes in - if isCurrent, let currentThemeIndex = themes.firstIndex(where: { $0.id == cloudTheme.theme.id }) { - let previousThemeIndex = themes.prefix(upTo: currentThemeIndex).reversed().firstIndex(where: { $0.file != nil }) - let newTheme: PresentationThemeReference - if let previousThemeIndex = previousThemeIndex { - newTheme = .cloud(PresentationCloudTheme(theme: themes[themes.index(before: previousThemeIndex.base)], resolvedWallpaper: nil)) - } else { - newTheme = .builtin(.nightAccent) + if isCurrent, let settings = cloudTheme.theme.settings { + let colorThemes = themes.filter { theme in + if let settings = theme.settings { + return true + } else { + return false + } + } + + if let currentThemeIndex = colorThemes.firstIndex(where: { $0.id == cloudTheme.theme.id }) { + let previousThemeIndex = themes.prefix(upTo: currentThemeIndex).reversed().firstIndex(where: { $0.file != nil }) + let newTheme: PresentationThemeReference + if let previousThemeIndex = previousThemeIndex { + selectThemeImpl?(.cloud(PresentationCloudTheme(theme: themes[themes.index(before: previousThemeIndex.base)], resolvedWallpaper: nil))) + } else { + selectAccentColorImpl?(nil) + } } - selectThemeImpl?(newTheme) } let _ = deleteThemeInteractively(account: context.account, accountManager: context.sharedContext.accountManager, theme: cloudTheme.theme).start() @@ -993,67 +915,6 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The presentControllerImpl?(actionSheet, nil) }) }))) - } else { - items.append(.action(ContextMenuActionItem(text: presentationData.strings.Appearance_ShareThemeColor, textColor: .primary, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Share"), color: theme.contextMenu.primaryColor) - }, action: { c, f in - c.dismiss(completion: { - - }) - }))) - items.append(.action(ContextMenuActionItem(text: presentationData.strings.Appearance_RemoveThemeColor, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor) - }, action: { c, f in - c.dismiss(completion: { - let actionSheet = ActionSheetController(presentationData: presentationData) - var items: [ActionSheetItem] = [] - items.append(ActionSheetButtonItem(title: presentationData.strings.Appearance_RemoveThemeColorConfirmation, color: .destructive, action: { [weak actionSheet] in - actionSheet?.dismissAnimated() - - let _ = updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in - let themeReference: PresentationThemeReference - if presentationData.autoNightModeTriggered { - themeReference = current.automaticThemeSwitchSetting.theme - } else { - themeReference = current.theme - } - - var themeSpecificAccentColors = current.themeSpecificAccentColors - var themeSpecificCustomColors = current.themeSpecificCustomColors - var customColors = themeSpecificCustomColors[themeReference.index]?.colors ?? [] - - var updatedAccentColor: PresentationThemeAccentColor? - if let index = customColors.firstIndex(where: { $0.index == accentColor.index }) { - if index > 0 { - updatedAccentColor = customColors[index - 1] - } else { - if case let .builtin(theme) = themeReference { - switch theme { - case .dayClassic: - updatedAccentColor = nil - case .day, .night, .nightAccent: - updatedAccentColor = PresentationThemeAccentColor(baseColor: .blue) - } - } else { - updatedAccentColor = PresentationThemeAccentColor(baseColor: .blue) - } - } - customColors.remove(at: index) - } else { - updatedAccentColor = PresentationThemeAccentColor(baseColor: .blue) - } - - themeSpecificAccentColors[themeReference.index] = updatedAccentColor - themeSpecificCustomColors[themeReference.index] = PresentationThemeCustomColors(colors: customColors) - return current.withUpdatedThemeSpecificCustomColors(themeSpecificCustomColors).withUpdatedThemeSpecificAccentColors(themeSpecificAccentColors) - }).start() - })) - actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ - ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in - actionSheet?.dismissAnimated() - }) - ])]) - presentControllerImpl?(actionSheet, nil) - }) - }))) } } let contextController = ContextController(account: context.account, presentationData: presentationData, source: .controller(ContextControllerContentSourceImpl(controller: themeController, sourceNode: node)), items: .single(items), reactionItems: [], gesture: gesture) @@ -1212,24 +1073,140 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The } let _ = applyTheme(accountManager: context.sharedContext.accountManager, account: context.account, theme: cloudTheme).start() - let _ = (resolvedWallpaper - |> mapToSignal { resolvedWallpaper -> Signal in + let currentTheme = context.sharedContext.accountManager.transaction { transaction -> (PresentationThemeReference) in + let settings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.presentationThemeSettings) as? PresentationThemeSettings ?? PresentationThemeSettings.defaultSettings + if autoNightModeTriggered { + return settings.automaticThemeSwitchSetting.theme + } else { + return settings.theme + } + } + + let _ = (combineLatest(resolvedWallpaper, currentTheme) + |> map { resolvedWallpaper, currentTheme -> Bool in var updatedTheme = theme + var currentThemeBaseIndex: Int64? + if case let .cloud(info) = currentTheme, let settings = info.theme.settings { + currentThemeBaseIndex = PresentationThemeReference.builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)).index + } else { + currentThemeBaseIndex = currentTheme.index + } + + var baseThemeIndex: Int64? + var updatedThemeBaseIndex: Int64? if case let .cloud(info) = theme { updatedTheme = .cloud(PresentationCloudTheme(theme: info.theme, resolvedWallpaper: resolvedWallpaper)) + if let settings = info.theme.settings { + baseThemeIndex = PresentationThemeReference.builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)).index + updatedThemeBaseIndex = baseThemeIndex + } + } else { + updatedThemeBaseIndex = theme.index } - return updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in + + let _ = updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in + var updatedThemeSpecificAccentColors = current.themeSpecificAccentColors + if let baseThemeIndex = baseThemeIndex { + updatedThemeSpecificAccentColors[baseThemeIndex] = PresentationThemeAccentColor(themeIndex: updatedTheme.index) + } + if autoNightModeTriggered { var updatedAutomaticThemeSwitchSetting = current.automaticThemeSwitchSetting updatedAutomaticThemeSwitchSetting.theme = updatedTheme - return current.withUpdatedAutomaticThemeSwitchSetting(updatedAutomaticThemeSwitchSetting) + + return current.withUpdatedAutomaticThemeSwitchSetting(updatedAutomaticThemeSwitchSetting).withUpdatedThemeSpecificAccentColors(updatedThemeSpecificAccentColors) } else { - return current.withUpdatedTheme(updatedTheme) + return current.withUpdatedTheme(updatedTheme).withUpdatedThemeSpecificAccentColors(updatedThemeSpecificAccentColors) } - }) - }).start() + }).start() + + return currentThemeBaseIndex != updatedThemeBaseIndex + } |> deliverOnMainQueue).start(next: { crossfadeAccentColors in + presentCrossfadeControllerImpl?((cloudTheme == nil || cloudTheme?.settings != nil) && !crossfadeAccentColors) + }) + } + selectAccentColorImpl = { accentColor in + var wallpaperSignal: Signal = .single(nil) + if let colorWallpaper = accentColor?.wallpaper, case let .file(file) = colorWallpaper { + wallpaperSignal = cachedWallpaper(account: context.account, slug: file.slug, settings: colorWallpaper.settings) + |> mapToSignal { cachedWallpaper in + if let wallpaper = cachedWallpaper?.wallpaper, case let .file(file) = wallpaper { + let resource = file.file.resource + let representation = CachedPatternWallpaperRepresentation(color: file.settings.color ?? 0xd6e2ee, bottomColor: file.settings.bottomColor, intensity: file.settings.intensity ?? 50, rotation: file.settings.rotation) + + var data: Data? + if let path = context.account.postbox.mediaBox.completedResourcePath(resource), let maybeData = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) { + data = maybeData + } else if let path = context.sharedContext.accountManager.mediaBox.completedResourcePath(resource), let maybeData = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) { + data = maybeData + } + + if let data = data { + context.sharedContext.accountManager.mediaBox.storeResourceData(resource.id, data: data, synchronous: true) + return (context.sharedContext.accountManager.mediaBox.cachedResourceRepresentation(resource, representation: representation, complete: true, fetch: true) + |> filter({ $0.complete }) + |> take(1) + |> mapToSignal { _ -> Signal in + return .single(wallpaper) + }) + } else { + return .single(nil) + } + } else { + return .single(nil) + } + } + } - presentCrossfadeControllerImpl?(cloudTheme == nil || cloudTheme?.settings != nil) + let _ = (wallpaperSignal + |> deliverOnMainQueue).start(next: { presetWallpaper in + let _ = updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in + let autoNightModeTriggered = context.sharedContext.currentPresentationData.with { $0 }.autoNightModeTriggered + var currentTheme = current.theme + if autoNightModeTriggered { + currentTheme = current.automaticThemeSwitchSetting.theme + } + + let generalThemeReference: PresentationThemeReference + if case let .cloud(theme) = currentTheme, let settings = theme.theme.settings { + generalThemeReference = .builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)) + } else { + generalThemeReference = currentTheme + } + + currentTheme = generalThemeReference + var updatedTheme = current.theme + var updatedAutomaticThemeSwitchSetting = current.automaticThemeSwitchSetting + + if autoNightModeTriggered { + var updatedAutomaticThemeSwitchSetting = current.automaticThemeSwitchSetting + updatedAutomaticThemeSwitchSetting.theme = generalThemeReference + } else { + updatedTheme = generalThemeReference + } + + guard let theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: generalThemeReference, accentColor: accentColor?.color, wallpaper: presetWallpaper) else { + return current + } + + var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers + var themeSpecificAccentColors = current.themeSpecificAccentColors + themeSpecificAccentColors[generalThemeReference.index] = accentColor?.withUpdatedWallpaper(presetWallpaper) + + if case let .builtin(theme) = generalThemeReference { + if let wallpaper = current.themeSpecificChatWallpapers[coloredThemeIndex(reference: currentTheme, accentColor: accentColor)], wallpaper.isColorOrGradient || wallpaper.isPattern || wallpaper.isBuiltin { + themeSpecificChatWallpapers[currentTheme.index] = nil + if let accentColor = accentColor { + themeSpecificChatWallpapers[coloredThemeIndex(reference: currentTheme, accentColor: accentColor)] = nil + } + } + } + + return PresentationThemeSettings(theme: updatedTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, automaticThemeSwitchSetting: updatedAutomaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) + }).start() + + presentCrossfadeControllerImpl?(true) + }) } moreImpl = { let presentationData = context.sharedContext.currentPresentationData.with { $0 } diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsThemeItem.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsThemeItem.swift index e177537d76..782f25eaef 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsThemeItem.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsThemeItem.swift @@ -273,7 +273,7 @@ private final class ThemeSettingsThemeItemIconNode : ListViewItemNode { if let strongSelf = self { strongSelf.item = item - if case let .cloud(theme) = item.themeReference, theme.theme.file == nil { + if case let .cloud(theme) = item.themeReference, theme.theme.file == nil && theme.theme.settings == nil { if updatedTheme { strongSelf.imageNode.setSignal(createThemeImage(theme: item.theme)) } @@ -345,6 +345,7 @@ class ThemeSettingsThemeItem: ListViewItem, ItemListItem { let theme: PresentationTheme let strings: PresentationStrings let themes: [PresentationThemeReference] + let allThemes: [PresentationThemeReference] let displayUnsupported: Bool let themeSpecificAccentColors: [Int64: PresentationThemeAccentColor] let themeSpecificChatWallpapers: [Int64: TelegramWallpaper] @@ -353,11 +354,12 @@ class ThemeSettingsThemeItem: ListViewItem, ItemListItem { let contextAction: ((PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void)? let tag: ItemListItemTag? - init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, sectionId: ItemListSectionId, themes: [PresentationThemeReference], displayUnsupported: Bool, themeSpecificAccentColors: [Int64: PresentationThemeAccentColor], themeSpecificChatWallpapers: [Int64: TelegramWallpaper], currentTheme: PresentationThemeReference, updatedTheme: @escaping (PresentationThemeReference) -> Void, contextAction: ((PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void)?, tag: ItemListItemTag? = nil) { + init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, sectionId: ItemListSectionId, themes: [PresentationThemeReference], allThemes: [PresentationThemeReference], displayUnsupported: Bool, themeSpecificAccentColors: [Int64: PresentationThemeAccentColor], themeSpecificChatWallpapers: [Int64: TelegramWallpaper], currentTheme: PresentationThemeReference, updatedTheme: @escaping (PresentationThemeReference) -> Void, contextAction: ((PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void)?, tag: ItemListItemTag? = nil) { self.context = context self.theme = theme self.strings = strings self.themes = themes + self.allThemes = allThemes self.displayUnsupported = displayUnsupported self.themeSpecificAccentColors = themeSpecificAccentColors self.themeSpecificChatWallpapers = themeSpecificChatWallpapers @@ -594,14 +596,26 @@ class ThemeSettingsThemeItemNode: ListViewItemNode, ItemListItemNode { strongSelf.listNode.position = CGPoint(x: contentSize.width / 2.0, y: contentSize.height / 2.0 + 2.0) strongSelf.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous], scrollToItem: nil, updateSizeAndInsets: ListViewUpdateSizeAndInsets(size: CGSize(width: contentSize.height, height: contentSize.width), insets: listInsets, duration: 0.0, curve: .Default(duration: nil)), stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in }) + var themes: [Int64: PresentationThemeReference] = [:] + for theme in item.allThemes { + themes[theme.index] = theme + } + var entries: [ThemeSettingsThemeEntry] = [] var index: Int = 0 - for theme in item.themes { + for var theme in item.themes { if !item.displayUnsupported, case let .cloud(theme) = theme, theme.theme.file == nil { continue } let title = themeDisplayName(strings: item.strings, reference: theme) - let accentColor = item.themeSpecificAccentColors[theme.index] + var accentColor = item.themeSpecificAccentColors[theme.index] + if let customThemeIndex = accentColor?.themeIndex { + if let customTheme = themes[customThemeIndex] { + theme = customTheme + } + accentColor = nil + } + let wallpaper = accentColor?.wallpaper entries.append(ThemeSettingsThemeEntry(index: index, themeReference: theme, title: title, accentColor: accentColor, selected: item.currentTheme.index == theme.index, theme: item.theme, wallpaper: wallpaper)) index += 1 diff --git a/submodules/TelegramCore/Sources/Wallpaper.swift b/submodules/TelegramCore/Sources/Wallpaper.swift index 6a13cce534..9b13b9fae1 100644 --- a/submodules/TelegramCore/Sources/Wallpaper.swift +++ b/submodules/TelegramCore/Sources/Wallpaper.swift @@ -25,6 +25,9 @@ func apiWallpaperSettings(_ wallpaperSettings: WallpaperSettings) -> Api.WallPap if wallpaperSettings.motion { flags |= (1 << 2) } + if let _ = wallpaperSettings.intensity { + flags |= (1 << 3) + } if let _ = wallpaperSettings.bottomColor { flags |= (1 << 4) } diff --git a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift index e4d7795242..078e387066 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift @@ -221,7 +221,7 @@ public func customizeDefaultDarkPresentationTheme(theme: PresentationTheme, edit ) } -public func makeDefaultDarkPresentationTheme(preview: Bool) -> PresentationTheme { +public func makeDefaultDarkPresentationTheme(customIndex: Int64? = nil, preview: Bool) -> PresentationTheme { let rootTabBar = PresentationThemeRootTabBar( backgroundColor: UIColor(rgb: 0x1c1c1d), separatorColor: UIColor(rgb: 0x3d3d40), @@ -532,7 +532,7 @@ public func makeDefaultDarkPresentationTheme(preview: Bool) -> PresentationTheme return PresentationTheme( name: .builtin(.night), - index: PresentationThemeReference.builtin(.night).index, + index: customIndex ?? PresentationThemeReference.builtin(.night).index, referenceTheme: .night, overallDarkAppearance: true, intro: intro, diff --git a/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift index 18483b9b9d..8d2f453945 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift @@ -441,7 +441,7 @@ public func customizeDefaultDarkTintedPresentationTheme(theme: PresentationTheme ) } -public func makeDefaultDarkTintedPresentationTheme(preview: Bool) -> PresentationTheme { +public func makeDefaultDarkTintedPresentationTheme(customIndex: Int64? = nil, preview: Bool) -> PresentationTheme { let accentColor = defaultDarkTintedAccentColor let secondaryBadgeTextColor: UIColor @@ -788,7 +788,7 @@ public func makeDefaultDarkTintedPresentationTheme(preview: Bool) -> Presentatio return PresentationTheme( name: .builtin(.nightAccent), - index: PresentationThemeReference.builtin(.nightAccent).index, + index: customIndex ?? PresentationThemeReference.builtin(.nightAccent).index, referenceTheme: .nightAccent, overallDarkAppearance: true, intro: intro, diff --git a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift index 5a8d14a491..611639e3ac 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift @@ -311,7 +311,7 @@ public func customizeDefaultDayTheme(theme: PresentationTheme, editing: Bool, ac ) } -public func makeDefaultDayPresentationTheme(serviceBackgroundColor: UIColor?, day: Bool, preview: Bool) -> PresentationTheme { +public func makeDefaultDayPresentationTheme(customIndex: Int64? = nil, serviceBackgroundColor: UIColor?, day: Bool, preview: Bool) -> PresentationTheme { var serviceBackgroundColor = serviceBackgroundColor ?? defaultServiceBackgroundColor let intro = PresentationThemeIntro( @@ -741,7 +741,7 @@ public func makeDefaultDayPresentationTheme(serviceBackgroundColor: UIColor?, da return PresentationTheme( name: .builtin(day ? .day : .dayClassic), - index: PresentationThemeReference.builtin(day ? .day : .dayClassic).index, + index: customIndex ?? PresentationThemeReference.builtin(day ? .day : .dayClassic).index, referenceTheme: day ? .day : .dayClassic, overallDarkAppearance: false, intro: intro, diff --git a/submodules/TelegramPresentationData/Sources/MakePresentationTheme.swift b/submodules/TelegramPresentationData/Sources/MakePresentationTheme.swift index db56eab238..fb3c52ce2e 100644 --- a/submodules/TelegramPresentationData/Sources/MakePresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/MakePresentationTheme.swift @@ -4,17 +4,17 @@ import Postbox import SyncCore import TelegramUIPreferences -public func makeDefaultPresentationTheme(reference: PresentationBuiltinThemeReference, serviceBackgroundColor: UIColor?, preview: Bool = false) -> PresentationTheme { +public func makeDefaultPresentationTheme(reference: PresentationBuiltinThemeReference, customIndex: Int64? = nil, serviceBackgroundColor: UIColor?, preview: Bool = false) -> PresentationTheme { let theme: PresentationTheme switch reference { case .dayClassic: - theme = makeDefaultDayPresentationTheme(serviceBackgroundColor: serviceBackgroundColor, day: false, preview: preview) + theme = makeDefaultDayPresentationTheme(customIndex: customIndex, serviceBackgroundColor: serviceBackgroundColor, day: false, preview: preview) case .day: - theme = makeDefaultDayPresentationTheme(serviceBackgroundColor: serviceBackgroundColor, day: true, preview: preview) + theme = makeDefaultDayPresentationTheme(customIndex: customIndex, serviceBackgroundColor: serviceBackgroundColor, day: true, preview: preview) case .night: - theme = makeDefaultDarkPresentationTheme(preview: preview) + theme = makeDefaultDarkPresentationTheme(customIndex: customIndex, preview: preview) case .nightAccent: - theme = makeDefaultDarkTintedPresentationTheme(preview: preview) + theme = makeDefaultDarkTintedPresentationTheme(customIndex: customIndex, preview: preview) } return theme } @@ -35,11 +35,11 @@ public func customizePresentationTheme(_ theme: PresentationTheme, editing: Bool return theme } -public func makePresentationTheme(mediaBox: MediaBox, themeReference: PresentationThemeReference, accentColor: UIColor? = nil, backgroundColors: (UIColor, UIColor?)? = nil, bubbleColors: (UIColor, UIColor?)? = nil, wallpaper: TelegramWallpaper? = nil, serviceBackgroundColor: UIColor? = nil, preview: Bool = false) -> PresentationTheme? { +public func makePresentationTheme(mediaBox: MediaBox, themeReference: PresentationThemeReference, customIndex: Int64? = nil, accentColor: UIColor? = nil, backgroundColors: (UIColor, UIColor?)? = nil, bubbleColors: (UIColor, UIColor?)? = nil, wallpaper: TelegramWallpaper? = nil, serviceBackgroundColor: UIColor? = nil, preview: Bool = false) -> PresentationTheme? { let theme: PresentationTheme switch themeReference { case let .builtin(reference): - let defaultTheme = makeDefaultPresentationTheme(reference: reference, serviceBackgroundColor: serviceBackgroundColor, preview: preview) + let defaultTheme = makeDefaultPresentationTheme(reference: reference, customIndex: customIndex, serviceBackgroundColor: serviceBackgroundColor, preview: preview) theme = customizePresentationTheme(defaultTheme, editing: true, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors, wallpaper: wallpaper) case let .local(info): if let path = mediaBox.completedResourcePath(info.resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead), let loadedTheme = makePresentationTheme(data: data, themeReference: themeReference, resolvedWallpaper: info.resolvedWallpaper) { @@ -49,7 +49,7 @@ public func makePresentationTheme(mediaBox: MediaBox, themeReference: Presentati } case let .cloud(info): if let settings = info.theme.settings { - if let loadedTheme = makePresentationTheme(mediaBox: mediaBox, themeReference: .builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)), accentColor: accentColor ?? UIColor(rgb: UInt32(bitPattern: settings.accentColor)), backgroundColors: nil, bubbleColors: bubbleColors ?? settings.messageColors.flatMap { (UIColor(rgb: UInt32(bitPattern: $0.top)), UIColor(rgb: UInt32(bitPattern: $0.bottom))) }, wallpaper: wallpaper ?? settings.wallpaper, serviceBackgroundColor: serviceBackgroundColor, preview: preview) { + if let loadedTheme = makePresentationTheme(mediaBox: mediaBox, themeReference: .builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)), customIndex: themeReference.index, accentColor: accentColor ?? UIColor(rgb: UInt32(bitPattern: settings.accentColor)), backgroundColors: nil, bubbleColors: bubbleColors ?? settings.messageColors.flatMap { (UIColor(rgb: UInt32(bitPattern: $0.top)), UIColor(rgb: UInt32(bitPattern: $0.bottom))) }, wallpaper: wallpaper ?? settings.wallpaper, serviceBackgroundColor: serviceBackgroundColor, preview: preview) { theme = loadedTheme } else { return nil diff --git a/submodules/TelegramUI/TelegramUI/ThemeUpdateManager.swift b/submodules/TelegramUI/TelegramUI/ThemeUpdateManager.swift index cfc7c701a1..ab8fbf9b7a 100644 --- a/submodules/TelegramUI/TelegramUI/ThemeUpdateManager.swift +++ b/submodules/TelegramUI/TelegramUI/ThemeUpdateManager.swift @@ -139,7 +139,7 @@ final class ThemeUpdateManagerImpl: ThemeUpdateManager { theme = updatedTheme } - return PresentationThemeSettings(theme: theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificCustomColors: current.themeSpecificCustomColors, themeSpecificChatWallpapers: current.themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, automaticThemeSwitchSetting: automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) + return PresentationThemeSettings(theme: theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: current.themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, automaticThemeSwitchSetting: automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) }) }).start() } diff --git a/submodules/TelegramUI/TelegramUI/WallpaperUploadManager.swift b/submodules/TelegramUI/TelegramUI/WallpaperUploadManager.swift index 6796e6ec0a..eeccfd0e1d 100644 --- a/submodules/TelegramUI/TelegramUI/WallpaperUploadManager.swift +++ b/submodules/TelegramUI/TelegramUI/WallpaperUploadManager.swift @@ -134,7 +134,7 @@ final class WallpaperUploadManagerImpl: WallpaperUploadManager { var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers themeSpecificChatWallpapers[themeReference.index] = updatedWallpaper themeSpecificChatWallpapers[coloredThemeIndex(reference: themeReference, accentColor: current.themeSpecificAccentColors[themeReference.index])] = updatedWallpaper - return PresentationThemeSettings(theme: current.theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificCustomColors: current.themeSpecificCustomColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) + return PresentationThemeSettings(theme: current.theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) })).start() } } diff --git a/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift b/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift index 2ec4c2b19a..79a5417cd3 100644 --- a/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift +++ b/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift @@ -353,6 +353,7 @@ public enum PresentationThemeBaseColor: Int32, CaseIterable { case white case custom case preset + case theme public var color: UIColor { let value: UInt32 @@ -379,39 +380,13 @@ public enum PresentationThemeBaseColor: Int32, CaseIterable { value = 0x000000 case .white: value = 0xffffff - case .custom, .preset: + case .custom, .preset, .theme: return .clear } return UIColor(rgb: value) } } -public struct PresentationThemeCustomColors: PostboxCoding, Equatable { - public static func == (lhs: PresentationThemeCustomColors, rhs: PresentationThemeCustomColors) -> Bool { - return lhs.colors == rhs.colors - } - - public let colors: [PresentationThemeAccentColor] - - public init(colors: [PresentationThemeAccentColor]) { - self.colors = colors - } - - public init(decoder: PostboxDecoder) { - if let colors = try? decoder.decodeObjectArrayWithCustomDecoderForKey("v", decoder: { decoder in - return PresentationThemeAccentColor(decoder: decoder) - }) { - self.colors = colors - } else { - self.colors = [] - } - } - - public func encode(_ encoder: PostboxEncoder) { - encoder.encodeObjectArray(self.colors, forKey: "v") - } -} - public struct PresentationThemeAccentColor: PostboxCoding, Equatable { public static func == (lhs: PresentationThemeAccentColor, rhs: PresentationThemeAccentColor) -> Bool { return lhs.index == rhs.index && lhs.baseColor == rhs.baseColor && lhs.accentColor == rhs.accentColor && lhs.bubbleColors?.0 == rhs.bubbleColors?.0 && lhs.bubbleColors?.1 == rhs.bubbleColors?.1 @@ -422,6 +397,7 @@ public struct PresentationThemeAccentColor: PostboxCoding, Equatable { public var accentColor: Int32? public var bubbleColors: (Int32, Int32?)? public var wallpaper: TelegramWallpaper? + public var themeIndex: Int64? public init(baseColor: PresentationThemeBaseColor) { if baseColor != .preset && baseColor != .custom { @@ -443,6 +419,15 @@ public struct PresentationThemeAccentColor: PostboxCoding, Equatable { self.wallpaper = wallpaper } + public init(themeIndex: Int64) { + self.index = -1 + self.baseColor = .theme + self.accentColor = nil + self.bubbleColors = nil + self.wallpaper = nil + self.themeIndex = themeIndex + } + public init(decoder: PostboxDecoder) { self.index = decoder.decodeInt32ForKey("i", orElse: -1) self.baseColor = PresentationThemeBaseColor(rawValue: decoder.decodeInt32ForKey("b", orElse: 0)) ?? .blue @@ -457,6 +442,7 @@ public struct PresentationThemeAccentColor: PostboxCoding, Equatable { self.bubbleColors = nil } self.wallpaper = decoder.decodeObjectForKey("w", decoder: { TelegramWallpaper(decoder: $0) }) as? TelegramWallpaper + self.themeIndex = decoder.decodeOptionalInt64ForKey("t") } public func encode(_ encoder: PostboxEncoder) { @@ -483,6 +469,11 @@ public struct PresentationThemeAccentColor: PostboxCoding, Equatable { } else { encoder.encodeNil(forKey: "w") } + if let themeIndex = self.themeIndex { + encoder.encodeInt64(themeIndex, forKey: "t") + } else { + encoder.encodeNil(forKey: "t") + } } public var color: UIColor { @@ -525,7 +516,6 @@ public struct PresentationThemeAccentColor: PostboxCoding, Equatable { public struct PresentationThemeSettings: PreferencesEntry { public var theme: PresentationThemeReference public var themeSpecificAccentColors: [Int64: PresentationThemeAccentColor] - public var themeSpecificCustomColors: [Int64: PresentationThemeCustomColors] public var themeSpecificChatWallpapers: [Int64: TelegramWallpaper] public var useSystemFont: Bool public var fontSize: PresentationFontSize @@ -565,24 +555,16 @@ public struct PresentationThemeSettings: PreferencesEntry { resources.append(contentsOf: wallpaperResources(chatWallpaper)) } } - for (_, colors) in self.themeSpecificCustomColors { - for color in colors.colors { - if let wallpaper = color.wallpaper { - resources.append(contentsOf: wallpaperResources(wallpaper)) - } - } - } return resources } public static var defaultSettings: PresentationThemeSettings { - return PresentationThemeSettings(theme: .builtin(.dayClassic), themeSpecificAccentColors: [:], themeSpecificCustomColors: [:], themeSpecificChatWallpapers: [:], useSystemFont: true, fontSize: .regular, automaticThemeSwitchSetting: AutomaticThemeSwitchSetting(trigger: .system, theme: .builtin(.night)), largeEmoji: true, disableAnimations: true) + return PresentationThemeSettings(theme: .builtin(.dayClassic), themeSpecificAccentColors: [:], themeSpecificChatWallpapers: [:], useSystemFont: true, fontSize: .regular, automaticThemeSwitchSetting: AutomaticThemeSwitchSetting(trigger: .system, theme: .builtin(.night)), largeEmoji: true, disableAnimations: true) } - public init(theme: PresentationThemeReference, themeSpecificAccentColors: [Int64: PresentationThemeAccentColor], themeSpecificCustomColors: [Int64: PresentationThemeCustomColors], themeSpecificChatWallpapers: [Int64: TelegramWallpaper], useSystemFont: Bool, fontSize: PresentationFontSize, automaticThemeSwitchSetting: AutomaticThemeSwitchSetting, largeEmoji: Bool, disableAnimations: Bool) { + public init(theme: PresentationThemeReference, themeSpecificAccentColors: [Int64: PresentationThemeAccentColor], themeSpecificChatWallpapers: [Int64: TelegramWallpaper], useSystemFont: Bool, fontSize: PresentationFontSize, automaticThemeSwitchSetting: AutomaticThemeSwitchSetting, largeEmoji: Bool, disableAnimations: Bool) { self.theme = theme self.themeSpecificAccentColors = themeSpecificAccentColors - self.themeSpecificCustomColors = themeSpecificCustomColors self.themeSpecificChatWallpapers = themeSpecificChatWallpapers self.useSystemFont = useSystemFont self.fontSize = fontSize @@ -600,12 +582,6 @@ public struct PresentationThemeSettings: PreferencesEntry { return TelegramWallpaper(decoder: decoder) }) - self.themeSpecificCustomColors = decoder.decodeObjectDictionaryForKey("themeSpecificCustomColors", keyDecoder: { decoder in - return decoder.decodeInt64ForKey("k", orElse: 0) - }, valueDecoder: { decoder in - return PresentationThemeCustomColors(decoder: decoder) - }) - self.themeSpecificAccentColors = decoder.decodeObjectDictionaryForKey("themeSpecificAccentColors", keyDecoder: { decoder in return decoder.decodeInt64ForKey("k", orElse: 0) }, valueDecoder: { decoder in @@ -624,9 +600,6 @@ public struct PresentationThemeSettings: PreferencesEntry { encoder.encodeObjectDictionary(self.themeSpecificAccentColors, forKey: "themeSpecificAccentColors", keyEncoder: { key, encoder in encoder.encodeInt64(key, forKey: "k") }) - encoder.encodeObjectDictionary(self.themeSpecificCustomColors, forKey: "themeSpecificCustomColors", keyEncoder: { key, encoder in - encoder.encodeInt64(key, forKey: "k") - }) encoder.encodeObjectDictionary(self.themeSpecificChatWallpapers, forKey: "themeSpecificChatWallpapers", keyEncoder: { key, encoder in encoder.encodeInt64(key, forKey: "k") }) @@ -646,43 +619,39 @@ public struct PresentationThemeSettings: PreferencesEntry { } public static func ==(lhs: PresentationThemeSettings, rhs: PresentationThemeSettings) -> Bool { - return lhs.theme == rhs.theme && lhs.themeSpecificAccentColors == rhs.themeSpecificAccentColors && lhs.themeSpecificCustomColors == rhs.themeSpecificCustomColors && lhs.themeSpecificChatWallpapers == rhs.themeSpecificChatWallpapers && lhs.useSystemFont == rhs.useSystemFont && lhs.fontSize == rhs.fontSize && lhs.automaticThemeSwitchSetting == rhs.automaticThemeSwitchSetting && lhs.largeEmoji == rhs.largeEmoji && lhs.disableAnimations == rhs.disableAnimations + return lhs.theme == rhs.theme && lhs.themeSpecificAccentColors == rhs.themeSpecificAccentColors && lhs.themeSpecificChatWallpapers == rhs.themeSpecificChatWallpapers && lhs.useSystemFont == rhs.useSystemFont && lhs.fontSize == rhs.fontSize && lhs.automaticThemeSwitchSetting == rhs.automaticThemeSwitchSetting && lhs.largeEmoji == rhs.largeEmoji && lhs.disableAnimations == rhs.disableAnimations } public func withUpdatedTheme(_ theme: PresentationThemeReference) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificCustomColors: self.themeSpecificCustomColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) + return PresentationThemeSettings(theme: theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) } public func withUpdatedThemeSpecificAccentColors(_ themeSpecificAccentColors: [Int64: PresentationThemeAccentColor]) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificCustomColors: self.themeSpecificCustomColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) - } - - public func withUpdatedThemeSpecificCustomColors(_ themeSpecificCustomColors: [Int64: PresentationThemeCustomColors]) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificCustomColors: themeSpecificCustomColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) + return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) } public func withUpdatedThemeSpecificChatWallpapers(_ themeSpecificChatWallpapers: [Int64: TelegramWallpaper]) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificCustomColors: self.themeSpecificCustomColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) + return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) } public func withUpdatedUseSystemFont(_ useSystemFont: Bool) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificCustomColors: self.themeSpecificCustomColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: useSystemFont, fontSize: self.fontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) + return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: useSystemFont, fontSize: self.fontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) } public func withUpdatedFontSize(_ fontSize: PresentationFontSize) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificCustomColors: self.themeSpecificCustomColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: fontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) + return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: fontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) } public func withUpdatedAutomaticThemeSwitchSetting(_ automaticThemeSwitchSetting: AutomaticThemeSwitchSetting) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificCustomColors: self.themeSpecificCustomColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, automaticThemeSwitchSetting: automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) + return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, automaticThemeSwitchSetting: automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: self.disableAnimations) } public func withUpdatedLargeEmoji(_ largeEmoji: Bool) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificCustomColors: self.themeSpecificCustomColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: largeEmoji, disableAnimations: self.disableAnimations) + return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: largeEmoji, disableAnimations: self.disableAnimations) } public func withUpdatedDisableAnimations(_ disableAnimations: Bool) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificCustomColors: self.themeSpecificCustomColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: disableAnimations) + return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, disableAnimations: disableAnimations) } } diff --git a/submodules/WallpaperResources/Sources/WallpaperResources.swift b/submodules/WallpaperResources/Sources/WallpaperResources.swift index 034981aafb..18d857c3d4 100644 --- a/submodules/WallpaperResources/Sources/WallpaperResources.swift +++ b/submodules/WallpaperResources/Sources/WallpaperResources.swift @@ -1159,78 +1159,101 @@ public func themeIconImage(account: Account, accountManager: AccountManager, the } else if case let .cloud(theme) = theme, let resource = theme.theme.file?.resource { reference = .theme(theme: .slug(theme.theme.slug), resource: resource) } + + let themeSignal: Signal if let reference = reference { - colorsSignal = telegramThemeData(account: account, accountManager: accountManager, reference: reference, synchronousLoad: false) - |> mapToSignal { data -> Signal<((UIColor, UIColor?), (UIColor, UIColor), (UIColor, UIColor), UIImage?, Int32?), NoError> in + themeSignal = telegramThemeData(account: account, accountManager: accountManager, reference: reference, synchronousLoad: false) + |> map { data -> PresentationTheme? in if let data = data, let theme = makePresentationTheme(data: data) { - var wallpaperSignal: Signal<((UIColor, UIColor?), (UIColor, UIColor), (UIColor, UIColor), UIImage?, Int32?), NoError> = .complete() - var rotation: Int32? - let backgroundColor: (UIColor, UIColor?) - let incomingColor = (theme.chat.message.incoming.bubble.withoutWallpaper.fill, theme.chat.message.incoming.bubble.withoutWallpaper.gradientFill) - let outgoingColor = (theme.chat.message.outgoing.bubble.withoutWallpaper.fill, theme.chat.message.outgoing.bubble.withoutWallpaper.gradientFill) - switch theme.chat.defaultWallpaper { - case .builtin: - backgroundColor = (UIColor(rgb: 0xd6e2ee), nil) - case let .color(color): - backgroundColor = (UIColor(rgb: UInt32(bitPattern: color)), nil) - case let .gradient(topColor, bottomColor, settings): - backgroundColor = (UIColor(rgb: UInt32(bitPattern: topColor)), UIColor(rgb: UInt32(bitPattern: bottomColor))) - rotation = settings.rotation - case .image: - backgroundColor = (.black, nil) - case let .file(file): - rotation = file.settings.rotation - if file.isPattern, let color = file.settings.color { - backgroundColor = (UIColor(rgb: UInt32(bitPattern: color)), file.settings.bottomColor.flatMap { UIColor(rgb: UInt32(bitPattern: $0)) }) - } else { - backgroundColor = (theme.chatList.backgroundColor, nil) - } - wallpaperSignal = cachedWallpaper(account: account, slug: file.slug, settings: file.settings) - |> mapToSignal { wallpaper in - if let wallpaper = wallpaper, case let .file(file) = wallpaper.wallpaper { - var convertedRepresentations: [ImageRepresentationWithReference] = [] - convertedRepresentations.append(ImageRepresentationWithReference(representation: TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 100, height: 100), resource: file.file.resource), reference: .media(media: .standalone(media: file.file), resource: file.file.resource))) - return wallpaperDatas(account: account, accountManager: accountManager, fileReference: .standalone(media: file.file), representations: convertedRepresentations, alwaysShowThumbnailFirst: false, thumbnail: false, onlyFullSize: true, autoFetchFullSize: true, synchronousLoad: false) - |> mapToSignal { _, fullSizeData, complete -> Signal<((UIColor, UIColor?), (UIColor, UIColor), (UIColor, UIColor), UIImage?, Int32?), NoError> in - guard complete, let fullSizeData = fullSizeData else { - return .complete() - } - accountManager.mediaBox.storeResourceData(file.file.resource.id, data: fullSizeData) - let _ = accountManager.mediaBox.cachedResourceRepresentation(file.file.resource, representation: CachedScaledImageRepresentation(size: CGSize(width: 720.0, height: 720.0), mode: .aspectFit), complete: true, fetch: true).start() - - if file.isPattern, let color = file.settings.color, let intensity = file.settings.intensity { + return theme + } else { + return nil + } + } + } else if case let .cloud(theme) = theme, let settings = theme.theme.settings { + themeSignal = Signal { subscriber in + let theme = makePresentationTheme(mediaBox: accountManager.mediaBox, themeReference: .builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)), accentColor: UIColor(rgb: UInt32(bitPattern: settings.accentColor)), backgroundColors: nil, bubbleColors: settings.messageColors.flatMap { (UIColor(rgb: UInt32(bitPattern: $0.top)), UIColor(rgb: UInt32(bitPattern: $0.bottom))) }, wallpaper: settings.wallpaper, serviceBackgroundColor: nil, preview: false) + subscriber.putNext(theme) + subscriber.putCompletion() + + return EmptyDisposable + } + } else { + themeSignal = .never() + } + + colorsSignal = themeSignal + |> mapToSignal { theme -> Signal<((UIColor, UIColor?), (UIColor, UIColor), (UIColor, UIColor), UIImage?, Int32?), NoError> in + if let theme = theme { + var wallpaperSignal: Signal<((UIColor, UIColor?), (UIColor, UIColor), (UIColor, UIColor), UIImage?, Int32?), NoError> = .complete() + var rotation: Int32? + let backgroundColor: (UIColor, UIColor?) + let incomingColor = (theme.chat.message.incoming.bubble.withoutWallpaper.fill, theme.chat.message.incoming.bubble.withoutWallpaper.gradientFill) + let outgoingColor = (theme.chat.message.outgoing.bubble.withoutWallpaper.fill, theme.chat.message.outgoing.bubble.withoutWallpaper.gradientFill) + switch theme.chat.defaultWallpaper { + case .builtin: + backgroundColor = (UIColor(rgb: 0xd6e2ee), nil) + case let .color(color): + backgroundColor = (UIColor(rgb: UInt32(bitPattern: color)), nil) + case let .gradient(topColor, bottomColor, settings): + backgroundColor = (UIColor(rgb: UInt32(bitPattern: topColor)), UIColor(rgb: UInt32(bitPattern: bottomColor))) + rotation = settings.rotation + case .image: + backgroundColor = (.black, nil) + case let .file(file): + rotation = file.settings.rotation + if file.isPattern, let color = file.settings.color { + backgroundColor = (UIColor(rgb: UInt32(bitPattern: color)), file.settings.bottomColor.flatMap { UIColor(rgb: UInt32(bitPattern: $0)) }) + } else { + backgroundColor = (theme.chatList.backgroundColor, nil) + } + wallpaperSignal = cachedWallpaper(account: account, slug: file.slug, settings: file.settings) + |> mapToSignal { wallpaper in + if let wallpaper = wallpaper, case let .file(file) = wallpaper.wallpaper { + var convertedRepresentations: [ImageRepresentationWithReference] = [] + convertedRepresentations.append(ImageRepresentationWithReference(representation: TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 100, height: 100), resource: file.file.resource), reference: .media(media: .standalone(media: file.file), resource: file.file.resource))) + return wallpaperDatas(account: account, accountManager: accountManager, fileReference: .standalone(media: file.file), representations: convertedRepresentations, alwaysShowThumbnailFirst: false, thumbnail: false, onlyFullSize: true, autoFetchFullSize: true, synchronousLoad: false) + |> mapToSignal { _, fullSizeData, complete -> Signal<((UIColor, UIColor?), (UIColor, UIColor), (UIColor, UIColor), UIImage?, Int32?), NoError> in + guard complete, let fullSizeData = fullSizeData else { + return .complete() + } + accountManager.mediaBox.storeResourceData(file.file.resource.id, data: fullSizeData) + let _ = accountManager.mediaBox.cachedResourceRepresentation(file.file.resource, representation: CachedScaledImageRepresentation(size: CGSize(width: 720.0, height: 720.0), mode: .aspectFit), complete: true, fetch: true).start() + + if file.isPattern { + if let color = file.settings.color, let intensity = file.settings.intensity { return accountManager.mediaBox.cachedResourceRepresentation(file.file.resource, representation: CachedPatternWallpaperRepresentation(color: color, bottomColor: file.settings.bottomColor, intensity: intensity, rotation: file.settings.rotation), complete: true, fetch: true) |> mapToSignal { _ in return .complete() } - } else if file.settings.blur { - return accountManager.mediaBox.cachedResourceRepresentation(file.file.resource, representation: CachedBlurredWallpaperRepresentation(), complete: true, fetch: true) - |> mapToSignal { _ in - if let image = UIImage(data: fullSizeData) { - return .single((backgroundColor, incomingColor, outgoingColor, image, rotation)) - } else { - return .complete() - } - } - } else if let image = UIImage(data: fullSizeData) { - return .single((backgroundColor, incomingColor, outgoingColor, image, rotation)) } else { return .complete() } + } else if file.settings.blur { + return accountManager.mediaBox.cachedResourceRepresentation(file.file.resource, representation: CachedBlurredWallpaperRepresentation(), complete: true, fetch: true) + |> mapToSignal { _ in + if let image = UIImage(data: fullSizeData) { + return .single((backgroundColor, incomingColor, outgoingColor, image, rotation)) + } else { + return .complete() + } + } + } else if let image = UIImage(data: fullSizeData) { + return .single((backgroundColor, incomingColor, outgoingColor, image, rotation)) + } else { + return .complete() } - } else { - return .complete() } + } else { + return .complete() } - } - return .single((backgroundColor, incomingColor, outgoingColor, nil, rotation)) - |> then(wallpaperSignal) - } else { - return .complete() + } } + return .single((backgroundColor, incomingColor, outgoingColor, nil, rotation)) + |> then(wallpaperSignal) + } else { + return .complete() } - } else { - colorsSignal = .never() } } return colorsSignal From c6e520e5c17b229b44dca62b5894b77062988b79 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Thu, 26 Dec 2019 12:32:03 +0300 Subject: [PATCH 4/4] Theme fixes --- .../Sources/Themes/EditThemeController.swift | 4 +- .../Themes/ThemeAccentColorController.swift | 46 +++++++++----- .../ThemeAccentColorControllerNode.swift | 6 +- .../Themes/ThemeSettingsAccentColorItem.swift | 11 +++- .../Themes/ThemeSettingsController.swift | 62 ++++++++++++------- .../Themes/ThemeSettingsThemeItem.swift | 20 +++++- .../Themes/WallpaperPatternPanelNode.swift | 13 +++- .../DefaultDarkPresentationTheme.swift | 6 +- .../DefaultDarkTintedPresentationTheme.swift | 6 +- .../Sources/DefaultDayPresentationTheme.swift | 6 +- .../Sources/MakePresentationTheme.swift | 18 +++--- .../Sources/PresentationTheme.swift | 22 +++++++ .../Sources/PresentationThemeSettings.swift | 10 +++ 13 files changed, 161 insertions(+), 69 deletions(-) diff --git a/submodules/SettingsUI/Sources/Themes/EditThemeController.swift b/submodules/SettingsUI/Sources/Themes/EditThemeController.swift index bd1121cc73..728bad5cb1 100644 --- a/submodules/SettingsUI/Sources/Themes/EditThemeController.swift +++ b/submodules/SettingsUI/Sources/Themes/EditThemeController.swift @@ -282,6 +282,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll initialState = EditThemeControllerState(mode: mode, title: generateThemeName(accentColor: theme.rootController.navigationBar.buttonColor), slug: "", updatedTheme: nil, updating: false) previewThemePromise.set(.single(theme.withUpdated(name: "", defaultWallpaper: wallpaper))) case let .edit(info): + settingsPromise.set(.single(info.theme.settings)) if let file = info.theme.file, let path = context.sharedContext.accountManager.mediaBox.completedResourcePath(file.resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path)), let theme = makePresentationTheme(data: data, resolvedWallpaper: info.resolvedWallpaper) { if case let .file(file) = theme.chat.defaultWallpaper, file.id == 0 { previewThemePromise.set(cachedWallpaper(account: context.account, slug: file.slug, settings: file.settings) @@ -295,7 +296,6 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll } else { previewThemePromise.set(.single(theme.withUpdated(name: nil, defaultWallpaper: info.resolvedWallpaper))) } - settingsPromise.set(.single(info.theme.settings)) } else { previewThemePromise.set(.single(presentationData.theme.withUpdated(name: "", defaultWallpaper: presentationData.chatWallpaper))) @@ -320,7 +320,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll let _ = (combineLatest(queue: Queue.mainQueue(), previewThemePromise.get(), settingsPromise.get()) |> take(1)).start(next: { theme, previousSettings in var controllerDismissImpl: (() -> Void)? - let controller = ThemeAccentColorController(context: context, mode: .edit(theme: theme, wallpaper: nil, defaultThemeReference: nil, create: false, completion: { updatedTheme, settings in + let controller = ThemeAccentColorController(context: context, mode: .edit(theme: theme, wallpaper: nil, generalThemeReference: nil, defaultThemeReference: nil, create: false, completion: { updatedTheme, settings in updateState { current in var state = current previewThemePromise.set(.single(updatedTheme)) diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift index adf2fda3be..9f4fedb065 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift @@ -17,13 +17,13 @@ private let randomBackgroundColors: [Int32] = [0x007aff, 0x00c2ed, 0x29b327, 0xe enum ThemeAccentColorControllerMode { case colors(themeReference: PresentationThemeReference, create: Bool) case background(themeReference: PresentationThemeReference) - case edit(theme: PresentationTheme, wallpaper: TelegramWallpaper?, defaultThemeReference: PresentationThemeReference?, create: Bool, completion: (PresentationTheme, TelegramThemeSettings?) -> Void) + case edit(theme: PresentationTheme, wallpaper: TelegramWallpaper?, generalThemeReference: PresentationThemeReference?, defaultThemeReference: PresentationThemeReference?, create: Bool, completion: (PresentationTheme, TelegramThemeSettings?) -> Void) var themeReference: PresentationThemeReference? { switch self { case let .colors(themeReference, _), let .background(themeReference): return themeReference - case let .edit(_, _, defaultThemeReference, _, _): + case let .edit(_, _, _, defaultThemeReference, _, _): return defaultThemeReference default: return nil @@ -119,7 +119,7 @@ final class ThemeAccentColorController: ViewController { let theme: PresentationTheme let wallpaper: TelegramWallpaper - if case let .edit(editedTheme, walpaper, _, _, _) = self.mode { + if case let .edit(editedTheme, walpaper, _, _, _, _) = self.mode { theme = editedTheme wallpaper = walpaper ?? editedTheme.chat.defaultWallpaper } else { @@ -178,28 +178,38 @@ final class ThemeAccentColorController: ViewController { prepare = .complete() } - if case let .edit(theme, _, themeReference, _, completion) = strongSelf.mode { + if case let .edit(theme, _, generalThemeReference, themeReference, _, completion) = strongSelf.mode { let _ = (prepare |> deliverOnMainQueue).start(completed: { [weak self] in let updatedTheme: PresentationTheme var settings: TelegramThemeSettings? + var hasSettings = false + var baseTheme: TelegramBaseTheme? + + if case let .cloud(theme) = generalThemeReference, let settings = theme.theme.settings { + hasSettings = true + baseTheme = settings.baseTheme + } else if case let .builtin(theme) = generalThemeReference { + hasSettings = true + baseTheme = theme.baseTheme + } if let themeReference = themeReference { updatedTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: themeReference, accentColor: state.accentColor, backgroundColors: state.backgroundColors, bubbleColors: state.messagesColors, wallpaper: state.initialWallpaper ?? coloredWallpaper, serviceBackgroundColor: serviceBackgroundColor) ?? defaultPresentationTheme - - if case let .builtin(theme) = themeReference { - var messageColors: (Int32, Int32)? - if let colors = state.messagesColors { - messageColors = (Int32(bitPattern: colors.0.rgb), Int32(bitPattern: colors.1?.rgb ?? colors.0.rgb)) - } - - settings = TelegramThemeSettings(baseTheme: theme.baseTheme, accentColor: Int32(bitPattern: state.accentColor.rgb), messageColors: messageColors, wallpaper: coloredWallpaper) - } } else { updatedTheme = customizePresentationTheme(theme, editing: false, accentColor: state.accentColor, backgroundColors: state.backgroundColors, bubbleColors: state.messagesColors, wallpaper: state.initialWallpaper ?? coloredWallpaper) } - + + if hasSettings, let baseTheme = baseTheme { + var messageColors: (Int32, Int32)? + if let colors = state.messagesColors { + messageColors = (Int32(bitPattern: colors.0.rgb), Int32(bitPattern: colors.1?.rgb ?? colors.0.rgb)) + } + + settings = TelegramThemeSettings(baseTheme: baseTheme, accentColor: Int32(bitPattern: state.accentColor.rgb), messageColors: messageColors, wallpaper: coloredWallpaper) + } + completion(updatedTheme, settings) }) } else if case let .colors(theme, create) = strongSelf.mode { @@ -208,6 +218,8 @@ final class ThemeAccentColorController: ViewController { if case let .cloud(theme) = theme, let settings = theme.theme.settings { telegramTheme = theme.theme baseTheme = settings.baseTheme + } else if case let .builtin(theme) = theme { + baseTheme = theme.baseTheme } else { baseTheme = .classic } @@ -365,9 +377,9 @@ final class ThemeAccentColorController: ViewController { } else if let customWallpaper = settings.themeSpecificChatWallpapers[themeReference.index] { wallpaper = customWallpaper } else { - let theme = makePresentationTheme(mediaBox: strongSelf.context.sharedContext.accountManager.mediaBox, themeReference: themeReference, accentColor: nil) ?? defaultPresentationTheme + let theme = makePresentationTheme(mediaBox: strongSelf.context.sharedContext.accountManager.mediaBox, themeReference: themeReference, accentColor: nil, wallpaper: themeSpecificAccentColor?.wallpaper) ?? defaultPresentationTheme if case let .builtin(themeName) = themeReference { - if case .dayClassic = themeName, settings.themeSpecificAccentColors[themeReference.index] != nil { + if case .dayClassic = themeName, settings.themeSpecificAccentColors[coloredThemeIndex(reference: themeReference, accentColor: themeSpecificAccentColor)] != nil { ignoreDefaultWallpaper = true } else if case .nightAccent = themeName { ignoreDefaultWallpaper = true @@ -466,7 +478,7 @@ final class ThemeAccentColorController: ViewController { } } } - } else if case let .edit(theme, wallpaper, _, _, _) = strongSelf.mode { + } else if case let .edit(theme, wallpaper, _, _, _, _) = strongSelf.mode { accentColor = theme.rootController.navigationBar.accentTextColor let wallpaper = wallpaper ?? theme.chat.defaultWallpaper diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift index f28b2f5103..b36d311ebb 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift @@ -258,7 +258,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate self.patternPanelNode = WallpaperPatternPanelNode(context: self.context, theme: self.theme, strings: self.presentationData.strings) let doneButtonType: WallpaperGalleryToolbarDoneButtonType - if case .edit(_, _, _, true, _) = self.mode { + if case .edit(_, _, _, _, true, _) = self.mode { doneButtonType = .proceed } else { doneButtonType = .set @@ -469,7 +469,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate if !updateOnlyWallpaper { if let themeReference = mode.themeReference { updatedTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: themeReference, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: messagesColors, serviceBackgroundColor: serviceBackgroundColor, preview: true) ?? defaultPresentationTheme - } else if case let .edit(theme, _, _, _, _) = mode { + } else if case let .edit(theme, _, _, _, _, _) = mode { updatedTheme = customizePresentationTheme(theme, editing: false, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: messagesColors) } else { updatedTheme = theme @@ -700,7 +700,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate doneButtonType = .apply cancelButtonType = .discard } else { - if case .edit(_, _, _, true, _) = self.mode { + if case .edit(_, _, _, _, true, _) = self.mode { doneButtonType = .proceed } else { doneButtonType = .set diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsAccentColorItem.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsAccentColorItem.swift index 189c6c7e92..5b723996fa 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsAccentColorItem.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsAccentColorItem.swift @@ -143,6 +143,15 @@ enum ThemeSettingsColorOption: Equatable { } } + var wallpaper: TelegramWallpaper? { + switch self { + case let .accentColor(color): + return color.wallpaper + case .theme: + return nil + } + } + var index: Int64 { switch self { case let .accentColor(color): @@ -918,7 +927,7 @@ class ThemeSettingsAccentColorItemNode: ListViewItemNode, ItemListItemNode { } let contextAction: ((ThemeSettingsColorOption?, Bool, ASDisplayNode, ContextGesture?) -> Void)? = { [weak item] color, selected, node, gesture in if let strongSelf = self, let item = strongSelf.item { - item.contextAction?(selected, item.themeReference, color, node, gesture) + item.contextAction?(selected, item.generalThemeReference, color, node, gesture) } } let openColorPicker: (Bool) -> Void = { [weak self] create in diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift index fd3fee4c71..86c7a91c1d 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift @@ -598,7 +598,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The if let wallpaper = wallpaper { effectiveWallpaper = wallpaper } else { - let theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: reference, accentColor: accentColor?.color, bubbleColors: accentColor?.customBubbleColors) + let theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: reference, accentColor: accentColor?.color, bubbleColors: accentColor?.customBubbleColors, wallpaper: accentColor?.wallpaper) effectiveWallpaper = theme?.chat.defaultWallpaper ?? .builtin(WallpaperSettings()) } return (accentColor, effectiveWallpaper) @@ -663,7 +663,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The let _ = (resolvedWallpaper |> deliverOnMainQueue).start(next: { wallpaper in - let controller = ThemeAccentColorController(context: context, mode: .edit(theme: theme, wallpaper: wallpaper, defaultThemeReference: nil, create: true, completion: { result, settings in + let controller = ThemeAccentColorController(context: context, mode: .edit(theme: theme, wallpaper: wallpaper, generalThemeReference: reference.generalThemeReference, defaultThemeReference: nil, create: true, completion: { result, settings in let controller = editThemeController(context: context, mode: .create(result, nil), navigateToChat: { peerId in if let navigationController = getNavigationControllerImpl?() { context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId))) @@ -704,14 +704,19 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The |> take(1) |> deliverOnMainQueue).start(next: { themes in if isCurrent, let currentThemeIndex = themes.firstIndex(where: { $0.id == theme.theme.id }) { - let previousThemeIndex = themes.prefix(upTo: currentThemeIndex).reversed().firstIndex(where: { $0.file != nil }) - let newTheme: PresentationThemeReference - if let previousThemeIndex = previousThemeIndex { - newTheme = .cloud(PresentationCloudTheme(theme: themes[themes.index(before: previousThemeIndex.base)], resolvedWallpaper: nil)) + if let settings = theme.theme.settings { + selectAccentColorImpl?(nil) } else { - newTheme = .builtin(.nightAccent) + let previousThemeIndex = themes.prefix(upTo: currentThemeIndex).reversed().firstIndex(where: { $0.file != nil }) + let newTheme: PresentationThemeReference + if let previousThemeIndex = previousThemeIndex { + newTheme = .cloud(PresentationCloudTheme(theme: themes[themes.index(before: previousThemeIndex.base)], resolvedWallpaper: nil)) + } else { + newTheme = .builtin(.nightAccent) + } + selectThemeImpl?(newTheme) } - selectThemeImpl?(newTheme) + } let _ = deleteThemeInteractively(account: context.account, accountManager: context.sharedContext.accountManager, theme: theme.theme).start() @@ -758,7 +763,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The } } return (accentColor, wallpaper) - } |> mapToSignal { accentColor, wallpaper -> Signal<(PresentationTheme?, TelegramWallpaper?), NoError> in + } |> mapToSignal { accentColor, wallpaper -> Signal<(PresentationTheme?, PresentationThemeReference, TelegramWallpaper?), NoError> in let generalThemeReference: PresentationThemeReference if let accentColor = accentColor, case let .cloud(theme) = reference, let settings = theme.theme.settings { generalThemeReference = .builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)) @@ -767,6 +772,13 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The } let effectiveWallpaper: TelegramWallpaper + let effectiveThemeReference: PresentationThemeReference + if let accentColor = accentColor, case let .theme(themeReference) = accentColor { + effectiveThemeReference = themeReference + } else { + effectiveThemeReference = reference + } + if let wallpaper = wallpaper { effectiveWallpaper = wallpaper } else { @@ -774,7 +786,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The if let accentColor = accentColor, case let .theme(themeReference) = accentColor { theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: themeReference) } else { - theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: generalThemeReference, accentColor: accentColor?.accentColor, bubbleColors: accentColor?.customBubbleColors) + theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: generalThemeReference, accentColor: accentColor?.accentColor, bubbleColors: accentColor?.customBubbleColors, wallpaper: accentColor?.wallpaper) } effectiveWallpaper = theme?.chat.defaultWallpaper ?? .builtin(WallpaperSettings()) } @@ -792,23 +804,26 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The return wallpaperSignal |> mapToSignal { wallpaper in return chatServiceBackgroundColor(wallpaper: wallpaper, mediaBox: context.sharedContext.accountManager.mediaBox) + |> map { serviceBackgroundColor in + return (wallpaper, serviceBackgroundColor) + } } - |> map { serviceBackgroundColor in + |> map { wallpaper, serviceBackgroundColor in if let accentColor = accentColor, case let .theme(themeReference) = accentColor { - return (makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: themeReference, serviceBackgroundColor: serviceBackgroundColor), wallpaper) + return (makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: themeReference, serviceBackgroundColor: serviceBackgroundColor), effectiveThemeReference, wallpaper) } else { - return (makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: generalThemeReference, accentColor: accentColor?.accentColor, bubbleColors: accentColor?.customBubbleColors, serviceBackgroundColor: serviceBackgroundColor), wallpaper) + return (makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: generalThemeReference, accentColor: accentColor?.accentColor, bubbleColors: accentColor?.customBubbleColors, serviceBackgroundColor: serviceBackgroundColor), effectiveThemeReference, wallpaper) } } } - |> deliverOnMainQueue).start(next: { theme, wallpaper in + |> deliverOnMainQueue).start(next: { theme, effectiveThemeReference, wallpaper in guard let theme = theme else { return } let presentationData = context.sharedContext.currentPresentationData.with { $0 } let strings = presentationData.strings - let themeController = ThemePreviewController(context: context, previewTheme: theme, source: .settings(reference, wallpaper)) + let themeController = ThemePreviewController(context: context, previewTheme: theme, source: .settings(effectiveThemeReference, wallpaper)) var items: [ContextMenuItem] = [] if let accentColor = accentColor { @@ -844,7 +859,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The let _ = (resolvedWallpaper |> deliverOnMainQueue).start(next: { wallpaper in - let controller = ThemeAccentColorController(context: context, mode: .edit(theme: theme, wallpaper: wallpaper, defaultThemeReference: nil, create: true, completion: { result, settings in + let controller = ThemeAccentColorController(context: context, mode: .edit(theme: theme, wallpaper: wallpaper, generalThemeReference: reference.generalThemeReference, defaultThemeReference: nil, create: true, completion: { result, settings in let controller = editThemeController(context: context, mode: .create(result, nil), navigateToChat: { peerId in if let navigationController = getNavigationControllerImpl?() { context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId))) @@ -1215,10 +1230,10 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The items.append(ActionSheetButtonItem(title: presentationData.strings.Appearance_CreateTheme, color: .accent, action: { [weak actionSheet] in actionSheet?.dismissAnimated() - let _ = (context.sharedContext.accountManager.transaction { transaction -> PresentationThemeReference? in + let _ = (context.sharedContext.accountManager.transaction { transaction -> PresentationThemeReference in let settings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.presentationThemeSettings) as? PresentationThemeSettings ?? PresentationThemeSettings.defaultSettings - var themeReference: PresentationThemeReference? + let themeReference: PresentationThemeReference let autoNightModeTriggered = context.sharedContext.currentPresentationData.with { $0 }.autoNightModeTriggered if autoNightModeTriggered { themeReference = settings.automaticThemeSwitchSetting.theme @@ -1226,14 +1241,15 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The themeReference = settings.theme } - if let themeReference = themeReference, case .builtin = themeReference { - } else { - themeReference = nil - } return themeReference } |> deliverOnMainQueue).start(next: { themeReference in - let controller = ThemeAccentColorController(context: context, mode: .edit(theme: presentationData.theme, wallpaper: presentationData.chatWallpaper, defaultThemeReference: themeReference, create: true, completion: { result, settings in + let defaultThemeReference: PresentationThemeReference? + if case .builtin = themeReference { + defaultThemeReference = themeReference + } + + let controller = ThemeAccentColorController(context: context, mode: .edit(theme: presentationData.theme, wallpaper: presentationData.chatWallpaper, generalThemeReference: themeReference.generalThemeReference, defaultThemeReference: themeReference, create: true, completion: { result, settings in let controller = editThemeController(context: context, mode: .create(result, settings), navigateToChat: { peerId in if let navigationController = getNavigationControllerImpl?() { context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId))) diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsThemeItem.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsThemeItem.swift index 782f25eaef..597965bdfd 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsThemeItem.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsThemeItem.swift @@ -305,7 +305,9 @@ private final class ThemeSettingsThemeItemIconNode : ListViewItemNode { } func prepareCrossfadeTransition() { - self.snapshotView?.removeFromSuperview() + guard self.snapshotView == nil else { + return + } if let snapshotView = self.containerNode.view.snapshotView(afterScreenUpdates: false) { self.view.insertSubview(snapshotView, aboveSubview: self.containerNode.view) @@ -314,8 +316,13 @@ private final class ThemeSettingsThemeItemIconNode : ListViewItemNode { } func animateCrossfadeTransition() { + guard self.snapshotView?.layer.animationKeys()?.isEmpty ?? true else { + return + } + self.snapshotView?.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak self] _ in self?.snapshotView?.removeFromSuperview() + self?.snapshotView = nil }) } @@ -603,7 +610,7 @@ class ThemeSettingsThemeItemNode: ListViewItemNode, ItemListItemNode { var entries: [ThemeSettingsThemeEntry] = [] var index: Int = 0 - for var theme in item.themes { + for var theme in item.themes.prefix(1) { if !item.displayUnsupported, case let .cloud(theme) = theme, theme.theme.file == nil { continue } @@ -647,7 +654,9 @@ class ThemeSettingsThemeItemNode: ListViewItemNode, ItemListItemNode { } func prepareCrossfadeTransition() { - self.snapshotView?.removeFromSuperview() + guard self.snapshotView == nil else { + return + } if let snapshotView = self.containerNode.view.snapshotView(afterScreenUpdates: false) { self.view.insertSubview(snapshotView, aboveSubview: self.containerNode.view) @@ -662,8 +671,13 @@ class ThemeSettingsThemeItemNode: ListViewItemNode, ItemListItemNode { } func animateCrossfadeTransition() { + guard self.snapshotView?.layer.animationKeys()?.isEmpty ?? true else { + return + } + self.snapshotView?.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak self] _ in self?.snapshotView?.removeFromSuperview() + self?.snapshotView = nil }) self.listNode.forEachVisibleItemNode { node in diff --git a/submodules/SettingsUI/Sources/Themes/WallpaperPatternPanelNode.swift b/submodules/SettingsUI/Sources/Themes/WallpaperPatternPanelNode.swift index 2714d7a77a..d24532e2a4 100644 --- a/submodules/SettingsUI/Sources/Themes/WallpaperPatternPanelNode.swift +++ b/submodules/SettingsUI/Sources/Themes/WallpaperPatternPanelNode.swift @@ -143,7 +143,7 @@ final class WallpaperPatternPanelNode: ASDisplayNode { selectedFileId = file.id } - for wallpaper in wallpapers { + for wallpaper in self.wallpapers { let node = SettingsThemeWallpaperNode(overlayBackgroundColor: self.serviceBackgroundColor.withAlphaComponent(0.4)) node.clipsToBounds = true node.cornerRadius = 5.0 @@ -251,7 +251,16 @@ final class WallpaperPatternPanelNode: ASDisplayNode { let frame = node.frame.insetBy(dx: -48.0, dy: 0.0) if frame.minX < bounds.minX || frame.maxX > bounds.maxX { - self.scrollNode.view.scrollRectToVisible(frame, animated: animated) + let transition: ContainedViewLayoutTransition = animated ? .animated(duration: 0.3, curve: .easeInOut) : .immediate + + var origin = CGPoint() + if frame.minX < bounds.minX { + origin.x = max(0.0, frame.minX) + } else if frame.maxX > bounds.maxX { + origin.x = min(self.scrollNode.view.contentSize.width - bounds.width, frame.maxX - bounds.width) + } + + transition.updateBounds(node: self.scrollNode, bounds: CGRect(origin: origin, size: self.scrollNode.frame.size)) } } diff --git a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift index 078e387066..e86c431f6c 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift @@ -221,7 +221,7 @@ public func customizeDefaultDarkPresentationTheme(theme: PresentationTheme, edit ) } -public func makeDefaultDarkPresentationTheme(customIndex: Int64? = nil, preview: Bool) -> PresentationTheme { +public func makeDefaultDarkPresentationTheme(extendingThemeReference: PresentationThemeReference? = nil, preview: Bool) -> PresentationTheme { let rootTabBar = PresentationThemeRootTabBar( backgroundColor: UIColor(rgb: 0x1c1c1d), separatorColor: UIColor(rgb: 0x3d3d40), @@ -531,8 +531,8 @@ public func makeDefaultDarkPresentationTheme(customIndex: Int64? = nil, preview: ) return PresentationTheme( - name: .builtin(.night), - index: customIndex ?? PresentationThemeReference.builtin(.night).index, + name: extendingThemeReference?.name ?? .builtin(.night), + index: extendingThemeReference?.index ?? PresentationThemeReference.builtin(.night).index, referenceTheme: .night, overallDarkAppearance: true, intro: intro, diff --git a/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift index 8d2f453945..9e0723a004 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift @@ -441,7 +441,7 @@ public func customizeDefaultDarkTintedPresentationTheme(theme: PresentationTheme ) } -public func makeDefaultDarkTintedPresentationTheme(customIndex: Int64? = nil, preview: Bool) -> PresentationTheme { +public func makeDefaultDarkTintedPresentationTheme(extendingThemeReference: PresentationThemeReference? = nil, preview: Bool) -> PresentationTheme { let accentColor = defaultDarkTintedAccentColor let secondaryBadgeTextColor: UIColor @@ -787,8 +787,8 @@ public func makeDefaultDarkTintedPresentationTheme(customIndex: Int64? = nil, pr ) return PresentationTheme( - name: .builtin(.nightAccent), - index: customIndex ?? PresentationThemeReference.builtin(.nightAccent).index, + name: extendingThemeReference?.name ?? .builtin(.nightAccent), + index: extendingThemeReference?.index ?? PresentationThemeReference.builtin(.nightAccent).index, referenceTheme: .nightAccent, overallDarkAppearance: true, intro: intro, diff --git a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift index 611639e3ac..273125f57c 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift @@ -311,7 +311,7 @@ public func customizeDefaultDayTheme(theme: PresentationTheme, editing: Bool, ac ) } -public func makeDefaultDayPresentationTheme(customIndex: Int64? = nil, serviceBackgroundColor: UIColor?, day: Bool, preview: Bool) -> PresentationTheme { +public func makeDefaultDayPresentationTheme(extendingThemeReference: PresentationThemeReference? = nil, serviceBackgroundColor: UIColor?, day: Bool, preview: Bool) -> PresentationTheme { var serviceBackgroundColor = serviceBackgroundColor ?? defaultServiceBackgroundColor let intro = PresentationThemeIntro( @@ -740,8 +740,8 @@ public func makeDefaultDayPresentationTheme(customIndex: Int64? = nil, serviceBa ) return PresentationTheme( - name: .builtin(day ? .day : .dayClassic), - index: customIndex ?? PresentationThemeReference.builtin(day ? .day : .dayClassic).index, + name: extendingThemeReference?.name ?? .builtin(day ? .day : .dayClassic), + index: extendingThemeReference?.index ?? PresentationThemeReference.builtin(day ? .day : .dayClassic).index, referenceTheme: day ? .day : .dayClassic, overallDarkAppearance: false, intro: intro, diff --git a/submodules/TelegramPresentationData/Sources/MakePresentationTheme.swift b/submodules/TelegramPresentationData/Sources/MakePresentationTheme.swift index fb3c52ce2e..dcf5101707 100644 --- a/submodules/TelegramPresentationData/Sources/MakePresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/MakePresentationTheme.swift @@ -4,23 +4,23 @@ import Postbox import SyncCore import TelegramUIPreferences -public func makeDefaultPresentationTheme(reference: PresentationBuiltinThemeReference, customIndex: Int64? = nil, serviceBackgroundColor: UIColor?, preview: Bool = false) -> PresentationTheme { +public func makeDefaultPresentationTheme(reference: PresentationBuiltinThemeReference, extendingThemeReference: PresentationThemeReference? = nil, serviceBackgroundColor: UIColor?, preview: Bool = false) -> PresentationTheme { let theme: PresentationTheme switch reference { case .dayClassic: - theme = makeDefaultDayPresentationTheme(customIndex: customIndex, serviceBackgroundColor: serviceBackgroundColor, day: false, preview: preview) + theme = makeDefaultDayPresentationTheme(extendingThemeReference: extendingThemeReference, serviceBackgroundColor: serviceBackgroundColor, day: false, preview: preview) case .day: - theme = makeDefaultDayPresentationTheme(customIndex: customIndex, serviceBackgroundColor: serviceBackgroundColor, day: true, preview: preview) + theme = makeDefaultDayPresentationTheme(extendingThemeReference: extendingThemeReference, serviceBackgroundColor: serviceBackgroundColor, day: true, preview: preview) case .night: - theme = makeDefaultDarkPresentationTheme(customIndex: customIndex, preview: preview) + theme = makeDefaultDarkPresentationTheme(extendingThemeReference: extendingThemeReference, preview: preview) case .nightAccent: - theme = makeDefaultDarkTintedPresentationTheme(customIndex: customIndex, preview: preview) + theme = makeDefaultDarkTintedPresentationTheme(extendingThemeReference: extendingThemeReference, preview: preview) } return theme } public func customizePresentationTheme(_ theme: PresentationTheme, editing: Bool, accentColor: UIColor?, backgroundColors: (UIColor, UIColor?)?, bubbleColors: (UIColor, UIColor?)?, wallpaper: TelegramWallpaper? = nil) -> PresentationTheme { - if accentColor == nil && bubbleColors == nil && backgroundColors == nil { + if accentColor == nil && bubbleColors == nil && backgroundColors == nil && wallpaper == nil { return theme } switch theme.referenceTheme { @@ -35,11 +35,11 @@ public func customizePresentationTheme(_ theme: PresentationTheme, editing: Bool return theme } -public func makePresentationTheme(mediaBox: MediaBox, themeReference: PresentationThemeReference, customIndex: Int64? = nil, accentColor: UIColor? = nil, backgroundColors: (UIColor, UIColor?)? = nil, bubbleColors: (UIColor, UIColor?)? = nil, wallpaper: TelegramWallpaper? = nil, serviceBackgroundColor: UIColor? = nil, preview: Bool = false) -> PresentationTheme? { +public func makePresentationTheme(mediaBox: MediaBox, themeReference: PresentationThemeReference, extendingThemeReference: PresentationThemeReference? = nil, accentColor: UIColor? = nil, backgroundColors: (UIColor, UIColor?)? = nil, bubbleColors: (UIColor, UIColor?)? = nil, wallpaper: TelegramWallpaper? = nil, serviceBackgroundColor: UIColor? = nil, preview: Bool = false) -> PresentationTheme? { let theme: PresentationTheme switch themeReference { case let .builtin(reference): - let defaultTheme = makeDefaultPresentationTheme(reference: reference, customIndex: customIndex, serviceBackgroundColor: serviceBackgroundColor, preview: preview) + let defaultTheme = makeDefaultPresentationTheme(reference: reference, extendingThemeReference: extendingThemeReference, serviceBackgroundColor: serviceBackgroundColor, preview: preview) theme = customizePresentationTheme(defaultTheme, editing: true, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors, wallpaper: wallpaper) case let .local(info): if let path = mediaBox.completedResourcePath(info.resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead), let loadedTheme = makePresentationTheme(data: data, themeReference: themeReference, resolvedWallpaper: info.resolvedWallpaper) { @@ -49,7 +49,7 @@ public func makePresentationTheme(mediaBox: MediaBox, themeReference: Presentati } case let .cloud(info): if let settings = info.theme.settings { - if let loadedTheme = makePresentationTheme(mediaBox: mediaBox, themeReference: .builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)), customIndex: themeReference.index, accentColor: accentColor ?? UIColor(rgb: UInt32(bitPattern: settings.accentColor)), backgroundColors: nil, bubbleColors: bubbleColors ?? settings.messageColors.flatMap { (UIColor(rgb: UInt32(bitPattern: $0.top)), UIColor(rgb: UInt32(bitPattern: $0.bottom))) }, wallpaper: wallpaper ?? settings.wallpaper, serviceBackgroundColor: serviceBackgroundColor, preview: preview) { + if let loadedTheme = makePresentationTheme(mediaBox: mediaBox, themeReference: .builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)), extendingThemeReference: themeReference, accentColor: accentColor ?? UIColor(rgb: UInt32(bitPattern: settings.accentColor)), backgroundColors: nil, bubbleColors: bubbleColors ?? settings.messageColors.flatMap { (UIColor(rgb: UInt32(bitPattern: $0.top)), UIColor(rgb: UInt32(bitPattern: $0.bottom))) }, wallpaper: wallpaper ?? settings.wallpaper, serviceBackgroundColor: serviceBackgroundColor, preview: preview) { theme = loadedTheme } else { return nil diff --git a/submodules/TelegramPresentationData/Sources/PresentationTheme.swift b/submodules/TelegramPresentationData/Sources/PresentationTheme.swift index 1b45d6a192..43342ae28c 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationTheme.swift @@ -1105,6 +1105,28 @@ public enum PresentationThemeName: Equatable { } } +public extension PresentationThemeReference { + public var name: PresentationThemeName { + switch self { + case let .builtin(theme): + switch theme { + case .day: + return .builtin(.day) + case .dayClassic: + return .builtin(.dayClassic) + case .night: + return .builtin(.night) + case .nightAccent: + return .builtin(.nightAccent) + } + case let .cloud(info): + return .custom(info.theme.title) + default: + return .custom("") + } + } +} + public final class PresentationTheme: Equatable { public let name: PresentationThemeName public let index: Int64 diff --git a/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift b/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift index 79a5417cd3..9a2cf3ee9f 100644 --- a/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift +++ b/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift @@ -220,6 +220,16 @@ public enum PresentationThemeReference: PostboxCoding, Equatable { return (Int64(namespace) << 32) | Int64(bitPattern: UInt64(UInt32(bitPattern: id))) } + + public var generalThemeReference: PresentationThemeReference { + let generalThemeReference: PresentationThemeReference + if case let .cloud(theme) = self, let settings = theme.theme.settings { + generalThemeReference = .builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)) + } else { + generalThemeReference = self + } + return generalThemeReference + } } public func coloredThemeIndex(reference: PresentationThemeReference, accentColor: PresentationThemeAccentColor?) -> Int64 {