Desktop session batch 09-12: frameless chrome, bisect removal, chat/idle fixes

Frameless (window_manager, hidden titlebar): chrome bar on welcome,
drag-to-move appbar + window buttons on connect, drag layer + window
buttons in session controls; min size 160x90; volume-scroll off for
drag; session maximize = fullscreen toggle. Verified on KDE Wayland.
Delete legacy/minimal/nosheet bisect screens; session routes direct
(black-screen fix verified incl. WAN).
Avatar: pipeline now 128px aspect-kept PNG (was cropped JPEG);
profile card centered 64px hover-to-change; member avatar drops
ResizeImage downscale. NOTE open: pipeline 512 KiB check vs server
64 KiB enforcement mismatch.
Fixes: idle warn/unready skipped while PLAYING; sendChat drops
blanks; one chat row per send (drop textless server feed echo);
chat field keeps focus after send. Playback libass true; sdk floor
3.13. Handoff 9-11: 9+10 fixed, 11 jumpy seek still open.
Docs: handoff/roadmap/protocol record all of the above; few-commits
preference going forward.
This commit is contained in:
foxyz committed 2026-09-12 11:42:18 +03:00
1 parent 3303d88a5b
commit ff154c5030
26 files changed
+1147 -881

No files matched your search

@@ -386,24 +386,29 @@ class SessionCoordinator {
}
}
final idleSecs = now.difference(_lastInput).inSeconds;
if (idleSecs >= 8 * 60 && !_warnedIdle) {
_warnedIdle = true;
_toastId++;
toasts.value = [
...toasts.peek(),
ToastItem(
id: _toastId,
text: 'idle — auto-unready in 2 min unless you press Space',
at: now)
];
unawaited(sfx.play(const SfxCue(SfxKind.warn)));
}
if (idleSecs >= 10 * 60) {
final self = selfMember.peek();
if (self != null && self.ready) {
_lastReady = false;
sync.sendReady(false, source: 'auto');
markInput();
// Steady playback counts as activity: only warn/unready when HELD.
// While the room is PLAYING the ready flag gates nothing, so an
// idle viewer must never lose it mid-watch.
if (room.peek()?.transport != 'playing') {
if (idleSecs >= 8 * 60 && !_warnedIdle) {
_warnedIdle = true;
_toastId++;
toasts.value = [
...toasts.peek(),
ToastItem(
id: _toastId,
text: 'idle — auto-unready in 2 min unless you press Space',
at: now)
];
unawaited(sfx.play(const SfxCue(SfxKind.warn)));
}
if (idleSecs >= 10 * 60) {
final self = selfMember.peek();
if (self != null && self.ready) {
_lastReady = false;
sync.sendReady(false, source: 'auto');
markInput();
}
}
}
}
@@ -482,6 +487,10 @@ class SessionCoordinator {
}
void sendChat(String text) {
// Enter in the chat field can fire both onSubmitted and the focused
// send button's onPressed; the first send clears the field, so the
// second arrives empty. Drop blanks so at most one message ships.
if (text.trim().isEmpty) return;
markInput();
sync.sendChat(text);
}