From 17885545eff46987604d9684f433e1995886b45c Mon Sep 17 00:00:00 2001 From: MuZhou233 Date: Tue, 2 Jan 2024 21:33:51 +0000 Subject: [PATCH] fix(yesod): update preview card --- lib/view/layout/bootstrap_breakpoints.dart | 14 ++ lib/view/layout/bootstrap_container.dart | 134 +++++++++++++++---- lib/view/pages/yesod/yesod_preview_card.dart | 23 ++-- lib/view/pages/yesod/yesod_recent_page.dart | 114 +++++++++------- 4 files changed, 200 insertions(+), 85 deletions(-) diff --git a/lib/view/layout/bootstrap_breakpoints.dart b/lib/view/layout/bootstrap_breakpoints.dart index 052dbed..f103c17 100644 --- a/lib/view/layout/bootstrap_breakpoints.dart +++ b/lib/view/layout/bootstrap_breakpoints.dart @@ -17,3 +17,17 @@ class BootstrapContainerMaxWidth { static const double xl = 1140; static const double xxl = 1320; } + +enum BootstrapSteps { + undefined._(0), + xxs._(1), + xs._(2), + sm._(3), + md._(4), + lg._(5), + xl._(6), + xxl._(7); + + const BootstrapSteps._(this.value); + final int value; +} diff --git a/lib/view/layout/bootstrap_container.dart b/lib/view/layout/bootstrap_container.dart index cc33769..d6fead4 100644 --- a/lib/view/layout/bootstrap_container.dart +++ b/lib/view/layout/bootstrap_container.dart @@ -3,11 +3,16 @@ import 'package:flutter/material.dart'; import 'bootstrap_breakpoints.dart'; class BootstrapContainer extends StatelessWidget { - const BootstrapContainer( - {super.key, required this.children, this.alignment = Alignment.center}); + const BootstrapContainer({ + super.key, + required this.children, + this.alignment = Alignment.center, + this.fill = BootstrapSteps.undefined, + }); final List children; final AlignmentGeometry alignment; + final BootstrapSteps fill; @override Widget build(BuildContext context) { @@ -16,22 +21,51 @@ class BootstrapContainer extends StatelessWidget { late double maxWidth; if (width >= BootstrapBreakpoints.xxl) { - maxWidth = BootstrapContainerMaxWidth.xxl; + if (fill.value >= BootstrapSteps.xxl.value) { + maxWidth = width; + } else { + maxWidth = BootstrapContainerMaxWidth.xxl; + } } else if (width >= BootstrapBreakpoints.xl) { - maxWidth = BootstrapContainerMaxWidth.xl; + if (fill.value >= BootstrapSteps.xl.value) { + maxWidth = width; + } else { + maxWidth = BootstrapContainerMaxWidth.xl; + } } else if (width >= BootstrapBreakpoints.lg) { - maxWidth = BootstrapContainerMaxWidth.lg; + if (fill.value >= BootstrapSteps.lg.value) { + maxWidth = width; + } else { + maxWidth = BootstrapContainerMaxWidth.lg; + } } else if (width >= BootstrapBreakpoints.md) { - maxWidth = BootstrapContainerMaxWidth.md; + if (fill.value >= BootstrapSteps.md.value) { + maxWidth = width; + } else { + maxWidth = BootstrapContainerMaxWidth.md; + } } else if (width >= BootstrapBreakpoints.sm) { - maxWidth = BootstrapContainerMaxWidth.sm; + if (fill.value >= BootstrapSteps.sm.value) { + maxWidth = width; + } else { + maxWidth = BootstrapContainerMaxWidth.sm; + } } else if (width >= BootstrapBreakpoints.xs) { - maxWidth = BootstrapContainerMaxWidth.xs; + if (fill.value >= BootstrapSteps.xs.value) { + maxWidth = width; + } else { + maxWidth = BootstrapContainerMaxWidth.xs; + } } else { - maxWidth = BootstrapContainerMaxWidth.xxs; + if (fill.value >= BootstrapSteps.xxs.value) { + maxWidth = width; + } else { + maxWidth = BootstrapContainerMaxWidth.xxs; + } } return _InheritedBootstrapContainer( width: maxWidth, + filled: maxWidth == width, child: Align( alignment: alignment, child: Container( @@ -54,10 +88,12 @@ class BootstrapContainer extends StatelessWidget { class _InheritedBootstrapContainer extends InheritedWidget { const _InheritedBootstrapContainer({ required this.width, + required this.filled, required super.child, }); final double width; + final bool filled; static _InheritedBootstrapContainer? of(BuildContext context) { return context @@ -70,19 +106,28 @@ class _InheritedBootstrapContainer extends InheritedWidget { } } +typedef BootstrapColumnBuilder = Widget Function( + BuildContext context, bool containerFilled); + class BootstrapColumn extends StatelessWidget { const BootstrapColumn( {super.key, - required this.child, + this.child, + this.builder, + this.fill = BootstrapSteps.undefined, this.xxs = -1, this.xs = -1, this.sm = -1, this.md = -1, this.lg = -1, this.xl = -1, - this.xxl = -1}); + this.xxl = -1}) + : assert(child != null || builder != null, + 'child or builder must not be null'); - final Widget child; + final BootstrapColumnBuilder? builder; + final Widget? child; + final BootstrapSteps fill; final int xxs; final int xs; final int sm; @@ -144,29 +189,64 @@ class BootstrapColumn extends StatelessWidget { if (containerWidth == BootstrapContainerMaxWidth.xxs || containerWidth < BootstrapContainerMaxWidth.xs) { - late double maxWidth = constraints.biggest.width; - if (maxWidth == double.infinity) { - maxWidth = BootstrapContainerMaxWidth.xs; + if (fill.value >= BootstrapSteps.xxs.value) { + columnWidth = containerWidth; + } else { + double maxWidth = constraints.biggest.width; + if (maxWidth == double.infinity) { + maxWidth = BootstrapContainerMaxWidth.xs; + } + columnWidth = maxWidth * xxs_ / 12; } - columnWidth = maxWidth * xxs_ / 12; } else if (containerWidth < BootstrapContainerMaxWidth.sm) { - columnWidth = BootstrapContainerMaxWidth.xs * xs_ / 12; + if (fill.value >= BootstrapSteps.xs.value) { + columnWidth = containerWidth; + } else { + columnWidth = BootstrapContainerMaxWidth.xs * xs_ / 12; + } } else if (containerWidth < BootstrapContainerMaxWidth.md) { - columnWidth = BootstrapContainerMaxWidth.sm * sm_ / 12; + if (fill.value >= BootstrapSteps.sm.value) { + columnWidth = containerWidth; + } else { + columnWidth = BootstrapContainerMaxWidth.sm * sm_ / 12; + } } else if (containerWidth < BootstrapContainerMaxWidth.lg) { - columnWidth = BootstrapContainerMaxWidth.md * md_ / 12; + if (fill.value >= BootstrapSteps.md.value) { + columnWidth = containerWidth; + } else { + columnWidth = BootstrapContainerMaxWidth.md * md_ / 12; + } } else if (containerWidth < BootstrapContainerMaxWidth.xl) { - columnWidth = BootstrapContainerMaxWidth.lg * lg_ / 12; + if (fill.value >= BootstrapSteps.lg.value) { + columnWidth = containerWidth; + } else { + columnWidth = BootstrapContainerMaxWidth.lg * lg_ / 12; + } } else if (containerWidth < BootstrapContainerMaxWidth.xxl) { - columnWidth = BootstrapContainerMaxWidth.xl * xl_ / 12; + if (fill.value >= BootstrapSteps.xl.value) { + columnWidth = containerWidth; + } else { + columnWidth = BootstrapContainerMaxWidth.xl * xl_ / 12; + } } else { - columnWidth = BootstrapContainerMaxWidth.xxl * xxl_ / 12; + if (fill.value >= BootstrapSteps.xxl.value) { + columnWidth = containerWidth; + } else { + columnWidth = BootstrapContainerMaxWidth.xxl * xxl_ / 12; + } + } + if (builder != null) { + return SizedBox( + width: columnWidth, + child: builder!(context, + _InheritedBootstrapContainer.of(context)?.filled ?? false), + ); + } else { + return SizedBox( + width: columnWidth, + child: child, + ); } - - return SizedBox( - width: columnWidth, - child: child, - ); }); } } diff --git a/lib/view/pages/yesod/yesod_preview_card.dart b/lib/view/pages/yesod/yesod_preview_card.dart index 5235d35..0907c85 100644 --- a/lib/view/pages/yesod/yesod_preview_card.dart +++ b/lib/view/pages/yesod/yesod_preview_card.dart @@ -17,6 +17,7 @@ class YesodPreviewCard extends StatelessWidget { this.iconUrl, this.images, this.description, + this.cardBorderRadius, }); final String? iconUrl; @@ -26,36 +27,42 @@ class YesodPreviewCard extends StatelessWidget { final String? description; final void Function() callback; final FeedListType listType; + final BorderRadius? cardBorderRadius; @override Widget build(BuildContext context) { + final cardBorderRadius_ = + cardBorderRadius ?? SpacingHelper.defaultBorderRadius; return LayoutBuilder(builder: (context, constraints) { const maxTitleLines = 2; const maxDescriptionLines = 3; - const cardPadding = 8.0; + const cardPaddingV = 16.0; + const cardPaddingH = 16.0; const imgPadding = 8; const iconSize = 18.0; final double leftImageSize = listType == FeedListType.magazine ? 128 : 0; final double bottomImageSize = constraints.biggest.width < 406 - ? (constraints.biggest.width - 4 * imgPadding) / 3 + ? (constraints.biggest.width - 2 * imgPadding - 2 * cardPaddingH) / 3 : 130; + debugPrint('${constraints.biggest.width} $bottomImageSize'); return Material( - borderRadius: SpacingHelper.defaultBorderRadius, + borderRadius: cardBorderRadius_, child: Ink( decoration: BoxDecoration( - borderRadius: SpacingHelper.defaultBorderRadius, + borderRadius: cardBorderRadius_, color: Theme.of(context).cardColor, ), child: InkWell( - borderRadius: SpacingHelper.defaultBorderRadius, + borderRadius: cardBorderRadius_, onTap: callback, child: Padding( - padding: const EdgeInsets.all(cardPadding), + padding: const EdgeInsets.fromLTRB( + cardPaddingH, cardPaddingV, cardPaddingH, cardPaddingV), child: Row(children: [ if (listType == FeedListType.magazine) Container( width: leftImageSize, - padding: const EdgeInsets.only(right: cardPadding), + padding: const EdgeInsets.only(right: cardPaddingV), child: ConstrainedBox( constraints: BoxConstraints( maxHeight: leftImageSize, @@ -71,7 +78,7 @@ class YesodPreviewCard extends StatelessWidget { ), Container( width: constraints.biggest.width - - 2 * cardPadding - + 2 * cardPaddingH - leftImageSize, constraints: listType == FeedListType.magazine ? BoxConstraints( diff --git a/lib/view/pages/yesod/yesod_recent_page.dart b/lib/view/pages/yesod/yesod_recent_page.dart index 98c4523..35ebbd8 100644 --- a/lib/view/pages/yesod/yesod_recent_page.dart +++ b/lib/view/pages/yesod/yesod_recent_page.dart @@ -9,6 +9,8 @@ import '../../../common/bloc_event_status_mixin.dart'; import '../../../model/yesod_model.dart'; import '../../../route.dart'; import '../../helper/duration_format.dart'; +import '../../helper/spacing.dart'; +import '../../layout/bootstrap_breakpoints.dart'; import '../../layout/bootstrap_container.dart'; import 'yesod_detail_page.dart'; import 'yesod_preview_card.dart'; @@ -87,56 +89,68 @@ class YesodRecentPage extends StatelessWidget { return FrameSeparateWidget( index: index, - child: BootstrapContainer(children: [ - BootstrapColumn( - xxs: 12, - md: 9, - lg: 7, - child: Padding( - padding: const EdgeInsets.only(top: 8), - child: OpenContainer( - tappable: - false, // https://github.com/flutter/flutter/issues/74111 - openBuilder: (_, __) { - return BlocProvider.value( - value: context.read(), - child: YesodDetailPage( - itemId: item.itemId, - ), - ); - }, - openColor: theme.colorScheme.primary, - closedShape: const RoundedRectangleBorder( - borderRadius: - BorderRadius.all(Radius.circular(12)), - ), - closedElevation: 0, - closedColor: theme.cardColor, - closedBuilder: (context, openContainer) { - return GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: () { - openContainer(); - context.read().add( - YesodFeedItemReadEvent(item.itemId)); - }, - child: YesodPreviewCard( - name: - '${item.feedConfigName} ${DurationHelper.recentString(item.publishedParsedTime.toDateTime())}', - title: item.title, - callback: openContainer, - iconUrl: item.feedAvatarUrl, - images: item.imageUrls, - description: item.shortDescription, - listType: state.feedListType ?? - FeedListType.card, - ), - ); - }, - ), - ), - ), - ]), + child: BootstrapContainer( + fill: BootstrapSteps.xs, + children: [ + BootstrapColumn( + fill: BootstrapSteps.xs, + xxs: 12, + md: 9, + lg: 7, + builder: (context, filled) { + return Padding( + padding: const EdgeInsets.only(top: 8), + child: OpenContainer( + tappable: + false, // https://github.com/flutter/flutter/issues/74111 + openBuilder: (_, __) { + return BlocProvider.value( + value: context.read(), + child: YesodDetailPage( + itemId: item.itemId, + ), + ); + }, + openColor: theme.colorScheme.primary, + closedShape: RoundedRectangleBorder( + borderRadius: filled + ? BorderRadius.zero + : SpacingHelper + .defaultBorderRadius, + ), + closedElevation: 0, + closedColor: theme.cardColor, + closedBuilder: + (context, openContainer) { + return GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + openContainer(); + context.read().add( + YesodFeedItemReadEvent( + item.itemId)); + }, + child: YesodPreviewCard( + name: + '${item.feedConfigName} ${DurationHelper.recentString(item.publishedParsedTime.toDateTime())}', + title: item.title, + callback: openContainer, + iconUrl: item.feedAvatarUrl, + images: item.imageUrls, + description: + item.shortDescription, + listType: state.feedListType ?? + FeedListType.card, + cardBorderRadius: filled + ? BorderRadius.zero + : null, + ), + ); + }, + ), + ); + }), + ]), ); } else { return Padding(