mirror of
https://github.com/gabehf/Fladder.git
synced 2026-03-07 21:48:14 -08:00
106 lines
4.4 KiB
Dart
106 lines
4.4 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
|
|
|
|
import 'package:fladder/models/items/episode_model.dart';
|
|
import 'package:fladder/screens/details_screens/components/media_stream_information.dart';
|
|
import 'package:fladder/screens/shared/media/episode_posters.dart';
|
|
import 'package:fladder/util/adaptive_layout/adaptive_layout.dart';
|
|
import 'package:fladder/util/localization_helper.dart';
|
|
import 'package:fladder/util/sticky_header_text.dart';
|
|
import 'package:fladder/util/string_extensions.dart';
|
|
|
|
class NextUpEpisode extends ConsumerWidget {
|
|
final EpisodeModel nextEpisode;
|
|
final Function(EpisodeModel episode)? onChanged;
|
|
const NextUpEpisode({required this.nextEpisode, this.onChanged, super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final alreadyPlayed = nextEpisode.userData.played;
|
|
final episodeSummary = nextEpisode.overview.summary.maxLength(limitTo: 250);
|
|
final style = Theme.of(context).textTheme.titleMedium;
|
|
return Column(
|
|
mainAxisSize: MainAxisSize.max,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
StickyHeaderText(
|
|
label: alreadyPlayed ? context.localized.reWatch : context.localized.nextUp,
|
|
),
|
|
SelectableText(
|
|
nextEpisode.seasonEpisodeLabelFull(context),
|
|
style: style?.copyWith(
|
|
color: Theme.of(context).colorScheme.onSurface.withValues(alpha: 0.75),
|
|
),
|
|
),
|
|
SelectableText(
|
|
nextEpisode.name,
|
|
style: Theme.of(context).textTheme.titleMedium,
|
|
),
|
|
const SizedBox(height: 16),
|
|
LayoutBuilder(
|
|
builder: (context, constraints) {
|
|
if (constraints.maxWidth < 550) {
|
|
return Column(
|
|
children: [
|
|
EpisodePoster(
|
|
episode: nextEpisode,
|
|
showLabel: false,
|
|
onTap: () => nextEpisode.navigateTo(context),
|
|
actions: const [],
|
|
isCurrentEpisode: false,
|
|
),
|
|
const SizedBox(height: 16),
|
|
if (nextEpisode.overview.summary.isNotEmpty)
|
|
HtmlWidget(
|
|
episodeSummary,
|
|
textStyle: Theme.of(context).textTheme.titleMedium,
|
|
),
|
|
],
|
|
);
|
|
} else {
|
|
return Row(
|
|
children: [
|
|
ConstrainedBox(
|
|
constraints: BoxConstraints(
|
|
maxHeight: AdaptiveLayout.poster(context).gridRatio,
|
|
maxWidth: MediaQuery.of(context).size.width / 2),
|
|
child: EpisodePoster(
|
|
episode: nextEpisode,
|
|
showLabel: false,
|
|
onTap: () => nextEpisode.navigateTo(context),
|
|
actions: const [],
|
|
isCurrentEpisode: false,
|
|
),
|
|
),
|
|
const SizedBox(width: 32),
|
|
Flexible(
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
MediaStreamInformation(
|
|
mediaStream: nextEpisode.mediaStreams,
|
|
onVersionIndexChanged: (index) => onChanged?.call(nextEpisode.copyWith(
|
|
mediaStreams: nextEpisode.mediaStreams.copyWith(versionStreamIndex: index),
|
|
)),
|
|
onAudioIndexChanged: (index) => onChanged?.call(nextEpisode.copyWith(
|
|
mediaStreams: nextEpisode.mediaStreams.copyWith(defaultAudioStreamIndex: index))),
|
|
onSubIndexChanged: (index) => onChanged?.call(nextEpisode.copyWith(
|
|
mediaStreams: nextEpisode.mediaStreams.copyWith(defaultSubStreamIndex: index))),
|
|
),
|
|
if (nextEpisode.overview.summary.isNotEmpty)
|
|
HtmlWidget(episodeSummary, textStyle: Theme.of(context).textTheme.titleMedium),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
},
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|