From 755ca63e4d37c1a54db7fc6475152319a4e46ceb Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Sun, 28 Jun 2026 20:53:56 +0800
Subject: [PATCH] Freeze 8.1.7 colorful theme tuning

---
 src/Apptag/AppGridTheme.swift |  300 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 282 insertions(+), 18 deletions(-)

diff --git a/src/Apptag/AppGridTheme.swift b/src/Apptag/AppGridTheme.swift
index f345a5c..052d1ee 100644
--- a/src/Apptag/AppGridTheme.swift
+++ b/src/Apptag/AppGridTheme.swift
@@ -1,6 +1,46 @@
 import SwiftUI
 import AppKit
 
+private struct AppGridThemeColor {
+    let red: Double
+    let green: Double
+    let blue: Double
+
+    func color(opacity: Double = 1) -> Color {
+        Color(red: red, green: green, blue: blue).opacity(opacity)
+    }
+
+    static func mix(_ lhs: AppGridThemeColor, _ rhs: AppGridThemeColor, amount: Double) -> AppGridThemeColor {
+        AppGridThemeColor(
+            red: lhs.red + (rhs.red - lhs.red) * amount,
+            green: lhs.green + (rhs.green - lhs.green) * amount,
+            blue: lhs.blue + (rhs.blue - lhs.blue) * amount
+        )
+    }
+}
+
+private struct AppGridThemeStop {
+    let color: AppGridThemeColor
+    let opacity: Double
+
+    func swiftUIColor() -> Color {
+        color.color(opacity: opacity)
+    }
+
+    static func mix(_ lhs: AppGridThemeStop, _ rhs: AppGridThemeStop, amount: Double) -> AppGridThemeStop {
+        AppGridThemeStop(
+            color: .mix(lhs.color, rhs.color, amount: amount),
+            opacity: lhs.opacity + (rhs.opacity - lhs.opacity) * amount
+        )
+    }
+}
+
+private struct AppGridThemePalette {
+    let base: [AppGridThemeStop]
+    let accent: [AppGridThemeStop]
+    let preview: [AppGridThemeStop]
+}
+
 enum AppGridTheme: String, CaseIterable, Identifiable {
     case defaultLight
     case deepBlue
@@ -12,7 +52,19 @@
     case colorful
 
     static let storageKey = "appGridThemeID"
+    static let deepBlueTuningStorageKey = "appGridThemeTuning.deepBlue"
+    static let colorfulTuningStorageKey = "appGridThemeTuning.colorful"
     static let fallback = AppGridTheme.defaultLight
+    static let settingsDisplayOrder: [AppGridTheme] = [
+        .defaultLight,
+        .black,
+        .pink,
+        .green,
+        .purple,
+        .blue,
+        .deepBlue,
+        .colorful
+    ]
     static var freeThemes: [AppGridTheme] {
         allCases.filter(\.isFreeTheme)
     }
@@ -164,7 +216,44 @@
         Color.white
     }
 
+    var supportsColorTuning: Bool {
+        self == .deepBlue || self == .colorful
+    }
+
+    var defaultColorTuning: Double {
+        switch self {
+        case .deepBlue:
+            return 0
+        case .colorful:
+            return 0
+        case .defaultLight, .black, .pink, .purple, .green, .blue:
+            return 0.5
+        }
+    }
+
+    var tuningStorageKey: String? {
+        switch self {
+        case .deepBlue:
+            return Self.deepBlueTuningStorageKey
+        case .colorful:
+            return Self.colorfulTuningStorageKey
+        case .defaultLight, .black, .pink, .purple, .green, .blue:
+            return nil
+        }
+    }
+
+    func normalizedTuning(_ value: Double?) -> Double {
+        min(1, max(0, value ?? defaultColorTuning))
+    }
+
     var backgroundBaseColors: [Color] {
+        backgroundBaseColors(tuning: nil)
+    }
+
+    func backgroundBaseColors(tuning: Double?) -> [Color] {
+        if supportsColorTuning {
+            return tunedPalette(tuning: tuning).base.map { $0.swiftUIColor() }
+        }
         switch self {
         case .defaultLight:
             return [
@@ -207,16 +296,18 @@
                 Color(red: 0.45, green: 0.96, blue: 1.00)
             ]
         case .colorful:
-            return [
-                Color(red: 0.10, green: 0.78, blue: 1.00),
-                Color(red: 0.34, green: 0.96, blue: 0.94),
-                Color(red: 0.73, green: 0.78, blue: 1.00),
-                Color(red: 1.00, green: 0.58, blue: 0.94)
-            ]
+            return tunedPalette(tuning: tuning).base.map { $0.swiftUIColor() }
         }
     }
 
     var backgroundAccentColors: [Color] {
+        backgroundAccentColors(tuning: nil)
+    }
+
+    func backgroundAccentColors(tuning: Double?) -> [Color] {
+        if supportsColorTuning {
+            return tunedPalette(tuning: tuning).accent.map { $0.swiftUIColor() }
+        }
         switch self {
         case .defaultLight:
             return [Color.clear, Color.clear]
@@ -256,16 +347,18 @@
                 Color(red: 0.00, green: 0.90, blue: 1.00).opacity(0.18)
             ]
         case .colorful:
-            return [
-                Color.white.opacity(0.16),
-                Color(red: 0.00, green: 0.78, blue: 1.00).opacity(0.22),
-                Color(red: 1.00, green: 0.45, blue: 0.95).opacity(0.22),
-                Color(red: 0.35, green: 1.00, blue: 0.92).opacity(0.18)
-            ]
+            return tunedPalette(tuning: tuning).accent.map { $0.swiftUIColor() }
         }
     }
 
     var previewColors: [Color] {
+        previewColors(tuning: nil)
+    }
+
+    func previewColors(tuning: Double?) -> [Color] {
+        if supportsColorTuning {
+            return tunedPalette(tuning: tuning).preview.map { $0.swiftUIColor() }
+        }
         switch self {
         case .defaultLight:
             return [Color.white, Color(red: 0.88, green: 0.90, blue: 0.92)]
@@ -282,12 +375,183 @@
         case .blue:
             return [Color(red: 0.70, green: 0.91, blue: 1.00), Color(red: 0.22, green: 0.58, blue: 1.00)]
         case .colorful:
-            return [
-                Color(red: 0.10, green: 0.78, blue: 1.00),
-                Color(red: 0.34, green: 0.96, blue: 0.94),
-                Color(red: 0.75, green: 0.82, blue: 1.00),
-                Color(red: 1.00, green: 0.56, blue: 0.94)
-            ]
+            return tunedPalette(tuning: tuning).preview.map { $0.swiftUIColor() }
         }
     }
+
+    private func tunedPalette(tuning: Double?) -> AppGridThemePalette {
+        let palettes = self == .deepBlue ? Self.darkColorfulPalettes : Self.lightColorfulPalettes
+        let normalized = normalizedTuning(tuning)
+        guard palettes.count > 1 else {
+            return palettes[0]
+        }
+        let scaled = normalized * Double(palettes.count - 1)
+        let lowerIndex = min(palettes.count - 1, max(0, Int(floor(scaled))))
+        let upperIndex = min(palettes.count - 1, lowerIndex + 1)
+        let amount = scaled - Double(lowerIndex)
+        guard lowerIndex != upperIndex else {
+            return palettes[lowerIndex]
+        }
+        return Self.mixPalettes(palettes[lowerIndex], palettes[upperIndex], amount: amount)
+    }
+
+    private static func mixPalettes(_ lhs: AppGridThemePalette, _ rhs: AppGridThemePalette, amount: Double) -> AppGridThemePalette {
+        AppGridThemePalette(
+            base: zip(lhs.base, rhs.base).map { .mix($0.0, $0.1, amount: amount) },
+            accent: zip(lhs.accent, rhs.accent).map { .mix($0.0, $0.1, amount: amount) },
+            preview: zip(lhs.preview, rhs.preview).map { .mix($0.0, $0.1, amount: amount) }
+        )
+    }
+}
+
+private extension AppGridTheme {
+    static let darkColorfulPalettes: [AppGridThemePalette] = [
+        AppGridThemePalette(
+            base: [
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.01, green: 0.03, blue: 0.08), opacity: 0.98),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.02, green: 0.13, blue: 0.20), opacity: 0.96),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.02, green: 0.28, blue: 0.28), opacity: 0.88),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.06, green: 0.08, blue: 0.18), opacity: 0.94)
+            ],
+            accent: [
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.00, green: 0.88, blue: 0.78), opacity: 0.22),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.10, green: 0.54, blue: 1.00), opacity: 0.18),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.08, green: 0.78, blue: 0.44), opacity: 0.16),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.45, green: 0.22, blue: 0.92), opacity: 0.12)
+            ],
+            preview: [
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.01, green: 0.06, blue: 0.12), opacity: 1),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.02, green: 0.42, blue: 0.38), opacity: 1)
+            ]
+        ),
+        AppGridThemePalette(
+            base: [
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.03, green: 0.02, blue: 0.08), opacity: 0.98),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.17, green: 0.04, blue: 0.19), opacity: 0.95),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.28, green: 0.04, blue: 0.20), opacity: 0.88),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.05, green: 0.06, blue: 0.16), opacity: 0.96)
+            ],
+            accent: [
+                AppGridThemeStop(color: AppGridThemeColor(red: 1.00, green: 0.22, blue: 0.62), opacity: 0.18),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.70, green: 0.20, blue: 1.00), opacity: 0.17),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.10, green: 0.72, blue: 1.00), opacity: 0.13),
+                AppGridThemeStop(color: AppGridThemeColor(red: 1.00, green: 0.58, blue: 0.82), opacity: 0.12)
+            ],
+            preview: [
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.05, green: 0.03, blue: 0.10), opacity: 1),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.44, green: 0.06, blue: 0.32), opacity: 1)
+            ]
+        ),
+        AppGridThemePalette(
+            base: [
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.00, green: 0.02, blue: 0.08), opacity: 0.99),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.02, green: 0.08, blue: 0.22), opacity: 0.97),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.00, green: 0.22, blue: 0.36), opacity: 0.88),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.03, green: 0.04, blue: 0.13), opacity: 0.96)
+            ],
+            accent: [
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.00, green: 0.62, blue: 1.00), opacity: 0.20),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.24, green: 0.34, blue: 1.00), opacity: 0.18),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.00, green: 1.00, blue: 0.92), opacity: 0.12),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.52, green: 0.20, blue: 1.00), opacity: 0.12)
+            ],
+            preview: [
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.00, green: 0.03, blue: 0.10), opacity: 1),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.00, green: 0.30, blue: 0.52), opacity: 1)
+            ]
+        ),
+        AppGridThemePalette(
+            base: [
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.01, green: 0.04, blue: 0.04), opacity: 0.99),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.02, green: 0.14, blue: 0.10), opacity: 0.95),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.02, green: 0.30, blue: 0.17), opacity: 0.86),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.04, green: 0.07, blue: 0.14), opacity: 0.96)
+            ],
+            accent: [
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.42, green: 1.00, blue: 0.52), opacity: 0.16),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.00, green: 0.88, blue: 0.78), opacity: 0.15),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.24, green: 0.44, blue: 1.00), opacity: 0.13),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.80, green: 0.80, blue: 0.28), opacity: 0.10)
+            ],
+            preview: [
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.01, green: 0.06, blue: 0.05), opacity: 1),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.03, green: 0.34, blue: 0.18), opacity: 1)
+            ]
+        ),
+        AppGridThemePalette(
+            base: [
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.02, green: 0.02, blue: 0.07), opacity: 0.98),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.10, green: 0.05, blue: 0.22), opacity: 0.95),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.18, green: 0.08, blue: 0.35), opacity: 0.86),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.02, green: 0.08, blue: 0.16), opacity: 0.96)
+            ],
+            accent: [
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.72, green: 0.48, blue: 1.00), opacity: 0.17),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.26, green: 0.86, blue: 1.00), opacity: 0.15),
+                AppGridThemeStop(color: AppGridThemeColor(red: 1.00, green: 0.52, blue: 0.86), opacity: 0.13),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.18, green: 0.92, blue: 0.76), opacity: 0.10)
+            ],
+            preview: [
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.03, green: 0.02, blue: 0.08), opacity: 1),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.24, green: 0.10, blue: 0.48), opacity: 1)
+            ]
+        )
+    ]
+
+    static let lightColorfulPalettes: [AppGridThemePalette] = [
+        AppGridThemePalette(
+            base: [
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.10, green: 0.78, blue: 1.00), opacity: 0.95),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.34, green: 0.96, blue: 0.94), opacity: 0.92),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.73, green: 0.78, blue: 1.00), opacity: 0.90),
+                AppGridThemeStop(color: AppGridThemeColor(red: 1.00, green: 0.58, blue: 0.94), opacity: 0.86)
+            ],
+            accent: [
+                AppGridThemeStop(color: AppGridThemeColor(red: 1.00, green: 1.00, blue: 1.00), opacity: 0.16),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.00, green: 0.78, blue: 1.00), opacity: 0.22),
+                AppGridThemeStop(color: AppGridThemeColor(red: 1.00, green: 0.45, blue: 0.95), opacity: 0.22),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.35, green: 1.00, blue: 0.92), opacity: 0.18)
+            ],
+            preview: [
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.10, green: 0.78, blue: 1.00), opacity: 1),
+                AppGridThemeStop(color: AppGridThemeColor(red: 1.00, green: 0.56, blue: 0.94), opacity: 1)
+            ]
+        ),
+        AppGridThemePalette(
+            base: [
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.72, green: 0.98, blue: 0.72), opacity: 0.94),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.48, green: 0.88, blue: 1.00), opacity: 0.92),
+                AppGridThemeStop(color: AppGridThemeColor(red: 1.00, green: 0.88, blue: 0.42), opacity: 0.84),
+                AppGridThemeStop(color: AppGridThemeColor(red: 1.00, green: 0.62, blue: 0.82), opacity: 0.84)
+            ],
+            accent: [
+                AppGridThemeStop(color: AppGridThemeColor(red: 1.00, green: 1.00, blue: 1.00), opacity: 0.20),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.20, green: 0.92, blue: 0.64), opacity: 0.20),
+                AppGridThemeStop(color: AppGridThemeColor(red: 1.00, green: 0.66, blue: 0.20), opacity: 0.16),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.50, green: 0.52, blue: 1.00), opacity: 0.16)
+            ],
+            preview: [
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.50, green: 0.92, blue: 1.00), opacity: 1),
+                AppGridThemeStop(color: AppGridThemeColor(red: 1.00, green: 0.78, blue: 0.38), opacity: 1)
+            ]
+        ),
+        AppGridThemePalette(
+            base: [
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.78, green: 0.90, blue: 1.00), opacity: 0.95),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.56, green: 0.72, blue: 1.00), opacity: 0.90),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.78, green: 0.65, blue: 1.00), opacity: 0.86),
+                AppGridThemeStop(color: AppGridThemeColor(red: 1.00, green: 0.72, blue: 0.96), opacity: 0.84)
+            ],
+            accent: [
+                AppGridThemeStop(color: AppGridThemeColor(red: 1.00, green: 1.00, blue: 1.00), opacity: 0.18),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.00, green: 0.70, blue: 1.00), opacity: 0.18),
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.82, green: 0.36, blue: 1.00), opacity: 0.18),
+                AppGridThemeStop(color: AppGridThemeColor(red: 1.00, green: 0.48, blue: 0.74), opacity: 0.16)
+            ],
+            preview: [
+                AppGridThemeStop(color: AppGridThemeColor(red: 0.62, green: 0.80, blue: 1.00), opacity: 1),
+                AppGridThemeStop(color: AppGridThemeColor(red: 1.00, green: 0.70, blue: 0.96), opacity: 1)
+            ]
+        )
+    ]
 }

--
Gitblit v1.9.3