@decentnetwork/beagle-ui 0.2.36 → 0.2.37
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 +78 -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.37";
|
|
2
2
|
// src/icons.jsx
|
|
3
3
|
var ICON_PATHS = {
|
|
4
4
|
// ---- tab bar (the four must feel like one set) ----
|
|
@@ -448,6 +448,10 @@ 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 }),
|
|
451
455
|
// Used by the browser's welcome flow, which also picks an avatar and marks
|
|
452
456
|
// first run done. Harmless where there is no welcome flow: nothing calls it.
|
|
453
457
|
setProfileFull: (p) => dkPost("/api/set-profile", p),
|
|
@@ -583,22 +587,27 @@ function useProtocolTails(peers, isProtocol, enabled) {
|
|
|
583
587
|
}, [peers, isProtocol, enabled]);
|
|
584
588
|
return fixes;
|
|
585
589
|
}
|
|
586
|
-
function useDaemonData() {
|
|
590
|
+
function useDaemonData(opts) {
|
|
591
|
+
const wantExits = !!(opts && opts.exits);
|
|
592
|
+
const wantExitsRef = React.useRef(wantExits);
|
|
593
|
+
wantExitsRef.current = wantExits;
|
|
587
594
|
const [snap, setSnap] = React.useState({
|
|
588
595
|
me: DK_ME_FALLBACK,
|
|
589
596
|
peers: [],
|
|
590
597
|
requests: [],
|
|
591
598
|
exits: [],
|
|
592
599
|
activeExit: null,
|
|
600
|
+
exitFeature: null,
|
|
601
|
+
routeFallback: null,
|
|
593
602
|
loaded: false,
|
|
594
603
|
locked: false
|
|
595
604
|
});
|
|
596
605
|
const [threads, setThreads] = React.useState({});
|
|
597
606
|
const refreshRef = React.useRef(null);
|
|
598
607
|
const refresh = React.useCallback(async () => {
|
|
599
|
-
var _a;
|
|
608
|
+
var _a, _b, _c;
|
|
600
609
|
try {
|
|
601
|
-
const d = await dkGet("/api/desktop");
|
|
610
|
+
const d = await dkGet(wantExitsRef.current ? "/api/desktop?exits=1" : "/api/desktop");
|
|
602
611
|
if (d && d.locked) {
|
|
603
612
|
setSnap((s) => ({ ...s, locked: true, loaded: true }));
|
|
604
613
|
return;
|
|
@@ -616,6 +625,8 @@ function useDaemonData() {
|
|
|
616
625
|
requests: d.requests || [],
|
|
617
626
|
exits: d.exits || [],
|
|
618
627
|
activeExit: (_a = d.activeExit) != null ? _a : null,
|
|
628
|
+
exitFeature: (_b = d.exitFeature) != null ? _b : null,
|
|
629
|
+
routeFallback: (_c = d.routeFallback) != null ? _c : null,
|
|
619
630
|
loaded: true
|
|
620
631
|
});
|
|
621
632
|
} catch (e) {
|
|
@@ -627,6 +638,10 @@ function useDaemonData() {
|
|
|
627
638
|
const t = setInterval(refresh, 2500);
|
|
628
639
|
return () => clearInterval(t);
|
|
629
640
|
}, [refresh]);
|
|
641
|
+
React.useEffect(() => {
|
|
642
|
+
if (wantExits)
|
|
643
|
+
refresh();
|
|
644
|
+
}, [wantExits, refresh]);
|
|
630
645
|
const inFlight = React.useRef(/* @__PURE__ */ new Set());
|
|
631
646
|
const cache = React.useRef({});
|
|
632
647
|
const [earlier, setEarlier] = React.useState({});
|
|
@@ -648,10 +663,10 @@ function useDaemonData() {
|
|
|
648
663
|
setThreads((t) => Object.assign({}, t, { [peerId]: withDay }));
|
|
649
664
|
setEarlier((e) => e[peerId] === c.more ? e : Object.assign({}, e, { [peerId]: c.more }));
|
|
650
665
|
}, []);
|
|
651
|
-
const loadThread = React.useCallback(async (peerId,
|
|
666
|
+
const loadThread = React.useCallback(async (peerId, opts2) => {
|
|
652
667
|
if (!peerId)
|
|
653
668
|
return;
|
|
654
|
-
if (
|
|
669
|
+
if (opts2 && opts2.reset)
|
|
655
670
|
delete cache.current[peerId];
|
|
656
671
|
if (inFlight.current.has(peerId))
|
|
657
672
|
return;
|
|
@@ -6161,15 +6176,40 @@ function PeerTable({ T, peers, onOpenChat }) {
|
|
|
6161
6176
|
borderBottom: i < peers.length - 1 ? "1px solid var(--line)" : "none"
|
|
6162
6177
|
} }, /* @__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
6178
|
}
|
|
6164
|
-
function
|
|
6179
|
+
function ReconnectBtn({ T, ip, onReconnect, label, icon = "refresh" }) {
|
|
6180
|
+
const [busy, setBusy] = React.useState(false);
|
|
6181
|
+
return /* @__PURE__ */ React.createElement(
|
|
6182
|
+
Btn,
|
|
6183
|
+
{
|
|
6184
|
+
size: "sm",
|
|
6185
|
+
icon,
|
|
6186
|
+
disabled: busy,
|
|
6187
|
+
onClick: async () => {
|
|
6188
|
+
if (busy || !onReconnect)
|
|
6189
|
+
return;
|
|
6190
|
+
setBusy(true);
|
|
6191
|
+
try {
|
|
6192
|
+
await onReconnect(ip);
|
|
6193
|
+
} finally {
|
|
6194
|
+
setBusy(false);
|
|
6195
|
+
}
|
|
6196
|
+
}
|
|
6197
|
+
},
|
|
6198
|
+
busy ? T.exitChecking || "checking\u2026" : label || T.exitReconnect || "Reconnect"
|
|
6199
|
+
);
|
|
6200
|
+
}
|
|
6201
|
+
function ExitCard({ T, region, activeExit, onSetExit, onReconnect, featureOn }) {
|
|
6165
6202
|
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
6203
|
const reach = region.nodes.filter((n) => n.reachable).length;
|
|
6167
|
-
const
|
|
6168
|
-
|
|
6204
|
+
const failed = region.nodes.filter((n) => n.status === "failed").length;
|
|
6205
|
+
const down = region.nodes.length - reach - failed;
|
|
6206
|
+
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
6207
|
})()), /* @__PURE__ */ React.createElement("div", null, region.nodes.map((n, i) => {
|
|
6170
6208
|
const active = n.ip === activeExit;
|
|
6171
6209
|
const stuck = n.online && !n.reachable;
|
|
6172
|
-
|
|
6210
|
+
const failed = n.status === "failed";
|
|
6211
|
+
const usable = n.reachable && featureOn !== false;
|
|
6212
|
+
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 automatically" }, 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 === "retrying" ? /* @__PURE__ */ React.createElement(Tag, { tone: "warn", title: "No answer \u2014 will try again shortly" }, T.exitRetrying || "retrying", " \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
6213
|
})));
|
|
6174
6214
|
}
|
|
6175
6215
|
function LanEnableCard({ backend, onArm, onCancel }) {
|
|
@@ -6273,12 +6313,14 @@ function LanEnableCard({ backend, onArm, onCancel }) {
|
|
|
6273
6313
|
"\u53D6\u6D88,\u6062\u590D\u6D88\u606F"
|
|
6274
6314
|
)));
|
|
6275
6315
|
}
|
|
6276
|
-
function NetworkTab({ T, me, peers, exits, activeExit, reqCount, onSetExit, onOpenChat, backend, onArmLan, onCancelLan }) {
|
|
6316
|
+
function NetworkTab({ T, me, peers, exits, activeExit, exitFeature, routeFallback, onReconnectExit, reqCount, onSetExit, onOpenChat, backend, onArmLan, onCancelLan }) {
|
|
6317
|
+
const featureOn = !exitFeature || exitFeature.available !== false;
|
|
6318
|
+
const anyFailed = (exits || []).some((r) => (r.nodes || []).some((n) => n.status === "failed"));
|
|
6277
6319
|
if (backend && backend.switchable && !backend.hasVirtualLan) {
|
|
6278
6320
|
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
6321
|
}
|
|
6280
6322
|
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 }))))));
|
|
6323
|
+
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 } }, 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
6324
|
}
|
|
6283
6325
|
Object.assign(window, { NetworkTab });
|
|
6284
6326
|
|
|
@@ -6696,6 +6738,15 @@ var STR = {
|
|
|
6696
6738
|
routeThru: "route",
|
|
6697
6739
|
egressVia: "all egress routed via",
|
|
6698
6740
|
stopRouting: "stop",
|
|
6741
|
+
exitFailed: "failed",
|
|
6742
|
+
exitReconnect: "Reconnect",
|
|
6743
|
+
exitReconnectAll: "Reconnect all",
|
|
6744
|
+
exitChecking: "checking\u2026",
|
|
6745
|
+
exitNotChecked: "not checked",
|
|
6746
|
+
exitRetrying: "retrying",
|
|
6747
|
+
noExitAvailable: "No exit available \u2014 routing and proxy are off.",
|
|
6748
|
+
noExitHint: "Every exit failed 3 times and is no longer checked automatically. Press Reconnect to try one again.",
|
|
6749
|
+
routeFellBack: "Routing fell back to direct: every exit it used failed. Reconnect one to route through it again.",
|
|
6699
6750
|
identity: "Identity",
|
|
6700
6751
|
userId: "user id",
|
|
6701
6752
|
carrierAddr: "carrier address",
|
|
@@ -6898,6 +6949,15 @@ var STR = {
|
|
|
6898
6949
|
routeThru: "\u8DEF\u7531",
|
|
6899
6950
|
egressVia: "\u5168\u90E8\u51FA\u53E3\u6D41\u91CF\u7ECF\u7531",
|
|
6900
6951
|
stopRouting: "\u505C\u6B62",
|
|
6952
|
+
exitFailed: "\u5DF2\u5931\u8D25",
|
|
6953
|
+
exitReconnect: "\u91CD\u65B0\u8FDE\u63A5",
|
|
6954
|
+
exitReconnectAll: "\u5168\u90E8\u91CD\u8FDE",
|
|
6955
|
+
exitChecking: "\u68C0\u6D4B\u4E2D\u2026",
|
|
6956
|
+
exitNotChecked: "\u672A\u68C0\u6D4B",
|
|
6957
|
+
exitRetrying: "\u91CD\u8BD5\u4E2D",
|
|
6958
|
+
noExitAvailable: "\u6CA1\u6709\u53EF\u7528\u7684\u51FA\u53E3 \u2014\u2014 \u8DEF\u7531\u548C\u4EE3\u7406\u5DF2\u5173\u95ED\u3002",
|
|
6959
|
+
noExitHint: "\u6240\u6709\u51FA\u53E3\u90FD\u8FDE\u7EED\u5931\u8D25 3 \u6B21,\u5DF2\u4E0D\u518D\u81EA\u52A8\u68C0\u6D4B\u3002\u70B9\u300C\u91CD\u65B0\u8FDE\u63A5\u300D\u518D\u8BD5\u4E00\u6B21\u3002",
|
|
6960
|
+
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
6961
|
identity: "\u8EAB\u4EFD",
|
|
6902
6962
|
userId: "\u7528\u6237 ID",
|
|
6903
6963
|
carrierAddr: "Carrier \u5730\u5740",
|
|
@@ -7192,7 +7252,7 @@ function DkApp() {
|
|
|
7192
7252
|
return hasTab(tabs, want) || DK_PEOPLE_TABS.includes(want) && showPeople ? want : firstTab;
|
|
7193
7253
|
});
|
|
7194
7254
|
const [activeId, setActiveId] = React.useState(null);
|
|
7195
|
-
const data = useDaemonData();
|
|
7255
|
+
const data = useDaemonData({ exits: tab === "network" });
|
|
7196
7256
|
const me = data.me;
|
|
7197
7257
|
const [upd, setUpd] = React.useState(null);
|
|
7198
7258
|
React.useEffect(() => {
|
|
@@ -7555,6 +7615,10 @@ function DkApp() {
|
|
|
7555
7615
|
const onEdit = (name, description) => dkApi.setProfile(name, description).then(data.refresh);
|
|
7556
7616
|
const onSetExit = () => {
|
|
7557
7617
|
};
|
|
7618
|
+
const onReconnectExit = (ip) => (ip ? dkApi.reconnectExit(ip) : dkApi.reconnectAllExits()).then((r) => {
|
|
7619
|
+
data.refresh();
|
|
7620
|
+
return r;
|
|
7621
|
+
});
|
|
7558
7622
|
const onOpenChat = (id) => {
|
|
7559
7623
|
setTab("chat");
|
|
7560
7624
|
openConversation(id);
|
|
@@ -7634,7 +7698,7 @@ function DkApp() {
|
|
|
7634
7698
|
fontWeight: 600,
|
|
7635
7699
|
background: tab === n.id ? "var(--accent)" : "transparent",
|
|
7636
7700
|
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(
|
|
7701
|
+
} }, /* @__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, 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
7702
|
ProfileTab,
|
|
7639
7703
|
{
|
|
7640
7704
|
T,
|
package/package.json
CHANGED