checkpoint: focus seed 1.0.1 localized dev switch
This commit is contained in:
@@ -1,19 +1,132 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
|
||||
import '../core/ambience.dart';
|
||||
import '../data/app_preferences_store.dart';
|
||||
import '../features/shell/focus_seed_home.dart';
|
||||
import '../l10n/generated/app_localizations.dart';
|
||||
import '../models/appearance_preference.dart';
|
||||
import '../models/language_preference.dart';
|
||||
import 'app_theme.dart';
|
||||
|
||||
class FocusSeedApp extends StatelessWidget {
|
||||
const FocusSeedApp({super.key});
|
||||
@visibleForTesting
|
||||
Locale focusSeedDefaultLocale({bool isRelease = kReleaseMode}) {
|
||||
return isRelease ? const Locale('en') : const Locale('zh');
|
||||
}
|
||||
|
||||
class FocusSeedApp extends StatefulWidget {
|
||||
const FocusSeedApp({this.locale, super.key});
|
||||
|
||||
final Locale? locale;
|
||||
|
||||
@override
|
||||
State<FocusSeedApp> createState() => _FocusSeedAppState();
|
||||
}
|
||||
|
||||
class _FocusSeedAppState extends State<FocusSeedApp>
|
||||
with WidgetsBindingObserver {
|
||||
final _preferencesStore = AppPreferencesStore();
|
||||
AppearancePreference _appearance = AppearancePreference.system;
|
||||
LanguagePreference _language = LanguagePreference.defaultLocale;
|
||||
DayPhase _dayPhase = dayPhaseFor(DateTime.now());
|
||||
Timer? _phaseTimer;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
_loadPreferences();
|
||||
_schedulePhaseRefresh();
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
_refreshDayPhase();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _loadPreferences() async {
|
||||
final appearance = await _preferencesStore.loadAppearance();
|
||||
final language = await _preferencesStore.loadLanguage();
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
_appearance = appearance;
|
||||
_language = language;
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _setAppearance(AppearancePreference appearance) async {
|
||||
setState(() => _appearance = appearance);
|
||||
await _preferencesStore.saveAppearance(appearance);
|
||||
}
|
||||
|
||||
Future<void> _setLanguage(LanguagePreference language) async {
|
||||
setState(() => _language = language);
|
||||
await _preferencesStore.saveLanguage(language);
|
||||
}
|
||||
|
||||
void _refreshDayPhase() {
|
||||
final phase = dayPhaseFor(DateTime.now());
|
||||
if (phase != _dayPhase && mounted) {
|
||||
setState(() => _dayPhase = phase);
|
||||
}
|
||||
_schedulePhaseRefresh();
|
||||
}
|
||||
|
||||
void _schedulePhaseRefresh() {
|
||||
_phaseTimer?.cancel();
|
||||
final now = DateTime.now();
|
||||
final delay = nextDayPhaseBoundary(now).difference(now);
|
||||
_phaseTimer = Timer(delay, _refreshDayPhase);
|
||||
}
|
||||
|
||||
ThemeMode get _themeMode => switch (_appearance) {
|
||||
AppearancePreference.system => ThemeMode.system,
|
||||
AppearancePreference.light => ThemeMode.light,
|
||||
AppearancePreference.dark => ThemeMode.dark,
|
||||
};
|
||||
|
||||
Locale get _resolvedLocale {
|
||||
return widget.locale ?? _language.locale ?? focusSeedDefaultLocale();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'Focus Seed',
|
||||
onGenerateTitle: (context) => AppLocalizations.of(context).appTitle,
|
||||
debugShowCheckedModeBanner: false,
|
||||
theme: AppTheme.light(),
|
||||
darkTheme: AppTheme.dark(),
|
||||
home: const FocusSeedHome(),
|
||||
theme: AppTheme.light(_dayPhase),
|
||||
darkTheme: AppTheme.dark(_dayPhase),
|
||||
themeMode: _themeMode,
|
||||
themeAnimationDuration: const Duration(milliseconds: 240),
|
||||
locale: _resolvedLocale,
|
||||
localizationsDelegates: const [
|
||||
AppLocalizations.delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
],
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
home: FocusSeedHome(
|
||||
appearance: _appearance,
|
||||
onAppearanceChanged: _setAppearance,
|
||||
language: _language,
|
||||
showLanguageTools: !kReleaseMode && widget.locale == null,
|
||||
onLanguageChanged: _setLanguage,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
_phaseTimer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user