105 lines
3.0 KiB
Dart
105 lines
3.0 KiB
Dart
|
|
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<String, dynamic> info,
|
||
|
|
});
|
||
|
|
|
||
|
|
String describePlaybackInfoPrefetchKey(PlaybackInfoPrefetchKey key) {
|
||
|
|
return 'serverId=${key.serverId} itemId=${key.itemId} '
|
||
|
|
'mediaSourceId=${key.mediaSourceId ?? '-'} '
|
||
|
|
'startTimeTicks=${key.startTimeTicks}';
|
||
|
|
}
|
||
|
|
|
||
|
|
final playbackInfoPrefetchProvider = FutureProvider.autoDispose
|
||
|
|
.family<PlaybackInfoPrefetchPayload?, PlaybackInfoPrefetchKey>((
|
||
|
|
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);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|