diff --git a/Assets/ColorScheme/Catppuccin.json b/Assets/ColorScheme/Catppuccin.json index 5336a71..d02708c 100644 --- a/Assets/ColorScheme/Catppuccin.json +++ b/Assets/ColorScheme/Catppuccin.json @@ -1,19 +1,40 @@ { - "mPrimary": "#cba6f7", - "mOnPrimary": "#11111b", - "mSecondary": "#fab387", - "mOnSecondary": "#11111b", - "mTertiary": "#a6e3a1", - "mOnTertiary": "#11111b", + "dark": { + "mPrimary": "#cba6f7", + "mOnPrimary": "#11111b", + "mSecondary": "#fab387", + "mOnSecondary": "#11111b", + "mTertiary": "#a6e3a1", + "mOnTertiary": "#11111b", - "mError": "#f38ba8", - "mOnError": "#11111b", + "mError": "#f38ba8", + "mOnError": "#11111b", - "mSurface": "#1e1e2e", - "mOnSurface": "#cdd6f4", - "mSurfaceVariant": "#313244", - "mOnSurfaceVariant": "#a3b4eb", - "mOutline": "#45475a", - "mOutlineVariant": "#2f303d", - "mShadow": "#11111b" + "mSurface": "#1e1e2e", + "mOnSurface": "#cdd6f4", + "mSurfaceVariant": "#313244", + "mOnSurfaceVariant": "#a3b4eb", + "mOutline": "#45475a", + "mOutlineVariant": "#2f303d", + "mShadow": "#11111b" + }, + "light": { + "mPrimary": "#8839ef", + "mOnPrimary": "#eff1f5", + "mSecondary": "#fe640b", + "mOnSecondary": "#eff1f5", + "mTertiary": "#40a02b", + "mOnTertiary": "#eff1f5", + + "mError": "#d20f39", + "mOnError": "#eff1f5", + + "mSurface": "#eff1f5", + "mOnSurface": "#4c4f69", + "mSurfaceVariant": "#ccd0da", + "mOnSurfaceVariant": "#6c6f85", + "mOutline": "#9ca0b0", + "mOutlineVariant": "#bcc0cc", + "mShadow": "#dce0e8" + } } diff --git a/Assets/ColorScheme/Dracula.json b/Assets/ColorScheme/Dracula.json index deb173c..d4cea09 100644 --- a/Assets/ColorScheme/Dracula.json +++ b/Assets/ColorScheme/Dracula.json @@ -1,19 +1,45 @@ { - "mPrimary": "#bd93f9", - "mOnPrimary": "#282A36", - "mSecondary": "#ff79c6", - "mOnSecondary": "#4e1d32", - "mTertiary": "#8be9fd", - "mOnTertiary": "#003543", + "dark": { + "mPrimary": "#bd93f9", + "mOnPrimary": "#282A36", + "mSecondary": "#ff79c6", + "mOnSecondary": "#4e1d32", + "mTertiary": "#8be9fd", + "mOnTertiary": "#003543", - "mError": "#FF5555", - "mOnError": "#282A36", + "mError": "#FF5555", + "mOnError": "#282A36", - "mSurface": "#282A36", - "mOnSurface": "#F8F8F2", - "mSurfaceVariant": "#44475A", - "mOnSurfaceVariant": "#d6d8e0", - "mOutline": "#4d5c86", - "mOutlineVariant": "#3a4666", - "mShadow": "#282A36" + "mSurface": "#282A36", + "mOnSurface": "#F8F8F2", + "mSurfaceVariant": "#44475A", + "mOnSurfaceVariant": "#d6d8e0", + "mOutline": "#4d5c86", + "mOutlineVariant": "#3a4666", + "mShadow": "#282A36" + }, + "light": { + "mPrimary": "#7b5cd6", + "mOnPrimary": "#ffffff", + + "mSecondary": "#e64590", + "mOnSecondary": "#ffffff", + + "mTertiary": "#26b5d6", + "mOnTertiary": "#ffffff", + + "mError": "#cc0000", + "mOnError": "#ffffff", + + "mSurface": "#f8f8f2", + "mOnSurface": "#282a36", + + "mSurfaceVariant": "#e6e6ea", + "mOnSurfaceVariant": "#44475a", + + "mOutline": "#b3b3c6", + "mOutlineVariant": "#d6d8e0", + + "mShadow": "#00000026" + } } diff --git a/Assets/ColorScheme/Gruvbox.json b/Assets/ColorScheme/Gruvbox.json index 654223d..077b5e8 100644 --- a/Assets/ColorScheme/Gruvbox.json +++ b/Assets/ColorScheme/Gruvbox.json @@ -1,19 +1,40 @@ { - "mPrimary": "#b8bb26", - "mOnPrimary": "#282828", - "mSecondary": "#fabd2f", - "mOnSecondary": "#282828", - "mTertiary": "#83a598", - "mOnTertiary": "#282828", + "dark": { + "mPrimary": "#b8bb26", + "mOnPrimary": "#282828", + "mSecondary": "#fabd2f", + "mOnSecondary": "#282828", + "mTertiary": "#83a598", + "mOnTertiary": "#282828", - "mError": "#fb4934", - "mOnError": "#282828", + "mError": "#fb4934", + "mOnError": "#282828", - "mSurface": "#282828", - "mOnSurface": "#fbf1c7", - "mSurfaceVariant": "#3c3836", - "mOnSurfaceVariant": "#ebdbb2", - "mOutline": "#665c54", - "mOutlineVariant": "#3c3836", - "mShadow": "#282828" + "mSurface": "#282828", + "mOnSurface": "#fbf1c7", + "mSurfaceVariant": "#3c3836", + "mOnSurfaceVariant": "#ebdbb2", + "mOutline": "#665c54", + "mOutlineVariant": "#3c3836", + "mShadow": "#282828" + }, + "light": { + "mPrimary": "#98971a", + "mOnPrimary": "#fbf1c7", + "mSecondary": "#d79921", + "mOnSecondary": "#fbf1c7", + "mTertiary": "#458588", + "mOnTertiary": "#fbf1c7", + + "mError": "#cc241d", + "mOnError": "#fbf1c7", + + "mSurface": "#fbf1c7", + "mOnSurface": "#3c3836", + "mSurfaceVariant": "#ebdbb2", + "mOnSurfaceVariant": "#7c6f64", + "mOutline": "#928374", + "mOutlineVariant": "#bdae93", + "mShadow": "#d5c4a1" + } } diff --git a/Assets/ColorScheme/Noctalia (default).json b/Assets/ColorScheme/Noctalia (default).json index 1a16c59..f72d025 100644 --- a/Assets/ColorScheme/Noctalia (default).json +++ b/Assets/ColorScheme/Noctalia (default).json @@ -1,14 +1,15 @@ { + "dark": { "mPrimary": "#c7a1d8", "mOnPrimary": "#1a151f", "mSecondary": "#a984c4", "mOnSecondary": "#f3edf7", "mTertiary": "#e0b7c9", "mOnTertiary": "#20161f", - + "mError": "#e9899d", "mOnError": "#1e1418", - + "mSurface": "#1c1822", "mOnSurface": "#e9e4f0", "mSurfaceVariant": "#262130", @@ -16,5 +17,30 @@ "mOutline": "#4d445a", "mOutlineVariant": "#342c42", "mShadow": "#120f18" + }, + "light": { + "mPrimary": "#8b4ea8", + "mOnPrimary": "#ffffff", + + "mSecondary": "#7a4d99", + "mOnSecondary": "#ffffff", + + "mTertiary": "#c47a94", + "mOnTertiary": "#ffffff", + + "mError": "#c03d5a", + "mOnError": "#ffffff", + + "mSurface": "#f5f1fa", + "mOnSurface": "#1c1822", + + "mSurfaceVariant": "#e7dfee", + "mOnSurfaceVariant": "#4a3d59", + + "mOutline": "#b8a9c9", + "mOutlineVariant": "#d8cfe2", + + "mShadow": "#00000026" } +} \ No newline at end of file diff --git a/Assets/ColorScheme/Nord.json b/Assets/ColorScheme/Nord.json index 1335d43..ed67760 100644 --- a/Assets/ColorScheme/Nord.json +++ b/Assets/ColorScheme/Nord.json @@ -1,19 +1,40 @@ { - "mPrimary": "#8fbcbb", - "mOnPrimary": "#2e3440", - "mSecondary": "#88c0d0", - "mOnSecondary": "#2e3440", - "mTertiary": "#5e81ac", - "mOnTertiary": "#2e3440", + "dark": { + "mPrimary": "#8fbcbb", + "mOnPrimary": "#2e3440", + "mSecondary": "#88c0d0", + "mOnSecondary": "#2e3440", + "mTertiary": "#5e81ac", + "mOnTertiary": "#2e3440", - "mError": "#bf616a", - "mOnError": "#2e3440", + "mError": "#bf616a", + "mOnError": "#2e3440", - "mSurface": "#2e3440", - "mOnSurface": "#d8dee9", - "mSurfaceVariant": "#3b4252", - "mOnSurfaceVariant": "#e5e9f0", - "mOutline": "#434c5e", - "mOutlineVariant": "#2e3440", - "mShadow": "#2e3440" + "mSurface": "#2e3440", + "mOnSurface": "#d8dee9", + "mSurfaceVariant": "#3b4252", + "mOnSurfaceVariant": "#e5e9f0", + "mOutline": "#434c5e", + "mOutlineVariant": "#2e3440", + "mShadow": "#2e3440" + }, + "light": { + "mPrimary": "#5e81ac", + "mOnPrimary": "#eceff4", + "mSecondary": "#88c0d0", + "mOnSecondary": "#eceff4", + "mTertiary": "#8fbcbb", + "mOnTertiary": "#eceff4", + + "mError": "#bf616a", + "mOnError": "#eceff4", + + "mSurface": "#eceff4", + "mOnSurface": "#2e3440", + "mSurfaceVariant": "#e5e9f0", + "mOnSurfaceVariant": "#4c566a", + "mOutline": "#d8dee9", + "mOutlineVariant": "#e5e9f0", + "mShadow": "#d8dee9" + } } diff --git a/Assets/ColorScheme/Rosepine.json b/Assets/ColorScheme/Rosepine.json index 009fa0a..7a606cf 100644 --- a/Assets/ColorScheme/Rosepine.json +++ b/Assets/ColorScheme/Rosepine.json @@ -1,19 +1,40 @@ { - "mPrimary": "#ebbcba", - "mOnPrimary": "#191724", - "mSecondary": "#9ccfd8", - "mOnSecondary": "#191724", - "mTertiary": "#f6c177", - "mOnTertiary": "#191724", + "dark": { + "mPrimary": "#ebbcba", + "mOnPrimary": "#191724", + "mSecondary": "#9ccfd8", + "mOnSecondary": "#191724", + "mTertiary": "#f6c177", + "mOnTertiary": "#191724", - "mError": "#eb6f92", - "mOnError": "#1f1d2e", + "mError": "#eb6f92", + "mOnError": "#1f1d2e", - "mSurface": "#191724", - "mOnSurface": "#e0def4", - "mSurfaceVariant": "#26233a", - "mOnSurfaceVariant": "#908caa", - "mOutline": "#44415a", - "mOutlineVariant": "#2e2c3c", - "mShadow": "#191724" + "mSurface": "#191724", + "mOnSurface": "#e0def4", + "mSurfaceVariant": "#26233a", + "mOnSurfaceVariant": "#908caa", + "mOutline": "#44415a", + "mOutlineVariant": "#2e2c3c", + "mShadow": "#191724" + }, + "light": { + "mPrimary": "#286983", + "mOnPrimary": "#faf4ed", + "mSecondary": "#56949f", + "mOnSecondary": "#faf4ed", + "mTertiary": "#d7827e", + "mOnTertiary": "#faf4ed", + + "mError": "#b4637a", + "mOnError": "#faf4ed", + + "mSurface": "#faf4ed", + "mOnSurface": "#575279", + "mSurfaceVariant": "#f2e9e1", + "mOnSurfaceVariant": "#797593", + "mOutline": "#9893a5", + "mOutlineVariant": "#cecacd", + "mShadow": "#f2e9e1" + } } diff --git a/Assets/ColorScheme/Solarized.json b/Assets/ColorScheme/Solarized.json index d81daf4..667cad7 100644 --- a/Assets/ColorScheme/Solarized.json +++ b/Assets/ColorScheme/Solarized.json @@ -1,19 +1,40 @@ { - "mPrimary": "#b58900", - "mOnPrimary": "#002b36", - "mSecondary": "#d33682", - "mOnSecondary": "#002b36", - "mTertiary": "#cb4b16", - "mOnTertiary": "#002b36", + "dark": { + "mPrimary": "#b58900", + "mOnPrimary": "#002b36", + "mSecondary": "#d33682", + "mOnSecondary": "#002b36", + "mTertiary": "#cb4b16", + "mOnTertiary": "#002b36", - "mError": "#dc322f", - "mOnError": "#002b36", + "mError": "#dc322f", + "mOnError": "#002b36", - "mSurface": "#002b36", - "mOnSurface": "#839496", - "mSurfaceVariant": "#073642", - "mOnSurfaceVariant": "#657b83", - "mOutline": "#006883", - "mOutlineVariant": "#004050", - "mShadow": "#002b36" + "mSurface": "#002b36", + "mOnSurface": "#839496", + "mSurfaceVariant": "#073642", + "mOnSurfaceVariant": "#657b83", + "mOutline": "#586e75", + "mOutlineVariant": "#073642", + "mShadow": "#002b36" + }, + "light": { + "mPrimary": "#b58900", + "mOnPrimary": "#fdf6e3", + "mSecondary": "#d33682", + "mOnSecondary": "#fdf6e3", + "mTertiary": "#cb4b16", + "mOnTertiary": "#fdf6e3", + + "mError": "#dc322f", + "mOnError": "#fdf6e3", + + "mSurface": "#fdf6e3", + "mOnSurface": "#657b83", + "mSurfaceVariant": "#eee8d5", + "mOnSurfaceVariant": "#839496", + "mOutline": "#93a1a1", + "mOutlineVariant": "#eee8d5", + "mShadow": "#eee8d5" + } } diff --git a/Assets/ColorScheme/Tokyo Night.json b/Assets/ColorScheme/Tokyo Night.json index 49a4d74..6b37c4e 100644 --- a/Assets/ColorScheme/Tokyo Night.json +++ b/Assets/ColorScheme/Tokyo Night.json @@ -1,19 +1,40 @@ { - "mPrimary": "#ff9e64", - "mOnPrimary": "#1a1b26", - "mSecondary": "#ff4499", - "mOnSecondary": "#1a1b26", - "mTertiary": "#7aa2f7", - "mOnTertiary": "#1a1b26", + "dark": { + "mPrimary": "#ff9e64", + "mOnPrimary": "#1a1b26", + "mSecondary": "#e0af68", + "mOnSecondary": "#1a1b26", + "mTertiary": "#7aa2f7", + "mOnTertiary": "#1a1b26", - "mError": "#f7768e", - "mOnError": "#1f1d2e", + "mError": "#f7768e", + "mOnError": "#1a1b26", - "mSurface": "#1a1b26", - "mOnSurface": "#a9b1d6", - "mSurfaceVariant": "#292e42", - "mOnSurfaceVariant": "#787c99", - "mOutline": "#3b4261", - "mOutlineVariant": "#282c41", - "mShadow": "#1a1b26" + "mSurface": "#1a1b26", + "mOnSurface": "#a9b1d6", + "mSurfaceVariant": "#292e42", + "mOnSurfaceVariant": "#787c99", + "mOutline": "#3b4261", + "mOutlineVariant": "#282c41", + "mShadow": "#1a1b26" + }, + "light": { + "mPrimary": "#8c4351", + "mOnPrimary": "#e6e7ed", + "mSecondary": "#8f5e15", + "mOnSecondary": "#e6e7ed", + "mTertiary": "#34548a", + "mOnTertiary": "#e6e7ed", + + "mError": "#965027", + "mOnError": "#e6e7ed", + + "mSurface": "#e6e7ed", + "mOnSurface": "#343b58", + "mSurfaceVariant": "#d5d6db", + "mOnSurfaceVariant": "#40434f", + "mOutline": "#6c6e75", + "mOutlineVariant": "#9699a3", + "mShadow": "#c0caf5" + } } diff --git a/Modules/SettingsPanel/Tabs/ColorSchemeTab.qml b/Modules/SettingsPanel/Tabs/ColorSchemeTab.qml index 5810740..b2e734c 100644 --- a/Modules/SettingsPanel/Tabs/ColorSchemeTab.qml +++ b/Modules/SettingsPanel/Tabs/ColorSchemeTab.qml @@ -11,21 +11,26 @@ ColumnLayout { spacing: 0 - // Helper function to get color from scheme file + // Helper function to get color from scheme file (supports dark/light variants) function getSchemeColor(schemePath, colorKey) { // Extract scheme name from path var schemeName = schemePath.split("/").pop().replace(".json", "") // Try to get from cached data first - if (schemeColorsCache[schemeName] && schemeColorsCache[schemeName][colorKey]) { - return schemeColorsCache[schemeName][colorKey] + if (schemeColorsCache[schemeName]) { + var entry = schemeColorsCache[schemeName] + var variant = entry + if (entry.dark || entry.light) { + variant = Settings.data.colorSchemes.darkMode ? (entry.dark || entry.light) : (entry.light || entry.dark) + } + if (variant && variant[colorKey]) return variant[colorKey] } // Return a default color if not cached yet return "#000000" } - // Cache for scheme colors + // Cache for scheme JSON (can be flat or {dark, light}) property var schemeColorsCache: ({}) // Scale properties for card animations @@ -34,33 +39,9 @@ ColumnLayout { // This function is called by the FileView Repeater when a scheme file is loaded function schemeLoaded(schemeName, jsonData) { - var colors = {} - - // Extract colors from JSON data - if (jsonData && typeof jsonData === 'object') { - colors.mPrimary = jsonData.mPrimary || jsonData.primary || "#000000" - colors.mSecondary = jsonData.mSecondary || jsonData.secondary || "#000000" - colors.mTertiary = jsonData.mTertiary || jsonData.tertiary || "#000000" - colors.mError = jsonData.mError || jsonData.error || "#ff0000" - colors.mSurface = jsonData.mSurface || jsonData.surface || "#ffffff" - colors.mOnSurface = jsonData.mOnSurface || jsonData.onSurface || "#000000" - colors.mOutline = jsonData.mOutline || jsonData.outline || "#666666" - } else { - // Default colors on failure - colors = { - "mPrimary": "#000000", - "mSecondary": "#000000", - "mTertiary": "#000000", - "mError": "#ff0000", - "mSurface": "#ffffff", - "mOnSurface": "#000000", - "mOutline": "#666666" - } - } - - // Update the cache. This must be done by re-assigning the whole object to trigger updates. + var value = jsonData || {} var newCache = schemeColorsCache - newCache[schemeName] = colors + newCache[schemeName] = value schemeColorsCache = newCache } @@ -138,16 +119,23 @@ ColumnLayout { } } - // Dark Mode Toggle + // Dark Mode Toggle (affects both Matugen and predefined schemes that provide variants) NToggle { label: "Dark Mode" - description: "Generate dark theme colors when using Matugen. Disable for light theme." + description: Settings.data.colorSchemes.useWallpaperColors + ? "Generate dark theme colors when using Matugen. Disable for light theme." + : "If the selected predefined scheme has light/dark variants, this chooses which one." checked: Settings.data.colorSchemes.darkMode - enabled: Settings.data.colorSchemes.useWallpaperColors + enabled: true onToggled: checked => { Settings.data.colorSchemes.darkMode = checked if (Settings.data.colorSchemes.useWallpaperColors) { ColorSchemeService.changedWallpaper() + } else if (Settings.data.colorSchemes.predefinedScheme) { + // Re-apply current scheme to pick the right variant + ColorSchemeService.applyScheme(Settings.data.colorSchemes.predefinedScheme) + // Force refresh of previews + var tmp = schemeColorsCache; schemeColorsCache = {}; schemeColorsCache = tmp } } } diff --git a/Services/ColorSchemeService.qml b/Services/ColorSchemeService.qml index 2dcab0f..17566ba 100644 --- a/Services/ColorSchemeService.qml +++ b/Services/ColorSchemeService.qml @@ -18,6 +18,8 @@ Singleton { property bool scanning: false property string schemesDirectory: Quickshell.shellDir + "/Assets/ColorScheme" property string colorsJsonFilePath: Settings.configDir + "colors.json" + // Internal: remember last path if needed + property string pendingApplyPath: "" function loadColorSchemes() { Logger.log("ColorScheme", "Load ColorScheme") @@ -29,7 +31,11 @@ Singleton { } function applyScheme(filePath) { - Quickshell.execDetached(["cp", filePath, colorsJsonFilePath]) + // Read the scheme JSON and write the effective variant to colors.json + pendingApplyPath = filePath + // Force reload by bouncing the path + schemeReader.path = "" + schemeReader.path = filePath } function changedWallpaper() { @@ -60,6 +66,72 @@ Singleton { } } + // Internal loader to read a scheme file + FileView { + id: schemeReader + onLoaded: { + try { + var data = JSON.parse(text()) + var variant = data + // If scheme provides dark/light variants, pick based on settings + if (data && (data.dark || data.light)) { + if (Settings.data.colorSchemes.darkMode) { + variant = data.dark || data.light + } else { + variant = data.light || data.dark + } + } + writeColorsToDisk(variant) + } catch (e) { + Logger.error("ColorScheme", "Failed to parse scheme JSON:", e) + } + } + } + + // Writer to colors.json using a JsonAdapter for safety + FileView { + id: colorsWriter + path: colorsJsonFilePath + JsonAdapter { + id: out + property color mPrimary: "#000000" + property color mOnPrimary: "#000000" + property color mSecondary: "#000000" + property color mOnSecondary: "#000000" + property color mTertiary: "#000000" + property color mOnTertiary: "#000000" + property color mError: "#ff0000" + property color mOnError: "#000000" + property color mSurface: "#ffffff" + property color mOnSurface: "#000000" + property color mSurfaceVariant: "#cccccc" + property color mOnSurfaceVariant: "#333333" + property color mOutline: "#666666" + property color mOutlineVariant: "#444444" + property color mShadow: "#000000" + } + } + + function writeColorsToDisk(obj) { + function pick(o, a, b, fallback) { return (o && (o[a] || o[b])) || fallback } + out.mPrimary = pick(obj, "mPrimary", "primary", out.mPrimary) + out.mOnPrimary = pick(obj, "mOnPrimary", "onPrimary", out.mOnPrimary) + out.mSecondary = pick(obj, "mSecondary", "secondary", out.mSecondary) + out.mOnSecondary = pick(obj, "mOnSecondary", "onSecondary", out.mOnSecondary) + out.mTertiary = pick(obj, "mTertiary", "tertiary", out.mTertiary) + out.mOnTertiary = pick(obj, "mOnTertiary", "onTertiary", out.mOnTertiary) + out.mError = pick(obj, "mError", "error", out.mError) + out.mOnError = pick(obj, "mOnError", "onError", out.mOnError) + out.mSurface = pick(obj, "mSurface", "surface", out.mSurface) + out.mOnSurface = pick(obj, "mOnSurface", "onSurface", out.mOnSurface) + out.mSurfaceVariant = pick(obj, "mSurfaceVariant", "surfaceVariant", out.mSurfaceVariant) + out.mOnSurfaceVariant = pick(obj, "mOnSurfaceVariant", "onSurfaceVariant", out.mOnSurfaceVariant) + out.mOutline = pick(obj, "mOutline", "outline", out.mOutline) + out.mOutlineVariant = pick(obj, "mOutlineVariant", "outlineVariant", out.mOutlineVariant) + out.mShadow = pick(obj, "mShadow", "shadow", out.mShadow) + colorsWriter.writeAdapter() + } + Process { id: generateColorsProcess command: {