Watch
1
0
Fork
You've already forked souveraine
0

config: never store a null option

Null-valued options serialised into config.json and segfaulted
JsonAdapter on the next launch, killing the shell after load.
Tristate strings (auto/on/off) with boolean fallback.
This commit is contained in:
Fimeg 2026-08-12 09:23:19 -04:00
commit f7e0e51116
3 changed files with 27 additions and 9 deletions

View file

@ -13,6 +13,15 @@ Singleton {
property int readWriteDelay: 50 // milliseconds property int readWriteDelay: 50 // milliseconds
property bool blockWrites: false property bool blockWrites: false
// Tri-state option: "auto" (or anything unrecognized) defers to the
// caller's default, "on"/"off" force it. Booleans are honored so old
// configs written before the string form keep working.
function tristate(value, fallback) {
if (value === "on" || value === true) return true;
if (value === "off" || value === false) return false;
return fallback;
}
function setNestedValue(nestedKey, value) { function setNestedValue(nestedKey, value) {
let keys = nestedKey.split("."); let keys = nestedKey.split(".");
let obj = root.options; let obj = root.options;
@ -326,9 +335,12 @@ Singleton {
property bool verbose: true property bool verbose: true
property bool vertical: false property bool vertical: false
property JsonObject resources: JsonObject { property JsonObject resources: JsonObject {
// null follows the active bar profile: compact bars rotate // "auto" follows the active bar profile: compact bars
// one stat; desktop bars render the full resource group. // rotate one stat; desktop bars render the full group.
property var rotate: null // "on"/"off" override it. Never null a null var is
// serialized into config.json and crashes JsonAdapter on
// the next load.
property string rotate: "auto"
property int rotateInterval: 4 property int rotateInterval: 4
property bool alwaysShowSwap: true property bool alwaysShowSwap: true
property bool alwaysShowCpu: true property bool alwaysShowCpu: true
@ -374,10 +386,11 @@ Singleton {
property JsonObject notifications: JsonObject { property JsonObject notifications: JsonObject {
property bool showUnreadCount: false property bool showUnreadCount: false
} }
// Status icons inside the right-hand pill. Null follows // Status icons inside the right-hand pill. "auto" follows
// the profile: a compact bar drops xkb and bluetooth. // the profile: a compact bar drops xkb and bluetooth.
property var showXkb: null // "on"/"off" override it. Never null see bar.resources.
property var showBluetooth: null property string showXkb: "auto"
property string showBluetooth: "auto"
} }
property JsonObject tooltips: JsonObject { property JsonObject tooltips: JsonObject {
property bool clickToShow: false property bool clickToShow: false

View file

@ -511,7 +511,7 @@ Item { // Bar content region
} }
} }
Loader { Loader {
active: Config.options.bar.indicators?.showXkb ?? (root.profile !== "compact") active: Config.tristate(Config.options.bar.indicators?.showXkb, root.profile !== "compact")
visible: active visible: active
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
Layout.rightMargin: indicatorsRowLayout.realSpacing Layout.rightMargin: indicatorsRowLayout.realSpacing
@ -543,7 +543,7 @@ Item { // Bar content region
color: rightSidebarButton.colText color: rightSidebarButton.colText
} }
Loader { Loader {
active: (Config.options.bar.indicators?.showBluetooth ?? (root.profile !== "compact")) && BluetoothStatus.available active: Config.tristate(Config.options.bar.indicators?.showBluetooth, root.profile !== "compact") && BluetoothStatus.available
visible: active visible: active
Layout.leftMargin: indicatorsRowLayout.realSpacing Layout.leftMargin: indicatorsRowLayout.realSpacing
sourceComponent: MaterialSymbol { sourceComponent: MaterialSymbol {

View file

@ -25,7 +25,12 @@ MouseArea {
// explicit config value outranks it. Same precedence as the bar layout: // explicit config value outranks it. Same precedence as the bar layout:
// config wins if it says anything, profile decides otherwise. // config wins if it says anything, profile decides otherwise.
property bool autoRotate: false property bool autoRotate: false
readonly property bool rotate: Config.options.bar.resources?.rotate ?? root.autoRotate readonly property bool rotate: {
const v = Config.options.bar.resources?.rotate;
if (v === "on" || v === true) return true;
if (v === "off" || v === false) return false;
return root.autoRotate;
}
implicitWidth: rowLayout.implicitWidth + rowLayout.anchors.leftMargin + rowLayout.anchors.rightMargin implicitWidth: rowLayout.implicitWidth + rowLayout.anchors.leftMargin + rowLayout.anchors.rightMargin
implicitHeight: Appearance.sizes.barHeight implicitHeight: Appearance.sizes.barHeight