@decentnetwork/beagle-ui 0.2.6 → 0.2.8

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.
Files changed (2) hide show
  1. package/dist/beagle-ui.js +242 -11
  2. package/package.json +1 -1
package/dist/beagle-ui.js CHANGED
@@ -1,4 +1,4 @@
1
- export const BEAGLE_UI_VERSION = "0.2.5";
1
+ export const BEAGLE_UI_VERSION = "0.2.7";
2
2
  // src/icons.jsx
3
3
  var ICON_PATHS = {
4
4
  // ---- tab bar (the four must feel like one set) ----
@@ -527,6 +527,9 @@ function PeerRow({ peer, T, active, onClick }) {
527
527
  minWidth: 0
528
528
  } }, dkContactPreview(peer.lastMsg) || peer.lastMsg))), /* @__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)" } }, peer.lastTime), peer.unread ? /* @__PURE__ */ React.createElement(Unread, { n: peer.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 })));
529
529
  }
530
+ function dkActivityTs(p) {
531
+ return Math.max(p.lastTs || 0, p.acceptedAt || 0, p.requestedAt || 0);
532
+ }
530
533
  function PeerSidebar({ T, peers, requests, activeId, onSelect, onAct, onAdd, prefillAddr, onPrefillConsumed }) {
531
534
  const [q, setQ] = React.useState("");
532
535
  const [addr, setAddr] = React.useState("");
@@ -564,7 +567,7 @@ function PeerSidebar({ T, peers, requests, activeId, onSelect, onAct, onAdd, pre
564
567
  const s = (p.alias || "") + " " + p.userId + " " + p.ip;
565
568
  return s.toLowerCase().includes(q.toLowerCase());
566
569
  }).slice().sort((a, b) => {
567
- const ta = a.lastTs || 0, tb = b.lastTs || 0;
570
+ const ta = dkActivityTs(a), tb = dkActivityTs(b);
568
571
  if (ta !== tb)
569
572
  return tb - ta;
570
573
  return String(a.alias || a.userId || "").localeCompare(String(b.alias || b.userId || ""));
@@ -2725,6 +2728,35 @@ function DkDisplaySettings({ t, setTweak }) {
2725
2728
  )));
2726
2729
  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"]])));
2727
2730
  }
2731
+ function DkAlertSettings({ t, setTweak }) {
2732
+ const zh = t.lang === "zh";
2733
+ const toggle = (key, label, sub, last) => /* @__PURE__ */ React.createElement("label", { style: {
2734
+ display: "flex",
2735
+ alignItems: "center",
2736
+ gap: 13,
2737
+ padding: "13px 16px",
2738
+ cursor: "pointer",
2739
+ borderBottom: last ? "none" : "1px solid var(--line)"
2740
+ } }, /* @__PURE__ */ React.createElement(
2741
+ "input",
2742
+ {
2743
+ type: "checkbox",
2744
+ checked: t[key] !== false,
2745
+ onChange: (e) => setTweak(key, e.target.checked),
2746
+ style: { width: 16, height: 16, accentColor: "var(--accent)" }
2747
+ }
2748
+ ), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }, /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--mono)", fontSize: 13.5, fontWeight: 600, color: "var(--text)" } }, label), /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 11.5, color: "var(--dim)", marginTop: 2 } }, sub)));
2749
+ return /* @__PURE__ */ React.createElement(Card, { label: zh ? "\u63D0\u9192" : "Alerts" }, toggle(
2750
+ "alertSound",
2751
+ zh ? "\u65B0\u6D88\u606F\u63D0\u793A\u97F3" : "Sound for new messages",
2752
+ zh ? "\u6536\u5230\u65B0\u6D88\u606F\u6216\u597D\u53CB\u8BF7\u6C42\u65F6\u64AD\u653E\u77ED\u4FC3\u63D0\u793A\u97F3\u3002\u6B63\u5728\u770B\u7684\u5F53\u524D\u4F1A\u8BDD\u4E0D\u4F1A\u54CD\u3002" : "A short chime when a message or friend request arrives. Silent for the conversation you are reading."
2753
+ ), toggle(
2754
+ "alertFlash",
2755
+ zh ? "\u6807\u7B7E\u9875\u95EA\u70C1" : "Flash the tab",
2756
+ zh ? "\u7A97\u53E3\u4E0D\u5728\u524D\u53F0\u65F6\uFF0C\u6807\u7B7E\u6807\u9898\u548C\u56FE\u6807\u95EA\u70C1\u63D0\u793A\uFF0C\u56DE\u5230\u7A97\u53E3\u5373\u505C\u6B62\u3002" : "While this window is in the background, the tab title and icon blink until you come back.",
2757
+ true
2758
+ ));
2759
+ }
2728
2760
  function ProfileTab({ T, me, onEdit, t, setTweak }) {
2729
2761
  var _a;
2730
2762
  const [qr, setQr] = React.useState(null);
@@ -2746,7 +2778,7 @@ function ProfileTab({ T, me, onEdit, t, setTweak }) {
2746
2778
  },
2747
2779
  style: { width: 16, height: 16, accentColor: "var(--accent)" }
2748
2780
  }
2749
- ), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }, /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--mono)", fontSize: 13.5, fontWeight: 600, color: "var(--text)" } }, T && T.autoAcceptLabel || "Auto-accept friend requests"), /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 11.5, color: "var(--dim)", marginTop: 2 } }, T && T.autoAcceptSub || "Off: requests wait in the sidebar for your approval.")))), hostHasKeyBackup && /* @__PURE__ */ React.createElement(DkKeyBackup, { t: t || {} }), t && setTweak && /* @__PURE__ */ React.createElement(DkDisplaySettings, { t, setTweak }), /* @__PURE__ */ React.createElement(Card, { label: T.network }, /* @__PURE__ */ React.createElement(FieldRow, { T, label: T.virtualIp, value: me.ip, copy: true }), /* @__PURE__ */ React.createElement(FieldRow, { T, label: T.wireLabel, value: `${me.wire} \xB7 lossless`, mono: false }), /* @__PURE__ */ React.createElement(DkVersionRow, { T, me }), /* @__PURE__ */ React.createElement(DkUpdateCheck, { T })), /* @__PURE__ */ React.createElement(Card, { label: T.dangerZone }, /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 13, padding: "14px 16px" } }, /* @__PURE__ */ React.createElement("div", { style: { width: 34, height: 34, borderRadius: 8, flexShrink: 0, background: "color-mix(in oklab, var(--danger), transparent 86%)", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--danger)" } }, /* @__PURE__ */ React.createElement(Icon, { name: "trash", size: 17, stroke: 2 })), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }, /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--mono)", fontSize: 13.5, fontWeight: 600, color: "var(--danger)" } }, T.deleteNode), /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12, color: "var(--faint)", marginTop: 1 } }, T.deleteSub)), /* @__PURE__ */ React.createElement(Btn, { tone: "danger", size: "sm" }, T.delete)))), qr && /* @__PURE__ */ React.createElement(DkQrModal, { T, value: qr.value, label: qr.label, onClose: () => setQr(null) }), editing && /* @__PURE__ */ React.createElement(DkEditModal, { T, me, onClose: () => setEditing(false), onSave: (name, description) => {
2781
+ ), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }, /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--mono)", fontSize: 13.5, fontWeight: 600, color: "var(--text)" } }, T && T.autoAcceptLabel || "Auto-accept friend requests"), /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 11.5, color: "var(--dim)", marginTop: 2 } }, T && T.autoAcceptSub || "Off: requests wait in the sidebar for your approval.")))), hostHasKeyBackup && /* @__PURE__ */ React.createElement(DkKeyBackup, { t: t || {} }), t && setTweak && /* @__PURE__ */ React.createElement(DkAlertSettings, { t, setTweak }), t && setTweak && /* @__PURE__ */ React.createElement(DkDisplaySettings, { t, setTweak }), /* @__PURE__ */ React.createElement(Card, { label: T.network }, /* @__PURE__ */ React.createElement(FieldRow, { T, label: T.virtualIp, value: me.ip, copy: true }), /* @__PURE__ */ React.createElement(FieldRow, { T, label: T.wireLabel, value: `${me.wire} \xB7 lossless`, mono: false }), /* @__PURE__ */ React.createElement(DkVersionRow, { T, me }), /* @__PURE__ */ React.createElement(DkUpdateCheck, { T })), /* @__PURE__ */ React.createElement(Card, { label: T.dangerZone }, /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 13, padding: "14px 16px" } }, /* @__PURE__ */ React.createElement("div", { style: { width: 34, height: 34, borderRadius: 8, flexShrink: 0, background: "color-mix(in oklab, var(--danger), transparent 86%)", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--danger)" } }, /* @__PURE__ */ React.createElement(Icon, { name: "trash", size: 17, stroke: 2 })), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }, /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--mono)", fontSize: 13.5, fontWeight: 600, color: "var(--danger)" } }, T.deleteNode), /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12, color: "var(--faint)", marginTop: 1 } }, T.deleteSub)), /* @__PURE__ */ React.createElement(Btn, { tone: "danger", size: "sm" }, T.delete)))), qr && /* @__PURE__ */ React.createElement(DkQrModal, { T, value: qr.value, label: qr.label, onClose: () => setQr(null) }), editing && /* @__PURE__ */ React.createElement(DkEditModal, { T, me, onClose: () => setEditing(false), onSave: (name, description) => {
2750
2782
  if (onEdit)
2751
2783
  onEdit(name, description);
2752
2784
  setEditing(false);
@@ -4310,6 +4342,183 @@ function NetworkTab({ T, me, peers, exits, activeExit, reqCount, onSetExit, onOp
4310
4342
  }
4311
4343
  Object.assign(window, { NetworkTab });
4312
4344
 
4345
+ // src/notify.jsx
4346
+ var dkAudioCtx = null;
4347
+ function dkAudio() {
4348
+ if (dkAudioCtx && dkAudioCtx.state !== "closed")
4349
+ return dkAudioCtx;
4350
+ try {
4351
+ dkAudioCtx = new (window.AudioContext || window.webkitAudioContext)();
4352
+ } catch (e) {
4353
+ dkAudioCtx = null;
4354
+ }
4355
+ return dkAudioCtx;
4356
+ }
4357
+ function dkUnlockAudioOnGesture() {
4358
+ const unlock = () => {
4359
+ const c = dkAudio();
4360
+ if (c && c.state === "suspended")
4361
+ c.resume().catch(() => {
4362
+ });
4363
+ };
4364
+ window.addEventListener("pointerdown", unlock, { passive: true });
4365
+ window.addEventListener("keydown", unlock, { passive: true });
4366
+ return () => {
4367
+ window.removeEventListener("pointerdown", unlock);
4368
+ window.removeEventListener("keydown", unlock);
4369
+ };
4370
+ }
4371
+ function dkChime(kind) {
4372
+ const c = dkAudio();
4373
+ if (!c)
4374
+ return;
4375
+ if (c.state === "suspended")
4376
+ c.resume().catch(() => {
4377
+ });
4378
+ const notes = kind === "request" ? [[660, 0], [880, 0.14]] : [[880, 0], [1175, 0.11]];
4379
+ const t0 = c.currentTime;
4380
+ for (const [freq, at] of notes) {
4381
+ const o = c.createOscillator(), g = c.createGain();
4382
+ o.type = "sine";
4383
+ o.frequency.value = freq;
4384
+ o.connect(g);
4385
+ g.connect(c.destination);
4386
+ const t = t0 + at;
4387
+ g.gain.setValueAtTime(1e-4, t);
4388
+ g.gain.exponentialRampToValueAtTime(0.18, t + 0.015);
4389
+ g.gain.exponentialRampToValueAtTime(1e-4, t + 0.17);
4390
+ o.start(t);
4391
+ o.stop(t + 0.2);
4392
+ }
4393
+ }
4394
+ var dkFlash = { timer: null, title: "", link: null, href: null, badged: null, on: false, n: 0, label: "" };
4395
+ function dkBadgedIcon(href) {
4396
+ return new Promise((res, rej) => {
4397
+ const img = new Image();
4398
+ img.onload = () => {
4399
+ try {
4400
+ if (!img.naturalWidth)
4401
+ return rej(new Error("icon has no intrinsic size"));
4402
+ const s = 64, cv = document.createElement("canvas");
4403
+ cv.width = s;
4404
+ cv.height = s;
4405
+ const cx = cv.getContext("2d");
4406
+ cx.drawImage(img, 0, 0, s, s);
4407
+ cx.beginPath();
4408
+ cx.arc(s - 14, 14, 12, 0, Math.PI * 2);
4409
+ cx.fillStyle = "#e5484d";
4410
+ cx.fill();
4411
+ cx.lineWidth = 3;
4412
+ cx.strokeStyle = "#fff";
4413
+ cx.stroke();
4414
+ res(cv.toDataURL("image/png"));
4415
+ } catch (e) {
4416
+ rej(e);
4417
+ }
4418
+ };
4419
+ img.onerror = () => rej(new Error("icon failed to load"));
4420
+ img.src = href;
4421
+ });
4422
+ }
4423
+ function dkFlashTick() {
4424
+ dkFlash.on = !dkFlash.on;
4425
+ document.title = `(${dkFlash.n}) ${dkFlash.on ? dkFlash.label : dkFlash.title}`;
4426
+ }
4427
+ function dkFlashStart(label, count) {
4428
+ dkFlash.n += count || 1;
4429
+ dkFlash.label = label;
4430
+ if (dkFlash.timer)
4431
+ return;
4432
+ dkFlash.title = document.title;
4433
+ dkFlash.link = document.querySelector('link[rel~="icon"]');
4434
+ dkFlash.href = dkFlash.link ? dkFlash.link.href : null;
4435
+ dkFlash.badged = null;
4436
+ dkFlash.on = false;
4437
+ if (dkFlash.href) {
4438
+ dkBadgedIcon(dkFlash.href).then((b) => {
4439
+ dkFlash.badged = b;
4440
+ if (dkFlash.timer && dkFlash.link)
4441
+ dkFlash.link.href = b;
4442
+ }).catch(() => {
4443
+ });
4444
+ }
4445
+ dkFlashTick();
4446
+ dkFlash.timer = setInterval(dkFlashTick, 1e3);
4447
+ }
4448
+ function dkFlashStop() {
4449
+ if (!dkFlash.timer)
4450
+ return;
4451
+ clearInterval(dkFlash.timer);
4452
+ dkFlash.timer = null;
4453
+ dkFlash.n = 0;
4454
+ document.title = dkFlash.title;
4455
+ if (dkFlash.link && dkFlash.href)
4456
+ dkFlash.link.href = dkFlash.href;
4457
+ }
4458
+ function dkLooking() {
4459
+ return document.visibilityState === "visible" && document.hasFocus();
4460
+ }
4461
+ function useIncomingAlerts({ T, peers, requests, loaded, activeId, sound = true, flash = true }) {
4462
+ const prev = React.useRef(null);
4463
+ React.useEffect(() => dkUnlockAudioOnGesture(), []);
4464
+ React.useEffect(() => {
4465
+ if (!flash)
4466
+ dkFlashStop();
4467
+ }, [flash]);
4468
+ React.useEffect(() => {
4469
+ const seen = () => {
4470
+ if (dkLooking())
4471
+ dkFlashStop();
4472
+ };
4473
+ window.addEventListener("focus", seen);
4474
+ window.addEventListener("pointerdown", seen, { passive: true });
4475
+ document.addEventListener("visibilitychange", seen);
4476
+ return () => {
4477
+ window.removeEventListener("focus", seen);
4478
+ window.removeEventListener("pointerdown", seen);
4479
+ document.removeEventListener("visibilitychange", seen);
4480
+ dkFlashStop();
4481
+ };
4482
+ }, []);
4483
+ React.useEffect(() => {
4484
+ if (!loaded)
4485
+ return;
4486
+ const byId = /* @__PURE__ */ new Map();
4487
+ for (const p of peers || []) {
4488
+ const dir = p.lastDir || (String(p.lastMsg || "").startsWith("you: ") ? "out" : "in");
4489
+ byId.set(p.id, { ts: p.lastTs || 0, dir });
4490
+ }
4491
+ const reqIds = new Set((requests || []).map((r) => r.id));
4492
+ const was = prev.current;
4493
+ prev.current = { byId, reqIds };
4494
+ if (!was)
4495
+ return;
4496
+ let msgs = 0, elsewhere = 0, reqs = 0;
4497
+ for (const [id, cur] of byId) {
4498
+ if (cur.dir !== "in" || !cur.ts)
4499
+ continue;
4500
+ const old = was.byId.get(id);
4501
+ if (old ? cur.ts <= old.ts : Date.now() - cur.ts > 3e4)
4502
+ continue;
4503
+ msgs += 1;
4504
+ if (id !== activeId)
4505
+ elsewhere += 1;
4506
+ }
4507
+ for (const id of reqIds)
4508
+ if (!was.reqIds.has(id))
4509
+ reqs += 1;
4510
+ if (!msgs && !reqs)
4511
+ return;
4512
+ const looking = dkLooking();
4513
+ if (sound && !(looking && !reqs && !elsewhere))
4514
+ dkChime(reqs && !msgs ? "request" : "message");
4515
+ if (flash && !looking) {
4516
+ const label = msgs ? T && T.alertMsg || "New message" : T && T.alertReq || "New friend request";
4517
+ dkFlashStart(label, msgs + reqs);
4518
+ }
4519
+ }, [peers, requests, loaded, activeId, T, sound, flash]);
4520
+ }
4521
+
4313
4522
  // src/settings-store.jsx
4314
4523
  var TWEAKS_STORAGE_KEY = "decentlan.tweaks";
4315
4524
  function useTweaks(defaults) {
@@ -4343,8 +4552,9 @@ Object.assign(window, { useTweaks });
4343
4552
  // src/app.jsx
4344
4553
  function ownershipFix(info) {
4345
4554
  const r = String(info && info.selfUpdateBlocked || "");
4346
- const at = r.indexOf("sudo chown");
4347
- return at >= 0 ? r.slice(at) : 'sudo chown -R $(id -u):$(id -g) "$(npm prefix -g)/lib/node_modules/@decentnetwork"';
4555
+ const at = r.indexOf("sudo npm i -g");
4556
+ const end = at >= 0 ? r.indexOf(".", at) : -1;
4557
+ return at >= 0 ? r.slice(at, end > at ? end : void 0) : "sudo npm i -g @decentnetwork/beagle@latest";
4348
4558
  }
4349
4559
  function dkParseDeepLinkAddress() {
4350
4560
  try {
@@ -4369,7 +4579,9 @@ var DK_DEFAULTS = (
4369
4579
  "accent": "#7B6CF6",
4370
4580
  "density": "compact",
4371
4581
  "lang": "en",
4372
- "startTab": "chat"
4582
+ "startTab": "chat",
4583
+ "alertSound": true,
4584
+ "alertFlash": true
4373
4585
  }
4374
4586
  );
4375
4587
  function dkDetectLang() {
@@ -4438,6 +4650,8 @@ var STR = {
4438
4650
  network: "Network",
4439
4651
  apps: "Apps",
4440
4652
  profile: "Profile",
4653
+ alertMsg: "New message",
4654
+ alertReq: "New friend request",
4441
4655
  recommended: "Discover",
4442
4656
  registered: "Names",
4443
4657
  here: "Here",
@@ -4618,6 +4832,8 @@ var STR = {
4618
4832
  network: "\u7F51\u7EDC",
4619
4833
  apps: "\u5E94\u7528",
4620
4834
  profile: "\u6211\u7684",
4835
+ alertMsg: "\u65B0\u6D88\u606F",
4836
+ alertReq: "\u65B0\u7684\u597D\u53CB\u8BF7\u6C42",
4621
4837
  recommended: "\u63A8\u8350",
4622
4838
  registered: "\u540D\u5F55",
4623
4839
  here: "\u5728\u573A",
@@ -4886,7 +5102,7 @@ function DkUpdateModal({ T, info, onClose }) {
4886
5102
  lineHeight: 1.6,
4887
5103
  borderLeft: "2px solid var(--danger)",
4888
5104
  paddingLeft: 10
4889
- } }, T.updNoPerm || "Automatic updates cannot write the global npm directory \u2014 this is what a first install with sudo leaves behind. Run this once and it never comes back:", /* @__PURE__ */ React.createElement("div", { style: { display: "flex", gap: 6, alignItems: "center", marginTop: 6 } }, /* @__PURE__ */ React.createElement("code", { style: {
5105
+ } }, T.updNoPerm || "This install lives under a system-owned prefix, so updating it is a privileged operation and this button cannot do it. Run it in a terminal:", /* @__PURE__ */ React.createElement("div", { style: { display: "flex", gap: 6, alignItems: "center", marginTop: 6 } }, /* @__PURE__ */ React.createElement("code", { style: {
4890
5106
  flex: 1,
4891
5107
  minWidth: 0,
4892
5108
  fontFamily: "var(--mono)",
@@ -4898,7 +5114,7 @@ function DkUpdateModal({ T, info, onClose }) {
4898
5114
  padding: "8px 10px",
4899
5115
  userSelect: "all",
4900
5116
  wordBreak: "break-all"
4901
- } }, ownershipFix(info)), /* @__PURE__ */ React.createElement(Btn, { size: "sm", icon: "copy", title: T.copy || "Copy", onClick: () => dkCopy(ownershipFix(info)) })), /* @__PURE__ */ React.createElement("div", { style: { marginTop: 6, fontSize: 11.5, color: "var(--faint)" } }, T.updNoPermAlt || "It touches only the directory, not the programs inside it. If you would rather not change anything under /usr/local, the alternative is to move npm out of it: `npm config set prefix ~/.npm-global`, then put `~/.npm-global/bin` first on your PATH.")), 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."), daemonPeerBehind && phase === "idle" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12, color: "var(--dim)", lineHeight: 1.5 } }, T.updPeerDaemon || "The peer version belongs to the running agentnet daemon, not to this app. Update it with:", /* @__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") }))), 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" && (() => {
5117
+ } }, ownershipFix(info)), /* @__PURE__ */ React.createElement(Btn, { size: "sm", icon: "copy", title: T.copy || "Copy", onClick: () => dkCopy(ownershipFix(info)) })), /* @__PURE__ */ React.createElement("div", { style: { marginTop: 6, fontSize: 11.5, color: "var(--faint)" } }, T.updNoPermAlt || "Do not widen permissions there to make this button work \u2014 a group-writable bin directory lets any admin user replace programs that root later runs. For one-click updates, move npm out of the system prefix instead: `npm config set prefix ~/.npm-global`, then put `~/.npm-global/bin` first on your PATH.")), 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."), daemonPeerBehind && phase === "idle" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12, color: "var(--dim)", lineHeight: 1.5 } }, T.updPeerDaemon || "The peer version belongs to the running agentnet daemon, not to this app. Update it with:", /* @__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") }))), 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" && (() => {
4902
5118
  const m = /`([^`]+)`/.exec(err || "");
4903
5119
  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."));
4904
5120
  })(), /* @__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))));
@@ -5010,6 +5226,15 @@ function DkApp() {
5010
5226
  const T = STR[t.lang] || STR.en;
5011
5227
  const vars = dkTheme(t.theme, t.accent);
5012
5228
  const rowPad = t.density === "comfortable" ? "11px 12px" : "7px 10px";
5229
+ useIncomingAlerts({
5230
+ T,
5231
+ peers,
5232
+ requests,
5233
+ loaded: data.loaded,
5234
+ activeId,
5235
+ sound: t.alertSound !== false,
5236
+ flash: t.alertFlash !== false
5237
+ });
5013
5238
  const callCtl = useCallController(me.userId, (peerId, video, direction) => {
5014
5239
  const text = `WebRTC ${video ? "video" : "audio"} call: ${direction}`;
5015
5240
  dkApi.logLocal(peerId, direction === "outgoing" ? "out" : "in", text).then(() => {
@@ -5151,10 +5376,16 @@ function DkApp() {
5151
5376
  { id: "recommended", icon: "sparkles", label: T.recommended },
5152
5377
  { id: "registered", icon: "at", label: T.registered },
5153
5378
  { id: "network", icon: "network", label: T.network },
5154
- { id: "apps", icon: "grid", label: T.apps },
5155
- { id: "profile", icon: "userRound", label: T.profile }
5379
+ { id: "apps", icon: "grid", label: T.apps }
5156
5380
  ];
5157
- 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(
5381
+ 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("button", { onClick: () => setTab("profile"), title: T.profile, style: {
5382
+ padding: 4,
5383
+ borderRadius: 12,
5384
+ cursor: "pointer",
5385
+ display: "flex",
5386
+ border: "1px solid " + (tab === "profile" ? "var(--line)" : "transparent"),
5387
+ background: tab === "profile" ? "var(--panel-2)" : "transparent"
5388
+ } }, /* @__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: T.profile }).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(
5158
5389
  DkLockedOut,
5159
5390
  {
5160
5391
  compact: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/beagle-ui",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "The Beagle chat UI, minus the machine it runs on — shared by the desktop install and the browser build.",
5
5
  "license": "MIT",
6
6
  "type": "module",