Theme improvements

This commit is contained in:
Ilya Laktyushin
2019-12-10 21:16:09 +04:00
parent 7d05d1f521
commit 05a3f563e9
11 changed files with 147 additions and 62 deletions

View File

@@ -33,13 +33,25 @@ public final class WallpaperBackgroundNode: ASDisplayNode {
} }
} }
} }
public var image: UIImage? { public var image: UIImage? {
didSet { didSet {
self.contentNode.contents = self.image?.cgImage self.contentNode.contents = self.image?.cgImage
} }
} }
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

View File

@@ -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 {
@@ -236,11 +253,11 @@ final class ThemeAccentColorController: ViewController {
messageColors = (bubbleColors.0, nil) messageColors = (bubbleColors.0, nil)
} }
} else { } else {
messageColors = nil if let themeReference = strongSelf.mode.themeReference, themeReference == .builtin(.dayClassic), settings.themeSpecificAccentColors[themeReference.index] == nil {
} messageColors = (UIColor(rgb: 0xe1ffc7), nil)
} else {
if strongSelf.mode.themeReference == .builtin(.dayClassic) { messageColors = nil
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

View File

@@ -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)
@@ -319,11 +371,13 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
strongSelf.updateMessagesLayout(layout: layout, bottomInset: messagesBottomInset, transition: .immediate) strongSelf.updateMessagesLayout(layout: layout, bottomInset: messagesBottomInset, transition: .immediate)
} }
}) })
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,11 +423,11 @@ 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
let sectionChanged = previousState.section != self.state.section let sectionChanged = previousState.section != self.state.section
if sectionChanged, let section = self.state.section { if sectionChanged, let section = self.state.section {
self.view.endEditing(true) self.view.endEditing(true)
@@ -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)

View File

@@ -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
} }

View File

@@ -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
} }
} }

View File

@@ -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?

View File

@@ -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")
}
} }
} }

View File

@@ -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 {

View File

@@ -2,7 +2,7 @@
"images" : [ "images" : [
{ {
"idiom" : "universal", "idiom" : "universal",
"filename" : "ic_input_change.pdf" "filename" : "ic_gradrotate.pdf"
} }
], ],
"info" : { "info" : {

View File

@@ -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)
} }