|
| 1 | +import 'package:core/core.dart'; |
1 | 2 | import 'package:flutter/material.dart'; |
| 3 | +import 'package:flutter_bloc/flutter_bloc.dart'; |
| 4 | +import 'package:flutter_news_app_mobile_client_full_source_code/app/bloc/app_bloc.dart'; |
2 | 5 | import 'package:flutter_news_app_mobile_client_full_source_code/l10n/l10n.dart'; |
3 | 6 | import 'package:ui_kit/ui_kit.dart'; |
4 | 7 |
|
5 | 8 | /// {@template decorator_dismissed_widget} |
6 | 9 | /// A widget displayed in place of a feed decorator after it has been |
7 | 10 | /// dismissed by the user. |
| 11 | +/// |
| 12 | +/// This widget's height dynamically adjusts to match the user's selected |
| 13 | +/// headline tile style to prevent layout shifts in the feed. |
8 | 14 | /// {@endtemplate} |
9 | 15 | class DecoratorDismissedWidget extends StatelessWidget { |
10 | 16 | /// {@macro decorator_dismissed_widget} |
11 | 17 | const DecoratorDismissedWidget({super.key}); |
12 | 18 |
|
| 19 | + /// Determines the height of the widget based on the user's feed preference. |
| 20 | + /// |
| 21 | + /// This ensures that when a decorator is dismissed, the placeholder that |
| 22 | + /// replaces it has a similar height to the surrounding headline tiles, |
| 23 | + /// preventing a jarring layout shift. |
| 24 | + double _getDynamicHeight(HeadlineImageStyle imageStyle) { |
| 25 | + return switch (imageStyle) { |
| 26 | + // Approximate height for a text-only list tile. |
| 27 | + HeadlineImageStyle.hidden => 80, |
| 28 | + // Approximate height for a list tile with a leading image. |
| 29 | + HeadlineImageStyle.smallThumbnail => 100, |
| 30 | + // Approximate height for a card with an image on top. |
| 31 | + HeadlineImageStyle.largeThumbnail => 280, |
| 32 | + }; |
| 33 | + } |
| 34 | + |
13 | 35 | @override |
14 | 36 | Widget build(BuildContext context) { |
15 | 37 | final theme = Theme.of(context); |
16 | 38 | final l10n = AppLocalizationsX(context).l10n; |
| 39 | + final headlineImageStyle = context |
| 40 | + .watch<AppBloc>() |
| 41 | + .state |
| 42 | + .headlineImageStyle; |
17 | 43 |
|
18 | 44 | return Card( |
19 | 45 | margin: const EdgeInsets.symmetric( |
20 | 46 | horizontal: AppSpacing.lg, |
21 | 47 | vertical: AppSpacing.md, |
22 | 48 | ), |
23 | | - // TODO(fulleni): size must reflect the hight of the selected headlines feed tile widget. |
24 | 49 | child: SizedBox( |
25 | | - // This height is an approximation of the CallToActionDecoratorWidget's |
26 | | - // height to ensure minimal layout shift upon dismissal. |
27 | | - height: 140, |
| 50 | + // The height is dynamically set to match the current headline tile |
| 51 | + // style, ensuring a smooth visual transition upon dismissal. |
| 52 | + height: _getDynamicHeight(headlineImageStyle), |
28 | 53 | child: Center( |
29 | 54 | child: Text( |
30 | 55 | l10n.decoratorDismissedConfirmation, |
|
0 commit comments