forked from Shinonome/dots-hyprland
make persistent states persistent
This commit is contained in:
@@ -1,7 +1,3 @@
|
|||||||
function trimFileProtocol(str) {
|
|
||||||
return str.startsWith("file://") ? str.slice(7) : str;
|
|
||||||
}
|
|
||||||
|
|
||||||
function toPlainObject(qtObj) {
|
function toPlainObject(qtObj) {
|
||||||
if (qtObj === null || typeof qtObj !== "object") return qtObj;
|
if (qtObj === null || typeof qtObj !== "object") return qtObj;
|
||||||
|
|
||||||
@@ -27,3 +23,23 @@ function toPlainObject(qtObj) {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function applyToQtObject(qtObj, jsonObj) {
|
||||||
|
if (!qtObj || typeof jsonObj !== "object" || jsonObj === null) return;
|
||||||
|
|
||||||
|
for (let key in jsonObj) {
|
||||||
|
if (!qtObj.hasOwnProperty(key)) continue;
|
||||||
|
|
||||||
|
// Check if the property is a QtObject (not a value)
|
||||||
|
const value = qtObj[key];
|
||||||
|
const jsonValue = jsonObj[key];
|
||||||
|
|
||||||
|
// If it's an object and not an array, recurse
|
||||||
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
||||||
|
applyToQtObject(value, jsonValue);
|
||||||
|
} else {
|
||||||
|
// Otherwise, assign the value
|
||||||
|
qtObj[key] = jsonValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -29,13 +29,8 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
bottomWidgetGroupRow.opacity = !collapsed
|
|
||||||
collapsedBottomWidgetGroupRow.opacity = collapsed
|
|
||||||
}
|
|
||||||
|
|
||||||
function setCollapsed(state) {
|
function setCollapsed(state) {
|
||||||
PersistentStates.sidebar.bottomGroup.collapsed = state
|
PersistentStateManager.setState("sidebar.bottomGroup.collapsed", state)
|
||||||
if (collapsed) {
|
if (collapsed) {
|
||||||
bottomWidgetGroupRow.opacity = 0
|
bottomWidgetGroupRow.opacity = 0
|
||||||
}
|
}
|
||||||
@@ -70,6 +65,7 @@ Rectangle {
|
|||||||
// The thing when collapsed
|
// The thing when collapsed
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: collapsedBottomWidgetGroupRow
|
id: collapsedBottomWidgetGroupRow
|
||||||
|
opacity: collapsed ? 1 : 0
|
||||||
visible: opacity > 0
|
visible: opacity > 0
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
@@ -111,6 +107,7 @@ Rectangle {
|
|||||||
RowLayout {
|
RowLayout {
|
||||||
id: bottomWidgetGroupRow
|
id: bottomWidgetGroupRow
|
||||||
|
|
||||||
|
opacity: collapsed ? 0 : 1
|
||||||
visible: opacity > 0
|
visible: opacity > 0
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
|
|||||||
@@ -25,27 +25,7 @@ Singleton {
|
|||||||
try {
|
try {
|
||||||
const json = JSON.parse(fileContent);
|
const json = JSON.parse(fileContent);
|
||||||
|
|
||||||
function applyToQtObject(qtObj, jsonObj) {
|
ObjectUtils.applyToQtObject(ConfigOptions, json);
|
||||||
if (!qtObj || typeof jsonObj !== "object" || jsonObj === null) return;
|
|
||||||
|
|
||||||
for (let key in jsonObj) {
|
|
||||||
if (!qtObj.hasOwnProperty(key)) continue;
|
|
||||||
|
|
||||||
// Check if the property is a QtObject (not a value)
|
|
||||||
const value = qtObj[key];
|
|
||||||
const jsonValue = jsonObj[key];
|
|
||||||
|
|
||||||
// If it's an object and not an array, recurse
|
|
||||||
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
||||||
applyToQtObject(value, jsonValue);
|
|
||||||
} else {
|
|
||||||
// Otherwise, assign the value
|
|
||||||
qtObj[key] = jsonValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
applyToQtObject(ConfigOptions, json);
|
|
||||||
if (root.firstLoad) {
|
if (root.firstLoad) {
|
||||||
root.firstLoad = false;
|
root.firstLoad = false;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
pragma Singleton
|
||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import "root:/modules/common"
|
||||||
|
import "root:/modules/common/functions/object_utils.js" as ObjectUtils
|
||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
import Quickshell.Hyprland
|
||||||
|
import Qt.labs.platform
|
||||||
|
|
||||||
|
Singleton {
|
||||||
|
id: root
|
||||||
|
property string fileDir: `${StandardPaths.standardLocations(StandardPaths.StateLocation)[0]}`
|
||||||
|
property string fileName: "states.json"
|
||||||
|
property string filePath: `${root.fileDir}/${root.fileName}`
|
||||||
|
|
||||||
|
function getState(nestedKey) {
|
||||||
|
let keys = nestedKey.split(".");
|
||||||
|
let obj = PersistentStates;
|
||||||
|
for (let i = 0; i < keys.length; ++i) {
|
||||||
|
if (obj[keys[i]] === undefined) {
|
||||||
|
console.error(`[PersistentStateManager] Key "${keys[i]}" not found in PersistentStates`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
obj = obj[keys[i]];
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setState(nestedKey, value) {
|
||||||
|
let keys = nestedKey.split(".");
|
||||||
|
let obj = PersistentStates;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the value at the innermost key
|
||||||
|
obj[keys[keys.length - 1]] = value;
|
||||||
|
|
||||||
|
saveStates()
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadStates() {
|
||||||
|
stateFileView.reload()
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveStates() {
|
||||||
|
console.log("[PersistentStateManager] Saving states to file:", root.filePath)
|
||||||
|
const plainStates = ObjectUtils.toPlainObject(PersistentStates)
|
||||||
|
stateFileView.setText(JSON.stringify(plainStates, null, 2))
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyStates(fileContent) {
|
||||||
|
try {
|
||||||
|
const json = JSON.parse(fileContent);
|
||||||
|
|
||||||
|
ObjectUtils.applyToQtObject(PersistentStates, json);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("[PersistentStateManager] Error reading file:", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: delayedFileRead
|
||||||
|
interval: ConfigOptions.hacks.arbitraryRaceConditionDelay
|
||||||
|
repeat: false
|
||||||
|
running: false
|
||||||
|
onTriggered: {
|
||||||
|
root.applyStates(stateFileView.text())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FileView {
|
||||||
|
id: stateFileView
|
||||||
|
path: root.filePath
|
||||||
|
watchChanges: true
|
||||||
|
// onFileChanged: {
|
||||||
|
// console.log("[PersistentStateManager] File changed, reloading...")
|
||||||
|
// this.reload()
|
||||||
|
// delayedFileRead.start()
|
||||||
|
// }
|
||||||
|
onLoadedChanged: {
|
||||||
|
const fileContent = stateFileView.text()
|
||||||
|
root.applyStates(fileContent)
|
||||||
|
}
|
||||||
|
onLoadFailed: (error) => {
|
||||||
|
console.log("[PersistentStateManager] File not found, creating new file")
|
||||||
|
root.saveStates()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,6 +19,7 @@ ShellRoot {
|
|||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
MaterialThemeLoader.reapplyTheme()
|
MaterialThemeLoader.reapplyTheme()
|
||||||
ConfigLoader.loadConfig()
|
ConfigLoader.loadConfig()
|
||||||
|
PersistentStateManager.loadStates()
|
||||||
}
|
}
|
||||||
|
|
||||||
Bar {}
|
Bar {}
|
||||||
|
|||||||
Reference in New Issue
Block a user