unity-hub-cli 0.6.0 → 0.7.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 +132 -146
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,28 +6,42 @@ import { render } from "ink";
|
|
|
6
6
|
|
|
7
7
|
// src/application/usecases.ts
|
|
8
8
|
var ListProjectsUseCase = class {
|
|
9
|
-
constructor(unityHubProjectsReader, gitRepositoryInfoReader, unityProjectOptionsReader, lockReader) {
|
|
9
|
+
constructor(unityHubProjectsReader, gitRepositoryInfoReader, unityProjectOptionsReader, lockReader, unityProcessReader) {
|
|
10
10
|
this.unityHubProjectsReader = unityHubProjectsReader;
|
|
11
11
|
this.gitRepositoryInfoReader = gitRepositoryInfoReader;
|
|
12
12
|
this.unityProjectOptionsReader = unityProjectOptionsReader;
|
|
13
13
|
this.lockReader = lockReader;
|
|
14
|
+
this.unityProcessReader = unityProcessReader;
|
|
14
15
|
}
|
|
15
16
|
async execute() {
|
|
16
17
|
const projects = await this.unityHubProjectsReader.listProjects();
|
|
17
|
-
const [repositoryInfoResults, lockResults] = await Promise.all([
|
|
18
|
+
const [repositoryInfoResults, lockResults, processResults] = await Promise.all([
|
|
18
19
|
Promise.allSettled(
|
|
19
20
|
projects.map((project) => this.gitRepositoryInfoReader.readRepositoryInfo(project.path))
|
|
20
21
|
),
|
|
21
|
-
Promise.allSettled(projects.map((project) => this.lockReader.isLocked(project.path)))
|
|
22
|
+
Promise.allSettled(projects.map((project) => this.lockReader.isLocked(project.path))),
|
|
23
|
+
Promise.allSettled(projects.map((project) => this.unityProcessReader.findByProjectPath(project.path)))
|
|
22
24
|
]);
|
|
23
25
|
return projects.map((project, index) => {
|
|
24
26
|
const repositoryResult = repositoryInfoResults[index];
|
|
25
27
|
const lockResult = lockResults[index];
|
|
28
|
+
const processResult = processResults[index];
|
|
26
29
|
const repository = repositoryResult.status === "fulfilled" ? repositoryResult.value ?? void 0 : void 0;
|
|
27
30
|
const isLocked = lockResult.status === "fulfilled" ? Boolean(lockResult.value) : false;
|
|
28
|
-
|
|
31
|
+
const hasRunningProcess = processResult.status === "fulfilled" ? Boolean(processResult.value) : false;
|
|
32
|
+
const launchStatus = this.determineLaunchStatus(hasRunningProcess, isLocked);
|
|
33
|
+
return { project, repository, isLocked, launchStatus };
|
|
29
34
|
});
|
|
30
35
|
}
|
|
36
|
+
determineLaunchStatus(hasRunningProcess, isLocked) {
|
|
37
|
+
if (hasRunningProcess) {
|
|
38
|
+
return "running";
|
|
39
|
+
}
|
|
40
|
+
if (isLocked) {
|
|
41
|
+
return "crashed";
|
|
42
|
+
}
|
|
43
|
+
return "idle";
|
|
44
|
+
}
|
|
31
45
|
};
|
|
32
46
|
var LaunchCancelledError = class extends Error {
|
|
33
47
|
constructor() {
|
|
@@ -58,10 +72,9 @@ var LaunchProjectUseCase = class {
|
|
|
58
72
|
}
|
|
59
73
|
};
|
|
60
74
|
var TerminateProjectUseCase = class {
|
|
61
|
-
constructor(unityProcessReader, unityProcessTerminator
|
|
75
|
+
constructor(unityProcessReader, unityProcessTerminator) {
|
|
62
76
|
this.unityProcessReader = unityProcessReader;
|
|
63
77
|
this.unityProcessTerminator = unityProcessTerminator;
|
|
64
|
-
this.unityTempDirectoryCleaner = unityTempDirectoryCleaner;
|
|
65
78
|
}
|
|
66
79
|
async execute(project) {
|
|
67
80
|
const unityProcess = await this.unityProcessReader.findByProjectPath(project.path);
|
|
@@ -78,17 +91,8 @@ var TerminateProjectUseCase = class {
|
|
|
78
91
|
message: "Failed to terminate the Unity process."
|
|
79
92
|
};
|
|
80
93
|
}
|
|
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
94
|
return {
|
|
90
|
-
terminated: true
|
|
91
|
-
message: cleanupMessage
|
|
95
|
+
terminated: true
|
|
92
96
|
};
|
|
93
97
|
}
|
|
94
98
|
};
|
|
@@ -348,117 +352,14 @@ var UnityHubProjectsReader = class {
|
|
|
348
352
|
|
|
349
353
|
// src/infrastructure/unityLock.ts
|
|
350
354
|
import { execFile } from "child_process";
|
|
351
|
-
import { constants as constants2
|
|
355
|
+
import { constants as constants2 } from "fs";
|
|
352
356
|
import { access as access2, rm } from "fs/promises";
|
|
353
357
|
import { join as join3 } from "path";
|
|
354
|
-
import readline from "readline";
|
|
355
358
|
import { promisify } from "util";
|
|
356
|
-
var RAW_PROMPT_MESSAGE = "Delete UnityLockfile and continue? Type 'y' to continue; anything else aborts: ";
|
|
357
359
|
var execFileAsync = promisify(execFile);
|
|
358
360
|
var buildBringToFrontScript = (pid) => {
|
|
359
361
|
return `tell application "System Events" to set frontmost of (first process whose unix id is ${pid}) to true`;
|
|
360
362
|
};
|
|
361
|
-
var isRawModeSupported = () => {
|
|
362
|
-
const stdin = process.stdin;
|
|
363
|
-
return Boolean(stdin?.isTTY && typeof stdin.setRawMode === "function" && process.stdout.isTTY);
|
|
364
|
-
};
|
|
365
|
-
var createPromptInterface = () => {
|
|
366
|
-
if (process.stdin.isTTY && process.stdout.isTTY) {
|
|
367
|
-
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
368
|
-
const close = () => rl.close();
|
|
369
|
-
return { rl, close };
|
|
370
|
-
}
|
|
371
|
-
try {
|
|
372
|
-
if (process.platform === "win32") {
|
|
373
|
-
const inCandidates = ["\\\\.\\CONIN$", "CONIN$"];
|
|
374
|
-
const outCandidates = ["\\\\.\\CONOUT$", "CONOUT$"];
|
|
375
|
-
for (const inPath of inCandidates) {
|
|
376
|
-
for (const outPath of outCandidates) {
|
|
377
|
-
try {
|
|
378
|
-
const input = createReadStream(inPath);
|
|
379
|
-
const output = createWriteStream(outPath);
|
|
380
|
-
const rl = readline.createInterface({ input, output });
|
|
381
|
-
const close = () => {
|
|
382
|
-
rl.close();
|
|
383
|
-
input.destroy();
|
|
384
|
-
output.end();
|
|
385
|
-
};
|
|
386
|
-
return { rl, close };
|
|
387
|
-
} catch {
|
|
388
|
-
continue;
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
} else {
|
|
393
|
-
const input = createReadStream("/dev/tty");
|
|
394
|
-
const output = createWriteStream("/dev/tty");
|
|
395
|
-
const rl = readline.createInterface({ input, output });
|
|
396
|
-
const close = () => {
|
|
397
|
-
rl.close();
|
|
398
|
-
input.destroy();
|
|
399
|
-
output.end();
|
|
400
|
-
};
|
|
401
|
-
return { rl, close };
|
|
402
|
-
}
|
|
403
|
-
} catch {
|
|
404
|
-
return void 0;
|
|
405
|
-
}
|
|
406
|
-
return void 0;
|
|
407
|
-
};
|
|
408
|
-
var promptYesNoSingleKey = async () => {
|
|
409
|
-
const stdin = process.stdin;
|
|
410
|
-
const supportsRaw = isRawModeSupported();
|
|
411
|
-
const previousRaw = supportsRaw ? stdin.isRaw === true : false;
|
|
412
|
-
const wasPaused = stdin.isPaused();
|
|
413
|
-
return await new Promise((resolve3) => {
|
|
414
|
-
const cleanup = () => {
|
|
415
|
-
stdin.removeListener("data", handleData);
|
|
416
|
-
if (wasPaused) {
|
|
417
|
-
stdin.pause();
|
|
418
|
-
}
|
|
419
|
-
if (supportsRaw) {
|
|
420
|
-
stdin.setRawMode(previousRaw);
|
|
421
|
-
}
|
|
422
|
-
};
|
|
423
|
-
const handleData = (data) => {
|
|
424
|
-
const char = data.toString();
|
|
425
|
-
const firstByte = data[0] ?? 0;
|
|
426
|
-
let result = false;
|
|
427
|
-
if (char === "y") {
|
|
428
|
-
result = true;
|
|
429
|
-
} else if (char === "n" || char === "N" || firstByte === 3 || firstByte === 27 || firstByte === 13) {
|
|
430
|
-
result = false;
|
|
431
|
-
} else {
|
|
432
|
-
result = false;
|
|
433
|
-
}
|
|
434
|
-
process.stdout.write("\n");
|
|
435
|
-
cleanup();
|
|
436
|
-
resolve3(result);
|
|
437
|
-
};
|
|
438
|
-
process.stdout.write(RAW_PROMPT_MESSAGE);
|
|
439
|
-
if (supportsRaw) {
|
|
440
|
-
stdin.setRawMode(true);
|
|
441
|
-
}
|
|
442
|
-
if (wasPaused) {
|
|
443
|
-
stdin.resume();
|
|
444
|
-
}
|
|
445
|
-
stdin.once("data", handleData);
|
|
446
|
-
});
|
|
447
|
-
};
|
|
448
|
-
var promptYesNoLine = async () => {
|
|
449
|
-
const prompt = createPromptInterface();
|
|
450
|
-
if (!prompt) {
|
|
451
|
-
console.error("UnityLockfile exists. No interactive console available for confirmation.");
|
|
452
|
-
return false;
|
|
453
|
-
}
|
|
454
|
-
const confirmed = await new Promise((resolve3) => {
|
|
455
|
-
prompt.rl.question(RAW_PROMPT_MESSAGE, (answer) => {
|
|
456
|
-
resolve3(answer.trim() === "y");
|
|
457
|
-
});
|
|
458
|
-
});
|
|
459
|
-
prompt.close();
|
|
460
|
-
return confirmed;
|
|
461
|
-
};
|
|
462
363
|
var pathExists = async (target) => {
|
|
463
364
|
try {
|
|
464
365
|
await access2(target, constants2.F_OK);
|
|
@@ -468,8 +369,9 @@ var pathExists = async (target) => {
|
|
|
468
369
|
}
|
|
469
370
|
};
|
|
470
371
|
var UnityLockChecker = class {
|
|
471
|
-
constructor(unityProcessReader) {
|
|
372
|
+
constructor(unityProcessReader, tempDirectoryCleaner) {
|
|
472
373
|
this.unityProcessReader = unityProcessReader;
|
|
374
|
+
this.tempDirectoryCleaner = tempDirectoryCleaner;
|
|
473
375
|
}
|
|
474
376
|
async check(projectPath) {
|
|
475
377
|
const activeProcess = await this.unityProcessReader.findByProjectPath(projectPath);
|
|
@@ -485,15 +387,22 @@ var UnityLockChecker = class {
|
|
|
485
387
|
if (!hasLockfile) {
|
|
486
388
|
return "allow";
|
|
487
389
|
}
|
|
488
|
-
console.log(`UnityLockfile found: ${lockfilePath}`);
|
|
489
|
-
console.log("
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
390
|
+
console.log(`UnityLockfile found without active Unity process: ${lockfilePath}`);
|
|
391
|
+
console.log("Assuming previous crash. Cleaning Temp directory and continuing launch.");
|
|
392
|
+
try {
|
|
393
|
+
await this.tempDirectoryCleaner.clean(projectPath);
|
|
394
|
+
} catch (error) {
|
|
395
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
396
|
+
console.error(`Failed to clean Temp directory: ${message}`);
|
|
397
|
+
}
|
|
398
|
+
try {
|
|
399
|
+
await rm(lockfilePath, { force: true });
|
|
400
|
+
console.log("Deleted UnityLockfile.");
|
|
401
|
+
} catch (error) {
|
|
402
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
403
|
+
console.error(`Failed to delete UnityLockfile: ${message}`);
|
|
494
404
|
}
|
|
495
|
-
|
|
496
|
-
console.log("Deleted UnityLockfile. Continuing launch.");
|
|
405
|
+
console.log("Continuing launch.");
|
|
497
406
|
return "allow";
|
|
498
407
|
}
|
|
499
408
|
async bringUnityToFront(pid) {
|
|
@@ -764,12 +673,16 @@ var formatUpdatedText = (lastModified) => {
|
|
|
764
673
|
var homeDirectory = process.env.HOME ?? "";
|
|
765
674
|
var homePrefix = homeDirectory ? `${homeDirectory}/` : "";
|
|
766
675
|
var minimumVisibleProjectCount = 4;
|
|
767
|
-
var defaultHintMessage = "Move with arrows or j/k \xB7 Launch with o \xB7 Quit Unity with q \xB7 Copy cd path with c";
|
|
676
|
+
var defaultHintMessage = "Move with arrows or j/k \xB7 Launch with o \xB7 Quit Unity with q \xB7 Refresh with r \xB7 Copy cd path with c";
|
|
768
677
|
var PROJECT_COLOR = "#abd8e7";
|
|
769
678
|
var BRANCH_COLOR = "#e3839c";
|
|
770
679
|
var PATH_COLOR = "#719bd8";
|
|
771
680
|
var LOCK_COLOR = "yellow";
|
|
772
|
-
var
|
|
681
|
+
var STATUS_LABELS = {
|
|
682
|
+
idle: "",
|
|
683
|
+
running: "[running]",
|
|
684
|
+
crashed: "[crash]"
|
|
685
|
+
};
|
|
773
686
|
var shortenHomePath = (targetPath) => {
|
|
774
687
|
if (!homeDirectory) {
|
|
775
688
|
return targetPath;
|
|
@@ -790,18 +703,21 @@ var App = ({
|
|
|
790
703
|
projects,
|
|
791
704
|
onLaunch,
|
|
792
705
|
onTerminate,
|
|
706
|
+
onRefresh,
|
|
793
707
|
useGitRootName = true,
|
|
794
708
|
showBranch = true,
|
|
795
709
|
showPath = true
|
|
796
710
|
}) => {
|
|
797
711
|
const { exit } = useApp();
|
|
798
712
|
const { stdout } = useStdout();
|
|
713
|
+
const [projectViews, setProjectViews] = useState(projects);
|
|
799
714
|
const [visibleCount, setVisibleCount] = useState(minimumVisibleProjectCount);
|
|
800
715
|
const [index, setIndex] = useState(0);
|
|
801
716
|
const [hint, setHint] = useState(defaultHintMessage);
|
|
802
717
|
const [windowStart, setWindowStart] = useState(0);
|
|
803
718
|
const [releasedProjects, setReleasedProjects] = useState(/* @__PURE__ */ new Set());
|
|
804
719
|
const [launchedProjects, setLaunchedProjects] = useState(/* @__PURE__ */ new Set());
|
|
720
|
+
const [isRefreshing, setIsRefreshing] = useState(false);
|
|
805
721
|
const linesPerProject = (showBranch ? 1 : 0) + (showPath ? 1 : 0) + 2;
|
|
806
722
|
const sortedProjects = useMemo(() => {
|
|
807
723
|
const fallbackTime = 0;
|
|
@@ -815,7 +731,7 @@ var App = ({
|
|
|
815
731
|
return view.project.title.toLocaleLowerCase();
|
|
816
732
|
};
|
|
817
733
|
const toTieBreaker = (view) => view.project.path.toLocaleLowerCase();
|
|
818
|
-
return [...
|
|
734
|
+
return [...projectViews].sort((a, b) => {
|
|
819
735
|
if (a.project.favorite !== b.project.favorite) {
|
|
820
736
|
return a.project.favorite ? -1 : 1;
|
|
821
737
|
}
|
|
@@ -831,7 +747,7 @@ var App = ({
|
|
|
831
747
|
}
|
|
832
748
|
return keyA.localeCompare(keyB);
|
|
833
749
|
});
|
|
834
|
-
}, [
|
|
750
|
+
}, [projectViews, useGitRootName]);
|
|
835
751
|
useEffect(() => {
|
|
836
752
|
const handleSigint = () => {
|
|
837
753
|
exit();
|
|
@@ -849,8 +765,7 @@ var App = ({
|
|
|
849
765
|
}
|
|
850
766
|
const borderRows = 2;
|
|
851
767
|
const hintRows = 1;
|
|
852
|
-
const
|
|
853
|
-
const reservedRows = borderRows + hintRows + hintMarginRows;
|
|
768
|
+
const reservedRows = borderRows + hintRows;
|
|
854
769
|
const availableRows = stdout.rows - reservedRows;
|
|
855
770
|
const rowsPerProject = Math.max(linesPerProject, 1);
|
|
856
771
|
const calculatedCount = Math.max(
|
|
@@ -1051,9 +966,63 @@ var App = ({
|
|
|
1051
966
|
}
|
|
1052
967
|
}, [index, onTerminate, sortedProjects]);
|
|
1053
968
|
useEffect(() => {
|
|
969
|
+
setProjectViews(projects);
|
|
1054
970
|
setReleasedProjects(/* @__PURE__ */ new Set());
|
|
1055
971
|
setLaunchedProjects(/* @__PURE__ */ new Set());
|
|
1056
972
|
}, [projects]);
|
|
973
|
+
const refreshProjects = useCallback(async () => {
|
|
974
|
+
if (!onRefresh) {
|
|
975
|
+
setHint("Refresh not available");
|
|
976
|
+
setTimeout(() => {
|
|
977
|
+
setHint(defaultHintMessage);
|
|
978
|
+
}, 2e3);
|
|
979
|
+
return;
|
|
980
|
+
}
|
|
981
|
+
if (isRefreshing) {
|
|
982
|
+
setHint("Already refreshing");
|
|
983
|
+
setTimeout(() => {
|
|
984
|
+
setHint(defaultHintMessage);
|
|
985
|
+
}, 2e3);
|
|
986
|
+
return;
|
|
987
|
+
}
|
|
988
|
+
setIsRefreshing(true);
|
|
989
|
+
setHint("Refreshing projects...");
|
|
990
|
+
try {
|
|
991
|
+
const updatedProjects = await onRefresh();
|
|
992
|
+
setProjectViews(updatedProjects);
|
|
993
|
+
setReleasedProjects(/* @__PURE__ */ new Set());
|
|
994
|
+
setLaunchedProjects(/* @__PURE__ */ new Set());
|
|
995
|
+
setIndex((previousIndex) => {
|
|
996
|
+
if (updatedProjects.length === 0) {
|
|
997
|
+
return 0;
|
|
998
|
+
}
|
|
999
|
+
const previousProject = sortedProjects[previousIndex]?.project;
|
|
1000
|
+
if (!previousProject) {
|
|
1001
|
+
return Math.min(previousIndex, updatedProjects.length - 1);
|
|
1002
|
+
}
|
|
1003
|
+
const nextIndex = updatedProjects.findIndex(
|
|
1004
|
+
(candidate) => candidate.project.id === previousProject.id
|
|
1005
|
+
);
|
|
1006
|
+
if (nextIndex === -1) {
|
|
1007
|
+
return Math.min(previousIndex, updatedProjects.length - 1);
|
|
1008
|
+
}
|
|
1009
|
+
return nextIndex;
|
|
1010
|
+
});
|
|
1011
|
+
setWindowStart(0);
|
|
1012
|
+
setHint("Project list refreshed");
|
|
1013
|
+
setTimeout(() => {
|
|
1014
|
+
setHint(defaultHintMessage);
|
|
1015
|
+
}, 2e3);
|
|
1016
|
+
} catch (error) {
|
|
1017
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1018
|
+
setHint(`Failed to refresh: ${message}`);
|
|
1019
|
+
setTimeout(() => {
|
|
1020
|
+
setHint(defaultHintMessage);
|
|
1021
|
+
}, 3e3);
|
|
1022
|
+
} finally {
|
|
1023
|
+
setIsRefreshing(false);
|
|
1024
|
+
}
|
|
1025
|
+
}, [isRefreshing, onRefresh, sortedProjects]);
|
|
1057
1026
|
useInput((input, key) => {
|
|
1058
1027
|
if (input === "j" || key.downArrow) {
|
|
1059
1028
|
move(1);
|
|
@@ -1069,6 +1038,10 @@ var App = ({
|
|
|
1069
1038
|
void launchSelected();
|
|
1070
1039
|
return;
|
|
1071
1040
|
}
|
|
1041
|
+
if (input === "r") {
|
|
1042
|
+
void refreshProjects();
|
|
1043
|
+
return;
|
|
1044
|
+
}
|
|
1072
1045
|
if (input === "c") {
|
|
1073
1046
|
copyProjectPath();
|
|
1074
1047
|
}
|
|
@@ -1089,7 +1062,7 @@ var App = ({
|
|
|
1089
1062
|
};
|
|
1090
1063
|
}, [limit, sortedProjects, windowStart]);
|
|
1091
1064
|
const scrollbarChars = useMemo(() => {
|
|
1092
|
-
const totalProjects =
|
|
1065
|
+
const totalProjects = projectViews.length;
|
|
1093
1066
|
const totalLines = totalProjects * linesPerProject;
|
|
1094
1067
|
const windowProjects = visibleProjects.length;
|
|
1095
1068
|
const visibleLines = windowProjects * linesPerProject;
|
|
@@ -1114,9 +1087,9 @@ var App = ({
|
|
|
1114
1087
|
}
|
|
1115
1088
|
return "|";
|
|
1116
1089
|
});
|
|
1117
|
-
}, [linesPerProject,
|
|
1090
|
+
}, [linesPerProject, projectViews.length, startIndex, visibleProjects]);
|
|
1118
1091
|
const rows = useMemo(() => {
|
|
1119
|
-
return visibleProjects.map(({ project, repository,
|
|
1092
|
+
return visibleProjects.map(({ project, repository, launchStatus }, offset) => {
|
|
1120
1093
|
const rowIndex = startIndex + offset;
|
|
1121
1094
|
const isSelected = rowIndex === index;
|
|
1122
1095
|
const arrow = isSelected ? ">" : " ";
|
|
@@ -1125,12 +1098,24 @@ var App = ({
|
|
|
1125
1098
|
const updatedText = formatUpdatedText(project.lastModified);
|
|
1126
1099
|
const pathLine = shortenHomePath(project.path);
|
|
1127
1100
|
const branchLine = formatBranch(repository?.branch);
|
|
1128
|
-
const
|
|
1101
|
+
const hasReleasedLock = releasedProjects.has(project.id);
|
|
1102
|
+
const isLocallyLaunched = launchedProjects.has(project.id);
|
|
1103
|
+
const displayStatus = (() => {
|
|
1104
|
+
if (isLocallyLaunched) {
|
|
1105
|
+
return "running";
|
|
1106
|
+
}
|
|
1107
|
+
if (hasReleasedLock) {
|
|
1108
|
+
return "idle";
|
|
1109
|
+
}
|
|
1110
|
+
return launchStatus;
|
|
1111
|
+
})();
|
|
1129
1112
|
const baseScrollbarIndex = offset * linesPerProject;
|
|
1130
1113
|
const titleScrollbar = scrollbarChars[baseScrollbarIndex] ?? " ";
|
|
1131
1114
|
const branchScrollbar = showBranch ? scrollbarChars[baseScrollbarIndex + 1] ?? " " : " ";
|
|
1132
1115
|
const pathScrollbar = showPath ? scrollbarChars[baseScrollbarIndex + 1 + (showBranch ? 1 : 0)] ?? " " : " ";
|
|
1133
1116
|
const spacerScrollbar = scrollbarChars[baseScrollbarIndex + linesPerProject - 1] ?? " ";
|
|
1117
|
+
const statusLabel = STATUS_LABELS[displayStatus];
|
|
1118
|
+
const statusColor = displayStatus === "running" ? LOCK_COLOR : displayStatus === "crashed" ? "red" : void 0;
|
|
1134
1119
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
1135
1120
|
/* @__PURE__ */ jsxs(Box, { flexGrow: 1, flexDirection: "column", children: [
|
|
1136
1121
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
@@ -1144,7 +1129,7 @@ var App = ({
|
|
|
1144
1129
|
versionLabel
|
|
1145
1130
|
] }),
|
|
1146
1131
|
updatedText ? /* @__PURE__ */ jsx(Text, { color: isSelected ? "green" : void 0, children: ` ${updatedText}` }) : null,
|
|
1147
|
-
|
|
1132
|
+
statusLabel && statusColor ? /* @__PURE__ */ jsx(Text, { color: statusColor, children: ` ${statusLabel}` }) : null
|
|
1148
1133
|
] }),
|
|
1149
1134
|
showBranch ? /* @__PURE__ */ jsxs(Text, { color: isSelected ? "green" : BRANCH_COLOR, children: [
|
|
1150
1135
|
" ",
|
|
@@ -1177,7 +1162,7 @@ var App = ({
|
|
|
1177
1162
|
]);
|
|
1178
1163
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
1179
1164
|
/* @__PURE__ */ jsx(Box, { flexDirection: "column", borderStyle: "round", borderColor: "green", children: rows.length === 0 ? /* @__PURE__ */ jsx(Text, { children: "No Unity Hub projects were found." }) : rows }),
|
|
1180
|
-
/* @__PURE__ */ jsx(Box, {
|
|
1165
|
+
/* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { children: hint }) })
|
|
1181
1166
|
] });
|
|
1182
1167
|
};
|
|
1183
1168
|
|
|
@@ -1188,17 +1173,18 @@ var bootstrap = async () => {
|
|
|
1188
1173
|
const gitRepositoryInfoReader = new GitRepositoryInfoReader();
|
|
1189
1174
|
const lockStatusReader = new UnityLockStatusReader();
|
|
1190
1175
|
const unityProcessReader = new MacUnityProcessReader();
|
|
1176
|
+
const unityTempDirectoryCleaner = new UnityTempDirectoryCleaner();
|
|
1191
1177
|
const listProjectsUseCase = new ListProjectsUseCase(
|
|
1192
1178
|
unityHubReader,
|
|
1193
1179
|
gitRepositoryInfoReader,
|
|
1194
1180
|
unityHubReader,
|
|
1195
|
-
lockStatusReader
|
|
1181
|
+
lockStatusReader,
|
|
1182
|
+
unityProcessReader
|
|
1196
1183
|
);
|
|
1197
1184
|
const editorPathResolver = new MacEditorPathResolver();
|
|
1198
1185
|
const processLauncher = new NodeProcessLauncher();
|
|
1199
|
-
const lockChecker = new UnityLockChecker(unityProcessReader);
|
|
1186
|
+
const lockChecker = new UnityLockChecker(unityProcessReader, unityTempDirectoryCleaner);
|
|
1200
1187
|
const unityProcessTerminator = new MacUnityProcessTerminator();
|
|
1201
|
-
const unityTempDirectoryCleaner = new UnityTempDirectoryCleaner();
|
|
1202
1188
|
const launchProjectUseCase = new LaunchProjectUseCase(
|
|
1203
1189
|
editorPathResolver,
|
|
1204
1190
|
processLauncher,
|
|
@@ -1208,8 +1194,7 @@ var bootstrap = async () => {
|
|
|
1208
1194
|
);
|
|
1209
1195
|
const terminateProjectUseCase = new TerminateProjectUseCase(
|
|
1210
1196
|
unityProcessReader,
|
|
1211
|
-
unityProcessTerminator
|
|
1212
|
-
unityTempDirectoryCleaner
|
|
1197
|
+
unityProcessTerminator
|
|
1213
1198
|
);
|
|
1214
1199
|
const useGitRootName = !process2.argv.includes("--no-git-root-name");
|
|
1215
1200
|
const showBranch = !process2.argv.includes("--hide-branch");
|
|
@@ -1223,6 +1208,7 @@ var bootstrap = async () => {
|
|
|
1223
1208
|
projects,
|
|
1224
1209
|
onLaunch: (project) => launchProjectUseCase.execute(project),
|
|
1225
1210
|
onTerminate: (project) => terminateProjectUseCase.execute(project),
|
|
1211
|
+
onRefresh: () => listProjectsUseCase.execute(),
|
|
1226
1212
|
useGitRootName,
|
|
1227
1213
|
showBranch,
|
|
1228
1214
|
showPath
|