herdr-remote 0.2.2 → 0.2.4
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/README.md +16 -121
- package/README.zh-CN.md +50 -0
- package/bin/herdr-remote.js +14 -15
- package/dist/tui.mjs +327 -199
- package/herdr-plugin.toml +7 -7
- package/package.json +4 -3
- package/src/i18n/en.js +76 -72
- package/src/i18n/zh.js +77 -73
- package/src/settings-model.js +44 -1
- package/src/updater.js +127 -23
package/dist/tui.mjs
CHANGED
|
@@ -360,7 +360,7 @@ var require_en = __commonJS({
|
|
|
360
360
|
"use strict";
|
|
361
361
|
module.exports = {
|
|
362
362
|
"app.name": "Herdr Remote",
|
|
363
|
-
"app.tagline": "Remote browser access to
|
|
363
|
+
"app.tagline": "Remote browser access to Herdr workspaces",
|
|
364
364
|
"common.yes": "Yes",
|
|
365
365
|
"common.no": "No",
|
|
366
366
|
"common.on": "on",
|
|
@@ -393,12 +393,12 @@ var require_en = __commonJS({
|
|
|
393
393
|
"nav.about": "Language & about",
|
|
394
394
|
"mode.local": "This machine only",
|
|
395
395
|
"mode.lan": "Local network / Tailscale",
|
|
396
|
-
"mode.official": "Official relay
|
|
396
|
+
"mode.official": "Official relay",
|
|
397
397
|
"mode.remote": "Self-hosted relay",
|
|
398
|
-
"mode.local.description": "
|
|
399
|
-
"mode.lan.description": "
|
|
400
|
-
"mode.official.description": "
|
|
401
|
-
"mode.remote.description": "
|
|
398
|
+
"mode.local.description": "Relay listens on 127.0.0.1. Local browser only.",
|
|
399
|
+
"mode.lan.description": "Relay listens on 0.0.0.0. Accessible over LAN or Tailscale.",
|
|
400
|
+
"mode.official.description": "Connect via official relay. No server needed.",
|
|
401
|
+
"mode.remote.description": "Connect via self-hosted relay for external access.",
|
|
402
402
|
"overview.title": "Status",
|
|
403
403
|
"overview.mode": "Access mode",
|
|
404
404
|
"overview.relay": "Relay",
|
|
@@ -413,20 +413,20 @@ var require_en = __commonJS({
|
|
|
413
413
|
"overview.relayRemote": "remote, {url}",
|
|
414
414
|
"overview.socketMissing": "not found \u2014 is Herdr running?",
|
|
415
415
|
"overview.unreachable": "unreachable: {message}",
|
|
416
|
-
"overview.notStarted": "Services
|
|
416
|
+
"overview.notStarted": "Services not running. Open Services tab to start.",
|
|
417
417
|
"pair.title": "Pair a device",
|
|
418
|
-
"pair.generate": "Generate
|
|
419
|
-
"pair.regenerate": "
|
|
420
|
-
"pair.working": "
|
|
418
|
+
"pair.generate": "Generate pairing code",
|
|
419
|
+
"pair.regenerate": "Regenerate code",
|
|
420
|
+
"pair.working": "Generating pairing code\u2026",
|
|
421
421
|
"pair.code": "Pairing code",
|
|
422
|
-
"pair.url": "
|
|
422
|
+
"pair.url": "Access URL",
|
|
423
423
|
"pair.expires": "Expires in {minutes} (at {time})",
|
|
424
|
-
"pair.expired": "
|
|
425
|
-
"pair.instructions": "Open
|
|
426
|
-
"pair.qrHint": "Scan
|
|
427
|
-
"pair.qrUnavailable": "
|
|
428
|
-
"pair.failed": "Could not create
|
|
429
|
-
"pair.hostOffline": "
|
|
424
|
+
"pair.expired": "Code expired. Generate a new one.",
|
|
425
|
+
"pair.instructions": "Open URL and enter code to pair.",
|
|
426
|
+
"pair.qrHint": "Scan QR code to open URL.",
|
|
427
|
+
"pair.qrUnavailable": "Terminal too narrow for QR code; use URL above.",
|
|
428
|
+
"pair.failed": "Could not create pairing code: {message}",
|
|
429
|
+
"pair.hostOffline": "Relay has no workstation connected. Start services first.",
|
|
430
430
|
"services.title": "Services",
|
|
431
431
|
"services.start": "Start services",
|
|
432
432
|
"services.stop": "Stop services",
|
|
@@ -436,71 +436,74 @@ var require_en = __commonJS({
|
|
|
436
436
|
"services.restarted": "Services restarted.",
|
|
437
437
|
"services.startFailed": "Could not start services: {message}",
|
|
438
438
|
"services.stopFailed": "Could not stop services: {message}",
|
|
439
|
-
"services.unsavedBlocked": "
|
|
440
|
-
"services.managedNotice": "
|
|
441
|
-
"services.logs": "Recent
|
|
442
|
-
"services.logEmpty": "No
|
|
439
|
+
"services.unsavedBlocked": "Unsaved changes. Save before restarting.",
|
|
440
|
+
"services.managedNotice": "Managed by {manager}; applied via keep-alive service.",
|
|
441
|
+
"services.logs": "Recent logs",
|
|
442
|
+
"services.logEmpty": "No logs.",
|
|
443
443
|
"services.logRelay": "Relay",
|
|
444
444
|
"services.logHost": "Host connector",
|
|
445
445
|
"relay.title": "Relay settings",
|
|
446
446
|
"relay.settings": "Settings",
|
|
447
|
+
"relay.locked": "fixed",
|
|
448
|
+
"relay.officialFixed": "The official relay address is fixed and cannot be edited.",
|
|
449
|
+
"relay.officialHint": "Official relay: address is fixed and no password is needed.",
|
|
447
450
|
"relay.password": "Relay password",
|
|
448
|
-
"relay.passwordHint": "Must match RELAY_PASSWORD on
|
|
451
|
+
"relay.passwordHint": "Must match RELAY_PASSWORD on relay. Leave empty if public.",
|
|
449
452
|
"relay.passwordSet": "set",
|
|
450
|
-
"relay.passwordEmpty": "not set (public
|
|
451
|
-
"relay.passwordSaved": "Relay password saved. Restart
|
|
452
|
-
"relay.showPassword": "Show
|
|
453
|
-
"relay.hidePassword": "Hide
|
|
454
|
-
"relay.identity": "Workstation
|
|
455
|
-
"relay.regenerate": "Generate
|
|
456
|
-
"relay.regenerated": "New workstation identity generated. Restart
|
|
457
|
-
"relay.envSnippet": "
|
|
458
|
-
"relay.envHint": "Run this on the relay host.",
|
|
459
|
-
"relay.test": "Test
|
|
453
|
+
"relay.passwordEmpty": "not set (public)",
|
|
454
|
+
"relay.passwordSaved": "Relay password saved. Restart services to apply.",
|
|
455
|
+
"relay.showPassword": "Show password",
|
|
456
|
+
"relay.hidePassword": "Hide password",
|
|
457
|
+
"relay.identity": "Workstation ID",
|
|
458
|
+
"relay.regenerate": "Generate new ID",
|
|
459
|
+
"relay.regenerated": "New workstation identity generated. Restart services to re-register.",
|
|
460
|
+
"relay.envSnippet": "Relay startup command",
|
|
461
|
+
"relay.envHint": "Run this command on the relay host.",
|
|
462
|
+
"relay.test": "Test relay connection",
|
|
460
463
|
"relay.testOk": "Relay reachable: version {version}, {hosts} workstation(s) connected.",
|
|
461
464
|
"relay.testFailed": "Relay unreachable: {message}",
|
|
462
|
-
"relay.selectAddress": "Choose
|
|
465
|
+
"relay.selectAddress": "Choose advertised address",
|
|
463
466
|
"relay.listenAddress": "Listen address",
|
|
464
|
-
"relay.listenAddressHint": "
|
|
467
|
+
"relay.listenAddressHint": "Server bind address. Browsers use advertised address below.",
|
|
465
468
|
"relay.addressTailscale": "Tailscale",
|
|
466
469
|
"relay.addressLan": "LAN",
|
|
467
470
|
"relay.addressVirtual": "virtual",
|
|
468
471
|
"relay.addressLoopback": "loopback",
|
|
469
|
-
"relay.noAddresses": "No non-loopback addresses found.
|
|
470
|
-
"relay.docsHint": "
|
|
472
|
+
"relay.noAddresses": "No non-loopback addresses found.",
|
|
473
|
+
"relay.docsHint": "Self-hosting guide: docs/self-hosted-relay.md",
|
|
471
474
|
"keepalive.title": "Keep-alive service",
|
|
472
475
|
"keepalive.manager": "Manager",
|
|
473
476
|
"keepalive.state": "State",
|
|
474
477
|
"keepalive.install": "Install and start",
|
|
475
478
|
"keepalive.uninstall": "Stop and remove",
|
|
476
|
-
"keepalive.restart": "Restart
|
|
479
|
+
"keepalive.restart": "Restart service",
|
|
477
480
|
"keepalive.installed": "Keep-alive installed with {manager}.",
|
|
478
481
|
"keepalive.uninstalled": "Keep-alive removed.",
|
|
479
482
|
"keepalive.restarted": "Keep-alive service restarted.",
|
|
480
483
|
"keepalive.failed": "Keep-alive operation failed: {message}",
|
|
481
484
|
"keepalive.unitPath": "Unit file",
|
|
482
|
-
"keepalive.logsHint": "
|
|
483
|
-
"keepalive.linger": "Start at boot
|
|
484
|
-
"keepalive.lingerEnabled": "
|
|
485
|
-
"keepalive.lingerDisabled": "
|
|
485
|
+
"keepalive.logsHint": "View logs: {command}",
|
|
486
|
+
"keepalive.linger": "Start at boot",
|
|
487
|
+
"keepalive.lingerEnabled": "Start at boot enabled.",
|
|
488
|
+
"keepalive.lingerDisabled": "Start at boot disabled (runs while logged in).",
|
|
486
489
|
"keepalive.enableLinger": "Enable start at boot",
|
|
487
|
-
"keepalive.lingerDone": "
|
|
488
|
-
"keepalive.fallbackNote": "No system service manager
|
|
490
|
+
"keepalive.lingerDone": "Start at boot enabled for {username}.",
|
|
491
|
+
"keepalive.fallbackNote": "No system service manager found; background process will not survive reboot.",
|
|
489
492
|
"herdr.title": "Herdr integration",
|
|
490
493
|
"herdr.socketPath": "Socket path",
|
|
491
494
|
"herdr.args": "Extra arguments",
|
|
492
495
|
"herdr.plugin": "Plugin registration",
|
|
493
496
|
"herdr.pluginRegistered": "Registered with Herdr.",
|
|
494
497
|
"herdr.pluginMissing": "Not registered with Herdr.",
|
|
495
|
-
"herdr.register": "Register
|
|
496
|
-
"herdr.unregister": "Unregister
|
|
498
|
+
"herdr.register": "Register as Herdr plugin",
|
|
499
|
+
"herdr.unregister": "Unregister plugin",
|
|
497
500
|
"herdr.registerDone": "Registered: {path}",
|
|
498
501
|
"herdr.unregisterDone": "Plugin unregistered.",
|
|
499
502
|
"herdr.registerFailed": "Registration failed: {message}",
|
|
500
|
-
"herdr.cliMissing": "
|
|
503
|
+
"herdr.cliMissing": "Command herdr not found in PATH.",
|
|
501
504
|
"about.title": "Language & about",
|
|
502
505
|
"about.language": "Interface language",
|
|
503
|
-
"about.languageAuto": "Follow
|
|
506
|
+
"about.languageAuto": "Follow system ({detected})",
|
|
504
507
|
"about.languageZh": "\u4E2D\u6587",
|
|
505
508
|
"about.languageEn": "English",
|
|
506
509
|
"about.version": "Version",
|
|
@@ -510,20 +513,20 @@ var require_en = __commonJS({
|
|
|
510
513
|
"about.docs": "Self-hosting guide: docs/self-hosted-relay.md",
|
|
511
514
|
"wizard.title": "First-time setup",
|
|
512
515
|
"wizard.step": "Step {current} of {total}",
|
|
513
|
-
"wizard.languageTitle": "Choose
|
|
514
|
-
"wizard.accessTitle": "
|
|
515
|
-
"wizard.accessHint": "
|
|
516
|
-
"wizard.addressTitle": "
|
|
517
|
-
"wizard.relayTitle": "
|
|
516
|
+
"wizard.languageTitle": "Choose language",
|
|
517
|
+
"wizard.accessTitle": "Access mode",
|
|
518
|
+
"wizard.accessHint": "Can be changed later in Relay settings.",
|
|
519
|
+
"wizard.addressTitle": "Browser access address",
|
|
520
|
+
"wizard.relayTitle": "Relay server",
|
|
518
521
|
"wizard.relayUrlLabel": "Relay URL (wss://\u2026)",
|
|
519
|
-
"wizard.relayHint": "
|
|
522
|
+
"wizard.relayHint": "Relay must be running. See docs/self-hosted-relay.md.",
|
|
520
523
|
"wizard.passwordTitle": "Relay password",
|
|
521
|
-
"wizard.passwordHint": "
|
|
522
|
-
"wizard.finishTitle": "
|
|
524
|
+
"wizard.passwordHint": "RELAY_PASSWORD of the relay. Leave empty if unset.",
|
|
525
|
+
"wizard.finishTitle": "Finish",
|
|
523
526
|
"wizard.finishHint": "Configuration will be saved to {path}.",
|
|
524
|
-
"wizard.startNow": "Start
|
|
525
|
-
"wizard.installKeepalive": "
|
|
526
|
-
"wizard.finish": "Save and
|
|
527
|
+
"wizard.startNow": "Start services now",
|
|
528
|
+
"wizard.installKeepalive": "Run in background",
|
|
529
|
+
"wizard.finish": "Save and finish",
|
|
527
530
|
"field.mode": "Access mode",
|
|
528
531
|
"field.port": "Relay port",
|
|
529
532
|
"field.lanHost": "Browser address",
|
|
@@ -536,15 +539,15 @@ var require_en = __commonJS({
|
|
|
536
539
|
"placeholder.autoDiscovered": "auto-discovered",
|
|
537
540
|
"placeholder.none": "none",
|
|
538
541
|
"error.invalidMode": "Unknown access mode.",
|
|
539
|
-
"error.invalidPort": "
|
|
540
|
-
"error.invalidLanHost": "
|
|
541
|
-
"error.invalidRelayUrl": "
|
|
542
|
-
"error.invalidPublicUrl": "
|
|
542
|
+
"error.invalidPort": "Port must be a number between 1 and 65535.",
|
|
543
|
+
"error.invalidLanHost": "Browser address must be a reachable LAN or Tailscale address, not loopback or 0.0.0.0.",
|
|
544
|
+
"error.invalidRelayUrl": "Relay URL must start with wss://, ws://, https:// or http://.",
|
|
545
|
+
"error.invalidPublicUrl": "Browser URL must start with https:// or http:// and cannot use 0.0.0.0 or ::.",
|
|
543
546
|
"error.invalidLanguage": "Unknown language.",
|
|
544
547
|
"error.invalidKeepalive": "Unknown keep-alive manager.",
|
|
545
548
|
"error.unknownField": "Unknown setting.",
|
|
546
|
-
"error.remoteUrlRequired": "
|
|
547
|
-
"error.saveFailed": "Could not save
|
|
549
|
+
"error.remoteUrlRequired": "Relay URL is required for self-hosted relay mode.",
|
|
550
|
+
"error.saveFailed": "Could not save configuration: {message}",
|
|
548
551
|
"hint.navigate": "\u2191\u2193 move",
|
|
549
552
|
"hint.select": "\u21B5 select",
|
|
550
553
|
"hint.edit": "\u21B5 edit",
|
|
@@ -554,22 +557,23 @@ var require_en = __commonJS({
|
|
|
554
557
|
"hint.mouseOn": "m mouse off",
|
|
555
558
|
"hint.mouseOff": "m mouse on",
|
|
556
559
|
"hint.mouseUnsupported": "mouse unsupported",
|
|
557
|
-
"hint.restartRequired": "Restart
|
|
558
|
-
"hint.unsavedChanges": "Unsaved changes
|
|
560
|
+
"hint.restartRequired": "Restart services to apply changes.",
|
|
561
|
+
"hint.unsavedChanges": "Unsaved changes (press s to save).",
|
|
559
562
|
"hint.save": "s save",
|
|
560
563
|
"hint.editing": "\u21B5 confirm \xB7 esc cancel",
|
|
561
564
|
"update.title": "Updates",
|
|
562
565
|
"update.check": "Check for updates",
|
|
563
566
|
"update.checking": "Checking npm\u2026",
|
|
564
567
|
"update.upToDate": "Up to date ({version})",
|
|
565
|
-
"update.available": "Update
|
|
568
|
+
"update.available": "Update {version} available (press Enter to install)",
|
|
566
569
|
"update.updating": "Installing {version}\u2026",
|
|
567
570
|
"update.done": "Updated to {version}",
|
|
568
|
-
"update.restartHint": "Update installed. Restart herdr-remote to
|
|
569
|
-
"update.errorNetwork": "Could not reach
|
|
570
|
-
"update.
|
|
571
|
-
"update.
|
|
572
|
-
"update.cannot.
|
|
571
|
+
"update.restartHint": "Update installed. Restart herdr-remote to apply.",
|
|
572
|
+
"update.errorNetwork": "Could not reach any npm registry",
|
|
573
|
+
"update.errorNetworkDetail": "No registry answered: {message}",
|
|
574
|
+
"update.errorFailed": "Update failed. Run: npm install -g herdr-remote@latest",
|
|
575
|
+
"update.cannot.source": "Source checkout \u2014 update with git",
|
|
576
|
+
"update.cannot.linked": "Linked package \u2014 managed by npm link"
|
|
573
577
|
};
|
|
574
578
|
}
|
|
575
579
|
});
|
|
@@ -580,7 +584,7 @@ var require_zh = __commonJS({
|
|
|
580
584
|
"use strict";
|
|
581
585
|
module.exports = {
|
|
582
586
|
"app.name": "Herdr Remote",
|
|
583
|
-
"app.tagline": "\u5728\u6D4F\u89C8\u5668\
|
|
587
|
+
"app.tagline": "\u5728\u6D4F\u89C8\u5668\u4E2D\u4F7F\u7528 Herdr \u5DE5\u4F5C\u533A",
|
|
584
588
|
"common.yes": "\u662F",
|
|
585
589
|
"common.no": "\u5426",
|
|
586
590
|
"common.on": "\u5F00",
|
|
@@ -598,11 +602,11 @@ var require_zh = __commonJS({
|
|
|
598
602
|
"common.disabled": "\u5DF2\u505C\u7528",
|
|
599
603
|
"common.loading": "\u5904\u7406\u4E2D\u2026",
|
|
600
604
|
"common.save": "\u4FDD\u5B58\u8BBE\u7F6E",
|
|
601
|
-
"common.saved": "\u914D\u7F6E\u5DF2\u4FDD\u5B58\
|
|
605
|
+
"common.saved": "\u914D\u7F6E\u5DF2\u4FDD\u5B58\u81F3 {path}",
|
|
602
606
|
"common.back": "\u8FD4\u56DE",
|
|
603
607
|
"common.cancel": "\u53D6\u6D88",
|
|
604
608
|
"common.confirm": "\u786E\u8BA4",
|
|
605
|
-
"common.pid": "
|
|
609
|
+
"common.pid": "PID {pid}",
|
|
606
610
|
"common.notApplicable": "\u4E0D\u9002\u7528",
|
|
607
611
|
"nav.overview": "\u6982\u89C8",
|
|
608
612
|
"nav.pair": "\u914D\u5BF9\u8BBE\u5907",
|
|
@@ -613,12 +617,12 @@ var require_zh = __commonJS({
|
|
|
613
617
|
"nav.about": "\u8BED\u8A00\u4E0E\u5173\u4E8E",
|
|
614
618
|
"mode.local": "\u4EC5\u672C\u673A",
|
|
615
619
|
"mode.lan": "\u5C40\u57DF\u7F51 / Tailscale",
|
|
616
|
-
"mode.official": "\u5B98\u65B9
|
|
617
|
-
"mode.remote": "\u81EA\u5EFA
|
|
618
|
-
"mode.local.description": "
|
|
619
|
-
"mode.lan.description": "
|
|
620
|
-
"mode.official.description": "\
|
|
621
|
-
"mode.remote.description": "\
|
|
620
|
+
"mode.official": "\u5B98\u65B9 Relay",
|
|
621
|
+
"mode.remote": "\u81EA\u5EFA Relay",
|
|
622
|
+
"mode.local.description": "\u76D1\u542C 127.0.0.1\uFF0C\u4EC5\u672C\u673A\u53EF\u8BBF\u95EE\u3002",
|
|
623
|
+
"mode.lan.description": "\u76D1\u542C 0.0.0.0\uFF0C\u5C40\u57DF\u7F51\u4E0E Tailscale \u8BBE\u5907\u53EF\u8BBF\u95EE\u3002",
|
|
624
|
+
"mode.official.description": "\u4F7F\u7528\u5B98\u65B9 Relay \u8DE8\u7F51\u8BBF\u95EE\uFF0C\u65E0\u9700\u81EA\u5EFA\u670D\u52A1\u5668\u3002",
|
|
625
|
+
"mode.remote.description": "\u8FDE\u63A5\u81EA\u5EFA Relay \u8DE8\u7F51\u8BBF\u95EE\u3002",
|
|
622
626
|
"overview.title": "\u72B6\u6001",
|
|
623
627
|
"overview.mode": "\u8BBF\u95EE\u65B9\u5F0F",
|
|
624
628
|
"overview.relay": "Relay",
|
|
@@ -628,25 +632,25 @@ var require_zh = __commonJS({
|
|
|
628
632
|
"overview.keepalive": "\u4FDD\u6D3B\u670D\u52A1",
|
|
629
633
|
"overview.devices": "\u6D4F\u89C8\u5668",
|
|
630
634
|
"overview.hosts": "\u5DE5\u4F5C\u7AD9",
|
|
631
|
-
"overview.uptime": "Relay \u8FD0\u884C\u65F6\
|
|
635
|
+
"overview.uptime": "Relay \u8FD0\u884C\u65F6\u95F4",
|
|
632
636
|
"overview.relayLocal": "\u672C\u5730\uFF0C{bind}:{port}",
|
|
633
637
|
"overview.relayRemote": "\u8FDC\u7A0B\uFF0C{url}",
|
|
634
|
-
"overview.socketMissing": "\u672A\u627E\u5230
|
|
638
|
+
"overview.socketMissing": "\u672A\u627E\u5230\uFF0C\u8BF7\u786E\u8BA4 Herdr \u662F\u5426\u8FD0\u884C",
|
|
635
639
|
"overview.unreachable": "\u65E0\u6CD5\u8BBF\u95EE\uFF1A{message}",
|
|
636
|
-
"overview.notStarted": "\u670D\u52A1\u672A\u8FD0\u884C\uFF0C\
|
|
640
|
+
"overview.notStarted": "\u670D\u52A1\u672A\u8FD0\u884C\uFF0C\u53EF\u524D\u5F80\u300C\u670D\u52A1\u300D\u542F\u52A8\u3002",
|
|
637
641
|
"pair.title": "\u914D\u5BF9\u8BBE\u5907",
|
|
638
|
-
"pair.generate": "\u751F\u6210\
|
|
639
|
-
"pair.regenerate": "\u91CD\u65B0\u751F\u6210
|
|
640
|
-
"pair.working": "\
|
|
642
|
+
"pair.generate": "\u751F\u6210\u914D\u5BF9\u7801",
|
|
643
|
+
"pair.regenerate": "\u91CD\u65B0\u751F\u6210",
|
|
644
|
+
"pair.working": "\u751F\u6210\u914D\u5BF9\u7801\u4E2D\u2026",
|
|
641
645
|
"pair.code": "\u914D\u5BF9\u7801",
|
|
642
|
-
"pair.url": "\
|
|
646
|
+
"pair.url": "\u8BBF\u95EE\u5730\u5740",
|
|
643
647
|
"pair.expires": "\u5269\u4F59 {minutes}\uFF08\u81F3 {time}\uFF09",
|
|
644
|
-
"pair.expired": "\u914D\u5BF9\u7801\u5DF2\u8FC7\u671F\uFF0C\
|
|
645
|
-
"pair.instructions": "\u6253\u5F00\u94FE\u63A5\
|
|
646
|
-
"pair.qrHint": "\
|
|
647
|
-
"pair.qrUnavailable": "\u7EC8\u7AEF\u5BBD\u5EA6\u4E0D\u8DB3\
|
|
648
|
+
"pair.expired": "\u914D\u5BF9\u7801\u5DF2\u8FC7\u671F\uFF0C\u9700\u91CD\u65B0\u751F\u6210\u3002",
|
|
649
|
+
"pair.instructions": "\u6253\u5F00\u94FE\u63A5\u5E76\u8F93\u5165\u914D\u5BF9\u7801\u3002",
|
|
650
|
+
"pair.qrHint": "\u626B\u63CF\u4E8C\u7EF4\u7801\u6253\u5F00\u94FE\u63A5\u3002",
|
|
651
|
+
"pair.qrUnavailable": "\u7EC8\u7AEF\u5BBD\u5EA6\u4E0D\u8DB3\uFF0C\u65E0\u6CD5\u663E\u793A\u4E8C\u7EF4\u7801\u3002",
|
|
648
652
|
"pair.failed": "\u751F\u6210\u914D\u5BF9\u7801\u5931\u8D25\uFF1A{message}",
|
|
649
|
-
"pair.hostOffline": "
|
|
653
|
+
"pair.hostOffline": "Relay \u672A\u8FDE\u63A5\u5DE5\u4F5C\u7AD9\uFF0C\u9700\u5148\u542F\u52A8\u670D\u52A1\u3002",
|
|
650
654
|
"services.title": "\u670D\u52A1",
|
|
651
655
|
"services.start": "\u542F\u52A8\u670D\u52A1",
|
|
652
656
|
"services.stop": "\u505C\u6B62\u670D\u52A1",
|
|
@@ -656,38 +660,41 @@ var require_zh = __commonJS({
|
|
|
656
660
|
"services.restarted": "\u670D\u52A1\u5DF2\u91CD\u542F\u3002",
|
|
657
661
|
"services.startFailed": "\u542F\u52A8\u670D\u52A1\u5931\u8D25\uFF1A{message}",
|
|
658
662
|
"services.stopFailed": "\u505C\u6B62\u670D\u52A1\u5931\u8D25\uFF1A{message}",
|
|
659
|
-
"services.unsavedBlocked": "\
|
|
660
|
-
"services.managedNotice": "\
|
|
663
|
+
"services.unsavedBlocked": "\u914D\u7F6E\u672A\u4FDD\u5B58\uFF0C\u8BF7\u5148\u4FDD\u5B58\u518D\u91CD\u542F\u3002",
|
|
664
|
+
"services.managedNotice": "\u7531 {manager} \u6258\u7BA1\uFF0C\u5DF2\u901A\u8FC7\u4FDD\u6D3B\u670D\u52A1\u6267\u884C\u3002",
|
|
661
665
|
"services.logs": "\u6700\u8FD1\u65E5\u5FD7",
|
|
662
|
-
"services.logEmpty": "\u6682\u65E0\u65E5\u5FD7\
|
|
666
|
+
"services.logEmpty": "\u6682\u65E0\u65E5\u5FD7\u3002",
|
|
663
667
|
"services.logRelay": "Relay",
|
|
664
668
|
"services.logHost": "\u4E3B\u673A\u8FDE\u63A5\u5668",
|
|
665
669
|
"relay.title": "Relay \u8BBE\u7F6E",
|
|
666
670
|
"relay.settings": "\u8BBE\u7F6E",
|
|
671
|
+
"relay.locked": "\u56FA\u5B9A",
|
|
672
|
+
"relay.officialFixed": "\u5B98\u65B9 relay \u5730\u5740\u56FA\u5B9A\uFF0C\u4E0D\u53EF\u4FEE\u6539\u3002",
|
|
673
|
+
"relay.officialHint": "\u5B98\u65B9 relay\uFF1A\u5730\u5740\u56FA\u5B9A\uFF0C\u65E0\u9700\u5BC6\u7801\u3002",
|
|
667
674
|
"relay.password": "Relay \u5BC6\u7801",
|
|
668
|
-
"relay.passwordHint": "\
|
|
675
|
+
"relay.passwordHint": "\u987B\u4E0E Relay \u7AEF\u7684 RELAY_PASSWORD \u4E00\u81F4\u3002\u7559\u7A7A\u4E3A\u516C\u7528 Relay\u3002",
|
|
669
676
|
"relay.passwordSet": "\u5DF2\u8BBE\u7F6E",
|
|
670
|
-
"relay.passwordEmpty": "\u672A\u8BBE\u7F6E\uFF08\u516C\u7528
|
|
671
|
-
"relay.passwordSaved": "Relay \u5BC6\u7801\u5DF2\u4FDD\u5B58\uFF0C\u91CD\u542F\u670D\u52A1\
|
|
677
|
+
"relay.passwordEmpty": "\u672A\u8BBE\u7F6E\uFF08\u516C\u7528\uFF09",
|
|
678
|
+
"relay.passwordSaved": "Relay \u5BC6\u7801\u5DF2\u4FDD\u5B58\uFF0C\u91CD\u542F\u670D\u52A1\u751F\u6548\u3002",
|
|
672
679
|
"relay.showPassword": "\u663E\u793A\u5BC6\u7801",
|
|
673
680
|
"relay.hidePassword": "\u9690\u85CF\u5BC6\u7801",
|
|
674
681
|
"relay.identity": "\u5DE5\u4F5C\u7AD9\u6807\u8BC6",
|
|
675
|
-
"relay.regenerate": "\u91CD\u65B0\u751F\u6210\
|
|
676
|
-
"relay.regenerated": "\u5DF2\u751F\u6210\u65B0\
|
|
677
|
-
"relay.envSnippet": "
|
|
678
|
-
"relay.envHint": "\u5728
|
|
679
|
-
"relay.test": "\u6D4B\u8BD5
|
|
680
|
-
"relay.testOk": "
|
|
681
|
-
"relay.testFailed": "
|
|
682
|
-
"relay.selectAddress": "\u9009\u62E9\
|
|
682
|
+
"relay.regenerate": "\u91CD\u65B0\u751F\u6210\u6807\u8BC6",
|
|
683
|
+
"relay.regenerated": "\u5DF2\u751F\u6210\u65B0\u6807\u8BC6\uFF0C\u91CD\u542F\u540E\u91CD\u65B0\u6CE8\u518C\u3002",
|
|
684
|
+
"relay.envSnippet": "Relay \u542F\u52A8\u547D\u4EE4",
|
|
685
|
+
"relay.envHint": "\u5728 Relay \u4E3B\u673A\u6267\u884C\u6B64\u547D\u4EE4\u3002",
|
|
686
|
+
"relay.test": "\u6D4B\u8BD5 Relay \u8FDE\u63A5",
|
|
687
|
+
"relay.testOk": "Relay \u53EF\u8BBF\u95EE\uFF1A\u7248\u672C {version}\uFF0C\u5DF2\u8FDE\u63A5 {hosts} \u53F0\u5DE5\u4F5C\u7AD9\u3002",
|
|
688
|
+
"relay.testFailed": "Relay \u65E0\u6CD5\u8BBF\u95EE\uFF1A{message}",
|
|
689
|
+
"relay.selectAddress": "\u9009\u62E9\u516C\u5E03\u5730\u5740",
|
|
683
690
|
"relay.listenAddress": "\u76D1\u542C\u5730\u5740",
|
|
684
|
-
"relay.listenAddressHint": "\
|
|
691
|
+
"relay.listenAddressHint": "\u670D\u52A1\u5668\u7ED1\u5B9A\u5730\u5740\uFF1B\u6D4F\u89C8\u5668\u8BBF\u95EE\u4E0B\u65B9\u516C\u5E03\u5730\u5740\u3002",
|
|
685
692
|
"relay.addressTailscale": "Tailscale",
|
|
686
693
|
"relay.addressLan": "\u5C40\u57DF\u7F51",
|
|
687
694
|
"relay.addressVirtual": "\u865A\u62DF\u7F51\u5361",
|
|
688
695
|
"relay.addressLoopback": "\u56DE\u73AF",
|
|
689
|
-
"relay.noAddresses": "\
|
|
690
|
-
"relay.docsHint": "\u81EA\u5EFA
|
|
696
|
+
"relay.noAddresses": "\u672A\u627E\u5230\u975E\u56DE\u73AF\u5730\u5740\u3002",
|
|
697
|
+
"relay.docsHint": "\u81EA\u5EFA\u6307\u5357\uFF1Adocs/self-hosted-relay.zh-CN.md",
|
|
691
698
|
"keepalive.title": "\u540E\u53F0\u4FDD\u6D3B\u670D\u52A1",
|
|
692
699
|
"keepalive.manager": "\u7BA1\u7406\u65B9\u5F0F",
|
|
693
700
|
"keepalive.state": "\u72B6\u6001",
|
|
@@ -700,24 +707,24 @@ var require_zh = __commonJS({
|
|
|
700
707
|
"keepalive.failed": "\u4FDD\u6D3B\u64CD\u4F5C\u5931\u8D25\uFF1A{message}",
|
|
701
708
|
"keepalive.unitPath": "\u5355\u5143\u6587\u4EF6",
|
|
702
709
|
"keepalive.logsHint": "\u67E5\u770B\u65E5\u5FD7\uFF1A{command}",
|
|
703
|
-
"keepalive.linger": "\
|
|
704
|
-
"keepalive.lingerEnabled": "\u5DF2\u5F00\u542F
|
|
705
|
-
"keepalive.lingerDisabled": "\u672A\u5F00\u542F
|
|
710
|
+
"keepalive.linger": "\u5F00\u673A\u81EA\u542F",
|
|
711
|
+
"keepalive.lingerEnabled": "\u5DF2\u5F00\u542F\u5F00\u673A\u81EA\u542F\u3002",
|
|
712
|
+
"keepalive.lingerDisabled": "\u672A\u5F00\u542F\u5F00\u673A\u81EA\u542F\uFF08\u4EC5\u767B\u5F55\u671F\u95F4\u8FD0\u884C\uFF09\u3002",
|
|
706
713
|
"keepalive.enableLinger": "\u5F00\u542F\u5F00\u673A\u81EA\u542F",
|
|
707
|
-
"keepalive.lingerDone": "\u5DF2\u4E3A {username} \u5F00\u542F
|
|
708
|
-
"keepalive.fallbackNote": "\u7CFB\u7EDF\
|
|
714
|
+
"keepalive.lingerDone": "\u5DF2\u4E3A {username} \u5F00\u542F\u5F00\u673A\u81EA\u542F\u3002",
|
|
715
|
+
"keepalive.fallbackNote": "\u65E0\u7CFB\u7EDF\u670D\u52A1\u7BA1\u7406\u5668\uFF0C\u4F7F\u7528\u540E\u53F0\u5B88\u62A4\u8FDB\u7A0B\uFF0C\u91CD\u542F\u540E\u4E0D\u81EA\u52A8\u6062\u590D\u3002",
|
|
709
716
|
"herdr.title": "Herdr \u96C6\u6210",
|
|
710
717
|
"herdr.socketPath": "\u5957\u63A5\u5B57\u8DEF\u5F84",
|
|
711
718
|
"herdr.args": "\u9644\u52A0\u53C2\u6570",
|
|
712
719
|
"herdr.plugin": "\u63D2\u4EF6\u6CE8\u518C",
|
|
713
720
|
"herdr.pluginRegistered": "\u5DF2\u6CE8\u518C\u5230 Herdr\u3002",
|
|
714
721
|
"herdr.pluginMissing": "\u5C1A\u672A\u6CE8\u518C\u5230 Herdr\u3002",
|
|
715
|
-
"herdr.register": "\
|
|
716
|
-
"herdr.unregister": "\u53D6\u6D88\u6CE8\u518C
|
|
722
|
+
"herdr.register": "\u6CE8\u518C\u4E3A Herdr \u63D2\u4EF6",
|
|
723
|
+
"herdr.unregister": "\u53D6\u6D88\u6CE8\u518C",
|
|
717
724
|
"herdr.registerDone": "\u5DF2\u6CE8\u518C\uFF1A{path}",
|
|
718
|
-
"herdr.unregisterDone": "\
|
|
725
|
+
"herdr.unregisterDone": "\u5DF2\u53D6\u6D88\u6CE8\u518C\u3002",
|
|
719
726
|
"herdr.registerFailed": "\u6CE8\u518C\u5931\u8D25\uFF1A{message}",
|
|
720
|
-
"herdr.cliMissing": "PATH \u4E2D\u627E\
|
|
727
|
+
"herdr.cliMissing": "PATH \u4E2D\u672A\u627E\u5230 herdr \u547D\u4EE4\u3002",
|
|
721
728
|
"about.title": "\u8BED\u8A00\u4E0E\u5173\u4E8E",
|
|
722
729
|
"about.language": "\u754C\u9762\u8BED\u8A00",
|
|
723
730
|
"about.languageAuto": "\u8DDF\u968F\u7CFB\u7EDF\uFF08{detected}\uFF09",
|
|
@@ -727,23 +734,23 @@ var require_zh = __commonJS({
|
|
|
727
734
|
"about.configPath": "\u914D\u7F6E\u6587\u4EF6",
|
|
728
735
|
"about.statePath": "\u72B6\u6001\u76EE\u5F55",
|
|
729
736
|
"about.relayPackage": "Relay \u5305",
|
|
730
|
-
"about.docs": "\u81EA\u5EFA
|
|
737
|
+
"about.docs": "\u81EA\u5EFA\u6307\u5357\uFF1Adocs/self-hosted-relay.zh-CN.md",
|
|
731
738
|
"wizard.title": "\u9996\u6B21\u8BBE\u7F6E",
|
|
732
739
|
"wizard.step": "\u7B2C {current} / {total} \u6B65",
|
|
733
740
|
"wizard.languageTitle": "\u9009\u62E9\u8BED\u8A00",
|
|
734
|
-
"wizard.accessTitle": "\
|
|
735
|
-
"wizard.accessHint": "\
|
|
736
|
-
"wizard.addressTitle": "\
|
|
737
|
-
"wizard.relayTitle": "
|
|
741
|
+
"wizard.accessTitle": "\u9009\u62E9\u8BBF\u95EE\u65B9\u5F0F",
|
|
742
|
+
"wizard.accessHint": "\u540E\u7EED\u53EF\u5728 Relay \u9875\u9762\u4FEE\u6539\u3002",
|
|
743
|
+
"wizard.addressTitle": "\u9009\u62E9\u8BBF\u95EE\u5730\u5740",
|
|
744
|
+
"wizard.relayTitle": "Relay \u670D\u52A1\u5668",
|
|
738
745
|
"wizard.relayUrlLabel": "Relay \u5730\u5740\uFF08wss://\u2026\uFF09",
|
|
739
|
-
"wizard.relayHint": "
|
|
746
|
+
"wizard.relayHint": "Relay \u9700\u5148\u8FD0\u884C\u3002\u642D\u5EFA\u6307\u5357\u89C1 docs/self-hosted-relay.zh-CN.md\u3002",
|
|
740
747
|
"wizard.passwordTitle": "Relay \u5BC6\u7801",
|
|
741
|
-
"wizard.passwordHint": "
|
|
748
|
+
"wizard.passwordHint": "Relay \u7684 RELAY_PASSWORD\u3002\u672A\u8BBE\u7559\u7A7A\u3002",
|
|
742
749
|
"wizard.finishTitle": "\u5B8C\u6210",
|
|
743
|
-
"wizard.finishHint": "\u914D\u7F6E\u5C06\u4FDD\u5B58\
|
|
750
|
+
"wizard.finishHint": "\u914D\u7F6E\u5C06\u4FDD\u5B58\u81F3 {path}\u3002",
|
|
744
751
|
"wizard.startNow": "\u7ACB\u5373\u542F\u52A8\u670D\u52A1",
|
|
745
|
-
"wizard.installKeepalive": "\
|
|
746
|
-
"wizard.finish": "\u4FDD\u5B58\u5E76\
|
|
752
|
+
"wizard.installKeepalive": "\u540E\u53F0\u4FDD\u6D3B",
|
|
753
|
+
"wizard.finish": "\u4FDD\u5B58\u5E76\u5B8C\u6210",
|
|
747
754
|
"field.mode": "\u8BBF\u95EE\u65B9\u5F0F",
|
|
748
755
|
"field.port": "Relay \u7AEF\u53E3",
|
|
749
756
|
"field.lanHost": "\u6D4F\u89C8\u5668\u5730\u5740",
|
|
@@ -756,14 +763,14 @@ var require_zh = __commonJS({
|
|
|
756
763
|
"placeholder.autoDiscovered": "\u81EA\u52A8\u63A2\u6D4B",
|
|
757
764
|
"placeholder.none": "\u65E0",
|
|
758
765
|
"error.invalidMode": "\u672A\u77E5\u7684\u8BBF\u95EE\u65B9\u5F0F\u3002",
|
|
759
|
-
"error.invalidPort": "\u7AEF\u53E3\
|
|
760
|
-
"error.invalidLanHost": "\u6D4F\u89C8\u5668\u5730\u5740\
|
|
761
|
-
"error.invalidRelayUrl": "Relay \u5730\u5740\
|
|
762
|
-
"error.invalidPublicUrl": "\u6D4F\u89C8\u5668\u5730\u5740\
|
|
766
|
+
"error.invalidPort": "\u7AEF\u53E3\u987B\u4E3A 1 \u5230 65535 \u4E4B\u95F4\u7684\u6570\u5B57\u3002",
|
|
767
|
+
"error.invalidLanHost": "\u6D4F\u89C8\u5668\u5730\u5740\u987B\u4E3A\u53EF\u8BBF\u95EE\u5C40\u57DF\u7F51\u6216 Tailscale \u5730\u5740\uFF0C\u4E0D\u80FD\u4E3A\u56DE\u73AF\u6216 0.0.0.0\u3002",
|
|
768
|
+
"error.invalidRelayUrl": "Relay \u5730\u5740\u987B\u4EE5 wss://\u3001ws://\u3001https:// \u6216 http:// \u5F00\u5934\u3002",
|
|
769
|
+
"error.invalidPublicUrl": "\u6D4F\u89C8\u5668\u5730\u5740\u987B\u4EE5 https:// \u6216 http:// \u5F00\u5934\uFF0C\u4E0D\u80FD\u4E3A 0.0.0.0 \u6216 ::\u3002",
|
|
763
770
|
"error.invalidLanguage": "\u672A\u77E5\u7684\u8BED\u8A00\u3002",
|
|
764
771
|
"error.invalidKeepalive": "\u672A\u77E5\u7684\u4FDD\u6D3B\u7BA1\u7406\u65B9\u5F0F\u3002",
|
|
765
772
|
"error.unknownField": "\u672A\u77E5\u7684\u8BBE\u7F6E\u9879\u3002",
|
|
766
|
-
"error.remoteUrlRequired": "\u81EA\u5EFA
|
|
773
|
+
"error.remoteUrlRequired": "\u81EA\u5EFA Relay \u6A21\u5F0F\u987B\u586B\u5199 Relay \u5730\u5740\u3002",
|
|
767
774
|
"error.saveFailed": "\u4FDD\u5B58\u914D\u7F6E\u5931\u8D25\uFF1A{message}",
|
|
768
775
|
"hint.navigate": "\u2191\u2193 \u79FB\u52A8",
|
|
769
776
|
"hint.select": "\u21B5 \u9009\u62E9",
|
|
@@ -774,22 +781,23 @@ var require_zh = __commonJS({
|
|
|
774
781
|
"hint.mouseOn": "m \u5173\u95ED\u9F20\u6807",
|
|
775
782
|
"hint.mouseOff": "m \u5F00\u542F\u9F20\u6807",
|
|
776
783
|
"hint.mouseUnsupported": "\u4E0D\u652F\u6301\u9F20\u6807",
|
|
777
|
-
"hint.restartRequired": "\
|
|
778
|
-
"hint.unsavedChanges": "\u6709\u672A\u4FDD\u5B58\
|
|
784
|
+
"hint.restartRequired": "\u91CD\u542F\u670D\u52A1\u751F\u6548\u3002",
|
|
785
|
+
"hint.unsavedChanges": "\u6709\u672A\u4FDD\u5B58\u4FEE\u6539\uFF08\u6309 s \u4FDD\u5B58\uFF09\u3002",
|
|
779
786
|
"hint.save": "s \u4FDD\u5B58",
|
|
780
787
|
"hint.editing": "\u21B5 \u786E\u8BA4 \xB7 esc \u53D6\u6D88",
|
|
781
788
|
"update.title": "\u66F4\u65B0",
|
|
782
789
|
"update.check": "\u68C0\u67E5\u66F4\u65B0",
|
|
783
|
-
"update.checking": "\
|
|
790
|
+
"update.checking": "\u67E5\u8BE2 npm \u4E2D\u2026",
|
|
784
791
|
"update.upToDate": "\u5DF2\u662F\u6700\u65B0\uFF08{version}\uFF09",
|
|
785
|
-
"update.available": "\
|
|
786
|
-
"update.updating": "\
|
|
787
|
-
"update.done": "\u5DF2\u66F4\u65B0\
|
|
788
|
-
"update.restartHint": "\u66F4\u65B0\u5DF2\u5B89\u88C5\uFF0C\u91CD\u542F herdr-remote \
|
|
789
|
-
"update.errorNetwork": "\u65E0\u6CD5\u8FDE\u63A5
|
|
792
|
+
"update.available": "\u65B0\u7248\u672C {version} \u53EF\u7528\uFF08\u6309 Enter \u5B89\u88C5\uFF09",
|
|
793
|
+
"update.updating": "\u5B89\u88C5 {version} \u4E2D\u2026",
|
|
794
|
+
"update.done": "\u5DF2\u66F4\u65B0\u81F3 {version}",
|
|
795
|
+
"update.restartHint": "\u66F4\u65B0\u5DF2\u5B89\u88C5\uFF0C\u91CD\u542F herdr-remote \u751F\u6548\u3002",
|
|
796
|
+
"update.errorNetwork": "\u6240\u6709 npm registry \u5747\u65E0\u6CD5\u8FDE\u63A5",
|
|
797
|
+
"update.errorNetworkDetail": "\u65E0 registry \u5E94\u7B54\uFF1A{message}",
|
|
790
798
|
"update.errorFailed": "\u66F4\u65B0\u5931\u8D25\uFF0C\u53EF\u624B\u52A8\u6267\u884C\uFF1Anpm install -g herdr-remote@latest",
|
|
791
|
-
"update.cannot.source": "\
|
|
792
|
-
"update.cannot.linked": "
|
|
799
|
+
"update.cannot.source": "\u6E90\u7801\u76EE\u5F55\u8FD0\u884C\uFF0C\u8BF7\u4F7F\u7528 git \u66F4\u65B0",
|
|
800
|
+
"update.cannot.linked": "npm link \u5DE5\u4F5C\u526F\u672C\uFF0C\u7531 npm link \u7BA1\u7406"
|
|
793
801
|
};
|
|
794
802
|
}
|
|
795
803
|
});
|
|
@@ -954,6 +962,7 @@ var require_settings_model = __commonJS({
|
|
|
954
962
|
ACCESS_MODES: ACCESS_MODES2,
|
|
955
963
|
KEEPALIVE_MANAGERS,
|
|
956
964
|
LANGUAGES,
|
|
965
|
+
OFFICIAL_RELAY_URL: OFFICIAL_RELAY_URL2,
|
|
957
966
|
configDir,
|
|
958
967
|
configPath: configPath2,
|
|
959
968
|
isLoopbackHost,
|
|
@@ -976,6 +985,14 @@ var require_settings_model = __commonJS({
|
|
|
976
985
|
{ id: "keepaliveManager", kind: "choice", choices: KEEPALIVE_MANAGERS, labelKey: "field.keepalive" }
|
|
977
986
|
];
|
|
978
987
|
var EMPTY = "";
|
|
988
|
+
var SELECTABLE_MODES2 = ["local", "lan", "official", "remote"];
|
|
989
|
+
function selectedMode2(draft) {
|
|
990
|
+
if (draft.relay.mode === "remote" && draft.relay.remoteUrl === OFFICIAL_RELAY_URL2) return "official";
|
|
991
|
+
return draft.relay.mode;
|
|
992
|
+
}
|
|
993
|
+
function isOfficialRelay2(draft) {
|
|
994
|
+
return selectedMode2(draft) === "official";
|
|
995
|
+
}
|
|
979
996
|
function clone(value) {
|
|
980
997
|
return JSON.parse(JSON.stringify(value));
|
|
981
998
|
}
|
|
@@ -1038,7 +1055,16 @@ var require_settings_model = __commonJS({
|
|
|
1038
1055
|
const value = typeof rawValue === "string" ? rawValue.trim() : rawValue;
|
|
1039
1056
|
switch (id) {
|
|
1040
1057
|
case "mode": {
|
|
1041
|
-
if (!
|
|
1058
|
+
if (!SELECTABLE_MODES2.includes(value)) return { draft, errorKey: "error.invalidMode" };
|
|
1059
|
+
if (value === "official") {
|
|
1060
|
+
next.relay.mode = "remote";
|
|
1061
|
+
next.relay.remoteUrl = OFFICIAL_RELAY_URL2;
|
|
1062
|
+
next.relay.publicUrl = EMPTY;
|
|
1063
|
+
break;
|
|
1064
|
+
}
|
|
1065
|
+
if (value === "remote" && next.relay.remoteUrl === OFFICIAL_RELAY_URL2) {
|
|
1066
|
+
next.relay.remoteUrl = EMPTY;
|
|
1067
|
+
}
|
|
1042
1068
|
next.relay.mode = value;
|
|
1043
1069
|
if (value === "lan" && (isLoopbackHost(next.relay.lanHost) || isUnspecifiedAddress(next.relay.lanHost))) {
|
|
1044
1070
|
next.relay.lanHost = EMPTY;
|
|
@@ -1139,8 +1165,11 @@ var require_settings_model = __commonJS({
|
|
|
1139
1165
|
}
|
|
1140
1166
|
module.exports = {
|
|
1141
1167
|
FIELDS: FIELDS2,
|
|
1168
|
+
SELECTABLE_MODES: SELECTABLE_MODES2,
|
|
1142
1169
|
createDraft: createDraft2,
|
|
1143
1170
|
fieldsForMode: fieldsForMode2,
|
|
1171
|
+
isOfficialRelay: isOfficialRelay2,
|
|
1172
|
+
selectedMode: selectedMode2,
|
|
1144
1173
|
getField: getField2,
|
|
1145
1174
|
getFieldPlaceholder: getFieldPlaceholder2,
|
|
1146
1175
|
setField: setField2,
|
|
@@ -2301,11 +2330,13 @@ var require_updater = __commonJS({
|
|
|
2301
2330
|
"src/updater.js"(exports, module) {
|
|
2302
2331
|
"use strict";
|
|
2303
2332
|
var fs = __require("node:fs");
|
|
2333
|
+
var os = __require("node:os");
|
|
2304
2334
|
var path = __require("node:path");
|
|
2305
2335
|
var { spawn } = __require("node:child_process");
|
|
2306
2336
|
var { PACKAGE_ROOT } = require_config();
|
|
2307
2337
|
var PACKAGE_NAME = "herdr-remote";
|
|
2308
|
-
var
|
|
2338
|
+
var DEFAULT_REGISTRY = "https://registry.npmjs.org";
|
|
2339
|
+
var MIRROR_REGISTRY = "https://registry.npmmirror.com";
|
|
2309
2340
|
function currentVersion() {
|
|
2310
2341
|
try {
|
|
2311
2342
|
return __require(path.join(PACKAGE_ROOT, "package.json")).version;
|
|
@@ -2325,6 +2356,43 @@ var require_updater = __commonJS({
|
|
|
2325
2356
|
function canSelfUpdate2() {
|
|
2326
2357
|
return installKind2() === "npm";
|
|
2327
2358
|
}
|
|
2359
|
+
function normalizeRegistry(value) {
|
|
2360
|
+
if (typeof value !== "string") return null;
|
|
2361
|
+
const trimmed = value.trim().replace(/\/+$/, "");
|
|
2362
|
+
if (!/^https?:\/\//i.test(trimmed)) return null;
|
|
2363
|
+
return trimmed;
|
|
2364
|
+
}
|
|
2365
|
+
function registryFromNpmrc(filePath) {
|
|
2366
|
+
let contents;
|
|
2367
|
+
try {
|
|
2368
|
+
contents = fs.readFileSync(filePath, "utf8");
|
|
2369
|
+
} catch {
|
|
2370
|
+
return null;
|
|
2371
|
+
}
|
|
2372
|
+
let found = null;
|
|
2373
|
+
for (const rawLine of contents.split(/\r?\n/)) {
|
|
2374
|
+
const line = rawLine.trim();
|
|
2375
|
+
if (!line || line.startsWith("#") || line.startsWith(";")) continue;
|
|
2376
|
+
const match = /^registry\s*=\s*(.+)$/i.exec(line);
|
|
2377
|
+
if (match) found = normalizeRegistry(match[1].replace(/^["']|["']$/g, ""));
|
|
2378
|
+
}
|
|
2379
|
+
return found;
|
|
2380
|
+
}
|
|
2381
|
+
function registryCandidates({ env = process.env, home = os.homedir(), cwd = process.cwd() } = {}) {
|
|
2382
|
+
const candidates = [];
|
|
2383
|
+
const add = (value) => {
|
|
2384
|
+
const normalized = normalizeRegistry(value);
|
|
2385
|
+
if (normalized && !candidates.includes(normalized)) candidates.push(normalized);
|
|
2386
|
+
};
|
|
2387
|
+
add(env.npm_config_registry);
|
|
2388
|
+
add(env.NPM_CONFIG_REGISTRY);
|
|
2389
|
+
add(env.HERDR_REMOTE_REGISTRY);
|
|
2390
|
+
add(registryFromNpmrc(path.join(cwd, ".npmrc")));
|
|
2391
|
+
add(registryFromNpmrc(path.join(home, ".npmrc")));
|
|
2392
|
+
add(DEFAULT_REGISTRY);
|
|
2393
|
+
add(MIRROR_REGISTRY);
|
|
2394
|
+
return candidates;
|
|
2395
|
+
}
|
|
2328
2396
|
function compareVersions(a, b) {
|
|
2329
2397
|
const parse = (value) => String(value).split("-")[0].split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
2330
2398
|
const left = parse(a);
|
|
@@ -2336,39 +2404,64 @@ var require_updater = __commonJS({
|
|
|
2336
2404
|
}
|
|
2337
2405
|
return 0;
|
|
2338
2406
|
}
|
|
2339
|
-
async function
|
|
2340
|
-
const current = currentVersion();
|
|
2407
|
+
async function askRegistry(registry, { timeoutMs, fetchImpl }) {
|
|
2341
2408
|
const controller = new AbortController();
|
|
2342
2409
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
2343
2410
|
try {
|
|
2344
|
-
const response = await fetchImpl(
|
|
2411
|
+
const response = await fetchImpl(`${registry}/${PACKAGE_NAME}/latest`, {
|
|
2345
2412
|
signal: controller.signal,
|
|
2346
2413
|
headers: { Accept: "application/vnd.npm.install-v1+json" }
|
|
2347
2414
|
});
|
|
2348
|
-
if (!response.ok) {
|
|
2349
|
-
return { ok: false, current, errorKey: "update.errorNetwork" };
|
|
2350
|
-
}
|
|
2415
|
+
if (!response.ok) return { ok: false, message: `HTTP ${response.status ?? "?"}` };
|
|
2351
2416
|
const body = await response.json();
|
|
2352
2417
|
const latest = typeof body?.version === "string" ? body.version : null;
|
|
2353
|
-
if (!latest) return { ok: false,
|
|
2354
|
-
return {
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
latest,
|
|
2358
|
-
updateAvailable: compareVersions(latest, current) > 0
|
|
2359
|
-
};
|
|
2360
|
-
} catch {
|
|
2361
|
-
return { ok: false, current, errorKey: "update.errorNetwork" };
|
|
2418
|
+
if (!latest) return { ok: false, message: "registry answered without a version" };
|
|
2419
|
+
return { ok: true, latest };
|
|
2420
|
+
} catch (error) {
|
|
2421
|
+
return { ok: false, message: error?.name === "AbortError" ? "timed out" : String(error?.message || error) };
|
|
2362
2422
|
} finally {
|
|
2363
2423
|
clearTimeout(timer);
|
|
2364
2424
|
}
|
|
2365
2425
|
}
|
|
2426
|
+
async function checkForUpdate2({
|
|
2427
|
+
timeoutMs = 6e3,
|
|
2428
|
+
fetchImpl = globalThis.fetch,
|
|
2429
|
+
registries = registryCandidates()
|
|
2430
|
+
} = {}) {
|
|
2431
|
+
const current = currentVersion();
|
|
2432
|
+
const failures = [];
|
|
2433
|
+
for (const registry of registries) {
|
|
2434
|
+
const attempt = await askRegistry(registry, { timeoutMs, fetchImpl });
|
|
2435
|
+
if (attempt.ok) {
|
|
2436
|
+
return {
|
|
2437
|
+
ok: true,
|
|
2438
|
+
current,
|
|
2439
|
+
latest: attempt.latest,
|
|
2440
|
+
registry,
|
|
2441
|
+
updateAvailable: compareVersions(attempt.latest, current) > 0
|
|
2442
|
+
};
|
|
2443
|
+
}
|
|
2444
|
+
failures.push(`${registry}: ${attempt.message}`);
|
|
2445
|
+
}
|
|
2446
|
+
return {
|
|
2447
|
+
ok: false,
|
|
2448
|
+
current,
|
|
2449
|
+
errorKey: "update.errorNetwork",
|
|
2450
|
+
message: failures.join("; "),
|
|
2451
|
+
triedRegistries: registries
|
|
2452
|
+
};
|
|
2453
|
+
}
|
|
2366
2454
|
function performUpdate2({
|
|
2367
2455
|
spawnImpl = spawn,
|
|
2368
2456
|
timeoutMs = 18e4,
|
|
2369
2457
|
// Seam for tests: the suite runs from a checkout, where the guard below is
|
|
2370
2458
|
// correctly the only reachable outcome.
|
|
2371
|
-
installKindImpl = installKind2
|
|
2459
|
+
installKindImpl = installKind2,
|
|
2460
|
+
// The registry that just answered the version check. Installing from
|
|
2461
|
+
// somewhere the machine has been shown to reach beats installing from a
|
|
2462
|
+
// default it may have no route to. Empty means "whatever npm is configured
|
|
2463
|
+
// with", which is the right answer when no check has run.
|
|
2464
|
+
registry = ""
|
|
2372
2465
|
} = {}) {
|
|
2373
2466
|
return new Promise((resolve) => {
|
|
2374
2467
|
const kind = installKindImpl();
|
|
@@ -2376,7 +2469,10 @@ var require_updater = __commonJS({
|
|
|
2376
2469
|
resolve({ ok: false, errorKey: `update.cannot.${kind}` });
|
|
2377
2470
|
return;
|
|
2378
2471
|
}
|
|
2379
|
-
const
|
|
2472
|
+
const args = ["install", "-g", `${PACKAGE_NAME}@latest`];
|
|
2473
|
+
const normalizedRegistry = normalizeRegistry(registry);
|
|
2474
|
+
if (normalizedRegistry) args.push("--registry", normalizedRegistry);
|
|
2475
|
+
const child = spawnImpl("npm", args, {
|
|
2380
2476
|
encoding: "utf8",
|
|
2381
2477
|
timeout: timeoutMs
|
|
2382
2478
|
});
|
|
@@ -2396,12 +2492,15 @@ var require_updater = __commonJS({
|
|
|
2396
2492
|
}
|
|
2397
2493
|
module.exports = {
|
|
2398
2494
|
PACKAGE_NAME,
|
|
2495
|
+
DEFAULT_REGISTRY,
|
|
2496
|
+
MIRROR_REGISTRY,
|
|
2399
2497
|
canSelfUpdate: canSelfUpdate2,
|
|
2400
2498
|
checkForUpdate: checkForUpdate2,
|
|
2401
2499
|
compareVersions,
|
|
2402
2500
|
currentVersion,
|
|
2403
2501
|
installKind: installKind2,
|
|
2404
|
-
performUpdate: performUpdate2
|
|
2502
|
+
performUpdate: performUpdate2,
|
|
2503
|
+
registryCandidates
|
|
2405
2504
|
};
|
|
2406
2505
|
}
|
|
2407
2506
|
});
|
|
@@ -3105,6 +3204,7 @@ function RelayScreen({ ctx }) {
|
|
|
3105
3204
|
const [revealTokens, setRevealTokens] = useState5(false);
|
|
3106
3205
|
const [showEnv, setShowEnv] = useState5(false);
|
|
3107
3206
|
const [password, setPassword] = useState5(ctx.runtime.relayPassword || "");
|
|
3207
|
+
const official = (0, import_settings_model.isOfficialRelay)(draft);
|
|
3108
3208
|
const fields = useMemo2(
|
|
3109
3209
|
() => (0, import_settings_model.fieldsForMode)(draft.relay.mode).filter((field) => ["mode", "port", "lanHost", "remoteUrl", "publicUrl"].includes(field.id)),
|
|
3110
3210
|
[draft.relay.mode]
|
|
@@ -3112,36 +3212,45 @@ function RelayScreen({ ctx }) {
|
|
|
3112
3212
|
const entries = [
|
|
3113
3213
|
...fields.map((field) => ({
|
|
3114
3214
|
id: field.id,
|
|
3115
|
-
|
|
3215
|
+
// The official relay's address is ours and its browser URL follows from
|
|
3216
|
+
// it, so neither is offered for editing: an editable box holding a value
|
|
3217
|
+
// that must not change is an invitation to break the setup.
|
|
3218
|
+
kind: official && (field.id === "remoteUrl" || field.id === "publicUrl") ? "readonly" : "field",
|
|
3116
3219
|
fieldKind: field.kind,
|
|
3117
3220
|
label: t(field.labelKey)
|
|
3118
3221
|
})),
|
|
3119
3222
|
// The password only matters when talking to a relay somebody else started;
|
|
3120
|
-
// a local relay is configured with our own token automatically
|
|
3121
|
-
|
|
3223
|
+
// a local relay is configured with our own token automatically, and the
|
|
3224
|
+
// official one authenticates workstations by their own host token.
|
|
3225
|
+
...draft.relay.mode === "remote" && !official ? [{ id: "password", kind: "password", label: t("relay.password") }] : [],
|
|
3122
3226
|
// Saving needs a row of its own. Every field here only edits a draft, and
|
|
3123
3227
|
// the services restart from what is on disk — with `s` as the sole way to
|
|
3124
3228
|
// commit, a change could look applied, survive a restart, and never take
|
|
3125
3229
|
// effect. It is also the only way to save with the mouse.
|
|
3126
3230
|
{ id: "save", kind: "action", label: t("common.save") },
|
|
3127
3231
|
{ id: "test", kind: "action", label: t("relay.test") },
|
|
3128
|
-
...draft.relay.mode === "remote" ? [
|
|
3232
|
+
...draft.relay.mode === "remote" && !official ? [
|
|
3129
3233
|
{ id: "reveal", kind: "action", label: revealTokens ? t("relay.hidePassword") : t("relay.showPassword") },
|
|
3130
3234
|
{ id: "env", kind: "action", label: t("relay.envSnippet") }
|
|
3131
3235
|
] : [],
|
|
3132
3236
|
{ id: "regenerate", kind: "action", label: t("relay.regenerate") }
|
|
3133
3237
|
];
|
|
3134
3238
|
const addresses = useMemo2(() => listReachableAddresses({ includeLoopback: false }), []);
|
|
3135
|
-
const
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3239
|
+
const applyFields = (updates) => {
|
|
3240
|
+
let next = draft;
|
|
3241
|
+
for (const [id, value] of updates) {
|
|
3242
|
+
const result = (0, import_settings_model.setField)(next, id, value);
|
|
3243
|
+
if (result.errorKey) {
|
|
3244
|
+
ctx.notify(t(result.errorKey), "error");
|
|
3245
|
+
return false;
|
|
3246
|
+
}
|
|
3247
|
+
next = result.draft;
|
|
3140
3248
|
}
|
|
3141
|
-
ctx.updateDraft(
|
|
3249
|
+
ctx.updateDraft(next);
|
|
3142
3250
|
ctx.notify("", "info");
|
|
3143
3251
|
return true;
|
|
3144
3252
|
};
|
|
3253
|
+
const applyField = (id, value) => applyFields([[id, value]]);
|
|
3145
3254
|
const save = () => {
|
|
3146
3255
|
try {
|
|
3147
3256
|
const result = (0, import_settings_model.saveDraft)(draft);
|
|
@@ -3155,6 +3264,10 @@ function RelayScreen({ ctx }) {
|
|
|
3155
3264
|
const activate = (id) => {
|
|
3156
3265
|
const entry = entries.find((candidate) => candidate.id === id);
|
|
3157
3266
|
if (!entry) return;
|
|
3267
|
+
if (entry.kind === "readonly") {
|
|
3268
|
+
ctx.notify(t("relay.officialFixed"), "info");
|
|
3269
|
+
return;
|
|
3270
|
+
}
|
|
3158
3271
|
if (entry.kind === "field" || entry.kind === "password") {
|
|
3159
3272
|
ctx.setEditing(id);
|
|
3160
3273
|
return;
|
|
@@ -3209,14 +3322,13 @@ function RelayScreen({ ctx }) {
|
|
|
3209
3322
|
{ id: "official", label: t("mode.official"), description: t("mode.official.description") },
|
|
3210
3323
|
{ id: "remote", label: t("mode.remote"), description: t("mode.remote.description") }
|
|
3211
3324
|
],
|
|
3212
|
-
current:
|
|
3325
|
+
current: (0, import_settings_model.selectedMode)(draft),
|
|
3213
3326
|
onPick: (choice) => {
|
|
3327
|
+
if (!applyField("mode", choice)) return;
|
|
3214
3328
|
if (choice === "official") {
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
return;
|
|
3329
|
+
setPassword("");
|
|
3330
|
+
(0, import_service.setRelayPassword)("");
|
|
3218
3331
|
}
|
|
3219
|
-
applyField("mode", choice);
|
|
3220
3332
|
ctx.setEditing(null);
|
|
3221
3333
|
},
|
|
3222
3334
|
onCancel: () => ctx.setEditing(null)
|
|
@@ -3280,10 +3392,14 @@ function RelayScreen({ ctx }) {
|
|
|
3280
3392
|
},
|
|
3281
3393
|
onCancel: () => ctx.setEditing(null)
|
|
3282
3394
|
}
|
|
3395
|
+
) : entry.kind === "readonly" ? (
|
|
3396
|
+
// Fixed by us, so it is printed rather than offered for editing.
|
|
3397
|
+
/* @__PURE__ */ jsx7(Text6, { color: theme.muted, children: `${(0, import_settings_model.getField)(draft, entry.id) || placeholderText(ctx, entry.id)} (${t("relay.locked")})` })
|
|
3283
3398
|
) : entry.fieldKind === "choice" ? (
|
|
3284
3399
|
// Choice fields are picked from a list, never typed, so they
|
|
3285
|
-
// show the translated label rather than the stored id
|
|
3286
|
-
|
|
3400
|
+
// show the translated label rather than the stored id — and the
|
|
3401
|
+
// official relay is named as itself, not as "self-hosted".
|
|
3402
|
+
/* @__PURE__ */ jsx7(Text6, { children: t(`mode.${(0, import_settings_model.selectedMode)(draft)}`) })
|
|
3287
3403
|
) : /* @__PURE__ */ jsx7(
|
|
3288
3404
|
TextField,
|
|
3289
3405
|
{
|
|
@@ -3300,13 +3416,13 @@ function RelayScreen({ ctx }) {
|
|
|
3300
3416
|
entry.id
|
|
3301
3417
|
)),
|
|
3302
3418
|
ctx.dirty ? /* @__PURE__ */ jsx7(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text6, { color: theme.warn, children: t("hint.unsavedChanges") }) }) : null,
|
|
3303
|
-
draft.relay.mode === "remote" ? /* @__PURE__ */ jsx7(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text6, { color: theme.muted, children: t("relay.passwordHint") }) }) : null,
|
|
3419
|
+
draft.relay.mode === "remote" ? /* @__PURE__ */ jsx7(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text6, { color: theme.muted, children: official ? t("relay.officialHint") : t("relay.passwordHint") }) }) : null,
|
|
3304
3420
|
/* @__PURE__ */ jsx7(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx7(Row, { label: t("relay.identity"), children: /* @__PURE__ */ jsx7(Text6, { color: theme.muted, children: ctx.runtime.hostId }) }) }),
|
|
3305
3421
|
showEnv ? /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginTop: 1, borderStyle: "round", borderColor: theme.border, paddingX: 1, children: [
|
|
3306
3422
|
/* @__PURE__ */ jsx7(Text6, { color: theme.muted, children: t("relay.envHint") }),
|
|
3307
3423
|
/* @__PURE__ */ jsx7(Text6, { children: relayStartCommand(ctx.config, password) })
|
|
3308
3424
|
] }) : null,
|
|
3309
|
-
/* @__PURE__ */ jsx7(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text6, { color: theme.muted, children: t("relay.docsHint") }) }),
|
|
3425
|
+
official ? null : /* @__PURE__ */ jsx7(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text6, { color: theme.muted, children: t("relay.docsHint") }) }),
|
|
3310
3426
|
/* @__PURE__ */ jsx7(Message, { text: ctx.message?.text ?? null, level: ctx.message?.level ?? "info" })
|
|
3311
3427
|
] });
|
|
3312
3428
|
}
|
|
@@ -3598,6 +3714,7 @@ function About({ ctx }) {
|
|
|
3598
3714
|
const { t, draft } = ctx;
|
|
3599
3715
|
const [selected, setSelected] = useState8("auto");
|
|
3600
3716
|
const [update, setUpdate] = useState8({ phase: "idle" });
|
|
3717
|
+
const registryRef = useState8(() => ({ current: "" }))[0];
|
|
3601
3718
|
const detected = detectLocale({ preference: "auto" });
|
|
3602
3719
|
const languageOptions = [
|
|
3603
3720
|
{ id: "auto", label: t("about.languageAuto", { detected }) },
|
|
@@ -3629,13 +3746,15 @@ function About({ ctx }) {
|
|
|
3629
3746
|
const result = await (0, import_updater.checkForUpdate)();
|
|
3630
3747
|
if (!result.ok) {
|
|
3631
3748
|
setUpdate({ phase: "error", messageKey: result.errorKey ?? "update.errorNetwork" });
|
|
3749
|
+
if (result.message) ctx.notify(t("update.errorNetworkDetail", { message: result.message }), "error");
|
|
3632
3750
|
return;
|
|
3633
3751
|
}
|
|
3752
|
+
registryRef.current = result.registry ?? "";
|
|
3634
3753
|
setUpdate(result.updateAvailable ? { phase: "available", latest: result.latest } : { phase: "current", latest: result.latest });
|
|
3635
3754
|
};
|
|
3636
3755
|
const runUpdate = async (latest) => {
|
|
3637
3756
|
setUpdate({ phase: "updating", latest });
|
|
3638
|
-
const result = await (0, import_updater.performUpdate)();
|
|
3757
|
+
const result = await (0, import_updater.performUpdate)({ registry: registryRef.current });
|
|
3639
3758
|
if (!result.ok) {
|
|
3640
3759
|
setUpdate({ phase: "error", messageKey: result.errorKey ?? "update.errorFailed" });
|
|
3641
3760
|
ctx.notify(t("update.errorFailed"), "error");
|
|
@@ -3712,7 +3831,7 @@ function About({ ctx }) {
|
|
|
3712
3831
|
children: updateLabel
|
|
3713
3832
|
}
|
|
3714
3833
|
) }),
|
|
3715
|
-
/* @__PURE__ */ jsx10(Row, { label: t("about.version"), children: /* @__PURE__ */ jsx10(Text9, { color: theme.muted, children: "0.2.
|
|
3834
|
+
/* @__PURE__ */ jsx10(Row, { label: t("about.version"), children: /* @__PURE__ */ jsx10(Text9, { color: theme.muted, children: "0.2.4" }) }),
|
|
3716
3835
|
/* @__PURE__ */ jsx10(Row, { label: t("about.configPath"), children: /* @__PURE__ */ jsx10(Text9, { color: theme.muted, children: (0, import_config.configPath)() }) }),
|
|
3717
3836
|
/* @__PURE__ */ jsx10(Row, { label: t("about.statePath"), children: /* @__PURE__ */ jsx10(Text9, { color: theme.muted, children: (0, import_config.stateDir)() }) }),
|
|
3718
3837
|
/* @__PURE__ */ jsx10(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx10(Text9, { color: theme.muted, children: t("about.docs") }) }),
|
|
@@ -3724,10 +3843,10 @@ function About({ ctx }) {
|
|
|
3724
3843
|
import { useMemo as useMemo3, useState as useState9 } from "react";
|
|
3725
3844
|
import { Box as Box10, Text as Text10, useInput as useInput8 } from "ink";
|
|
3726
3845
|
import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
3727
|
-
function stepsFor(mode) {
|
|
3846
|
+
function stepsFor(mode, remoteUrl) {
|
|
3728
3847
|
const steps = ["language", "access"];
|
|
3729
3848
|
if (mode === "lan") steps.push("address");
|
|
3730
|
-
if (mode === "remote") steps.push("relayUrl", "password");
|
|
3849
|
+
if (mode === "remote" && remoteUrl !== import_config.OFFICIAL_RELAY_URL) steps.push("relayUrl", "password");
|
|
3731
3850
|
steps.push("finish");
|
|
3732
3851
|
return steps;
|
|
3733
3852
|
}
|
|
@@ -3742,18 +3861,26 @@ function Wizard({ ctx, onDone }) {
|
|
|
3742
3861
|
() => listReachableAddresses({ includeLoopback: false }),
|
|
3743
3862
|
[]
|
|
3744
3863
|
);
|
|
3745
|
-
const steps = useMemo3(
|
|
3864
|
+
const steps = useMemo3(
|
|
3865
|
+
() => stepsFor(draft.relay.mode, draft.relay.remoteUrl),
|
|
3866
|
+
[draft.relay.mode, draft.relay.remoteUrl]
|
|
3867
|
+
);
|
|
3746
3868
|
const stepIndex = Math.max(0, steps.indexOf(step));
|
|
3747
|
-
const
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3869
|
+
const applyAll = (updates) => {
|
|
3870
|
+
let next = draft;
|
|
3871
|
+
for (const [id, value] of updates) {
|
|
3872
|
+
const result = (0, import_settings_model.setField)(next, id, value);
|
|
3873
|
+
if (result.errorKey) {
|
|
3874
|
+
ctx.notify(t(result.errorKey), "error");
|
|
3875
|
+
return false;
|
|
3876
|
+
}
|
|
3877
|
+
next = result.draft;
|
|
3752
3878
|
}
|
|
3753
|
-
ctx.updateDraft(
|
|
3879
|
+
ctx.updateDraft(next);
|
|
3754
3880
|
ctx.notify("", "info");
|
|
3755
3881
|
return true;
|
|
3756
3882
|
};
|
|
3883
|
+
const apply = (id, value) => applyAll([[id, value]]);
|
|
3757
3884
|
const advance = (from, order = steps) => {
|
|
3758
3885
|
const index = order.indexOf(from);
|
|
3759
3886
|
setStep(order[Math.min(order.length - 1, index + 1)]);
|
|
@@ -3835,16 +3962,17 @@ function Wizard({ ctx, onDone }) {
|
|
|
3835
3962
|
description: t("mode.remote.description")
|
|
3836
3963
|
}
|
|
3837
3964
|
],
|
|
3838
|
-
current:
|
|
3965
|
+
current: (0, import_settings_model.selectedMode)(draft),
|
|
3839
3966
|
onPick: (choice) => {
|
|
3840
3967
|
if (choice === "official") {
|
|
3841
|
-
if (!apply("mode", "
|
|
3842
|
-
if (!apply("remoteUrl", import_config.OFFICIAL_RELAY_URL)) return;
|
|
3968
|
+
if (!apply("mode", "official")) return;
|
|
3843
3969
|
(0, import_service.setRelayPassword)("");
|
|
3844
|
-
advance("access",
|
|
3970
|
+
advance("access", stepsFor("remote", import_config.OFFICIAL_RELAY_URL));
|
|
3845
3971
|
return;
|
|
3846
3972
|
}
|
|
3847
|
-
if (apply("mode", choice))
|
|
3973
|
+
if (apply("mode", choice)) {
|
|
3974
|
+
advance("access", stepsFor(choice, choice === "remote" ? "" : draft.relay.remoteUrl));
|
|
3975
|
+
}
|
|
3848
3976
|
},
|
|
3849
3977
|
onCancel: back
|
|
3850
3978
|
}
|