guru_sdk/guru_ui/lib/pages/store/purchase_card.dart

235 lines
7.5 KiB
Dart
Raw Normal View History

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,
))
]));
}
}