#99 — WebSocket-Live-Sync für Einkaufslisten #98

Closed
opened 2026-08-18 13:13:59 +02:00 by lena · 0 comments
lena commented 2026-08-18 13:13:59 +02:00 (Migrated from git.butzei.de)

Story: WebSocket-Live-Sync für Einkaufslisten

As a Mitglied einer geteilten Einkaufsliste,
I want to Änderungen anderer Mitglieder (neue Mitglieder, umbenannte Liste, gelöschte Liste) live sehen,
ohne manuell neu zu laden,
so that eine geteilte Einkaufsliste sich genauso "live" anfühlt wie eine geteilte Todo-Liste.

Depends on: #89 (führt das Sharing-Modell für Einkaufslisten ein, das dies erst nötig macht).

Hintergrund: #81 hat Einkaufslisten bewusst ohne WebSocket-Broadcast gebaut ("Single-Owner-Modell, keine
Live-Collaboration-Story") — der Frontend-Code refetcht seitdem nach jeder Mutation, statt auf einen Broadcast zu
lauschen. #89 macht Einkaufslisten jetzt echt mehrpersonenfähig (Owner/Member, Einladungslinks), aber die
Refetch-Strategie wurde bewusst NICHT mitgezogen, um #89 nicht weiter aufzublähen (siehe
docs/features/done/89_unified_list_types_overview_design.md, Abschnitt "Bewusst nicht in dieser Story"). Der
reale Effekt: Wenn Mitglied B einer Einkaufsliste beitritt, sieht Mitglied A das erst nach einem manuellen
Neuladen der Seite — kein Broadcast informiert es live.

Acceptance criteria:

  • Neuer ChangePublisher<ShoppingListId, ShoppingListDto>, analog zu ChangePublisher<TodoListId, TodoListDto> — jede Mutation, die eine Einkaufsliste selbst verändert (Umbenennen, Löschen, Mitglied
    beitreten/entfernen, Default setzen), publiziert ein Update-Event.
  • Neue ShoppingListBroadcastDto, analog zu TodoListBroadcastDto — schließt per-viewer-Felder
    (CurrentUserRole, IsDefault) aus, genau wie beim Todo-Pendant (Begründung: ein privates
    Nutzer-Feld darf nicht listenweit gebroadcastet werden).
  • Frontend: TodoListMenu.tsx's Shopping-Lists-Fetch wird von "refetch nach jeder Mutation" auf eine echte
    WS-Subscription umgestellt, analog zu subscribeToDtoChanges<TodoListId, TodoListBroadcastDto> für
    Todo-Listen.
  • Bestehende Refetch-Aufrufe (z. B. nach RenameShoppingListCommand) werden entfernt, wo der Broadcast sie
    jetzt überflüssig macht — kein doppeltes Update.

Out of scope for this story:

  • Live-Sync für Produkte/Kategorien innerhalb einer Einkaufsliste (nur die Listen-Metadaten selbst — Titel,
    Mitgliedschaft, Default-Status). Produkt-/Kategorie-Live-Sync ist eine deutlich größere, separate
    Betrachtung und nicht Teil dieser Story.

Verified against code (2026-08-07): ReactUi/src/components/TodoListMenu.tsx's fetchShoppingLists
(Kommentar "No WebSocket change stream for Shopping Lists") ist die Stelle, die ersetzt werden muss.
CqsTodo/Entities/ChangePublisher.cs/TodoListMappings.Map(TodoListDto) sind die Vorlagen, die für Shopping
gespiegelt werden.

# Story: WebSocket-Live-Sync für Einkaufslisten **As a** Mitglied einer geteilten Einkaufsliste, **I want to** Änderungen anderer Mitglieder (neue Mitglieder, umbenannte Liste, gelöschte Liste) live sehen, ohne manuell neu zu laden, **so that** eine geteilte Einkaufsliste sich genauso "live" anfühlt wie eine geteilte Todo-Liste. **Depends on:** `#89` (führt das Sharing-Modell für Einkaufslisten ein, das dies erst nötig macht). **Hintergrund:** `#81` hat Einkaufslisten bewusst ohne WebSocket-Broadcast gebaut ("Single-Owner-Modell, keine Live-Collaboration-Story") — der Frontend-Code refetcht seitdem nach jeder Mutation, statt auf einen Broadcast zu lauschen. `#89` macht Einkaufslisten jetzt echt mehrpersonenfähig (Owner/Member, Einladungslinks), aber die Refetch-Strategie wurde bewusst NICHT mitgezogen, um `#89` nicht weiter aufzublähen (siehe `docs/features/done/89_unified_list_types_overview_design.md`, Abschnitt "Bewusst nicht in dieser Story"). Der reale Effekt: Wenn Mitglied B einer Einkaufsliste beitritt, sieht Mitglied A das erst nach einem manuellen Neuladen der Seite — kein Broadcast informiert es live. **Acceptance criteria:** - [ ] Neuer `ChangePublisher<ShoppingListId, ShoppingListDto>`, analog zu `ChangePublisher<TodoListId, TodoListDto>` — jede Mutation, die eine Einkaufsliste selbst verändert (Umbenennen, Löschen, Mitglied beitreten/entfernen, Default setzen), publiziert ein Update-Event. - [ ] Neue `ShoppingListBroadcastDto`, analog zu `TodoListBroadcastDto` — schließt per-viewer-Felder (`CurrentUserRole`, `IsDefault`) aus, genau wie beim Todo-Pendant (Begründung: ein privates Nutzer-Feld darf nicht listenweit gebroadcastet werden). - [ ] Frontend: `TodoListMenu.tsx`'s Shopping-Lists-Fetch wird von "refetch nach jeder Mutation" auf eine echte WS-Subscription umgestellt, analog zu `subscribeToDtoChanges<TodoListId, TodoListBroadcastDto>` für Todo-Listen. - [ ] Bestehende Refetch-Aufrufe (z. B. nach `RenameShoppingListCommand`) werden entfernt, wo der Broadcast sie jetzt überflüssig macht — kein doppeltes Update. **Out of scope for this story:** - Live-Sync für Produkte/Kategorien innerhalb einer Einkaufsliste (nur die Listen-Metadaten selbst — Titel, Mitgliedschaft, Default-Status). Produkt-/Kategorie-Live-Sync ist eine deutlich größere, separate Betrachtung und nicht Teil dieser Story. **Verified against code (2026-08-07):** `ReactUi/src/components/TodoListMenu.tsx`'s `fetchShoppingLists` (Kommentar "No WebSocket change stream for Shopping Lists") ist die Stelle, die ersetzt werden muss. `CqsTodo/Entities/ChangePublisher.cs`/`TodoListMappings.Map(TodoListDto)` sind die Vorlagen, die für Shopping gespiegelt werden.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
robert/todo#98
No description provided.