diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift index 7c62b63322..b2715bf6cd 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift @@ -137,43 +137,61 @@ final class ThemeAccentColorController: ViewController { }, apply: { [weak self] state, serviceBackgroundColor in if let strongSelf = self { let context = strongSelf.context - if case let .edit(theme, _, themeReference, _, completion) = strongSelf.mode { - let updatedTheme: PresentationTheme - if let themeReference = themeReference { - updatedTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: themeReference, accentColor: state.accentColor, bubbleColors: state.messagesColors, backgroundColors: state.backgroundColors, serviceBackgroundColor: serviceBackgroundColor) ?? defaultPresentationTheme + + var coloredWallpaper: TelegramWallpaper? + if let backgroundColors = state.backgroundColors { + let color = Int32(bitPattern: backgroundColors.0.rgb) + let bottomColor = backgroundColors.1.flatMap { Int32(bitPattern: $0.rgb) } + + if let patternWallpaper = state.patternWallpaper { + coloredWallpaper = patternWallpaper.withUpdatedSettings(WallpaperSettings(motion: state.motion, color: color, bottomColor: bottomColor, intensity: state.patternIntensity, rotation: state.rotation)) + } else if let bottomColor = bottomColor { + coloredWallpaper = .gradient(color, bottomColor, WallpaperSettings(motion: state.motion, rotation: state.rotation)) } else { - updatedTheme = customizePresentationTheme(theme, editing: false, accentColor: state.accentColor, backgroundColors: state.backgroundColors, bubbleColors: state.messagesColors) + coloredWallpaper = .color(color) + } + } + + let prepare: Signal + if let patternWallpaper = state.patternWallpaper, case let .file(file) = patternWallpaper, let backgroundColors = state.backgroundColors { + let resource = file.file.resource + let representation = CachedPatternWallpaperRepresentation(color: Int32(bitPattern: backgroundColors.0.rgb), bottomColor: backgroundColors.1.flatMap { Int32(bitPattern: $0.rgb) }, intensity: state.patternIntensity, rotation: state.rotation) + + var data: Data? + if let path = strongSelf.context.account.postbox.mediaBox.completedResourcePath(resource), let maybeData = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) { + data = maybeData + } else if let path = strongSelf.context.sharedContext.accountManager.mediaBox.completedResourcePath(resource), let maybeData = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) { + data = maybeData } - completion(updatedTheme) - } else { - let prepare: Signal - if let patternWallpaper = state.patternWallpaper, case let .file(file) = patternWallpaper, let backgroundColors = state.backgroundColors { - let resource = file.file.resource - let representation = CachedPatternWallpaperRepresentation(color: Int32(bitPattern: backgroundColors.0.rgb), bottomColor: backgroundColors.1.flatMap { Int32(bitPattern: $0.rgb) }, intensity: state.patternIntensity, rotation: state.rotation) - - var data: Data? - if let path = strongSelf.context.account.postbox.mediaBox.completedResourcePath(resource), let maybeData = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) { - data = maybeData - } else if let path = strongSelf.context.sharedContext.accountManager.mediaBox.completedResourcePath(resource), let maybeData = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) { - data = maybeData - } - - if let data = data { - strongSelf.context.sharedContext.accountManager.mediaBox.storeResourceData(resource.id, data: data, synchronous: true) - prepare = (strongSelf.context.sharedContext.accountManager.mediaBox.cachedResourceRepresentation(resource, representation: representation, complete: true, fetch: true) - |> filter({ $0.complete }) - |> take(1) - |> mapToSignal { _ -> Signal in - return .complete() - }) - } else { - prepare = .complete() - } + if let data = data { + strongSelf.context.sharedContext.accountManager.mediaBox.storeResourceData(resource.id, data: data, synchronous: true) + prepare = (strongSelf.context.sharedContext.accountManager.mediaBox.cachedResourceRepresentation(resource, representation: representation, complete: true, fetch: true) + |> filter({ $0.complete }) + |> take(1) + |> mapToSignal { _ -> Signal in + return .complete() + }) } else { prepare = .complete() } - + } else { + prepare = .complete() + } + + if case let .edit(theme, _, themeReference, _, completion) = strongSelf.mode { + let _ = (prepare + |> deliverOnMainQueue).start(completed: { [weak self] in + let updatedTheme: PresentationTheme + 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 + } else { + updatedTheme = customizePresentationTheme(theme, editing: false, accentColor: state.accentColor, backgroundColors: state.backgroundColors, bubbleColors: state.messagesColors, wallpaper: state.initialWallpaper ?? coloredWallpaper) + } + + completion(updatedTheme) + }) + } else { let _ = (prepare |> then(updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in let autoNightModeTriggered = context.sharedContext.currentPresentationData.with { $0 }.autoNightModeTriggered @@ -198,17 +216,8 @@ final class ThemeAccentColorController: ViewController { themeSpecificAccentColors[currentTheme.index] = color var wallpaper = themeSpecificChatWallpapers[currentTheme.index] - if let backgroundColors = state.backgroundColors { - let color = Int32(bitPattern: backgroundColors.0.rgb) - let bottomColor = backgroundColors.1.flatMap { Int32(bitPattern: $0.rgb) } - - if let patternWallpaper = state.patternWallpaper { - wallpaper = patternWallpaper.withUpdatedSettings(WallpaperSettings(motion: state.motion, color: color, bottomColor: bottomColor, intensity: state.patternIntensity, rotation: state.rotation)) - } else if let bottomColor = bottomColor { - wallpaper = .gradient(color, bottomColor, WallpaperSettings(motion: state.motion, rotation: state.rotation)) - } else { - wallpaper = .color(color) - } + if let coloredWallpaper = coloredWallpaper { + wallpaper = coloredWallpaper } themeSpecificChatWallpapers[currentTheme.index] = wallpaper @@ -239,7 +248,7 @@ final class ThemeAccentColorController: ViewController { let accentColor: UIColor var initialWallpaper: TelegramWallpaper? - let backgroundColors: (UIColor, UIColor?)? + var backgroundColors: (UIColor, UIColor?)? var patternWallpaper: TelegramWallpaper? var patternIntensity: Int32 = 50 var motion = false @@ -249,13 +258,44 @@ final class ThemeAccentColorController: ViewController { var ignoreDefaultWallpaper = false + func extractWallpaperParameters(_ wallpaper: TelegramWallpaper?) { + guard let wallpaper = wallpaper else { + return + } + if case let .file(file) = wallpaper, file.isPattern { + var patternColor = UIColor(rgb: 0xd6e2ee, alpha: 0.5) + var bottomColor: UIColor? + if let color = file.settings.color { + if let intensity = file.settings.intensity { + patternIntensity = intensity + } + patternColor = UIColor(rgb: UInt32(bitPattern: color)) + if let bottomColorValue = file.settings.bottomColor { + bottomColor = UIColor(rgb: UInt32(bitPattern: bottomColorValue)) + } + } + patternWallpaper = wallpaper + backgroundColors = (patternColor, bottomColor) + motion = file.settings.motion + rotation = file.settings.rotation ?? 0 + } else if case let .color(color) = wallpaper { + backgroundColors = (UIColor(rgb: UInt32(bitPattern: color)), nil) + } else if case let .gradient(topColor, bottomColor, settings) = wallpaper { + backgroundColors = (UIColor(rgb: UInt32(bitPattern: topColor)), UIColor(rgb: UInt32(bitPattern: bottomColor))) + motion = settings.motion + rotation = settings.rotation ?? 0 + } else { + backgroundColors = nil + } + } + if let themeReference = strongSelf.mode.themeReference { accentColor = settings.themeSpecificAccentColors[themeReference.index]?.color ?? defaultDayAccentColor let wallpaper: TelegramWallpaper if let customWallpaper = settings.themeSpecificChatWallpapers[themeReference.index] { wallpaper = customWallpaper } else { - let theme = makePresentationTheme(mediaBox: strongSelf.context.sharedContext.accountManager.mediaBox, themeReference: themeReference, accentColor: nil, bubbleColors: nil) ?? defaultPresentationTheme + let theme = makePresentationTheme(mediaBox: strongSelf.context.sharedContext.accountManager.mediaBox, themeReference: themeReference, accentColor: nil) ?? defaultPresentationTheme if case let .builtin(themeName) = themeReference { if case .dayClassic = themeName, settings.themeSpecificAccentColors[themeReference.index] != nil { ignoreDefaultWallpaper = true @@ -274,31 +314,7 @@ final class ThemeAccentColorController: ViewController { if let initialBackgroundColor = strongSelf.initialBackgroundColor { backgroundColors = (initialBackgroundColor, nil) } else if !ignoreDefaultWallpaper { - if case let .file(file) = wallpaper, file.isPattern { - var patternColor = UIColor(rgb: 0xd6e2ee, alpha: 0.5) - var bottomColor: UIColor? - if let color = file.settings.color { - if let intensity = file.settings.intensity { - patternIntensity = intensity - } - patternColor = UIColor(rgb: UInt32(bitPattern: color)) - if let bottomColorValue = file.settings.bottomColor { - bottomColor = UIColor(rgb: UInt32(bitPattern: bottomColorValue)) - } - } - patternWallpaper = wallpaper - backgroundColors = (patternColor, bottomColor) - motion = file.settings.motion - rotation = file.settings.rotation ?? 0 - } else if case let .color(color) = wallpaper { - backgroundColors = (UIColor(rgb: UInt32(bitPattern: color)), nil) - } else if case let .gradient(topColor, bottomColor, settings) = wallpaper { - backgroundColors = (UIColor(rgb: UInt32(bitPattern: topColor)), UIColor(rgb: UInt32(bitPattern: bottomColor))) - motion = settings.motion - rotation = settings.rotation ?? 0 - } else { - backgroundColors = nil - } + extractWallpaperParameters(wallpaper) } else { backgroundColors = nil } @@ -318,14 +334,10 @@ final class ThemeAccentColorController: ViewController { } } else if case let .edit(theme, wallpaper, _, _, _) = strongSelf.mode { accentColor = theme.rootController.navigationBar.accentTextColor - if case let .color(color) = theme.chat.defaultWallpaper { - backgroundColors = (UIColor(rgb: UInt32(bitPattern: color)), nil) - } else if case let .gradient(topColor, bottomColor, settings) = theme.chat.defaultWallpaper { - backgroundColors = (UIColor(rgb: UInt32(bitPattern: topColor)), UIColor(rgb: UInt32(bitPattern: bottomColor))) - rotation = settings.rotation ?? 0 - } else { - backgroundColors = nil - } + + let wallpaper = wallpaper ?? theme.chat.defaultWallpaper + extractWallpaperParameters(wallpaper) + let topMessageColor = theme.chat.message.outgoing.bubble.withWallpaper.fill let bottomMessageColor = theme.chat.message.outgoing.bubble.withWallpaper.gradientFill diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift index e5d9c58aba..06212bb676 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift @@ -188,12 +188,12 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate private let serviceBackgroundColorPromise = Promise() private var wallpaperDisposable = MetaDisposable() - private var preview = false - private var currentBackgroundColor: UIColor? + private var currentBackgroundColors: (UIColor, UIColor?)? + private var currentBackgroundPromise = Promise<(UIColor, UIColor?)?>() + private var patternWallpaper: TelegramWallpaper? private var patternArguments: PatternWallpaperArguments? - - private var patternArgumentsValue = Promise() + private var patternArgumentsPromise = Promise() private var patternArgumentsDisposable: Disposable? private var tapGestureRecognizer: UITapGestureRecognizer? @@ -399,7 +399,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate self.stateDisposable = (self.statePromise.get() |> deliverOn(Queue.concurrentDefaultQueue()) - |> map { state -> (PresentationTheme, (TelegramWallpaper, UIImage?, Signal<(TransformImageArguments) -> DrawingContext?, NoError>?), UIColor, UIColor?, [UIColor], Bool) in + |> map { state -> (PresentationTheme, (TelegramWallpaper, UIImage?, Signal<(TransformImageArguments) -> DrawingContext?, NoError>?), UIColor, (UIColor, UIColor?)?, [UIColor], Bool) in let accentColor = state.accentColor var backgroundColors = state.backgroundColors let messagesColors = state.messagesColors @@ -439,12 +439,10 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate suggestedWallpaper = .gradient(Int32(bitPattern: topColor.rgb), Int32(bitPattern: bottomColor.rgb), WallpaperSettings()) wallpaperSignal = gradientImage([topColor, bottomColor], rotation: state.rotation) backgroundColors = (topColor, bottomColor) - singleBackgroundColor = bottomColor case .nightAccent: let color = accentColor.withMultiplied(hue: 1.024, saturation: 0.573, brightness: 0.18) suggestedWallpaper = .color(Int32(bitPattern: color.rgb)) backgroundColors = (color, nil) - singleBackgroundColor = color default: suggestedWallpaper = .builtin(WallpaperSettings()) } @@ -457,7 +455,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate let serviceBackgroundColor = serviceColor(for: (wallpaper, wallpaperImage)) let updatedTheme: PresentationTheme if let themeReference = mode.themeReference { - updatedTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: themeReference, accentColor: accentColor, bubbleColors: messagesColors, backgroundColors: backgroundColors, serviceBackgroundColor: serviceBackgroundColor, preview: true) ?? defaultPresentationTheme + 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 { updatedTheme = customizePresentationTheme(theme, editing: false, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: messagesColors) } else { @@ -468,9 +466,9 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate let patternColors = calcPatternColors(for: state) - return (updatedTheme, (wallpaper, wallpaperImage, wallpaperSignal), serviceBackgroundColor, singleBackgroundColor, patternColors, state.preview) + return (updatedTheme, (wallpaper, wallpaperImage, wallpaperSignal), serviceBackgroundColor, backgroundColors, patternColors, state.preview) } - |> deliverOnMainQueue).start(next: { [weak self] theme, wallpaperImageAndSignal, serviceBackgroundColor, singleBackgroundColor, patternColors, preview in + |> deliverOnMainQueue).start(next: { [weak self] theme, wallpaperImageAndSignal, serviceBackgroundColor, backgroundColors, patternColors, preview in guard let strongSelf = self else { return } @@ -495,13 +493,13 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate strongSelf.immediateBackgroundNode.image = nil strongSelf.immediateBackgroundNode.isHidden = false strongSelf.signalBackgroundNode.isHidden = true - + strongSelf.patternWallpaper = nil } else if let wallpaperImage = wallpaperImage { strongSelf.immediateBackgroundNode.image = wallpaperImage strongSelf.immediateBackgroundNode.isHidden = false strongSelf.signalBackgroundNode.isHidden = true - + strongSelf.patternWallpaper = nil } else if let wallpaperSignal = wallpaperSignal { strongSelf.signalBackgroundNode.contentMode = .scaleToFill @@ -520,7 +518,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate if dispatch { if let _ = strongSelf.patternArgumentsDisposable { } else { - let throttledSignal = strongSelf.patternArgumentsValue.get() + let throttledSignal = strongSelf.patternArgumentsPromise.get() |> mapToThrottled { next -> Signal in return .single(next) |> then(.complete() |> delay(0.016667, queue: Queue.concurrentDefaultQueue())) } @@ -534,7 +532,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate }) } - strongSelf.patternArgumentsValue.set(.single(TransformImageArguments(corners: ImageCorners(), imageSize: layout.size, boundingSize: layout.size, intrinsicInsets: UIEdgeInsets(), custom: patternArguments))) + strongSelf.patternArgumentsPromise.set(.single(TransformImageArguments(corners: ImageCorners(), imageSize: layout.size, boundingSize: layout.size, intrinsicInsets: UIEdgeInsets(), custom: patternArguments))) } else { strongSelf.patternArgumentsDisposable?.dispose() strongSelf.patternArgumentsDisposable = nil @@ -550,8 +548,12 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate } strongSelf.wallpaper = wallpaper strongSelf.patternArguments = patternArguments - strongSelf.currentBackgroundColor = singleBackgroundColor - + + if !preview { + strongSelf.currentBackgroundColors = backgroundColors + strongSelf.patternPanelNode.backgroundColors = backgroundColors + } + if let (layout, navigationBarHeight, messagesBottomInset) = strongSelf.validLayout { strongSelf.updateChatsLayout(layout: layout, topInset: navigationBarHeight, transition: .immediate) strongSelf.updateMessagesLayout(layout: layout, bottomInset: messagesBottomInset, transition: .immediate) @@ -1031,7 +1033,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate @objc private func togglePattern() { let wallpaper = self.state.previousPatternWallpaper ?? self.patternPanelNode.wallpapers.first - let backgroundColor = self.currentBackgroundColor + let backgroundColors = self.currentBackgroundColors var appeared = false self.updateState({ current in @@ -1044,8 +1046,8 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate updated.displayPatternPanel = true if current.patternWallpaper == nil, let wallpaper = wallpaper { updated.patternWallpaper = wallpaper - if updated.backgroundColors == nil, let color = backgroundColor { - updated.backgroundColors = (color, nil) + if updated.backgroundColors == nil { + updated.backgroundColors = backgroundColors } appeared = true } diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAutoNightSettingsController.swift b/submodules/SettingsUI/Sources/Themes/ThemeAutoNightSettingsController.swift index 1e411fc73f..f9ed43dac9 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAutoNightSettingsController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAutoNightSettingsController.swift @@ -523,7 +523,7 @@ public func themeAutoNightSettingsController(context: AccountContext) -> ViewCon } })) }, updateTheme: { theme in - guard let presentationTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: theme, accentColor: nil, bubbleColors: nil, serviceBackgroundColor: .black) else { + guard let presentationTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: theme) else { return } diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift index a8f175e5a1..7fcb29126c 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift @@ -481,7 +481,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The currentTheme = current.automaticThemeSwitchSetting.theme } - guard let theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: currentTheme, accentColor: color?.color, bubbleColors: nil) else { + guard let theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: currentTheme, accentColor: color?.color) else { return current } @@ -559,7 +559,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The }))) } else { items.append(.action(ContextMenuActionItem(text: strings.Theme_Context_ChangeColors, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ApplyTheme"), color: theme.contextMenu.primaryColor) }, action: { c, f in - guard let theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: reference, accentColor: nil, bubbleColors: nil, backgroundColors: nil, preview: false) else { + guard let theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: reference, preview: false) else { return } @@ -725,7 +725,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The return controller?.navigationController as? NavigationController } selectThemeImpl = { theme in - guard let presentationTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: theme, accentColor: nil, bubbleColors: nil, serviceBackgroundColor: .black) else { + guard let presentationTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: theme) else { return } diff --git a/submodules/SettingsUI/Sources/Themes/WallpaperColorPanelNode.swift b/submodules/SettingsUI/Sources/Themes/WallpaperColorPanelNode.swift index eb9c41287b..6cba98b03f 100644 --- a/submodules/SettingsUI/Sources/Themes/WallpaperColorPanelNode.swift +++ b/submodules/SettingsUI/Sources/Themes/WallpaperColorPanelNode.swift @@ -284,7 +284,7 @@ private class ColorInputFieldNode: ASDisplayNode, UITextFieldDelegate { private func updateSelectionLayout(size: CGSize, transition: ContainedViewLayoutTransition) { self.measureNode.attributedText = NSAttributedString(string: self.textFieldNode.textField.text ?? "", font: self.textFieldNode.textField.font) let size = self.measureNode.updateLayout(size) - transition.updateFrame(node: self.selectionNode, frame: CGRect(x: self.textFieldNode.frame.minX, y: 6.0, width: max(45.0, size.width), height: 20.0)) + transition.updateFrame(node: self.selectionNode, frame: CGRect(x: self.textFieldNode.frame.minX, y: 6.0, width: max(0.0, size.width), height: 20.0)) } private func updateSelectionVisibility() { diff --git a/submodules/SettingsUI/Sources/Themes/WallpaperGalleryController.swift b/submodules/SettingsUI/Sources/Themes/WallpaperGalleryController.swift index 0563302b6f..c2607874c9 100644 --- a/submodules/SettingsUI/Sources/Themes/WallpaperGalleryController.swift +++ b/submodules/SettingsUI/Sources/Themes/WallpaperGalleryController.swift @@ -733,7 +733,7 @@ public class WallpaperGalleryController: ViewController { self.overlayNode?.insertSubnode(patternPanelNode, belowSubnode: self.toolbarNode!) } - let panelHeight: CGFloat = 190.0 + let panelHeight: CGFloat = 235.0 var patternPanelFrame = CGRect(x: 0.0, y: layout.size.height, width: layout.size.width, height: panelHeight) if self.patternPanelEnabled { patternPanelFrame.origin = CGPoint(x: 0.0, y: layout.size.height - bottomInset - panelHeight) diff --git a/submodules/SettingsUI/Sources/Themes/WallpaperPatternPanelNode.swift b/submodules/SettingsUI/Sources/Themes/WallpaperPatternPanelNode.swift index d0e7ba4b90..1ae6a7e093 100644 --- a/submodules/SettingsUI/Sources/Themes/WallpaperPatternPanelNode.swift +++ b/submodules/SettingsUI/Sources/Themes/WallpaperPatternPanelNode.swift @@ -40,6 +40,12 @@ final class WallpaperPatternPanelNode: ASDisplayNode { } } + var backgroundColors: (UIColor, UIColor?)? = nil { + didSet { + self.updateWallpapers() + } + } + private var validLayout: CGSize? var patternChanged: ((TelegramWallpaper?, Int32?, Bool) -> Void)? @@ -128,15 +134,17 @@ final class WallpaperPatternPanelNode: ASDisplayNode { node.removeFromSupernode() } + let backgroundColors = self.backgroundColors ?? (UIColor(rgb: 0xd6e2ee), nil) + var selected = true for wallpaper in wallpapers { - let node = SettingsThemeWallpaperNode(overlayBackgroundColor: UIColor(rgb: 0x748698, alpha: 0.4)) + let node = SettingsThemeWallpaperNode(overlayBackgroundColor: self.serviceBackgroundColor.withAlphaComponent(0.4)) node.clipsToBounds = true node.cornerRadius = 5.0 var updatedWallpaper = wallpaper if case let .file(file) = updatedWallpaper { - let settings = WallpaperSettings(blur: false, motion: false, color: 0xd6e2ee, intensity: 100) + let settings = WallpaperSettings(blur: false, motion: false, color: Int32(bitPattern: backgroundColors.0.rgb), bottomColor: backgroundColors.1.flatMap { Int32(bitPattern: $0.rgb) }, intensity: 100) updatedWallpaper = .file(id: file.id, accessHash: file.accessHash, isCreator: file.isCreator, isDefault: file.isDefault, isPattern: file.isPattern, isDark: file.isDark, slug: file.slug, file: file.file, settings: settings) } @@ -193,6 +201,11 @@ final class WallpaperPatternPanelNode: ASDisplayNode { var wallpaper = initialWallpaper ?? self.wallpapers.first if let wallpaper = wallpaper { + var selectedFileId: Int64? + if case let .file(file) = wallpaper { + selectedFileId = file.id + } + self.currentWallpaper = wallpaper self.sliderView?.value = 40.0 @@ -200,7 +213,11 @@ final class WallpaperPatternPanelNode: ASDisplayNode { if let subnodes = self.scrollNode.subnodes { for case let subnode as SettingsThemeWallpaperNode in subnodes { - subnode.setSelected(wallpaper == subnode.wallpaper, animated: false) + var selected = false + if case let .file(file) = subnode.wallpaper, file.id == selectedFileId { + selected = true + } + subnode.setSelected(selected, animated: false) } } diff --git a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift index 794aa65ef4..4a72514c1a 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift @@ -6,7 +6,7 @@ import TelegramUIPreferences public let defaultDarkPresentationTheme = makeDefaultDarkPresentationTheme(preview: false) -public func customizeDefaultDarkPresentationTheme(theme: PresentationTheme, editing: Bool, accentColor: UIColor?, backgroundColors: (UIColor, UIColor?)?, bubbleColors: (UIColor, UIColor?)?) -> PresentationTheme { +public func customizeDefaultDarkPresentationTheme(theme: PresentationTheme, editing: Bool, accentColor: UIColor?, backgroundColors: (UIColor, UIColor?)?, bubbleColors: (UIColor, UIColor?)?, wallpaper forcedWallpaper: TelegramWallpaper? = nil) -> PresentationTheme { if (theme.referenceTheme != .night) { return theme } @@ -80,7 +80,9 @@ public func customizeDefaultDarkPresentationTheme(theme: PresentationTheme, edit } var defaultWallpaper: TelegramWallpaper? - if let backgroundColors = backgroundColors { + if let forcedWallpaper = forcedWallpaper { + defaultWallpaper = forcedWallpaper + } else if let backgroundColors = backgroundColors { if let secondColor = backgroundColors.1 { defaultWallpaper = .gradient(Int32(bitPattern: backgroundColors.0.rgb), Int32(bitPattern: secondColor.rgb), WallpaperSettings()) } else { diff --git a/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift index f36b7344ab..7b11115f77 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift @@ -7,15 +7,7 @@ import TelegramUIPreferences private let defaultDarkTintedAccentColor = UIColor(rgb: 0x2ea6ff) public let defaultDarkTintedPresentationTheme = makeDefaultDarkTintedPresentationTheme(preview: false) -//public func makeDarkAccentPresentationTheme(accentColor: UIColor?, bubbleColors: (UIColor, UIColor?)?, preview: Bool) -> PresentationTheme { -// var accentColor = accentColor ?? defaultDarkAccentColor -// if accentColor == PresentationThemeBaseColor.blue.color { -// accentColor = defaultDarkAccentColor -// } -// return makeDarkPresentationTheme(accentColor: accentColor, bubbleColors: bubbleColors, preview: preview) -//} - -public func customizeDefaultDarkTintedPresentationTheme(theme: PresentationTheme, editing: Bool, accentColor: UIColor?, backgroundColors: (UIColor, UIColor?)?, bubbleColors: (UIColor, UIColor?)?) -> PresentationTheme { +public func customizeDefaultDarkTintedPresentationTheme(theme: PresentationTheme, editing: Bool, accentColor: UIColor?, backgroundColors: (UIColor, UIColor?)?, bubbleColors: (UIColor, UIColor?)?, wallpaper forcedWallpaper: TelegramWallpaper? = nil) -> PresentationTheme { if (theme.referenceTheme != .nightAccent) { return theme } @@ -217,7 +209,9 @@ public func customizeDefaultDarkTintedPresentationTheme(theme: PresentationTheme } var defaultWallpaper: TelegramWallpaper? - if let backgroundColors = backgroundColors { + if let forcedWallpaper = forcedWallpaper { + defaultWallpaper = forcedWallpaper + } else if let backgroundColors = backgroundColors { if let secondColor = backgroundColors.1 { defaultWallpaper = .gradient(Int32(bitPattern: backgroundColors.0.rgb), Int32(bitPattern: secondColor.rgb), WallpaperSettings()) } else { diff --git a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift index 9e62e708a8..366dfa1ca5 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift @@ -8,7 +8,7 @@ public let defaultServiceBackgroundColor = UIColor(rgb: 0x000000, alpha: 0.3) public let defaultPresentationTheme = makeDefaultDayPresentationTheme(serviceBackgroundColor: defaultServiceBackgroundColor, day: false, preview: false) public let defaultDayAccentColor = UIColor(rgb: 0x007ee5) -public func customizeDefaultDayTheme(theme: PresentationTheme, editing: Bool, accentColor: UIColor?, backgroundColors: (UIColor, UIColor?)?, bubbleColors: (UIColor, UIColor?)?, serviceBackgroundColor: UIColor?) -> PresentationTheme { +public func customizeDefaultDayTheme(theme: PresentationTheme, editing: Bool, accentColor: UIColor?, backgroundColors: (UIColor, UIColor?)?, bubbleColors: (UIColor, UIColor?)?, wallpaper forcedWallpaper: TelegramWallpaper? = nil, serviceBackgroundColor: UIColor?) -> PresentationTheme { if (theme.referenceTheme != .day && theme.referenceTheme != .dayClassic) { return theme } @@ -172,7 +172,9 @@ public func customizeDefaultDayTheme(theme: PresentationTheme, editing: Bool, ac } var defaultWallpaper: TelegramWallpaper? - if let backgroundColors = backgroundColors { + if let forcedWallpaper = forcedWallpaper { + defaultWallpaper = forcedWallpaper + } else if let backgroundColors = backgroundColors { if let secondColor = backgroundColors.1 { defaultWallpaper = .gradient(Int32(bitPattern: backgroundColors.0.rgb), Int32(bitPattern: secondColor.rgb), WallpaperSettings()) } else { diff --git a/submodules/TelegramPresentationData/Sources/MakePresentationTheme.swift b/submodules/TelegramPresentationData/Sources/MakePresentationTheme.swift index 2517d0a65b..f176fc1c69 100644 --- a/submodules/TelegramPresentationData/Sources/MakePresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/MakePresentationTheme.swift @@ -1,6 +1,7 @@ import Foundation import UIKit import Postbox +import SyncCore import TelegramUIPreferences public func makeDefaultPresentationTheme(reference: PresentationBuiltinThemeReference, serviceBackgroundColor: UIColor?, preview: Bool = false) -> PresentationTheme { @@ -18,37 +19,37 @@ public func makeDefaultPresentationTheme(reference: PresentationBuiltinThemeRefe return theme } -public func customizePresentationTheme(_ theme: PresentationTheme, editing: Bool, accentColor: UIColor?, backgroundColors: (UIColor, UIColor?)?, bubbleColors: (UIColor, UIColor?)?) -> PresentationTheme { +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 { return theme } switch theme.referenceTheme { case .day, .dayClassic: - return customizeDefaultDayTheme(theme: theme, editing: editing, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors, serviceBackgroundColor: nil) + return customizeDefaultDayTheme(theme: theme, editing: editing, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors, wallpaper: wallpaper, serviceBackgroundColor: nil) case .night: - return customizeDefaultDarkPresentationTheme(theme: theme, editing: editing, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors) + return customizeDefaultDarkPresentationTheme(theme: theme, editing: editing, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors, wallpaper: wallpaper) case .nightAccent: - return customizeDefaultDarkTintedPresentationTheme(theme: theme, editing: editing, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors) + return customizeDefaultDarkTintedPresentationTheme(theme: theme, editing: editing, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors, wallpaper: wallpaper) } return theme } -public func makePresentationTheme(mediaBox: MediaBox, themeReference: PresentationThemeReference, accentColor: UIColor?, bubbleColors: (UIColor, UIColor?)?, backgroundColors: (UIColor, UIColor?)? = nil, serviceBackgroundColor: UIColor? = nil, preview: Bool = false) -> PresentationTheme? { +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? { let theme: PresentationTheme switch themeReference { case let .builtin(reference): let defaultTheme = makeDefaultPresentationTheme(reference: reference, serviceBackgroundColor: serviceBackgroundColor, preview: preview) - theme = customizePresentationTheme(defaultTheme, editing: true, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors) + 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, resolvedWallpaper: info.resolvedWallpaper) { - theme = customizePresentationTheme(loadedTheme, editing: false, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors) + theme = customizePresentationTheme(loadedTheme, editing: false, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors, wallpaper: wallpaper) } else { return nil } case let .cloud(info): if let file = info.theme.file, let path = mediaBox.completedResourcePath(file.resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead), let loadedTheme = makePresentationTheme(data: data, resolvedWallpaper: info.resolvedWallpaper) { - theme = customizePresentationTheme(loadedTheme, editing: false, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors) + theme = customizePresentationTheme(loadedTheme, editing: false, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors, wallpaper: wallpaper) } else { return nil } diff --git a/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift b/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift index 54f92d68ad..5375b2543d 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift @@ -39,6 +39,8 @@ extension TelegramWallpaper: Codable { case "builtin": self = .builtin(WallpaperSettings()) default: + let options = ["motion", "blur"] + if [6,7].contains(value.count), let color = UIColor(hexString: value) { self = .color(Int32(bitPattern: color.rgb)) } else { @@ -52,28 +54,40 @@ extension TelegramWallpaper: Codable { blur = true } - if components.count >= 2 && components.count <= 4 && [6,7].contains(components[0].count) && !["motion", "blur"].contains(components[0]) && [6,7].contains(components[1].count) && !["motion", "blur"].contains(components[1]), let topColor = UIColor(hexString: components[0]), let bottomColor = UIColor(hexString: components[1]) { + if components.count >= 2 && components.count <= 4 && [6,7].contains(components[0].count) && !options.contains(components[0]) && [6,7].contains(components[1].count) && !options.contains(components[1]), let topColor = UIColor(hexString: components[0]), let bottomColor = UIColor(hexString: components[1]) { self = .gradient(Int32(bitPattern: topColor.rgb), Int32(bitPattern: bottomColor.rgb), WallpaperSettings(blur: blur, motion: motion)) } else { var slug: String? var color: Int32? + var bottomColor: Int32? var intensity: Int32? if !components.isEmpty { slug = components[0] } - if components.count > 1, !["motion", "blur"].contains(components[1]), components[1].count == 6, let value = UIColor(hexString: components[1]) { - color = Int32(bitPattern: value.rgb) - } - if components.count > 2, !["motion", "blur"].contains(components[2]), let value = Int32(components[2]) { - if value >= 0 && value <= 100 { - intensity = value - } else { - intensity = 50 + if components.count > 1 { + for i in 1 ..< components.count { + let component = components[i] + if options.contains(component) { + continue + } + if component.count == 6, let value = UIColor(hexString: component) { + if color == nil { + color = Int32(bitPattern: value.rgb) + } else if bottomColor == nil { + bottomColor = Int32(bitPattern: value.rgb) + } + } else if component.count <= 3, let value = Int32(component) { + if value >= 0 && value <= 100 { + intensity = value + } else { + intensity = 50 + } + } } } if let slug = slug { - self = .file(id: 0, accessHash: 0, isCreator: false, isDefault: false, isPattern: color != nil, isDark: false, slug: slug, file: TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], immediateThumbnailData: nil, mimeType: "", size: nil, attributes: []), settings: WallpaperSettings(blur: blur, motion: motion, color: color, intensity: intensity)) + self = .file(id: 0, accessHash: 0, isCreator: false, isDefault: false, isPattern: color != nil, isDark: false, slug: slug, file: TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], immediateThumbnailData: nil, mimeType: "", size: nil, attributes: []), settings: WallpaperSettings(blur: blur, motion: motion, color: color, bottomColor: bottomColor, intensity: intensity)) } else { throw PresentationThemeDecodingError.generic } @@ -113,6 +127,9 @@ extension TelegramWallpaper: Codable { if let intensity = file.settings.intensity { components.append("\(intensity)") } + if let bottomColor = file.settings.bottomColor { + components.append(String(format: "%06x", bottomColor)) + } } if file.settings.motion { components.append("motion") diff --git a/submodules/WallpaperResources/Sources/WallpaperResources.swift b/submodules/WallpaperResources/Sources/WallpaperResources.swift index 1a17a01b25..fd84461012 100644 --- a/submodules/WallpaperResources/Sources/WallpaperResources.swift +++ b/submodules/WallpaperResources/Sources/WallpaperResources.swift @@ -1067,7 +1067,7 @@ public func themeIconImage(account: Account, accountManager: AccountManager, the incomingColor = UIColor(rgb: 0xffffff) if let accentColor = accentColor { if let bubbleColors = bubbleColors { - backgroundColor = UIColor(rgb: 0xffffff) + backgroundColor = UIColor(rgb: 0xd6e2ee) outgoingColor = bubbleColors } else { backgroundColor = accentColor.withMultiplied(hue: 1.019, saturation: 0.867, brightness: 0.965) @@ -1127,7 +1127,7 @@ public func themeIconImage(account: Account, accountManager: AccountManager, the backgroundColor = (.black, nil) case let .file(file): if file.isPattern, let color = file.settings.color { - backgroundColor = (UIColor(rgb: UInt32(bitPattern: color)), nil) + backgroundColor = (UIColor(rgb: UInt32(bitPattern: color)), file.settings.bottomColor.flatMap { UIColor(rgb: UInt32(bitPattern: $0)) }) } else { backgroundColor = (theme.chatList.backgroundColor, nil) }