Solo: no idle unready, no party corner in fullscreen; a cancelled Invite returns to solo
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0115d54ab8
commit
059b7dd306
4 files changed
+38
-4
No files matched your search
@@ -97,6 +97,7 @@ class ConnectFlow extends ChangeNotifier {
|
||||
_notify();
|
||||
return;
|
||||
}
|
||||
final fromSolo = mode == ConnectMode.host && _session.solo.value;
|
||||
try {
|
||||
if (mode == ConnectMode.host) {
|
||||
await _session.host(params, form);
|
||||
@@ -111,10 +112,14 @@ class ConnectFlow extends ChangeNotifier {
|
||||
return;
|
||||
}
|
||||
if (myAttempt != _attempt) {
|
||||
// Cancelled after it got through: back out.
|
||||
// Cancelled after it got through: back out (an Invite: back to solo).
|
||||
try {
|
||||
if (fromSolo) {
|
||||
await _session.cancelInvite();
|
||||
} else {
|
||||
await _session.leave();
|
||||
await _session.stopServer();
|
||||
}
|
||||
} catch (_) {}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -240,6 +240,9 @@ class SessionCoordinator {
|
||||
StreamSubscription? _statusSub;
|
||||
|
||||
bool _manualClose = false;
|
||||
/// A solo session (set by SessionState): no idle unready / sit out,
|
||||
/// there is nobody to hold up.
|
||||
bool solo = false;
|
||||
bool _playerReady = false;
|
||||
bool _wasPlayAllowed = false;
|
||||
// Last ready flag the server reported for self; restored after a
|
||||
@@ -949,7 +952,9 @@ class SessionCoordinator {
|
||||
// activity so a pause after a long watch starts a fresh idle clock.
|
||||
if (r != null) _readyAfterJoinBack(r, now);
|
||||
final sitOutWhenIdle = AppSettings.instance.idleSitsOut.peek();
|
||||
final event = _idle.tick(now,
|
||||
final event = solo
|
||||
? IdleEvent.none
|
||||
: _idle.tick(now,
|
||||
playing: serverState.peek()?.transport == 'playing',
|
||||
selfReady: selfMember.peek()?.ready ?? false);
|
||||
switch (event) {
|
||||
|
||||
@@ -296,7 +296,7 @@ class _SessionPlayerState extends State<SessionPlayer> {
|
||||
_status(),
|
||||
_progressLine(),
|
||||
_jellyfinOverlay(),
|
||||
if (widget.fullscreen) ...[_pausedParty(), _unreadChip()],
|
||||
if (widget.fullscreen) ...[if (!SessionState.instance.solo.value) _pausedParty(), _unreadChip()],
|
||||
] else
|
||||
_miniOverlay(),
|
||||
// Sitting out: nothing is loaded; the card covers the
|
||||
|
||||
@@ -260,12 +260,13 @@ class SessionState {
|
||||
/// pick, seeked to where it was; if hosting fails, solo comes back.
|
||||
Future<void> host(ConnectParams params, ConnectForm form) async {
|
||||
if (!solo.peek()) return _host(params, form: form);
|
||||
final carry = _carry();
|
||||
final carry = _invited = _carry();
|
||||
switching.value = true;
|
||||
try {
|
||||
await coordinator.leave();
|
||||
await stopServer();
|
||||
solo.value = false;
|
||||
coordinator.solo = false;
|
||||
try {
|
||||
await _host(params, form: form);
|
||||
} catch (_) {
|
||||
@@ -289,6 +290,27 @@ class SessionState {
|
||||
}
|
||||
}
|
||||
|
||||
/// What an Invite from solo carried over, for [cancelInvite].
|
||||
({PickedMedia pick, double position})? _invited;
|
||||
|
||||
/// Invite cancelled after the hosted server already came up: back to
|
||||
/// solo with the same media, not out of the session.
|
||||
Future<void> cancelInvite() async {
|
||||
final carry = _invited;
|
||||
switching.value = true;
|
||||
try {
|
||||
await coordinator.leave();
|
||||
await stopServer();
|
||||
await _host(_soloParams!, soloSession: true);
|
||||
if (carry != null) await _resume(carry);
|
||||
} catch (e) {
|
||||
debugPrint('back to solo failed: $e');
|
||||
await leave();
|
||||
} finally {
|
||||
switching.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Watch alone: the same hosted path, on 127.0.0.1 and a free port, no
|
||||
/// password, nothing put up yet. Nobody else can reach it.
|
||||
Future<void> startSolo(ConnectParams params) async {
|
||||
@@ -394,6 +416,7 @@ class SessionState {
|
||||
rethrow;
|
||||
}
|
||||
solo.value = soloSession;
|
||||
coordinator.solo = soloSession;
|
||||
route.value = AppRoute.session;
|
||||
} finally {
|
||||
if (form != null) await _saveFormQuietly();
|
||||
@@ -478,6 +501,7 @@ class SessionState {
|
||||
await coordinator.leave();
|
||||
await stopServer();
|
||||
solo.value = false;
|
||||
coordinator.solo = false;
|
||||
serverLabel.value = '';
|
||||
status.value = const HealthStatus(HealthSeverity.info, 'idle');
|
||||
route.value = AppRoute.home;
|
||||
|
||||
Reference in new issue
Block a user