a demonstration replicated social networking web app built with anproto wiredove.net/
social ed25519 protocols
at master 84 lines 2.4 kB view raw
1import { normalizeTimestamp } from './utils.js' 2 3const timestampInsertState = new WeakMap() 4 5const buildTimestampState = (container) => { 6 const entries = [] 7 const children = Array.from(container.children) 8 for (const child of children) { 9 if (!child || !child.dataset) { continue } 10 const childTs = normalizeTimestamp(child.dataset.ts) 11 if (!childTs) { continue } 12 entries.push({ ts: childTs, node: child }) 13 } 14 entries.sort((a, b) => b.ts - a.ts) 15 return { 16 entries, 17 childCount: children.length 18 } 19} 20 21const getTimestampState = (container) => { 22 const existing = timestampInsertState.get(container) 23 const currentChildCount = container.children.length 24 if (existing && existing.childCount === currentChildCount) { 25 return existing 26 } 27 const next = buildTimestampState(container) 28 timestampInsertState.set(container, next) 29 return next 30} 31 32const findInsertIndex = (entries, stamp) => { 33 let lo = 0 34 let hi = entries.length 35 while (lo < hi) { 36 const mid = Math.floor((lo + hi) / 2) 37 if (entries[mid].ts >= stamp) { 38 lo = mid + 1 39 } else { 40 hi = mid 41 } 42 } 43 return lo 44} 45 46const removeEntryForNode = (entries, node) => { 47 const idx = entries.findIndex((entry) => entry.node === node) 48 if (idx >= 0) { 49 entries.splice(idx, 1) 50 } 51} 52 53export const insertByTimestamp = (container, hash, ts, hashFn) => { 54 if (!container || !hash) { return null } 55 const stamp = normalizeTimestamp(ts) 56 if (!stamp) { return null } 57 const state = getTimestampState(container) 58 const entries = state.entries 59 let div = document.getElementById(hash) 60 if (!div) { 61 div = hashFn(hash) 62 } 63 if (!div) { return null } 64 div.dataset.ts = stamp.toString() 65 if (div.parentNode === container) { 66 removeEntryForNode(entries, div) 67 container.removeChild(div) 68 } 69 const insertIdx = findInsertIndex(entries, stamp) 70 const beforeNode = insertIdx < entries.length ? entries[insertIdx].node : null 71 if (beforeNode && beforeNode.parentNode === container) { 72 container.insertBefore(div, beforeNode) 73 } else { 74 const sentinel = container.querySelector('.scroll-sentinel') 75 if (sentinel && sentinel.parentNode === container) { 76 container.insertBefore(div, sentinel) 77 } else { 78 container.appendChild(div) 79 } 80 } 81 entries.splice(insertIdx, 0, { ts: stamp, node: div }) 82 state.childCount = container.children.length 83 return div 84}