connect method
void
connect({
- required String sessionId,
- required SocketRole role,
- String? clientId,
- dynamic onLog()?,
- dynamic onImageReceived()?,
- dynamic onControllerConnected()?,
- dynamic onControllerDisconnected()?,
- dynamic onViewerConnected()?,
- dynamic onViewerDisconnected()?,
- dynamic onPairingSuccess()?,
- dynamic onPairingRejected()?,
- dynamic onSessionEnded()?,
- dynamic onActionReceived()?,
- dynamic onError()?,
- dynamic onWarning()?,
Implementation
void connect({
required String sessionId,
required SocketRole role,
String? clientId,
Function(String)? onLog,
Function(Uint8List, String, Map<String, dynamic>?)? onImageReceived,
Function()? onControllerConnected,
Function()? onControllerDisconnected,
Function()? onViewerConnected,
Function()? onViewerDisconnected,
Function()? onPairingSuccess,
Function(String)? onPairingRejected,
Function()? onSessionEnded,
Function(Map<String, dynamic>)? onActionReceived,
Function(String)? onError,
Function(String)? onWarning,
}) {
this.onLog = onLog;
this.onImageReceived = onImageReceived;
this.onControllerConnected = onControllerConnected;
this.onControllerDisconnected = onControllerDisconnected;
this.onViewerConnected = onViewerConnected;
this.onViewerDisconnected = onViewerDisconnected;
this.onPairingSuccess = onPairingSuccess;
this.onPairingRejected = onPairingRejected;
this.onSessionEnded = onSessionEnded;
this.onActionReceived = onActionReceived;
this.onError = onError;
this.onWarning = onWarning;
currentSessionId = sessionId;
currentRole = role;
// Tear down any previous socket cleanly
_teardown();
_socket = IO.io(
'https://mirror.plushvie.store',
IO.OptionBuilder()
.setTransports(['websocket'])
.disableAutoConnect()
.enableReconnection()
.setReconnectionAttempts(5)
.setReconnectionDelay(1000)
.build(),
);
// ── connect ───────────────────────────────────────────────────────────
_socket!.onConnect((_) {
onLog?.call('✅ Connected to server: ${_socket!.id}');
final payload = <String, dynamic>{
'sessionId': sessionId,
'role': role == SocketRole.viewer ? 'viewer' : 'controller',
};
if (role == SocketRole.viewer && clientId != null) {
payload['clientId'] = clientId;
}
_socket!.emit('join-tryon-session', payload);
onLog?.call('📡 Emitted join-tryon-session');
if (role == SocketRole.viewer) {
isViewerConnected = true;
_startHeartbeat();
}
// _startPresenceTimer();
});
_socket!.onConnectError((data) {
onLog?.call('❌ Connection error: $data');
onError?.call(data.toString());
});
_socket!.onDisconnect((_) {
onLog?.call('❌ Disconnected from server');
_stopHeartbeat();
_stopPresenceTimer();
isViewerConnected = false;
});
// ── Pairing ───────────────────────────────────────────────────────────
_socket!.on('pairing-success', (_) {
onLog?.call('✅ Pairing success!');
onPairingSuccess?.call();
});
_socket!.on('pairing-rejected', (data) {
final reason = data is Map ? data['reason'] : data.toString();
onLog?.call('❌ Pairing rejected: $reason');
onPairingRejected?.call(reason);
});
// ── Presence events ───────────────────────────────────────────────────
// Remote controller joined
_socket!.on('controller-connected', (_) {
onLog?.call('📱 Remote controller connected');
isControllerConnected = true;
_lastControllerAck = DateTime.now();
onControllerConnected?.call();
final ctx = navigatorKeyTry.currentContext;
if (ctx != null) {
ctx.read<TryOnDataUiProvider>().sendStackToRemote();
ctx.read<TryOnDataUiProvider>().sendKioskRightPanel();
}
});
// Kiosk itself reconnected (server echo)
_socket!.on('viewer-connected', (_) {
onLog?.call('🖥 Viewer (kiosk) connected');
isViewerConnected = true;
onViewerConnected?.call();
});
// Remote controller disconnected
_socket!.on('controller-disconnected', (_) {
onLog?.call('📴 Remote controller disconnected');
_markControllerOffline();
});
// Kiosk temporarily lost connection (server tells remote — we also handle it locally)
_socket!.on('viewer-disconnected-temporary', (_) {
onLog?.call('⚠️ Viewer temporarily disconnected');
onViewerDisconnected?.call();
});
// ── Data events ───────────────────────────────────────────────────────
_socket!.on('tryon-viewer-action', (action) {
onLog?.call('🎮 Remote action received: $action');
if (action is Map) {
onActionReceived?.call(Map<String, dynamic>.from(action));
}
});
_socket!.on('tryon-image', (data) => _handleImageReceived(data));
_socket!.on('tryon-error', (msg) {
final e = msg.toString();
onLog?.call('❌ Error: $e');
onError?.call(e);
});
_socket!.on('tryon-warning', (msg) {
final w = msg.toString();
onLog?.call('⚠️ Warning: $w');
onWarning?.call(w);
});
// ── Session ended ─────────────────────────────────────────────────────
_socket!.on('tryon-session-ended', (_) {
onLog?.call('🔴 Session ended');
onSessionEnded?.call();
_teardown();
});
_socket!.connect();
onLog?.call('🔌 Connecting to socket…');
}