Commit Graph
3 Commits
Author SHA1 Message Date
ekklesiaandClaude Opus 5 7f4a122900 feat: one setting per application, and never the shape of the machine
A laptop is going in for the women's Bible study, and the obvious way to
build that — a laptop profile that turns off the children's church
applications — is the wrong way. A laptop may well take children's church,
and a tower may well be a Bible study. Hardware cannot be allowed to
decide purpose, so every optional application gets a setting of its own:

    WONDERINK_ENABLED       already existed; behaviour unchanged
    DVD_ENABLED             new
    PARENT_CALL_ENABLED     new

and DEVICE_TYPE says only what the hardware IS. classroom-desktop-layout
never reads it, and there is a test that says so, because this is the rule
that will be under pressure the first time somebody adds a device.

All three default to true, so an existing classroom that has never heard
of any of them comes up exactly as it did before. The settings are
appended to device.conf by the same mechanism every other setting has
used, so an upgrade gains them without losing a byte an administrator
wrote.

The disc player is the one place hardware still votes, and it is a veto:
DVD_ENABLED can take the player away from a machine that has a drive,
nothing can put it on a machine that has none. A button that cannot work
is worse than no button.

The layout's launcher markers are replaced by a feature block of three
plain booleans. The old mechanism commented a line out of an array, which
worked for launchers and could not express Parent Call, because that is a
whole widget rather than one entry. Three booleans express both, and the
launcher list is now built from them in one fixed order, so a disabled
application closes the row up rather than leaving a gap, and the same
enabled set produces the same bar on every machine in the church.

Also here, because it is the bar and not a feature: sortingStrategy=0.
Plasma's default is 1, "manually", and the task manager accepts a
reordering drop only in that mode — MouseHandler.qml tests
tasksModel.sortMode === SortManual before it will move anything. The
classroom never wrote the key, so it had the default, and any teacher
could drag the launchers into a different order. This is the applet's own
lever refusing the drop rather than something of ours putting the bar back
afterwards.

The test now runs the layout the package actually ships, in node, with
Plasma's API stubbed, and asserts the launcher string that comes out.
Asserting against a copy of the file's text in the test was how the old
one worked, and a copy is a thing that drifts.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-20 20:55:09 -05:00
ekklesiaandClaude Opus 5 de5025ad22 feat: give Wonder Ink tabs, and let a device say it has no Wonder Ink
Teachers prepare a lesson across several tabs — the lesson, its video,
the activity — and app mode is the one thing that cannot give them that.

Chrome cannot be asked for "tabs but no omnibox". App mode has no tabs; a
normal window has an address bar and no policy, flag or extension removes
it; tabbed web apps need a manifest on a site that is not ours and push
off-origin links out into a normal browser window, which is the whole of
what this design exists to prevent. So the tab strip is ours, and the
engine is Chromium either way.

QtWebEngine, from Debian, measured before it was chosen rather than
after. The usual and correct objection is codecs: on Debian 13 it reports
H.264, AAC, MP3, VP8 and VP9 all playable, MediaSource supports avc1,
mp4a and vp9, and a 720p H.264 file decoded and played to the end in the
lab. app.wonderink.org loads, and its sign-in is an ordinary email and
password form rather than a Google flow that would mind an embedded
browser. The user agent has the QtWebEngine token stripped so a site
gating on it sees the Chromium this actually is, and Widevine is handed
over from Chrome's own bundle when the machine has Chrome, which a
classroom always does.

    [ Lesson ] [ Video ] [ Activity ]

The strip appears only above one tab, so an ordinary lesson looks exactly
like the application it replaces. A tab can only come from the lesson —
target=_blank, window.open, a middle click, a Ctrl+click — and there is
no address bar, no search and no button that makes a blank tab. No
allowlist of domains either, on purpose: a list would have to be right
about every video service a lesson might ever embed.

Three bugs the lab caught and this fixes. A lesson calling window.print()
did nothing at all, which is worse than no print button because a teacher
concludes the printer is broken; printRequested is now bound to the page
that asked. Leaving fullscreen left the window 200 pixels wide in the
corner — a window that has only ever been maximised has no ordinary
geometry to return to — so the fullscreen bit is cleared rather than
maximised being re-requested. And the Present view video failure written
up in docs/wonder-ink.md is acted on at last: that investigation named
the autoplay gesture chain as the likeliest cause and declined to fix it,
because in Chrome the only lever governed the ordinary browser as well.
Here it does not — this profile is Wonder Ink and nothing else — so a
lesson may start its own video and no other page in the room may.
Reproduced both ways in the lab with an unmuted video started by a script
with no gesture: NotAllowedError at Chrome's default, playing as shipped.
That is not proof Present view is fixed; the lab has no Wonder Ink
account, and candidates 2 and 3 in that document are still open.

Measured on a rebooted machine, from the package: tabs open from a link
and from window.open, switch, and close; closing one leaves the others;
closing the last closes Wonder Ink; H.264 video plays and fills the
display in fullscreen and comes back maximised with its tabs; the print
dialog offers the room's own Elmer queue; a download lands in ~/Downloads;
back and forward work from a right-click menu that is built rather than
filtered; pressing the panel button twice raises one window rather than
starting a second on the same profile; KWin reports the window as
ekklesia-wonderink, which is one panel button and not two.

Separate from the browser as before, in its own profile, with cookies
that live only as long as the window — what the Chrome policy did for
wonderink.org, and the reason closing Wonder Ink ends a teacher's
session. Chrome's old profile directory is left untouched beside it, and
the browser's own policy is not edited by any of this.

Wonder Ink is now optional per device, through WONDERINK_ENABLED in
device.conf, because one future device is a laptop that will not have it.
It rides the mechanism the disc player already uses: one marked line in
the packaged layout, edited by classroom-desktop-layout. False takes the
launcher off the panel and makes the command refuse to start; the
browser, Parent Call and the disc player are untouched and the panel
stays balanced. Absent means yes, so every existing room is unchanged.

One scale, still. Chrome has to be handed UI_SCALE because it was
measured not to follow the compositor; Qt does follow it — devicePixelRatio
2.0 at UI_SCALE=2.0, measured — so Wonder Ink is deliberately not told,
or the room would get it twice.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-19 21:29:17 -05:00
ekklesiaandClaude Opus 5 d2d30d6b0c feat: take the last of sway out of the classroom
The DVD player was the only thing still speaking a compositor the room
no longer runs. It asked sway's tree whether VLC's window had really
gone fullscreen, because VLC reports playing while its window is still
the black startup one the loading cover exists to hide.

VLC's own status was measured as a replacement and is not one: it
reports fullscreen true in the same 250ms poll as playing, because the
flag is the option it was started with and not a report about its
window. So the cover is held for a floor and capped by the deadline that
was already there, and the compositor is not asked anything.

Focus-or-launch went the same way. The session already takes an
exclusive lock, so a second one cannot start, and bringing an existing
one to the front is the panel's job.

classroom-window, classroom_sway and classroom_chrome are gone with it —
the last of them was reachable from nothing at all.

DVD also moves out of the status row, where it sat beside the clock as
though a disc were a machine reading. It is an application: it is in the
row with Wonder Ink and the browser, and classroom-provision removes it
from the layout on a machine with no optical drive, which retires
DVD_ENABLED. A computer that moves between rooms takes its drive with
it; nobody remembers to edit a file when it does.

The panel is rebuilt from the package at every login now. Plasma keeps
whatever panel it first built, so an update could change the bar in the
package and never change it in a room — measured, with an icon that
outlived the file it came from. Editing the live panel configuration was
tried instead and destroyed the panel, because the shell owns that file.
Removing it before the shell starts is safe and makes the desktop
stateless.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-10 13:00:50 -05:00