@decentnetwork/beagle 0.1.99 → 0.1.101

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.
@@ -1,4 +1,4 @@
1
- window.__DK_UI_VERSION="0.1.99";
1
+ window.__DK_UI_VERSION="0.1.101";
2
2
  "use strict";
3
3
  (() => {
4
4
  // packages/beagle-ui/dist/beagle-ui.js
@@ -2169,9 +2169,9 @@ ${peer.address}`
2169
2169
  pill("peer", me.peerVer, true)
2170
2170
  ]), !embedded && unsure && /* @__PURE__ */ React.createElement("div", { style: { fontSize: 11, color: "var(--faint)", fontFamily: "var(--ui)" } }, T.verInstalledHint), line(T.verChannel || "channel", [/* @__PURE__ */ React.createElement("span", { key: "ch" }, me.channel)])));
2171
2171
  }
2172
- function DkQrModal({ T, value, label, onClose }) {
2172
+ function DkQr({ value, px = 248 }) {
2173
2173
  const qr = React.useMemo(() => {
2174
- if (typeof qrcode === "undefined")
2174
+ if (typeof qrcode === "undefined" || !value)
2175
2175
  return null;
2176
2176
  try {
2177
2177
  const q = qrcode(0, "M");
@@ -2182,15 +2182,36 @@ ${peer.address}`
2182
2182
  return null;
2183
2183
  }
2184
2184
  }, [value]);
2185
- const count = qr ? qr.getModuleCount() : 0;
2185
+ if (!qr)
2186
+ return /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--mono)", fontSize: 12, color: "var(--faint)", padding: 48 } }, "QR unavailable");
2187
+ const count = qr.getModuleCount();
2186
2188
  const quiet = 4;
2187
2189
  const total = count + quiet * 2;
2188
- const px = 248;
2189
- return /* @__PURE__ */ React.createElement("div", { onClick: onClose, style: { position: "fixed", inset: 0, zIndex: 90, background: "color-mix(in oklab, #000, transparent 38%)", display: "flex", alignItems: "center", justifyContent: "center", padding: 24 } }, /* @__PURE__ */ React.createElement("div", { onClick: (e) => e.stopPropagation(), style: { background: "var(--panel)", border: "1px solid var(--line)", borderRadius: 16, padding: 22, display: "flex", flexDirection: "column", alignItems: "center", gap: 16, maxWidth: 340 } }, /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 10, alignSelf: "stretch" } }, /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 11.5, fontWeight: 700, letterSpacing: 0.5, textTransform: "uppercase", color: "var(--faint)" } }, label), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }), /* @__PURE__ */ React.createElement(Btn, { icon: "x", size: "sm", onClick: onClose })), qr ? /* @__PURE__ */ React.createElement("svg", { width: px, height: px, viewBox: `0 0 ${total} ${total}`, shapeRendering: "crispEdges", style: { display: "block", borderRadius: 10, background: "#fff" } }, /* @__PURE__ */ React.createElement("rect", { width: total, height: total, fill: "#fff" }), Array.from({ length: count }).map(
2190
+ return /* @__PURE__ */ React.createElement("svg", { width: px, height: px, viewBox: `0 0 ${total} ${total}`, shapeRendering: "crispEdges", style: { display: "block", borderRadius: 10, background: "#fff", maxWidth: "100%", height: "auto" } }, /* @__PURE__ */ React.createElement("rect", { width: total, height: total, fill: "#fff" }), Array.from({ length: count }).map(
2190
2191
  (_, r) => Array.from({ length: count }).map(
2191
2192
  (__, c) => qr.isDark(r, c) ? /* @__PURE__ */ React.createElement("rect", { key: `${r}-${c}`, x: c + quiet, y: r + quiet, width: 1.04, height: 1.04, fill: "#000" }) : null
2192
2193
  )
2193
- )) : /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--mono)", fontSize: 12, color: "var(--faint)", padding: 48 } }, "QR unavailable"), /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--mono)", fontSize: 11, color: "var(--dim)", wordBreak: "break-all", textAlign: "center", maxWidth: 280, lineHeight: 1.5 } }, value), /* @__PURE__ */ React.createElement(CopyBtn, { value, copiedText: T.copied, copyFailedText: T.copyFailed, copyTitle: T.copy })));
2194
+ ));
2195
+ }
2196
+ function DkQrModal({ T, value, label, onClose }) {
2197
+ return /* @__PURE__ */ React.createElement("div", { onClick: onClose, style: { position: "fixed", inset: 0, zIndex: 90, background: "color-mix(in oklab, #000, transparent 38%)", display: "flex", alignItems: "center", justifyContent: "center", padding: 24 } }, /* @__PURE__ */ React.createElement("div", { onClick: (e) => e.stopPropagation(), style: { background: "var(--panel)", border: "1px solid var(--line)", borderRadius: 16, padding: 22, display: "flex", flexDirection: "column", alignItems: "center", gap: 16, maxWidth: 340 } }, /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 10, alignSelf: "stretch" } }, /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 11.5, fontWeight: 700, letterSpacing: 0.5, textTransform: "uppercase", color: "var(--faint)" } }, label), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }), /* @__PURE__ */ React.createElement(Btn, { icon: "x", size: "sm", onClick: onClose })), /* @__PURE__ */ React.createElement(DkQr, { value }), /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--mono)", fontSize: 11, color: "var(--dim)", wordBreak: "break-all", textAlign: "center", maxWidth: 280, lineHeight: 1.5 } }, value), /* @__PURE__ */ React.createElement(CopyBtn, { value, copiedText: T.copied, copyFailedText: T.copyFailed, copyTitle: T.copy })));
2198
+ }
2199
+ function dkShareLink(me) {
2200
+ const ens = String(me && me.ens || "").trim();
2201
+ const slug = ens ? ens.replace(/\.beagles\.eth$/i, "") : String(me && me.carrier || "");
2202
+ return slug ? "https://app.beagle.chat/" + encodeURIComponent(slug) : "";
2203
+ }
2204
+ function DkShareSheet({ T, me, zh, onClose }) {
2205
+ const link = dkShareLink(me);
2206
+ const [copied, setCopied] = React.useState(false);
2207
+ const copy = () => dkCopy(link).then(() => {
2208
+ setCopied(true);
2209
+ setTimeout(() => setCopied(false), 1500);
2210
+ });
2211
+ const canShare = typeof navigator !== "undefined" && !!navigator.share;
2212
+ const share = () => navigator.share({ title: (me.name || "Beagle") + " \xB7 Beagle", text: zh ? "\u5728 Beagle \u4E0A\u52A0\u6211\u4E3A\u597D\u53CB" : "Add me on Beagle", url: link }).catch(() => {
2213
+ });
2214
+ return /* @__PURE__ */ React.createElement("div", { onClick: onClose, style: { position: "fixed", inset: 0, zIndex: 90, background: "color-mix(in oklab, #000, transparent 38%)", display: "flex", alignItems: "center", justifyContent: "center", padding: 16 } }, /* @__PURE__ */ React.createElement("div", { onClick: (e) => e.stopPropagation(), style: { width: 360, maxWidth: "100%", background: "var(--panel)", border: "1px solid var(--line)", borderRadius: 16, padding: 18, display: "flex", flexDirection: "column", alignItems: "center", gap: 14 } }, /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 10, alignSelf: "stretch" } }, /* @__PURE__ */ React.createElement(DkAvatar, { peer: { ...me, id: me.userId, agent: false }, size: 34, radius: 9, dot: false }), /* @__PURE__ */ React.createElement("div", { style: { flex: 1, minWidth: 0 } }, /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--mono)", fontSize: 13.5, fontWeight: 700, color: "var(--text)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } }, zh ? "\u5206\u4EAB\u6211\u7684\u94FE\u63A5" : "Share my link"), /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 11.5, color: "var(--faint)" } }, zh ? "\u5BF9\u65B9\u6253\u5F00\u5373\u53EF\u52A0\u4F60\u4E3A\u597D\u53CB" : "Anyone who opens it can add you")), /* @__PURE__ */ React.createElement(Btn, { icon: "x", size: "sm", onClick: onClose })), link ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(DkQr, { value: link, px: 220 }), /* @__PURE__ */ React.createElement("div", { style: { alignSelf: "stretch", fontFamily: "var(--mono)", fontSize: 12, color: "var(--text)", wordBreak: "break-all", textAlign: "center", lineHeight: 1.5, padding: "8px 10px", borderRadius: 8, background: "var(--panel-2)", border: "1px solid var(--line)" } }, link), /* @__PURE__ */ React.createElement("div", { style: { display: "flex", gap: 8, alignSelf: "stretch" } }, /* @__PURE__ */ React.createElement(Btn, { tone: "solid", icon: copied ? "check" : "copy", size: "lg", onClick: copy, style: { flex: 1 } }, copied ? zh ? "\u5DF2\u590D\u5236" : "Copied" : zh ? "\u590D\u5236\u94FE\u63A5" : "Copy link"), canShare && /* @__PURE__ */ React.createElement(Btn, { icon: "share", size: "lg", onClick: share, style: { flex: 1 } }, zh ? "\u5206\u4EAB" : "Share"))) : /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12.5, color: "var(--faint)", padding: 24 } }, zh ? "\u8EAB\u4EFD\u8FD8\u6CA1\u51C6\u5907\u597D" : "Your identity is not ready yet.")));
2194
2215
  }
2195
2216
  function Card({ label, children, trailing }) {
2196
2217
  return /* @__PURE__ */ React.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 10 } }, /* @__PURE__ */ React.createElement(Section, { label, trailing }), /* @__PURE__ */ React.createElement("div", { style: { borderRadius: 11, border: "1px solid var(--line)", overflow: "hidden", background: "var(--panel)" } }, children));
@@ -2907,7 +2928,7 @@ ${peer.address}`
2907
2928
  setEditing(false);
2908
2929
  } }));
2909
2930
  }
2910
- Object.assign(window, { ProfileTab, DkPunkAvatar, DkEnsAvatar, DkPublicProfile });
2931
+ Object.assign(window, { DkShareSheet, ProfileTab, DkPunkAvatar, DkEnsAvatar, DkPublicProfile });
2911
2932
  var DK_PHONE_MQ = "(max-width: 700px)";
2912
2933
  function useIsPhone() {
2913
2934
  const mq = React.useMemo(() => typeof window !== "undefined" && window.matchMedia ? window.matchMedia(DK_PHONE_MQ) : null, []);
@@ -5450,6 +5471,17 @@ ${peer.address}`
5450
5471
  });
5451
5472
  });
5452
5473
  const phone = useIsPhone();
5474
+ const [sharing, setSharing] = React.useState(false);
5475
+ const shareBtn = /* @__PURE__ */ React.createElement(
5476
+ "button",
5477
+ {
5478
+ onClick: () => setSharing(true),
5479
+ title: t.lang === "zh" ? "\u5206\u4EAB\u6211\u7684\u94FE\u63A5" : "Share my link",
5480
+ "aria-label": "share",
5481
+ style: { width: 32, height: 32, flexShrink: 0, borderRadius: 8, border: "1px solid var(--line)", background: "transparent", cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center", padding: 0 }
5482
+ },
5483
+ /* @__PURE__ */ React.createElement(Icon, { name: "share", size: 16, stroke: 2, color: "var(--accent)" })
5484
+ );
5453
5485
  React.useEffect(() => {
5454
5486
  if (!phone && !activeId && peers.length)
5455
5487
  setActiveId(peers[0].id);
@@ -5616,7 +5648,7 @@ ${peer.address}`
5616
5648
  display: "flex",
5617
5649
  border: "1px solid " + (tab === "profile" ? "var(--line)" : "transparent"),
5618
5650
  background: tab === "profile" ? "var(--panel-2)" : "transparent"
5619
- } }, /* @__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("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 }), /* @__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)" } }), /* @__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: {
5651
+ } }, /* @__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("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: {
5620
5652
  display: "inline-flex",
5621
5653
  alignItems: "center",
5622
5654
  gap: 6,
@@ -5664,7 +5696,7 @@ ${peer.address}`
5664
5696
  setWelcomeDone(true);
5665
5697
  }
5666
5698
  }
5667
- ), /* @__PURE__ */ React.createElement(IncomingCallModal, { T, ctl: callCtl, peers }), /* @__PURE__ */ React.createElement(CallOverlay, { T, ctl: callCtl, peers }), /* @__PURE__ */ React.createElement(RtcFileInbox, { T, peers, ctl: rtcFileCtl }), upd && /* @__PURE__ */ React.createElement(
5699
+ ), sharing && /* @__PURE__ */ React.createElement(DkShareSheet, { T, me, zh: t.lang === "zh", onClose: () => setSharing(false) }), /* @__PURE__ */ React.createElement(IncomingCallModal, { T, ctl: callCtl, peers }), /* @__PURE__ */ React.createElement(CallOverlay, { T, ctl: callCtl, peers }), /* @__PURE__ */ React.createElement(RtcFileInbox, { T, peers, ctl: rtcFileCtl }), upd && /* @__PURE__ */ React.createElement(
5668
5700
  DkUpdateModal,
5669
5701
  {
5670
5702
  T,
package/dist/server.js CHANGED
@@ -2038,6 +2038,8 @@ export function startBeagleServer(opts) {
2038
2038
  // toggle rather than showing a state it cannot know.
2039
2039
  autoAccept: typeof node.autoAccept === "boolean" ? node.autoAccept : null,
2040
2040
  avatarUrl: ensPub.get(identity.userid ?? "")?.avatarUrl ?? null,
2041
+ // My beagles.eth name, for the share link (app.beagle.chat/<name>).
2042
+ ens: ensPub.get(identity.userid ?? "")?.ens ?? "",
2041
2043
  punkId: myPunk ?? node.punkId ?? null,
2042
2044
  // The UI compares this against its baked-in __DK_UI_VERSION and
2043
2045
  // reloads itself when they differ — an open tab otherwise runs a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/beagle",
3
- "version": "0.1.99",
3
+ "version": "0.1.101",
4
4
  "description": "Beagle — P2P chat, file transfer and calls for regular users, on the Decent Network. No admin privilege required.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -28,14 +28,14 @@
28
28
  "dependencies": {
29
29
  "@decentnetwork/chat-components": "^0.1.3",
30
30
  "@decentnetwork/lan": "^0.1.283",
31
- "@decentnetwork/peer": "^0.1.164",
31
+ "@decentnetwork/peer": "^0.1.166",
32
32
  "@decentnetwork/peer-webrtc": "^0.2.16",
33
33
  "js-yaml": "^4.1.0",
34
34
  "ws": "^8.21.1",
35
35
  "yargs": "^17.7.2"
36
36
  },
37
37
  "devDependencies": {
38
- "@decentnetwork/beagle-ui": "^0.2.15",
38
+ "@decentnetwork/beagle-ui": "^0.2.16",
39
39
  "@types/js-yaml": "^4.0.9",
40
40
  "@types/node": "^20.11.0",
41
41
  "@types/yargs": "^17.0.32",