Cette mise à jour majeure vise à améliorer significativement les performances de l'application, en particulier au démarrage, et à standardiser l'infrastructure backend. Les principaux changements incluent la migration de toutes les Cloud Functions vers une région européenne (`europe-west9`), l'optimisation du chargement des données, et l'introduction d'un moniteur de performance pour le débogage.
**Changements Backend (Cloud Functions) :**
- **Migration de la Région :**
- Toutes les Cloud Functions ont été déplacées de `us-central1` à `europe-west9` (Paris) pour réduire la latence pour les utilisateurs européens. Cela concerne les appels depuis le frontend (ex: `api_config.dart`, `email_service.dart`) et les définitions des fonctions elles-mêmes (`index.js`, etc.).
- **Standardisation des Fonctions :**
- La plupart des fonctions `onCall` (v1) ont été migrées vers le format `onRequest` (v2) avec une gestion d'authentification et de CORS unifiée, améliorant la robustesse et la cohérence.
- Les triggers Firestore (`onDocumentCreated`, `onDocumentUpdated`) et les tâches planifiées (`onSchedule`) ont été mis à jour pour spécifier explicitement la région `europe-west9`.
- **Mise à jour des Index Firestore :**
- Les index `firestore.indexes.json` ont été mis à jour pour supporter les nouvelles requêtes de l'application et optimiser les performances de filtrage.
**Améliorations des Performances Frontend :**
- **Chargement Asynchrone et Mis en Cache :**
- Le chargement des données utilisateur (`LocalUserProvider`) et des événements (`EventProvider`) a été optimisé pour utiliser un cache local à court terme (5 minutes pour l'utilisateur, 30 secondes pour les événements).
- Les données ne sont rechargées que si le cache a expiré ou si un rechargement est forcé, évitant des appels réseau redondants et accélérant la navigation.
- **Démarrage de l'Application Optimisé :**
- Le processus de connexion automatique (`main.dart`) a été revu. L'application navigue désormais immédiatement vers la page demandée sans attendre la fin du chargement des données utilisateur, qui s'effectue en arrière-plan.
- Un écran de chargement plus esthétique avec le logo de l'entreprise a été ajouté, remplaçant l'indicateur de chargement simple.
- **Chargement de la Page Calendrier :**
- Le chargement et la sélection de l'événement par défaut sur la page `CalendarPage` sont maintenant entièrement asynchrones, rendant l'affichage de la page quasi instantané.
**Nouveaux Outils et Améliorations UX :**
- **Moniteur de Performance :**
- Ajout d'un nouvel outil `PerformanceMonitor` (`lib/utils/performance_monitor.dart`) pour mesurer précisément le temps d'exécution des opérations critiques (appels API, parsing, etc.) en mode débogage. Il aide à identifier les goulots d'étranglement.
- **Amélioration du Formulaire de Connexion :**
- Les champs "Email" et "Mot de passe" sur la page de connexion (`LoginPage`) supportent désormais l'autocomplétion du navigateur (`AutofillGroup`).
- Appuyer sur "Entrée" dans l'un des champs déclenche désormais la connexion, améliorant l'ergonomie.
**Mise à jour de la version :**
- La version de l'application a été incrémentée à `1.0.9`.
105 lines
3.7 KiB
Dart
105 lines
3.7 KiB
Dart
import 'package:em2rp/view_model/login_view_model.dart';
|
|
import 'package:em2rp/views/widgets/auth/mail_textfield.dart';
|
|
import 'package:em2rp/views/widgets/error_message.dart';
|
|
import 'package:em2rp/views/widgets/auth/forgot_password_button.dart';
|
|
import 'package:em2rp/views/widgets/image/big_image_left.dart';
|
|
import 'package:em2rp/views/widgets/auth/login_button.dart';
|
|
import 'package:em2rp/views/widgets/image/em2_logo_n_sur_b.dart';
|
|
import 'package:em2rp/views/widgets/auth/password_textfield.dart';
|
|
import 'package:em2rp/views/widgets/auth/welcome_text.dart';
|
|
import 'package:em2rp/views/widgets/auth/forgot_password_dialog.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:provider/provider.dart';
|
|
|
|
class LoginPage extends StatelessWidget {
|
|
const LoginPage({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return ChangeNotifierProvider(
|
|
create: (_) => LoginViewModel(),
|
|
child: Scaffold(
|
|
body: LayoutBuilder(
|
|
builder: (context, constraints) {
|
|
return constraints.maxWidth > 900
|
|
? _buildLargeScreenLayout(context)
|
|
: _buildSmallScreenLayout(context);
|
|
},
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildLargeScreenLayout(BuildContext context) {
|
|
return Row(
|
|
children: <Widget>[
|
|
const Expanded(flex: 6, child: BigLeftImageWidget()),
|
|
Expanded(
|
|
flex: 4,
|
|
child: Padding(
|
|
padding:
|
|
const EdgeInsets.symmetric(horizontal: 50.0, vertical: 30.0),
|
|
child: _buildLoginForm(context),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildSmallScreenLayout(BuildContext context) {
|
|
return Center(
|
|
child: SingleChildScrollView(
|
|
padding: const EdgeInsets.all(20.0),
|
|
child: _buildLoginForm(context),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildLoginForm(BuildContext context) {
|
|
return Consumer<LoginViewModel>(
|
|
builder: (context, loginViewModel, child) {
|
|
return AutofillGroup(
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children: <Widget>[
|
|
const LogoWidget(),
|
|
const SizedBox(height: 30),
|
|
const WelcomeTextWidget(),
|
|
const SizedBox(height: 40),
|
|
EmailTextFieldWidget(
|
|
emailController: loginViewModel.emailController,
|
|
highlightEmailField: loginViewModel.highlightEmailField,
|
|
onSubmitted: () => loginViewModel.signIn(context),
|
|
),
|
|
const SizedBox(height: 20),
|
|
PasswordTextFieldWidget(
|
|
passwordController: loginViewModel.passwordController,
|
|
obscurePassword: loginViewModel.obscurePassword,
|
|
highlightPasswordField: loginViewModel.highlightPasswordField,
|
|
onTogglePasswordVisibility:
|
|
loginViewModel.togglePasswordVisibility,
|
|
onSubmitted: () => loginViewModel.signIn(context),
|
|
),
|
|
ForgotPasswordButtonWidget(
|
|
onPressed: () => showDialog(
|
|
context: context,
|
|
builder: (BuildContext context) =>
|
|
const ForgotPasswordDialogWidget(),
|
|
),
|
|
),
|
|
const SizedBox(height: 30),
|
|
LoginButtonWidget(
|
|
isLoading: loginViewModel.isLoading,
|
|
onPressed: () => loginViewModel.signIn(context),
|
|
),
|
|
const SizedBox(height: 20),
|
|
ErrorMessageWidget(errorMessage: loginViewModel.errorMessage),
|
|
],
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|