From 508c1407be683e3ecc537874ffeebdc9de6f73e2 Mon Sep 17 00:00:00 2001 From: LemmyCook Date: Tue, 2 Sep 2025 10:34:05 -0400 Subject: [PATCH] DarkModeToggle: new bar widget --- Commons/Settings.qml | 8 +++++- Modules/Bar/Widgets/DarkModeToggle.qml | 23 +++++++++++++++ Modules/SettingsPanel/Tabs/ColorSchemeTab.qml | 28 ++++++++----------- Modules/SettingsPanel/Tabs/GeneralTab.qml | 12 ++------ Services/BarWidgetRegistry.qml | 4 +++ Services/ColorSchemeService.qml | 24 ++++++++++++---- Services/MatugenService.qml | 26 ++++++++++++++--- 7 files changed, 89 insertions(+), 36 deletions(-) create mode 100644 Modules/Bar/Widgets/DarkModeToggle.qml diff --git a/Commons/Settings.qml b/Commons/Settings.qml index afac08c..442341f 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -63,6 +63,7 @@ Singleton { Logger.log("Settings", "Bar monitor list is empty, will show on all available screens") } } + Item { Component.onCompleted: { @@ -100,8 +101,13 @@ Singleton { // Emit the signal root.settingsLoaded() + // Kickoff ColorScheme service + ColorSchemeService.init() + + // Kickoff Matugen service + MatugenService.init() + Qt.callLater(function () { - // Some stuff like settings validation should just be executed once on startup and not on every reload validateMonitorConfigurations() }) } diff --git a/Modules/Bar/Widgets/DarkModeToggle.qml b/Modules/Bar/Widgets/DarkModeToggle.qml new file mode 100644 index 0000000..ae7d933 --- /dev/null +++ b/Modules/Bar/Widgets/DarkModeToggle.qml @@ -0,0 +1,23 @@ +import Quickshell +import qs.Commons +import qs.Widgets +import qs.Services + +NIconButton { + id: root + + property ShellScreen screen + property real scaling: 1.0 + + icon: "contrast" + tooltipText: "Toggle light/dark mode" + sizeRatio: 0.8 + + colorBg: Color.mSurfaceVariant + colorFg: Color.mOnSurface + colorBorder: Color.transparent + colorBorderHover: Color.transparent + + anchors.verticalCenter: parent.verticalCenter + onClicked: Settings.data.colorSchemes.darkMode = !Settings.data.colorSchemes.darkMode +} diff --git a/Modules/SettingsPanel/Tabs/ColorSchemeTab.qml b/Modules/SettingsPanel/Tabs/ColorSchemeTab.qml index e3e9aac..5196387 100644 --- a/Modules/SettingsPanel/Tabs/ColorSchemeTab.qml +++ b/Modules/SettingsPanel/Tabs/ColorSchemeTab.qml @@ -63,7 +63,6 @@ ColumnLayout { if (exitCode === 0) { // Matugen exists, enable it Settings.data.colorSchemes.useWallpaperColors = true - Settings.data.colorSchemes.predefinedScheme = "" MatugenService.generateFromWallpaper() ToastService.showNotice("Matugen", "Enabled") } else { @@ -122,19 +121,7 @@ ColumnLayout { description: Settings.data.colorSchemes.useWallpaperColors ? "Generate dark theme colors when using Matugen." : "Use a dark variant if available." checked: Settings.data.colorSchemes.darkMode enabled: true - onToggled: checked => { - Settings.data.colorSchemes.darkMode = checked - if (Settings.data.colorSchemes.useWallpaperColors) { - MatugenService.generateFromWallpaper() - } 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 - } - } + onToggled: checked => Settings.data.colorSchemes.darkMode = checked } // Use Matugen @@ -149,6 +136,11 @@ ColumnLayout { } else { Settings.data.colorSchemes.useWallpaperColors = false ToastService.showNotice("Matugen", "Disabled") + + if (Settings.data.colorSchemes.predefinedScheme) { + + ColorSchemeService.applyScheme(Settings.data.colorSchemes.predefinedScheme) + } } } } @@ -199,7 +191,8 @@ ColumnLayout { radius: Style.radiusM * scaling color: getSchemeColor(modelData, "mSurface") border.width: Math.max(1, Style.borderL * scaling) - border.color: Settings.data.colorSchemes.predefinedScheme === modelData ? Color.mPrimary : Color.mOutline + border.color: (!Settings.data.colorSchemes.useWallpaperColors + && (Settings.data.colorSchemes.predefinedScheme === modelData)) ? Color.mPrimary : Color.mOutline scale: root.cardScaleLow // Mouse area for selection @@ -290,9 +283,10 @@ ColumnLayout { } } - // Selection indicator + // Selection indicator (Checkmark) Rectangle { - visible: Settings.data.colorSchemes.predefinedScheme === schemePath + visible: !Settings.data.colorSchemes.useWallpaperColors + && (Settings.data.colorSchemes.predefinedScheme === schemePath) anchors.right: parent.right anchors.top: parent.top anchors.margins: Style.marginS * scaling diff --git a/Modules/SettingsPanel/Tabs/GeneralTab.qml b/Modules/SettingsPanel/Tabs/GeneralTab.qml index 4d38d23..e7ed212 100644 --- a/Modules/SettingsPanel/Tabs/GeneralTab.qml +++ b/Modules/SettingsPanel/Tabs/GeneralTab.qml @@ -58,27 +58,21 @@ ColumnLayout { label: "Show Corners" description: "Display rounded corners on the edge of the screen." checked: Settings.data.general.showScreenCorners - onToggled: checked => - Settings.data.general.showScreenCorners = checked - + onToggled: checked => Settings.data.general.showScreenCorners = checked } NToggle { label: "Dim Desktop" description: "Dim the desktop when panels or menus are open." checked: Settings.data.general.dimDesktop - onToggled: checked => - Settings.data.general.dimDesktop = checked - + onToggled: checked => Settings.data.general.dimDesktop = checked } NToggle { label: "Auto-hide Dock" description: "Automatically hide the dock when not in use." checked: Settings.data.dock.autoHide - onToggled: checked => - Settings.data.dock.autoHide = checked - + onToggled: checked => Settings.data.dock.autoHide = checked } ColumnLayout { diff --git a/Services/BarWidgetRegistry.qml b/Services/BarWidgetRegistry.qml index e27aaec..fc7016a 100644 --- a/Services/BarWidgetRegistry.qml +++ b/Services/BarWidgetRegistry.qml @@ -16,6 +16,7 @@ Singleton { "Bluetooth": bluetoothComponent, "Brightness": brightnessComponent, "Clock": clockComponent, + "DarkModeToggle": darkModeToggle, "KeyboardLayout": keyboardLayoutComponent, "MediaMini": mediaMiniComponent, "Microphone": microphoneComponent, @@ -51,6 +52,9 @@ Singleton { property Component clockComponent: Component { Clock {} } + property Component darkModeToggle: Component { + DarkModeToggle {} + } property Component keyboardLayoutComponent: Component { KeyboardLayout {} } diff --git a/Services/ColorSchemeService.qml b/Services/ColorSchemeService.qml index 624c05e..096f8f9 100644 --- a/Services/ColorSchemeService.qml +++ b/Services/ColorSchemeService.qml @@ -10,16 +10,30 @@ import qs.Services Singleton { id: root - Component.onCompleted: { - Logger.log("ColorScheme", "Service started") - loadColorSchemes() - } - property var schemes: [] property bool scanning: false property string schemesDirectory: Quickshell.shellDir + "/Assets/ColorScheme" property string colorsJsonFilePath: Settings.configDir + "colors.json" + Connections { + target: Settings.data.colorSchemes + function onDarkModeChanged() { + Logger.log("ColorScheme", "Detected dark mode change") + if (!Settings.data.colorSchemes.useWallpaperColors && Settings.data.colorSchemes.predefinedScheme) { + // Re-apply current scheme to pick the right variant + applyScheme(Settings.data.colorSchemes.predefinedScheme) + } + } + } + + // -------------------------------- + function init() { + // does nothing but ensure the singleton is created + // do not remove + Logger.log("ColorScheme", "Service started") + loadColorSchemes() + } + function loadColorSchemes() { Logger.log("ColorScheme", "Load ColorScheme") scanning = true diff --git a/Services/MatugenService.qml b/Services/MatugenService.qml index b41a532..ef80b7d 100644 --- a/Services/MatugenService.qml +++ b/Services/MatugenService.qml @@ -10,7 +10,7 @@ import qs.Services Singleton { id: root - property string dynamicConfigPath: Settings.cacheDir + "matugen.dynamic.toml" + property string dynamicConfigPath: Settings.isLoaded ? Settings.cacheDir + "matugen.dynamic.toml" : "" // External state management Connections { @@ -23,6 +23,23 @@ Singleton { } } + Connections { + target: Settings.data.colorSchemes + function onDarkModeChanged() { + Logger.log("Matugen", "Detected dark mode change") + if (Settings.data.colorSchemes.useWallpaperColors) { + MatugenService.generateFromWallpaper() + } + } + } + + // -------------------------------- + function init() { + // does nothing but ensure the singleton is created + // do not remove + Logger.log("Matugen", "Service started") + } + // Build TOML content based on settings function buildConfigToml() { return Matugen.buildConfigToml() @@ -30,11 +47,12 @@ Singleton { // Generate colors using current wallpaper and settings function generateFromWallpaper() { - // Ensure cache dir exists - Quickshell.execDetached(["mkdir", "-p", Settings.cacheDir]) - Logger.log("Matugen", "Generating from wallpaper on screen:", Screen.name) var wp = WallpaperService.getWallpaper(Screen.name).replace(/'/g, "'\\''") + if (wp === "") { + Logger.error("Matugen", "No wallpaper was found") + return + } var content = buildConfigToml() var mode = Settings.data.colorSchemes.darkMode ? "dark" : "light"