sidebar: live config: save ags values

This commit is contained in:
end-4
2025-04-03 11:25:31 +02:00
parent 5526340041
commit a238caf3fe
5 changed files with 86 additions and 25 deletions
@@ -14,13 +14,21 @@ function overrideConfigRecursive(userOverrides, configOptions = {}) {
} }
// Load default options from ~/.config/ags/modules/.configuration/default_options.jsonc // Load default options from ~/.config/ags/modules/.configuration/default_options.jsonc
const configFileContents = Utils.readFile(`${App.configDir}/modules/.configuration/default_options.jsonc`); const defaultConfigFile = `${App.configDir}/modules/.configuration/default_options.jsonc`;
let configOptions = parseJSONC(configFileContents); const defaultConfigFileContents = Utils.readFile(defaultConfigFile);
const userOverrideContents = Utils.readFile(`${App.configDir}/user_options.jsonc`); const defaultConfigOptions = parseJSONC(defaultConfigFileContents);
let userOverrides = parseJSONC(userOverrideContents);
// Clone the default config to avoid modifying the original
let configOptions = JSON.parse(JSON.stringify(defaultConfigOptions));
// Load user overrides
const userOverrideFile = `${App.configDir}/user_options.jsonc`;
const userOverrideContents = Utils.readFile(userOverrideFile);
const userOverrides = parseJSONC(userOverrideContents);
// Override defaults with user's options // Override defaults with user's options
overrideConfigRecursive(userOverrides, configOptions); overrideConfigRecursive(userOverrides, configOptions);
globalThis['userOptionsDefaults'] = defaultConfigOptions;
globalThis['userOptions'] = configOptions; globalThis['userOptions'] = configOptions;
export default configOptions; export default configOptions;
-3
View File
@@ -1,6 +1,3 @@
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
export function parseJSONC(jsoncString) { export function parseJSONC(jsoncString) {
let result = ""; let result = "";
let inString = false; let inString = false;
+33
View File
@@ -0,0 +1,33 @@
export function getNestedProperty(obj, path) {
return path.split('.').reduce((current, key) => {
return (current && typeof current === 'object' && current.hasOwnProperty(key)) ? current[key] : undefined;
}, obj);
}
export function updateNestedProperty(obj, path, newValue) {
const pathArray = path.split('.');
const lastKeyIndex = pathArray.length - 1;
let current = obj;
for (let i = 0; i < lastKeyIndex; i++) {
const key = pathArray[i];
if (!current || typeof current !== 'object') {
return false; // Previous part of path is not an object
}
if (!current.hasOwnProperty(key)) {
current[key] = {}; // Create the missing object
}
current = current[key];
}
const lastKey = pathArray[lastKeyIndex];
if (!current || typeof current !== 'object') {
return false; // Parent is not an object
}
current[lastKey] = newValue;
return true;
}
@@ -7,6 +7,7 @@ const { execAsync, exec } = Utils;
import { MaterialIcon } from '../../.commonwidgets/materialicon.js'; import { MaterialIcon } from '../../.commonwidgets/materialicon.js';
import { setupCursorHover } from '../../.widgetutils/cursorhover.js'; import { setupCursorHover } from '../../.widgetutils/cursorhover.js';
import { ConfigGap, ConfigSpinButton, ConfigToggle } from '../../.commonwidgets/configwidgets.js'; import { ConfigGap, ConfigSpinButton, ConfigToggle } from '../../.commonwidgets/configwidgets.js';
import { getNestedProperty, updateNestedProperty } from '../../.miscutils/objects.js';
const HyprlandToggle = ({ icon, name, desc = null, option, enableValue = 1, disableValue = 0, extraOnChange = () => { }, extraOnReset = () => { }, save = true }) => ConfigToggle({ const HyprlandToggle = ({ icon, name, desc = null, option, enableValue = 1, disableValue = 0, extraOnChange = () => { }, extraOnReset = () => { }, save = true }) => ConfigToggle({
icon: icon, icon: icon,
@@ -71,6 +72,38 @@ const HyprlandSpinButton = ({ icon, name, desc = null, option, save = true, extr
...rest, ...rest,
}); });
const AgsSpinButton = ({
icon, name, desc = null, option,
save = true, extraOnChange = () => { },
...rest
}) => ConfigSpinButton({
icon: icon,
name: name,
desc: desc,
resetButton: true,
initValue: getNestedProperty(userOptions, option),
fetchValue: () => getNestedProperty(userOptions, option),
step: 10, minValue: 0, maxValue: 1000,
onChange: (self, newValue) => {
updateNestedProperty(userOptions, option, newValue);
if (save) execAsync(['bash', '-c', `${App.configDir}/scripts/ags/agsconfigurator.py \
--key ${option} \
--value ${newValue} \
--file ${App.configDir}/user_options.jsonc`
]).catch(print);
extraOnChange(self, newValue);
},
onReset: async (self) => {
updateNestedProperty(userOptions, option,
getNestedProperty(userOptionsDefaults, option));
if (save) exec(`bash -c '${App.configDir}/scripts/ags/agsconfigurator.py \
--key ${option} \
--reset \
--file ${App.configDir}/user_options.jsonc'`);
},
...rest,
})
const Subcategory = (children) => Box({ const Subcategory = (children) => Box({
className: 'margin-left-20', className: 'margin-left-20',
vertical: true, vertical: true,
@@ -130,15 +163,12 @@ export default (props) => {
extraOnReset: (self, newValue) => execAsync(['gsettings', 'set', 'org.gnome.desktop.interface', 'enable-animations', 'true']), extraOnReset: (self, newValue) => execAsync(['gsettings', 'set', 'org.gnome.desktop.interface', 'enable-animations', 'true']),
}), }),
Subcategory([ Subcategory([
ConfigSpinButton({ AgsSpinButton({
option: "animations.choreographyDelay",
icon: 'clear_all', icon: 'clear_all',
name: getString('Choreography delay'), name: getString('Choreography delay'),
desc: getString('In milliseconds, the delay between animations of a series'), desc: getString('In milliseconds, the delay between animations of a series'),
initValue: userOptions.animations.choreographyDelay,
step: 10, minValue: 0, maxValue: 1000, step: 10, minValue: 0, maxValue: 1000,
onChange: (self, newValue) => {
userOptions.animations.choreographyDelay = newValue
},
}) })
]), ]),
] ]
@@ -158,21 +188,12 @@ export default (props) => {
className: 'sidebar-centermodules-scrollgradient-bottom' className: 'sidebar-centermodules-scrollgradient-bottom'
})] })]
}); });
const footNote = Box({
homogeneous: true,
children: [Label({
hpack: 'center',
className: 'txt txt-italic txt-subtext margin-5',
label: getString('AGS-related changes aren\'t saved'),
})]
})
return Box({ return Box({
...props, ...props,
className: 'spacing-v-5', className: 'spacing-v-5',
vertical: true, vertical: true,
children: [ children: [
mainContent, mainContent,
footNote,
] ]
}); });
} }
+5 -3
View File
@@ -5,9 +5,11 @@
// vim: `:vsp` to split window, move cursor to the path, press `gf`. // vim: `:vsp` to split window, move cursor to the path, press `gf`.
// `Ctrl-w` twice to switch between the files // `Ctrl-w` twice to switch between the files
// //
// Limitations of this file // Limitations of this file:
// Don't expect every JSONC feature in... say, vscode, to work. // * Only line comments (//) are allowed
// You can only have comments on top of the file // * Comments are not allowed in or below the actual content
// (will be nuked with updates from the UI)
//
// //
// Example: Put this to show 8 (instead of 10) workspaces on the bar // Example: Put this to show 8 (instead of 10) workspaces on the bar
// "workspaces": {"shown": 8 } // "workspaces": {"shown": 8 }