@decentnetwork/beagle 0.1.60 → 0.1.63
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/carrier-node.d.ts +5 -0
- package/dist/carrier-node.js +2 -0
- package/dist/desktop/app.js +510 -417
- package/dist/embedded-host.d.ts +3 -0
- package/dist/embedded-host.js +20 -2
- package/dist/server.js +165 -16
- package/package.json +3 -3
package/dist/desktop/app.js
CHANGED
|
@@ -1,324 +1,7 @@
|
|
|
1
|
-
window.__DK_UI_VERSION="0.1.
|
|
1
|
+
window.__DK_UI_VERSION="0.1.63";
|
|
2
2
|
"use strict";
|
|
3
3
|
(() => {
|
|
4
4
|
// packages/beagle-ui/dist/beagle-ui.js
|
|
5
|
-
var ICON_PATHS = {
|
|
6
|
-
// ---- tab bar (the four must feel like one set) ----
|
|
7
|
-
users: '<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/>',
|
|
8
|
-
grid: '<rect x="3" y="3" width="7.5" height="7.5" rx="1.6"/><rect x="13.5" y="3" width="7.5" height="7.5" rx="1.6"/><rect x="13.5" y="13.5" width="7.5" height="7.5" rx="1.6"/><rect x="3" y="13.5" width="7.5" height="7.5" rx="1.6"/>',
|
|
9
|
-
wallet: '<path d="M19 7V6a2 2 0 0 0-2-2H6a3 3 0 0 0-3 3v10a3 3 0 0 0 3 3h12a2 2 0 0 0 2-2v-1"/><path d="M3 7a3 3 0 0 0 3 3h13a2 2 0 0 1 2 2v0a2 2 0 0 1-2 2h-3"/><circle cx="16.5" cy="14" r="1.15" fill="currentColor" stroke="none"/>',
|
|
10
|
-
userRound: '<circle cx="12" cy="8" r="4.5"/><path d="M20 21a8 8 0 0 0-16 0"/>',
|
|
11
|
-
// ---- actions / chrome ----
|
|
12
|
-
search: '<circle cx="11" cy="11" r="7.5"/><path d="m21 21-4.3-4.3"/>',
|
|
13
|
-
plus: '<path d="M5 12h14M12 5v14"/>',
|
|
14
|
-
chevronRight: '<path d="m9 18 6-6-6-6"/>',
|
|
15
|
-
chevronLeft: '<path d="m15 18-6-6 6-6"/>',
|
|
16
|
-
info: '<circle cx="12" cy="12" r="9.5"/><path d="M12 16.5v-5M12 7.6h.01"/>',
|
|
17
|
-
more: '<circle cx="5" cy="12" r="1.4" fill="currentColor" stroke="none"/><circle cx="12" cy="12" r="1.4" fill="currentColor" stroke="none"/><circle cx="19" cy="12" r="1.4" fill="currentColor" stroke="none"/>',
|
|
18
|
-
x: '<path d="M18 6 6 18M6 6l12 12"/>',
|
|
19
|
-
check: '<path d="M20 6 9 17l-5-5"/>',
|
|
20
|
-
checkCheck: '<path d="M18 6 7 17l-5-5"/><path d="m22 10-7.6 7.6L13 16"/>',
|
|
21
|
-
copy: '<rect x="9" y="9" width="12" height="12" rx="2.4"/><path d="M6 15H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v1"/>',
|
|
22
|
-
// Three linked nodes — an address is for passing ON to someone else, so it
|
|
23
|
-
// must not wear the same glyph as the userid's plain copy.
|
|
24
|
-
share: '<circle cx="18" cy="5" r="2.6"/><circle cx="6" cy="12" r="2.6"/><circle cx="18" cy="19" r="2.6"/><path d="M8.3 10.8l7.4-4.3M8.3 13.2l7.4 4.3"/>',
|
|
25
|
-
refresh: '<path d="M21 12a9 9 0 1 1-2.6-6.3"/><path d="M21 4v4.5h-4.5"/>',
|
|
26
|
-
clock: '<circle cx="12" cy="12" r="9.5"/><path d="M12 7.5V12l3 2"/>',
|
|
27
|
-
edit: '<path d="M11 4H6a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-5"/><path d="M18.5 2.5a2.12 2.12 0 0 1 3 3L12 15l-4 1 1-4Z"/>',
|
|
28
|
-
qr: '<rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><path d="M14 14h3v3M21 14v.01M14 21h.01M17 21h.01M21 17v4"/>',
|
|
29
|
-
// ---- app tiles ----
|
|
30
|
-
video: '<path d="m22 8.5-5.4 3.5 5.4 3.5V8.5Z"/><rect x="2" y="6" width="14.5" height="12" rx="3"/>',
|
|
31
|
-
monitor: '<rect x="2" y="3" width="20" height="14" rx="2"/><path d="M8 21h8M12 17v4"/>',
|
|
32
|
-
sparkles: '<path d="M12 3.5 13.6 9 19 10.5 13.6 12 12 17.5 10.4 12 5 10.5 10.4 9 12 3.5Z"/><path d="M19 3.5v3.2M20.6 5.1h-3.2"/><path d="M5 16v2.4M6.2 17.2H3.8"/>',
|
|
33
|
-
mic: '<rect x="9" y="2.5" width="6" height="11.5" rx="3"/><path d="M5.5 11a6.5 6.5 0 0 0 13 0"/><path d="M12 17.5v3.5"/>',
|
|
34
|
-
flask: '<path d="M9.5 3v6.2L4.8 17.4A2 2 0 0 0 6.5 20.5h11a2 2 0 0 0 1.7-3.1L14.5 9.2V3"/><path d="M8.5 3h7"/><path d="M7.3 15h9.4"/>',
|
|
35
|
-
headphones: '<path d="M3.5 14v-1.5a8.5 8.5 0 0 1 17 0V14"/><path d="M3.5 14.5a2.5 2.5 0 0 1 2.5-2.5h0a1.5 1.5 0 0 1 1.5 1.5v3.5a1.5 1.5 0 0 1-1.5 1.5h0a2.5 2.5 0 0 1-2.5-2.5Z"/><path d="M20.5 14.5a2.5 2.5 0 0 0-2.5-2.5h0a1.5 1.5 0 0 0-1.5 1.5v3.5a1.5 1.5 0 0 0 1.5 1.5h0a2.5 2.5 0 0 0 2.5-2.5Z"/>',
|
|
36
|
-
globe: '<circle cx="12" cy="12" r="9.5"/><path d="M2.5 12h19"/><path d="M12 2.5a14 14 0 0 1 0 19 14 14 0 0 1 0-19Z"/>',
|
|
37
|
-
store: '<path d="M4 9.5V19a1.5 1.5 0 0 0 1.5 1.5h13A1.5 1.5 0 0 0 20 19V9.5"/><path d="M3 6.5 4.5 3.5h15L21 6.5a2.5 2.5 0 0 1-4.5 1.5 2.5 2.5 0 0 1-4.5 0 2.5 2.5 0 0 1-4.5 0A2.5 2.5 0 0 1 3 6.5Z"/>',
|
|
38
|
-
// ---- chat composer ----
|
|
39
|
-
camera: '<path d="M14.5 4.5h-5L7.2 7.2H4.5A2.5 2.5 0 0 0 2 9.7V18a2.5 2.5 0 0 0 2.5 2.5h15A2.5 2.5 0 0 0 22 18V9.7a2.5 2.5 0 0 0-2.5-2.5h-2.7L14.5 4.5Z"/><circle cx="12" cy="13.5" r="3.2"/>',
|
|
40
|
-
phone: '<path d="M16.5 21a2 2 0 0 0 2-2.2 1.9 1.9 0 0 0-.6-1.2l-2-1.7a2 2 0 0 0-2.4-.1l-.9.6a14 14 0 0 1-5-5l.6-.9a2 2 0 0 0-.1-2.4l-1.7-2a1.9 1.9 0 0 0-1.2-.6A2 2 0 0 0 3 5.5 16 16 0 0 0 16.5 21Z"/>',
|
|
41
|
-
bolt: '<path d="M13 2 4 13h7l-1 9 9-11h-7l1-9Z"/>',
|
|
42
|
-
arrowUp: '<path d="M12 20V5M6 11l6-6 6 6"/>',
|
|
43
|
-
send: '<path d="M21.5 4.5 10.5 13.5"/><path d="M21.5 4.5 14.8 21.5 11 13l-8.5-3.8 19-4.7Z"/>',
|
|
44
|
-
// ---- account ----
|
|
45
|
-
shield: '<path d="M12 21.5s7.5-3.8 7.5-9.5V5.5L12 2.8 4.5 5.5V12c0 5.7 7.5 9.5 7.5 9.5Z"/>',
|
|
46
|
-
download: '<path d="M12 3.5v11M7.5 10l4.5 4.5 4.5-4.5"/><path d="M5 20.5h14"/>',
|
|
47
|
-
// Folder with a magnifier corner — "reveal / show in file manager".
|
|
48
|
-
folderOpen: '<path d="M3 7.5a2 2 0 0 1 2-2h4l2 2.5h8a2 2 0 0 1 2 2V17a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2Z"/><circle cx="12" cy="13" r="2.4"/><path d="M13.9 14.9 15.5 16.5"/>',
|
|
49
|
-
migrate: '<path d="M8 4 4 8l4 4"/><path d="M4 8h13a3 3 0 0 1 3 3v1"/><path d="m16 20 4-4-4-4"/><path d="M20 16H7a3 3 0 0 1-3-3v-1"/>',
|
|
50
|
-
starCoin: '<circle cx="12" cy="12" r="9"/><path d="m12 7.2 1.4 2.9 3.2.4-2.3 2.2.6 3.1-2.9-1.5-2.9 1.5.6-3.1L8.4 10.5l3.2-.4L12 7.2Z" fill="currentColor" stroke="none"/>',
|
|
51
|
-
link: '<path d="M10.5 13.5a4 4 0 0 0 5.7 0l2.3-2.3a4 4 0 0 0-5.7-5.7l-1 1"/><path d="M13.5 10.5a4 4 0 0 0-5.7 0l-2.3 2.3a4 4 0 0 0 5.7 5.7l1-1"/>',
|
|
52
|
-
trendingUp: '<path d="M22 7.5 13.5 16l-4.5-4.5L2 18.5"/><path d="M16.5 7.5H22v5.5"/>',
|
|
53
|
-
bell: '<path d="M18 8.5a6 6 0 0 0-12 0c0 6.5-2.5 8-2.5 8h17S18 15 18 8.5Z"/><path d="M13.7 20.5a2 2 0 0 1-3.4 0"/>',
|
|
54
|
-
bot: '<rect x="3.5" y="9" width="17" height="11" rx="3"/><path d="M12 4.5v4.5"/><circle cx="12" cy="3" r="1.4"/><path d="M8.5 14.5h.01M15.5 14.5h.01"/><path d="M2 13.5v3M22 13.5v3"/>',
|
|
55
|
-
scan: '<path d="M3 8V6a3 3 0 0 1 3-3h2"/><path d="M16 3h2a3 3 0 0 1 3 3v2"/><path d="M21 16v2a3 3 0 0 1-3 3h-2"/><path d="M8 21H6a3 3 0 0 1-3-3v-2"/><path d="M7 12h10"/>',
|
|
56
|
-
userPlus: '<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M19 8v6M22 11h-6"/>',
|
|
57
|
-
at: '<circle cx="12" cy="12" r="4"/><path d="M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-3.9 7.9"/>',
|
|
58
|
-
keyRound: '<circle cx="7.5" cy="15.5" r="5.5"/><path d="m21 2-9.6 9.6"/><path d="m15.5 7.5 3 3L22 7l-3-3"/>',
|
|
59
|
-
alert: '<path d="M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/><path d="M12 9v4M12 17h.01"/>',
|
|
60
|
-
chevronDown: '<path d="m6 9 6 6 6-6"/>',
|
|
61
|
-
eye: '<path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/>',
|
|
62
|
-
book: '<path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2Z"/>',
|
|
63
|
-
trash: '<path d="M3 6h18"/><path d="M8 6V4.5A1.5 1.5 0 0 1 9.5 3h5A1.5 1.5 0 0 1 16 4.5V6"/><path d="M18.5 6l-1 13.5a2 2 0 0 1-2 1.5h-7a2 2 0 0 1-2-1.5L5.5 6"/><path d="M10 10.5v6M14 10.5v6"/>',
|
|
64
|
-
arrowDown: '<path d="M12 4v15M6 13l6 6 6-6"/>',
|
|
65
|
-
shrink: '<path d="M4 14h6v6"/><path d="M20 10h-6V4"/><path d="m14 10 7-7"/><path d="m3 21 7-7"/>',
|
|
66
|
-
maximize: '<path d="M8 3H5a2 2 0 0 0-2 2v3"/><path d="M21 8V5a2 2 0 0 0-2-2h-3"/><path d="M3 16v3a2 2 0 0 0 2 2h3"/><path d="M16 21h3a2 2 0 0 0 2-2v-3"/>',
|
|
67
|
-
theater: '<rect x="2.5" y="6.5" width="19" height="11" rx="2"/>',
|
|
68
|
-
speaker: '<path d="M11 5 6 9H3v6h3l5 4V5Z"/><path d="M16 9a3 3 0 0 1 0 6"/><path d="M19 7a6 6 0 0 1 0 10"/>',
|
|
69
|
-
micFill: '<rect x="9" y="2.5" width="6" height="11.5" rx="3"/><path d="M5.5 11a6.5 6.5 0 0 0 13 0"/><path d="M12 17.5v3.5"/>'
|
|
70
|
-
};
|
|
71
|
-
function Icon({ name, size = 24, stroke = 1.75, color = "currentColor", fill = "none", style }) {
|
|
72
|
-
const d = ICON_PATHS[name];
|
|
73
|
-
if (!d)
|
|
74
|
-
return null;
|
|
75
|
-
return /* @__PURE__ */ React.createElement(
|
|
76
|
-
"svg",
|
|
77
|
-
{
|
|
78
|
-
width: size,
|
|
79
|
-
height: size,
|
|
80
|
-
viewBox: "0 0 24 24",
|
|
81
|
-
fill,
|
|
82
|
-
stroke: color,
|
|
83
|
-
strokeWidth: stroke,
|
|
84
|
-
strokeLinecap: "round",
|
|
85
|
-
strokeLinejoin: "round",
|
|
86
|
-
style: { display: "block", flexShrink: 0, ...style },
|
|
87
|
-
dangerouslySetInnerHTML: { __html: d }
|
|
88
|
-
}
|
|
89
|
-
);
|
|
90
|
-
}
|
|
91
|
-
Object.assign(window, { Icon, ICON_PATHS });
|
|
92
|
-
var DK_FALLBACK_ICE_SERVERS = [
|
|
93
|
-
{ urls: "stun:stun.l.google.com:19302" },
|
|
94
|
-
{ urls: "turn:tokyo.fi.chat:3478", username: "allcom", credential: "allcompass" },
|
|
95
|
-
{ urls: "turn:tokyo.fi.chat:3478?transport=tcp", username: "allcom", credential: "allcompass" }
|
|
96
|
-
];
|
|
97
|
-
var DK_LIVE_ICE_SERVERS = [];
|
|
98
|
-
var _dkIcePromise = null;
|
|
99
|
-
var _dkIceWarmPromise = null;
|
|
100
|
-
function dkWarmCallIce(iceServers) {
|
|
101
|
-
if (_dkIceWarmPromise)
|
|
102
|
-
return _dkIceWarmPromise;
|
|
103
|
-
if (!window.RTCPeerConnection || !iceServers || !iceServers.length) {
|
|
104
|
-
_dkIceWarmPromise = Promise.resolve();
|
|
105
|
-
return _dkIceWarmPromise;
|
|
106
|
-
}
|
|
107
|
-
_dkIceWarmPromise = new Promise((resolve) => {
|
|
108
|
-
let pc;
|
|
109
|
-
let finished = false;
|
|
110
|
-
const done = (why) => {
|
|
111
|
-
if (finished)
|
|
112
|
-
return;
|
|
113
|
-
finished = true;
|
|
114
|
-
try {
|
|
115
|
-
if (pc)
|
|
116
|
-
pc.close();
|
|
117
|
-
} catch (e) {
|
|
118
|
-
}
|
|
119
|
-
console.log("[rtc] ICE warmup done (" + why + ")");
|
|
120
|
-
resolve();
|
|
121
|
-
};
|
|
122
|
-
try {
|
|
123
|
-
pc = new RTCPeerConnection({ iceServers, iceTransportPolicy: "all" });
|
|
124
|
-
const timer = setTimeout(() => done("timeout"), 5e3);
|
|
125
|
-
pc.onicecandidate = (ev) => {
|
|
126
|
-
const c = ev.candidate && ev.candidate.candidate;
|
|
127
|
-
if (c && /typ relay/.test(c)) {
|
|
128
|
-
clearTimeout(timer);
|
|
129
|
-
done("relay");
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
pc.onicegatheringstatechange = () => {
|
|
133
|
-
if (pc.iceGatheringState === "complete") {
|
|
134
|
-
clearTimeout(timer);
|
|
135
|
-
done("gather-complete");
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
pc.createDataChannel("ice-warm");
|
|
139
|
-
pc.createOffer().then((o) => pc.setLocalDescription(o)).catch(() => done("offer-fail"));
|
|
140
|
-
} catch (e) {
|
|
141
|
-
done("error");
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
return _dkIceWarmPromise;
|
|
145
|
-
}
|
|
146
|
-
function dkLoadCallIceServers() {
|
|
147
|
-
if (_dkIcePromise)
|
|
148
|
-
return _dkIcePromise;
|
|
149
|
-
_dkIcePromise = (async () => {
|
|
150
|
-
try {
|
|
151
|
-
const r = await fetch("/api/call-ice-servers", { headers: { "cache-control": "no-cache" } });
|
|
152
|
-
const d = await r.json();
|
|
153
|
-
if (d && d.ok && Array.isArray(d.iceServers) && d.iceServers.length) {
|
|
154
|
-
DK_LIVE_ICE_SERVERS.splice(0, DK_LIVE_ICE_SERVERS.length, ...d.iceServers);
|
|
155
|
-
console.log("[rtc] Carrier bootstrap ICE servers:", DK_LIVE_ICE_SERVERS.map((s) => s.urls));
|
|
156
|
-
await dkWarmCallIce(DK_LIVE_ICE_SERVERS);
|
|
157
|
-
return DK_LIVE_ICE_SERVERS;
|
|
158
|
-
}
|
|
159
|
-
console.warn("[rtc] call-ice-servers unavailable:", d && d.error);
|
|
160
|
-
} catch (e) {
|
|
161
|
-
console.warn("[rtc] call-ice-servers fetch failed", e);
|
|
162
|
-
}
|
|
163
|
-
console.warn("[rtc] falling back to tokyo TURN \u2014 web\u2194Android online ICE may fail");
|
|
164
|
-
DK_LIVE_ICE_SERVERS.splice(0, DK_LIVE_ICE_SERVERS.length, ...DK_FALLBACK_ICE_SERVERS.map((s) => ({ ...s })));
|
|
165
|
-
await dkWarmCallIce(DK_LIVE_ICE_SERVERS);
|
|
166
|
-
return DK_LIVE_ICE_SERVERS;
|
|
167
|
-
})();
|
|
168
|
-
return _dkIcePromise;
|
|
169
|
-
}
|
|
170
|
-
function dkAwaitCallIceServers(ms) {
|
|
171
|
-
const budget = typeof ms === "number" ? ms : 1e4;
|
|
172
|
-
return Promise.race([
|
|
173
|
-
dkLoadCallIceServers(),
|
|
174
|
-
new Promise((resolve) => setTimeout(() => {
|
|
175
|
-
if (!DK_LIVE_ICE_SERVERS.length) {
|
|
176
|
-
DK_LIVE_ICE_SERVERS.splice(0, DK_LIVE_ICE_SERVERS.length, ...DK_FALLBACK_ICE_SERVERS.map((s) => ({ ...s })));
|
|
177
|
-
console.warn("[rtc] ICE wait timed out \u2014 using fallback");
|
|
178
|
-
}
|
|
179
|
-
resolve(DK_LIVE_ICE_SERVERS);
|
|
180
|
-
}, budget))
|
|
181
|
-
]).then(() => DK_LIVE_ICE_SERVERS);
|
|
182
|
-
}
|
|
183
|
-
dkLoadCallIceServers();
|
|
184
|
-
function dkRtcParseEnvelope(data) {
|
|
185
|
-
const text = String(data || "").replace(/\0+$/u, "").trim();
|
|
186
|
-
if (!text)
|
|
187
|
-
return null;
|
|
188
|
-
try {
|
|
189
|
-
const obj = JSON.parse(text);
|
|
190
|
-
if (obj && obj.dkRtc === 1 && typeof obj.kind === "string")
|
|
191
|
-
return obj;
|
|
192
|
-
} catch (e) {
|
|
193
|
-
}
|
|
194
|
-
return null;
|
|
195
|
-
}
|
|
196
|
-
function dkRtcSignalBus() {
|
|
197
|
-
if (window.__dkRtcSignalBus)
|
|
198
|
-
return window.__dkRtcSignalBus;
|
|
199
|
-
const PW = window.PeerWebRTC;
|
|
200
|
-
const handlers = /* @__PURE__ */ new Map();
|
|
201
|
-
const pendingCalls = [];
|
|
202
|
-
const PENDING_CALL_CAP = 16;
|
|
203
|
-
let started = false;
|
|
204
|
-
let stopped = false;
|
|
205
|
-
function emit(kind, userid, payload) {
|
|
206
|
-
const set = handlers.get(kind);
|
|
207
|
-
if (!set || !set.size) {
|
|
208
|
-
if (kind === "call") {
|
|
209
|
-
pendingCalls.push({ userid, payload });
|
|
210
|
-
if (pendingCalls.length > PENDING_CALL_CAP)
|
|
211
|
-
pendingCalls.shift();
|
|
212
|
-
}
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
for (const h of Array.from(set)) {
|
|
216
|
-
try {
|
|
217
|
-
h(userid, payload);
|
|
218
|
-
} catch (e) {
|
|
219
|
-
console.warn("[rtc] signal handler failed", e);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
async function pollLoop() {
|
|
224
|
-
let cursor = null;
|
|
225
|
-
while (!stopped) {
|
|
226
|
-
let signals = [];
|
|
227
|
-
try {
|
|
228
|
-
const u = cursor == null ? "/api/call-poll" : "/api/call-poll?since=" + cursor;
|
|
229
|
-
const r = await fetch(u, { headers: { "cache-control": "no-cache" } });
|
|
230
|
-
const d = await r.json();
|
|
231
|
-
signals = d && d.signals || [];
|
|
232
|
-
if (d && typeof d.cursor === "number")
|
|
233
|
-
cursor = d.cursor;
|
|
234
|
-
} catch (e) {
|
|
235
|
-
await new Promise((res) => setTimeout(res, 1e3));
|
|
236
|
-
continue;
|
|
237
|
-
}
|
|
238
|
-
for (const s of signals) {
|
|
239
|
-
const env = dkRtcParseEnvelope(s.data);
|
|
240
|
-
if (env) {
|
|
241
|
-
emit(env.kind, s.userid, env);
|
|
242
|
-
continue;
|
|
243
|
-
}
|
|
244
|
-
if (PW) {
|
|
245
|
-
try {
|
|
246
|
-
emit("call", s.userid, PW.decodeSignal(s.data));
|
|
247
|
-
} catch (e) {
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
const bus = {
|
|
254
|
-
start() {
|
|
255
|
-
if (started)
|
|
256
|
-
return;
|
|
257
|
-
started = true;
|
|
258
|
-
stopped = false;
|
|
259
|
-
pollLoop();
|
|
260
|
-
},
|
|
261
|
-
on(kind, cb) {
|
|
262
|
-
if (!handlers.has(kind))
|
|
263
|
-
handlers.set(kind, /* @__PURE__ */ new Set());
|
|
264
|
-
handlers.get(kind).add(cb);
|
|
265
|
-
this.start();
|
|
266
|
-
if (kind === "call" && pendingCalls.length) {
|
|
267
|
-
const queued = pendingCalls.splice(0);
|
|
268
|
-
console.log("[rtc] flushing " + queued.length + " buffered call signal(s)");
|
|
269
|
-
for (const q of queued) {
|
|
270
|
-
try {
|
|
271
|
-
cb(q.userid, q.payload);
|
|
272
|
-
} catch (e) {
|
|
273
|
-
console.warn("[rtc] buffered call handler failed", e);
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
return () => {
|
|
278
|
-
var _a;
|
|
279
|
-
return (_a = handlers.get(kind)) == null ? void 0 : _a.delete(cb);
|
|
280
|
-
};
|
|
281
|
-
},
|
|
282
|
-
async send(userid, data) {
|
|
283
|
-
const body = JSON.stringify({ userid, data: typeof data === "string" ? data : JSON.stringify(data) });
|
|
284
|
-
const r = await fetch("/api/call-signal", {
|
|
285
|
-
method: "POST",
|
|
286
|
-
headers: { "content-type": "application/json" },
|
|
287
|
-
body
|
|
288
|
-
});
|
|
289
|
-
const d = await r.json().catch(() => ({ ok: r.ok }));
|
|
290
|
-
if (!d.ok)
|
|
291
|
-
throw new Error(d.error || "call-signal send failed");
|
|
292
|
-
},
|
|
293
|
-
stop() {
|
|
294
|
-
stopped = true;
|
|
295
|
-
}
|
|
296
|
-
};
|
|
297
|
-
window.__dkRtcSignalBus = bus;
|
|
298
|
-
return bus;
|
|
299
|
-
}
|
|
300
|
-
function makeDaemonSignaling() {
|
|
301
|
-
const PW = window.PeerWebRTC;
|
|
302
|
-
const bus = dkRtcSignalBus();
|
|
303
|
-
let off = null;
|
|
304
|
-
return {
|
|
305
|
-
async send(peerId, signal) {
|
|
306
|
-
await bus.send(peerId, PW.encodeSignal(signal));
|
|
307
|
-
},
|
|
308
|
-
onSignal(cb) {
|
|
309
|
-
if (off)
|
|
310
|
-
off();
|
|
311
|
-
off = bus.on("call", cb);
|
|
312
|
-
},
|
|
313
|
-
stop() {
|
|
314
|
-
if (off) {
|
|
315
|
-
off();
|
|
316
|
-
off = null;
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
};
|
|
320
|
-
}
|
|
321
|
-
Object.assign(window, { dkRtcSignalBus, makeDaemonSignaling });
|
|
322
5
|
var H = {};
|
|
323
6
|
var hostNeedsWelcome = false;
|
|
324
7
|
var hostPrefersRtcFile = false;
|
|
@@ -625,19 +308,106 @@ window.__DK_UI_VERSION="0.1.60";
|
|
|
625
308
|
setThreads((t) => Object.assign({}, t, { [peerId]: withDay }));
|
|
626
309
|
} catch (e) {
|
|
627
310
|
}
|
|
628
|
-
}, []);
|
|
629
|
-
return Object.assign({}, snap, { threads, refresh, loadThread });
|
|
311
|
+
}, []);
|
|
312
|
+
return Object.assign({}, snap, { threads, refresh, loadThread });
|
|
313
|
+
}
|
|
314
|
+
Object.assign(window, {
|
|
315
|
+
dkHash,
|
|
316
|
+
dkIdenticon,
|
|
317
|
+
dkClock,
|
|
318
|
+
dkDayLabel,
|
|
319
|
+
dkApi,
|
|
320
|
+
useDaemonData,
|
|
321
|
+
DK_ME_FALLBACK,
|
|
322
|
+
dkCopy
|
|
323
|
+
});
|
|
324
|
+
var ICON_PATHS = {
|
|
325
|
+
// ---- tab bar (the four must feel like one set) ----
|
|
326
|
+
users: '<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/>',
|
|
327
|
+
grid: '<rect x="3" y="3" width="7.5" height="7.5" rx="1.6"/><rect x="13.5" y="3" width="7.5" height="7.5" rx="1.6"/><rect x="13.5" y="13.5" width="7.5" height="7.5" rx="1.6"/><rect x="3" y="13.5" width="7.5" height="7.5" rx="1.6"/>',
|
|
328
|
+
wallet: '<path d="M19 7V6a2 2 0 0 0-2-2H6a3 3 0 0 0-3 3v10a3 3 0 0 0 3 3h12a2 2 0 0 0 2-2v-1"/><path d="M3 7a3 3 0 0 0 3 3h13a2 2 0 0 1 2 2v0a2 2 0 0 1-2 2h-3"/><circle cx="16.5" cy="14" r="1.15" fill="currentColor" stroke="none"/>',
|
|
329
|
+
userRound: '<circle cx="12" cy="8" r="4.5"/><path d="M20 21a8 8 0 0 0-16 0"/>',
|
|
330
|
+
// ---- actions / chrome ----
|
|
331
|
+
search: '<circle cx="11" cy="11" r="7.5"/><path d="m21 21-4.3-4.3"/>',
|
|
332
|
+
plus: '<path d="M5 12h14M12 5v14"/>',
|
|
333
|
+
chevronRight: '<path d="m9 18 6-6-6-6"/>',
|
|
334
|
+
chevronLeft: '<path d="m15 18-6-6 6-6"/>',
|
|
335
|
+
info: '<circle cx="12" cy="12" r="9.5"/><path d="M12 16.5v-5M12 7.6h.01"/>',
|
|
336
|
+
more: '<circle cx="5" cy="12" r="1.4" fill="currentColor" stroke="none"/><circle cx="12" cy="12" r="1.4" fill="currentColor" stroke="none"/><circle cx="19" cy="12" r="1.4" fill="currentColor" stroke="none"/>',
|
|
337
|
+
x: '<path d="M18 6 6 18M6 6l12 12"/>',
|
|
338
|
+
check: '<path d="M20 6 9 17l-5-5"/>',
|
|
339
|
+
checkCheck: '<path d="M18 6 7 17l-5-5"/><path d="m22 10-7.6 7.6L13 16"/>',
|
|
340
|
+
copy: '<rect x="9" y="9" width="12" height="12" rx="2.4"/><path d="M6 15H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v1"/>',
|
|
341
|
+
// Three linked nodes — an address is for passing ON to someone else, so it
|
|
342
|
+
// must not wear the same glyph as the userid's plain copy.
|
|
343
|
+
share: '<circle cx="18" cy="5" r="2.6"/><circle cx="6" cy="12" r="2.6"/><circle cx="18" cy="19" r="2.6"/><path d="M8.3 10.8l7.4-4.3M8.3 13.2l7.4 4.3"/>',
|
|
344
|
+
refresh: '<path d="M21 12a9 9 0 1 1-2.6-6.3"/><path d="M21 4v4.5h-4.5"/>',
|
|
345
|
+
clock: '<circle cx="12" cy="12" r="9.5"/><path d="M12 7.5V12l3 2"/>',
|
|
346
|
+
edit: '<path d="M11 4H6a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-5"/><path d="M18.5 2.5a2.12 2.12 0 0 1 3 3L12 15l-4 1 1-4Z"/>',
|
|
347
|
+
qr: '<rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><path d="M14 14h3v3M21 14v.01M14 21h.01M17 21h.01M21 17v4"/>',
|
|
348
|
+
// ---- app tiles ----
|
|
349
|
+
video: '<path d="m22 8.5-5.4 3.5 5.4 3.5V8.5Z"/><rect x="2" y="6" width="14.5" height="12" rx="3"/>',
|
|
350
|
+
monitor: '<rect x="2" y="3" width="20" height="14" rx="2"/><path d="M8 21h8M12 17v4"/>',
|
|
351
|
+
sparkles: '<path d="M12 3.5 13.6 9 19 10.5 13.6 12 12 17.5 10.4 12 5 10.5 10.4 9 12 3.5Z"/><path d="M19 3.5v3.2M20.6 5.1h-3.2"/><path d="M5 16v2.4M6.2 17.2H3.8"/>',
|
|
352
|
+
mic: '<rect x="9" y="2.5" width="6" height="11.5" rx="3"/><path d="M5.5 11a6.5 6.5 0 0 0 13 0"/><path d="M12 17.5v3.5"/>',
|
|
353
|
+
flask: '<path d="M9.5 3v6.2L4.8 17.4A2 2 0 0 0 6.5 20.5h11a2 2 0 0 0 1.7-3.1L14.5 9.2V3"/><path d="M8.5 3h7"/><path d="M7.3 15h9.4"/>',
|
|
354
|
+
headphones: '<path d="M3.5 14v-1.5a8.5 8.5 0 0 1 17 0V14"/><path d="M3.5 14.5a2.5 2.5 0 0 1 2.5-2.5h0a1.5 1.5 0 0 1 1.5 1.5v3.5a1.5 1.5 0 0 1-1.5 1.5h0a2.5 2.5 0 0 1-2.5-2.5Z"/><path d="M20.5 14.5a2.5 2.5 0 0 0-2.5-2.5h0a1.5 1.5 0 0 0-1.5 1.5v3.5a1.5 1.5 0 0 0 1.5 1.5h0a2.5 2.5 0 0 0 2.5-2.5Z"/>',
|
|
355
|
+
globe: '<circle cx="12" cy="12" r="9.5"/><path d="M2.5 12h19"/><path d="M12 2.5a14 14 0 0 1 0 19 14 14 0 0 1 0-19Z"/>',
|
|
356
|
+
store: '<path d="M4 9.5V19a1.5 1.5 0 0 0 1.5 1.5h13A1.5 1.5 0 0 0 20 19V9.5"/><path d="M3 6.5 4.5 3.5h15L21 6.5a2.5 2.5 0 0 1-4.5 1.5 2.5 2.5 0 0 1-4.5 0 2.5 2.5 0 0 1-4.5 0A2.5 2.5 0 0 1 3 6.5Z"/>',
|
|
357
|
+
// ---- chat composer ----
|
|
358
|
+
camera: '<path d="M14.5 4.5h-5L7.2 7.2H4.5A2.5 2.5 0 0 0 2 9.7V18a2.5 2.5 0 0 0 2.5 2.5h15A2.5 2.5 0 0 0 22 18V9.7a2.5 2.5 0 0 0-2.5-2.5h-2.7L14.5 4.5Z"/><circle cx="12" cy="13.5" r="3.2"/>',
|
|
359
|
+
phone: '<path d="M16.5 21a2 2 0 0 0 2-2.2 1.9 1.9 0 0 0-.6-1.2l-2-1.7a2 2 0 0 0-2.4-.1l-.9.6a14 14 0 0 1-5-5l.6-.9a2 2 0 0 0-.1-2.4l-1.7-2a1.9 1.9 0 0 0-1.2-.6A2 2 0 0 0 3 5.5 16 16 0 0 0 16.5 21Z"/>',
|
|
360
|
+
bolt: '<path d="M13 2 4 13h7l-1 9 9-11h-7l1-9Z"/>',
|
|
361
|
+
arrowUp: '<path d="M12 20V5M6 11l6-6 6 6"/>',
|
|
362
|
+
send: '<path d="M21.5 4.5 10.5 13.5"/><path d="M21.5 4.5 14.8 21.5 11 13l-8.5-3.8 19-4.7Z"/>',
|
|
363
|
+
// ---- account ----
|
|
364
|
+
shield: '<path d="M12 21.5s7.5-3.8 7.5-9.5V5.5L12 2.8 4.5 5.5V12c0 5.7 7.5 9.5 7.5 9.5Z"/>',
|
|
365
|
+
download: '<path d="M12 3.5v11M7.5 10l4.5 4.5 4.5-4.5"/><path d="M5 20.5h14"/>',
|
|
366
|
+
// Folder with a magnifier corner — "reveal / show in file manager".
|
|
367
|
+
folderOpen: '<path d="M3 7.5a2 2 0 0 1 2-2h4l2 2.5h8a2 2 0 0 1 2 2V17a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2Z"/><circle cx="12" cy="13" r="2.4"/><path d="M13.9 14.9 15.5 16.5"/>',
|
|
368
|
+
migrate: '<path d="M8 4 4 8l4 4"/><path d="M4 8h13a3 3 0 0 1 3 3v1"/><path d="m16 20 4-4-4-4"/><path d="M20 16H7a3 3 0 0 1-3-3v-1"/>',
|
|
369
|
+
starCoin: '<circle cx="12" cy="12" r="9"/><path d="m12 7.2 1.4 2.9 3.2.4-2.3 2.2.6 3.1-2.9-1.5-2.9 1.5.6-3.1L8.4 10.5l3.2-.4L12 7.2Z" fill="currentColor" stroke="none"/>',
|
|
370
|
+
link: '<path d="M10.5 13.5a4 4 0 0 0 5.7 0l2.3-2.3a4 4 0 0 0-5.7-5.7l-1 1"/><path d="M13.5 10.5a4 4 0 0 0-5.7 0l-2.3 2.3a4 4 0 0 0 5.7 5.7l1-1"/>',
|
|
371
|
+
trendingUp: '<path d="M22 7.5 13.5 16l-4.5-4.5L2 18.5"/><path d="M16.5 7.5H22v5.5"/>',
|
|
372
|
+
bell: '<path d="M18 8.5a6 6 0 0 0-12 0c0 6.5-2.5 8-2.5 8h17S18 15 18 8.5Z"/><path d="M13.7 20.5a2 2 0 0 1-3.4 0"/>',
|
|
373
|
+
bot: '<rect x="3.5" y="9" width="17" height="11" rx="3"/><path d="M12 4.5v4.5"/><circle cx="12" cy="3" r="1.4"/><path d="M8.5 14.5h.01M15.5 14.5h.01"/><path d="M2 13.5v3M22 13.5v3"/>',
|
|
374
|
+
scan: '<path d="M3 8V6a3 3 0 0 1 3-3h2"/><path d="M16 3h2a3 3 0 0 1 3 3v2"/><path d="M21 16v2a3 3 0 0 1-3 3h-2"/><path d="M8 21H6a3 3 0 0 1-3-3v-2"/><path d="M7 12h10"/>',
|
|
375
|
+
userPlus: '<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M19 8v6M22 11h-6"/>',
|
|
376
|
+
at: '<circle cx="12" cy="12" r="4"/><path d="M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-3.9 7.9"/>',
|
|
377
|
+
keyRound: '<circle cx="7.5" cy="15.5" r="5.5"/><path d="m21 2-9.6 9.6"/><path d="m15.5 7.5 3 3L22 7l-3-3"/>',
|
|
378
|
+
alert: '<path d="M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/><path d="M12 9v4M12 17h.01"/>',
|
|
379
|
+
chevronDown: '<path d="m6 9 6 6 6-6"/>',
|
|
380
|
+
eye: '<path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/>',
|
|
381
|
+
book: '<path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2Z"/>',
|
|
382
|
+
trash: '<path d="M3 6h18"/><path d="M8 6V4.5A1.5 1.5 0 0 1 9.5 3h5A1.5 1.5 0 0 1 16 4.5V6"/><path d="M18.5 6l-1 13.5a2 2 0 0 1-2 1.5h-7a2 2 0 0 1-2-1.5L5.5 6"/><path d="M10 10.5v6M14 10.5v6"/>',
|
|
383
|
+
arrowDown: '<path d="M12 4v15M6 13l6 6 6-6"/>',
|
|
384
|
+
shrink: '<path d="M4 14h6v6"/><path d="M20 10h-6V4"/><path d="m14 10 7-7"/><path d="m3 21 7-7"/>',
|
|
385
|
+
maximize: '<path d="M8 3H5a2 2 0 0 0-2 2v3"/><path d="M21 8V5a2 2 0 0 0-2-2h-3"/><path d="M3 16v3a2 2 0 0 0 2 2h3"/><path d="M16 21h3a2 2 0 0 0 2-2v-3"/>',
|
|
386
|
+
theater: '<rect x="2.5" y="6.5" width="19" height="11" rx="2"/>',
|
|
387
|
+
speaker: '<path d="M11 5 6 9H3v6h3l5 4V5Z"/><path d="M16 9a3 3 0 0 1 0 6"/><path d="M19 7a6 6 0 0 1 0 10"/>',
|
|
388
|
+
micFill: '<rect x="9" y="2.5" width="6" height="11.5" rx="3"/><path d="M5.5 11a6.5 6.5 0 0 0 13 0"/><path d="M12 17.5v3.5"/>'
|
|
389
|
+
};
|
|
390
|
+
function Icon({ name, size = 24, stroke = 1.75, color = "currentColor", fill = "none", style }) {
|
|
391
|
+
const d = ICON_PATHS[name];
|
|
392
|
+
if (!d)
|
|
393
|
+
return null;
|
|
394
|
+
return /* @__PURE__ */ React.createElement(
|
|
395
|
+
"svg",
|
|
396
|
+
{
|
|
397
|
+
width: size,
|
|
398
|
+
height: size,
|
|
399
|
+
viewBox: "0 0 24 24",
|
|
400
|
+
fill,
|
|
401
|
+
stroke: color,
|
|
402
|
+
strokeWidth: stroke,
|
|
403
|
+
strokeLinecap: "round",
|
|
404
|
+
strokeLinejoin: "round",
|
|
405
|
+
style: { display: "block", flexShrink: 0, ...style },
|
|
406
|
+
dangerouslySetInnerHTML: { __html: d }
|
|
407
|
+
}
|
|
408
|
+
);
|
|
630
409
|
}
|
|
631
|
-
Object.assign(window, {
|
|
632
|
-
dkHash,
|
|
633
|
-
dkIdenticon,
|
|
634
|
-
dkClock,
|
|
635
|
-
dkDayLabel,
|
|
636
|
-
dkApi,
|
|
637
|
-
useDaemonData,
|
|
638
|
-
DK_ME_FALLBACK,
|
|
639
|
-
dkCopy
|
|
640
|
-
});
|
|
410
|
+
Object.assign(window, { Icon, ICON_PATHS });
|
|
641
411
|
function RequestsBlock({ T, requests, onAct }) {
|
|
642
412
|
const [acted, setActed] = React.useState({});
|
|
643
413
|
const [failed, setFailed] = React.useState({});
|
|
@@ -2925,11 +2695,14 @@ ${peer.address}`
|
|
|
2925
2695
|
return /* @__PURE__ */ React.createElement(Card, { label: zh ? "\u663E\u793A" : "Display" }, /* @__PURE__ */ React.createElement("div", { style: { ...row, borderBottom: "1px solid var(--line)" } }, /* @__PURE__ */ React.createElement("span", { style: name }, zh ? "\u8BED\u8A00" : "Language"), seg("lang", t.lang, (v) => setTweak("lang", v), [["en", "EN"], ["zh", "\u4E2D\u6587"]])), /* @__PURE__ */ React.createElement("div", { style: row }, /* @__PURE__ */ React.createElement("span", { style: name }, zh ? "\u4E3B\u9898" : "Theme"), seg("theme", t.theme, (v) => setTweak("theme", v), [["dark", zh ? "\u6DF1\u8272" : "Dark"], ["light", zh ? "\u6D45\u8272" : "Light"]])));
|
|
2926
2696
|
}
|
|
2927
2697
|
function ProfileTab({ T, me, onEdit, t, setTweak }) {
|
|
2698
|
+
var _a;
|
|
2928
2699
|
const [qr, setQr] = React.useState(null);
|
|
2929
2700
|
const [editing, setEditing] = React.useState(false);
|
|
2930
2701
|
const [ensRec, setEnsRec] = React.useState(null);
|
|
2931
|
-
const
|
|
2932
|
-
const
|
|
2702
|
+
const pubPunk = ensRec && ensRec.nft === "CryptoPunks" && ensRec.nftid > 0 ? ensRec.nftid : null;
|
|
2703
|
+
const pubAvatar = ensRec && ensRec.texts && ensRec.texts.avatar || null;
|
|
2704
|
+
const punkId = (_a = me.punkId) != null ? _a : pubPunk;
|
|
2705
|
+
const upAvatar = me.avatarUrl || pubAvatar;
|
|
2933
2706
|
return /* @__PURE__ */ React.createElement("div", { style: { flex: 1, overflow: "auto", background: "var(--bg)" } }, /* @__PURE__ */ React.createElement("div", { style: { maxWidth: 760, margin: "0 auto", padding: "24px 28px 60px", display: "flex", flexDirection: "column", gap: 24 } }, /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 18, padding: "20px 22px", borderRadius: 14, background: "var(--panel)", border: "1px solid var(--line)" } }, /* @__PURE__ */ React.createElement("div", { style: { position: "relative" } }, upAvatar ? /* @__PURE__ */ React.createElement("img", { src: upAvatar, alt: "", width: 68, height: 68, style: { width: 68, height: 68, borderRadius: 16, objectFit: "cover", background: "var(--panel-2)" } }) : punkId != null ? /* @__PURE__ */ React.createElement(DkPunkAvatar, { id: punkId, size: 68, radius: 16, fallbackSeed: me.userId }) : /* @__PURE__ */ React.createElement(DkIdenticon, { seed: me.userId, size: 68, radius: 16 }), /* @__PURE__ */ React.createElement("span", { style: { position: "absolute", right: -3, bottom: -3, width: 18, height: 18, borderRadius: 999, background: "var(--online)", border: "3px solid var(--panel)" } })), /* @__PURE__ */ React.createElement("div", { style: { flex: 1, minWidth: 0 } }, /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 10 } }, /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 22, fontWeight: 700, letterSpacing: -0.5, color: "var(--text)" } }, me.name), /* @__PURE__ */ React.createElement(Tag, { tone: "ok" }, "online"), me.isExit && /* @__PURE__ */ React.createElement(Tag, { tone: "warn" }, "exit", me.exitRegion ? ` \xB7 ${me.exitRegion.toUpperCase()}` : "")), /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--mono)", fontSize: 13, color: "var(--dim)", marginTop: 4 } }, me.handle), me.description ? /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12.5, color: "var(--faint)", marginTop: 3 } }, me.description) : null), /* @__PURE__ */ React.createElement(Btn, { icon: "edit", onClick: () => setEditing(true) }, T.editProfile)), /* @__PURE__ */ React.createElement(Card, { label: T.identity }, /* @__PURE__ */ React.createElement(FieldRow, { T, label: T.userId, value: me.userId, copy: true, qr: true, onQr: (v, l) => setQr({ value: v, label: l }) }), /* @__PURE__ */ React.createElement(FieldRow, { T, label: T.carrierAddr, value: me.carrier, copy: true, qr: true, onQr: (v, l) => setQr({ value: v, label: l }) }), /* @__PURE__ */ React.createElement(FieldRow, { T, label: T.netKey, value: me.netKey, copy: true, last: true })), /* @__PURE__ */ React.createElement(DkEnsCard, { T, me, onRecord: setEnsRec }), typeof me.autoAccept === "boolean" && /* @__PURE__ */ React.createElement(Card, { label: T && T.friendsSettings || "Friends" }, /* @__PURE__ */ React.createElement("label", { style: { display: "flex", alignItems: "center", gap: 13, padding: "14px 16px", cursor: "pointer" } }, /* @__PURE__ */ React.createElement(
|
|
2934
2707
|
"input",
|
|
2935
2708
|
{
|
|
@@ -3034,95 +2807,409 @@ ${peer.address}`
|
|
|
3034
2807
|
return s;
|
|
3035
2808
|
return s.slice(0, head) + "\u2026" + s.slice(-tail);
|
|
3036
2809
|
}
|
|
3037
|
-
function RouteTag({ peer }) {
|
|
3038
|
-
if (!peer.online)
|
|
3039
|
-
return /* @__PURE__ */ React.createElement(Tag, { tone: "off" }, "offline");
|
|
3040
|
-
const relay = peer.via === "relay";
|
|
3041
|
-
const via = peer.via || "online";
|
|
3042
|
-
return /* @__PURE__ */ React.createElement(Tag, { tone: relay ? "warn" : "ok" }, peer.ping != null ? `${via} \xB7 ${peer.ping}ms` : via);
|
|
2810
|
+
function RouteTag({ peer }) {
|
|
2811
|
+
if (!peer.online)
|
|
2812
|
+
return /* @__PURE__ */ React.createElement(Tag, { tone: "off" }, "offline");
|
|
2813
|
+
const relay = peer.via === "relay";
|
|
2814
|
+
const via = peer.via || "online";
|
|
2815
|
+
return /* @__PURE__ */ React.createElement(Tag, { tone: relay ? "warn" : "ok" }, peer.ping != null ? `${via} \xB7 ${peer.ping}ms` : via);
|
|
2816
|
+
}
|
|
2817
|
+
function Tag({ children, tone = "neutral", style, title }) {
|
|
2818
|
+
const tones = {
|
|
2819
|
+
neutral: { bg: "var(--chip)", fg: "var(--dim)", bd: "transparent" },
|
|
2820
|
+
ok: { bg: "color-mix(in oklab, var(--online), transparent 86%)", fg: "var(--online)", bd: "transparent" },
|
|
2821
|
+
warn: { bg: "color-mix(in oklab, var(--warn), transparent 86%)", fg: "var(--warn)", bd: "transparent" },
|
|
2822
|
+
off: { bg: "var(--chip)", fg: "var(--faint)", bd: "transparent" },
|
|
2823
|
+
accent: { bg: "color-mix(in oklab, var(--accent), transparent 86%)", fg: "var(--accent)", bd: "transparent" },
|
|
2824
|
+
danger: { bg: "color-mix(in oklab, var(--danger), transparent 88%)", fg: "var(--danger)", bd: "transparent" }
|
|
2825
|
+
};
|
|
2826
|
+
const t = tones[tone] || tones.neutral;
|
|
2827
|
+
return /* @__PURE__ */ React.createElement("span", { title, style: {
|
|
2828
|
+
display: "inline-flex",
|
|
2829
|
+
alignItems: "center",
|
|
2830
|
+
gap: 4,
|
|
2831
|
+
height: 18,
|
|
2832
|
+
padding: "0 6px",
|
|
2833
|
+
borderRadius: 4,
|
|
2834
|
+
background: t.bg,
|
|
2835
|
+
color: t.fg,
|
|
2836
|
+
border: `1px solid ${t.bd}`,
|
|
2837
|
+
fontFamily: "var(--mono)",
|
|
2838
|
+
fontSize: 11,
|
|
2839
|
+
fontWeight: 600,
|
|
2840
|
+
letterSpacing: -0.1,
|
|
2841
|
+
lineHeight: 1,
|
|
2842
|
+
whiteSpace: "nowrap",
|
|
2843
|
+
...style
|
|
2844
|
+
} }, children);
|
|
2845
|
+
}
|
|
2846
|
+
function Unread({ n }) {
|
|
2847
|
+
if (!n)
|
|
2848
|
+
return null;
|
|
2849
|
+
return /* @__PURE__ */ React.createElement("span", { style: {
|
|
2850
|
+
minWidth: 18,
|
|
2851
|
+
height: 18,
|
|
2852
|
+
padding: "0 5px",
|
|
2853
|
+
borderRadius: 999,
|
|
2854
|
+
flexShrink: 0,
|
|
2855
|
+
background: "var(--accent)",
|
|
2856
|
+
color: "#fff",
|
|
2857
|
+
fontFamily: "var(--mono)",
|
|
2858
|
+
fontSize: 11,
|
|
2859
|
+
fontWeight: 700,
|
|
2860
|
+
lineHeight: "18px",
|
|
2861
|
+
textAlign: "center"
|
|
2862
|
+
} }, n);
|
|
2863
|
+
}
|
|
2864
|
+
function Btn({ children, icon, tone = "ghost", onClick, size = "md", title, style }) {
|
|
2865
|
+
const tones = {
|
|
2866
|
+
ghost: { bg: "transparent", fg: "var(--text)", bd: "var(--line)" },
|
|
2867
|
+
solid: { bg: "var(--accent)", fg: "#fff", bd: "transparent" },
|
|
2868
|
+
soft: { bg: "var(--chip)", fg: "var(--text)", bd: "transparent" },
|
|
2869
|
+
ok: { bg: "color-mix(in oklab, var(--online), transparent 84%)", fg: "var(--online)", bd: "transparent" },
|
|
2870
|
+
danger: { bg: "transparent", fg: "var(--danger)", bd: "color-mix(in oklab, var(--danger), transparent 70%)" }
|
|
2871
|
+
};
|
|
2872
|
+
const t = tones[tone] || tones.ghost;
|
|
2873
|
+
const h = size === "sm" ? 26 : size === "lg" ? 36 : 30;
|
|
2874
|
+
return /* @__PURE__ */ React.createElement("button", { onClick, title, style: {
|
|
2875
|
+
height: h,
|
|
2876
|
+
padding: icon && !children ? 0 : "0 11px",
|
|
2877
|
+
minWidth: icon && !children ? h : "auto",
|
|
2878
|
+
borderRadius: 6,
|
|
2879
|
+
cursor: "pointer",
|
|
2880
|
+
fontFamily: "var(--mono)",
|
|
2881
|
+
fontWeight: 600,
|
|
2882
|
+
fontSize: size === "sm" ? 12 : 12.5,
|
|
2883
|
+
letterSpacing: -0.1,
|
|
2884
|
+
background: t.bg,
|
|
2885
|
+
color: t.fg,
|
|
2886
|
+
border: `1px solid ${t.bd}`,
|
|
2887
|
+
display: "inline-flex",
|
|
2888
|
+
alignItems: "center",
|
|
2889
|
+
justifyContent: "center",
|
|
2890
|
+
gap: 6,
|
|
2891
|
+
whiteSpace: "nowrap",
|
|
2892
|
+
...style
|
|
2893
|
+
} }, icon && /* @__PURE__ */ React.createElement(Icon, { name: icon, size: 15, stroke: 2 }), children);
|
|
2894
|
+
}
|
|
2895
|
+
function Section({ label, count, trailing, style }) {
|
|
2896
|
+
return /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 8, padding: "0 2px", ...style } }, /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 11, fontWeight: 700, letterSpacing: 1, textTransform: "uppercase", color: "var(--faint)" } }, label), count != null && /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 11, fontWeight: 700, color: "var(--faint)" } }, count), /* @__PURE__ */ React.createElement("div", { style: { flex: 1, height: 1, background: "var(--line)" } }), trailing);
|
|
2897
|
+
}
|
|
2898
|
+
Object.assign(window, { DkIdenticon, DkBot, DkAvatar, DkImgAvatar, StatusDot, Mono, shortKey, RouteTag, Tag, Unread, Btn, Section });
|
|
2899
|
+
var APPS = [
|
|
2900
|
+
{
|
|
2901
|
+
id: "meet",
|
|
2902
|
+
name: "Beagle Meet",
|
|
2903
|
+
origin: "https://snoopy.fi.chat",
|
|
2904
|
+
url: "https://snoopy.fi.chat",
|
|
2905
|
+
blurb: { en: "Video calls and rooms \u2014 your Beagle identity is the login.", zh: "\u89C6\u9891\u4F1A\u8BAE\u548C\u623F\u95F4 \u2014\u2014 \u7528 Beagle \u8EAB\u4EFD\u76F4\u63A5\u767B\u5F55\u3002" },
|
|
2906
|
+
icon: "video"
|
|
2907
|
+
},
|
|
2908
|
+
{
|
|
2909
|
+
id: "interview",
|
|
2910
|
+
name: "interview.network",
|
|
2911
|
+
origin: "https://interview.network",
|
|
2912
|
+
url: "https://interview.network",
|
|
2913
|
+
blurb: { en: "Interviews, scheduled and held against a verified identity.", zh: "\u9762\u8BD5\u5B89\u6392\u4E0E\u8FDB\u884C\uFF0C\u8EAB\u4EFD\u53EF\u9A8C\u8BC1\u3002" },
|
|
2914
|
+
icon: "users"
|
|
2915
|
+
},
|
|
2916
|
+
{
|
|
2917
|
+
id: "readyplayer",
|
|
2918
|
+
name: "readyplayer.network",
|
|
2919
|
+
origin: "https://readyplayer.network",
|
|
2920
|
+
url: "https://readyplayer.network",
|
|
2921
|
+
blurb: { en: "Membership and the services that come with it.", zh: "\u4F1A\u5458\u4E0E\u914D\u5957\u670D\u52A1\u3002" },
|
|
2922
|
+
icon: "starCoin"
|
|
2923
|
+
},
|
|
2924
|
+
{
|
|
2925
|
+
id: "btc",
|
|
2926
|
+
name: "btc.fi.chat",
|
|
2927
|
+
origin: "https://btc.fi.chat",
|
|
2928
|
+
url: "https://btc.fi.chat",
|
|
2929
|
+
blurb: { en: "Trading desk and signals.", zh: "\u4EA4\u6613\u53F0\u4E0E\u4FE1\u53F7\u3002" },
|
|
2930
|
+
icon: "trendingUp"
|
|
2931
|
+
}
|
|
2932
|
+
];
|
|
2933
|
+
function dkB64Url(obj) {
|
|
2934
|
+
const json = JSON.stringify(obj);
|
|
2935
|
+
const b64 = btoa(unescape(encodeURIComponent(json)));
|
|
2936
|
+
return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
2937
|
+
}
|
|
2938
|
+
function AppsTab({ T, t }) {
|
|
2939
|
+
const zh = t && t.lang === "zh";
|
|
2940
|
+
const [busy, setBusy] = React.useState(null);
|
|
2941
|
+
const [err, setErr] = React.useState(null);
|
|
2942
|
+
const open = async (app) => {
|
|
2943
|
+
setBusy(app.id);
|
|
2944
|
+
setErr(null);
|
|
2945
|
+
const win = window.open("", "_blank");
|
|
2946
|
+
try {
|
|
2947
|
+
const r = await dkPost("/api/launch-token", { origin: app.origin });
|
|
2948
|
+
if (!r || r.ok === false)
|
|
2949
|
+
throw new Error(r && r.error || "could not sign");
|
|
2950
|
+
const { ok, ...assertion } = r;
|
|
2951
|
+
const url = app.url + "#beagle=" + dkB64Url(assertion);
|
|
2952
|
+
if (win)
|
|
2953
|
+
win.location = url;
|
|
2954
|
+
else
|
|
2955
|
+
window.open(url, "_blank");
|
|
2956
|
+
} catch (e) {
|
|
2957
|
+
if (win)
|
|
2958
|
+
win.close();
|
|
2959
|
+
setErr(String(e && e.message || e));
|
|
2960
|
+
} finally {
|
|
2961
|
+
setBusy(null);
|
|
2962
|
+
}
|
|
2963
|
+
};
|
|
2964
|
+
return /* @__PURE__ */ React.createElement("div", { style: { flex: 1, overflow: "auto", background: "var(--bg)" } }, /* @__PURE__ */ React.createElement("div", { style: { maxWidth: 760, margin: "0 auto", padding: "24px 28px 60px", display: "flex", flexDirection: "column", gap: 16 } }, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--mono)", fontSize: 11, fontWeight: 700, letterSpacing: 0.6, textTransform: "uppercase", color: "var(--faint)" } }, zh ? "\u5E94\u7528" : "Apps"), /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12.5, color: "var(--faint)", marginTop: 6, lineHeight: 1.6 } }, zh ? "\u8FD9\u4E9B\u5E94\u7528\u63A5\u53D7 Beagle \u8EAB\u4EFD\u3002\u4ECE\u8FD9\u91CC\u6253\u5F00\u4E0D\u9700\u8981\u518D\u767B\u5F55\u4E00\u6B21 \u2014\u2014 \u4F1A\u5E26\u4E0A\u4E00\u4E2A\u4E24\u5206\u949F\u5185\u6709\u6548\u7684\u7B7E\u540D\u3002" : "These accept a Beagle identity. Opening one from here does not ask you to sign in again \u2014 it carries a signature that is good for two minutes.")), err && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--mono)", fontSize: 11.5, color: "#f85149" } }, err), APPS.map((app) => /* @__PURE__ */ React.createElement("div", { key: app.id, style: {
|
|
2965
|
+
display: "flex",
|
|
2966
|
+
alignItems: "center",
|
|
2967
|
+
gap: 14,
|
|
2968
|
+
padding: "14px 16px",
|
|
2969
|
+
borderRadius: 12,
|
|
2970
|
+
background: "var(--panel)",
|
|
2971
|
+
border: "1px solid var(--line)"
|
|
2972
|
+
} }, /* @__PURE__ */ React.createElement("div", { style: {
|
|
2973
|
+
width: 38,
|
|
2974
|
+
height: 38,
|
|
2975
|
+
borderRadius: 10,
|
|
2976
|
+
flexShrink: 0,
|
|
2977
|
+
background: "var(--panel-2)",
|
|
2978
|
+
display: "flex",
|
|
2979
|
+
alignItems: "center",
|
|
2980
|
+
justifyContent: "center"
|
|
2981
|
+
} }, /* @__PURE__ */ React.createElement(Icon, { name: app.icon, size: 19, color: "var(--accent)", stroke: 1.8 })), /* @__PURE__ */ React.createElement("div", { style: { flex: 1, minWidth: 0 } }, /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 14, fontWeight: 600, color: "var(--text)" } }, app.name), /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12.5, color: "var(--faint)", marginTop: 2 } }, zh ? app.blurb.zh : app.blurb.en), /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--mono)", fontSize: 11, color: "var(--dim)", marginTop: 3 } }, app.origin.replace(/^https?:\/\//, ""))), /* @__PURE__ */ React.createElement(Btn, { tone: "accent", size: "sm", onClick: busy ? void 0 : () => open(app) }, busy === app.id ? zh ? "\u6253\u5F00\u4E2D\u2026" : "opening\u2026" : zh ? "\u6253\u5F00" : "Open")))));
|
|
2982
|
+
}
|
|
2983
|
+
var DK_FALLBACK_ICE_SERVERS = [
|
|
2984
|
+
{ urls: "stun:stun.l.google.com:19302" },
|
|
2985
|
+
{ urls: "turn:tokyo.fi.chat:3478", username: "allcom", credential: "allcompass" },
|
|
2986
|
+
{ urls: "turn:tokyo.fi.chat:3478?transport=tcp", username: "allcom", credential: "allcompass" }
|
|
2987
|
+
];
|
|
2988
|
+
var DK_LIVE_ICE_SERVERS = [];
|
|
2989
|
+
var _dkIcePromise = null;
|
|
2990
|
+
var _dkIceWarmPromise = null;
|
|
2991
|
+
function dkWarmCallIce(iceServers) {
|
|
2992
|
+
if (_dkIceWarmPromise)
|
|
2993
|
+
return _dkIceWarmPromise;
|
|
2994
|
+
if (!window.RTCPeerConnection || !iceServers || !iceServers.length) {
|
|
2995
|
+
_dkIceWarmPromise = Promise.resolve();
|
|
2996
|
+
return _dkIceWarmPromise;
|
|
2997
|
+
}
|
|
2998
|
+
_dkIceWarmPromise = new Promise((resolve) => {
|
|
2999
|
+
let pc;
|
|
3000
|
+
let finished = false;
|
|
3001
|
+
const done = (why) => {
|
|
3002
|
+
if (finished)
|
|
3003
|
+
return;
|
|
3004
|
+
finished = true;
|
|
3005
|
+
try {
|
|
3006
|
+
if (pc)
|
|
3007
|
+
pc.close();
|
|
3008
|
+
} catch (e) {
|
|
3009
|
+
}
|
|
3010
|
+
console.log("[rtc] ICE warmup done (" + why + ")");
|
|
3011
|
+
resolve();
|
|
3012
|
+
};
|
|
3013
|
+
try {
|
|
3014
|
+
pc = new RTCPeerConnection({ iceServers, iceTransportPolicy: "all" });
|
|
3015
|
+
const timer = setTimeout(() => done("timeout"), 5e3);
|
|
3016
|
+
pc.onicecandidate = (ev) => {
|
|
3017
|
+
const c = ev.candidate && ev.candidate.candidate;
|
|
3018
|
+
if (c && /typ relay/.test(c)) {
|
|
3019
|
+
clearTimeout(timer);
|
|
3020
|
+
done("relay");
|
|
3021
|
+
}
|
|
3022
|
+
};
|
|
3023
|
+
pc.onicegatheringstatechange = () => {
|
|
3024
|
+
if (pc.iceGatheringState === "complete") {
|
|
3025
|
+
clearTimeout(timer);
|
|
3026
|
+
done("gather-complete");
|
|
3027
|
+
}
|
|
3028
|
+
};
|
|
3029
|
+
pc.createDataChannel("ice-warm");
|
|
3030
|
+
pc.createOffer().then((o) => pc.setLocalDescription(o)).catch(() => done("offer-fail"));
|
|
3031
|
+
} catch (e) {
|
|
3032
|
+
done("error");
|
|
3033
|
+
}
|
|
3034
|
+
});
|
|
3035
|
+
return _dkIceWarmPromise;
|
|
3036
|
+
}
|
|
3037
|
+
function dkLoadCallIceServers() {
|
|
3038
|
+
if (_dkIcePromise)
|
|
3039
|
+
return _dkIcePromise;
|
|
3040
|
+
_dkIcePromise = (async () => {
|
|
3041
|
+
try {
|
|
3042
|
+
const r = await fetch("/api/call-ice-servers", { headers: { "cache-control": "no-cache" } });
|
|
3043
|
+
const d = await r.json();
|
|
3044
|
+
if (d && d.ok && Array.isArray(d.iceServers) && d.iceServers.length) {
|
|
3045
|
+
DK_LIVE_ICE_SERVERS.splice(0, DK_LIVE_ICE_SERVERS.length, ...d.iceServers);
|
|
3046
|
+
console.log("[rtc] Carrier bootstrap ICE servers:", DK_LIVE_ICE_SERVERS.map((s) => s.urls));
|
|
3047
|
+
await dkWarmCallIce(DK_LIVE_ICE_SERVERS);
|
|
3048
|
+
return DK_LIVE_ICE_SERVERS;
|
|
3049
|
+
}
|
|
3050
|
+
console.warn("[rtc] call-ice-servers unavailable:", d && d.error);
|
|
3051
|
+
} catch (e) {
|
|
3052
|
+
console.warn("[rtc] call-ice-servers fetch failed", e);
|
|
3053
|
+
}
|
|
3054
|
+
console.warn("[rtc] falling back to tokyo TURN \u2014 web\u2194Android online ICE may fail");
|
|
3055
|
+
DK_LIVE_ICE_SERVERS.splice(0, DK_LIVE_ICE_SERVERS.length, ...DK_FALLBACK_ICE_SERVERS.map((s) => ({ ...s })));
|
|
3056
|
+
await dkWarmCallIce(DK_LIVE_ICE_SERVERS);
|
|
3057
|
+
return DK_LIVE_ICE_SERVERS;
|
|
3058
|
+
})();
|
|
3059
|
+
return _dkIcePromise;
|
|
3043
3060
|
}
|
|
3044
|
-
function
|
|
3045
|
-
const
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
alignItems: "center",
|
|
3057
|
-
gap: 4,
|
|
3058
|
-
height: 18,
|
|
3059
|
-
padding: "0 6px",
|
|
3060
|
-
borderRadius: 4,
|
|
3061
|
-
background: t.bg,
|
|
3062
|
-
color: t.fg,
|
|
3063
|
-
border: `1px solid ${t.bd}`,
|
|
3064
|
-
fontFamily: "var(--mono)",
|
|
3065
|
-
fontSize: 11,
|
|
3066
|
-
fontWeight: 600,
|
|
3067
|
-
letterSpacing: -0.1,
|
|
3068
|
-
lineHeight: 1,
|
|
3069
|
-
whiteSpace: "nowrap",
|
|
3070
|
-
...style
|
|
3071
|
-
} }, children);
|
|
3061
|
+
function dkAwaitCallIceServers(ms) {
|
|
3062
|
+
const budget = typeof ms === "number" ? ms : 1e4;
|
|
3063
|
+
return Promise.race([
|
|
3064
|
+
dkLoadCallIceServers(),
|
|
3065
|
+
new Promise((resolve) => setTimeout(() => {
|
|
3066
|
+
if (!DK_LIVE_ICE_SERVERS.length) {
|
|
3067
|
+
DK_LIVE_ICE_SERVERS.splice(0, DK_LIVE_ICE_SERVERS.length, ...DK_FALLBACK_ICE_SERVERS.map((s) => ({ ...s })));
|
|
3068
|
+
console.warn("[rtc] ICE wait timed out \u2014 using fallback");
|
|
3069
|
+
}
|
|
3070
|
+
resolve(DK_LIVE_ICE_SERVERS);
|
|
3071
|
+
}, budget))
|
|
3072
|
+
]).then(() => DK_LIVE_ICE_SERVERS);
|
|
3072
3073
|
}
|
|
3073
|
-
|
|
3074
|
-
|
|
3074
|
+
dkLoadCallIceServers();
|
|
3075
|
+
function dkRtcParseEnvelope(data) {
|
|
3076
|
+
const text = String(data || "").replace(/\0+$/u, "").trim();
|
|
3077
|
+
if (!text)
|
|
3075
3078
|
return null;
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
color: "#fff",
|
|
3084
|
-
fontFamily: "var(--mono)",
|
|
3085
|
-
fontSize: 11,
|
|
3086
|
-
fontWeight: 700,
|
|
3087
|
-
lineHeight: "18px",
|
|
3088
|
-
textAlign: "center"
|
|
3089
|
-
} }, n);
|
|
3079
|
+
try {
|
|
3080
|
+
const obj = JSON.parse(text);
|
|
3081
|
+
if (obj && obj.dkRtc === 1 && typeof obj.kind === "string")
|
|
3082
|
+
return obj;
|
|
3083
|
+
} catch (e) {
|
|
3084
|
+
}
|
|
3085
|
+
return null;
|
|
3090
3086
|
}
|
|
3091
|
-
function
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3087
|
+
function dkRtcSignalBus() {
|
|
3088
|
+
if (window.__dkRtcSignalBus)
|
|
3089
|
+
return window.__dkRtcSignalBus;
|
|
3090
|
+
const PW = window.PeerWebRTC;
|
|
3091
|
+
const handlers = /* @__PURE__ */ new Map();
|
|
3092
|
+
const pendingCalls = [];
|
|
3093
|
+
const PENDING_CALL_CAP = 16;
|
|
3094
|
+
let started = false;
|
|
3095
|
+
let stopped = false;
|
|
3096
|
+
function emit(kind, userid, payload) {
|
|
3097
|
+
const set = handlers.get(kind);
|
|
3098
|
+
if (!set || !set.size) {
|
|
3099
|
+
if (kind === "call") {
|
|
3100
|
+
pendingCalls.push({ userid, payload });
|
|
3101
|
+
if (pendingCalls.length > PENDING_CALL_CAP)
|
|
3102
|
+
pendingCalls.shift();
|
|
3103
|
+
}
|
|
3104
|
+
return;
|
|
3105
|
+
}
|
|
3106
|
+
for (const h of Array.from(set)) {
|
|
3107
|
+
try {
|
|
3108
|
+
h(userid, payload);
|
|
3109
|
+
} catch (e) {
|
|
3110
|
+
console.warn("[rtc] signal handler failed", e);
|
|
3111
|
+
}
|
|
3112
|
+
}
|
|
3113
|
+
}
|
|
3114
|
+
async function pollLoop() {
|
|
3115
|
+
let cursor = null;
|
|
3116
|
+
while (!stopped) {
|
|
3117
|
+
let signals = [];
|
|
3118
|
+
try {
|
|
3119
|
+
const u = cursor == null ? "/api/call-poll" : "/api/call-poll?since=" + cursor;
|
|
3120
|
+
const r = await fetch(u, { headers: { "cache-control": "no-cache" } });
|
|
3121
|
+
const d = await r.json();
|
|
3122
|
+
signals = d && d.signals || [];
|
|
3123
|
+
if (d && typeof d.cursor === "number")
|
|
3124
|
+
cursor = d.cursor;
|
|
3125
|
+
} catch (e) {
|
|
3126
|
+
await new Promise((res) => setTimeout(res, 1e3));
|
|
3127
|
+
continue;
|
|
3128
|
+
}
|
|
3129
|
+
for (const s of signals) {
|
|
3130
|
+
const env = dkRtcParseEnvelope(s.data);
|
|
3131
|
+
if (env) {
|
|
3132
|
+
emit(env.kind, s.userid, env);
|
|
3133
|
+
continue;
|
|
3134
|
+
}
|
|
3135
|
+
if (PW) {
|
|
3136
|
+
try {
|
|
3137
|
+
emit("call", s.userid, PW.decodeSignal(s.data));
|
|
3138
|
+
} catch (e) {
|
|
3139
|
+
}
|
|
3140
|
+
}
|
|
3141
|
+
}
|
|
3142
|
+
}
|
|
3143
|
+
}
|
|
3144
|
+
const bus = {
|
|
3145
|
+
start() {
|
|
3146
|
+
if (started)
|
|
3147
|
+
return;
|
|
3148
|
+
started = true;
|
|
3149
|
+
stopped = false;
|
|
3150
|
+
pollLoop();
|
|
3151
|
+
},
|
|
3152
|
+
on(kind, cb) {
|
|
3153
|
+
if (!handlers.has(kind))
|
|
3154
|
+
handlers.set(kind, /* @__PURE__ */ new Set());
|
|
3155
|
+
handlers.get(kind).add(cb);
|
|
3156
|
+
this.start();
|
|
3157
|
+
if (kind === "call" && pendingCalls.length) {
|
|
3158
|
+
const queued = pendingCalls.splice(0);
|
|
3159
|
+
console.log("[rtc] flushing " + queued.length + " buffered call signal(s)");
|
|
3160
|
+
for (const q of queued) {
|
|
3161
|
+
try {
|
|
3162
|
+
cb(q.userid, q.payload);
|
|
3163
|
+
} catch (e) {
|
|
3164
|
+
console.warn("[rtc] buffered call handler failed", e);
|
|
3165
|
+
}
|
|
3166
|
+
}
|
|
3167
|
+
}
|
|
3168
|
+
return () => {
|
|
3169
|
+
var _a;
|
|
3170
|
+
return (_a = handlers.get(kind)) == null ? void 0 : _a.delete(cb);
|
|
3171
|
+
};
|
|
3172
|
+
},
|
|
3173
|
+
async send(userid, data) {
|
|
3174
|
+
const body = JSON.stringify({ userid, data: typeof data === "string" ? data : JSON.stringify(data) });
|
|
3175
|
+
const r = await fetch("/api/call-signal", {
|
|
3176
|
+
method: "POST",
|
|
3177
|
+
headers: { "content-type": "application/json" },
|
|
3178
|
+
body
|
|
3179
|
+
});
|
|
3180
|
+
const d = await r.json().catch(() => ({ ok: r.ok }));
|
|
3181
|
+
if (!d.ok)
|
|
3182
|
+
throw new Error(d.error || "call-signal send failed");
|
|
3183
|
+
},
|
|
3184
|
+
stop() {
|
|
3185
|
+
stopped = true;
|
|
3186
|
+
}
|
|
3098
3187
|
};
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
return /* @__PURE__ */ React.createElement("button", { onClick, title, style: {
|
|
3102
|
-
height: h,
|
|
3103
|
-
padding: icon && !children ? 0 : "0 11px",
|
|
3104
|
-
minWidth: icon && !children ? h : "auto",
|
|
3105
|
-
borderRadius: 6,
|
|
3106
|
-
cursor: "pointer",
|
|
3107
|
-
fontFamily: "var(--mono)",
|
|
3108
|
-
fontWeight: 600,
|
|
3109
|
-
fontSize: size === "sm" ? 12 : 12.5,
|
|
3110
|
-
letterSpacing: -0.1,
|
|
3111
|
-
background: t.bg,
|
|
3112
|
-
color: t.fg,
|
|
3113
|
-
border: `1px solid ${t.bd}`,
|
|
3114
|
-
display: "inline-flex",
|
|
3115
|
-
alignItems: "center",
|
|
3116
|
-
justifyContent: "center",
|
|
3117
|
-
gap: 6,
|
|
3118
|
-
whiteSpace: "nowrap",
|
|
3119
|
-
...style
|
|
3120
|
-
} }, icon && /* @__PURE__ */ React.createElement(Icon, { name: icon, size: 15, stroke: 2 }), children);
|
|
3188
|
+
window.__dkRtcSignalBus = bus;
|
|
3189
|
+
return bus;
|
|
3121
3190
|
}
|
|
3122
|
-
function
|
|
3123
|
-
|
|
3191
|
+
function makeDaemonSignaling() {
|
|
3192
|
+
const PW = window.PeerWebRTC;
|
|
3193
|
+
const bus = dkRtcSignalBus();
|
|
3194
|
+
let off = null;
|
|
3195
|
+
return {
|
|
3196
|
+
async send(peerId, signal) {
|
|
3197
|
+
await bus.send(peerId, PW.encodeSignal(signal));
|
|
3198
|
+
},
|
|
3199
|
+
onSignal(cb) {
|
|
3200
|
+
if (off)
|
|
3201
|
+
off();
|
|
3202
|
+
off = bus.on("call", cb);
|
|
3203
|
+
},
|
|
3204
|
+
stop() {
|
|
3205
|
+
if (off) {
|
|
3206
|
+
off();
|
|
3207
|
+
off = null;
|
|
3208
|
+
}
|
|
3209
|
+
}
|
|
3210
|
+
};
|
|
3124
3211
|
}
|
|
3125
|
-
Object.assign(window, {
|
|
3212
|
+
Object.assign(window, { dkRtcSignalBus, makeDaemonSignaling });
|
|
3126
3213
|
function useCallController(selfId, onCallLog) {
|
|
3127
3214
|
const [incoming, setIncoming] = React.useState(null);
|
|
3128
3215
|
const [active, setActive] = React.useState(null);
|
|
@@ -4291,6 +4378,7 @@ ${peer.address}`
|
|
|
4291
4378
|
en: {
|
|
4292
4379
|
chat: "Chat",
|
|
4293
4380
|
network: "Network",
|
|
4381
|
+
apps: "Apps",
|
|
4294
4382
|
profile: "Profile",
|
|
4295
4383
|
recommended: "Discover",
|
|
4296
4384
|
registered: "Names",
|
|
@@ -4422,6 +4510,7 @@ ${peer.address}`
|
|
|
4422
4510
|
updRestarting: "Restarting\u2026 this page reloads when it\u2019s back. (If beagle was started by hand in a terminal, run it again.)",
|
|
4423
4511
|
updNpx: "Running via npx \u2014 restarting picks up the latest version automatically.",
|
|
4424
4512
|
updDev: "Running from a source checkout \u2014 update with:",
|
|
4513
|
+
updUnknown: "Update now runs the global install. If that is not how this was installed, run:",
|
|
4425
4514
|
updLanNote: "agentnet (lan): one click reinstalls it and asks the running daemon to restart itself. Manual equivalent:",
|
|
4426
4515
|
updCheck: "check for updates",
|
|
4427
4516
|
updCheckLabel: "updates",
|
|
@@ -4468,6 +4557,7 @@ ${peer.address}`
|
|
|
4468
4557
|
zh: {
|
|
4469
4558
|
chat: "\u804A\u5929",
|
|
4470
4559
|
network: "\u7F51\u7EDC",
|
|
4560
|
+
apps: "\u5E94\u7528",
|
|
4471
4561
|
profile: "\u6211\u7684",
|
|
4472
4562
|
recommended: "\u63A8\u8350",
|
|
4473
4563
|
registered: "\u540D\u5F55",
|
|
@@ -4599,6 +4689,7 @@ ${peer.address}`
|
|
|
4599
4689
|
updRestarting: "\u6B63\u5728\u91CD\u542F\u2026\u5B8C\u6210\u540E\u672C\u9875\u4F1A\u81EA\u52A8\u5237\u65B0\u3002(\u5982\u679C beagle \u662F\u5728\u7EC8\u7AEF\u91CC\u624B\u52A8\u542F\u52A8\u7684,\u8BF7\u91CD\u65B0\u8FD0\u884C\u4E00\u6B21\u3002)",
|
|
4600
4690
|
updNpx: "\u4F60\u662F\u7528 npx \u8FD0\u884C\u7684\u2014\u2014\u91CD\u542F\u5373\u81EA\u52A8\u83B7\u53D6\u6700\u65B0\u7248\u3002",
|
|
4601
4691
|
updDev: "\u5F53\u524D\u4ECE\u6E90\u7801\u76EE\u5F55\u8FD0\u884C,\u8BF7\u624B\u52A8\u66F4\u65B0:",
|
|
4692
|
+
updUnknown: "\u300C\u7ACB\u5373\u66F4\u65B0\u300D\u4F1A\u6267\u884C\u5168\u5C40\u5B89\u88C5\u3002\u5982\u679C\u4E0D\u662F\u8FD9\u6837\u88C5\u7684,\u8BF7\u8FD0\u884C:",
|
|
4602
4693
|
updLanNote: "agentnet(lan):\u4E00\u952E\u91CD\u88C5\u5E76\u8BA9\u8FD0\u884C\u4E2D\u7684 daemon \u81EA\u6211\u91CD\u542F\u3002\u7B49\u4EF7\u624B\u52A8\u547D\u4EE4:",
|
|
4603
4694
|
updCheck: "\u68C0\u67E5\u66F4\u65B0",
|
|
4604
4695
|
updCheckLabel: "\u66F4\u65B0",
|
|
@@ -4721,10 +4812,10 @@ ${peer.address}`
|
|
|
4721
4812
|
background: tone ? "var(--accent)" : "transparent",
|
|
4722
4813
|
color: tone ? "#fff" : "var(--text)"
|
|
4723
4814
|
} }, label);
|
|
4724
|
-
return /* @__PURE__ */ React.createElement("div", { style: { position: "fixed", inset: 0, zIndex: 95, background: "color-mix(in oklab, #000, transparent 38%)", display: "flex", alignItems: "center", justifyContent: "center", padding: 24 } }, /* @__PURE__ */ React.createElement("div", { style: { width: 430, maxWidth: "94vw", background: "var(--panel)", border: "1px solid var(--line)", borderRadius: 16, padding: "20px 22px", display: "flex", flexDirection: "column", gap: 14 } }, /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 13.5, fontWeight: 700, color: "var(--text)" } }, T.updTitle || "Update available"), /* @__PURE__ */ React.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 6 } }, behind.map((u) => /* @__PURE__ */ React.createElement("div", { key: u.pkg, style: { display: "flex", alignItems: "center", gap: 10, fontFamily: "var(--mono)", fontSize: 12.5 } }, /* @__PURE__ */ React.createElement("span", { style: { width: 70, color: "var(--faint)" } }, short(u.pkg)), /* @__PURE__ */ React.createElement("span", { style: { color: "var(--dim)" } }, u.current), /* @__PURE__ */ React.createElement("span", { style: { color: "var(--faint)" } }, "\u2192"), /* @__PURE__ */ React.createElement("span", { style: { color: "var(--accent)", fontWeight: 700 } }, u.latest)))), phase === "idle" && appBehind && info.mode === "dev" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12, color: "var(--dim)", lineHeight: 1.5 } }, T.updDev || "Running from a source checkout \u2014 update with:", /* @__PURE__ */ React.createElement("br", null), /* @__PURE__ */ React.createElement("code", { style: { fontFamily: "var(--mono)", fontSize: 11.5, color: "var(--text)" } }, "git pull && npm run build")), phase === "idle" && appBehind && info.mode === "npx" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12, color: "var(--dim)", lineHeight: 1.5 } }, T.updNpx || "Running via npx \u2014 restarting picks up the latest version automatically."), lanBehind && phase === "idle" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12, color: "var(--dim)", lineHeight: 1.5 } }, T.updLanNote || "agentnet (lan): one click reinstalls it and asks the running daemon to restart itself. Manual equivalent:", /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 8, marginTop: 6 } }, /* @__PURE__ */ React.createElement("code", { style: { flex: 1, minWidth: 0, fontFamily: "var(--mono)", fontSize: 11.5, color: "var(--text)", background: "var(--panel-2)", border: "1px solid var(--line)", borderRadius: 8, padding: "8px 10px", userSelect: "all", wordBreak: "break-all" } }, "npm i -g @decentnetwork/lan@latest && agentnet restart"), /* @__PURE__ */ React.createElement(Btn, { size: "sm", icon: "copy", title: T.copy || "Copy", onClick: () => dkCopy("npm i -g @decentnetwork/lan@latest && agentnet restart") }))), phase === "lan-done" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12.5, color: "var(--online)" } }, T.updLanDone || "lan updated \u2014 daemon restarted with the new version \u2713"), phase === "lan-norestart" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12.5, color: "var(--warn, #f59e0b)" } }, T.updLanNoRestart || "lan updated, but the daemon was not running (or refused) \u2014 the new version applies on its next start."), phase === "running" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12.5, color: "var(--dim)" } }, T.updBusy || "Updating\u2026 (about a minute)"), phase === "done" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12.5, color: "var(--online)" } }, T.updDone || "Updated \u2014 restart to apply."), phase === "restarting" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12.5, color: "var(--dim)" } }, T.updRestarting || "Restarting\u2026 this page reloads when it\u2019s back. (If beagle was started by hand in a terminal, run it again.)"), phase === "error" && (() => {
|
|
4815
|
+
return /* @__PURE__ */ React.createElement("div", { style: { position: "fixed", inset: 0, zIndex: 95, background: "color-mix(in oklab, #000, transparent 38%)", display: "flex", alignItems: "center", justifyContent: "center", padding: 24 } }, /* @__PURE__ */ React.createElement("div", { style: { width: 430, maxWidth: "94vw", background: "var(--panel)", border: "1px solid var(--line)", borderRadius: 16, padding: "20px 22px", display: "flex", flexDirection: "column", gap: 14 } }, /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 13.5, fontWeight: 700, color: "var(--text)" } }, T.updTitle || "Update available"), /* @__PURE__ */ React.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 6 } }, behind.map((u) => /* @__PURE__ */ React.createElement("div", { key: u.pkg, style: { display: "flex", alignItems: "center", gap: 10, fontFamily: "var(--mono)", fontSize: 12.5 } }, /* @__PURE__ */ React.createElement("span", { style: { width: 70, color: "var(--faint)" } }, short(u.pkg)), /* @__PURE__ */ React.createElement("span", { style: { color: "var(--dim)" } }, u.current), /* @__PURE__ */ React.createElement("span", { style: { color: "var(--faint)" } }, "\u2192"), /* @__PURE__ */ React.createElement("span", { style: { color: "var(--accent)", fontWeight: 700 } }, u.latest)))), phase === "idle" && appBehind && info.mode === "dev" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12, color: "var(--dim)", lineHeight: 1.5 } }, T.updDev || "Running from a source checkout \u2014 update with:", /* @__PURE__ */ React.createElement("br", null), /* @__PURE__ */ React.createElement("code", { style: { fontFamily: "var(--mono)", fontSize: 11.5, color: "var(--text)" } }, "git pull && npm run build")), phase === "idle" && appBehind && info.mode === "unknown" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12, color: "var(--dim)", lineHeight: 1.5 } }, T.updUnknown || "Update now runs the global install. If that is not how this was installed, run:", /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 8, marginTop: 6 } }, /* @__PURE__ */ React.createElement("code", { style: { flex: 1, minWidth: 0, fontFamily: "var(--mono)", fontSize: 11.5, color: "var(--text)", background: "var(--panel-2)", border: "1px solid var(--line)", borderRadius: 8, padding: "8px 10px", userSelect: "all", wordBreak: "break-all" } }, "npm i -g @decentnetwork/beagle@latest"), /* @__PURE__ */ React.createElement(Btn, { size: "sm", icon: "copy", title: T.copy || "Copy", onClick: () => dkCopy("npm i -g @decentnetwork/beagle@latest") }))), phase === "idle" && appBehind && info.mode === "npx" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12, color: "var(--dim)", lineHeight: 1.5 } }, T.updNpx || "Running via npx \u2014 restarting picks up the latest version automatically."), lanBehind && phase === "idle" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12, color: "var(--dim)", lineHeight: 1.5 } }, T.updLanNote || "agentnet (lan): one click reinstalls it and asks the running daemon to restart itself. Manual equivalent:", /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 8, marginTop: 6 } }, /* @__PURE__ */ React.createElement("code", { style: { flex: 1, minWidth: 0, fontFamily: "var(--mono)", fontSize: 11.5, color: "var(--text)", background: "var(--panel-2)", border: "1px solid var(--line)", borderRadius: 8, padding: "8px 10px", userSelect: "all", wordBreak: "break-all" } }, "npm i -g @decentnetwork/lan@latest && agentnet restart"), /* @__PURE__ */ React.createElement(Btn, { size: "sm", icon: "copy", title: T.copy || "Copy", onClick: () => dkCopy("npm i -g @decentnetwork/lan@latest && agentnet restart") }))), phase === "lan-done" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12.5, color: "var(--online)" } }, T.updLanDone || "lan updated \u2014 daemon restarted with the new version \u2713"), phase === "lan-norestart" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12.5, color: "var(--warn, #f59e0b)" } }, T.updLanNoRestart || "lan updated, but the daemon was not running (or refused) \u2014 the new version applies on its next start."), phase === "running" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12.5, color: "var(--dim)" } }, T.updBusy || "Updating\u2026 (about a minute)"), phase === "done" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12.5, color: "var(--online)" } }, T.updDone || "Updated \u2014 restart to apply."), phase === "restarting" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12.5, color: "var(--dim)" } }, T.updRestarting || "Restarting\u2026 this page reloads when it\u2019s back. (If beagle was started by hand in a terminal, run it again.)"), phase === "error" && (() => {
|
|
4725
4816
|
const m = /`([^`]+)`/.exec(err || "");
|
|
4726
4817
|
return /* @__PURE__ */ React.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 8 } }, /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12, color: "var(--danger)", wordBreak: "break-word" } }, m ? err.replace("`" + m[1] + "`", "") : err), m && /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 8 } }, /* @__PURE__ */ React.createElement("code", { style: { flex: 1, minWidth: 0, fontFamily: "var(--mono)", fontSize: 11.5, color: "var(--text)", background: "var(--panel-2)", border: "1px solid var(--line)", borderRadius: 8, padding: "8px 10px", userSelect: "all", wordBreak: "break-all" } }, m[1]), /* @__PURE__ */ React.createElement(Btn, { size: "sm", icon: "copy", title: T.copy || "Copy", onClick: () => dkCopy(m[1]) })), m && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 11.5, color: "var(--dim)" } }, T.updManualHint || "Run it in a terminal, then click Restart to apply."));
|
|
4727
|
-
})(), /* @__PURE__ */ React.createElement("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8 } }, (phase === "idle" || phase === "error" || phase === "lan-done" || phase === "lan-norestart") && btn(phase === "idle" ? T.updLater || "Later" : T.receivedClose || "Close", onClose), phase === "idle" && lanBehind && btn(T.updLanNow || "Update lan", doLanUpdate, !appBehind), phase === "idle" && appBehind && info.mode === "global" && btn(T.updNow || "Update now", doUpdate, true), phase === "idle" && appBehind && info.mode === "npx" && btn(T.updRestart || "Restart", doRestart, true), phase === "error" && btn(T.updRestart || "Restart", doRestart, true), phase === "done" && btn(T.updRestart || "Restart", doRestart, true))));
|
|
4818
|
+
})(), /* @__PURE__ */ React.createElement("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8 } }, (phase === "idle" || phase === "error" || phase === "lan-done" || phase === "lan-norestart") && btn(phase === "idle" ? T.updLater || "Later" : T.receivedClose || "Close", onClose), phase === "idle" && lanBehind && btn(T.updLanNow || "Update lan", doLanUpdate, !appBehind), phase === "idle" && appBehind && (info.mode === "global" || info.mode === "unknown") && btn(T.updNow || "Update now", doUpdate, true), phase === "idle" && appBehind && info.mode === "npx" && btn(T.updRestart || "Restart", doRestart, true), phase === "error" && btn(T.updRestart || "Restart", doRestart, true), phase === "done" && btn(T.updRestart || "Restart", doRestart, true))));
|
|
4728
4819
|
}
|
|
4729
4820
|
function DkApp() {
|
|
4730
4821
|
const [t, setTweak] = useTweaks({ ...DK_DEFAULTS, lang: dkDetectLang() });
|
|
@@ -4974,11 +5065,13 @@ ${peer.address}`
|
|
|
4974
5065
|
{ id: "recommended", icon: "sparkles", label: T.recommended },
|
|
4975
5066
|
{ id: "registered", icon: "at", label: T.registered },
|
|
4976
5067
|
{ id: "network", icon: "network", label: T.network },
|
|
5068
|
+
{ id: "apps", icon: "grid", label: T.apps },
|
|
4977
5069
|
{ id: "profile", icon: "userRound", label: T.profile }
|
|
4978
5070
|
];
|
|
4979
|
-
return /* @__PURE__ */ React.createElement("div", { style: { ...vars, "--row-pad": rowPad, position: "fixed", inset: 0, display: "flex", background: "var(--bg)", color: "var(--text)", fontFamily: "var(--ui)" } }, /* @__PURE__ */ React.createElement("div", { style: { width: 68, flexShrink: 0, borderRight: "1px solid var(--line)", background: "var(--rail)", display: "flex", flexDirection: "column", alignItems: "center", padding: "14px 0", gap: 8 } }, /* @__PURE__ */ React.createElement("div", { style: { width: 38, height: 38, borderRadius: 10, background: "var(--accent)", display: "flex", alignItems: "center", justifyContent: "center", marginBottom: 8 } }, /* @__PURE__ */ React.createElement(Icon, { name: "terminal", size: 20, color: "#fff", stroke: 2.2 })), nav.map((n) => /* @__PURE__ */ React.createElement(RailBtn, { key: n.id, icon: n.icon, label: n.label, active: tab === n.id, soon: n.soon, onClick: () => setTab(n.id) })), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }), /* @__PURE__ */ React.createElement("div", { style: { position: "relative" } }, /* @__PURE__ */ React.createElement(DkAvatar, { peer: { ...me, id: me.userId, agent: false }, size: 36, radius: 9 }))), /* @__PURE__ */ React.createElement("div", { style: { flex: 1, minWidth: 0, minHeight: 0, display: "flex", flexDirection: "column" } }, /* @__PURE__ */ React.createElement(DkBrowserNotice, { lang: t.lang }), /* @__PURE__ */ React.createElement("div", { style: { height: 46, flexShrink: 0, borderBottom: "1px solid var(--line)", background: "var(--panel)", display: "flex", alignItems: "center", gap: 12, padding: "0 16px" } }, /* @__PURE__ */ React.createElement("svg", { width: 20, height: 20, viewBox: "0 0 24 24", fill: "none", stroke: "var(--accent)", strokeWidth: 2.2, strokeLinecap: "round", strokeLinejoin: "round", style: { display: "block", flexShrink: 0 } }, /* @__PURE__ */ React.createElement("path", { d: "m4.5 17 6-6-6-6" }), /* @__PURE__ */ React.createElement("path", { d: "M12 18.5h7.5" })), /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 14, fontWeight: 700, letterSpacing: -0.3, color: "var(--text)" } }, "beagle"), /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 12, color: "var(--faint)" } }, "\xB7 ", nav.find((n) => n.id === tab).label.toLowerCase()), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }), /* @__PURE__ */ React.createElement(Tag, { tone: "accent" }, me.channel, " \xB7 lan ", me.lanVer), /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 7, padding: "0 4px" } }, /* @__PURE__ */ React.createElement(StatusDot, { online: me.online }), /* @__PURE__ */ React.createElement(Mono, { size: 12.5, copy: me.ip }, me.ip)), /* @__PURE__ */ React.createElement("span", { style: { width: 1, height: 22, background: "var(--line)" } }), /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 8 } }, /* @__PURE__ */ React.createElement(DkAvatar, { peer: { ...me, id: me.userId, agent: false }, size: 26, radius: 7 }), /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 12.5, fontWeight: 600, color: "var(--text)" } }, me.name))), tab === "chat" && /* @__PURE__ */ React.createElement(ChatTab, { T, lang: t.lang, peers, requests, activeId, thread: data.threads[activeId], onSelect, onAct, onAdd, onSend, onSendFile, onSendRtcFile, onAlias, onRemove, onOpenNet, onCall, onReloadThread: () => activeId && data.loadThread(activeId), prefillAddr: pendingAddr, onPrefillConsumed: () => setPendingAddr("") }), 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 === "profile" && /* @__PURE__ */ React.createElement(ProfileTab, { T, me, onEdit, t, setTweak })), data.locked && /* @__PURE__ */ React.createElement(
|
|
5071
|
+
return /* @__PURE__ */ React.createElement("div", { style: { ...vars, "--row-pad": rowPad, position: "fixed", inset: 0, display: "flex", background: "var(--bg)", color: "var(--text)", fontFamily: "var(--ui)" } }, /* @__PURE__ */ React.createElement("div", { style: { width: 68, flexShrink: 0, borderRight: "1px solid var(--line)", background: "var(--rail)", display: "flex", flexDirection: "column", alignItems: "center", padding: "14px 0", gap: 8 } }, /* @__PURE__ */ React.createElement("div", { style: { width: 38, height: 38, borderRadius: 10, background: "var(--accent)", display: "flex", alignItems: "center", justifyContent: "center", marginBottom: 8 } }, /* @__PURE__ */ React.createElement(Icon, { name: "terminal", size: 20, color: "#fff", stroke: 2.2 })), nav.map((n) => /* @__PURE__ */ React.createElement(RailBtn, { key: n.id, icon: n.icon, label: n.label, active: tab === n.id, soon: n.soon, onClick: () => setTab(n.id) })), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }), /* @__PURE__ */ React.createElement("div", { style: { position: "relative" } }, /* @__PURE__ */ React.createElement(DkAvatar, { peer: { ...me, id: me.userId, agent: false }, size: 36, radius: 9 }))), /* @__PURE__ */ React.createElement("div", { style: { flex: 1, minWidth: 0, minHeight: 0, display: "flex", flexDirection: "column" } }, /* @__PURE__ */ React.createElement(DkBrowserNotice, { lang: t.lang }), /* @__PURE__ */ React.createElement("div", { style: { height: 46, flexShrink: 0, borderBottom: "1px solid var(--line)", background: "var(--panel)", display: "flex", alignItems: "center", gap: 12, padding: "0 16px" } }, /* @__PURE__ */ React.createElement("svg", { width: 20, height: 20, viewBox: "0 0 24 24", fill: "none", stroke: "var(--accent)", strokeWidth: 2.2, strokeLinecap: "round", strokeLinejoin: "round", style: { display: "block", flexShrink: 0 } }, /* @__PURE__ */ React.createElement("path", { d: "m4.5 17 6-6-6-6" }), /* @__PURE__ */ React.createElement("path", { d: "M12 18.5h7.5" })), /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 14, fontWeight: 700, letterSpacing: -0.3, color: "var(--text)" } }, "beagle"), /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 12, color: "var(--faint)" } }, "\xB7 ", nav.find((n) => n.id === tab).label.toLowerCase()), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }), /* @__PURE__ */ React.createElement(Tag, { tone: "accent" }, me.channel, " \xB7 lan ", me.lanVer), /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 7, padding: "0 4px" } }, /* @__PURE__ */ React.createElement(StatusDot, { online: me.online }), /* @__PURE__ */ React.createElement(Mono, { size: 12.5, copy: me.ip }, me.ip)), /* @__PURE__ */ React.createElement("span", { style: { width: 1, height: 22, background: "var(--line)" } }), /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 8 } }, /* @__PURE__ */ React.createElement(DkAvatar, { peer: { ...me, id: me.userId, agent: false }, size: 26, radius: 7 }), /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 12.5, fontWeight: 600, color: "var(--text)" } }, me.name))), tab === "chat" && /* @__PURE__ */ React.createElement(ChatTab, { T, lang: t.lang, peers, requests, activeId, thread: data.threads[activeId], onSelect, onAct, onAdd, onSend, onSendFile, onSendRtcFile, onAlias, onRemove, onOpenNet, onCall, onReloadThread: () => activeId && data.loadThread(activeId), prefillAddr: pendingAddr, onPrefillConsumed: () => setPendingAddr("") }), 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 }), tab === "profile" && /* @__PURE__ */ React.createElement(ProfileTab, { T, me, onEdit, t, setTweak })), data.locked && /* @__PURE__ */ React.createElement(
|
|
4980
5072
|
DkLockedOut,
|
|
4981
5073
|
{
|
|
5074
|
+
compact: true,
|
|
4982
5075
|
lang: t.lang,
|
|
4983
5076
|
onTakeover: () => window.BeagleWeb.takeover().then((st) => {
|
|
4984
5077
|
data.refresh();
|