diff --git a/modules/common/ags/layouts/quicksettings.js b/modules/common/ags/layouts/quicksettings.js index f43a80c..c8bb317 100644 --- a/modules/common/ags/layouts/quicksettings.js +++ b/modules/common/ags/layouts/quicksettings.js @@ -3,7 +3,7 @@ import * as audio from "../modules/audio.js"; import * as brightness from "../modules/brightness.js"; import * as network from "../modules/network.js"; import * as bluetooth from "../modules/bluetooth.js"; -// import * as darkmode from "../modules/darkmode.js"; +import * as darkmode from "../modules/darkmode.js"; // import * as nightmode from "../modules/nightmode.js"; import * as mpris from "../modules/mpris.js"; import PopupWindow from "../misc/popup.js"; @@ -20,7 +20,6 @@ const Row = (toggles = [], menus = []) => children: [ Widget.Box({ homogeneous: true, - class_name: "row horizontal", children: toggles, }), ...menus, @@ -45,18 +44,13 @@ export const Quicksettings = () => [network.Toggle({}), bluetooth.Toggle({})], [network.Selection({}), bluetooth.Selection({})], ), - // Box({ - // children: [darkmode.DarkToggle(), nightmode.NightToggle()], - // }), + Widget.Box({ + homogeneous: true, + children: [darkmode.Toggle(), darkmode.Toggle()], + }), // Box({ // children: [audio.AppMixerToggle(), audio.MuteToggle()], // }), - // Submenu({ - // menuName: "app-mixer", - // icon: FontIcon({ icon: "" }), - // title: "App Mixer", - // contentType: audio.AppMixer, - // }), Widget.Box({ children: mprisService .bind("players") diff --git a/modules/common/ags/misc/menu.js b/modules/common/ags/misc/menu.js index 25913cb..d8f9d8d 100644 --- a/modules/common/ags/misc/menu.js +++ b/modules/common/ags/misc/menu.js @@ -88,6 +88,47 @@ export const ArrowToggleButton = ({ ], }); +/** + * @typedef {{ + * icon: Gtk.Widget, + * label: Gtk.Widget, + * activate: () => void + * deactivate: () => void + * connection: [GObject.Object, () => boolean] + * } & import("types/widgets/box").BoxProps} SimpleToggleButtonProps + * @param {SimpleToggleButtonProps} props + */ +export const SimpleToggleButton = ({ + icon, + label, + activate, + deactivate, + connection: [service, condition], +}) => + Widget.Box({ + className: "qs-button surface", + setup: (self) => + self.hook(service, () => { + self.toggleClassName("accent", condition()); + }), + children: [ + Widget.Button({ + child: Widget.Box({ + hexpand: true, + children: [icon, label], + }), + onClicked: () => { + if (condition()) { + deactivate(); + } else { + activate(); + } + }, + }), + ], + }); + + /** * @typedef {{ * name: string, diff --git a/modules/common/ags/modules/darkmode.js b/modules/common/ags/modules/darkmode.js index aeb12e0..08ef2e2 100644 --- a/modules/common/ags/modules/darkmode.js +++ b/modules/common/ags/modules/darkmode.js @@ -1,87 +1,51 @@ -import GLib from 'gi://GLib'; +import Gio from "gi://Gio"; +import GLib from "gi://GLib?version=2.0"; -import Service from 'resource:///com/github/Aylur/ags/service.js' -import { exec, execAsync } from 'resource:///com/github/Aylur/ags/utils.js'; -import { Icon, Label, Button, Box, Stack } from 'resource:///com/github/Aylur/ags/widget.js'; +import { SimpleToggleButton } from "../misc/menu.js"; -class ThemeService extends Service { - static { - Service.register(this); - } +const theme = Variable(/** @type {"light" | "dark"} */ ("light")); - _dark = false; - - get dark() { - return this._dark; - } - - set dark(value) { - this._dark = value; - execAsync(`gsettings set org.gnome.desktop.interface color-scheme prefer-${this._dark ? "dark" : "light"}`).catch( - print - ); - execAsync(`gsettings set org.gnome.desktop.interface gtk-theme adw-gtk3${this._dark ? "-dark" : ""}`).catch( - print - ); - const conf = GLib.get_user_config_dir(); - execAsync(`ln -sf ${conf}/kitty/${this._dark ? "dark" : "light"}.conf ${conf}/kitty/theme.conf`).catch( - print - ); - execAsync("pkill -USR1 kitty").catch(print); - this.emit("changed"); - } - - toggle() { - this.dark = !this.dark; - } - - constructor() { - super(); - this._dark = exec(`gsettings get org.gnome.desktop.interface color-scheme`) === "'prefer-dark'"; - // Ensure that the gtk theme is in sync with the theme. - this._dark = this._dark; - } -} - -const Theme = new ThemeService(); - -export const Indicator = ({ ...props } = {}) => - Stack({ - items: [ - ["light", Icon("weather-clear-symbolic")], - ["dark", Icon("weather-clear-night-symbolic")], - ], - ...props, - connections: [ - [ - Theme, - (stack) => { - stack.shown = Theme.dark ? "dark" : "light"; - }, - ], - ], - }); - -export const ThemeLabel = () => - Label({ - connections: [ - [ - Theme, - (label) => { - label.label = Theme.dark ? "Dark Theme" : "Light Theme"; - }, - ], - ], - }); - -export const DarkToggle = ({ ...props } = {}) => - Button({ - className: "qs-button surface", - hexpand: true, - onClicked: () => Theme.toggle(), - child: Box({ - children: [Indicator({ className: "qs-icon" }), ThemeLabel()], +/** @param {Partial} props */ +export const Toggle = ({ ...props } = {}) => + SimpleToggleButton({ + icon: Widget.Icon({ + className: "qs-icon", + icon: theme + .bind() + .as((x) => + x === "light" + ? "weather-clear-symbolic" + : "weather-clear-night-symbolic", + ), }), - connections: [[Theme, (button) => button.toggleClassName("accent", Theme.dark)]], + label: Widget.Label({ + label: theme.bind().as((x) => (x === "light" ? "Light" : "Dark")), + }), + activate: () => theme.setValue("dark"), + deactivate: () => theme.setValue("light"), + connection: [theme, () => theme.value === "dark"], ...props, }); + +function init() { + const settings = new Gio.Settings({ + schema: "org.gnome.desktop.interface", + }); + const initial = /** @type {"prefer-light" | "prefer-dark"}} */ ( + settings.get_value("color-scheme").get_string()[0] + ); + theme.setValue(/** @type {any}} */ (initial.substring("prefer-".length))); + theme.connect("changed", () => { + settings.set_string("color-scheme", `prefer-${theme.value}`); + settings.set_string( + "gtk-theme", + `adw-gtk3${theme.value === "dark" ? "-dark" : ""}`, + ); + + const conf = GLib.get_user_config_dir(); + Utils.execAsync( + `bash -c 'ln -sf ${conf}/kitty/${theme.value}.conf ${conf}/kitty/theme.conf && pkill -USR1 kitty'`, + ).catch(print); + }); +} +init();