Files
MatchLiveTv/mobile/lib/providers/session_provider.dart
Emiliano Frascaro 1d67459bbe YouTube come destinazione pubblica, non Match Live TV.
Non propone più il link MLTV per sessioni YouTube; la pagina /live
reindirizza a YouTube; il relay verso YouTube si riavvia al connect.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 07:25:07 +02:00

194 lines
5.5 KiB
Dart

import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../shared/models/device_state.dart';
import '../shared/models/match.dart';
import '../shared/models/stream_session.dart';
class SessionState {
const SessionState({
this.session,
this.match,
this.elapsed = Duration.zero,
this.connected = false,
this.cameraDevice,
this.viewerCount = 0,
});
final StreamSession? session;
final MatchModel? match;
final Duration elapsed;
final bool connected;
final DeviceStateModel? cameraDevice;
final int viewerCount;
SessionState copyWith({
StreamSession? session,
MatchModel? match,
Duration? elapsed,
bool? connected,
DeviceStateModel? cameraDevice,
int? viewerCount,
}) {
return SessionState(
session: session ?? this.session,
match: match ?? this.match,
elapsed: elapsed ?? this.elapsed,
connected: connected ?? this.connected,
cameraDevice: cameraDevice ?? this.cameraDevice,
viewerCount: viewerCount ?? this.viewerCount,
);
}
}
class SessionNotifier extends StateNotifier<SessionState> {
SessionNotifier() : super(const SessionState());
void setSession(StreamSession session, {MatchModel? match}) {
state = state.copyWith(session: session, match: match);
}
void updateYoutubeLinks({
required String? youtubeWatchUrl,
required String? shareUrl,
String? youtubeBroadcastId,
bool youtubeReady = true,
}) {
final s = state.session;
if (s == null || s.platform != 'youtube') return;
state = state.copyWith(
session: StreamSession(
id: s.id,
matchId: s.matchId,
status: s.status,
platform: s.platform,
rtmpIngestUrl: s.rtmpIngestUrl,
hlsPlaybackUrl: s.hlsPlaybackUrl,
watchPageUrl: s.watchPageUrl,
shareUrl: shareUrl,
youtubeWatchUrl: youtubeWatchUrl,
youtubeBroadcastId: youtubeBroadcastId ?? s.youtubeBroadcastId,
youtubeReady: youtubeReady,
privacyStatus: s.privacyStatus,
qualityPreset: s.qualityPreset,
targetBitrate: s.targetBitrate,
startedAt: s.startedAt,
disconnectionCount: s.disconnectionCount,
score: s.score,
devices: s.devices,
),
);
}
void setMatch(MatchModel match) {
state = state.copyWith(match: match);
}
void setElapsed(Duration elapsed) {
state = state.copyWith(elapsed: elapsed);
}
void setConnected(bool connected) {
state = state.copyWith(connected: connected);
}
void setCameraDevice(DeviceStateModel? device) {
state = state.copyWith(cameraDevice: device);
}
void setViewerCount(int count) {
state = state.copyWith(viewerCount: count);
}
void updateDeviceState(DeviceStateModel device) {
if (device.deviceRole == 'camera') {
state = state.copyWith(cameraDevice: device);
}
if (device.status != null && state.session != null) {
final s = state.session!;
final incoming = device.status!;
// Non sovrascrivere una pausa intenzionale con stati transitori (live/connecting).
if (s.status == 'paused' && incoming != 'paused' && incoming != 'ended') {
state = state.copyWith(cameraDevice: device);
return;
}
state = state.copyWith(
session: StreamSession(
id: s.id,
matchId: s.matchId,
status: incoming,
platform: s.platform,
rtmpIngestUrl: s.rtmpIngestUrl,
hlsPlaybackUrl: s.hlsPlaybackUrl,
watchPageUrl: s.watchPageUrl,
shareUrl: s.shareUrl,
youtubeWatchUrl: s.youtubeWatchUrl,
youtubeBroadcastId: s.youtubeBroadcastId,
youtubeReady: s.youtubeReady,
privacyStatus: s.privacyStatus,
qualityPreset: s.qualityPreset,
targetBitrate: s.targetBitrate,
startedAt: s.startedAt,
disconnectionCount: s.disconnectionCount,
score: s.score,
devices: s.devices,
),
);
}
}
void applyCommand(String action) {
final session = state.session;
if (session == null) return;
String newStatus = session.status;
switch (action) {
case 'start_stream':
newStatus = 'live';
break;
case 'pause_stream':
newStatus = 'paused';
break;
case 'resume_stream':
newStatus = 'connecting';
break;
case 'stop_stream':
newStatus = 'ended';
break;
}
if (newStatus != session.status) {
state = state.copyWith(
session: StreamSession(
id: session.id,
matchId: session.matchId,
status: newStatus,
platform: session.platform,
rtmpIngestUrl: session.rtmpIngestUrl,
hlsPlaybackUrl: session.hlsPlaybackUrl,
watchPageUrl: session.watchPageUrl,
shareUrl: session.shareUrl,
youtubeWatchUrl: session.youtubeWatchUrl,
youtubeBroadcastId: session.youtubeBroadcastId,
youtubeReady: session.youtubeReady,
privacyStatus: session.privacyStatus,
qualityPreset: session.qualityPreset,
targetBitrate: session.targetBitrate,
startedAt: session.startedAt,
disconnectionCount: session.disconnectionCount,
score: session.score,
devices: session.devices,
),
);
}
}
void clear() {
state = const SessionState();
}
}
final sessionProvider =
StateNotifierProvider<SessionNotifier, SessionState>((ref) {
return SessionNotifier();
});