diff options
Diffstat (limited to 'raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Common/Proc.qml')
| -rw-r--r-- | raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Common/Proc.qml | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Common/Proc.qml b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Common/Proc.qml new file mode 100644 index 0000000..813f938 --- /dev/null +++ b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Common/Proc.qml @@ -0,0 +1,141 @@ +pragma Singleton +pragma ComponentBehavior: Bound + +import QtQuick +import Quickshell + +Singleton { + id: root + + readonly property int noTimeout: -1 + property int defaultDebounceMs: 50 + property int defaultTimeoutMs: 10000 + property var _procDebouncers: ({}) + + function runCommand(id, command, callback, debounceMs, timeoutMs) { + const wait = (typeof debounceMs === "number" && debounceMs >= 0) ? debounceMs : defaultDebounceMs; + const timeout = (typeof timeoutMs === "number") ? timeoutMs : defaultTimeoutMs; + let procId = id ? id : Math.random(); + const isRandomId = !id; + + if (!_procDebouncers[procId]) { + const t = Qt.createQmlObject('import QtQuick; Timer { repeat: false }', root); + t.triggered.connect(function () { + _launchProc(procId, isRandomId); + }); + _procDebouncers[procId] = { + timer: t, + command: command, + callback: callback, + waitMs: wait, + timeoutMs: timeout, + isRandomId: isRandomId + }; + } else { + _procDebouncers[procId].command = command; + _procDebouncers[procId].callback = callback; + _procDebouncers[procId].waitMs = wait; + _procDebouncers[procId].timeoutMs = timeout; + } + + const entry = _procDebouncers[procId]; + entry.timer.interval = entry.waitMs; + entry.timer.restart(); + } + + function _launchProc(id, isRandomId) { + const entry = _procDebouncers[id]; + if (!entry) + return; + const proc = Qt.createQmlObject('import Quickshell.Io; Process { running: false }', root); + const out = Qt.createQmlObject('import Quickshell.Io; StdioCollector {}', proc); + const err = Qt.createQmlObject('import Quickshell.Io; StdioCollector {}', proc); + const timeoutTimer = Qt.createQmlObject('import QtQuick; Timer { repeat: false }', root); + + proc.stdout = out; + proc.stderr = err; + proc.command = entry.command; + + let capturedOut = ""; + let capturedErr = ""; + let exitSeen = false; + let exitCodeValue = -1; + let outSeen = false; + let errSeen = false; + let timedOut = false; + + timeoutTimer.interval = entry.timeoutMs; + timeoutTimer.triggered.connect(function () { + if (!exitSeen) { + timedOut = true; + proc.running = false; + exitSeen = true; + exitCodeValue = 124; + maybeComplete(); + } + }); + + out.streamFinished.connect(function () { + try { + capturedOut = out.text || ""; + } catch (e) { + capturedOut = ""; + } + outSeen = true; + maybeComplete(); + }); + + err.streamFinished.connect(function () { + try { + capturedErr = err.text || ""; + } catch (e) { + capturedErr = ""; + } + errSeen = true; + maybeComplete(); + }); + + proc.exited.connect(function (code) { + timeoutTimer.stop(); + exitSeen = true; + exitCodeValue = code; + maybeComplete(); + }); + + function maybeComplete() { + if (!exitSeen || !outSeen || !errSeen) + return; + timeoutTimer.stop(); + if (entry && entry.callback && typeof entry.callback === "function") { + try { + const safeOutput = capturedOut !== null && capturedOut !== undefined ? capturedOut : ""; + const safeExitCode = exitCodeValue !== null && exitCodeValue !== undefined ? exitCodeValue : -1; + entry.callback(safeOutput, safeExitCode); + } catch (e) { + console.warn("runCommand callback error for command:", entry.command, "Error:", e); + } + } + try { + proc.destroy(); + } catch (_) {} + try { + timeoutTimer.destroy(); + } catch (_) {} + + if (isRandomId || entry.isRandomId) { + Qt.callLater(function () { + if (_procDebouncers[id]) { + try { + _procDebouncers[id].timer.destroy(); + } catch (_) {} + delete _procDebouncers[id]; + } + }); + } + } + + proc.running = true; + if (entry.timeoutMs !== noTimeout) + timeoutTimer.start(); + } +} |