mirror of
https://github.com/gabehf/Fladder.git
synced 2026-03-07 21:48:14 -08:00
feature: Version selection (#235)
Co-authored-by: PartyDonut <PartyDonut@users.noreply.github.com>
This commit is contained in:
parent
935d6fe176
commit
f0414439f3
13 changed files with 142 additions and 60 deletions
|
|
@ -1178,5 +1178,6 @@
|
||||||
"homeStreamingQualityDesc": "Maximum streaming quality when connected to home network",
|
"homeStreamingQualityDesc": "Maximum streaming quality when connected to home network",
|
||||||
"qualityOptionsTitle": "Quality options",
|
"qualityOptionsTitle": "Quality options",
|
||||||
"qualityOptionsOriginal": "Original",
|
"qualityOptionsOriginal": "Original",
|
||||||
"qualityOptionsAuto": "Auto"
|
"qualityOptionsAuto": "Auto",
|
||||||
|
"version": "Version"
|
||||||
}
|
}
|
||||||
|
|
@ -173,8 +173,7 @@ class EpisodeModel extends ItemStreamModel with EpisodeModelMappable {
|
||||||
parentImages: ImagesData.fromBaseItemParent(item, ref),
|
parentImages: ImagesData.fromBaseItemParent(item, ref),
|
||||||
canDelete: item.canDelete,
|
canDelete: item.canDelete,
|
||||||
canDownload: item.canDownload,
|
canDownload: item.canDownload,
|
||||||
mediaStreams:
|
mediaStreams: MediaStreamsModel.fromMediaStreamsList(item.mediaSources, ref),
|
||||||
MediaStreamsModel.fromMediaStreamsList(item.mediaSources?.firstOrNull, item.mediaStreams ?? [], ref),
|
|
||||||
jellyType: item.type,
|
jellyType: item.type,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
import 'package:dart_mappable/dart_mappable.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart';
|
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart';
|
||||||
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart' as dto;
|
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart' as dto;
|
||||||
import 'package:fladder/models/item_base_model.dart';
|
import 'package:fladder/models/item_base_model.dart';
|
||||||
|
|
@ -7,9 +10,6 @@ import 'package:fladder/models/items/item_shared_models.dart';
|
||||||
import 'package:fladder/models/items/media_streams_model.dart';
|
import 'package:fladder/models/items/media_streams_model.dart';
|
||||||
import 'package:fladder/models/items/movie_model.dart';
|
import 'package:fladder/models/items/movie_model.dart';
|
||||||
import 'package:fladder/models/items/overview_model.dart';
|
import 'package:fladder/models/items/overview_model.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
||||||
|
|
||||||
import 'package:dart_mappable/dart_mappable.dart';
|
|
||||||
|
|
||||||
part 'item_stream_model.mapper.dart';
|
part 'item_stream_model.mapper.dart';
|
||||||
|
|
||||||
|
|
@ -55,8 +55,7 @@ class ItemStreamModel extends ItemBaseModel with ItemStreamModelMappable {
|
||||||
parentImages: ImagesData.fromBaseItemParent(item, ref),
|
parentImages: ImagesData.fromBaseItemParent(item, ref),
|
||||||
canDelete: item.canDelete,
|
canDelete: item.canDelete,
|
||||||
canDownload: item.canDownload,
|
canDownload: item.canDownload,
|
||||||
mediaStreams:
|
mediaStreams: MediaStreamsModel.fromMediaStreamsList(item.mediaSources, ref),
|
||||||
MediaStreamsModel.fromMediaStreamsList(item.mediaSources?.firstOrNull, item.mediaStreams ?? [], ref),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,19 +12,23 @@ import 'package:fladder/util/localization_helper.dart';
|
||||||
import 'package:fladder/util/video_properties.dart';
|
import 'package:fladder/util/video_properties.dart';
|
||||||
|
|
||||||
class MediaStreamsModel {
|
class MediaStreamsModel {
|
||||||
|
final int? versionStreamIndex;
|
||||||
final int? defaultAudioStreamIndex;
|
final int? defaultAudioStreamIndex;
|
||||||
final int? defaultSubStreamIndex;
|
final int? defaultSubStreamIndex;
|
||||||
final List<VideoStreamModel> videoStreams;
|
final List<VersionStreamModel> versionStreams;
|
||||||
final List<AudioStreamModel> audioStreams;
|
|
||||||
final List<SubStreamModel> subStreams;
|
|
||||||
MediaStreamsModel({
|
MediaStreamsModel({
|
||||||
|
this.versionStreamIndex,
|
||||||
this.defaultAudioStreamIndex,
|
this.defaultAudioStreamIndex,
|
||||||
this.defaultSubStreamIndex,
|
this.defaultSubStreamIndex,
|
||||||
required this.videoStreams,
|
required this.versionStreams,
|
||||||
required this.audioStreams,
|
|
||||||
required this.subStreams,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
VersionStreamModel? get currentVersionStream => versionStreams.elementAtOrNull(versionStreamIndex ?? 0);
|
||||||
|
|
||||||
|
List<VideoStreamModel> get videoStreams => currentVersionStream?.videoStreams ?? [];
|
||||||
|
List<AudioStreamModel> get audioStreams => currentVersionStream?.audioStreams ?? [];
|
||||||
|
List<SubStreamModel> get subStreams => currentVersionStream?.subStreams ?? [];
|
||||||
|
|
||||||
bool get isNull {
|
bool get isNull {
|
||||||
return defaultAudioStreamIndex == null ||
|
return defaultAudioStreamIndex == null ||
|
||||||
defaultSubStreamIndex == null ||
|
defaultSubStreamIndex == null ||
|
||||||
|
|
@ -92,44 +96,61 @@ class MediaStreamsModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
static MediaStreamsModel fromMediaStreamsList(
|
static MediaStreamsModel fromMediaStreamsList(
|
||||||
dto.MediaSourceInfo? mediaSource, List<dto.MediaStream> streams, Ref ref) {
|
List<dto.MediaSourceInfo>? mediaSource,
|
||||||
|
Ref ref,
|
||||||
|
) {
|
||||||
return MediaStreamsModel(
|
return MediaStreamsModel(
|
||||||
defaultAudioStreamIndex: mediaSource?.defaultAudioStreamIndex,
|
defaultAudioStreamIndex: mediaSource?.firstOrNull?.defaultAudioStreamIndex,
|
||||||
defaultSubStreamIndex: mediaSource?.defaultSubtitleStreamIndex,
|
defaultSubStreamIndex: mediaSource?.firstOrNull?.defaultSubtitleStreamIndex,
|
||||||
videoStreams: streams
|
versionStreams: mediaSource?.mapIndexed(
|
||||||
.where((element) => element.type == dto.MediaStreamType.video)
|
(index, element) {
|
||||||
.map(
|
final streams = element.mediaStreams ?? [];
|
||||||
(e) => VideoStreamModel.fromMediaStream(e),
|
return VersionStreamModel(
|
||||||
)
|
name: element.name ?? "",
|
||||||
.sortByExternal(),
|
index: index,
|
||||||
audioStreams: streams
|
id: element.id,
|
||||||
.where((element) => element.type == dto.MediaStreamType.audio)
|
defaultAudioStreamIndex: element.defaultAudioStreamIndex,
|
||||||
.map(
|
defaultSubStreamIndex: element.defaultSubtitleStreamIndex,
|
||||||
(e) => AudioStreamModel.fromMediaStream(e),
|
videoStreams: streams
|
||||||
)
|
.where((element) => element.type == dto.MediaStreamType.video)
|
||||||
.sortByExternal(),
|
.map(
|
||||||
subStreams: streams
|
(e) => VideoStreamModel.fromMediaStream(e),
|
||||||
.where((element) => element.type == dto.MediaStreamType.subtitle)
|
)
|
||||||
.map(
|
.sortByExternal(),
|
||||||
(sub) => SubStreamModel.fromMediaStream(sub, ref),
|
audioStreams: streams
|
||||||
)
|
.where((element) => element.type == dto.MediaStreamType.audio)
|
||||||
.sortByExternal(),
|
.map(
|
||||||
);
|
(e) => AudioStreamModel.fromMediaStream(e),
|
||||||
|
)
|
||||||
|
.sortByExternal(),
|
||||||
|
subStreams: streams
|
||||||
|
.where((element) => element.type == dto.MediaStreamType.subtitle)
|
||||||
|
.map(
|
||||||
|
(sub) => SubStreamModel.fromMediaStream(sub, ref),
|
||||||
|
)
|
||||||
|
.sortByExternal());
|
||||||
|
},
|
||||||
|
).toList() ??
|
||||||
|
[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaStreamsModel copyWith({
|
MediaStreamsModel copyWith({
|
||||||
|
int? versionStreamIndex,
|
||||||
int? defaultAudioStreamIndex,
|
int? defaultAudioStreamIndex,
|
||||||
int? defaultSubStreamIndex,
|
int? defaultSubStreamIndex,
|
||||||
List<VideoStreamModel>? videoStreams,
|
List<VersionStreamModel>? versionStreams,
|
||||||
List<AudioStreamModel>? audioStreams,
|
|
||||||
List<SubStreamModel>? subStreams,
|
|
||||||
}) {
|
}) {
|
||||||
|
final streamIndexChanged = versionStreamIndex != this.versionStreamIndex && versionStreamIndex != null;
|
||||||
|
final currentVersionStreams = versionStreams ?? this.versionStreams;
|
||||||
return MediaStreamsModel(
|
return MediaStreamsModel(
|
||||||
defaultAudioStreamIndex: defaultAudioStreamIndex ?? this.defaultAudioStreamIndex,
|
versionStreamIndex: versionStreamIndex ?? this.versionStreamIndex,
|
||||||
defaultSubStreamIndex: defaultSubStreamIndex ?? this.defaultSubStreamIndex,
|
defaultAudioStreamIndex: streamIndexChanged
|
||||||
videoStreams: videoStreams ?? this.videoStreams,
|
? currentVersionStreams.elementAtOrNull(versionStreamIndex)?.defaultAudioStreamIndex
|
||||||
audioStreams: audioStreams ?? this.audioStreams,
|
: defaultAudioStreamIndex ?? this.defaultAudioStreamIndex,
|
||||||
subStreams: subStreams ?? this.subStreams,
|
defaultSubStreamIndex: streamIndexChanged
|
||||||
|
? currentVersionStreams.elementAtOrNull(versionStreamIndex)?.defaultSubStreamIndex
|
||||||
|
: defaultSubStreamIndex ?? this.defaultSubStreamIndex,
|
||||||
|
versionStreams: versionStreams ?? this.versionStreams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -154,6 +175,28 @@ class StreamModel {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class VersionStreamModel {
|
||||||
|
final String name;
|
||||||
|
final int index;
|
||||||
|
final String? id;
|
||||||
|
final int? defaultAudioStreamIndex;
|
||||||
|
final int? defaultSubStreamIndex;
|
||||||
|
final List<VideoStreamModel> videoStreams;
|
||||||
|
final List<AudioStreamModel> audioStreams;
|
||||||
|
final List<SubStreamModel> subStreams;
|
||||||
|
|
||||||
|
VersionStreamModel({
|
||||||
|
required this.name,
|
||||||
|
required this.index,
|
||||||
|
this.id,
|
||||||
|
required this.defaultAudioStreamIndex,
|
||||||
|
required this.defaultSubStreamIndex,
|
||||||
|
required this.videoStreams,
|
||||||
|
required this.audioStreams,
|
||||||
|
required this.subStreams,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
class VideoStreamModel extends StreamModel {
|
class VideoStreamModel extends StreamModel {
|
||||||
final int width;
|
final int width;
|
||||||
final int height;
|
final int height;
|
||||||
|
|
|
||||||
|
|
@ -96,8 +96,7 @@ class MovieModel extends ItemStreamModel with MovieModelMappable {
|
||||||
parentImages: ImagesData.fromBaseItemParent(item, ref),
|
parentImages: ImagesData.fromBaseItemParent(item, ref),
|
||||||
canDelete: item.canDelete,
|
canDelete: item.canDelete,
|
||||||
canDownload: item.canDownload,
|
canDownload: item.canDownload,
|
||||||
mediaStreams:
|
mediaStreams: MediaStreamsModel.fromMediaStreamsList(item.mediaSources, ref),
|
||||||
MediaStreamsModel.fromMediaStreamsList(item.mediaSources?.firstOrNull, item.mediaStreams ?? [], ref),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -210,7 +210,7 @@ class PlaybackModelHelper {
|
||||||
enableDirectPlay: type != PlaybackType.transcode,
|
enableDirectPlay: type != PlaybackType.transcode,
|
||||||
enableDirectStream: type != PlaybackType.transcode,
|
enableDirectStream: type != PlaybackType.transcode,
|
||||||
maxStreamingBitrate: qualityOptions.enabledFirst.keys.firstOrNull?.bitRate,
|
maxStreamingBitrate: qualityOptions.enabledFirst.keys.firstOrNull?.bitRate,
|
||||||
mediaSourceId: firstItemToPlay.id,
|
mediaSourceId: streamModel?.currentVersionStream?.id,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -219,9 +219,7 @@ class PlaybackModelHelper {
|
||||||
|
|
||||||
final mediaSource = playbackInfo.mediaSources?.first;
|
final mediaSource = playbackInfo.mediaSources?.first;
|
||||||
|
|
||||||
final mediaStreamsWithUrls = MediaStreamsModel.fromMediaStreamsList(
|
final mediaStreamsWithUrls = MediaStreamsModel.fromMediaStreamsList(playbackInfo.mediaSources, ref).copyWith(
|
||||||
playbackInfo.mediaSources?.firstOrNull, playbackInfo.mediaSources?.firstOrNull?.mediaStreams ?? [], ref)
|
|
||||||
.copyWith(
|
|
||||||
defaultAudioStreamIndex: streamModel?.defaultAudioStreamIndex,
|
defaultAudioStreamIndex: streamModel?.defaultAudioStreamIndex,
|
||||||
defaultSubStreamIndex: streamModel?.defaultSubStreamIndex,
|
defaultSubStreamIndex: streamModel?.defaultSubStreamIndex,
|
||||||
);
|
);
|
||||||
|
|
@ -352,9 +350,7 @@ class PlaybackModelHelper {
|
||||||
|
|
||||||
final mediaSource = playbackInfo.mediaSources?.first;
|
final mediaSource = playbackInfo.mediaSources?.first;
|
||||||
|
|
||||||
final mediaStreamsWithUrls = MediaStreamsModel.fromMediaStreamsList(
|
final mediaStreamsWithUrls = MediaStreamsModel.fromMediaStreamsList(playbackInfo.mediaSources, ref).copyWith(
|
||||||
playbackInfo.mediaSources?.firstOrNull, playbackInfo.mediaSources?.firstOrNull?.mediaStreams ?? [], ref)
|
|
||||||
.copyWith(
|
|
||||||
defaultAudioStreamIndex: audioIndex,
|
defaultAudioStreamIndex: audioIndex,
|
||||||
defaultSubStreamIndex: subIndex,
|
defaultSubStreamIndex: subIndex,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -199,8 +199,7 @@ class VideoStream {
|
||||||
playbackUrl: playbackUrl,
|
playbackUrl: playbackUrl,
|
||||||
playbackType: playType,
|
playbackType: playType,
|
||||||
playSessionId: info.playSessionId ?? "",
|
playSessionId: info.playSessionId ?? "",
|
||||||
mediaStreamsModel: MediaStreamsModel.fromMediaStreamsList(
|
mediaStreamsModel: MediaStreamsModel.fromMediaStreamsList(info.mediaSources, ref),
|
||||||
info.mediaSources?.firstOrNull, info.mediaSources?.firstOrNull?.mediaStreams ?? [], ref),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -106,4 +106,12 @@ class EpisodeDetailsProvider extends StateNotifier<EpisodeDetailModel> {
|
||||||
defaultAudioStreamIndex: index,
|
defaultAudioStreamIndex: index,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setVersionIndex(int index) {
|
||||||
|
state = state.copyWith(
|
||||||
|
episode: state.episode?.copyWith(
|
||||||
|
mediaStreams: state.episode?.mediaStreams.copyWith(
|
||||||
|
versionStreamIndex: index,
|
||||||
|
)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
import 'package:chopper/chopper.dart';
|
import 'package:chopper/chopper.dart';
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
import 'package:fladder/models/item_base_model.dart';
|
import 'package:fladder/models/item_base_model.dart';
|
||||||
import 'package:fladder/models/items/movie_model.dart';
|
import 'package:fladder/models/items/movie_model.dart';
|
||||||
import 'package:fladder/providers/api_provider.dart';
|
import 'package:fladder/providers/api_provider.dart';
|
||||||
import 'package:fladder/providers/related_provider.dart';
|
import 'package:fladder/providers/related_provider.dart';
|
||||||
import 'package:fladder/providers/service_provider.dart';
|
import 'package:fladder/providers/service_provider.dart';
|
||||||
import 'package:fladder/providers/sync_provider.dart';
|
import 'package:fladder/providers/sync_provider.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|
||||||
|
|
||||||
part 'movies_details_provider.g.dart';
|
part 'movies_details_provider.g.dart';
|
||||||
|
|
||||||
|
|
@ -49,4 +50,8 @@ class MovieDetails extends _$MovieDetails {
|
||||||
void setAudioIndex(int index) {
|
void setAudioIndex(int index) {
|
||||||
state = state?.copyWith(mediaStreams: state?.mediaStreams.copyWith(defaultAudioStreamIndex: index));
|
state = state?.copyWith(mediaStreams: state?.mediaStreams.copyWith(defaultAudioStreamIndex: index));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setVersionIndex(int index) {
|
||||||
|
state = state?.copyWith(mediaStreams: state?.mediaStreams.copyWith(versionStreamIndex: index));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,16 @@ import 'package:fladder/util/localization_helper.dart';
|
||||||
|
|
||||||
class MediaStreamInformation extends ConsumerWidget {
|
class MediaStreamInformation extends ConsumerWidget {
|
||||||
final MediaStreamsModel mediaStream;
|
final MediaStreamsModel mediaStream;
|
||||||
|
final Function(int index)? onVersionIndexChanged;
|
||||||
final Function(int index)? onAudioIndexChanged;
|
final Function(int index)? onAudioIndexChanged;
|
||||||
final Function(int index)? onSubIndexChanged;
|
final Function(int index)? onSubIndexChanged;
|
||||||
const MediaStreamInformation(
|
const MediaStreamInformation({
|
||||||
{required this.mediaStream, this.onAudioIndexChanged, this.onSubIndexChanged, super.key});
|
required this.mediaStream,
|
||||||
|
required this.onVersionIndexChanged,
|
||||||
|
this.onAudioIndexChanged,
|
||||||
|
this.onSubIndexChanged,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
|
@ -19,6 +25,23 @@ class MediaStreamInformation extends ConsumerWidget {
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
|
if (mediaStream.versionStreams.isNotEmpty && mediaStream.versionStreams.length > 1)
|
||||||
|
_StreamOptionSelect(
|
||||||
|
label: Text(context.localized.version),
|
||||||
|
current: mediaStream.currentVersionStream?.name ?? "",
|
||||||
|
itemBuilder: (context) => mediaStream.versionStreams
|
||||||
|
.map((e) => PopupMenuItem(
|
||||||
|
value: e,
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
child: textWidget(
|
||||||
|
context,
|
||||||
|
selected: mediaStream.currentVersionStream == e,
|
||||||
|
label: e.name,
|
||||||
|
),
|
||||||
|
onTap: () => onVersionIndexChanged?.call(e.index),
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
if (mediaStream.videoStreams.isNotEmpty)
|
if (mediaStream.videoStreams.isNotEmpty)
|
||||||
_StreamOptionSelect(
|
_StreamOptionSelect(
|
||||||
label: Text(context.localized.video),
|
label: Text(context.localized.video),
|
||||||
|
|
@ -112,6 +135,7 @@ class _StreamOptionSelect<T> extends StatelessWidget {
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
||||||
enabled: itemList.length > 1,
|
enabled: itemList.length > 1,
|
||||||
itemBuilder: itemBuilder,
|
itemBuilder: itemBuilder,
|
||||||
|
enableFeedback: false,
|
||||||
menuPadding: const EdgeInsets.symmetric(vertical: 16),
|
menuPadding: const EdgeInsets.symmetric(vertical: 16),
|
||||||
padding: padding,
|
padding: padding,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,9 @@ class _ItemDetailScreenState extends ConsumerState<EpisodeDetailScreen> {
|
||||||
padding: padding,
|
padding: padding,
|
||||||
child: MediaStreamInformation(
|
child: MediaStreamInformation(
|
||||||
mediaStream: details.episode!.mediaStreams,
|
mediaStream: details.episode!.mediaStreams,
|
||||||
|
onVersionIndexChanged: (index) {
|
||||||
|
ref.read(providerInstance.notifier).setVersionIndex(index);
|
||||||
|
},
|
||||||
onSubIndexChanged: (index) {
|
onSubIndexChanged: (index) {
|
||||||
ref.read(providerInstance.notifier).setSubIndex(index);
|
ref.read(providerInstance.notifier).setSubIndex(index);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
import 'package:fladder/models/settings/home_settings_model.dart';
|
|
||||||
import 'package:fladder/util/adaptive_layout.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:auto_route/auto_route.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
|
|
@ -7,6 +5,7 @@ import 'package:ficonsax/ficonsax.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
import 'package:fladder/models/item_base_model.dart';
|
import 'package:fladder/models/item_base_model.dart';
|
||||||
|
import 'package:fladder/models/settings/home_settings_model.dart';
|
||||||
import 'package:fladder/providers/items/movies_details_provider.dart';
|
import 'package:fladder/providers/items/movies_details_provider.dart';
|
||||||
import 'package:fladder/providers/user_provider.dart';
|
import 'package:fladder/providers/user_provider.dart';
|
||||||
import 'package:fladder/screens/details_screens/components/media_stream_information.dart';
|
import 'package:fladder/screens/details_screens/components/media_stream_information.dart';
|
||||||
|
|
@ -18,6 +17,7 @@ import 'package:fladder/screens/shared/media/expanding_overview.dart';
|
||||||
import 'package:fladder/screens/shared/media/external_urls.dart';
|
import 'package:fladder/screens/shared/media/external_urls.dart';
|
||||||
import 'package:fladder/screens/shared/media/people_row.dart';
|
import 'package:fladder/screens/shared/media/people_row.dart';
|
||||||
import 'package:fladder/screens/shared/media/poster_row.dart';
|
import 'package:fladder/screens/shared/media/poster_row.dart';
|
||||||
|
import 'package:fladder/util/adaptive_layout.dart';
|
||||||
import 'package:fladder/util/item_base_model/item_base_model_extensions.dart';
|
import 'package:fladder/util/item_base_model/item_base_model_extensions.dart';
|
||||||
import 'package:fladder/util/item_base_model/play_item_helpers.dart';
|
import 'package:fladder/util/item_base_model/play_item_helpers.dart';
|
||||||
import 'package:fladder/util/list_padding.dart';
|
import 'package:fladder/util/list_padding.dart';
|
||||||
|
|
@ -126,6 +126,9 @@ class _ItemDetailScreenState extends ConsumerState<MovieDetailScreen> {
|
||||||
).padding(padding),
|
).padding(padding),
|
||||||
if (details.mediaStreams.isNotEmpty)
|
if (details.mediaStreams.isNotEmpty)
|
||||||
MediaStreamInformation(
|
MediaStreamInformation(
|
||||||
|
onVersionIndexChanged: (index) {
|
||||||
|
ref.read(providerInstance.notifier).setVersionIndex(index);
|
||||||
|
},
|
||||||
onSubIndexChanged: (index) {
|
onSubIndexChanged: (index) {
|
||||||
ref.read(providerInstance.notifier).setSubIndex(index);
|
ref.read(providerInstance.notifier).setSubIndex(index);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,9 @@ class NextUpEpisode extends ConsumerWidget {
|
||||||
children: [
|
children: [
|
||||||
MediaStreamInformation(
|
MediaStreamInformation(
|
||||||
mediaStream: nextEpisode.mediaStreams,
|
mediaStream: nextEpisode.mediaStreams,
|
||||||
|
onVersionIndexChanged: (index) => onChanged?.call(nextEpisode.copyWith(
|
||||||
|
mediaStreams: nextEpisode.mediaStreams.copyWith(versionStreamIndex: index),
|
||||||
|
)),
|
||||||
onAudioIndexChanged: (index) => onChanged?.call(nextEpisode.copyWith(
|
onAudioIndexChanged: (index) => onChanged?.call(nextEpisode.copyWith(
|
||||||
mediaStreams: nextEpisode.mediaStreams.copyWith(defaultAudioStreamIndex: index))),
|
mediaStreams: nextEpisode.mediaStreams.copyWith(defaultAudioStreamIndex: index))),
|
||||||
onSubIndexChanged: (index) => onChanged?.call(nextEpisode.copyWith(
|
onSubIndexChanged: (index) => onChanged?.call(nextEpisode.copyWith(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue