1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-06 05:25:41 -05:00
Files
DankMaterialShell/Common/Proc.qml
2025-10-29 17:23:38 -04:00

111 lines
3.7 KiB
QML

pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import Quickshell.Io
Singleton {
id: root
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 > 0) ? 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() {
capturedOut = out.text || ""
outSeen = true
maybeComplete()
})
err.streamFinished.connect(function() {
capturedErr = err.text || ""
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 (typeof entry.callback === "function") {
try { entry.callback(capturedOut, exitCodeValue) } catch (e) { console.warn("runCommand callback 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
timeoutTimer.start()
}
}