mirror of
https://github.com/yattee/yattee.git
synced 2026-07-20 14:22:02 +00:00
Add custom accent color with system color picker
Add a Custom swatch to the appearance settings accent color grid, backed by a hex value stored in settings (synced via iCloud like the rest). iOS uses the native ColorPicker wheel; macOS uses a circular swatch that opens NSColorPanel, since the SwiftUI color well looks out of place among the circles. All accent consumers now read the resolved color through SettingsManager.resolvedAccentColor. The indigo preset is retired from the grid but kept in the enum, so users who selected it keep their color until they pick another one. Claude-Session: https://claude.ai/code/session_0154KH8RAVAvm6iVanhmoW8o
This commit is contained in:
@@ -13,6 +13,7 @@ enum SettingsKey: String, CaseIterable {
|
|||||||
// General
|
// General
|
||||||
case theme
|
case theme
|
||||||
case accentColor
|
case accentColor
|
||||||
|
case customAccentColor
|
||||||
case showWatchedCheckmark
|
case showWatchedCheckmark
|
||||||
|
|
||||||
// Playback
|
// Playback
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import SwiftUI
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
import UIKit
|
import UIKit
|
||||||
#elseif os(macOS)
|
#elseif os(macOS)
|
||||||
@@ -37,6 +38,23 @@ extension SettingsManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var customAccentColor: Color {
|
||||||
|
get {
|
||||||
|
let hex = _customAccentColor ?? string(for: .customAccentColor) ?? ""
|
||||||
|
return Color(hex: hex) ?? AccentColor.default.color
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
let hex = newValue.toHexString()
|
||||||
|
_customAccentColor = hex
|
||||||
|
set(hex, for: .customAccentColor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The effective accent color, resolving `.custom` to the user-picked value.
|
||||||
|
var resolvedAccentColor: Color {
|
||||||
|
accentColor == .custom ? customAccentColor : accentColor.color
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - App Icon Settings
|
// MARK: - App Icon Settings
|
||||||
|
|
||||||
var appIcon: AppIcon {
|
var appIcon: AppIcon {
|
||||||
|
|||||||
@@ -35,10 +35,20 @@ enum AccentColor: String, CaseIterable, Codable {
|
|||||||
case blue
|
case blue
|
||||||
case purple
|
case purple
|
||||||
case indigo
|
case indigo
|
||||||
|
case custom
|
||||||
|
|
||||||
|
/// Fixed swatches shown in the settings grid; `.custom` is rendered
|
||||||
|
/// separately as a color picker, and `.indigo` is retired from the grid
|
||||||
|
/// but still resolves for users who selected it before it was removed.
|
||||||
|
static var presets: [AccentColor] {
|
||||||
|
allCases.filter { $0 != .custom && $0 != .indigo }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The color for `.custom` lives in settings storage — resolve through
|
||||||
|
/// `SettingsManager.resolvedAccentColor` instead of this property.
|
||||||
var color: Color {
|
var color: Color {
|
||||||
switch self {
|
switch self {
|
||||||
case .default: return .blue // System default accent color
|
case .default, .custom: return .blue // System default accent color
|
||||||
case .red: return .red
|
case .red: return .red
|
||||||
case .pink: return .pink
|
case .pink: return .pink
|
||||||
case .orange: return .orange
|
case .orange: return .orange
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ final class SettingsManager {
|
|||||||
// Theme
|
// Theme
|
||||||
var _theme: AppTheme?
|
var _theme: AppTheme?
|
||||||
var _accentColor: AccentColor?
|
var _accentColor: AccentColor?
|
||||||
|
var _customAccentColor: String?
|
||||||
var _showWatchedCheckmark: Bool?
|
var _showWatchedCheckmark: Bool?
|
||||||
|
|
||||||
// Playback
|
// Playback
|
||||||
@@ -417,6 +418,7 @@ final class SettingsManager {
|
|||||||
func clearCache() {
|
func clearCache() {
|
||||||
_theme = nil
|
_theme = nil
|
||||||
_accentColor = nil
|
_accentColor = nil
|
||||||
|
_customAccentColor = nil
|
||||||
_showWatchedCheckmark = nil
|
_showWatchedCheckmark = nil
|
||||||
_preferredQuality = nil
|
_preferredQuality = nil
|
||||||
_cellularQuality = nil
|
_cellularQuality = nil
|
||||||
|
|||||||
@@ -10353,6 +10353,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"settings.appearance.accentColor.custom" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Custom"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"settings.appearance.accentColor.default" : {
|
"settings.appearance.accentColor.default" : {
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"en" : {
|
"en" : {
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ struct ChannelView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var accentColor: Color {
|
private var accentColor: Color {
|
||||||
appEnvironment?.settingsManager.accentColor.color ?? .accentColor
|
appEnvironment?.settingsManager.resolvedAccentColor ?? .accentColor
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grid layout configuration
|
// Grid layout configuration
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ struct BookmarkCardView: View {
|
|||||||
var isCompact: Bool = false
|
var isCompact: Bool = false
|
||||||
|
|
||||||
private var accentColor: Color {
|
private var accentColor: Color {
|
||||||
appEnvironment?.settingsManager.accentColor.color ?? .accentColor
|
appEnvironment?.settingsManager.resolvedAccentColor ?? .accentColor
|
||||||
}
|
}
|
||||||
|
|
||||||
private var video: Video {
|
private var video: Video {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ struct BookmarkRowView: View {
|
|||||||
var loadMoreVideos: LoadMoreVideosCallback? = nil
|
var loadMoreVideos: LoadMoreVideosCallback? = nil
|
||||||
|
|
||||||
private var accentColor: Color {
|
private var accentColor: Color {
|
||||||
appEnvironment?.settingsManager.accentColor.color ?? .accentColor
|
appEnvironment?.settingsManager.resolvedAccentColor ?? .accentColor
|
||||||
}
|
}
|
||||||
|
|
||||||
private var isBookmarkValid: Bool {
|
private var isBookmarkValid: Bool {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ struct BookmarkTagsView: View {
|
|||||||
var maxVisible: Int = 3
|
var maxVisible: Int = 3
|
||||||
|
|
||||||
private var accentColor: Color {
|
private var accentColor: Color {
|
||||||
appEnvironment?.settingsManager.accentColor.color ?? .accentColor
|
appEnvironment?.settingsManager.resolvedAccentColor ?? .accentColor
|
||||||
}
|
}
|
||||||
|
|
||||||
private var visibleTags: [String] {
|
private var visibleTags: [String] {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ struct CommentView: View {
|
|||||||
private var contentService: ContentService? { appEnvironment?.contentService }
|
private var contentService: ContentService? { appEnvironment?.contentService }
|
||||||
private var instancesManager: InstancesManager? { appEnvironment?.instancesManager }
|
private var instancesManager: InstancesManager? { appEnvironment?.instancesManager }
|
||||||
private var navigationCoordinator: NavigationCoordinator? { appEnvironment?.navigationCoordinator }
|
private var navigationCoordinator: NavigationCoordinator? { appEnvironment?.navigationCoordinator }
|
||||||
private var accentColor: Color { appEnvironment?.settingsManager.accentColor.color ?? .accentColor }
|
private var accentColor: Color { appEnvironment?.settingsManager.resolvedAccentColor ?? .accentColor }
|
||||||
|
|
||||||
init(comment: Comment, videoID: String? = nil, source: ContentSource? = nil, isReply: Bool = false) {
|
init(comment: Comment, videoID: String? = nil, source: ContentSource? = nil, isReply: Bool = false) {
|
||||||
self.comment = comment
|
self.comment = comment
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ struct TagInputView: View {
|
|||||||
@FocusState private var textFieldFocused: Bool
|
@FocusState private var textFieldFocused: Bool
|
||||||
|
|
||||||
private var accentColor: Color {
|
private var accentColor: Color {
|
||||||
appEnvironment?.settingsManager.accentColor.color ?? .accentColor
|
appEnvironment?.settingsManager.resolvedAccentColor ?? .accentColor
|
||||||
}
|
}
|
||||||
|
|
||||||
private let maxTags = 10
|
private let maxTags = 10
|
||||||
|
|||||||
@@ -364,7 +364,7 @@ private struct CompletedDownloadsSectionContentView: View {
|
|||||||
let isGroupedMode: Bool
|
let isGroupedMode: Bool
|
||||||
|
|
||||||
private var accentColor: Color {
|
private var accentColor: Color {
|
||||||
appEnvironment?.settingsManager.accentColor.color ?? .accentColor
|
appEnvironment?.settingsManager.resolvedAccentColor ?? .accentColor
|
||||||
}
|
}
|
||||||
|
|
||||||
private var completedFiltered: [Download] {
|
private var completedFiltered: [Download] {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ struct HomeShortcutCardView<StatusIndicator: View>: View {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
private var accentColor: Color {
|
private var accentColor: Color {
|
||||||
appEnvironment?.settingsManager.accentColor.color ?? .accentColor
|
appEnvironment?.settingsManager.resolvedAccentColor ?? .accentColor
|
||||||
}
|
}
|
||||||
|
|
||||||
let icon: String
|
let icon: String
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ struct HomeShortcutRowView<StatusIndicator: View>: View {
|
|||||||
var statusIndicator: StatusIndicator?
|
var statusIndicator: StatusIndicator?
|
||||||
|
|
||||||
private var accentColor: Color {
|
private var accentColor: Color {
|
||||||
appEnvironment?.settingsManager.accentColor.color ?? .accentColor
|
appEnvironment?.settingsManager.resolvedAccentColor ?? .accentColor
|
||||||
}
|
}
|
||||||
|
|
||||||
init(
|
init(
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ struct HomeShortcutStyleView: View {
|
|||||||
|
|
||||||
/// The user's accent color, used by the Accent palette (uniform fill).
|
/// The user's accent color, used by the Accent palette (uniform fill).
|
||||||
private var accentColor: Color {
|
private var accentColor: Color {
|
||||||
appEnvironment?.settingsManager.accentColor.color ?? .accentColor
|
appEnvironment?.settingsManager.resolvedAccentColor ?? .accentColor
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called after any value changes so the owner persists immediately. The
|
/// Called after any value changes so the owner persists immediately. The
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ struct HomeView: View {
|
|||||||
private var settingsManager: SettingsManager? { appEnvironment?.settingsManager }
|
private var settingsManager: SettingsManager? { appEnvironment?.settingsManager }
|
||||||
|
|
||||||
private var accentColor: Color {
|
private var accentColor: Color {
|
||||||
appEnvironment?.settingsManager.accentColor.color ?? .accentColor
|
appEnvironment?.settingsManager.resolvedAccentColor ?? .accentColor
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !os(tvOS)
|
#if !os(tvOS)
|
||||||
@@ -408,7 +408,7 @@ struct HomeView: View {
|
|||||||
private func colorfulColor(atPosition position: Int) -> Color {
|
private func colorfulColor(atPosition position: Int) -> Color {
|
||||||
let palette = settingsManager?.homeShortcutColorfulPalette ?? .accent
|
let palette = settingsManager?.homeShortcutColorfulPalette ?? .accent
|
||||||
let customHex = settingsManager?.homeShortcutCustomPaletteColors ?? []
|
let customHex = settingsManager?.homeShortcutCustomPaletteColors ?? []
|
||||||
let accentColor = settingsManager?.accentColor.color ?? .accentColor
|
let accentColor = settingsManager?.resolvedAccentColor ?? .accentColor
|
||||||
return HomeShortcutColorfulPalette.color(forPosition: position, palette: palette, customHex: customHex, accentColor: accentColor)
|
return HomeShortcutColorfulPalette.color(forPosition: position, palette: palette, customHex: customHex, accentColor: accentColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ struct ExpandedPlayerSheet: View {
|
|||||||
var playerState: PlayerState? { playerService?.state }
|
var playerState: PlayerState? { playerService?.state }
|
||||||
var downloadManager: DownloadManager? { appEnvironment?.downloadManager }
|
var downloadManager: DownloadManager? { appEnvironment?.downloadManager }
|
||||||
var navigationCoordinator: NavigationCoordinator? { appEnvironment?.navigationCoordinator }
|
var navigationCoordinator: NavigationCoordinator? { appEnvironment?.navigationCoordinator }
|
||||||
var accentColor: Color { appEnvironment?.settingsManager.accentColor.color ?? .accentColor }
|
var accentColor: Color { appEnvironment?.settingsManager.resolvedAccentColor ?? .accentColor }
|
||||||
|
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
var inAppOrientationLock: Bool { appEnvironment?.settingsManager.inAppOrientationLock ?? false }
|
var inAppOrientationLock: Bool { appEnvironment?.settingsManager.inAppOrientationLock ?? false }
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ struct FloatingDetailsPanel: View {
|
|||||||
@State private var isDragHandleActive: Bool = false
|
@State private var isDragHandleActive: Bool = false
|
||||||
|
|
||||||
private var settingsManager: SettingsManager? { appEnvironment?.settingsManager }
|
private var settingsManager: SettingsManager? { appEnvironment?.settingsManager }
|
||||||
private var accentColor: Color { settingsManager?.accentColor.color ?? .accentColor }
|
private var accentColor: Color { settingsManager?.resolvedAccentColor ?? .accentColor }
|
||||||
private var playerService: PlayerService? { appEnvironment?.playerService }
|
private var playerService: PlayerService? { appEnvironment?.playerService }
|
||||||
private var playerState: PlayerState? { playerService?.state }
|
private var playerState: PlayerState? { playerService?.state }
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ struct PanelPinButton: View {
|
|||||||
private static let buttonSize: CGFloat = 36
|
private static let buttonSize: CGFloat = 36
|
||||||
|
|
||||||
private var accentColor: Color {
|
private var accentColor: Color {
|
||||||
appEnvironment?.settingsManager.accentColor.color ?? .accentColor
|
appEnvironment?.settingsManager.resolvedAccentColor ?? .accentColor
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ struct PortraitDetailsPanel: View {
|
|||||||
@State private var showPlaylistSheet: Bool = false
|
@State private var showPlaylistSheet: Bool = false
|
||||||
|
|
||||||
private var settingsManager: SettingsManager? { appEnvironment?.settingsManager }
|
private var settingsManager: SettingsManager? { appEnvironment?.settingsManager }
|
||||||
private var accentColor: Color { settingsManager?.accentColor.color ?? .accentColor }
|
private var accentColor: Color { settingsManager?.resolvedAccentColor ?? .accentColor }
|
||||||
private var playerService: PlayerService? { appEnvironment?.playerService }
|
private var playerService: PlayerService? { appEnvironment?.playerService }
|
||||||
private var playerState: PlayerState? { playerService?.state }
|
private var playerState: PlayerState? { playerService?.state }
|
||||||
private var isPanelDragging: Bool { appEnvironment?.navigationCoordinator.isPanelDragging ?? false }
|
private var isPanelDragging: Bool { appEnvironment?.navigationCoordinator.isPanelDragging ?? false }
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
#if os(macOS)
|
||||||
|
import AppKit
|
||||||
|
#endif
|
||||||
|
|
||||||
struct AppearanceSettingsView: View {
|
struct AppearanceSettingsView: View {
|
||||||
@Environment(\.appEnvironment) private var appEnvironment
|
@Environment(\.appEnvironment) private var appEnvironment
|
||||||
@@ -146,13 +149,17 @@ private struct AccentColorSection: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
SettingsFormSection("settings.appearance.accentColor.header") {
|
SettingsFormSection("settings.appearance.accentColor.header") {
|
||||||
LazyVGrid(columns: [GridItem(.adaptive(minimum: 50))], spacing: 16) {
|
LazyVGrid(columns: [GridItem(.adaptive(minimum: 50))], spacing: 16) {
|
||||||
ForEach(AccentColor.allCases, id: \.self) { accentColor in
|
ForEach(AccentColor.presets, id: \.self) { accentColor in
|
||||||
AccentColorButton(
|
AccentColorButton(
|
||||||
accentColor: accentColor,
|
accentColor: accentColor,
|
||||||
isSelected: settings.accentColor == accentColor,
|
isSelected: settings.accentColor == accentColor,
|
||||||
onSelect: { settings.accentColor = accentColor }
|
onSelect: { settings.accentColor = accentColor }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !os(tvOS)
|
||||||
|
CustomAccentColorButton(settings: settings)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
.padding(.vertical, 8)
|
.padding(.vertical, 8)
|
||||||
}
|
}
|
||||||
@@ -222,6 +229,110 @@ private struct AccentColorButton: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Custom Accent Color Button
|
||||||
|
|
||||||
|
#if !os(tvOS)
|
||||||
|
private struct CustomAccentColorButton: View {
|
||||||
|
@Bindable var settings: SettingsManager
|
||||||
|
|
||||||
|
private var isSelected: Bool { settings.accentColor == .custom }
|
||||||
|
|
||||||
|
#if os(macOS)
|
||||||
|
var body: some View {
|
||||||
|
Button {
|
||||||
|
settings.accentColor = .custom
|
||||||
|
ColorPanelBridge.shared.open(with: NSColor(settings.customAccentColor)) { nsColor in
|
||||||
|
settings.customAccentColor = Color(nsColor: nsColor)
|
||||||
|
settings.accentColor = .custom
|
||||||
|
}
|
||||||
|
} label: {
|
||||||
|
ZStack {
|
||||||
|
Circle()
|
||||||
|
.strokeBorder(
|
||||||
|
AngularGradient(
|
||||||
|
colors: [.red, .yellow, .green, .cyan, .blue, .purple, .red],
|
||||||
|
center: .center
|
||||||
|
),
|
||||||
|
lineWidth: 4
|
||||||
|
)
|
||||||
|
.frame(width: 40, height: 40)
|
||||||
|
|
||||||
|
Circle()
|
||||||
|
.fill(settings.customAccentColor)
|
||||||
|
.frame(width: 28, height: 28)
|
||||||
|
|
||||||
|
if isSelected {
|
||||||
|
Image(systemName: "checkmark")
|
||||||
|
.font(.caption.bold())
|
||||||
|
.foregroundStyle(.white)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.buttonStyle(.plain)
|
||||||
|
.accessibilityLabel(String(localized: "settings.appearance.accentColor.custom"))
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
private var pickedColor: Binding<Color> {
|
||||||
|
Binding(
|
||||||
|
get: { settings.customAccentColor },
|
||||||
|
set: { newColor in
|
||||||
|
settings.customAccentColor = newColor
|
||||||
|
settings.accentColor = .custom
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
ZStack {
|
||||||
|
Circle()
|
||||||
|
.fill(settings.customAccentColor)
|
||||||
|
.frame(width: 40, height: 40)
|
||||||
|
.opacity(isSelected ? 1 : 0)
|
||||||
|
|
||||||
|
ColorPicker(
|
||||||
|
String(localized: "settings.appearance.accentColor.custom"),
|
||||||
|
selection: pickedColor,
|
||||||
|
supportsOpacity: false
|
||||||
|
)
|
||||||
|
.labelsHidden()
|
||||||
|
|
||||||
|
if isSelected {
|
||||||
|
Image(systemName: "checkmark")
|
||||||
|
.font(.caption.bold())
|
||||||
|
.foregroundStyle(.white)
|
||||||
|
.allowsHitTesting(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.accessibilityLabel(String(localized: "settings.appearance.accentColor.custom"))
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if os(macOS)
|
||||||
|
/// Routes NSColorPanel target/action callbacks to the settings binding.
|
||||||
|
/// NSColorPanel keeps only a weak target, so this must outlive the view.
|
||||||
|
@MainActor
|
||||||
|
private final class ColorPanelBridge: NSObject {
|
||||||
|
static let shared = ColorPanelBridge()
|
||||||
|
private var onChange: ((NSColor) -> Void)?
|
||||||
|
|
||||||
|
func open(with color: NSColor, onChange: @escaping (NSColor) -> Void) {
|
||||||
|
self.onChange = onChange
|
||||||
|
let panel = NSColorPanel.shared
|
||||||
|
panel.showsAlpha = false
|
||||||
|
panel.color = color
|
||||||
|
panel.setTarget(self)
|
||||||
|
panel.setAction(#selector(colorChanged(_:)))
|
||||||
|
panel.makeKeyAndOrderFront(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func colorChanged(_ sender: NSColorPanel) {
|
||||||
|
onChange?(sender.color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
// MARK: - Theme Display Names
|
// MARK: - Theme Display Names
|
||||||
|
|
||||||
extension AppTheme {
|
extension AppTheme {
|
||||||
@@ -251,6 +362,7 @@ extension AccentColor {
|
|||||||
case .blue: return String(localized: "settings.appearance.accentColor.blue")
|
case .blue: return String(localized: "settings.appearance.accentColor.blue")
|
||||||
case .purple: return String(localized: "settings.appearance.accentColor.purple")
|
case .purple: return String(localized: "settings.appearance.accentColor.purple")
|
||||||
case .indigo: return String(localized: "settings.appearance.accentColor.indigo")
|
case .indigo: return String(localized: "settings.appearance.accentColor.indigo")
|
||||||
|
case .custom: return String(localized: "settings.appearance.accentColor.custom")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ struct SubscriptionsView: View {
|
|||||||
|
|
||||||
private var dataManager: DataManager? { appEnvironment?.dataManager }
|
private var dataManager: DataManager? { appEnvironment?.dataManager }
|
||||||
private var subscriptionService: SubscriptionService? { appEnvironment?.subscriptionService }
|
private var subscriptionService: SubscriptionService? { appEnvironment?.subscriptionService }
|
||||||
private var accentColor: Color { appEnvironment?.settingsManager.accentColor.color ?? .accentColor }
|
private var accentColor: Color { appEnvironment?.settingsManager.resolvedAccentColor ?? .accentColor }
|
||||||
private var yatteeServer: Instance? {
|
private var yatteeServer: Instance? {
|
||||||
appEnvironment?.instancesManager.enabledYatteeServerInstances.first
|
appEnvironment?.instancesManager.enabledYatteeServerInstances.first
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ struct VideoInfoView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var accentColor: Color {
|
private var accentColor: Color {
|
||||||
appEnvironment?.settingsManager.accentColor.color ?? .accentColor
|
appEnvironment?.settingsManager.resolvedAccentColor ?? .accentColor
|
||||||
}
|
}
|
||||||
|
|
||||||
private var dataManager: DataManager? { appEnvironment?.dataManager }
|
private var dataManager: DataManager? { appEnvironment?.dataManager }
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ struct YatteeApp: App {
|
|||||||
.appEnvironment(appEnvironment)
|
.appEnvironment(appEnvironment)
|
||||||
#if !os(tvOS)
|
#if !os(tvOS)
|
||||||
.preferredColorScheme(appEnvironment.settingsManager.theme.colorScheme)
|
.preferredColorScheme(appEnvironment.settingsManager.theme.colorScheme)
|
||||||
.tint(appEnvironment.settingsManager.accentColor.color)
|
.tint(appEnvironment.settingsManager.resolvedAccentColor)
|
||||||
#endif
|
#endif
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
.frame(minWidth: 800, minHeight: 500)
|
.frame(minWidth: 800, minHeight: 500)
|
||||||
|
|||||||
@@ -65,6 +65,20 @@ struct AccentColorTests {
|
|||||||
#expect(color == decoded)
|
#expect(color == decoded)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test("Presets exclude custom and retired indigo")
|
||||||
|
func presetsExcludeHiddenCases() {
|
||||||
|
#expect(!AccentColor.presets.contains(.custom))
|
||||||
|
#expect(!AccentColor.presets.contains(.indigo))
|
||||||
|
#expect(AccentColor.presets.count == AccentColor.allCases.count - 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test("Retired indigo still decodes and resolves")
|
||||||
|
func retiredIndigoStillWorks() throws {
|
||||||
|
let decoded = try JSONDecoder().decode(AccentColor.self, from: Data("\"indigo\"".utf8))
|
||||||
|
#expect(decoded == .indigo)
|
||||||
|
#expect(AccentColor(rawValue: "indigo") == .indigo)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - VideoQuality Tests
|
// MARK: - VideoQuality Tests
|
||||||
|
|||||||
Reference in New Issue
Block a user