@decentnetwork/lan 0.1.88 → 0.1.89

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
@@ -13,6 +13,9 @@ export interface PeerManagerOptions {
13
13
  expressNodes?: BootstrapNode[];
14
14
  /** Use express only for friend-request bootstrap, never for data-plane sendText. */
15
15
  expressControlPlaneOnly?: boolean;
16
+ /** Display name advertised to friends (this node's name, so friend lists show
17
+ * "cn"/"tokyo"/"mac-dev" instead of the generic "@decentnetwork/peer"). */
18
+ nickname?: string;
16
19
  }
17
20
  export declare class PeerManager extends EventEmitter {
18
21
  private peer;
@@ -26,6 +26,7 @@ export class PeerManager extends EventEmitter {
26
26
  bootstrapNodes: opts.bootstrapNodes,
27
27
  expressNodes: opts.expressNodes,
28
28
  expressControlPlaneOnly: opts.expressControlPlaneOnly,
29
+ nickname: opts.nickname,
29
30
  // Register our IP channel (163) as the SDK's bulk-data stream so it
30
31
  // rides a single transport instead of fanning out over UDP + relay +
31
32
  // TCP relay (which delivered 3-4 duplicates of every IP packet).
package/dist/cli/index.js CHANGED
File without changes
@@ -181,6 +181,9 @@ export class DaemonServer {
181
181
  bootstrapNodes: this.config.carrier.bootstrapNodes,
182
182
  expressNodes: this.config.carrier.expressNodes ?? [],
183
183
  expressControlPlaneOnly: true,
184
+ // Advertise this node's name so friends see "cn"/"tokyo"/"mac-dev"
185
+ // instead of the generic "@decentnetwork/peer".
186
+ nickname: this.config.node.name,
184
187
  });
185
188
  await this.peerManager.start();
186
189
  this.logger.info(`Identity: ${this.peerManager.getAddress()}`);
@@ -235,10 +238,13 @@ export class DaemonServer {
235
238
  const uid = f.carrierId ?? f.pubkey ?? "";
236
239
  const meta = this.friendMeta?.get(uid);
237
240
  const lastMsg = last.get(uid);
241
+ // The build-default nickname is useless (every node sends it) —
242
+ // treat it as no-name so the UI falls back to alias/userid.
243
+ const realName = f.name && f.name !== "@decentnetwork/peer" ? f.name : undefined;
238
244
  return {
239
245
  userid: uid,
240
246
  alias: meta?.alias,
241
- name: meta?.alias || f.name || uid,
247
+ name: meta?.alias || realName || uid,
242
248
  status: f.status,
243
249
  lastSeen: f.lastSeen,
244
250
  pinned: meta?.pinned ?? false,
package/dist/ui/server.js CHANGED
@@ -262,19 +262,34 @@ async function refresh(){
262
262
  </div>\`).join('') : '<div class="empty">No pending requests.</div>';
263
263
  document.getElementById('friends').innerHTML = fr.length ? fr.map(f => {
264
264
  const uid = f.userid||f.carrierId;
265
- const nm = f.alias || f.name || short(uid);
265
+ const nm = friendName(f, uid);
266
266
  const lm = f.lastMessage;
267
267
  const preview = lm ? ((lm.dir==='out'?'You: ':'') + lm.text) : (f.status||'offline');
268
268
  const badge = f.unread ? '<span style="background:#e74c3c;color:#fff;border-radius:10px;padding:0 .45rem;font-size:.7rem;margin-left:.4rem">'+f.unread+'</span>' : '';
269
269
  return \`<div class="row" style="cursor:pointer" onclick="openChat('\${esc(uid)}')" title="open chat">
270
- <span class="dot \${esc(f.status||'offline')}"></span>
270
+ \${avatar(uid, nm, f.status)}
271
271
  <div class="meta"><div class="name">\${esc(nm)}\${badge}</div>
272
- <div class="sub">\${esc(preview)}</div></div>
272
+ <div class="sub"><span class="dot \${esc(f.status||'offline')}" style="display:inline-block;vertical-align:middle"></span> \${esc(preview)}</div></div>
273
273
  <button onclick="event.stopPropagation();editAlias('\${esc(uid)}')" title="rename" style="padding:.2rem .55rem">✎</button>
274
274
  <button class="reject" onclick="event.stopPropagation();delFriend('\${esc(uid)}')" title="remove friend" style="padding:.2rem .55rem">×</button>
275
275
  </div>\`;
276
276
  }).join('') : '<div class="empty">No friends yet.</div>';
277
277
  }
278
+ // The build default "@decentnetwork/peer" is useless (every node sends it) —
279
+ // treat it as no-name and fall back to alias / short userid.
280
+ function friendName(f, uid){
281
+ const n = f.alias || (f.name && f.name !== '@decentnetwork/peer' ? f.name : '');
282
+ return n || short(uid);
283
+ }
284
+ // Deterministic colored-initial avatar from the userid (no protocol/avatar
285
+ // exchange needed yet — same userid always gets the same color + letter).
286
+ function avatar(uid, nm, status){
287
+ const colors=['#e74c3c','#e67e22','#f39c12','#16a085','#27ae60','#2980b9','#8e44ad','#2c3e50','#d35400','#c0392b'];
288
+ let h=0; for(let i=0;i<String(uid).length;i++) h=(h*31+uid.charCodeAt(i))>>>0;
289
+ const c=colors[h%colors.length];
290
+ const ch=((nm||'?').trim().charAt(0)||'?').toUpperCase();
291
+ return '<span style="display:inline-flex;width:2rem;height:2rem;border-radius:50%;background:'+c+';color:#fff;align-items:center;justify-content:center;font-weight:700;flex:0 0 auto">'+esc(ch)+'</span>';
292
+ }
278
293
  function copyId(){ const id=(window.me&&(window.me.address||window.me.userid))||''; if(id&&navigator.clipboard){ navigator.clipboard.writeText(id); toast('Your address copied — share it so others can add you'); } }
279
294
  async function delFriend(uid){ if(!confirm('Remove this friend and your messages with them?')) return; const r=await api('/api/friend-remove',{userid:uid}); toast(r.ok?'Removed':(r.error||'failed')); if(chatWith===uid) closeChat(); refresh(); }
280
295
  async function editAlias(uid){ const cur=(window.friendsById[uid]||{}).alias||''; const a=prompt('Local name for this friend (empty to clear):', cur); if(a===null) return; const r=await api('/api/friend-alias',{userid:uid,alias:a}); toast(r.ok?'Saved':(r.error||'failed')); refresh(); }
@@ -286,7 +301,7 @@ let chatWith = null, chatTimer = null;
286
301
  async function openChat(userid){
287
302
  chatWith = userid;
288
303
  const f = window.friendsById[userid] || {};
289
- document.getElementById('chatName').textContent = f.alias || f.name || short(userid);
304
+ document.getElementById('chatName').textContent = friendName(f, userid);
290
305
  document.getElementById('chatSub').textContent = (f.status||'') + ' · ' + short(userid);
291
306
  document.getElementById('chat').style.display = 'block';
292
307
  api('/api/chat-mark-read', {userid}); // clears the unread badge
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/lan",
3
- "version": "0.1.88",
3
+ "version": "0.1.89",
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",
@@ -58,7 +58,7 @@
58
58
  "access": "public"
59
59
  },
60
60
  "scripts": {
61
- "build": "tsc -p tsconfig.json",
61
+ "build": "tsc -p tsconfig.json && chmod +x dist/cli/index.js",
62
62
  "build:helper": "cd helper/tun-helper && go build -o ../../bin/tun-helper-$(go env GOOS)-$(go env GOARCH) .",
63
63
  "build:helper:linux-amd64": "cd helper/tun-helper && GOOS=linux GOARCH=amd64 go build -o ../../bin/tun-helper-linux-amd64 .",
64
64
  "build:helper:linux-arm64": "cd helper/tun-helper && GOOS=linux GOARCH=arm64 go build -o ../../bin/tun-helper-linux-arm64 .",
@@ -77,7 +77,7 @@
77
77
  },
78
78
  "dependencies": {
79
79
  "@decentnetwork/dora": "^0.1.6",
80
- "@decentnetwork/peer": "^0.1.39",
80
+ "@decentnetwork/peer": "^0.1.40",
81
81
  "js-yaml": "^4.1.0",
82
82
  "yargs": "^17.7.2"
83
83
  },