Protocol 11: sit out replaces kicking; nudge
Anyone can sit anyone out (host included); only you bring yourself back. Out members stay in chat and the party, never block or count, and load no media; a card with the live position and Join back (Space) replaces the video. The mini player's x sits you out; optionally idle does too. Nudge: the server forwards it to the target only (3/s, 20/min per sender); the target hears the nudge sound, gets a toast and a taskbar attention request. Kick, its messages, errors and dialog are gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
dbfd351ee4
commit
8b81da4069
46 files changed
+855
-599
No files matched your search
@@ -4,7 +4,7 @@ import 'dart:convert';
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
import 'package:web_socket_channel/web_socket_channel.dart';
|
||||
|
||||
enum SyncStatus { idle, connecting, open, kicked, closed, error }
|
||||
enum SyncStatus { idle, connecting, open, closed, error }
|
||||
|
||||
class SyncClient {
|
||||
/// Local clock; injectable so tests can run a client whose clock is off.
|
||||
@@ -23,13 +23,14 @@ class SyncClient {
|
||||
StreamSubscription? _sub;
|
||||
final StreamController<StateBroadcast> _states = StreamController.broadcast();
|
||||
final StreamController<FeedMessage> _feeds = StreamController.broadcast();
|
||||
final StreamController<String> _kicked = StreamController.broadcast();
|
||||
final StreamController<NudgeNotice> _nudges = StreamController.broadcast();
|
||||
final StreamController<String> _errors = StreamController.broadcast();
|
||||
final StreamController<SyncStatus> _status = StreamController.broadcast();
|
||||
|
||||
Stream<StateBroadcast> get states => _states.stream;
|
||||
Stream<FeedMessage> get feeds => _feeds.stream;
|
||||
Stream<String> get kicked => _kicked.stream;
|
||||
/// Someone poked this member (`nudge`).
|
||||
Stream<NudgeNotice> get nudges => _nudges.stream;
|
||||
Stream<String> get errors => _errors.stream;
|
||||
Stream<SyncStatus> get status => _status.stream;
|
||||
|
||||
@@ -153,14 +154,10 @@ class SyncClient {
|
||||
// one toast, one sfx.
|
||||
if (f.action != 'chat') _feeds.add(f);
|
||||
} catch (_) {}
|
||||
case 'kicked':
|
||||
case 'nudge':
|
||||
try {
|
||||
final msg = KickedMessage.fromJson(decoded);
|
||||
_kicked.add(msg.reason);
|
||||
_status.add(SyncStatus.kicked);
|
||||
} catch (_) {
|
||||
_kicked.add('');
|
||||
}
|
||||
_nudges.add(NudgeNotice.fromJson(decoded));
|
||||
} catch (_) {}
|
||||
case 'pong':
|
||||
try {
|
||||
final pong = PongMessage.fromJson(decoded);
|
||||
@@ -255,8 +252,14 @@ class SyncClient {
|
||||
_send(ArtMessage(mediaId: mediaId, poster: poster, banner: banner).toJson());
|
||||
}
|
||||
|
||||
void sendKick(String target, {String reason = ''}) {
|
||||
_send(KickRequest(target: target, reason: reason).toJson());
|
||||
/// Sits the member [target] out, or with [out] false brings this
|
||||
/// member back (only oneself can come back).
|
||||
void sendOut(String target, bool out) {
|
||||
_send(OutIntent(target: target, out: out).toJson());
|
||||
}
|
||||
|
||||
void sendNudge(String target) {
|
||||
_send(NudgeIntent(target: target).toJson());
|
||||
}
|
||||
|
||||
Future<void> disconnect() async {
|
||||
@@ -283,7 +286,7 @@ class SyncClient {
|
||||
await disconnect();
|
||||
await _states.close();
|
||||
await _feeds.close();
|
||||
await _kicked.close();
|
||||
await _nudges.close();
|
||||
await _errors.close();
|
||||
await _status.close();
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user