import 'dart:async'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../core/domain/usecases/usecase_helpers.dart'; import '../core/infra/emby_api/playback_resolver.dart'; import '../shared/utils/app_logger.dart'; import 'di_providers.dart'; const _tag = 'PlaybackInfoPrefetch'; typedef PlaybackInfoPrefetchKey = ({ String serverId, String itemId, String? mediaSourceId, int startTimeTicks, }); typedef PlaybackInfoPrefetchPayload = ({ String serverId, String itemId, String? mediaSourceId, int startTimeTicks, Map info, }); String describePlaybackInfoPrefetchKey(PlaybackInfoPrefetchKey key) { return 'serverId=${key.serverId} itemId=${key.itemId} ' 'mediaSourceId=${key.mediaSourceId ?? '-'} ' 'startTimeTicks=${key.startTimeTicks}'; } final playbackInfoPrefetchProvider = FutureProvider.autoDispose .family(( ref, key, ) async { final keepAlive = ref.keepAlive(); Timer? cacheTimer; var disposed = false; ref.onDispose(() { disposed = true; cacheTimer?.cancel(); }); try { AppLogger.debug( _tag, 'fetch start ${describePlaybackInfoPrefetchKey(key)}', ); final gateway = await ref.read(embyGatewayProvider.future); final sessionRepo = await ref.read(sessionRepositoryProvider.future); final serverRepo = await ref.read(serverRepositoryProvider.future); final ctx = await resolveAuthedContextForServer( sessionRepository: sessionRepo, serverRepository: serverRepo, serverId: key.serverId, ); if (ctx == null) { AppLogger.debug( _tag, 'fetch skipped missing auth ${describePlaybackInfoPrefetchKey(key)}', ); return null; } final info = await gateway.fetchPlaybackInfo( ctx: ctx, itemId: key.itemId, mediaSourceId: key.mediaSourceId, startTimeTicks: key.startTimeTicks, isPlayback: true, deviceProfile: PlaybackResolver.deviceProfile(), ); if (info.isEmpty) { AppLogger.debug( _tag, 'fetch empty ${describePlaybackInfoPrefetchKey(key)}', ); return null; } AppLogger.debug( _tag, 'fetch success ${describePlaybackInfoPrefetchKey(key)} ' 'payloadKeys=${info.length}', ); return ( serverId: key.serverId, itemId: key.itemId, mediaSourceId: key.mediaSourceId, startTimeTicks: key.startTimeTicks, info: info, ); } catch (e) { AppLogger.debug( _tag, 'fetch failed ${describePlaybackInfoPrefetchKey(key)}', e, ); return null; } finally { if (!disposed) { cacheTimer = Timer(const Duration(minutes: 2), keepAlive.close); } } });