Files
Toju/toju-app/src/app/domains/screen-share/README.md

4.9 KiB

Screen Share Domain

Manages screen sharing sessions, source selection (Electron), quality presets, and screen-share-specific UI. Like voice-connection, the actual WebRTC track distribution lives in infrastructure/realtime; this domain provides the application-facing API for display-media capture and playback.

The mixed live-stream workspace is intentionally not part of this domain. It lives in features/room/voice-workspace because it composes screen share, voice-session, voice-connection, and camera state in one shell.

Module map

screen-share/
├── application/
│   ├── facades/
│   │   └── screen-share.facade.ts                 Proxy to RealtimeSessionFacade for screen share signals and methods
│   └── services/
│       └── screen-share-source-picker.service.ts  Electron desktop source picker (Promise-based open/confirm/cancel)
│
├── domain/
│   └── constants/
│       └── screen-share.constants.ts              Quality presets and types (re-exported from shared-kernel)
│
├── feature/
│   ├── screen-share-quality-dialog/               Quality preset picker before capture
│   ├── screen-share-source-picker/                Electron source selection dialog
│   └── screen-share-viewer/                       Single-stream video player with fullscreen + volume
│
└── index.ts                                       Barrel exports

Service relationships

graph TD
    SSF[ScreenShareFacade]
    Picker[ScreenShareSourcePickerService]
    RSF[RealtimeSessionFacade]
    Config[screen-share.constants]
    Viewer[ScreenShareViewerComponent]
    Workspace[VoiceWorkspaceComponent]

    SSF --> RSF
    Viewer --> SSF
    Workspace --> SSF
    Picker --> Config

    click SSF "application/facades/screen-share.facade.ts" "Proxy to RealtimeSessionFacade" _blank
    click Picker "application/services/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 "../../features/room/voice-workspace/voice-workspace.component.ts" "Room-level live stream workspace" _blank
    click Config "domain/constants/screen-share.constants.ts" "Quality presets" _blank

Starting a screen share

sequenceDiagram
    participant User
    participant Controls as VoiceControls
    participant Facade as ScreenShareFacade
    participant Realtime as RealtimeSessionFacade
    participant Picker as SourcePickerService

    User->>Controls: Click "Share Screen"

    alt Electron
        Controls->>Picker: open(sources)
        Picker-->>Controls: selected source + includeSystemAudio
    end

    Controls->>Facade: startScreenShare(options)
    Facade->>Realtime: startScreenShare(options)
    Note over Realtime: Captures screen via platform strategy
    Note over Realtime: Waits for SCREEN_SHARE_REQUEST from viewers
    Realtime-->>Facade: MediaStream

    User->>Controls: Click "Stop"
    Controls->>Facade: stopScreenShare()
    Facade->>Realtime: stopScreenShare()

Source picker (Electron)

ScreenShareSourcePickerService manages a Promise-based flow for Electron desktop capture. open() sets a signal with the available sources, and the UI renders a picker dialog. When the user selects a source, confirm(sourceId, includeSystemAudio) resolves the Promise. cancel() rejects with an AbortError.

Sources are classified as either screen or window based on the source ID prefix or name. The includeSystemAudio preference is persisted to voice settings storage.

Quality presets

Screen share quality is configured through presets defined in the shared kernel:

Preset Resolution Framerate
low Reduced Lower FPS
balanced Medium Medium FPS
high Full High FPS

The quality dialog can be shown before each share (askScreenShareQuality setting) or skipped to use the last chosen preset.

Viewer component

ScreenShareViewerComponent is a single-stream video player. It supports:

  • Fullscreen toggle (browser Fullscreen API with CSS fallback)
  • Volume control for remote streams (delegated to VoicePlaybackService)
  • Local shares are always muted to avoid feedback
  • Focus events from other components via a viewer:focus custom DOM event
  • Auto-stop when the watched user stops sharing or the stream's video tracks end

Voice workspace integration

VoiceWorkspaceComponent in features/room/voice-workspace is the multi-stream grid view inside the room shell. It consumes ScreenShareFacade for display-media capture and on-demand remote screen-share requests, but it is not part of this domain because it also owns camera presentation and voice-session controls.