diff --git a/Tusker/Preferences/Preferences.swift b/Tusker/Preferences/Preferences.swift index 92dd08a2..0f7707fe 100644 --- a/Tusker/Preferences/Preferences.swift +++ b/Tusker/Preferences/Preferences.swift @@ -38,6 +38,7 @@ class Preferences: Codable, ObservableObject { let container = try decoder.container(keyedBy: CodingKeys.self) self.theme = try container.decode(UIUserInterfaceStyle.self, forKey: .theme) + self.accentColor = try container.decodeIfPresent(AccentColor.self, forKey: .accentColor) ?? .default self.avatarStyle = try container.decode(AvatarStyle.self, forKey: .avatarStyle) self.hideCustomEmojiInUsernames = try container.decode(Bool.self, forKey: .hideCustomEmojiInUsernames) self.showIsStatusReplyIcon = try container.decode(Bool.self, forKey: .showIsStatusReplyIcon) @@ -90,6 +91,7 @@ class Preferences: Codable, ObservableObject { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(theme, forKey: .theme) + try container.encode(accentColor, forKey: .accentColor) try container.encode(avatarStyle, forKey: .avatarStyle) try container.encode(hideCustomEmojiInUsernames, forKey: .hideCustomEmojiInUsernames) try container.encode(showIsStatusReplyIcon, forKey: .showIsStatusReplyIcon) @@ -136,6 +138,7 @@ class Preferences: Codable, ObservableObject { // MARK: Appearance @Published var theme = UIUserInterfaceStyle.unspecified + @Published var accentColor = AccentColor.default @Published var avatarStyle = AvatarStyle.roundRect @Published var hideCustomEmojiInUsernames = false @Published var showIsStatusReplyIcon = false @@ -196,6 +199,7 @@ class Preferences: Codable, ObservableObject { private enum CodingKeys: String, CodingKey { case theme + case accentColor case avatarStyle case hideCustomEmojiInUsernames case showIsStatusReplyIcon @@ -299,3 +303,83 @@ extension Preferences { } extension UIUserInterfaceStyle: Codable {} + +extension Preferences { + enum AccentColor: String, Codable, CaseIterable { + case `default` + case purple + case indigo + case blue + case cyan + case teal + case mint + case green +// case yellow + case orange + case red + case pink +// case brown + + var color: UIColor? { + switch self { + case .default: + return nil + case .blue: + return .systemBlue +// case .brown: +// return .systemBrown + case .cyan: + return .systemCyan + case .green: + return .systemGreen + case .indigo: + return .systemIndigo + case .mint: + return .systemMint + case .orange: + return .systemOrange + case .pink: + return .systemPink + case .purple: + return .systemPurple + case .red: + return .systemRed + case .teal: + return .systemTeal +// case .yellow: +// return .systemYellow + } + } + + var name: String { + switch self { + case .default: + return "Default" + case .blue: + return "Blue" +// case .brown: +// return "Brown" + case .cyan: + return "Cyan" + case .green: + return "Green" + case .indigo: + return "Indigo" + case .mint: + return "Mint" + case .orange: + return "Orange" + case .pink: + return "Pink" + case .purple: + return "Purple" + case .red: + return "Red" + case .teal: + return "Teal" +// case .yellow: +// return "Yellow" + } + } + } +} diff --git a/Tusker/Scenes/AuxiliarySceneDelegate.swift b/Tusker/Scenes/AuxiliarySceneDelegate.swift index b017c7b4..eaecac21 100644 --- a/Tusker/Scenes/AuxiliarySceneDelegate.swift +++ b/Tusker/Scenes/AuxiliarySceneDelegate.swift @@ -113,5 +113,6 @@ class AuxiliarySceneDelegate: UIResponder, UIWindowSceneDelegate { @objc private func themePrefChanged() { window?.overrideUserInterfaceStyle = Preferences.shared.theme + window?.tintColor = Preferences.shared.accentColor.color } } diff --git a/Tusker/Scenes/ComposeSceneDelegate.swift b/Tusker/Scenes/ComposeSceneDelegate.swift index 3836317a..1abd3b7c 100644 --- a/Tusker/Scenes/ComposeSceneDelegate.swift +++ b/Tusker/Scenes/ComposeSceneDelegate.swift @@ -101,6 +101,7 @@ class ComposeSceneDelegate: UIResponder, UIWindowSceneDelegate { @objc private func themePrefChanged() { window?.overrideUserInterfaceStyle = Preferences.shared.theme + window?.tintColor = Preferences.shared.accentColor.color } } diff --git a/Tusker/Scenes/MainSceneDelegate.swift b/Tusker/Scenes/MainSceneDelegate.swift index e7fcf866..34a4ec0f 100644 --- a/Tusker/Scenes/MainSceneDelegate.swift +++ b/Tusker/Scenes/MainSceneDelegate.swift @@ -244,6 +244,7 @@ class MainSceneDelegate: UIResponder, UIWindowSceneDelegate, TuskerSceneDelegate @objc func themePrefChanged() { window?.overrideUserInterfaceStyle = Preferences.shared.theme + window?.tintColor = Preferences.shared.accentColor.color } func showAddAccount() { diff --git a/Tusker/Screens/Preferences/AppearancePrefsView.swift b/Tusker/Screens/Preferences/AppearancePrefsView.swift index 1ef18170..53fdf872 100644 --- a/Tusker/Screens/Preferences/AppearancePrefsView.swift +++ b/Tusker/Screens/Preferences/AppearancePrefsView.swift @@ -10,14 +10,20 @@ import SwiftUI struct AppearancePrefsView : View { @ObservedObject var preferences = Preferences.shared - var theme: Binding = Binding(get: { + private var theme: Binding = Binding(get: { Preferences.shared.theme }, set: { Preferences.shared.theme = $0 NotificationCenter.default.post(name: .themePreferenceChanged, object: nil) }) + private var accentColor: Binding = Binding { + Preferences.shared.accentColor + } set: { + Preferences.shared.accentColor = $0 + NotificationCenter.default.post(name: .themePreferenceChanged, object: nil) + } - var useCircularAvatars: Binding = Binding(get: { + private var useCircularAvatars: Binding = Binding(get: { Preferences.shared.avatarStyle == .circle }) { Preferences.shared.avatarStyle = $0 ? .circle : .roundRect @@ -25,11 +31,7 @@ struct AppearancePrefsView : View { var body: some View { List { - Picker(selection: theme, label: Text("Theme")) { - Text("Use System Theme").tag(UIUserInterfaceStyle.unspecified) - Text("Light").tag(UIUserInterfaceStyle.light) - Text("Dark").tag(UIUserInterfaceStyle.dark) - } + themeSection accountsSection postsSection } @@ -37,6 +39,29 @@ struct AppearancePrefsView : View { .navigationBarTitle(Text("Appearance")) } + private var themeSection: some View { + Section { + Picker(selection: theme, label: Text("Theme")) { + Text("Use System Theme").tag(UIUserInterfaceStyle.unspecified) + Text("Light").tag(UIUserInterfaceStyle.light) + Text("Dark").tag(UIUserInterfaceStyle.dark) + } + + Picker(selection: accentColor, label: Text("Accent Color")) { + ForEach(Preferences.AccentColor.allCases, id: \.rawValue) { color in + HStack { + Text(color.name) + if let color = color.color { + Spacer() + Image(uiImage: UIImage(systemName: "circle.fill")!.withTintColor(color, renderingMode: .alwaysTemplate).withRenderingMode(.alwaysOriginal)) + } + } + .tag(color) + } + } + } + } + private var accountsSection: some View { Section(header: Text("Accounts")) { Toggle(isOn: useCircularAvatars) { diff --git a/Tusker/Views/Status/BaseStatusTableViewCell.swift b/Tusker/Views/Status/BaseStatusTableViewCell.swift index 15ef71dc..0be91061 100644 --- a/Tusker/Views/Status/BaseStatusTableViewCell.swift +++ b/Tusker/Views/Status/BaseStatusTableViewCell.swift @@ -48,12 +48,12 @@ class BaseStatusTableViewCell: UITableViewCell { private var favorited = false { didSet { - favoriteButton.tintColor = favorited ? UIColor(displayP3Red: 1, green: 0.8, blue: 0, alpha: 1) : tintColor + favoriteButton.tintColor = favorited ? UIColor(displayP3Red: 1, green: 0.8, blue: 0, alpha: 1) : .tintColor } } private var reblogged = false { didSet { - reblogButton.tintColor = reblogged ? UIColor(displayP3Red: 1, green: 0.8, blue: 0, alpha: 1) : tintColor + reblogButton.tintColor = reblogged ? UIColor(displayP3Red: 1, green: 0.8, blue: 0, alpha: 1) : .tintColor } } diff --git a/Tusker/Views/Status/ConversationMainStatusTableViewCell.xib b/Tusker/Views/Status/ConversationMainStatusTableViewCell.xib index 07032279..5bcd4dae 100644 --- a/Tusker/Views/Status/ConversationMainStatusTableViewCell.xib +++ b/Tusker/Views/Status/ConversationMainStatusTableViewCell.xib @@ -77,7 +77,7 @@