// --- This file has been auto-generated. For permanent changes alter the appropriate block in the README.org. --- // --- This file has been auto-generated. For permanent changes alter the appropriate block in the README.org. --- import Quickshell import Quickshell.Io import QtQuick import QtQuick.Layouts ShellRoot { QtObject { id: colors readonly property color base: "#1e1e2e" readonly property color surface0: "#313244" readonly property color surface1: "#45475a" readonly property color text: "#cdd6f4" readonly property color subtext0: "#a6adc8" readonly property color green: "#a6e3a1" readonly property color blue: "#89b4fa" readonly property color red: "#f38ba8" readonly property color yellow: "#f9e2af" readonly property color peach: "#fab387" } QtObject { id: state property int step: 0 property bool running: false property bool failed: false property string log: "" readonly property var steps: [ { label: "Updating flake.lock", cmd: ["nix", "flake", "update"], cwd: "/home/henrov/Repos/nixos/Droidnix" }, { label: "Updating Flatpaks", cmd: ["flatpak", "update", "-y"], cwd: "/home/henrov" }, { label: "Staging changes", cmd: ["git", "add", "."], cwd: "/home/henrov/Repos/nixos/Droidnix" }, { label: "Committing changes", cmd: ["git", "commit", "-m", "Updated system"], cwd: "/home/henrov/Repos/nixos/Droidnix" }, { label: "Pushing to remote", cmd: ["git", "push"], cwd: "/home/henrov/Repos/nixos/Droidnix" }, { label: "Rebuilding NixOS", cmd: ["sudo", "nixos-rebuild", "switch", "--flake", ".#traveldroid"], cwd: "/home/henrov/Repos/nixos/Droidnix" }, { label: "Reloading Hyprland", cmd: ["hyprctl", "reload"], cwd: "/home/henrov" }, ] } function runStep(index) { if (index >= state.steps.length) { state.running = false state.step = state.steps.length return } state.step = index state.log = "" // clear log for each new step state.running = true stepProc.command = state.steps[index].cmd stepProc.workingDirectory = state.steps[index].cwd stepProc.running = true } Process { id: stepProc stdout: SplitParser { onRead: (line) => { state.log = (state.log + "\n" + line).split("\n").slice(-8).join("\n").trim() } } stderr: SplitParser { onRead: (line) => { if (line.trim() !== "") state.log = (state.log + "\n" + line).split("\n").slice(-8).join("\n").trim() } } onExited: (code) => { if (code !== 0 && state.step !== 3) { state.failed = true state.running = false } else { runStep(state.step + 1) } } } FloatingWindow { id: root title: "quickshell-updater" visible: true width: 520 height: contentCol.implicitHeight + 32 color: "transparent" Shortcut { sequence: "Escape" onActivated: Qt.quit() } // Gradient border Rectangle { anchors.fill: parent anchors.margins: -2 radius: 18 z: -1 gradient: Gradient { orientation: Gradient.Horizontal GradientStop { position: 0.0; color: colors.blue } GradientStop { position: 1.0; color: colors.green } } } Rectangle { anchors.fill: parent radius: 16 color: colors.base ColumnLayout { id: contentCol anchors { top: parent.top left: parent.left right: parent.right margins: 20 } spacing: 12 // Title Text { text: " System Update" color: colors.text font.pixelSize: 15 font.bold: true Layout.topMargin: 4 } // Steps list Repeater { model: state.steps.length delegate: RowLayout { spacing: 10 Layout.fillWidth: true // Icon Text { font.pixelSize: 14 text: { if (state.failed && index === state.step) return "✗" if (index < state.step || (!state.running && index === state.step)) return "✓" if (index === state.step && state.running) return "…" return "○" } color: { if (state.failed && index === state.step) return colors.red if (index < state.step || (!state.running && !state.failed && index === state.step)) return colors.green if (index === state.step && state.running) return colors.yellow return colors.surface1 } } Text { text: state.steps[index].label font.pixelSize: 13 color: { if (state.failed && index === state.step) return colors.red if (index < state.step) return colors.subtext0 if (index === state.step) return colors.text return colors.surface1 } } // Spinner for active step Text { visible: index === state.step && state.running text: "⠋" color: colors.blue font.pixelSize: 13 RotationAnimation on rotation { running: index === state.step && state.running from: 0; to: 360 duration: 1000 loops: Animation.Infinite } } } } // Log output Rectangle { Layout.fillWidth: true height: 160 radius: 8 color: colors.surface0 visible: state.log !== "" Text { anchors { fill: parent margins: 8 } text: state.log color: colors.subtext0 font.pixelSize: 11 font.family: "monospace" wrapMode: Text.WrapAnywhere elide: Text.ElideLeft verticalAlignment: Text.AlignBottom } } // Status / close RowLayout { Layout.fillWidth: true Layout.bottomMargin: 4 Text { text: { if (state.failed) return "✗ Failed at: " + state.steps[state.step].label if (state.step === state.steps.length) return "✓ Done!" if (state.running) return "Running…" return "Press Start" } color: { if (state.failed) return colors.red if (state.step === state.steps.length) return colors.green return colors.subtext0 } font.pixelSize: 12 } Item { Layout.fillWidth: true } // Start button Rectangle { visible: !state.running && state.step === 0 width: 80; height: 28 radius: 14 gradient: Gradient { orientation: Gradient.Horizontal GradientStop { position: 0.0; color: colors.blue } GradientStop { position: 1.0; color: colors.green } } Text { anchors.centerIn: parent text: "Start" color: colors.base font.pixelSize: 12 font.bold: true } MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor onClicked: runStep(0) } } // Close button Rectangle { visible: !state.running && state.step > 0 width: 80; height: 28 radius: 14 color: colors.surface1 Text { anchors.centerIn: parent text: "Close" color: colors.text font.pixelSize: 12 } MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor onClicked: Qt.quit() } } } } } } }