Restructure step 0: Connection extracted from the coordinator

Connection owns the socket lifecycle, connect/dial with epochs,
reconnect, the clock offset, diagnostics upload and a sealed ConnState
signal; the hello is built by an injectable builder, the resume token
stays private, and the reconnect delay and silence limit are parameters.
The coordinator maps ConnState to the same health texts and keeps the
reconnect restore and drop handling (step 1 replaces them).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
foxyzandClaude Opus 5.5 committed 2026-10-15 19:52:49 +03:00
1 parent a52133b313
commit eac45746ce
13 files changed
+780 -368

No files matched your search

+3 -3
View File
@@ -78,7 +78,7 @@ MemoryImage _memo(Object key, Uint8List bytes) {
/// Callers rebuild on [SessionCoordinator.avatars] and [Profile.picture]
/// (see [PartyWatch]).
ImageProvider? memberAvatarImage(MemberView m, SessionCoordinator coord) {
if (m.id.isNotEmpty && m.id == coord.sync.memberId) {
if (m.id.isNotEmpty && m.id == coord.connection.memberId) {
final own = Profile.instance.picture.value;
if (own != null) return _memo('self', own);
}
@@ -105,10 +105,10 @@ AvatarInfo selfAvatarInfo({bool ready = false, bool host = false, bool out = fal
/// [m] as the party strip, toasts and the chat show it.
AvatarInfo memberAvatarInfo(MemberView m, StateBroadcast? r, SessionCoordinator coord) {
final self = m.id.isNotEmpty && m.id == coord.sync.memberId;
final self = m.id.isNotEmpty && m.id == coord.connection.memberId;
final relay = r == null ? null : stateMediaRelay(r);
final playing = r?.media != null;
final delivery = r == null ? null : deliveryOf(r, selfId: coord.sync.memberId, names: coord.memberNames);
final delivery = r == null ? null : deliveryOf(r, selfId: coord.connection.memberId, names: coord.memberNames);
return AvatarInfo(
id: m.id,
name: m.name,
+1 -1
View File
@@ -516,7 +516,7 @@ class MembersCard extends StatelessWidget {
: '${session.lastForm.host}:${session.lastForm.port}';
final delivery = r == null
? null
: deliveryOf(r, selfId: coord.sync.memberId, names: coord.memberNames);
: deliveryOf(r, selfId: coord.connection.memberId, names: coord.memberNames);
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
+1 -1
View File
@@ -50,7 +50,7 @@ class _SitOutCardState extends State<SitOutCard> {
final now = coord.nowPlaying.value;
final playing = r?.transport == 'playing';
final duration = (r?.media?['duration'] as num?)?.toDouble() ?? 0;
final at = r == null ? 0.0 : serverPositionAt(r, coord.sync.serverNow());
final at = r == null ? 0.0 : serverPositionAt(r, coord.connection.serverNow());
Duration secs(double s) => Duration(milliseconds: (s * 1000).round());
final where = r?.media == null
? 'Nothing is up'