From 0467a7b6121f6203e9c4ff6bdee9991c4d3fdc79 Mon Sep 17 00:00:00 2001 From: Myx Date: Mon, 23 Mar 2026 01:05:28 +0100 Subject: [PATCH] documentation improvement --- README.md | 60 ++++++++++++++++++- src/app/core/models/index.ts | 2 - src/app/domains/attachment/README.md | 18 +++--- src/app/domains/auth/README.md | 10 ++-- src/app/domains/chat/README.md | 22 +++---- src/app/domains/screen-share/README.md | 16 ++--- src/app/domains/server-directory/README.md | 16 ++--- src/app/domains/voice-connection/README.md | 18 +++--- src/app/domains/voice-session/README.md | 12 ++-- src/app/infrastructure/persistence/README.md | 6 +- src/app/infrastructure/realtime/README.md | 54 ++++++++--------- .../realtime/media/noise-reduction.manager.ts | 4 -- src/app/shared-kernel/chat-events.ts | 27 --------- 13 files changed, 145 insertions(+), 120 deletions(-) diff --git a/README.md b/README.md index 4014324..94fc0fa 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,12 @@ # Toju / Zoracord -Desktop chat app with three parts: +Desktop chat app with four parts: - `src/` Angular client - `electron/` desktop shell, IPC, and local database - `server/` directory server, join request API, and websocket events +- `website/` Toju website served at toju.app ## Install @@ -59,3 +60,60 @@ Inside `server/`: # Images + +## Main Toju app Structure + +| Path | Description | +|------|-------------| +| `src/app/` | Main application root | +| `src/app/core/` | Core utilities, services, models | +| `src/app/domains/` | Domain-driven modules | +| `src/app/features/` | UI feature modules | +| `src/app/infrastructure/` | Low-level infrastructure (DB, realtime, etc.) | +| `src/app/shared/` | Shared UI components | +| `src/app/shared-kernel/` | Shared domain contracts & models | +| `src/app/store/` | Global state management | +| `src/assets/` | Static assets | +| `src/environments/` | Environment configs | + +--- + +### Domains + +| Path | Link | +|------|------| +| Attachment | [app/domains/attachment/README.md](src/app/domains/attachment/README.md) | +| Auth | [app/domains/auth/README.md](src/app/domains/auth/README.md) | +| Chat | [app/domains/chat/README.md](src/app/domains/chat/README.md) | +| Screen Share | [app/domains/screen-share/README.md](src/app/domains/screen-share/README.md) | +| Server Directory | [app/domains/server-directory/README.md](src/app/domains/server-directory/README.md) | +| Voice Connection | [app/domains/voice-connection/README.md](src/app/domains/voice-connection/README.md) | +| Voice Session | [app/domains/voice-session/README.md](src/app/domains/voice-session/README.md) | +| Domains Root | [app/domains/README.md](src/app/domains/README.md) | + +--- + +### Infrastructure + +| Path | Link | +|------|------| +| Persistence | [src/app/infrastructure/persistence/README.md](src/app/infrastructure/persistence/README.md) | +| Realtime | [src/app/infrastructure/realtime/README.md](src/app/infrastructure/realtime/README.md) | + +--- + +### Shared Kernel + +| Path | Link | +|------|------| +| Shared Kernel | [src/app/shared-kernel/README.md](src/app/shared-kernel/README.md) | + +--- + +### Entry Points + +| File | Link | +|------|------| +| Main | [main.ts](src/main.ts) | +| Index HTML | [index.html](src/index.html) | +| App Root | [app/app.ts](src/app/app.ts) | diff --git a/src/app/core/models/index.ts b/src/app/core/models/index.ts index e4fd2b4..8f58525 100644 --- a/src/app/core/models/index.ts +++ b/src/app/core/models/index.ts @@ -10,7 +10,6 @@ * instead of this file. */ -// ── shared-kernel re-exports ──────────────────────────────────────── export type { User, UserStatus, @@ -50,5 +49,4 @@ export type { ChatAttachmentMeta } from '../../shared-kernel'; -// ── domain re-exports ─────────────────────────────────────────────── export type { ServerInfo } from '../../domains/server-directory'; diff --git a/src/app/domains/attachment/README.md b/src/app/domains/attachment/README.md index 76dc568..21928b8 100644 --- a/src/app/domains/attachment/README.md +++ b/src/app/domains/attachment/README.md @@ -54,15 +54,15 @@ graph TD Persistence --> Store Storage --> Helpers[attachment-storage.helpers] - click Facade "application/attachment.facade.ts" "Thin entry point" - click Manager "application/attachment-manager.service.ts" "Orchestrates lifecycle" - click Transfer "application/attachment-transfer.service.ts" "P2P file transfer protocol" - click Transport "application/attachment-transfer-transport.service.ts" "Base64 encode/decode, chunked streaming" - click Persistence "application/attachment-persistence.service.ts" "DB + filesystem persistence" - click Store "application/attachment-runtime.store.ts" "In-memory signal-based state" - click Storage "infrastructure/attachment-storage.service.ts" "Electron filesystem access" - click Helpers "infrastructure/attachment-storage.helpers.ts" "Path helpers" - click Logic "domain/attachment.logic.ts" "Pure decision functions" + click Facade "application/attachment.facade.ts" "Thin entry point" _blank + click Manager "application/attachment-manager.service.ts" "Orchestrates lifecycle" _blank + click Transfer "application/attachment-transfer.service.ts" "P2P file transfer protocol" _blank + click Transport "application/attachment-transfer-transport.service.ts" "Base64 encode/decode, chunked streaming" _blank + click Persistence "application/attachment-persistence.service.ts" "DB + filesystem persistence" _blank + click Store "application/attachment-runtime.store.ts" "In-memory signal-based state" _blank + click Storage "infrastructure/attachment-storage.service.ts" "Electron filesystem access" _blank + click Helpers "infrastructure/attachment-storage.helpers.ts" "Path helpers" _blank + click Logic "domain/attachment.logic.ts" "Pure decision functions" _blank ``` ## File transfer protocol diff --git a/src/app/domains/auth/README.md b/src/app/domains/auth/README.md index cd30683..04d1708 100644 --- a/src/app/domains/auth/README.md +++ b/src/app/domains/auth/README.md @@ -36,11 +36,11 @@ graph TD Auth --> SD Login --> Store - click Auth "application/auth.service.ts" "HTTP login/register" - click Login "feature/login/" "Login form" - click Register "feature/register/" "Registration form" - click UserBar "feature/user-bar/" "Current user display" - click SD "../server-directory/application/server-directory.facade.ts" "Resolves API URL" + click Auth "application/auth.service.ts" "HTTP login/register" _blank + click Login "feature/login/" "Login form" _blank + click Register "feature/register/" "Registration form" _blank + click UserBar "feature/user-bar/" "Current user display" _blank + click SD "../server-directory/application/server-directory.facade.ts" "Resolves API URL" _blank ``` ## Login flow diff --git a/src/app/domains/chat/README.md b/src/app/domains/chat/README.md index 69cdd1f..c8f7d9c 100644 --- a/src/app/domains/chat/README.md +++ b/src/app/domains/chat/README.md @@ -54,14 +54,14 @@ graph TD List --> Item Item --> Overlays - click Chat "feature/chat-messages/chat-messages.component.ts" "Root chat view" - click List "feature/chat-messages/components/message-list/" "Paginated message list" - click Composer "feature/chat-messages/components/message-composer/" "Markdown toolbar + send" - click Overlays "feature/chat-messages/components/message-overlays/" "Context menus, reaction picker" - click Item "feature/chat-messages/components/message-item/" "Single message bubble" - click GIF "feature/klipy-gif-picker/" "GIF search panel" - click Typing "feature/typing-indicator/" "Typing indicator" - click Users "feature/user-list/" "Online user sidebar" + click Chat "feature/chat-messages/chat-messages.component.ts" "Root chat view" _blank + click List "feature/chat-messages/components/message-list/" "Paginated message list" _blank + click Composer "feature/chat-messages/components/message-composer/" "Markdown toolbar + send" _blank + click Overlays "feature/chat-messages/components/message-overlays/" "Context menus, reaction picker" _blank + click Item "feature/chat-messages/components/message-item/" "Single message bubble" _blank + click GIF "feature/klipy-gif-picker/" "GIF search panel" _blank + click Typing "feature/typing-indicator/" "Typing indicator" _blank + click Users "feature/user-list/" "Online user sidebar" _blank ``` ## Message lifecycle @@ -122,9 +122,9 @@ graph LR Klipy --> SD Klipy --> API - click Picker "feature/klipy-gif-picker/" "GIF search panel" - click Klipy "application/klipy.service.ts" "GIF search via KLIPY API" - click SD "../server-directory/application/server-directory.facade.ts" "Resolves API base URL" + click Picker "feature/klipy-gif-picker/" "GIF search panel" _blank + click Klipy "application/klipy.service.ts" "GIF search via KLIPY API" _blank + click SD "../server-directory/application/server-directory.facade.ts" "Resolves API base URL" _blank ``` ## Domain rules diff --git a/src/app/domains/screen-share/README.md b/src/app/domains/screen-share/README.md index 4c93f89..0dbfcc3 100644 --- a/src/app/domains/screen-share/README.md +++ b/src/app/domains/screen-share/README.md @@ -44,14 +44,14 @@ graph TD Workspace --> Tile Picker --> Config - click SSF "application/screen-share.facade.ts" "Proxy to RealtimeSessionFacade" - click Picker "application/screen-share-source-picker.service.ts" "Electron source picker" - click RSF "../../infrastructure/realtime/realtime-session.service.ts" "Low-level WebRTC composition root" - click Viewer "feature/screen-share-viewer/screen-share-viewer.component.ts" "Single-stream player" - click Workspace "feature/screen-share-workspace/screen-share-workspace.component.ts" "Multi-stream workspace" - click Tile "feature/screen-share-workspace/screen-share-stream-tile.component.ts" "Stream tile" - click Playback "feature/screen-share-workspace/screen-share-playback.service.ts" "Per-user volume state" - click Config "domain/screen-share.config.ts" "Quality presets" + click SSF "application/screen-share.facade.ts" "Proxy to RealtimeSessionFacade" _blank + click Picker "application/screen-share-source-picker.service.ts" "Electron source picker" _blank + click RSF "../../infrastructure/realtime/realtime-session.service.ts" "Low-level WebRTC composition root" _blank + click Viewer "feature/screen-share-viewer/screen-share-viewer.component.ts" "Single-stream player" _blank + click Workspace "feature/screen-share-workspace/screen-share-workspace.component.ts" "Multi-stream workspace" _blank + click Tile "feature/screen-share-workspace/screen-share-stream-tile.component.ts" "Stream tile" _blank + click Playback "feature/screen-share-workspace/screen-share-playback.service.ts" "Per-user volume state" _blank + click Config "domain/screen-share.config.ts" "Quality presets" _blank ``` ## Starting a screen share diff --git a/src/app/domains/server-directory/README.md b/src/app/domains/server-directory/README.md index 7604c62..d750e57 100644 --- a/src/app/domains/server-directory/README.md +++ b/src/app/domains/server-directory/README.md @@ -53,14 +53,14 @@ graph TD State --> Defaults Health --> Compat - click Facade "application/server-directory.facade.ts" "High-level API" - click State "application/server-endpoint-state.service.ts" "Signal-based endpoint state" - click API "infrastructure/server-directory-api.service.ts" "HTTP client for server API" - click Health "infrastructure/server-endpoint-health.service.ts" "Health probe" - click Compat "infrastructure/server-endpoint-compatibility.service.ts" "Version compatibility" - click Storage "infrastructure/server-endpoint-storage.service.ts" "localStorage persistence" - click Defaults "domain/server-endpoint-defaults.ts" "Default endpoint templates" - click Models "domain/server-directory.models.ts" "Domain types" + click Facade "application/server-directory.facade.ts" "High-level API" _blank + click State "application/server-endpoint-state.service.ts" "Signal-based endpoint state" _blank + click API "infrastructure/server-directory-api.service.ts" "HTTP client for server API" _blank + click Health "infrastructure/server-endpoint-health.service.ts" "Health probe" _blank + click Compat "infrastructure/server-endpoint-compatibility.service.ts" "Version compatibility" _blank + click Storage "infrastructure/server-endpoint-storage.service.ts" "localStorage persistence" _blank + click Defaults "domain/server-endpoint-defaults.ts" "Default endpoint templates" _blank + click Models "domain/server-directory.models.ts" "Domain types" _blank ``` ## Endpoint lifecycle diff --git a/src/app/domains/voice-connection/README.md b/src/app/domains/voice-connection/README.md index fe3f362..9940776 100644 --- a/src/app/domains/voice-connection/README.md +++ b/src/app/domains/voice-connection/README.md @@ -31,11 +31,11 @@ graph TD VAS --> VCF VPS --> VCF - click VCF "application/voice-connection.facade.ts" "Proxy to RealtimeSessionFacade" - click VAS "application/voice-activity.service.ts" "RMS-based speaking detection" - click VPS "application/voice-playback.service.ts" "Per-peer GainNode volume chain" - click RSF "../../infrastructure/realtime/realtime-session.service.ts" "Low-level WebRTC composition root" - click Models "domain/voice-connection.models.ts" "Re-exported types" + click VCF "application/voice-connection.facade.ts" "Proxy to RealtimeSessionFacade" _blank + click VAS "application/voice-activity.service.ts" "RMS-based speaking detection" _blank + click VPS "application/voice-playback.service.ts" "Per-peer GainNode volume chain" _blank + click RSF "../../infrastructure/realtime/realtime-session.service.ts" "Low-level WebRTC composition root" _blank + click Models "domain/voice-connection.models.ts" "Re-exported types" _blank ``` ## Voice connection facade @@ -63,8 +63,8 @@ graph LR RMS -- yes --> Speaking[speakingSignal = true] RMS -- no, 8 frames --> Silent[speakingSignal = false] - click Stream "application/voice-activity.service.ts" "VoiceActivityService.trackStream()" - click Poll "application/voice-activity.service.ts" "VoiceActivityService.poll()" + click Stream "application/voice-activity.service.ts" "VoiceActivityService.trackStream()" _blank + click Poll "application/voice-activity.service.ts" "VoiceActivityService.poll()" _blank ``` | Parameter | Value | @@ -88,8 +88,8 @@ graph LR Gain --> Dest[MediaStreamAudioDestinationNode] Dest --> Audio[HTMLAudioElement
.play] - click Remote "application/voice-playback.service.ts" "VoicePlaybackService.setupPeer()" - click Gain "application/voice-playback.service.ts" "VoicePlaybackService.setUserVolume()" + click Remote "application/voice-playback.service.ts" "VoicePlaybackService.setupPeer()" _blank + click Gain "application/voice-playback.service.ts" "VoicePlaybackService.setUserVolume()" _blank ``` Volume per peer is stored in localStorage and restored on reconnect. The range is 0% to 200% (gain values 0.0 to 2.0). When the user deafens, all gain nodes are set to zero; undeafening restores the previous values. diff --git a/src/app/domains/voice-session/README.md b/src/app/domains/voice-session/README.md index cb36a7f..9a51bc9 100644 --- a/src/app/domains/voice-session/README.md +++ b/src/app/domains/voice-session/README.md @@ -47,12 +47,12 @@ graph TD VSF --> Store VWS --> VSF - click VSF "application/voice-session.facade.ts" "Tracks active voice session" - click VWS "application/voice-workspace.service.ts" "Workspace mode and focused stream" - click VSS "infrastructure/voice-settings.storage.ts" "localStorage persistence for audio settings" - click Logic "domain/voice-session.logic.ts" "Pure helper functions" - click VC "feature/voice-controls/" "Full voice control panel" - click FC "feature/floating-voice-controls/" "Minimal floating overlay" + click VSF "application/voice-session.facade.ts" "Tracks active voice session" _blank + click VWS "application/voice-workspace.service.ts" "Workspace mode and focused stream" _blank + click VSS "infrastructure/voice-settings.storage.ts" "localStorage persistence for audio settings" _blank + click Logic "domain/voice-session.logic.ts" "Pure helper functions" _blank + click VC "feature/voice-controls/" "Full voice control panel" _blank + click FC "feature/floating-voice-controls/" "Minimal floating overlay" _blank ``` ## Session lifecycle diff --git a/src/app/infrastructure/persistence/README.md b/src/app/infrastructure/persistence/README.md index a3699ef..9b46199 100644 --- a/src/app/infrastructure/persistence/README.md +++ b/src/app/infrastructure/persistence/README.md @@ -23,9 +23,9 @@ graph TD Decision -- Electron --> IPC[ElectronDatabaseService
IPC to main process] IPC --> Main[Electron main process
TypeORM + SQLite] - click Facade "database.service.ts" "DatabaseService - platform-agnostic facade" - click IDB "browser-database.service.ts" "IndexedDB backend for web" - click IPC "electron-database.service.ts" "IPC client for Electron" + click Facade "database.service.ts" "DatabaseService - platform-agnostic facade" _blank + click IDB "browser-database.service.ts" "IndexedDB backend for web" _blank + click IPC "electron-database.service.ts" "IPC client for Electron" _blank ``` `DatabaseService` is an `@Injectable({ providedIn: 'root' })` that injects both backends and delegates every call to whichever one matches the current platform. Consumers never import a backend directly. diff --git a/src/app/infrastructure/realtime/README.md b/src/app/infrastructure/realtime/README.md index f28c0dd..e8cb6f6 100644 --- a/src/app/infrastructure/realtime/README.md +++ b/src/app/infrastructure/realtime/README.md @@ -87,28 +87,28 @@ graph TD SSM --> ElectronCap[Electron capture] SSM --> LinuxCap[Linux audio routing] - click WS "realtime-session.service.ts" "WebRTCService - composition root" - click SC "signaling/signaling-transport-handler.ts" "Routes messages to the right WebSocket" - click PCM "peer-connection-manager/peer-connection.manager.ts" "Owns all RTCPeerConnection instances" - click MM "media/media.manager.ts" "getUserMedia, mute, deafen, gain pipeline" - click SSM "media/screen-share.manager.ts" "Screen capture and per-peer distribution" - click State "state/webrtc-state-controller.ts" "Angular Signals for connection state" - click VSC "media/voice-session-controller.ts" "Higher-level voice session wrapper" - click PMF "streams/peer-media-facade.ts" "Unified API over peers, media, screen share" - click RSSRC "streams/remote-screen-share-request-controller.ts" "On-demand screen share delivery" - click SM1 "signaling/signaling.manager.ts" "One WebSocket per signaling URL" - click SM2 "signaling/signaling.manager.ts" "One WebSocket per signaling URL" - click Coord "signaling/server-signaling-coordinator.ts" "Maps peers/servers to signaling URLs" - click Conn "peer-connection-manager/connection/create-peer-connection.ts" "RTCPeerConnection factory" - click Neg "peer-connection-manager/connection/negotiation.ts" "Offer/answer/ICE with collision handling" - click DC "peer-connection-manager/messaging/data-channel.ts" "Ordered data channel for chat + control" - click Ping "peer-connection-manager/messaging/ping.ts" "Latency measurement via PING/PONG" - click Rec "peer-connection-manager/recovery/peer-recovery.ts" "Disconnect grace period + reconnect loop" - click RS "peer-connection-manager/streams/remote-streams.ts" "Classifies incoming tracks" - click NR "media/noise-reduction.manager.ts" "RNNoise AudioWorklet graph" - click BrowserCap "media/screen-share-platforms/browser-screen-share.capture.ts" "Standard getDisplayMedia" - click ElectronCap "media/screen-share-platforms/desktop-electron-screen-share.capture.ts" "Electron source picker" - click LinuxCap "media/screen-share-platforms/linux-electron-screen-share.capture.ts" "PulseAudio/PipeWire routing" + click WS "realtime-session.service.ts" "WebRTCService - composition root" _blank + click SC "signaling/signaling-transport-handler.ts" "Routes messages to the right WebSocket" _blank + click PCM "peer-connection-manager/peer-connection.manager.ts" "Owns all RTCPeerConnection instances" _blank + click MM "media/media.manager.ts" "getUserMedia, mute, deafen, gain pipeline" _blank + click SSM "media/screen-share.manager.ts" "Screen capture and per-peer distribution" _blank + click State "state/webrtc-state-controller.ts" "Angular Signals for connection state" _blank + click VSC "media/voice-session-controller.ts" "Higher-level voice session wrapper" _blank + click PMF "streams/peer-media-facade.ts" "Unified API over peers, media, screen share" _blank + click RSSRC "streams/remote-screen-share-request-controller.ts" "On-demand screen share delivery" _blank + click SM1 "signaling/signaling.manager.ts" "One WebSocket per signaling URL" _blank + click SM2 "signaling/signaling.manager.ts" "One WebSocket per signaling URL" _blank + click Coord "signaling/server-signaling-coordinator.ts" "Maps peers/servers to signaling URLs" _blank + click Conn "peer-connection-manager/connection/create-peer-connection.ts" "RTCPeerConnection factory" _blank + click Neg "peer-connection-manager/connection/negotiation.ts" "Offer/answer/ICE with collision handling" _blank + click DC "peer-connection-manager/messaging/data-channel.ts" "Ordered data channel for chat + control" _blank + click Ping "peer-connection-manager/messaging/ping.ts" "Latency measurement via PING/PONG" _blank + click Rec "peer-connection-manager/recovery/peer-recovery.ts" "Disconnect grace period + reconnect loop" _blank + click RS "peer-connection-manager/streams/remote-streams.ts" "Classifies incoming tracks" _blank + click NR "media/noise-reduction.manager.ts" "RNNoise AudioWorklet graph" _blank + click BrowserCap "media/screen-share-platforms/browser-screen-share.capture.ts" "Standard getDisplayMedia" _blank + click ElectronCap "media/screen-share-platforms/desktop-electron-screen-share.capture.ts" "Electron source picker" _blank + click LinuxCap "media/screen-share-platforms/linux-electron-screen-share.capture.ts" "PulseAudio/PipeWire routing" _blank ``` ## Signaling (WebSocket) @@ -222,11 +222,11 @@ graph LR GainNode --> Out Out --> Peers[replaceTrack on
all peer audio senders] - click Mic "media/media.manager.ts" "MediaManager.enableVoice()" - click Worklet "media/noise-reduction.manager.ts" "NoiseReductionManager.enable()" - click GainNode "media/media.manager.ts" "MediaManager.applyInputGainToCurrentStream()" - click Out "media/media.manager.ts" "MediaManager.localMediaStream" - click Peers "media/media.manager.ts" "MediaManager.bindLocalTracksToAllPeers()" + click Mic "media/media.manager.ts" "MediaManager.enableVoice()" _blank + click Worklet "media/noise-reduction.manager.ts" "NoiseReductionManager.enable()" _blank + click GainNode "media/media.manager.ts" "MediaManager.applyInputGainToCurrentStream()" _blank + click Out "media/media.manager.ts" "MediaManager.localMediaStream" _blank + click Peers "media/media.manager.ts" "MediaManager.bindLocalTracksToAllPeers()" _blank ``` `MediaManager` grabs the mic with `getUserMedia`, optionally pipes it through the RNNoise AudioWorklet for noise reduction (48 kHz, loaded from `rnnoise-worklet.js`), optionally runs it through a `GainNode` for input volume control, and then pushes the resulting stream to every connected peer via `replaceTrack`. diff --git a/src/app/infrastructure/realtime/media/noise-reduction.manager.ts b/src/app/infrastructure/realtime/media/noise-reduction.manager.ts index 9f0d142..6146c2f 100644 --- a/src/app/infrastructure/realtime/media/noise-reduction.manager.ts +++ b/src/app/infrastructure/realtime/media/noise-reduction.manager.ts @@ -47,8 +47,6 @@ export class NoiseReductionManager { constructor(private readonly logger: WebRTCLogger) {} - // ─── Public API ────────────────────────────────────────────────── - /** Whether noise reduction is currently active. */ get isEnabled(): boolean { return this._isEnabled; @@ -138,8 +136,6 @@ export class NoiseReductionManager { this.workletLoaded = false; } - // ─── Internals ─────────────────────────────────────────────────── - /** * Build the AudioWorklet processing graph: * rawStream → source → workletNode → destination diff --git a/src/app/shared-kernel/chat-events.ts b/src/app/shared-kernel/chat-events.ts index ec5154f..111ecd5 100644 --- a/src/app/shared-kernel/chat-events.ts +++ b/src/app/shared-kernel/chat-events.ts @@ -10,8 +10,6 @@ import type { VoiceState } from './voice-state.models'; import type { BanEntry } from './moderation.models'; import type { ChatAttachmentAnnouncement, ChatAttachmentMeta } from './attachment-contracts'; -// ── Inventory item (data structure, not an event) ─────────────────── - export interface ChatInventoryItem { id: string; ts: number; @@ -19,7 +17,6 @@ export interface ChatInventoryItem { ac?: number; } -// ── Base ──────────────────────────────────────────────────────────── // Every field that appears on any event is kept optional here so that // code which accesses `event.roomId` etc. without narrowing first // still compiles. Individual event interfaces below then make the @@ -74,8 +71,6 @@ export interface ChatEventBase { expiresAt?: number; } -// ── Messaging ─────────────────────────────────────────────────────── - export interface ChatMessageEvent extends ChatEventBase { type: 'message' | 'chat-message'; message: Message; @@ -93,8 +88,6 @@ export interface MessageDeletedEvent extends ChatEventBase { messageId: string; } -// ── Reactions ─────────────────────────────────────────────────────── - export interface ReactionAddedEvent extends ChatEventBase { type: 'reaction' | 'reaction-added'; messageId: string; @@ -108,8 +101,6 @@ export interface ReactionRemovedEvent extends ChatEventBase { emoji: string; } -// ── File transfer ─────────────────────────────────────────────────── - export interface FileAnnounceChatEvent extends ChatEventBase { type: 'file-announce'; messageId: string; @@ -143,8 +134,6 @@ export interface FileNotFoundChatEvent extends ChatEventBase { fileId: string; } -// ── Sync protocol ─────────────────────────────────────────────────── - export interface ChatInventoryRequestEvent extends ChatEventBase { type: 'chat-inventory-request'; roomId: string; @@ -184,8 +173,6 @@ export interface ChatSyncFullEvent extends ChatEventBase { messages: Message[]; } -// ── Room management ───────────────────────────────────────────────── - export interface RoomDeletedEvent extends ChatEventBase { type: 'room-deleted'; roomId: string; @@ -212,8 +199,6 @@ export interface HostChangeEvent extends ChatEventBase { previousHostOderId: string; } -// ── Voice & screen state ──────────────────────────────────────────── - export interface VoiceStateEvent extends ChatEventBase { type: 'voice-state'; voiceState: Partial; @@ -240,8 +225,6 @@ export interface ScreenShareStopEvent extends ChatEventBase { type: 'screen-share-stop'; } -// ── Server icon ───────────────────────────────────────────────────── - export interface ServerIconSummaryEvent extends ChatEventBase { type: 'server-icon-summary'; roomId: string; @@ -267,8 +250,6 @@ export interface ServerIconUpdateEvent extends ChatEventBase { iconUpdatedAt: number; } -// ── Server state ──────────────────────────────────────────────────── - export interface ServerStateRequestEvent extends ChatEventBase { type: 'server-state-request'; roomId: string; @@ -280,8 +261,6 @@ export interface ServerStateFullEvent extends ChatEventBase { room: Partial; } -// ── Member roster ─────────────────────────────────────────────────── - export interface MemberRosterRequestEvent extends ChatEventBase { type: 'member-roster-request'; roomId: string; @@ -302,8 +281,6 @@ export interface RoleChangeEvent extends ChatEventBase { type: 'role-change'; } -// ── Moderation ────────────────────────────────────────────────────── - export interface KickEvent extends ChatEventBase { type: 'kick'; } @@ -316,16 +293,12 @@ export interface UnbanEvent extends ChatEventBase { type: 'unban'; } -// ── Channel ───────────────────────────────────────────────────────── - export interface ChannelsUpdateEvent extends ChatEventBase { type: 'channels-update'; roomId: string; channels: Channel[]; } -// ── Discriminated union ───────────────────────────────────────────── - /** Discriminated union of all P2P chat events. Narrow via `event.type`. */ export type ChatEvent = | ChatMessageEvent