183 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Dart
		
	
	
		
		
			
		
	
	
			183 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Dart
		
	
	
| 
								 | 
							
								import 'package:design/design.dart';
							 | 
						||
| 
								 | 
							
								import 'package:guru_app/financial/iap/iap_model.dart';
							 | 
						||
| 
								 | 
							
								import 'package:guru_ui/pages/store/store_page.dart';
							 | 
						||
| 
								 | 
							
								import 'package:guru_ui/widget/image/adaptive_image.dart';
							 | 
						||
| 
								 | 
							
								import 'package:guru_widgets/button/guru_button.dart';
							 | 
						||
| 
								 | 
							
								import 'package:guru_widgets/theme/guru_theme.dart';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								part 'bundle_card.g.dart';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								@DesignSpec(width: 670, height: 388, specMode: SpecMode.nested)
							 | 
						||
| 
								 | 
							
								abstract class BundleCardDesignSpec implements BasicDesignSpec {
							 | 
						||
| 
								 | 
							
								  @SpecEdgeInsets.only(
							 | 
						||
| 
								 | 
							
								      top: SpecHeight(12),
							 | 
						||
| 
								 | 
							
								      bottom: SpecHeight(18),
							 | 
						||
| 
								 | 
							
								      start: SpecWidth(12),
							 | 
						||
| 
								 | 
							
								      end: SpecWidth(12))
							 | 
						||
| 
								 | 
							
								  EdgeInsets get bundleCardPadding;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  @SpecEdgeInsets.only(
							 | 
						||
| 
								 | 
							
								    top: SpecHeight(18),
							 | 
						||
| 
								 | 
							
								    start: SpecWidth(24),
							 | 
						||
| 
								 | 
							
								    end: SpecWidth(24),
							 | 
						||
| 
								 | 
							
								  )
							 | 
						||
| 
								 | 
							
								  EdgeInsets get bundleInfoPadding;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  @SpecHeight(-56)
							 | 
						||
| 
								 | 
							
								  double get bundleLabelTopSpcing;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  @SpecHeight(-40)
							 | 
						||
| 
								 | 
							
								  double get bundleLabelRightSpcing;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  @SpecHeight(136)
							 | 
						||
| 
								 | 
							
								  double get bundleLabelSize;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  @SpecAbsoluteFontSize(32)
							 | 
						||
| 
								 | 
							
								  double get bundleTitleFontsize;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  @SpecAbsoluteFontSize(20)
							 | 
						||
| 
								 | 
							
								  double get bundleSummaryFontsize;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  @SpecHeight(8)
							 | 
						||
| 
								 | 
							
								  double get bundleTitleBottomSpcing;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  @SpecSize(SpecWidth(200), SpecHeight(80))
							 | 
						||
| 
								 | 
							
								  Size get bundleButtonSize;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  static BundleCardDesignSpec create(Size size,
							 | 
						||
| 
								 | 
							
								          {Offset offset = Offset.zero}) =>
							 | 
						||
| 
								 | 
							
								      _BundleCardDesignSpec.from(size, offset: offset);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef BundleContaineBuilder<T> = Widget Function(
							 | 
						||
| 
								 | 
							
								    BuildContext, BundleCardDesignSpec);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class BundleCardStyle {
							 | 
						||
| 
								 | 
							
								  final String name;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const BundleCardStyle.create(this.name);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // 游戏内货币的资源条
							 | 
						||
| 
								 | 
							
								  static const BundleCardStyle igc = BundleCardStyle.create("igc");
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class BundleCardStyleTheme {
							 | 
						||
| 
								 | 
							
								  final Color? titleColor;
							 | 
						||
| 
								 | 
							
								  final Color? summaryColor;
							 | 
						||
| 
								 | 
							
								  final GuruButtonStyle? buttonStyle;
							 | 
						||
| 
								 | 
							
								  final Decoration? background;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const BundleCardStyleTheme({
							 | 
						||
| 
								 | 
							
								    this.titleColor,
							 | 
						||
| 
								 | 
							
								    this.summaryColor,
							 | 
						||
| 
								 | 
							
								    this.buttonStyle,
							 | 
						||
| 
								 | 
							
								    this.background,
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  static const defaultTheme = BundleCardStyleTheme();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class BundleCardModel {
							 | 
						||
| 
								 | 
							
								  final IapProduct? product;
							 | 
						||
| 
								 | 
							
								  final BundleItem bundleItem;
							 | 
						||
| 
								 | 
							
								  final BundleCardStyleTheme styleTheme;
							 | 
						||
| 
								 | 
							
								  final BundleCardDesignSpec designSpec;
							 | 
						||
| 
								 | 
							
								  final VoidCallback onTap;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  BundleCardModel(
							 | 
						||
| 
								 | 
							
								      {required this.product,
							 | 
						||
| 
								 | 
							
								      required this.bundleItem,
							 | 
						||
| 
								 | 
							
								      required this.styleTheme,
							 | 
						||
| 
								 | 
							
								      required this.designSpec,
							 | 
						||
| 
								 | 
							
								      required this.onTap});
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class BundleCard extends StatelessWidget {
							 | 
						||
| 
								 | 
							
								  final BundleCardModel model;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  IapProduct? get product => model.product;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  BundleItem get bundleItem => model.bundleItem;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  BundleCardStyleTheme get styleTheme => model.styleTheme;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  BundleCardDesignSpec get designSpec => model.designSpec;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const BundleCard({Key? key, required this.model}) : super(key: key);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  @override
							 | 
						||
| 
								 | 
							
								  Widget build(BuildContext context) {
							 | 
						||
| 
								 | 
							
								    return Container(
							 | 
						||
| 
								 | 
							
								      width: double.infinity,
							 | 
						||
| 
								 | 
							
								      padding: designSpec.bundleCardPadding,
							 | 
						||
| 
								 | 
							
								      decoration: styleTheme.background ??
							 | 
						||
| 
								 | 
							
								          const BoxDecoration(
							 | 
						||
| 
								 | 
							
								              borderRadius: BorderRadius.all(Radius.circular(12)),
							 | 
						||
| 
								 | 
							
								              gradient: LinearGradient(
							 | 
						||
| 
								 | 
							
								                  colors: [Color(0xFF913A95), Color(0xFFAD56B0)],
							 | 
						||
| 
								 | 
							
								                  begin: Alignment.centerLeft,
							 | 
						||
| 
								 | 
							
								                  end: Alignment.centerRight),
							 | 
						||
| 
								 | 
							
								              boxShadow: [
							 | 
						||
| 
								 | 
							
								                BoxShadow(
							 | 
						||
| 
								 | 
							
								                  color: Color.fromRGBO(168, 117, 169, 1),
							 | 
						||
| 
								 | 
							
								                  offset: Offset(0, 2),
							 | 
						||
| 
								 | 
							
								                )
							 | 
						||
| 
								 | 
							
								              ]),
							 | 
						||
| 
								 | 
							
								      child: Stack(
							 | 
						||
| 
								 | 
							
								        clipBehavior: Clip.none,
							 | 
						||
| 
								 | 
							
								        children: [
							 | 
						||
| 
								 | 
							
								        Column(
							 | 
						||
| 
								 | 
							
								          mainAxisSize: MainAxisSize.min,
							 | 
						||
| 
								 | 
							
								          children: [
							 | 
						||
| 
								 | 
							
								            bundleItem.builder(context, designSpec),
							 | 
						||
| 
								 | 
							
								            Padding(padding: designSpec.bundleInfoPadding, child: Row(
							 | 
						||
| 
								 | 
							
								              mainAxisAlignment: MainAxisAlignment.spaceBetween,
							 | 
						||
| 
								 | 
							
								              children: [
							 | 
						||
| 
								 | 
							
								                Column(
							 | 
						||
| 
								 | 
							
								                      mainAxisAlignment: MainAxisAlignment.start,
							 | 
						||
| 
								 | 
							
								                      children: [
							 | 
						||
| 
								 | 
							
								                  Text(
							 | 
						||
| 
								 | 
							
								                    bundleItem.title,
							 | 
						||
| 
								 | 
							
								                    style: TextStyle(
							 | 
						||
| 
								 | 
							
								                        color: styleTheme.titleColor ?? Colors.white,
							 | 
						||
| 
								 | 
							
								                        fontWeight: GuruTheme.fwExtraBold,
							 | 
						||
| 
								 | 
							
								                        fontSize: designSpec.bundleTitleFontsize,
							 | 
						||
| 
								 | 
							
								                        height: 1.25),
							 | 
						||
| 
								 | 
							
								                  ),
							 | 
						||
| 
								 | 
							
								                  if (bundleItem.summary != null)
							 | 
						||
| 
								 | 
							
								                    Padding(
							 | 
						||
| 
								 | 
							
								                        padding: EdgeInsets.only(
							 | 
						||
| 
								 | 
							
								                            top: designSpec.bundleTitleBottomSpcing),
							 | 
						||
| 
								 | 
							
								                        child: Text(
							 | 
						||
| 
								 | 
							
								                          bundleItem.summary!,
							 | 
						||
| 
								 | 
							
								                          style: TextStyle(
							 | 
						||
| 
								 | 
							
								                              color: styleTheme.summaryColor ?? Colors.white,
							 | 
						||
| 
								 | 
							
								                              fontSize: designSpec.bundleSummaryFontsize,
							 | 
						||
| 
								 | 
							
								                              fontWeight: GuruTheme.fwMedium),
							 | 
						||
| 
								 | 
							
								                        ))
							 | 
						||
| 
								 | 
							
								                ]),
							 | 
						||
| 
								 | 
							
								                GuruButton(
							 | 
						||
| 
								 | 
							
								                    size: designSpec.bundleButtonSize,
							 | 
						||
| 
								 | 
							
								                    action: product != null ? product!.details.price : 'BUY',
							 | 
						||
| 
								 | 
							
								                    summary: bundleItem.summary,
							 | 
						||
| 
								 | 
							
								                    style: styleTheme.buttonStyle,
							 | 
						||
| 
								 | 
							
								                    onPressed: () {
							 | 
						||
| 
								 | 
							
								                      model.onTap.call();
							 | 
						||
| 
								 | 
							
								                    })
							 | 
						||
| 
								 | 
							
								              ],
							 | 
						||
| 
								 | 
							
								            )),
							 | 
						||
| 
								 | 
							
								            
							 | 
						||
| 
								 | 
							
								          ],
							 | 
						||
| 
								 | 
							
								        ),
							 | 
						||
| 
								 | 
							
								        if (bundleItem.label != null)
							 | 
						||
| 
								 | 
							
								          Positioned.directional(
							 | 
						||
| 
								 | 
							
								              textDirection: Directionality.of(context),
							 | 
						||
| 
								 | 
							
								              top: designSpec.bundleLabelTopSpcing,
							 | 
						||
| 
								 | 
							
								              end: designSpec.bundleLabelRightSpcing,
							 | 
						||
| 
								 | 
							
								              child: AdaptiveImage(bundleItem.label!,
							 | 
						||
| 
								 | 
							
								                  height: designSpec.bundleLabelSize))
							 | 
						||
| 
								 | 
							
								      ]),
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 |