Files
eryao/apps/lib/app/app.dart
T

142 lines
4.2 KiB
Dart
Raw Normal View History

import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import '../core/auth/session_store.dart';
import '../data/network/api_client.dart';
import '../data/storage/local_kv_store.dart';
import '../features/auth/data/apis/auth_api.dart';
import '../features/auth/data/repositories/auth_repository.dart';
import '../features/auth/presentation/bloc/auth_bloc.dart';
import '../features/auth/presentation/bloc/auth_state.dart';
import '../features/auth/presentation/screens/login_screen.dart';
import '../features/home/presentation/screens/home_screen.dart';
2026-04-03 16:56:47 +08:00
import '../features/settings/data/models/profile_settings.dart';
import '../l10n/app_localizations.dart';
import '../shared/widgets/app_loading_indicator.dart';
import 'app_theme.dart';
import 'di/injection.dart';
class EryaoApp extends StatefulWidget {
const EryaoApp({super.key});
@override
State<EryaoApp> createState() => _EryaoAppState();
}
class _EryaoAppState extends State<EryaoApp> {
final SessionStore _sessionStore = SessionStore(LocalKvStore());
late final AuthBloc _authBloc;
Locale _locale = const Locale('zh');
2026-04-03 16:56:47 +08:00
ProfileSettingsV1 _profileSettings = ProfileSettingsV1.defaultsForLocale(
const Locale('zh'),
);
@override
void initState() {
super.initState();
final apiClient = ApiClient(
baseUrl: appDependencies.backendUrl,
tokenProvider: _sessionStore.getToken,
onUnauthorized: () {
return _authBloc.handleUnauthorized401();
},
);
final authApi = AuthApi(apiClient: apiClient);
final authRepository = AuthRepositoryImpl(
authApi: authApi,
sessionStore: _sessionStore,
);
_authBloc = AuthBloc(repository: authRepository);
_bootstrap();
}
@override
void dispose() {
_authBloc.dispose();
super.dispose();
}
Future<void> _bootstrap() async {
final localeCode = await _sessionStore.getLocaleCode();
2026-04-03 16:56:47 +08:00
final locale = localeCode == 'en' ? const Locale('en') : const Locale('zh');
if (mounted) {
setState(() {
2026-04-03 16:56:47 +08:00
_locale = locale;
_profileSettings = ProfileSettingsV1.defaultsForLocale(locale);
});
}
await _authBloc.start();
}
2026-04-03 16:56:47 +08:00
Future<void> _handleInterfaceLanguageChanged(String languageTag) async {
final locale = localeFromLanguageTag(languageTag);
await _sessionStore.saveLocaleCode(locale.languageCode);
if (!mounted) {
return;
}
setState(() {
_locale = locale;
2026-04-03 16:56:47 +08:00
_profileSettings = _profileSettings.copyWith(
preferences: _profileSettings.preferences.copyWith(
interfaceLanguage: languageTag,
),
);
});
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _authBloc,
builder: (context, _) {
return MaterialApp(
debugShowCheckedModeBanner: false,
onGenerateTitle: (context) => AppLocalizations.of(context)!.appTitle,
locale: _locale,
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: AppLocalizations.supportedLocales,
theme: AppTheme.light(),
home: _buildHomeByAuthState(_authBloc.state),
);
},
);
}
Widget _buildHomeByAuthState(AuthState state) {
if (state.status == AuthStatus.initial ||
state.status == AuthStatus.loading) {
return const Scaffold(
body: Center(
child: AppLoadingIndicator(variant: AppLoadingVariant.surface),
),
);
}
if (state.status == AuthStatus.authenticated && state.user != null) {
return HomeScreen(
account: state.user!.email,
sessionStore: _sessionStore,
2026-04-03 16:56:47 +08:00
currentLocale: _locale,
profileSettings: _profileSettings,
coinBalance: 100,
onLocaleChanged: _handleInterfaceLanguageChanged,
onLogout: _authBloc.logout,
);
}
return LoginScreen(
currentLocale: _locale,
2026-04-03 16:56:47 +08:00
onLocaleChanged: (_) {},
onRequestOtp: _authBloc.sendOtp,
onLoginWithOtp: (email, otp) {
return _authBloc.loginWithOtp(email: email, otp: otp);
},
);
}
}