af014d9829
A workspace could not be created on Windows: "cwd must be an absolute path" for D:\…, because createLane/canonicalCwd tested for a leading "/". - lanes.js: path.isAbsolute/path.resolve; canonicalCwd stops at any root (a missing drive looped forever); resolveLaneByCwd and /ensure accept "\" too - native-dialog.js: the Windows picker gets an invisible TopMost owner form, shown first — an ownerless dialog from the background server opened behind the browser, or hidden - windows-hide.js: every child process on Windows starts with windowsHide, required first by the server and the detached scripts (a console window flashed per git/npm call) - Confirm/update/clear-data modals and the quota panel scroll instead of overflowing a short window
42 lines
1.7 KiB
JavaScript
42 lines
1.7 KiB
JavaScript
/**
|
|
* @file Makes every child process on Windows start with `windowsHide: true`.
|
|
* The dashboard runs detached, with no console of its own, so Windows gave
|
|
* each console program it ran (git, npm, where, …) a NEW console window — a
|
|
* flash that stole focus on every poll. Node has no global default, so this
|
|
* patches `ChildProcess.prototype.spawn` (the one path spawn/exec/execFile/fork
|
|
* and their promisified forms all take) and wraps the sync exports. Require it
|
|
* FIRST in an entry point: a `const { execSync } = require("child_process")`
|
|
* evaluated before it keeps the unwrapped function. A no-op off Windows.
|
|
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
|
*/
|
|
|
|
const DONE = Symbol.for("agenthub.windowsHide");
|
|
|
|
function install(cp = require("child_process"), platform = process.platform) {
|
|
if (platform !== "win32" || cp[DONE]) return;
|
|
cp[DONE] = true;
|
|
|
|
const spawn = cp.ChildProcess.prototype.spawn;
|
|
cp.ChildProcess.prototype.spawn = function (options) {
|
|
options.windowsHide = true;
|
|
return spawn.call(this, options);
|
|
};
|
|
|
|
// spawnSync(cmd, args?, opts?), execFileSync(file, args?, opts?), execSync(cmd, opts?)
|
|
for (const name of ["spawnSync", "execFileSync", "execSync"]) {
|
|
const fn = cp[name];
|
|
cp[name] = function (...args) {
|
|
while (args.length > 1 && args[args.length - 1] == null) args.pop();
|
|
const last = args[args.length - 1];
|
|
if (args.length > 1 && typeof last === "object" && !Array.isArray(last)) {
|
|
args[args.length - 1] = { ...last, windowsHide: true };
|
|
} else {
|
|
args.push({ windowsHide: true });
|
|
}
|
|
return fn.apply(this, args);
|
|
};
|
|
}
|
|
}
|
|
|
|
module.exports = { install };
|