fix: harden classroom presentations

This commit is contained in:
ekklesia
2026-09-23 00:02:25 -05:00
parent ec1e0d1cd7
commit 6f2d169355
16 changed files with 709 additions and 215 deletions
+28 -20
View File
@@ -52,6 +52,8 @@ hash.
This is not a new renderer. LibreOffice does exactly the rendering
Impress would have done live — it is the same engine — and poppler does
what every PDF viewer does. The classroom's own code displays a PNG.
Because playback is made from static page images, PowerPoint animations,
video, audio and other interactive content are not supported.
What it buys:
* **A teacher can never reach an editor**, because no editor ever runs
@@ -74,14 +76,15 @@ interactive runs, so no UI integration package is needed.
## Where things are
```
~/Downloads/ the teacher's own download. NEVER touched.
~/Downloads/ completed presentations move from here
~/Downloads/Wonder Ink/ Wonder Ink's worksheets. NEVER touched.
~/.local/share/ekklesia-classroom/presentations/
imported.json which downloads have been dealt with
<id>/
presentation.json title, pages, thumbnail slide, timers
Session 7 - Romans.pptx the managed copy, original name kept
original/
Session 7 - Romans.pptx the one original, name kept
slides.pdf what everything is rendered from
pages/page-001.png ... one per slide, 1920px wide
thumbnail.png the card picture, from the chosen slide
@@ -108,20 +111,22 @@ A file is imported when **all** of these hold:
* its fingerprint — path, size, modification time — is not already in
`imported.json`.
Two downloads of the same name are two presentations. The second gets
`(2)` after its title; neither overwrites the other.
Two downloads of the same name are two presentations in separate id
directories. The second gets `(2)` after its title; neither overwrites the
other.
**Crash safety.** The metadata is written saying `importing` *before* any
work, and the fingerprint is recorded at the same moment so a file that
crashes the converter cannot be retried forever. On startup the importer
sweeps every directory still saying `importing`, deletes it and forgets
its fingerprint, so an import interrupted by a reboot simply happens
again. A presentation becomes visible to a teacher only once every file
**Move and crash safety.** On one filesystem the completed download is
renamed atomically. Across filesystems it is copied to a hidden temporary,
flushed, published atomically, and only then removed from Downloads. The
metadata and transaction fingerprint are written first. On startup, an
interruption before the source was removed discards the partial destination
and retries; an interruption after the move resumes conversion from the
managed original. A presentation becomes ready only once every derived file
it needs is on disk.
A file that cannot be converted gets a card saying so, offering only
**Remove**. The teacher's download is untouched, which is what the card
says.
**Remove**. Its managed original remains recoverable even when PDF or page
generation fails.
## The three things kept apart
@@ -129,7 +134,7 @@ This is the part most worth not breaking.
| | Changed by | Never changed by |
| --- | --- | --- |
| **Library thumbnail** | *Use this slide as the picture* in Quick Look | presenting, importing |
| **Library cover** | *Use as cover* in Quick Look | presenting, importing |
| **Starting slide** | nothing — always slide 1 | choosing a thumbnail |
| **Retention** | a slide actually reaching the screen | Quick Look, opening the library, choosing a thumbnail, preview generation, a viewer that failed to start |
@@ -159,8 +164,9 @@ The cleanup runs hourly in the importer and:
directory so a crash cannot make a presentation permanently
un-removable;
* only ever removes a directory under the library root;
* never touches `~/Downloads`, and therefore never a Wonder Ink
worksheet;
* removes the managed original and all derived assets together;
* never touches unrelated files in `~/Downloads`, and therefore never a
Wonder Ink worksheet;
* tolerates a directory that is already half gone.
## The presenter
@@ -181,11 +187,13 @@ Page Up and Page Down are what the clicker in the cupboard sends.
Going past the last slide finishes, rather than showing a black "click to
exit" slide.
**Fullscreen is re-asserted, not assumed.** Measured in the lab: focusing
another window on the same workspace dropped the slideshow to half the
screen with the library beside it. `window-state-event` puts it back for
as long as the presentation is running, and stops the moment Escape is
pressed so it can never fight the teacher's way out.
**Fullscreen is re-asserted, not assumed.** The presenter requests
fullscreen after its Wayland surface is mapped, and its stable `Presenting`
title lets a presenter-only KWin rule apply fullscreen and remove the border
without affecting the library or Quick Look. `window-state-event` reasserts
the state for as long as the presentation is running and stops the moment
Escape is pressed. The library is hidden during playback and restored on
exit; the Plasma panel itself is never hidden or reconfigured.
## Fonts
Binary file not shown.

After

Width:  |  Height:  |  Size: 535 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 906 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 536 KiB

+16 -15
View File
@@ -497,21 +497,25 @@ sudo reboot
- [ ] It does **not** appear in the library while it is still downloading
- [ ] It appears by itself within a few seconds of the download finishing
- [ ] The title is readable — not a hash, not a long filename
- [ ] The original download is still in Chrome's downloads, untouched
- [ ] The completed original moved out of Downloads into the managed library;
there is no duplicate
- [ ] Download the **PDF and the PPTX** of the same session: two cards,
the second titled `(2)`, neither overwriting the other
### Quick Look
- [ ] **Quick Look** opens and shows slide 1
- [ ] **Quick Look** opens on the currently selected cover slide
- [ ] **Next** and **Previous** move through every slide
- [ ] The text and layout are right — check a slide with a Bible verse
- [ ] Go to the session-number slide, usually slide 2
- [ ] **Use this slide as the picture** changes the card
- [ ] **Use as cover** changes the card and shows **Current cover**
- [ ] **Back to Presentations** returns without presenting
- [ ] Close the library, open it again: the chosen picture is still there
- [ ] Reboot, open it again: still there
- [ ] `classroom-presentation-import --status` shows `presented never`
- [ ] At 1920×1080 and 1366×768, scale 1.0 and the larger supported scale,
the title, slide navigation, cover action, Back and Present all remain
above the panel without manually resizing
That last line is the one that matters. Quick Look, browsing every slide
and changing the picture must not have counted as a presentation.
@@ -519,6 +523,7 @@ and changing the picture must not have counted as a presentation.
### Present
- [ ] **Present** from the card fills the **external television**
- [ ] No panel, title bar, border, desktop or other application is visible
- [ ] It starts at slide **1**, not at the slide chosen for the picture
- [ ] **Present** from inside Quick Look does the same
- [ ] Space, the arrow keys and Page Up/Page Down all move slides
@@ -546,21 +551,17 @@ Use a **test copy**. Not tomorrow's session.
- [ ] **Remove** asks first
- [ ] The card goes, and its slides and pictures go with it
- [ ] The original download in Chrome is untouched
- [ ] Its managed original goes too; unrelated downloads and another similarly
named presentation remain
- [ ] It does not come back on the next scan or after a reboot
### The manual
### Help is temporarily hidden
- [ ] **Help** is on the bar, bottom left
- [ ] It opens with no address bar and no tabs
- [ ] It shows Browser, Presentations, sound and the common pages
- [ ] It does **not** mention Wonder Ink, Parent Call or the DVD
- [ ] It works with the network unplugged
- [ ] On a children's classroom machine it shows the opposite set
- [ ] Print `/usr/local/share/ekklesia-classroom/manual/classroom-manual.pdf`
and check the conditional wording reads sensibly in a room that
does not have every feature
- [ ] The revision date is on the printed copy
- [ ] No **Help** launcher is visible on the teacher-facing bar
- [ ] The manual sources, generated HTML/PDF, launcher and feature-aware build
pipeline remain installed for the later documentation correction pass
- [ ] Presentations and Wonder Ink title bars show only Close, with no
double-chevron keep-above control
### Wi-Fi — look, do not touch