Cette mise à jour améliore la génération de QR codes pour les équipements et les containers en ajoutant un retour visuel à l'utilisateur et une gestion des erreurs plus robuste. **Changements :** - **Ajout d'un indicateur de chargement :** Un `CircularProgressIndicator` est désormais affiché pendant que les données des équipements ou des containers sélectionnés sont récupérées, informant l'utilisateur qu'une opération est en cours. - **Gestion des erreurs :** Un bloc `try...catch` a été ajouté autour de la logique de génération dans les pages de gestion des équipements (`EquipmentManagementPage`) et des containers (`ContainerManagementPage`). - **Affichage des erreurs :** En cas d'échec, le chargement est stoppé et une `SnackBar` rouge apparaît pour notifier l'utilisateur de l'erreur, améliorant ainsi la robustesse de la fonctionnalité.
224 lines
7.2 KiB
Dart
224 lines
7.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:em2rp/services/update_service.dart';
|
|
import 'package:em2rp/utils/colors.dart';
|
|
|
|
/// Dialog pour informer l'utilisateur d'une mise à jour disponible
|
|
class UpdateDialog extends StatelessWidget {
|
|
final UpdateInfo updateInfo;
|
|
|
|
const UpdateDialog({
|
|
super.key,
|
|
required this.updateInfo,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return PopScope(
|
|
// Empêcher la fermeture si c'est une mise à jour forcée
|
|
canPop: !updateInfo.forceUpdate,
|
|
child: AlertDialog(
|
|
title: Row(
|
|
children: [
|
|
Icon(
|
|
updateInfo.forceUpdate ? Icons.update : Icons.system_update,
|
|
color: updateInfo.forceUpdate ? Colors.orange : AppColors.rouge,
|
|
size: 28,
|
|
),
|
|
const SizedBox(width: 12),
|
|
Expanded(
|
|
child: Text(
|
|
updateInfo.forceUpdate
|
|
? 'Mise à jour requise'
|
|
: 'Mise à jour disponible',
|
|
style: const TextStyle(fontSize: 20),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
content: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// Versions
|
|
Container(
|
|
padding: const EdgeInsets.all(12),
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey[100],
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
child: Column(
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
const Text(
|
|
'Version actuelle :',
|
|
style: TextStyle(fontWeight: FontWeight.w500),
|
|
),
|
|
Text(
|
|
updateInfo.currentVersion,
|
|
style: const TextStyle(
|
|
fontFamily: 'monospace',
|
|
color: Colors.grey,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 8),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
const Text(
|
|
'Nouvelle version :',
|
|
style: TextStyle(fontWeight: FontWeight.bold),
|
|
),
|
|
Text(
|
|
updateInfo.newVersion,
|
|
style: const TextStyle(
|
|
fontFamily: 'monospace',
|
|
fontWeight: FontWeight.bold,
|
|
color: AppColors.rouge,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
const SizedBox(height: 16),
|
|
|
|
// Message principal
|
|
if (updateInfo.forceUpdate) ...[
|
|
Container(
|
|
padding: const EdgeInsets.all(12),
|
|
decoration: BoxDecoration(
|
|
color: Colors.orange.withValues(alpha: 0.1),
|
|
borderRadius: BorderRadius.circular(8),
|
|
border: Border.all(color: Colors.orange, width: 2),
|
|
),
|
|
child: const Row(
|
|
children: [
|
|
Icon(Icons.warning, color: Colors.orange),
|
|
SizedBox(width: 12),
|
|
Expanded(
|
|
child: Text(
|
|
'Cette mise à jour est obligatoire pour continuer à utiliser l\'application.',
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
color: Colors.orange,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(height: 16),
|
|
],
|
|
|
|
Text(
|
|
updateInfo.forceUpdate
|
|
? 'L\'application va se recharger pour appliquer la mise à jour.'
|
|
: 'Une nouvelle version de l\'application est disponible. Voulez-vous mettre à jour maintenant ?',
|
|
style: const TextStyle(fontSize: 15),
|
|
),
|
|
|
|
// Notes de version
|
|
if (updateInfo.releaseNotes != null &&
|
|
updateInfo.releaseNotes!.isNotEmpty) ...[
|
|
const SizedBox(height: 16),
|
|
const Text(
|
|
'Nouveautés :',
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 15,
|
|
),
|
|
),
|
|
const SizedBox(height: 8),
|
|
Container(
|
|
padding: const EdgeInsets.all(12),
|
|
decoration: BoxDecoration(
|
|
color: Colors.blue.withValues(alpha: 0.05),
|
|
borderRadius: BorderRadius.circular(8),
|
|
border: Border.all(color: Colors.blue.withValues(alpha: 0.2)),
|
|
),
|
|
child: Text(
|
|
updateInfo.releaseNotes!,
|
|
style: const TextStyle(fontSize: 14),
|
|
),
|
|
),
|
|
],
|
|
],
|
|
),
|
|
actions: [
|
|
if (!updateInfo.forceUpdate)
|
|
TextButton(
|
|
onPressed: () => Navigator.of(context).pop(),
|
|
child: const Text('Plus tard'),
|
|
),
|
|
ElevatedButton.icon(
|
|
onPressed: () async {
|
|
Navigator.of(context).pop();
|
|
// Recharger l'application
|
|
await UpdateService.reloadApp();
|
|
},
|
|
icon: const Icon(Icons.refresh, color: Colors.white),
|
|
label: Text(
|
|
updateInfo.forceUpdate ? 'Mettre à jour' : 'Mettre à jour maintenant',
|
|
style: const TextStyle(color: Colors.white),
|
|
),
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: updateInfo.forceUpdate ? Colors.orange : AppColors.rouge,
|
|
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Widget pour vérifier automatiquement les mises à jour
|
|
class UpdateChecker extends StatefulWidget {
|
|
final Widget child;
|
|
|
|
const UpdateChecker({
|
|
super.key,
|
|
required this.child,
|
|
});
|
|
|
|
@override
|
|
State<UpdateChecker> createState() => _UpdateCheckerState();
|
|
}
|
|
|
|
class _UpdateCheckerState extends State<UpdateChecker> {
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_checkForUpdate();
|
|
}
|
|
|
|
Future<void> _checkForUpdate() async {
|
|
final updateInfo = await UpdateService.checkOnStartup();
|
|
|
|
if (updateInfo != null && mounted) {
|
|
// Attendre que l'interface soit complètement chargée
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
if (mounted) {
|
|
showDialog(
|
|
context: context,
|
|
barrierDismissible: !updateInfo.forceUpdate,
|
|
builder: (context) => UpdateDialog(updateInfo: updateInfo),
|
|
);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return widget.child;
|
|
}
|
|
}
|
|
|