Add light mode for predefined color schemes

This commit is contained in:
Ly-sec
2025-08-18 13:37:43 +02:00
parent c482f800fe
commit 9a71598944
10 changed files with 379 additions and 141 deletions

View File

@@ -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"
}
}

View File

@@ -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"
}
}

View File

@@ -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"
}
}

View File

@@ -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"
}
}

View File

@@ -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"
}
}

View File

@@ -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"
}
}

View File

@@ -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"
}
}

View File

@@ -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"
}
}

View File

@@ -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
}
}
}

View File

@@ -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: {