Files
plezy/lib/watch_together/models/watch_session.dart
T

170 lines
4.3 KiB
Dart

/// Session role - whether this device is the host or a guest
enum SessionRole { host, guest }
/// Control mode - who can control playback
enum ControlMode {
/// Only the host can control playback
hostOnly,
/// Anyone in the session can control playback
anyone,
}
/// Current state of the watch together session
enum SessionState {
/// Not connected to any session
disconnected,
/// Attempting to connect/create session
connecting,
/// Successfully connected to session
connected,
/// Connection error occurred
error,
}
/// Represents a participant in a watch together session
class Participant {
final String peerId;
final String displayName;
final bool isHost;
final Duration lastKnownPosition;
final bool isBuffering;
const Participant({
required this.peerId,
required this.displayName,
required this.isHost,
this.lastKnownPosition = Duration.zero,
this.isBuffering = false,
});
Participant copyWith({
String? peerId,
String? displayName,
bool? isHost,
Duration? lastKnownPosition,
bool? isBuffering,
}) {
return Participant(
peerId: peerId ?? this.peerId,
displayName: displayName ?? this.displayName,
isHost: isHost ?? this.isHost,
lastKnownPosition: lastKnownPosition ?? this.lastKnownPosition,
isBuffering: isBuffering ?? this.isBuffering,
);
}
@override
bool operator ==(Object other) =>
identical(this, other) || other is Participant && runtimeType == other.runtimeType && peerId == other.peerId;
@override
int get hashCode => peerId.hashCode;
}
/// Represents a watch together session
class WatchSession {
/// Unique identifier for this session (used for joining)
final String sessionId;
/// This device's role in the session
final SessionRole role;
/// Who can control playback
final ControlMode controlMode;
/// Current connection state
final SessionState state;
/// Error message if state is error
final String? errorMessage;
/// Rating key of the media being watched (for validation)
final String? mediaRatingKey;
/// Server ID of the media being watched (same-server requirement)
final String? mediaServerId;
/// Title of the media being watched
final String? mediaTitle;
/// The host's peer ID (used to identify host messages)
final String? hostPeerId;
const WatchSession({
required this.sessionId,
required this.role,
required this.controlMode,
required this.state,
this.errorMessage,
this.mediaRatingKey,
this.mediaServerId,
this.mediaTitle,
this.hostPeerId,
});
/// Whether this device is the host
bool get isHost => role == SessionRole.host;
/// Whether the session is currently connected
bool get isConnected => state == SessionState.connected;
WatchSession copyWith({
String? sessionId,
SessionRole? role,
ControlMode? controlMode,
SessionState? state,
String? errorMessage,
String? mediaRatingKey,
String? mediaServerId,
String? mediaTitle,
String? hostPeerId,
}) {
return WatchSession(
sessionId: sessionId ?? this.sessionId,
role: role ?? this.role,
controlMode: controlMode ?? this.controlMode,
state: state ?? this.state,
errorMessage: errorMessage ?? this.errorMessage,
mediaRatingKey: mediaRatingKey ?? this.mediaRatingKey,
mediaServerId: mediaServerId ?? this.mediaServerId,
mediaTitle: mediaTitle ?? this.mediaTitle,
hostPeerId: hostPeerId ?? this.hostPeerId,
);
}
/// Create a new session as host
factory WatchSession.createAsHost({
required String sessionId,
required String hostPeerId,
required ControlMode controlMode,
String? mediaRatingKey,
String? mediaServerId,
String? mediaTitle,
}) {
return WatchSession(
sessionId: sessionId,
role: SessionRole.host,
controlMode: controlMode,
state: SessionState.connecting,
hostPeerId: hostPeerId,
mediaRatingKey: mediaRatingKey,
mediaServerId: mediaServerId,
mediaTitle: mediaTitle,
);
}
/// Create a session as guest (joining)
factory WatchSession.joinAsGuest({required String sessionId}) {
return WatchSession(
sessionId: sessionId,
role: SessionRole.guest,
controlMode: ControlMode.hostOnly, // Will be updated when connected
state: SessionState.connecting,
);
}
}