@decentnetwork/beagle-ui 0.2.27 → 0.2.29
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 +268 -19
- 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.29";
|
|
2
2
|
// src/icons.jsx
|
|
3
3
|
var ICON_PATHS = {
|
|
4
4
|
// ---- tab bar (the four must feel like one set) ----
|
|
@@ -114,6 +114,8 @@ Object.assign(ICON_PATHS, {
|
|
|
114
114
|
plug: '<path d="M9 2v6M15 2v6"/><path d="M7 8h10v3a5 5 0 0 1-10 0V8Z"/><path d="M12 16v6"/>',
|
|
115
115
|
// A form with a filled-in field: the glyph for "Fill with Beagle" and any
|
|
116
116
|
// other host app that puts your identity into someone else's page.
|
|
117
|
+
// A pane pinned to the right edge — "keep this beside the page".
|
|
118
|
+
dock: '<rect x="3" y="4" width="18" height="16" rx="2"/><path d="M14 4v16"/><path d="M17 9.5h1.5M17 13h1.5"/>',
|
|
117
119
|
form: '<rect x="4" y="3" width="16" height="18" rx="2"/><path d="M8 8h8M8 12h5"/><path d="M8 16h3"/><path d="m14.5 17.5 1.6 1.6 3.4-3.6"/>'
|
|
118
120
|
});
|
|
119
121
|
|
|
@@ -128,12 +130,16 @@ var hostTabs = null;
|
|
|
128
130
|
var hostHideApps = null;
|
|
129
131
|
var hostApps = null;
|
|
130
132
|
var hostProfileSections = null;
|
|
133
|
+
var hostHeaderActions = null;
|
|
134
|
+
var hostIsProtocolMessage = null;
|
|
131
135
|
function setUiHost(host) {
|
|
132
136
|
H = host || {};
|
|
133
137
|
hostTabs = Array.isArray(H.hostTabs) ? H.hostTabs : null;
|
|
134
138
|
hostHideApps = Array.isArray(H.hideApps) ? H.hideApps : null;
|
|
135
139
|
hostApps = Array.isArray(H.hostApps) ? H.hostApps : null;
|
|
136
140
|
hostProfileSections = Array.isArray(H.hostProfileSections) ? H.hostProfileSections : null;
|
|
141
|
+
hostHeaderActions = Array.isArray(H.hostHeaderActions) ? H.hostHeaderActions : null;
|
|
142
|
+
hostIsProtocolMessage = typeof H.isProtocolMessage === "function" ? H.isProtocolMessage : null;
|
|
137
143
|
hostNeedsWelcome = !!H.hostNeedsWelcome;
|
|
138
144
|
hostPrefersRtcFile = !!H.hostPrefersRtcFile;
|
|
139
145
|
hostHasKeyBackup = !!H.hostHasKeyBackup;
|
|
@@ -160,6 +166,142 @@ function DkBrowserNotice(props) {
|
|
|
160
166
|
return H.DkBrowserNotice ? /* @__PURE__ */ React.createElement(H.DkBrowserNotice, { ...props }) : null;
|
|
161
167
|
}
|
|
162
168
|
|
|
169
|
+
// src/host-messages.js
|
|
170
|
+
function protocolTest(rule) {
|
|
171
|
+
if (typeof rule !== "function")
|
|
172
|
+
return () => false;
|
|
173
|
+
return (msg) => {
|
|
174
|
+
if (!msg)
|
|
175
|
+
return false;
|
|
176
|
+
try {
|
|
177
|
+
const v = rule(msg);
|
|
178
|
+
return typeof v === "string" ? v || true : !!v;
|
|
179
|
+
} catch (e) {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
function stripOwnPrefix(text) {
|
|
185
|
+
return String(text == null ? "" : text).replace(/^you:\s*/i, "");
|
|
186
|
+
}
|
|
187
|
+
function lastMessageOf(peer) {
|
|
188
|
+
const raw = String(peer && peer.lastMsg || "");
|
|
189
|
+
return {
|
|
190
|
+
text: stripOwnPrefix(raw),
|
|
191
|
+
dir: peer && peer.lastDir || (/^you:\s*/i.test(raw) ? "out" : "in"),
|
|
192
|
+
ts: peer && peer.lastTs || 0
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function lastIsProtocol(peer, isProto) {
|
|
196
|
+
const last = lastMessageOf(peer);
|
|
197
|
+
if (!last.text)
|
|
198
|
+
return false;
|
|
199
|
+
return isProto(last);
|
|
200
|
+
}
|
|
201
|
+
function newestHumanMessage(msgs, isProto) {
|
|
202
|
+
const arr = msgs || [];
|
|
203
|
+
for (let i = arr.length - 1; i >= 0; i--) {
|
|
204
|
+
const m = arr[i];
|
|
205
|
+
if (!m)
|
|
206
|
+
continue;
|
|
207
|
+
if (m.file)
|
|
208
|
+
return m;
|
|
209
|
+
if (!m.text)
|
|
210
|
+
continue;
|
|
211
|
+
if (isProto({ text: m.text, dir: m.dir, ts: m.ts }))
|
|
212
|
+
continue;
|
|
213
|
+
return m;
|
|
214
|
+
}
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
function humanUnread(msgs, unread, isProto) {
|
|
218
|
+
const want = Number(unread) || 0;
|
|
219
|
+
if (want <= 0)
|
|
220
|
+
return { count: 0, exact: true };
|
|
221
|
+
const arr = msgs || [];
|
|
222
|
+
const window2 = arr.slice(Math.max(0, arr.length - want));
|
|
223
|
+
let n = 0;
|
|
224
|
+
for (const m of window2) {
|
|
225
|
+
if (!m || m.dir !== "in")
|
|
226
|
+
continue;
|
|
227
|
+
if (m.text && !m.file && isProto({ text: m.text, dir: m.dir, ts: m.ts }))
|
|
228
|
+
continue;
|
|
229
|
+
n++;
|
|
230
|
+
}
|
|
231
|
+
return { count: n, exact: window2.length >= want };
|
|
232
|
+
}
|
|
233
|
+
function rosterRow(peer, isProto, fix) {
|
|
234
|
+
const hidden = lastIsProtocol(peer, isProto);
|
|
235
|
+
if (!hidden) {
|
|
236
|
+
return {
|
|
237
|
+
preview: peer && peer.lastMsg || "",
|
|
238
|
+
lastTime: peer && peer.lastTime || "",
|
|
239
|
+
unread: Number(peer && peer.unread || 0),
|
|
240
|
+
activityTs: Number(peer && peer.lastTs || 0),
|
|
241
|
+
hidden: false
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
return {
|
|
245
|
+
preview: fix && fix.preview || "",
|
|
246
|
+
lastTime: fix && fix.lastTime || "",
|
|
247
|
+
unread: fix && fix.unreadExact ? fix.unread : 0,
|
|
248
|
+
activityTs: fix && fix.ts || 0,
|
|
249
|
+
hidden: true,
|
|
250
|
+
pending: !fix
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
function rosterUnreadTotal(peers, isProto, fixes) {
|
|
254
|
+
return (peers || []).reduce((n, p) => n + rosterRow(p, isProto, fixes && fixes[p.id]).unread, 0);
|
|
255
|
+
}
|
|
256
|
+
function collapseProtocol(thread, isProto, lang) {
|
|
257
|
+
const out = [];
|
|
258
|
+
let run = null;
|
|
259
|
+
const flush = () => {
|
|
260
|
+
if (!run)
|
|
261
|
+
return;
|
|
262
|
+
out.push({
|
|
263
|
+
protocol: true,
|
|
264
|
+
id: `proto-${run.first.id || run.startIndex}`,
|
|
265
|
+
count: run.items.length,
|
|
266
|
+
label: run.label,
|
|
267
|
+
dir: run.first.from === "me" ? "out" : "in",
|
|
268
|
+
text: run.items.map((m) => m.text).join("\n"),
|
|
269
|
+
line: protocolLine(run, lang)
|
|
270
|
+
});
|
|
271
|
+
run = null;
|
|
272
|
+
};
|
|
273
|
+
(thread || []).forEach((m, i) => {
|
|
274
|
+
const hit = m && !m.day ? isProto({ text: m.text, dir: m && m.from === "me" ? "out" : "in", ts: m && m.ts }) : false;
|
|
275
|
+
if (!hit || m && m.file) {
|
|
276
|
+
flush();
|
|
277
|
+
out.push(m);
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
if (!run)
|
|
281
|
+
run = { first: m, startIndex: i, items: [], label: typeof hit === "string" ? hit : "" };
|
|
282
|
+
if (!run.label && typeof hit === "string")
|
|
283
|
+
run.label = hit;
|
|
284
|
+
run.items.push(m);
|
|
285
|
+
});
|
|
286
|
+
flush();
|
|
287
|
+
return out;
|
|
288
|
+
}
|
|
289
|
+
function protocolLine(run, lang) {
|
|
290
|
+
const arrow = run.first.from === "me" ? "\u2192" : "\u2190";
|
|
291
|
+
const n = run.items.length;
|
|
292
|
+
if (run.label) {
|
|
293
|
+
return `\u2699 ${arrow} ${run.label}${n > 1 ? ` \xB7 ${n}` : ""}`;
|
|
294
|
+
}
|
|
295
|
+
if (n > 1) {
|
|
296
|
+
return lang === "zh" ? `\u2699 ${arrow} ${n} \u6761\u534F\u8BAE\u6D88\u606F` : `\u2699 ${arrow} ${n} protocol messages`;
|
|
297
|
+
}
|
|
298
|
+
return `\u2699 ${arrow} ${protocolSummary(run.first.text)}`;
|
|
299
|
+
}
|
|
300
|
+
function protocolSummary(text, max = 72) {
|
|
301
|
+
const s = String(text == null ? "" : text).replace(/\s+/g, " ").trim();
|
|
302
|
+
return s.length > max ? s.slice(0, max - 1) + "\u2026" : s;
|
|
303
|
+
}
|
|
304
|
+
|
|
163
305
|
// src/data-ipc.jsx
|
|
164
306
|
function dkHash(s) {
|
|
165
307
|
let h = 2166136261;
|
|
@@ -392,6 +534,48 @@ function dkThreadMsg(m) {
|
|
|
392
534
|
components: m.components
|
|
393
535
|
};
|
|
394
536
|
}
|
|
537
|
+
var DK_TAIL_MIN = 30;
|
|
538
|
+
var DK_TAIL_MAX = 200;
|
|
539
|
+
function useProtocolTails(peers, isProtocol, enabled) {
|
|
540
|
+
const [fixes, setFixes] = React.useState({});
|
|
541
|
+
const cache = React.useRef(/* @__PURE__ */ new Map());
|
|
542
|
+
const inFlight = React.useRef(/* @__PURE__ */ new Set());
|
|
543
|
+
React.useEffect(() => {
|
|
544
|
+
if (!enabled)
|
|
545
|
+
return;
|
|
546
|
+
for (const p of peers || []) {
|
|
547
|
+
if (!p || !lastIsProtocol(p, isProtocol))
|
|
548
|
+
continue;
|
|
549
|
+
const unread = Number(p.unread) || 0;
|
|
550
|
+
const key = `${p.lastTs || 0}:${unread}`;
|
|
551
|
+
const had = cache.current.get(p.id);
|
|
552
|
+
if (had && had.key === key)
|
|
553
|
+
continue;
|
|
554
|
+
if (inFlight.current.has(p.id))
|
|
555
|
+
continue;
|
|
556
|
+
const limit = Math.min(DK_TAIL_MAX, Math.max(DK_TAIL_MIN, unread + 5));
|
|
557
|
+
inFlight.current.add(p.id);
|
|
558
|
+
dkGet("/api/chat-history?peer=" + encodeURIComponent(p.id) + "&limit=" + limit).then((d) => {
|
|
559
|
+
const msgs = d && d.chats && d.chats[p.id] || [];
|
|
560
|
+
const human = newestHumanMessage(msgs, isProtocol);
|
|
561
|
+
const count = humanUnread(msgs, unread, isProtocol);
|
|
562
|
+
const fix = {
|
|
563
|
+
preview: human ? (human.dir === "out" ? "you: " : "") + (human.file ? human.file.name : human.text || "") : "",
|
|
564
|
+
lastTime: human ? dkClock(human.ts) : "",
|
|
565
|
+
ts: human ? human.ts : 0,
|
|
566
|
+
unread: count.count,
|
|
567
|
+
unreadExact: count.exact
|
|
568
|
+
};
|
|
569
|
+
cache.current.set(p.id, { key, fix });
|
|
570
|
+
setFixes((f) => Object.assign({}, f, { [p.id]: fix }));
|
|
571
|
+
}).catch(() => {
|
|
572
|
+
}).finally(() => {
|
|
573
|
+
inFlight.current.delete(p.id);
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
}, [peers, isProtocol, enabled]);
|
|
577
|
+
return fixes;
|
|
578
|
+
}
|
|
395
579
|
function useDaemonData() {
|
|
396
580
|
const [snap, setSnap] = React.useState({
|
|
397
581
|
me: DK_ME_FALLBACK,
|
|
@@ -1561,8 +1745,9 @@ function RequestsBlock({ T, requests, onAct }) {
|
|
|
1561
1745
|
paddingLeft: 8
|
|
1562
1746
|
} }, r.descr), failed[r.id] && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 11, color: "var(--danger)" } }, failed[r.id]), /* @__PURE__ */ React.createElement("div", { style: { display: "flex", gap: 6 } }, /* @__PURE__ */ React.createElement(Btn, { tone: "ok", icon: "check", size: "sm", onClick: () => act(r, "accept"), style: { flex: 1 } }, T.accept), /* @__PURE__ */ React.createElement(Btn, { tone: "danger", icon: "x", size: "sm", onClick: () => act(r, "reject"), style: { flex: 1 } }, T.reject))))));
|
|
1563
1747
|
}
|
|
1564
|
-
function PeerRow({ peer, T, active, onClick, muted }) {
|
|
1748
|
+
function PeerRow({ peer, T, active, onClick, muted, isProtocol, fix }) {
|
|
1565
1749
|
const name = peer.alias || peer.userId;
|
|
1750
|
+
const row = rosterRow(peer, isProtocol || (() => false), fix);
|
|
1566
1751
|
return /* @__PURE__ */ React.createElement("button", { onClick, style: {
|
|
1567
1752
|
display: "flex",
|
|
1568
1753
|
alignItems: "center",
|
|
@@ -1591,12 +1776,13 @@ function PeerRow({ peer, T, active, onClick, muted }) {
|
|
|
1591
1776
|
textOverflow: "ellipsis",
|
|
1592
1777
|
flex: 1,
|
|
1593
1778
|
minWidth: 0
|
|
1594
|
-
} }, dkRowPreview(
|
|
1779
|
+
} }, dkRowPreview(row.preview)))), /* @__PURE__ */ React.createElement("div", { style: { display: "flex", flexDirection: "column", alignItems: "flex-end", gap: 4, flexShrink: 0 } }, /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 10.5, color: "var(--faint)" } }, row.lastTime), row.unread ? /* @__PURE__ */ React.createElement(Unread, { n: row.unread }) : peer.pending ? /* @__PURE__ */ React.createElement(Icon, { name: "clock", size: 11, stroke: 2.2, color: "var(--warn, #d29922)", title: "friend request pending" }) : /* @__PURE__ */ React.createElement(StatusDot, { online: peer.online })));
|
|
1595
1780
|
}
|
|
1596
|
-
function dkActivityTs(p) {
|
|
1597
|
-
|
|
1781
|
+
function dkActivityTs(p, isProtocol, fix) {
|
|
1782
|
+
const row = rosterRow(p, isProtocol || (() => false), fix);
|
|
1783
|
+
return Math.max(row.activityTs, p.acceptedAt || 0, p.requestedAt || 0);
|
|
1598
1784
|
}
|
|
1599
|
-
function PeerSidebar({ T, peers, requests, activeId, onSelect, onAct, onAdd, prefillAddr, onPrefillConsumed, muted, wide }) {
|
|
1785
|
+
function PeerSidebar({ T, peers, requests, activeId, onSelect, onAct, onAdd, prefillAddr, onPrefillConsumed, muted, wide, isProtocol, protocolFix }) {
|
|
1600
1786
|
const [q, setQ] = React.useState("");
|
|
1601
1787
|
const [addr, setAddr] = React.useState("");
|
|
1602
1788
|
const [addState, setAddState] = React.useState(null);
|
|
@@ -1641,7 +1827,8 @@ function PeerSidebar({ T, peers, requests, activeId, onSelect, onAct, onAdd, pre
|
|
|
1641
1827
|
}).slice().sort((a, b) => {
|
|
1642
1828
|
if (!!a.pinned !== !!b.pinned)
|
|
1643
1829
|
return a.pinned ? -1 : 1;
|
|
1644
|
-
const ta = dkActivityTs(a
|
|
1830
|
+
const ta = dkActivityTs(a, isProtocol, protocolFix && protocolFix[a.id]);
|
|
1831
|
+
const tb = dkActivityTs(b, isProtocol, protocolFix && protocolFix[b.id]);
|
|
1645
1832
|
if (ta !== tb)
|
|
1646
1833
|
return tb - ta;
|
|
1647
1834
|
return String(a.alias || a.userId || "").localeCompare(String(b.alias || b.userId || ""));
|
|
@@ -1680,7 +1867,7 @@ function PeerSidebar({ T, peers, requests, activeId, onSelect, onAct, onAdd, pre
|
|
|
1680
1867
|
fontSize: 11.5,
|
|
1681
1868
|
lineHeight: 1.35,
|
|
1682
1869
|
color: addState.kind === "err" ? "var(--bad, #e5484d)" : addState.kind === "ok" ? "var(--good, #46a758)" : "var(--faint)"
|
|
1683
|
-
} }, addState.msg), /* @__PURE__ */ React.createElement("div", { style: { position: "relative", display: "flex", alignItems: "center" } }, /* @__PURE__ */ React.createElement(Icon, { name: "search", size: 15, color: "var(--faint)", stroke: 2, style: { position: "absolute", left: 9 } }), /* @__PURE__ */ React.createElement("input", { value: q, onChange: (e) => setQ(e.target.value), placeholder: T.search, style: { ...inputStyle, paddingLeft: 30 } }))), /* @__PURE__ */ React.createElement("div", { style: { flex: 1, overflow: "auto", padding: "10px 8px 16px" } }, /* @__PURE__ */ React.createElement(RequestsBlock, { T, requests, onAct }), /* @__PURE__ */ React.createElement(Section, { label: T.peers, count: `${online}/${peers.length}`, style: { margin: "6px 4px 8px" } }), /* @__PURE__ */ React.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 2 } }, filtered.map((p) => /* @__PURE__ */ React.createElement(PeerRow, { key: p.id, peer: p, T, active: p.id === activeId, onClick: () => onSelect(p.id), muted: !!muted && muted.includes(p.id) })), !filtered.length && /* @__PURE__ */ React.createElement("div", { style: { padding: 16, textAlign: "center", fontFamily: "var(--mono)", fontSize: 12, color: "var(--faint)" } }, "no matches"))));
|
|
1870
|
+
} }, addState.msg), /* @__PURE__ */ React.createElement("div", { style: { position: "relative", display: "flex", alignItems: "center" } }, /* @__PURE__ */ React.createElement(Icon, { name: "search", size: 15, color: "var(--faint)", stroke: 2, style: { position: "absolute", left: 9 } }), /* @__PURE__ */ React.createElement("input", { value: q, onChange: (e) => setQ(e.target.value), placeholder: T.search, style: { ...inputStyle, paddingLeft: 30 } }))), /* @__PURE__ */ React.createElement("div", { style: { flex: 1, overflow: "auto", padding: "10px 8px 16px" } }, /* @__PURE__ */ React.createElement(RequestsBlock, { T, requests, onAct }), /* @__PURE__ */ React.createElement(Section, { label: T.peers, count: `${online}/${peers.length}`, style: { margin: "6px 4px 8px" } }), /* @__PURE__ */ React.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 2 } }, filtered.map((p) => /* @__PURE__ */ React.createElement(PeerRow, { key: p.id, peer: p, T, active: p.id === activeId, onClick: () => onSelect(p.id), muted: !!muted && muted.includes(p.id), isProtocol, fix: protocolFix && protocolFix[p.id] })), !filtered.length && /* @__PURE__ */ React.createElement("div", { style: { padding: 16, textAlign: "center", fontFamily: "var(--mono)", fontSize: 12, color: "var(--faint)" } }, "no matches"))));
|
|
1684
1871
|
}
|
|
1685
1872
|
var inputStyle = {
|
|
1686
1873
|
flex: 1,
|
|
@@ -2680,7 +2867,7 @@ function Msg({ m, peer, T, lang, onTheater, onDelete, onCancel, onRetry, onRetry
|
|
|
2680
2867
|
) : mine && m.via === "offline" && m.status !== "queued" && m.status !== "sending" ? /* @__PURE__ */ React.createElement(Icon, { name: "check", size: 12, stroke: 2.2, color: "#f59e0b", title: T.viaOutOffline || "posted to the offline relay \u2014 they get it when they come online" }) : mine && m.status === "sent" && m.confirmed === false ? /* @__PURE__ */ React.createElement(Icon, { name: "check", size: 12, stroke: 2.2, color: "var(--faint)", title: T.sentUnconfirmed || "sent \u2014 not confirmed by the peer" }) : mine && m.status && /* @__PURE__ */ React.createElement(Icon, { name: "checkCheck", size: 12, stroke: 2.2, color: m.status === "read" ? "var(--accent)" : "var(--faint)" })))
|
|
2681
2868
|
);
|
|
2682
2869
|
}
|
|
2683
|
-
function Conversation({ T, peer, lang, peers, onOpenChat, thread: threadProp, onSend, onSendFile, onSendRtcFile, onAlias, onRemove, onOpenNet, onCall, onReloadThread, hasEarlier, onLoadEarlier, onAssistantRemove, onAssistantAdopt, muted, onToggleMute, phone, onBack }) {
|
|
2870
|
+
function Conversation({ T, peer, lang, peers, onOpenChat, thread: threadProp, onSend, onSendFile, onSendRtcFile, onAlias, onRemove, onOpenNet, onCall, onReloadThread, hasEarlier, onLoadEarlier, onAssistantRemove, onAssistantAdopt, isProtocol, muted, onToggleMute, phone, onBack }) {
|
|
2684
2871
|
const scrollRef = React.useRef(null);
|
|
2685
2872
|
const prependRef = React.useRef(null);
|
|
2686
2873
|
const [earlierBusy, setEarlierBusy] = React.useState(false);
|
|
@@ -3102,7 +3289,15 @@ ${peer.address}`
|
|
|
3102
3289
|
fontSize: 12.5,
|
|
3103
3290
|
color: "var(--text)"
|
|
3104
3291
|
} }, /* @__PURE__ */ React.createElement(Icon, { name: "clock", size: 13, stroke: 2.2, color: "#d29922" }), /* @__PURE__ */ React.createElement("span", null, T.pendingFriend || "Waiting for them to accept your friend request \u2014 messages will queue and deliver once they do.")),
|
|
3105
|
-
/* @__PURE__ */ React.createElement("div", { ref: scrollRef, onScroll: updateFollowScroll, style: { flex: 1, overflow: "auto", padding: phone ? "12px 10px" : "18px 22px", WebkitOverflowScrolling: "touch" } }, /* @__PURE__ */ React.createElement("div", { style: { maxWidth: 1200, margin: "0 auto" } }, hasEarlier && /* @__PURE__ */ React.createElement("div", { style: { display: "flex", justifyContent: "center", margin: "4px 0 10px" } }, /* @__PURE__ */ React.createElement(Btn, { size: "sm", onClick: loadEarlier, disabled: earlierBusy }, earlierBusy ? T.loadingEarlier || "Loading\u2026" : T.loadEarlier || "Load earlier messages")), thread.filter((m) => m.day || !hidden.has(m.id)).map((m, i) => m.day ? /* @__PURE__ */ React.createElement("div", { key: i, style: { display: "flex", justifyContent: "center", margin: "14px 0" } }, /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 10.5, fontWeight: 600, color: "var(--faint)", background: "var(--chip)", padding: "3px 10px", borderRadius: 999 } }, m.day)) : /* @__PURE__ */ React.createElement(
|
|
3292
|
+
/* @__PURE__ */ React.createElement("div", { ref: scrollRef, onScroll: updateFollowScroll, style: { flex: 1, overflow: "auto", padding: phone ? "12px 10px" : "18px 22px", WebkitOverflowScrolling: "touch" } }, /* @__PURE__ */ React.createElement("div", { style: { maxWidth: 1200, margin: "0 auto" } }, hasEarlier && /* @__PURE__ */ React.createElement("div", { style: { display: "flex", justifyContent: "center", margin: "4px 0 10px" } }, /* @__PURE__ */ React.createElement(Btn, { size: "sm", onClick: loadEarlier, disabled: earlierBusy }, earlierBusy ? T.loadingEarlier || "Loading\u2026" : T.loadEarlier || "Load earlier messages")), collapseProtocol(thread, isProtocol || (() => false), lang).filter((m) => m.day || m.protocol || !hidden.has(m.id)).map((m, i) => m.day ? /* @__PURE__ */ React.createElement("div", { key: i, style: { display: "flex", justifyContent: "center", margin: "14px 0" } }, /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 10.5, fontWeight: 600, color: "var(--faint)", background: "var(--chip)", padding: "3px 10px", borderRadius: 999 } }, m.day)) : m.protocol ? /* @__PURE__ */ React.createElement("div", { key: m.id || i, style: { display: "flex", justifyContent: "center", margin: "4px 0" } }, /* @__PURE__ */ React.createElement("span", { title: m.text, style: {
|
|
3293
|
+
fontFamily: "var(--mono)",
|
|
3294
|
+
fontSize: 10.5,
|
|
3295
|
+
color: "var(--faint)",
|
|
3296
|
+
maxWidth: "86%",
|
|
3297
|
+
whiteSpace: "nowrap",
|
|
3298
|
+
overflow: "hidden",
|
|
3299
|
+
textOverflow: "ellipsis"
|
|
3300
|
+
} }, m.line)) : /* @__PURE__ */ React.createElement(
|
|
3106
3301
|
Msg,
|
|
3107
3302
|
{
|
|
3108
3303
|
key: m.id || i,
|
|
@@ -3273,12 +3468,12 @@ function MenuItem({ icon, label, onClick, danger }) {
|
|
|
3273
3468
|
function ChatEmpty({ T }) {
|
|
3274
3469
|
return /* @__PURE__ */ React.createElement("div", { style: { flex: 1, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", gap: 12, color: "var(--faint)", background: "var(--bg)" } }, /* @__PURE__ */ React.createElement(Icon, { name: "message", size: 40, stroke: 1.4, color: "var(--line)" }), /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--mono)", fontSize: 13 } }, T.pickPeer));
|
|
3275
3470
|
}
|
|
3276
|
-
function ChatTab({ T, lang, peers, requests, activeId, thread, onSelect, onAct, onAdd, onSend, onSendFile, onSendRtcFile, onAlias, onRemove, onOpenNet, onCall, onReloadThread, hasEarlier, onLoadEarlier, onAssistantRemove, onAssistantAdopt, prefillAddr, onPrefillConsumed, muted, onToggleMute, phone, onBack }) {
|
|
3471
|
+
function ChatTab({ T, lang, peers, requests, activeId, thread, isProtocol, protocolFix, onSelect, onAct, onAdd, onSend, onSendFile, onSendRtcFile, onAlias, onRemove, onOpenNet, onCall, onReloadThread, hasEarlier, onLoadEarlier, onAssistantRemove, onAssistantAdopt, prefillAddr, onPrefillConsumed, muted, onToggleMute, phone, onBack }) {
|
|
3277
3472
|
const peer = peers.find((p) => p.id === activeId);
|
|
3278
3473
|
if (phone) {
|
|
3279
|
-
return peer ? /* @__PURE__ */ React.createElement(Conversation, { T, peer, lang, peers, onOpenChat: onSelect, thread, onSend, onSendFile, onSendRtcFile, onAlias, onRemove, onOpenNet, onCall, onReloadThread, hasEarlier, onLoadEarlier, onAssistantRemove, onAssistantAdopt, muted: !!muted && muted.includes(peer.id), onToggleMute, phone: true, onBack }) : /* @__PURE__ */ React.createElement(PeerSidebar, { T, peers, requests, activeId, onSelect, onAct, onAdd, prefillAddr, onPrefillConsumed, muted, wide: true });
|
|
3474
|
+
return peer ? /* @__PURE__ */ React.createElement(Conversation, { T, peer, lang, peers, onOpenChat: onSelect, thread, isProtocol, onSend, onSendFile, onSendRtcFile, onAlias, onRemove, onOpenNet, onCall, onReloadThread, hasEarlier, onLoadEarlier, onAssistantRemove, onAssistantAdopt, muted: !!muted && muted.includes(peer.id), onToggleMute, phone: true, onBack }) : /* @__PURE__ */ React.createElement(PeerSidebar, { T, peers, requests, activeId, onSelect, onAct, onAdd, prefillAddr, onPrefillConsumed, muted, isProtocol, protocolFix, wide: true });
|
|
3280
3475
|
}
|
|
3281
|
-
return /* @__PURE__ */ React.createElement("div", { style: { flex: 1, display: "flex", minWidth: 0, minHeight: 0 } }, /* @__PURE__ */ React.createElement(PeerSidebar, { T, peers, requests, activeId, onSelect, onAct, onAdd, prefillAddr, onPrefillConsumed, muted }), peer ? /* @__PURE__ */ React.createElement(Conversation, { T, peer, lang, peers, onOpenChat: onSelect, thread, onSend, onSendFile, onSendRtcFile, onAlias, onRemove, onOpenNet, onCall, onReloadThread, hasEarlier, onLoadEarlier, onAssistantRemove, onAssistantAdopt, muted: !!muted && muted.includes(peer.id), onToggleMute }) : /* @__PURE__ */ React.createElement(ChatEmpty, { T }));
|
|
3476
|
+
return /* @__PURE__ */ React.createElement("div", { style: { flex: 1, display: "flex", minWidth: 0, minHeight: 0 } }, /* @__PURE__ */ React.createElement(PeerSidebar, { T, peers, requests, activeId, onSelect, onAct, onAdd, prefillAddr, onPrefillConsumed, muted, isProtocol, protocolFix }), peer ? /* @__PURE__ */ React.createElement(Conversation, { T, peer, lang, peers, onOpenChat: onSelect, thread, isProtocol, onSend, onSendFile, onSendRtcFile, onAlias, onRemove, onOpenNet, onCall, onReloadThread, hasEarlier, onLoadEarlier, onAssistantRemove, onAssistantAdopt, muted: !!muted && muted.includes(peer.id), onToggleMute }) : /* @__PURE__ */ React.createElement(ChatEmpty, { T }));
|
|
3282
3477
|
}
|
|
3283
3478
|
Object.assign(window, { ChatTab });
|
|
3284
3479
|
|
|
@@ -5922,7 +6117,7 @@ function dkFlashStop() {
|
|
|
5922
6117
|
function dkLooking() {
|
|
5923
6118
|
return document.visibilityState === "visible" && document.hasFocus();
|
|
5924
6119
|
}
|
|
5925
|
-
function useIncomingAlerts({ T, peers, requests, loaded, activeId, sound = true, flash = true, muted }) {
|
|
6120
|
+
function useIncomingAlerts({ T, peers, requests, loaded, activeId, sound = true, flash = true, muted, isProtocol }) {
|
|
5926
6121
|
const prev = React.useRef(null);
|
|
5927
6122
|
const mutedRef = React.useRef(/* @__PURE__ */ new Set());
|
|
5928
6123
|
mutedRef.current = new Set(muted || []);
|
|
@@ -5952,7 +6147,8 @@ function useIncomingAlerts({ T, peers, requests, loaded, activeId, sound = true,
|
|
|
5952
6147
|
const byId = /* @__PURE__ */ new Map();
|
|
5953
6148
|
for (const p of peers || []) {
|
|
5954
6149
|
const dir = p.lastDir || (String(p.lastMsg || "").startsWith("you: ") ? "out" : "in");
|
|
5955
|
-
|
|
6150
|
+
const quiet = typeof isProtocol === "function" && lastIsProtocol(p, isProtocol);
|
|
6151
|
+
byId.set(p.id, { ts: p.lastTs || 0, dir, quiet });
|
|
5956
6152
|
}
|
|
5957
6153
|
const reqIds = new Set((requests || []).map((r) => r.id));
|
|
5958
6154
|
const was = prev.current;
|
|
@@ -5963,6 +6159,8 @@ function useIncomingAlerts({ T, peers, requests, loaded, activeId, sound = true,
|
|
|
5963
6159
|
for (const [id, cur] of byId) {
|
|
5964
6160
|
if (cur.dir !== "in" || !cur.ts)
|
|
5965
6161
|
continue;
|
|
6162
|
+
if (cur.quiet)
|
|
6163
|
+
continue;
|
|
5966
6164
|
const old = was.byId.get(id);
|
|
5967
6165
|
if (old ? cur.ts <= old.ts : Date.now() - cur.ts > 3e4)
|
|
5968
6166
|
continue;
|
|
@@ -6810,6 +7008,8 @@ function DkApp() {
|
|
|
6810
7008
|
const rowPad = t.density === "comfortable" ? "11px 12px" : "7px 10px";
|
|
6811
7009
|
const mutedIds = Array.isArray(t.alertMuted) ? t.alertMuted : [];
|
|
6812
7010
|
const onToggleMute = (id) => setTweak("alertMuted", mutedIds.includes(id) ? mutedIds.filter((x) => x !== id) : mutedIds.concat(id));
|
|
7011
|
+
const isProtocol = React.useMemo(() => protocolTest(hostIsProtocolMessage), []);
|
|
7012
|
+
const protocolFix = useProtocolTails(peers, isProtocol, !!hostIsProtocolMessage);
|
|
6813
7013
|
useIncomingAlerts({
|
|
6814
7014
|
T,
|
|
6815
7015
|
peers,
|
|
@@ -6818,7 +7018,8 @@ function DkApp() {
|
|
|
6818
7018
|
activeId,
|
|
6819
7019
|
sound: t.alertSound !== false,
|
|
6820
7020
|
flash: t.alertFlash !== false,
|
|
6821
|
-
muted: mutedIds
|
|
7021
|
+
muted: mutedIds,
|
|
7022
|
+
isProtocol
|
|
6822
7023
|
});
|
|
6823
7024
|
const assistant = useAssistant({
|
|
6824
7025
|
lang: t.lang,
|
|
@@ -6852,6 +7053,54 @@ function DkApp() {
|
|
|
6852
7053
|
});
|
|
6853
7054
|
const phone = useIsPhone();
|
|
6854
7055
|
const [sharing, setSharing] = React.useState(false);
|
|
7056
|
+
const headerActions = (hostHeaderActions || []).filter((a) => a && a.id && typeof a.onClick === "function");
|
|
7057
|
+
const headerActionBtns = headerActions.map((a) => {
|
|
7058
|
+
let on = false;
|
|
7059
|
+
try {
|
|
7060
|
+
on = typeof a.active === "function" ? !!a.active() : false;
|
|
7061
|
+
} catch (e) {
|
|
7062
|
+
on = false;
|
|
7063
|
+
}
|
|
7064
|
+
const label = pickText(a.label, t.lang, a.id);
|
|
7065
|
+
return /* @__PURE__ */ React.createElement(
|
|
7066
|
+
"button",
|
|
7067
|
+
{
|
|
7068
|
+
key: a.id,
|
|
7069
|
+
title: label,
|
|
7070
|
+
"aria-label": label,
|
|
7071
|
+
"aria-pressed": on,
|
|
7072
|
+
onClick: () => {
|
|
7073
|
+
try {
|
|
7074
|
+
a.onClick({ T, t, me, activeId, phone });
|
|
7075
|
+
} catch (e) {
|
|
7076
|
+
}
|
|
7077
|
+
},
|
|
7078
|
+
style: {
|
|
7079
|
+
width: 32,
|
|
7080
|
+
height: 32,
|
|
7081
|
+
flexShrink: 0,
|
|
7082
|
+
borderRadius: 8,
|
|
7083
|
+
cursor: "pointer",
|
|
7084
|
+
padding: 0,
|
|
7085
|
+
border: "1px solid " + (on ? "var(--accent)" : "var(--line)"),
|
|
7086
|
+
background: on ? "color-mix(in oklab, var(--accent), transparent 86%)" : "transparent",
|
|
7087
|
+
display: "flex",
|
|
7088
|
+
alignItems: "center",
|
|
7089
|
+
justifyContent: "center"
|
|
7090
|
+
}
|
|
7091
|
+
},
|
|
7092
|
+
/* @__PURE__ */ React.createElement(
|
|
7093
|
+
Icon,
|
|
7094
|
+
{
|
|
7095
|
+
name: typeof a.icon === "string" ? a.icon : void 0,
|
|
7096
|
+
svgPath: a.icon && typeof a.icon === "object" ? a.icon.svgPath : void 0,
|
|
7097
|
+
size: 16,
|
|
7098
|
+
stroke: 2,
|
|
7099
|
+
color: on ? "var(--accent)" : "var(--dim)"
|
|
7100
|
+
}
|
|
7101
|
+
)
|
|
7102
|
+
);
|
|
7103
|
+
});
|
|
6855
7104
|
const shareBtn = /* @__PURE__ */ React.createElement(
|
|
6856
7105
|
"button",
|
|
6857
7106
|
{
|
|
@@ -7022,7 +7271,7 @@ function DkApp() {
|
|
|
7022
7271
|
const lastPeople = React.useRef("here");
|
|
7023
7272
|
if (peopleTab)
|
|
7024
7273
|
lastPeople.current = tab;
|
|
7025
|
-
const unreadTotal = (peers
|
|
7274
|
+
const unreadTotal = rosterUnreadTotal(peers, isProtocol, protocolFix) + (requests || []).length;
|
|
7026
7275
|
const NAV_FOR = {
|
|
7027
7276
|
chat: { icon: "message", label: T.chat, active: tab === "chat", badge: unreadTotal, go: () => setTab("chat") },
|
|
7028
7277
|
people: { icon: "users", label: T.people, active: peopleTab, go: () => setTab(lastPeople.current) },
|
|
@@ -7066,7 +7315,7 @@ function DkApp() {
|
|
|
7066
7315
|
display: "flex",
|
|
7067
7316
|
border: "1px solid " + (tab === "profile" ? "var(--line)" : "transparent"),
|
|
7068
7317
|
background: tab === "profile" ? "var(--panel-2)" : "transparent"
|
|
7069
|
-
} }, /* @__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" } }, !inConversation && /* @__PURE__ */ React.createElement(DkBrowserNotice, { lang: t.lang }), !inConversation && /* @__PURE__ */ React.createElement("div", { style: { height: 46, boxSizing: "content-box", paddingTop: phone ? "env(safe-area-inset-top, 0px)" : 0, flexShrink: 0, borderBottom: "1px solid var(--line)", background: "var(--panel)", display: "flex", alignItems: "center", gap: phone ? 8 : 12, paddingLeft: phone ? 12 : 16, paddingRight: phone ? 12 : 16 } }, /* @__PURE__ */ React.createElement(Brand, { T, style: { gap: 12, flexShrink: 0 } }, /* @__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)", whiteSpace: "nowrap" } }, "\xB7 ", (nav.find((n) => n.id === tab) || { label: T.profile }).label.toLowerCase()), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }), phone ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(StatusDot, { online: me.online }), shareBtn, /* @__PURE__ */ React.createElement("button", { onClick: () => setTab("profile"), title: T.profile, style: { padding: 0, border: "none", background: "transparent", cursor: "pointer", display: "flex" } }, /* @__PURE__ */ React.createElement(DkAvatar, { peer: { ...me, id: me.userId, agent: false }, size: 28, radius: 7, dot: false }))) : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__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)" } }), shareBtn, /* @__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)))), phone && peopleTab && /* @__PURE__ */ React.createElement("div", { style: { flexShrink: 0, display: "flex", gap: 6, padding: "8px 12px", borderBottom: "1px solid var(--line)", background: "var(--panel)", overflowX: "auto" } }, nav.filter((n) => DK_PEOPLE_TABS.includes(n.id)).map((n) => /* @__PURE__ */ React.createElement("button", { key: n.id, onClick: () => setTab(n.id), style: {
|
|
7318
|
+
} }, /* @__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" } }, !inConversation && /* @__PURE__ */ React.createElement(DkBrowserNotice, { lang: t.lang }), !inConversation && /* @__PURE__ */ React.createElement("div", { style: { height: 46, boxSizing: "content-box", paddingTop: phone ? "env(safe-area-inset-top, 0px)" : 0, flexShrink: 0, borderBottom: "1px solid var(--line)", background: "var(--panel)", display: "flex", alignItems: "center", gap: phone ? 8 : 12, paddingLeft: phone ? 12 : 16, paddingRight: phone ? 12 : 16 } }, /* @__PURE__ */ React.createElement(Brand, { T, style: { gap: 12, flexShrink: 0 } }, /* @__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)", whiteSpace: "nowrap" } }, "\xB7 ", (nav.find((n) => n.id === tab) || { label: T.profile }).label.toLowerCase()), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }), phone ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(StatusDot, { online: me.online }), headerActionBtns, shareBtn, /* @__PURE__ */ React.createElement("button", { onClick: () => setTab("profile"), title: T.profile, style: { padding: 0, border: "none", background: "transparent", cursor: "pointer", display: "flex" } }, /* @__PURE__ */ React.createElement(DkAvatar, { peer: { ...me, id: me.userId, agent: false }, size: 28, radius: 7, dot: false }))) : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__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)" } }), headerActionBtns, shareBtn, /* @__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)))), phone && peopleTab && /* @__PURE__ */ React.createElement("div", { style: { flexShrink: 0, display: "flex", gap: 6, padding: "8px 12px", borderBottom: "1px solid var(--line)", background: "var(--panel)", overflowX: "auto" } }, nav.filter((n) => DK_PEOPLE_TABS.includes(n.id)).map((n) => /* @__PURE__ */ React.createElement("button", { key: n.id, onClick: () => setTab(n.id), style: {
|
|
7070
7319
|
display: "inline-flex",
|
|
7071
7320
|
alignItems: "center",
|
|
7072
7321
|
gap: 6,
|
|
@@ -7080,7 +7329,7 @@ function DkApp() {
|
|
|
7080
7329
|
fontWeight: 600,
|
|
7081
7330
|
background: tab === n.id ? "var(--accent)" : "transparent",
|
|
7082
7331
|
color: tab === n.id ? "#fff" : "var(--dim)"
|
|
7083
|
-
} }, /* @__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, 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(
|
|
7332
|
+
} }, /* @__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(
|
|
7084
7333
|
ProfileTab,
|
|
7085
7334
|
{
|
|
7086
7335
|
T,
|
package/package.json
CHANGED