Skip to content

[Feature] Projector: line-by-line display mode with parallel translation #61

Description

@TheMaestr-o

Problem

The projector currently shows a full verse at once. On large screens this results in small text that is hard to follow. A line-by-line mode — showing 1 or 2 lines at a time — keeps the display clean, the text large, and the congregation focused.


Display layout

Three layers rendered simultaneously on the projection screen:

  Early in the morning our song       ← previous line, fading out upward, dimmed
  Holy, holy, holy Lord               ← CURRENT line, full size, centred
  Heilig, heilig, heilig, Herr Gott   ← translation subline, smaller
  When the morning stars began        ← next line, barely visible at bottom

When the operator advances, the current line slides up and the next line enters from below — smooth transition, configurable speed.


Bilingual support

Each song part carries a language tag and a translation_type:

singable — professional translation that fits the melody. Both languages displayed at equal size. The congregation can sing in either language.

  Holy, holy, holy, Lord God Almighty
  Heilig, heilig, heilig, Herr Gott Allmächtiger

reference — literal translation for comprehension only. Cannot be sung to this melody. Displayed small and dimmed below the main line.

  Holy, holy, holy, Lord God Almighty
  ₛ Heilig, heilig, heilig, Herr Gott Allmächtiger

Language role switching

The operator can flip which language is primary at any moment during the service — no reload, instant sync to the display window:

  • 🇬🇧 primary → 🇩🇪 reference below
  • 🇩🇪 primary → 🇬🇧 reference below

Presenter dashboard

┌─────────────────────────────────────┐
│  Verse 2 · line 3 / 5               │
│                                     │
│  [ NOW ]                            │
│  Holy, holy, holy Lord              │
│                                     │
│  [ NEXT ]                           │
│  Early in the morning our song      │
│                                     │
│  ← Back     Forward →    [B] Blank  │
│                                     │
│  🇬🇧 Primary  |  🇩🇪 Reference  [⇄] │
│  Lines: [1] [2]        A−  A+       │
└─────────────────────────────────────┘

Keyboard shortcuts

Key Action
← → previous / next line
B blank screen
F request fullscreen on display window
1 / 2 switch 1 or 2 lines per slide

DB changes required

  • Add language VARCHAR to song_parts
  • Add translation_type ENUM('original', 'singable', 'reference') to song_parts
  • New migration in packages/db/migrations/
  • Admin UI: language + type selectors per song part
  • SongPartDto extended with language and translationType

BroadcastChannel — new message types

type direction payload
lineIndex both { partIndex, lineIndex }
lineMode presenter → display { active, linesPerSlide: 1|2 }
secondaryLang presenter → display { lang: string | null }
primaryLang presenter → display { lang: string }
blank presenter → display { active: boolean }
transition presenter → display { style: 'fade'|'slide', durationMs: number }

Acceptance criteria

  • Existing full-verse projector mode is untouched
  • Line-by-line toggle switches mode live without reload
  • 1-line / 2-line sub-toggle works instantly on both windows
  • Three-layer rendering: current (full) / previous (dimmed) / next (preview)
  • Slide-up and fade transitions configurable
  • singable translations shown full-size alongside main line
  • reference translations shown small and dimmed below
  • Language role swap (primary ↔ reference) works live during service
  • Presenter dashboard shows Part · line X / N indicator
  • Language selector only appears when song has ≥ 2 languages tagged
  • All new UI strings in DE and EN
  • BroadcastChannel sync for all new message types
  • DB migration adds language and translation_type to song_parts
  • Admin UI allows tagging language and type per part
  • Works on touch devices (swipe to advance)
  • ?screenshot=1 / ?projector=1 modes unaffected

App: Songbook (songs.sdarm.life)
Severity: 🟠 High

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions