Swiftgram/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift
2023-04-17 20:21:14 +04:00

2125 lines
100 KiB
Swift

import Foundation
import UIKit
import TelegramCore
import TelegramUIPreferences
private func decodeColor<Key>(_ values: KeyedDecodingContainer<Key>, _ key: Key, decoder: Decoder? = nil, fallbackKey: String? = nil) throws -> UIColor {
if let decoder = decoder as? PresentationThemeDecoding, let fallbackKey = fallbackKey {
var codingPath = decoder.codingPath.map { $0.stringValue }
codingPath.append(key.stringValue)
let key = codingPath.joined(separator: ".")
decoder.fallbackKeys[key] = fallbackKey
}
let value = try values.decode(String.self, forKey: key)
if value.lowercased() == "clear" {
return UIColor.clear
} else if let color = UIColor(hexString: value) {
return color
} else {
throw PresentationThemeDecodingError.generic
}
}
private func encodeColor<Key>(_ values: inout KeyedEncodingContainer<Key>, _ value: UIColor, _ key: Key) throws {
if value == UIColor.clear {
try values.encode("clear", forKey: key)
} else if value.alpha < 1.0 {
try values.encode(String(format: "%08x", value.argb), forKey: key)
} else {
try values.encode(String(format: "%06x", value.rgb), forKey: key)
}
}
private func decodeColorList<Key>(_ values: KeyedDecodingContainer<Key>, _ key: Key) throws -> [UIColor] {
let colorValues = try values.decode([String].self, forKey: key)
var result: [UIColor] = []
for value in colorValues {
if value.lowercased() == "clear" {
result.append(UIColor.clear)
} else if let color = UIColor(hexString: value) {
result.append(color)
} else {
throw PresentationThemeDecodingError.generic
}
}
return result
}
private func encodeColorList<Key>(_ values: inout KeyedEncodingContainer<Key>, _ colors: [UIColor], _ key: Key) throws {
var stringList: [String] = []
for value in colors {
if value == UIColor.clear {
stringList.append("clear")
} else if value.alpha < 1.0 {
stringList.append(String(format: "%08x", value.argb))
} else {
stringList.append(String(format: "%06x", value.rgb))
}
}
try values.encode(stringList, forKey: key)
}
struct TelegramWallpaperStandardizedCodable: Codable {
let value: TelegramWallpaper
init(_ value: TelegramWallpaper) {
self.value = value
}
init(from decoder: Decoder) throws {
let values = try decoder.singleValueContainer()
if let value = try? values.decode(String.self) {
switch value.lowercased() {
case "builtin":
self.value = .builtin(WallpaperSettings())
default:
let optionKeys = ["motion", "blur"]
if [6, 8].contains(value.count), let color = UIColor(hexString: value) {
self.value = .color(color.argb)
} else {
let components = value.components(separatedBy: " ")
var blur = false
var motion = false
if components.contains("motion") {
motion = true
}
if components.contains("blur") {
blur = true
}
var slug: String?
var colors: [UIColor] = []
var intensity: Int32?
var rotation: Int32?
for i in 0 ..< components.count {
let component = components[i]
if optionKeys.contains(component) {
continue
}
if i == 0 && component.count > 8 {
slug = component
} else if [6, 8].contains(component.count), let color = UIColor(hexString: component) {
colors.append(color)
} else if component.count <= 4, let value = Int32(component) {
if intensity == nil {
if value >= -100 && value <= 100 {
intensity = value
} else {
intensity = 50
}
} else if rotation == nil {
if value >= 0 && value < 360 {
rotation = value
}
}
}
}
if let slug = slug {
self.value = .file(TelegramWallpaper.File(id: 0, accessHash: 0, isCreator: false, isDefault: false, isPattern: !colors.isEmpty, isDark: false, slug: slug, file: TelegramMediaFile(fileId: EngineMedia.Id(namespace: 0, id: 0), partialReference: nil, resource: WallpaperDataResource(slug: slug), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "", size: nil, attributes: []), settings: WallpaperSettings(blur: blur, motion: motion, colors: colors.map { $0.argb }, intensity: intensity, rotation: rotation)))
} else if colors.count > 1 {
self.value = .gradient(TelegramWallpaper.Gradient(id: nil, colors: colors.map { $0.argb }, settings: WallpaperSettings(blur: blur, motion: motion, rotation: rotation)))
} else {
throw PresentationThemeDecodingError.generic
}
}
}
} else {
throw PresentationThemeDecodingError.generic
}
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self.value {
case .builtin:
try container.encode("builtin")
case let .color(color):
try container.encode(String(format: "%06x", color))
case let .gradient(gradient):
var components: [String] = []
for color in gradient.colors {
components.append(String(format: "%06x", color))
}
if let rotation = gradient.settings.rotation {
components.append("\(rotation)")
}
if gradient.settings.motion {
components.append("motion")
}
if gradient.settings.blur {
components.append("blur")
}
try container.encode(components.joined(separator: " "))
case let .file(file):
var components: [String] = []
components.append(file.slug)
if self.value.isPattern {
if file.settings.colors.count >= 1 {
components.append(String(format: "%06x", file.settings.colors[0]))
}
if let intensity = file.settings.intensity {
components.append("\(intensity)")
}
if file.settings.colors.count >= 2 {
components.append(String(format: "%06x", file.settings.colors[1]))
}
if file.settings.colors.count >= 3 {
components.append(String(format: "%06x", file.settings.colors[2]))
}
if file.settings.colors.count >= 4 {
components.append(String(format: "%06x", file.settings.colors[3]))
}
if let rotation = file.settings.rotation, rotation != 0 {
components.append("\(rotation)")
}
}
if file.settings.motion {
components.append("motion")
}
if file.settings.blur {
components.append("blur")
}
try container.encode(components.joined(separator: " "))
default:
break
}
}
}
extension PresentationThemeStatusBarStyle: Codable {
public init(from decoder: Decoder) throws {
let values = try decoder.singleValueContainer()
if let value = try? values.decode(String.self) {
switch value.lowercased() {
case "black":
self = .black
case "white":
self = .white
default:
self = .black
}
} else {
self = .black
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .black:
try container.encode("black")
case .white:
try container.encode("white")
}
}
}
extension PresentationThemeActionSheetBackgroundType: Codable {
public init(from decoder: Decoder) throws {
let values = try decoder.singleValueContainer()
if let value = try? values.decode(String.self) {
switch value.lowercased() {
case "light":
self = .light
case "dark":
self = .dark
default:
self = .light
}
} else {
self = .light
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .light:
try container.encode("light")
case .dark:
try container.encode("dark")
}
}
}
extension PresentationThemeKeyboardColor: Codable {
public init(from decoder: Decoder) throws {
let values = try decoder.singleValueContainer()
if let value = try? values.decode(String.self) {
switch value.lowercased() {
case "light":
self = .light
case "dark":
self = .dark
default:
self = .light
}
} else {
self = .light
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .light:
try container.encode("light")
case .dark:
try container.encode("dark")
}
}
}
extension PresentationThemeExpandedNotificationBackgroundType: Codable {
public init(from decoder: Decoder) throws {
let values = try decoder.singleValueContainer()
if let value = try? values.decode(String.self) {
switch value.lowercased() {
case "light":
self = .light
case "dark":
self = .dark
default:
self = .light
}
} else {
self = .light
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .light:
try container.encode("light")
case .dark:
try container.encode("dark")
}
}
}
extension PresentationThemeGradientColors: Codable {
enum CodingKeys: String, CodingKey {
case top
case bottom
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(topColor: try decodeColor(values, .top),
bottomColor: try decodeColor(values, .bottom))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.topColor, .top)
try encodeColor(&values, self.bottomColor, .bottom)
}
}
extension PresentationThemeIntro: Codable {
enum CodingKeys: String, CodingKey {
case statusBar
case primaryText
case accentText
case disabledText
case startButton
case dot
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(statusBarStyle: try values.decode(PresentationThemeStatusBarStyle.self, forKey: .statusBar),
primaryTextColor: try decodeColor(values, .primaryText),
accentTextColor: try decodeColor(values, .accentText),
disabledTextColor: try decodeColor(values, .disabledText),
startButtonColor: try decodeColor(values, .startButton),
dotColor: try decodeColor(values, .dot))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try values.encode(self.statusBarStyle, forKey: .statusBar)
try encodeColor(&values, self.primaryTextColor, .primaryText)
try encodeColor(&values, self.accentTextColor, .accentText)
try encodeColor(&values, self.disabledTextColor, .disabledText)
try encodeColor(&values, self.startButtonColor, .startButton)
try encodeColor(&values, self.dotColor, .dot)
}
}
extension PresentationThemePasscode: Codable {
enum CodingKeys: String, CodingKey {
case bg
case button
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(backgroundColors: try values.decode(PresentationThemeGradientColors.self, forKey: .bg),
buttonColor: try decodeColor(values, .button))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try values.encode(self.backgroundColors, forKey: .bg)
try encodeColor(&values, self.buttonColor, .button)
}
}
extension PresentationThemeRootTabBar: Codable {
enum CodingKeys: String, CodingKey {
case background
case separator
case icon
case selectedIcon
case text
case selectedText
case badgeBackground
case badgeStroke
case badgeText
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(backgroundColor: try decodeColor(values, .background),
separatorColor: try decodeColor(values, .separator),
iconColor: try decodeColor(values, .icon),
selectedIconColor: try decodeColor(values, .selectedIcon),
textColor: try decodeColor(values, .text),
selectedTextColor: try decodeColor(values, .selectedText),
badgeBackgroundColor: try decodeColor(values, .badgeBackground),
badgeStrokeColor: try decodeColor(values, .badgeStroke),
badgeTextColor: try decodeColor(values, .badgeText))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.backgroundColor, .background)
try encodeColor(&values, self.separatorColor, .separator)
try encodeColor(&values, self.iconColor, .icon)
try encodeColor(&values, self.selectedIconColor, .selectedIcon)
try encodeColor(&values, self.textColor, .text)
try encodeColor(&values, self.selectedTextColor, .selectedText)
try encodeColor(&values, self.badgeBackgroundColor, .badgeBackground)
try encodeColor(&values, self.badgeStrokeColor, .badgeStroke)
try encodeColor(&values, self.badgeTextColor, .badgeText)
}
}
extension PresentationThemeRootNavigationBar: Codable {
enum CodingKeys: String, CodingKey {
case button
case disabledButton
case primaryText
case secondaryText
case control
case accentText
case background
case separator
case badgeFill
case badgeStroke
case badgeText
case segmentedBg
case segmentedFg
case segmentedText
case segmentedDivider
case clearButtonBackground
case clearButtonForeground
case opaqueBackground
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
let blurredBackgroundColor = try decodeColor(values, .background)
let opaqueBackgroundColor: UIColor
if blurredBackgroundColor.alpha >= 0.99 {
opaqueBackgroundColor = blurredBackgroundColor
} else {
opaqueBackgroundColor = (try? decodeColor(values, .opaqueBackground)) ?? blurredBackgroundColor
}
self.init(
buttonColor: try decodeColor(values, .button),
disabledButtonColor: try decodeColor(values, .disabledButton),
primaryTextColor: try decodeColor(values, .primaryText),
secondaryTextColor: try decodeColor(values, .secondaryText),
controlColor: try decodeColor(values, .control),
accentTextColor: try decodeColor(values, .accentText),
blurredBackgroundColor: blurredBackgroundColor,
opaqueBackgroundColor: opaqueBackgroundColor,
separatorColor: try decodeColor(values, .separator),
badgeBackgroundColor: try decodeColor(values, .badgeFill),
badgeStrokeColor: try decodeColor(values, .badgeStroke),
badgeTextColor: try decodeColor(values, .badgeText),
segmentedBackgroundColor: try decodeColor(values, .segmentedBg, decoder: decoder, fallbackKey: "root.searchBar.inputFill"),
segmentedForegroundColor: try decodeColor(values, .segmentedFg, decoder: decoder, fallbackKey: "root.navBar.background"),
segmentedTextColor: try decodeColor(values, .segmentedText, decoder: decoder, fallbackKey: "root.navBar.primaryText"),
segmentedDividerColor: try decodeColor(values, .segmentedDivider, decoder: decoder, fallbackKey: "list.freeInputField.stroke"),
clearButtonBackgroundColor: try decodeColor(values, .clearButtonBackground, decoder: decoder, fallbackKey: "list.freeInputField.bg"),
clearButtonForegroundColor: try decodeColor(values, .clearButtonForeground, decoder: decoder, fallbackKey: "list.freeInputField.primary")
)
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.buttonColor, .button)
try encodeColor(&values, self.disabledButtonColor, .disabledButton)
try encodeColor(&values, self.primaryTextColor, .primaryText)
try encodeColor(&values, self.secondaryTextColor, .secondaryText)
try encodeColor(&values, self.controlColor, .control)
try encodeColor(&values, self.accentTextColor, .accentText)
try encodeColor(&values, self.blurredBackgroundColor, .background)
try encodeColor(&values, self.opaqueBackgroundColor, .opaqueBackground)
try encodeColor(&values, self.separatorColor, .separator)
try encodeColor(&values, self.badgeBackgroundColor, .badgeFill)
try encodeColor(&values, self.badgeStrokeColor, .badgeStroke)
try encodeColor(&values, self.badgeTextColor, .badgeText)
try encodeColor(&values, self.segmentedBackgroundColor, .segmentedBg)
try encodeColor(&values, self.segmentedForegroundColor, .segmentedFg)
try encodeColor(&values, self.segmentedTextColor, .segmentedText)
try encodeColor(&values, self.segmentedDividerColor, .segmentedDivider)
}
}
extension PresentationThemeNavigationSearchBar: Codable {
enum CodingKeys: String, CodingKey {
case background
case accent
case inputFill
case inputText
case inputPlaceholderText
case inputIcon
case inputClearButton
case separator
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(backgroundColor: try decodeColor(values, .background),
accentColor: try decodeColor(values, .accent),
inputFillColor: try decodeColor(values, .inputFill),
inputTextColor: try decodeColor(values, .inputText),
inputPlaceholderTextColor: try decodeColor(values, .inputPlaceholderText),
inputIconColor: try decodeColor(values, .inputIcon),
inputClearButtonColor: try decodeColor(values, .inputClearButton),
separatorColor: try decodeColor(values, .separator))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.backgroundColor, .background)
try encodeColor(&values, self.accentColor, .accent)
try encodeColor(&values, self.inputFillColor, .inputFill)
try encodeColor(&values, self.inputTextColor, .inputText)
try encodeColor(&values, self.inputPlaceholderTextColor, .inputPlaceholderText)
try encodeColor(&values, self.inputIconColor, .inputIcon)
try encodeColor(&values, self.inputClearButtonColor, .inputClearButton)
try encodeColor(&values, self.separatorColor, .separator)
}
}
extension PresentationThemeRootController: Codable {
enum CodingKeys: String, CodingKey {
case statusBar
case tabBar
case navBar
case searchBar
case keyboard
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(statusBarStyle: try values.decode(PresentationThemeStatusBarStyle.self, forKey: .statusBar),
tabBar: try values.decode(PresentationThemeRootTabBar.self, forKey: .tabBar),
navigationBar: try values.decode(PresentationThemeRootNavigationBar.self, forKey: .navBar),
navigationSearchBar: try values.decode(PresentationThemeNavigationSearchBar.self, forKey: .searchBar),
keyboardColor: try values.decode(PresentationThemeKeyboardColor.self, forKey: .keyboard))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try values.encode(self.statusBarStyle, forKey: .statusBar)
try values.encode(self.tabBar, forKey: .tabBar)
try values.encode(self.navigationBar, forKey: .navBar)
try values.encode(self.navigationSearchBar, forKey: .searchBar)
try values.encode(self.keyboardColor, forKey: .keyboard)
}
}
extension PresentationThemeActionSheet: Codable {
enum CodingKeys: String, CodingKey {
case dim
case bgType
case opaqueItemBg
case itemBg
case opaqueItemHighlightedBg
case itemHighlightedBg
case opaqueItemSeparator
case standardActionText
case destructiveActionText
case disabledActionText
case primaryText
case secondaryText
case controlAccent
case inputBg
case inputHollowBg
case inputBorder
case inputPlaceholder
case inputText
case inputClearButton
case checkContent
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(dimColor: try decodeColor(values, .dim),
backgroundType: try values.decode(PresentationThemeActionSheetBackgroundType.self, forKey: .bgType),
opaqueItemBackgroundColor: try decodeColor(values, .opaqueItemBg),
itemBackgroundColor: try decodeColor(values, .itemBg),
opaqueItemHighlightedBackgroundColor: try decodeColor(values, .opaqueItemHighlightedBg),
itemHighlightedBackgroundColor: try decodeColor(values, .itemHighlightedBg),
opaqueItemSeparatorColor: try decodeColor(values, .opaqueItemSeparator),
standardActionTextColor: try decodeColor(values, .standardActionText),
destructiveActionTextColor: try decodeColor(values, .destructiveActionText),
disabledActionTextColor: try decodeColor(values, .disabledActionText),
primaryTextColor: try decodeColor(values, .primaryText),
secondaryTextColor: try decodeColor(values, .secondaryText),
controlAccentColor: try decodeColor(values, .controlAccent),
inputBackgroundColor: try decodeColor(values, .inputBg),
inputHollowBackgroundColor: try decodeColor(values, .inputHollowBg),
inputBorderColor: try decodeColor(values, .inputBorder),
inputPlaceholderColor: try decodeColor(values, .inputPlaceholder),
inputTextColor: try decodeColor(values, .inputText),
inputClearButtonColor: try decodeColor(values, .inputClearButton),
checkContentColor: try decodeColor(values, .checkContent))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.dimColor, .dim)
try values.encode(self.backgroundType, forKey: .bgType)
try encodeColor(&values, self.opaqueItemBackgroundColor, .opaqueItemBg)
try encodeColor(&values, self.itemBackgroundColor, .itemBg)
try encodeColor(&values, self.opaqueItemHighlightedBackgroundColor, .opaqueItemHighlightedBg)
try encodeColor(&values, self.itemHighlightedBackgroundColor, .itemHighlightedBg)
try encodeColor(&values, self.opaqueItemSeparatorColor, .opaqueItemSeparator)
try encodeColor(&values, self.standardActionTextColor, .standardActionText)
try encodeColor(&values, self.destructiveActionTextColor, .destructiveActionText)
try encodeColor(&values, self.disabledActionTextColor, .disabledActionText)
try encodeColor(&values, self.primaryTextColor, .primaryText)
try encodeColor(&values, self.secondaryTextColor, .secondaryText)
try encodeColor(&values, self.controlAccentColor, .controlAccent)
try encodeColor(&values, self.inputBackgroundColor, .inputBg)
try encodeColor(&values, self.inputHollowBackgroundColor, .inputHollowBg)
try encodeColor(&values, self.inputBorderColor, .inputBorder)
try encodeColor(&values, self.inputPlaceholderColor, .inputPlaceholder)
try encodeColor(&values, self.inputTextColor, .inputText)
try encodeColor(&values, self.inputClearButtonColor, .inputClearButton)
try encodeColor(&values, self.checkContentColor, .checkContent)
}
}
extension PresentationThemeSwitch: Codable {
enum CodingKeys: String, CodingKey {
case frame
case handle
case content
case positive
case negative
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(frameColor: try decodeColor(values, .frame),
handleColor: try decodeColor(values, .handle),
contentColor: try decodeColor(values, .content),
positiveColor: try decodeColor(values, .positive),
negativeColor: try decodeColor(values, .negative))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.frameColor, .frame)
try encodeColor(&values, self.handleColor, .handle)
try encodeColor(&values, self.contentColor, .content)
try encodeColor(&values, self.positiveColor, .positive)
try encodeColor(&values, self.negativeColor, .negative)
}
}
extension PresentationThemeFillForeground: Codable {
enum CodingKeys: String, CodingKey {
case bg
case fg
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(fillColor: try decodeColor(values, .bg),
foregroundColor: try decodeColor(values, .fg))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.fillColor, .bg)
try encodeColor(&values, self.foregroundColor, .fg)
}
}
extension PresentationThemeItemDisclosureActions: Codable {
enum CodingKeys: String, CodingKey {
case neutral1
case neutral2
case destructive
case constructive
case accent
case warning
case inactive
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(neutral1: try values.decode(PresentationThemeFillForeground.self, forKey: .neutral1),
neutral2: try values.decode(PresentationThemeFillForeground.self, forKey: .neutral2),
destructive: try values.decode(PresentationThemeFillForeground.self, forKey: .destructive),
constructive: try values.decode(PresentationThemeFillForeground.self, forKey: .constructive),
accent: try values.decode(PresentationThemeFillForeground.self, forKey: .accent),
warning: try values.decode(PresentationThemeFillForeground.self, forKey: .warning),
inactive: try values.decode(PresentationThemeFillForeground.self, forKey: .inactive))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try values.encode(self.neutral1, forKey: .neutral1)
try values.encode(self.neutral2, forKey: .neutral2)
try values.encode(self.destructive, forKey: .destructive)
try values.encode(self.constructive, forKey: .constructive)
try values.encode(self.accent, forKey: .accent)
try values.encode(self.warning, forKey: .warning)
try values.encode(self.inactive, forKey: .inactive)
}
}
extension PresentationThemeItemBarChart: Codable {
enum CodingKeys: String, CodingKey {
case color1
case color2
case color3
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(color1: try decodeColor(values, .color1),
color2: try decodeColor(values, .color2),
color3: try decodeColor(values, .color3))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.color1, .color1)
try encodeColor(&values, self.color2, .color2)
try encodeColor(&values, self.color3, .color3)
}
}
extension PresentationThemeFillStrokeForeground: Codable {
enum CodingKeys: String, CodingKey {
case bg
case stroke
case fg
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(fillColor: try decodeColor(values, .bg),
strokeColor: try decodeColor(values, .stroke),
foregroundColor: try decodeColor(values, .fg))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.fillColor, .bg)
try encodeColor(&values, self.strokeColor, .stroke)
try encodeColor(&values, self.foregroundColor, .fg)
}
}
extension PresentationInputFieldTheme: Codable {
enum CodingKeys: String, CodingKey {
case bg
case stroke
case placeholder
case primary
case control
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(backgroundColor: try decodeColor(values, .bg),
strokeColor: try decodeColor(values, .stroke),
placeholderColor: try decodeColor(values, .placeholder),
primaryColor: try decodeColor(values, .primary),
controlColor: try decodeColor(values, .control))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.backgroundColor, .bg)
try encodeColor(&values, self.strokeColor, .stroke)
try encodeColor(&values, self.placeholderColor, .placeholder)
try encodeColor(&values, self.primaryColor, .primary)
try encodeColor(&values, self.controlColor, .control)
}
}
extension PresentationThemeList.PaymentOption: Codable {
enum CodingKeys: String, CodingKey {
case inactiveFill
case inactiveForeground
case activeFill
case activeForeground
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(
inactiveFillColor: try decodeColor(values, .inactiveFill),
inactiveForegroundColor: try decodeColor(values, .inactiveForeground),
activeFillColor: try decodeColor(values, .activeFill),
activeForegroundColor: try decodeColor(values, .activeForeground)
)
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.activeFillColor, .inactiveFill)
try encodeColor(&values, self.activeForegroundColor, .inactiveForeground)
try encodeColor(&values, self.activeFillColor, .activeFill)
try encodeColor(&values, self.activeForegroundColor, .activeForeground)
}
}
extension PresentationThemeList: Codable {
enum CodingKeys: String, CodingKey {
case blocksBg
case modalBlocksBg
case plainBg
case modalPlainBg
case primaryText
case secondaryText
case disabledText
case accent
case highlighted
case destructive
case placeholderText
case itemBlocksBg
case itemModalBlocksBg
case itemHighlightedBg
case blocksSeparator
case plainSeparator
case disclosureArrow
case sectionHeaderText
case freeText
case freeTextError
case freeTextSuccess
case freeMonoIcon
case `switch`
case disclosureActions
case check
case controlSecondary
case freeInputField
case freePlainInputField
case mediaPlaceholder
case scrollIndicator
case pageIndicatorInactive
case inputClearButton
case itemBarChart
case itemInputField
case paymentOption
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
let freePlainInputField: PresentationInputFieldTheme
if let value = try? values.decode(PresentationInputFieldTheme.self, forKey: .freePlainInputField) {
freePlainInputField = value
} else {
freePlainInputField = try values.decode(PresentationInputFieldTheme.self, forKey: .freeInputField)
}
let freeTextSuccessColor = try decodeColor(values, .freeTextSuccess)
self.init(
blocksBackgroundColor: try decodeColor(values, .blocksBg),
modalBlocksBackgroundColor: try decodeColor(values, .modalBlocksBg, decoder: decoder, fallbackKey: "list.blocksBg"),
plainBackgroundColor: try decodeColor(values, .plainBg),
modalPlainBackgroundColor: try decodeColor(values, .modalPlainBg, decoder: decoder, fallbackKey: "list.plainBg"),
itemPrimaryTextColor: try decodeColor(values, .primaryText),
itemSecondaryTextColor: try decodeColor(values, .secondaryText),
itemDisabledTextColor: try decodeColor(values, .disabledText),
itemAccentColor: try decodeColor(values, .accent),
itemHighlightedColor: try decodeColor(values, .highlighted),
itemDestructiveColor: try decodeColor(values, .destructive),
itemPlaceholderTextColor: try decodeColor(values, .placeholderText),
itemBlocksBackgroundColor: try decodeColor(values, .itemBlocksBg),
itemModalBlocksBackgroundColor: try decodeColor(values, .itemModalBlocksBg, decoder: decoder, fallbackKey: "list.itemBlocksBg"),
itemHighlightedBackgroundColor: try decodeColor(values, .itemHighlightedBg),
itemBlocksSeparatorColor: try decodeColor(values, .blocksSeparator),
itemPlainSeparatorColor: try decodeColor(values, .plainSeparator),
disclosureArrowColor: try decodeColor(values, .disclosureArrow),
sectionHeaderTextColor: try decodeColor(values, .sectionHeaderText),
freeTextColor: try decodeColor(values, .freeText),
freeTextErrorColor: try decodeColor(values, .freeTextError),
freeTextSuccessColor: freeTextSuccessColor,
freeMonoIconColor: try decodeColor(values, .freeMonoIcon),
itemSwitchColors: try values.decode(PresentationThemeSwitch.self, forKey: .switch),
itemDisclosureActions: try values.decode(PresentationThemeItemDisclosureActions.self, forKey: .disclosureActions),
itemCheckColors: try values.decode(PresentationThemeFillStrokeForeground.self, forKey: .check),
controlSecondaryColor: try decodeColor(values, .controlSecondary),
freeInputField: try values.decode(PresentationInputFieldTheme.self, forKey: .freeInputField),
freePlainInputField: freePlainInputField,
mediaPlaceholderColor: try decodeColor(values, .mediaPlaceholder),
scrollIndicatorColor: try decodeColor(values, .scrollIndicator),
pageIndicatorInactiveColor: try decodeColor(values, .pageIndicatorInactive),
inputClearButtonColor: try decodeColor(values, .inputClearButton),
itemBarChart: try values.decode(PresentationThemeItemBarChart.self, forKey: .itemBarChart),
itemInputField: try values.decode(PresentationInputFieldTheme.self, forKey: .itemInputField),
paymentOption: (try? values.decode(PresentationThemeList.PaymentOption.self, forKey: .paymentOption)) ?? PresentationThemeList.PaymentOption(
inactiveFillColor: freeTextSuccessColor.withMultipliedAlpha(0.3),
inactiveForegroundColor: freeTextSuccessColor,
activeFillColor: freeTextSuccessColor,
activeForegroundColor: UIColor(rgb: 0xffffff)
)
)
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.blocksBackgroundColor, .blocksBg)
try encodeColor(&values, self.plainBackgroundColor, .plainBg)
try encodeColor(&values, self.itemPrimaryTextColor, .primaryText)
try encodeColor(&values, self.itemSecondaryTextColor, .secondaryText)
try encodeColor(&values, self.itemDisabledTextColor, .disabledText)
try encodeColor(&values, self.itemAccentColor, .accent)
try encodeColor(&values, self.itemHighlightedColor, .highlighted)
try encodeColor(&values, self.itemDestructiveColor, .destructive)
try encodeColor(&values, self.itemPlaceholderTextColor, .placeholderText)
try encodeColor(&values, self.itemBlocksBackgroundColor, .itemBlocksBg)
try encodeColor(&values, self.itemHighlightedBackgroundColor, .itemHighlightedBg)
try encodeColor(&values, self.itemBlocksSeparatorColor, .blocksSeparator)
try encodeColor(&values, self.itemPlainSeparatorColor, .plainSeparator)
try encodeColor(&values, self.disclosureArrowColor, .disclosureArrow)
try encodeColor(&values, self.sectionHeaderTextColor, .sectionHeaderText)
try encodeColor(&values, self.freeTextColor, .freeText)
try encodeColor(&values, self.freeTextErrorColor, .freeTextError)
try encodeColor(&values, self.freeTextSuccessColor, .freeTextSuccess)
try encodeColor(&values, self.freeMonoIconColor, .freeMonoIcon)
try values.encode(self.itemSwitchColors, forKey: .`switch`)
try values.encode(self.itemDisclosureActions, forKey: .disclosureActions)
try values.encode(self.itemCheckColors, forKey: .check)
try encodeColor(&values, self.controlSecondaryColor, .controlSecondary)
try values.encode(self.freeInputField, forKey: .freeInputField)
try encodeColor(&values, self.mediaPlaceholderColor, .mediaPlaceholder)
try encodeColor(&values, self.scrollIndicatorColor, .scrollIndicator)
try encodeColor(&values, self.pageIndicatorInactiveColor, .pageIndicatorInactive)
try encodeColor(&values, self.inputClearButtonColor, .inputClearButton)
try values.encode(self.itemBarChart, forKey: .itemBarChart)
try values.encode(self.itemInputField, forKey: .itemInputField)
}
}
extension PresentationThemeArchiveAvatarColors: Codable {
enum CodingKeys: String, CodingKey {
case background
case foreground
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(backgroundColors: try values.decode(PresentationThemeGradientColors.self, forKey: .background),
foregroundColor: try decodeColor(values, .foreground))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try values.encode(self.backgroundColors, forKey: .background)
try encodeColor(&values, self.foregroundColor, .foreground)
}
}
extension PresentationThemeChatList: Codable {
enum CodingKeys: String, CodingKey {
case bg
case itemSeparator
case itemBg
case pinnedItemBg
case itemHighlightedBg
case pinnedItemHighlightedBg
case itemSelectedBg
case title
case secretTitle
case dateText
case authorName
case messageText
case messageHighlightedText
case messageDraftText
case checkmark
case pendingIndicator
case failedFill
case failedFg
case muteIcon
case unreadBadgeActiveBg
case unreadBadgeActiveText
case unreadBadgeInactiveBg
case unreadBadgeInactiveText
case reactionBadgeActiveBg
case pinnedBadge
case pinnedSearchBar
case regularSearchBar
case sectionHeaderBg
case sectionHeaderText
case verifiedIconBg
case verifiedIconFg
case secretIcon
case pinnedArchiveAvatar
case unpinnedArchiveAvatar
case onlineDot
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
let codingPath = decoder.codingPath.map { $0.stringValue }.joined(separator: ".")
self.init(backgroundColor: try decodeColor(values, .bg),
itemSeparatorColor: try decodeColor(values, .itemSeparator),
itemBackgroundColor: try decodeColor(values, .itemBg),
pinnedItemBackgroundColor: try decodeColor(values, .pinnedItemBg),
itemHighlightedBackgroundColor: try decodeColor(values, .itemHighlightedBg),
pinnedItemHighlightedBackgroundColor: try decodeColor(values, .pinnedItemHighlightedBg, fallbackKey: "\(codingPath).itemHighlightedBg"),
itemSelectedBackgroundColor: try decodeColor(values, .itemSelectedBg),
titleColor: try decodeColor(values, .title),
secretTitleColor: try decodeColor(values, .secretTitle),
dateTextColor: try decodeColor(values, .dateText),
authorNameColor: try decodeColor(values, .authorName),
messageTextColor: try decodeColor(values, .messageText),
messageHighlightedTextColor: try decodeColor(values, .messageHighlightedText),
messageDraftTextColor: try decodeColor(values, .messageDraftText),
checkmarkColor: try decodeColor(values, .checkmark),
pendingIndicatorColor: try decodeColor(values, .pendingIndicator),
failedFillColor: try decodeColor(values, .failedFill),
failedForegroundColor: try decodeColor(values, .failedFg),
muteIconColor: try decodeColor(values, .muteIcon),
unreadBadgeActiveBackgroundColor: try decodeColor(values, .unreadBadgeActiveBg),
unreadBadgeActiveTextColor: try decodeColor(values, .unreadBadgeActiveText),
unreadBadgeInactiveBackgroundColor: try decodeColor(values, .unreadBadgeInactiveBg),
unreadBadgeInactiveTextColor: try decodeColor(values, .unreadBadgeInactiveText),
reactionBadgeActiveBackgroundColor: try decodeColor(values, .reactionBadgeActiveBg, fallbackKey: "\(codingPath).unreadBadgeActiveBg"),
pinnedBadgeColor: try decodeColor(values, .pinnedBadge),
pinnedSearchBarColor: try decodeColor(values, .pinnedSearchBar),
regularSearchBarColor: try decodeColor(values, .regularSearchBar),
sectionHeaderFillColor: try decodeColor(values, .sectionHeaderBg),
sectionHeaderTextColor: try decodeColor(values, .sectionHeaderText),
verifiedIconFillColor: try decodeColor(values, .verifiedIconBg),
verifiedIconForegroundColor: try decodeColor(values, .verifiedIconFg),
secretIconColor: try decodeColor(values, .secretIcon),
pinnedArchiveAvatarColor: try values.decode(PresentationThemeArchiveAvatarColors.self, forKey: .pinnedArchiveAvatar),
unpinnedArchiveAvatarColor: try values.decode(PresentationThemeArchiveAvatarColors.self, forKey: .unpinnedArchiveAvatar),
onlineDotColor: try decodeColor(values, .onlineDot))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.backgroundColor, .bg)
try encodeColor(&values, self.itemSeparatorColor, .itemSeparator)
try encodeColor(&values, self.itemBackgroundColor, .itemBg)
try encodeColor(&values, self.pinnedItemBackgroundColor, .pinnedItemBg)
try encodeColor(&values, self.itemHighlightedBackgroundColor, .itemHighlightedBg)
try encodeColor(&values, self.pinnedItemHighlightedBackgroundColor, .pinnedItemHighlightedBg)
try encodeColor(&values, self.itemSelectedBackgroundColor, .itemSelectedBg)
try encodeColor(&values, self.titleColor, .title)
try encodeColor(&values, self.secretTitleColor, .secretTitle)
try encodeColor(&values, self.dateTextColor, .dateText)
try encodeColor(&values, self.authorNameColor, .authorName)
try encodeColor(&values, self.messageTextColor, .messageText)
try encodeColor(&values, self.messageHighlightedTextColor, .messageHighlightedText)
try encodeColor(&values, self.messageDraftTextColor, .messageDraftText)
try encodeColor(&values, self.checkmarkColor, .checkmark)
try encodeColor(&values, self.pendingIndicatorColor, .pendingIndicator)
try encodeColor(&values, self.failedFillColor, .failedFill)
try encodeColor(&values, self.failedForegroundColor, .failedFg)
try encodeColor(&values, self.muteIconColor, .muteIcon)
try encodeColor(&values, self.unreadBadgeActiveBackgroundColor, .unreadBadgeActiveBg)
try encodeColor(&values, self.unreadBadgeActiveTextColor, .unreadBadgeActiveText)
try encodeColor(&values, self.unreadBadgeInactiveBackgroundColor, .unreadBadgeInactiveBg)
try encodeColor(&values, self.unreadBadgeInactiveTextColor, .unreadBadgeInactiveText)
try encodeColor(&values, self.reactionBadgeActiveBackgroundColor, .reactionBadgeActiveBg)
try encodeColor(&values, self.pinnedBadgeColor, .pinnedBadge)
try encodeColor(&values, self.pinnedSearchBarColor, .pinnedSearchBar)
try encodeColor(&values, self.regularSearchBarColor, .regularSearchBar)
try encodeColor(&values, self.sectionHeaderFillColor, .sectionHeaderBg)
try encodeColor(&values, self.sectionHeaderTextColor, .sectionHeaderText)
try encodeColor(&values, self.verifiedIconFillColor, .verifiedIconBg)
try encodeColor(&values, self.verifiedIconForegroundColor, .verifiedIconFg)
try encodeColor(&values, self.secretIconColor, .secretIcon)
try values.encode(self.pinnedArchiveAvatarColor, forKey: .pinnedArchiveAvatar)
try values.encode(self.unpinnedArchiveAvatarColor, forKey: .unpinnedArchiveAvatar)
try encodeColor(&values, self.onlineDotColor, .onlineDot)
}
}
extension PresentationThemeBubbleShadow: Codable {
enum CodingKeys: String, CodingKey {
case color
case radius
case verticalOffset
}
public init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(
color: try decodeColor(values, .color),
radius: try CGFloat(Double(truncating: values.decode(Decimal.self, forKey: .radius) as NSNumber)),
verticalOffset: try CGFloat(Double(truncating: values.decode(Decimal.self, forKey: .verticalOffset) as NSNumber))
)
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.color, .color)
try values.encode(Decimal(Double(self.radius)), forKey: .radius)
try values.encode(Decimal(Double(self.verticalOffset)), forKey: .verticalOffset)
}
}
extension PresentationThemeBubbleColorComponents: Codable {
enum CodingKeys: String, CodingKey {
case bg
case gradientBg
case highlightedBg
case stroke
case shadow
case bgList
case reactionInactiveBg
case reactionInactiveFg
case reactionInactiveMediaPlaceholder
case reactionActiveMediaPlaceholder
case reactionActiveBg
case reactionActiveFg
case __workaroundNonexistingKey
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
let codingPath = decoder.codingPath.map { $0.stringValue }.joined(separator: ".")
let fill: [UIColor]
if let bgList = try? decodeColorList(values, .bgList) {
fill = bgList
} else {
var fillColor = try decodeColor(values, .bg)
var gradientColor = try decodeColor(values, .gradientBg, decoder: decoder, fallbackKey: "\(codingPath).bg")
if gradientColor.rgb != fillColor.rgb {
fillColor = fillColor.withAlphaComponent(1.0)
gradientColor = gradientColor.withAlphaComponent(1.0)
}
fill = [fillColor, gradientColor]
}
let fallbackKeyPrefix: String
if codingPath.hasPrefix("chat.message.incoming.") {
fallbackKeyPrefix = "chat.message.incoming."
} else {
fallbackKeyPrefix = "chat.message.outgoing."
}
let reactionInactiveBackground: UIColor
if let color = try? decodeColor(values, .reactionInactiveBg) {
reactionInactiveBackground = color
} else {
reactionInactiveBackground = (try decodeColor(values, .__workaroundNonexistingKey, fallbackKey: "\(fallbackKeyPrefix).accentControl")).withMultipliedAlpha(0.1)
}
let reactionInactiveMediaPlaceholder: UIColor
if let color = try? decodeColor(values, .reactionInactiveMediaPlaceholder) {
reactionInactiveMediaPlaceholder = color
} else {
reactionInactiveMediaPlaceholder = (try decodeColor(values, .__workaroundNonexistingKey, fallbackKey: "\(fallbackKeyPrefix).accentControl")).withMultipliedAlpha(0.1)
}
let reactionActiveMediaPlaceholder: UIColor
if let color = try? decodeColor(values, .reactionActiveMediaPlaceholder) {
reactionActiveMediaPlaceholder = color
} else {
reactionActiveMediaPlaceholder = (try decodeColor(values, .__workaroundNonexistingKey, fallbackKey: "\(fallbackKeyPrefix).accentControl")).withMultipliedAlpha(0.1)
}
let reactionInactiveForeground: UIColor
if let color = try? decodeColor(values, .reactionInactiveFg) {
reactionInactiveForeground = color
} else {
reactionInactiveForeground = try decodeColor(values, .__workaroundNonexistingKey, fallbackKey: "\(fallbackKeyPrefix).accentControl")
}
let reactionActiveBackground: UIColor
if let color = try? decodeColor(values, .reactionActiveBg) {
reactionActiveBackground = color
} else {
reactionActiveBackground = try decodeColor(values, .__workaroundNonexistingKey, fallbackKey: "\(fallbackKeyPrefix).accentControl")
}
let reactionActiveForeground: UIColor
if let color = try? decodeColor(values, .reactionActiveFg) {
reactionActiveForeground = color
} else {
reactionActiveForeground = .clear
}
self.init(
fill: fill,
highlightedFill: try decodeColor(values, .highlightedBg),
stroke: try decodeColor(values, .stroke),
shadow: try? values.decode(PresentationThemeBubbleShadow.self, forKey: .shadow),
reactionInactiveBackground: reactionInactiveBackground,
reactionInactiveForeground: reactionInactiveForeground,
reactionActiveBackground: reactionActiveBackground,
reactionActiveForeground: reactionActiveForeground,
reactionInactiveMediaPlaceholder: reactionInactiveMediaPlaceholder,
reactionActiveMediaPlaceholder: reactionActiveMediaPlaceholder
)
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
if self.fill.count <= 2 {
if self.fill.count > 1 {
try encodeColor(&values, self.fill[0], .bg)
try encodeColor(&values, self.fill[1], .gradientBg)
} else {
try encodeColor(&values, self.fill[0], .bg)
try encodeColor(&values, self.fill[0], .gradientBg)
}
} else {
try encodeColorList(&values, self.fill, .bgList)
}
try encodeColor(&values, self.highlightedFill, .highlightedBg)
try encodeColor(&values, self.stroke, .stroke)
try encodeColor(&values, self.reactionInactiveBackground, .reactionInactiveBg)
try encodeColor(&values, self.reactionInactiveForeground, .reactionInactiveFg)
try encodeColor(&values, self.reactionActiveBackground, .reactionActiveBg)
try encodeColor(&values, self.reactionActiveForeground, .reactionActiveFg)
try encodeColor(&values, self.reactionInactiveMediaPlaceholder, .reactionInactiveMediaPlaceholder)
try encodeColor(&values, self.reactionActiveMediaPlaceholder, .reactionActiveMediaPlaceholder)
}
}
extension PresentationThemeBubbleColor: Codable {
enum CodingKeys: String, CodingKey {
case withWp
case withoutWp
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(withWallpaper: try values.decode(PresentationThemeBubbleColorComponents.self, forKey: .withWp),
withoutWallpaper: try values.decode(PresentationThemeBubbleColorComponents.self, forKey: .withoutWp))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try values.encode(self.withWallpaper, forKey: .withWp)
try values.encode(self.withoutWallpaper, forKey: .withoutWp)
}
}
extension PresentationThemeVariableColor: Codable {
enum CodingKeys: String, CodingKey {
case withWp
case withoutWp
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(withWallpaper: try decodeColor(values, .withWp),
withoutWallpaper: try decodeColor(values, .withoutWp))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.withWallpaper, .withWp)
try encodeColor(&values, self.withoutWallpaper, .withoutWp)
}
}
extension PresentationThemeChatBubblePolls: Codable {
enum CodingKeys: String, CodingKey {
case radioButton
case radioProgress
case highlight
case separator
case bar
case barIconForeground
case barPositive
case barNegative
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
let bar = try decodeColor(values, .bar)
self.init(
radioButton: try decodeColor(values, .radioButton),
radioProgress: try decodeColor(values, .radioProgress),
highlight: try decodeColor(values, .highlight),
separator: try decodeColor(values, .separator),
bar: bar,
barIconForeground: (try? decodeColor(values, .barIconForeground)) ?? .clear,
barPositive: (try? decodeColor(values, .barPositive)) ?? bar,
barNegative: (try? decodeColor(values, .barNegative)) ?? bar
)
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.radioButton, .radioButton)
try encodeColor(&values, self.radioProgress, .radioProgress)
try encodeColor(&values, self.highlight, .highlight)
try encodeColor(&values, self.separator, .separator)
try encodeColor(&values, self.bar, .bar)
try encodeColor(&values, self.barIconForeground, .barIconForeground)
try encodeColor(&values, self.barPositive, .barPositive)
try encodeColor(&values, self.barNegative, .barNegative)
}
}
extension PresentationThemePartedColors: Codable {
enum CodingKeys: String, CodingKey {
case bubble
case primaryText
case secondaryText
case linkText
case linkHighlight
case scam
case textHighlight
case accentText
case accentControl
case mediaActiveControl
case mediaInactiveControl
case mediaControlInnerBg
case pendingActivity
case fileTitle
case fileDescription
case fileDuration
case mediaPlaceholder
case polls
case actionButtonsBg
case actionButtonsStroke
case actionButtonsText
case textSelection
case textSelectionKnob
case accentControlDisabled
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
let codingPath = decoder.codingPath.map { $0.stringValue }.joined(separator: ".")
let accentControlColor = try decodeColor(values, .accentControl)
self.init(
bubble: try values.decode(PresentationThemeBubbleColor.self, forKey: .bubble),
primaryTextColor: try decodeColor(values, .primaryText),
secondaryTextColor: try decodeColor(values, .secondaryText),
linkTextColor: try decodeColor(values, .linkText),
linkHighlightColor: try decodeColor(values, .linkHighlight),
scamColor: try decodeColor(values, .scam),
textHighlightColor: try decodeColor(values, .textHighlight),
accentTextColor: try decodeColor(values, .accentText),
accentControlColor: accentControlColor,
accentControlDisabledColor: (try? decodeColor(values, .accentControlDisabled)) ?? accentControlColor.withAlphaComponent(0.5),
mediaActiveControlColor: try decodeColor(values, .mediaActiveControl),
mediaInactiveControlColor: try decodeColor(values, .mediaInactiveControl),
mediaControlInnerBackgroundColor: try decodeColor(values, .mediaControlInnerBg, decoder: decoder, fallbackKey: "\(codingPath).bubble.withWp.bg"),
pendingActivityColor: try decodeColor(values, .pendingActivity),
fileTitleColor: try decodeColor(values, .fileTitle),
fileDescriptionColor: try decodeColor(values, .fileDescription),
fileDurationColor: try decodeColor(values, .fileDuration),
mediaPlaceholderColor: try decodeColor(values, .mediaPlaceholder),
polls: try values.decode(PresentationThemeChatBubblePolls.self, forKey: .polls),
actionButtonsFillColor: try values.decode(PresentationThemeVariableColor.self, forKey: .actionButtonsBg),
actionButtonsStrokeColor: try values.decode(PresentationThemeVariableColor.self, forKey: .actionButtonsStroke),
actionButtonsTextColor: try values.decode(PresentationThemeVariableColor.self, forKey: .actionButtonsText),
textSelectionColor: try decodeColor(values, .textSelection),
textSelectionKnobColor: try decodeColor(values, .textSelectionKnob)
)
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try values.encode(self.bubble, forKey: .bubble)
try encodeColor(&values, self.primaryTextColor, .primaryText)
try encodeColor(&values, self.secondaryTextColor, .secondaryText)
try encodeColor(&values, self.linkTextColor, .linkText)
try encodeColor(&values, self.linkHighlightColor, .linkHighlight)
try encodeColor(&values, self.scamColor, .scam)
try encodeColor(&values, self.textHighlightColor, .textHighlight)
try encodeColor(&values, self.accentTextColor, .accentText)
try encodeColor(&values, self.accentControlColor, .accentControl)
try encodeColor(&values, self.mediaActiveControlColor, .mediaActiveControl)
try encodeColor(&values, self.mediaInactiveControlColor, .mediaInactiveControl)
try encodeColor(&values, self.mediaControlInnerBackgroundColor, .mediaControlInnerBg)
try encodeColor(&values, self.pendingActivityColor, .pendingActivity)
try encodeColor(&values, self.fileTitleColor, .fileTitle)
try encodeColor(&values, self.fileDescriptionColor, .fileDescription)
try encodeColor(&values, self.fileDurationColor, .fileDuration)
try encodeColor(&values, self.mediaPlaceholderColor, .mediaPlaceholder)
try values.encode(self.polls, forKey: .polls)
try values.encode(self.actionButtonsFillColor, forKey: .actionButtonsBg)
try values.encode(self.actionButtonsStrokeColor, forKey: .actionButtonsStroke)
try values.encode(self.actionButtonsTextColor, forKey: .actionButtonsText)
try encodeColor(&values, self.textSelectionColor, .textSelection)
try encodeColor(&values, self.textSelectionKnobColor, .textSelectionKnob)
}
}
extension PresentationThemeChatMessage: Codable {
enum CodingKeys: String, CodingKey {
case incoming
case outgoing
case freeform
case infoPrimaryText
case infoLinkText
case outgoingCheck
case mediaDateAndStatusBg
case mediaDateAndStatusText
case shareButtonBg
case shareButtonStroke
case shareButtonFg
case mediaOverlayControl
case selectionControl
case deliveryFailed
case mediaHighlightOverlay
case stickerPlaceholder
case stickerPlaceholderShimmer
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(incoming: try values.decode(PresentationThemePartedColors.self, forKey: .incoming),
outgoing: try values.decode(PresentationThemePartedColors.self, forKey: .outgoing),
freeform: try values.decode(PresentationThemeBubbleColor.self, forKey: .freeform),
infoPrimaryTextColor: try decodeColor(values, .infoPrimaryText),
infoLinkTextColor: try decodeColor(values, .infoLinkText),
outgoingCheckColor: try decodeColor(values, .outgoingCheck),
mediaDateAndStatusFillColor: try decodeColor(values, .mediaDateAndStatusBg),
mediaDateAndStatusTextColor: try decodeColor(values, .mediaDateAndStatusText),
shareButtonFillColor: try values.decode(PresentationThemeVariableColor.self, forKey: .shareButtonBg),
shareButtonStrokeColor: try values.decode(PresentationThemeVariableColor.self, forKey: .shareButtonStroke),
shareButtonForegroundColor: try values.decode(PresentationThemeVariableColor.self, forKey: .shareButtonFg),
mediaOverlayControlColors: try values.decode(PresentationThemeFillForeground.self, forKey: .mediaOverlayControl),
selectionControlColors: try values.decode(PresentationThemeFillStrokeForeground.self, forKey: .selectionControl),
deliveryFailedColors: try values.decode(PresentationThemeFillForeground.self, forKey: .deliveryFailed),
mediaHighlightOverlayColor: try decodeColor(values, .mediaHighlightOverlay),
stickerPlaceholderColor: try values.decode(PresentationThemeVariableColor.self, forKey: .stickerPlaceholder),
stickerPlaceholderShimmerColor: try values.decode(PresentationThemeVariableColor.self, forKey: .stickerPlaceholderShimmer)
)
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try values.encode(self.incoming, forKey: .incoming)
try values.encode(self.outgoing, forKey: .outgoing)
try values.encode(self.freeform, forKey: .freeform)
try encodeColor(&values, self.infoPrimaryTextColor, .infoPrimaryText)
try encodeColor(&values, self.infoLinkTextColor, .infoLinkText)
try encodeColor(&values, self.outgoingCheckColor, .outgoingCheck)
try encodeColor(&values, self.mediaDateAndStatusFillColor, .mediaDateAndStatusBg)
try encodeColor(&values, self.mediaDateAndStatusTextColor, .mediaDateAndStatusText)
try values.encode(self.shareButtonFillColor, forKey: .shareButtonBg)
try values.encode(self.shareButtonStrokeColor, forKey: .shareButtonStroke)
try values.encode(self.shareButtonForegroundColor, forKey: .shareButtonFg)
try values.encode(self.mediaOverlayControlColors, forKey: .mediaOverlayControl)
try values.encode(self.selectionControlColors, forKey: .selectionControl)
try values.encode(self.deliveryFailedColors, forKey: .deliveryFailed)
try encodeColor(&values, self.mediaHighlightOverlayColor, .mediaHighlightOverlay)
try values.encode(self.stickerPlaceholderColor, forKey: .stickerPlaceholder)
try values.encode(self.stickerPlaceholderShimmerColor, forKey: .stickerPlaceholderShimmer)
}
}
extension PresentationThemeServiceMessageColorComponents: Codable {
enum CodingKeys: String, CodingKey {
case bg
case primaryText
case linkHighlight
case scam
case dateFillStatic
case dateFillFloat
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(fill: try decodeColor(values, .bg),
primaryText: try decodeColor(values, .primaryText),
linkHighlight: try decodeColor(values, .linkHighlight),
scam: try decodeColor(values, .scam),
dateFillStatic: try decodeColor(values, .dateFillStatic),
dateFillFloating: try decodeColor(values, .dateFillFloat))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.fill, .bg)
try encodeColor(&values, self.primaryText, .primaryText)
try encodeColor(&values, self.linkHighlight, .linkHighlight)
try encodeColor(&values, self.scam, .scam)
try encodeColor(&values, self.dateFillStatic, .dateFillStatic)
try encodeColor(&values, self.dateFillFloating, .dateFillFloat)
}
}
extension PresentationThemeServiceMessageColor: Codable {
enum CodingKeys: String, CodingKey {
case withDefaultWp
case withCustomWp
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(withDefaultWallpaper: try values.decode(PresentationThemeServiceMessageColorComponents.self, forKey: .withDefaultWp),
withCustomWallpaper: try values.decode(PresentationThemeServiceMessageColorComponents.self, forKey: .withCustomWp))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try values.encode(self.withDefaultWallpaper, forKey: .withDefaultWp)
try values.encode(self.withCustomWallpaper, forKey: .withCustomWp)
}
}
extension PresentationThemeServiceMessage: Codable {
enum CodingKeys: String, CodingKey {
case components
case unreadBarBg
case unreadBarStroke
case unreadBarText
case dateText
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(components: try values.decode(PresentationThemeServiceMessageColor.self, forKey: .components),
unreadBarFillColor: try decodeColor(values, .unreadBarBg),
unreadBarStrokeColor: try decodeColor(values, .unreadBarStroke),
unreadBarTextColor: try decodeColor(values, .unreadBarText),
dateTextColor: try values.decode(PresentationThemeVariableColor.self, forKey: .dateText))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try values.encode(self.components, forKey: .components)
try encodeColor(&values, self.unreadBarFillColor, .unreadBarBg)
try encodeColor(&values, self.unreadBarStrokeColor, .unreadBarStroke)
try encodeColor(&values, self.unreadBarTextColor, .unreadBarText)
try values.encode(self.dateTextColor, forKey: .dateText)
}
}
extension PresentationThemeChatInputPanelMediaRecordingControl: Codable {
enum CodingKeys: String, CodingKey {
case button
case micLevel
case activeIcon
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(buttonColor: try decodeColor(values, .button),
micLevelColor: try decodeColor(values, .micLevel),
activeIconColor: try decodeColor(values, .activeIcon))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.buttonColor, .button)
try encodeColor(&values, self.micLevelColor, .micLevel)
try encodeColor(&values, self.activeIconColor, .activeIcon)
}
}
extension PresentationThemeChatInputPanel: Codable {
enum CodingKeys: String, CodingKey {
case panelBg
case panelBgNoWallpaper
case panelSeparator
case panelControlAccent
case panelControl
case panelControlDisabled
case panelControlDestructive
case inputBg
case inputStroke
case inputPlaceholder
case inputText
case inputControl
case actionControlBg
case actionControlFg
case primaryText
case secondaryText
case mediaRecordDot
case mediaRecordControl
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
let codingPath = decoder.codingPath.map { $0.stringValue }.joined(separator: ".")
self.init(panelBackgroundColor: try decodeColor(values, .panelBg),
panelBackgroundColorNoWallpaper: try decodeColor(values, .panelBg, decoder: decoder, fallbackKey: "\(codingPath).panelBgNoWallpaper"),
panelSeparatorColor: try decodeColor(values, .panelSeparator),
panelControlAccentColor: try decodeColor(values, .panelControlAccent),
panelControlColor: try decodeColor(values, .panelControl),
panelControlDisabledColor: try decodeColor(values, .panelControlDisabled),
panelControlDestructiveColor: try decodeColor(values, .panelControlDestructive),
inputBackgroundColor: try decodeColor(values, .inputBg),
inputStrokeColor: try decodeColor(values, .inputStroke),
inputPlaceholderColor: try decodeColor(values, .inputPlaceholder),
inputTextColor: try decodeColor(values, .inputText),
inputControlColor: try decodeColor(values, .inputControl),
actionControlFillColor: try decodeColor(values, .actionControlBg),
actionControlForegroundColor: try decodeColor(values, .actionControlFg),
primaryTextColor: try decodeColor(values, .primaryText),
secondaryTextColor: try decodeColor(values, .secondaryText),
mediaRecordingDotColor: try decodeColor(values, .mediaRecordDot),
mediaRecordingControl: try values.decode(PresentationThemeChatInputPanelMediaRecordingControl.self, forKey: .mediaRecordControl))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.panelBackgroundColor, .panelBg)
try encodeColor(&values, self.panelSeparatorColor, .panelSeparator)
try encodeColor(&values, self.panelControlAccentColor, .panelControlAccent)
try encodeColor(&values, self.panelControlColor, .panelControl)
try encodeColor(&values, self.panelControlDisabledColor, .panelControlDisabled)
try encodeColor(&values, self.panelControlDestructiveColor, .panelControlDestructive)
try encodeColor(&values, self.inputBackgroundColor, .inputBg)
try encodeColor(&values, self.inputStrokeColor, .inputStroke)
try encodeColor(&values, self.inputPlaceholderColor, .inputPlaceholder)
try encodeColor(&values, self.inputTextColor, .inputText)
try encodeColor(&values, self.inputControlColor, .inputControl)
try encodeColor(&values, self.actionControlFillColor, .actionControlBg)
try encodeColor(&values, self.actionControlForegroundColor, .actionControlFg)
try encodeColor(&values, self.primaryTextColor, .primaryText)
try encodeColor(&values, self.secondaryTextColor, .secondaryText)
try encodeColor(&values, self.mediaRecordingDotColor, .mediaRecordDot)
try values.encode(self.mediaRecordingControl, forKey: .mediaRecordControl)
}
}
extension PresentationThemeInputMediaPanel: Codable {
enum CodingKeys: String, CodingKey {
case panelSeparator
case panelIcon
case panelHighlightedIconBg
case panelHighlightedIcon
case panelContentVibrantOverlay
case panelContentControlVibrantOverlay
case panelContentControlVibrantSelection
case panelContentControlOpaqueOverlay
case panelContentControlOpaqueSelection
case stickersBg
case stickersSectionText
case stickersSearchBg
case stickersSearchPlaceholder
case stickersSearchPrimary
case stickersSearchControl
case gifsBg
case bg
case panelContentVibrantSearchOverlay
case panelContentVibrantSearchOverlaySelected
case panelContentVibrantSearchOverlayHighlight
case panelContentOpaqueSearchOverlay
case panelContentOpaqueSearchOverlaySelected
case panelContentOpaqueSearchOverlayHighlight
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
let backgroundColor: UIColor
if let value = try? decodeColor(values, .bg) {
backgroundColor = value
} else {
backgroundColor = try decodeColor(values, .gifsBg).withMultipliedAlpha(0.75)
}
let panelHighlightedIconColor: UIColor
if let value = try? decodeColor(values, .panelHighlightedIcon) {
panelHighlightedIconColor = value
} else if let value = try? decodeColor(values, .panelHighlightedIcon, fallbackKey: "chat.inputPanel.inputText") {
let defaultColor = try decodeColor(values, .panelIcon)
panelHighlightedIconColor = defaultColor.mixedWith(value, alpha: 0.35)
} else {
panelHighlightedIconColor = try decodeColor(values, .panelIcon)
}
let codingPath = decoder.codingPath.map { $0.stringValue }.joined(separator: ".")
self.init(panelSeparatorColor: try decodeColor(values, .panelSeparator),
panelIconColor: try decodeColor(values, .panelIcon),
panelHighlightedIconBackgroundColor: try decodeColor(values, .panelHighlightedIconBg),
panelHighlightedIconColor: panelHighlightedIconColor,
panelContentVibrantOverlayColor: try decodeColor(values, .panelContentVibrantOverlay, fallbackKey: "\(codingPath).stickersSectionText"),
panelContentControlVibrantOverlayColor: try decodeColor(values, .panelContentControlVibrantOverlay, fallbackKey: "\(codingPath).stickersSectionText"),
panelContentControlVibrantSelectionColor: try decodeColor(values, .panelContentControlVibrantSelection, fallbackKey: "\(codingPath).stickersSectionText"),
panelContentControlOpaqueOverlayColor: try decodeColor(values, .panelContentControlOpaqueOverlay, fallbackKey: "\(codingPath).stickersSectionText"),
panelContentControlOpaqueSelectionColor: try decodeColor(values, .panelContentControlOpaqueSelection, fallbackKey: "\(codingPath).stickersSectionText"),
panelContentVibrantSearchOverlayColor: try decodeColor(values, .panelContentVibrantSearchOverlay, fallbackKey: "\(codingPath).stickersSectionText"),
panelContentVibrantSearchOverlaySelectedColor: try decodeColor(values, .panelContentVibrantSearchOverlaySelected, fallbackKey: "\(codingPath).stickersSectionText"),
panelContentVibrantSearchOverlayHighlightColor: try decodeColor(values, .panelContentVibrantSearchOverlayHighlight, fallbackKey: "\(codingPath).panelHighlightedIconBg"),
panelContentOpaqueSearchOverlayColor: try decodeColor(values, .panelContentOpaqueSearchOverlay, fallbackKey: "\(codingPath).stickersSectionText"),
panelContentOpaqueSearchOverlaySelectedColor: try decodeColor(values, .panelContentOpaqueSearchOverlaySelected, fallbackKey: "\(codingPath).stickersSectionText"),
panelContentOpaqueSearchOverlayHighlightColor: try decodeColor(values, .panelContentOpaqueSearchOverlayHighlight, fallbackKey: "\(codingPath).panelHighlightedIconBg"),
stickersBackgroundColor: try decodeColor(values, .stickersBg),
stickersSectionTextColor: try decodeColor(values, .stickersSectionText),
stickersSearchBackgroundColor: try decodeColor(values, .stickersSearchBg),
stickersSearchPlaceholderColor: try decodeColor(values, .stickersSearchPlaceholder),
stickersSearchPrimaryColor: try decodeColor(values, .stickersSearchPrimary),
stickersSearchControlColor: try decodeColor(values, .stickersSearchControl),
gifsBackgroundColor: try decodeColor(values, .gifsBg), backgroundColor: backgroundColor)
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.panelSeparatorColor, .panelSeparator)
try encodeColor(&values, self.panelIconColor, .panelIcon)
try encodeColor(&values, self.panelHighlightedIconBackgroundColor, .panelHighlightedIconBg)
try encodeColor(&values, self.panelHighlightedIconColor, .panelHighlightedIcon)
try encodeColor(&values, self.panelContentVibrantOverlayColor, .panelContentVibrantOverlay)
try encodeColor(&values, self.panelContentControlVibrantOverlayColor, .panelContentControlVibrantOverlay)
try encodeColor(&values, self.panelContentControlVibrantSelectionColor, .panelContentControlVibrantSelection)
try encodeColor(&values, self.panelContentControlOpaqueOverlayColor, .panelContentControlOpaqueOverlay)
try encodeColor(&values, self.panelContentControlOpaqueSelectionColor, .panelContentControlOpaqueSelection)
try encodeColor(&values, self.panelContentVibrantSearchOverlayColor, .panelContentVibrantSearchOverlay)
try encodeColor(&values, self.panelContentVibrantSearchOverlaySelectedColor, .panelContentVibrantSearchOverlaySelected)
try encodeColor(&values, self.panelContentVibrantSearchOverlayHighlightColor, .panelContentVibrantSearchOverlayHighlight)
try encodeColor(&values, self.panelContentOpaqueSearchOverlayColor, .panelContentOpaqueSearchOverlay)
try encodeColor(&values, self.panelContentOpaqueSearchOverlaySelectedColor, .panelContentOpaqueSearchOverlaySelected)
try encodeColor(&values, self.panelContentOpaqueSearchOverlayHighlightColor, .panelContentOpaqueSearchOverlayHighlight)
try encodeColor(&values, self.stickersBackgroundColor, .stickersBg)
try encodeColor(&values, self.stickersSectionTextColor, .stickersSectionText)
try encodeColor(&values, self.stickersSearchBackgroundColor, .stickersSearchBg)
try encodeColor(&values, self.stickersSearchPlaceholderColor, .stickersSearchPlaceholder)
try encodeColor(&values, self.stickersSearchPrimaryColor, .stickersSearchPrimary)
try encodeColor(&values, self.stickersSearchControlColor, .stickersSearchControl)
try encodeColor(&values, self.gifsBackgroundColor, .gifsBg)
try encodeColor(&values, self.backgroundColor, .bg)
}
}
extension PresentationThemeInputButtonPanel: Codable {
enum CodingKeys: String, CodingKey {
case panelBg
case panelSeparator
case buttonBg
case buttonHighlight
case buttonStroke
case buttonHighlightedBg
case buttonHighlightedStroke
case buttonText
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(panelSeparatorColor: try decodeColor(values, .panelSeparator),
panelBackgroundColor: try decodeColor(values, .panelBg),
buttonFillColor: try decodeColor(values, .buttonBg),
buttonHighlightColor: try decodeColor(values, .buttonHighlight),
buttonStrokeColor: try decodeColor(values, .buttonStroke),
buttonHighlightedFillColor: try decodeColor(values, .buttonHighlightedBg),
buttonHighlightedStrokeColor: try decodeColor(values, .buttonHighlightedStroke),
buttonTextColor: try decodeColor(values, .buttonText))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.panelBackgroundColor, .panelBg)
try encodeColor(&values, self.panelSeparatorColor, .panelSeparator)
try encodeColor(&values, self.buttonFillColor, .buttonBg)
try encodeColor(&values, self.buttonHighlightColor, .buttonHighlight)
try encodeColor(&values, self.buttonStrokeColor, .buttonStroke)
try encodeColor(&values, self.buttonHighlightedFillColor, .buttonHighlightedBg)
try encodeColor(&values, self.buttonHighlightedStrokeColor, .buttonHighlightedStroke)
try encodeColor(&values, self.buttonTextColor, .buttonText)
}
}
extension PresentationThemeChatHistoryNavigation: Codable {
enum CodingKeys: String, CodingKey {
case bg
case stroke
case fg
case badgeBg
case badgeStroke
case badgeText
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(fillColor: try decodeColor(values, .bg),
strokeColor: try decodeColor(values, .stroke),
foregroundColor: try decodeColor(values, .fg),
badgeBackgroundColor: try decodeColor(values, .badgeBg),
badgeStrokeColor: try decodeColor(values, .badgeStroke),
badgeTextColor: try decodeColor(values, .badgeText))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.fillColor, .bg)
try encodeColor(&values, self.strokeColor, .stroke)
try encodeColor(&values, self.foregroundColor, .fg)
try encodeColor(&values, self.badgeBackgroundColor, .badgeBg)
try encodeColor(&values, self.badgeStrokeColor, .badgeStroke)
try encodeColor(&values, self.badgeTextColor, .badgeText)
}
}
extension PresentationThemeChat: Codable {
enum CodingKeys: String, CodingKey {
case defaultWallpaper
case message
case animateMessageColors
case serviceMessage
case inputPanel
case inputMediaPanel
case inputButtonPanel
case historyNav
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
var wallpaper = (try values.decode(TelegramWallpaperStandardizedCodable.self, forKey: .defaultWallpaper)).value
if let decoder = decoder as? PresentationThemeDecoding {
if case .file = wallpaper, let resolvedWallpaper = decoder.resolvedWallpaper {
wallpaper = resolvedWallpaper
}
}
self.init(defaultWallpaper: wallpaper,
animateMessageColors: (try? values.decode(Bool.self, forKey: .animateMessageColors)) ?? false,
message: try values.decode(PresentationThemeChatMessage.self, forKey: .message),
serviceMessage: try values.decode(PresentationThemeServiceMessage.self, forKey: .serviceMessage),
inputPanel: try values.decode(PresentationThemeChatInputPanel.self, forKey: .inputPanel),
inputMediaPanel: try values.decode(PresentationThemeInputMediaPanel.self, forKey: .inputMediaPanel),
inputButtonPanel: try values.decode(PresentationThemeInputButtonPanel.self, forKey: .inputButtonPanel),
historyNavigation: try values.decode(PresentationThemeChatHistoryNavigation.self, forKey: .historyNav))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try values.encode(TelegramWallpaperStandardizedCodable(self.defaultWallpaper), forKey: .defaultWallpaper)
try values.encode(self.animateMessageColors, forKey: .animateMessageColors)
try values.encode(self.message, forKey: .message)
try values.encode(self.serviceMessage, forKey: .serviceMessage)
try values.encode(self.inputPanel, forKey: .inputPanel)
try values.encode(self.inputMediaPanel, forKey: .inputMediaPanel)
try values.encode(self.inputButtonPanel, forKey: .inputButtonPanel)
try values.encode(self.historyNavigation, forKey: .historyNav)
}
}
extension PresentationThemeExpandedNotificationNavigationBar: Codable {
enum CodingKeys: String, CodingKey {
case background
case primaryText
case control
case separator
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(backgroundColor: try decodeColor(values, .background),
primaryTextColor: try decodeColor(values, .primaryText),
controlColor: try decodeColor(values, .control),
separatorColor: try decodeColor(values, .separator))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.backgroundColor, .background)
try encodeColor(&values, self.primaryTextColor, .primaryText)
try encodeColor(&values, self.controlColor, .control)
try encodeColor(&values, self.separatorColor, .separator)
}
}
extension PresentationThemeExpandedNotification: Codable {
enum CodingKeys: String, CodingKey {
case bgType
case navBar
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(backgroundType: try values.decode(PresentationThemeExpandedNotificationBackgroundType.self, forKey: .bgType),
navigationBar: try values.decode(PresentationThemeExpandedNotificationNavigationBar.self, forKey: .navBar))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try values.encode(self.backgroundType, forKey: .bgType)
try values.encode(self.navigationBar, forKey: .navBar)
}
}
extension PresentationThemeContextMenu: Codable {
enum CodingKeys: String, CodingKey {
case dim
case background
case itemSeparator
case sectionSeparator
case itemBg
case itemHighlightedBg
case primary
case secondary
case destructive
case badgeFill
case badgeForeground
case badgeInactiveFill
case badgeInactiveForeground
case extractedTint
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
let destructiveColor = try decodeColor(values, .destructive)
let backgroundColor = try decodeColor(values, .background)
self.init(
dimColor: try decodeColor(values, .dim),
backgroundColor: backgroundColor,
itemSeparatorColor: try decodeColor(values, .itemSeparator),
sectionSeparatorColor: try decodeColor(values, .sectionSeparator),
itemBackgroundColor: try decodeColor(values, .itemBg),
itemHighlightedBackgroundColor: try decodeColor(values, .itemHighlightedBg),
primaryColor: try decodeColor(values, .primary),
secondaryColor: try decodeColor(values, .secondary),
destructiveColor: destructiveColor,
badgeFillColor: (try? decodeColor(values, .badgeFill)) ?? destructiveColor,
badgeForegroundColor: (try? decodeColor(values, .badgeForeground)) ?? backgroundColor,
badgeInactiveFillColor: (try? decodeColor(values, .badgeInactiveFill)) ?? destructiveColor,
badgeInactiveForegroundColor: (try? decodeColor(values, .badgeInactiveForeground)) ?? backgroundColor,
extractedContentTintColor: (try? decodeColor(values, .extractedTint)) ?? backgroundColor
)
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.dimColor, .dim)
try encodeColor(&values, self.backgroundColor, .background)
try encodeColor(&values, self.itemSeparatorColor, .itemSeparator)
try encodeColor(&values, self.sectionSeparatorColor, .sectionSeparator)
try encodeColor(&values, self.itemBackgroundColor, .itemBg)
try encodeColor(&values, self.itemHighlightedBackgroundColor, .itemHighlightedBg)
try encodeColor(&values, self.primaryColor, .primary)
try encodeColor(&values, self.secondaryColor, .secondary)
try encodeColor(&values, self.destructiveColor, .destructive)
}
}
extension PresentationThemeInAppNotification: Codable {
enum CodingKeys: String, CodingKey {
case bg
case primaryText
case expanded
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(fillColor: try decodeColor(values, .bg),
primaryTextColor: try decodeColor(values, .primaryText),
expandedNotification: try values.decode(PresentationThemeExpandedNotification.self, forKey: .expanded))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.fillColor, .bg)
try encodeColor(&values, self.primaryTextColor, .primaryText)
try values.encode(self.expandedNotification, forKey: .expanded)
}
}
extension PresentationThemeChart: Codable {
enum CodingKeys: String, CodingKey {
case labels
case helperLines
case strongLines
case barStrongLines
case detailsText
case detailsArrow
case detailsView
case rangeViewFrame
case rangeViewMarker
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.init(labelsColor: try decodeColor(values, .labels), helperLinesColor: try decodeColor(values, .helperLines), strongLinesColor: try decodeColor(values, .strongLines), barStrongLinesColor: try decodeColor(values, .barStrongLines), detailsTextColor: try decodeColor(values, .detailsText), detailsArrowColor: try decodeColor(values, .detailsArrow), detailsViewColor: try decodeColor(values, .detailsView), rangeViewFrameColor: try decodeColor(values, .rangeViewFrame), rangeViewMarkerColor: try decodeColor(values, .rangeViewMarker))
}
public func encode(to encoder: Encoder) throws {
var values = encoder.container(keyedBy: CodingKeys.self)
try encodeColor(&values, self.labelsColor, .labels)
try encodeColor(&values, self.helperLinesColor, .helperLines)
try encodeColor(&values, self.strongLinesColor, .strongLines)
try encodeColor(&values, self.barStrongLinesColor, .barStrongLines)
try encodeColor(&values, self.detailsTextColor, .detailsText)
try encodeColor(&values, self.detailsArrowColor, .detailsArrow)
try encodeColor(&values, self.detailsViewColor, .detailsView)
try encodeColor(&values, self.rangeViewFrameColor, .rangeViewFrame)
try encodeColor(&values, self.rangeViewMarkerColor, .rangeViewMarker)
}
}
extension PresentationThemeName: Codable {
public init(from decoder: Decoder) throws {
let value = try decoder.singleValueContainer()
self = .custom(try value.decode(String.self))
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case let .builtin(name):
switch name {
case .day:
try container.encode("Day")
case .dayClassic:
try container.encode("Classic")
case .nightAccent:
try container.encode("Night Tinted")
case .night:
try container.encode("Night")
}
case let .custom(name):
try container.encode(name)
}
}
}
extension PresentationBuiltinThemeReference: Codable {
public init(from decoder: Decoder) throws {
let values = try decoder.singleValueContainer()
if let value = try? values.decode(String.self) {
switch value.lowercased() {
case "day":
self = .day
case "classic":
self = .dayClassic
case "nighttinted":
self = .nightAccent
case "night":
self = .night
default:
self = .dayClassic
}
} else {
self = .dayClassic
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .day:
try container.encode("day")
case .dayClassic:
try container.encode("classic")
case .nightAccent:
try container.encode("nighttinted")
case .night:
try container.encode("night")
}
}
}
extension PresentationTheme: Codable {
enum CodingKeys: String, CodingKey {
case name
case basedOn
case dark
case intro
case passcode
case root
case list
case chatList
case chat
case actionSheet
case contextMenu
case notification
case chart
}
public convenience init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
let referenceTheme: PresentationBuiltinThemeReference
if let theme = try? values.decode(PresentationBuiltinThemeReference.self, forKey: .basedOn) {
referenceTheme = theme
} else {
referenceTheme = .dayClassic
}
let index: Int64
if let decoder = decoder as? PresentationThemeDecoding {
let serviceBackgroundColor = decoder.serviceBackgroundColor ?? defaultServiceBackgroundColor
decoder.referenceTheme = makeDefaultPresentationTheme(reference: referenceTheme, serviceBackgroundColor: serviceBackgroundColor)
index = decoder.reference?.index ?? Int64.random(in: Int64.min ... Int64.max)
} else {
index = Int64.random(in: Int64.min ... Int64.max)
}
self.init(name: (try? values.decode(PresentationThemeName.self, forKey: .name)) ?? .custom("Untitled"),
index: index,
referenceTheme: referenceTheme,
overallDarkAppearance: (try? values.decode(Bool.self, forKey: .dark)) ?? false,
intro: try values.decode(PresentationThemeIntro.self, forKey: .intro),
passcode: try values.decode(PresentationThemePasscode.self, forKey: .passcode),
rootController: try values.decode(PresentationThemeRootController.self, forKey: .root),
list: try values.decode(PresentationThemeList.self, forKey: .list),
chatList: try values.decode(PresentationThemeChatList.self, forKey: .chatList),
chat: try values.decode(PresentationThemeChat.self, forKey: .chat),
actionSheet: try values.decode(PresentationThemeActionSheet.self, forKey: .actionSheet),
contextMenu: try values.decode(PresentationThemeContextMenu.self, forKey: .contextMenu),
inAppNotification: try values.decode(PresentationThemeInAppNotification.self, forKey: .notification),
chart: try values.decode(PresentationThemeChart.self, forKey: .chart)
)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.name, forKey: .name)
try container.encode(self.referenceTheme, forKey: .basedOn)
try container.encode(self.overallDarkAppearance, forKey: .dark)
try container.encode(self.intro, forKey: .intro)
try container.encode(self.passcode, forKey: .passcode)
try container.encode(self.rootController, forKey: .root)
try container.encode(self.list, forKey: .list)
try container.encode(self.chatList, forKey: .chatList)
try container.encode(self.chat, forKey: .chat)
try container.encode(self.actionSheet, forKey: .actionSheet)
try container.encode(self.contextMenu, forKey: .contextMenu)
try container.encode(self.inAppNotification, forKey: .notification)
try container.encode(self.chart, forKey: .chart)
}
}