@decentnetwork/beagle-ui 0.2.36 → 0.2.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/beagle-ui.js +94 -14
- package/package.json +1 -1
package/dist/beagle-ui.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const BEAGLE_UI_VERSION = "0.2.
|
|
1
|
+
export const BEAGLE_UI_VERSION = "0.2.38";
|
|
2
2
|
// src/icons.jsx
|
|
3
3
|
var ICON_PATHS = {
|
|
4
4
|
// ---- tab bar (the four must feel like one set) ----
|
|
@@ -448,6 +448,12 @@ var dkApi = {
|
|
|
448
448
|
cancelSend: (userid, ids) => dkPost("/api/file-cancel", { userid, ids }),
|
|
449
449
|
retrySend: (userid, ids) => dkPost("/api/file-retry", { userid, ids }),
|
|
450
450
|
setProfile: (name, description) => dkPost("/api/set-profile", { name, description }),
|
|
451
|
+
// Probe a failed exit once, now (or every failed exit with all=true). Exits
|
|
452
|
+
// that failed three times in a row are never probed again on their own.
|
|
453
|
+
reconnectExit: (ip) => dkPost("/api/exits/reconnect", { ip }),
|
|
454
|
+
reconnectAllExits: () => dkPost("/api/exits/reconnect", { all: true }),
|
|
455
|
+
// Every exit once, now, failed ones included.
|
|
456
|
+
refreshExits: () => dkPost("/api/exits/refresh", {}),
|
|
451
457
|
// Used by the browser's welcome flow, which also picks an avatar and marks
|
|
452
458
|
// first run done. Harmless where there is no welcome flow: nothing calls it.
|
|
453
459
|
setProfileFull: (p) => dkPost("/api/set-profile", p),
|
|
@@ -583,22 +589,33 @@ function useProtocolTails(peers, isProtocol, enabled) {
|
|
|
583
589
|
}, [peers, isProtocol, enabled]);
|
|
584
590
|
return fixes;
|
|
585
591
|
}
|
|
586
|
-
function useDaemonData() {
|
|
592
|
+
function useDaemonData(opts) {
|
|
593
|
+
const wantExits = !!(opts && opts.exits);
|
|
594
|
+
const wantExitsRef = React.useRef(wantExits);
|
|
595
|
+
wantExitsRef.current = wantExits;
|
|
596
|
+
const exitsOpenedRef = React.useRef(false);
|
|
587
597
|
const [snap, setSnap] = React.useState({
|
|
588
598
|
me: DK_ME_FALLBACK,
|
|
589
599
|
peers: [],
|
|
590
600
|
requests: [],
|
|
591
601
|
exits: [],
|
|
592
602
|
activeExit: null,
|
|
603
|
+
exitFeature: null,
|
|
604
|
+
routeFallback: null,
|
|
593
605
|
loaded: false,
|
|
594
606
|
locked: false
|
|
595
607
|
});
|
|
596
608
|
const [threads, setThreads] = React.useState({});
|
|
597
609
|
const refreshRef = React.useRef(null);
|
|
598
610
|
const refresh = React.useCallback(async () => {
|
|
599
|
-
var _a;
|
|
611
|
+
var _a, _b, _c;
|
|
600
612
|
try {
|
|
601
|
-
|
|
613
|
+
let path = "/api/desktop";
|
|
614
|
+
if (wantExitsRef.current) {
|
|
615
|
+
path += exitsOpenedRef.current ? "?exits=1&open=1" : "?exits=1";
|
|
616
|
+
exitsOpenedRef.current = false;
|
|
617
|
+
}
|
|
618
|
+
const d = await dkGet(path);
|
|
602
619
|
if (d && d.locked) {
|
|
603
620
|
setSnap((s) => ({ ...s, locked: true, loaded: true }));
|
|
604
621
|
return;
|
|
@@ -616,6 +633,8 @@ function useDaemonData() {
|
|
|
616
633
|
requests: d.requests || [],
|
|
617
634
|
exits: d.exits || [],
|
|
618
635
|
activeExit: (_a = d.activeExit) != null ? _a : null,
|
|
636
|
+
exitFeature: (_b = d.exitFeature) != null ? _b : null,
|
|
637
|
+
routeFallback: (_c = d.routeFallback) != null ? _c : null,
|
|
619
638
|
loaded: true
|
|
620
639
|
});
|
|
621
640
|
} catch (e) {
|
|
@@ -627,6 +646,12 @@ function useDaemonData() {
|
|
|
627
646
|
const t = setInterval(refresh, 2500);
|
|
628
647
|
return () => clearInterval(t);
|
|
629
648
|
}, [refresh]);
|
|
649
|
+
React.useEffect(() => {
|
|
650
|
+
if (wantExits) {
|
|
651
|
+
exitsOpenedRef.current = true;
|
|
652
|
+
refresh();
|
|
653
|
+
}
|
|
654
|
+
}, [wantExits, refresh]);
|
|
630
655
|
const inFlight = React.useRef(/* @__PURE__ */ new Set());
|
|
631
656
|
const cache = React.useRef({});
|
|
632
657
|
const [earlier, setEarlier] = React.useState({});
|
|
@@ -648,10 +673,10 @@ function useDaemonData() {
|
|
|
648
673
|
setThreads((t) => Object.assign({}, t, { [peerId]: withDay }));
|
|
649
674
|
setEarlier((e) => e[peerId] === c.more ? e : Object.assign({}, e, { [peerId]: c.more }));
|
|
650
675
|
}, []);
|
|
651
|
-
const loadThread = React.useCallback(async (peerId,
|
|
676
|
+
const loadThread = React.useCallback(async (peerId, opts2) => {
|
|
652
677
|
if (!peerId)
|
|
653
678
|
return;
|
|
654
|
-
if (
|
|
679
|
+
if (opts2 && opts2.reset)
|
|
655
680
|
delete cache.current[peerId];
|
|
656
681
|
if (inFlight.current.has(peerId))
|
|
657
682
|
return;
|
|
@@ -6161,15 +6186,40 @@ function PeerTable({ T, peers, onOpenChat }) {
|
|
|
6161
6186
|
borderBottom: i < peers.length - 1 ? "1px solid var(--line)" : "none"
|
|
6162
6187
|
} }, /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 10, minWidth: 0 } }, /* @__PURE__ */ React.createElement(DkAvatar, { peer: p, size: 26, radius: 6 }), /* @__PURE__ */ React.createElement("span", { style: { fontFamily: p.alias ? "var(--ui)" : "var(--mono)", fontSize: 13, fontWeight: 600, color: "var(--text)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" } }, p.alias || shortKey(p.userId, 8, 5)), p.agent && /* @__PURE__ */ React.createElement(Icon, { name: "bot", size: 12, color: "var(--faint)", stroke: 2 })), /* @__PURE__ */ React.createElement(Mono, { size: 12.5, dim: true, copy: p.ip }, p.ip), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(RouteTag, { peer: p })), /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 11.5, color: p.wire === "64" ? "var(--warn)" : "var(--dim)" } }, p.wire === "64" ? "old\xB764" : "new\xB7163"), /* @__PURE__ */ React.createElement("div", { style: { display: "flex", justifyContent: "flex-end", gap: 6 } }, /* @__PURE__ */ React.createElement(Btn, { icon: "message", size: "sm", title: T.openChat, onClick: () => onOpenChat(p.id) }), /* @__PURE__ */ React.createElement(Btn, { icon: "signal", size: "sm", title: T.ping })))));
|
|
6163
6188
|
}
|
|
6164
|
-
function
|
|
6189
|
+
function ReconnectBtn({ T, ip, onReconnect, label, icon = "refresh" }) {
|
|
6190
|
+
const [busy, setBusy] = React.useState(false);
|
|
6191
|
+
return /* @__PURE__ */ React.createElement(
|
|
6192
|
+
Btn,
|
|
6193
|
+
{
|
|
6194
|
+
size: "sm",
|
|
6195
|
+
icon,
|
|
6196
|
+
disabled: busy,
|
|
6197
|
+
onClick: async () => {
|
|
6198
|
+
if (busy || !onReconnect)
|
|
6199
|
+
return;
|
|
6200
|
+
setBusy(true);
|
|
6201
|
+
try {
|
|
6202
|
+
await onReconnect(ip);
|
|
6203
|
+
} finally {
|
|
6204
|
+
setBusy(false);
|
|
6205
|
+
}
|
|
6206
|
+
}
|
|
6207
|
+
},
|
|
6208
|
+
busy ? T.exitChecking || "checking\u2026" : label || T.exitReconnect || "Reconnect"
|
|
6209
|
+
);
|
|
6210
|
+
}
|
|
6211
|
+
function ExitCard({ T, region, activeExit, onSetExit, onReconnect, featureOn }) {
|
|
6165
6212
|
return /* @__PURE__ */ React.createElement("div", { style: { borderRadius: 11, border: "1px solid var(--line)", overflow: "hidden", background: "var(--panel)" } }, /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 10, padding: "11px 14px", borderBottom: "1px solid var(--line)", background: "var(--panel-2)" } }, /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 11, fontWeight: 700, letterSpacing: 0.5, padding: "2px 7px", borderRadius: 5, background: "var(--chip)", color: "var(--dim)" } }, region.flag), /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--ui)", fontSize: 13.5, fontWeight: 600, color: "var(--text)" } }, region.label), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }), (() => {
|
|
6166
6213
|
const reach = region.nodes.filter((n) => n.reachable).length;
|
|
6167
|
-
const
|
|
6168
|
-
|
|
6214
|
+
const failed = region.nodes.filter((n) => n.status === "failed").length;
|
|
6215
|
+
const down = region.nodes.length - reach - failed;
|
|
6216
|
+
return /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 11, color: down + failed > 0 ? "var(--warn)" : "var(--faint)" } }, reach, "/", region.nodes.length, " ", T.up, failed > 0 ? ` \xB7 ${failed} ${T.exitFailed || "failed"}` : "", down > 0 ? ` \xB7 ${down} down` : "");
|
|
6169
6217
|
})()), /* @__PURE__ */ React.createElement("div", null, region.nodes.map((n, i) => {
|
|
6170
6218
|
const active = n.ip === activeExit;
|
|
6171
6219
|
const stuck = n.online && !n.reachable;
|
|
6172
|
-
|
|
6220
|
+
const failed = n.status === "failed";
|
|
6221
|
+
const usable = n.reachable && featureOn !== false;
|
|
6222
|
+
return /* @__PURE__ */ React.createElement("div", { key: n.ip, className: "dk-wrap", style: { display: "flex", alignItems: "center", gap: 12, rowGap: 6, padding: "10px 14px", borderBottom: i < region.nodes.length - 1 ? "1px solid var(--line)" : "none", background: active ? "color-mix(in oklab, var(--accent), transparent 92%)" : "transparent" } }, /* @__PURE__ */ React.createElement(StatusDot, { online: n.reachable }), /* @__PURE__ */ React.createElement(Mono, { size: 13, copy: n.ip }, n.ip), /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 11, color: "var(--faint)" } }, n.host), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }), n.reachable ? /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 11.5, color: n.ping > 200 ? "var(--warn)" : "var(--dim)" } }, n.ping, "ms") : failed ? /* @__PURE__ */ React.createElement(Tag, { tone: "danger", title: "Failed 3 checks in a row \u2014 no longer checked; Reconnect to try again" }, T.exitFailed || "failed") : n.status === "unknown" ? /* @__PURE__ */ React.createElement(Tag, { tone: "off" }, T.exitNotChecked || "not checked") : stuck ? /* @__PURE__ */ React.createElement(Tag, { tone: "warn", title: "Announces online but IP won't pass \u2014 session desync or NAT-blocked" }, "online \xB7 no route") : n.status === "down" ? /* @__PURE__ */ React.createElement(Tag, { tone: "warn", title: "No answer \u2014 checked again only when you open this panel or press Refresh; 3 in a row and it is no longer checked" }, T.exitDown || "down", " \xB7 ", n.fails, "/3") : /* @__PURE__ */ React.createElement(Tag, { tone: "off" }, "offline"), failed ? /* @__PURE__ */ React.createElement(ReconnectBtn, { T, ip: n.ip, onReconnect }) : active ? /* @__PURE__ */ React.createElement(Btn, { tone: "ok", icon: "check", size: "sm", onClick: () => onSetExit(null) }, T.routing) : /* @__PURE__ */ React.createElement(Btn, { size: "sm", icon: "route", disabled: !usable, onClick: () => usable && onSetExit(n.ip), style: { opacity: usable ? 1 : 0.4 } }, T.routeThru));
|
|
6173
6223
|
})));
|
|
6174
6224
|
}
|
|
6175
6225
|
function LanEnableCard({ backend, onArm, onCancel }) {
|
|
@@ -6273,12 +6323,14 @@ function LanEnableCard({ backend, onArm, onCancel }) {
|
|
|
6273
6323
|
"\u53D6\u6D88,\u6062\u590D\u6D88\u606F"
|
|
6274
6324
|
)));
|
|
6275
6325
|
}
|
|
6276
|
-
function NetworkTab({ T, me, peers, exits, activeExit, reqCount, onSetExit, onOpenChat, backend, onArmLan, onCancelLan }) {
|
|
6326
|
+
function NetworkTab({ T, me, peers, exits, activeExit, exitFeature, routeFallback, onReconnectExit, onRefreshExits, reqCount, onSetExit, onOpenChat, backend, onArmLan, onCancelLan }) {
|
|
6327
|
+
const featureOn = !exitFeature || exitFeature.available !== false;
|
|
6328
|
+
const anyFailed = (exits || []).some((r) => (r.nodes || []).some((n) => n.status === "failed"));
|
|
6277
6329
|
if (backend && backend.switchable && !backend.hasVirtualLan) {
|
|
6278
6330
|
return /* @__PURE__ */ React.createElement("div", { style: { flex: 1, overflow: "auto", background: "var(--bg)" } }, /* @__PURE__ */ React.createElement("div", { className: "dk-page", style: { maxWidth: 1040, margin: "0 auto", padding: "24px 28px 60px", display: "flex", flexDirection: "column", gap: 26 } }, /* @__PURE__ */ React.createElement(MyNode, { T, me, activeExit, peers, reqCount }), /* @__PURE__ */ React.createElement(LanEnableCard, { backend, onArm: onArmLan, onCancel: onCancelLan })));
|
|
6279
6331
|
}
|
|
6280
6332
|
const lanless = !!backend && backend.hasVirtualLan === false;
|
|
6281
|
-
return /* @__PURE__ */ React.createElement("div", { style: { flex: 1, overflow: "auto", background: "var(--bg)" } }, /* @__PURE__ */ React.createElement("div", { className: "dk-page", style: { maxWidth: 1040, margin: "0 auto", padding: "24px 28px 60px", display: "flex", flexDirection: "column", gap: 26 } }, /* @__PURE__ */ React.createElement(MyNode, { T, me, activeExit, peers, reqCount }), /* @__PURE__ */ React.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 12 } }, /* @__PURE__ */ React.createElement(Section, { label: T.peerRouting, count: peers.length }), /* @__PURE__ */ React.createElement(PeerTable, { T, peers, onOpenChat }), !peers.length && /* @__PURE__ */ React.createElement("div", { style: { padding: "14px 16px", borderRadius: 11, border: "1px dashed var(--line)", fontFamily: "var(--ui)", fontSize: 12.5, color: "var(--faint)" } }, T.noPeersYet || "No friends yet \u2014 add one from Chat and it shows up here with its route.")), lanless ? null : /* @__PURE__ */ React.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 12 } }, /* @__PURE__ */ React.createElement(Section, { label: T.exitNodes, trailing: /* @__PURE__ */ React.createElement("div", { style: { display: "flex", gap: 6 } }, /* @__PURE__ */ React.createElement(Btn, { icon: "plus", size: "sm" }, T.addExit)) }), activeExit && /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 10, padding: "11px 14px", borderRadius: 10, background: "color-mix(in oklab, var(--warn), transparent 90%)", border: "1px solid color-mix(in oklab, var(--warn), transparent 70%)" } }, /* @__PURE__ */ React.createElement(Icon, { name: "route", size: 17, color: "var(--warn)", stroke: 2 }), /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 12.5, color: "var(--text)" } }, T.egressVia), /* @__PURE__ */ React.createElement(Mono, { size: 13, copy: activeExit }, activeExit), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }), /* @__PURE__ */ React.createElement(Btn, { tone: "danger", icon: "unlink", size: "sm", onClick: () => onSetExit(null) }, T.stopRouting)), /* @__PURE__ */ React.createElement("div", { className: "dk-grid1", style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 } }, exits.map((r) => /* @__PURE__ */ React.createElement(ExitCard, { key: r.region, T, region: r, activeExit, onSetExit }))))));
|
|
6333
|
+
return /* @__PURE__ */ React.createElement("div", { style: { flex: 1, overflow: "auto", background: "var(--bg)" } }, /* @__PURE__ */ React.createElement("div", { className: "dk-page", style: { maxWidth: 1040, margin: "0 auto", padding: "24px 28px 60px", display: "flex", flexDirection: "column", gap: 26 } }, /* @__PURE__ */ React.createElement(MyNode, { T, me, activeExit, peers, reqCount }), /* @__PURE__ */ React.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 12 } }, /* @__PURE__ */ React.createElement(Section, { label: T.peerRouting, count: peers.length }), /* @__PURE__ */ React.createElement(PeerTable, { T, peers, onOpenChat }), !peers.length && /* @__PURE__ */ React.createElement("div", { style: { padding: "14px 16px", borderRadius: 11, border: "1px dashed var(--line)", fontFamily: "var(--ui)", fontSize: 12.5, color: "var(--faint)" } }, T.noPeersYet || "No friends yet \u2014 add one from Chat and it shows up here with its route.")), lanless ? null : /* @__PURE__ */ React.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 12 } }, /* @__PURE__ */ React.createElement(Section, { label: T.exitNodes, trailing: /* @__PURE__ */ React.createElement("div", { style: { display: "flex", gap: 6 } }, onRefreshExits && (exits || []).length > 0 && /* @__PURE__ */ React.createElement(ReconnectBtn, { T, ip: null, onReconnect: () => onRefreshExits(), label: T.exitRefresh || "Refresh" }), anyFailed && onReconnectExit && /* @__PURE__ */ React.createElement(ReconnectBtn, { T, ip: null, onReconnect: onReconnectExit, label: T.exitReconnectAll || "Reconnect all" }), /* @__PURE__ */ React.createElement(Btn, { icon: "plus", size: "sm" }, T.addExit)) }), !featureOn && /* @__PURE__ */ React.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 4, padding: "11px 14px", borderRadius: 10, background: "var(--panel-2)", border: "1px dashed var(--line)" } }, /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 12.5, fontWeight: 700, color: "var(--text)" } }, T.noExitAvailable || "No exit available \u2014 routing and proxy are off."), anyFailed && /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--ui)", fontSize: 12, color: "var(--dim)" } }, T.noExitHint || "Every exit failed 3 times and is no longer checked automatically. Press Reconnect to try one again.")), routeFallback && routeFallback.from && /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 10, padding: "11px 14px", borderRadius: 10, background: "color-mix(in oklab, var(--warn), transparent 90%)", border: "1px solid color-mix(in oklab, var(--warn), transparent 70%)" } }, /* @__PURE__ */ React.createElement(Icon, { name: "route", size: 17, color: "var(--warn)", stroke: 2 }), /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 12.5, color: "var(--text)" } }, T.routeFellBack || "Routing fell back to direct: every exit it used failed. Reconnect one to route through it again.")), activeExit && /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 10, padding: "11px 14px", borderRadius: 10, background: "color-mix(in oklab, var(--warn), transparent 90%)", border: "1px solid color-mix(in oklab, var(--warn), transparent 70%)" } }, /* @__PURE__ */ React.createElement(Icon, { name: "route", size: 17, color: "var(--warn)", stroke: 2 }), /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 12.5, color: "var(--text)" } }, T.egressVia), /* @__PURE__ */ React.createElement(Mono, { size: 13, copy: activeExit }, activeExit), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }), /* @__PURE__ */ React.createElement(Btn, { tone: "danger", icon: "unlink", size: "sm", onClick: () => onSetExit(null) }, T.stopRouting)), /* @__PURE__ */ React.createElement("div", { className: "dk-grid1", style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 } }, exits.map((r) => /* @__PURE__ */ React.createElement(ExitCard, { key: r.region, T, region: r, activeExit, onSetExit, onReconnect: onReconnectExit, featureOn }))))));
|
|
6282
6334
|
}
|
|
6283
6335
|
Object.assign(window, { NetworkTab });
|
|
6284
6336
|
|
|
@@ -6696,6 +6748,16 @@ var STR = {
|
|
|
6696
6748
|
routeThru: "route",
|
|
6697
6749
|
egressVia: "all egress routed via",
|
|
6698
6750
|
stopRouting: "stop",
|
|
6751
|
+
exitFailed: "failed",
|
|
6752
|
+
exitReconnect: "Reconnect",
|
|
6753
|
+
exitReconnectAll: "Reconnect all",
|
|
6754
|
+
exitChecking: "checking\u2026",
|
|
6755
|
+
exitNotChecked: "not checked",
|
|
6756
|
+
exitDown: "down",
|
|
6757
|
+
exitRefresh: "Refresh",
|
|
6758
|
+
noExitAvailable: "No exit available \u2014 routing and proxy are off.",
|
|
6759
|
+
noExitHint: "Every exit failed 3 checks in a row and is no longer checked. Press Reconnect to try one again.",
|
|
6760
|
+
routeFellBack: "Routing fell back to direct: every exit it used failed. Reconnect one to route through it again.",
|
|
6699
6761
|
identity: "Identity",
|
|
6700
6762
|
userId: "user id",
|
|
6701
6763
|
carrierAddr: "carrier address",
|
|
@@ -6898,6 +6960,16 @@ var STR = {
|
|
|
6898
6960
|
routeThru: "\u8DEF\u7531",
|
|
6899
6961
|
egressVia: "\u5168\u90E8\u51FA\u53E3\u6D41\u91CF\u7ECF\u7531",
|
|
6900
6962
|
stopRouting: "\u505C\u6B62",
|
|
6963
|
+
exitFailed: "\u5DF2\u5931\u8D25",
|
|
6964
|
+
exitReconnect: "\u91CD\u65B0\u8FDE\u63A5",
|
|
6965
|
+
exitReconnectAll: "\u5168\u90E8\u91CD\u8FDE",
|
|
6966
|
+
exitChecking: "\u68C0\u6D4B\u4E2D\u2026",
|
|
6967
|
+
exitNotChecked: "\u672A\u68C0\u6D4B",
|
|
6968
|
+
exitDown: "\u4E0D\u901A",
|
|
6969
|
+
exitRefresh: "\u5237\u65B0",
|
|
6970
|
+
noExitAvailable: "\u6CA1\u6709\u53EF\u7528\u7684\u51FA\u53E3 \u2014\u2014 \u8DEF\u7531\u548C\u4EE3\u7406\u5DF2\u5173\u95ED\u3002",
|
|
6971
|
+
noExitHint: "\u6240\u6709\u51FA\u53E3\u90FD\u8FDE\u7EED 3 \u6B21\u68C0\u6D4B\u5931\u8D25,\u5DF2\u4E0D\u518D\u68C0\u6D4B\u3002\u70B9\u300C\u91CD\u65B0\u8FDE\u63A5\u300D\u518D\u8BD5\u4E00\u6B21\u3002",
|
|
6972
|
+
routeFellBack: "\u8DEF\u7531\u5DF2\u6539\u56DE\u76F4\u8FDE:\u5B83\u4F7F\u7528\u7684\u51FA\u53E3\u5168\u90E8\u5931\u8D25\u3002\u91CD\u65B0\u8FDE\u63A5\u5176\u4E2D\u4E00\u4E2A\u5373\u53EF\u6062\u590D\u3002",
|
|
6901
6973
|
identity: "\u8EAB\u4EFD",
|
|
6902
6974
|
userId: "\u7528\u6237 ID",
|
|
6903
6975
|
carrierAddr: "Carrier \u5730\u5740",
|
|
@@ -7192,7 +7264,7 @@ function DkApp() {
|
|
|
7192
7264
|
return hasTab(tabs, want) || DK_PEOPLE_TABS.includes(want) && showPeople ? want : firstTab;
|
|
7193
7265
|
});
|
|
7194
7266
|
const [activeId, setActiveId] = React.useState(null);
|
|
7195
|
-
const data = useDaemonData();
|
|
7267
|
+
const data = useDaemonData({ exits: tab === "network" });
|
|
7196
7268
|
const me = data.me;
|
|
7197
7269
|
const [upd, setUpd] = React.useState(null);
|
|
7198
7270
|
React.useEffect(() => {
|
|
@@ -7555,6 +7627,14 @@ function DkApp() {
|
|
|
7555
7627
|
const onEdit = (name, description) => dkApi.setProfile(name, description).then(data.refresh);
|
|
7556
7628
|
const onSetExit = () => {
|
|
7557
7629
|
};
|
|
7630
|
+
const onReconnectExit = (ip) => (ip ? dkApi.reconnectExit(ip) : dkApi.reconnectAllExits()).then((r) => {
|
|
7631
|
+
data.refresh();
|
|
7632
|
+
return r;
|
|
7633
|
+
});
|
|
7634
|
+
const onRefreshExits = () => dkApi.refreshExits().then((r) => {
|
|
7635
|
+
data.refresh();
|
|
7636
|
+
return r;
|
|
7637
|
+
});
|
|
7558
7638
|
const onOpenChat = (id) => {
|
|
7559
7639
|
setTab("chat");
|
|
7560
7640
|
openConversation(id);
|
|
@@ -7634,7 +7714,7 @@ function DkApp() {
|
|
|
7634
7714
|
fontWeight: 600,
|
|
7635
7715
|
background: tab === n.id ? "var(--accent)" : "transparent",
|
|
7636
7716
|
color: tab === n.id ? "#fff" : "var(--dim)"
|
|
7637
|
-
} }, /* @__PURE__ */ React.createElement(Icon, { name: n.icon, size: 14, stroke: 2, color: tab === n.id ? "#fff" : "var(--dim)" }), n.label))), tab === "chat" && /* @__PURE__ */ React.createElement(ChatTab, { T, lang: t.lang, phone, isProtocol, protocolFix, onBack: closeConversation, peers, requests, activeId, thread: activeId === ASSISTANT_ID ? assistant.thread : data.threads[activeId], onSelect, onAct, onAdd, onSend, onSendFile, onSendRtcFile, onAlias, onRemove, onOpenNet, onCall, onReloadThread: () => activeId && data.loadThread(activeId), hasEarlier: !!(activeId && activeId !== ASSISTANT_ID && data.earlier[activeId]), onAssistantRemove: activeId === ASSISTANT_ID ? assistant.removeFriends : null, onAssistantAdopt: activeId === ASSISTANT_ID ? assistant.adoptServicePeers : null, onLoadEarlier: () => activeId && data.loadEarlier(activeId), prefillAddr: pendingAddr, onPrefillConsumed: () => setPendingAddr(""), muted: mutedIds, onToggleMute }), tab === "here" && /* @__PURE__ */ React.createElement(DiscoverTab, { T, kind: "bridge", peers, meId: me.userId, onAdd, onOpenChat }), tab === "recommended" && /* @__PURE__ */ React.createElement(DiscoverTab, { T, kind: "recommended", peers, meId: me.userId, onAdd, onOpenChat }), tab === "registered" && /* @__PURE__ */ React.createElement(DiscoverTab, { T, kind: "registered", peers, meId: me.userId, onAdd, onOpenChat }), tab === "network" && /* @__PURE__ */ React.createElement(NetworkTab, { T, me, peers, exits, activeExit, reqCount: requests.length, onSetExit, onOpenChat, backend, onArmLan: armLan, onCancelLan: cancelLan }), tab === "apps" && /* @__PURE__ */ React.createElement(AppsTab, { T, t, me, peers, phone, setTab }), tabs.map((x) => x.kind === "host" && tab === x.id ? /* @__PURE__ */ React.createElement(HostTabPane, { key: x.id, tab: x, props: { T, t, me, peers, phone, setTab }, lang: t.lang }) : null), tab === "profile" && /* @__PURE__ */ React.createElement(
|
|
7717
|
+
} }, /* @__PURE__ */ React.createElement(Icon, { name: n.icon, size: 14, stroke: 2, color: tab === n.id ? "#fff" : "var(--dim)" }), n.label))), tab === "chat" && /* @__PURE__ */ React.createElement(ChatTab, { T, lang: t.lang, phone, isProtocol, protocolFix, onBack: closeConversation, peers, requests, activeId, thread: activeId === ASSISTANT_ID ? assistant.thread : data.threads[activeId], onSelect, onAct, onAdd, onSend, onSendFile, onSendRtcFile, onAlias, onRemove, onOpenNet, onCall, onReloadThread: () => activeId && data.loadThread(activeId), hasEarlier: !!(activeId && activeId !== ASSISTANT_ID && data.earlier[activeId]), onAssistantRemove: activeId === ASSISTANT_ID ? assistant.removeFriends : null, onAssistantAdopt: activeId === ASSISTANT_ID ? assistant.adoptServicePeers : null, onLoadEarlier: () => activeId && data.loadEarlier(activeId), prefillAddr: pendingAddr, onPrefillConsumed: () => setPendingAddr(""), muted: mutedIds, onToggleMute }), tab === "here" && /* @__PURE__ */ React.createElement(DiscoverTab, { T, kind: "bridge", peers, meId: me.userId, onAdd, onOpenChat }), tab === "recommended" && /* @__PURE__ */ React.createElement(DiscoverTab, { T, kind: "recommended", peers, meId: me.userId, onAdd, onOpenChat }), tab === "registered" && /* @__PURE__ */ React.createElement(DiscoverTab, { T, kind: "registered", peers, meId: me.userId, onAdd, onOpenChat }), tab === "network" && /* @__PURE__ */ React.createElement(NetworkTab, { T, me, peers, exits, activeExit, exitFeature: data.exitFeature, routeFallback: data.routeFallback, onReconnectExit, onRefreshExits, reqCount: requests.length, onSetExit, onOpenChat, backend, onArmLan: armLan, onCancelLan: cancelLan }), tab === "apps" && /* @__PURE__ */ React.createElement(AppsTab, { T, t, me, peers, phone, setTab }), tabs.map((x) => x.kind === "host" && tab === x.id ? /* @__PURE__ */ React.createElement(HostTabPane, { key: x.id, tab: x, props: { T, t, me, peers, phone, setTab }, lang: t.lang }) : null), tab === "profile" && /* @__PURE__ */ React.createElement(
|
|
7638
7718
|
ProfileTab,
|
|
7639
7719
|
{
|
|
7640
7720
|
T,
|
package/package.json
CHANGED