refactor: deduplicate shared patterns, replace hardcoded colors

This commit is contained in:
edde746
2026-03-03 22:43:00 +01:00
parent 8f3d52142d
commit cd2ab9d9cd
42 changed files with 685 additions and 612 deletions
@@ -4,23 +4,12 @@ import 'dart:convert';
import 'package:uuid/uuid.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import '../../services/base_peer_service.dart';
import '../../utils/app_logger.dart';
import '../models/sync_message.dart';
/// Error types that can occur in the peer service
enum PeerErrorType { connectionFailed, peerDisconnected, dataChannelError, serverError, timeout, unknown }
/// Represents an error in the peer service
class PeerError {
final PeerErrorType type;
final String message;
final dynamic originalError;
const PeerError({required this.type, required this.message, this.originalError});
@override
String toString() => 'PeerError($type): $message';
}
// Re-export so existing callers that import from here keep working.
export '../../services/base_peer_service.dart' show PeerError, PeerErrorType;
/// Service for managing Watch Together connections via a WebSocket relay
///
@@ -29,7 +18,7 @@ class PeerError {
/// - Joining sessions (as guest)
/// - Sending/receiving sync messages through the relay server
/// - Reconnection on WebSocket drops
class WatchTogetherPeerService {
class WatchTogetherPeerService with KeepaliveMixin {
static const String _baseUrl = 'https://ice.plezy.app';
static String get healthUrl => '$_baseUrl/health';
static const String _relayUrl = 'wss://ice.plezy.app/relay';
@@ -53,11 +42,11 @@ class WatchTogetherPeerService {
static const int _maxReconnectAttempts = 3;
Timer? _reconnectTimer;
// Keepalive
Timer? _pingTimer;
Timer? _pongTimer;
static const Duration _pingInterval = Duration(seconds: 15);
static const Duration _pongTimeout = Duration(seconds: 30);
// Keepalive (via KeepaliveMixin)
@override
Duration get pingInterval => const Duration(seconds: 15);
@override
Duration get pongTimeout => const Duration(seconds: 30);
/// Stream of peer IDs when a new peer connects
Stream<String> get onPeerConnected => _peerConnectedController.stream;
@@ -111,7 +100,7 @@ class WatchTogetherPeerService {
_channelSubscription?.cancel();
_channelSubscription = channel.stream.listen(
(data) {
_resetPongTimer();
resetPongTimer();
_handleServerMessage(data as String, setupCompleter: setupCompleter);
},
onError: (error) {
@@ -203,7 +192,7 @@ class WatchTogetherPeerService {
}
case 'pong':
// Handled by _resetPongTimer already
// Handled by resetPongTimer() already
break;
default:
@@ -214,30 +203,15 @@ class WatchTogetherPeerService {
}
}
/// Start the keepalive ping timer.
void _startPingTimer() {
_pingTimer?.cancel();
_pingTimer = Timer.periodic(_pingInterval, (_) {
_sendRaw({'type': 'ping'});
});
_resetPongTimer();
}
@override
void sendPing() => _sendRaw({'type': 'ping'});
/// Reset the pong timeout timer (called on every incoming message).
void _resetPongTimer() {
_pongTimer?.cancel();
_pongTimer = Timer(_pongTimeout, () {
appLogger.w('WatchTogether: Pong timeout — closing WebSocket');
@override
void onPongTimeout() {
appLogger.w('WatchTogether: Pong timeout — closing WebSocket');
try {
_channel?.sink.close();
});
}
/// Stop keepalive timers.
void _stopTimers() {
_pingTimer?.cancel();
_pingTimer = null;
_pongTimer?.cancel();
_pongTimer = null;
} catch (_) {}
}
/// Send a raw JSON map to the relay.
@@ -251,7 +225,7 @@ class WatchTogetherPeerService {
/// Handle the WebSocket being closed unexpectedly — attempt reconnection.
void _handleWebSocketClosed() {
_stopTimers();
stopKeepalive();
_channelSubscription?.cancel();
_channelSubscription = null;
_channel = null;
@@ -295,7 +269,7 @@ class WatchTogetherPeerService {
final completer = Completer<void>();
_listenToChannel(channel, setupCompleter: completer);
_startPingTimer();
startKeepalive();
// Re-send create or join
if (_isHost) {
@@ -332,7 +306,7 @@ class WatchTogetherPeerService {
final completer = Completer<void>();
_listenToChannel(channel, setupCompleter: completer);
_startPingTimer();
startKeepalive();
_sendRaw({'type': 'create', 'sessionId': _sessionId, 'peerId': _myPeerId});
@@ -369,7 +343,7 @@ class WatchTogetherPeerService {
final completer = Completer<void>();
_listenToChannel(channel, setupCompleter: completer);
_startPingTimer();
startKeepalive();
_sendRaw({'type': 'join', 'sessionId': _sessionId, 'peerId': _myPeerId});
@@ -408,12 +382,14 @@ class WatchTogetherPeerService {
_reconnectTimer?.cancel();
_reconnectTimer = null;
_stopTimers();
stopKeepalive();
_channelSubscription?.cancel();
_channelSubscription = null;
await _channel?.sink.close();
try {
await _channel?.sink.close();
} catch (_) {}
_channel = null;
_connectedPeers.clear();