From a0c9f26f1c69eefe61ec319db8ba0a53555128c6 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 25 Jun 2019 23:54:31 +0200 Subject: [PATCH] Added support for theme-specific accent colors --- .../Sources/PresentationData.swift | 8 +- .../TelegramUI/CustomWallpaperPicker.swift | 2 +- .../TelegramUI/LegacyPreferencesImport.swift | 6 +- .../TelegramUI/SuppressContactsWarning.swift | 2 +- .../TelegramUI/ThemeGridController.swift | 4 +- .../ThemeSettingsAccentColorItem.swift | 170 ++++++++---------- .../TelegramUI/ThemeSettingsController.swift | 117 +++++++----- .../TelegramUI/ThemeSettingsThemeItem.swift | 64 ++++--- .../WallpaperGalleryController.swift | 2 +- .../TelegramUI/WallpaperUploadManager.swift | 2 +- .../Sources/PresentationThemeSettings.swift | 120 +++++++++++-- 11 files changed, 305 insertions(+), 192 deletions(-) diff --git a/submodules/TelegramPresentationData/Sources/PresentationData.swift b/submodules/TelegramPresentationData/Sources/PresentationData.swift index b1c42ddcbc..4d87418c76 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationData.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationData.swift @@ -271,6 +271,8 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager) - effectiveTheme = themeSettings.theme } + let effectiveAccentColor = themeSettings.themeSpecificAccentColors[effectiveTheme.index]?.color ?? defaultDayAccentColor + switch effectiveTheme { case let .builtin(reference): switch reference { @@ -281,7 +283,7 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager) - case .nightAccent: themeValue = defaultDarkAccentPresentationTheme case .day: - themeValue = makeDefaultDayPresentationTheme(accentColor: themeSettings.themeAccentColor ?? defaultDayAccentColor, serviceBackgroundColor: defaultServiceBackgroundColor) + themeValue = makeDefaultDayPresentationTheme(accentColor: effectiveAccentColor, serviceBackgroundColor: defaultServiceBackgroundColor) } } let dateTimeFormat = currentDateTimeFormat() @@ -550,6 +552,8 @@ public func updatedPresentationData(accountManager: AccountManager, applicationI effectiveTheme = themeSettings.theme } + let effectiveAccentColor = themeSettings.themeSpecificAccentColors[effectiveTheme.index]?.color ?? defaultDayAccentColor + let themeValue: PresentationTheme switch effectiveTheme { case let .builtin(reference): @@ -561,7 +565,7 @@ public func updatedPresentationData(accountManager: AccountManager, applicationI case .nightAccent: themeValue = defaultDarkAccentPresentationTheme case .day: - themeValue = makeDefaultDayPresentationTheme(accentColor: themeSettings.themeAccentColor ?? defaultDayAccentColor, serviceBackgroundColor: serviceBackgroundColor) + themeValue = makeDefaultDayPresentationTheme(accentColor: effectiveAccentColor, serviceBackgroundColor: serviceBackgroundColor) } } diff --git a/submodules/TelegramUI/TelegramUI/CustomWallpaperPicker.swift b/submodules/TelegramUI/TelegramUI/CustomWallpaperPicker.swift index 749935bd96..691a0a0d10 100644 --- a/submodules/TelegramUI/TelegramUI/CustomWallpaperPicker.swift +++ b/submodules/TelegramUI/TelegramUI/CustomWallpaperPicker.swift @@ -150,7 +150,7 @@ func uploadCustomWallpaper(context: AccountContext, wallpaper: WallpaperGalleryE let _ = (updatePresentationThemeSettingsInteractively(accountManager: accountManager, { current in var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers themeSpecificChatWallpapers[current.theme.index] = wallpaper - return PresentationThemeSettings(chatWallpaper: wallpaper, theme: current.theme, themeAccentColor: current.themeAccentColor, themeSpecificChatWallpapers: themeSpecificChatWallpapers, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) + return PresentationThemeSettings(chatWallpaper: wallpaper, theme: current.theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) })).start() } diff --git a/submodules/TelegramUI/TelegramUI/LegacyPreferencesImport.swift b/submodules/TelegramUI/TelegramUI/LegacyPreferencesImport.swift index 3ddb5f2e46..f26c2d1eb5 100644 --- a/submodules/TelegramUI/TelegramUI/LegacyPreferencesImport.swift +++ b/submodules/TelegramUI/TelegramUI/LegacyPreferencesImport.swift @@ -189,7 +189,8 @@ func importLegacyPreferences(accountManager: AccountManager, account: TemporaryA settings.theme = .builtin(.day) if presentationState.userInfo != 0 { - settings.themeAccentColor = presentationState.userInfo + //themeSpecificAccentColors: current.themeSpecificAccentColors + //settings.themeAccentColor = presentationState.userInfo } settings.chatWallpaper = .color(0xffffff) case 2: @@ -214,7 +215,8 @@ func importLegacyPreferences(accountManager: AccountManager, account: TemporaryA settings.fontSize = fontSizeMap[presentationState.fontSize] ?? .regular if presentationState.userInfo != 0 { - settings.themeAccentColor = presentationState.userInfo + //themeSpecificAccentColors: current.themeSpecificAccentColors + //settings.themeAccentColor = presentationState.userInfo } } diff --git a/submodules/TelegramUI/TelegramUI/SuppressContactsWarning.swift b/submodules/TelegramUI/TelegramUI/SuppressContactsWarning.swift index e7646ab873..29ad6725c2 100644 --- a/submodules/TelegramUI/TelegramUI/SuppressContactsWarning.swift +++ b/submodules/TelegramUI/TelegramUI/SuppressContactsWarning.swift @@ -8,7 +8,7 @@ import DeviceAccess func presentContactsWarningSuppression(context: AccountContext, present: (ViewController, Any?) -> Void) { let presentationData = context.sharedContext.currentPresentationData.with { $0 } present(textAlertController(context: context, title: presentationData.strings.Contacts_PermissionsSuppressWarningTitle, text: presentationData.strings.Contacts_PermissionsSuppressWarningText, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Contacts_PermissionsKeepDisabled, action: { - ApplicationSpecificNotice.setContactsPermissionWarning(accountManager: context.sharedContext.accountManager, value: Int32(Date().timeIntervalSince1970)) + ApplicationSpecificNotice.setPermissionWarning(accountManager: context.sharedContext.accountManager, permission: .contacts, value: Int32(Date().timeIntervalSince1970)) }), TextAlertAction(type: .defaultAction, title: presentationData.strings.Contacts_PermissionsEnable, action: { let _ = (DeviceAccess.authorizationStatus(subject: .contacts) |> take(1) diff --git a/submodules/TelegramUI/TelegramUI/ThemeGridController.swift b/submodules/TelegramUI/TelegramUI/ThemeGridController.swift index 91adf13aea..64638e049f 100644 --- a/submodules/TelegramUI/TelegramUI/ThemeGridController.swift +++ b/submodules/TelegramUI/TelegramUI/ThemeGridController.swift @@ -185,7 +185,7 @@ final class ThemeGridController: ViewController { var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers themeSpecificChatWallpapers[current.theme.index] = fallbackWallpaper - return PresentationThemeSettings(chatWallpaper: fallbackWallpaper, theme: current.theme, themeAccentColor: current.themeAccentColor, themeSpecificChatWallpapers: themeSpecificChatWallpapers, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) + return PresentationThemeSettings(chatWallpaper: fallbackWallpaper, theme: current.theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) })).start() break } @@ -257,7 +257,7 @@ final class ThemeGridController: ViewController { } else { wallpaper = .builtin(WallpaperSettings()) } - return PresentationThemeSettings(chatWallpaper: wallpaper, theme: current.theme, themeAccentColor: current.themeAccentColor, themeSpecificChatWallpapers: [:], fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) + return PresentationThemeSettings(chatWallpaper: wallpaper, theme: current.theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: [:], fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) }) }).start() diff --git a/submodules/TelegramUI/TelegramUI/ThemeSettingsAccentColorItem.swift b/submodules/TelegramUI/TelegramUI/ThemeSettingsAccentColorItem.swift index 156e9cf282..439f65876f 100644 --- a/submodules/TelegramUI/TelegramUI/ThemeSettingsAccentColorItem.swift +++ b/submodules/TelegramUI/TelegramUI/ThemeSettingsAccentColorItem.swift @@ -5,33 +5,26 @@ import AsyncDisplayKit import SwiftSignalKit import TelegramCore import TelegramPresentationData +import TelegramUIPreferences -private func generateBorderImage(theme: PresentationTheme, bordered: Bool, selected: Bool) -> UIImage? { - return generateImage(CGSize(width: 30.0, height: 30.0), rotatedContext: { size, context in +private func generateSwatchImage(color: PresentationThemeAccentColor, selected: Bool) -> UIImage? { + return generateImage(CGSize(width: 40.0, height: 40.0), rotatedContext: { size, context in let bounds = CGRect(origin: CGPoint(), size: size) - context.setFillColor(theme.list.itemBlocksBackgroundColor.cgColor) - context.fill(bounds) - context.setBlendMode(.clear) - context.fillEllipse(in: bounds) - context.setBlendMode(.normal) + context.clear(bounds) + + let fillColor = UIColor(rgb: UInt32(bitPattern: color.color)) + let strokeColor = UIColor(rgb: UInt32(bitPattern: color.baseColor.colorValue)) + + context.setFillColor(fillColor.cgColor) + context.setStrokeColor(strokeColor.cgColor) + context.setLineWidth(2.0) - let lineWidth: CGFloat if selected { - var accentColor = theme.list.itemAccentColor - if accentColor.rgb == UIColor.white.rgb { - accentColor = UIColor(rgb: 0x999999) - } - context.setStrokeColor(accentColor.cgColor) - lineWidth = 2.0 + context.fillEllipse(in: bounds.insetBy(dx: 4.0, dy: 4.0)) + context.strokeEllipse(in: bounds.insetBy(dx: 1.0, dy: 1.0)) } else { - context.setStrokeColor(theme.list.disclosureArrowColor.withAlphaComponent(0.4).cgColor) - lineWidth = 1.0 - } - - if bordered || selected { - context.setLineWidth(lineWidth) - context.strokeEllipse(in: bounds.insetBy(dx: lineWidth / 2.0, dy: lineWidth / 2.0)) + context.fillEllipse(in: bounds) } })?.stretchableImage(withLeftCapWidth: 15, topCapHeight: 15) } @@ -40,18 +33,18 @@ class ThemeSettingsAccentColorItem: ListViewItem, ItemListItem { var sectionId: ItemListSectionId let theme: PresentationTheme - let strings: PresentationStrings - let colors: [UIColor] - let currentColor: UIColor - let updated: (UIColor) -> Void + let colors: [PresentationThemeBaseColor] + let currentColor: PresentationThemeAccentColor + let updated: (PresentationThemeAccentColor) -> Void + let toggleSlider: () -> Void let tag: ItemListItemTag? - init(theme: PresentationTheme, strings: PresentationStrings, sectionId: ItemListSectionId, colors: [UIColor], currentColor: UIColor, updated: @escaping (UIColor) -> Void, tag: ItemListItemTag? = nil) { + init(theme: PresentationTheme, sectionId: ItemListSectionId, colors: [PresentationThemeBaseColor], currentColor: PresentationThemeAccentColor, updated: @escaping (PresentationThemeAccentColor) -> Void, toggleSlider: @escaping () -> Void, tag: ItemListItemTag? = nil) { self.theme = theme - self.strings = strings self.colors = colors self.currentColor = currentColor self.updated = updated + self.toggleSlider = toggleSlider self.tag = tag self.sectionId = sectionId } @@ -92,8 +85,6 @@ class ThemeSettingsAccentColorItem: ListViewItem, ItemListItem { private final class ThemeSettingsAccentColorNode : ASDisplayNode { private let iconNode: ASImageNode - private let overlayNode: ASImageNode - private let textNode: ASTextNode private var action: (() -> Void)? override init() { @@ -101,25 +92,13 @@ private final class ThemeSettingsAccentColorNode : ASDisplayNode { self.iconNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 62.0, height: 62.0)) self.iconNode.isLayerBacked = true - self.overlayNode = ASImageNode() - self.overlayNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 62.0, height: 62.0)) - self.overlayNode.isLayerBacked = true - - self.textNode = ASTextNode() - self.textNode.isUserInteractionEnabled = false - self.textNode.displaysAsynchronously = true - super.init() self.addSubnode(self.iconNode) - self.addSubnode(self.overlayNode) - self.addSubnode(self.textNode) } - func setup(theme: PresentationTheme, icon: UIImage, title: NSAttributedString, bordered: Bool, selected: Bool, action: @escaping () -> Void) { - self.iconNode.image = icon - self.textNode.attributedText = title - self.overlayNode.image = generateBorderImage(theme: theme, bordered: bordered, selected: selected) + func setup(color: PresentationThemeAccentColor, selected: Bool, action: @escaping () -> Void) { + self.iconNode.image = generateSwatchImage(color: color, selected: selected) self.action = { action() } @@ -139,12 +118,8 @@ private final class ThemeSettingsAccentColorNode : ASDisplayNode { override func layout() { super.layout() - - let bounds = self.bounds - - self.iconNode.frame = CGRect(origin: CGPoint(x: 10.0, y: 14.0), size: CGSize(width: 62.0, height: 62.0)) - self.overlayNode.frame = CGRect(origin: CGPoint(x: 10.0, y: 14.0), size: CGSize(width: 62.0, height: 62.0)) - self.textNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 14.0 + 60.0 + 4.0 + 9.0), size: CGSize(width: bounds.size.width, height: 16.0)) + + self.iconNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 40.0, height: 40.0)) } } @@ -190,6 +165,15 @@ class ThemeSettingsAccentColorItemNode: ListViewItemNode, ItemListItemNode { self.scrollNode.view.showsHorizontalScrollIndicator = false } + private func scrollToNode(_ node: ThemeSettingsAccentColorNode, animated: Bool) { + let bounds = self.scrollNode.view.bounds + 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) + } + } + func asyncLayout() -> (_ item: ThemeSettingsAccentColorItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) { let currentItem = self.item @@ -197,14 +181,13 @@ class ThemeSettingsAccentColorItemNode: ListViewItemNode, ItemListItemNode { var themeUpdated = false if currentItem?.theme !== item.theme { themeUpdated = true - } let contentSize: CGSize let insets: UIEdgeInsets let separatorHeight = UIScreenPixel - contentSize = CGSize(width: params.width, height: 116.0) + contentSize = CGSize(width: params.width, height: 60.0) insets = itemListNeighborsGroupedInsets(neighbors) let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets) @@ -230,33 +213,36 @@ class ThemeSettingsAccentColorItemNode: ListViewItemNode, ItemListItemNode { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } switch neighbors.top { - case .sameSection(false): - strongSelf.topStripeNode.isHidden = true - default: - strongSelf.topStripeNode.isHidden = false + case .sameSection(false): + strongSelf.topStripeNode.isHidden = true + default: + strongSelf.topStripeNode.isHidden = false } let bottomStripeInset: CGFloat let bottomStripeOffset: CGFloat switch neighbors.bottom { - case .sameSection(false): - bottomStripeInset = params.leftInset + 16.0 - bottomStripeOffset = -separatorHeight - default: - bottomStripeInset = 0.0 - bottomStripeOffset = 0.0 + case .sameSection(false): + bottomStripeInset = params.leftInset + 16.0 + bottomStripeOffset = -separatorHeight + default: + bottomStripeInset = 0.0 + bottomStripeOffset = 0.0 } strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight)) strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight)) - strongSelf.scrollNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 2.0), size: CGSize(width: layoutSize.width, height: layoutSize.height)) + strongSelf.scrollNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: layoutSize.width, height: layoutSize.height)) - let nodeInset: CGFloat = 4.0 - let nodeSize = CGSize(width: 80.0, height: 112.0) + let nodeInset: CGFloat = 15.0 + let nodeSize = CGSize(width: 40.0, height: 40.0) var nodeOffset = nodeInset + var updated = false + var selectedNode: ThemeSettingsAccentColorNode? + var i = 0 - for icon in item.colors { + for color in item.colors { let imageNode: ThemeSettingsAccentColorNode if strongSelf.nodes.count > i { imageNode = strongSelf.nodes[i] @@ -264,41 +250,27 @@ class ThemeSettingsAccentColorItemNode: ListViewItemNode, ItemListItemNode { imageNode = ThemeSettingsAccentColorNode() strongSelf.nodes.append(imageNode) strongSelf.scrollNode.addSubnode(imageNode) + updated = true } -// if let image = UIImage(named: icon.imageName, in: Bundle.main, compatibleWith: nil) { -// let selected = icon.name == item.currentIconName -// -// var name = "Icon" -// var bordered = true -// switch icon.name { -// case "Blue": -// name = item.strings.Appearance_AppIconDefault -// case "Black": -// name = item.strings.Appearance_AppIconDefaultX -// case "BlueClassic": -// name = item.strings.Appearance_AppIconClassic -// case "BlackClassic": -// name = item.strings.Appearance_AppIconClassicX -// case "BlueFilled": -// name = item.strings.Appearance_AppIconFilled -// bordered = false -// case "BlackFilled": -// name = item.strings.Appearance_AppIconFilledX -// bordered = false -// case "WhiteFilled": -// name = "⍺ White" -// default: -// break -// } -// -// imageNode.setup(theme: item.theme, icon: image, title: NSAttributedString(string: name, font: textFont, textColor: selected ? item.theme.list.itemAccentColor : item.theme.list.itemPrimaryTextColor, paragraphAlignment: .center), bordered: bordered, selected: selected, action: { -// item.updated(icon.name) -// }) -// } + let accentColor: PresentationThemeAccentColor + let selected = item.currentColor.baseColor == color + if selected { + accentColor = item.currentColor + selectedNode = imageNode + } else { + accentColor = PresentationThemeAccentColor(baseColor: color, value: 0.5) + } - imageNode.frame = CGRect(origin: CGPoint(x: nodeOffset, y: 0.0), size: nodeSize) - nodeOffset += nodeSize.width + 15.0 + imageNode.setup(color: accentColor, selected: selected, action: { [weak self, weak imageNode] in + item.updated(accentColor) + if let imageNode = imageNode { + self?.scrollToNode(imageNode, animated: true) + } + }) + + imageNode.frame = CGRect(origin: CGPoint(x: nodeOffset, y: 10.0), size: nodeSize) + nodeOffset += nodeSize.width + 18.0 i += 1 } @@ -309,6 +281,10 @@ class ThemeSettingsAccentColorItemNode: ListViewItemNode, ItemListItemNode { strongSelf.scrollNode.view.contentSize = contentSize } } + + if updated, let selectedNode = selectedNode { + strongSelf.scrollToNode(selectedNode, animated: false) + } } }) } diff --git a/submodules/TelegramUI/TelegramUI/ThemeSettingsController.swift b/submodules/TelegramUI/TelegramUI/ThemeSettingsController.swift index ea4044a5f1..5813018150 100644 --- a/submodules/TelegramUI/TelegramUI/ThemeSettingsController.swift +++ b/submodules/TelegramUI/TelegramUI/ThemeSettingsController.swift @@ -9,7 +9,7 @@ import TelegramUIPreferences private final class ThemeSettingsControllerArguments { let context: AccountContext - let selectTheme: (Int32) -> Void + let selectTheme: (PresentationThemeReference) -> Void let selectFontSize: (PresentationFontSize) -> Void let openWallpaperSettings: () -> Void let openAccentColor: (Int32) -> Void @@ -18,7 +18,7 @@ private final class ThemeSettingsControllerArguments { let disableAnimations: (Bool) -> Void let selectAppIcon: (String) -> Void - init(context: AccountContext, selectTheme: @escaping (Int32) -> Void, selectFontSize: @escaping (PresentationFontSize) -> Void, openWallpaperSettings: @escaping () -> Void, openAccentColor: @escaping (Int32) -> Void, openAutoNightTheme: @escaping () -> Void, toggleLargeEmoji: @escaping (Bool) -> Void, disableAnimations: @escaping (Bool) -> Void, selectAppIcon: @escaping (String) -> Void) { + init(context: AccountContext, selectTheme: @escaping (PresentationThemeReference) -> Void, selectFontSize: @escaping (PresentationFontSize) -> Void, openWallpaperSettings: @escaping () -> Void, openAccentColor: @escaping (Int32) -> Void, openAutoNightTheme: @escaping () -> Void, toggleLargeEmoji: @escaping (Bool) -> Void, disableAnimations: @escaping (Bool) -> Void, selectAppIcon: @escaping (String) -> Void) { self.context = context self.selectTheme = selectTheme self.selectFontSize = selectFontSize @@ -62,9 +62,9 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry { case fontSize(PresentationTheme, PresentationFontSize) case chatPreview(PresentationTheme, PresentationTheme, TelegramWallpaper, PresentationFontSize, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder) case wallpaper(PresentationTheme, String) - case accentColor(PresentationTheme, String, Int32) + case accentColor(PresentationTheme, String, PresentationThemeAccentColor?) case autoNightTheme(PresentationTheme, String, String) - case themeItem(PresentationTheme, PresentationStrings, [PresentationBuiltinThemeReference], PresentationBuiltinThemeReference, UIColor?) + case themeItem(PresentationTheme, PresentationStrings, [PresentationThemeReference], PresentationThemeReference, [Int64: PresentationThemeAccentColor]) case iconHeader(PresentationTheme, String) case iconItem(PresentationTheme, PresentationStrings, [PresentationAppIcon], String?) case otherHeader(PresentationTheme, String) @@ -228,18 +228,28 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry { arguments.openWallpaperSettings() }) case let .accentColor(theme, text, color): - return ItemListDisclosureItem(theme: theme, icon: nil, title: text, label: "", labelStyle: .color(UIColor(rgb: UInt32(bitPattern: color))), sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { - arguments.openAccentColor(color) + let colorValue = color?.baseColor.colorValue ?? defaultDayAccentColor + let accentColor = UIColor(rgb: UInt32(bitPattern: colorValue)) + return ItemListDisclosureItem(theme: theme, icon: nil, title: text, label: "", labelStyle: .color(accentColor), sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { + arguments.openAccentColor(colorValue) }, tag: ThemeSettingsEntryTag.accentColor) +// return ThemeSettingsAccentColorItem(theme: theme, sectionId: self.section, colors: PresentationThemeBaseColor.allCases, currentColor: color ?? PresentationThemeAccentColor(baseColor: .blue, value: 0.5), updated: { color in +// let _ = updatePresentationThemeSettingsInteractively(accountManager: arguments.context.sharedContext.accountManager, { current in +// var themeSpecificAccentColors = current.themeSpecificAccentColors +// themeSpecificAccentColors[current.theme.index] = color +// return PresentationThemeSettings(chatWallpaper: current.chatWallpaper, theme: current.theme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: current.themeSpecificChatWallpapers, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) +// }).start() +// }, toggleSlider: { +// }) case let .autoNightTheme(theme, text, value): return ItemListDisclosureItem(theme: theme, icon: nil, title: text, label: value, labelStyle: .text, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { arguments.openAutoNightTheme() }) case let .themeListHeader(theme, text): return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section) - case let .themeItem(theme, strings, themes, currentTheme, themeAccentColor): - return ThemeSettingsThemeItem(theme: theme, strings: strings, sectionId: self.section, themes: themes.map { ($0, $0 == .day ? themeAccentColor : nil) }, currentTheme: currentTheme, updated: { theme in - arguments.selectTheme(theme.rawValue) + case let .themeItem(theme, strings, themes, currentTheme, themeSpecificAccentColors): + return ThemeSettingsThemeItem(theme: theme, strings: strings, sectionId: self.section, themes: themes, themeSpecificAccentColors: themeSpecificAccentColors, currentTheme: currentTheme, updated: { theme in + arguments.selectTheme(theme) }) case let .iconHeader(theme, text): return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section) @@ -263,16 +273,16 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry { } } -private func themeSettingsControllerEntries(presentationData: PresentationData, theme: PresentationTheme, themeAccentColor: Int32?, autoNightSettings: AutomaticThemeSwitchSetting, strings: PresentationStrings, wallpaper: TelegramWallpaper, fontSize: PresentationFontSize, dateTimeFormat: PresentationDateTimeFormat, largeEmoji: Bool, disableAnimations: Bool, availableAppIcons: [PresentationAppIcon], currentAppIconName: String?) -> [ThemeSettingsControllerEntry] { +private func themeSettingsControllerEntries(presentationData: PresentationData, theme: PresentationTheme, themeReference: PresentationThemeReference, themeSpecificAccentColors: [Int64: PresentationThemeAccentColor], autoNightSettings: AutomaticThemeSwitchSetting, strings: PresentationStrings, wallpaper: TelegramWallpaper, fontSize: PresentationFontSize, dateTimeFormat: PresentationDateTimeFormat, largeEmoji: Bool, disableAnimations: Bool, availableAppIcons: [PresentationAppIcon], currentAppIconName: String?) -> [ThemeSettingsControllerEntry] { var entries: [ThemeSettingsControllerEntry] = [] entries.append(.themeListHeader(presentationData.theme, strings.Appearance_ColorTheme.uppercased())) entries.append(.chatPreview(presentationData.theme, theme, wallpaper, fontSize, presentationData.strings, dateTimeFormat, presentationData.nameDisplayOrder)) - if case let .builtin(theme) = theme.name { - entries.append(.themeItem(presentationData.theme, presentationData.strings, [.dayClassic, .day, .nightAccent, .nightGrayscale], theme.reference, themeAccentColor != nil ? UIColor(rgb: UInt32(bitPattern: themeAccentColor!)) : nil)) + if case .builtin = themeReference { + entries.append(.themeItem(presentationData.theme, presentationData.strings, [.builtin(.dayClassic), .builtin(.day), .builtin(.nightAccent), .builtin(.nightGrayscale)], themeReference, themeSpecificAccentColors)) } if theme.name == .builtin(.day) { - entries.append(.accentColor(presentationData.theme, strings.Appearance_AccentColor, themeAccentColor ?? defaultDayAccentColor)) + entries.append(.accentColor(presentationData.theme, strings.Appearance_AccentColor, themeSpecificAccentColors[themeReference.index])) } entries.append(.wallpaper(presentationData.theme, strings.Settings_ChatBackground)) @@ -306,8 +316,6 @@ private func themeSettingsControllerEntries(presentationData: PresentationData, return entries } -private let themeColors = [UIColor(rgb: 0x007aff), UIColor(rgb: 0x70bb23), UIColor(rgb: 0xeb6ca4), UIColor(rgb: 0xf08200), UIColor(rgb: 0x9472ee), UIColor(rgb: 0xd33213), UIColor(rgb: 0xedb400), UIColor(rgb: 0x6d839e), UIColor(rgb: 0x000000)] - public func themeSettingsController(context: AccountContext, focusOnItemTag: ThemeSettingsEntryTag? = nil) -> ViewController { var pushControllerImpl: ((ViewController) -> Void)? var presentControllerImpl: ((ViewController) -> Void)? @@ -318,19 +326,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The let currentAppIconName = ValuePromise() currentAppIconName.set(context.sharedContext.applicationBindings.getAlternateIconName() ?? "Blue") - let arguments = ThemeSettingsControllerArguments(context: context, selectTheme: { index in - let theme: PresentationThemeReference - switch index { - case 1: - theme = .builtin(.nightGrayscale) - case 2: - theme = .builtin(.day) - case 3: - theme = .builtin(.nightAccent) - default: - theme = .builtin(.dayClassic) - } - + let arguments = ThemeSettingsControllerArguments(context: context, selectTheme: { theme in let _ = (context.sharedContext.accountManager.transaction { transaction -> Void in transaction.updateSharedData(ApplicationSpecificSharedDataKeys.presentationThemeSettings, { entry in let current: PresentationThemeSettings @@ -345,51 +341,78 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The if let themeSpecificWallpaper = current.themeSpecificChatWallpapers[theme.index] { wallpaper = themeSpecificWallpaper } else { - switch index { - case 1: - wallpaper = .color(0x000000) - case 2: - wallpaper = .color(0xffffff) - case 3: - wallpaper = .color(0x18222d) - default: - wallpaper = .builtin(WallpaperSettings()) + if case let .builtin(theme) = theme { + switch theme { + case .day: + wallpaper = .color(0xffffff) + case .dayClassic: + wallpaper = .builtin(WallpaperSettings()) + case .nightAccent: + wallpaper = .color(0x18222d) + case .nightGrayscale: + wallpaper = .color(0x000000) + } + } else { + wallpaper = .builtin(WallpaperSettings()) } } - return PresentationThemeSettings(chatWallpaper: wallpaper, theme: theme, themeAccentColor: current.themeAccentColor, themeSpecificChatWallpapers: current.themeSpecificChatWallpapers, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) + return PresentationThemeSettings(chatWallpaper: wallpaper, theme: theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: current.themeSpecificChatWallpapers, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) }) }).start() }, selectFontSize: { size in let _ = updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in - return PresentationThemeSettings(chatWallpaper: current.chatWallpaper, theme: current.theme, themeAccentColor: current.themeAccentColor, themeSpecificChatWallpapers: current.themeSpecificChatWallpapers, fontSize: size, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) + return PresentationThemeSettings(chatWallpaper: current.chatWallpaper, theme: current.theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: current.themeSpecificChatWallpapers, fontSize: size, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) }).start() }, openWallpaperSettings: { pushControllerImpl?(ThemeGridController(context: context)) }, openAccentColor: { color in presentControllerImpl?(ThemeAccentColorActionSheet(context: context, currentValue: color, applyValue: { color in + let themeAccentColor: PresentationThemeBaseColor + switch color { + case 0xf83b4c: + themeAccentColor = .red + case 0xff7519: + themeAccentColor = .orange + case 0xeba239: + themeAccentColor = .yellow + case 0x29b327: + themeAccentColor = .green + case 0x00c2ed: + themeAccentColor = .cyan + case 0x007ee5: + themeAccentColor = .blue + case 0x7748ff: + themeAccentColor = .purple + case 0xff5da2: + themeAccentColor = .pink + default: + themeAccentColor = .blue + } + let _ = updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in - return PresentationThemeSettings(chatWallpaper: current.chatWallpaper, theme: current.theme, themeAccentColor: color, themeSpecificChatWallpapers: current.themeSpecificChatWallpapers, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) + var themeSpecificAccentColors = current.themeSpecificAccentColors + themeSpecificAccentColors[current.theme.index] = PresentationThemeAccentColor(baseColor: themeAccentColor, value: 0.5) + + return PresentationThemeSettings(chatWallpaper: current.chatWallpaper, theme: current.theme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: current.themeSpecificChatWallpapers, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) }).start() })) }, openAutoNightTheme: { pushControllerImpl?(themeAutoNightSettingsController(context: context)) }, toggleLargeEmoji: { largeEmoji in let _ = updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in - return PresentationThemeSettings(chatWallpaper: current.chatWallpaper, theme: current.theme, themeAccentColor: current.themeAccentColor, themeSpecificChatWallpapers: current.themeSpecificChatWallpapers, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: largeEmoji, disableAnimations: current.disableAnimations) + return PresentationThemeSettings(chatWallpaper: current.chatWallpaper, theme: current.theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: current.themeSpecificChatWallpapers, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: largeEmoji, disableAnimations: current.disableAnimations) }).start() }, disableAnimations: { disabled in let _ = updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in - return PresentationThemeSettings(chatWallpaper: current.chatWallpaper, theme: current.theme, themeAccentColor: current.themeAccentColor, themeSpecificChatWallpapers: current.themeSpecificChatWallpapers, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: disabled) + return PresentationThemeSettings(chatWallpaper: current.chatWallpaper, theme: current.theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: current.themeSpecificChatWallpapers, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: disabled) }).start() }, selectAppIcon: { name in currentAppIconName.set(name) context.sharedContext.applicationBindings.requestSetAlternateIconName(name, { _ in }) }) - - let previousTheme = Atomic(value: nil) - + let signal = combineLatest(context.sharedContext.presentationData |> deliverOnMainQueue, context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.presentationThemeSettings]) |> deliverOnMainQueue, availableAppIcons, currentAppIconName.get() |> deliverOnMainQueue) |> map { presentationData, sharedData, availableAppIcons, currentAppIconName -> (ItemListControllerState, (ItemListNodeState, ThemeSettingsControllerEntry.ItemGenerationArguments)) in let theme: PresentationTheme @@ -410,7 +433,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The case .nightAccent: theme = defaultDarkAccentPresentationTheme case .day: - theme = makeDefaultDayPresentationTheme(accentColor: settings.themeAccentColor ?? defaultDayAccentColor, serviceBackgroundColor: defaultServiceBackgroundColor) + theme = makeDefaultDayPresentationTheme(accentColor: settings.themeSpecificAccentColors[settings.theme.index]?.color ?? defaultDayAccentColor, serviceBackgroundColor: defaultServiceBackgroundColor) } } wallpaper = settings.chatWallpaper @@ -421,7 +444,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The disableAnimations = settings.disableAnimations let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.Appearance_Title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back)) - let listState = ItemListNodeState(entries: themeSettingsControllerEntries(presentationData: presentationData, theme: theme, themeAccentColor: settings.themeAccentColor, autoNightSettings: settings.automaticThemeSwitchSetting, strings: presentationData.strings, wallpaper: wallpaper, fontSize: fontSize, dateTimeFormat: dateTimeFormat, largeEmoji: largeEmoji, disableAnimations: disableAnimations, availableAppIcons: availableAppIcons, currentAppIconName: currentAppIconName), style: .blocks, ensureVisibleItemTag: focusOnItemTag, animateChanges: false) + let listState = ItemListNodeState(entries: themeSettingsControllerEntries(presentationData: presentationData, theme: theme, themeReference: settings.theme, themeSpecificAccentColors: settings.themeSpecificAccentColors, autoNightSettings: settings.automaticThemeSwitchSetting, strings: presentationData.strings, wallpaper: wallpaper, fontSize: fontSize, dateTimeFormat: dateTimeFormat, largeEmoji: largeEmoji, disableAnimations: disableAnimations, availableAppIcons: availableAppIcons, currentAppIconName: currentAppIconName), style: .blocks, ensureVisibleItemTag: focusOnItemTag, animateChanges: false) return (controllerState, (listState, arguments)) } diff --git a/submodules/TelegramUI/TelegramUI/ThemeSettingsThemeItem.swift b/submodules/TelegramUI/TelegramUI/ThemeSettingsThemeItem.swift index 1d13c1f872..1804314760 100644 --- a/submodules/TelegramUI/TelegramUI/ThemeSettingsThemeItem.swift +++ b/submodules/TelegramUI/TelegramUI/ThemeSettingsThemeItem.swift @@ -37,8 +37,11 @@ private func generateBorderImage(theme: PresentationTheme, bordered: Bool, selec })?.stretchableImage(withLeftCapWidth: 15, topCapHeight: 15) } -private func generateThemeIconImage(theme: PresentationBuiltinThemeReference, accentColor: UIColor?) -> UIImage { +private func generateThemeIconImage(theme: PresentationThemeReference, accentColor: Int32?) -> UIImage { return generateImage(CGSize(width: 98.0, height: 62.0), rotatedContext: { size, context in + guard case let .builtin(theme) = theme else { + return + } let bounds = CGRect(origin: CGPoint(), size: size) let background: UIColor @@ -53,7 +56,7 @@ private func generateThemeIconImage(theme: PresentationBuiltinThemeReference, ac background = .white incomingBubble = UIColor(rgb: 0xd5dde6) if let accentColor = accentColor { - outgoingBubble = accentColor + outgoingBubble = UIColor(rgb: UInt32(bitPattern: accentColor)) } else { outgoingBubble = UIColor(rgb: 0x007aff) } @@ -66,7 +69,7 @@ private func generateThemeIconImage(theme: PresentationBuiltinThemeReference, ac incomingBubble = UIColor(rgb: 0x32475e) outgoingBubble = UIColor(rgb: 0x3d6a97) } - + context.setFillColor(background.cgColor) context.fill(bounds) @@ -91,15 +94,17 @@ class ThemeSettingsThemeItem: ListViewItem, ItemListItem { let theme: PresentationTheme let strings: PresentationStrings - let themes: [(PresentationBuiltinThemeReference, UIColor?)] - let currentTheme: PresentationBuiltinThemeReference - let updated: (PresentationBuiltinThemeReference) -> Void + let themes: [PresentationThemeReference] + let themeSpecificAccentColors: [Int64: PresentationThemeAccentColor] + let currentTheme: PresentationThemeReference + let updated: (PresentationThemeReference) -> Void let tag: ItemListItemTag? - init(theme: PresentationTheme, strings: PresentationStrings, sectionId: ItemListSectionId, themes: [(PresentationBuiltinThemeReference, UIColor?)], currentTheme: PresentationBuiltinThemeReference, updated: @escaping (PresentationBuiltinThemeReference) -> Void, tag: ItemListItemTag? = nil) { + init(theme: PresentationTheme, strings: PresentationStrings, sectionId: ItemListSectionId, themes: [PresentationThemeReference], themeSpecificAccentColors: [Int64: PresentationThemeAccentColor], currentTheme: PresentationThemeReference, updated: @escaping (PresentationThemeReference) -> Void, tag: ItemListItemTag? = nil) { self.theme = theme self.strings = strings self.themes = themes + self.themeSpecificAccentColors = themeSpecificAccentColors self.currentTheme = currentTheme self.updated = updated self.tag = tag @@ -312,7 +317,7 @@ class ThemeSettingsThemeItemNode: ListViewItemNode, ItemListItemNode { var selectedNode: ThemeSettingsThemeItemIconNode? var i = 0 - for (theme, accentColor) in item.themes { + for theme in item.themes { let imageNode: ThemeSettingsThemeItemIconNode if strongSelf.nodes.count > i { imageNode = strongSelf.nodes[i] @@ -328,27 +333,34 @@ class ThemeSettingsThemeItemNode: ListViewItemNode, ItemListItemNode { selectedNode = imageNode } - let name: String - switch theme { - case .dayClassic: - name = item.strings.Appearance_ThemeCarouselClassic - case .day: - name = item.strings.Appearance_ThemeCarouselDay - case .nightGrayscale: - name = item.strings.Appearance_ThemeCarouselNight - case .nightAccent: - name = item.strings.Appearance_ThemeCarouselNightBlue + let name: String? + if case let .builtin(theme) = theme { + switch theme { + case .dayClassic: + name = item.strings.Appearance_ThemeCarouselClassic + case .day: + name = item.strings.Appearance_ThemeCarouselDay + case .nightGrayscale: + name = item.strings.Appearance_ThemeCarouselNight + case .nightAccent: + name = item.strings.Appearance_ThemeCarouselNightBlue + } + } else { + name = nil } - imageNode.setup(theme: item.theme, icon: generateThemeIconImage(theme: theme, accentColor: accentColor), title: NSAttributedString(string: name, font: textFont, textColor: selected ? item.theme.list.itemAccentColor : item.theme.list.itemPrimaryTextColor, paragraphAlignment: .center), bordered: true, selected: selected, action: { [weak self, weak imageNode] in - item.updated(theme) - if let imageNode = imageNode { - self?.scrollToNode(imageNode, animated: true) - } - }) - imageNode.frame = CGRect(origin: CGPoint(x: nodeOffset, y: 0.0), size: nodeSize) - nodeOffset += nodeSize.width + 2.0 + if let name = name { + imageNode.setup(theme: item.theme, icon: generateThemeIconImage(theme: theme, accentColor: item.themeSpecificAccentColors[theme.index]?.color), title: NSAttributedString(string: name, font: textFont, textColor: selected ? item.theme.list.itemAccentColor : item.theme.list.itemPrimaryTextColor, paragraphAlignment: .center), bordered: true, selected: selected, action: { [weak self, weak imageNode] in + item.updated(theme) + if let imageNode = imageNode { + self?.scrollToNode(imageNode, animated: true) + } + }) + + imageNode.frame = CGRect(origin: CGPoint(x: nodeOffset, y: 0.0), size: nodeSize) + nodeOffset += nodeSize.width + 2.0 + } i += 1 } diff --git a/submodules/TelegramUI/TelegramUI/WallpaperGalleryController.swift b/submodules/TelegramUI/TelegramUI/WallpaperGalleryController.swift index ade8118541..d026577e9b 100644 --- a/submodules/TelegramUI/TelegramUI/WallpaperGalleryController.swift +++ b/submodules/TelegramUI/TelegramUI/WallpaperGalleryController.swift @@ -380,7 +380,7 @@ class WallpaperGalleryController: ViewController { let _ = (updatePresentationThemeSettingsInteractively(accountManager: strongSelf.context.sharedContext.accountManager, { current in var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers themeSpecificChatWallpapers[current.theme.index] = wallpaper - return PresentationThemeSettings(chatWallpaper: wallpaper, theme: current.theme, themeAccentColor: current.themeAccentColor, themeSpecificChatWallpapers: themeSpecificChatWallpapers, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) + return PresentationThemeSettings(chatWallpaper: wallpaper, theme: current.theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) }) |> deliverOnMainQueue).start(completed: { self?.dismiss(forceAway: true) }) diff --git a/submodules/TelegramUI/TelegramUI/WallpaperUploadManager.swift b/submodules/TelegramUI/TelegramUI/WallpaperUploadManager.swift index f6f1621572..4677124776 100644 --- a/submodules/TelegramUI/TelegramUI/WallpaperUploadManager.swift +++ b/submodules/TelegramUI/TelegramUI/WallpaperUploadManager.swift @@ -139,7 +139,7 @@ final class WallpaperUploadManager { var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers themeSpecificChatWallpapers[current.theme.index] = updatedWallpaper - return PresentationThemeSettings(chatWallpaper: updatedWallpaper, theme: current.theme, themeAccentColor: current.themeAccentColor, themeSpecificChatWallpapers: themeSpecificChatWallpapers, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, disableAnimations: current.disableAnimations) + return PresentationThemeSettings(chatWallpaper: updatedWallpaper, theme: current.theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, 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 88cf1c3af1..407ec6df35 100644 --- a/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift +++ b/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift @@ -164,11 +164,97 @@ public struct AutomaticThemeSwitchSetting: PostboxCoding, Equatable { } } +public enum PresentationThemeBaseColor: Int32, CaseIterable { + case blue + case cyan + case green + case pink + case orange + case purple + case red + case yellow + case gray + case black + + public var colorValue: Int32 { + switch self { + case .blue: + return 0x007ee5 + case .cyan: + return 0x00c2ed + case .green: + return 0x29b327 + case .pink: + return 0xff5da2 + case .orange: + return 0xff7519 + case .purple: + return 0x7748ff + case .red: + return 0xf83b4c + case .yellow: + return 0xeba239 + case .gray: + return 0x6d839e + case .black: + return 0x000000 + } + +// switch self { +// case .blue: +// return 0x007aff +// case .cyan: +// return 0x00c2ed +// case .green: +// return 0x70bb23 +// case .pink: +// return 0xeb6ca4 +// case .orange: +// return 0xf08200 +// case .purple: +// return 0x9472ee +// case .red: +// return 0xd33213 +// case .yellow: +// return 0xedb400 +// case .gray: +// return 0x6d839e +// case .black: +// return 0x000000 +// } + } +} + +public struct PresentationThemeAccentColor: PostboxCoding, Equatable { + public var baseColor: PresentationThemeBaseColor + public var value: CGFloat + + public init(baseColor: PresentationThemeBaseColor, value: CGFloat) { + self.baseColor = baseColor + self.value = value + } + + public init(decoder: PostboxDecoder) { + self.baseColor = PresentationThemeBaseColor(rawValue: decoder.decodeInt32ForKey("b", orElse: 0)) ?? .blue + self.value = CGFloat(decoder.decodeDoubleForKey("v", orElse: 0.5)) + } + + public func encode(_ encoder: PostboxEncoder) { + encoder.encodeInt32(self.baseColor.rawValue, forKey: "b") + encoder.encodeDouble(Double(self.value), forKey: "v") + } + + public var color: Int32 { + return self.baseColor.colorValue + } +} + public struct PresentationThemeSettings: PreferencesEntry { public var chatWallpaper: TelegramWallpaper public var theme: PresentationThemeReference - public var themeAccentColor: Int32? - public var themeSpecificChatWallpapers: Dictionary +// public var themeAccentColor: Int32? + public var themeSpecificAccentColors: [Int64: PresentationThemeAccentColor] + public var themeSpecificChatWallpapers: [Int64: TelegramWallpaper] public var fontSize: PresentationFontSize public var automaticThemeSwitchSetting: AutomaticThemeSwitchSetting public var largeEmoji: Bool @@ -198,13 +284,13 @@ public struct PresentationThemeSettings: PreferencesEntry { } public static var defaultSettings: PresentationThemeSettings { - return PresentationThemeSettings(chatWallpaper: .builtin(WallpaperSettings()), theme: .builtin(.dayClassic), themeAccentColor: nil, themeSpecificChatWallpapers: [:], fontSize: .regular, automaticThemeSwitchSetting: AutomaticThemeSwitchSetting(trigger: .none, theme: .nightAccent), largeEmoji: true, disableAnimations: true) + return PresentationThemeSettings(chatWallpaper: .builtin(WallpaperSettings()), theme: .builtin(.dayClassic), themeSpecificAccentColors: [:], themeSpecificChatWallpapers: [:], fontSize: .regular, automaticThemeSwitchSetting: AutomaticThemeSwitchSetting(trigger: .none, theme: .nightAccent), largeEmoji: true, disableAnimations: true) } - public init(chatWallpaper: TelegramWallpaper, theme: PresentationThemeReference, themeAccentColor: Int32?, themeSpecificChatWallpapers: Dictionary, fontSize: PresentationFontSize, automaticThemeSwitchSetting: AutomaticThemeSwitchSetting, largeEmoji: Bool, disableAnimations: Bool) { + public init(chatWallpaper: TelegramWallpaper, theme: PresentationThemeReference, themeSpecificAccentColors: [Int64: PresentationThemeAccentColor], themeSpecificChatWallpapers: [Int64: TelegramWallpaper], fontSize: PresentationFontSize, automaticThemeSwitchSetting: AutomaticThemeSwitchSetting, largeEmoji: Bool, disableAnimations: Bool) { self.chatWallpaper = chatWallpaper self.theme = theme - self.themeAccentColor = themeAccentColor + self.themeSpecificAccentColors = themeSpecificAccentColors self.themeSpecificChatWallpapers = themeSpecificChatWallpapers self.fontSize = fontSize self.automaticThemeSwitchSetting = automaticThemeSwitchSetting @@ -215,7 +301,14 @@ public struct PresentationThemeSettings: PreferencesEntry { public init(decoder: PostboxDecoder) { self.chatWallpaper = (decoder.decodeObjectForKey("w", decoder: { TelegramWallpaper(decoder: $0) }) as? TelegramWallpaper) ?? .builtin(WallpaperSettings()) self.theme = decoder.decodeObjectForKey("t", decoder: { PresentationThemeReference(decoder: $0) }) as! PresentationThemeReference - self.themeAccentColor = decoder.decodeOptionalInt32ForKey("themeAccentColor") + //self.themeAccentColor = decoder.decodeOptionalInt32ForKey("themeAccentColor") + + self.themeSpecificAccentColors = decoder.decodeObjectDictionaryForKey("themeSpecificAccentColors", keyDecoder: { decoder in + return decoder.decodeInt64ForKey("k", orElse: 0) + }, valueDecoder: { decoder in + return PresentationThemeAccentColor(decoder: decoder) + }) + self.themeSpecificChatWallpapers = decoder.decodeObjectDictionaryForKey("themeSpecificChatWallpapers", keyDecoder: { decoder in return decoder.decodeInt64ForKey("k", orElse: 0) }, valueDecoder: { decoder in @@ -230,11 +323,14 @@ public struct PresentationThemeSettings: PreferencesEntry { public func encode(_ encoder: PostboxEncoder) { encoder.encodeObject(self.chatWallpaper, forKey: "w") encoder.encodeObject(self.theme, forKey: "t") - if let themeAccentColor = self.themeAccentColor { - encoder.encodeInt32(themeAccentColor, forKey: "themeAccentColor") - } else { - encoder.encodeNil(forKey: "themeAccentColor") - } +// if let themeAccentColor = self.themeAccentColor { +// encoder.encodeInt32(themeAccentColor, forKey: "themeAccentColor") +// } else { +// encoder.encodeNil(forKey: "themeAccentColor") +// } + encoder.encodeObjectDictionary(self.themeSpecificAccentColors, forKey: "themeSpecificAccentColors", keyEncoder: { key, encoder in + encoder.encodeInt64(key, forKey: "k") + }) encoder.encodeObjectDictionary(self.themeSpecificChatWallpapers, forKey: "themeSpecificChatWallpapers", keyEncoder: { key, encoder in encoder.encodeInt64(key, forKey: "k") }) @@ -253,7 +349,7 @@ public struct PresentationThemeSettings: PreferencesEntry { } public static func ==(lhs: PresentationThemeSettings, rhs: PresentationThemeSettings) -> Bool { - return lhs.chatWallpaper == rhs.chatWallpaper && lhs.theme == rhs.theme && lhs.themeAccentColor == rhs.themeAccentColor && lhs.themeSpecificChatWallpapers == rhs.themeSpecificChatWallpapers && lhs.fontSize == rhs.fontSize && lhs.automaticThemeSwitchSetting == rhs.automaticThemeSwitchSetting && lhs.largeEmoji == rhs.largeEmoji && lhs.disableAnimations == rhs.disableAnimations + return lhs.chatWallpaper == rhs.chatWallpaper && lhs.theme == rhs.theme && lhs.themeSpecificAccentColors == rhs.themeSpecificAccentColors && lhs.themeSpecificChatWallpapers == rhs.themeSpecificChatWallpapers && lhs.fontSize == rhs.fontSize && lhs.automaticThemeSwitchSetting == rhs.automaticThemeSwitchSetting && lhs.largeEmoji == rhs.largeEmoji && lhs.disableAnimations == rhs.disableAnimations } }