124 lines
4.7 KiB
Dart
124 lines
4.7 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||
import 'package:flutter_localizations/flutter_localizations.dart'; // Localization
|
||
import 'package:hive_flutter/hive_flutter.dart';
|
||
import 'models/sake_item.dart';
|
||
import 'models/user_profile.dart';
|
||
import 'models/menu_settings.dart';
|
||
import 'providers/theme_provider.dart';
|
||
import 'screens/main_screen.dart';
|
||
import 'screens/license_screen.dart';
|
||
import 'services/migration_service.dart';
|
||
|
||
/// 店舗向けビルドかどうかを判定するビルド時フラグ
|
||
///
|
||
/// ビルドコマンド:
|
||
/// - 消費者向け: flutter build apk --release --dart-define=IS_BUSINESS_APP=false
|
||
/// - 店舗向け: flutter build apk --release --dart-define=IS_BUSINESS_APP=true
|
||
///
|
||
/// デフォルトはfalse(消費者向け)
|
||
const bool isBusinessApp = bool.fromEnvironment('IS_BUSINESS_APP', defaultValue: false);
|
||
|
||
void main() async {
|
||
WidgetsFlutterBinding.ensureInitialized();
|
||
|
||
await Hive.initFlutter();
|
||
|
||
Hive.registerAdapter(SakeItemAdapter());
|
||
Hive.registerAdapter(UserProfileAdapter());
|
||
Hive.registerAdapter(MenuSettingsAdapter());
|
||
Hive.registerAdapter(DisplayDataAdapter());
|
||
Hive.registerAdapter(HiddenSpecsAdapter());
|
||
Hive.registerAdapter(UserDataAdapter());
|
||
Hive.registerAdapter(GamificationAdapter());
|
||
Hive.registerAdapter(MetadataAdapter());
|
||
Hive.registerAdapter(ItemTypeAdapter()); // Restored missing adapter
|
||
// Open all boxes first (faster to open them together)
|
||
// Reverted to synchronous wait to ensure Providers have data immediately
|
||
// Open all boxes in parallel (Much faster than sequential)
|
||
await Future.wait([
|
||
Hive.openBox('settings'),
|
||
Hive.openBox<UserProfile>('user_profile'),
|
||
Hive.openBox<SakeItem>('sake_items'),
|
||
Hive.openBox<MenuSettings>('menu_settings'),
|
||
]);
|
||
|
||
// Migration — バージョン番号で管理(単一フラグだと将来の追加マイグレーションが走らないため)
|
||
// migration_completed=true の旧ユーザーはバージョン 1 扱いとして互換性を維持する
|
||
const int currentMigrationVersion = 1;
|
||
final box = Hive.box('settings');
|
||
final legacyCompleted = box.get('migration_completed', defaultValue: false) as bool;
|
||
final storedVersion = legacyCompleted
|
||
? box.get('migration_version', defaultValue: 1) as int // 旧ユーザー: 既に完了済み=v1
|
||
: box.get('migration_version', defaultValue: 0) as int; // 新規ユーザー: 未実行=v0
|
||
|
||
if (storedVersion < currentMigrationVersion) {
|
||
final migrationSucceeded = await MigrationService.runMigration();
|
||
if (migrationSucceeded) {
|
||
await box.put('migration_version', currentMigrationVersion);
|
||
await box.put('migration_completed', true); // 旧フラグも維持(後方互換)
|
||
} else {
|
||
// バックアップ失敗などでマイグレーションが中断された場合は
|
||
// バージョンを進めない。次回起動で再試行される。
|
||
debugPrint('[main] Migration aborted — migration_version not updated');
|
||
}
|
||
}
|
||
|
||
// v1.0.33: AI 解析キャッシュをインメモリ化したため、旧 Hive ボックスをディスクから削除する
|
||
// (既存ユーザーのデータ残骸クリーンアップ。ボックスが存在しない場合は何もしない)
|
||
for (final boxName in ['analysis_cache_v1', 'brand_index_v1']) {
|
||
try {
|
||
await Hive.deleteBoxFromDisk(boxName);
|
||
} catch (_) {
|
||
// 存在しない場合は無視
|
||
}
|
||
}
|
||
|
||
runApp(
|
||
const ProviderScope(
|
||
child: MyApp(),
|
||
),
|
||
);
|
||
}
|
||
|
||
class MyApp extends ConsumerWidget {
|
||
const MyApp({super.key});
|
||
|
||
@override
|
||
Widget build(BuildContext context, WidgetRef ref) {
|
||
final lightTheme = ref.watch(lightThemeProvider);
|
||
final darkTheme = ref.watch(darkThemeProvider);
|
||
final themeMode = ref.watch(themeModeProvider);
|
||
final locale = ref.watch(localeProvider); // NEW: User-selected locale
|
||
|
||
return MaterialApp(
|
||
debugShowCheckedModeBanner: false,
|
||
title: 'Ponshu Room Lite',
|
||
theme: lightTheme,
|
||
darkTheme: darkTheme,
|
||
themeMode: themeMode,
|
||
locale: locale, // NEW: Apply user's locale choice
|
||
|
||
// Localization (UPDATED)
|
||
localizationsDelegates: const [
|
||
GlobalMaterialLocalizations.delegate,
|
||
GlobalWidgetsLocalizations.delegate,
|
||
GlobalCupertinoLocalizations.delegate,
|
||
],
|
||
supportedLocales: const [
|
||
Locale('ja'),
|
||
Locale('en'),
|
||
],
|
||
|
||
navigatorObservers: [routeObserver],
|
||
home: const MainScreen(),
|
||
routes: {
|
||
'/upgrade': (context) => const LicenseScreen(),
|
||
},
|
||
);
|
||
}
|
||
}
|
||
|
||
// Global RouteObserver
|
||
final RouteObserver<ModalRoute<void>> routeObserver = RouteObserver<ModalRoute<void>>();
|