@timmy6942025/cli-timer 1.0.0 → 1.1.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/.github/workflows/npm-publish.yml +34 -0
- package/README.md +15 -17
- package/package.json +1 -1
- package/settings-ui/main.go +8 -0
- package/settings-ui/main_test.go +1 -0
- package/settings-ui/prebuilt/darwin-arm64/cli-timer-settings-ui +0 -0
- package/settings-ui/prebuilt/darwin-x64/cli-timer-settings-ui +0 -0
- package/settings-ui/prebuilt/linux-arm64/cli-timer-settings-ui +0 -0
- package/settings-ui/prebuilt/linux-x64/cli-timer-settings-ui +0 -0
- package/settings-ui/prebuilt/windows-arm64/cli-timer-settings-ui.exe +0 -0
- package/settings-ui/prebuilt/windows-x64/cli-timer-settings-ui.exe +0 -0
- package/src/index.js +216 -10
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: npm-publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
tags:
|
|
7
|
+
- "v*"
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
publish:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
id-token: write
|
|
15
|
+
steps:
|
|
16
|
+
- name: Checkout
|
|
17
|
+
uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Setup Node.js
|
|
20
|
+
uses: actions/setup-node@v4
|
|
21
|
+
with:
|
|
22
|
+
node-version: 22
|
|
23
|
+
registry-url: https://registry.npmjs.org
|
|
24
|
+
|
|
25
|
+
- name: Install dependencies
|
|
26
|
+
run: npm ci
|
|
27
|
+
|
|
28
|
+
- name: Run tests
|
|
29
|
+
run: npm test
|
|
30
|
+
|
|
31
|
+
- name: Publish package
|
|
32
|
+
run: npm publish --access public --provenance
|
|
33
|
+
env:
|
|
34
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/README.md
CHANGED
|
@@ -2,28 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
A simple and customizable, easy to setup/use timer and stopwatch that runs in your terminal.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Install
|
|
6
6
|
|
|
7
|
-
Install
|
|
7
|
+
Install globally (this is all you need):
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
npm
|
|
10
|
+
npm i -g @timmy6942025/cli-timer
|
|
11
|
+
# or
|
|
12
|
+
bun add -g @timmy6942025/cli-timer
|
|
11
13
|
```
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
node bin/timer.js 5 min
|
|
17
|
-
node bin/stopwatch.js
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
Or install globally from this folder:
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
npm link
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
Then use commands:
|
|
15
|
+
Then use commands anywhere:
|
|
27
16
|
|
|
28
17
|
```bash
|
|
29
18
|
timer 5 min
|
|
@@ -96,6 +85,14 @@ Open interactive settings UI:
|
|
|
96
85
|
timer settings
|
|
97
86
|
```
|
|
98
87
|
|
|
88
|
+
`timer settings` ships with prebuilt Bubble Tea binaries for:
|
|
89
|
+
|
|
90
|
+
- Linux x64 / arm64
|
|
91
|
+
- macOS x64 / arm64
|
|
92
|
+
- Windows x64 / arm64
|
|
93
|
+
|
|
94
|
+
If your platform is unsupported, it falls back to running the Go source (`go run`) when Go is installed.
|
|
95
|
+
|
|
99
96
|
This launches a Bubble Tea based screen where you can change:
|
|
100
97
|
|
|
101
98
|
- Font
|
|
@@ -104,6 +101,7 @@ This launches a Bubble Tea based screen where you can change:
|
|
|
104
101
|
- Show controls
|
|
105
102
|
- Tick rate (50-1000 ms)
|
|
106
103
|
- Completion message
|
|
104
|
+
- System notification on completion (default On)
|
|
107
105
|
- Pause key / pause alt key
|
|
108
106
|
- Restart key
|
|
109
107
|
- Exit key / exit alt key
|
package/package.json
CHANGED
package/settings-ui/main.go
CHANGED
|
@@ -45,6 +45,7 @@ type config struct {
|
|
|
45
45
|
ShowControls bool `json:"showControls"`
|
|
46
46
|
TickRateMs int `json:"tickRateMs"`
|
|
47
47
|
CompletionMessage string `json:"completionMessage"`
|
|
48
|
+
NotifyOnComplete bool `json:"notifyOnComplete"`
|
|
48
49
|
Keybindings keybindings `json:"keybindings"`
|
|
49
50
|
}
|
|
50
51
|
|
|
@@ -149,6 +150,7 @@ func buildMenuItems(cfg config) []list.Item {
|
|
|
149
150
|
menuEntry{id: "controls", title: "Show controls", description: boolText(cfg.ShowControls)},
|
|
150
151
|
menuEntry{id: "tickRate", title: "Tick rate", description: fmt.Sprintf("%d ms", cfg.TickRateMs)},
|
|
151
152
|
menuEntry{id: "message", title: "Completion message", description: summarizeMessage(cfg.CompletionMessage)},
|
|
153
|
+
menuEntry{id: "notify", title: "System notification", description: boolText(cfg.NotifyOnComplete)},
|
|
152
154
|
menuEntry{id: "pauseKey", title: "Pause key", description: keyTokenLabel(cfg.Keybindings.PauseKey)},
|
|
153
155
|
menuEntry{id: "pauseAltKey", title: "Pause alt key", description: keyTokenLabel(cfg.Keybindings.PauseAltKey)},
|
|
154
156
|
menuEntry{id: "restartKey", title: "Restart key", description: keyTokenLabel(cfg.Keybindings.RestartKey)},
|
|
@@ -230,6 +232,7 @@ func normalizeConfig(cfg config) config {
|
|
|
230
232
|
ShowControls: true,
|
|
231
233
|
TickRateMs: defaultTickRateMs,
|
|
232
234
|
CompletionMessage: defaultCompletionMessage,
|
|
235
|
+
NotifyOnComplete: true,
|
|
233
236
|
Keybindings: defaultKeybindings,
|
|
234
237
|
}
|
|
235
238
|
|
|
@@ -245,6 +248,7 @@ func normalizeConfig(cfg config) config {
|
|
|
245
248
|
if cfg.CompletionMessage != "" {
|
|
246
249
|
result.CompletionMessage = normalizeCompletionMessage(cfg.CompletionMessage)
|
|
247
250
|
}
|
|
251
|
+
result.NotifyOnComplete = cfg.NotifyOnComplete
|
|
248
252
|
result.Keybindings = normalizeKeybindings(cfg.Keybindings)
|
|
249
253
|
return result
|
|
250
254
|
}
|
|
@@ -454,6 +458,10 @@ func (m *model) applyMenuAction() tea.Cmd {
|
|
|
454
458
|
m.messageInput.Focus()
|
|
455
459
|
m.screen = screenMessageEditor
|
|
456
460
|
return nil
|
|
461
|
+
case "notify":
|
|
462
|
+
m.payload.Config.NotifyOnComplete = !m.payload.Config.NotifyOnComplete
|
|
463
|
+
m.refreshMenu()
|
|
464
|
+
return nil
|
|
457
465
|
case "pauseKey":
|
|
458
466
|
m.openKeyPicker("pauseKey", "Select Pause Key")
|
|
459
467
|
return nil
|
package/settings-ui/main_test.go
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/index.js
CHANGED
|
@@ -5,6 +5,7 @@ const { spawnSync } = require("child_process");
|
|
|
5
5
|
const figlet = require("figlet");
|
|
6
6
|
|
|
7
7
|
const PROJECT_ROOT = path.join(__dirname, "..");
|
|
8
|
+
const PREBUILT_SETTINGS_UI_DIR = path.join(PROJECT_ROOT, "settings-ui", "prebuilt");
|
|
8
9
|
const CONFIG_DIR = path.join(os.homedir(), ".cli-timer");
|
|
9
10
|
const CONFIG_PATH = path.join(CONFIG_DIR, "config.json");
|
|
10
11
|
const SETTINGS_STATE_PATH = path.join(CONFIG_DIR, "settings-state.json");
|
|
@@ -37,6 +38,7 @@ const DEFAULT_CONFIG = Object.freeze({
|
|
|
37
38
|
showControls: true,
|
|
38
39
|
tickRateMs: 100,
|
|
39
40
|
completionMessage: "Time is up!",
|
|
41
|
+
notifyOnComplete: true,
|
|
40
42
|
keybindings: { ...DEFAULT_KEYBINDINGS }
|
|
41
43
|
});
|
|
42
44
|
|
|
@@ -200,6 +202,7 @@ function normalizeConfig(raw) {
|
|
|
200
202
|
showControls: DEFAULT_CONFIG.showControls,
|
|
201
203
|
tickRateMs: DEFAULT_CONFIG.tickRateMs,
|
|
202
204
|
completionMessage: DEFAULT_CONFIG.completionMessage,
|
|
205
|
+
notifyOnComplete: DEFAULT_CONFIG.notifyOnComplete,
|
|
203
206
|
keybindings: { ...DEFAULT_KEYBINDINGS }
|
|
204
207
|
};
|
|
205
208
|
|
|
@@ -219,6 +222,9 @@ function normalizeConfig(raw) {
|
|
|
219
222
|
if (typeof raw.completionMessage === "string") {
|
|
220
223
|
next.completionMessage = normalizeCompletionMessage(raw.completionMessage);
|
|
221
224
|
}
|
|
225
|
+
if (typeof raw.notifyOnComplete === "boolean") {
|
|
226
|
+
next.notifyOnComplete = raw.notifyOnComplete;
|
|
227
|
+
}
|
|
222
228
|
next.keybindings = normalizeKeybindings(raw.keybindings);
|
|
223
229
|
if (typeof raw.font === "string") {
|
|
224
230
|
const normalizedFont = normalizeFontName(raw.font);
|
|
@@ -452,9 +458,135 @@ function drawFrame({ mode, seconds, paused, config, done }) {
|
|
|
452
458
|
}
|
|
453
459
|
}
|
|
454
460
|
|
|
461
|
+
function escapeAppleScriptString(value) {
|
|
462
|
+
return String(value).replace(/\\/g, "\\\\").replace(/\"/g, "\\\"");
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
function escapePowerShellSingleQuotedString(value) {
|
|
466
|
+
return String(value).replace(/'/g, "''");
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
function spawnOk(command, args, options) {
|
|
470
|
+
try {
|
|
471
|
+
const result = spawnSync(command, args, { stdio: "ignore", ...options });
|
|
472
|
+
return !result.error && result.status === 0;
|
|
473
|
+
} catch (_error) {
|
|
474
|
+
return false;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
function sendSystemNotification({ title, message }) {
|
|
479
|
+
const safeTitle = String(title || "").trim() || "Timer";
|
|
480
|
+
const safeMessage = String(message || "").trim();
|
|
481
|
+
|
|
482
|
+
if (!safeMessage) {
|
|
483
|
+
return false;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
try {
|
|
487
|
+
if (process.platform === "darwin") {
|
|
488
|
+
const script = `display notification "${escapeAppleScriptString(safeMessage)}" with title "${escapeAppleScriptString(safeTitle)}"`;
|
|
489
|
+
if (spawnOk("osascript", ["-e", script])) {
|
|
490
|
+
return true;
|
|
491
|
+
}
|
|
492
|
+
if (spawnOk("terminal-notifier", ["-title", safeTitle, "-message", safeMessage])) {
|
|
493
|
+
return true;
|
|
494
|
+
}
|
|
495
|
+
return false;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
if (process.platform === "win32") {
|
|
499
|
+
const titlePs = escapePowerShellSingleQuotedString(safeTitle);
|
|
500
|
+
const messagePs = escapePowerShellSingleQuotedString(safeMessage);
|
|
501
|
+
|
|
502
|
+
const ps = [
|
|
503
|
+
"$ErrorActionPreference = 'Stop'",
|
|
504
|
+
"try {",
|
|
505
|
+
" [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] > $null",
|
|
506
|
+
" $template = [Windows.UI.Notifications.ToastTemplateType]::ToastText02",
|
|
507
|
+
" $xml = [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent($template)",
|
|
508
|
+
" $txt = $xml.GetElementsByTagName('text')",
|
|
509
|
+
` $txt.Item(0).AppendChild($xml.CreateTextNode('${titlePs}')) > $null`,
|
|
510
|
+
` $txt.Item(1).AppendChild($xml.CreateTextNode('${messagePs}')) > $null`,
|
|
511
|
+
" $toast = [Windows.UI.Notifications.ToastNotification]::new($xml)",
|
|
512
|
+
" $notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier('cli-timer')",
|
|
513
|
+
" $notifier.Show($toast)",
|
|
514
|
+
"} catch { exit 1 }"
|
|
515
|
+
].join("; ");
|
|
516
|
+
|
|
517
|
+
const powershellArgs = ["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Sta", "-Command", ps];
|
|
518
|
+
if (spawnOk("powershell", powershellArgs, { windowsHide: true })) {
|
|
519
|
+
return true;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
const balloon = [
|
|
523
|
+
"$ErrorActionPreference = 'Stop'",
|
|
524
|
+
"try {",
|
|
525
|
+
" Add-Type -AssemblyName System.Windows.Forms",
|
|
526
|
+
" Add-Type -AssemblyName System.Drawing",
|
|
527
|
+
" $notify = New-Object System.Windows.Forms.NotifyIcon",
|
|
528
|
+
" $notify.Icon = [System.Drawing.SystemIcons]::Information",
|
|
529
|
+
` $notify.BalloonTipTitle = '${titlePs}'`,
|
|
530
|
+
` $notify.BalloonTipText = '${messagePs}'`,
|
|
531
|
+
" $notify.Visible = $true",
|
|
532
|
+
" $notify.ShowBalloonTip(5000)",
|
|
533
|
+
" Start-Sleep -Milliseconds 5500",
|
|
534
|
+
" $notify.Dispose()",
|
|
535
|
+
"} catch { exit 1 }"
|
|
536
|
+
].join("; ");
|
|
537
|
+
|
|
538
|
+
const balloonArgs = [
|
|
539
|
+
"-NoProfile",
|
|
540
|
+
"-NonInteractive",
|
|
541
|
+
"-ExecutionPolicy",
|
|
542
|
+
"Bypass",
|
|
543
|
+
"-Sta",
|
|
544
|
+
"-Command",
|
|
545
|
+
balloon
|
|
546
|
+
];
|
|
547
|
+
return spawnOk("powershell", balloonArgs, { windowsHide: true });
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
if (process.platform === "linux") {
|
|
551
|
+
if (spawnOk("termux-notification", ["--title", safeTitle, "--content", safeMessage])) {
|
|
552
|
+
return true;
|
|
553
|
+
}
|
|
554
|
+
if (spawnOk("notify-send", [safeTitle, safeMessage])) {
|
|
555
|
+
return true;
|
|
556
|
+
}
|
|
557
|
+
if (spawnOk("kdialog", ["--title", safeTitle, "--passivepopup", safeMessage, "5"])) {
|
|
558
|
+
return true;
|
|
559
|
+
}
|
|
560
|
+
if (spawnOk("zenity", ["--notification", `--text=${safeTitle}: ${safeMessage}`])) {
|
|
561
|
+
return true;
|
|
562
|
+
}
|
|
563
|
+
return false;
|
|
564
|
+
}
|
|
565
|
+
} catch (_error) {
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
return false;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
function notifyTimerFinished(config, initialSeconds) {
|
|
572
|
+
if (!config || !config.notifyOnComplete) {
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
const message = config.completionMessage || "Time is up!";
|
|
576
|
+
const title = initialSeconds ? `Timer finished (${formatHms(initialSeconds)})` : "Timer finished";
|
|
577
|
+
const notified = sendSystemNotification({ title, message });
|
|
578
|
+
if (!notified) {
|
|
579
|
+
try {
|
|
580
|
+
process.stderr.write("\x07");
|
|
581
|
+
} catch (_error) {
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
455
586
|
function runNonInteractiveTimer(initialSeconds, tickRateMs) {
|
|
456
587
|
const startedAt = Date.now();
|
|
457
588
|
let lastSecond = null;
|
|
589
|
+
let notified = false;
|
|
458
590
|
|
|
459
591
|
function printRemaining() {
|
|
460
592
|
const elapsed = Math.floor((Date.now() - startedAt) / 1000);
|
|
@@ -475,6 +607,10 @@ function runNonInteractiveTimer(initialSeconds, tickRateMs) {
|
|
|
475
607
|
const remaining = printRemaining();
|
|
476
608
|
if (remaining <= 0) {
|
|
477
609
|
clearInterval(interval);
|
|
610
|
+
if (!notified) {
|
|
611
|
+
notified = true;
|
|
612
|
+
notifyTimerFinished(readConfig(), initialSeconds);
|
|
613
|
+
}
|
|
478
614
|
}
|
|
479
615
|
}, tickRateMs);
|
|
480
616
|
}
|
|
@@ -495,6 +631,7 @@ function runClock({ mode, initialSeconds, config }) {
|
|
|
495
631
|
|
|
496
632
|
let paused = false;
|
|
497
633
|
let done = false;
|
|
634
|
+
let didNotifyCompletion = false;
|
|
498
635
|
const baseSeconds = initialSeconds;
|
|
499
636
|
let anchorMs = Date.now();
|
|
500
637
|
let elapsedWhilePaused = 0;
|
|
@@ -518,9 +655,13 @@ function runClock({ mode, initialSeconds, config }) {
|
|
|
518
655
|
}
|
|
519
656
|
|
|
520
657
|
function refreshDoneState(displaySeconds) {
|
|
521
|
-
if (isTimer && displaySeconds <= 0) {
|
|
658
|
+
if (isTimer && displaySeconds <= 0 && !done) {
|
|
522
659
|
done = true;
|
|
523
660
|
paused = true;
|
|
661
|
+
if (!didNotifyCompletion) {
|
|
662
|
+
didNotifyCompletion = true;
|
|
663
|
+
notifyTimerFinished(config, baseSeconds);
|
|
664
|
+
}
|
|
524
665
|
}
|
|
525
666
|
}
|
|
526
667
|
|
|
@@ -544,6 +685,7 @@ function runClock({ mode, initialSeconds, config }) {
|
|
|
544
685
|
function restart() {
|
|
545
686
|
paused = false;
|
|
546
687
|
done = false;
|
|
688
|
+
didNotifyCompletion = false;
|
|
547
689
|
elapsedWhilePaused = 0;
|
|
548
690
|
anchorMs = Date.now();
|
|
549
691
|
lastDrawState = "";
|
|
@@ -645,11 +787,52 @@ function runSettingsUI() {
|
|
|
645
787
|
|
|
646
788
|
ensureConfigDir();
|
|
647
789
|
|
|
648
|
-
const
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
790
|
+
const platformMap = {
|
|
791
|
+
linux: "linux",
|
|
792
|
+
darwin: "darwin",
|
|
793
|
+
win32: "windows"
|
|
794
|
+
};
|
|
795
|
+
const archMap = {
|
|
796
|
+
x64: "x64",
|
|
797
|
+
arm64: "arm64"
|
|
798
|
+
};
|
|
799
|
+
|
|
800
|
+
function getSettingsBinaryTarget() {
|
|
801
|
+
const platform = platformMap[process.platform];
|
|
802
|
+
const arch = archMap[process.arch];
|
|
803
|
+
if (!platform || !arch) {
|
|
804
|
+
return null;
|
|
805
|
+
}
|
|
806
|
+
return `${platform}-${arch}`;
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
function getPrebuiltSettingsBinaryPath() {
|
|
810
|
+
const target = getSettingsBinaryTarget();
|
|
811
|
+
if (!target) {
|
|
812
|
+
return null;
|
|
813
|
+
}
|
|
814
|
+
const binaryName = process.platform === "win32" ? "cli-timer-settings-ui.exe" : "cli-timer-settings-ui";
|
|
815
|
+
const fullPath = path.join(PREBUILT_SETTINGS_UI_DIR, target, binaryName);
|
|
816
|
+
if (!fs.existsSync(fullPath)) {
|
|
817
|
+
return null;
|
|
818
|
+
}
|
|
819
|
+
return fullPath;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
function hasGoToolchain() {
|
|
823
|
+
const goVersion = spawnSync("go", ["version"], { stdio: "ignore" });
|
|
824
|
+
return !(goVersion.error || goVersion.status !== 0);
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
function runPrebuiltSettingsUI(binaryPath) {
|
|
828
|
+
return spawnSync(binaryPath, ["--state", SETTINGS_STATE_PATH], { stdio: "inherit" });
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
function runGoSettingsUI() {
|
|
832
|
+
return spawnSync("go", ["run", ".", "--state", SETTINGS_STATE_PATH], {
|
|
833
|
+
cwd: path.join(PROJECT_ROOT, "settings-ui"),
|
|
834
|
+
stdio: "inherit"
|
|
835
|
+
});
|
|
653
836
|
}
|
|
654
837
|
|
|
655
838
|
const state = {
|
|
@@ -660,16 +843,39 @@ function runSettingsUI() {
|
|
|
660
843
|
|
|
661
844
|
fs.writeFileSync(SETTINGS_STATE_PATH, JSON.stringify(state), "utf8");
|
|
662
845
|
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
846
|
+
let result;
|
|
847
|
+
const prebuiltPath = getPrebuiltSettingsBinaryPath();
|
|
848
|
+
const canRunGo = hasGoToolchain();
|
|
849
|
+
|
|
850
|
+
if (prebuiltPath) {
|
|
851
|
+
result = runPrebuiltSettingsUI(prebuiltPath);
|
|
852
|
+
if (result.error && canRunGo) {
|
|
853
|
+
result = runGoSettingsUI();
|
|
854
|
+
}
|
|
855
|
+
} else if (canRunGo) {
|
|
856
|
+
result = runGoSettingsUI();
|
|
857
|
+
} else {
|
|
858
|
+
const target = getSettingsBinaryTarget();
|
|
859
|
+
if (target) {
|
|
860
|
+
process.stderr.write(`No prebuilt settings UI binary for ${target}, and Go is not installed.\n`);
|
|
861
|
+
} else {
|
|
862
|
+
process.stderr.write(
|
|
863
|
+
`No prebuilt settings UI binary for ${process.platform}/${process.arch}, and Go is not installed.\n`
|
|
864
|
+
);
|
|
865
|
+
}
|
|
866
|
+
process.stderr.write("Install Go or use a supported platform for `timer settings`.\n");
|
|
867
|
+
process.exitCode = 1;
|
|
868
|
+
}
|
|
667
869
|
|
|
668
870
|
try {
|
|
669
871
|
fs.unlinkSync(SETTINGS_STATE_PATH);
|
|
670
872
|
} catch (_error) {
|
|
671
873
|
}
|
|
672
874
|
|
|
875
|
+
if (!result) {
|
|
876
|
+
return;
|
|
877
|
+
}
|
|
878
|
+
|
|
673
879
|
if (result.error) {
|
|
674
880
|
process.stderr.write(`Failed to run settings UI: ${result.error.message}\n`);
|
|
675
881
|
process.exitCode = 1;
|