cicy-desktop 2.1.133 → 2.1.135
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -137,7 +137,7 @@ async function startLogin({ onResult } = {}) {
|
|
|
137
137
|
// browser, locked-down shell) openExternal silently fails and the user is
|
|
138
138
|
// left stuck "等回调" with no recourse — so we ALSO return the url to the
|
|
139
139
|
// renderer (below) to show a manual "open / copy this link" fallback.
|
|
140
|
-
|
|
140
|
+
require("./open-external").openExternalRobust(url).catch((e) => log.warn(`[auth-loopback] open failed: ${e.message}`));
|
|
141
141
|
|
|
142
142
|
_timeoutHandle = setTimeout(() => {
|
|
143
143
|
try { onResult && onResult({ error: "timeout" }); } catch {}
|
package/src/backends/ipc.js
CHANGED
|
@@ -199,10 +199,12 @@ function register(opts = {}) {
|
|
|
199
199
|
});
|
|
200
200
|
|
|
201
201
|
// --- shell / app / tos / logs (last rebuild!) ---
|
|
202
|
-
ipcMain.handle("shell:open-external", (_e, url) => {
|
|
202
|
+
ipcMain.handle("shell:open-external", async (_e, url) => {
|
|
203
203
|
if (!url) return false;
|
|
204
|
-
shell.openExternal
|
|
205
|
-
|
|
204
|
+
// Robust open: shell.openExternal silently fails on some Windows profiles;
|
|
205
|
+
// fall back to rundll32/explorer/start (the "手动打开" button uses this too).
|
|
206
|
+
const { openExternalRobust } = require("./open-external");
|
|
207
|
+
return await openExternalRobust(url);
|
|
206
208
|
});
|
|
207
209
|
ipcMain.handle("app:quit", () => {
|
|
208
210
|
setTimeout(() => app.quit(), 100);
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Robust "open this URL in the system browser".
|
|
2
|
+
//
|
|
3
|
+
// electron's shell.openExternal silently fails on some Windows setups — a fresh
|
|
4
|
+
// user profile, a locked-down shell, or console-launched (npx) electron — leaving
|
|
5
|
+
// browser-login stuck ("点了没反应"). When it fails we fall back to the OS URL
|
|
6
|
+
// openers directly. Order matters: rundll32 / explorer / open / xdg-open take the
|
|
7
|
+
// URL as a SINGLE argv (no shell parsing), so the login URL's `&`/`?` query params
|
|
8
|
+
// survive. `cmd start` is last because cmd treats `&` as a command separator.
|
|
9
|
+
|
|
10
|
+
const { shell } = require("electron");
|
|
11
|
+
const { spawn } = require("child_process");
|
|
12
|
+
const log = require("electron-log");
|
|
13
|
+
|
|
14
|
+
function trySpawn(cmd, args) {
|
|
15
|
+
try {
|
|
16
|
+
const child = spawn(cmd, args, { detached: true, stdio: "ignore", windowsHide: true });
|
|
17
|
+
child.on("error", (err) => log.warn(`[open-external] ${cmd} error: ${err.message}`));
|
|
18
|
+
child.unref();
|
|
19
|
+
return true;
|
|
20
|
+
} catch (e) {
|
|
21
|
+
log.warn(`[open-external] spawn ${cmd} threw: ${e.message}`);
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Returns true if SOME mechanism was dispatched (best-effort — the OS may still
|
|
27
|
+
// have no default browser, which no opener can fix; the renderer always also
|
|
28
|
+
// shows a copy-link fallback).
|
|
29
|
+
async function openExternalRobust(rawUrl) {
|
|
30
|
+
const url = String(rawUrl || "");
|
|
31
|
+
if (!url) return false;
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
await shell.openExternal(url);
|
|
35
|
+
return true;
|
|
36
|
+
} catch (e) {
|
|
37
|
+
log.warn(`[open-external] shell.openExternal failed, falling back: ${e && e.message}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (process.platform === "win32") {
|
|
41
|
+
// FileProtocolHandler + explorer pass the URL untouched (good for query strings).
|
|
42
|
+
if (trySpawn("rundll32", ["url.dll,FileProtocolHandler", url])) return true;
|
|
43
|
+
if (trySpawn("explorer.exe", [url])) return true;
|
|
44
|
+
return trySpawn("cmd", ["/c", "start", "", url]);
|
|
45
|
+
}
|
|
46
|
+
if (process.platform === "darwin") return trySpawn("open", [url]);
|
|
47
|
+
return trySpawn("xdg-open", [url]);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = { openExternalRobust };
|
|
@@ -121,6 +121,18 @@ function importTarball(dest, installDir) {
|
|
|
121
121
|
});
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
// `wsl --terminate <distro>`: stop the distro so the NEXT `wsl -d` cold-boots it
|
|
125
|
+
// clean. This is the fix for the「引擎没起来」-on-fresh-install failure: a distro
|
|
126
|
+
// straight out of `wsl --import` is frequently half-initialized / unresponsive,
|
|
127
|
+
// so startEngine's first `wsl -d` command times out, dockerd never launches, and
|
|
128
|
+
// its log is never even created (exactly what we saw on a new Windows user). A
|
|
129
|
+
// terminate + cold boot makes that first real command hit a clean distro.
|
|
130
|
+
function wslTerminate() {
|
|
131
|
+
return new Promise((resolve) => {
|
|
132
|
+
execFile("wsl", ["--terminate", DISTRO], { timeout: 30000, windowsHide: true }, () => resolve());
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
124
136
|
async function installDistro({ emit } = {}) {
|
|
125
137
|
// 1) Download the PRE-BAKED rootfs (Ubuntu+Docker+image baked in, ~444MB) with
|
|
126
138
|
// a real progress bar. curl is ~10× faster than node's downloader on OSS.
|
|
@@ -147,7 +159,13 @@ async function installDistro({ emit } = {}) {
|
|
|
147
159
|
await ensureWslKernel({ emit });
|
|
148
160
|
await importTarball(dest, installDir);
|
|
149
161
|
}
|
|
150
|
-
// 3)
|
|
162
|
+
// 3) Force a clean cold boot. A freshly-imported distro is often wedged, so the
|
|
163
|
+
// next `wsl -d` (startEngine) would time out → dockerd never starts. Terminate
|
|
164
|
+
// now so that first real command boots a clean distro instead.
|
|
165
|
+
emit && emit({ phase: "container", status: "running", message: "重置运行环境(冷启动)…" });
|
|
166
|
+
try { await wslTerminate(); } catch {}
|
|
167
|
+
|
|
168
|
+
// 4) Free the ~444MB package now that the distro has everything.
|
|
151
169
|
try { fs.unlinkSync(dest); } catch {}
|
|
152
170
|
}
|
|
153
171
|
|
|
@@ -195,6 +213,7 @@ async function startEngine() {
|
|
|
195
213
|
// attempts we hard-kill any half-dead daemon so the next launch is clean.
|
|
196
214
|
for (let attempt = 1; attempt <= 3; attempt++) {
|
|
197
215
|
const at0 = Date.now();
|
|
216
|
+
let launchErr = null;
|
|
198
217
|
log.info(`[startEngine] attempt ${attempt}/3 — (re)launch dockerd + wait for socket`);
|
|
199
218
|
try {
|
|
200
219
|
await wslRun(
|
|
@@ -213,17 +232,24 @@ async function startEngine() {
|
|
|
213
232
|
// cold again (a restart loop → 「引擎没起来」even though dockerd was fine).
|
|
214
233
|
"for i in $(seq 1 120); do [ -S /var/run/docker.sock ] && docker version >/dev/null 2>&1 && break; sleep 1; done",
|
|
215
234
|
{ timeout: 150000 });
|
|
216
|
-
} catch (e) { log.warn(`[startEngine] attempt ${attempt} launch/wait errored: ${e.message}`); }
|
|
235
|
+
} catch (e) { launchErr = e; log.warn(`[startEngine] attempt ${attempt} launch/wait errored: ${e.message}`); }
|
|
217
236
|
if (await dockerEngineUp()) { log.info(`[startEngine] ✓ dockerd up on attempt ${attempt} (${((Date.now() - at0) / 1000).toFixed(1)}s)`); return true; }
|
|
218
237
|
log.warn(`[startEngine] attempt ${attempt} dockerd still not up after ${((Date.now() - at0) / 1000).toFixed(1)}s`);
|
|
219
|
-
//
|
|
220
|
-
//
|
|
221
|
-
//
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
238
|
+
// Reset between attempts. If the launch itself ERRORED (timeout = WSL wedged /
|
|
239
|
+
// unresponsive — the post-import failure where the command can't even get into
|
|
240
|
+
// the distro), `wsl --terminate` so the next attempt cold-boots a CLEAN distro;
|
|
241
|
+
// clearing pid files inside a wedged WSL does nothing. Otherwise dockerd just
|
|
242
|
+
// died/is slow — clear stale runtime files only when it's actually gone.
|
|
243
|
+
if (launchErr) {
|
|
244
|
+
log.info(`[startEngine] launch errored → wsl --terminate for a clean cold boot`);
|
|
245
|
+
try { await wslTerminate(); } catch {}
|
|
246
|
+
} else {
|
|
247
|
+
try {
|
|
248
|
+
await wslRun(
|
|
249
|
+
"if ! pgrep dockerd >/dev/null 2>&1; then rm -f /var/run/docker.pid /run/docker.pid /var/run/docker.sock /run/docker.sock; fi; sleep 1",
|
|
250
|
+
{ timeout: 15000 });
|
|
251
|
+
} catch {}
|
|
252
|
+
}
|
|
227
253
|
}
|
|
228
254
|
log.error("[startEngine] ✗ dockerd NOT up after 3 attempts");
|
|
229
255
|
return false;
|