refactoring : barrel pattern
This commit is contained in:
+80
-227
@@ -1,28 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
import '../providers/battle_provider.dart';
|
||||
import '../providers.dart';
|
||||
|
||||
import '../game/enums.dart';
|
||||
import '../game/model/item.dart';
|
||||
import '../game/model/damage_event.dart';
|
||||
import '../game/model/effect_event.dart';
|
||||
import '../game/models.dart';
|
||||
import 'dart:async';
|
||||
import '../widgets/responsive_container.dart';
|
||||
import '../utils/item_utils.dart';
|
||||
import '../widgets/battle/character_status_card.dart';
|
||||
import '../widgets/battle/battle_log_overlay.dart';
|
||||
import '../widgets/battle/floating_battle_texts.dart';
|
||||
import '../widgets/stage/shop_ui.dart';
|
||||
import '../widgets/stage/rest_ui.dart';
|
||||
import '../widgets/battle/shake_widget.dart';
|
||||
import '../widgets/battle/battle_animation_widget.dart';
|
||||
import '../widgets/battle/explosion_widget.dart';
|
||||
import '../widgets.dart';
|
||||
import '../utils.dart';
|
||||
import 'main_menu_screen.dart';
|
||||
import '../game/config/battle_config.dart';
|
||||
import '../game/config/theme_config.dart';
|
||||
import '../game/config/app_strings.dart';
|
||||
import '../providers/settings_provider.dart'; // Import SettingsProvider
|
||||
import '../game/config.dart';
|
||||
|
||||
class BattleScreen extends StatefulWidget {
|
||||
const BattleScreen({super.key});
|
||||
@@ -97,7 +84,12 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||
position = position - stackOffset;
|
||||
}
|
||||
|
||||
position = position + Offset(renderBox.size.width / 2 - 20, -20);
|
||||
position =
|
||||
position +
|
||||
Offset(
|
||||
renderBox.size.width / 2 + BattleConfig.damageTextOffsetX,
|
||||
BattleConfig.damageTextOffsetY,
|
||||
);
|
||||
|
||||
final String id = UniqueKey().toString();
|
||||
|
||||
@@ -141,9 +133,10 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||
// Let's just wrap `FloatingDamageText` in a `Transform.scale` with a value.
|
||||
// I'll define a variable scale.
|
||||
|
||||
double scale = 1.0;
|
||||
// Heuristic: If damage is high (e.g. > 15), assume it might be risky/crit
|
||||
if (event.damage > 15) scale = 3;
|
||||
double scale = BattleConfig.damageScaleNormal;
|
||||
if (event.damage > BattleConfig.highDamageThreshold) {
|
||||
scale = BattleConfig.damageScaleHigh;
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_floatingDamageTexts.add(
|
||||
@@ -195,7 +188,8 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||
// "[UI Debug] Feedback Event: ${event.id}, Type: ${event.feedbackType}",
|
||||
// );
|
||||
if (_lastFeedbackTime != null &&
|
||||
DateTime.now().difference(_lastFeedbackTime!).inMilliseconds < 300) {
|
||||
DateTime.now().difference(_lastFeedbackTime!).inMilliseconds <
|
||||
BattleConfig.feedbackCooldownMs) {
|
||||
return; // Skip if too soon
|
||||
}
|
||||
_lastFeedbackTime = DateTime.now();
|
||||
@@ -227,12 +221,12 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||
|
||||
if (event.target == EffectTarget.enemy) {
|
||||
// Enemy is top-right, so effect should be left-bottom of its card
|
||||
offsetX = renderBox.size.width * 0.1; // 20% from left edge
|
||||
offsetY = renderBox.size.height * 0.8; // 80% from top edge
|
||||
offsetX = renderBox.size.width * BattleConfig.effectEnemyOffsetX;
|
||||
offsetY = renderBox.size.height * BattleConfig.effectEnemyOffsetY;
|
||||
} else {
|
||||
// Player is bottom-left, so effect should be right-top of its card
|
||||
offsetX = renderBox.size.width * 0.8; // 80% from left edge
|
||||
offsetY = renderBox.size.height * 0.2; // 20% from top edge
|
||||
offsetX = renderBox.size.width * BattleConfig.effectPlayerOffsetX;
|
||||
offsetY = renderBox.size.height * BattleConfig.effectPlayerOffsetY;
|
||||
}
|
||||
|
||||
position = position + Offset(offsetX, offsetY);
|
||||
@@ -488,17 +482,39 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||
}
|
||||
|
||||
void _showRiskLevelSelection(BuildContext context, ActionType actionType) {
|
||||
// 1. Check if we need to trigger enemy animation first
|
||||
bool triggered = _triggerEnemyDefenseIfNeeded(context);
|
||||
if (triggered)
|
||||
return; // If triggered, we wait for animation (and input block)
|
||||
|
||||
final battleProvider = context.read<BattleProvider>();
|
||||
final player = battleProvider.player;
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return RiskSelectionDialog(
|
||||
actionType: actionType,
|
||||
player: player,
|
||||
onSelected: (risk) {
|
||||
context.read<BattleProvider>().playerAction(actionType, risk);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Triggers enemy defense animation if applicable. Returns true if triggered.
|
||||
bool _triggerEnemyDefenseIfNeeded(BuildContext context) {
|
||||
final battleProvider = context.read<BattleProvider>();
|
||||
|
||||
// Check turn to reset flag
|
||||
if (battleProvider.turnCount != _lastTurnCount) {
|
||||
_lastTurnCount = battleProvider.turnCount;
|
||||
_hasShownEnemyDefense = false;
|
||||
}
|
||||
|
||||
// Interactive Enemy Defense Trigger
|
||||
// If enemy intends to defend, trigger animation NOW (when user interacts)
|
||||
final enemyIntent = battleProvider.currentEnemyIntent;
|
||||
if (enemyIntent != null &&
|
||||
enemyIntent.type == EnemyActionType.defend &&
|
||||
@@ -538,102 +554,10 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||
.then((_) {
|
||||
if (mounted) setState(() => _isEnemyAttacking = false);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
final baseValue = actionType == ActionType.attack
|
||||
? player.totalAtk
|
||||
: player.totalDefense;
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return SimpleDialog(
|
||||
title: Text("Select Risk Level for ${actionType.name}"),
|
||||
children: RiskLevel.values.map((risk) {
|
||||
String infoText = "";
|
||||
Color infoColor = Colors.black;
|
||||
double efficiency = 0.0;
|
||||
int expectedValue = 0;
|
||||
|
||||
switch (risk) {
|
||||
case RiskLevel.safe:
|
||||
efficiency = actionType == ActionType.attack
|
||||
? BattleConfig.attackSafeEfficiency
|
||||
: BattleConfig.defendSafeEfficiency;
|
||||
infoColor = ThemeConfig.riskSafe;
|
||||
break;
|
||||
case RiskLevel.normal:
|
||||
efficiency = actionType == ActionType.attack
|
||||
? BattleConfig.attackNormalEfficiency
|
||||
: BattleConfig.defendNormalEfficiency;
|
||||
infoColor = ThemeConfig.riskNormal;
|
||||
break;
|
||||
case RiskLevel.risky:
|
||||
efficiency = actionType == ActionType.attack
|
||||
? BattleConfig.attackRiskyEfficiency
|
||||
: BattleConfig.defendRiskyEfficiency;
|
||||
infoColor = ThemeConfig.riskRisky;
|
||||
break;
|
||||
}
|
||||
|
||||
expectedValue = (baseValue * efficiency).toInt();
|
||||
String valueUnit = actionType == ActionType.attack
|
||||
? "Dmg"
|
||||
: "Armor";
|
||||
String successRate = "";
|
||||
|
||||
double baseChance = 0.0;
|
||||
switch (risk) {
|
||||
case RiskLevel.safe:
|
||||
baseChance = BattleConfig.safeBaseChance;
|
||||
efficiency = actionType == ActionType.attack
|
||||
? BattleConfig.attackSafeEfficiency
|
||||
: BattleConfig.defendSafeEfficiency;
|
||||
break;
|
||||
case RiskLevel.normal:
|
||||
baseChance = BattleConfig.normalBaseChance;
|
||||
efficiency = actionType == ActionType.attack
|
||||
? BattleConfig.attackNormalEfficiency
|
||||
: BattleConfig.defendNormalEfficiency;
|
||||
break;
|
||||
case RiskLevel.risky:
|
||||
baseChance = BattleConfig.riskyBaseChance;
|
||||
efficiency = actionType == ActionType.attack
|
||||
? BattleConfig.attackRiskyEfficiency
|
||||
: BattleConfig.defendRiskyEfficiency;
|
||||
break;
|
||||
}
|
||||
|
||||
double finalChance = baseChance + (player.totalLuck / 100.0);
|
||||
if (finalChance > 1.0) finalChance = 1.0;
|
||||
successRate = "${(finalChance * 100).toInt()}%";
|
||||
|
||||
infoText =
|
||||
"Success: $successRate, Eff: ${(efficiency * 100).toInt()}% ($expectedValue $valueUnit)";
|
||||
|
||||
return SimpleDialogOption(
|
||||
onPressed: () {
|
||||
context.read<BattleProvider>().playerAction(actionType, risk);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
risk.name,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text(
|
||||
infoText,
|
||||
style: TextStyle(fontSize: 12, color: infoColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
},
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -664,39 +588,7 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||
Column(
|
||||
children: [
|
||||
// Top Bar
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Flexible(
|
||||
child: FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
child: Text(
|
||||
"Stage ${battleProvider.stage}",
|
||||
style: const TextStyle(
|
||||
color: ThemeConfig.textColorWhite,
|
||||
fontSize: ThemeConfig.fontSizeHeader,
|
||||
fontWeight: ThemeConfig.fontWeightBold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
child: Text(
|
||||
"${AppStrings.turn} ${battleProvider.turnCount}",
|
||||
style: const TextStyle(
|
||||
color: ThemeConfig.textColorWhite,
|
||||
fontSize: ThemeConfig.fontSizeHeader,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const BattleHeader(),
|
||||
|
||||
// Battle Area (Characters) - Expanded to fill available space
|
||||
Expanded(
|
||||
@@ -742,43 +634,33 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||
top: 60,
|
||||
left: 16,
|
||||
right: 16,
|
||||
height: 150,
|
||||
height: BattleConfig.logsOverlayHeight,
|
||||
child: BattleLogOverlay(logs: battleProvider.logs),
|
||||
),
|
||||
|
||||
// 4. Floating Action Buttons (Bottom Right)
|
||||
// 4. Battle Controls (Bottom Right)
|
||||
Positioned(
|
||||
bottom: 20,
|
||||
right: 20,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
_buildFloatingActionButton(
|
||||
context,
|
||||
"ATK",
|
||||
ThemeConfig.btnActionActive,
|
||||
ActionType.attack,
|
||||
child: BattleControls(
|
||||
isAttackEnabled:
|
||||
battleProvider.isPlayerTurn &&
|
||||
!battleProvider.player.isDead &&
|
||||
!battleProvider.enemy.isDead &&
|
||||
!battleProvider.showRewardPopup &&
|
||||
!_isPlayerAttacking &&
|
||||
!_isEnemyAttacking,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_buildFloatingActionButton(
|
||||
context,
|
||||
"DEF",
|
||||
ThemeConfig.btnDefendActive,
|
||||
ActionType.defend,
|
||||
!battleProvider.player.isDead &&
|
||||
!battleProvider.enemy.isDead &&
|
||||
!battleProvider.showRewardPopup &&
|
||||
!_isPlayerAttacking &&
|
||||
!_isEnemyAttacking,
|
||||
isDefendEnabled:
|
||||
battleProvider.isPlayerTurn &&
|
||||
!battleProvider.player.isDead &&
|
||||
!battleProvider.enemy.isDead &&
|
||||
!battleProvider.showRewardPopup &&
|
||||
!_isPlayerAttacking &&
|
||||
!_isEnemyAttacking,
|
||||
),
|
||||
],
|
||||
!battleProvider.player.isDead &&
|
||||
!battleProvider.enemy.isDead &&
|
||||
!battleProvider.showRewardPopup &&
|
||||
!_isPlayerAttacking &&
|
||||
!_isEnemyAttacking,
|
||||
onAttackPressed: () =>
|
||||
_showRiskLevelSelection(context, ActionType.attack),
|
||||
onDefendPressed: () =>
|
||||
_showRiskLevelSelection(context, ActionType.defend),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -789,7 +671,7 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||
child: FloatingActionButton(
|
||||
heroTag: "logToggle",
|
||||
mini: true,
|
||||
backgroundColor: Colors.grey[800],
|
||||
backgroundColor: ThemeConfig.toggleBtnBg,
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_showLogs = !_showLogs;
|
||||
@@ -820,7 +702,7 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||
Icon(
|
||||
Icons.monetization_on,
|
||||
color: ThemeConfig.statGoldColor,
|
||||
size: 18,
|
||||
size: ThemeConfig.itemIconSizeSmall,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
@@ -846,7 +728,8 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||
content: Text(
|
||||
"${AppStrings.inventoryFull} Cannot take item.",
|
||||
),
|
||||
backgroundColor: Colors.red,
|
||||
backgroundColor:
|
||||
ThemeConfig.snackBarErrorBg,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -860,7 +743,7 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||
Container(
|
||||
padding: const EdgeInsets.all(4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blueGrey[700],
|
||||
color: ThemeConfig.rewardItemBg,
|
||||
borderRadius: BorderRadius.circular(
|
||||
4,
|
||||
),
|
||||
@@ -875,8 +758,9 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||
),
|
||||
child: Image.asset(
|
||||
ItemUtils.getIconPath(item.slot),
|
||||
width: 24,
|
||||
height: 24,
|
||||
width: ThemeConfig.itemIconSizeMedium,
|
||||
height:
|
||||
ThemeConfig.itemIconSizeMedium,
|
||||
fit: BoxFit.contain,
|
||||
filterQuality: FilterQuality.high,
|
||||
),
|
||||
@@ -934,16 +818,16 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||
color: ThemeConfig.statHpColor,
|
||||
fontSize: ThemeConfig.fontSizeHuge,
|
||||
fontWeight: ThemeConfig.fontWeightBold,
|
||||
letterSpacing: 4.0,
|
||||
letterSpacing: ThemeConfig.letterSpacingHeader,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.grey[800],
|
||||
backgroundColor: ThemeConfig.menuButtonBg,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 32,
|
||||
vertical: 16,
|
||||
horizontal: ThemeConfig.paddingBtnHorizontal,
|
||||
vertical: ThemeConfig.paddingBtnVertical,
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
@@ -1013,35 +897,4 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildFloatingActionButton(
|
||||
BuildContext context,
|
||||
String label,
|
||||
Color color,
|
||||
ActionType actionType,
|
||||
bool isEnabled,
|
||||
) {
|
||||
String iconPath;
|
||||
if (actionType == ActionType.attack) {
|
||||
iconPath = 'assets/data/icon/icon_weapon.png';
|
||||
} else {
|
||||
iconPath = 'assets/data/icon/icon_shield.png';
|
||||
}
|
||||
|
||||
return FloatingActionButton(
|
||||
heroTag: label,
|
||||
onPressed: isEnabled
|
||||
? () => _showRiskLevelSelection(context, actionType)
|
||||
: null,
|
||||
backgroundColor: isEnabled ? color : ThemeConfig.btnDisabled,
|
||||
child: Image.asset(
|
||||
iconPath,
|
||||
width: 32,
|
||||
height: 32,
|
||||
color: ThemeConfig.textColorWhite, // Tint icon white
|
||||
fit: BoxFit.contain,
|
||||
filterQuality: FilterQuality.high,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../providers/battle_provider.dart';
|
||||
import '../game/data/player_table.dart';
|
||||
import '../providers.dart';
|
||||
import '../game/data.dart';
|
||||
import 'main_wrapper.dart';
|
||||
import '../widgets/responsive_container.dart';
|
||||
import '../game/config/theme_config.dart';
|
||||
import '../game/config/app_strings.dart';
|
||||
import '../widgets.dart';
|
||||
import '../game/config.dart';
|
||||
|
||||
class CharacterSelectionScreen extends StatelessWidget {
|
||||
const CharacterSelectionScreen({super.key});
|
||||
@@ -75,7 +74,9 @@ class CharacterSelectionScreen extends StatelessWidget {
|
||||
Text(
|
||||
warrior.description,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(color: ThemeConfig.textColorGrey),
|
||||
style: const TextStyle(
|
||||
color: ThemeConfig.textColorGrey,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
const Divider(),
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../providers/battle_provider.dart';
|
||||
import '../game/model/item.dart';
|
||||
import '../providers.dart';
|
||||
import '../game/models.dart';
|
||||
import '../game/enums.dart';
|
||||
import '../utils/item_utils.dart';
|
||||
import '../game/config/theme_config.dart';
|
||||
import '../game/config/app_strings.dart';
|
||||
import '../widgets/inventory/character_stats_widget.dart';
|
||||
import '../widgets/inventory/inventory_grid_widget.dart';
|
||||
import '../utils.dart';
|
||||
import '../game/config.dart';
|
||||
import '../widgets.dart';
|
||||
|
||||
class InventoryScreen extends StatelessWidget {
|
||||
const InventoryScreen({super.key});
|
||||
|
||||
@@ -2,11 +2,10 @@ import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'character_selection_screen.dart';
|
||||
import 'main_wrapper.dart';
|
||||
import '../widgets/responsive_container.dart';
|
||||
import '../widgets.dart';
|
||||
import '../game/save_manager.dart';
|
||||
import '../providers/battle_provider.dart';
|
||||
import '../game/config/theme_config.dart';
|
||||
import '../game/config/app_strings.dart';
|
||||
import '../providers.dart';
|
||||
import '../game/config.dart';
|
||||
|
||||
class MainMenuScreen extends StatefulWidget {
|
||||
const MainMenuScreen({super.key});
|
||||
@@ -61,10 +60,7 @@ class _MainMenuScreenState extends State<MainMenuScreen> {
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
ThemeConfig.mainMenuBgTop,
|
||||
ThemeConfig.mainMenuBgBottom,
|
||||
],
|
||||
colors: [ThemeConfig.mainMenuBgTop, ThemeConfig.mainMenuBgBottom],
|
||||
),
|
||||
),
|
||||
child: ResponsiveContainer(
|
||||
@@ -121,10 +117,11 @@ class _MainMenuScreenState extends State<MainMenuScreen> {
|
||||
onPressed: () {
|
||||
// Warn if save exists? Or just overwrite on save.
|
||||
// For now, simpler flow.
|
||||
Navigator.push(
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const CharacterSelectionScreen(),
|
||||
builder: (context) =>
|
||||
const CharacterSelectionScreen(),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../providers.dart';
|
||||
import '../game/enums.dart';
|
||||
import 'battle_screen.dart';
|
||||
import 'inventory_screen.dart';
|
||||
import 'settings_screen.dart';
|
||||
import '../widgets/responsive_container.dart';
|
||||
import '../game/config/theme_config.dart';
|
||||
import '../widgets.dart';
|
||||
import '../game/config.dart';
|
||||
|
||||
class MainWrapper extends StatefulWidget {
|
||||
const MainWrapper({super.key});
|
||||
@@ -23,37 +26,82 @@ class _MainWrapperState extends State<MainWrapper> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: ThemeConfig.mainMenuBgTop, // Outer background for web
|
||||
body: Center(
|
||||
child: ResponsiveContainer(
|
||||
child: Scaffold(
|
||||
body: IndexedStack(index: _currentIndex, children: _screens),
|
||||
bottomNavigationBar: BottomNavigationBar(
|
||||
currentIndex: _currentIndex,
|
||||
onTap: (index) {
|
||||
setState(() {
|
||||
_currentIndex = index;
|
||||
});
|
||||
},
|
||||
items: const [
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.flash_on),
|
||||
label: 'Battle',
|
||||
return Consumer<BattleProvider>(
|
||||
builder: (context, battleProvider, child) {
|
||||
// Determine the first tab's icon and label based on StageType
|
||||
String stageLabel = "Battle";
|
||||
IconData stageIcon = Icons.flash_on;
|
||||
|
||||
// Ensure we check null safety if currentStage isn't ready (though it should be)
|
||||
// battleProvider.currentStage might be accessed safely if standardized
|
||||
// Assuming battleProvider.currentStage is accessible or we check stage type logic
|
||||
try {
|
||||
final stageType = battleProvider.currentStage.type;
|
||||
switch (stageType) {
|
||||
case StageType.battle:
|
||||
case StageType.elite:
|
||||
stageLabel = "Battle";
|
||||
stageIcon = Icons.flash_on;
|
||||
break;
|
||||
case StageType.shop:
|
||||
stageLabel = "Shop";
|
||||
stageIcon = Icons.store;
|
||||
break;
|
||||
case StageType.rest:
|
||||
stageLabel = "Rest";
|
||||
stageIcon = Icons.hotel;
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
// Fallback if not initialized
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: ThemeConfig.mainMenuBgTop,
|
||||
body: Center(
|
||||
child: ResponsiveContainer(
|
||||
child: Scaffold(
|
||||
body: IndexedStack(index: _currentIndex, children: _screens),
|
||||
bottomNavigationBar: Theme(
|
||||
data: Theme.of(
|
||||
context,
|
||||
).copyWith(canvasColor: ThemeConfig.mainMenuBgBottom),
|
||||
child: BottomNavigationBar(
|
||||
currentIndex: _currentIndex,
|
||||
onTap: (index) {
|
||||
setState(() {
|
||||
_currentIndex = index;
|
||||
});
|
||||
},
|
||||
backgroundColor: ThemeConfig.mainMenuBgBottom,
|
||||
selectedItemColor: ThemeConfig.mainIconColor,
|
||||
unselectedItemColor: ThemeConfig.textColorGrey,
|
||||
selectedFontSize:
|
||||
ThemeConfig.fontSizeLarge, // Highlight selection
|
||||
unselectedFontSize: ThemeConfig.fontSizeSmall,
|
||||
type: BottomNavigationBarType
|
||||
.fixed, // Ensure consistent formatting
|
||||
items: [
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(stageIcon),
|
||||
label: stageLabel,
|
||||
),
|
||||
const BottomNavigationBarItem(
|
||||
icon: Icon(Icons.backpack),
|
||||
label: 'Inventory',
|
||||
),
|
||||
const BottomNavigationBarItem(
|
||||
icon: Icon(Icons.settings),
|
||||
label: 'Settings',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.backpack),
|
||||
label: 'Inventory',
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.settings),
|
||||
label: 'Settings',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../providers/battle_provider.dart';
|
||||
import '../providers/settings_provider.dart'; // Import SettingsProvider
|
||||
import '../providers.dart';
|
||||
import 'main_menu_screen.dart';
|
||||
import '../game/config/theme_config.dart';
|
||||
import '../game/config/app_strings.dart';
|
||||
import '../game/config.dart';
|
||||
|
||||
class SettingsScreen extends StatelessWidget {
|
||||
const SettingsScreen({super.key});
|
||||
|
||||
Reference in New Issue
Block a user