Files
sync_replay_project/apps/desktop/lib/src/session/idle.dart
T
foxyzandClaude Opus 5.5 81cac1214d Server on an isolate, dedicated server binary, room -> server (proto 5)
- serve(Map config, events) is the one server entrypoint: the app
  hosts it via Isolate.spawn (crash surfaced on the Host card, logs
  forwarded as [server]); bin/server.dart is the dedicated server,
  compiled into the bundle as watch-together-server. --headless gone.
- Host identity via a per-hosting hostKey in hello, replacing the
  loopback heuristic.
- Rename room -> server across code, files and wire (t:"state",
  /health name); protocol bumped to 5.
- CI compiles the server binary; isolate smoke tests in server and
  desktop suites. Docs updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 00:55:14 +03:00

44 lines
1.3 KiB
Dart

enum IdleEvent { none, warn, unready }
/// Idle auto-unready clock. Idle time counts from the later of the user's
/// last input and the last moment playback was running: watching is
/// activity, so a long watch followed by a pause starts a fresh 10 min.
/// The unready also always trails its warning by the full grace period.
class IdleTracker {
static const warnAfter = Duration(minutes: 8);
static const unreadyAfter = Duration(minutes: 10);
DateTime _lastActive;
DateTime? _warnedAt;
IdleTracker(DateTime now) : _lastActive = now;
void activity(DateTime now) {
_lastActive = now;
_warnedAt = null;
}
/// Called once per tick. Warn and unready only matter while self is
/// ready; while playing the ready flag gates nothing.
IdleEvent tick(DateTime now, {required bool playing, required bool selfReady}) {
if (playing) {
activity(now);
return IdleEvent.none;
}
if (!selfReady) return IdleEvent.none;
final warnedAt = _warnedAt;
if (warnedAt != null) {
if (now.difference(warnedAt) >= unreadyAfter - warnAfter) {
activity(now);
return IdleEvent.unready;
}
return IdleEvent.none;
}
if (now.difference(_lastActive) >= warnAfter) {
_warnedAt = now;
return IdleEvent.warn;
}
return IdleEvent.none;
}
}