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