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
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NoSignal: CachyOS repos enable/disable (sudoless, auto-tier)
|
||||||
|
CachyRepoToggleRow {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
SelectRow {
|
SelectRow {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
last: true
|
last: true
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,13 @@ pragma ComponentBehavior: Bound
|
||||||
// NoSignal Quick Settings popout (off the media / battery pill). Avatar + user +
|
// NoSignal Quick Settings popout (off the media / battery pill). Avatar + user +
|
||||||
// uptime + power button; 2-col toggle grid; brightness + volume sliders; media
|
// uptime + power button; 2-col toggle grid; brightness + volume sliders; media
|
||||||
// card. Wired to the real services (Network, Bluetooth, Notifs, Audio,
|
// 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
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
import Quickshell.Bluetooth
|
import Quickshell.Bluetooth
|
||||||
import qs.services
|
import qs.services
|
||||||
import qs.utils
|
import qs.utils
|
||||||
|
|
@ -20,6 +23,35 @@ NsPanel {
|
||||||
|
|
||||||
readonly property var brightMon: Brightness.monitors[0] ?? null
|
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 ───────────────────────────────────────────────────────────
|
// ── Header ───────────────────────────────────────────────────────────
|
||||||
RowLayout {
|
RowLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
@ -128,21 +160,31 @@ NsPanel {
|
||||||
icon: "nightlight"
|
icon: "nightlight"
|
||||||
label: "Night Light"
|
label: "Night Light"
|
||||||
sub: on ? "Warm 3500K" : "Off"
|
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 {
|
QSToggle {
|
||||||
id: airTog
|
id: airTog
|
||||||
icon: "airplanemode_active"
|
icon: "airplanemode_active"
|
||||||
label: "Airplane"
|
label: "Airplane"
|
||||||
sub: on ? "On" : "Off"
|
// Reflects the real radio state: airplane is "On" when both Wi-Fi and
|
||||||
onToggled: on = !on
|
// Bluetooth are down. Network.wifiEnabled tracks nmcli; the adapter
|
||||||
}
|
// tracks BlueZ, so the tile self-corrects if radios change elsewhere.
|
||||||
QSToggle {
|
readonly property bool radiosOff: !Network.wifiEnabled && !(Bluetooth.defaultAdapter?.enabled ?? false)
|
||||||
id: vpnTog
|
sub: radiosOff ? "On" : "Off"
|
||||||
icon: "vpn_key"
|
on: radiosOff
|
||||||
label: "VPN"
|
onToggled: {
|
||||||
sub: on ? "On" : "Off"
|
if (radiosOff)
|
||||||
onToggled: on = !on
|
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