fix: Lots of navigation improvements

This commit is contained in:
PartyDonut 2025-10-03 13:02:51 +02:00
parent c299492d6d
commit 5174bb3a6c
55 changed files with 1019 additions and 832 deletions

View file

@ -5,9 +5,11 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fladder/models/item_base_model.dart';
import 'package:fladder/screens/details_screens/components/overview_header.dart';
import 'package:fladder/screens/shared/media/poster_row.dart';
import 'package:fladder/util/adaptive_layout/adaptive_layout.dart';
import 'package:fladder/util/fladder_image.dart';
import 'package:fladder/util/focus_provider.dart';
import 'package:fladder/util/localization_helper.dart';
import 'package:fladder/widgets/shared/custom_shader_mask.dart';
import 'package:fladder/widgets/shared/ensure_visible.dart';
class DetailedBanner extends ConsumerStatefulWidget {
@ -29,122 +31,81 @@ class _DetailedBannerState extends ConsumerState<DetailedBanner> {
@override
Widget build(BuildContext context) {
final size = MediaQuery.sizeOf(context);
final color = Theme.of(context).colorScheme.surface;
final stops = [0.05, 0.35, 0.65, 0.95];
return Column(
final phoneOffsetHeight =
AdaptiveLayout.viewSizeOf(context) <= ViewSize.phone ? MediaQuery.paddingOf(context).top + 80 : 0.0;
return Stack(
children: [
SizedBox(
width: double.infinity,
height: size.height * 0.50,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
color.withValues(alpha: 0.85),
color.withValues(alpha: 0.75),
color.withValues(alpha: 0),
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
ExcludeFocus(
child: Align(
alignment: Alignment.topRight,
child: Transform.translate(
offset: Offset(0, -phoneOffsetHeight),
child: FractionallySizedBox(
widthFactor: 0.85,
child: AspectRatio(
aspectRatio: 1.8,
child: CustomShaderMask(
child: FladderImage(
image: selectedPoster.images?.primary,
),
),
),
),
),
child: Stack(
children: [
ExcludeFocus(
child: Align(
alignment: Alignment.topRight,
child: AspectRatio(
aspectRatio: 1.7,
child: ShaderMask(
shaderCallback: (Rect bounds) {
return LinearGradient(
colors: [
Colors.white,
Colors.white,
Colors.white,
Colors.white.withAlpha(0),
],
stops: stops,
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
).createShader(bounds);
},
child: ShaderMask(
shaderCallback: (Rect bounds) {
return LinearGradient(
colors: [
Colors.white.withAlpha(0),
Colors.white,
Colors.white,
Colors.white,
],
stops: stops,
begin: Alignment.centerLeft,
end: Alignment.centerRight,
).createShader(bounds);
},
child: FladderImage(
image: selectedPoster.images?.primary,
),
),
),
),
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: FractionallySizedBox(
widthFactor: 0.5,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
spacing: 16,
children: [
Flexible(
child: OverviewHeader(
name: selectedPoster.parentBaseModel.name,
subTitle: selectedPoster.label(context),
image: selectedPoster.getPosters,
logoAlignment: Alignment.centerLeft,
summary: selectedPoster.overview.summary,
productionYear: selectedPoster.overview.productionYear,
runTime: selectedPoster.overview.runTime,
genres: selectedPoster.overview.genreItems,
studios: selectedPoster.overview.studios,
officialRating: selectedPoster.overview.parentalRating,
communityRating: selectedPoster.overview.communityRating,
),
),
SizedBox(
height: size.height * 0.05,
)
],
),
),
),
],
),
),
),
FocusProvider(
autoFocus: true,
child: PosterRow(
key: const Key("detailed-banner-row"),
primaryPosters: true,
label: context.localized.nextUp,
posters: widget.posters,
onFocused: (poster) {
context.ensureVisible(
alignment: 1.0,
);
setState(() {
selectedPoster = poster;
});
widget.onSelect(poster);
},
SizedBox(
width: double.infinity,
height: size.height * 0.85,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16).copyWith(bottom: 4),
child: FractionallySizedBox(
widthFactor: AdaptiveLayout.viewSizeOf(context) <= ViewSize.phone ? 1.0 : 0.55,
child: OverviewHeader(
name: selectedPoster.parentBaseModel.name,
subTitle: selectedPoster.label(context),
image: selectedPoster.getPosters,
logoAlignment: AdaptiveLayout.viewSizeOf(context) <= ViewSize.phone
? Alignment.center
: Alignment.centerLeft,
summary: selectedPoster.overview.summary,
productionYear: selectedPoster.overview.productionYear,
runTime: selectedPoster.overview.runTime,
genres: selectedPoster.overview.genreItems,
studios: selectedPoster.overview.studios,
officialRating: selectedPoster.overview.parentalRating,
communityRating: selectedPoster.overview.communityRating,
),
),
),
),
FocusProvider(
autoFocus: true,
child: PosterRow(
primaryPosters: true,
label: context.localized.nextUp,
posters: widget.posters,
onFocused: (poster) {
context.ensureVisible(
alignment: 1.0,
);
setState(() {
selectedPoster = poster;
});
widget.onSelect(poster);
},
),
),
const SizedBox(height: 16)
],
),
)
),
],
);
}