Add position-based colorful Home shortcut palettes

Colorful shortcut cards now color by grid position instead of shortcut
identity, so colors stay in the same slot when shortcuts are reordered.

Adds a Palette option (Classic default, plus Sunset, Meadow, Berry,
Grape) and a Custom palette with a swatch-list editor (ColorPicker + hex
fields) and a switchable comma-separated text field. Color is resolved
per position and wraps by palette length, wired via a new
homeShortcutColorfulColor environment value and a Color(hex:) extension.
This commit is contained in:
Arkadiusz Fal
2026-05-28 23:26:05 +02:00
parent bcd4206c55
commit 486024834d
10 changed files with 596 additions and 51 deletions

View File

@@ -65,6 +65,8 @@ enum SettingsKey: String, CaseIterable {
case homeShortcutVisibility
case homeShortcutLayout
case homeShortcutCardStyle
case homeShortcutColorfulPalette
case homeShortcutCustomPaletteColors
case homeSectionOrder
case homeSectionVisibility
case homeSectionItemsLimit
@@ -137,6 +139,7 @@ enum SettingsKey: String, CaseIterable {
case .preferredQuality, .cellularQuality, .allowSoftwareDecodedFormats, .macPlayerMode, .listStyle,
// Home layout different UI paradigms per platform
.homeShortcutOrder, .homeShortcutVisibility, .homeShortcutLayout, .homeShortcutCardStyle,
.homeShortcutColorfulPalette, .homeShortcutCustomPaletteColors,
.homeSectionOrder, .homeSectionVisibility, .homeSectionItemsLimit, .homeSectionLayout,
// Top Shelf tvOS only
.topShelfSections,

View File

@@ -110,6 +110,40 @@ extension SettingsManager {
}
}
/// Palette used by the "colorful" card style. Colors are applied by grid
/// position. Default is Classic.
var homeShortcutColorfulPalette: HomeShortcutColorfulPalette {
get {
if let cached = _homeShortcutColorfulPalette { return cached }
guard let rawValue = string(for: .homeShortcutColorfulPalette) else {
return .classic
}
return HomeShortcutColorfulPalette(rawValue: rawValue) ?? .classic
}
set {
_homeShortcutColorfulPalette = newValue
set(newValue.rawValue, for: .homeShortcutColorfulPalette)
}
}
/// User-supplied hex colors for the custom "colorful" palette. Stored as a
/// single comma-separated string. Defaults to a starter set of colors.
var homeShortcutCustomPaletteColors: [String] {
get {
if let cached = _homeShortcutCustomPaletteColors { return cached }
guard let raw = string(for: .homeShortcutCustomPaletteColors) else {
return HomeShortcutColorfulPalette.customStarterColors
}
let colors = raw.split(separator: ",").map { $0.trimmingCharacters(in: .whitespaces) }.filter { !$0.isEmpty }
return colors
}
set {
_homeShortcutCustomPaletteColors = newValue
let joined = newValue.map { $0.trimmingCharacters(in: .whitespaces) }.filter { !$0.isEmpty }.joined(separator: ",")
set(joined, for: .homeShortcutCustomPaletteColors)
}
}
/// Layout mode for home sections (list or grid). Default is list on iOS/macOS, grid on tvOS.
var homeSectionLayout: HomeSectionLayout {
get {

View File

@@ -109,6 +109,8 @@ final class SettingsManager {
var _homeShortcutVisibility: [HomeShortcutItem: Bool]?
var _homeShortcutLayout: HomeShortcutLayout?
var _homeShortcutCardStyle: HomeShortcutCardStyle?
var _homeShortcutColorfulPalette: HomeShortcutColorfulPalette?
var _homeShortcutCustomPaletteColors: [String]?
var _homeSectionOrder: [HomeSectionItem]?
var _homeSectionVisibility: [HomeSectionItem: Bool]?
var _homeSectionItemsLimit: Int?
@@ -465,6 +467,8 @@ final class SettingsManager {
_homeShortcutVisibility = nil
_homeShortcutLayout = nil
_homeShortcutCardStyle = nil
_homeShortcutColorfulPalette = nil
_homeShortcutCustomPaletteColors = nil
_homeSectionOrder = nil
_homeSectionVisibility = nil
_homeSectionItemsLimit = nil