import 'package:auto_size_text/auto_size_text.dart'; import 'package:design/design.dart'; import 'package:guru_app/financial/iap/iap_model.dart'; import 'package:guru_ui/guru_widget.dart'; import 'package:guru_ui/localizations/ui_strings.dart'; import 'package:guru_ui/pages/store/store_design_spec.dart'; import 'package:guru_ui/pages/store/store_page.dart'; import 'package:guru_widgets/common/flexible_container.dart'; import 'package:guru_widgets/common/spacer.dart'; import 'package:guru_widgets/theme/guru_theme.dart'; import 'package:guru_ui/localizations/l10n/generated/app_localizations.dart'; part 'purchase_card.g.dart'; @DesignSpec(width: 210, height: 320, specMode: SpecMode.useSize) abstract class PurchaseCardDesignSpec implements BasicDesignSpec { @SpecRadius.circular(SpecHeight(24)) BorderRadius get cardRadius; @SpecRadius.circular(SpecHeight(12)) BorderRadius get exhibitionRadius; @SpecRect.fromLTRB(SpecHorizontal(12), SpecVertical(13), SpecHorizontal(12), SpecVertical(106)) Rect get exhibitionPositionedRect; @SpecEdgeInsets.only( start: SpecHorizontal(12), end: SpecHorizontal(12), top: SpecVertical(22), bottom: SpecVertical(2)) EdgeInsets get extraBonusPadding; @SpecFontSize(18) double get bonusFontSize; @SpecAbsoluteFontSize(36) double get quantityFontSize; @SpecEdgeInsets.symmetric(horizontal: SpecHorizontal(12)) EdgeInsets get quantityPadding; @SpecHeight(4) double get quantityUnitSpacing; @SpecHeight(34) double get quantityUnitSize; @SpecSize(SpecWidth(144), SpecHeight(112)) Size get illustrationSize; @SpecEdgeInsets.only(top: SpecVertical(18), bottom: SpecVertical(12)) EdgeInsets get illustrationPadding; @SpecHeight(12) double get purchaseButtonTopSpacing; @SpecAspectHeightSize(60, 2.83333333) Size get purchaseButtonSize; @SpecHeight(92, consistent: true) double get labelSize; @SpecHeight(88, consistent: true) double get labelTopSpacing; @SpecWidth(6) double get labalEndSpacing; static PurchaseCardDesignSpec from(Size size, {Offset offset = Offset.zero}) => _PurchaseCardDesignSpec.from(size, offset: offset); } class PurchaseCardStyle { final String name; const PurchaseCardStyle.create(this.name); // 游戏内货币的资源条 static const PurchaseCardStyle igc = PurchaseCardStyle.create("_igc"); } class PurchaseCardStyleTheme { // 额外Bonus的颜色,如果不提供将填充黑色 final Color? extraBonusColor; // 数量的颜色,如果不提供将填充黑色 final Color? quantityColor; // 数量前缀的单位icon, 如果不提供将不显示 final QuantityPrefix? quantityPrefix; // 数量前前缀的单位icon, 如果不提供将不显示 final String? quantityUnit; // 是否使用千分位分隔符 final bool? useThousandsSeparator; // 展览区域的渐变背景,如果不提供将不显示 final Gradient? exhibitionGradient; // 卡片组中各个卡版的默认背景色,如果不提供将会使用GuruTheme中的containerColor替代 final Color? backgroundColor; // PurchaseButton的样式 final GuruButtonStyle? purchaseButtonStyle; PurchaseCardStyleTheme({ this.extraBonusColor, this.quantityColor, this.quantityPrefix, this.quantityUnit, this.exhibitionGradient, this.backgroundColor, this.useThousandsSeparator = true, this.purchaseButtonStyle, }); } class PurchaseCardModel { final IapProduct? product; final CardItem cardItem; final PurchaseCardStyleTheme styleTheme; final PurchaseCardDesignSpec designSpec; final VoidCallback onTap; PurchaseCardModel( {required this.product, required this.cardItem, required this.styleTheme, required this.designSpec, required this.onTap}); } class PurchaseCard extends StatelessWidget { final PurchaseCardModel model; IapProduct? get product => model.product; CardItem get cardItem => model.cardItem; PurchaseCardStyleTheme get styleTheme => model.styleTheme; PurchaseCardDesignSpec get designSpec => model.designSpec; const PurchaseCard({Key? key, required this.model}) : super(key: key); @override Widget build(BuildContext context) { final extraBonus = cardItem.extraBonus ?? 0; final uiStrings = UIStrings.get(); return FlexibleContainer( width: designSpec.measuredSize.width, height: designSpec.measuredSize.height, radius: designSpec.cardRadius, color: styleTheme.backgroundColor, child: Stack(fit: StackFit.expand, children: [ Positioned( left: designSpec.exhibitionPositionedRect.left, right: designSpec.exhibitionPositionedRect.right, top: designSpec.exhibitionPositionedRect.top, bottom: designSpec.exhibitionPositionedRect.bottom, child: DecoratedBox( decoration: BoxDecoration( borderRadius: designSpec.exhibitionRadius, gradient: styleTheme.exhibitionGradient))), Column(crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( padding: designSpec.extraBonusPadding, child: Text( extraBonus > 0 ? "${(extraBonus * 100).toInt()}% ${uiStrings.bonus}" : " ", style: TextStyle( fontSize: designSpec.bonusFontSize, fontWeight: GuruTheme.fwSemiBold, color: styleTheme.extraBonusColor ?? const Color(0xFFFF2830)), )), Padding( padding: designSpec.quantityPadding, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ if (styleTheme.quantityUnit != null) ...[ Image.asset(styleTheme.quantityUnit!, width: designSpec.quantityUnitSize, height: designSpec.quantityUnitSize), SizedSpacer(width: designSpec.quantityUnitSpacing) ], AutoSizeText( cardItem.quantity.toString(), minFontSize: 5, style: TextStyle( fontSize: designSpec.quantityFontSize, fontWeight: GuruTheme.fwBold, color: styleTheme.quantityColor), ) ], ), ), Padding( padding: designSpec.illustrationPadding, child: AdaptiveImage( cardItem.illustration, width: designSpec.illustrationSize.width, height: designSpec.illustrationSize.height, fit: BoxFit.cover ), ), GuruButton( size: designSpec.purchaseButtonSize, sizeSpec: GuruButtonSizeSpec.s5, style: GuruButtonStyle.purchase, action: product != null ? product!.details.price : '1000000000', onPressed: () { model.onTap.call(); }, ) ]), if (cardItem.label != null) Positioned.directional(textDirection: Directionality.of(context), top: designSpec.labelTopSpacing, end: designSpec.labalEndSpacing, child: AdaptiveImage( cardItem.label!, width: designSpec.labelSize, height: designSpec.labelSize, )) ])); } }