2025-05-21 18:35:07 +03:00

371 lines
15 KiB
Swift

import SGSimpleSettings
import Foundation
import UIKit
import TelegramCore
private extension PeerNameColors.Colors {
init?(colors: EngineAvailableColorOptions.MultiColorPack) {
if colors.colors.isEmpty {
return nil
}
self._main = UIColor(rgb: colors.colors[0])
if colors.colors.count > 1 {
self._secondary = UIColor(rgb: colors.colors[1])
} else {
self._secondary = nil
}
if colors.colors.count > 2 {
self._tertiary = UIColor(rgb: colors.colors[2])
} else {
self._tertiary = nil
}
}
}
public class PeerNameColors: Equatable {
public enum Subject {
case background
case palette
case stories
}
public struct Colors: Equatable {
private let _main: UIColor
private let _secondary: UIColor?
private let _tertiary: UIColor?
// MARK: Swiftgram
public var main: UIColor {
let currentSaturation = SGSimpleSettings.shared.accountColorsSaturation
if currentSaturation == 0 {
return _main
} else {
return _main.withReducedSaturation(CGFloat(currentSaturation) / 100.0)
}
}
public var secondary: UIColor? {
let currentSaturation = SGSimpleSettings.shared.accountColorsSaturation
if currentSaturation == 0 {
return _secondary
} else {
return _secondary?.withReducedSaturation(CGFloat(currentSaturation) / 100.0)
}
}
public var tertiary: UIColor? {
let currentSaturation = SGSimpleSettings.shared.accountColorsSaturation
if currentSaturation == 0 {
return _tertiary
} else {
return _tertiary?.withReducedSaturation(CGFloat(currentSaturation) / 100.0)
}
}
public init(main: UIColor, secondary: UIColor?, tertiary: UIColor?) {
self._main = main
self._secondary = secondary
self._tertiary = tertiary
}
public init(main: UIColor) {
self._main = main
self._secondary = nil
self._tertiary = nil
}
public init?(colors: [UIColor]) {
guard let first = colors.first else {
return nil
}
self._main = first
if colors.count == 3 {
self._secondary = colors[1]
self._tertiary = colors[2]
} else if colors.count == 2, let second = colors.last {
self._secondary = second
self._tertiary = nil
} else {
self._secondary = nil
self._tertiary = nil
}
}
}
public static var defaultSingleColors: [Int32: Colors] {
return [
0: Colors(main: UIColor(rgb: 0xcc5049)),
1: Colors(main: UIColor(rgb: 0xd67722)),
2: Colors(main: UIColor(rgb: 0x955cdb)),
3: Colors(main: UIColor(rgb: 0x40a920)),
4: Colors(main: UIColor(rgb: 0x309eba)),
5: Colors(main: UIColor(rgb: 0x368ad1)),
6: Colors(main: UIColor(rgb: 0xc7508b))
]
}
public static var defaultValue: PeerNameColors {
return PeerNameColors(
colors: defaultSingleColors,
darkColors: [:],
displayOrder: [5, 3, 1, 0, 2, 4, 6],
chatFolderTagDisplayOrder: [5, 3, 1, 0, 2, 4, 6],
profileColors: [:],
profileDarkColors: [:],
profilePaletteColors: [:],
profilePaletteDarkColors: [:],
profileStoryColors: [:],
profileStoryDarkColors: [:],
profileDisplayOrder: [],
nameColorsChannelMinRequiredBoostLevel: [:],
profileColorsChannelMinRequiredBoostLevel: [:],
profileColorsGroupMinRequiredBoostLevel: [:]
)
}
public let colors: [Int32: Colors]
public let darkColors: [Int32: Colors]
public let displayOrder: [Int32]
public let chatFolderTagDisplayOrder: [Int32]
public let profileColors: [Int32: Colors]
public let profileDarkColors: [Int32: Colors]
public let profilePaletteColors: [Int32: Colors]
public let profilePaletteDarkColors: [Int32: Colors]
public let profileStoryColors: [Int32: Colors]
public let profileStoryDarkColors: [Int32: Colors]
public let profileDisplayOrder: [Int32]
public let nameColorsChannelMinRequiredBoostLevel: [Int32: Int32]
public let profileColorsChannelMinRequiredBoostLevel: [Int32: Int32]
public let profileColorsGroupMinRequiredBoostLevel: [Int32: Int32]
public func get(_ color: PeerNameColor, dark: Bool = false) -> Colors {
if dark, let colors = self.darkColors[color.rawValue] {
return colors
} else if let colors = self.colors[color.rawValue] {
return colors
} else {
return PeerNameColors.defaultSingleColors[5]!
}
}
public func getChatFolderTag(_ color: PeerNameColor, dark: Bool = false) -> Colors {
if dark, let colors = self.darkColors[color.rawValue] {
return colors
} else if let colors = self.colors[color.rawValue] {
return colors
} else {
return PeerNameColors.defaultSingleColors[5]!
}
}
public func getProfile(_ color: PeerNameColor, dark: Bool = false, subject: Subject = .background) -> Colors {
switch subject {
case .background:
if dark, let colors = self.profileDarkColors[color.rawValue] {
return colors
} else if let colors = self.profileColors[color.rawValue] {
return colors
} else {
return Colors(main: UIColor(rgb: 0xcc5049))
}
case .palette:
if dark, let colors = self.profilePaletteDarkColors[color.rawValue] {
return colors
} else if let colors = self.profilePaletteColors[color.rawValue] {
return colors
} else {
return self.getProfile(color, dark: dark, subject: .background)
}
case .stories:
if dark, let colors = self.profileStoryDarkColors[color.rawValue] {
return colors
} else if let colors = self.profileStoryColors[color.rawValue] {
return colors
} else {
return self.getProfile(color, dark: dark, subject: .background)
}
}
}
fileprivate init(
colors: [Int32: Colors],
darkColors: [Int32: Colors],
displayOrder: [Int32],
chatFolderTagDisplayOrder: [Int32],
profileColors: [Int32: Colors],
profileDarkColors: [Int32: Colors],
profilePaletteColors: [Int32: Colors],
profilePaletteDarkColors: [Int32: Colors],
profileStoryColors: [Int32: Colors],
profileStoryDarkColors: [Int32: Colors],
profileDisplayOrder: [Int32],
nameColorsChannelMinRequiredBoostLevel: [Int32: Int32],
profileColorsChannelMinRequiredBoostLevel: [Int32: Int32],
profileColorsGroupMinRequiredBoostLevel: [Int32: Int32]
) {
self.colors = colors
self.darkColors = darkColors
self.displayOrder = displayOrder
self.chatFolderTagDisplayOrder = chatFolderTagDisplayOrder
self.profileColors = profileColors
self.profileDarkColors = profileDarkColors
self.profilePaletteColors = profilePaletteColors
self.profilePaletteDarkColors = profilePaletteDarkColors
self.profileStoryColors = profileStoryColors
self.profileStoryDarkColors = profileStoryDarkColors
self.profileDisplayOrder = profileDisplayOrder
self.nameColorsChannelMinRequiredBoostLevel = nameColorsChannelMinRequiredBoostLevel
self.profileColorsChannelMinRequiredBoostLevel = profileColorsChannelMinRequiredBoostLevel
self.profileColorsGroupMinRequiredBoostLevel = profileColorsGroupMinRequiredBoostLevel
}
public static func with(availableReplyColors: EngineAvailableColorOptions, availableProfileColors: EngineAvailableColorOptions) -> PeerNameColors {
var colors: [Int32: Colors] = [:]
var darkColors: [Int32: Colors] = [:]
var displayOrder: [Int32] = []
var profileColors: [Int32: Colors] = [:]
var profileDarkColors: [Int32: Colors] = [:]
var profilePaletteColors: [Int32: Colors] = [:]
var profilePaletteDarkColors: [Int32: Colors] = [:]
var profileStoryColors: [Int32: Colors] = [:]
var profileStoryDarkColors: [Int32: Colors] = [:]
var profileDisplayOrder: [Int32] = []
var nameColorsChannelMinRequiredBoostLevel: [Int32: Int32] = [:]
var profileColorsChannelMinRequiredBoostLevel: [Int32: Int32] = [:]
var profileColorsGroupMinRequiredBoostLevel: [Int32: Int32] = [:]
if !availableReplyColors.options.isEmpty {
for option in availableReplyColors.options {
if let requiredChannelMinBoostLevel = option.value.requiredChannelMinBoostLevel {
nameColorsChannelMinRequiredBoostLevel[option.key] = requiredChannelMinBoostLevel
}
if let parsedLight = PeerNameColors.Colors(colors: option.value.light.background) {
colors[option.key] = parsedLight
}
if let parsedDark = (option.value.dark?.background).flatMap(PeerNameColors.Colors.init(colors:)) {
darkColors[option.key] = parsedDark
}
for option in availableReplyColors.options {
if !displayOrder.contains(option.key) {
displayOrder.append(option.key)
}
}
}
} else {
let defaultValue = PeerNameColors.defaultValue
colors = defaultValue.colors
darkColors = defaultValue.darkColors
displayOrder = defaultValue.displayOrder
}
if !availableProfileColors.options.isEmpty {
for option in availableProfileColors.options {
if let requiredChannelMinBoostLevel = option.value.requiredChannelMinBoostLevel {
profileColorsChannelMinRequiredBoostLevel[option.key] = requiredChannelMinBoostLevel
}
if let requiredGroupMinBoostLevel = option.value.requiredGroupMinBoostLevel {
profileColorsGroupMinRequiredBoostLevel[option.key] = requiredGroupMinBoostLevel
}
if let parsedLight = PeerNameColors.Colors(colors: option.value.light.background) {
profileColors[option.key] = parsedLight
}
if let parsedDark = (option.value.dark?.background).flatMap(PeerNameColors.Colors.init(colors:)) {
profileDarkColors[option.key] = parsedDark
}
if let parsedPaletteLight = PeerNameColors.Colors(colors: option.value.light.palette) {
profilePaletteColors[option.key] = parsedPaletteLight
}
if let parsedPaletteDark = (option.value.dark?.palette).flatMap(PeerNameColors.Colors.init(colors:)) {
profilePaletteDarkColors[option.key] = parsedPaletteDark
}
if let parsedStoryLight = (option.value.light.stories).flatMap(PeerNameColors.Colors.init(colors:)) {
profileStoryColors[option.key] = parsedStoryLight
}
if let parsedStoryDark = (option.value.dark?.stories).flatMap(PeerNameColors.Colors.init(colors:)) {
profileStoryDarkColors[option.key] = parsedStoryDark
}
for option in availableProfileColors.options {
if !profileDisplayOrder.contains(option.key) {
profileDisplayOrder.append(option.key)
}
}
}
}
return PeerNameColors(
colors: colors,
darkColors: darkColors,
displayOrder: displayOrder,
chatFolderTagDisplayOrder: PeerNameColors.defaultValue.chatFolderTagDisplayOrder,
profileColors: profileColors,
profileDarkColors: profileDarkColors,
profilePaletteColors: profilePaletteColors,
profilePaletteDarkColors: profilePaletteDarkColors,
profileStoryColors: profileStoryColors,
profileStoryDarkColors: profileStoryDarkColors,
profileDisplayOrder: profileDisplayOrder,
nameColorsChannelMinRequiredBoostLevel: nameColorsChannelMinRequiredBoostLevel,
profileColorsChannelMinRequiredBoostLevel: profileColorsChannelMinRequiredBoostLevel,
profileColorsGroupMinRequiredBoostLevel: profileColorsGroupMinRequiredBoostLevel
)
}
public static func == (lhs: PeerNameColors, rhs: PeerNameColors) -> Bool {
if lhs.colors != rhs.colors {
return false
}
if lhs.darkColors != rhs.darkColors {
return false
}
if lhs.displayOrder != rhs.displayOrder {
return false
}
if lhs.chatFolderTagDisplayOrder != rhs.chatFolderTagDisplayOrder {
return false
}
if lhs.profileColors != rhs.profileColors {
return false
}
if lhs.profileDarkColors != rhs.profileDarkColors {
return false
}
if lhs.profilePaletteColors != rhs.profilePaletteColors {
return false
}
if lhs.profilePaletteDarkColors != rhs.profilePaletteDarkColors {
return false
}
if lhs.profileStoryColors != rhs.profileStoryColors {
return false
}
if lhs.profileStoryDarkColors != rhs.profileStoryDarkColors {
return false
}
if lhs.profileDisplayOrder != rhs.profileDisplayOrder {
return false
}
return true
}
}
// MARK: Swiftgram
extension UIColor {
func withReducedSaturation(_ factor: CGFloat) -> UIColor {
var hue: CGFloat = 0
var saturation: CGFloat = 0
var brightness: CGFloat = 0
var alpha: CGFloat = 0
if self.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha) {
let newSaturation = max(0, min(1, saturation * factor))
return UIColor(hue: hue, saturation: newSaturation, brightness: brightness, alpha: alpha)
}
return self
}
}