@termix-ssh/plugin-sdk 1.0.15 → 1.0.17
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/CHANGELOG.md +23 -0
- package/PLUGIN-GUIDE.md +92 -72
- package/dist/backend.d.ts +370 -0
- package/dist/capabilities.js +2 -0
- package/dist/frontend.d.ts +45 -0
- package/dist/host/{PluginsTab-S33WIIGC.js → PluginsTab-YAGYRBIE.js} +3 -3
- package/dist/host/{chunk-57DJU2ZA.js → chunk-2MU6WNSX.js} +1 -1
- package/dist/host/{chunk-VFTB2RDP.js → chunk-446UEDSK.js} +4 -2
- package/dist/host/{chunk-3L45NNT5.js → chunk-7LEJ3HYF.js} +20 -3
- package/dist/host/{chunk-V44FCJBQ.js → chunk-J2AILBXM.js} +540 -400
- package/dist/host/{chunk-2IV3VX7F.js → chunk-LQKK2JJA.js} +5 -1
- package/dist/host/core-classes.json +1 -1
- package/dist/host/{linked-server-SCJH7DSL.js → linked-server-OUF3POT7.js} +5 -3
- package/dist/host/{rbac-api-KA5IPQQL.js → rbac-api-LZVENREG.js} +1 -1
- package/dist/host/testing-host.js +4 -4
- package/dist/host/types/src/types/onboarding.d.ts +0 -1
- package/dist/host/types/src/ui/auth/Auth.d.ts +1 -0
- package/dist/host/types/src/ui/lib/linked-server.d.ts +2 -0
- package/dist/host/types/src/ui/plugin-host/NativeView.d.ts +19 -0
- package/dist/host/types/src/ui/plugin-host/sdk-ui.d.ts +2 -6
- package/dist/host/types/src/ui/shell/CompanionFrame.d.ts +11 -0
- package/dist/host/types/src/ui/shell/companions.d.ts +63 -0
- package/dist/host/ui.js +149 -815
- package/dist/host/{use-permissions-LLN6TLAL.js → use-permissions-BYCDS5PD.js} +1 -1
- package/dist/manifest.d.ts +1 -1
- package/dist/manifest.js +1 -1
- package/dist/testing.d.ts +5 -1
- package/dist/testing.js +28 -0
- package/package.json +1 -1
- package/schema/manifest.schema.json +2 -0
- package/dist/host/types/src/ui/api/sync-api.d.ts +0 -93
- package/dist/host/types/src/ui/auth/ElectronLoginForm.d.ts +0 -9
- package/dist/host/types/src/ui/hooks/use-sync-status.d.ts +0 -4
- package/dist/host/types/src/ui/lib/sync-status.d.ts +0 -6
- package/dist/host/types/src/ui/settings/sync/LinkServerDialog.d.ts +0 -12
- package/dist/host/types/src/ui/settings/sync/ProxySettingsFields.d.ts +0 -15
- package/dist/host/types/src/ui/settings/sync/saved-servers.d.ts +0 -3
|
@@ -3,14 +3,16 @@ import {
|
|
|
3
3
|
hasPermission,
|
|
4
4
|
resetPermissionsCache,
|
|
5
5
|
usePermissions
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-2MU6WNSX.js";
|
|
7
7
|
import {
|
|
8
|
+
ArrowDownToLine,
|
|
9
|
+
ArrowLeftToLine,
|
|
10
|
+
ArrowRightToLine,
|
|
8
11
|
Button,
|
|
9
12
|
Check,
|
|
10
13
|
Checkbox,
|
|
11
14
|
CheckboxIndicator,
|
|
12
15
|
CircleSlash,
|
|
13
|
-
Cloud,
|
|
14
16
|
Columns2,
|
|
15
17
|
DefaultsOnly,
|
|
16
18
|
DocsLink,
|
|
@@ -27,6 +29,7 @@ import {
|
|
|
27
29
|
OPEN_PLUGIN_SETTINGS_EVENT,
|
|
28
30
|
PLUGINS_CHANGED_EVENT,
|
|
29
31
|
PLUGIN_SETTINGS_CHANGED_EVENT,
|
|
32
|
+
PanelRight,
|
|
30
33
|
Plug,
|
|
31
34
|
PluginIcon,
|
|
32
35
|
Puzzle,
|
|
@@ -80,7 +83,7 @@ import {
|
|
|
80
83
|
withIconBoundary,
|
|
81
84
|
withPluginContext,
|
|
82
85
|
withPluginScope
|
|
83
|
-
} from "./chunk-
|
|
86
|
+
} from "./chunk-LQKK2JJA.js";
|
|
84
87
|
import {
|
|
85
88
|
SYNC_CHANGED_EVENT,
|
|
86
89
|
TRUST_TOKEN_KEY,
|
|
@@ -118,7 +121,6 @@ import {
|
|
|
118
121
|
logActivity,
|
|
119
122
|
manifestDeclares,
|
|
120
123
|
markUserAuthenticated,
|
|
121
|
-
notifySyncChanged,
|
|
122
124
|
parseCustomKeybindings,
|
|
123
125
|
patchOpenTab,
|
|
124
126
|
pluginStepKey,
|
|
@@ -130,7 +132,7 @@ import {
|
|
|
130
132
|
usePluginStore,
|
|
131
133
|
useTabTypes,
|
|
132
134
|
websocketAuthProtocols
|
|
133
|
-
} from "./chunk-
|
|
135
|
+
} from "./chunk-7LEJ3HYF.js";
|
|
134
136
|
import {
|
|
135
137
|
define_import_meta_env_default,
|
|
136
138
|
init_define_import_meta_env
|
|
@@ -1122,13 +1124,6 @@ var en_default = {
|
|
|
1122
1124
|
pluginsLoadFailed: "The plugin list could not be loaded. You can choose plugins later from the Plugins tab.",
|
|
1123
1125
|
securityTitle: "Secure your account",
|
|
1124
1126
|
securityIntro: "Add a passkey or an authenticator app to your account. You can also do this later in Settings, under Security.",
|
|
1125
|
-
desktopTitle: "How do you want to use Termix?",
|
|
1126
|
-
desktopBody: "You can change this any time from Sync in the sidebar.",
|
|
1127
|
-
desktopLocalTitle: "On this device only",
|
|
1128
|
-
desktopLocalBody: "Everything is stored here. Nothing to set up.",
|
|
1129
|
-
desktopLinkTitle: "With my Termix server",
|
|
1130
|
-
desktopLinkBody: "Sign in to your server to use the same hosts and settings on every device.",
|
|
1131
|
-
desktopLinked: "Linked to {{server}}",
|
|
1132
1127
|
pluginsDocsLink: "Read about each one"
|
|
1133
1128
|
},
|
|
1134
1129
|
desktopUpdates: {
|
|
@@ -1149,6 +1144,11 @@ var en_default = {
|
|
|
1149
1144
|
ready: "Termix {{version}} is ready to install",
|
|
1150
1145
|
readyHint: "It installs the next time Termix restarts."
|
|
1151
1146
|
},
|
|
1147
|
+
companion: {
|
|
1148
|
+
close: "Close panel",
|
|
1149
|
+
moveSide: "Move panel",
|
|
1150
|
+
resize: "Resize panel"
|
|
1151
|
+
},
|
|
1152
1152
|
nav: {
|
|
1153
1153
|
home: "Home",
|
|
1154
1154
|
terminal: "Terminal",
|
|
@@ -1159,7 +1159,6 @@ var en_default = {
|
|
|
1159
1159
|
hosts: "Hosts",
|
|
1160
1160
|
credentials: "Credentials",
|
|
1161
1161
|
connections: "Connections",
|
|
1162
|
-
sync: "Sync",
|
|
1163
1162
|
reconnectDisconnectedTerminals: "Reconnect all disconnected terminals",
|
|
1164
1163
|
reconnectingTerminals_one: "Reconnecting {{count}} terminal",
|
|
1165
1164
|
reconnectingTerminals_other: "Reconnecting {{count}} terminals",
|
|
@@ -2058,6 +2057,14 @@ var en_default = {
|
|
|
2058
2057
|
title: "Set sign in rules",
|
|
2059
2058
|
consequence: "It can sign people out when idle, limit session length, turn off remember me and require a second factor."
|
|
2060
2059
|
},
|
|
2060
|
+
"ssh:transport": {
|
|
2061
|
+
title: "Choose how hosts are reached",
|
|
2062
|
+
consequence: "It can carry the SSH connection to a host over its own route, so it sees everything sent to and from those hosts, passwords included."
|
|
2063
|
+
},
|
|
2064
|
+
"sync:provide": {
|
|
2065
|
+
title: "Run sync",
|
|
2066
|
+
consequence: "It can answer all sync requests, so it sees the data that devices and servers sync."
|
|
2067
|
+
},
|
|
2061
2068
|
"system:tls": {
|
|
2062
2069
|
title: "Manage certificates",
|
|
2063
2070
|
consequence: "It can replace the certificate Termix serves over HTTPS and answer domain checks from certificate authorities."
|
|
@@ -2526,87 +2533,6 @@ var en_default = {
|
|
|
2526
2533
|
noData: "No data",
|
|
2527
2534
|
filter: "Filter..."
|
|
2528
2535
|
},
|
|
2529
|
-
sync: {
|
|
2530
|
-
minutesAgo_one: "{{count}} minute ago",
|
|
2531
|
-
minutesAgo_other: "{{count}} minutes ago",
|
|
2532
|
-
hoursAgo_one: "{{count}} hour ago",
|
|
2533
|
-
hoursAgo_other: "{{count}} hours ago",
|
|
2534
|
-
pending_one: "{{count}} change waiting to sync",
|
|
2535
|
-
pending_other: "{{count}} changes waiting to sync",
|
|
2536
|
-
proxy: {
|
|
2537
|
-
headersTitle: "Extra headers",
|
|
2538
|
-
headersHint: "Sent with every request to the server, for example a Cloudflare Access service token.",
|
|
2539
|
-
headerName: "Header name",
|
|
2540
|
-
headerValue: "Value",
|
|
2541
|
-
savedValue: "Saved, type to change",
|
|
2542
|
-
addHeader: "Add header",
|
|
2543
|
-
removeHeader: "Remove header",
|
|
2544
|
-
basicAuthTitle: "Username and password",
|
|
2545
|
-
basicAuthHint: "For a proxy that asks for a username and password before Termix.",
|
|
2546
|
-
username: "Username",
|
|
2547
|
-
password: "Password",
|
|
2548
|
-
allowInvalidCertificate: "Trust a self-signed certificate",
|
|
2549
|
-
allowInvalidCertificateHint: "Only for your own server, when its certificate is not from a known authority."
|
|
2550
|
-
},
|
|
2551
|
-
problems: {
|
|
2552
|
-
invalidUrl: "That does not look like a web address.",
|
|
2553
|
-
unreachable: "Could not reach the server. Check the address and that the server is running.",
|
|
2554
|
-
unreachableWithReason: "Could not reach the server: {{reason}}",
|
|
2555
|
-
tlsUntrusted: "The server certificate is not trusted. If this is your own server with a self-signed certificate, turn on the option below.",
|
|
2556
|
-
basicAuthRequired: "Something in front of the server asks for a username and password. Enter them below.",
|
|
2557
|
-
proxyLogin: "A login page or proxy answered instead of Termix. Add the headers it needs below, or check the address.",
|
|
2558
|
-
notTermix: "There is no Termix server at that address. If it runs under a path, include it, like https://example.com/termix.",
|
|
2559
|
-
versionMismatch: "That server runs an older Termix. Update it to 2.9 or newer to link.",
|
|
2560
|
-
differentAccount: "You signed in to a different account. Sign in to the account this device is linked to, or unlink first."
|
|
2561
|
-
},
|
|
2562
|
-
wizard: {
|
|
2563
|
-
title: "Link to a Termix server",
|
|
2564
|
-
reloginTitle: "Sign in again",
|
|
2565
|
-
savedServers: "Recent servers",
|
|
2566
|
-
removeServer: "Remove from the list",
|
|
2567
|
-
serverDescription: "Enter the address you use to open Termix in your browser.",
|
|
2568
|
-
signinDescription: "Sign in to {{url}}",
|
|
2569
|
-
chooseDescription: "This device already has data. What should happen to it?",
|
|
2570
|
-
finishingDescription: "Linking this device.",
|
|
2571
|
-
serverUrl: "Server address",
|
|
2572
|
-
serverUrlHint: "For example https://termix.example.com",
|
|
2573
|
-
showProxySettings: "Reverse proxy settings",
|
|
2574
|
-
hideProxySettings: "Hide reverse proxy settings",
|
|
2575
|
-
continue: "Continue",
|
|
2576
|
-
back: "Back",
|
|
2577
|
-
mergeTitle: "Add it to my account",
|
|
2578
|
-
mergeBody_one: "The item on this device is added to your account. Items your account already has stay as they are on the server.",
|
|
2579
|
-
mergeBody_other: "The {{count}} items on this device are added to your account. Items your account already has stay as they are on the server.",
|
|
2580
|
-
replaceTitle: "Replace it with my account",
|
|
2581
|
-
replaceBody_one: "The item on this device is removed, and this device takes everything from your account. Hosts kept on this device only stay.",
|
|
2582
|
-
replaceBody_other: "The {{count}} items on this device are removed, and this device takes everything from your account. Hosts kept on this device only stay.",
|
|
2583
|
-
link: "Link",
|
|
2584
|
-
linking: "Linking and running the first sync...",
|
|
2585
|
-
linked: "Linked. Your data is syncing now.",
|
|
2586
|
-
signedInAgain: "Signed in. Sync is running again."
|
|
2587
|
-
},
|
|
2588
|
-
entities: {
|
|
2589
|
-
hosts: "Hosts",
|
|
2590
|
-
sshCredentials: "Credentials",
|
|
2591
|
-
sshFolders: "Folders",
|
|
2592
|
-
userPreferences: "Preferences",
|
|
2593
|
-
pluginUserSettings: "Plugin settings",
|
|
2594
|
-
sharedHosts: "Hosts shared with you",
|
|
2595
|
-
sharedCredentials: "Credentials shared with you",
|
|
2596
|
-
vaultProfiles: "Vault profiles",
|
|
2597
|
-
snippetFolders: "Snippet folders",
|
|
2598
|
-
snippets: "Snippets",
|
|
2599
|
-
dashboardServiceLinks: "Service links",
|
|
2600
|
-
homepageItems: "Homepage items",
|
|
2601
|
-
networkTopology: "Network map",
|
|
2602
|
-
workspaces: "Workspaces",
|
|
2603
|
-
hostDefaults: "Host defaults",
|
|
2604
|
-
hostDefaultsAdmin: "Server host defaults",
|
|
2605
|
-
aiProviders: "AI providers",
|
|
2606
|
-
homepageLayouts: "Homepage layouts",
|
|
2607
|
-
accountProfile: "Account profile"
|
|
2608
|
-
}
|
|
2609
|
-
},
|
|
2610
2536
|
hostDefaults: {
|
|
2611
2537
|
source: {
|
|
2612
2538
|
folder: "Folder {{name}}",
|
|
@@ -2667,8 +2593,8 @@ var localeLoaders = Object.fromEntries(
|
|
|
2667
2593
|
Object.entries(LOCALE_FILES).map(([code, file]) => [
|
|
2668
2594
|
code,
|
|
2669
2595
|
() => {
|
|
2670
|
-
const
|
|
2671
|
-
return
|
|
2596
|
+
const load2 = translatedFiles[`../locales/translated/${file}.json`];
|
|
2597
|
+
return load2 ? load2() : Promise.reject(new Error(`no ${file}`));
|
|
2672
2598
|
}
|
|
2673
2599
|
])
|
|
2674
2600
|
);
|
|
@@ -2771,130 +2697,6 @@ function consumeLoginLanguage() {
|
|
|
2771
2697
|
}
|
|
2772
2698
|
var i18n_default = i18n;
|
|
2773
2699
|
|
|
2774
|
-
// src/ui/api/sync-api.ts
|
|
2775
|
-
init_define_import_meta_env();
|
|
2776
|
-
async function getSyncStatus() {
|
|
2777
|
-
return (await authApi.get("/sync/link/status")).data;
|
|
2778
|
-
}
|
|
2779
|
-
async function probeServer(target) {
|
|
2780
|
-
return (await authApi.post("/sync/link/probe", target)).data;
|
|
2781
|
-
}
|
|
2782
|
-
async function getLinkPreview() {
|
|
2783
|
-
return (await authApi.get("/sync/link/preview")).data?.counts ?? {};
|
|
2784
|
-
}
|
|
2785
|
-
async function completeLink(input) {
|
|
2786
|
-
return (await authApi.post("/sync/link/complete", input)).data;
|
|
2787
|
-
}
|
|
2788
|
-
async function reloginLink(token) {
|
|
2789
|
-
return (await authApi.post("/sync/link/relogin", { token })).data;
|
|
2790
|
-
}
|
|
2791
|
-
async function unlinkServer(keepData) {
|
|
2792
|
-
return (await authApi.post("/sync/link/unlink", { keepData })).data;
|
|
2793
|
-
}
|
|
2794
|
-
async function syncNow() {
|
|
2795
|
-
return (await authApi.post("/sync/link/sync", {}, { timeout: 3e5 })).data;
|
|
2796
|
-
}
|
|
2797
|
-
async function updateSyncSettings(settings) {
|
|
2798
|
-
return (await authApi.put("/sync/link/settings", settings)).data;
|
|
2799
|
-
}
|
|
2800
|
-
async function getSyncConflicts() {
|
|
2801
|
-
return (await authApi.get("/sync/link/conflicts")).data?.conflicts ?? [];
|
|
2802
|
-
}
|
|
2803
|
-
async function settleSyncConflict(id, keep) {
|
|
2804
|
-
await authApi.post(`/sync/link/conflicts/${id}`, { keep });
|
|
2805
|
-
}
|
|
2806
|
-
async function getSyncErrors() {
|
|
2807
|
-
return (await authApi.get("/sync/link/errors")).data?.errors ?? [];
|
|
2808
|
-
}
|
|
2809
|
-
async function retrySyncErrors() {
|
|
2810
|
-
return (await authApi.post("/sync/link/errors/retry", {}, { timeout: 3e5 })).data;
|
|
2811
|
-
}
|
|
2812
|
-
|
|
2813
|
-
// src/ui/lib/sync-status.ts
|
|
2814
|
-
init_define_import_meta_env();
|
|
2815
|
-
var IDLE_MS = 15e3;
|
|
2816
|
-
var BUSY_MS = 2e3;
|
|
2817
|
-
var snapshot = null;
|
|
2818
|
-
var timer = null;
|
|
2819
|
-
var lastSyncAt;
|
|
2820
|
-
var listeners = /* @__PURE__ */ new Set();
|
|
2821
|
-
function emit() {
|
|
2822
|
-
for (const listener of listeners) listener();
|
|
2823
|
-
}
|
|
2824
|
-
function announce() {
|
|
2825
|
-
notifySyncChanged();
|
|
2826
|
-
window.dispatchEvent(new CustomEvent("hosts:refresh"));
|
|
2827
|
-
window.dispatchEvent(new CustomEvent("termix:hosts-changed"));
|
|
2828
|
-
window.dispatchEvent(new CustomEvent("termix:credentials-changed"));
|
|
2829
|
-
window.dispatchEvent(new CustomEvent("termix:plugins-changed"));
|
|
2830
|
-
}
|
|
2831
|
-
async function poll() {
|
|
2832
|
-
timer = null;
|
|
2833
|
-
try {
|
|
2834
|
-
const next = await getSyncStatus();
|
|
2835
|
-
const syncedAt = next.lastSyncAt ?? null;
|
|
2836
|
-
if (lastSyncAt !== void 0 && syncedAt !== lastSyncAt) announce();
|
|
2837
|
-
if (snapshot && snapshot.linked !== next.linked) notifySyncChanged();
|
|
2838
|
-
lastSyncAt = syncedAt;
|
|
2839
|
-
snapshot = next;
|
|
2840
|
-
emit();
|
|
2841
|
-
} catch {
|
|
2842
|
-
}
|
|
2843
|
-
schedule();
|
|
2844
|
-
}
|
|
2845
|
-
function schedule(delay) {
|
|
2846
|
-
if (listeners.size === 0 || timer) return;
|
|
2847
|
-
const busy = snapshot?.status === "syncing" || !!snapshot?.pending;
|
|
2848
|
-
timer = setTimeout(() => void poll(), delay ?? (busy ? BUSY_MS : IDLE_MS));
|
|
2849
|
-
}
|
|
2850
|
-
function subscribeSyncStatus(listener) {
|
|
2851
|
-
listeners.add(listener);
|
|
2852
|
-
if (isElectron() && listeners.size === 1 && !timer) void poll();
|
|
2853
|
-
return () => {
|
|
2854
|
-
listeners.delete(listener);
|
|
2855
|
-
if (listeners.size === 0 && timer) {
|
|
2856
|
-
clearTimeout(timer);
|
|
2857
|
-
timer = null;
|
|
2858
|
-
}
|
|
2859
|
-
};
|
|
2860
|
-
}
|
|
2861
|
-
function getSyncStatusSnapshot() {
|
|
2862
|
-
return snapshot;
|
|
2863
|
-
}
|
|
2864
|
-
function setSyncStatus(next) {
|
|
2865
|
-
snapshot = next;
|
|
2866
|
-
if (lastSyncAt !== void 0 && (next.lastSyncAt ?? null) !== lastSyncAt) {
|
|
2867
|
-
announce();
|
|
2868
|
-
}
|
|
2869
|
-
lastSyncAt = next.lastSyncAt ?? null;
|
|
2870
|
-
emit();
|
|
2871
|
-
if (timer) clearTimeout(timer);
|
|
2872
|
-
timer = null;
|
|
2873
|
-
schedule(BUSY_MS);
|
|
2874
|
-
}
|
|
2875
|
-
function refreshSyncStatus() {
|
|
2876
|
-
if (timer) clearTimeout(timer);
|
|
2877
|
-
timer = null;
|
|
2878
|
-
void poll();
|
|
2879
|
-
}
|
|
2880
|
-
|
|
2881
|
-
// src/ui/hooks/use-sync-status.ts
|
|
2882
|
-
init_define_import_meta_env();
|
|
2883
|
-
import { useSyncExternalStore } from "react";
|
|
2884
|
-
function useSyncStatus() {
|
|
2885
|
-
return useSyncExternalStore(
|
|
2886
|
-
subscribeSyncStatus,
|
|
2887
|
-
getSyncStatusSnapshot,
|
|
2888
|
-
() => null
|
|
2889
|
-
);
|
|
2890
|
-
}
|
|
2891
|
-
function useSyncAttentionCount() {
|
|
2892
|
-
const status = useSyncStatus();
|
|
2893
|
-
if (!status?.linked) return null;
|
|
2894
|
-
const count = (status.conflicts ?? 0) + (status.errors ?? 0) + (status.status === "signed_out" ? 1 : 0);
|
|
2895
|
-
return count || null;
|
|
2896
|
-
}
|
|
2897
|
-
|
|
2898
2700
|
// src/ui/shell/panel-registry.ts
|
|
2899
2701
|
init_define_import_meta_env();
|
|
2900
2702
|
var registry = createRegistry();
|
|
@@ -2906,7 +2708,7 @@ var resetPanels = registry.reset;
|
|
|
2906
2708
|
|
|
2907
2709
|
// src/ui/sidebar/rail-items.ts
|
|
2908
2710
|
init_define_import_meta_env();
|
|
2909
|
-
import { useMemo, useSyncExternalStore
|
|
2711
|
+
import { useMemo, useSyncExternalStore } from "react";
|
|
2910
2712
|
var RAIL_GROUP_ORDER = ["objects", "tools", "system"];
|
|
2911
2713
|
var RAIL_ITEMS = [
|
|
2912
2714
|
{
|
|
@@ -2939,15 +2741,6 @@ var RAIL_ITEMS = [
|
|
|
2939
2741
|
mobilePrimary: true,
|
|
2940
2742
|
group: "tools"
|
|
2941
2743
|
},
|
|
2942
|
-
{
|
|
2943
|
-
id: "sync",
|
|
2944
|
-
icon: Cloud,
|
|
2945
|
-
labelKey: "nav.sync",
|
|
2946
|
-
electronOnly: true,
|
|
2947
|
-
placement: "footer",
|
|
2948
|
-
group: "system",
|
|
2949
|
-
useBadge: useSyncAttentionCount
|
|
2950
|
-
},
|
|
2951
2744
|
{
|
|
2952
2745
|
id: "plugins",
|
|
2953
2746
|
icon: Puzzle,
|
|
@@ -3006,7 +2799,7 @@ function permittedRailItems(items, permissions) {
|
|
|
3006
2799
|
);
|
|
3007
2800
|
}
|
|
3008
2801
|
function useRailItems() {
|
|
3009
|
-
const items =
|
|
2802
|
+
const items = useSyncExternalStore(
|
|
3010
2803
|
registeredRailItems.subscribe,
|
|
3011
2804
|
railItemsSnapshot,
|
|
3012
2805
|
railItemsSnapshot
|
|
@@ -3371,12 +3164,12 @@ var resetDashboardCards = registry3.reset;
|
|
|
3371
3164
|
init_define_import_meta_env();
|
|
3372
3165
|
var points = /* @__PURE__ */ new Map();
|
|
3373
3166
|
function point(id) {
|
|
3374
|
-
let
|
|
3375
|
-
if (!
|
|
3376
|
-
|
|
3377
|
-
points.set(id,
|
|
3167
|
+
let registry6 = points.get(id);
|
|
3168
|
+
if (!registry6) {
|
|
3169
|
+
registry6 = createRegistry();
|
|
3170
|
+
points.set(id, registry6);
|
|
3378
3171
|
}
|
|
3379
|
-
return
|
|
3172
|
+
return registry6;
|
|
3380
3173
|
}
|
|
3381
3174
|
function registerExtension(pointId, extension) {
|
|
3382
3175
|
return point(pointId).register(extension);
|
|
@@ -3417,21 +3210,21 @@ init_define_import_meta_env();
|
|
|
3417
3210
|
var actions3 = /* @__PURE__ */ new Map();
|
|
3418
3211
|
var slots = /* @__PURE__ */ new Map();
|
|
3419
3212
|
var contributions = /* @__PURE__ */ new Map();
|
|
3420
|
-
var
|
|
3213
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
3421
3214
|
var snapshots = /* @__PURE__ */ new Map();
|
|
3422
3215
|
var EMPTY = [];
|
|
3423
|
-
function
|
|
3216
|
+
function emit() {
|
|
3424
3217
|
snapshots.clear();
|
|
3425
|
-
for (const listener of
|
|
3218
|
+
for (const listener of listeners) listener();
|
|
3426
3219
|
}
|
|
3427
3220
|
function registerAction(id, handler, options = {}) {
|
|
3428
3221
|
const action = { id, handler, ...options };
|
|
3429
3222
|
actions3.set(id, action);
|
|
3430
|
-
|
|
3223
|
+
emit();
|
|
3431
3224
|
return () => {
|
|
3432
3225
|
if (actions3.get(id) === action) {
|
|
3433
3226
|
actions3.delete(id);
|
|
3434
|
-
|
|
3227
|
+
emit();
|
|
3435
3228
|
}
|
|
3436
3229
|
};
|
|
3437
3230
|
}
|
|
@@ -3451,11 +3244,11 @@ async function invokeAction(id, ...args) {
|
|
|
3451
3244
|
}
|
|
3452
3245
|
function declareActionSlot(slot) {
|
|
3453
3246
|
slots.set(slot.id, slot);
|
|
3454
|
-
|
|
3247
|
+
emit();
|
|
3455
3248
|
return () => {
|
|
3456
3249
|
if (slots.get(slot.id) === slot) {
|
|
3457
3250
|
slots.delete(slot.id);
|
|
3458
|
-
|
|
3251
|
+
emit();
|
|
3459
3252
|
}
|
|
3460
3253
|
};
|
|
3461
3254
|
}
|
|
@@ -3476,7 +3269,7 @@ function registerSlotContribution(slotId, contribution) {
|
|
|
3476
3269
|
}
|
|
3477
3270
|
const stored = { ...contribution, kind };
|
|
3478
3271
|
forSlot.set(contribution.actionId, stored);
|
|
3479
|
-
|
|
3272
|
+
emit();
|
|
3480
3273
|
return () => {
|
|
3481
3274
|
if (contributions.get(slotId)?.get(contribution.actionId) === stored) {
|
|
3482
3275
|
unregisterSlotContribution(slotId, contribution.actionId);
|
|
@@ -3487,7 +3280,7 @@ function unregisterSlotContribution(slotId, actionId) {
|
|
|
3487
3280
|
const forSlot = contributions.get(slotId);
|
|
3488
3281
|
if (!forSlot?.delete(actionId)) return;
|
|
3489
3282
|
if (forSlot.size === 0) contributions.delete(slotId);
|
|
3490
|
-
|
|
3283
|
+
emit();
|
|
3491
3284
|
}
|
|
3492
3285
|
function getSlotContributions(slotId) {
|
|
3493
3286
|
const cached = snapshots.get(slotId);
|
|
@@ -3504,9 +3297,9 @@ function getSlotContributions(slotId) {
|
|
|
3504
3297
|
return sorted;
|
|
3505
3298
|
}
|
|
3506
3299
|
function subscribeToActionRegistry(listener) {
|
|
3507
|
-
|
|
3300
|
+
listeners.add(listener);
|
|
3508
3301
|
return () => {
|
|
3509
|
-
|
|
3302
|
+
listeners.delete(listener);
|
|
3510
3303
|
};
|
|
3511
3304
|
}
|
|
3512
3305
|
function resetActionRegistry() {
|
|
@@ -3514,7 +3307,7 @@ function resetActionRegistry() {
|
|
|
3514
3307
|
slots.clear();
|
|
3515
3308
|
contributions.clear();
|
|
3516
3309
|
snapshots.clear();
|
|
3517
|
-
|
|
3310
|
+
emit();
|
|
3518
3311
|
}
|
|
3519
3312
|
|
|
3520
3313
|
// src/ui/lib/plugin-transport.ts
|
|
@@ -3612,14 +3405,14 @@ async function pluginWsUrl(pluginId, path2, options = {}) {
|
|
|
3612
3405
|
init_define_import_meta_env();
|
|
3613
3406
|
import {
|
|
3614
3407
|
createElement,
|
|
3615
|
-
useSyncExternalStore as
|
|
3408
|
+
useSyncExternalStore as useSyncExternalStore2
|
|
3616
3409
|
} from "react";
|
|
3617
3410
|
var components = /* @__PURE__ */ new Map();
|
|
3618
|
-
var
|
|
3411
|
+
var listeners2 = /* @__PURE__ */ new Set();
|
|
3619
3412
|
var version = 0;
|
|
3620
3413
|
function notify() {
|
|
3621
3414
|
version += 1;
|
|
3622
|
-
for (const listener of
|
|
3415
|
+
for (const listener of listeners2) listener();
|
|
3623
3416
|
}
|
|
3624
3417
|
function registerPluginComponent(id, component) {
|
|
3625
3418
|
components.set(id, component);
|
|
@@ -3632,11 +3425,11 @@ function registerPluginComponent(id, component) {
|
|
|
3632
3425
|
};
|
|
3633
3426
|
}
|
|
3634
3427
|
function subscribe(listener) {
|
|
3635
|
-
|
|
3636
|
-
return () =>
|
|
3428
|
+
listeners2.add(listener);
|
|
3429
|
+
return () => listeners2.delete(listener);
|
|
3637
3430
|
}
|
|
3638
3431
|
function usePluginComponent(id) {
|
|
3639
|
-
|
|
3432
|
+
useSyncExternalStore2(subscribe, () => version);
|
|
3640
3433
|
return components.get(id);
|
|
3641
3434
|
}
|
|
3642
3435
|
function PluginComponent({
|
|
@@ -3730,7 +3523,7 @@ import { createContext, useContext, useEffect as useEffect3, useState as useStat
|
|
|
3730
3523
|
|
|
3731
3524
|
// src/ui/look/theme-registry.ts
|
|
3732
3525
|
init_define_import_meta_env();
|
|
3733
|
-
import { useSyncExternalStore as
|
|
3526
|
+
import { useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
3734
3527
|
var SYSTEM_THEME = "system";
|
|
3735
3528
|
var BUILTIN_THEMES = [
|
|
3736
3529
|
{
|
|
@@ -3749,23 +3542,23 @@ var BUILTIN_THEMES = [
|
|
|
3749
3542
|
var builtins = new Map(BUILTIN_THEMES.map((theme) => [theme.id, theme]));
|
|
3750
3543
|
var pluginThemes = /* @__PURE__ */ new Map();
|
|
3751
3544
|
var pluginThemesKnown = false;
|
|
3752
|
-
var
|
|
3753
|
-
var
|
|
3754
|
-
function
|
|
3755
|
-
|
|
3756
|
-
for (const listener of
|
|
3545
|
+
var listeners3 = /* @__PURE__ */ new Set();
|
|
3546
|
+
var snapshot = null;
|
|
3547
|
+
function emit2() {
|
|
3548
|
+
snapshot = null;
|
|
3549
|
+
for (const listener of listeners3) listener();
|
|
3757
3550
|
}
|
|
3758
3551
|
function listThemes() {
|
|
3759
|
-
if (!
|
|
3552
|
+
if (!snapshot) {
|
|
3760
3553
|
const replaced = BUILTIN_THEMES.map(
|
|
3761
3554
|
(theme) => pluginThemes.get(theme.id) ?? theme
|
|
3762
3555
|
);
|
|
3763
3556
|
const extra = [...pluginThemes.values()].filter(
|
|
3764
3557
|
(theme) => !builtins.has(theme.id)
|
|
3765
3558
|
);
|
|
3766
|
-
|
|
3559
|
+
snapshot = [...replaced, ...extra];
|
|
3767
3560
|
}
|
|
3768
|
-
return
|
|
3561
|
+
return snapshot;
|
|
3769
3562
|
}
|
|
3770
3563
|
function getTheme(id) {
|
|
3771
3564
|
return pluginThemes.get(id) ?? builtins.get(id);
|
|
@@ -3780,16 +3573,16 @@ function setPluginThemes(themes) {
|
|
|
3780
3573
|
});
|
|
3781
3574
|
if (same && !first) return;
|
|
3782
3575
|
pluginThemes = next;
|
|
3783
|
-
|
|
3576
|
+
emit2();
|
|
3784
3577
|
}
|
|
3785
3578
|
function subscribeThemes(listener) {
|
|
3786
|
-
|
|
3579
|
+
listeners3.add(listener);
|
|
3787
3580
|
return () => {
|
|
3788
|
-
|
|
3581
|
+
listeners3.delete(listener);
|
|
3789
3582
|
};
|
|
3790
3583
|
}
|
|
3791
3584
|
function useThemes() {
|
|
3792
|
-
return
|
|
3585
|
+
return useSyncExternalStore3(subscribeThemes, listThemes, listThemes);
|
|
3793
3586
|
}
|
|
3794
3587
|
function themeMode(id) {
|
|
3795
3588
|
if (id === SYSTEM_THEME) {
|
|
@@ -3973,9 +3766,9 @@ function useSshAuthProviders() {
|
|
|
3973
3766
|
|
|
3974
3767
|
// src/ui/hooks/use-action-slot.ts
|
|
3975
3768
|
init_define_import_meta_env();
|
|
3976
|
-
import { useMemo as useMemo3, useSyncExternalStore as
|
|
3769
|
+
import { useMemo as useMemo3, useSyncExternalStore as useSyncExternalStore4 } from "react";
|
|
3977
3770
|
function useActionSlot(slotId, context) {
|
|
3978
|
-
const contributions2 =
|
|
3771
|
+
const contributions2 = useSyncExternalStore4(
|
|
3979
3772
|
subscribeToActionRegistry,
|
|
3980
3773
|
() => getSlotContributions(slotId),
|
|
3981
3774
|
() => getSlotContributions(slotId)
|
|
@@ -4964,28 +4757,28 @@ function restoreSplitTabs(persisted, tabs, openedAt = Date.now()) {
|
|
|
4964
4757
|
|
|
4965
4758
|
// src/ui/shell/split/split-drag.ts
|
|
4966
4759
|
init_define_import_meta_env();
|
|
4967
|
-
import { useSyncExternalStore as
|
|
4760
|
+
import { useSyncExternalStore as useSyncExternalStore5 } from "react";
|
|
4968
4761
|
var state = null;
|
|
4969
4762
|
var hitTest = null;
|
|
4970
4763
|
var dropHandler = null;
|
|
4971
|
-
var
|
|
4972
|
-
function
|
|
4973
|
-
for (const listener of
|
|
4764
|
+
var listeners4 = /* @__PURE__ */ new Set();
|
|
4765
|
+
function emit3() {
|
|
4766
|
+
for (const listener of listeners4) listener();
|
|
4974
4767
|
}
|
|
4975
4768
|
function beginSplitDrag(source, x, y) {
|
|
4976
4769
|
state = { source, x, y, hover: hitTest?.(x, y, source) ?? null };
|
|
4977
|
-
|
|
4770
|
+
emit3();
|
|
4978
4771
|
}
|
|
4979
4772
|
function moveSplitDrag(x, y) {
|
|
4980
4773
|
if (!state) return;
|
|
4981
4774
|
state = { ...state, x, y, hover: hitTest?.(x, y, state.source) ?? null };
|
|
4982
|
-
|
|
4775
|
+
emit3();
|
|
4983
4776
|
}
|
|
4984
4777
|
function endSplitDrag(commit) {
|
|
4985
4778
|
const ended = state;
|
|
4986
4779
|
if (!ended) return;
|
|
4987
4780
|
state = null;
|
|
4988
|
-
|
|
4781
|
+
emit3();
|
|
4989
4782
|
if (commit && ended.hover) dropHandler?.(ended.source, ended.hover);
|
|
4990
4783
|
}
|
|
4991
4784
|
function isSplitDragging() {
|
|
@@ -5004,11 +4797,11 @@ function setSplitDropHandler(next) {
|
|
|
5004
4797
|
};
|
|
5005
4798
|
}
|
|
5006
4799
|
function subscribe2(listener) {
|
|
5007
|
-
|
|
5008
|
-
return () =>
|
|
4800
|
+
listeners4.add(listener);
|
|
4801
|
+
return () => listeners4.delete(listener);
|
|
5009
4802
|
}
|
|
5010
4803
|
function useSplitDrag() {
|
|
5011
|
-
return
|
|
4804
|
+
return useSyncExternalStore5(
|
|
5012
4805
|
subscribe2,
|
|
5013
4806
|
() => state,
|
|
5014
4807
|
() => null
|
|
@@ -5047,18 +4840,18 @@ function dropTargetRect(rect, target) {
|
|
|
5047
4840
|
|
|
5048
4841
|
// src/ui/shell/split/split-targets.ts
|
|
5049
4842
|
init_define_import_meta_env();
|
|
5050
|
-
import { useSyncExternalStore as
|
|
4843
|
+
import { useSyncExternalStore as useSyncExternalStore6 } from "react";
|
|
5051
4844
|
var EMPTY2 = { splits: [], canStartSplit: false };
|
|
5052
|
-
var
|
|
4845
|
+
var snapshot2 = EMPTY2;
|
|
5053
4846
|
var snapshotKey = "";
|
|
5054
4847
|
var opener = null;
|
|
5055
|
-
var
|
|
4848
|
+
var listeners5 = /* @__PURE__ */ new Set();
|
|
5056
4849
|
function publishSplitTargets(next) {
|
|
5057
4850
|
const key = JSON.stringify(next);
|
|
5058
4851
|
if (key === snapshotKey) return;
|
|
5059
4852
|
snapshotKey = key;
|
|
5060
|
-
|
|
5061
|
-
for (const listener of
|
|
4853
|
+
snapshot2 = next;
|
|
4854
|
+
for (const listener of listeners5) listener();
|
|
5062
4855
|
}
|
|
5063
4856
|
function setSplitOpener(next) {
|
|
5064
4857
|
opener = next;
|
|
@@ -5074,13 +4867,13 @@ function openInSplit(target, open) {
|
|
|
5074
4867
|
else open();
|
|
5075
4868
|
}
|
|
5076
4869
|
function subscribe3(listener) {
|
|
5077
|
-
|
|
5078
|
-
return () =>
|
|
4870
|
+
listeners5.add(listener);
|
|
4871
|
+
return () => listeners5.delete(listener);
|
|
5079
4872
|
}
|
|
5080
4873
|
function useSplitTargets() {
|
|
5081
|
-
return
|
|
4874
|
+
return useSyncExternalStore6(
|
|
5082
4875
|
subscribe3,
|
|
5083
|
-
() =>
|
|
4876
|
+
() => snapshot2,
|
|
5084
4877
|
() => EMPTY2
|
|
5085
4878
|
);
|
|
5086
4879
|
}
|
|
@@ -5122,25 +4915,25 @@ function buildLayoutTabSnapshots(tabs, genSlotId = createId) {
|
|
|
5122
4915
|
}));
|
|
5123
4916
|
return { snapshots: snapshots2, slotIdByTabId };
|
|
5124
4917
|
}
|
|
5125
|
-
function snapshotData(
|
|
5126
|
-
if (
|
|
4918
|
+
function snapshotData(snapshot3) {
|
|
4919
|
+
if (snapshot3.data) return snapshot3.data;
|
|
5127
4920
|
const legacy = {};
|
|
5128
|
-
if (
|
|
5129
|
-
if (
|
|
5130
|
-
legacy.initialFilePath =
|
|
5131
|
-
if (
|
|
4921
|
+
if (snapshot3.fleetId !== void 0) legacy.fleetId = snapshot3.fleetId;
|
|
4922
|
+
if (snapshot3.initialFilePath)
|
|
4923
|
+
legacy.initialFilePath = snapshot3.initialFilePath;
|
|
4924
|
+
if (snapshot3.initialPath) legacy.initialPath = snapshot3.initialPath;
|
|
5132
4925
|
return Object.keys(legacy).length > 0 ? legacy : void 0;
|
|
5133
4926
|
}
|
|
5134
|
-
function resolveLayoutTabTarget(
|
|
4927
|
+
function resolveLayoutTabTarget(snapshot3, allHosts) {
|
|
5135
4928
|
let host;
|
|
5136
|
-
if (
|
|
5137
|
-
host = allHosts.find((h) => h.syncId ===
|
|
4929
|
+
if (snapshot3.hostSyncId) {
|
|
4930
|
+
host = allHosts.find((h) => h.syncId === snapshot3.hostSyncId);
|
|
5138
4931
|
if (!host) return { kind: "skip" };
|
|
5139
4932
|
}
|
|
5140
|
-
if (opensAsSingleton(
|
|
4933
|
+
if (opensAsSingleton(snapshot3.type, !!host)) {
|
|
5141
4934
|
return { kind: "singleton", host };
|
|
5142
4935
|
}
|
|
5143
|
-
if (!host && isUnregisteredPluginTabType(
|
|
4936
|
+
if (!host && isUnregisteredPluginTabType(snapshot3.type)) {
|
|
5144
4937
|
return { kind: "singleton" };
|
|
5145
4938
|
}
|
|
5146
4939
|
return host ? { kind: "host", host } : { kind: "skip" };
|
|
@@ -5420,11 +5213,11 @@ function createTabStageStore() {
|
|
|
5420
5213
|
const paneEls = /* @__PURE__ */ new Map();
|
|
5421
5214
|
const listeners9 = /* @__PURE__ */ new Set();
|
|
5422
5215
|
let normalView = null;
|
|
5423
|
-
let
|
|
5216
|
+
let version4 = 0;
|
|
5424
5217
|
let order2 = [];
|
|
5425
5218
|
let lastAnimatedTabId = null;
|
|
5426
5219
|
const bump = () => {
|
|
5427
|
-
|
|
5220
|
+
version4 += 1;
|
|
5428
5221
|
for (const listener of listeners9) listener();
|
|
5429
5222
|
};
|
|
5430
5223
|
function getNode(tabId, ownBackground) {
|
|
@@ -5532,7 +5325,7 @@ function createTabStageStore() {
|
|
|
5532
5325
|
listeners9.delete(listener);
|
|
5533
5326
|
};
|
|
5534
5327
|
},
|
|
5535
|
-
version: () =>
|
|
5328
|
+
version: () => version4
|
|
5536
5329
|
};
|
|
5537
5330
|
}
|
|
5538
5331
|
|
|
@@ -6908,7 +6701,7 @@ function useSplit({
|
|
|
6908
6701
|
useEffect9(() => {
|
|
6909
6702
|
if (!focusedPaneId || !focusedPaneTabId) return;
|
|
6910
6703
|
let attempts = 0;
|
|
6911
|
-
let
|
|
6704
|
+
let timer;
|
|
6912
6705
|
const attempt = () => {
|
|
6913
6706
|
const focused = document.activeElement;
|
|
6914
6707
|
const paneEl = paneEls.get(focusedPaneId);
|
|
@@ -6924,12 +6717,12 @@ function useSplit({
|
|
|
6924
6717
|
handle.focus();
|
|
6925
6718
|
return;
|
|
6926
6719
|
}
|
|
6927
|
-
if (attempts++ < 10)
|
|
6720
|
+
if (attempts++ < 10) timer = setTimeout(attempt, 100);
|
|
6928
6721
|
};
|
|
6929
6722
|
const frame = requestAnimationFrame(attempt);
|
|
6930
6723
|
return () => {
|
|
6931
6724
|
cancelAnimationFrame(frame);
|
|
6932
|
-
if (
|
|
6725
|
+
if (timer) clearTimeout(timer);
|
|
6933
6726
|
};
|
|
6934
6727
|
}, [focusedPaneId, focusedPaneTabId]);
|
|
6935
6728
|
useEffect9(() => {
|
|
@@ -7047,34 +6840,34 @@ function useWorkspaceLayout(tabsState, regions) {
|
|
|
7047
6840
|
try {
|
|
7048
6841
|
const slotIdToNewTabId = /* @__PURE__ */ new Map();
|
|
7049
6842
|
const skippedTabs = [];
|
|
7050
|
-
for (const
|
|
7051
|
-
const target = resolveLayoutTabTarget(
|
|
6843
|
+
for (const snapshot3 of payload.tabs) {
|
|
6844
|
+
const target = resolveLayoutTabTarget(snapshot3, hostsRef.current);
|
|
7052
6845
|
if (target.kind === "skip") {
|
|
7053
|
-
skippedTabs.push(
|
|
6846
|
+
skippedTabs.push(snapshot3.hostNameSnapshot || snapshot3.label);
|
|
7054
6847
|
continue;
|
|
7055
6848
|
}
|
|
7056
6849
|
if (target.kind === "singleton") {
|
|
7057
6850
|
const newTabId = tabsState.openSingletonTab(
|
|
7058
|
-
|
|
6851
|
+
snapshot3.type,
|
|
7059
6852
|
void 0,
|
|
7060
6853
|
target.host,
|
|
7061
|
-
snapshotData(
|
|
6854
|
+
snapshotData(snapshot3)
|
|
7062
6855
|
);
|
|
7063
|
-
slotIdToNewTabId.set(
|
|
6856
|
+
slotIdToNewTabId.set(snapshot3.slotId, newTabId ?? snapshot3.type);
|
|
7064
6857
|
continue;
|
|
7065
6858
|
}
|
|
7066
6859
|
if (target.kind === "host") {
|
|
7067
6860
|
const newTabId = tabsState.openTab(
|
|
7068
6861
|
target.host,
|
|
7069
|
-
|
|
6862
|
+
snapshot3.type,
|
|
7070
6863
|
{
|
|
7071
6864
|
instanceId: createId(),
|
|
7072
6865
|
restoredSessionId: null,
|
|
7073
|
-
savedLabel:
|
|
6866
|
+
savedLabel: snapshot3.customLabel ?? snapshot3.label
|
|
7074
6867
|
},
|
|
7075
|
-
{ data: snapshotData(
|
|
6868
|
+
{ data: snapshotData(snapshot3) }
|
|
7076
6869
|
);
|
|
7077
|
-
slotIdToNewTabId.set(
|
|
6870
|
+
slotIdToNewTabId.set(snapshot3.slotId, newTabId);
|
|
7078
6871
|
}
|
|
7079
6872
|
}
|
|
7080
6873
|
const splitIdBySlotId = /* @__PURE__ */ new Map();
|
|
@@ -7161,7 +6954,7 @@ function useShellKeybindings({
|
|
|
7161
6954
|
toggleFullscreenRef.current = toggleFullscreen;
|
|
7162
6955
|
useEffect11(() => {
|
|
7163
6956
|
let cancelled = false;
|
|
7164
|
-
const
|
|
6957
|
+
const load2 = () => {
|
|
7165
6958
|
getUserPreferences().then((prefs) => {
|
|
7166
6959
|
if (cancelled) return;
|
|
7167
6960
|
globalKeybindingsRef.current = parseCustomKeybindings(
|
|
@@ -7170,11 +6963,11 @@ function useShellKeybindings({
|
|
|
7170
6963
|
}).catch(() => {
|
|
7171
6964
|
});
|
|
7172
6965
|
};
|
|
7173
|
-
|
|
7174
|
-
window.addEventListener("customKeybindingsChanged",
|
|
6966
|
+
load2();
|
|
6967
|
+
window.addEventListener("customKeybindingsChanged", load2);
|
|
7175
6968
|
return () => {
|
|
7176
6969
|
cancelled = true;
|
|
7177
|
-
window.removeEventListener("customKeybindingsChanged",
|
|
6970
|
+
window.removeEventListener("customKeybindingsChanged", load2);
|
|
7178
6971
|
};
|
|
7179
6972
|
}, []);
|
|
7180
6973
|
useEffect11(() => {
|
|
@@ -7539,19 +7332,19 @@ function useShellLifecycle({
|
|
|
7539
7332
|
|
|
7540
7333
|
// src/ui/shell/controller/shell-store.ts
|
|
7541
7334
|
init_define_import_meta_env();
|
|
7542
|
-
import { useSyncExternalStore as
|
|
7335
|
+
import { useSyncExternalStore as useSyncExternalStore7 } from "react";
|
|
7543
7336
|
var current = null;
|
|
7544
|
-
var
|
|
7337
|
+
var listeners6 = /* @__PURE__ */ new Set();
|
|
7545
7338
|
function publishShellController(next) {
|
|
7546
7339
|
if (next === current) return;
|
|
7547
7340
|
current = next;
|
|
7548
|
-
for (const listener of
|
|
7341
|
+
for (const listener of listeners6) listener();
|
|
7549
7342
|
}
|
|
7550
7343
|
function useShellSnapshot() {
|
|
7551
|
-
return
|
|
7344
|
+
return useSyncExternalStore7(
|
|
7552
7345
|
(listener) => {
|
|
7553
|
-
|
|
7554
|
-
return () =>
|
|
7346
|
+
listeners6.add(listener);
|
|
7347
|
+
return () => listeners6.delete(listener);
|
|
7555
7348
|
},
|
|
7556
7349
|
() => current,
|
|
7557
7350
|
() => current
|
|
@@ -7622,7 +7415,6 @@ function ShellControllerProvider({
|
|
|
7622
7415
|
});
|
|
7623
7416
|
openSingletonRef.current = tabsState.openSingletonTab;
|
|
7624
7417
|
const { tabs, activeTabId } = tabsState;
|
|
7625
|
-
useSyncStatus();
|
|
7626
7418
|
const palette = {
|
|
7627
7419
|
isOpen: paletteOpen,
|
|
7628
7420
|
open: () => setPaletteOpen(true),
|
|
@@ -7821,25 +7613,25 @@ function computeAdaptivePollDelay(policy, state2, random = Math.random) {
|
|
|
7821
7613
|
const jitter = base * jitterRatio * (random() * 2 - 1);
|
|
7822
7614
|
return Math.max(min, Math.min(max, Math.round(base + jitter)));
|
|
7823
7615
|
}
|
|
7824
|
-
function runAdaptivePolling(
|
|
7616
|
+
function runAdaptivePolling(poll, policy, options = {}) {
|
|
7825
7617
|
const enabled = options.enabled ?? (() => true);
|
|
7826
7618
|
const visible = options.visible ?? (() => typeof document === "undefined" || document.visibilityState !== "hidden");
|
|
7827
7619
|
const state2 = {
|
|
7828
7620
|
stablePolls: 0,
|
|
7829
7621
|
consecutiveFailures: 0
|
|
7830
7622
|
};
|
|
7831
|
-
let
|
|
7623
|
+
let timer = null;
|
|
7832
7624
|
let stopped = false;
|
|
7833
7625
|
let inFlight = false;
|
|
7834
7626
|
const clearTimer = () => {
|
|
7835
|
-
if (!
|
|
7836
|
-
clearTimeout(
|
|
7837
|
-
|
|
7627
|
+
if (!timer) return;
|
|
7628
|
+
clearTimeout(timer);
|
|
7629
|
+
timer = null;
|
|
7838
7630
|
};
|
|
7839
|
-
const
|
|
7631
|
+
const schedule = () => {
|
|
7840
7632
|
clearTimer();
|
|
7841
7633
|
if (stopped || !enabled() || !visible()) return;
|
|
7842
|
-
|
|
7634
|
+
timer = setTimeout(
|
|
7843
7635
|
() => void tick(),
|
|
7844
7636
|
Math.min(
|
|
7845
7637
|
policy.maxIntervalMs,
|
|
@@ -7854,7 +7646,7 @@ function runAdaptivePolling(poll2, policy, options = {}) {
|
|
|
7854
7646
|
inFlight = true;
|
|
7855
7647
|
const startedAt = Date.now();
|
|
7856
7648
|
try {
|
|
7857
|
-
const changed = await
|
|
7649
|
+
const changed = await poll();
|
|
7858
7650
|
state2.consecutiveFailures = 0;
|
|
7859
7651
|
state2.stablePolls = changed === false ? state2.stablePolls + 1 : 0;
|
|
7860
7652
|
} catch (error) {
|
|
@@ -7864,7 +7656,7 @@ function runAdaptivePolling(poll2, policy, options = {}) {
|
|
|
7864
7656
|
} finally {
|
|
7865
7657
|
state2.lastPollDurationMs = Date.now() - startedAt;
|
|
7866
7658
|
inFlight = false;
|
|
7867
|
-
|
|
7659
|
+
schedule();
|
|
7868
7660
|
}
|
|
7869
7661
|
};
|
|
7870
7662
|
const onVisibility = () => {
|
|
@@ -7880,7 +7672,7 @@ function runAdaptivePolling(poll2, policy, options = {}) {
|
|
|
7880
7672
|
document.addEventListener("visibilitychange", onVisibility);
|
|
7881
7673
|
}
|
|
7882
7674
|
if (options.runImmediately ?? true) void tick();
|
|
7883
|
-
else
|
|
7675
|
+
else schedule();
|
|
7884
7676
|
return () => {
|
|
7885
7677
|
stopped = true;
|
|
7886
7678
|
clearTimer();
|
|
@@ -7906,7 +7698,7 @@ import {
|
|
|
7906
7698
|
useCallback as useCallback7,
|
|
7907
7699
|
useRef as useRef7,
|
|
7908
7700
|
useMemo as useMemo6,
|
|
7909
|
-
useSyncExternalStore as
|
|
7701
|
+
useSyncExternalStore as useSyncExternalStore8,
|
|
7910
7702
|
useState as useState13
|
|
7911
7703
|
} from "react";
|
|
7912
7704
|
|
|
@@ -8018,7 +7810,7 @@ function ServerStatusProvider({
|
|
|
8018
7810
|
storeRef.current = new ServerStatusStore();
|
|
8019
7811
|
}
|
|
8020
7812
|
const store = storeRef.current;
|
|
8021
|
-
const [
|
|
7813
|
+
const [version4, setVersion] = useState13(0);
|
|
8022
7814
|
const mountedRef = useRef7(true);
|
|
8023
7815
|
const refreshInFlightRef = useRef7(null);
|
|
8024
7816
|
useEffect14(() => store.subscribeAll(() => setVersion((v) => v + 1)), [store]);
|
|
@@ -8101,7 +7893,7 @@ function ServerStatusProvider({
|
|
|
8101
7893
|
}),
|
|
8102
7894
|
// version refreshes the statuses/initialLoadComplete snapshots
|
|
8103
7895
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
8104
|
-
[
|
|
7896
|
+
[version4, refreshStatuses, getStatus]
|
|
8105
7897
|
);
|
|
8106
7898
|
return /* @__PURE__ */ jsx8(StatusStoreContext.Provider, { value: store, children: /* @__PURE__ */ jsx8(ServerStatusContext.Provider, { value: contextValue, children }) });
|
|
8107
7899
|
}
|
|
@@ -8123,7 +7915,7 @@ function useServerStatus() {
|
|
|
8123
7915
|
}
|
|
8124
7916
|
function useHostStatus(hostId, statusCheckEnabled = true) {
|
|
8125
7917
|
const store = useStatusStore();
|
|
8126
|
-
const status =
|
|
7918
|
+
const status = useSyncExternalStore8(
|
|
8127
7919
|
(onChange) => store.subscribeHost(hostId, onChange),
|
|
8128
7920
|
() => store.getStatus(hostId),
|
|
8129
7921
|
() => store.getStatus(hostId)
|
|
@@ -8132,7 +7924,7 @@ function useHostStatus(hostId, statusCheckEnabled = true) {
|
|
|
8132
7924
|
}
|
|
8133
7925
|
function useServerStatusMeta() {
|
|
8134
7926
|
const store = useStatusStore();
|
|
8135
|
-
|
|
7927
|
+
useSyncExternalStore8(
|
|
8136
7928
|
(onChange) => store.subscribeMeta(onChange),
|
|
8137
7929
|
() => store.getMetaSnapshot(),
|
|
8138
7930
|
() => store.getMetaSnapshot()
|
|
@@ -8142,7 +7934,7 @@ function useServerStatusMeta() {
|
|
|
8142
7934
|
var noStatus = () => "unknown";
|
|
8143
7935
|
function useOptionalHostStatusEntry(hostId) {
|
|
8144
7936
|
const store = useContext4(StatusStoreContext);
|
|
8145
|
-
const status =
|
|
7937
|
+
const status = useSyncExternalStore8(
|
|
8146
7938
|
(onChange) => store && hostId !== void 0 ? store.subscribeHost(hostId, onChange) : () => {
|
|
8147
7939
|
},
|
|
8148
7940
|
() => store && hostId !== void 0 ? store.getStatus(hostId) : "unknown",
|
|
@@ -8394,7 +8186,7 @@ var pluginHostBridge = {
|
|
|
8394
8186
|
window.removeEventListener(PLUGIN_SETTINGS_CHANGED_EVENT, onChanged);
|
|
8395
8187
|
};
|
|
8396
8188
|
}, [pluginId, scope, numericHostId]);
|
|
8397
|
-
const
|
|
8189
|
+
const save2 = useCallback8(
|
|
8398
8190
|
async (values) => {
|
|
8399
8191
|
const saved = await SETTINGS_WRITERS[scope](
|
|
8400
8192
|
pluginId,
|
|
@@ -8405,7 +8197,7 @@ var pluginHostBridge = {
|
|
|
8405
8197
|
},
|
|
8406
8198
|
[pluginId, scope, numericHostId]
|
|
8407
8199
|
);
|
|
8408
|
-
return useMemo8(() => ({ ...state2, save }), [state2,
|
|
8200
|
+
return useMemo8(() => ({ ...state2, save: save2 }), [state2, save2]);
|
|
8409
8201
|
},
|
|
8410
8202
|
useHost(hostId) {
|
|
8411
8203
|
const pluginId = usePluginScope();
|
|
@@ -8578,7 +8370,7 @@ function onRemoteServerChange(listener) {
|
|
|
8578
8370
|
|
|
8579
8371
|
// src/ui/look/layout-registry.ts
|
|
8580
8372
|
init_define_import_meta_env();
|
|
8581
|
-
import { useSyncExternalStore as
|
|
8373
|
+
import { useSyncExternalStore as useSyncExternalStore9 } from "react";
|
|
8582
8374
|
var descriptorSnapshot = [];
|
|
8583
8375
|
var descriptorListeners = /* @__PURE__ */ new Set();
|
|
8584
8376
|
var registered = createRegistry();
|
|
@@ -8604,7 +8396,7 @@ function subscribeDescriptors(listener) {
|
|
|
8604
8396
|
};
|
|
8605
8397
|
}
|
|
8606
8398
|
function useLayouts() {
|
|
8607
|
-
return
|
|
8399
|
+
return useSyncExternalStore9(subscribeDescriptors, listLayouts, listLayouts);
|
|
8608
8400
|
}
|
|
8609
8401
|
function layoutLabel(layout, t) {
|
|
8610
8402
|
if (!layout.pluginId) return layout.label;
|
|
@@ -8615,6 +8407,86 @@ function layoutLabel(layout, t) {
|
|
|
8615
8407
|
|
|
8616
8408
|
// src/ui/plugin-host/app.ts
|
|
8617
8409
|
init_define_import_meta_env();
|
|
8410
|
+
import { useEffect as useEffect16 } from "react";
|
|
8411
|
+
|
|
8412
|
+
// src/ui/shell/companions.ts
|
|
8413
|
+
init_define_import_meta_env();
|
|
8414
|
+
import { useSyncExternalStore as useSyncExternalStore10 } from "react";
|
|
8415
|
+
var registry5 = createRegistry(byOrderThenId);
|
|
8416
|
+
var registerCompanionDef = registry5.register;
|
|
8417
|
+
var getCompanionDef = registry5.get;
|
|
8418
|
+
var listCompanionDefs = registry5.list;
|
|
8419
|
+
var useCompanionDefs = registry5.useList;
|
|
8420
|
+
var resetCompanions = registry5.reset;
|
|
8421
|
+
function companionApplies(def, tab) {
|
|
8422
|
+
if (!tab.host) return false;
|
|
8423
|
+
if (def.tabTypes?.length && !def.tabTypes.includes(tab.type)) return false;
|
|
8424
|
+
return def.when ? def.when(tab, tab.host) : true;
|
|
8425
|
+
}
|
|
8426
|
+
var STORAGE_KEY = "termix:companions";
|
|
8427
|
+
var EMPTY3 = { openId: null, seen: false };
|
|
8428
|
+
var states = /* @__PURE__ */ new Map();
|
|
8429
|
+
var listeners7 = /* @__PURE__ */ new Set();
|
|
8430
|
+
var version2 = 0;
|
|
8431
|
+
function load() {
|
|
8432
|
+
try {
|
|
8433
|
+
const raw = localStorage.getItem(STORAGE_KEY);
|
|
8434
|
+
if (!raw) return;
|
|
8435
|
+
const parsed = JSON.parse(raw);
|
|
8436
|
+
states = new Map(Object.entries(parsed));
|
|
8437
|
+
} catch {
|
|
8438
|
+
}
|
|
8439
|
+
}
|
|
8440
|
+
function save() {
|
|
8441
|
+
try {
|
|
8442
|
+
const entries = [...states.entries()].slice(-200);
|
|
8443
|
+
localStorage.setItem(
|
|
8444
|
+
STORAGE_KEY,
|
|
8445
|
+
JSON.stringify(Object.fromEntries(entries))
|
|
8446
|
+
);
|
|
8447
|
+
} catch {
|
|
8448
|
+
}
|
|
8449
|
+
}
|
|
8450
|
+
load();
|
|
8451
|
+
function companionKey(tab) {
|
|
8452
|
+
return tab.instanceId ?? tab.id;
|
|
8453
|
+
}
|
|
8454
|
+
function getCompanionState(key) {
|
|
8455
|
+
return states.get(key) ?? EMPTY3;
|
|
8456
|
+
}
|
|
8457
|
+
function patchCompanionState(key, patch) {
|
|
8458
|
+
const next = { ...getCompanionState(key), ...patch };
|
|
8459
|
+
states = new Map(states);
|
|
8460
|
+
states.delete(key);
|
|
8461
|
+
states.set(key, next);
|
|
8462
|
+
version2 += 1;
|
|
8463
|
+
save();
|
|
8464
|
+
for (const listener of listeners7) listener();
|
|
8465
|
+
}
|
|
8466
|
+
function subscribe4(listener) {
|
|
8467
|
+
listeners7.add(listener);
|
|
8468
|
+
return () => listeners7.delete(listener);
|
|
8469
|
+
}
|
|
8470
|
+
function useCompanionState(key) {
|
|
8471
|
+
useSyncExternalStore10(
|
|
8472
|
+
subscribe4,
|
|
8473
|
+
() => version2,
|
|
8474
|
+
() => version2
|
|
8475
|
+
);
|
|
8476
|
+
return getCompanionState(key);
|
|
8477
|
+
}
|
|
8478
|
+
function toggleCompanion(tab, id) {
|
|
8479
|
+
const key = companionKey(tab);
|
|
8480
|
+
const current2 = getCompanionState(key);
|
|
8481
|
+
const target = id ?? current2.openId ?? listCompanionDefs().find((def) => companionApplies(def, tab))?.id ?? null;
|
|
8482
|
+
if (!target) return;
|
|
8483
|
+
patchCompanionState(key, {
|
|
8484
|
+
seen: true,
|
|
8485
|
+
openId: current2.openId === target ? null : target
|
|
8486
|
+
});
|
|
8487
|
+
}
|
|
8488
|
+
|
|
8489
|
+
// src/ui/plugin-host/app.ts
|
|
8618
8490
|
var ONBOARDING_ID = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
8619
8491
|
function createDocsApi(manifest) {
|
|
8620
8492
|
const url = pluginDocsUrl(manifest?.docs);
|
|
@@ -8709,6 +8581,40 @@ function createPluginApp(pluginId, manifest, contributes, options = {}) {
|
|
|
8709
8581
|
})
|
|
8710
8582
|
);
|
|
8711
8583
|
},
|
|
8584
|
+
registerCompanion(id, component, options2 = {}) {
|
|
8585
|
+
const useDefaults = options2.useDefaults;
|
|
8586
|
+
const Defaults = useDefaults ? scoped(function CompanionDefaultsReader({
|
|
8587
|
+
onValue
|
|
8588
|
+
}) {
|
|
8589
|
+
const value = useDefaults();
|
|
8590
|
+
const { open, side, size, edgeButton } = value;
|
|
8591
|
+
useEffect16(() => {
|
|
8592
|
+
onValue({ open, side, size, edgeButton });
|
|
8593
|
+
}, [onValue, open, side, size, edgeButton]);
|
|
8594
|
+
return null;
|
|
8595
|
+
}) : void 0;
|
|
8596
|
+
return track(
|
|
8597
|
+
registerCompanionDef({
|
|
8598
|
+
id: `${pluginId}.${id}`,
|
|
8599
|
+
pluginId,
|
|
8600
|
+
component: scoped(
|
|
8601
|
+
component
|
|
8602
|
+
),
|
|
8603
|
+
icon: withIconBoundary(pluginId, options2.icon),
|
|
8604
|
+
titleKey: options2.titleKey ? key(options2.titleKey) : void 0,
|
|
8605
|
+
order: options2.order,
|
|
8606
|
+
tabTypes: options2.tabTypes,
|
|
8607
|
+
when: options2.when,
|
|
8608
|
+
Defaults
|
|
8609
|
+
})
|
|
8610
|
+
);
|
|
8611
|
+
},
|
|
8612
|
+
toggleCompanion(tab, id) {
|
|
8613
|
+
toggleCompanion(
|
|
8614
|
+
tab,
|
|
8615
|
+
id ? `${pluginId}.${id}` : void 0
|
|
8616
|
+
);
|
|
8617
|
+
},
|
|
8712
8618
|
registerTab(type, component, options2 = {}) {
|
|
8713
8619
|
requireDeclared("tab", type, "tab type");
|
|
8714
8620
|
return track(
|
|
@@ -8960,8 +8866,8 @@ function createPluginApp(pluginId, manifest, contributes, options = {}) {
|
|
|
8960
8866
|
},
|
|
8961
8867
|
registerOnboardingStep(step) {
|
|
8962
8868
|
requireStepId(step.id, "onboarding step");
|
|
8963
|
-
const
|
|
8964
|
-
if (!Number.isInteger(
|
|
8869
|
+
const version4 = step.version ?? 1;
|
|
8870
|
+
if (!Number.isInteger(version4) || version4 < 1) {
|
|
8965
8871
|
throw new Error(
|
|
8966
8872
|
`${pluginId}: onboarding step "${step.id}" needs a whole version of 1 or more`
|
|
8967
8873
|
);
|
|
@@ -8971,7 +8877,7 @@ function createPluginApp(pluginId, manifest, contributes, options = {}) {
|
|
|
8971
8877
|
onboardingSteps.register({
|
|
8972
8878
|
id: pluginStepKey(pluginId, step.id),
|
|
8973
8879
|
pluginId,
|
|
8974
|
-
version:
|
|
8880
|
+
version: version4,
|
|
8975
8881
|
titleKey: key(step.titleKey),
|
|
8976
8882
|
descriptionKey: step.descriptionKey ? key(step.descriptionKey) : void 0,
|
|
8977
8883
|
icon: step.icon ? withIconBoundary(pluginId, step.icon) : void 0,
|
|
@@ -9111,24 +9017,24 @@ function createPluginApp(pluginId, manifest, contributes, options = {}) {
|
|
|
9111
9017
|
|
|
9112
9018
|
// src/ui/hooks/use-installed-plugins.ts
|
|
9113
9019
|
init_define_import_meta_env();
|
|
9114
|
-
import { useEffect as
|
|
9020
|
+
import { useEffect as useEffect17, useState as useState15 } from "react";
|
|
9115
9021
|
function useInstalledPlugins() {
|
|
9116
9022
|
const [plugins, setPlugins] = useState15([]);
|
|
9117
|
-
|
|
9023
|
+
useEffect17(() => {
|
|
9118
9024
|
let cancelled = false;
|
|
9119
9025
|
let request = 0;
|
|
9120
|
-
const
|
|
9026
|
+
const load2 = () => {
|
|
9121
9027
|
const current2 = ++request;
|
|
9122
9028
|
void getPlugins().then((loaded) => {
|
|
9123
9029
|
if (!cancelled && current2 === request) setPlugins(loaded);
|
|
9124
9030
|
}).catch(() => {
|
|
9125
9031
|
});
|
|
9126
9032
|
};
|
|
9127
|
-
|
|
9128
|
-
window.addEventListener(PLUGINS_CHANGED_EVENT,
|
|
9033
|
+
load2();
|
|
9034
|
+
window.addEventListener(PLUGINS_CHANGED_EVENT, load2);
|
|
9129
9035
|
return () => {
|
|
9130
9036
|
cancelled = true;
|
|
9131
|
-
window.removeEventListener(PLUGINS_CHANGED_EVENT,
|
|
9037
|
+
window.removeEventListener(PLUGINS_CHANGED_EVENT, load2);
|
|
9132
9038
|
};
|
|
9133
9039
|
}, []);
|
|
9134
9040
|
return plugins;
|
|
@@ -9549,10 +9455,10 @@ function ComponentSlot({
|
|
|
9549
9455
|
// src/ui/shell/tab-handles.ts
|
|
9550
9456
|
init_define_import_meta_env();
|
|
9551
9457
|
import { useSyncExternalStore as useSyncExternalStore11 } from "react";
|
|
9552
|
-
var
|
|
9458
|
+
var version3 = 0;
|
|
9553
9459
|
var listeners8 = /* @__PURE__ */ new Set();
|
|
9554
9460
|
var callbacks = /* @__PURE__ */ new WeakMap();
|
|
9555
|
-
function
|
|
9461
|
+
function subscribe5(listener) {
|
|
9556
9462
|
listeners8.add(listener);
|
|
9557
9463
|
return () => listeners8.delete(listener);
|
|
9558
9464
|
}
|
|
@@ -9563,7 +9469,7 @@ function trackTabHandle(ref) {
|
|
|
9563
9469
|
callback = (value) => {
|
|
9564
9470
|
if (ref.current === value) return;
|
|
9565
9471
|
ref.current = value;
|
|
9566
|
-
|
|
9472
|
+
version3 += 1;
|
|
9567
9473
|
for (const listener of listeners8) listener();
|
|
9568
9474
|
};
|
|
9569
9475
|
callbacks.set(ref, callback);
|
|
@@ -9572,9 +9478,9 @@ function trackTabHandle(ref) {
|
|
|
9572
9478
|
}
|
|
9573
9479
|
function useTabHandlesVersion() {
|
|
9574
9480
|
return useSyncExternalStore11(
|
|
9575
|
-
|
|
9576
|
-
() =>
|
|
9577
|
-
() =>
|
|
9481
|
+
subscribe5,
|
|
9482
|
+
() => version3,
|
|
9483
|
+
() => version3
|
|
9578
9484
|
);
|
|
9579
9485
|
}
|
|
9580
9486
|
|
|
@@ -10018,8 +9924,8 @@ function runAdaptiveBackgroundTask(kind, action, task, options = {}) {
|
|
|
10018
9924
|
|
|
10019
9925
|
// src/ui/shell/tabUtils.tsx
|
|
10020
9926
|
init_define_import_meta_env();
|
|
10021
|
-
import { lazy, memo, Suspense } from "react";
|
|
10022
|
-
import { useTranslation as
|
|
9927
|
+
import { lazy, memo as memo2, Suspense } from "react";
|
|
9928
|
+
import { useTranslation as useTranslation9 } from "react-i18next";
|
|
10023
9929
|
|
|
10024
9930
|
// src/ui/lib/host-to-ssh-host.ts
|
|
10025
9931
|
init_define_import_meta_env();
|
|
@@ -10057,10 +9963,258 @@ function hostToSSHHost(h) {
|
|
|
10057
9963
|
};
|
|
10058
9964
|
}
|
|
10059
9965
|
|
|
9966
|
+
// src/ui/shell/CompanionFrame.tsx
|
|
9967
|
+
init_define_import_meta_env();
|
|
9968
|
+
import {
|
|
9969
|
+
memo,
|
|
9970
|
+
useCallback as useCallback9,
|
|
9971
|
+
useEffect as useEffect18,
|
|
9972
|
+
useMemo as useMemo10,
|
|
9973
|
+
useRef as useRef8,
|
|
9974
|
+
useState as useState16
|
|
9975
|
+
} from "react";
|
|
9976
|
+
import { useTranslation as useTranslation8 } from "react-i18next";
|
|
9977
|
+
import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
9978
|
+
var DEFAULT_SIDE_SIZE = 360;
|
|
9979
|
+
var DEFAULT_BOTTOM_SIZE = 280;
|
|
9980
|
+
var MIN_SIZE = 200;
|
|
9981
|
+
function DefaultsReader({
|
|
9982
|
+
def,
|
|
9983
|
+
onValue
|
|
9984
|
+
}) {
|
|
9985
|
+
const Reader = def.Defaults;
|
|
9986
|
+
const report = useCallback9(
|
|
9987
|
+
(value) => onValue(def.id, value),
|
|
9988
|
+
[def.id, onValue]
|
|
9989
|
+
);
|
|
9990
|
+
return Reader ? /* @__PURE__ */ jsx13(Reader, { onValue: report }) : null;
|
|
9991
|
+
}
|
|
9992
|
+
function sideIcon(side) {
|
|
9993
|
+
if (side === "left") return ArrowLeftToLine;
|
|
9994
|
+
if (side === "bottom") return ArrowDownToLine;
|
|
9995
|
+
return ArrowRightToLine;
|
|
9996
|
+
}
|
|
9997
|
+
var CompanionFrame = memo(function CompanionFrame2({
|
|
9998
|
+
tab,
|
|
9999
|
+
isVisible,
|
|
10000
|
+
children
|
|
10001
|
+
}) {
|
|
10002
|
+
const defs = useCompanionDefs();
|
|
10003
|
+
const applicable = useMemo10(
|
|
10004
|
+
() => defs.filter((def) => companionApplies(def, tab)),
|
|
10005
|
+
// tab.host and tab.type decide it
|
|
10006
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
10007
|
+
[defs, tab.type, tab.host]
|
|
10008
|
+
);
|
|
10009
|
+
if (applicable.length === 0) return /* @__PURE__ */ jsx13(Fragment3, { children });
|
|
10010
|
+
return /* @__PURE__ */ jsx13(CompanionLayout, { tab, defs: applicable, isVisible, children });
|
|
10011
|
+
});
|
|
10012
|
+
function CompanionLayout({
|
|
10013
|
+
tab,
|
|
10014
|
+
defs,
|
|
10015
|
+
isVisible,
|
|
10016
|
+
children
|
|
10017
|
+
}) {
|
|
10018
|
+
const { t } = useTranslation8();
|
|
10019
|
+
const isMobile = useIsMobile();
|
|
10020
|
+
const key = companionKey(tab);
|
|
10021
|
+
const state2 = useCompanionState(key);
|
|
10022
|
+
const [defaults3, setDefaults] = useState16(
|
|
10023
|
+
{}
|
|
10024
|
+
);
|
|
10025
|
+
const [dragging, setDragging] = useState16(false);
|
|
10026
|
+
const [mounted, setMounted] = useState16(/* @__PURE__ */ new Set());
|
|
10027
|
+
const rootRef = useRef8(null);
|
|
10028
|
+
const onDefaults = useCallback9((id, value) => {
|
|
10029
|
+
setDefaults((prev) => {
|
|
10030
|
+
const old = prev[id];
|
|
10031
|
+
if (old && old.open === value.open && old.side === value.side && old.size === value.size && old.edgeButton === value.edgeButton) {
|
|
10032
|
+
return prev;
|
|
10033
|
+
}
|
|
10034
|
+
return { ...prev, [id]: value };
|
|
10035
|
+
});
|
|
10036
|
+
}, []);
|
|
10037
|
+
useEffect18(() => {
|
|
10038
|
+
if (state2.seen || !isVisible) return;
|
|
10039
|
+
const ready = defs.every(
|
|
10040
|
+
(def) => !def.Defaults || defaults3[def.id] !== void 0
|
|
10041
|
+
);
|
|
10042
|
+
if (!ready) return;
|
|
10043
|
+
const auto = defs.find((def) => defaults3[def.id]?.open);
|
|
10044
|
+
patchCompanionState(key, { seen: true, openId: auto?.id ?? null });
|
|
10045
|
+
}, [state2.seen, isVisible, defs, defaults3, key]);
|
|
10046
|
+
const active = defs.find((def) => def.id === state2.openId) ?? null;
|
|
10047
|
+
useEffect18(() => {
|
|
10048
|
+
if (!active) return;
|
|
10049
|
+
setMounted(
|
|
10050
|
+
(prev) => prev.has(active.id) ? prev : new Set(prev).add(active.id)
|
|
10051
|
+
);
|
|
10052
|
+
}, [active]);
|
|
10053
|
+
const activeDefaults = active ? defaults3[active.id] : void 0;
|
|
10054
|
+
const side = isMobile ? "bottom" : state2.side ?? activeDefaults?.side ?? "right";
|
|
10055
|
+
const baseSize = state2.size ?? activeDefaults?.size ?? (side === "bottom" ? DEFAULT_BOTTOM_SIZE : DEFAULT_SIDE_SIZE);
|
|
10056
|
+
const setSide = useCallback9(
|
|
10057
|
+
(next) => patchCompanionState(key, { side: next }),
|
|
10058
|
+
[key]
|
|
10059
|
+
);
|
|
10060
|
+
const close = useCallback9(
|
|
10061
|
+
() => patchCompanionState(key, { openId: null }),
|
|
10062
|
+
[key]
|
|
10063
|
+
);
|
|
10064
|
+
const startResize = (event) => {
|
|
10065
|
+
event.preventDefault();
|
|
10066
|
+
const root = rootRef.current;
|
|
10067
|
+
if (!root) return;
|
|
10068
|
+
const rect = root.getBoundingClientRect();
|
|
10069
|
+
const total = side === "bottom" ? rect.height : rect.width;
|
|
10070
|
+
const max = Math.max(MIN_SIZE, total - MIN_SIZE);
|
|
10071
|
+
setDragging(true);
|
|
10072
|
+
const move = (e) => {
|
|
10073
|
+
const raw = side === "right" ? rect.right - e.clientX : side === "left" ? e.clientX - rect.left : rect.bottom - e.clientY;
|
|
10074
|
+
patchCompanionState(key, {
|
|
10075
|
+
size: Math.round(Math.min(max, Math.max(MIN_SIZE, raw)))
|
|
10076
|
+
});
|
|
10077
|
+
};
|
|
10078
|
+
const up = () => {
|
|
10079
|
+
setDragging(false);
|
|
10080
|
+
window.removeEventListener("mousemove", move);
|
|
10081
|
+
window.removeEventListener("mouseup", up);
|
|
10082
|
+
};
|
|
10083
|
+
window.addEventListener("mousemove", move);
|
|
10084
|
+
window.addEventListener("mouseup", up);
|
|
10085
|
+
};
|
|
10086
|
+
const getHandle = useCallback9(
|
|
10087
|
+
() => tab.terminalRef?.current ?? null,
|
|
10088
|
+
[tab.terminalRef]
|
|
10089
|
+
);
|
|
10090
|
+
const sshHost = useMemo10(
|
|
10091
|
+
() => tab.host ? hostToSSHHost(tab.host) : void 0,
|
|
10092
|
+
[tab.host]
|
|
10093
|
+
);
|
|
10094
|
+
const showEdge = defs.filter((def) => defaults3[def.id]?.edgeButton !== false);
|
|
10095
|
+
const vertical = side === "bottom";
|
|
10096
|
+
const clamped = vertical ? Math.min(baseSize, 2e3) : baseSize;
|
|
10097
|
+
const paneStyle = isMobile ? { height: "55%" } : vertical ? { height: clamped } : { width: clamped };
|
|
10098
|
+
const SideIcon = sideIcon(side);
|
|
10099
|
+
return /* @__PURE__ */ jsxs6("div", { className: "flex h-full w-full min-h-0 min-w-0", children: [
|
|
10100
|
+
defs.map(
|
|
10101
|
+
(def) => def.Defaults ? /* @__PURE__ */ jsx13(DefaultsReader, { def, onValue: onDefaults }, def.id) : null
|
|
10102
|
+
),
|
|
10103
|
+
/* @__PURE__ */ jsxs6(
|
|
10104
|
+
"div",
|
|
10105
|
+
{
|
|
10106
|
+
ref: rootRef,
|
|
10107
|
+
className: cn(
|
|
10108
|
+
"relative flex flex-1 min-h-0 min-w-0",
|
|
10109
|
+
vertical ? "flex-col" : side === "left" ? "flex-row-reverse" : "flex-row"
|
|
10110
|
+
),
|
|
10111
|
+
children: [
|
|
10112
|
+
/* @__PURE__ */ jsx13("div", { className: "relative flex-1 min-h-0 min-w-0", children }),
|
|
10113
|
+
defs.map((def) => {
|
|
10114
|
+
if (!mounted.has(def.id)) return null;
|
|
10115
|
+
const open = active?.id === def.id;
|
|
10116
|
+
const Component = def.component;
|
|
10117
|
+
const Icon = def.icon;
|
|
10118
|
+
return /* @__PURE__ */ jsxs6(
|
|
10119
|
+
"div",
|
|
10120
|
+
{
|
|
10121
|
+
className: cn(
|
|
10122
|
+
"relative flex-shrink-0 flex-col min-h-0 min-w-0 bg-background border-border",
|
|
10123
|
+
open ? "flex" : "hidden",
|
|
10124
|
+
vertical ? "border-t" : side === "left" ? "border-r" : "border-l",
|
|
10125
|
+
isMobile && "absolute inset-x-0 bottom-0 z-20 shadow-lg"
|
|
10126
|
+
),
|
|
10127
|
+
style: paneStyle,
|
|
10128
|
+
children: [
|
|
10129
|
+
!isMobile && /* @__PURE__ */ jsx13(
|
|
10130
|
+
"div",
|
|
10131
|
+
{
|
|
10132
|
+
role: "separator",
|
|
10133
|
+
"aria-label": t("companion.resize"),
|
|
10134
|
+
onMouseDown: startResize,
|
|
10135
|
+
className: cn(
|
|
10136
|
+
"absolute z-10",
|
|
10137
|
+
vertical ? "inset-x-0 -top-1 h-2 cursor-row-resize" : side === "left" ? "inset-y-0 -right-1 w-2 cursor-col-resize" : "inset-y-0 -left-1 w-2 cursor-col-resize",
|
|
10138
|
+
dragging && "bg-primary/30"
|
|
10139
|
+
)
|
|
10140
|
+
}
|
|
10141
|
+
),
|
|
10142
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1.5 h-8 px-2 border-b border-border flex-shrink-0", children: [
|
|
10143
|
+
Icon && /* @__PURE__ */ jsx13(Icon, { className: "size-3.5 text-muted-foreground" }),
|
|
10144
|
+
/* @__PURE__ */ jsx13("span", { className: "text-xs font-medium truncate flex-1", children: def.titleKey ? t(def.titleKey) : def.id }),
|
|
10145
|
+
!isMobile && /* @__PURE__ */ jsx13(
|
|
10146
|
+
"button",
|
|
10147
|
+
{
|
|
10148
|
+
type: "button",
|
|
10149
|
+
className: "p-1 text-muted-foreground hover:text-foreground",
|
|
10150
|
+
title: t("companion.moveSide"),
|
|
10151
|
+
onClick: () => setSide(
|
|
10152
|
+
side === "right" ? "bottom" : side === "bottom" ? "left" : "right"
|
|
10153
|
+
),
|
|
10154
|
+
children: /* @__PURE__ */ jsx13(SideIcon, { className: "size-3.5" })
|
|
10155
|
+
}
|
|
10156
|
+
),
|
|
10157
|
+
/* @__PURE__ */ jsx13(
|
|
10158
|
+
"button",
|
|
10159
|
+
{
|
|
10160
|
+
type: "button",
|
|
10161
|
+
className: "p-1 text-muted-foreground hover:text-foreground",
|
|
10162
|
+
title: t("companion.close"),
|
|
10163
|
+
onClick: close,
|
|
10164
|
+
children: /* @__PURE__ */ jsx13(X, { className: "size-3.5" })
|
|
10165
|
+
}
|
|
10166
|
+
)
|
|
10167
|
+
] }),
|
|
10168
|
+
/* @__PURE__ */ jsx13("div", { className: "flex-1 min-h-0 min-w-0 overflow-hidden", children: /* @__PURE__ */ jsx13(
|
|
10169
|
+
Component,
|
|
10170
|
+
{
|
|
10171
|
+
tab,
|
|
10172
|
+
host: tab.host,
|
|
10173
|
+
sshHost,
|
|
10174
|
+
getHandle,
|
|
10175
|
+
side,
|
|
10176
|
+
isVisible: isVisible && open,
|
|
10177
|
+
close,
|
|
10178
|
+
setSide
|
|
10179
|
+
}
|
|
10180
|
+
) })
|
|
10181
|
+
]
|
|
10182
|
+
},
|
|
10183
|
+
def.id
|
|
10184
|
+
);
|
|
10185
|
+
})
|
|
10186
|
+
]
|
|
10187
|
+
}
|
|
10188
|
+
),
|
|
10189
|
+
showEdge.length > 0 && !isMobile && /* @__PURE__ */ jsx13("div", { className: "flex flex-col flex-shrink-0 w-6 items-center gap-1 pt-1 border-l border-border bg-background", children: showEdge.map((def) => {
|
|
10190
|
+
const Icon = def.icon ?? PanelRight;
|
|
10191
|
+
const open = active?.id === def.id;
|
|
10192
|
+
return /* @__PURE__ */ jsx13(
|
|
10193
|
+
"button",
|
|
10194
|
+
{
|
|
10195
|
+
type: "button",
|
|
10196
|
+
title: def.titleKey ? t(def.titleKey) : def.id,
|
|
10197
|
+
"aria-pressed": open,
|
|
10198
|
+
onClick: () => patchCompanionState(key, {
|
|
10199
|
+
seen: true,
|
|
10200
|
+
openId: open ? null : def.id
|
|
10201
|
+
}),
|
|
10202
|
+
className: cn(
|
|
10203
|
+
"p-1 text-muted-foreground hover:text-foreground",
|
|
10204
|
+
open && "text-foreground bg-accent"
|
|
10205
|
+
),
|
|
10206
|
+
children: /* @__PURE__ */ jsx13(Icon, { className: "size-3.5" })
|
|
10207
|
+
},
|
|
10208
|
+
def.id
|
|
10209
|
+
);
|
|
10210
|
+
}) })
|
|
10211
|
+
] });
|
|
10212
|
+
}
|
|
10213
|
+
|
|
10060
10214
|
// src/ui/shell/tabUtils.tsx
|
|
10061
|
-
import { jsx as
|
|
10215
|
+
import { jsx as jsx14, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
10062
10216
|
var PluginsTab = lazy(
|
|
10063
|
-
() => import("./PluginsTab-
|
|
10217
|
+
() => import("./PluginsTab-YAGYRBIE.js").then((m) => ({ default: m.PluginsTab }))
|
|
10064
10218
|
);
|
|
10065
10219
|
function preloadTabSurface(type) {
|
|
10066
10220
|
const loader = getTabType(type)?.preload;
|
|
@@ -10073,37 +10227,37 @@ function EmptyState({
|
|
|
10073
10227
|
icon: Icon,
|
|
10074
10228
|
messageKey
|
|
10075
10229
|
}) {
|
|
10076
|
-
const { t } =
|
|
10077
|
-
return /* @__PURE__ */
|
|
10078
|
-
/* @__PURE__ */
|
|
10079
|
-
/* @__PURE__ */
|
|
10230
|
+
const { t } = useTranslation9();
|
|
10231
|
+
return /* @__PURE__ */ jsxs7("div", { className: "flex flex-col items-center justify-center flex-1 gap-3 p-6 text-center", children: [
|
|
10232
|
+
/* @__PURE__ */ jsx14("div", { className: "size-10 rounded-full bg-muted/40 flex items-center justify-center", children: /* @__PURE__ */ jsx14(Icon, { className: "size-5 text-muted-foreground/30" }) }),
|
|
10233
|
+
/* @__PURE__ */ jsx14("span", { className: "text-sm font-semibold text-muted-foreground/60", children: t(messageKey) })
|
|
10080
10234
|
] });
|
|
10081
10235
|
}
|
|
10082
10236
|
function TabChunkFallback() {
|
|
10083
|
-
return /* @__PURE__ */
|
|
10237
|
+
return /* @__PURE__ */ jsx14("div", { className: "flex h-full w-full items-center justify-center bg-background", children: /* @__PURE__ */ jsx14("div", { className: "size-5 rounded-full border-2 border-muted-foreground/30 border-t-muted-foreground/70 animate-spin" }) });
|
|
10084
10238
|
}
|
|
10085
10239
|
function withTabSuspense(node) {
|
|
10086
|
-
return /* @__PURE__ */
|
|
10240
|
+
return /* @__PURE__ */ jsx14(Suspense, { fallback: /* @__PURE__ */ jsx14(TabChunkFallback, {}), children: node });
|
|
10087
10241
|
}
|
|
10088
10242
|
function PanelTabFrame({ children }) {
|
|
10089
|
-
return /* @__PURE__ */
|
|
10243
|
+
return /* @__PURE__ */ jsx14("div", { className: "flex h-full w-full justify-center overflow-y-auto bg-background", children: /* @__PURE__ */ jsx14("div", { className: "flex flex-col flex-1 min-h-0 w-full max-w-5xl", children }) });
|
|
10090
10244
|
}
|
|
10091
10245
|
function tabIcon(type) {
|
|
10092
10246
|
switch (type) {
|
|
10093
10247
|
case "user-profile":
|
|
10094
10248
|
case "admin-settings":
|
|
10095
|
-
return /* @__PURE__ */
|
|
10249
|
+
return /* @__PURE__ */ jsx14(Settings, { className: "size-3.5" });
|
|
10096
10250
|
case "split-screen":
|
|
10097
|
-
return /* @__PURE__ */
|
|
10251
|
+
return /* @__PURE__ */ jsx14(LayoutPanelLeft, { className: "size-3.5" });
|
|
10098
10252
|
case "plugins":
|
|
10099
|
-
return /* @__PURE__ */
|
|
10253
|
+
return /* @__PURE__ */ jsx14(Puzzle, { className: "size-3.5" });
|
|
10100
10254
|
default: {
|
|
10101
10255
|
const Icon = getTabType(type)?.icon;
|
|
10102
|
-
return Icon ? /* @__PURE__ */
|
|
10256
|
+
return Icon ? /* @__PURE__ */ jsx14(Icon, { className: "size-3.5" }) : null;
|
|
10103
10257
|
}
|
|
10104
10258
|
}
|
|
10105
10259
|
}
|
|
10106
|
-
var RegisteredTab =
|
|
10260
|
+
var RegisteredTab = memo2(function RegisteredTab2({
|
|
10107
10261
|
def,
|
|
10108
10262
|
tab,
|
|
10109
10263
|
isVisible,
|
|
@@ -10113,7 +10267,7 @@ var RegisteredTab = memo(function RegisteredTab2({
|
|
|
10113
10267
|
}) {
|
|
10114
10268
|
const { host, label } = tab;
|
|
10115
10269
|
if (def.requiresHost && !host) {
|
|
10116
|
-
return /* @__PURE__ */
|
|
10270
|
+
return /* @__PURE__ */ jsx14(
|
|
10117
10271
|
EmptyState,
|
|
10118
10272
|
{
|
|
10119
10273
|
icon: Server,
|
|
@@ -10122,7 +10276,7 @@ var RegisteredTab = memo(function RegisteredTab2({
|
|
|
10122
10276
|
);
|
|
10123
10277
|
}
|
|
10124
10278
|
const Component = def.component;
|
|
10125
|
-
const content = /* @__PURE__ */
|
|
10279
|
+
const content = /* @__PURE__ */ jsx14(
|
|
10126
10280
|
Component,
|
|
10127
10281
|
{
|
|
10128
10282
|
tab,
|
|
@@ -10139,10 +10293,10 @@ var RegisteredTab = memo(function RegisteredTab2({
|
|
|
10139
10293
|
}
|
|
10140
10294
|
);
|
|
10141
10295
|
return withTabSuspense(
|
|
10142
|
-
def.panelFrame ? /* @__PURE__ */
|
|
10296
|
+
/* @__PURE__ */ jsx14(CompanionFrame, { tab, isVisible, children: def.panelFrame ? /* @__PURE__ */ jsx14(PanelTabFrame, { children: content }) : content })
|
|
10143
10297
|
);
|
|
10144
10298
|
});
|
|
10145
|
-
var PanelAsTab =
|
|
10299
|
+
var PanelAsTab = memo2(function PanelAsTab2({
|
|
10146
10300
|
panel,
|
|
10147
10301
|
isVisible,
|
|
10148
10302
|
targetTab,
|
|
@@ -10150,7 +10304,7 @@ var PanelAsTab = memo(function PanelAsTab2({
|
|
|
10150
10304
|
}) {
|
|
10151
10305
|
const Panel = panel.component;
|
|
10152
10306
|
return withTabSuspense(
|
|
10153
|
-
/* @__PURE__ */
|
|
10307
|
+
/* @__PURE__ */ jsx14(PanelTabFrame, { children: /* @__PURE__ */ jsx14(
|
|
10154
10308
|
Panel,
|
|
10155
10309
|
{
|
|
10156
10310
|
targetTab,
|
|
@@ -10175,7 +10329,7 @@ function renderTabContent(tab, context) {
|
|
|
10175
10329
|
case "split-screen":
|
|
10176
10330
|
return null;
|
|
10177
10331
|
case "plugins":
|
|
10178
|
-
return withTabSuspense(/* @__PURE__ */
|
|
10332
|
+
return withTabSuspense(/* @__PURE__ */ jsx14(PluginsTab, {}));
|
|
10179
10333
|
case "user-profile":
|
|
10180
10334
|
case "admin-settings":
|
|
10181
10335
|
return null;
|
|
@@ -10185,7 +10339,7 @@ function renderTabContent(tab, context) {
|
|
|
10185
10339
|
if (!def) {
|
|
10186
10340
|
const panel = getPanel(tab.type);
|
|
10187
10341
|
if (panel) {
|
|
10188
|
-
return /* @__PURE__ */
|
|
10342
|
+
return /* @__PURE__ */ jsx14(
|
|
10189
10343
|
PanelAsTab,
|
|
10190
10344
|
{
|
|
10191
10345
|
panel,
|
|
@@ -10195,9 +10349,9 @@ function renderTabContent(tab, context) {
|
|
|
10195
10349
|
}
|
|
10196
10350
|
);
|
|
10197
10351
|
}
|
|
10198
|
-
return /* @__PURE__ */
|
|
10352
|
+
return /* @__PURE__ */ jsx14(PluginViewPlaceholder, { kind: "tab", viewId: tab.type });
|
|
10199
10353
|
}
|
|
10200
|
-
return /* @__PURE__ */
|
|
10354
|
+
return /* @__PURE__ */ jsx14(
|
|
10201
10355
|
RegisteredTab,
|
|
10202
10356
|
{
|
|
10203
10357
|
def,
|
|
@@ -10265,20 +10419,6 @@ export {
|
|
|
10265
10419
|
changeAppLanguage,
|
|
10266
10420
|
rememberLoginLanguage,
|
|
10267
10421
|
i18n_default,
|
|
10268
|
-
probeServer,
|
|
10269
|
-
getLinkPreview,
|
|
10270
|
-
completeLink,
|
|
10271
|
-
reloginLink,
|
|
10272
|
-
unlinkServer,
|
|
10273
|
-
syncNow,
|
|
10274
|
-
updateSyncSettings,
|
|
10275
|
-
getSyncConflicts,
|
|
10276
|
-
settleSyncConflict,
|
|
10277
|
-
getSyncErrors,
|
|
10278
|
-
retrySyncErrors,
|
|
10279
|
-
setSyncStatus,
|
|
10280
|
-
refreshSyncStatus,
|
|
10281
|
-
useSyncStatus,
|
|
10282
10422
|
getPanel,
|
|
10283
10423
|
listPanels,
|
|
10284
10424
|
usePanels,
|