v0.0.23: ETH display everywhere, local build, web UX fixes
Version: 0.0.22 → 0.0.23, SW cache wz-v3 → wz-v4 TUI: - Own messages show ETH address (0x...) instead of fingerprint - Received messages: async ETH cache lookup (resolve on first sight) - /info shows Identity + Fingerprint - Welcome message shows ETH address Web: - Header shows only ETH address (single element, click to copy) - Own messages show ETH format - Received messages resolve sender ETH via /v1/resolve/ - /peer 0x... resolves via /v1/resolve/ endpoint - Click messages area → focuses text input Client: - register_bundle sends eth_address to server - ETH↔fingerprint mapping stored on registration Build: - --local: build on current machine (auto-detect apt/dnf/pacman/brew) - --local-ship: build locally + deploy to all servers - --local-clean: build + clean cargo cache Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -50,7 +50,7 @@ async fn pwa_manifest() -> impl IntoResponse {
|
||||
|
||||
async fn service_worker() -> impl IntoResponse {
|
||||
([(header::CONTENT_TYPE, "application/javascript")], r##"
|
||||
const CACHE = 'wz-v3';
|
||||
const CACHE = 'wz-v4';
|
||||
const SHELL = ['/', '/wasm/warzone_wasm.js', '/wasm/warzone_wasm_bg.wasm', '/icon.svg', '/manifest.json'];
|
||||
|
||||
self.addEventListener('install', e => {
|
||||
@@ -209,8 +209,8 @@ const WEB_HTML: &str = r##"<!DOCTYPE html>
|
||||
<!-- Chat screen -->
|
||||
<div id="chat" class="screen">
|
||||
<div id="chat-header">
|
||||
<span class="tag tag-fp" id="hdr-fp"></span>
|
||||
<span class="tag" id="hdr-eth" style="background:#1a1a3e;color:#4fc3f7;font-size:0.8em;cursor:pointer" title=""></span>
|
||||
<span class="tag tag-fp" id="hdr-fp" style="cursor:pointer" title="Click to copy"></span>
|
||||
<span id="hdr-eth" style="display:none"></span>
|
||||
<span>→</span>
|
||||
<input id="peer-input" placeholder="Paste peer fingerprint..." autocomplete="off">
|
||||
<span class="tag-server" id="hdr-server"></span>
|
||||
@@ -242,7 +242,7 @@ let pollTimer = null;
|
||||
let ws = null; // WebSocket connection
|
||||
let wasmReady = false;
|
||||
|
||||
const VERSION = '0.0.22';
|
||||
const VERSION = '0.0.23';
|
||||
let DEBUG = true; // toggle with /debug command
|
||||
|
||||
// ── Receipt tracking ──
|
||||
@@ -616,13 +616,16 @@ async function handleIncomingMessage(bytes) {
|
||||
|
||||
let fromLabel = result.sender.slice(0, 19);
|
||||
try {
|
||||
const ar = await fetch(SERVER + '/v1/alias/whois/' + senderFP);
|
||||
const ar = await fetch(SERVER + '/v1/resolve/' + senderFP);
|
||||
const ad = await ar.json();
|
||||
if (ad.alias) fromLabel = '@' + ad.alias;
|
||||
if (ad.eth_address) fromLabel = ad.eth_address.slice(0, 12) + '...';
|
||||
// Alias overrides ETH
|
||||
const aw = await fetch(SERVER + '/v1/alias/whois/' + senderFP);
|
||||
const adata = await aw.json();
|
||||
if (adata.alias) fromLabel = '@' + adata.alias;
|
||||
} catch(e) {}
|
||||
|
||||
addMsg(fromLabel, result.text, false);
|
||||
// Send delivery receipt
|
||||
if (result.message_id) sendReceipt(result.sender, result.message_id, 'delivered');
|
||||
lastDmPeer = normFP(result.sender);
|
||||
return;
|
||||
@@ -653,13 +656,16 @@ async function handleIncomingMessage(bytes) {
|
||||
|
||||
let fromLabel = result.sender.slice(0, 19);
|
||||
try {
|
||||
const ar = await fetch(SERVER + '/v1/alias/whois/' + normFP(result.sender));
|
||||
const rfp = normFP(result.sender);
|
||||
const ar = await fetch(SERVER + '/v1/resolve/' + rfp);
|
||||
const ad = await ar.json();
|
||||
if (ad.alias) fromLabel = '@' + ad.alias;
|
||||
if (ad.eth_address) fromLabel = ad.eth_address.slice(0, 12) + '...';
|
||||
const aw = await fetch(SERVER + '/v1/alias/whois/' + rfp);
|
||||
const adata = await aw.json();
|
||||
if (adata.alias) fromLabel = '@' + adata.alias;
|
||||
} catch(e2) {}
|
||||
|
||||
addMsg(fromLabel, result.text, false);
|
||||
// Send delivery receipt
|
||||
if (result.message_id) sendReceipt(result.sender, result.message_id, 'delivered');
|
||||
lastDmPeer = normFP(result.sender);
|
||||
return;
|
||||
@@ -859,18 +865,21 @@ let pendingFiles = {}; // file_id -> { filename, chunks: [], total, received,
|
||||
async function enterChat() {
|
||||
document.getElementById('setup').classList.remove('active');
|
||||
document.getElementById('chat').classList.add('active');
|
||||
document.getElementById('hdr-fp').textContent = myFingerprint.slice(0, 19);
|
||||
document.getElementById('hdr-server').textContent = SERVER;
|
||||
|
||||
await registerKey();
|
||||
addSys('Identity: ' + myEthAddress);
|
||||
addSys('Fingerprint: ' + myFingerprint);
|
||||
addSys('Key registered with server');
|
||||
|
||||
// Show ETH in header, fallback to fingerprint
|
||||
const hdrFp = document.getElementById('hdr-fp');
|
||||
if (myEthAddress) {
|
||||
document.getElementById('hdr-eth').textContent = myEthAddress.slice(0, 10) + '...';
|
||||
document.getElementById('hdr-eth').title = myEthAddress;
|
||||
hdrFp.textContent = myEthAddress.slice(0, 12) + '...';
|
||||
hdrFp.title = myEthAddress;
|
||||
hdrFp.onclick = function() { navigator.clipboard.writeText(myEthAddress); addSys('Copied: ' + myEthAddress); };
|
||||
} else {
|
||||
hdrFp.textContent = (myEthAddress ? myEthAddress.slice(0,12) + '...' : myFingerprint.slice(0,19));
|
||||
hdrFp.title = myFingerprint;
|
||||
}
|
||||
addSys('Identity: ' + (myEthAddress || myFingerprint));
|
||||
addSys('Key registered with server');
|
||||
|
||||
addSys('v' + VERSION + ' | DM: paste peer fingerprint or @alias above');
|
||||
addSys('/alias · /g · /gleave · /gkick · /gmembers · /glist · /friend · /file · /info');
|
||||
@@ -986,7 +995,7 @@ async function sendToGroup(groupName, text) {
|
||||
body: JSON.stringify({ from: myFP, messages })
|
||||
});
|
||||
|
||||
addMsg(myFingerprint.slice(0, 19) + ' [' + groupName + ']', text, true, null);
|
||||
addMsg((myEthAddress ? myEthAddress.slice(0,12) + '...' : myFingerprint.slice(0,19)) + ' [' + groupName + ']', text, true, null);
|
||||
}
|
||||
|
||||
// ── Send handler ──
|
||||
@@ -1092,18 +1101,19 @@ async function doSend() {
|
||||
$peerInput.value = lastDmPeer;
|
||||
try {
|
||||
await sendEncrypted(lastDmPeer, replyText.trim());
|
||||
addMsg(myFingerprint.slice(0, 19), replyText.trim(), true);
|
||||
addMsg((myEthAddress ? myEthAddress.slice(0,12) + '...' : myFingerprint.slice(0,19)), replyText.trim(), true);
|
||||
} catch(e) { addSys('Reply failed: ' + e.message); }
|
||||
return;
|
||||
}
|
||||
if (text.startsWith('/p ') || text.startsWith('/peer ')) {
|
||||
let val = text.startsWith('/p ') ? text.slice(3).trim() : text.slice(6).trim();
|
||||
if (val.startsWith('@')) {
|
||||
const resp = await fetch(SERVER + '/v1/alias/resolve/' + val.slice(1));
|
||||
if (val.startsWith('@') || val.startsWith('0x') || val.startsWith('0X')) {
|
||||
const endpoint = val.startsWith('@') ? '/v1/alias/resolve/' + val.slice(1) : '/v1/resolve/' + val;
|
||||
const resp = await fetch(SERVER + endpoint);
|
||||
const data = await resp.json();
|
||||
if (data.error) { addSys('Unknown alias ' + val); return; }
|
||||
if (data.error) { addSys('Cannot resolve ' + val + ': ' + data.error); return; }
|
||||
$peerInput.value = data.fingerprint;
|
||||
addSys(val + ' → ' + data.fingerprint.slice(0,16) + '...');
|
||||
addSys(val + ' \u2192 ' + data.fingerprint.slice(0,16) + '...');
|
||||
} else {
|
||||
$peerInput.value = val;
|
||||
}
|
||||
@@ -1197,7 +1207,7 @@ async function doSend() {
|
||||
try {
|
||||
const msgId = await sendEncrypted(peer, text);
|
||||
sentMsgReceipts[msgId] = { status: 'sent', el: null };
|
||||
addMsg(myFingerprint.slice(0, 19), text, true, msgId);
|
||||
addMsg((myEthAddress ? myEthAddress.slice(0,12) + '...' : myFingerprint.slice(0,19)), text, true, msgId);
|
||||
} catch(e) {
|
||||
addSys('Send failed: ' + e.message);
|
||||
}
|
||||
@@ -1218,6 +1228,7 @@ document.getElementById('btn-show-recover').onclick = () => document.getElementB
|
||||
document.getElementById('btn-recover').onclick = () => doRecover();
|
||||
document.getElementById('btn-enter').onclick = () => enterChat();
|
||||
document.getElementById('send-btn').onclick = () => doSend();
|
||||
document.getElementById('messages').onclick = () => document.getElementById('msg-input').focus();
|
||||
document.getElementById('hdr-eth').onclick = function() {
|
||||
if (myEthAddress) navigator.clipboard.writeText(myEthAddress).then(() => addSys('Copied ETH address'));
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user