Design doc audit: update badges, fix outdated descriptions, add CDN/replication docs

Badge updates:
- BlobHeader: Planned → Complete (has receipt/comment slots, reactions, policy)
- LAN Discovery: Planned → Complete (iroh mDNS integration)
- UPnP TCP: Planned → Complete (both UDP+TCP renewal cycles)
- HTTP Post Delivery: added Complete badge

Description fixes:
- Share links: removed hostlist encoding, added tiered serving (redirect → punch → proxy)
- Eviction formula: added share_boost factor (+100 for 3+ downstream)
- Message types table: added ReplicationRequest/Response (0xE1/0xE2), count 41 → 49
- Engagement: added tombstone propagation description

New sections:
- Device roles & bandwidth budgets (Intermittent/Available/Persistent)
- Active CDN replication (10-min cycle, target prioritization, graceful degradation)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Scott Reimers 2026-03-21 00:20:47 -04:00
parent 075366e876
commit 3cc39590a7
4 changed files with 94 additions and 42 deletions

View file

@ -357,6 +357,8 @@ function toast(msg) {
// --- Notifications (Tauri plugin) ---
let _notifReady = false;
let _activeNotificationIds = new Set();
async function maybeNotify(title, body, tag) {
try {
if (window.__TAURI__?.notification) {
@ -367,16 +369,42 @@ async function maybeNotify(title, body, tag) {
granted = perm === 'granted';
}
if (granted) {
sendNotification({ title, body, channelId: 'default' });
sendNotification({ title, body, channelId: 'default', id: tag ? hashCode(tag) : undefined });
if (tag) _activeNotificationIds.add(tag);
}
} else if ('Notification' in window) {
// Fallback for browsers
if (Notification.permission === 'default') await Notification.requestPermission();
if (Notification.permission === 'granted') new Notification(title, { body, tag, silent: false });
}
} catch (_) {}
}
async function clearNotifications(tagPrefix) {
try {
if (window.__TAURI__?.notification) {
const { removeActive } = window.__TAURI__.notification;
if (!removeActive) return;
const toRemove = [..._activeNotificationIds].filter(t => t.startsWith(tagPrefix));
for (const tag of toRemove) {
try {
await removeActive({ notifications: [{ id: hashCode(tag) }] });
} catch (_) {}
_activeNotificationIds.delete(tag);
}
}
} catch (_) {}
}
function hashCode(str) {
let hash = 0;
for (let i = 0; i < str.length; i++) {
const ch = str.charCodeAt(i);
hash = ((hash << 5) - hash) + ch;
hash |= 0;
}
return Math.abs(hash);
}
// --- Popover helpers ---
let popoverOnClose = null;
function openPopover(title, html, opts = {}) {
@ -897,8 +925,9 @@ async function loadMessages(force) {
const input = $('#popover-reply-input');
if (input) setTimeout(() => input.focus(), 100);
// Mark conversation as read (DB-backed)
// Mark conversation as read (DB-backed) and clear notifications
invoke('mark_conversation_read', { partnerId }).catch(() => {});
clearNotifications(`msg-`);
// Mark incoming encrypted messages as "seen"
for (const p of threadPosts) {
@ -952,6 +981,7 @@ async function loadMessages(force) {
onClose() {
// Mark conversation as read when closing the popover
invoke('mark_conversation_read', { partnerId }).catch(() => {});
clearNotifications(`msg-`);
}
});
});
@ -2730,6 +2760,7 @@ document.querySelectorAll('.tab').forEach(tab => {
if (target === 'messages') {
if (!conversationsList.children.length) conversationsList.innerHTML = renderLoading();
loadMessages(true); loadDmRecipientOptions();
clearNotifications('msg-');
}
if (target === 'settings') { loadRedundancy(); loadPublicVisible(); loadCacheSizeSetting(); }
});