Collaborative cursors: portert fra SpacetimeDB til WebSocket

SpacetimeDB er fjernet (mars 2026). Oppdatert til å bruke
eksisterende WebSocket/portvokter med ephemeral cursor_move-
meldinger (ikke persistert i PG). In-memory HashMap i Rust.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
vegard 2026-03-19 16:57:47 +00:00
parent 2d663f8f67
commit db95cd33d1

View file

@ -1,29 +1,86 @@
# Collaborative Cursors — Sanntids-pekere for flerbrukermiljø # Collaborative Cursors — Sanntids-pekere for flerbrukermiljø
## Idé ## Idé
Alle brukere som er på samme side ser hverandres musepekere som fargede prikker med navn. Fungerer på storyboard, kanban, whiteboard og kalender. Alle brukere som er på samme arbeidsflate ser hverandres
musepekere som fargede prikker med navn. Fungerer på spatial
## Hvorfor interessant? canvas, storyboard, kanban, whiteboard og kalender.
Gir "jamming together"-følelse under innspilling og planlegging. Produsent og host ser hverandre jobbe i sanntid uten å snakke om det. ## Hvorfor interessant?
## Fungerer slik Gir "jamming together"-følelse under innspilling og planlegging.
1. Klient sender `{ user_id, x, y, page }` til SpacetimeDB ved musebevegelse (throttlet til ~10 Hz) Produsent og host ser hverandre jobbe i sanntid uten å snakke
2. Andre klienter renderer fargede SVG-sirkler med brukernavn om det. Essensielt for delte arbeidsflater (møterom, studio).
3. Prikken fader ut etter 5 sekunder uten bevegelse
4. Valgfritt: kort "trail" som viser bevegelsesretning ## Fungerer slik
## Bygger på 1. Klient sender `{ user_id, x, y, context_id }` via WebSocket
- SpacetimeDB (pub/sub for posisjoner) ved musebevegelse (throttlet til ~10 Hz)
- Svelte ($state store for cursor-map) 2. Portvokteren broadcaster til andre klienter i samme kontekst
3. Andre klienter renderer fargede SVG-sirkler med brukernavn
## Innsats 4. Prikken fader ut etter 5 sekunder uten bevegelse
Lav — under 50 linjer Svelte + en SpacetimeDB-reducer. 5. Valgfritt: kort "trail" som viser bevegelsesretning
## Wow-faktor ## Teknisk implementering
Middels — visuelt tiltalende, men ikke kritisk funksjonalitet.
### Kanal
## Åpne spørsmål
- Bør pekere vises i chat-visning også, eller bare canvas-baserte views? Bruker eksisterende WebSocket-tilkobling til portvokteren.
- Throttling-strategi: SpacetimeDB-reducer eller klient-side debounce? Ny meldingstype `cursor_move` som **ikke** persisteres i PG —
dette er ephemeral data som kun lever i minne.
```
Klient → WS → portvokteren → broadcast til andre i samme context_id
```
Portvokteren holder en in-memory map:
```rust
cursors: HashMap<(ContextId, UserId), CursorPosition>
```
Ryddes automatisk ved disconnect eller timeout (5s).
### Throttling
Klientside: `requestAnimationFrame` + 100ms minimum intervall.
~10 meldinger per sekund per bruker. Ved 10 samtidige brukere
i ett rom: ~100 meldinger/sekund — trivielt for WebSocket.
### Rendering
Canvas-laget (over objektene, under toolbar):
```svelte
{#each cursors as cursor (cursor.userId)}
<div
class="cursor-indicator"
style:left="{cursor.x}px"
style:top="{cursor.y}px"
style:background={cursor.color}
style:opacity={cursor.fresh ? 1 : 0}
>
<span class="cursor-label">{cursor.name}</span>
</div>
{/each}
```
## Bygger på
- WebSocket / portvokteren (erstatter SpacetimeDB)
- Canvas-komponent (cursor-lag over objekter)
- Svelte ($state for cursor-map)
## Innsats
Lav — under 100 linjer Svelte + ~50 linjer Rust i portvokteren.
## Wow-faktor
Middels-høy — visuelt tiltalende og essensielt for delte
arbeidsflater (møterom, studio, samarbeid).
## Åpne spørsmål
- Bør pekere vises i chat-visning også, eller bare canvas?
(Sannsynligvis bare canvas og andre spatial views)
- Fargetildeling: per bruker (konsistent) eller per sesjon?
(Per bruker, lagret i person-node metadata)