fix(tv): fade media detail transitions
This commit is contained in:
@@ -101,6 +101,24 @@ class MediaDetailScreen extends StatefulWidget {
|
||||
State<MediaDetailScreen> createState() => _MediaDetailScreenState();
|
||||
}
|
||||
|
||||
PageRoute<bool> mediaDetailRoute({required MediaItem metadata, bool isOffline = false, int? initialSeasonIndex}) {
|
||||
final page = MediaDetailScreen(metadata: metadata, isOffline: isOffline, initialSeasonIndex: initialSeasonIndex);
|
||||
if (!PlatformDetector.isTV()) return MaterialPageRoute<bool>(builder: (_) => page);
|
||||
|
||||
return PageRouteBuilder<bool>(
|
||||
opaque: false,
|
||||
pageBuilder: (_, __, ___) => page,
|
||||
transitionsBuilder: (_, animation, __, child) {
|
||||
return FadeTransition(
|
||||
opacity: CurvedAnimation(parent: animation, curve: Curves.easeOutCubic, reverseCurve: Curves.easeInCubic),
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
transitionDuration: AppDurations.animMedium,
|
||||
reverseTransitionDuration: AppDurations.animMedium,
|
||||
);
|
||||
}
|
||||
|
||||
class _MediaDetailScreenState extends State<MediaDetailScreen>
|
||||
with WatchStateAware, DeletionAware, MountedSetStateMixin, ServerBoundMediaMixin, RouteAware {
|
||||
/// Public input alias — used as the live source of truth until the detail
|
||||
|
||||
@@ -131,10 +131,7 @@ Future<MediaNavigationResult> navigateToMediaItem(
|
||||
);
|
||||
final result = await Navigator.push<bool>(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
MediaDetailScreen(metadata: showStub, isOffline: isOffline, initialSeasonIndex: mi.index),
|
||||
),
|
||||
mediaDetailRoute(metadata: showStub, isOffline: isOffline, initialSeasonIndex: mi.index),
|
||||
);
|
||||
if (result == true) {
|
||||
onRefresh?.call(mi.id);
|
||||
@@ -154,12 +151,7 @@ Future<MediaNavigationResult> _showDetail(
|
||||
bool isOffline,
|
||||
void Function(String)? onRefresh,
|
||||
) async {
|
||||
final result = await Navigator.push<bool>(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => MediaDetailScreen(metadata: mi, isOffline: isOffline),
|
||||
),
|
||||
);
|
||||
final result = await Navigator.push<bool>(context, mediaDetailRoute(metadata: mi, isOffline: isOffline));
|
||||
if (result == true) {
|
||||
onRefresh?.call(mi.id);
|
||||
}
|
||||
|
||||
@@ -949,10 +949,7 @@ void _navigateToSeason(BuildContext context, MediaItem episode, {bool isOffline
|
||||
);
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) =>
|
||||
MediaDetailScreen(metadata: showStub, isOffline: isOffline, initialSeasonIndex: episode.parentIndex),
|
||||
),
|
||||
mediaDetailRoute(metadata: showStub, isOffline: isOffline, initialSeasonIndex: episode.parentIndex),
|
||||
);
|
||||
} else if (episode.parentId != null) {
|
||||
// Fallback: navigate to season directly if no grandparent
|
||||
@@ -969,12 +966,7 @@ void _navigateToSeason(BuildContext context, MediaItem episode, {bool isOffline
|
||||
serverId: episode.serverId,
|
||||
serverName: episode.serverName,
|
||||
);
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => MediaDetailScreen(metadata: seasonStub, isOffline: isOffline),
|
||||
),
|
||||
);
|
||||
Navigator.push(context, mediaDetailRoute(metadata: seasonStub, isOffline: isOffline));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1016,9 +1008,7 @@ void _navigateToDetail(BuildContext context, MediaItem mi, {bool isOffline = fal
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => MediaDetailScreen(metadata: target, isOffline: isOffline, initialSeasonIndex: initialSeasonIndex),
|
||||
),
|
||||
mediaDetailRoute(metadata: target, isOffline: isOffline, initialSeasonIndex: initialSeasonIndex),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -654,7 +654,7 @@ class MediaContextMenuState extends State<MediaContextMenu> {
|
||||
await _navigateToRelated(
|
||||
context,
|
||||
mediaItem!.kind == MediaKind.season ? mediaItem.parentId : mediaItem.grandparentId,
|
||||
(item) => MediaDetailScreen(metadata: item),
|
||||
(item) => mediaDetailRoute(metadata: item),
|
||||
t.messages.errorLoadingSeries,
|
||||
);
|
||||
break;
|
||||
@@ -667,7 +667,7 @@ class MediaContextMenuState extends State<MediaContextMenu> {
|
||||
await _navigateToRelated(
|
||||
context,
|
||||
seasonParentKey,
|
||||
(show) => MediaDetailScreen(metadata: show, initialSeasonIndex: seasonIndex),
|
||||
(show) => mediaDetailRoute(metadata: show, initialSeasonIndex: seasonIndex),
|
||||
t.messages.errorLoadingSeason,
|
||||
);
|
||||
break;
|
||||
@@ -800,7 +800,7 @@ class MediaContextMenuState extends State<MediaContextMenu> {
|
||||
Future<void> _navigateToRelated(
|
||||
BuildContext context,
|
||||
String? id,
|
||||
Widget Function(MediaItem) screenBuilder,
|
||||
Route<Object?> Function(MediaItem) routeBuilder,
|
||||
String errorPrefix,
|
||||
) async {
|
||||
if (id == null) return;
|
||||
@@ -810,7 +810,7 @@ class MediaContextMenuState extends State<MediaContextMenu> {
|
||||
try {
|
||||
final metadata = await client.fetchItem(id);
|
||||
if (metadata != null && context.mounted) {
|
||||
await Navigator.push(context, MaterialPageRoute(builder: (context) => screenBuilder(metadata)));
|
||||
await Navigator.push(context, routeBuilder(metadata));
|
||||
widget.onRefresh?.call(_itemId());
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
Reference in New Issue
Block a user