feat(nosignal): CachyOS repo toggle + wire Quick Settings placebos
- CachyRepoToggleRow.qml (Settings -> Services): sudoless CachyOS optimized repos + linux-cachyos kernel switch, auto-tier (v4>v3); polls nosignal-cachy-repo status, runs enable/disable in a floating kitty. Inserted after SudoToggleRow in ServicesPage.qml. - NsQuickSettings.qml: Night Light now drives hyprsunset (tile bound to the real pgrep'd process, not a flag); Airplane drives nmcli + bluetoothctl and binds to real radio state; VPN placebo tile removed (no backend). Both built + live-tested on the reference box (06-17 PM). Helper script, sudoers and hyprsunset dep ship in the nosignal builder. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
53c5833de0
commit
44b257ce85
3 changed files with 131 additions and 11 deletions
73
modules/nexus/common/CachyRepoToggleRow.qml
Normal file
73
modules/nexus/common/CachyRepoToggleRow.qml
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
// CachyRepoToggleRow.qml (NoSignal) — Settings -> Services toggle to enable /
|
||||
// disable the CachyOS pacman repositories. Auto-detects the best x86-64 microarch
|
||||
// tier the CPU supports (v4 > v3). Live state polls `nosignal-cachy-repo status`
|
||||
// (no root). enable/disable run in a floating terminal so the pacman/download
|
||||
// output stays visible; the grant is passwordless via sudo -n
|
||||
// (/etc/sudoers.d/02-nosignal-cachy). enable adds repos, converts userspace to
|
||||
// the optimized builds (pacman -Suu, pacman pinned stock), and installs the
|
||||
// linux-cachyos kernel; disable reverts to stock and removes the cachy kernel
|
||||
// (keeping stock `linux` bootable). A reboot switches the running kernel.
|
||||
//
|
||||
// Untracked file under modules/nexus/common — auto-discovered as the type
|
||||
// `CachyRepoToggleRow` via `import qs.modules.nexus.common`. Survives caelestia
|
||||
// upgrades; pairs with the one-line insert in ServicesPage.qml.
|
||||
import QtQuick
|
||||
import Quickshell.Io
|
||||
import qs.modules.nexus.common
|
||||
|
||||
ToggleRow {
|
||||
id: root
|
||||
|
||||
property bool repoOn: false // NB: not `enabled` (reserved Item property)
|
||||
|
||||
text: qsTr("CachyOS repositories")
|
||||
subtext: repoOn
|
||||
? qsTr("On — CachyOS optimized builds + linux-cachyos kernel (reboot to run it)")
|
||||
: qsTr("Switch to CachyOS optimized builds + linux-cachyos kernel (reboot after)")
|
||||
|
||||
onToggled: {
|
||||
if (checked)
|
||||
enableProc.running = true;
|
||||
else
|
||||
disableProc.running = true;
|
||||
reconcile.restart();
|
||||
}
|
||||
|
||||
// --- live state -----------------------------------------------------------
|
||||
Process {
|
||||
id: statusProc
|
||||
command: ["/usr/local/bin/nosignal-cachy-repo", "status"]
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
root.repoOn = text.trim() === "enabled";
|
||||
root.checked = root.repoOn; // drive switch from real state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- actions (passwordless; shown in a terminal for pacman output) ---------
|
||||
Process {
|
||||
id: enableProc
|
||||
command: ["kitty", "--class", "TUI.float", "-e", "sh", "-c", "sudo -n /usr/local/bin/nosignal-cachy-repo enable; printf '\\nPress Enter to close...'; read _"]
|
||||
onExited: reconcile.restart()
|
||||
}
|
||||
Process {
|
||||
id: disableProc
|
||||
command: ["kitty", "--class", "TUI.float", "-e", "sh", "-c", "sudo -n /usr/local/bin/nosignal-cachy-repo disable; printf '\\nPress Enter to close...'; read _"]
|
||||
onExited: reconcile.restart()
|
||||
}
|
||||
|
||||
// --- polling --------------------------------------------------------------
|
||||
Timer {
|
||||
interval: 5000
|
||||
repeat: true
|
||||
running: true
|
||||
triggeredOnStart: true
|
||||
onTriggered: statusProc.running = true
|
||||
}
|
||||
Timer {
|
||||
id: reconcile
|
||||
interval: 2000
|
||||
onTriggered: statusProc.running = true
|
||||
}
|
||||
}
|
||||
|
|
@ -216,6 +216,11 @@ PageBase {
|
|||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
// NoSignal: CachyOS repos enable/disable (sudoless, auto-tier)
|
||||
CachyRepoToggleRow {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
SelectRow {
|
||||
Layout.fillWidth: true
|
||||
last: true
|
||||
|
|
|
|||
|
|
@ -3,10 +3,13 @@ pragma ComponentBehavior: Bound
|
|||
// NoSignal Quick Settings popout (off the media / battery pill). Avatar + user +
|
||||
// uptime + power button; 2-col toggle grid; brightness + volume sliders; media
|
||||
// card. Wired to the real services (Network, Bluetooth, Notifs, Audio,
|
||||
// Brightness, Players); Night Light / Airplane / VPN are stateful toggles for now.
|
||||
// Brightness, Players). Night Light drives hyprsunset; Airplane drives the
|
||||
// NetworkManager + Bluetooth radios. (VPN tile removed pending a real backend.)
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import Quickshell.Bluetooth
|
||||
import qs.services
|
||||
import qs.utils
|
||||
|
|
@ -20,6 +23,35 @@ NsPanel {
|
|||
|
||||
readonly property var brightMon: Brightness.monitors[0] ?? null
|
||||
|
||||
// Night Light state tracks the real hyprsunset process rather than a local
|
||||
// flag, so the tile stays correct across shell reloads or changes made
|
||||
// elsewhere. Seeded on load (probe runs immediately), reconciled on a timer,
|
||||
// and re-checked right after a toggle.
|
||||
property bool nightLightOn: false
|
||||
|
||||
Process {
|
||||
id: nightProbe
|
||||
command: ["pgrep", "-x", "hyprsunset"]
|
||||
running: true
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: root.nightLightOn = text.trim().length > 0
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: 3000
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: nightProbe.running = true
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: nightRefresh
|
||||
interval: 500
|
||||
repeat: false
|
||||
onTriggered: nightProbe.running = true
|
||||
}
|
||||
|
||||
// ── Header ───────────────────────────────────────────────────────────
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
|
@ -128,21 +160,31 @@ NsPanel {
|
|||
icon: "nightlight"
|
||||
label: "Night Light"
|
||||
sub: on ? "Warm 3500K" : "Off"
|
||||
onToggled: on = !on
|
||||
on: root.nightLightOn
|
||||
onToggled: {
|
||||
if (root.nightLightOn)
|
||||
Quickshell.execDetached(["pkill", "-x", "hyprsunset"]);
|
||||
else
|
||||
Quickshell.execDetached(["sh", "-c", "pkill -x hyprsunset; hyprsunset -t 3500"]);
|
||||
nightRefresh.restart();
|
||||
}
|
||||
}
|
||||
QSToggle {
|
||||
id: airTog
|
||||
icon: "airplanemode_active"
|
||||
label: "Airplane"
|
||||
sub: on ? "On" : "Off"
|
||||
onToggled: on = !on
|
||||
}
|
||||
QSToggle {
|
||||
id: vpnTog
|
||||
icon: "vpn_key"
|
||||
label: "VPN"
|
||||
sub: on ? "On" : "Off"
|
||||
onToggled: on = !on
|
||||
// Reflects the real radio state: airplane is "On" when both Wi-Fi and
|
||||
// Bluetooth are down. Network.wifiEnabled tracks nmcli; the adapter
|
||||
// tracks BlueZ, so the tile self-corrects if radios change elsewhere.
|
||||
readonly property bool radiosOff: !Network.wifiEnabled && !(Bluetooth.defaultAdapter?.enabled ?? false)
|
||||
sub: radiosOff ? "On" : "Off"
|
||||
on: radiosOff
|
||||
onToggled: {
|
||||
if (radiosOff)
|
||||
Quickshell.execDetached(["sh", "-c", "nmcli radio all on; bluetoothctl power on"]);
|
||||
else
|
||||
Quickshell.execDetached(["sh", "-c", "nmcli radio all off; bluetoothctl power off"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue