ua-labels: derive source from User-Agent, persist peerID in localStorage

Server now parses the User-Agent header on /api/send when no explicit
source is provided, producing labels like 'iphone-safari',
'macos-chrome', 'windows-firefox' so the feed shows where messages
came from at a glance.

Browser-side peerID is now stored in localStorage instead of being
freshly random on each page load — refreshing or reopening the tab
keeps the same identity for the same browser profile.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Claude Opus 4.7
2026-05-21 01:19:14 -05:00
parent 618d330682
commit 625143f87a
4 changed files with 46 additions and 4 deletions

View File

@@ -151,7 +151,12 @@
if (!roomMatch) { window.location.replace("/"); }
const room = roomMatch ? roomMatch[1] : "";
const fullUrl = window.location.origin + "/r/" + room;
const peerID = "browser-" + Array.from(crypto.getRandomValues(new Uint8Array(6))).map(b=>b.toString(16).padStart(2,"0")).join("");
// Stable per-device id — persists across reloads (unless cleared).
let peerID = localStorage.getItem("tether-peerID");
if (!peerID) {
peerID = "browser-" + Array.from(crypto.getRandomValues(new Uint8Array(6))).map(b=>b.toString(16).padStart(2,"0")).join("");
localStorage.setItem("tether-peerID", peerID);
}
$("roomTag").textContent = room;
$("sessionUrl").textContent = fullUrl;
@@ -218,16 +223,16 @@
const r = await fetch("/api/send?room=" + room, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ type: "clipboard", text, source: "web", from: peerID, room }),
body: JSON.stringify({ type: "clipboard", text, from: peerID, room }),
});
status(r.ok ? "delivered ✓" : "server returned " + r.status, r.ok ? "ok" : "err");
} catch (e) { status("network error", "err"); }
});
// ── Signaling ─────────────────────────────────────────────────────────
// Let the server fill in source from User-Agent unless caller specifies.
async function postMessage(m) {
m.from = m.from || peerID;
m.source = m.source || "web";
m.room = room;
await fetch("/api/send?room=" + room, {
method: "POST",