feat: Optimize theme data handling and simplify widget structure in NotesApp

This commit is contained in:
2026-05-21 17:02:05 +02:00
parent 063b300428
commit 62d47904d9
+141 -144
View File
@@ -102,6 +102,7 @@ class _NotesAppState extends State<NotesApp>
setState(() {
_themeSeedColor = Color(storedColorValue);
_themeData = AppTheme.theme(seedColor: _themeSeedColor);
});
}
@@ -115,10 +116,14 @@ class _NotesAppState extends State<NotesApp>
setState(() {
_themeSeedColor = color;
_themeData = AppTheme.theme(seedColor: _themeSeedColor);
});
}
ThemeData get _theme => AppTheme.theme(seedColor: _themeSeedColor);
// Cached ThemeData to avoid recomputing on every build.
ThemeData? _themeData;
ThemeData get _theme => _themeData ??= AppTheme.theme(seedColor: _themeSeedColor);
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
@@ -767,43 +772,30 @@ class _NotesAppState extends State<NotesApp>
}
Widget _buildLoadingScreen() {
return MaterialApp(
navigatorKey: _navigatorKey,
title: 'Mis Notas',
debugShowCheckedModeBanner: false,
theme: _theme,
home: const Scaffold(
body: SafeArea(
child: Column(
children: [
Expanded(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
SizedBox(height: 16),
Text('Preparando el vault local...'),
],
),
return const Scaffold(
body: SafeArea(
child: Column(
children: [
Expanded(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
SizedBox(height: 16),
Text('Preparando el vault local...'),
],
),
),
],
),
),
],
),
),
);
}
Widget _buildAppShell({required Widget home}) {
return MaterialApp(
navigatorKey: _navigatorKey,
title: 'Mis Notas',
debugShowCheckedModeBanner: false,
scaffoldMessengerKey: _scaffoldMessengerKey,
theme: _theme,
home: home,
);
return home;
}
Widget _buildMainShell(NoteRepository repository) {
@@ -829,69 +821,62 @@ class _NotesAppState extends State<NotesApp>
onThemeColorSelected: _setThemeSeedColor,
);
return MaterialApp(
navigatorKey: _navigatorKey,
title: 'Mis Notas',
debugShowCheckedModeBanner: false,
scaffoldMessengerKey: _scaffoldMessengerKey,
theme: _theme,
home: Shortcuts(
shortcuts: <LogicalKeySet, Intent>{
LogicalKeySet(LogicalKeyboardKey.f5): const PerformSyncIntent(),
return Shortcuts(
shortcuts: <LogicalKeySet, Intent>{
LogicalKeySet(LogicalKeyboardKey.f5): const PerformSyncIntent(),
},
child: Actions(
actions: <Type, Action<Intent>>{
PerformSyncIntent: CallbackAction<PerformSyncIntent>(
onInvoke: (PerformSyncIntent intent) {
_performSync();
return null;
},
),
},
child: Actions(
actions: <Type, Action<Intent>>{
PerformSyncIntent: CallbackAction<PerformSyncIntent>(
onInvoke: (PerformSyncIntent intent) {
_performSync();
return null;
},
),
},
child: Focus(
autofocus: true,
child: Scaffold(
body: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [
Color(0xFF191A1D),
Color(0xFF222326),
Color(0xFF101114),
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
child: Focus(
autofocus: true,
child: Scaffold(
body: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [
Color(0xFF191A1D),
Color(0xFF222326),
Color(0xFF101114),
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
child: SafeArea(
child: Column(
children: [
Expanded(
child: AnimatedSwitcher(
duration: _screenTransitionDuration,
switchInCurve: Curves.easeOutCubic,
switchOutCurve: Curves.easeInCubic,
transitionBuilder:
(Widget child, Animation<double> animation) {
final Animation<Offset> offsetAnimation =
Tween<Offset>(
begin: const Offset(0.08, 0.0),
end: Offset.zero,
).animate(animation);
),
child: SafeArea(
child: Column(
children: [
Expanded(
child: AnimatedSwitcher(
duration: _screenTransitionDuration,
switchInCurve: Curves.easeOutCubic,
switchOutCurve: Curves.easeInCubic,
transitionBuilder:
(Widget child, Animation<double> animation) {
final Animation<Offset> offsetAnimation =
Tween<Offset>(
begin: const Offset(0.08, 0.0),
end: Offset.zero,
).animate(animation);
return FadeTransition(
opacity: animation,
child: SlideTransition(
position: offsetAnimation,
child: child,
),
);
},
child: activeScreen,
),
return FadeTransition(
opacity: animation,
child: SlideTransition(
position: offsetAnimation,
child: child,
),
);
},
child: activeScreen,
),
],
),
),
],
),
),
),
@@ -951,64 +936,76 @@ class _NotesAppState extends State<NotesApp>
@override
Widget build(BuildContext context) {
Widget homeWidget;
if (_isBootstrapping) {
return _buildLoadingScreen();
}
homeWidget = _buildLoadingScreen();
} else {
final NoteRepository? repository = _repository;
final NoteRepository? repository = _repository;
if (repository != null) {
return _buildMainShell(repository);
}
switch (_phase) {
case _AppPhase.loading:
return _buildLoadingScreen();
case _AppPhase.access:
return _buildAppShell(
home: VaultAccessScreen(
isBusy: _isUnlocking,
onCreateAccountPressed: (String email, String password) async {
await _beginRemoteVaultFlow(
username: email,
password: password,
isRegister: true,
);
},
onSignInPressed: (String email, String password) async {
await _beginRemoteVaultFlow(
username: email,
password: password,
isRegister: false,
);
},
onContinueWithoutAccount: _enterWithoutAccount,
),
);
case _AppPhase.biometricChoice:
return _buildAppShell(
home: BiometricChoiceScreen(
isBusy: _isUnlocking,
onEnableBiometrics: () =>
_completeBiometricChoice(enableBiometrics: true),
onSkipBiometrics: () =>
_completeBiometricChoice(enableBiometrics: false),
),
);
case _AppPhase.biometricGate:
return _buildAppShell(
home: BiometricGateScreen(
key: ValueKey<int>(_biometricGateSession),
isBusy: _isUnlocking,
onUnlockRequested: _unlockBiometricGate,
),
);
case _AppPhase.notes:
if (repository == null) {
return _buildLoadingScreen();
if (repository != null) {
homeWidget = _buildMainShell(repository);
} else {
switch (_phase) {
case _AppPhase.loading:
homeWidget = _buildLoadingScreen();
break;
case _AppPhase.access:
homeWidget = _buildAppShell(
home: VaultAccessScreen(
isBusy: _isUnlocking,
onCreateAccountPressed: (String email, String password) async {
await _beginRemoteVaultFlow(
username: email,
password: password,
isRegister: true,
);
},
onSignInPressed: (String email, String password) async {
await _beginRemoteVaultFlow(
username: email,
password: password,
isRegister: false,
);
},
onContinueWithoutAccount: _enterWithoutAccount,
),
);
break;
case _AppPhase.biometricChoice:
homeWidget = _buildAppShell(
home: BiometricChoiceScreen(
isBusy: _isUnlocking,
onEnableBiometrics: () =>
_completeBiometricChoice(enableBiometrics: true),
onSkipBiometrics: () =>
_completeBiometricChoice(enableBiometrics: false),
),
);
break;
case _AppPhase.biometricGate:
homeWidget = _buildAppShell(
home: BiometricGateScreen(
key: ValueKey<int>(_biometricGateSession),
isBusy: _isUnlocking,
onUnlockRequested: _unlockBiometricGate,
),
);
break;
case _AppPhase.notes:
homeWidget = _buildLoadingScreen();
break;
}
return _buildMainShell(repository);
}
}
return MaterialApp(
navigatorKey: _navigatorKey,
title: 'Mis Notas',
debugShowCheckedModeBanner: false,
scaffoldMessengerKey: _scaffoldMessengerKey,
theme: _theme,
home: homeWidget,
);
}
}