This appears to have been a hack for something that may have been necessary in older versions of iOS. Current iOS seems to just return true with no side-effects from this super call so there's no reason to retain this hack apparent.
517 lines
22 KiB
Swift
517 lines
22 KiB
Swift
//
|
|
// Copyright 2021 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
//
|
|
|
|
import Foundation
|
|
import SignalServiceKit
|
|
import UIKit
|
|
|
|
/// Represents the chat color chosen for a particular scope.
|
|
///
|
|
/// Possible scopes (ordered by priority):
|
|
/// (1) Thread: Applies to a specific conversation.
|
|
/// (2) Global: Applies to all other conversations.
|
|
///
|
|
/// On its own, a `ChatColorSetting` may not contain enough information to
|
|
/// compute the color to use for a particular conversation. To compute the
|
|
/// color to use, you generally need the `ChatColorSetting` for both scopes,
|
|
/// the `Wallpaper` for both scopes (which may have their own preferred
|
|
/// color), and the default fallback.
|
|
public enum ChatColorSetting: Equatable {
|
|
case auto
|
|
case builtIn(PaletteChatColor)
|
|
case custom(CustomChatColor.Key, CustomChatColor)
|
|
|
|
public var constantColor: ColorOrGradientSetting? {
|
|
switch self {
|
|
case .auto:
|
|
return nil
|
|
case .builtIn(let value):
|
|
return value.colorSetting
|
|
case .custom(_, let value):
|
|
return value.colorSetting
|
|
}
|
|
}
|
|
|
|
public static func == (lhs: ChatColorSetting, rhs: ChatColorSetting) -> Bool {
|
|
switch (lhs, rhs) {
|
|
case (.auto, .auto):
|
|
return true
|
|
case (.builtIn(let lhs), .builtIn(let rhs)) where lhs.rawValue == rhs.rawValue:
|
|
return true
|
|
case (.custom(let lhs, _), .custom(let rhs, _)) where lhs.rawValue == rhs.rawValue:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
public struct CustomChatColor: Codable {
|
|
public struct Key {
|
|
public let rawValue: String
|
|
|
|
public static func generateRandom() -> Self {
|
|
return Key(rawValue: UUID().uuidString)
|
|
}
|
|
}
|
|
|
|
public let colorSetting: ColorOrGradientSetting
|
|
public let creationTimestamp: UInt64
|
|
|
|
public init(colorSetting: ColorOrGradientSetting, creationTimestamp: UInt64) {
|
|
self.colorSetting = colorSetting
|
|
self.creationTimestamp = creationTimestamp
|
|
}
|
|
|
|
private enum CodingKeys: String, CodingKey {
|
|
case colorSetting = "setting"
|
|
case creationTimestamp
|
|
|
|
// Deprecated keys that may still exist in values stored in the database:
|
|
// - "id"
|
|
// - "isBuiltIn"
|
|
// - "updateTimestamp"
|
|
}
|
|
}
|
|
|
|
// MARK: -
|
|
|
|
public class ChatColors: Dependencies {
|
|
public enum Constants {
|
|
fileprivate static let globalKey = "defaultKey"
|
|
public static let defaultColor: PaletteChatColor = .ultramarine
|
|
}
|
|
|
|
public init() {
|
|
SwiftSingletons.register(self)
|
|
}
|
|
|
|
/// The keys in this store are `CustomChatColor.Key`. The values are
|
|
/// `CustomChatColor`s.
|
|
private static let customColorsStore = SDSKeyValueStore(collection: "customColorsStore.3")
|
|
|
|
public func fetchCustomValues(tx: SDSAnyReadTransaction) -> [(key: CustomChatColor.Key, value: CustomChatColor)] {
|
|
var customChatColors = [(key: CustomChatColor.Key, value: CustomChatColor)]()
|
|
for key in Self.customColorsStore.allKeys(transaction: tx) {
|
|
let colorKey = CustomChatColor.Key(rawValue: key)
|
|
guard let colorValue = Self.fetchCustomValue(for: colorKey, tx: tx) else { continue }
|
|
customChatColors.append((colorKey, colorValue))
|
|
}
|
|
return customChatColors.sorted(by: { $0.value.creationTimestamp < $1.value.creationTimestamp })
|
|
}
|
|
|
|
public static func fetchCustomValue(for key: CustomChatColor.Key, tx: SDSAnyReadTransaction) -> CustomChatColor? {
|
|
do {
|
|
return try customColorsStore.getCodableValue(forKey: key.rawValue, transaction: tx)
|
|
} catch {
|
|
owsFailDebug("Couldn't decode custom color: \(error)")
|
|
return nil
|
|
}
|
|
}
|
|
|
|
public func upsertCustomValue(_ value: CustomChatColor, for key: CustomChatColor.Key, tx: SDSAnyWriteTransaction) {
|
|
do {
|
|
try Self.customColorsStore.setCodable(value, key: key.rawValue, transaction: tx)
|
|
} catch {
|
|
owsFailDebug("Couldn't save custom color: \(error)")
|
|
}
|
|
Self.postChatColorsDidChangeNotification(for: nil, tx: tx)
|
|
}
|
|
|
|
public func deleteCustomValue(for key: CustomChatColor.Key, tx: SDSAnyWriteTransaction) {
|
|
Self.customColorsStore.removeValue(forKey: key.rawValue, transaction: tx)
|
|
Self.postChatColorsDidChangeNotification(for: nil, tx: tx)
|
|
}
|
|
|
|
/// Returns the number of conversations that use a given value.
|
|
public static func usageCount(of colorKey: CustomChatColor.Key, tx: SDSAnyReadTransaction) -> Int {
|
|
let chatColorSettingStore = DependenciesBridge.shared.chatColorSettingStore
|
|
var count: Int = 0
|
|
for scopeKey in chatColorSettingStore.fetchAllScopeKeys(tx: tx.asV2Read) {
|
|
if colorKey.rawValue == chatColorSettingStore.fetchRawSetting(for: scopeKey, tx: tx.asV2Read) {
|
|
count += 1
|
|
}
|
|
}
|
|
return count
|
|
}
|
|
|
|
/// The color that should actually be used when rendering messages.
|
|
///
|
|
/// - Parameters:
|
|
/// - previewWallpaper: If provided, use this `Wallpaper` rather than the
|
|
/// one that's currently assigned. This is useful if you want to preview
|
|
/// the rendered color when selecting `Wallpaper`. (The logic is more
|
|
/// complicated than checking the color for the `Wallpaper` since it may
|
|
/// be overridden by an explicit color that takes precedence.)
|
|
///
|
|
/// - Returns: The color to use for outgoing message bubbles.
|
|
public static func resolvedChatColor(
|
|
for thread: TSThread?,
|
|
previewWallpaper: Wallpaper? = nil,
|
|
tx: SDSAnyReadTransaction
|
|
) -> ColorOrGradientSetting {
|
|
if let threadColor = chatColorSetting(for: thread, tx: tx).constantColor {
|
|
return threadColor
|
|
}
|
|
return autoChatColor(for: thread, previewWallpaper: previewWallpaper, tx: tx)
|
|
}
|
|
|
|
/// The color that should be rendered in the "auto" bubble in the chat color editor.
|
|
///
|
|
/// For the global scope, this will either be the wallpaper color or the
|
|
/// default fallback.
|
|
///
|
|
/// For the thread scope, this might be the global color, global wallpaper,
|
|
/// thread wallpaper, or default fallback.
|
|
public static func autoChatColor(for thread: TSThread?, tx: SDSAnyReadTransaction) -> ColorOrGradientSetting {
|
|
return autoChatColor(for: thread, previewWallpaper: nil, tx: tx)
|
|
}
|
|
|
|
private static func autoChatColor(
|
|
for thread: TSThread?,
|
|
previewWallpaper: Wallpaper?,
|
|
tx: SDSAnyReadTransaction
|
|
) -> ColorOrGradientSetting {
|
|
// If we're editing the color for a specific thread, then we'll prefer the
|
|
// globally-selected value instead of both the thread-specific and global
|
|
// wallpaper values.
|
|
if thread != nil, let globalColor = chatColorSetting(for: nil, tx: tx).constantColor {
|
|
return globalColor
|
|
}
|
|
let resolvedWallpaper = previewWallpaper ?? Wallpaper.wallpaperForRendering(for: thread, transaction: tx)
|
|
if let wallpaperColor = resolvedWallpaper?.defaultChatColor {
|
|
return wallpaperColor.colorSetting
|
|
}
|
|
return Constants.defaultColor.colorSetting
|
|
}
|
|
|
|
/// The currently-chosen setting for a particular scope.
|
|
///
|
|
/// This doesn't always contain enough information to render a color on the
|
|
/// screen. For example, a user may choose `.auto`, in which case you need
|
|
/// to run additional logic to determine which color corresponds to `.auto`.
|
|
public static func chatColorSetting(for thread: TSThread?, tx: SDSAnyReadTransaction) -> ChatColorSetting {
|
|
let chatColorSettingStore = DependenciesBridge.shared.chatColorSettingStore
|
|
let persistenceKey: String = thread?.uniqueId ?? Constants.globalKey
|
|
guard let valueId = chatColorSettingStore.fetchRawSetting(for: persistenceKey, tx: tx.asV2Read) else {
|
|
return .auto
|
|
}
|
|
if let paletteChatColor = PaletteChatColor(rawValue: valueId) {
|
|
return .builtIn(paletteChatColor)
|
|
}
|
|
let customColorKey = CustomChatColor.Key(rawValue: valueId)
|
|
if let customChatColor = Self.fetchCustomValue(for: customColorKey, tx: tx) {
|
|
return .custom(customColorKey, customChatColor)
|
|
}
|
|
// This isn't necessarily an error. A user might apply a custom chat color
|
|
// value to a conversation (or the global default), then delete the custom
|
|
// chat color value. In that case, all references to the value should
|
|
// behave as "auto" (the default).
|
|
return .auto
|
|
}
|
|
|
|
public static let chatColorsDidChangeNotification = NSNotification.Name("chatColorsDidChange")
|
|
|
|
public static func setChatColorSetting(_ value: ChatColorSetting, for thread: TSThread?, tx: SDSAnyWriteTransaction) {
|
|
let chatColorSettingStore = DependenciesBridge.shared.chatColorSettingStore
|
|
chatColorSettingStore.setRawSetting({ () -> String? in
|
|
switch value {
|
|
case .auto:
|
|
return nil
|
|
case .builtIn(let paletteChatColor):
|
|
return paletteChatColor.rawValue
|
|
case .custom(let colorKey, _):
|
|
return colorKey.rawValue
|
|
}
|
|
}(), for: thread?.uniqueId ?? Constants.globalKey, tx: tx.asV2Write)
|
|
postChatColorsDidChangeNotification(for: thread, tx: tx)
|
|
}
|
|
|
|
public static func resetAllSettings(transaction tx: SDSAnyWriteTransaction) {
|
|
DependenciesBridge.shared.chatColorSettingStore.resetAllSettings(tx: tx.asV2Write)
|
|
postChatColorsDidChangeNotification(for: nil, tx: tx)
|
|
}
|
|
|
|
private static func postChatColorsDidChangeNotification(for thread: TSThread?, tx: SDSAnyWriteTransaction) {
|
|
let threadUniqueId = thread?.uniqueId
|
|
tx.addAsyncCompletionOnMain {
|
|
NotificationCenter.default.post(name: chatColorsDidChangeNotification, object: threadUniqueId)
|
|
}
|
|
}
|
|
|
|
// MARK: -
|
|
}
|
|
|
|
public enum PaletteChatColor: String, CaseIterable {
|
|
// Default
|
|
case ultramarine = "Ultramarine"
|
|
|
|
// Solid Colors
|
|
case crimson = "Crimson"
|
|
case vermilion = "Vermilion"
|
|
case burlap = "Burlap"
|
|
case forest = "Forest"
|
|
case wintergreen = "Wintergreen"
|
|
case teal = "Teal"
|
|
case blue = "Blue"
|
|
case indigo = "Indigo"
|
|
case violet = "Violet"
|
|
case plum = "Plum"
|
|
case taupe = "Taupe"
|
|
case steel = "Steel"
|
|
|
|
// Gradients
|
|
case ember = "Ember"
|
|
case midnight = "Midnight"
|
|
case infrared = "Infrared"
|
|
case lagoon = "Lagoon"
|
|
case fluorescent = "Fluorescent"
|
|
case basil = "Basil"
|
|
case sublime = "Sublime"
|
|
case sea = "Sea"
|
|
case tangerine = "Tangerine"
|
|
|
|
private static func parseAngleDegreesFromSpec(_ angleDegreesFromSpec: CGFloat) -> CGFloat {
|
|
// In our models:
|
|
// If angleRadians = 0, gradientColor1 is N.
|
|
// If angleRadians = PI / 2, gradientColor1 is E.
|
|
// etc.
|
|
//
|
|
// In the spec:
|
|
// If angleDegrees = 180, gradientColor1 is N.
|
|
// If angleDegrees = 270, gradientColor1 is E.
|
|
// etc.
|
|
return ((angleDegreesFromSpec - 180) / 180) * CGFloat.pi
|
|
}
|
|
|
|
public var colorSetting: ColorOrGradientSetting {
|
|
switch self {
|
|
case .ultramarine:
|
|
return .gradient(
|
|
gradientColor1: UIColor(rgbHex: 0x0552F0).asOWSColor,
|
|
gradientColor2: UIColor(rgbHex: 0x2C6BED).asOWSColor,
|
|
angleRadians: CGFloat.pi * 0
|
|
)
|
|
case .crimson:
|
|
return .solidColor(color: UIColor(rgbHex: 0xCF163E).asOWSColor)
|
|
case .vermilion:
|
|
return .solidColor(color: UIColor(rgbHex: 0xC73F0A).asOWSColor)
|
|
case .burlap:
|
|
return .solidColor(color: UIColor(rgbHex: 0x6F6A58).asOWSColor)
|
|
case .forest:
|
|
return .solidColor(color: UIColor(rgbHex: 0x3B7845).asOWSColor)
|
|
case .wintergreen:
|
|
return .solidColor(color: UIColor(rgbHex: 0x1D8663).asOWSColor)
|
|
case .teal:
|
|
return .solidColor(color: UIColor(rgbHex: 0x077D92).asOWSColor)
|
|
case .blue:
|
|
return .solidColor(color: UIColor(rgbHex: 0x336BA3).asOWSColor)
|
|
case .indigo:
|
|
return .solidColor(color: UIColor(rgbHex: 0x6058CA).asOWSColor)
|
|
case .violet:
|
|
return .solidColor(color: UIColor(rgbHex: 0x9932C8).asOWSColor)
|
|
case .plum:
|
|
return .solidColor(color: UIColor(rgbHex: 0xAA377A).asOWSColor)
|
|
case .taupe:
|
|
return .solidColor(color: UIColor(rgbHex: 0x8F616A).asOWSColor)
|
|
case .steel:
|
|
return .solidColor(color: UIColor(rgbHex: 0x71717F).asOWSColor)
|
|
case .ember:
|
|
return .gradient(
|
|
gradientColor1: UIColor(rgbHex: 0xE57C00).asOWSColor,
|
|
gradientColor2: UIColor(rgbHex: 0x5E0000).asOWSColor,
|
|
angleRadians: Self.parseAngleDegreesFromSpec(168)
|
|
)
|
|
case .midnight:
|
|
return .gradient(
|
|
gradientColor1: UIColor(rgbHex: 0x2C2C3A).asOWSColor,
|
|
gradientColor2: UIColor(rgbHex: 0x787891).asOWSColor,
|
|
angleRadians: Self.parseAngleDegreesFromSpec(180)
|
|
)
|
|
case .infrared:
|
|
return .gradient(
|
|
gradientColor1: UIColor(rgbHex: 0xF65560).asOWSColor,
|
|
gradientColor2: UIColor(rgbHex: 0x442CED).asOWSColor,
|
|
angleRadians: Self.parseAngleDegreesFromSpec(192)
|
|
)
|
|
case .lagoon:
|
|
return .gradient(
|
|
gradientColor1: UIColor(rgbHex: 0x004066).asOWSColor,
|
|
gradientColor2: UIColor(rgbHex: 0x32867D).asOWSColor,
|
|
angleRadians: Self.parseAngleDegreesFromSpec(180)
|
|
)
|
|
case .fluorescent:
|
|
return .gradient(
|
|
gradientColor1: UIColor(rgbHex: 0xEC13DD).asOWSColor,
|
|
gradientColor2: UIColor(rgbHex: 0x1B36C6).asOWSColor,
|
|
angleRadians: Self.parseAngleDegreesFromSpec(192)
|
|
)
|
|
case .basil:
|
|
return .gradient(
|
|
gradientColor1: UIColor(rgbHex: 0x2F9373).asOWSColor,
|
|
gradientColor2: UIColor(rgbHex: 0x077343).asOWSColor,
|
|
angleRadians: Self.parseAngleDegreesFromSpec(180)
|
|
)
|
|
case .sublime:
|
|
return .gradient(
|
|
gradientColor1: UIColor(rgbHex: 0x6281D5).asOWSColor,
|
|
gradientColor2: UIColor(rgbHex: 0x974460).asOWSColor,
|
|
angleRadians: Self.parseAngleDegreesFromSpec(180)
|
|
)
|
|
case .sea:
|
|
return .gradient(
|
|
gradientColor1: UIColor(rgbHex: 0x498FD4).asOWSColor,
|
|
gradientColor2: UIColor(rgbHex: 0x2C66A0).asOWSColor,
|
|
angleRadians: Self.parseAngleDegreesFromSpec(180)
|
|
)
|
|
case .tangerine:
|
|
return .gradient(
|
|
gradientColor1: UIColor(rgbHex: 0xDB7133).asOWSColor,
|
|
gradientColor2: UIColor(rgbHex: 0x911231).asOWSColor,
|
|
angleRadians: Self.parseAngleDegreesFromSpec(192)
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: -
|
|
|
|
public extension ChatColors {
|
|
|
|
// Represents the "message sender" to "group name color" mapping
|
|
// for a given CVC load.
|
|
struct GroupNameColors {
|
|
fileprivate let colorMap: [SignalServiceAddress: UIColor]
|
|
// TODO: Pending design.
|
|
fileprivate let defaultColor: UIColor
|
|
|
|
public func color(for address: SignalServiceAddress) -> UIColor {
|
|
colorMap[address] ?? defaultColor
|
|
}
|
|
|
|
fileprivate static var defaultColors: GroupNameColors {
|
|
GroupNameColors(colorMap: [:], defaultColor: Theme.primaryTextColor)
|
|
}
|
|
}
|
|
|
|
static func groupNameColors(forThread thread: TSThread) -> GroupNameColors {
|
|
guard let groupThread = thread as? TSGroupThread else {
|
|
return .defaultColors
|
|
}
|
|
let groupMembership = groupThread.groupMembership
|
|
let values = Self.groupNameColorValues
|
|
let isDarkThemeEnabled = Theme.isDarkThemeEnabled
|
|
var lastIndex: Int = 0
|
|
var colorMap = [SignalServiceAddress: UIColor]()
|
|
let addresses = Array(groupMembership.fullMembers).stableSort()
|
|
for (index, address) in addresses.enumerated() {
|
|
let valueIndex = index % values.count
|
|
guard let value = values[safe: valueIndex] else {
|
|
owsFailDebug("Invalid values.")
|
|
return .defaultColors
|
|
}
|
|
colorMap[address] = value.color(isDarkThemeEnabled: isDarkThemeEnabled)
|
|
lastIndex = index
|
|
}
|
|
let defaultValueIndex = (lastIndex + 1) % values.count
|
|
guard let defaultValue = values[safe: defaultValueIndex] else {
|
|
owsFailDebug("Invalid values.")
|
|
return .defaultColors
|
|
}
|
|
let defaultColor = defaultValue.color(isDarkThemeEnabled: isDarkThemeEnabled)
|
|
return GroupNameColors(colorMap: colorMap, defaultColor: defaultColor)
|
|
}
|
|
|
|
private static var defaultGroupNameColor: UIColor {
|
|
let isDarkThemeEnabled = Theme.isDarkThemeEnabled
|
|
return Self.groupNameColorValues.first!.color(isDarkThemeEnabled: isDarkThemeEnabled)
|
|
}
|
|
|
|
fileprivate struct GroupNameColorValue {
|
|
let lightTheme: UIColor
|
|
let darkTheme: UIColor
|
|
|
|
func color(isDarkThemeEnabled: Bool) -> UIColor {
|
|
isDarkThemeEnabled ? darkTheme : lightTheme
|
|
}
|
|
}
|
|
|
|
// In descending order of contrast with the other values.
|
|
fileprivate static let groupNameColorValues: [GroupNameColorValue] = [
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x006DA3),
|
|
darkTheme: UIColor(rgbHex: 0x00A7FA)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x007A3D),
|
|
darkTheme: UIColor(rgbHex: 0x00B85C)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0xC13215),
|
|
darkTheme: UIColor(rgbHex: 0xFF6F52)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0xB814B8),
|
|
darkTheme: UIColor(rgbHex: 0xF65AF6)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x5B6976),
|
|
darkTheme: UIColor(rgbHex: 0x8BA1B6)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x3D7406),
|
|
darkTheme: UIColor(rgbHex: 0x5EB309)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0xCC0066),
|
|
darkTheme: UIColor(rgbHex: 0xF76EB2)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x2E51FF),
|
|
darkTheme: UIColor(rgbHex: 0x8599FF)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x9C5711),
|
|
darkTheme: UIColor(rgbHex: 0xD5920B)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x007575),
|
|
darkTheme: UIColor(rgbHex: 0x00B2B2)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0xD00B4D),
|
|
darkTheme: UIColor(rgbHex: 0xFF6B9C)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x8F2AF4),
|
|
darkTheme: UIColor(rgbHex: 0xBF80FF)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0xD00B0B),
|
|
darkTheme: UIColor(rgbHex: 0xFF7070)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x067906),
|
|
darkTheme: UIColor(rgbHex: 0x0AB80A)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x5151F6),
|
|
darkTheme: UIColor(rgbHex: 0x9494FF)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x866118),
|
|
darkTheme: UIColor(rgbHex: 0xD68F00)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x067953),
|
|
darkTheme: UIColor(rgbHex: 0x00B87A)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0xA20CED),
|
|
darkTheme: UIColor(rgbHex: 0xCF7CF8)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x4B7000),
|
|
darkTheme: UIColor(rgbHex: 0x74AD00)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0xC70A88),
|
|
darkTheme: UIColor(rgbHex: 0xF76EC9)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0xB34209),
|
|
darkTheme: UIColor(rgbHex: 0xF57A3D)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x06792D),
|
|
darkTheme: UIColor(rgbHex: 0x0AB844)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x7A3DF5),
|
|
darkTheme: UIColor(rgbHex: 0xAF8AF9)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x6B6B24),
|
|
darkTheme: UIColor(rgbHex: 0xA4A437)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0xD00B2C),
|
|
darkTheme: UIColor(rgbHex: 0xF77389)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x2D7906),
|
|
darkTheme: UIColor(rgbHex: 0x42B309)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0xAF0BD0),
|
|
darkTheme: UIColor(rgbHex: 0xE06EF7)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x32763E),
|
|
darkTheme: UIColor(rgbHex: 0x4BAF5C)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x2662D9),
|
|
darkTheme: UIColor(rgbHex: 0x7DA1E8)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x76681E),
|
|
darkTheme: UIColor(rgbHex: 0xB89B0A)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x067462),
|
|
darkTheme: UIColor(rgbHex: 0x09B397)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x6447F5),
|
|
darkTheme: UIColor(rgbHex: 0xA18FF9)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x5E6E0C),
|
|
darkTheme: UIColor(rgbHex: 0x8FAA09)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x077288),
|
|
darkTheme: UIColor(rgbHex: 0x00AED1)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0xC20AA3),
|
|
darkTheme: UIColor(rgbHex: 0xF75FDD)),
|
|
GroupNameColorValue(lightTheme: UIColor(rgbHex: 0x2D761E),
|
|
darkTheme: UIColor(rgbHex: 0x43B42D))
|
|
]
|
|
}
|