Changeset 5412cbb in Klonkt for src/assets
- Timestamp:
- 08/12/2026 08:38:08 PM (3 months ago)
- Children:
- 2086ea2
- Parents:
- 4bb93aa
- Location:
- src/assets
- Files:
-
- 3 edited
-
css/ward.css (modified) (1 diff)
-
js/ward-sky.js (modified) (3 diffs)
-
js/ward.js (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/assets/css/ward.css
r4bb93aa r5412cbb 150 150 .wave-answers button { border: 0; border-radius: 10px; padding: 12px; background: var(--accent); color: #fff; font: inherit; font-weight: 600; } 151 151 #wave-cancel { margin-top: 10px; border: 0; background: none; color: var(--dim); font: inherit; } 152 153 /* ── De vriendenkiezer achter de (+) ──────────────────────────────────── */ 154 dialog#friends-dialog { 155 border: 0; border-radius: 16px; padding: 18px; max-width: 380px; width: calc(100% - 48px); 156 max-height: 70vh; overflow-y: auto; 157 background: var(--card); color: var(--ink); 158 } 159 dialog#friends-dialog::backdrop { background: rgba(0,0,0,.4); } 160 dialog#friends-dialog h2 { margin: 0 0 12px; font-size: 1.05rem; } 161 .friend button.row { 162 width: 100%; display: flex; align-items: center; gap: 10px; text-align: left; 163 border: 0; background: none; color: var(--ink); padding: 4px 2px; font: inherit; cursor: pointer; 164 } 165 .friend .avatar { width: 36px; height: 36px; border-radius: 50%; object-fit: cover; } 166 .friend .wie { display: flex; flex-direction: column; } 167 #friends-cancel { margin-top: 12px; border: 0; background: none; color: var(--dim); font: inherit; } -
src/assets/js/ward-sky.js
r4bb93aa r5412cbb 152 152 * @param {(index:number)=>void} onPick een gezicht aangetikt 153 153 */ 154 constructor(canvas, onPick ) {154 constructor(canvas, onPick, onNew) { 155 155 this.canvas = canvas; 156 156 this.g = canvas.getContext('2d'); 157 157 this.onPick = onPick; 158 // De (+) in het midden: de deur naar iemand NIEUW. Hij zit op de 159 // OORSPRONG van het veld en pant en zoomt met de gezichten mee, zodat hij 160 // altijd het midden van de vliegende avatars is, waar de hemel ook heen 161 // drijft. De plaatsing houdt daar bewust ruimte vrij (elk gezicht hangt 162 // minstens 1.4 cel naar buiten). 163 this.onNew = onNew; 158 164 this.faces = []; 159 165 this.spots = []; … … 211 217 const s = Math.min(Math.max(this.scale, 0.5), 1.6); 212 218 const draw = FACE * s; 219 220 // De (+) eerst, dan de gezichten eroverheen als het krap wordt. 221 if (this.interactive && this.onNew) { 222 const px = cx + this.panX; 223 const py = cy + this.panY; 224 const pr = 22 * s; 225 g.beginPath(); g.arc(px, py, pr, 0, Math.PI * 2); 226 g.fillStyle = 'rgba(255,255,255,0.92)'; g.fill(); 227 g.strokeStyle = '#11131a'; g.lineWidth = Math.max(2, 3 * s); g.lineCap = 'round'; 228 g.beginPath(); 229 g.moveTo(px - pr * 0.45, py); g.lineTo(px + pr * 0.45, py); 230 g.moveTo(px, py - pr * 0.45); g.lineTo(px, py + pr * 0.45); 231 g.stroke(); 232 } 213 233 214 234 for (let i = 0; i < this.spots.length; i++) { … … 248 268 if (moved < 6) { 249 269 const r = c.getBoundingClientRect(); 250 const hit = nearestFace(e.clientX - r.left, e.clientY - r.top, this.spots, { 270 const x = e.clientX - r.left; 271 const y = e.clientY - r.top; 272 const hit = nearestFace(x, y, this.spots, { 251 273 cx: this.w / 2, cy: this.h / 2, cell: CELL, scale: this.scale, 252 274 panX: this.panX, panY: this.panY, 253 275 }); 254 if (hit != null) this.onPick?.(hit); 276 if (hit != null) { this.onPick?.(hit); return; } 277 // Geen gezicht? Dan misschien de (+): zelfde middelpunt als getekend, 278 // met een raakzone die meeschaalt zodat mikken bij elke zoom klopt. 279 const s2 = Math.min(Math.max(this.scale, 0.5), 1.6); 280 const d = Math.hypot(x - (this.w / 2 + this.panX), y - (this.h / 2 + this.panY)); 281 if (d <= 26 * s2) this.onNew?.(); 255 282 } 256 283 }; -
src/assets/js/ward.js
r4bb93aa r5412cbb 232 232 const c = convs[i]; 233 233 if (c) openThread(c); 234 }); 234 }, () => openFriendsPicker()); 235 236 /* ── De (+): de deur naar iemand nieuw ───────────────────────────────── 237 De hemel toont alleen met wie je al sprak; de kiezer toont iedereen met 238 een volgrelatie. Kies iemand en het lege gesprek opent gewoon: het 239 eerste bericht maakt het echt. */ 240 const friendsDlg = document.getElementById('friends-dialog'); 241 async function openFriendsPicker() { 242 const list = document.getElementById('friends-list'); 243 list.replaceChildren(); 244 friendsDlg.showModal(); 245 try { 246 const r = await fetch('/ward/api/friends', { headers: { Accept: 'application/json' } }); 247 const items = r.ok ? (await r.json()).items || [] : []; 248 document.getElementById('friends-empty').hidden = items.length > 0; 249 items.forEach((f) => { 250 const li = el('li', 'card friend'); 251 const row = el('button', 'row'); 252 row.type = 'button'; 253 if (f.icon) { 254 const img = el('img', 'avatar'); 255 img.src = f.icon; img.alt = ''; img.loading = 'lazy'; 256 row.append(img); 257 } 258 const kolom = el('span', 'wie'); 259 kolom.append(el('span', 'name', f.name), el('span', 'hint', f.handle)); 260 row.append(kolom); 261 row.addEventListener('click', () => { 262 friendsDlg.close(); 263 openThread({ uri: f.uri, name: f.name, icon: f.icon }); 264 }); 265 li.append(row); 266 list.append(li); 267 }); 268 } catch { /* de kiezer blijft leeg staan; annuleren kan altijd */ } 269 } 270 document.getElementById('friends-cancel').addEventListener('click', () => friendsDlg.close()); 235 271 236 272 /* ── Het gesprek: een overlay OVER de levende hemel ────────────────────
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)