feat: steadier live updates and notices for public proposals

- The web pings the live connection, reconnects when it goes quiet and
  reloads what each screen shows after reconnecting.
- Dropping a card on a column it cannot go to puts it back.
- Owners and admins get a notice when a proposal arrives.
- The proposal limit lives in Redis, so it holds across instances.
- REST tells whether I voted; pasted images leave the attachment list.
- Deleting a project removes its Git integration; no lint warnings left.
- Reactions and the blocked badge are components of their own.
- Docs: what is done and what is left (chapter 10), Word and PDF.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-12 19:57:21 +02:00
parent 74903f7842
commit c91df110f8
50 changed files with 615 additions and 321 deletions

View File

@@ -1,5 +1,8 @@
import { inject, Injectable } from '@angular/core';
import { AccessTokenSource } from '@task-stream/web/shared/infrastructure';
import {
AccessTokenSource,
RealtimeConnection,
} from '@task-stream/web/shared/infrastructure';
import {
Activity,
CommentChanged,
@@ -38,6 +41,11 @@ import {
export class GraphqlRealtimeGateway extends TrackerRealtimeGateway {
private readonly gql = inject(GraphqlOperations);
private readonly tokens = inject(AccessTokenSource);
private readonly connection = inject(RealtimeConnection);
reconnects(): Observable<void> {
return this.connection.reconnected$;
}
private signedIn<T>(stream: () => Observable<T>): Observable<T> {
return defer(() => this.tokens.accessToken()).pipe(