feat(front): 프론트 화면 개선 및 설정 저장소 추가
- front_screen_animation.dart: 프론트 화면 애니메이션 추가 - settings_repository.dart: 설정 저장소 구현 - front/widgets/: 프론트 화면 위젯 분리 - mobile_carousel_layout.dart: 모바일 레이아웃 개선 - app.dart: 앱 설정 개선 - game_text_l10n.dart: 텍스트 추가
This commit is contained in:
@@ -10,6 +10,7 @@ import 'package:askiineverdie/src/core/model/pq_config.dart';
|
||||
import 'package:askiineverdie/src/core/notification/notification_service.dart';
|
||||
import 'package:askiineverdie/src/core/storage/save_manager.dart';
|
||||
import 'package:askiineverdie/src/core/storage/save_repository.dart';
|
||||
import 'package:askiineverdie/src/core/storage/settings_repository.dart';
|
||||
import 'package:askiineverdie/src/features/front/front_screen.dart';
|
||||
import 'package:askiineverdie/src/features/front/save_picker_dialog.dart';
|
||||
import 'package:askiineverdie/src/features/game/game_play_screen.dart';
|
||||
@@ -28,8 +29,10 @@ class AskiiNeverDieApp extends StatefulWidget {
|
||||
class _AskiiNeverDieAppState extends State<AskiiNeverDieApp> {
|
||||
late final GameSessionController _controller;
|
||||
late final NotificationService _notificationService;
|
||||
late final SettingsRepository _settingsRepository;
|
||||
bool _isCheckingSave = true;
|
||||
bool _hasSave = false;
|
||||
ThemeMode _themeMode = ThemeMode.system;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -47,11 +50,28 @@ class _AskiiNeverDieAppState extends State<AskiiNeverDieApp> {
|
||||
saveManager: SaveManager(SaveRepository()),
|
||||
);
|
||||
_notificationService = NotificationService();
|
||||
_settingsRepository = SettingsRepository();
|
||||
|
||||
// 초기 설정 로드
|
||||
_loadSettings();
|
||||
// 세이브 파일 존재 여부 확인
|
||||
_checkForExistingSave();
|
||||
}
|
||||
|
||||
/// 저장된 설정 불러오기
|
||||
Future<void> _loadSettings() async {
|
||||
final themeMode = await _settingsRepository.loadThemeMode();
|
||||
if (mounted) {
|
||||
setState(() => _themeMode = themeMode);
|
||||
}
|
||||
}
|
||||
|
||||
/// 테마 모드 변경
|
||||
void _changeThemeMode(ThemeMode mode) {
|
||||
setState(() => _themeMode = mode);
|
||||
_settingsRepository.saveThemeMode(mode);
|
||||
}
|
||||
|
||||
/// 세이브 파일 존재 여부 확인 후 자동 로드
|
||||
Future<void> _checkForExistingSave() async {
|
||||
final exists = await _controller.saveManager.saveExists();
|
||||
@@ -70,6 +90,32 @@ class _AskiiNeverDieAppState extends State<AskiiNeverDieApp> {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/// 라이트 테마
|
||||
ThemeData get _lightTheme => ThemeData(
|
||||
colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF234361)),
|
||||
scaffoldBackgroundColor: const Color(0xFFF4F5F7),
|
||||
useMaterial3: true,
|
||||
);
|
||||
|
||||
/// 다크 테마 (OLED 저전력 모드 - 순수 검정)
|
||||
ThemeData get _darkTheme => ThemeData(
|
||||
colorScheme: ColorScheme.dark(
|
||||
surface: Colors.black,
|
||||
primary: const Color(0xFF4FC3F7), // 시안
|
||||
secondary: const Color(0xFFFF4081), // 마젠타
|
||||
onSurface: Colors.white70,
|
||||
primaryContainer: const Color(0xFF1A3A4A),
|
||||
onPrimaryContainer: Colors.white,
|
||||
),
|
||||
scaffoldBackgroundColor: Colors.black,
|
||||
useMaterial3: true,
|
||||
// 카드/다이얼로그도 검정 배경 사용
|
||||
cardColor: const Color(0xFF121212),
|
||||
dialogTheme: const DialogThemeData(
|
||||
backgroundColor: Color(0xFF121212),
|
||||
),
|
||||
);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
@@ -77,11 +123,9 @@ class _AskiiNeverDieAppState extends State<AskiiNeverDieApp> {
|
||||
debugShowCheckedModeBanner: false,
|
||||
localizationsDelegates: L10n.localizationsDelegates,
|
||||
supportedLocales: L10n.supportedLocales,
|
||||
theme: ThemeData(
|
||||
colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF234361)),
|
||||
scaffoldBackgroundColor: const Color(0xFFF4F5F7),
|
||||
useMaterial3: true,
|
||||
),
|
||||
theme: _lightTheme,
|
||||
darkTheme: _darkTheme,
|
||||
themeMode: _themeMode,
|
||||
builder: (context, child) {
|
||||
// 현재 로케일을 게임 텍스트 l10n 시스템에 동기화
|
||||
final locale = Localizations.localeOf(context);
|
||||
@@ -110,6 +154,8 @@ class _AskiiNeverDieAppState extends State<AskiiNeverDieApp> {
|
||||
// 로드 실패 시 프론트 화면으로
|
||||
setState(() => _hasSave = false);
|
||||
},
|
||||
currentThemeMode: _themeMode,
|
||||
onThemeModeChange: _changeThemeMode,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -118,6 +164,7 @@ class _AskiiNeverDieAppState extends State<AskiiNeverDieApp> {
|
||||
onNewCharacter: _navigateToNewCharacter,
|
||||
onLoadSave: _loadSave,
|
||||
onHallOfFame: _navigateToHallOfFame,
|
||||
hasSaveFile: _hasSave,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -187,6 +234,8 @@ class _AskiiNeverDieAppState extends State<AskiiNeverDieApp> {
|
||||
builder: (context) => GamePlayScreen(
|
||||
controller: _controller,
|
||||
forceCarouselLayout: testMode,
|
||||
currentThemeMode: _themeMode,
|
||||
onThemeModeChange: _changeThemeMode,
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -196,7 +245,11 @@ class _AskiiNeverDieAppState extends State<AskiiNeverDieApp> {
|
||||
void _navigateToGame(BuildContext context) {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (context) => GamePlayScreen(controller: _controller),
|
||||
builder: (context) => GamePlayScreen(
|
||||
controller: _controller,
|
||||
currentThemeMode: _themeMode,
|
||||
onThemeModeChange: _changeThemeMode,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -235,10 +288,17 @@ class _SplashScreen extends StatelessWidget {
|
||||
|
||||
/// 자동 로드 화면 (세이브 파일 자동 로드)
|
||||
class _AutoLoadScreen extends StatefulWidget {
|
||||
const _AutoLoadScreen({required this.controller, required this.onLoadFailed});
|
||||
const _AutoLoadScreen({
|
||||
required this.controller,
|
||||
required this.onLoadFailed,
|
||||
required this.currentThemeMode,
|
||||
required this.onThemeModeChange,
|
||||
});
|
||||
|
||||
final GameSessionController controller;
|
||||
final VoidCallback onLoadFailed;
|
||||
final ThemeMode currentThemeMode;
|
||||
final void Function(ThemeMode mode) onThemeModeChange;
|
||||
|
||||
@override
|
||||
State<_AutoLoadScreen> createState() => _AutoLoadScreenState();
|
||||
@@ -262,7 +322,8 @@ class _AutoLoadScreenState extends State<_AutoLoadScreen> {
|
||||
MaterialPageRoute<void>(
|
||||
builder: (context) => GamePlayScreen(
|
||||
controller: widget.controller,
|
||||
// 자동 로드 시에는 플랫폼 기본값 사용 (모바일만 캐로셀)
|
||||
currentThemeMode: widget.currentThemeMode,
|
||||
onThemeModeChange: widget.onThemeModeChange,
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -274,19 +335,19 @@ class _AutoLoadScreenState extends State<_AutoLoadScreen> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const Scaffold(
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
const Text(
|
||||
'ASCII NEVER DIE',
|
||||
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
CircularProgressIndicator(),
|
||||
SizedBox(height: 16),
|
||||
Text('Loading...'),
|
||||
const SizedBox(height: 16),
|
||||
const CircularProgressIndicator(),
|
||||
const SizedBox(height: 16),
|
||||
Text(game_l10n.uiLoading),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user