feat(ui): 반응형 레이아웃 및 저장 시스템 개선

## 반응형 레이아웃
- app.dart: 화면 크기별 레이아웃 분기 로직 추가 (+173 라인)
- game_play_screen.dart: 반응형 UI 구조 개선
- layouts/, pages/ 디렉토리 추가 (새 레이아웃 시스템)
- carousel_nav_bar.dart: 캐러셀 네비게이션 바 추가
- enhanced_animation_panel.dart: 향상된 애니메이션 패널

## 저장 시스템
- save_manager.dart: 저장 관리 기능 확장
- save_repository.dart: 저장소 인터페이스 개선
- save_service.dart: 저장 서비스 로직 추가

## UI 개선
- notification_service.dart: 알림 시스템 기능 확장
- notification_overlay.dart: 오버레이 UI 개선
- equipment_stats_panel.dart: 장비 스탯 패널 개선
- cinematic_view.dart: 시네마틱 뷰 개선
- new_character_screen.dart: 캐릭터 생성 화면 개선

## 다국어
- game_text_l10n.dart: 텍스트 추가 (+182 라인)

## 테스트
- 관련 테스트 파일 업데이트
This commit is contained in:
JiWoong Sul
2025-12-23 17:52:43 +09:00
parent 1da6fa7a2b
commit e6af7dd91a
28 changed files with 2734 additions and 73 deletions

View File

@@ -18,7 +18,9 @@ class NewCharacterScreen extends StatefulWidget {
const NewCharacterScreen({super.key, this.onCharacterCreated});
/// 캐릭터 생성 완료 시 호출되는 콜백
final void Function(GameState initialState)? onCharacterCreated;
/// testMode: 웹에서도 모바일 캐로셀 레이아웃 사용
final void Function(GameState initialState, {bool testMode})?
onCharacterCreated;
@override
State<NewCharacterScreen> createState() => _NewCharacterScreenState();
@@ -53,6 +55,9 @@ class _NewCharacterScreenState extends State<NewCharacterScreen> {
// 이름 생성용 RNG
late DeterministicRandom _nameRng;
// 테스트 모드 (웹에서 모바일 캐로셀 레이아웃 활성화)
bool _testModeEnabled = false;
@override
void initState() {
super.initState();
@@ -198,7 +203,7 @@ class _NewCharacterScreenState extends State<NewCharacterScreen> {
queue: QueueState.empty(),
);
widget.onCharacterCreated?.call(initialState);
widget.onCharacterCreated?.call(initialState, testMode: _testModeEnabled);
}
@override
@@ -230,6 +235,10 @@ class _NewCharacterScreenState extends State<NewCharacterScreen> {
Expanded(child: _buildKlassSection()),
],
),
const SizedBox(height: 16),
// 테스트 모드 토글 (웹에서 모바일 레이아웃 테스트)
_buildTestModeToggle(),
const SizedBox(height: 24),
// Sold! 버튼
@@ -583,8 +592,9 @@ class _NewCharacterScreenState extends State<NewCharacterScreen> {
final percent = (passive.value * 100).round();
return switch (passive.type) {
ClassPassiveType.hpBonus => game_l10n.passiveHpBonus(percent),
ClassPassiveType.physicalDamageBonus =>
game_l10n.passivePhysicalBonus(percent),
ClassPassiveType.physicalDamageBonus => game_l10n.passivePhysicalBonus(
percent,
),
ClassPassiveType.defenseBonus => game_l10n.passiveDefenseBonus(percent),
ClassPassiveType.magicDamageBonus => game_l10n.passiveMagicBonus(percent),
ClassPassiveType.evasionBonus => game_l10n.passiveEvasionBonus(percent),
@@ -595,4 +605,17 @@ class _NewCharacterScreenState extends State<NewCharacterScreen> {
ClassPassiveType.firstStrikeBonus => passive.description,
};
}
/// 테스트 모드 토글 위젯
Widget _buildTestModeToggle() {
return Card(
child: SwitchListTile(
title: Text(game_l10n.uiTestMode),
subtitle: Text(game_l10n.uiTestModeDesc),
value: _testModeEnabled,
onChanged: (value) => setState(() => _testModeEnabled = value),
secondary: const Icon(Icons.phone_android),
),
);
}
}