235 lines
7.5 KiB
Dart
235 lines
7.5 KiB
Dart
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,
|
||
))
|
||
]));
|
||
}
|
||
}
|