Plain Play requests the default media version (index 0 or the saved preference), but the offline resolvers rejected the single downloaded row when a non-default version was downloaded, then threw "No video URL available" with no client to fall back to. Three-part fix sharing one matcher (downloadedVersionMatches): - getPlaybackData falls back to the downloaded version when there is no client to stream from; the result now carries the effective mediaIndex/mediaSourceId so cached media info and the committed session describe the file actually played. - navigateToVideoPlayer seeds the selection from the download record for isOffline plays with no explicit version, covering the external player branch and offline-library plays with a reachable server. - PlaybackSession.fromContext prefers the result source id over the requested one, keeping in-player state in sync after a fallback. Online pinning is untouched: with a live client an explicitly requested non-downloaded version still streams from the server.
31 lines
1.1 KiB
Dart
31 lines
1.1 KiB
Dart
import '../database/app_database.dart';
|
|
|
|
/// Single source of truth for "does this downloaded row satisfy a version
|
|
/// request".
|
|
///
|
|
/// Source-id comparison wins when both sides have one — Jellyfin merged
|
|
/// versions can reorder between item fetches, so the stable id is the only
|
|
/// trustworthy discriminator there. Otherwise fall back to the media index.
|
|
/// A null [requestedMediaIndex] means "any version" (the caller has no
|
|
/// version opinion, e.g. external-player launches keyed by item only).
|
|
bool downloadedVersionMatches(
|
|
DownloadedMediaItem row, {
|
|
int? requestedMediaIndex,
|
|
String? requestedMediaSourceId,
|
|
}) {
|
|
final downloadedSourceId = row.mediaSourceId;
|
|
final requestedSourceId = requestedMediaSourceId?.trim();
|
|
final comparedBySourceId =
|
|
requestedSourceId != null &&
|
|
requestedSourceId.isNotEmpty &&
|
|
downloadedSourceId != null &&
|
|
downloadedSourceId.isNotEmpty;
|
|
if (comparedBySourceId) {
|
|
return downloadedSourceId == requestedSourceId;
|
|
}
|
|
if (requestedMediaIndex == null) {
|
|
return true;
|
|
}
|
|
return row.mediaIndex == requestedMediaIndex;
|
|
}
|