Initial commit

This commit is contained in:
admin1
2026-07-14 11:11:36 +08:00
commit 656499cf94
604 changed files with 119518 additions and 0 deletions
@@ -0,0 +1,104 @@
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);
}
}
});