1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-05 21:15:38 -05:00

proc: ability to run command with noTimeout

This commit is contained in:
bbedward
2025-12-04 16:09:38 -05:00
parent 4291cfe82f
commit 63d121b796
2 changed files with 90 additions and 73 deletions

View File

@@ -3,122 +3,139 @@ pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import Quickshell import Quickshell
import Quickshell.Io
Singleton { Singleton {
id: root id: root
readonly property int noTimeout: -1
property int defaultDebounceMs: 50 property int defaultDebounceMs: 50
property int defaultTimeoutMs: 10000 property int defaultTimeoutMs: 10000
property var _procDebouncers: ({}) property var _procDebouncers: ({})
function runCommand(id, command, callback, debounceMs, timeoutMs) { function runCommand(id, command, callback, debounceMs, timeoutMs) {
const wait = (typeof debounceMs === "number" && debounceMs >= 0) ? debounceMs : defaultDebounceMs const wait = (typeof debounceMs === "number" && debounceMs >= 0) ? debounceMs : defaultDebounceMs;
const timeout = (typeof timeoutMs === "number" && timeoutMs > 0) ? timeoutMs : defaultTimeoutMs const timeout = (typeof timeoutMs === "number") ? timeoutMs : defaultTimeoutMs;
let procId = id ? id : Math.random() let procId = id ? id : Math.random();
const isRandomId = !id const isRandomId = !id;
if (!_procDebouncers[procId]) { if (!_procDebouncers[procId]) {
const t = Qt.createQmlObject('import QtQuick; Timer { repeat: false }', root) const t = Qt.createQmlObject('import QtQuick; Timer { repeat: false }', root);
t.triggered.connect(function() { _launchProc(procId, isRandomId) }) t.triggered.connect(function () {
_procDebouncers[procId] = { timer: t, command: command, callback: callback, waitMs: wait, timeoutMs: timeout, isRandomId: isRandomId } _launchProc(procId, isRandomId);
});
_procDebouncers[procId] = {
timer: t,
command: command,
callback: callback,
waitMs: wait,
timeoutMs: timeout,
isRandomId: isRandomId
};
} else { } else {
_procDebouncers[procId].command = command _procDebouncers[procId].command = command;
_procDebouncers[procId].callback = callback _procDebouncers[procId].callback = callback;
_procDebouncers[procId].waitMs = wait _procDebouncers[procId].waitMs = wait;
_procDebouncers[procId].timeoutMs = timeout _procDebouncers[procId].timeoutMs = timeout;
} }
const entry = _procDebouncers[procId] const entry = _procDebouncers[procId];
entry.timer.interval = entry.waitMs entry.timer.interval = entry.waitMs;
entry.timer.restart() entry.timer.restart();
} }
function _launchProc(id, isRandomId) { function _launchProc(id, isRandomId) {
const entry = _procDebouncers[id] const entry = _procDebouncers[id];
if (!entry) return 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);
const proc = Qt.createQmlObject('import Quickshell.Io; Process { running: false }', root) proc.stdout = out;
const out = Qt.createQmlObject('import Quickshell.Io; StdioCollector {}', proc) proc.stderr = err;
const err = Qt.createQmlObject('import Quickshell.Io; StdioCollector {}', proc) proc.command = entry.command;
const timeoutTimer = Qt.createQmlObject('import QtQuick; Timer { repeat: false }', root)
proc.stdout = out let capturedOut = "";
proc.stderr = err let capturedErr = "";
proc.command = entry.command let exitSeen = false;
let exitCodeValue = -1;
let outSeen = false;
let errSeen = false;
let timedOut = false;
let capturedOut = "" timeoutTimer.interval = entry.timeoutMs;
let capturedErr = "" timeoutTimer.triggered.connect(function () {
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) { if (!exitSeen) {
timedOut = true timedOut = true;
proc.running = false proc.running = false;
exitSeen = true exitSeen = true;
exitCodeValue = 124 exitCodeValue = 124;
maybeComplete() maybeComplete();
} }
}) });
out.streamFinished.connect(function() { out.streamFinished.connect(function () {
try { try {
capturedOut = out.text || "" capturedOut = out.text || "";
} catch (e) { } catch (e) {
capturedOut = "" capturedOut = "";
} }
outSeen = true outSeen = true;
maybeComplete() maybeComplete();
}) });
err.streamFinished.connect(function() { err.streamFinished.connect(function () {
try { try {
capturedErr = err.text || "" capturedErr = err.text || "";
} catch (e) { } catch (e) {
capturedErr = "" capturedErr = "";
} }
errSeen = true errSeen = true;
maybeComplete() maybeComplete();
}) });
proc.exited.connect(function(code) { proc.exited.connect(function (code) {
timeoutTimer.stop() timeoutTimer.stop();
exitSeen = true exitSeen = true;
exitCodeValue = code exitCodeValue = code;
maybeComplete() maybeComplete();
}) });
function maybeComplete() { function maybeComplete() {
if (!exitSeen || !outSeen || !errSeen) return if (!exitSeen || !outSeen || !errSeen)
timeoutTimer.stop() return;
timeoutTimer.stop();
if (entry && entry.callback && typeof entry.callback === "function") { if (entry && entry.callback && typeof entry.callback === "function") {
try { try {
const safeOutput = capturedOut !== null && capturedOut !== undefined ? capturedOut : "" const safeOutput = capturedOut !== null && capturedOut !== undefined ? capturedOut : "";
const safeExitCode = exitCodeValue !== null && exitCodeValue !== undefined ? exitCodeValue : -1 const safeExitCode = exitCodeValue !== null && exitCodeValue !== undefined ? exitCodeValue : -1;
entry.callback(safeOutput, safeExitCode) entry.callback(safeOutput, safeExitCode);
} catch (e) { } catch (e) {
console.warn("runCommand callback error for command:", entry.command, "Error:", e) console.warn("runCommand callback error for command:", entry.command, "Error:", e);
} }
} }
try { proc.destroy() } catch (_) {} try {
try { timeoutTimer.destroy() } catch (_) {} proc.destroy();
} catch (_) {}
try {
timeoutTimer.destroy();
} catch (_) {}
if (isRandomId || entry.isRandomId) { if (isRandomId || entry.isRandomId) {
Qt.callLater(function() { Qt.callLater(function () {
if (_procDebouncers[id]) { if (_procDebouncers[id]) {
try { _procDebouncers[id].timer.destroy() } catch (_) {} try {
delete _procDebouncers[id] _procDebouncers[id].timer.destroy();
} catch (_) {}
delete _procDebouncers[id];
} }
}) });
} }
} }
proc.running = true proc.running = true;
timeoutTimer.start() if (entry.timeoutMs !== noTimeout)
timeoutTimer.start();
} }
} }

View File

@@ -110,7 +110,7 @@ DankModal {
console.warn("Failed to parse dms color pick JSON:", e); console.warn("Failed to parse dms color pick JSON:", e);
root.show(); root.show();
} }
}); }, 0, Proc.noTimeout);
} }
modalWidth: 680 modalWidth: 680