import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; import 'di/injection.dart'; import '../core/l10n/l10n.dart'; import '../l10n/app_localizations.dart'; import '../features/auth/presentation/bloc/auth_bloc.dart'; import '../features/auth/presentation/bloc/auth_event.dart'; import '../features/auth/presentation/bloc/auth_state.dart'; import '../features/chat/presentation/bloc/chat_bloc.dart'; import '../data/cache/cache_scope.dart'; import 'services/app_prewarm_orchestrator.dart'; import 'router/app_router.dart'; import '../core/theme/app_theme.dart'; class LinksyApp extends StatefulWidget { const LinksyApp({super.key}); @override State createState() => _LinksyAppState(); } class _LinksyAppState extends State { late final AuthBloc _authBloc; late final GoRouter _router; int _cacheScopeVersion = 0; Future _onAuthenticated(String userId) async { _cacheScopeVersion += 1; final scopeKey = 'user:$userId:v$_cacheScopeVersion'; CacheScope.configureProvider(() => scopeKey); await sl().switchUser(userId); await sl().ensureStartedFor(userId); } Future _onUnauthenticated() async { _cacheScopeVersion += 1; final scopeKey = 'anonymous:v$_cacheScopeVersion'; CacheScope.configureProvider(() => scopeKey); await sl().switchUser(null); sl().reset(); } @override void initState() { super.initState(); _authBloc = sl(); const initialScopeKey = 'anonymous:v0'; CacheScope.configureProvider(() => initialScopeKey); _authBloc.add(AuthStarted()); _router = createAppRouter(_authBloc); } @override void dispose() { _router.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return BlocProvider.value( value: _authBloc, child: BlocListener( listener: (context, state) { if (state is AuthAuthenticated) { unawaited(_onAuthenticated(state.user.id)); } if (state is AuthUnauthenticated) { unawaited(_onUnauthenticated()); } }, child: MaterialApp.router( onGenerateTitle: (context) => AppLocalizations.of(context).appTitle, debugShowCheckedModeBanner: false, theme: AppTheme.light, darkTheme: AppTheme.dark, themeMode: ThemeMode.system, locale: const Locale('zh'), supportedLocales: AppLocalizations.supportedLocales, localizationsDelegates: AppLocalizations.localizationsDelegates, builder: (context, child) { L10n.setLocale(Localizations.localeOf(context)); return child ?? const SizedBox.shrink(); }, routerConfig: _router, ), ), ); } }