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

View file

@ -14,13 +14,21 @@ function overrideConfigRecursive(userOverrides, configOptions = {}) {
}
// Load default options from ~/.config/ags/modules/.configuration/default_options.jsonc
const configFileContents = Utils.readFile(`${App.configDir}/modules/.configuration/default_options.jsonc`);
let configOptions = parseJSONC(configFileContents);
const userOverrideContents = Utils.readFile(`${App.configDir}/user_options.jsonc`);
let userOverrides = parseJSONC(userOverrideContents);
const defaultConfigFile = `${App.configDir}/modules/.configuration/default_options.jsonc`;
const defaultConfigFileContents = Utils.readFile(defaultConfigFile);
const defaultConfigOptions = parseJSONC(defaultConfigFileContents);
// 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
overrideConfigRecursive(userOverrides, configOptions);
globalThis['userOptionsDefaults'] = defaultConfigOptions;
globalThis['userOptions'] = configOptions;
export default configOptions;

View file

@ -1,6 +1,3 @@
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
export function parseJSONC(jsoncString) {
let result = "";
let inString = false;

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

View file

@ -7,6 +7,7 @@ const { execAsync, exec } = Utils;
import { MaterialIcon } from '../../.commonwidgets/materialicon.js';
import { setupCursorHover } from '../../.widgetutils/cursorhover.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({
icon: icon,
@ -24,7 +25,7 @@ const HyprlandToggle = ({ icon, name, desc = null, option, enableValue = 1, disa
]).catch(print);
else
execAsync(['hyprctl', 'keyword', option, `${newValue ? enableValue : disableValue}`]).catch(print);
extraOnChange(self, newValue);
},
onReset: async (self) => {
@ -71,6 +72,38 @@ const HyprlandSpinButton = ({ icon, name, desc = null, option, save = true, extr
...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({
className: 'margin-left-20',
vertical: true,
@ -130,15 +163,12 @@ export default (props) => {
extraOnReset: (self, newValue) => execAsync(['gsettings', 'set', 'org.gnome.desktop.interface', 'enable-animations', 'true']),
}),
Subcategory([
ConfigSpinButton({
AgsSpinButton({
option: "animations.choreographyDelay",
icon: 'clear_all',
name: getString('Choreography delay'),
desc: getString('In milliseconds, the delay between animations of a series'),
initValue: userOptions.animations.choreographyDelay,
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'
})]
});
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({
...props,
className: 'spacing-v-5',
vertical: true,
children: [
mainContent,
footNote,
]
});
}

View file

@ -5,9 +5,11 @@
// vim: `:vsp` to split window, move cursor to the path, press `gf`.
// `Ctrl-w` twice to switch between the files
//
// Limitations of this file
// Don't expect every JSONC feature in... say, vscode, to work.
// You can only have comments on top of the file
// Limitations of this file:
// * Only line comments (//) are allowed
// * 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
// "workspaces": {"shown": 8 }