- 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>
44 lines
1.3 KiB
Dart
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;
|
|
}
|
|
}
|