unity-hub-cli 0.4.0 → 0.5.0
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/dist/index.js +299 -16
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -57,6 +57,41 @@ var LaunchProjectUseCase = class {
|
|
|
57
57
|
await this.unityHubProjectsReader.updateLastModified(project.path, /* @__PURE__ */ new Date());
|
|
58
58
|
}
|
|
59
59
|
};
|
|
60
|
+
var TerminateProjectUseCase = class {
|
|
61
|
+
constructor(unityProcessReader, unityProcessTerminator, unityTempDirectoryCleaner) {
|
|
62
|
+
this.unityProcessReader = unityProcessReader;
|
|
63
|
+
this.unityProcessTerminator = unityProcessTerminator;
|
|
64
|
+
this.unityTempDirectoryCleaner = unityTempDirectoryCleaner;
|
|
65
|
+
}
|
|
66
|
+
async execute(project) {
|
|
67
|
+
const unityProcess = await this.unityProcessReader.findByProjectPath(project.path);
|
|
68
|
+
if (!unityProcess) {
|
|
69
|
+
return {
|
|
70
|
+
terminated: false,
|
|
71
|
+
message: "No Unity process is running for this project."
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
const terminated = await this.unityProcessTerminator.terminate(unityProcess);
|
|
75
|
+
if (!terminated) {
|
|
76
|
+
return {
|
|
77
|
+
terminated: false,
|
|
78
|
+
message: "Failed to terminate the Unity process."
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
let cleanupMessage = void 0;
|
|
82
|
+
try {
|
|
83
|
+
await this.unityTempDirectoryCleaner.clean(project.path);
|
|
84
|
+
} catch (error) {
|
|
85
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
86
|
+
console.error("Failed to clean Unity Temp directory:", message);
|
|
87
|
+
cleanupMessage = `Unity terminated, but failed to clean Temp: ${message}`;
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
terminated: true,
|
|
91
|
+
message: cleanupMessage
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
};
|
|
60
95
|
|
|
61
96
|
// src/infrastructure/editor.ts
|
|
62
97
|
import { constants } from "fs";
|
|
@@ -70,7 +105,7 @@ var MacEditorPathResolver = class {
|
|
|
70
105
|
try {
|
|
71
106
|
await access(editorPath, constants.X_OK);
|
|
72
107
|
} catch {
|
|
73
|
-
throw new Error(
|
|
108
|
+
throw new Error(`Unity Editor not found for version ${version.value}.`);
|
|
74
109
|
}
|
|
75
110
|
return editorPath;
|
|
76
111
|
}
|
|
@@ -161,7 +196,7 @@ import { spawn } from "child_process";
|
|
|
161
196
|
var NodeProcessLauncher = class {
|
|
162
197
|
async launch(command, args, options) {
|
|
163
198
|
const detached = options?.detached ?? false;
|
|
164
|
-
await new Promise((
|
|
199
|
+
await new Promise((resolve3, reject) => {
|
|
165
200
|
const child = spawn(command, args, {
|
|
166
201
|
detached,
|
|
167
202
|
stdio: "ignore"
|
|
@@ -173,7 +208,7 @@ var NodeProcessLauncher = class {
|
|
|
173
208
|
const handleSpawn = () => {
|
|
174
209
|
child.off("error", handleError);
|
|
175
210
|
child.unref();
|
|
176
|
-
|
|
211
|
+
resolve3();
|
|
177
212
|
};
|
|
178
213
|
child.once("error", handleError);
|
|
179
214
|
child.once("spawn", handleSpawn);
|
|
@@ -234,17 +269,17 @@ var UnityHubProjectsReader = class {
|
|
|
234
269
|
content = await readFile2(HUB_PROJECTS_PATH, "utf8");
|
|
235
270
|
} catch {
|
|
236
271
|
throw new Error(
|
|
237
|
-
`Unity Hub
|
|
272
|
+
`Unity Hub project list not found (${HUB_PROJECTS_PATH}).`
|
|
238
273
|
);
|
|
239
274
|
}
|
|
240
275
|
let json;
|
|
241
276
|
try {
|
|
242
277
|
json = JSON.parse(content);
|
|
243
278
|
} catch {
|
|
244
|
-
throw new Error("Unity Hub
|
|
279
|
+
throw new Error("Unable to read the Unity Hub project list (permissions/format error).");
|
|
245
280
|
}
|
|
246
281
|
if (json.schema_version && json.schema_version !== schemaVersion) {
|
|
247
|
-
throw new Error(
|
|
282
|
+
throw new Error(`Unsupported schema_version (${json.schema_version}).`);
|
|
248
283
|
}
|
|
249
284
|
const entries = Object.values(json.data ?? {});
|
|
250
285
|
if (entries.length === 0) {
|
|
@@ -259,14 +294,14 @@ var UnityHubProjectsReader = class {
|
|
|
259
294
|
content = await readFile2(HUB_PROJECTS_PATH, "utf8");
|
|
260
295
|
} catch {
|
|
261
296
|
throw new Error(
|
|
262
|
-
`Unity Hub
|
|
297
|
+
`Unity Hub project list not found (${HUB_PROJECTS_PATH}).`
|
|
263
298
|
);
|
|
264
299
|
}
|
|
265
300
|
let json;
|
|
266
301
|
try {
|
|
267
302
|
json = JSON.parse(content);
|
|
268
303
|
} catch {
|
|
269
|
-
throw new Error("Unity Hub
|
|
304
|
+
throw new Error("Unable to read the Unity Hub project list (permissions/format error).");
|
|
270
305
|
}
|
|
271
306
|
if (!json.data) {
|
|
272
307
|
return;
|
|
@@ -369,7 +404,7 @@ var promptYesNoSingleKey = async () => {
|
|
|
369
404
|
const supportsRaw = isRawModeSupported();
|
|
370
405
|
const previousRaw = supportsRaw ? stdin.isRaw === true : false;
|
|
371
406
|
const wasPaused = stdin.isPaused();
|
|
372
|
-
return await new Promise((
|
|
407
|
+
return await new Promise((resolve3) => {
|
|
373
408
|
const cleanup = () => {
|
|
374
409
|
stdin.removeListener("data", handleData);
|
|
375
410
|
if (wasPaused) {
|
|
@@ -392,7 +427,7 @@ var promptYesNoSingleKey = async () => {
|
|
|
392
427
|
}
|
|
393
428
|
process.stdout.write("\n");
|
|
394
429
|
cleanup();
|
|
395
|
-
|
|
430
|
+
resolve3(result);
|
|
396
431
|
};
|
|
397
432
|
process.stdout.write(RAW_PROMPT_MESSAGE);
|
|
398
433
|
if (supportsRaw) {
|
|
@@ -410,9 +445,9 @@ var promptYesNoLine = async () => {
|
|
|
410
445
|
console.error("UnityLockfile exists. No interactive console available for confirmation.");
|
|
411
446
|
return false;
|
|
412
447
|
}
|
|
413
|
-
const confirmed = await new Promise((
|
|
448
|
+
const confirmed = await new Promise((resolve3) => {
|
|
414
449
|
prompt.rl.question(RAW_PROMPT_MESSAGE, (answer) => {
|
|
415
|
-
|
|
450
|
+
resolve3(answer.trim() === "y");
|
|
416
451
|
});
|
|
417
452
|
});
|
|
418
453
|
prompt.close();
|
|
@@ -452,6 +487,166 @@ var UnityLockStatusReader = class {
|
|
|
452
487
|
}
|
|
453
488
|
};
|
|
454
489
|
|
|
490
|
+
// src/infrastructure/unityProcess.ts
|
|
491
|
+
import { execFile } from "child_process";
|
|
492
|
+
import { resolve as resolve2 } from "path";
|
|
493
|
+
import { promisify } from "util";
|
|
494
|
+
var execFileAsync = promisify(execFile);
|
|
495
|
+
var UNITY_EXECUTABLE_PATTERN = /Unity\.app\/Contents\/MacOS\/Unity/i;
|
|
496
|
+
var PROJECT_PATH_PATTERN = /-(?:projectPath|projectpath)\s+("[^"]+"|'[^']+'|[^\s"']+)/i;
|
|
497
|
+
var PROCESS_LIST_ARGS = ["-axo", "pid=,command=", "-ww"];
|
|
498
|
+
var PROCESS_LIST_COMMAND = "ps";
|
|
499
|
+
var TERMINATE_TIMEOUT_MILLIS = 5e3;
|
|
500
|
+
var TERMINATE_POLL_INTERVAL_MILLIS = 200;
|
|
501
|
+
var delay = async (duration) => {
|
|
502
|
+
await new Promise((resolveDelay) => {
|
|
503
|
+
setTimeout(() => {
|
|
504
|
+
resolveDelay();
|
|
505
|
+
}, duration);
|
|
506
|
+
});
|
|
507
|
+
};
|
|
508
|
+
var normalizePath = (target) => {
|
|
509
|
+
const resolved = resolve2(target);
|
|
510
|
+
if (resolved.endsWith("/")) {
|
|
511
|
+
return resolved.slice(0, -1);
|
|
512
|
+
}
|
|
513
|
+
return resolved;
|
|
514
|
+
};
|
|
515
|
+
var arePathsEqual = (left, right) => {
|
|
516
|
+
const normalizedLeft = normalizePath(left);
|
|
517
|
+
const normalizedRight = normalizePath(right);
|
|
518
|
+
return normalizedLeft.localeCompare(normalizedRight, void 0, { sensitivity: "base" }) === 0;
|
|
519
|
+
};
|
|
520
|
+
var extractProjectPath = (command) => {
|
|
521
|
+
const match = command.match(PROJECT_PATH_PATTERN);
|
|
522
|
+
if (!match) {
|
|
523
|
+
return void 0;
|
|
524
|
+
}
|
|
525
|
+
const raw = match[1];
|
|
526
|
+
if (!raw) {
|
|
527
|
+
return void 0;
|
|
528
|
+
}
|
|
529
|
+
const trimmed = raw.trim();
|
|
530
|
+
if (trimmed.startsWith('"') && trimmed.endsWith('"')) {
|
|
531
|
+
return trimmed.slice(1, -1);
|
|
532
|
+
}
|
|
533
|
+
if (trimmed.startsWith("'") && trimmed.endsWith("'")) {
|
|
534
|
+
return trimmed.slice(1, -1);
|
|
535
|
+
}
|
|
536
|
+
return trimmed;
|
|
537
|
+
};
|
|
538
|
+
var isUnityMainProcess = (command) => {
|
|
539
|
+
return UNITY_EXECUTABLE_PATTERN.test(command);
|
|
540
|
+
};
|
|
541
|
+
var isProcessMissingError = (error) => {
|
|
542
|
+
if (typeof error !== "object" || error === null) {
|
|
543
|
+
return false;
|
|
544
|
+
}
|
|
545
|
+
const nodeError = error;
|
|
546
|
+
return nodeError.code === "ESRCH";
|
|
547
|
+
};
|
|
548
|
+
var ensureProcessAlive = (pid) => {
|
|
549
|
+
try {
|
|
550
|
+
process.kill(pid, 0);
|
|
551
|
+
return true;
|
|
552
|
+
} catch (error) {
|
|
553
|
+
if (isProcessMissingError(error)) {
|
|
554
|
+
return false;
|
|
555
|
+
}
|
|
556
|
+
throw error;
|
|
557
|
+
}
|
|
558
|
+
};
|
|
559
|
+
var MacUnityProcessReader = class {
|
|
560
|
+
async findByProjectPath(projectPath) {
|
|
561
|
+
const normalizedTarget = normalizePath(projectPath);
|
|
562
|
+
const processes = await this.listUnityProcesses();
|
|
563
|
+
return processes.find((candidate) => arePathsEqual(candidate.projectPath, normalizedTarget));
|
|
564
|
+
}
|
|
565
|
+
async listUnityProcesses() {
|
|
566
|
+
let stdout;
|
|
567
|
+
try {
|
|
568
|
+
const result = await execFileAsync(PROCESS_LIST_COMMAND, PROCESS_LIST_ARGS);
|
|
569
|
+
stdout = result.stdout;
|
|
570
|
+
} catch (error) {
|
|
571
|
+
throw new Error(`Failed to retrieve Unity process list: ${error instanceof Error ? error.message : String(error)}`);
|
|
572
|
+
}
|
|
573
|
+
const lines = stdout.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
|
|
574
|
+
return lines.map((line) => {
|
|
575
|
+
const match = line.match(/^(\d+)\s+(.*)$/);
|
|
576
|
+
if (!match) {
|
|
577
|
+
return void 0;
|
|
578
|
+
}
|
|
579
|
+
const pidValue = Number.parseInt(match[1] ?? "", 10);
|
|
580
|
+
if (!Number.isFinite(pidValue)) {
|
|
581
|
+
return void 0;
|
|
582
|
+
}
|
|
583
|
+
const command = match[2] ?? "";
|
|
584
|
+
if (!isUnityMainProcess(command)) {
|
|
585
|
+
return void 0;
|
|
586
|
+
}
|
|
587
|
+
const projectArgument = extractProjectPath(command);
|
|
588
|
+
if (!projectArgument) {
|
|
589
|
+
return void 0;
|
|
590
|
+
}
|
|
591
|
+
return {
|
|
592
|
+
pid: pidValue,
|
|
593
|
+
projectPath: normalizePath(projectArgument)
|
|
594
|
+
};
|
|
595
|
+
}).filter((process3) => Boolean(process3));
|
|
596
|
+
}
|
|
597
|
+
};
|
|
598
|
+
var MacUnityProcessTerminator = class {
|
|
599
|
+
async terminate(unityProcess) {
|
|
600
|
+
try {
|
|
601
|
+
process.kill(unityProcess.pid, "SIGTERM");
|
|
602
|
+
} catch (error) {
|
|
603
|
+
if (isProcessMissingError(error)) {
|
|
604
|
+
return false;
|
|
605
|
+
}
|
|
606
|
+
throw new Error(
|
|
607
|
+
`Failed to terminate the Unity process (PID: ${unityProcess.pid}): ${error instanceof Error ? error.message : String(error)}`
|
|
608
|
+
);
|
|
609
|
+
}
|
|
610
|
+
const deadline = Date.now() + TERMINATE_TIMEOUT_MILLIS;
|
|
611
|
+
while (Date.now() < deadline) {
|
|
612
|
+
await delay(TERMINATE_POLL_INTERVAL_MILLIS);
|
|
613
|
+
const alive = ensureProcessAlive(unityProcess.pid);
|
|
614
|
+
if (!alive) {
|
|
615
|
+
return true;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
try {
|
|
619
|
+
process.kill(unityProcess.pid, "SIGKILL");
|
|
620
|
+
} catch (error) {
|
|
621
|
+
if (isProcessMissingError(error)) {
|
|
622
|
+
return true;
|
|
623
|
+
}
|
|
624
|
+
throw new Error(
|
|
625
|
+
`Failed to forcefully terminate the Unity process (PID: ${unityProcess.pid}): ${error instanceof Error ? error.message : String(error)}`
|
|
626
|
+
);
|
|
627
|
+
}
|
|
628
|
+
await delay(TERMINATE_POLL_INTERVAL_MILLIS);
|
|
629
|
+
return !ensureProcessAlive(unityProcess.pid);
|
|
630
|
+
}
|
|
631
|
+
};
|
|
632
|
+
|
|
633
|
+
// src/infrastructure/unityTemp.ts
|
|
634
|
+
import { rm as rm2 } from "fs/promises";
|
|
635
|
+
import { join as join4 } from "path";
|
|
636
|
+
var TEMP_DIRECTORY_NAME = "Temp";
|
|
637
|
+
var UnityTempDirectoryCleaner = class {
|
|
638
|
+
async clean(projectPath) {
|
|
639
|
+
const tempDirectoryPath = join4(projectPath, TEMP_DIRECTORY_NAME);
|
|
640
|
+
try {
|
|
641
|
+
await rm2(tempDirectoryPath, {
|
|
642
|
+
recursive: true,
|
|
643
|
+
force: true
|
|
644
|
+
});
|
|
645
|
+
} catch {
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
};
|
|
649
|
+
|
|
455
650
|
// src/presentation/App.tsx
|
|
456
651
|
import clipboard from "clipboardy";
|
|
457
652
|
import { Box, Text, useApp, useInput, useStdout } from "ink";
|
|
@@ -540,7 +735,7 @@ var formatUpdatedText = (lastModified) => {
|
|
|
540
735
|
var homeDirectory = process.env.HOME ?? "";
|
|
541
736
|
var homePrefix = homeDirectory ? `${homeDirectory}/` : "";
|
|
542
737
|
var minimumVisibleProjectCount = 4;
|
|
543
|
-
var defaultHintMessage = "Move with arrows or j/k \xB7 Launch with o \xB7
|
|
738
|
+
var defaultHintMessage = "Move with arrows or j/k \xB7 Launch with o \xB7 Quit Unity with q \xB7 Copy cd path with c";
|
|
544
739
|
var PROJECT_COLOR = "#abd8e7";
|
|
545
740
|
var BRANCH_COLOR = "#e3839c";
|
|
546
741
|
var PATH_COLOR = "#719bd8";
|
|
@@ -565,6 +760,7 @@ var buildCdCommand = (targetPath) => {
|
|
|
565
760
|
var App = ({
|
|
566
761
|
projects,
|
|
567
762
|
onLaunch,
|
|
763
|
+
onTerminate,
|
|
568
764
|
useGitRootName = true,
|
|
569
765
|
showBranch = true,
|
|
570
766
|
showPath = true
|
|
@@ -575,6 +771,8 @@ var App = ({
|
|
|
575
771
|
const [index, setIndex] = useState(0);
|
|
576
772
|
const [hint, setHint] = useState(defaultHintMessage);
|
|
577
773
|
const [windowStart, setWindowStart] = useState(0);
|
|
774
|
+
const [releasedProjects, setReleasedProjects] = useState(/* @__PURE__ */ new Set());
|
|
775
|
+
const [launchedProjects, setLaunchedProjects] = useState(/* @__PURE__ */ new Set());
|
|
578
776
|
const linesPerProject = (showBranch ? 1 : 0) + (showPath ? 1 : 0) + 2;
|
|
579
777
|
const sortedProjects = useMemo(() => {
|
|
580
778
|
const fallbackTime = 0;
|
|
@@ -748,6 +946,19 @@ var App = ({
|
|
|
748
946
|
}
|
|
749
947
|
try {
|
|
750
948
|
await onLaunch(project);
|
|
949
|
+
setLaunchedProjects((previous) => {
|
|
950
|
+
const next = new Set(previous);
|
|
951
|
+
next.add(project.id);
|
|
952
|
+
return next;
|
|
953
|
+
});
|
|
954
|
+
setReleasedProjects((previous) => {
|
|
955
|
+
if (!previous.has(project.id)) {
|
|
956
|
+
return previous;
|
|
957
|
+
}
|
|
958
|
+
const next = new Set(previous);
|
|
959
|
+
next.delete(project.id);
|
|
960
|
+
return next;
|
|
961
|
+
});
|
|
751
962
|
setHint(`Launched: ${project.title}`);
|
|
752
963
|
setTimeout(() => {
|
|
753
964
|
setHint(defaultHintMessage);
|
|
@@ -767,6 +978,53 @@ var App = ({
|
|
|
767
978
|
}, 3e3);
|
|
768
979
|
}
|
|
769
980
|
}, [index, onLaunch, sortedProjects]);
|
|
981
|
+
const terminateSelected = useCallback(async () => {
|
|
982
|
+
const projectView = sortedProjects[index];
|
|
983
|
+
if (!projectView) {
|
|
984
|
+
setHint("No project to terminate");
|
|
985
|
+
setTimeout(() => {
|
|
986
|
+
setHint(defaultHintMessage);
|
|
987
|
+
}, 2e3);
|
|
988
|
+
return;
|
|
989
|
+
}
|
|
990
|
+
try {
|
|
991
|
+
const result = await onTerminate(projectView.project);
|
|
992
|
+
if (!result.terminated) {
|
|
993
|
+
setHint(result.message ?? "No running Unity for this project");
|
|
994
|
+
setTimeout(() => {
|
|
995
|
+
setHint(defaultHintMessage);
|
|
996
|
+
}, 3e3);
|
|
997
|
+
return;
|
|
998
|
+
}
|
|
999
|
+
setHint(`Stopped Unity: ${projectView.project.title}`);
|
|
1000
|
+
setTimeout(() => {
|
|
1001
|
+
setHint(defaultHintMessage);
|
|
1002
|
+
}, 3e3);
|
|
1003
|
+
setLaunchedProjects((previous) => {
|
|
1004
|
+
if (!previous.has(projectView.project.id)) {
|
|
1005
|
+
return previous;
|
|
1006
|
+
}
|
|
1007
|
+
const next = new Set(previous);
|
|
1008
|
+
next.delete(projectView.project.id);
|
|
1009
|
+
return next;
|
|
1010
|
+
});
|
|
1011
|
+
setReleasedProjects((previous) => {
|
|
1012
|
+
const next = new Set(previous);
|
|
1013
|
+
next.add(projectView.project.id);
|
|
1014
|
+
return next;
|
|
1015
|
+
});
|
|
1016
|
+
} catch (error) {
|
|
1017
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1018
|
+
setHint(`Failed to stop: ${message}`);
|
|
1019
|
+
setTimeout(() => {
|
|
1020
|
+
setHint(defaultHintMessage);
|
|
1021
|
+
}, 3e3);
|
|
1022
|
+
}
|
|
1023
|
+
}, [index, onTerminate, sortedProjects]);
|
|
1024
|
+
useEffect(() => {
|
|
1025
|
+
setReleasedProjects(/* @__PURE__ */ new Set());
|
|
1026
|
+
setLaunchedProjects(/* @__PURE__ */ new Set());
|
|
1027
|
+
}, [projects]);
|
|
770
1028
|
useInput((input, key) => {
|
|
771
1029
|
if (input === "j" || key.downArrow) {
|
|
772
1030
|
move(1);
|
|
@@ -774,8 +1032,13 @@ var App = ({
|
|
|
774
1032
|
if (input === "k" || key.upArrow) {
|
|
775
1033
|
move(-1);
|
|
776
1034
|
}
|
|
1035
|
+
if (input === "q") {
|
|
1036
|
+
void terminateSelected();
|
|
1037
|
+
return;
|
|
1038
|
+
}
|
|
777
1039
|
if (input === "o") {
|
|
778
1040
|
void launchSelected();
|
|
1041
|
+
return;
|
|
779
1042
|
}
|
|
780
1043
|
if (input === "c") {
|
|
781
1044
|
copyProjectPath();
|
|
@@ -833,6 +1096,7 @@ var App = ({
|
|
|
833
1096
|
const updatedText = formatUpdatedText(project.lastModified);
|
|
834
1097
|
const pathLine = shortenHomePath(project.path);
|
|
835
1098
|
const branchLine = formatBranch(repository?.branch);
|
|
1099
|
+
const activeLock = isLocked && !releasedProjects.has(project.id) || launchedProjects.has(project.id);
|
|
836
1100
|
const baseScrollbarIndex = offset * linesPerProject;
|
|
837
1101
|
const titleScrollbar = scrollbarChars[baseScrollbarIndex] ?? " ";
|
|
838
1102
|
const branchScrollbar = showBranch ? scrollbarChars[baseScrollbarIndex + 1] ?? " " : " ";
|
|
@@ -851,7 +1115,7 @@ var App = ({
|
|
|
851
1115
|
versionLabel
|
|
852
1116
|
] }),
|
|
853
1117
|
updatedText ? /* @__PURE__ */ jsx(Text, { color: isSelected ? "green" : void 0, children: ` ${updatedText}` }) : null,
|
|
854
|
-
|
|
1118
|
+
activeLock ? /* @__PURE__ */ jsx(Text, { color: LOCK_COLOR, children: ` ${LOCK_LABEL}` }) : null
|
|
855
1119
|
] }),
|
|
856
1120
|
showBranch ? /* @__PURE__ */ jsxs(Text, { color: isSelected ? "green" : BRANCH_COLOR, children: [
|
|
857
1121
|
" ",
|
|
@@ -871,9 +1135,19 @@ var App = ({
|
|
|
871
1135
|
] })
|
|
872
1136
|
] }, project.id);
|
|
873
1137
|
});
|
|
874
|
-
}, [
|
|
1138
|
+
}, [
|
|
1139
|
+
index,
|
|
1140
|
+
launchedProjects,
|
|
1141
|
+
releasedProjects,
|
|
1142
|
+
scrollbarChars,
|
|
1143
|
+
showBranch,
|
|
1144
|
+
showPath,
|
|
1145
|
+
startIndex,
|
|
1146
|
+
useGitRootName,
|
|
1147
|
+
visibleProjects
|
|
1148
|
+
]);
|
|
875
1149
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
876
|
-
/* @__PURE__ */ jsx(Box, { flexDirection: "column", borderStyle: "round", borderColor: "green", children: rows.length === 0 ? /* @__PURE__ */ jsx(Text, { children: "Unity Hub
|
|
1150
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", borderStyle: "round", borderColor: "green", children: rows.length === 0 ? /* @__PURE__ */ jsx(Text, { children: "No Unity Hub projects were found." }) : rows }),
|
|
877
1151
|
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { children: hint }) })
|
|
878
1152
|
] });
|
|
879
1153
|
};
|
|
@@ -893,6 +1167,9 @@ var bootstrap = async () => {
|
|
|
893
1167
|
const editorPathResolver = new MacEditorPathResolver();
|
|
894
1168
|
const processLauncher = new NodeProcessLauncher();
|
|
895
1169
|
const lockChecker = new UnityLockChecker();
|
|
1170
|
+
const unityProcessReader = new MacUnityProcessReader();
|
|
1171
|
+
const unityProcessTerminator = new MacUnityProcessTerminator();
|
|
1172
|
+
const unityTempDirectoryCleaner = new UnityTempDirectoryCleaner();
|
|
896
1173
|
const launchProjectUseCase = new LaunchProjectUseCase(
|
|
897
1174
|
editorPathResolver,
|
|
898
1175
|
processLauncher,
|
|
@@ -900,6 +1177,11 @@ var bootstrap = async () => {
|
|
|
900
1177
|
unityHubReader,
|
|
901
1178
|
lockChecker
|
|
902
1179
|
);
|
|
1180
|
+
const terminateProjectUseCase = new TerminateProjectUseCase(
|
|
1181
|
+
unityProcessReader,
|
|
1182
|
+
unityProcessTerminator,
|
|
1183
|
+
unityTempDirectoryCleaner
|
|
1184
|
+
);
|
|
903
1185
|
const useGitRootName = !process2.argv.includes("--no-git-root-name");
|
|
904
1186
|
const showBranch = !process2.argv.includes("--hide-branch");
|
|
905
1187
|
const showPath = !process2.argv.includes("--hide-path");
|
|
@@ -911,6 +1193,7 @@ var bootstrap = async () => {
|
|
|
911
1193
|
{
|
|
912
1194
|
projects,
|
|
913
1195
|
onLaunch: (project) => launchProjectUseCase.execute(project),
|
|
1196
|
+
onTerminate: (project) => terminateProjectUseCase.execute(project),
|
|
914
1197
|
useGitRootName,
|
|
915
1198
|
showBranch,
|
|
916
1199
|
showPath
|