mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 14:45:21 +00:00
Theme improvements
This commit is contained in:
@@ -40,6 +40,18 @@ public final class WallpaperBackgroundNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public var rotation: CGFloat = 0.0 {
|
||||||
|
didSet {
|
||||||
|
let transition: ContainedViewLayoutTransition = .animated(duration: 0.3, curve: .easeInOut)
|
||||||
|
var fromValue: CGFloat = 0.0
|
||||||
|
if let value = (self.layer.value(forKeyPath: "transform.rotation.z") as? NSNumber)?.floatValue {
|
||||||
|
fromValue = CGFloat(value)
|
||||||
|
}
|
||||||
|
self.contentNode.layer.transform = CATransform3DMakeRotation(self.rotation, 0.0, 0.0, 1.0)
|
||||||
|
self.contentNode.layer.animateRotation(from: fromValue, to: self.rotation, duration: 0.3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public var imageContentMode: UIView.ContentMode {
|
public var imageContentMode: UIView.ContentMode {
|
||||||
didSet {
|
didSet {
|
||||||
self.contentNode.contentMode = self.imageContentMode
|
self.contentNode.contentMode = self.imageContentMode
|
||||||
|
|||||||
@@ -203,10 +203,13 @@ final class ThemeAccentColorController: ViewController {
|
|||||||
let settings = (sharedData.entries[ApplicationSpecificSharedDataKeys.presentationThemeSettings] as? PresentationThemeSettings) ?? PresentationThemeSettings.defaultSettings
|
let settings = (sharedData.entries[ApplicationSpecificSharedDataKeys.presentationThemeSettings] as? PresentationThemeSettings) ?? PresentationThemeSettings.defaultSettings
|
||||||
|
|
||||||
let accentColor: UIColor
|
let accentColor: UIColor
|
||||||
|
var initialWallpaper: TelegramWallpaper?
|
||||||
let backgroundColors: (UIColor, UIColor?)?
|
let backgroundColors: (UIColor, UIColor?)?
|
||||||
let messageColors: (UIColor, UIColor?)?
|
let messageColors: (UIColor, UIColor?)?
|
||||||
var defaultMessagesColor: UIColor?
|
var defaultMessagesColor: UIColor?
|
||||||
|
|
||||||
|
var ignoreDefaultWallpaper = false
|
||||||
|
|
||||||
if let themeReference = strongSelf.mode.themeReference {
|
if let themeReference = strongSelf.mode.themeReference {
|
||||||
accentColor = settings.themeSpecificAccentColors[themeReference.index]?.color ?? defaultDayAccentColor
|
accentColor = settings.themeSpecificAccentColors[themeReference.index]?.color ?? defaultDayAccentColor
|
||||||
let wallpaper: TelegramWallpaper
|
let wallpaper: TelegramWallpaper
|
||||||
@@ -214,12 +217,24 @@ final class ThemeAccentColorController: ViewController {
|
|||||||
wallpaper = customWallpaper
|
wallpaper = customWallpaper
|
||||||
} else {
|
} 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, bubbleColors: nil) ?? defaultPresentationTheme
|
||||||
|
if case let .builtin(themeName) = themeReference {
|
||||||
|
if case .dayClassic = themeName, settings.themeSpecificAccentColors[themeReference.index] != nil {
|
||||||
|
ignoreDefaultWallpaper = true
|
||||||
|
} else if case .nightAccent = themeName {
|
||||||
|
ignoreDefaultWallpaper = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wallpaper = theme.chat.defaultWallpaper
|
wallpaper = theme.chat.defaultWallpaper
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !wallpaper.isColorOrGradient && !ignoreDefaultWallpaper {
|
||||||
|
initialWallpaper = wallpaper
|
||||||
|
}
|
||||||
|
|
||||||
if let initialBackgroundColor = strongSelf.initialBackgroundColor {
|
if let initialBackgroundColor = strongSelf.initialBackgroundColor {
|
||||||
backgroundColors = (initialBackgroundColor, nil)
|
backgroundColors = (initialBackgroundColor, nil)
|
||||||
} else {
|
} else if !ignoreDefaultWallpaper {
|
||||||
if case let .color(color) = wallpaper {
|
if case let .color(color) = wallpaper {
|
||||||
backgroundColors = (UIColor(rgb: UInt32(bitPattern: color)), nil)
|
backgroundColors = (UIColor(rgb: UInt32(bitPattern: color)), nil)
|
||||||
} else if case let .gradient(topColor, bottomColor, _) = wallpaper {
|
} else if case let .gradient(topColor, bottomColor, _) = wallpaper {
|
||||||
@@ -227,6 +242,8 @@ final class ThemeAccentColorController: ViewController {
|
|||||||
} else {
|
} else {
|
||||||
backgroundColors = nil
|
backgroundColors = nil
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
backgroundColors = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if let bubbleColors = settings.themeSpecificAccentColors[themeReference.index]?.customBubbleColors {
|
if let bubbleColors = settings.themeSpecificAccentColors[themeReference.index]?.customBubbleColors {
|
||||||
@@ -235,12 +252,12 @@ final class ThemeAccentColorController: ViewController {
|
|||||||
} else {
|
} else {
|
||||||
messageColors = (bubbleColors.0, nil)
|
messageColors = (bubbleColors.0, nil)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if let themeReference = strongSelf.mode.themeReference, themeReference == .builtin(.dayClassic), settings.themeSpecificAccentColors[themeReference.index] == nil {
|
||||||
|
messageColors = (UIColor(rgb: 0xe1ffc7), nil)
|
||||||
} else {
|
} else {
|
||||||
messageColors = nil
|
messageColors = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if strongSelf.mode.themeReference == .builtin(.dayClassic) {
|
|
||||||
defaultMessagesColor = UIColor(rgb: 0xe1ffc7)
|
|
||||||
}
|
}
|
||||||
} else if case let .edit(theme, wallpaper, _, _, _) = strongSelf.mode {
|
} else if case let .edit(theme, wallpaper, _, _, _) = strongSelf.mode {
|
||||||
accentColor = theme.rootController.navigationBar.accentTextColor
|
accentColor = theme.rootController.navigationBar.accentTextColor
|
||||||
@@ -265,7 +282,7 @@ final class ThemeAccentColorController: ViewController {
|
|||||||
messageColors = nil
|
messageColors = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
let initialState = ThemeColorState(section: strongSelf.section, accentColor: accentColor, backgroundColors: backgroundColors, defaultMessagesColor: defaultMessagesColor, messagesColors: messageColors)
|
let initialState = ThemeColorState(section: strongSelf.section, accentColor: accentColor, initialWallpaper: initialWallpaper, backgroundColors: backgroundColors, defaultMessagesColor: defaultMessagesColor, messagesColors: messageColors)
|
||||||
|
|
||||||
strongSelf.controllerNode.updateState({ _ in
|
strongSelf.controllerNode.updateState({ _ in
|
||||||
return initialState
|
return initialState
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ import TelegramUIPreferences
|
|||||||
import ChatListUI
|
import ChatListUI
|
||||||
import AccountContext
|
import AccountContext
|
||||||
|
|
||||||
|
private func radiansToDegrees(_ radians: CGFloat) -> CGFloat {
|
||||||
|
return radians * 180.0 / CGFloat.pi
|
||||||
|
}
|
||||||
|
|
||||||
private func generateMaskImage(color: UIColor) -> UIImage? {
|
private func generateMaskImage(color: UIColor) -> UIImage? {
|
||||||
return generateImage(CGSize(width: 1.0, height: 80.0), opaque: false, rotatedContext: { size, context in
|
return generateImage(CGSize(width: 1.0, height: 80.0), opaque: false, rotatedContext: { size, context in
|
||||||
let bounds = CGRect(origin: CGPoint(), size: size)
|
let bounds = CGRect(origin: CGPoint(), size: size)
|
||||||
@@ -36,25 +40,31 @@ struct ThemeColorState {
|
|||||||
fileprivate var section: ThemeColorSection?
|
fileprivate var section: ThemeColorSection?
|
||||||
fileprivate var colorPanelCollapsed: Bool
|
fileprivate var colorPanelCollapsed: Bool
|
||||||
var accentColor: UIColor
|
var accentColor: UIColor
|
||||||
|
var initialWallpaper: TelegramWallpaper?
|
||||||
var backgroundColors: (UIColor, UIColor?)?
|
var backgroundColors: (UIColor, UIColor?)?
|
||||||
var defaultMessagesColor: UIColor?
|
var defaultMessagesColor: UIColor?
|
||||||
var messagesColors: (UIColor, UIColor?)?
|
var messagesColors: (UIColor, UIColor?)?
|
||||||
|
var rotation: CGFloat
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
self.section = nil
|
self.section = nil
|
||||||
self.colorPanelCollapsed = false
|
self.colorPanelCollapsed = false
|
||||||
self.accentColor = .clear
|
self.accentColor = .clear
|
||||||
|
self.initialWallpaper = nil
|
||||||
self.backgroundColors = nil
|
self.backgroundColors = nil
|
||||||
self.messagesColors = nil
|
self.messagesColors = nil
|
||||||
|
self.rotation = 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
init(section: ThemeColorSection, accentColor: UIColor, backgroundColors: (UIColor, UIColor?)?, defaultMessagesColor: UIColor?, messagesColors: (UIColor, UIColor?)?) {
|
init(section: ThemeColorSection, accentColor: UIColor, initialWallpaper: TelegramWallpaper?, backgroundColors: (UIColor, UIColor?)?, defaultMessagesColor: UIColor?, messagesColors: (UIColor, UIColor?)?, rotation: CGFloat = 0.0) {
|
||||||
self.section = section
|
self.section = section
|
||||||
self.colorPanelCollapsed = false
|
self.colorPanelCollapsed = false
|
||||||
self.accentColor = accentColor
|
self.accentColor = accentColor
|
||||||
|
self.initialWallpaper = initialWallpaper
|
||||||
self.backgroundColors = backgroundColors
|
self.backgroundColors = backgroundColors
|
||||||
self.defaultMessagesColor = defaultMessagesColor
|
self.defaultMessagesColor = defaultMessagesColor
|
||||||
self.messagesColors = messagesColors
|
self.messagesColors = messagesColors
|
||||||
|
self.rotation = rotation
|
||||||
}
|
}
|
||||||
|
|
||||||
func areColorsEqual(to otherState: ThemeColorState) -> Bool {
|
func areColorsEqual(to otherState: ThemeColorState) -> Bool {
|
||||||
@@ -117,10 +127,11 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
|||||||
|
|
||||||
private var serviceColorDisposable: Disposable?
|
private var serviceColorDisposable: Disposable?
|
||||||
private var colorsDisposable: Disposable?
|
private var colorsDisposable: Disposable?
|
||||||
private let colors = Promise<(UIColor, (UIColor, UIColor?)?, (UIColor, UIColor?)?)>()
|
private let colors = Promise<(UIColor, (UIColor, UIColor?)?, (UIColor, UIColor?)?, TelegramWallpaper?, CGFloat)>()
|
||||||
private let themePromise = Promise<PresentationTheme>()
|
private let themePromise = Promise<PresentationTheme>()
|
||||||
private var wallpaper: TelegramWallpaper
|
private var wallpaper: TelegramWallpaper
|
||||||
private var serviceBackgroundColor: UIColor?
|
private var serviceBackgroundColor: UIColor?
|
||||||
|
private let serviceBackgroundColorPromise = Promise<UIColor>()
|
||||||
|
|
||||||
private var tapGestureRecognizer: UITapGestureRecognizer?
|
private var tapGestureRecognizer: UITapGestureRecognizer?
|
||||||
|
|
||||||
@@ -129,14 +140,18 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
|||||||
private var validLayout: (ContainerViewLayout, CGFloat, CGFloat)?
|
private var validLayout: (ContainerViewLayout, CGFloat, CGFloat)?
|
||||||
|
|
||||||
var requiresWallpaperChange: Bool {
|
var requiresWallpaperChange: Bool {
|
||||||
return self.state.backgroundColors == nil && self.chatBackgroundNode.image != nil
|
switch self.wallpaper {
|
||||||
|
case .image, .file:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init(context: AccountContext, mode: ThemeAccentColorControllerMode, theme: PresentationTheme, wallpaper: TelegramWallpaper, dismiss: @escaping () -> Void, apply: @escaping (ThemeColorState, UIColor?) -> Void) {
|
init(context: AccountContext, mode: ThemeAccentColorControllerMode, theme: PresentationTheme, wallpaper: TelegramWallpaper, dismiss: @escaping () -> Void, apply: @escaping (ThemeColorState, UIColor?) -> Void) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
self.state = ThemeColorState()
|
self.state = ThemeColorState()
|
||||||
|
|
||||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
self.wallpaper = self.presentationData.chatWallpaper
|
self.wallpaper = self.presentationData.chatWallpaper
|
||||||
@@ -223,6 +238,8 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
|||||||
var updated = current
|
var updated = current
|
||||||
if let firstColor = firstColor {
|
if let firstColor = firstColor {
|
||||||
updated.backgroundColors = (firstColor, secondColor)
|
updated.backgroundColors = (firstColor, secondColor)
|
||||||
|
} else {
|
||||||
|
updated.backgroundColors = nil
|
||||||
}
|
}
|
||||||
return updated
|
return updated
|
||||||
})
|
})
|
||||||
@@ -250,6 +267,20 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.colorPanelNode.rotate = { [weak self] in
|
||||||
|
if let strongSelf = self {
|
||||||
|
strongSelf.updateState({ current in
|
||||||
|
var updated = current
|
||||||
|
var newRotation = updated.rotation + CGFloat.pi / 4.0
|
||||||
|
if newRotation >= CGFloat.pi * 2.0 {
|
||||||
|
newRotation = 0.0
|
||||||
|
}
|
||||||
|
updated.rotation = newRotation
|
||||||
|
return updated
|
||||||
|
}, animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.toolbarNode.cancel = {
|
self.toolbarNode.cancel = {
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
@@ -261,22 +292,42 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
|||||||
|
|
||||||
self.colorsDisposable = (self.colors.get()
|
self.colorsDisposable = (self.colors.get()
|
||||||
|> deliverOn(Queue.concurrentDefaultQueue())
|
|> deliverOn(Queue.concurrentDefaultQueue())
|
||||||
|> map { accentColor, backgroundColors, messagesColors -> (PresentationTheme, (TelegramWallpaper, UIImage?), UIColor) in
|
|> map { accentColor, backgroundColors, messagesColors, initialWallpaper, rotation -> (PresentationTheme, (TelegramWallpaper, UIImage?), UIColor) in
|
||||||
var wallpaper = context.sharedContext.currentPresentationData.with { $0 }.chatWallpaper
|
var wallpaper: TelegramWallpaper
|
||||||
var wallpaperImage: UIImage?
|
var wallpaperImage: UIImage?
|
||||||
|
var backgroundColors = backgroundColors
|
||||||
if let backgroundColors = backgroundColors {
|
if let backgroundColors = backgroundColors {
|
||||||
if let bottomColor = backgroundColors.1 {
|
if let bottomColor = backgroundColors.1 {
|
||||||
wallpaper = .gradient(Int32(bitPattern: backgroundColors.0.rgb), Int32(bitPattern: bottomColor.rgb), WallpaperSettings())
|
wallpaper = .gradient(Int32(bitPattern: backgroundColors.0.rgb), Int32(bitPattern: bottomColor.rgb), WallpaperSettings(rotation: Int32(radiansToDegrees(rotation))))
|
||||||
wallpaperImage = chatControllerBackgroundImage(theme: nil, wallpaper: wallpaper, mediaBox: context.sharedContext.accountManager.mediaBox, knockoutMode: false)
|
wallpaperImage = chatControllerBackgroundImage(theme: nil, wallpaper: wallpaper, mediaBox: context.sharedContext.accountManager.mediaBox, knockoutMode: false)
|
||||||
} else {
|
} else {
|
||||||
wallpaper = .color(Int32(bitPattern: backgroundColors.0.rgb))
|
wallpaper = .color(Int32(bitPattern: backgroundColors.0.rgb))
|
||||||
}
|
}
|
||||||
|
} else if let themeReference = mode.themeReference, case let .builtin(theme) = themeReference, initialWallpaper == nil {
|
||||||
|
var suggestedWallpaper: TelegramWallpaper
|
||||||
|
switch theme {
|
||||||
|
case .dayClassic:
|
||||||
|
let topColor = accentColor.withMultiplied(hue: 1.010, saturation: 0.414, brightness: 0.957)
|
||||||
|
let bottomColor = accentColor.withMultiplied(hue: 1.019, saturation: 0.867, brightness: 0.965)
|
||||||
|
suggestedWallpaper = .gradient(Int32(bitPattern: topColor.rgb), Int32(bitPattern: bottomColor.rgb), WallpaperSettings())
|
||||||
|
backgroundColors = (topColor, 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)
|
||||||
|
default:
|
||||||
|
suggestedWallpaper = .builtin(WallpaperSettings())
|
||||||
|
}
|
||||||
|
wallpaperImage = chatControllerBackgroundImage(theme: nil, wallpaper: suggestedWallpaper, mediaBox: context.sharedContext.accountManager.mediaBox, knockoutMode: false)
|
||||||
|
wallpaper = suggestedWallpaper
|
||||||
|
} else {
|
||||||
|
wallpaper = initialWallpaper ?? .builtin(WallpaperSettings())
|
||||||
}
|
}
|
||||||
|
|
||||||
let serviceBackgroundColor = serviceColor(for: (wallpaper, wallpaperImage))
|
let serviceBackgroundColor = serviceColor(for: (wallpaper, wallpaperImage))
|
||||||
let updatedTheme: PresentationTheme
|
let updatedTheme: PresentationTheme
|
||||||
if let themeReference = mode.themeReference {
|
if let themeReference = mode.themeReference {
|
||||||
updatedTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: themeReference, accentColor: accentColor, bubbleColors: messagesColors, serviceBackgroundColor: serviceBackgroundColor, preview: true) ?? defaultPresentationTheme
|
updatedTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: themeReference, accentColor: accentColor, bubbleColors: messagesColors, backgroundColors: backgroundColors, serviceBackgroundColor: serviceBackgroundColor, preview: true) ?? defaultPresentationTheme
|
||||||
} else if case let .edit(theme, _, _, _, _) = mode {
|
} else if case let .edit(theme, _, _, _, _) = mode {
|
||||||
updatedTheme = customizePresentationTheme(theme, editing: false, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: messagesColors)
|
updatedTheme = customizePresentationTheme(theme, editing: false, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: messagesColors)
|
||||||
} else {
|
} else {
|
||||||
@@ -297,6 +348,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
|||||||
strongSelf.themeUpdated?(theme)
|
strongSelf.themeUpdated?(theme)
|
||||||
strongSelf.themePromise.set(.single(theme))
|
strongSelf.themePromise.set(.single(theme))
|
||||||
strongSelf.serviceBackgroundColor = serviceBackgroundColor
|
strongSelf.serviceBackgroundColor = serviceBackgroundColor
|
||||||
|
strongSelf.serviceBackgroundColorPromise.set(.single(serviceBackgroundColor))
|
||||||
|
|
||||||
strongSelf.colorPanelNode.updateTheme(theme)
|
strongSelf.colorPanelNode.updateTheme(theme)
|
||||||
strongSelf.toolbarNode.updateThemeAndStrings(theme: theme, strings: strongSelf.presentationData.strings)
|
strongSelf.toolbarNode.updateThemeAndStrings(theme: theme, strings: strongSelf.presentationData.strings)
|
||||||
@@ -320,10 +372,12 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
self.serviceColorDisposable = (self.themePromise.get()
|
self.serviceColorDisposable = (((self.themePromise.get()
|
||||||
|> mapToSignal { theme -> Signal<UIColor, NoError> in
|
|> mapToSignal { theme -> Signal<UIColor, NoError> in
|
||||||
return chatServiceBackgroundColor(wallpaper: wallpaper, mediaBox: context.account.postbox.mediaBox)
|
return chatServiceBackgroundColor(wallpaper: wallpaper, mediaBox: context.account.postbox.mediaBox)
|
||||||
}
|
})
|
||||||
|
|> take(1)
|
||||||
|
|> then(self.serviceBackgroundColorPromise.get()))
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] color in
|
|> deliverOnMainQueue).start(next: { [weak self] color in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.pageControlBackgroundNode.backgroundColor = color
|
strongSelf.pageControlBackgroundNode.backgroundColor = color
|
||||||
@@ -369,7 +423,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
|||||||
|
|
||||||
let colorsChanged = !previousState.areColorsEqual(to: self.state)
|
let colorsChanged = !previousState.areColorsEqual(to: self.state)
|
||||||
if colorsChanged {
|
if colorsChanged {
|
||||||
self.colors.set(.single((self.state.accentColor, self.state.backgroundColors, self.state.messagesColors)))
|
self.colors.set(.single((self.state.accentColor, self.state.backgroundColors, self.state.messagesColors, self.state.initialWallpaper, self.state.rotation)))
|
||||||
}
|
}
|
||||||
|
|
||||||
let colorPanelCollapsed = self.state.colorPanelCollapsed
|
let colorPanelCollapsed = self.state.colorPanelCollapsed
|
||||||
@@ -386,18 +440,28 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
|||||||
firstColor = self.state.accentColor ?? .blue
|
firstColor = self.state.accentColor ?? .blue
|
||||||
secondColor = nil
|
secondColor = nil
|
||||||
case .background:
|
case .background:
|
||||||
|
if let themeReference = self.mode.themeReference, case let .builtin(theme) = themeReference {
|
||||||
|
switch theme {
|
||||||
|
case .dayClassic:
|
||||||
|
defaultColor = self.state.accentColor.withMultiplied(hue: 1.019, saturation: 0.867, brightness: 0.965)
|
||||||
|
case .nightAccent:
|
||||||
|
defaultColor = self.state.accentColor.withMultiplied(hue: 1.024, saturation: 0.573, brightness: 0.18)
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
if let backgroundColors = self.state.backgroundColors {
|
if let backgroundColors = self.state.backgroundColors {
|
||||||
firstColor = backgroundColors.0
|
firstColor = backgroundColors.0
|
||||||
secondColor = backgroundColors.1
|
secondColor = backgroundColors.1
|
||||||
} else if let image = self.chatBackgroundNode.image {
|
} else if let image = self.chatBackgroundNode.image, previousState.initialWallpaper != nil {
|
||||||
firstColor = averageColor(from: image)
|
firstColor = averageColor(from: image)
|
||||||
secondColor = nil
|
secondColor = nil
|
||||||
} else {
|
} else {
|
||||||
firstColor = .white
|
firstColor = nil
|
||||||
secondColor = nil
|
secondColor = nil
|
||||||
}
|
}
|
||||||
case .messages:
|
case .messages:
|
||||||
defaultColor = self.state.defaultMessagesColor ?? (self.state.accentColor ?? UIColor(rgb: 0x007e55))
|
defaultColor = self.state.defaultMessagesColor ?? (self.state.accentColor ?? UIColor(rgb: 0x007ee5))
|
||||||
if let messagesColors = self.state.messagesColors {
|
if let messagesColors = self.state.messagesColors {
|
||||||
firstColor = messagesColors.0
|
firstColor = messagesColors.0
|
||||||
secondColor = messagesColors.1
|
secondColor = messagesColors.1
|
||||||
@@ -434,6 +498,9 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
|||||||
func updateSection(_ section: ThemeColorSection) {
|
func updateSection(_ section: ThemeColorSection) {
|
||||||
self.updateState({ current in
|
self.updateState({ current in
|
||||||
var updated = current
|
var updated = current
|
||||||
|
if section == .background {
|
||||||
|
updated.initialWallpaper = nil
|
||||||
|
}
|
||||||
updated.section = section
|
updated.section = section
|
||||||
return updated
|
return updated
|
||||||
}, animated: true)
|
}, animated: true)
|
||||||
|
|||||||
@@ -33,26 +33,7 @@ private func generateSwatchImage(theme: PresentationTheme, color: PresentationTh
|
|||||||
context.setLineWidth(2.0)
|
context.setLineWidth(2.0)
|
||||||
|
|
||||||
if selected {
|
if selected {
|
||||||
context.saveGState()
|
context.fillEllipse(in: bounds.insetBy(dx: 4.0, dy: 4.0))
|
||||||
context.addEllipse(in: bounds.insetBy(dx: 4.0, dy: 4.0))
|
|
||||||
context.clip()
|
|
||||||
|
|
||||||
if let colors = bubbles {
|
|
||||||
var colors: (UIColor, UIColor) = (colors.0, colors.1 ?? colors.0)
|
|
||||||
|
|
||||||
let gradientColors = [colors.0.cgColor, colors.1.cgColor] as CFArray
|
|
||||||
var locations: [CGFloat] = [0.0, 1.0]
|
|
||||||
let colorSpace = CGColorSpaceCreateDeviceRGB()
|
|
||||||
let gradient = CGGradient(colorsSpace: colorSpace, colors: gradientColors, locations: &locations)!
|
|
||||||
|
|
||||||
context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions())
|
|
||||||
|
|
||||||
context.fill(CGRect(x: 0.0, y: 0.0, width: size.width / 2.0, height: size.height))
|
|
||||||
} else {
|
|
||||||
context.fill(bounds)
|
|
||||||
}
|
|
||||||
|
|
||||||
context.restoreGState()
|
|
||||||
context.strokeEllipse(in: bounds.insetBy(dx: 1.0, dy: 1.0))
|
context.strokeEllipse(in: bounds.insetBy(dx: 1.0, dy: 1.0))
|
||||||
|
|
||||||
if more {
|
if more {
|
||||||
@@ -63,8 +44,10 @@ private func generateSwatchImage(theme: PresentationTheme, color: PresentationTh
|
|||||||
context.fillEllipse(in: CGRect(origin: CGPoint(x: 25.0, y: 18.0), size: dotSize))
|
context.fillEllipse(in: CGRect(origin: CGPoint(x: 25.0, y: 18.0), size: dotSize))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
context.fillEllipse(in: bounds)
|
||||||
|
|
||||||
context.saveGState()
|
context.saveGState()
|
||||||
context.addEllipse(in: bounds)
|
context.addEllipse(in: bounds.insetBy(dx: 10.0, dy: 10.0))
|
||||||
context.clip()
|
context.clip()
|
||||||
|
|
||||||
if let colors = bubbles {
|
if let colors = bubbles {
|
||||||
@@ -75,11 +58,7 @@ private func generateSwatchImage(theme: PresentationTheme, color: PresentationTh
|
|||||||
let colorSpace = CGColorSpaceCreateDeviceRGB()
|
let colorSpace = CGColorSpaceCreateDeviceRGB()
|
||||||
let gradient = CGGradient(colorsSpace: colorSpace, colors: gradientColors, locations: &locations)!
|
let gradient = CGGradient(colorsSpace: colorSpace, colors: gradientColors, locations: &locations)!
|
||||||
|
|
||||||
context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions())
|
context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 10.0), end: CGPoint(x: 0.0, y: size.height - 10.0), options: CGGradientDrawingOptions())
|
||||||
|
|
||||||
context.fill(CGRect(x: 0.0, y: 0.0, width: size.width / 2.0, height: size.height))
|
|
||||||
} else {
|
|
||||||
context.fill(bounds)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
context.restoreGState()
|
context.restoreGState()
|
||||||
@@ -362,6 +341,9 @@ class ThemeSettingsAccentColorItemNode: ListViewItemNode, ItemListItemNode {
|
|||||||
var updated = false
|
var updated = false
|
||||||
var selectedNode: ThemeSettingsAccentColorNode?
|
var selectedNode: ThemeSettingsAccentColorNode?
|
||||||
|
|
||||||
|
strongSelf.customNode.frame = CGRect(origin: CGPoint(x: nodeOffset, y: 9.0), size: CGSize(width: 42.0, height: 42.0))
|
||||||
|
nodeOffset += nodeSize.width + 18.0
|
||||||
|
|
||||||
var i = 0
|
var i = 0
|
||||||
for color in item.colors {
|
for color in item.colors {
|
||||||
let imageNode: ThemeSettingsAccentColorNode
|
let imageNode: ThemeSettingsAccentColorNode
|
||||||
@@ -395,11 +377,9 @@ class ThemeSettingsAccentColorItemNode: ListViewItemNode, ItemListItemNode {
|
|||||||
selectedNode = imageNode
|
selectedNode = imageNode
|
||||||
}
|
}
|
||||||
|
|
||||||
imageNode.setup(theme: item.theme, color: accentColor, bubbles: accentColor.customBubbleColors, selected: selected, more: itemColor != nil, action: { [weak self, weak imageNode] in
|
imageNode.setup(theme: item.theme, color: accentColor, bubbles: accentColor.customBubbleColors, selected: selected, more: true, action: { [weak self, weak imageNode] in
|
||||||
if selected {
|
if selected {
|
||||||
if itemColor != nil {
|
|
||||||
item.openColorPicker()
|
item.openColorPicker()
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
item.updated(itemColor)
|
item.updated(itemColor)
|
||||||
}
|
}
|
||||||
@@ -414,7 +394,7 @@ class ThemeSettingsAccentColorItemNode: ListViewItemNode, ItemListItemNode {
|
|||||||
i += 1
|
i += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
strongSelf.customNode.frame = CGRect(origin: CGPoint(x: nodeOffset, y: 9.0), size: CGSize(width: 42.0, height: 42.0))
|
// strongSelf.customNode.frame = CGRect(origin: CGPoint(x: nodeOffset, y: 9.0), size: CGSize(width: 42.0, height: 42.0))
|
||||||
|
|
||||||
for k in (i ..< strongSelf.colorNodes.count).reversed() {
|
for k in (i ..< strongSelf.colorNodes.count).reversed() {
|
||||||
let node = strongSelf.colorNodes[k]
|
let node = strongSelf.colorNodes[k]
|
||||||
@@ -422,7 +402,7 @@ class ThemeSettingsAccentColorItemNode: ListViewItemNode, ItemListItemNode {
|
|||||||
node.removeFromSupernode()
|
node.removeFromSupernode()
|
||||||
}
|
}
|
||||||
|
|
||||||
let contentSize = CGSize(width: strongSelf.customNode.frame.maxX + nodeInset, height: strongSelf.scrollNode.frame.height)
|
let contentSize = CGSize(width: strongSelf.colorNodes.last!.frame.maxX + nodeInset, height: strongSelf.scrollNode.frame.height)
|
||||||
if strongSelf.scrollNode.view.contentSize != contentSize {
|
if strongSelf.scrollNode.view.contentSize != contentSize {
|
||||||
strongSelf.scrollNode.view.contentSize = contentSize
|
strongSelf.scrollNode.view.contentSize = contentSize
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -486,7 +486,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
|
|||||||
themeSpecificAccentColors[currentTheme.index] = color
|
themeSpecificAccentColors[currentTheme.index] = color
|
||||||
|
|
||||||
if case let .builtin(theme) = currentTheme, theme == .dayClassic || theme == .nightAccent {
|
if case let .builtin(theme) = currentTheme, theme == .dayClassic || theme == .nightAccent {
|
||||||
if let wallpaper = current.themeSpecificChatWallpapers[currentTheme.index], wallpaper.isColorOrGradient {
|
if let wallpaper = current.themeSpecificChatWallpapers[currentTheme.index], wallpaper.isColorOrGradient || wallpaper.isBuiltin {
|
||||||
themeSpecificChatWallpapers[currentTheme.index] = nil
|
themeSpecificChatWallpapers[currentTheme.index] = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -344,6 +344,7 @@ final class WallpaperColorPanelNode: ASDisplayNode {
|
|||||||
|
|
||||||
var colorsChanged: ((UIColor?, UIColor?, Bool) -> Void)?
|
var colorsChanged: ((UIColor?, UIColor?, Bool) -> Void)?
|
||||||
var colorSelected: (() -> Void)?
|
var colorSelected: (() -> Void)?
|
||||||
|
var rotate: (() -> Void)?
|
||||||
|
|
||||||
private var validLayout: CGSize?
|
private var validLayout: CGSize?
|
||||||
|
|
||||||
|
|||||||
@@ -5,12 +5,14 @@ public struct WallpaperSettings: PostboxCoding, Equatable {
|
|||||||
public let motion: Bool
|
public let motion: Bool
|
||||||
public let color: Int32?
|
public let color: Int32?
|
||||||
public let intensity: Int32?
|
public let intensity: Int32?
|
||||||
|
public let rotation: Int32?
|
||||||
|
|
||||||
public init(blur: Bool = false, motion: Bool = false, color: Int32? = nil, intensity: Int32? = nil) {
|
public init(blur: Bool = false, motion: Bool = false, color: Int32? = nil, intensity: Int32? = nil, rotation: Int32? = nil) {
|
||||||
self.blur = blur
|
self.blur = blur
|
||||||
self.motion = motion
|
self.motion = motion
|
||||||
self.color = color
|
self.color = color
|
||||||
self.intensity = intensity
|
self.intensity = intensity
|
||||||
|
self.rotation = rotation
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(decoder: PostboxDecoder) {
|
public init(decoder: PostboxDecoder) {
|
||||||
@@ -18,6 +20,7 @@ public struct WallpaperSettings: PostboxCoding, Equatable {
|
|||||||
self.motion = decoder.decodeInt32ForKey("m", orElse: 0) != 0
|
self.motion = decoder.decodeInt32ForKey("m", orElse: 0) != 0
|
||||||
self.color = decoder.decodeOptionalInt32ForKey("c")
|
self.color = decoder.decodeOptionalInt32ForKey("c")
|
||||||
self.intensity = decoder.decodeOptionalInt32ForKey("i")
|
self.intensity = decoder.decodeOptionalInt32ForKey("i")
|
||||||
|
self.rotation = decoder.decodeOptionalInt32ForKey("r")
|
||||||
}
|
}
|
||||||
|
|
||||||
public func encode(_ encoder: PostboxEncoder) {
|
public func encode(_ encoder: PostboxEncoder) {
|
||||||
@@ -33,6 +36,11 @@ public struct WallpaperSettings: PostboxCoding, Equatable {
|
|||||||
} else {
|
} else {
|
||||||
encoder.encodeNil(forKey: "i")
|
encoder.encodeNil(forKey: "i")
|
||||||
}
|
}
|
||||||
|
if let rotation = self.rotation {
|
||||||
|
encoder.encodeInt32(rotation, forKey: "r")
|
||||||
|
} else {
|
||||||
|
encoder.encodeNil(forKey: "r")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public func customizeDefaultDayTheme(theme: PresentationTheme, editing: Bool, ac
|
|||||||
} else {
|
} else {
|
||||||
if let accentColor = accentColor {
|
if let accentColor = accentColor {
|
||||||
let hsb = accentColor.hsb
|
let hsb = accentColor.hsb
|
||||||
bubbleColors = (UIColor(hue: hsb.0, saturation: hsb.2 > 0.0 ? 0.14 : 0.0, brightness: 0.79 + hsb.2 * 0.21, alpha: 1.0), nil)
|
bubbleColors = (UIColor(hue: hsb.0, saturation: (hsb.1 > 0.0 && hsb.2 > 0.0) ? 0.14 : 0.0, brightness: 0.79 + hsb.2 * 0.21, alpha: 1.0), nil)
|
||||||
if accentColor.lightness > 0.705 {
|
if accentColor.lightness > 0.705 {
|
||||||
outgoingAccent = UIColor(hue: hsb.0, saturation: min(1.0, hsb.1 * 1.1), brightness: min(hsb.2, 0.6), alpha: 1.0)
|
outgoingAccent = UIColor(hue: hsb.0, saturation: min(1.0, hsb.1 * 1.1), brightness: min(hsb.2, 0.6), alpha: 1.0)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"filename" : "ic_input_change.pdf"
|
"filename" : "ic_gradrotate.pdf"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
Binary file not shown.
@@ -53,11 +53,11 @@ final class WebSearchNavigationContentNode: NavigationBarContentNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override var nominalHeight: CGFloat {
|
override var nominalHeight: CGFloat {
|
||||||
return 54.0
|
return 56.0
|
||||||
}
|
}
|
||||||
|
|
||||||
override func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) {
|
override func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||||
let searchBarFrame = CGRect(origin: CGPoint(x: 0.0, y: size.height - self.nominalHeight), size: CGSize(width: size.width, height: 54.0))
|
let searchBarFrame = CGRect(origin: CGPoint(x: 0.0, y: size.height - self.nominalHeight), size: CGSize(width: size.width, height: 56.0))
|
||||||
self.searchBar.frame = searchBarFrame
|
self.searchBar.frame = searchBarFrame
|
||||||
self.searchBar.updateLayout(boundingSize: searchBarFrame.size, leftInset: leftInset, rightInset: rightInset, transition: transition)
|
self.searchBar.updateLayout(boundingSize: searchBarFrame.size, leftInset: leftInset, rightInset: rightInset, transition: transition)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user