From 44ec243be885cd889ac001eb3195044bee270d08 Mon Sep 17 00:00:00 2001 From: vegard Date: Thu, 19 Mar 2026 16:52:57 +0000 Subject: [PATCH] Proposals: varslingssystem + universell input MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Varsling: notification-noder i grafen, trigger ved edge-opprettelse/ nevnelse/oppgave. WebSocket toast + ulest-badge + valgfri epost. Universell input: én TipTap-komponent med kontekst-drevne moduser (chat/forum/editor/code). Markup-bytte (WYSIWYG/markdown/LaTeX). Draft-caching i localStorage + valgfri graf-synk for kryssenhets. Integrert medieinput og inline-handlinger (@mentions, [[lenker]]). Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/proposals/universell_input.md | 214 +++++++++++++++++++++++++++++ docs/proposals/varsling.md | 75 ++++++++++ 2 files changed, 289 insertions(+) create mode 100644 docs/proposals/universell_input.md create mode 100644 docs/proposals/varsling.md diff --git a/docs/proposals/universell_input.md b/docs/proposals/universell_input.md new file mode 100644 index 0000000..bb86533 --- /dev/null +++ b/docs/proposals/universell_input.md @@ -0,0 +1,214 @@ +# Proposal: Universell input — én editor, alle kontekster + +## Konsept + +Én TipTap-basert input-komponent som tilpasser seg konteksten. +Kompakt i chat, trådet i forum, fullskjerm i editor. Brukeren +velger markup-modus (WYSIWYG, markdown, LaTeX). Usendt innhold +caches automatisk. + +## Problemstilling + +I dag har vi separate input-komponenter for ulike kontekster: +- Chat: enkel textarea med enter-sender +- NodeEditor (slettet): TipTap med tittel + innhold +- EditorTrait: TipTap med toolbar + +Disse er inkonsistente. Brukeren lærer tre forskjellige +input-mønstre. Og ingen av dem cacher usendt innhold. + +## Modell: én komponent, kontekst-drevne moduser + +```svelte + + context={nodeId} + onSubmit={send} + placeholder="Skriv en melding..." +/> +``` + +### Moduser + +| Modus | Utseende | Oppførsel | +|-------|----------|-----------| +| `chat` | Kompakt, én linje (utvider seg) | Enter = send, Shift+Enter = linjeskift | +| `forum` | Tittel-felt + brødtekst | Knapp = post, mer plass | +| `editor` | Full toolbar, ingen send-knapp | Auto-lagring, kontinuerlig | +| `code` | Monospace, syntax highlighting | Tab = indent, ingen auto-format | + +### Smart default per kontekst + +Konteksten bestemmer default-modus: +- ChatTrait → `chat` +- ForumTrait → `forum` +- EditorTrait → `editor` +- Frittstående → `editor` + +Men brukeren kan alltid bytte. Skriv mye i chat? Klikk +"utvid" → midlertidig editor-modus. Send tilbake som melding. + +## Markup-moduser + +Samme underliggende TipTap-dokument, tre visninger: + +### WYSIWYG (default) +- Det du ser er det du får +- Toolbar med formatering (bold, italic, lenker, lister, bilder) +- Mest tilgjengelig for de fleste + +### Markdown +- Kildekode-visning med markdown-syntaks +- Forhåndsvisning ved siden av (split) eller toggle +- For de som tenker i markdown + +### LaTeX +- Matematisk notasjon, formler +- KaTeX-rendering i forhåndsvisning +- Kanskje mest relevant i editor-modus + +Brukeren velger sin preferanse — lagres i +`metadata.preferences.input_mode`. Kan overrides per kontekst. + +### Bytte mellom moduser + +Knapp i input-feltet: `[W]` / `[M]` / `[L]` +Bytter visning, dokumentet konverteres automatisk. +TipTap sin interne representasjon er den samme uansett. + +## Draft-caching + +### Lokal cache (localStorage) + +Usendt innhold lagres automatisk, knyttet til kontekst: + +``` +draft:chat:redaksjonen-uuid → "Jeg tenker vi bør..." +draft:forum:redaksjonen-uuid:ny-tråd → { title: "Forslag", body: "..." } +draft:editor:artikkel-uuid → { document: "..." } +``` + +- Lagres ved hvert tastetrykk (debounced, 500ms) +- Gjenopprettes når du navigerer tilbake +- Slettes når innholdet sendes/publiseres +- Viser diskret indikator: "Utkast lagret" + +### Graf-synk (valgfritt, for kryssenhets) + +For lengre tekster (editor-modus) kan draftet lagres som en +node i grafen: + +``` +node_kind: 'draft' +metadata: { context_id: "artikkel-uuid", auto_saved: true } +belongs_to → kontekst-noden +created_by → brukeren +``` + +Synkroniseres via WebSocket. Åpner du editoren på telefonen +ser du det du skrev på PC-en. Eksplisitt handling for å +publisere/sende — draftet er privat til det. + +## Medieinput integrert + +Universell input inkluderer alle input-modaliteter: + +| Modalitet | Mekanisme | +|-----------|-----------| +| Tekst | Tastatur, standard | +| Bilde | Paste fra clipboard, drag-and-drop, kamera | +| Lyd | Opptak-knapp, voice memo | +| Video | Opptak-knapp (webcam/skjerm) | +| Fil | Drag-and-drop, filvelger | +| Tegning | Skisse-modus (enkel canvas) | +| Lokasjon | "Del posisjon"-knapp | +| Lenke | Paste URL → auto-preview med synops-clip | + +Alt ender som noder i grafen. Tekst = innholds-node. +Bilde/lyd/video = media-node med CAS-lagring. + +## Inline-handlinger + +Mens du skriver kan du trigge handlinger: + +- `@person` → nevne noen (autocomplete fra kontakter) +- `@bot` → AI-assistent svarer +- `/kommando` → slash-kommandoer (som i chat-apper) +- `[[nodetittel]]` → lenke til eksisterende node +- Paste URL → auto-embed med forhåndsvisning + +## Tilbakemeldings-indikatorer + +Input-feltet viser tilstand: + +``` +┌─────────────────────────────────────┐ +│ Skriv en melding... │ +│ │ +│ 📎 🎤 [W] [Send] │ +│ Utkast lagret · 142 tegn │ +└─────────────────────────────────────┘ +``` + +- 📎 = legg ved fil/bilde +- 🎤 = voice memo +- [W] / [M] / [L] = markup-modus +- Tegnteller (valgfritt) +- "Utkast lagret" / "Lagrer..." / "Ikke lagret" + +## Komponent-arkitektur + +``` +UniversalInput (wrapper) +├── TipTapEditor (kjerne — samme instans uansett modus) +├── ModeSelector (chat/forum/editor/code) +├── MarkupToggle (WYSIWYG/markdown/LaTeX) +├── MediaButtons (fil, opptak, kamera, tegning, lokasjon) +├── DraftManager (localStorage + valgfri graf-synk) +├── MentionProvider (@person, @bot, [[node]]) +└── ActionBar (send/post/lagre + indikatorer) +``` + +TipTap-instansen er den samme — wrapper-en endrer layout, +toolbar-synlighet og submit-oppførsel basert på modus. + +## Implementering + +### Fase 1: Konsolidert input +- UniversalInput-komponent med chat/editor-modus +- Erstatt eksisterende input i ChatTrait og EditorTrait +- Draft-caching i localStorage + +### Fase 2: Forum-modus +- Tittel + brødtekst layout +- Integrert med ForumTrait (fra chat/forum-dualitet) + +### Fase 3: Markup-moduser +- Markdown-visning med forhåndsvisning +- LaTeX via KaTeX +- Brukerpreferanse + +### Fase 4: Medieinput +- Paste-deteksjon for bilder +- Opptak-knapper (lyd, video) +- Fil-opplasting + +### Fase 5: Inline-handlinger +- @mentions med autocomplete +- [[node-lenker]] med søk +- URL auto-embed + +### Fase 6: Kryssenhets drafts +- Draft-noder i grafen +- WebSocket-synkronisering + +## Hva som eksisterer allerede + +- TipTap-editor i EditorTrait (✓) +- Voice memo-opptak (✓) +- Bilde-paste i TipTap (✓) +- @bot-trigger i chat (✓) +- synops-clip for URL-parsing (✓) +- CAS for medielagring (✓) + +Hovedsakelig konsolidering og utvidelse, ikke nybygg. diff --git a/docs/proposals/varsling.md b/docs/proposals/varsling.md new file mode 100644 index 0000000..841ddd9 --- /dev/null +++ b/docs/proposals/varsling.md @@ -0,0 +1,75 @@ +# Proposal: Varslingssystem + +## Konsept + +Når noe skjer som angår deg — ny samtale, ny melding, ny oppgave, +noen nevner deg — får du et varsel. Varsler er noder i grafen, +ikke en separat mekanisme. + +## Varsling som noder + +``` +node_kind: 'notification' +metadata: { + type: "added_to_conversation", + actor_id: "vegard-uuid", + target_id: "redaksjonen-uuid", + seen: false +} +belongs_to → din person-node +``` + +Fordeler: +- Varsler er søkbare, filtrerbare, arkiverbare +- Samme PG NOTIFY → WebSocket-pipeline som alt annet +- Ingen ny infrastruktur + +## Trigger-hendelser + +| Hendelse | Varsel | +|----------|--------| +| Lagt til i samtale | "Vegard la deg til i Redaksjonen" | +| Nevnt i melding (@Trond) | "Vegard nevnte deg i Redaksjonen" | +| Ny melding i samtale (valgfritt) | "3 nye meldinger i Redaksjonen" | +| Tildelt oppgave | "Vegard tildelte deg: Fiks lyden" | +| Innsendt artikkel behandlet | "Artikkelen din ble godkjent" | +| Orkestrering fullført | "Transkribering ferdig" | + +## Leveringskanaler + +Samme varsel kan leveres via flere kanaler: + +- **WebSocket → toast i appen** (alltid, sanntid) +- **Ulest-badge i Mine ting** (alltid) +- **Epost** (konfigurerbart per bruker i metadata.preferences) +- **Lyd-ping** (konfigurerbart) + +Brukerens preferanser styrer hva som trigger epost vs bare +in-app varsel. Default: alt in-app, epost kun for direkte +nevnelser og invitasjoner. + +## Visning + +Varsler vises som: +- Klokke-ikon i header med ulest-teller +- Dropdown med siste varsler +- Klikk → naviger til relevant kontekst +- "Marker alle som lest" + +Kan også være et panel i arbeidsflaten ("Varsler"-trait) +for de som vil ha det synlig. + +## Ikke-forstyrrende + +- Ingen popup-vinduer, ingen blokkerende dialoger +- Toast forsvinner etter 5 sekunder +- Bruker velger selv hva som sender epost +- "Ikke forstyrr"-modus per arbeidsflate + +## Implementering + +1. `notification`-node-type i maskinrommet +2. Trigger-logikk i vaktmesteren (ved edge-opprettelse, melding, etc.) +3. Frontend: toast-komponent + varsler-dropdown i header +4. `synops-notify` CLI finnes allerede — utvid med notification-noder +5. Epost-varsling via eksisterende `synops-mail --send`