Files
asciinevrdie/lib/src/features/game/widgets/speed_boost_button.dart
JiWoong Sul f6799e0243 fix(monetization): 광고/보상 로직 버그 수정 및 오프라인 2배 구현
- 인터스티셜 광고 실패 시 onComplete 콜백 미호출 수정
- AdType.rewardReturn 추가, 복귀 보상에 올바른 타입 적용
- SpeedBoostButton 기본 배율 10→5로 수정
- 유료 유저 오프라인 시간 2배 인정 로직 구현
- IAP 상품 ID remove_ads → remove_ads_and 변경
2026-03-09 15:34:21 +09:00

148 lines
4.3 KiB
Dart

import 'package:flutter/material.dart';
import 'package:asciineverdie/data/game_text_l10n.dart' as l10n;
import 'package:asciineverdie/src/core/engine/iap_service.dart';
import 'package:asciineverdie/src/shared/retro_colors.dart';
/// 속도 부스트 버튼 위젯 (Phase 6)
///
/// 게임 화면에 표시되는 속도 부스트 활성화 버튼
class SpeedBoostButton extends StatelessWidget {
const SpeedBoostButton({
super.key,
required this.isActive,
required this.remainingSeconds,
required this.onActivate,
this.boostMultiplier = 5,
});
/// 부스트 활성화 여부
final bool isActive;
/// 남은 시간 (초)
final int remainingSeconds;
/// 부스트 배율
final int boostMultiplier;
/// 활성화 콜백
final VoidCallback onActivate;
@override
Widget build(BuildContext context) {
final isPaidUser = IAPService.instance.isAdRemovalPurchased;
final gold = RetroColors.goldOf(context);
final goldDark = RetroColors.goldDarkOf(context);
final expColor = RetroColors.expOf(context);
// 부스트 활성화 중일 때
if (isActive) {
return _buildActiveButton(context, expColor);
}
// 부스트 비활성화 상태
return _buildInactiveButton(context, gold, goldDark, isPaidUser);
}
Widget _buildActiveButton(BuildContext context, Color expColor) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
decoration: BoxDecoration(
color: expColor.withValues(alpha: 0.3),
borderRadius: BorderRadius.circular(8),
border: Border.all(color: expColor, width: 2),
boxShadow: [
BoxShadow(
color: expColor.withValues(alpha: 0.5),
blurRadius: 8,
spreadRadius: 1,
),
],
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
Text('', style: TextStyle(fontSize: 18, color: expColor)),
const SizedBox(width: 4),
Text(
'${boostMultiplier}x',
style: TextStyle(
fontFamily: 'PressStart2P',
fontSize: 14,
color: expColor,
fontWeight: FontWeight.bold,
),
),
],
),
const SizedBox(height: 4),
Text(
l10n.speedBoostRemaining(remainingSeconds),
style: TextStyle(
fontFamily: 'PressStart2P',
fontSize: 10,
color: expColor.withValues(alpha: 0.8),
),
),
],
),
);
}
Widget _buildInactiveButton(
BuildContext context,
Color gold,
Color goldDark,
bool isPaidUser,
) {
return GestureDetector(
onTap: onActivate,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
decoration: BoxDecoration(
color: gold.withValues(alpha: 0.2),
borderRadius: BorderRadius.circular(8),
border: Border.all(color: gold, width: 2),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text('', style: TextStyle(fontSize: 18, color: gold)),
const SizedBox(width: 4),
Text(
'${boostMultiplier}x',
style: TextStyle(
fontFamily: 'PressStart2P',
fontSize: 12,
color: gold,
),
),
// 광고 아이콘 (무료 유저만)
if (!isPaidUser) ...[
const SizedBox(width: 6),
Container(
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 2),
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.2),
borderRadius: BorderRadius.circular(4),
),
child: const Text(
'AD',
style: TextStyle(
fontFamily: 'PressStart2P',
fontSize: 8,
color: Colors.white,
),
),
),
],
],
),
),
);
}
}