Live-save bar settings as you edit
Every layout mutation (add/remove/reorder, settings dialog Apply, position or centerAnchor change) now writes ~/.config/omarchy/bar.json immediately. No more Save button — replaced with an inline 'Auto-saving to ...' status line next to Reset to defaults. To stop the FileView feedback loop (write → inotify → reload → set draft → write again) the shell keeps a one-shot suppressReload flag that swallows the userFile.onLoaded triggered by our own setText.
This commit is contained in:
@@ -27,11 +27,35 @@ ShellRoot {
|
|||||||
|
|
||||||
property string fontFamily: "JetBrainsMono Nerd Font"
|
property string fontFamily: "JetBrainsMono Nerd Font"
|
||||||
|
|
||||||
property var defaultConfig: ({})
|
// Bundled fallback so 'Reset to defaults' never produces an empty bar even
|
||||||
|
// if bar-defaults.json fails to load. Keep in rough sync with the layout
|
||||||
|
// shipped in default/quickshell/bar/bar-defaults.json.
|
||||||
|
readonly property var builtinBarConfig: ({
|
||||||
|
position: "top",
|
||||||
|
fontFamily: "JetBrainsMono Nerd Font",
|
||||||
|
centerAnchor: "calendar",
|
||||||
|
layout: {
|
||||||
|
left: [{ id: "omarchy" }, { id: "workspacesPro" }, { id: "activeWindow" }],
|
||||||
|
center: [
|
||||||
|
{ id: "media" },
|
||||||
|
{ id: "calendar", format: "dddd HH:mm", formatAlt: "dd MMMM 'W'ww yyyy", verticalFormat: "HH\n—\nmm" },
|
||||||
|
{ id: "weatherFlyout" }, { id: "update" }, { id: "voxtype" },
|
||||||
|
{ id: "screenRecording" }, { id: "idle" }, { id: "notifications" }
|
||||||
|
],
|
||||||
|
right: [
|
||||||
|
{ id: "tray" }, { id: "systemStats" }, { id: "microphone" },
|
||||||
|
{ id: "bluetoothPanel" }, { id: "networkPanel" }, { id: "audioPanel" },
|
||||||
|
{ id: "nightLight" }, { id: "brightness" }, { id: "powerProfile" },
|
||||||
|
{ id: "battery" }, { id: "controlCenter" }, { id: "powerMenu" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
property var defaultConfig: builtinBarConfig
|
||||||
property var draft: ({ position: "top", centerAnchor: "calendar", layout: { left: [], center: [], right: [] }, fontFamily: "JetBrainsMono Nerd Font" })
|
property var draft: ({ position: "top", centerAnchor: "calendar", layout: { left: [], center: [], right: [] }, fontFamily: "JetBrainsMono Nerd Font" })
|
||||||
property var registry: ({})
|
property var registry: ({})
|
||||||
property bool dirty: false
|
|
||||||
property int draftRevision: 0
|
property int draftRevision: 0
|
||||||
|
property bool suppressReload: false
|
||||||
|
|
||||||
function cloneJson(value) {
|
function cloneJson(value) {
|
||||||
return JSON.parse(JSON.stringify(value || null))
|
return JSON.parse(JSON.stringify(value || null))
|
||||||
@@ -76,13 +100,17 @@ ShellRoot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function loadConfig() {
|
function loadConfig() {
|
||||||
try {
|
var defaults = builtinBarConfig
|
||||||
var defaults = defaultsFile.text() ? JSON.parse(defaultsFile.text()) : {}
|
var diskText = defaultsFile.text()
|
||||||
defaultConfig = defaults
|
if (diskText) {
|
||||||
} catch (e) {
|
try {
|
||||||
console.warn("Bad defaults JSON:", e)
|
defaults = JSON.parse(diskText)
|
||||||
defaultConfig = {}
|
} catch (e) {
|
||||||
|
console.warn("Bad defaults JSON, falling back to builtin:", e)
|
||||||
|
defaults = builtinBarConfig
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
defaultConfig = defaults
|
||||||
|
|
||||||
var userText = userFile.text() || "{}"
|
var userText = userFile.text() || "{}"
|
||||||
var user = {}
|
var user = {}
|
||||||
@@ -95,17 +123,14 @@ ShellRoot {
|
|||||||
fontFamily: String(merged.fontFamily || "JetBrainsMono Nerd Font"),
|
fontFamily: String(merged.fontFamily || "JetBrainsMono Nerd Font"),
|
||||||
layout: normalizeLayout(merged.layout || {})
|
layout: normalizeLayout(merged.layout || {})
|
||||||
}
|
}
|
||||||
dirty = false
|
|
||||||
draftRevision++
|
draftRevision++
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveConfig() {
|
function persistDraft() {
|
||||||
// Persist the full picture rather than a diff so what the user sees in the
|
// Suppress the inotify callback that this write triggers so the FileView
|
||||||
// GUI is what lives in bar.json. This means Omarchy defaults changes won't
|
// reload doesn't race with rapid edits and clobber them.
|
||||||
// propagate after a user has saved at least once, which is the right
|
suppressReload = true
|
||||||
// tradeoff for a customizer: predictable layouts > silent migrations.
|
|
||||||
userFile.setText(JSON.stringify(draft, null, 2) + "\n")
|
userFile.setText(JSON.stringify(draft, null, 2) + "\n")
|
||||||
dirty = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetToDefaults() {
|
function resetToDefaults() {
|
||||||
@@ -126,12 +151,13 @@ ShellRoot {
|
|||||||
fontFamily: String(source.fontFamily || "JetBrainsMono Nerd Font"),
|
fontFamily: String(source.fontFamily || "JetBrainsMono Nerd Font"),
|
||||||
layout: normalizeLayout(source.layout || {})
|
layout: normalizeLayout(source.layout || {})
|
||||||
}
|
}
|
||||||
|
suppressReload = true
|
||||||
userFile.setText(JSON.stringify(payload, null, 2) + "\n")
|
userFile.setText(JSON.stringify(payload, null, 2) + "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
function markDirty() {
|
function markDirty() {
|
||||||
dirty = true
|
|
||||||
draftRevision++
|
draftRevision++
|
||||||
|
persistDraft()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace the whole `layout` object so any binding that reads `draft.layout`
|
// Replace the whole `layout` object so any binding that reads `draft.layout`
|
||||||
@@ -289,7 +315,10 @@ ShellRoot {
|
|||||||
atomicWrites: true
|
atomicWrites: true
|
||||||
printErrors: false
|
printErrors: false
|
||||||
onLoaded: {
|
onLoaded: {
|
||||||
if (root.dirty) return
|
if (root.suppressReload) {
|
||||||
|
root.suppressReload = false
|
||||||
|
return
|
||||||
|
}
|
||||||
root.loadConfig()
|
root.loadConfig()
|
||||||
}
|
}
|
||||||
onFileChanged: reload()
|
onFileChanged: reload()
|
||||||
@@ -339,18 +368,19 @@ ShellRoot {
|
|||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "Auto-saving to ~/.config/omarchy/bar.json"
|
||||||
|
color: Qt.darker(root.foreground, 1.5)
|
||||||
|
font.family: root.fontFamily
|
||||||
|
font.pixelSize: 11
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
ActionPill {
|
ActionPill {
|
||||||
text: "Reset to defaults"
|
text: "Reset to defaults"
|
||||||
foreground: root.urgent
|
foreground: root.urgent
|
||||||
onClicked: root.resetToDefaults()
|
onClicked: root.resetToDefaults()
|
||||||
}
|
}
|
||||||
|
|
||||||
ActionPill {
|
|
||||||
text: root.dirty ? "Save" : "Saved"
|
|
||||||
foreground: root.dirty ? root.accent : Qt.darker(root.foreground, 1.5)
|
|
||||||
bordered: root.dirty
|
|
||||||
onClicked: if (root.dirty) root.saveConfig()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user