fix(nosignal): hardware-test round 3 — notif Clear + Game Mode → DeckShift
F2: NsNotifications.qml "Clear" mirrors the service (Notifs.list.slice() → n.close()) instead of n.notification?.dismiss() — cards now actually leave the list, and it works for disk-restored notifications (whose notification is null). C2: Toggles.qml gameMode delegate launches the guarded switch-to-gaming via Quickshell.execDetached (debounced + disabled + 5s timer so a double-click can't fire two SDDM restarts), and the tile is hidden entirely when DeckShift isn't installed (Process probe for the gamescope session file). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
44b257ce85
commit
2cc089b41f
2 changed files with 55 additions and 4 deletions
|
|
@ -71,8 +71,16 @@ NsPanel {
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: {
|
onClicked: {
|
||||||
for (const n of Notifs.notClosed)
|
// Mirror the service's own clear() / clearNotifs shortcut:
|
||||||
n.notification?.dismiss();
|
// NotifData.close() sets `closed` (drops it from notClosed so the
|
||||||
|
// card disappears), removes it from Notifs.list, dismisses the
|
||||||
|
// server notification and destroys it. Calling
|
||||||
|
// `notification?.dismiss()` directly cleared nothing — it never
|
||||||
|
// touched the list, and is a no-op for notifications restored from
|
||||||
|
// disk (their `notification` is null). Iterate a slice() copy so
|
||||||
|
// mutating the list mid-loop is safe.
|
||||||
|
for (const n of Notifs.list.slice())
|
||||||
|
n.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
import Quickshell.Bluetooth
|
import Quickshell.Bluetooth
|
||||||
import Caelestia.Components
|
import Caelestia.Components
|
||||||
import Caelestia.Config
|
import Caelestia.Config
|
||||||
|
|
@ -17,6 +19,18 @@ StyledRect {
|
||||||
required property DrawerVisibilities visibilities
|
required property DrawerVisibilities visibilities
|
||||||
required property BarPopouts.Wrapper popouts
|
required property BarPopouts.Wrapper popouts
|
||||||
|
|
||||||
|
// NoSignal: the gamepad "Game Mode" toggle launches DeckShift gaming. Hide it
|
||||||
|
// entirely when DeckShift isn't installed (no gamescope session file) — checked
|
||||||
|
// once at load by deckshiftProbe below.
|
||||||
|
property bool deckshiftInstalled: false
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: deckshiftProbe
|
||||||
|
running: true
|
||||||
|
command: ["test", "-f", "/usr/share/wayland-sessions/gamescope-session-steam-nm.desktop"]
|
||||||
|
onExited: (exitCode, exitStatus) => root.deckshiftInstalled = exitCode === 0
|
||||||
|
}
|
||||||
|
|
||||||
readonly property var quickToggles: {
|
readonly property var quickToggles: {
|
||||||
const seenIds = new Set();
|
const seenIds = new Set();
|
||||||
|
|
||||||
|
|
@ -32,6 +46,11 @@ StyledRect {
|
||||||
return GlobalConfig.utilities.vpn.provider.some(p => typeof p === "object" ? (p.enabled === true) : false);
|
return GlobalConfig.utilities.vpn.provider.some(p => typeof p === "object" ? (p.enabled === true) : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NoSignal: drop the Game Mode tile unless DeckShift is installed.
|
||||||
|
if (item.id === "gameMode") {
|
||||||
|
return root.deckshiftInstalled;
|
||||||
|
}
|
||||||
|
|
||||||
seenIds.add(item.id);
|
seenIds.add(item.id);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
@ -126,9 +145,33 @@ StyledRect {
|
||||||
DelegateChoice {
|
DelegateChoice {
|
||||||
roleValue: "gameMode"
|
roleValue: "gameMode"
|
||||||
delegate: Toggle {
|
delegate: Toggle {
|
||||||
|
id: gmTog
|
||||||
|
// NoSignal: launch the DeckShift gaming session if installed;
|
||||||
|
// otherwise do nothing. (Was caelestia's cosmetic Game Mode.)
|
||||||
|
// Kept styled as an off-toggle (muted, outline icon) — the
|
||||||
|
// gamepad is a momentary LAUNCHER, not a stateful toggle.
|
||||||
|
// DEBOUNCED: a fast double-click must not fire two
|
||||||
|
// `switch-to-gaming` runs — two SDDM restarts race the
|
||||||
|
// one-shot autologin and drop you at the password greeter.
|
||||||
|
// Guard mirrors the Super+Shift+S bind + the deckshift-login
|
||||||
|
// install-check, so it no-ops if DeckShift is absent.
|
||||||
|
property bool launching: false
|
||||||
icon: "gamepad"
|
icon: "gamepad"
|
||||||
checked: GameMode.enabled
|
disabled: launching
|
||||||
onClicked: GameMode.enabled = !GameMode.enabled
|
onClicked: {
|
||||||
|
if (gmTog.launching)
|
||||||
|
return;
|
||||||
|
gmTog.launching = true;
|
||||||
|
gmTog.internalChecked = false; // don't latch "on"
|
||||||
|
relockTimer.start();
|
||||||
|
Quickshell.execDetached(["sh", "-c", "[ -x /usr/local/bin/switch-to-gaming ] && [ -f /usr/share/wayland-sessions/gamescope-session-steam-nm.desktop ] && exec /usr/local/bin/switch-to-gaming"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: relockTimer
|
||||||
|
interval: 5000
|
||||||
|
onTriggered: gmTog.launching = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DelegateChoice {
|
DelegateChoice {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue