configoptions: use quickshell jsonadapter

This commit is contained in:
end-4
2025-06-30 14:27:26 +02:00
parent 22319ffccf
commit 7ca0f263ba
50 changed files with 455 additions and 546 deletions
+4 -5
View File
@@ -18,7 +18,7 @@ Singleton {
readonly property string interfaceRole: "interface"
readonly property string apiKeyEnvVarName: "API_KEY"
property Component aiMessageComponent: AiMessageData {}
property string systemPrompt: ConfigOptions?.ai?.systemPrompt ?? ""
property string systemPrompt: Config.options?.ai?.systemPrompt ?? ""
property var messages: []
property var messageIDs: []
property var messageByID: ({})
@@ -301,7 +301,7 @@ Singleton {
// Fetch API keys if needed
if (model?.requires_key) KeyringStorage.fetchKeyringData();
// See if policy prevents online models
if (ConfigOptions.policies.ai === 2 && !model.endpoint.includes("localhost")) {
if (Config.options.policies.ai === 2 && !model.endpoint.includes("localhost")) {
root.addMessage(StringUtils.format(StringUtils.format("Online models disallowed\n\nControlled by `policies.ai` config option"), model.name), root.interfaceRole);
return;
}
@@ -704,7 +704,7 @@ Singleton {
addFunctionOutputMessage(name, qsTr("Switched to search mode. Continue with the user's request."))
requester.makeRequest();
} else if (name === "get_shell_config") {
const configJson = ObjectUtils.toPlainObject(ConfigOptions)
const configJson = ObjectUtils.toPlainObject(Config.options)
addFunctionOutputMessage(name, JSON.stringify(configJson));
requester.makeRequest();
} else if (name === "set_shell_config") {
@@ -714,8 +714,7 @@ Singleton {
}
const key = args.key;
const value = args.value;
ConfigLoader.setLiveConfigValue(key, value);
ConfigLoader.saveConfig();
Config.setNestedValue(key, value);
}
else root.addMessage(qsTr("Unknown function call: {0}"), "assistant");
}
+1 -1
View File
@@ -12,7 +12,7 @@ import Quickshell.Io
*/
Singleton {
id: root
property bool sloppySearch: ConfigOptions?.search.sloppy ?? false
property bool sloppySearch: Config.options?.search.sloppy ?? false
property real scoreThreshold: 0.2
property var substitutions: ({
"code-url-handler": "visual-studio-code",
+3 -3
View File
@@ -26,15 +26,15 @@ Singleton {
property bool lastReady: false
property real lastVolume: 0
function onVolumeChanged() {
if (!ConfigOptions.audio.protection.enable) return;
if (!Config.options.audio.protection.enable) return;
if (!lastReady) {
lastVolume = sink.audio.volume;
lastReady = true;
return;
}
const newVolume = sink.audio.volume;
const maxAllowedIncrease = ConfigOptions.audio.protection.maxAllowedIncrease / 100;
const maxAllowed = ConfigOptions.audio.protection.maxAllowed / 100;
const maxAllowedIncrease = Config.options.audio.protection.maxAllowedIncrease / 100;
const maxAllowed = Config.options.audio.protection.maxAllowed / 100;
if (newVolume - lastVolume > maxAllowedIncrease) {
sink.audio.volume = lastVolume;
+5 -5
View File
@@ -12,11 +12,11 @@ Singleton {
property bool isCharging: chargeState == UPowerDeviceState.Charging
property bool isPluggedIn: isCharging || chargeState == UPowerDeviceState.PendingCharge
property real percentage: UPower.displayDevice.percentage
readonly property bool allowAutomaticSuspend: ConfigOptions.battery.automaticSuspend
readonly property bool allowAutomaticSuspend: Config.options.battery.automaticSuspend
property bool isLow: percentage <= ConfigOptions.battery.low / 100
property bool isCritical: percentage <= ConfigOptions.battery.critical / 100
property bool isSuspending: percentage <= ConfigOptions.battery.suspend / 100
property bool isLow: percentage <= Config.options.battery.low / 100
property bool isCritical: percentage <= Config.options.battery.critical / 100
property bool isSuspending: percentage <= Config.options.battery.suspend / 100
property bool isLowAndNotCharging: isLow && !isCharging
property bool isCriticalAndNotCharging: isCritical && !isCharging
@@ -29,7 +29,7 @@ Singleton {
onIsCriticalAndNotChargingChanged: {
if (available && isCriticalAndNotCharging)
Quickshell.execDetached(["bash", "-c", `notify-send "Critically low battery" "🙏 I beg for pleas charg\nAutomatic suspend triggers at ${ConfigOptions.battery.suspend}%" -u critical -a "Shell"`]);
Quickshell.execDetached(["bash", "-c", `notify-send "Critically low battery" "🙏 I beg for pleas charg\nAutomatic suspend triggers at ${Config.options.battery.suspend}%" -u critical -a "Shell"`]);
}
onIsSuspendingAndNotChargingChanged: {
+2 -2
View File
@@ -19,7 +19,7 @@ Singleton {
property string failMessage: qsTr("That didn't work. Tips:\n- Check your tags and NSFW settings\n- If you don't have a tag in mind, type a page number")
property var responses: []
property int runningRequests: 0
property var defaultUserAgent: ConfigOptions?.networking?.userAgent || "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
property var defaultUserAgent: Config.options?.networking?.userAgent || "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
property var providerList: Object.keys(providers).filter(provider => provider !== "system" && providers[provider].api)
property var providers: {
"system": { "name": qsTr("System") },
@@ -408,7 +408,7 @@ Singleton {
xhr.setRequestHeader("User-Agent", defaultUserAgent)
}
else if (currentProvider == "zerochan") {
const userAgent = ConfigOptions?.sidebar?.booru?.zerochan?.username ? `Desktop sidebar booru viewer - username: ${ConfigOptions.sidebar.booru.zerochan.username}` : defaultUserAgent
const userAgent = Config.options?.sidebar?.booru?.zerochan?.username ? `Desktop sidebar booru viewer - username: ${Config.options.sidebar.booru.zerochan.username}` : defaultUserAgent
xhr.setRequestHeader("User-Agent", userAgent)
}
root.runningRequests++;
+2 -2
View File
@@ -11,7 +11,7 @@ import Quickshell.Io
Singleton {
id: root
property bool sloppySearch: ConfigOptions?.search.sloppy ?? false
property bool sloppySearch: Config.options?.search.sloppy ?? false
property real scoreThreshold: 0.2
property list<string> entries: []
readonly property var preparedEntries: entries.map(a => ({
@@ -51,7 +51,7 @@ Singleton {
Timer {
id: delayedUpdateTimer
interval: ConfigOptions.hacks.arbitraryRaceConditionDelay
interval: Config.options.hacks.arbitraryRaceConditionDelay
repeat: false
onTriggered: {
root.refresh()
@@ -1,137 +0,0 @@
pragma Singleton
pragma ComponentBehavior: Bound
import "root:/modules/common"
import "root:/modules/common/functions/file_utils.js" as FileUtils
import "root:/modules/common/functions/string_utils.js" as StringUtils
import "root:/modules/common/functions/object_utils.js" as ObjectUtils
import QtQuick
import Quickshell
import Quickshell.Io
import Quickshell.Hyprland
import Qt.labs.platform
/**
* Loads and manages the shell configuration file.
* The config file is by default at XDG_CONFIG_HOME/illogical-impulse/config.json.
* Automatically reloaded when the file changes.
*/
Singleton {
id: root
property string filePath: Directories.shellConfigPath
property bool firstLoad: true
property bool preventNextLoad: false
property var preventNextNotification: false
function loadConfig() {
configFileView.reload()
}
function applyConfig(fileContent) {
try {
if (fileContent.trim() === "") {
console.warn("[ConfigLoader] Config file is empty, skipping load.");
return;
}
const json = JSON.parse(fileContent);
ObjectUtils.applyToQtObject(ConfigOptions, json);
if (root.firstLoad) {
root.firstLoad = false;
root.preventNextLoad = true;
root.saveConfig(); // Make sure new properties are added to the user's config file
}
} catch (e) {
console.error("[ConfigLoader] Error reading file:", e);
console.log("[ConfigLoader] File content was:", fileContent);
Quickshell.execDetached(["bash", "-c", `notify-send '${qsTr("Shell configuration failed to load")}' '${root.filePath}'`])
return;
}
}
function setLiveConfigValue(nestedKey, value) {
let keys = nestedKey.split(".");
let obj = ConfigOptions;
let parents = [obj];
// Traverse and collect parent objects
for (let i = 0; i < keys.length - 1; ++i) {
if (!obj[keys[i]] || typeof obj[keys[i]] !== "object") {
obj[keys[i]] = {};
}
obj = obj[keys[i]];
parents.push(obj);
}
// Convert value to correct type using JSON.parse when safe
let convertedValue = value;
if (typeof value === "string") {
let trimmed = value.trim();
if (trimmed === "true" || trimmed === "false" || !isNaN(Number(trimmed))) {
try {
convertedValue = JSON.parse(trimmed);
} catch (e) {
convertedValue = value;
}
}
}
obj[keys[keys.length - 1]] = convertedValue;
}
function saveConfig() {
const plainConfig = ObjectUtils.toPlainObject(ConfigOptions)
Quickshell.execDetached(["bash", "-c", `echo '${StringUtils.shellSingleQuoteEscape(JSON.stringify(plainConfig, null, 2))}' > '${FileUtils.trimFileProtocol(root.filePath)}'`])
}
function setConfigValueAndSave(nestedKey, value, preventNextNotification = true) {
setLiveConfigValue(nestedKey, value);
root.preventNextNotification = preventNextNotification;
saveConfig();
}
Timer {
id: delayedFileRead
interval: ConfigOptions.hacks.arbitraryRaceConditionDelay
running: false
onTriggered: {
if (root.preventNextLoad) {
root.preventNextLoad = false;
return;
}
if (root.firstLoad) {
root.applyConfig(configFileView.text())
} else {
root.applyConfig(configFileView.text())
if (!root.preventNextNotification) {
// Quickshell.execDetached(["bash", "-c", `notify-send '${qsTr("Shell configuration reloaded")}' '${root.filePath}'`])
} else {
root.preventNextNotification = false;
}
}
}
}
FileView {
id: configFileView
path: Qt.resolvedUrl(root.filePath)
watchChanges: true
onFileChanged: {
this.reload()
delayedFileRead.start()
}
onLoadedChanged: {
const fileContent = configFileView.text()
delayedFileRead.start()
}
onLoadFailed: (error) => {
if(error == FileViewError.FileNotFound) {
console.log("[ConfigLoader] File not found, creating new file.")
root.saveConfig()
Quickshell.execDetached(["bash", "-c", `notify-send '${qsTr("Shell configuration created")}' '${root.filePath}'`])
} else {
Quickshell.execDetached(["bash", "-c", `notify-send '${qsTr("Shell configuration failed to load")}' '${root.filePath}'`])
}
}
}
}
+3 -3
View File
@@ -9,8 +9,8 @@ pragma ComponentBehavior: Bound
* A nice wrapper for date and time strings.
*/
Singleton {
property string time: Qt.locale().toString(clock.date, ConfigOptions?.time.format ?? "hh:mm")
property string date: Qt.locale().toString(clock.date, ConfigOptions?.time.dateFormat ?? "dddd, dd/MM")
property string time: Qt.locale().toString(clock.date, Config.options?.time.format ?? "hh:mm")
property string date: Qt.locale().toString(clock.date, Config.options?.time.dateFormat ?? "dddd, dd/MM")
property string collapsedCalendarFormat: Qt.locale().toString(clock.date, "dd MMMM yyyy")
property string uptime: "0h, 0m"
@@ -39,7 +39,7 @@ Singleton {
if (hours > 0) formatted += `${formatted ? ", " : ""}${hours}h`
if (minutes > 0 || !formatted) formatted += `${formatted ? ", " : ""}${minutes}m`
uptime = formatted
interval = ConfigOptions?.resources?.updateInterval ?? 3000
interval = Config.options?.resources?.updateInterval ?? 3000
}
}
@@ -34,7 +34,7 @@ Singleton {
Timer {
id: delayedFileRead
interval: ConfigOptions?.hacks?.arbitraryRaceConditionDelay ?? 100
interval: Config.options?.hacks?.arbitraryRaceConditionDelay ?? 100
repeat: false
running: false
onTriggered: {
@@ -76,7 +76,7 @@ Singleton {
Timer {
id: delayedFileRead
interval: ConfigOptions?.hacks?.arbitraryRaceConditionDelay ?? 100
interval: Config.options?.hacks?.arbitraryRaceConditionDelay ?? 100
repeat: false
running: false
onTriggered: {
@@ -53,7 +53,7 @@ Singleton {
previousCpuStats = { total, idle }
}
interval = ConfigOptions?.resources?.updateInterval ?? 3000
interval = Config.options?.resources?.updateInterval ?? 3000
}
}