@decentnetwork/lan 0.1.100 → 0.1.102

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.
Binary file
Binary file
Binary file
Binary file
@@ -942,11 +942,20 @@ function PeerRow({ peer, T, active, onClick }) {
942
942
  function PeerSidebar({ T, peers, requests, activeId, onSelect, onAct, onAdd }) {
943
943
  const [q, setQ] = React.useState("");
944
944
  const [addr, setAddr] = React.useState("");
945
+ const [addState, setAddState] = React.useState(null);
945
946
  const submitAddr = () => {
946
- if (addr.trim()) {
947
- onAdd(addr);
948
- setAddr("");
949
- }
947
+ const v = addr.trim();
948
+ if (!v || addState && addState.kind === "sending") return;
949
+ setAddState({ kind: "sending", msg: T.addSending });
950
+ Promise.resolve(onAdd(v)).then((r) => {
951
+ if (r && r.ok) {
952
+ setAddr("");
953
+ setAddState({ kind: "ok", msg: T.addSent });
954
+ } else {
955
+ setAddState({ kind: "err", msg: r && r.error ? `${T.addFailed}: ${r.error}` : T.addFailed });
956
+ }
957
+ setTimeout(() => setAddState((s) => s && s.kind !== "sending" ? null : s), 6e3);
958
+ });
950
959
  };
951
960
  const filtered = peers.filter((p) => {
952
961
  if (!q) return true;
@@ -956,7 +965,12 @@ function PeerSidebar({ T, peers, requests, activeId, onSelect, onAct, onAdd }) {
956
965
  const online = peers.filter((p) => p.online).length;
957
966
  return /* @__PURE__ */ React.createElement("div", { style: { width: 320, flexShrink: 0, borderRight: "1px solid var(--line)", display: "flex", flexDirection: "column", background: "var(--panel)" } }, /* @__PURE__ */ React.createElement("div", { style: { padding: "12px 12px 10px", borderBottom: "1px solid var(--line)", display: "flex", flexDirection: "column", gap: 8 } }, /* @__PURE__ */ React.createElement("div", { style: { display: "flex", gap: 7 } }, /* @__PURE__ */ React.createElement("input", { value: addr, onChange: (e) => setAddr(e.target.value), onKeyDown: (e) => {
958
967
  if (e.key === "Enter") submitAddr();
959
- }, placeholder: T.addPlaceholder, style: inputStyle }), /* @__PURE__ */ React.createElement(Btn, { tone: "solid", icon: "userPlus", onClick: submitAddr }, T.add)), /* @__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) })), !filtered.length && /* @__PURE__ */ React.createElement("div", { style: { padding: 16, textAlign: "center", fontFamily: "var(--mono)", fontSize: 12, color: "var(--faint)" } }, "no matches"))));
968
+ }, placeholder: T.addPlaceholder, style: inputStyle }), /* @__PURE__ */ React.createElement(Btn, { tone: "solid", icon: "userPlus", onClick: submitAddr }, T.add)), addState && /* @__PURE__ */ React.createElement("div", { style: {
969
+ fontFamily: "var(--mono)",
970
+ fontSize: 11.5,
971
+ lineHeight: 1.35,
972
+ color: addState.kind === "err" ? "var(--bad, #e5484d)" : addState.kind === "ok" ? "var(--good, #46a758)" : "var(--faint)"
973
+ } }, 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) })), !filtered.length && /* @__PURE__ */ React.createElement("div", { style: { padding: 16, textAlign: "center", fontFamily: "var(--mono)", fontSize: 12, color: "var(--faint)" } }, "no matches"))));
960
974
  }
961
975
  const inputStyle = {
962
976
  flex: 1,
@@ -1205,6 +1219,9 @@ const STR = {
1205
1219
  addPlaceholder: "paste a friend's carrier address\u2026",
1206
1220
  add: "Add",
1207
1221
  search: "search peers / ip\u2026",
1222
+ addSending: "sending friend-request\u2026",
1223
+ addSent: "friend-request sent \u2014 they appear once they accept",
1224
+ addFailed: "could not send",
1208
1225
  requests: "Friend requests",
1209
1226
  accept: "accept",
1210
1227
  reject: "reject",
@@ -1277,6 +1294,9 @@ const STR = {
1277
1294
  addPlaceholder: "\u7C98\u8D34\u597D\u53CB\u7684 carrier \u5730\u5740\u2026",
1278
1295
  add: "\u6DFB\u52A0",
1279
1296
  search: "\u641C\u7D22\u597D\u53CB / IP\u2026",
1297
+ addSending: "\u6B63\u5728\u53D1\u9001\u597D\u53CB\u8BF7\u6C42\u2026",
1298
+ addSent: "\u597D\u53CB\u8BF7\u6C42\u5DF2\u53D1\u9001 \u2014 \u5BF9\u65B9\u63A5\u53D7\u540E\u4F1A\u51FA\u73B0\u5728\u5217\u8868",
1299
+ addFailed: "\u53D1\u9001\u5931\u8D25",
1280
1300
  requests: "\u597D\u53CB\u8BF7\u6C42",
1281
1301
  accept: "\u63A5\u53D7",
1282
1302
  reject: "\u62D2\u7EDD",
@@ -1397,7 +1417,11 @@ function DkApp() {
1397
1417
  if (peer.id === activeId) setActiveId(null);
1398
1418
  };
1399
1419
  const onAdd = (address) => {
1400
- if (address && address.trim()) dkApi.add(address.trim()).then(data.refresh);
1420
+ if (!address || !address.trim()) return Promise.resolve({ ok: false, error: "empty address" });
1421
+ return dkApi.add(address.trim()).then((r) => {
1422
+ data.refresh();
1423
+ return r;
1424
+ });
1401
1425
  };
1402
1426
  const onSend = (text) => {
1403
1427
  if (!activeId || !text || !text.trim()) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/lan",
3
- "version": "0.1.100",
3
+ "version": "0.1.102",
4
4
  "description": "Private virtual LAN for self-hosted services and AI agents, built on Elastos Carrier. NAT-traversal, name service, ACL, all over a peer-to-peer mesh — no public IP required.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -79,7 +79,7 @@
79
79
  },
80
80
  "dependencies": {
81
81
  "@decentnetwork/dora": "^0.1.6",
82
- "@decentnetwork/peer": "^0.1.43",
82
+ "@decentnetwork/peer": "^0.1.45",
83
83
  "ink": "^5.2.1",
84
84
  "js-yaml": "^4.1.0",
85
85
  "react": "^18.3.1",